script-tag, author-format, module loading

405 views
Skip to first unread message

Wes Garland

unread,
Oct 21, 2010, 10:18:21 AM10/21/10
to comm...@googlegroups.com
Are there are any implementations out there which pass the CommonJS modules test suite?

It's a given that, due to CommonJS module-scope, we must use a function() {...} wrapper in the module authoring format if we are to support this.

However, merely using a function wrapper does not solve all the issues surrounding this style of module loading.  There is at least one other issue -- module naming.

How does module naming work when injecting or inlining SCRIPT tags which contain modules in author format?  How do you know what they are called? Is it possible to find out what DOM container a particular function was declared in?

You can't put the name of the module in the module itself, without completely altering the semantics of CommonJS module-naming.  In SecurableModules, module filenames are canonical identifiers for the module, and renaming module filenames causes their names to change.

In my script-tag loader, my boiler-plate looks something like this:

commonjs.moduleMemo["${moduleCname}"] = {}; (function (require, exports, module) { ${moduleSourceCode}
})(requireFactory("${moduleCname}"), commonjs.moduleMemo["${moduleCname}"], moduleObjectFactory(${moduleCname});

Obviously, I am using a server process or build step to achieve this goal.

What are other people doing?

Wes

--
Wesley W. Garland
Director, Product Development
PageMail, Inc.
+1 613 542 2787 x 102

jbrantly

unread,
Oct 21, 2010, 11:04:08 AM10/21/10
to CommonJS
There was discussion on this on the first page of the huge AMD thread.
Basically though it's possible to keep track of which "anonymous
definition" goes with which script load.

Wes Garland

unread,
Oct 21, 2010, 11:11:15 AM10/21/10
to comm...@googlegroups.com
> Basically though it's possible to keep track of which "anonymous definition" goes with which script load.

I can't find this, nor can I find it in the Wiki.

Do you have a pointer?  In my mind, this is a major technical hurdle.

jbrantly

unread,
Oct 21, 2010, 11:24:18 AM10/21/10
to CommonJS
Hopefully they don't mind me quoting them:

http://groups.google.com/group/commonjs/browse_thread/thread/9dba57ef7f51439a

KZyp:

Also, one more thought/question, is it possible to make the very first
id optional? Can that be implied from module/script that was
requested,
associating the script with the require.def call by the script
element's
onload/onreadystate event that require.def precedes (or do browsers
sequence the script executions so you can determine the id by the
order
of requested by scripts)?

JBurke:

The order is not guaranteed. In particular, IE does not fire the
readystate change directly after executing the script. There is a test
in RequireJS at this location if you want to confirm:
http://github.com/jrburke/requirejs/tree/master/tests/browsertests/sc...

KZyp:

Awesome, great tests. And yes, I can definitely reproduce the scripts
executing out of order, and the onreadystatechange definite does not
fire directly after the execution, but... Everytime I run the test,
the
order that the scripts are executed exactly matches the order of the
firing of the onreadystatechange events. If script five executes
before
script four, then the onreadystatechange for five will fire before the
onreadystatechange for four. While it is not as convenient as having
the
event fire directly after the script executes, it does seem to provide
the information necessary to associate requests with script executions
(and thus anonymous require.def calls with module ids).

JBurke:

Ah, great observation! There does seem to be a way to tie them
together. It does make implementation a bit more complicated, but
certainly doable.

Kris Zyp

unread,
Oct 21, 2010, 11:34:20 AM10/21/10
to comm...@googlegroups.com
We actually had some discussions off-list, as it turns out the required
technique is a little different than described in this thread. Briefly,
to identify anonymous modules from scripts:
* In non-IE browsers, the onload event is sufficient, it always fires
immediately after the script is executed.
* In IE, if the script is in the cache, it actually executes *during*
the DOM insertion of the script tag, so you can keep track of which
script is being requested in case define() is called during the DOM
insertion.
* In IE, if the script is not in the cache, when define() is called you
can iterate through the script tags and the currently executing one will
have a script.readyState == "interactive"

See RequireJS source code if you need more hints.

Anyway, the bottom line from a spec perspective is that it is
implemented, it works, and it is possible. Hope that helps.
Kris

--
Thanks,
Kris

Wes Garland

unread,
Oct 21, 2010, 12:43:40 PM10/21/10
to comm...@googlegroups.com
On Thu, Oct 21, 2010 at 11:34 AM, Kris Zyp <kri...@gmail.com> wrote:
 We actually had some discussions off-list, as it turns out the required
technique is a little different than described in this thread. Briefly,
to identify anonymous modules from scripts:

Thanks for taking the time to break down the technique. I was hoping something that existed. This means that it is possible for define to find the canonical path of the module based on the SRC= attribute of the SCRIPT tag, correct?
 
* In non-IE browsers, the onload event is sufficient, it always fires
immediately after the script is executed.

Do you know if this exact behaviour is blessed/required by W3C?  If so, then that is a powerful argument that this technique is sufficient.

Do you know if it works on mobile opera, mobile safari, camino, konqueror, amaya?

I'm guessing Palm and Blackberry browsers are out of reach anyhow.

Wes

Stefaan

unread,
Oct 21, 2010, 1:19:52 PM10/21/10
to CommonJS


On Oct 21, 5:43 pm, Wes Garland <w...@page.ca> wrote:
I'm actually doing something like that at the mo - although still
under development and only firefox at the mo, so the info from KrisZ
is very valuable.

I'm matching with onLoad event for modules that are loaded via the
system, and matching with script-tag-src for modules that are loaded
via script-tag.
I found 2 problems with the latter:
1) when the module-file gets renamed (f.i. because there are multiple
version of the same compilation).
2) when there are multiple script-tags in the page, some loading
modules and others for other stuff.
In such a case, I'm using some extra attribute, call it 'main' or
'platform' or whatever, to filter the ones that load modules and that
correspond to a particular version - idea stolen from requireJS
documentation, I must add.

One of the other things I needed to re-introduce is 'require.pause'
and 'require.resume' - to be able to load multiple modules in one file
from script-tag.

Loading multiple modules in one file via the module-system can again
use onLoad events - essentially doing an implicit pause-resume.
Although I must say I didn't do too much testing on this yet so not
sure if there are any race-conditions breaking this strategy.

I'm using no top-level IDs at all in my definitions - they are all
matched to onLoad-event or script-tag-src, and when using multiple
modules, I have one main module without ID and the others relative to
this one. This allows to load multiple different versions of the
system that are using modules that are common to both versions. Only
thing that doesn't work with this strategy are foreign modules - i.e.
modules that are not relative to the module-file that is being loaded,
these are the only ones that do need top-level IDs, and so didn't find
a secure way yet to load these from script-tag - was planning to only
allow load via modules-system.

Stefaan

James Burke

unread,
Oct 21, 2010, 1:34:27 PM10/21/10
to comm...@googlegroups.com
On Thu, Oct 21, 2010 at 8:34 AM, Kris Zyp <kri...@gmail.com> wrote:
> See RequireJS source code if you need more hints.

There is a specific implementation of these ideas that does not use
any RequireJS code, basically just a stand-alone browser test, that
might be more informative on the particular techniques Kris outlines:
http://github.com/jrburke/requirejs/blob/master/tests/browsertests/scriptloadinteractive/index.html

James

Reply all
Reply to author
Forward
0 new messages