Module Application Compatibility proposals

49 views
Skip to first unread message

ZER0

unread,
Nov 3, 2011, 11:39:09 AM11/3/11
to mozilla-la...@googlegroups.com
Rocketeers!

We're thinking to give to every single module the capability to declare
for which application is designed for (e.g. Firefox, Fennec, etc).

At the moment, this is done at runtime:

"use strict";

if (!require("api-utils/xul-app").is("Firefox")) {
throw new Error(...);
}
// module code

"use strict";

if (!require("api-utils/xul-app").isOneOf(["Firefox", "Fennec"])) {
throw new Error(...);
}
// module code

But we think it should be better having this information at packaging
time, using the `cfx` tool, that display a warning about that, without
having to run the code. In addition, is some kind of information that is
useful when we build the dependencies graph; and for sharing modules.

In that way, the `cfx` can package the addon for the proper target(s)
automatically.
Note that if a module claims to be compatible with an application, `cfx`
will assume implicitly that also the dependencies of that module are
compatible as well. Only if the declaration is missing the `cfx` will
check the dependencies compatibility.

So we can have a module with multiple implementation for different
application, for example:

// we are in tabs.js, that claims to be compatible with Firefox
// and Fennec

let app = require("api-utils/xul-app");

if (app.is("Firefox")) {
module.setExports(require("tabs-firefox")); // compatible with FF
} else if (app.is("Fennec")){
// Ideally we already claim the compatibility for both, so this `if`
// could be unnecessary
module.setExports(require("tabs-fennec")); // compatible with Fennec
}

And if we have some generic approach for that information, we could
extend it in the future to include other data like "experimental" flag,
for example.

So guess what, we end up with module metadata. :)

So here, some proposal, that I'd like to discuss with you. Feel free to
add other approach!

1. Using "require" to define the meta data as javascript object. The
module we
require is a "special one" that we use just to "trigger" `cfx`.

"use strict";

require("@meta").data = {"compatibility" : ["Firefox", "Fennec"]};

2. Adding `meta` property to the `module` object. In this way the module
itself
can access to this information.

"use strict";

module.meta = {"compatibility" : ["Firefox", "Fennec"]};
// module code

3. Adding `meta` property to the `exports` object. In this way both
module and the module that require this one can access to this information.

"use strict";

exports.meta = {
"compatibility" : ["Firefox", "Fennec"]
};
// module code

4. Use a JavaScript object at the beginning, like "use strict"; without
assign it, so it will be discarded. No one can access to this
information at runtime.

"use strict";

{"compatibility" : ["Firefox", "Fennec"]};
// module code

5. Use jsdoc-style comment:

"use strict";

/**
* @application Firefox, Fennec
*/
//module code

6. Last but not least, using the Module Metadata proposal by CommonJS:
<http://wiki.commonjs.org/wiki/Modules/Metadata>

"use strict";

META({
"compatibility" : ["Firefox", "Fennec"]
});
// module code

Note that the JavaScript object I used is not the definitive one.


Irakli Gozalishvili

unread,
Nov 4, 2011, 10:20:06 AM11/4/11
to mozilla-la...@googlegroups.com

Hereis my feedback:

1. -1 too magical & contradicts with idea that module exports are immutable after the are exported
2. +1 I like that, also metadata could be shared if desired exports.module = module
3. +1 Can't decide if I prefer 2. or not, depends how often requirer will need this
4. +1 I like this as it makes clear that metadata is immutable at runtime, also I would go for the folllowing instead

meta: ({ firefox: true })

Label makes it easier to parse and read

5. -1 no syntax highlighting, no parse errors on mistypes
6. -1 yet another global :(
7. Mabe something like:

module.meta({ .... })

Just like 2. & also makes it more obvious that metadata is immutable.

Typed on touchscreen device

--
You received this message because you are subscribed to the Google Groups "mozilla-labs-jetpack" group.
To post to this group, send email to mozilla-la...@googlegroups.com.
To unsubscribe from this group, send email to mozilla-labs-jet...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/mozilla-labs-jetpack?hl=en.

Myk Melez

unread,
Nov 8, 2011, 2:14:30 AM11/8/11
to mozilla-la...@googlegroups.com, Irakli Gozalishvili
On 2011-11-04 07:20, Irakli Gozalishvili wrote:
>
> 1. -1 too magical & contradicts with idea that module exports are
> immutable after the are exported
>
Option 1 also seems fairly complicated relative to the others.

> 2. +1 I like that, also metadata could be shared if desired
> exports.module = module
> 3. +1 Can't decide if I prefer 2. or not, depends how often requirer
> will need this
> 4. +1 I like this as it makes clear that metadata is immutable at runtime,
>

I like these too. Between 2 and 3, 2 seems preferable to me, since it
doesn't add a symbol to every module's `exports` object, so it reduces
the surface area that modules expose by default.

Plus, currently there are no symbols in the `exports` namespace that are
special in any way, and the module has complete control over what to put
in that namespace; whereas 3 would make the `meta` symbol special.

And the "module" object seems like the more logical home for metadata
about the module anyway.

We could still implement some other way for modules to retrieve metadata
about other modules at runtime if that seems useful, f.e. via a
getMetadata method on the require method:

require.getMetadata("module")

And I wonder whether we need a "meta" object at all. Isn't this the
purpose of the 'module` object: to collect metadata about the module? It
seems like we should be able to hang this information directly off that
object.

> also I would go for the folllowing instead
>
> meta: ({ firefox: true })
>
> Label makes it easier to parse and read
>

I like the simplicity of this approach, but I'm concerned that it would
be ambiguous, since it doesn't mention compatibility.

Nevertheless, it's true that the word "compatibility" is fairly long and
complex. Since modules "require" other modules and "export"
functionality, we might say they "support" host applications and make
the meta object look like:

{ supports: ["firefox", "fennec"] }

Or:

{ supports: { firefox: true, fennec: true } }

> 5. -1 no syntax highlighting, no parse errors on mistypes
> 6. -1 yet another global :(
>

Indeed!

> 7. Mabe something like:
>
> module.meta({ .... })
>
> Just like 2. & also makes it more obvious that metadata is immutable.
>

Since this method, like the property assignment, happens at runtime,
might developers think they can call it again later?

Perhaps making developers define a constant would send the clearest signal:

const meta = { ... };

But I suspect it's sufficient to document that the object is immutable
and throw a friendly and informative exception if code tries to modify
it after defining it.

> Typed on touchscreen device
>
Wow, impressive! :-)

-myk

ZER0

unread,
Nov 8, 2011, 2:29:13 PM11/8/11
to mozilla-la...@googlegroups.com
On 11/08/11 8:14 AM, Myk Melez wrote:

[adding metadata to module object]

>> 2. +1 I like that, also metadata could be shared if desired
>> exports.module = module

> I like these too. Between 2 and 3, 2 seems preferable to me, since it


> doesn't add a symbol to every module's `exports` object, so it reduces
> the surface area that modules expose by default.

> Plus, currently there are no symbols in the `exports` namespace that are
> special in any way, and the module has complete control over what to put
> in that namespace; whereas 3 would make the `meta` symbol special.

> And the "module" object seems like the more logical home for metadata
> about the module anyway.

Good to see we're all on the same page! I also prefer use `module`
instead of `require`.

> We could still implement some other way for modules to retrieve metadata
> about other modules at runtime if that seems useful, f.e. via a
> getMetadata method on the require method:
>
> require.getMetadata("module")

Indeed!

> And I wonder whether we need a "meta" object at all. Isn't this the
> purpose of the 'module` object: to collect metadata about the module? It
> seems like we should be able to hang this information directly off that
> object.

True. I'm just worried that in this way `module` could be transformed in
a sort of "junk collector", where people add arbitrary stuff. Also, it
should be clear that `supports` is immutable and has a specific meaning
for the SDK.
Of course, we could `seal` the module itself.

>> also I would go for the folllowing instead
>>
>> meta: ({ firefox: true })

>> Label makes it easier to parse and read

Note that this approach made the label unusable as "label" (but I guess
it's perfectly fine in our case, we don't want use `continue` on that).

> I like the simplicity of this approach, but I'm concerned that it would
> be ambiguous, since it doesn't mention compatibility.

Well, can be easily transformed in:

supports: {firefox : true, fennec : true};

Or (I personally prefer this one):

supports: ["firefox", "fennec"];

I guess we agreed that the options available at the moment are:

a. Using module to store this information: adding a `supports` property
directly, or using a `metadata` property as middleman, decided if we
want seal it or not.

b. Using a JavaScript object (� la "use strict")

c. Using a label.

We should also think how the approach we will choose it will works in
case of additional future information (e.g. `experiment` boolean value,
or module's `version`).

ZER0

unread,
Nov 8, 2011, 8:01:04 PM11/8/11
to mozilla-la...@googlegroups.com
Rocketeers!

After a meeting, we filtered out the proposals to the one that use labels.

One proposal use one label to point to a JS object. So, an example of
module, could be:

"use strict";

// The module supports both Firefox and Fennec
meta: {
supports : ["Firefox", "Fennec"]
};

let app = require("api-utils/xul-app");

if (app.is("Firefox")) {
module.exports = require("foo-firefox");


} else if (app.is("Fennec")) {

module.exports = require("foo-fennec");
}

with more properties, will be:

"use strict";

// The module supports both Firefox and Fennec,
// and is marked as experimental
meta: {
supports : ["Firefox", "Fennec"],
flags: ["experimental"],
version: "0.1"
};

let app = require("api-utils/xul-app");

if (app.is("Firefox")) {
module.exports = require("foo-firefox");


} else if (app.is("Fennec")) {

module.exports = require("foo-fennec");
}

The second proposal, is use different labels without having a javascript
object but just primitives/array:

"use strict";

// The module supports both Firefox and Fennec
supports: ["Firefox", "Fennec"];

let app = require("api-utils/xul-app");

if (app.is("Firefox")) {
module.exports = require("foo-firefox");


} else if (app.is("Fennec")) {

module.exports = require("foo-fennec");
}

In that case, different properties will have different labels:

"use strict";

// The module supports both Firefox and Fennec
// and is marked as experimental
supports: ["Firefox", "Fennec"];
flags: ["experimental"];
version: "1.0";

let app = require("api-utils/xul-app");

if (app.is("Firefox")) {
module.exports = require("foo-firefox");


} else if (app.is("Fennec")) {

module.exports = require("foo-fennec");
}

Personally, although initially I was more in favor of the last approach,
now that I can see them on real code, if we can be strict about
definition of the meta's object, it's better have these metadata delimited.
Not sure honestly about the term "meta" as label's name.

What are you thoughts about it?

Myk Melez

unread,
Nov 9, 2011, 5:04:23 AM11/9/11
to mozilla-la...@googlegroups.com, ZER0
On 2011-11-08 17:01, ZER0 wrote:
Not sure honestly about the term "meta" as label's name.

What are you thoughts about it?
Bear in mind that you are asking a broad audience to help you paint a bicycle shed. ;-) Having said that...

How about "manifest"? The structure isn't a classic manifest file, but it contains the kind of information that would normally be contained in such a file. It's a kind of "inline manifest."

-myk

ZER0

unread,
Nov 9, 2011, 5:52:06 AM11/9/11
to Myk Melez, mozilla-la...@googlegroups.com
On 11/09/11 11:04 AM, Myk Melez wrote:

>> Not sure honestly about the term "meta" as label's name.

>> What are you thoughts about it?
> Bear in mind that you are asking a broad audience to help you paint a
> bicycle shed. ;-) Having said that...

Not sure what it means.. :) However, I was asking about the whole ideas,
not just the name, if it's that what you meant! :)

> How about "manifest"? The structure isn't a classic manifest file

> <http://en.wikipedia.org/wiki/Manifest_file>, but it contains the kind


> of information that would normally be contained in such a file. It's a
> kind of "inline manifest."

Ehe, when I wrote this email, it was my first attempt. :) Then I decided
to rollback to "meta" because was short, and I was worried that
"manifest" could be misleading. Honestly, the term that I personally
find to fit best is "module" itself, but of course can't be used. :)

Alexandre poirot

unread,
Nov 9, 2011, 9:00:48 AM11/9/11
to mozilla-la...@googlegroups.com
This syntax doesn't look valid: "meta: {}".
Did you meant: "meta = {}" ?

Having said that I prefer the solution using module as it limits the number of special globals.
Then I don't see that much value in such feature? The important part is about how we are going to load different pieces of code for each platform and this proposal doesn't digg this way, whereas it may have consequences on this metadata declaration.

2011/11/9 ZER0 <ze...@mozilla.com>

ZER0

unread,
Nov 9, 2011, 9:32:08 AM11/9/11
to mozilla-la...@googlegroups.com
On 11/09/11 15:00 PM, Alexandre poirot wrote:

> This syntax doesn't look valid: "meta: {}".
> Did you meant: "meta = {}" ?

I mean exactly "meta: {}", it's a label.

> Having said that I prefer the solution using module as it limits the
> number of special globals.

It's not a special global in fact! :)

> Then I don't see that much value in such feature? The important part is
> about how we are going to load different pieces of code for each
> platform

The important part is how we're going to add metadata to a specific
single module, and not to the whole package (with packages.json).

Then, we can use this information to specify which platform this module
support. As I wrote in my first post, this information will be parsed by
cfx in order to package the addon for the right platform, and have a
dependencies graph with the compatibilities for each module.

Loading different module's implementation "automagically" is not covered
by this proposal directly. As I shown in the code, is something you can
do it by your own, and you're interested in the running application at
runtime.

Alexandre poirot

unread,
Nov 9, 2011, 10:11:58 AM11/9/11
to mozilla-la...@googlegroups.com
This kind of labels?
https://developer.mozilla.org/en/JavaScript/Reference/Statements/label
I don't feel really confident about using a not so known JS feature.
It looks nice and simple but the syntax is hard to explain.
At first sight it will look like invalid JS code to many people!

Then as this feature is highly related to dynamic code loading,
it would make sense to ensure it fits this need.


2011/11/9 ZER0 <ze...@mozilla.com>

Irakli Gozalishvili

unread,
Nov 9, 2011, 7:01:38 PM11/9/11
to mozilla-la...@googlegroups.com
Alex,

Primary reason we for choosing labeled anonymous object over other options listed above was:

It's explicitness about the fact that metadata, is immutable (as there is no reference to it) and it's not part of the module implementation. Also, this is not something average developer will have to deal with. Explaining what code does should be as easy as explaining what "strict mode", in fact your link will be quite helpful:


BTW do you have a better option in mind ?

Irakli Gozalishvili

unread,
Nov 9, 2011, 7:03:45 PM11/9/11
to mozilla-la...@googlegroups.com
On Tuesday, 2011-11-08 at 17:01 , ZER0 wrote:
Not sure honestly about the term "meta" as label's name.
I personally like it a lot it's short and obvious, also other languages like clojure for example use meta for exact same purposes.

Alexandre poirot

unread,
Nov 10, 2011, 12:03:59 PM11/10/11
to mozilla-la...@googlegroups.com
2011/11/10 Irakli Gozalishvili <rfo...@gmail.com>

Alex,

Primary reason we for choosing labeled anonymous object over other options listed above was:

It's explicitness about the fact that metadata, is immutable (as there is no reference to it) and it's not part of the module implementation. Also, this is not something average developer will have to deal with. Explaining what code does should be as easy as explaining what "strict mode", in fact your link will be quite helpful:


BTW do you have a better option in mind ?

I don't know what we are going to do with these data, but I'd expect to use them during runtime. So that this choice won't simplify final implementation of it. Are we sure that this syntax is correct? Aren't we just lucky that something is accepted after a label? Then we have to be carefull when it comes to compile time parsing. Currently we only parse `require()`. It is simplier to match than this metadata object but we are not doing it very nicely! (I don't think we can build a regexp for JSON!)
Then about exclicitness, I don't see much differences between exports and meta, both are immutables.
Finally, if we start suggesting modules over packages for libraries, average developers will have to deal with this metadata object.

TBH I like the initial option 2:

module.meta = {"compatibility" : ["Firefox", "Fennec"]};

Do we plan to use versions?
module.meta = {"supports" : {"Firefox" : [7, "*"], "Fennec" : ['*', 9]}};


Irakli Gozalishvili

unread,
Nov 10, 2011, 6:51:25 PM11/10/11
to mozilla-la...@googlegroups.com

On Thursday, 2011-11-10 at 09:03 , Alexandre poirot wrote:

2011/11/10 Irakli Gozalishvili <rfo...@gmail.com>
Alex,

Primary reason we for choosing labeled anonymous object over other options listed above was:

It's explicitness about the fact that metadata, is immutable (as there is no reference to it) and it's not part of the module implementation. Also, this is not something average developer will have to deal with. Explaining what code does should be as easy as explaining what "strict mode", in fact your link will be quite helpful:


BTW do you have a better option in mind ?

I don't know what we are going to do with these data, but I'd expect to use them during runtime.

My understanding is that metadata is for cfx, so that it could strip out modules that are not relevant when building for specific platform. ZERO is that right ?
 
So that this choice won't simplify final implementation of it. Are we sure that this syntax is correct? Aren't we just lucky that something is accepted after a label?

Depends on definition of luck, initially ZERO suggested just anonymous object. IMO label makes it easier to parse out and gives bit of idea what this unassigned object is for.  
 
Then we have to be carefull when it comes to compile time parsing. Currently we only parse `require()`. It is simplier to match than this metadata object but we are not doing it very nicely! (I don't think we can build a regexp for JSON!)

It should be relatively easy:

1. Strip out all comments
2. Find /meta\:\S*\{/
3. Find matching /}/

everything between 2 and 3 is a json that can be parsed via JSON parser.
 
Then about exclicitness, I don't see much differences between exports and meta, both are immutables.

What I meant is this:

var metadata = {}
module.meta = metadata
setTimeout(function() {
metadata.foo = 'bar'
}) 

should this code be valid ? should it throw ?

Or what if:

module.meta = {
  get supports() {
    if (monday) {
return ...
    } else {
       return ...
    }
  }
}

just an object without any references to it does not rises those questions.

Finally, if we start suggesting modules over packages for libraries, average developers will have to deal with this metadata object.

TBH I like the initial option 2:
module.meta = {"compatibility" : ["Firefox", "Fennec"]};


I don't mind that too much, but still it raises questions mentioned above and make parsing even harder. 

James Burke

unread,
Nov 13, 2011, 9:01:32 PM11/13/11
to mozilla-labs-jetpack
On Nov 3, 7:39 am, ZER0 <z...@mozilla.com> wrote:
> We're thinking to give to every single module the capability to declare
> for which application is designed for (e.g. Firefox, Fennec, etc).
> [snip]
> But we think it should be better having this information at packaging
> time, using the `cfx` tool, that display a warning about that, without
> having to run the code. In addition, is some kind of information that is
> useful when we build the dependencies graph; and for sharing modules.

I am unclear on the need for individual modules in a package to need
to declare themselves with individual metadata. I can see the case for
saying "do it as a different package, or reserve a spot in the
package.json for this".

That said, in the AMD world, it is common that people will want to
deliver just one JS file as "the package", and requiring a
package.json file for just one file is not ergonomic. I was looking at
supporting the contents of the package.json in a JS comment, something
like:

/**package.json:
{...}
*/

Just an example, I do not really care what the comment format was,
just that it was a comment with a particular name that had a JSON blob
in it.

I favor a comment over JS code because this info is needed to set up a
project, but not needed at runtime, and for web deployment, using a
comment meant that it automatically got stripped when the code is
minified for deployment.

Jetpack's needs may be different, so feel free to disregard this. If
there was something that Jetpack chose that would fit for the AMD
world though, I would look at trying to reuse it.

James

Irakli Gozalishvili

unread,
Nov 14, 2011, 4:21:52 PM11/14/11
to mozilla-la...@googlegroups.com

On Sunday, 2011-11-13 at 18:01 , James Burke wrote:

On Nov 3, 7:39 am, ZER0 <z...@mozilla.com> wrote:
We're thinking to give to every single module the capability to declare
for which application is designed for (e.g. Firefox, Fennec, etc).
[snip]
But we think it should be better having this information at packaging
time, using the `cfx` tool, that display a warning about that, without
having to run the code. In addition, is some kind of information that is
useful when we build the dependencies graph; and for sharing modules.

I am unclear on the need for individual modules in a package to need
to declare themselves with individual metadata. I can see the case for
saying "do it as a different package, or reserve a spot in the
package.json for this".

In fact in long term we would like to get rid off packages, which is a reason why module based metadata becomes relevant (also not all the modules will come with metadata of course) 
 

That said, in the AMD world, it is common that people will want to
deliver just one JS file as "the package", and requiring a
package.json file for just one file is not ergonomic. I was looking at
supporting the contents of the package.json in a JS comment, something
like:

/**package.json:
{...}
*/

Just an example, I do not really care what the comment format was,
just that it was a comment with a particular name that had a JSON blob
in it.

I favor a comment over JS code because this info is needed to set up a
project, but not needed at runtime, and for web deployment, using a
comment meant that it automatically got stripped when the code is
minified for deployment.

We actually considered that as well, but what we thought was better with labeled objects was that editors could help editing and highlight errors in embedded JSON metadata. BTW closure compiler should be smart enough to strip out such un-refferenced objects as well, not sure about other minifiers though.   
 

Jetpack's needs may be different, so feel free to disregard this. If
there was something that Jetpack chose that would fit for the AMD
world though, I would look at trying to reuse it.

BTW main thing we need metadata today is to annotate modules which platforms they are compatible with. Also, so far we have very poor support for branching code paths depending on platform:


var foo = platform === 'bar' ? require('bar/foo') : require('baz/foo')

I can imagine you have much better pattern for requirejs, mind sharing that with us ?

Thanks! 

 

James

James Burke

unread,
Nov 14, 2011, 11:27:11 PM11/14/11
to mozilla-labs-jetpack
On Nov 14, 1:21 pm, Irakli Gozalishvili <rfo...@gmail.com> wrote:
> In fact in long term we would like to get rid off packages, which is a reason why module based metadata becomes relevant (also not all the modules will come with metadata of course)

I'm all for that. In particular, I do not like the package.json 'main'
property that needs to be used at runtime to resolve modules. I'm OK
with having a package.json with info about a collection of modules,
but I do not like the runtime tax with current CommonJS packages. It
requires more info to configure at runtime -- very awkward for web
loading.

> We actually considered that as well, but what we thought was better with labeled objects was that editors could help editing and highlight errors in embedded JSON metadata. BTW closure compiler should be smart enough to strip out such un-refferenced objects as well, not sure about other minifiers though.

Good point. However for me, labels just look unnatural, not idiomatic.
JSON errors from comments should be very visible, on first use of the
module I expect, and that info does not change very often. But this is
a style issue, YMMV.

> BTW main thing we need metadata today is to annotate modules which platforms they are compatible with. Also, so far we have very poor support for branching code paths depending on platform:
>
> var foo = platform === 'bar' ? require('bar/foo') : require('baz/foo')
>
> I can imagine you have much better pattern for requirejs, mind sharing that with us ?

Yes, this is a classic use case for a loader plugin in the AMD world.
In particular, I use an "env" plugin to do this:

var foo = require('env!env/foo')

Where the env plugin replaces the 'env/' part with the appropriate
environment and load it. So, in this use case, if the env plugin
determined it was running in the firefox env, it would load 'firefox/
foo'.

I use this approach in the requirejs optimizer to support both rhino
and node in one file, and I'm using this approach (with a different
implementation of the env plugin) for a phonegap-based project, where
it supports android, ios or plain web environments. Here is a link to
that loader plugin:

https://github.com/jrburke/submarine/blob/master/phonegap/www/js/env.js

Alexandre poirot

unread,
Nov 15, 2011, 9:48:46 AM11/15/11
to mozilla-la...@googlegroups.com
I really like the require's plugin. It allows to determine which file to load, and in our case, which file to ship in the XPI, with an unique pattern: require(...!dependency)



2011/11/15 James Burke <jrb...@gmail.com>

Irakli Gozalishvili

unread,
Feb 6, 2012, 2:31:19 PM2/6/12
to mozilla-la...@googlegroups.com
Coming back to this thread since ZER0 reminded me to do that :)

So I do like loader plugins as well, but it's something that we may get in a future and is independent of metadata proposal.
So my opinion still is the same I think, here is my list ordered by preference:

1. labeled objects meta: ({ … })
    Pros: 
- Explicit about the immutability
        - GC-ed on first gc cycle 
        - Minifies should be able to strip it out as unreferenced objects 
        - Editors may help catching errors
        - Easy to parse
    Cons:
        - Depends on non very popular JS feature (labels)
        - Some may confuse with meta = {} (I think we should wrap in parens, maybe even double meta: (({})) to make it stand out)

  2. Define as meta property for module: module.meta = { … }
      Pros:
 - Plain JS, no globals no exports just convention
      Cons:
         - May be defined in multiple expressions, making it hard to parse both by code and by eyes
         - We will look like plain js but we'll have to add limitations that may be confusing

With all pros and cons listed I think it would make sense to go with #1 and maybe refine that later. I could also be convinced in` #2 

Regards
--
Irakli Gozalishvili
Web: http://www.jeditoolkit.com/

Christoph Dorn

unread,
Feb 6, 2012, 3:30:51 PM2/6/12
to mozilla-la...@googlegroups.com

I beg you don't go down the loader plugin route which prefixes plugins to the require string literal:

� require("<plugin>!<id>");

'require()' is used to create a static link. That is it. If you use it for anything else it makes it a lot harder to use the module on other platforms or optimize a set of modules by pre-running plugins.

You can achieve the same using two other solutions:

� 1) If you have a module that should **always** be exposed in a certain way (e.g. coffescript), a "preloader" should be declared in package.json which can be run at optimization time or at dynamic load time.
� 2) If you have a module that should be exposed in more than one way you should be loading the source (after resolving the ID), modify it and then run it by passing it to a loader method or whatever. The application should include everything needed to do this and this process is not optimizable beyond what can be implemented in-application.

Don't confuse the two. (1) is critical for cross-loader optimization and (2) gives you complete flexibility without needing a loader to implement various plugins.

I would be happy to propose alternatives to various scenarios.

Ideally this should be discussed further on the CommonJS list as I know there are several key people who object to these loader plugins for various reasons. They are just not easily portable and bloat loader implementations too much.

See what can be done without them: https://github.com/sourcemint/loader-js

Christoph



Irakli Gozalishvili wrote:
Coming back to this thread since ZER0 reminded me to do that :)

So I do like loader plugins as well, but it's something that we may get in a future and is independent of metadata proposal.
So my opinion still is the same I think, here is my list ordered by preference:

1. labeled objects meta: ({ � })
� � Pros:�
-�Explicit about the immutability
� � � � - GC-ed on first gc cycle�
� � � � - Minifies should be able to strip it out as unreferenced objects�
� � � � - Editors may help catching errors
� � � � - Easy to parse
� � Cons:
� � � � - Depends on non very popular JS feature (labels)
� � � � - Some may confuse with meta = {} (I think we should wrap in parens, maybe even double meta: (({})) to make it stand out)

� 2. Define as meta property for module: module.meta = { � }
� � � Pros:
�- Plain JS, no globals no exports just convention
� � � Cons:
� � � � �- May be defined in multiple expressions, making it hard to parse both by code and by eyes
� � � � �- We will look like plain js but we'll have to add limitations that may be confusing

With all pros and cons listed I think it would make sense to go with #1 and maybe refine that later. I could also be convinced in` #2�

Regards

Reply all
Reply to author
Forward
0 new messages