Mochabot log - CommonJS IRC channel: #commonjs on irc.freenode.net

2010-11-09:

[2:19] <Wes-> deanlandolt: any idea why require.main returns main module's module object instead of exports?
[2:19] * Wes- mulls syntax
[2:19] <Wes-> <form name=area id=areaForm action="javascript:require(module.main.id).showArea();">
[2:21] <Wes-> <form name=area id=areaForm action="javascript:module.main.showArea();">
[19:37] <Wes-> deanlandolt: around?
[19:38] <deanlandolt> Wes- hey, yeah...
[19:38] <Wes-> deanlandolt: view source -- http://www.page.ca/~wes/BravoJS/demos/area/
[19:38] <Wes-> Does that "read" sensibly to you?
[19:38] <deanlandolt> still haven't had time to comb through everything...been slammed by enterprisey crap :-/
[19:38] <deanlandolt> i'll read it now
[19:38] <Wes-> deanlandolt: I know how that goes!!! :)
[19:38] <deanlandolt> wait...read sensibly? like, width, length, area?
[19:39] <deanlandolt> the only nonsensical thing is that area isn't disabled
[19:39] <Wes-> deanlandolt: Like how the CommonJS interacts with the HTML in a usable bootstrappy sense
[19:39] <deanlandolt> oh, you mean the underlying code :)
[19:40] * Wes- fixes area :)
[19:40] <Wes-> But, yeah
[19:40] <deanlandolt> i like the action="javascript:require(module.main.id).showArea(); idiom though
[19:41] <deanlandolt> but wouldn't javascript:module.main.showArea(); read a little better?
[19:41] <Wes-> I think it may be a tad long, but in general, yeah, I think not relying on properties of window to access CommonJS is wise
[19:42] <mschwartz> http://www.barryvan.com.au/2009/05/avoid-javascripts-with-keyword/
[19:42] <Wes-> deanlandolt: Yeah, but module.main (previously require.main) returns the module variable, rather than the exports
[19:42] <deanlandolt> ah, so yeah, module isn't a global
[19:42] <Wes-> Now, WHY that is, I'm not sure
[19:42] <mschwartz> Wes- that URL was for you
[19:43] <mschwartz> seems to me, "with" is ideal for implementing modules client-side
[19:43] <mschwartz> you inject script tag to execute JS
[19:43] <mschwartz> instead
[19:44] <Wes-> mschwartz: I've thought about that a number of times -- it's equivalent to "using namespace" -- but it has a couple of REALLY ugly sides (beyond the political issues)
[19:44] <mschwartz> with (module) { try {eval(js_string);} catch (e) { ...} }
[19:44] <Wes-> namely, 1) it's a huge performance hit on all modern browsers, 2) it is disabled in ES5 "use strict"
[19:45] <Wes-> deanlandolt: Do you know why require.main returns the module variable instead of the exports?
[19:46] <mschwartz> http://ejohn.org/blog/ecmascript-5-strict-mode-json-and-more/
[19:46] <mschwartz> While the feature was certainly mis-understood and possibly mis-used I'm not convinced that it's enough to be stricken from the record.
[19:46] <mschwartz> I think it's incredibly valuable
[19:46] <deanlandolt> Wes-: my best guess is because of the if (require.main === module) idom
[19:46] <mschwartz> in rare circumstances
[19:46] <Wes-> deanlandolt: require.main === exports works there though, right?
[19:47] <deanlandolt> mschwartz: perhaps, but it's been *officially* stricken from the record :)
[19:47] <deanlandolt> Wes- hmm, yeah, that's a good point...much more sane
[19:47] <Wes-> I'm going to post another q
[19:47] <deanlandolt> why does everyone do it the other way around, i wonder?
[19:47] <mschwartz> you don't have to use strict
[19:48] <mschwartz> at least not everywhere
[19:48] <deanlandolt> mschwartz: no, you don't but strict mode is the /official/ mode going forward...as such its clear that with will probably never get the optimization love it would need to get it out of the slow path
[19:49] <deanlandolt> maybe that could change, but that seems to be one thing tc39 actually agrees on :)
[19:49] <mschwartz> does this bravo.js really emulate modules?
[19:49] <mschwartz> can a module set a global variable?
[19:49] <mschwartz> foo = 10;
[19:50] <mschwartz> in the browser, I think you'll end up with window.foo = 10
[19:50] <mschwartz> if you do with(something)
[19:51] <mschwartz> the module would do foo=10 and set something.foo=10
[19:51] <mschwartz> and you can throw away something
[19:52] <mschwartz> FWIW, there are only two cases I've found for using with
[19:52] <mschwartz> this seems like one
[19:52] <mschwartz> another is in a templating engine
[19:54] <deanlandolt> mschwartz: yeah, both legit cases...i agree
[19:55] <mschwartz> I figure if there are two cases, there's likely more
[19:55] <deanlandolt> hopefully by the time harmony comes around (and nixes with for good) they damn well better have a substitute
[19:55] <deanlandolt> simple modules fixes the former case...and may help in the latter
[19:55] <mschwartz> the foo=10 case
[19:55] <mschwartz> that could really screw you over
[19:55] <Wes-> mschwartz: Modules CAN set global variables, this is unavoidable using ES3 and web browsers -- but they won't set any globals by accident, providing the scripts are running in ES-5 strict mode
[19:56] <mschwartz> you include someone's module and you ahve a global collision
[19:57] <deanlandolt> mschwartz: sure, but there are far more dangerous implications for including arbitrary, unvetted modules :)
[19:57] <mschwartz> Wes: using "with", a Module would have to set window.foo = 10 to set the global variable
[19:58] <Wes-> no, there's other ways too
[19:58] <Wes-> you can mis-purpose eval
[19:58] <Wes-> or travel up the scope chain of a function's constructor
[19:58] <Wes-> Using with offers no more protection than function-scope
[19:58] <Wes-> and comes at a terrible price (no JIT)
[19:59] <Wes-> (no ES-5 strict, and in the future, no ES-Harmony either)
[20:00] <mschwartz> http://requirejs.org/
[20:00] <Wes-> mschwartz: You're not really up on CommonJS, are you? :)
[20:00] <mschwartz> I know enough about the mechanism of module
[20:00] <mschwartz> modules
[20:00] <mschwartz> "with" came to mind immediately
[20:01] <mschwartz> because of the global variable thing
[20:01] <mschwartz> like
[20:01] <mschwartz> in a module, I could easily see someone doing:
[20:01] <mschwartz> var id = 0;
[20:01] <mschwartz> function one() {
[20:01] <mschwartz> var myid = ++id;
[20:02] <mschwartz> }
[20:02] <mschwartz> function two() {
[20:02] <mschwartz> var myid = ++id;
[20:02] <mschwartz> }
[20:02] <mschwartz> etc.
[20:02] <mschwartz> works great in a sandbox
[20:03] <mschwartz> sucks if my code has a global var id
[20:03] <mschwartz> and I'm including some wizz-bang module that does the above
[20:03] <Wes-> well, if you care about that particular problem, you should have probably invented a module system that didn't have that bug
[20:03] <Wes-> Or just used CommonJS
[20:04] <deanlandolt> mschwartz: if you care about that problem you should probably lint your included modules :)
[20:04] <deanlandolt> Wes-: commonjs modules have that bug though
[20:04] <mschwartz> why isn't that valid inside a module?
[20:04] <Wes-> deanlandolt: No, he should use a module system that's not so broken that it runs abritrary code in the global context
[20:04] <mschwartz> a module is supposed to run in a sandbox
[20:04] <deanlandolt> ah, yes
[20:04] <Wes-> deanlandolt: No they don't
[20:05] <deanlandolt> hmm, well if modules are fn wrapped they wouldn't exhibit the bug but i thought gpsee doesn't fn wrap
[20:05] <Wes-> deanlandolt: If that was a commonjs module the 'var id' would have been declared in the module-scope, not the global object
[20:05] <deanlandolt> so var id would just get hoisted
[20:05] <mschwartz> right
[20:05] <mschwartz> I suggested with(module) {
[20:05] <mschwartz> then var id is module.id
[20:05] <mschwartz> (in module scope)
[20:05] <Wes-> deanlandolt: gpsee doesn't fn wrap but it does not hoist variables from modules to global scoep!!
[20:06] <deanlandolt> so SM internals gives you some mechanism to prevent this?
[20:06] <deanlandolt> this isn't an issue w/ main modules? i guess i just assumed it was...so all the better, i guess
[20:07] <Wes-> deanlandolt: Yes - I am have extremely good control over the scope chain in GPSEE. There is a proxy between modules and the global that I can even use to further restrict up/down access if I want to implement any kind of sandboxing
[20:08] <deanlandolt> ah, sweet
[20:08] <mschwartz> wes: GPSEE runs in the browser?
[20:08] <Wes-> deanlandolt: main modules it is ATM, but that's an implementation detail. Modules/1.0 does not document clearly what the right behaviour is. That is hopefully corrected in my current draft proposal.
[20:08] <deanlandolt> mschwartz: no, but in the browser modules would typically be fn-wrapped and not exhibit the bug you referenced
[20:08] <Wes-> mschwartz: no
[20:09] <Wes-> deanlandolt: For non-program modules that statement is true. It's more interesting for program moudles in /1.x because the behaviour actually isn't defined
[20:09] <Wes-> deanlandolt: A reasoanble /1.1 program module could exist inside script tags with no wrapper
[20:11] <deanlandolt> well, none the less...better safe than sorry...if you're requiring arbitrary code you haven't vetted you could have other problems...js isn't secure yet
[20:11] <deanlandolt> and SecurableModules certainly aren't SecureModules
[20:12] <Wes-> *nod* - although at least with the draft I'm playing with, you need to purposefully /try/ to set global variables (i.e. by dereferencing window), even from a program module
[20:12] <deanlandolt> yeah, forcing the fn wrapper does solve a few of these oddities
[20:12] <Wes-> Interesting question, should program modules in the browser launch when window.onload, or when their dependencies have been satisfied?
[20:13] <Wes-> deanlandolt: Definitely. The more I play with them the more I'm convinced we should have done this two years ago
[20:14] <deanlandolt> Wes-: that's a tough question...onload fires way too late, right? so you really mean on dom ready, right?
[20:15] <deanlandolt> even still, your modules might not care at all about the dom so that seems like it could be (in admittedly rare cases) a bit limiting
[20:15] <deanlandolt> but if you need dom-ready just include a dom-ready module in your dep list :)
[20:15] <Wes-> deanlandolt: Well, that's a good question right there... Right now, I'm running the main module as soon as possible, but the naive thought is "it should run on window.onload"
[20:15] <Wes-> OTOH, you might be using the main module to draw the page (document.write)
[20:15] <Wes-> or maybe you are using elements from the main module in event handlers
[20:15] <deanlandolt> yeah, but you don't need onload for that...just dom-ready
[20:16] <Wes-> like, form onclicks
[20:16] <Wes-> So I guess the real questoin is --- is there a reason you can think of to artificially delay the running of the program module in the browser?
[20:16] <Wes-> programmers who need the delay can always do this
[20:16] <deanlandolt> Wes-: yeah, that's dom-ready
[20:17] <Wes-> BODY onload = require(module.main.id).go();
[20:17] <Wes-> (ugh at the verbosity, for now)
[20:17] <deanlandolt> but it seems like it'd be a really elegant solution to have a dom-ready dependency
[20:17] <deanlandolt> and that dependency would delay your execution until you can munge the dom
[20:17] <Wes-> Yeah. There's still some interesting shaking-out for the browser side that hasn't really been discussed
[20:18] <Wes-> deanlandolt: OTOH, if you have a dependency on anything other than the main module, you're stuff waiting for dom ready anyhow, right?
[20:18] <deanlandolt> that'd be an easy module to write if it weren't for one complication...i guess it'd have to set an event listener so it'd probably have to return a promise or some such...
[20:18] <Wes-> because you need that to perform script-tag injection of XHR?
[20:19] <deanlandolt> perhaps not...console would probably be available immediately
[20:19] * Wes- thinks
[20:19] <deanlandolt> perhaps you're just doing logging (yeah, that's kinda stupid...but still :)
[20:20] <deanlandolt> you're probably right though...no sense in complicating matters...may as well spec dom-ready and be done with it
[20:20] <Wes-> I think I'm going to leave kick-off as earlier as possible, and if anybody needs it later they can delay it easily enough
[20:21] <deanlandolt> i'll have to think on that...it would be nice to not have to double-wrap
[20:21] <deanlandolt> (meaning, wrapping the contents of your wrapped module in a readiness fn)
[20:21] <mschwartz> modules shouldn't document.write()
[20:21] <mschwartz> solved
[20:22] <mschwartz> the body onload works
[20:22] <Wes-> Yeah, that's true - although you could make your readiness an export from the main module and at least get a nice looking event declaration :)
[20:23] <deanlandolt> mschwartz: how does onload work? do you really want your module execution to be delayed until your images have loaded?
[20:24] <Wes-> and the ads!
[20:25] <mschwartz> everything but the ads, actually
[20:25] <mschwartz> but sure
[20:26] <mschwartz> the important .js file was loaded in the head
[20:26] <mschwartz> bravo.js
[20:27] <mschwartz> fwiw
[20:27] <mschwartz> almost all the ads I see these days are loaded in iframes or deferred via adding script tags to the dom
[22:09] <kixxauth> Wes-: A browser loader may execute at any time (depending on the implementation) so...
[22:10] <kixxauth> it SHOULD provide an event emitter / promise that indicates that DOM ready has fired in case the loaded modules do not get a chance to listen for it.
[22:10] <kixxauth> is that what you guys are thinking?
[22:13] <kixxauth> I don't think it would be good practice for loaders to defer exection of the module chain until DOM ready fires.
[22:14] <kixxauth> There are too many things that a program might want to do before that point in implementations that allow it.

 

 

Logs by date :