1.5 The "require" function may have a "main" property that is read-only, don't delete and represents the top-level "module" object of the program. If this property is provided, it must be referentially identical to the "module" object of the main program.Ok, so I have two problems with this. I don't know of a way other than defineProperty that allows you to set a read-only don't delete attribute like this so does this mean this specification only works with ES5?
3.1 The "module" object must have a read-only, don't delete "id" property that is the top-level "id" of the module. The "id" property must be such that require(module.id) will return the exports object from which the module.id originated. (That is to say module.id can be passed to another module, and requiring that must return the original module).Again, read-only === ES5.
3.2 The "module" object may have a "uri" String that is the fully-qualified URI to the resource from which the module was created. The "uri" property must not exist in a sandbox.Does this mean that the attribute must start with http:// or file:// or some other standard URI prefix? This clearly isn't applicable when importing packages inside of a sandbox that doesn't allow IO which is fine since it's optional but this attribute might be in conflict with point 1 in the Unspecified section which states this specification does not define how modules are stored.
In reviewing the Modules 1.1 specification I ran in to a few hickups trying to figure out what some of the points mean within the CouchDB view server implementation.
CouchDB is a weird case, modules aren't loaded over http or the filesystem but instead are strings attached to the design document. This is nice because we don't have to do any IO to load modules and each design document becomes it's own sandbox. This case is a little odd next to the existing Modules implementations but as we create more sandboxed implementations this approach might be more common since it allows a sandbox to exclude access to sockets and the filesystem entirely.
1.5 The "require" function may have a "main" property that is read-only, don't delete and represents the top-level "module" object of the program. If this property is provided, it must be referentially identical to the "module" object of the main program.Ok, so I have two problems with this. I don't know of a way other than defineProperty that allows you to set a read-only don't delete attribute like this so does this mean this specification only works with ES5?
The other problem I have is that the whole idea of a "main" is specific to SSJS, which is fine if the property is not required but I would hope that if not applicable require.main would be set to null for easier comparison operations and the attribute actually be required.
In fact, when attempting to use this attribute in a Modules 1.0 implementation ( require.main === module ) is always true because both are undefined, which is exactly the opposite behavior you would want.
3.1 The "module" object must have a read-only, don't delete "id" property that is the top-level "id" of the module. The "id" property must be such that require(module.id) will return the exports object from which the module.id originated. (That is to say module.id can be passed to another module, and requiring that must return the original module).Again, read-only === ES5.
3.2 The "module" object may have a "uri" String that is the fully-qualified URI to the resource from which the module was created. The "uri" property must not exist in a sandbox.Does this mean that the attribute must start with http:// or file:// or some other standard URI prefix? This clearly isn't applicable when importing packages inside of a sandbox that doesn't allow IO which is fine since it's optional but this attribute might be in conflict with point 1 in the Unspecified section which states this specification does not define how modules are stored.
*All* JS embeddings let you set this that the C level. If this really can't be done from within CouchDB its not a gross abuse to just set it as a normal property.On 22 Mar 2010, at 18:06, Mikeal Rogers wrote:In reviewing the Modules 1.1 specification I ran in to a few hickups trying to figure out what some of the points mean within the CouchDB view server implementation.
CouchDB is a weird case, modules aren't loaded over http or the filesystem but instead are strings attached to the design document. This is nice because we don't have to do any IO to load modules and each design document becomes it's own sandbox. This case is a little odd next to the existing Modules implementations but as we create more sandboxed implementations this approach might be more common since it allows a sandbox to exclude access to sockets and the filesystem entirely.
1.5 The "require" function may have a "main" property that is read-only, don't delete and represents the top-level "module" object of the program. If this property is provided, it must be referentially identical to the "module" object of the main program.Ok, so I have two problems with this. I don't know of a way other than defineProperty that allows you to set a read-only don't delete attribute like this so does this mean this specification only works with ES5?
You'd have to check that the module is not undefined first, but hopefully there will be fewer 1.0 impls out there going forward so this problem should vanish over time.
In fact, when attempting to use this attribute in a Modules 1.0 implementation ( require.main === module ) is always true because both are undefined, which is exactly the opposite behavior you would want.
3.2 The "module" object may have a "uri" String that is the fully-qualified URI to the resource from which the module was created. The "uri" property must not exist in a sandbox.Does this mean that the attribute must start with http:// or file:// or some other standard URI prefix? This clearly isn't applicable when importing packages inside of a sandbox that doesn't allow IO which is fine since it's optional but this attribute might be in conflict with point 1 in the Unspecified section which states this specification does not define how modules are stored.
No, any scheme: you like is perfectly valid. Something like "couchdb://db/collection/id#moduleName" would be fine, or any of the many possible ways you could combine/generate something unique. Fully qualified just means 'make it as global as is reasonable for your embedding' (or thats what I meant it to mean - I added the .url property)
Ok, so I have two problems with this. I don't know of a way other than defineProperty that allows you to set a read-only don't delete attribute like this so does this mean this specification only works with ES5?
The other problem I have is that the whole idea of a "main" is specific to SSJS, which is fine if the property is not required but I would hope that if not applicable require.main would be set to null for easier comparison operations and the attribute actually be required.
3.2 The "module" object may have a "uri" String that is the fully-qualified URI to the resource from which the module was created. The "uri" property must not exist in a sandbox.Does this mean that the attribute must start with http:// or file:// or some other standard URI prefix? This clearly isn't applicable when importing packages inside of a sandbox that doesn't allow IO which is fine since it's optional but this attribute might be in conflict with point 1 in the Unspecified section which states this specification does not define how modules are stored.
~Daniel Friesen (Dantman, Nadir-Seen-Fire) [http://daniel.friesen.name]
On Mon, Mar 22, 2010 at 2:06 PM, Mikeal Rogers <mikeal...@gmail.com> wrote:Ok, so I have two problems with this. I don't know of a way other than defineProperty that allows you to set a read-only don't delete attribute like this so does this mean this specification only works with ES5?
JS_DefineProperty() will do this with flags JSPROP_READONLY | JSPROP_PERMANENTThe other problem I have is that the whole idea of a "main" is specific to SSJS, which is fine if the property is not required but I would hope that if not applicable require.main would be set to null for easier comparison operations and the attribute actually be required.
"main" is whatever context the top-most require() runs in. You can't have modules in isolation, something has to require them. That's main.
I think you've made a lot of good points. If you have the time to
fork Modules/1.1 (and also Packages/1.0) as a lettered proposal and
then make some changes (so we can watch the diffs), I think we could
be on our way to another point revision of both.
In verbiage, I'd rather not introduce the "should" moral imperative.
Let's use "may" or "must" strictly, and fill out any surrounding
criteria so the behaviors are detectable.
You raise a good point about the require.main == module or
require.main === module idiom (I'm using == in Narwhal since we have a
migration shim from the older proposal where require.main ===
module.id). We should specify a working solution for systems that
have no "main", preferably backward compatible. I'd like to hear
ideas.
Kris Kowal
--
You received this message because you are subscribed to the Google Groups "CommonJS" group.
To post to this group, send email to comm...@googlegroups.com.
To unsubscribe from this group, send email to commonjs+u...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/commonjs?hl=en.
> It is entirely possible to define a sandbox with a require function that itself cannot be requiredNot if I read the modules specification correctly when I was implementing -- there is even a test suite test that tests this, I believe.
Now I'm not saying this is good or bad -- just pointing it out in case the modules proposal gets evolved one more step.
What scope object do you use for evaluating these functions? Do you execute them with your global object as the scope object?
> For instance, CouchDB show and list definitions MUST be function literals and are not
> expected to be valid CommonJS modules
How I set GPSEE up is to make the global object a slightly special-cased module scope; it has exports, module, and require just like any other module scope. It's slightly special-cased because a) it doesn't executed as the result of a require statement, and b) I take steps make sure require(module.id) works as expected.
Incidentally, are you supporting arbitrary native modules, or only JS-language modules? If you want to support native modules, it's probably worth our while to work together, at least at the module C API level.
On Mon, Mar 22, 2010 at 11:06 AM, Mikeal Rogers <mikeal...@gmail.com> wrote:I think you've made a lot of good points. If you have the time to
> In reviewing the Modules 1.1 specification I ran in to a few hickups trying
> to figure out what some of the points mean within the CouchDB view server
> implementation.
fork Modules/1.1 (and also Packages/1.0) as a lettered proposal and
then make some changes (so we can watch the diffs), I think we could
be on our way to another point revision of both.
In verbiage, I'd rather not introduce the "should" moral imperative.
Let's use "may" or "must" strictly, and fill out any surrounding
criteria so the behaviors are detectable.
You raise a good point about the require.main == module or
require.main === module idiom (I'm using == in Narwhal since we have a
migration shim from the older proposal where require.main ===
module.id). We should specify a working solution for systems that
have no "main", preferably backward compatible. I'd like to hear
ideas.
Alas, nothing better than copy and paste.
> In the case that a certain behavior is not required but encouraged is there
> a specific verbiage we should use?
Not really. We don't have any formal guidelines or patterns. I try to
keep non-normative, untestable stuff in an italicized ''Note:'' block
or in a footnote.
> One solution is to set require.main to {} when not applicable. I don't like
> the way that it looks, but it's truthy so it won't compare well against
> undefined unlike null.
Sounds good to me.
Kris Kowal
Also perhaps a side note, but if implementations are using an actual
Module class (the interoperablejs tests used to have tests for a
require.Module) and making module objects instances of that, it would be
nice for the object to have the same prototype.
~Daniel Friesen (Dantman, Nadir-Seen-Fire) [http://daniel.friesen.name]
> module.id <http://module.id>). We should specify a working
> solution for systems that
> have no "main", preferably backward compatible. I'd like to hear
> ideas.
>
> Kris Kowal
>
> --
> You received this message because you are subscribed to the Google
> Groups "CommonJS" group.
> To post to this group, send email to comm...@googlegroups.com
> <mailto:comm...@googlegroups.com>.
> To unsubscribe from this group, send email to
> commonjs+u...@googlegroups.com
> <mailto:commonjs%2Bunsu...@googlegroups.com>.
Thanks, these revisions look great.
The only verbiage that worries me is "top-level object". This could
mean a variety of things, some of which are terribly wrong. I think
this has to mean: "the "module" object in the context of the first
module instantiated of the running program. If you agree, I'll patch
the draft myself.
I also don't think it's necessary to equivocate about what "main"
should be if there is no main. I think it's fine to state explicitly
that it must be an empty object, maybe even something specific so
people can test whether there is a main; though, the obvious
candidate, "global", is flawed since there will likely be future ES
strict worlds where such an object does not exist.
Kris Kowal
The tricky part is wrapping a new require function for each module with a reference to it's parent since there is no other way to keep track of where the module was imported in the property tree to support relative imports.
We don't do anything in C. It's all stuff that we pipe directly to the spidermonkey js process which is started as a subprocess from Erlang. At some later date we may run this directly inside of an Erlang "process" using erlang_js.
On Tue, Mar 23, 2010 at 6:28 PM, Mikeal Rogers <mikeal...@gmail.com> wrote:Thanks, these revisions look great.
> Ok, I "forked" the 1.1 specification and wrote up a draft for 1.2
>
> http://wiki.commonjs.org/wiki/Modules/1.2
>
> I also made sure to stagger and comment my changes so it's easy to view the
> diffs from the 1.1 proposal
>
> http://wiki.commonjs.org/index.php?title=Modules/1.2&action=history
>
> My goal with with this draft is to only refine key points of the 1.1
> specification to allow CouchDB and future implementations to write compliant
> implementations and not to introduce new features or deprecations so that
> most, if not all, existing 1.1 implementations would already be compliant
> with 1.2
The only verbiage that worries me is "top-level object". This could
mean a variety of things, some of which are terribly wrong. I think
this has to mean: "the "module" object in the context of the first
module instantiated of the running program. If you agree, I'll patch
the draft myself.
I also don't think it's necessary to equivocate about what "main"
should be if there is no main. I think it's fine to state explicitly
that it must be an empty object, maybe even something specific so
people can test whether there is a main; though, the obvious
candidate, "global", is flawed since there will likely be future ES
strict worlds where such an object does not exist.
The idea you're expressing in this proposal is indeed more subtle than
I was expecting. Thanks.
On Tue, Mar 23, 2010 at 8:24 PM, Mikeal Rogers
<mikeal...@gmail.com> wrote:
>> The only verbiage that worries me is "top-level object". This
>> could mean a variety of things, some of which are terribly wrong.
>> I think this has to mean: "the "module" object in the context of
>> the first module instantiated of the running program. If you
>> agree, I'll patch the draft myself.
> So, what I mean to say is "this must at least be {} but you can do whatever
> you want if your top-level scope is not a module" but perhaps the phrasing
> is inadequate currently as: "If the top-level object of a program is not a
> module this attribute must be set to an object even if it is empty."
Taking a step back, the known purposes of require.main are:
1.) within a module, to detect whether the module is the entry point,
which dictates whether to take control of the program.
if (require.main == module) …
2.) to require the main module, which is handy for grabbing
configuration from its exports.
require(require.main.id)
Neither of these use-cases are relevant outside a module. In CouchDB,
the first case should never be trigged in a module, and the second
would never be done inside a module, and require() would have to throw
an error. In both cases, it would be sufficent for main to be an
empty object. It would be potentially misleading for it to be an
object with an "id" property, since the second case must fail.
So, I'm not sure it would be good to permit extensions to the "main"
object if it's not related to a real module. I'm interested if you
have a different use for "main".
I can see why you wouldn't want "the first module to be executed" to
provide the "main" object. The same argument could be made for
browsers, although I personally prefer there to be a single entry
point module for my client-side code, with no inline scripts or
wrapper scripts filled with islanded code. It might be possible to
achieve something like that if the external "require" function were
only permitted to be called once, to specify an entry point, but
that's entirely up to you as far as I'm concerned. Perhaps:
The "require" function may have a "main" property. The "main"
property must be an Object. The "main" object may be either empty
or be the "module" object in the context of one loaded module.
Kris Kowal
Kris Kowal
Alright, here's the change:
http://wiki.commonjs.org/index.php?title=Modules%2F1.2&diff=2497&oldid=2494
Does anyone else have outstanding issues with these revisions? These
changes are very minor. I would venture to call it 1.1.1, or to back
port these changes over the existing 1.1 spec since I don't think they
will cause anyone to fall out of compatibility.
Kris Kowal
I've had a strong issue with the restriction modules place on scope from
the beginning, and it makes things troublesome for my own code. So
MonkeyScript is being designed to work both with modules and classic
load style code (course they blend together very well). So the main
script executed can either be a module or a plain script (well actually
in the previous Lite you could also `monkeyscript
javascript:"print('foo');"` but that's a side point) in the case of
running a module require.main works as expected (potentially even using
an absolute file), but in the case of a normal script being executed
.main would be a non-module, but the main executed thing is still a file
on the system so I feel like putting the script's url into the .main.url
to match up with the behavior of when you execute a module.
~Daniel Friesen (Dantman, Nadir-Seen-Fire) [http://daniel.friesen.name]
> if (require.main == module) �
>
> 2.) to require the main module, which is handy for grabbing
> configuration from its exports.
>
> require(require.main.id <http://require.main.id>)
> <mailto:comm...@googlegroups.com>.
> To unsubscribe from this group, send email to
> commonjs+u...@googlegroups.com
> <mailto:commonjs%2Bunsu...@googlegroups.com>.
1.1.1 - using semver is good. (Of course there is nothing to say that going to here 1.2 is forbidden under semver)
Adding a .path property as well as a .uri property perhaps? I believe this has been mentioned in passing before. Path would be optional, uri (file:// if nothing else) should be required?
The other thing that is maybe worth adding is module.resource - use case is basicaly to access content next to a module on disk:
module.resource("image.jpg")
As it stands in flusspferd we have that returning a opened, readable stream, and module.resource.resolve(name) returning a path. But the feature is more important to me than the exact implementation details. Thoughts?
-ash
1.1.1 - using semver is good. (Of course there is nothing to say that going to here 1.2 is forbidden under semver)
The other thing that is maybe worth adding is module.resource - use case is basicaly to access content next to a module on disk:
module.resource("image.jpg")
Ash, Wes,
Since we appear to agree about the work so far, I think we should
stamp and one of you ought to fork it. Adding .resource is definitely
a 1.2 feature, not just editorial. .uri and .path should not be
required, but we should specify them. But consensus isn't cheap and I
think we should reward Mikael with an expedient rev for his effort.
Kris Kowal
In ringojs we have a module.directory property in addition to
module.path as a shortcut to fs.directory(module.path). It's quite
handy for a number of occasions, and I just mention that in case
somebody else thinks it's a good idea.
> The other thing that is maybe worth adding is module.resource - use case is basicaly to access content next to a module on disk:
>
> module.resource("image.jpg")
>
> As it stands in flusspferd we have that returning a opened, readable stream, and module.resource.resolve(name) returning a path. But the feature is more important to me than the exact implementation details. Thoughts?
Would module.resource() use file or module semantics? In other words,
would "image.jpg" denote a resource relative to the current module, or
would that be a top-level resource and only "./image.jpg" be relative?
I'll argue that it has to be the latter, else it becomes impossible to
specify absolute ids/paths.
One limitation with module.resource() is that it is only usable from
within the module (apart from require.main, obviously). In ringo, we
have therefore chosen to implement this as an external utility
function called resolveId() that resolves a module id path relative to
another one:
http://ringojs.org/api/ringo/fileutils#resolveId
I think these are things to consider when adding an API/amendment for
accessing resources on the module path.
Hannes
> -ash
On 24 Mar 2010, at 19:23, Kris Kowal wrote:
> On Wed, Mar 24, 2010 at 5:16 AM, Wes Garland <w...@page.ca> wrote:
>>> 1.1.1 - using semver is good. (Of course there is nothing to say that
>>> going to here 1.2 is forbidden under semver)
>> +1.0.0
>
> Ash, Wes,
>
> Since we appear to agree about the work so far, I think we should
> stamp and one of you ought to fork it. Adding .resource is definitely
> a 1.2 feature, not just editorial. .uri and .path should not be
> required, but we should specify them. But consensus isn't cheap and I
> think we should reward Mikael with an expedient rev for his effort.
>
> Kris Kowal
Good point.
On 24 Mar 2010, at 20:40, Hannes Wallnoefer wrote:
> 2010/3/24 Ash Berlin <ash_flu...@firemirror.com>:
>>
>> Adding a .path property as well as a .uri property perhaps? I believe this has been mentioned in passing before. Path would be optional, uri (file:// if nothing else) should be required?
>
> In ringojs we have a module.directory property in addition to
> module.path as a shortcut to fs.directory(module.path). It's quite
> handy for a number of occasions, and I just mention that in case
> somebody else thinks it's a good idea.
The way I envisage things module.directory would be the same as module.resource('.')
>
>> The other thing that is maybe worth adding is module.resource - use case is basicaly to access content next to a module on disk:
>>
>> module.resource("image.jpg")
>>
>> As it stands in flusspferd we have that returning a opened, readable stream, and module.resource.resolve(name) returning a path. But the feature is more important to me than the exact implementation details. Thoughts?
>
> Would module.resource() use file or module semantics? In other words,
> would "image.jpg" denote a resource relative to the current module, or
> would that be a top-level resource and only "./image.jpg" be relative?
> I'll argue that it has to be the latter, else it becomes impossible to
> specify absolute ids/paths.
File semantics i think. 'image.jpg' and './image.jpg' would both be the picture file that is in the same directory as the module. Except of course it could also return URL as string (or what ever else we decide) representing a HTTP resource, not just file on disk.
>
> One limitation with module.resource() is that it is only usable from
> within the module (apart from require.main, obviously). In ringo, we
> have therefore chosen to implement this as an external utility
> function called resolveId() that resolves a module id path relative to
> another one:
>
> http://ringojs.org/api/ringo/fileutils#resolveId
>
> I think these are things to consider when adding an API/amendment for
> accessing resources on the module path.
Agreed - the way I've gotten around this problem is to pass/require to be passed in the module object from the module in question. With the exception of the (proposed) setExports behaviour, is there any danger to providing a method to get this resource() behaviour for any module?
Let's start a new thread for .resource. I think this one has wrapped
around the planet a few times this week.
Kris Kowal