Implementing Mozilla’s toSource() method in Internet Explorer

Consider the following: (when using FireFox 3.6)

javascript:
  x=function(){alert('caveat compter')};
  alert(['JSON:\t',JSON.stringify(x),'\n\ntoSource():\t',x.toSource()].join(''));

which displays:

JSON:

toSource(): (function () {alert(“caveat compter”);})

or even:

javascript:
x=[];x[3]=x;
alert('toSource():\t'+x.toSource());
alert('JSON can not handle this at all and goes "infinite".');
alert('JSON:\n'+JSON.stringify(x));

which displays:

toSource(): #1=[, , , #1#]

and the “going ‘infinite'” message whence follows JSON’s stackoverflow recursive digression.

The examples emphasize the subtleties of expression explicitly excluded from JSON representation that are rendered by toSource().

It is not easy to compose a program to replicate the same results, for ALL cases, as the Gecko toSource() primitive, which is exceptionally powerful.

Below are a few of the ‘moving targets’ that a program duplicating toSource() functionality MUST handle successfully:

javascript:
function render(title,src){ (function(objRA){
    alert([ title, src,
        '\ntoSource():',objRA.toSource(),
        '\nJSON:',JSON.stringify(objRA)     ].join('\n'));
    })(eval(src));
}
render('Simple Raw Object source code:',
    '[new Array, new Object, new Number, new String, ' +
        'new Boolean, new Date, new RegExp, new Function]'  );

render( 'Literal Instances source code:',
    '[ [], 1, true, {}, "", /./, new Date(), function(){} ]'    );

render( 'some predefined entities:',
    '[JSON, Math, null, Infinity, NaN, ' +
        'void(0), Function, Array, Object, undefined]'      );

which displays:

    Simple Raw Object source code:
    [new Array, new Object, new Number, new String, 
                new Boolean, new Date, new RegExp, new Function]

    toSource():
    [[], {}, (new Number(0)), (new String("")), 
                (new Boolean(false)), (new Date(1302637995772)), /(?:)/, 
                            (function anonymous() {})]

    JSON:
    [[],{},0,"",false,"2011-04-12T19:53:15.772Z",{},null]

and then displays:

    Literal Instances source code: 
    [ [], 1, true, {}, "", /./, new Date(), function(){} ]

    toSource():  
    [[], 1, true, {}, "", /./, (new Date(1302638514097)), (function () {})]

    JSON:  
    [[],1,true,{},"",{},"2011-04-12T20:01:54.097Z",null]

and lastly:

    some predefined entities:
    [JSON, Math, null, Infinity, NaN, void(0), 
                        Function, Array, Object, undefined]

    toSource():
    [JSON, Math, null, Infinity, NaN, (void 0), 
        function Function() {[native code]}, function Array() {[native code]}, 
            function Object() {[native code]}, (void 0)]

    JSON:
    [{},{},null,null,null,null,null,null,null,null]

The previous analysis is significant if the translations are ‘to be used’ or less stringent if the need is for simple benign human consumption to view an object’s internals. A primary JSON feature, as a representation, is the transfer of some structured information ‘to be used’ between environments.

The quality of a toSource() function is a factor in the denotational semantics of a programme influencing, but not limited to:
round trip computations, least fixed point properties, and inverse functions.

  • Does repetition of code conversion
    quiesce to a static state?
  • Does obj.toSource() ==
    eval(eval(eval(obj.toSource()).toSource()).toSource()).toSource()?
  • Does it make sense to consider
    whether obj == eval(obj.toSource())?
  • Does undoing a conversion result in, not
    just a similar object, but an
    IDENTICAL one?
    This is a loaded
    question with profound implications
    when cloning an operational object.

and many, many more …

Note that the above questions take on added significance when obj contains an executed code object, such as (new Function … )()!

Leave a Comment