Function.prototype.toString to discover function dependencies

Chuck Jazdzewski chuckj at microsoft.com
Mon Sep 20 16:38:09 PDT 2010


> #3 could be relaxed to "The number of function arguments need to stay the same. The name can change, but code inside the function needs to change to use the new name, and the use of those names needs to be preserved".

This weaker 3 runs into problems if the new name is a free variable in the body of the function (alpha-renaming name capture) as well as potentially breaking direct (closure capture) calls to eval(). Both would need to be excluded to allow argument renames, such as "...and the function does not contain a direct call to eval. The new name must not be the same as the name used in any other variable references in the function body." The last restriction is a bit stronger than necessary but weaker forms are more complicated without being more useful.

Chuck.

-----Original Message-----
From: es-discuss-bounces at mozilla.org [mailto:es-discuss-bounces at mozilla.org] On Behalf Of James Burke
Sent: Monday, September 20, 2010 2:45 PM
To: Mark S. Miller
Cc: commonjs at googlegroups.com; es-discuss at mozilla.org
Subject: Re: Function.prototype.toString to discover function dependencies

On Sun, Sep 19, 2010 at 12:41 PM, Mark S. Miller <erights at google.com> wrote:
> Given source code, of course, either recognition trick works. Given 
> only meaning preserving source code, which is the most I was willing 
> to propose on that strawman page, these recognition tricks fail 
> <http://wiki.ecmascript.org/doku.php?id=strawman:function_to_string#discussion>.
> Would we be willing to specify enough fidelity with the original 
> source code that your trick would work? I don't know. Perhaps AST 
> preserving? Perhaps preserving of some abstraction over equivalent 
> ASTs? I would like to clean up Function.prototype.toString for ES-Harmony. Opinions?

If "meaning preserving source code" had qualifications like:

1) If line returns are removed, comments must be removed.
2) String literals need to stay string literals.
3) The number of function arguments must stay the same, and function argument names and their use within the function must be preserved.

that might be enough to give implementors enough flexibility but still allow the require dependencies to be found? Although I am not a language expert, maybe there are still holes with those qualifications.

#3 could be relaxed to "The number of function arguments need to stay the same. The name can change, but code inside the function needs to change to use the new name, and the use of those names needs to be preserved".

That would require a bit more work from my side. If the toString converted the function to something like function(r,e,m) {var f=r('foo'),b=r('bar');}, then it would require more work to pull out the r function arg. A bit less efficient, but doable. Probably not too bad given that this should just be used in a "source code loading"
form, and not something that is used after optimization. For optimization it will be common to place many require.def calls into one file, so names for the modules and the dependencies can be pulled out from the source and injected into the optimized require.def call.

But if it is all the same to implementors, then I prefer the first, stronger wording of #3.

I went ahead and put support for this require.def toString approach into the RequireJS implementation to try it out. There are still some edges to clean up, but we will see how it goes. Right now I assume the above qualifications on the toString() form. This seems to work out, but more testing is needed. For the apparently small number of implementations that do not preserve some usable string for Function.prototype.toString, then the advice will be to use an optimized/built version of the code that has pulled the dependencies out already, or to use use the other syntax supported by RequireJS:

require.def(['foo', 'bar'], function(foo, bar){
    //return a value to define the module. Alternatively,
    //as for 'exports' as a dependency in the dependency
    //array and specify it as a matching function arg
    //if dealing with a rare circular dependency failure case.
    return function(){};
});

James
_______________________________________________
es-discuss mailing list
es-discuss at mozilla.org
https://mail.mozilla.org/listinfo/es-discuss



More information about the es-discuss mailing list