Modules/ProposalForNativeExtension

From CommonJS Spec Wiki
Jump to: navigation, search

Proposal

This is a proposal for addition to the CommonJS Modules spec to define the two separate options for the, as yet undefined, area of functionality surrounding modules and natives.

So far this area has been specifically left undefined as an implementation detail. However, it is the purpose of this proposal to recognize the necessity of explicitly specifying the two major options for how this should be implemented.

This proposal is meant to recognize how some implementations already work and give a name to the two separate existing standards. That way everyone should know what the differences are and the implications.


Modules (with global natives) "MGN"

Uses the same natives at the script which loads it.

Modifying the prototype of a native from within an MGN module would NOT limit those changes to the scope of the module.

e.g. http://gist.github.com/269015

Prior art: script tags in an html page in any browser. Each script runs in the same environment with access to the same natives.


Modules (with sandboxed natives) "MSB"

Uses fresh "sandboxed" natives.

Modifying the prototype of a native from within an MSB module would limit those changes to the scope of the module and its exports.

Instances of these "sandboxed" natives may be exported using `exports` or available from an exported closure.

e.g. http://gist.github.com/268551

Prior art: "How To Subclass The JavaScript Array Object " http://dean.edwards.name/weblog/2006/11/hooray/


Why do we need to specify this?

Currently many real-world JavaScript libraries and frameworks expect to be able to modify the global environment by extending native prototypes. This is a core feature of JavaScript.

Also, making modules secure is a very important feature.

Not all implementations of CommonJS support the same things. It's important when talking about an environments support for CommonJS that we be explicit about exactly what level of support they have.

Giving these two Module options separate names and separate APIs is important in order to manage user expectation.

API

This proposal is less interested in the specific API implementation of each of these options as it is with specifying that they are separate and important things.

One option for the API would be to use a separate function name for requiring:

MGN: `require('extend-my-natives')`

MSB: `requireSafe('sandbox-my-natives')`


An alternative options would be to pass an additional argument to `require`

MGN: `require('extend-my-natives')`

MSB: `require('sandbox-my-natives', true)`


"I personally prefer having separate function names since that's a bit clearer when reading the code. But I'm sure other people care about it more." — Thomas Aylott


Notes

These two specifications are not mutually exclusive.

An environment may claim CommonJS compliance if it implements at least one of these Modules specifications.

i.e. NodeJS could implement MGN and not MSB and still be a CommonJS compatible environment.

Extending native prototypes is the devil

I know how many people personally feel about extending native prototypes. Many people hang their hearts on their sleeves by using the derogatory term "polluting". I'm sure some would like to freeze the prototypes of all natives. But regardless of how we may personally feel about PrototypeJS, MooTools or whatever other JavaScript we've seen that has possibly abused prototypes in the past. We simply need to recognize that extending native prototypes is a very basic core feature of JavaScript that needs to be more easily and explicitly supported.