Proposal: module.resolve()

2 views
Skip to first unread message

George Moschovitis

unread,
Sep 12, 2009, 5:34:44 AM9/12/09
to CommonJS
Narwhal includes a convenient .resolve() function in the Path object.
I would like to propose that we add we add a resolve() function to the
'module' free variable:

var Path = require("file").Path;

module.resolve = function(path) {
return new Path(this.path).resolve(path);
}

Using this function we can easily create paths relative to the current
module:

var str = module.resolve("../templates/home.html").read();

-g.

Daniel Friesen

unread,
Sep 12, 2009, 6:41:19 AM9/12/09
to comm...@googlegroups.com
Some sort of getResource was discussed in a past thread.
require() may be used in dozens of contexts. On the filesystem, on the
web, in a database, js embedded into templates in a Wiki, packaged up
into something like a .jar .tar, or even compress by gzip, and so on...

IMHO, a path is a bad way to represent this.

My vote:

-1 to something that resolves a path
+.5 to something like getResource() which may follow a similar to the
kind of rules that we have in require already and returns a stream as
defined in the IO/* we chose.
+.5 to something that resolves an absolute url relative to the module. A
url is more reasonable to represent something on the filesystem, in a
package database (there's already one for jars, and that could easily
inspire one that applies to zips), or in the various locations. The only
thing an implementation needs to do is support creating those urls, and
support extracting data from those urls in whatever generic method we give.

~Daniel Friesen (Dantman, Nadir-Seen-Fire) [http://daniel.friesen.name]

George Moschovitis

unread,
Sep 12, 2009, 7:05:05 AM9/12/09
to CommonJS
What you say sounds reasonable.
What I am looking for is a way to access a 'resource' relative to a
module.
There are more clever people on this list to work out the
implementation/api details ;-)

-g.

Wes Garland

unread,
Sep 12, 2009, 9:03:34 AM9/12/09
to comm...@googlegroups.com
I agree with George on this one: that's a valueable addition, however it winds up being implemented.

It means you can do things like find config files based upon the module's install location, which is part of a relocatable package system requirement.

Maybe a module-relative stream open command instead?  That way the module could be on disk, database, HTTP, etc.

var stream = module.related.open("r");

or something

Wes

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

Kris Kowal

unread,
Sep 12, 2009, 3:56:04 PM9/12/09
to comm...@googlegroups.com
On Sat, Sep 12, 2009 at 6:03 AM, Wes Garland <w...@page.ca> wrote:
> I agree with George on this one: that's a valueable addition, however it
> winds up being implemented.
>
> It means you can do things like find config files based upon the module's
> install location, which is part of a relocatable package system requirement.
>
> Maybe a module-relative stream open command instead?  That way the module
> could be on disk, database, HTTP, etc.
>
> var stream = module.related.open("r");
>
> or something

I think the original idea was something like:

module.resource(id).open(…);

where id conforms to our notions of relative and top level
identifiers. The resource, in this case would have to be in the
module library paths.

Tom has also been asking for package relative resources. Presently,
we do not maintain a reference between modules and the package that
contains them, but that is likely change, I think, as there are other
package-relative features seemingly in the works.

Ihab had an idea of using something like # or ! as a package relative
root for another feature we've been discussing offlist, but the intent
was for that to be like a top-level identifier that's restricted to
the current package as a self-defence mechanism for packages for
downloaded modules mixed with less suspicious packages. That needs
further thought.

require("#./only-my-modules");

But perhaps an identifier prefix would be good for package root
relative resource identifiers, e.g.,

module.resource("@media/icons/logo-512.png")
.open("rb")
.copy(system.stdout);

Kris Kowal

Wes Garland

unread,
Sep 12, 2009, 6:07:22 PM9/12/09
to comm...@googlegroups.com
I'm still wondering how require("#./only-my-modules"); differs from require("./only-my-modules");

Module names starting with . are not supposed to be searched on the module path, anyhow.

Kris Kowal

unread,
Sep 12, 2009, 6:14:35 PM9/12/09
to comm...@googlegroups.com
On Sat, Sep 12, 2009 at 3:07 PM, Wes Garland <w...@page.ca> wrote:
> I'm still wondering how require("#./only-my-modules"); differs from
> require("./only-my-modules");
>
> Module names starting with . are not supposed to be searched on the module
> path, anyhow.

In Narwhal, they are. The only difference between relative and
top-level in Narwhal, with regard to module path searching, is that a
relative identifier gets converted to a top-level identifier by
resolving it against the top-level identifier of the calling module.

I presume that your implementation resolves the identifier against the
calling module's canonical path instead of its top-level identifier.

This is an area that the specification does not yet address, but it is
likely to be important if we standardize packaging. I think it's
important that we keep paths and identifiers decoupled in the interest
of maintaining the possibility of non-path-like module storage
systems.

Kris Kowal

Wes Garland

unread,
Sep 12, 2009, 9:45:12 PM9/12/09
to comm...@googlegroups.com
That's odd. I was pretty sure that the require() argument had been finalized as such:
 - If it starts with "./" or "../", it is relative to the current module
 - If it starts with "/" the behaviour is undefined
 - If it starts with anything else it's searched on the module path
 - Programs are modules

That's how GPSEE is implemented, and it used to pass the test suite.  How about helma, v8cgi and flusspferd?

Wes

--

Tom Robinson

unread,
Sep 13, 2009, 5:15:16 AM9/13/09
to comm...@googlegroups.com
They are relative, just not necessarily on disk.

Kris Kowal

unread,
Sep 13, 2009, 5:30:19 AM9/13/09
to comm...@googlegroups.com
On Sat, Sep 12, 2009 at 6:45 PM, Wes Garland <w...@page.ca> wrote:
> That's how GPSEE is implemented, and it used to pass the test suite.  How
> about helma, v8cgi and flusspferd?

None of the tests in the suite address behaviors of modules in
different library paths because library paths are not a feature
required by the specification. So, this is definitely a grey area.

We may want to make some extensions to the standard, for loaders that
have certain things in common, like packages and load paths. These
would not be mandatory or applicable to all CommonJS module system
implementation, but would give us some additional consistency among
our file-system based implementations and alternately database backed
or all http based implementations.

Kris Kowal

sleepnova

unread,
Sep 15, 2009, 3:35:24 AM9/15/09
to CommonJS
If you ever seen JSEXT ActiveDirectory API before?
It's a fancy way to map files and directories (path context) to
properties and objects (js object context).
I think it would be convent to have this kind of high level API for
both File and Module resource access.

JSEXT ActiveDirectory - http://jsext.sourceforge.net/JSEXT1.ActiveDirectory.html

Daniel Friesen

unread,
Sep 15, 2009, 7:12:05 PM9/15/09
to comm...@googlegroups.com
Something like that can easily be implemented using level 1 filesystem
as a module.

~Daniel Friesen (Dantman, Nadir-Seen-Fire) [http://daniel.friesen.name]

Hannes Wallnoefer

unread,
Sep 16, 2009, 4:16:02 AM9/16/09
to CommonJS
I agree this is a needed feature, especially for retrieving resources
other than modules. As to what that method should return, I see three
options:

- a file.Path object or a string to be interpreted as path object -
this is maybe the easiest option to implement for common file based
modules, but it might exclude modulels that are not file based.

- an stream object - also easy to implement, but you only get the
content of the resource, but not the metadata such as size and last
modification time etc.

- we introduce and use a new class such as Resource or URL, which may
implement some parts of file.Path like open(), size(), or mtime(), but
is non-modifiable (no write(), move(), remove() etc).

Hannes

Wes Garland

unread,
Sep 16, 2009, 10:29:25 AM9/16/09
to comm...@googlegroups.com
Hannes:

Your point about the metadata is interesting.  GPSEE uses metadata about modules to know if it should do dynamic pre-compilation; I can easily see similar requirements elsewhere....  for example, an app that does module-relative loading of images which pre-generates and stores thumbnails.

I still think the stream is the "winner", although maybe we should return an object instead containing an open stream, size, and last modification time?  Those are all transportable to pretty much any storage subsystem, including remote HTTP.

Wes

Kris Kowal

unread,
Sep 16, 2009, 5:08:56 PM9/16/09
to comm...@googlegroups.com
On Wed, Sep 16, 2009 at 1:16 AM, Hannes Wallnoefer <han...@gmail.com> wrote:
> - we introduce and use a new class such as Resource or URL, which may
> implement some parts of file.Path like open(), size(), or mtime(), but
> is non-modifiable (no write(), move(), remove() etc).

+1

Ash Berlin

unread,
Sep 16, 2009, 5:13:03 PM9/16/09
to comm...@googlegroups.com

Why exactly does it have to be non-modifiable? sure if its over http
you can't. But if its local file I don't see we should restrict
permissions like that.

Kris Kowal

unread,
Sep 16, 2009, 5:21:14 PM9/16/09
to comm...@googlegroups.com
On Wed, Sep 16, 2009 at 2:13 PM, Ash Berlin
<ash_flu...@firemirror.com> wrote:
> Why exactly does it have to be non-modifiable? sure if its over http
> you can't. But if its local file I don't see we should restrict
> permissions like that.

I think normative text should say that the object returned by
.resource(id) must have an "open" property that will return a stream
for read when applied with no arguments. It may be a good idea to
include other methods analogous to the file system Path object like
mtime (which I'm going to call lastModified in the next revision in
adherence to the resolution on literate names over unix names). It
would not be necessary to restrict the objects further.

With this specification, it would be sufficient for an implementation
to return a Path object, or something more restrictive in sandboxed
systems.

Kris Kowal

Reply all
Reply to author
Forward
0 new messages