Skip to content

Commit ae1f9e4

Browse files
author
Chuck Dumont
authored
Merge pull request #145 from chuckdumont/work2
Reduce local namespace polution in bootstrap
2 parents 5d1ff60 + 77f37c5 commit ae1f9e4

11 files changed

+1530
-377
lines changed

lib/DojoAMDMainTemplate.runtime.js

+32-7
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
* See the License for the specific language governing permissions and
1414
* limitations under the License.
1515
*/
16-
/* globals loaderScope __webpack_require__ installedModules */
16+
/* globals loaderScope __webpack_require__ installedModules globalRequireContext */
1717

1818
module.exports = {
1919
main: function() {
@@ -30,10 +30,10 @@ module.exports = {
3030
return loaderScope.require.toAbsMid(name, referenceModule);
3131
}
3232

33-
// dojo require function");
33+
// dojo require function.
3434
function req(config, dependencies, callback) {
3535
return contextRequire(config, dependencies, callback, 0, req);
36-
}
36+
};
3737

3838
function createContextRequire(moduleId) { // eslint-disable-line no-unused-vars
3939
if (typeof(moduleId) === "number") { // Number.isInteger does not work in IE
@@ -114,10 +114,10 @@ module.exports = {
114114
}
115115

116116
function contextRequire(a1, a2, a3, referenceModule, req) { // eslint-disable-line no-shadow
117-
if (!referenceModule && loaderScope.buildContext) {
117+
if (!referenceModule && globalRequireContext) {
118118
// No reference module means we were called by global require, so use the build context
119119
// as the reference module since that's what would have been used for constructing the absMid
120-
referenceModule = loaderScope.buildContext + 'x';
120+
referenceModule = globalRequireContext + 'x';
121121
}
122122
var type = ({}.toString).call(a1);
123123
if (type === '[object String]') {
@@ -151,10 +151,35 @@ module.exports = {
151151
}
152152
}
153153
},
154+
155+
makeDeprecatedReq: function() {
156+
(function() {
157+
function warnDeprecated() {
158+
console.warn('req is deprecated and will be removed in a future release. Use __webpack_require__.dj.r instead.');
159+
}
160+
var req = __webpack_require__.dj.r;
161+
function depReq() {
162+
warnDeprecated();
163+
return req.apply(this, arguments);
164+
};
165+
Object.keys(req).forEach(function(name) {
166+
Object.defineProperty(depReq, name, {
167+
get: function() {
168+
warnDeprecated();
169+
return req[name];
170+
},
171+
enumerable: true,
172+
configurable: false
173+
});
174+
});
175+
return depReq;
176+
})();
177+
},
178+
154179
undef: function() {
155180
function undef(mid, referenceModule) { // eslint-disable-line no-unused-vars
156-
if (!referenceModule && typeof buildContext !== 'undefined') {
157-
referenceModule = loaderScope.buildContext + 'x'; // global require
181+
if (!referenceModule && globalRequireContext) {
182+
referenceModule = globalRequireContext + 'x'; // global require
158183
}
159184
var module = findModule(mid, referenceModule, true, true); // eslint-disable-line no-undef
160185
if (module) {

lib/DojoAMDMainTemplatePlugin.js

+26-32
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,6 @@ module.exports = class DojoAMDMainTemplatePlugin {
4646
});
4747
compilation.plugin("before-chunk-assets", this.relativizeAbsoluteAbsMids.bind(context));
4848
plugin(compilation.mainTemplate, {
49-
"bootstrap" : this.bootstrap,
5049
"require-extensions" : this.requireExtensions,
5150
"dojo-require-extensions" : this.dojoRequireExtensions, // plugin specific event
5251
"render-dojo-config-vars" : this.renderDojoConfigVars, // plugin specific event
@@ -67,11 +66,14 @@ module.exports = class DojoAMDMainTemplatePlugin {
6766
this.embeddedLoaderHasConfigApi = !!scope.require.packs;
6867
}
6968

70-
bootstrap(source, chunk) {
71-
const buf = [];
69+
requireExtensions(...args) {
70+
return this.compilation.mainTemplate.applyPluginsWaterfall("dojo-require-extensions", ...args); // plugin specific event
71+
}
72+
73+
dojoRequireExtensions(source, chunk, ...rest) {
7274
const {mainTemplate} = this.compilation;
7375
const runtimeSource = Template.getFunctionContent(require("./DojoAMDMainTemplate.runtime.js").main);
74-
buf.push(source);
76+
const buf = [];
7577
buf.push(runtimeSource);
7678
buf.push("req.toUrl = toUrl;");
7779
buf.push("req.toAbsMid = toAbsMid;");
@@ -89,22 +91,12 @@ module.exports = class DojoAMDMainTemplatePlugin {
8991
buf.push(mainTemplate.indent(`(this||window)[${jsonpFn}].registerAbsMids = registerAbsMids;`));
9092
}
9193
buf.push("})();");
92-
return mainTemplate.asString(buf);
93-
}
94-
95-
requireExtensions(...args) {
96-
return this.compilation.mainTemplate.applyPluginsWaterfall("dojo-require-extensions", ...args); // plugin specific event
97-
}
98-
99-
dojoRequireExtensions(source, ...rest) {
100-
const {mainTemplate} = this.compilation;
101-
const buf = [];
102-
buf.push(source);
10394
buf.push("");
10495
buf.push("// expose the Dojo compatibility functions as a properties of " + mainTemplate.requireFn);
10596
buf.push("var globalScope = (function(){return this||window;})();");
10697
buf.push(mainTemplate.requireFn + ".dj = {");
10798
buf.push(mainTemplate.indent([
99+
"r: req,",
108100
"c: createContextRequire,",
109101
"m: dojoModuleFromWebpackModule,",
110102
"h: resolveTernaryHasExpression,",
@@ -131,10 +123,8 @@ module.exports = class DojoAMDMainTemplatePlugin {
131123
but the loader specified at ${this.embeddedLoaderFilename} was built without the config API. Please rebuild the embedded loader with 'dojo-config-api' feature enabled`);
132124
}
133125
}
134-
buf.push(mainTemplate.applyPluginsWaterfall("render-dojo-config-vars", loaderScope, "", ...rest));
135-
if (this.buildContext) {
136-
buf.push(`loaderScope.buildContext = "${this.buildContext}"`);
137-
}
126+
buf.push(mainTemplate.applyPluginsWaterfall("render-dojo-config-vars", loaderScope, "", chunk, ...rest));
127+
buf.push(`var globalRequireContext = "${this.globalRequireContext || 'null'}"`);
138128
buf.push("var dojoLoader = " + mainTemplate.requireFn + "(" + JSON.stringify(dojoLoaderModule.id) + ");");
139129
buf.push("dojoLoader.call(loaderScope, userConfig, defaultConfig, loaderScope, loaderScope);");
140130
if (loaderScope) {
@@ -148,11 +138,15 @@ but the loader specified at ${this.embeddedLoaderFilename} was built without the
148138
buf.push("req.signal = loaderScope.require.signal");
149139
const loaderConfig = this.compiler.applyPluginsBailResult("get dojo config");
150140
if (loaderConfig.has && loaderConfig.has['dojo-undef-api']) {
151-
const undefSource = Template.getFunctionContent(require("./DojoAMDMainTemplate.runtime.js").undef);
152-
buf.push("req.undef = " + undefSource);
141+
buf.push("req.undef = " + Template.getFunctionContent(require("./DojoAMDMainTemplate.runtime.js").undef));
153142
}
154-
buf.push("");
155-
return mainTemplate.asString(buf);
143+
return mainTemplate.asString([
144+
source,
145+
"(function() {",
146+
mainTemplate.indent(buf),
147+
"})();",
148+
"var req=" + Template.getFunctionContent(require("./DojoAMDMainTemplate.runtime.js").makeDeprecatedReq)
149+
]);
156150
}
157151

158152
renderDojoConfigVars(loaderScope) {
@@ -224,20 +218,20 @@ but the loader specified at ${this.embeddedLoaderFilename} was built without the
224218
* They have the form '$$root$$/<absolute-path>' where '$$root$$' can be changed using the globalContext.varName
225219
* option. So as not to expose absolute paths on the client for security reasons, we determine the closest common
226220
* directory for all the absolute absMids and rewrite the absMids in the form '$$root$$/<relative-path>', where the
227-
* path is relative to the buildContext path, and the buildContext path is calculated as the globalContext
221+
* path is relative to the globalRequireContext path, and the globalRequireContext path is calculated as the globalContext
228222
* directory relative to the closest common directory. For example, if the globalContext path is '/a/b/c/d/e'
229-
* and the closest common directory is '/a/b/c', then the buildContext path would be'$$root$$/d/e', and the
223+
* and the closest common directory is '/a/b/c', then the globalRequireContext path would be'$$root$$/d/e', and the
230224
* modified absMid for the module with absolute absMid '$$root$$/a/b/c/d/f/foo' would be '$$root$$/d/f/foo'. The
231-
* buildContext path is emitted to the client so that runtime global require calls specifying relative module ids
225+
* globalRequireContext path is emitted to the client so that runtime global require calls specifying relative module ids
232226
* can be resolved on the client. If at runtime, the client calls global require with the module id '../f/foo',
233-
* then the absMid for the module will be computed by resolving the specified module id against the buildContext
227+
* then the absMid for the module will be computed by resolving the specified module id against the globalRequireContext
234228
* path ('$$root$$/d/e'), resulting in '$$root$$/d/f/foo' and the client will locate the module by looking
235229
* it up in the table of registered absMids.
236230
*
237-
* In the event that runtime global require calls attempt to traverse the buildContext parent hierarchy
231+
* In the event that runtime global require calls attempt to traverse the globalRequireContext parent hierarchy
238232
* beyond the level of the closest common directory, the globalContext.numParents option can be specified
239233
* to indicate the number of parent directories beyond the closest common directory to include in
240-
* the buildContext path. In the example above, a numParents value of 1 would result in the buildContext
234+
* the globalRequireContext path. In the example above, a numParents value of 1 would result in the globalRequireContext
241235
* path changing from '$$root$$/d/e' to '$$root$$/c/d/e' and the absMid for the module with absolute path
242236
* '/a/b/c/d/f/foo' changing from '$$root$$/d/f/foo' to '$$root$$/c/d/f/foo'.
243237
*/
@@ -273,9 +267,9 @@ but the loader specified at ${this.embeddedLoaderFilename} was built without the
273267
// Determine the relative path from the adjusted common root to the global context and set it
274268
// as the build context that gets adorned and emitted to the client.
275269
var relative = path.relative(commonRoot, context);
276-
this.buildContext = path.join(rootVarName, relative).replace(/\\/g,'/');
277-
if (!this.buildContext.endsWith('/')) {
278-
this.buildContext += '/';
270+
this.globalRequireContext = path.join(rootVarName, relative).replace(/\\/g,'/');
271+
if (!this.globalRequireContext.endsWith('/')) {
272+
this.globalRequireContext += '/';
279273
}
280274
// Now rewrite the absMids to be relative to the computed build context
281275
relMods.forEach(module => {

lib/ScopedRequirePlugin.js

+1-8
Original file line numberDiff line numberDiff line change
@@ -7,20 +7,13 @@ module.exports = class ScopedRequirePlugin {
77
return ""; // don't set global require
88
});
99

10-
compilation.mainTemplate.plugin("require", function(source) {
11-
// This code, together with the 'render' plugin below, defines a scoped
12-
// Dojo require variable for each AMD module so that referencing 'require' from
13-
// within the module will yield the Dojo function.
14-
return source.replace(/__webpack_require__\);/g, "__webpack_require__, req);");
15-
});
16-
1710
compilation.moduleTemplate.plugin("render", function(source, module) {
1811
var result = source;
1912
if (module.isAMD) {
2013
// Define a module scoped 'require' variable for AMD modules that references the
2114
// the Dojo require function.
2215
result = new ConcatSource();
23-
result.add("var require = arguments[3];");
16+
result.add("var require = __webpack_require__.dj.r;");
2417
result.add(source);
2518
}
2619
return result;

0 commit comments

Comments
 (0)