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`.
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.
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 On Nov 3, 2011 8: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).
> 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`.
> 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.
> Note that the JavaScript object I used is not the definitive one.
> -- > 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-labs-jetpack@googlegroups.com > . > To unsubscribe from this group, send email to > mozilla-labs-jetpack+unsubscribe@googlegroups.com. > For more options, visit this group at > http://groups.google.com/group/mozilla-labs-jetpack?hl=en.
> 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.
>> 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`).
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.
> 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 <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."
>> 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. :)
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.
> 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?
> -- > 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-labs-jetpack@googlegroups.com > . > To unsubscribe from this group, send email to > mozilla-labs-jetpack+unsubscribe@googlegroups.com. > For more options, visit this group at > http://groups.google.com/group/mozilla-labs-jetpack?hl=en.
> 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.
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.
> > 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.
> -- > 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-labs-jetpack@googlegroups.com > . > To unsubscribe from this group, send email to > mozilla-labs-jetpack+unsubscribe@googlegroups.com. > For more options, visit this group at > http://groups.google.com/group/mozilla-labs-jetpack?hl=en.
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:
On Wednesday, 2011-11-09 at 07:11 , Alexandre poirot wrote: > 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.
> > > 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.
> > -- > > 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-labs-jetpack@googlegroups.com (mailto:mozilla-labs-jetpack@googlegroups.com). > > To unsubscribe from this group, send email to mozilla-labs-jetpack+unsubscribe@googlegroups.com (mailto:mozilla-labs-jetpack%2Bunsubscribe@googlegroups.com). > > For more options, visit this group at http://groups.google.com/group/mozilla-labs-jetpack?hl=en.
> -- > 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-labs-jetpack@googlegroups.com (mailto:mozilla-labs-jetpack@googlegroups.com). > To unsubscribe from this group, send email to mozilla-labs-jetpack+unsubscribe@googlegroups.com (mailto:mozilla-labs-jetpack+unsubscribe@googlegroups.com). > For more options, visit this group at http://groups.google.com/group/mozilla-labs-jetpack?hl=en.
> 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:
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]}};
> On Wednesday, 2011-11-09 at 07:11 , Alexandre poirot wrote:
> 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.
> > 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.
> -- > 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-labs-jetpack@googlegroups.com > . > To unsubscribe from this group, send email to > mozilla-labs-jetpack+unsubscribe@googlegroups.com. > For more options, visit this group at > http://groups.google.com/group/mozilla-labs-jetpack?hl=en.
> -- > 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-labs-jetpack@googlegroups.com > . > To unsubscribe from this group, send email to > mozilla-labs-jetpack+unsubscribe@googlegroups.com. > For more options, visit this group at > http://groups.google.com/group/mozilla-labs-jetpack?hl=en.
> -- > 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-labs-jetpack@googlegroups.com > . > To unsubscribe from this group, send email to > mozilla-labs-jetpack+unsubscribe@googlegroups.com. > For more options, visit this group at > http://groups.google.com/group/mozilla-labs-jetpack?hl=en.
On Thursday, 2011-11-10 at 09:03 , Alexandre poirot wrote: > 2011/11/10 Irakli Gozalishvili <rfo...@gmail.com (mailto: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:
> 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.
> > On Wednesday, 2011-11-09 at 07:11 , Alexandre poirot wrote:
> > > 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.
> > > > > 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.
> > > > -- > > > > 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-labs-jetpack@googlegroups.com (mailto:mozilla-labs-jetpack@googlegroups.com). > > > > To unsubscribe from this group, send email to mozilla-labs-jetpack+unsubscribe@googlegroups.com (mailto:mozilla-labs-jetpack%2Bunsubscribe@googlegroups.com). > > > > For more options, visit this group at http://groups.google.com/group/mozilla-labs-jetpack?hl=en.
> > > -- > > > 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-labs-jetpack@googlegroups.com (mailto:mozilla-labs-jetpack@googlegroups.com). > > > To unsubscribe from this group, send email to mozilla-labs-jetpack+unsubscribe@googlegroups.com (mailto:mozilla-labs-jetpack+unsubscribe@googlegroups.com). > > > For more options, visit this group at http://groups.google.com/group/mozilla-labs-jetpack?hl=en.
> > -- > > 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-labs-jetpack@googlegroups.com (mailto:mozilla-labs-jetpack@googlegroups.com). > > To unsubscribe from this group, send email to mozilla-labs-jetpack+unsubscribe@googlegroups.com (mailto:mozilla-labs-jetpack%2Bunsubscribe@googlegroups.com). > > For more options, visit this group at http://groups.google.com/group/mozilla-labs-jetpack?hl=en.
> -- > 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-labs-jetpack@googlegroups.com (mailto:mozilla-labs-jetpack@googlegroups.com). > To unsubscribe from this group, send email to mozilla-labs-jetpack+unsubscribe@googlegroups.com (mailto:mozilla-labs-jetpack+unsubscribe@googlegroups.com). > For more options, visit this group at http://groups.google.com/group/mozilla-labs-jetpack?hl=en.
> 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.
On Sunday, 2011-11-13 at 18:01 , James Burke wrote: > On Nov 3, 7:39 am, ZER0 <z...@mozilla.com (http://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 ?
> -- > 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-labs-jetpack@googlegroups.com (mailto:mozilla-labs-jetpack@googlegroups.com). > To unsubscribe from this group, send email to mozilla-labs-jetpack+unsubscribe@googlegroups.com (mailto:mozilla-labs-jetpack+unsubscribe@googlegroups.com). > For more options, visit this group at http://groups.google.com/group/mozilla-labs-jetpack?hl=en.
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:
> 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:
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)
> 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:
> > 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:
> -- > 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-labs-jetpack@googlegroups.com > . > To unsubscribe from this group, send email to > mozilla-labs-jetpack+unsubscribe@googlegroups.com. > For more options, visit this group at > http://groups.google.com/group/mozilla-labs-jetpack?hl=en.
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/
On Tuesday, 2011-11-15 at 06:48 , Alexandre poirot wrote: > 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 <jrbu...@gmail.com (mailto:jrbu...@gmail.com)> > > On Nov 14, 1:21 pm, Irakli Gozalishvili <rfo...@gmail.com (mailto: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:
> > > 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:
> > -- > > 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-labs-jetpack@googlegroups.com (mailto:mozilla-labs-jetpack@googlegroups.com). > > To unsubscribe from this group, send email to mozilla-labs-jetpack+unsubscribe@googlegroups.com (mailto:mozilla-labs-jetpack%2Bunsubscribe@googlegroups.com). > > For more options, visit this group at http://groups.google.com/group/mozilla-labs-jetpack?hl=en.
> -- > 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-labs-jetpack@googlegroups.com (mailto:mozilla-labs-jetpack@googlegroups.com). > To unsubscribe from this group, send email to mozilla-labs-jetpack+unsubscribe@googlegroups.com (mailto:mozilla-labs-jetpack+unsubscribe@googlegroups.com). > For more options, visit this group at http://groups.google.com/group/mozilla-labs-jetpack?hl=en.
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.
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