addon-sdk/source/lib/sdk/loader/cuddlefish.js

changeset 0
6474c204b198
equal deleted inserted replaced
-1:000000000000 0:53039d511417
1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4 'use strict';
5
6 module.metadata = {
7 "stability": "unstable"
8 };
9
10 // This module is manually loaded by bootstrap.js in a sandbox and immediatly
11 // put in module cache so that it is never loaded in any other way.
12
13 /* Workarounds to include dependencies in the manifest
14 require('chrome') // Otherwise CFX will complain about Components
15 require('toolkit/loader') // Otherwise CFX will stip out loader.js
16 require('sdk/addon/runner') // Otherwise CFX will stip out addon/runner.js
17 require('sdk/system/xul-app') // Otherwise CFX will stip out sdk/system/xul-app
18 */
19
20 const { classes: Cc, Constructor: CC, interfaces: Ci, utils: Cu } = Components;
21
22 // `loadSandbox` is exposed by bootstrap.js
23 const loaderURI = module.uri.replace("sdk/loader/cuddlefish.js",
24 "toolkit/loader.js");
25 const xulappURI = module.uri.replace("loader/cuddlefish.js",
26 "system/xul-app.js");
27 // We need to keep a reference to the sandbox in order to unload it in
28 // bootstrap.js
29
30 const loaderSandbox = loadSandbox(loaderURI);
31 const loaderModule = loaderSandbox.exports;
32
33 const xulappSandbox = loadSandbox(xulappURI);
34 const xulappModule = xulappSandbox.exports;
35
36 const { override, load } = loaderModule;
37
38 /**
39 * Ensure the current application satisfied the requirements specified in the
40 * module given. If not, an exception related to the incompatibility is
41 * returned; `null` otherwise.
42 *
43 * @param {Object} module
44 * The module to check
45 * @returns {Error}
46 */
47 function incompatibility(module) {
48 let { metadata, id } = module;
49
50 // if metadata or engines are not specified we assume compatibility is not
51 // an issue.
52 if (!metadata || !("engines" in metadata))
53 return null;
54
55 let { engines } = metadata;
56
57 if (engines === null || typeof(engines) !== "object")
58 return new Error("Malformed engines' property in metadata");
59
60 let applications = Object.keys(engines);
61
62 let versionRange;
63 applications.forEach(function(name) {
64 if (xulappModule.is(name)) {
65 versionRange = engines[name];
66 // Continue iteration. We want to ensure the module doesn't
67 // contain a typo in the applications' name or some unknown
68 // application - `is` function throws an exception in that case.
69 }
70 });
71
72 if (typeof(versionRange) === "string") {
73 if (xulappModule.satisfiesVersion(versionRange))
74 return null;
75
76 return new Error("Unsupported Application version: The module " + id +
77 " currently supports only version " + versionRange + " of " +
78 xulappModule.name + ".");
79 }
80
81 return new Error("Unsupported Application: The module " + id +
82 " currently supports only " + applications.join(", ") + ".")
83 }
84
85 function CuddlefishLoader(options) {
86 let { manifest } = options;
87
88 options = override(options, {
89 // Put `api-utils/loader` and `api-utils/cuddlefish` loaded as JSM to module
90 // cache to avoid subsequent loads via `require`.
91 modules: override({
92 'toolkit/loader': loaderModule,
93 'sdk/loader/cuddlefish': exports,
94 'sdk/system/xul-app': xulappModule
95 }, options.modules),
96 resolve: function resolve(id, requirer) {
97 let entry = requirer && requirer in manifest && manifest[requirer];
98 let uri = null;
99
100 // If manifest entry for this requirement is present we follow manifest.
101 // Note: Standard library modules like 'panel' will be present in
102 // manifest unless they were moved to platform.
103 if (entry) {
104 let requirement = entry.requirements[id];
105 // If requirer entry is in manifest and it's requirement is not, than
106 // it has no authority to load since linker was not able to find it.
107 if (!requirement)
108 throw Error('Module: ' + requirer + ' has no authority to load: '
109 + id, requirer);
110
111 uri = requirement;
112 } else {
113 // If requirer is off manifest than it's a system module and we allow it
114 // to go off manifest by resolving a relative path.
115 uri = loaderModule.resolve(id, requirer);
116 }
117 return uri;
118 },
119 load: function(loader, module) {
120 let result;
121 let error;
122
123 // In order to get the module's metadata, we need to load the module.
124 // if an exception is raised here, it could be that is due to application
125 // incompatibility. Therefore the exception is stored, and thrown again
126 // only if the module seems be compatible with the application currently
127 // running. Otherwise the incompatibility message takes the precedence.
128 try {
129 result = load(loader, module);
130 }
131 catch (e) {
132 error = e;
133 }
134
135 error = incompatibility(module) || error;
136
137 if (error)
138 throw error;
139
140 return result;
141 }
142 });
143
144 let loader = loaderModule.Loader(options);
145 // Hack to allow loading from `toolkit/loader`.
146 loader.modules[loaderURI] = loaderSandbox;
147 return loader;
148 }
149
150 exports = override(loaderModule, {
151 Loader: CuddlefishLoader
152 });

mercurial