Showing posts with label javascript. Show all posts
Showing posts with label javascript. Show all posts

2012-10-04

The Node.js REPL and Backslashes in Strings

I thought there was something weird going on with the node.js REPL's handling of backslashes in Strings. I was thinking, "Why are there twice as many backslashes!?" Then, it hit me: the output is correct! It is escaping the value of the string, just as if a programmer were to have typed it. Duh. You can use the output as-is when copy-and-pasting. No need to manually add extra backspaces! That's pretty convenient, eh? This really had me confused me at first, though, because I am so used to the behavior of Chrome's console, which prints out the unescaped string values (even though it does put quotes around the value).

$ node
> "\ "
' '
> JSON.stringify("\ ")
'" "'
> "\\"
'\\'
> JSON.stringify("\\")
'"\\\\"'
> new Buffer("\\")
<Buffer 5c>
> new Buffer([0x5c]).toString()
'\\'
> new Buffer([0x5c, 0x5c]).toString()
'\\\\'

2009-12-30

Closure Compiler

I've been trying out Google's supposedly wicked Closure Compiler. It seems to work well for normal things; but, there still is a bit farther to go. I don't know if there is something wrong with the way that I write javascript; but, it seems that the Closure Compiler just can't handle it properly...

By the way, there was a very eye-opening and interesting post on the Google Code Blog. Basically, they came up with a wonderful idea: send all modules, split-up and commented-out, to the client, then eval() them on-the-fly. Now, why the hell didn't anyone think of that before!? D'OH!!! Anyway, props to the thinker who came up with that solution.

Well, okay, back to the point of this blog.

In order to see how well the compiler works, I wrote some slightly bloated code (see code appendices below).

For some reason, though, the output is really not as optimized as I would have hoped...

For example:
if((b=b)&&f===b.tagName){a=b.innerHTML||"";b.parentNode.removeChild(b)}a=(a=a)?a.replace(/^\s*\/\*\s*(.*?)\s*\*\/\s*$/,"$1"):void 0;if(a){a=["{",a,"}"].join("");eval(a)}

Could probably be further reduced to:
if(b&&f===b.tagName){a=b.innerHTML||"";b.parentNode.removeChild(b)}if(a){eval(["{",a.replace(/^\s*\/\*\s*(.*?)\s*\*\/\s*$/,"$1"),"}"].join(""))}

And even further yet to:
if(b&&f===b.tagName){eval(["{",(b.innerHTML||"").replace(/^\s*\/\*\s*(.*?)\s*\*\/\s*$/,"$1"),"}"].join(""));b.parentNode.removeChild(b)}

Maybe there's some cross-browser stuff (of which I should mention I am not really familiar). I dunno.

All-in-all, from what I've seen so far, it's really good at reducing unnecessary, or "dead", code. As such, I'd have say that I want to start using the Closure Compiler for my own projects! At this point it looks like nothing beats a hand-coder for optimization, though--I'll have to go over the output and manually fix all the (a = a) stuff.





Appendix


module.js
// ==ClosureCompiler==
// @compilation_level ADVANCED_OPTIMIZATIONS
// @output_file_name default.js
// @formatting pretty_print
// ==/ClosureCompiler==

// ADD YOUR CODE HERE
var xvn = function(doc){
 var SCRIPT = doc.createElement('script').tagName;

 var __loaded_modules = {};
 function mark_as_loaded(id) {
  __loaded_modules[id] = true;
 }
 function is_loaded(id) {
  return (id) && (__loaded_modules[id]);
 }

 function get_elm(id) {
  var elm;
  if (id) {
   elm = doc.getElementById(id);
  }
  return elm;
 }

 function grab_js(elm) {
  var js;
  if (elm && SCRIPT === elm.tagName) {
   js = elm.innerHTML || "";
   elm.parentNode.removeChild(elm);
  }
  return js;
 }

 function clean_js(js) {
  if (!js) return;

  return js.replace(/^\s*\/\*\s*(.*?)\s*\*\/\s*$/,"$1");
 }

 function eval_js(js) {
  if (!js) return;

  var new_js = ['{', js, '}'].join("");
  eval(new_js);
 }

 return {
  'load_module':function(id){
   if (!is_loaded(id)) {
    eval_js(clean_js(grab_js(get_elm(id))));
    mark_as_loaded(id);
   }
  }
 };
};
window['xvn'] = xvn;

module-compiled.js
window.xvn=function(d){var f=d.createElement("script").tagName,e={};return{load_module:function(c){if(!(c&&e[c])){var a;var b;if(c)b=d.getElementById(c);if((b=b)&&f===b.tagName){a=b.innerHTML||"";b.parentNode.removeChild(b)}a=(a=a)?a.replace(/^\s*\/\*\s*(.*?)\s*\*\/\s*$/,"$1"):void 0;if(a){a=["{",a,"}"].join("");eval(a)}e[c]=true}}}};

index.html
<!DOCTYPE html>
<html>
<head>
 <title>Module Loading Tests</title>
 <script type="text/javascript" src="./module-compiled.js"></script>
</head>
<body>
 <div id="click-me-man" onclick="my_xvn.load_module('mod1');">Load Mod1</div>

 <script type="text/javascript" id="mod1">
 /*
  alert("Hey!");
 */
 </script>

 <script type="text/javascript">
  var my_xvn = new xvn(document);
 </script>
</body>
</html>

2008-08-23

Bitwise Operations and Unsigned Numbers in Javascript

EDIT (2012-09-28):

I stumbled upon an easier way: just do an unsigned right-shift with zero! Duh!
var a = 0x03000000
var b = (a << 6) >>> 0
console.log(b.toString(16).toUpperCase())
This will yield the expected C0000000.



Bitwise operators in javascript, as I discovered, treat their operands--and consequently their results--as 32-bit signed integers.
The only exception is the unsigned right-shift operator, which is written as >>>.

So, the following causes a big problem:
var a = 0x03000000;
var b = a << 6;
console.log(b.toString(16).toUpperCase());
One would expect to see C0000000; however, the result is actually -40000000. This is because the left-most bit of b is 1, which, when a number is signed, tells javascript that it is negative.
hex: C    0    0    0    0    0    0    0
bin: 1100 0000 0000 0000 0000 0000 0000 0000
So, how can this signed number be reinterpreted as an unsigned number? Let's try... We'll start with 0xC0000000, which is an unsigned integer.
var a = 0xC0000000;
console.log(a.toString(16).toUpperCase());
Then, we'll add 1 by or-ing it in. This should result in 0xC0000001; however, bitwise operations result in signed numbers. So, javascript thinks that it is 0x-3FFFFFFF.
var b = a | 1;
console.log(b.toString(16).toUpperCase());
Now, one must use the unsigned right-shift in javascript to divide by two. This shifts all bits to the right, pads the left with zeros, and drops the bits from the right. The operand and result will be interpreted as unsigned integers.
var c = b >>> 1;
console.log(c.toString(16).toUpperCase());
In order to reverse the previous operation, the number must be multiplied by 2, and the bit lost from the shift must be replaced.
var d = (c * 2) + (b & 1);
console.log(d.toString(16).toUpperCase());

So, basically, stuff gets to be a bit messy when using bitwise operators in javascript.