mozilla/addon-sdk — pull request #448 by Gozala (2012-05-22 22:13:36+00:00)
Title: Bug 743359 - Add support for multiple module paths to a loader.

Last week we discussed with discussed with @Mossop details of where SDK modules will have to live in Firefox / Fennec ... and how loader is supposed to handle that (see [JEP SDK in Firefox][] for more details).

Apparently mozilla toolkit code on some platforms is exposed under different URI (`resource://gre/modules/`) from rest of the code (`resource:///modules/`) which was incompatible with previous design with single `baseURI`. To address that use case I made following changes to a loader:

**1.** `Loader` no longer takes `baseURI` option, instead it takes `paths` hash representing mapping between module `id` prefixes to an associated base `uri`. All the module requirements that start with `{{prefix}}` are
resolved to a URI as `requirement.replace('{{prefix}}', options.paths[{{prefix}}])`. This way default loader config described under [JEP SDK in Firefox][] can be passed as follows:

```js
Loader({
paths: {
'': 'resource:///modules/'
'toolkit/': 'resource://gre/modules/'
}
})
```

**2.** Change described above made it possible to pass in module overlays. This way already loaded modules can be provided to avoid subsequent loads.

```js
Loader({
modules: {
'api-utils/cuddlefish': cuddlefish,
'api-utils/loader': loader
}
})
```
**3.** I also took this opportunity to simplify manifest based resolve logic to leverage above described `paths` option. At bootstrap I map current manifest to a format to one we agreed on using in future cfx-js, as it makes resolution logic trivial. New format is described in the last section of [JEP Linker][].

**4.** I have revisited `main` option previously passed to `Loader` that @ochameau disliked. Now loader instance has `loader.main` method that can be used as plain `require`. Loader will take care of creating appropriate `module` instance and exposing it via `require.main` to comply with commonjs spec.

**5.** Required changes made use of `override` that was mutating first argument little painful (as frozen objects were defining non-configurable properties that is impossible to override). There for now `override` creates new object containing all properties form first argument overridden with properties of the second optional argument.

**6.** Instead of copying globals on each module now we just delete shadowing properties from them so that globals from prototype are automatically used.

**7.** `require, module, exports` are now exposed as prototype properties of sandbox instead of own properties.

**8.** Value of `module.id` before depended on load order and could have being relative like `../../foo`. Now
it's always a full form `package/path/to/module` regardless of load order. Also all the resolution / mapping logic is simplified and is defined in terms of `id's`. Module `uri`'s now are only used internally for caching.

[JEP SDK in Firefox]:https://github.com/mozilla/addon-sdk/wiki/JEP%20SDK%20in%20Firefox
[JEP Linker]:https://github.com/mozilla/addon-sdk/wiki/JEP-Linker