Skip to content

Commit

Permalink
Enable use of dojoES6Promise polyfill in async mode
Browse files Browse the repository at this point in the history
  • Loading branch information
chuckdumont committed Apr 20, 2019
1 parent 30eee12 commit 226d2a8
Show file tree
Hide file tree
Showing 14 changed files with 140 additions and 172 deletions.
30 changes: 15 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,26 +20,26 @@
<!-- TOC START min:1 max:3 link:true asterisk:false update:true -->
- [Introduction](#introduction)
- [The Dojo loader](#the-dojo-loader)
- [CommonJS require vs. Dojo synchronous require](#commonjs-require-vs-dojo-synchronous-require)
- [CommonJS require vs. Dojo synchronous require](#commonjs-require-vs-dojo-synchronous-require)
- [The Dojo loader config](#the-dojo-loader-config)
- [Dojo loader extensions](#dojo-loader-extensions)
- [The dojo/has loader extension](#the-dojohas-loader-extension)
- [The dojo/loaderProxy loader extension](#the-dojoloaderproxy-loader-extension)
- [Options](#options)
- [async](#async)
- [loaderConfig](#loaderconfig)
- [environment](#environment)
- [buildEnvironment](#buildenvironment)
- [globalContext](#globalcontext)
- [loader](#loader)
- [locales](#locales)
- [cjsRequirePatterns](#cjsrequirepatterns)
- [coerceUndefinedToFalse](#coerceundefinedtofalse)
- [noConsole](#noconsole)
- [async](#async)
- [loaderConfig](#loaderconfig)
- [environment](#environment)
- [buildEnvironment](#buildenvironment)
- [globalContext](#globalcontext)
- [loader](#loader)
- [locales](#locales)
- [cjsRequirePatterns](#cjsrequirepatterns)
- [coerceUndefinedToFalse](#coerceundefinedtofalse)
- [noConsole](#noconsole)
- [Building the Dojo loader](#building-the-dojo-loader)
- [The `dojo-config-api` feature](#the-dojo-config-api-feature)
- [The `dojo-undef-api` feature](#the-dojo-undef-api-feature)
- [ES6 Promise dependency in Webpack 2.x](#es6-promise-dependency-in-webpack-2x)
- [ES6 Promise polyfill](#es6-promise-polyfill)
- [Order of Plugin Registration](#order-of-plugin-registration)
- [The global require function](#the-global-require-function)
- [Use of run-time identifiers and expressions in dependency arrays](#use-of-run-time-identifiers-and-expressions-in-dependency-arrays)
Expand Down Expand Up @@ -254,7 +254,7 @@ Promise.resolve(require('myAmdModule')).then(function(myAmdModule) {
});
```

Because async mode depends on ES6 Promise, you need to provide a polyfill on platforms that don't support Promise natively (e.g. IE9). Note that the amd/dojoES6Promise polyfill provided by this package cannot be used for this purpose because the AMD modules that implement the polyfill (dojo/Deferred, etc.) cannot be loaded without the Promise support.
Because async mode depends on ES6 `Promise`, you need to provide a polyfill on platforms that don't support `Promise` natively (e.g. IE11). You can use the [Dojo ES6 Promise](eS6-promise-polyfill) polyfill for this purpose.

##### Wrapped promises

Expand Down Expand Up @@ -378,9 +378,9 @@ There are two ways to use the embedded Dojo loader without the config API.

This plugin supports the `dojo-undef-api` feature. If this feature is enabled in the Dojo loader config's `has` property at build time, then `require.undef` may be called at runtime to remove a module from the list of defined modules. This generally works only with AMD modules, not CommonJS modules. `require.undef` is primarily useful for test frameworks that need to load and unload modules without having to reload the entire application.

# ES6 Promise dependency in Webpack 2.x
# ES6 Promise polyfill

Webpack 2.x includes code in your packed application that uses ES6 Promise. If you need to support browsers that lack ES6 Promise support (e.g. IE 11), then you will need to provide this capability in your application. This plugin provides a tiny wrapper module named [dojoES6Promise](https://github.com/OpenNTF/dojo-webpack-plugin/blob/master/amd/dojoES6Promise.js) that implements ES6 Promise using dojo/Deferred. All you need to do is include this module as an AMD dependency in your application. See [bootstrap.js](https://github.com/OpenNTF/dojo-webpack-plugin-sample/blob/master/js/bootstrap.js) in the sample application for an example.
Webpack 2.x and greater includes code in your packed application that uses ES6 `Promise`. If you need to support browsers that lack ES6 `Promise` support (e.g. IE 11), then you will need to provide this capability in your application. This plugin provides a tiny wrapper module named [dojoES6Promise](https://github.com/OpenNTF/dojo-webpack-plugin/blob/master/amd/dojoES6Promise.js) that implements ES6 `Promise` using `dojo/Deferred`. All you need to do is include this module as an AMD dependency in your application. See [bootstrap.js](https://github.com/OpenNTF/dojo-webpack-plugin-sample/blob/master/js/bootstrap.js) in the sample application for an example.

# Order of Plugin Registration

Expand Down
8 changes: 6 additions & 2 deletions amd/dojoES6Promise.js
Original file line number Diff line number Diff line change
Expand Up @@ -96,10 +96,14 @@
}
});
Promise.all = function(iterable) {
return wrap(all(array.map(iterable, function(wrapped) {return wrapped.promise;})));
return wrap(all(array.map(iterable, function(wrapped) {
return wrapped instanceof Promise ? wrapped.promise : wrapped;
})));
};
Promise.race = function(iterable) {
return wrap(first(array.map(iterable, function(wrapped) {return wrapped.promise;})));
return wrap(first(array.map(iterable, function(wrapped) {
return wrapped instanceof Promise ? wrapped.promise : wrapped;
})));
};
Promise.reject = function(reason) {
return wrap((new Deferred()).reject(reason));
Expand Down
4 changes: 2 additions & 2 deletions lib/DojoAMDMainTemplatePlugin.js
Original file line number Diff line number Diff line change
Expand Up @@ -120,8 +120,8 @@ module.exports = class DojoAMDMainTemplatePlugin {
if (this.options.async) {
buf.push(this.indent([
"d: asyncDefineModule,",
"w: asyncWrapDependencies,",
"u: asyncUnwrapDependencies"
"w: wrapPromises,",
"u: unwrapPromises"
]));
}
buf.push("};");
Expand Down
20 changes: 9 additions & 11 deletions loaders/dojo/i18n/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ module.exports = function(content) {
// the requested locale. For example if the requested locale is en-us, then bundle
// locales en and en-us and en-us-xyz all match.
function getAvailableLocales(requestedLocale, bundle) {
/* istanbul ignore if */
if (!bundle.root || typeof bundle.root !== 'object') {
return [];
}
Expand Down Expand Up @@ -67,7 +68,7 @@ module.exports = function(content) {
var res = this._module.request.replace(/\\/g, "/").split("!").pop();

// Determine if this is the default bundle or a locale specific bundle
const buf = [], regex = /^(.+)\/nls\/([^/]+)\/?(.*?)$/;
const buf = [], deps = [], regex = /^(.+)\/nls\/([^/]+)\/?(.*?)$/;
const resMatch = regex.exec(res);
const pluginOptions = callSyncBail(this._compiler, "dojo-webpack-plugin-options");
const requestedLocales = pluginOptions.locales;
Expand Down Expand Up @@ -98,20 +99,17 @@ module.exports = function(content) {
localeAbsMid = localeAbsMid.substring(0, localeAbsMid.length-3);
}
bundledLocales.push(loc);
buf.push(`require("${localeRes}?absMid=${localeAbsMid}");`);
deps.push(`${localeRes}?absMid=${localeAbsMid}`);
});
});

}
const runner = require.resolve(pluginOptions.async ? "./asyncRunner" : "./runner.js").replace(/\\/g, "/");
buf.push(`require("${res}?absMid=${absMid}");`);
buf.push(`var req = ${this._compilation.mainTemplate.requireFn}.${pluginOptions.requireFnPropName}.c();`);
if (pluginOptions.async) {
buf.push(`module.exports = Promise.resolve(require("${runner}")("${absMid}", req)).then(function(m){return module.exports=m});`);
buf.push('module.exports.__DOJO_WEBPACK_DEFINE_PROMISE__ = true;');
} else {
buf.push(`module.exports = require("${runner}")("${absMid}", req);`);
}
const runner = require.resolve("../runner.js").replace(/\\/g, "/");
deps.push(`${res}?absMid=${absMid}`);
const req = `${this._compilation.mainTemplate.requireFn}.${pluginOptions.requireFnPropName}.c()`;
buf.push(`define(["dojo/i18n", "${runner}","${deps.join("\",\"")}"], function(loader, runner) {`);
buf.push(` return runner(loader, "${absMid}", ${req}, ${(!!pluginOptions.async).toString()});`);
buf.push('});');
return buf.join("\n");
};

Expand Down
28 changes: 0 additions & 28 deletions loaders/dojo/i18n/runner.js

This file was deleted.

24 changes: 0 additions & 24 deletions loaders/dojo/loaderProxy/asyncRunner.js

This file was deleted.

32 changes: 10 additions & 22 deletions loaders/dojo/loaderProxy/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,31 +40,19 @@ module.exports = function() {
or else use the 'name' query arg.`);
}
}
const pluginOptions = callSyncBail(this._compiler, "dojo-webpack-plugin-options");
const deps = query.deps ? query.deps.split(",") : [];
const buf = [];
const runner = require.resolve(pluginOptions.async ? "./asyncRunner.js" : "./runner.js").replace(/\\/g, "/");
this._module.addAbsMid(`${toAbsMid(loader)}!${toAbsMid(name)}`);
buf.push("var runner = require(\"" + runner + "\");");
buf.push("var loader = require(\"" + loader + "?absMid=" + toAbsMid(loader) + "\");");
buf.push(`var req = ${this._compilation.mainTemplate.requireFn}.${pluginOptions.requireFnPropName}.c();`);
deps.forEach((dep) => {
dep = decodeURIComponent(dep);
dep = dep.split("!").map((segment) => {
return toAbsMid(segment);
}).join("!");
buf.push("require(\"" + dep + "?absMid=" + dep.replace(/\!/g, "%21") + "\");");
});
if (pluginOptions.async) {
buf.push(`module.exports = Promise.resolve(runner(loader, "${name}", req)).then(function(m){return module.exports=m});`);
buf.push('module.exports.__DOJO_WEBPACK_DEFINE_PROMISE__ = true;');
} else {
buf.push(`module.exports = runner(loader, "${name}", req);`);
}

this._module.addAbsMid(`${toAbsMid(loader)}!${toAbsMid(name)}`);;
this._module.filterAbsMids && this._module.filterAbsMids(absMid => {
return !/loaderProxy/.test(absMid);
});

const pluginOptions = callSyncBail(this._compiler, "dojo-webpack-plugin-options");
const buf = [];
const runner = require.resolve("../runner.js").replace(/\\/g, "/");
const req = `${this._compilation.mainTemplate.requireFn}.${pluginOptions.requireFnPropName}.c()`;
const deps = query.deps ? query.deps.split(",") : [];
buf.push(`define(["${loader}","${runner}","${deps.join("\",\"")}"], function(loader, runner) {`);
buf.push(` return runner(loader, "${name}", ${req}, ${(!!pluginOptions.async).toString()});`);
buf.push('});');

return buf.join("\n");
};
27 changes: 0 additions & 27 deletions loaders/dojo/loaderProxy/runner.js

This file was deleted.

31 changes: 22 additions & 9 deletions loaders/dojo/i18n/asyncRunner.js → loaders/dojo/runner.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* (C) Copyright HCL Technologies Ltd. 2018
* (C) Copyright HCL Technologies Ltd. 2019
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -13,12 +13,25 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
module.exports = function(name, req) {
return Promise.resolve(require("dojo/i18n?absMid=dojo/i18n")).then(function(loader) {
return new Promise(function(resolve) {
loader.load(name, req, function(data) {
resolve(data);
}, {isBuild:true});
define([], function() {
return function(ldr, name, req, async) {
var resolveFn, result, resultSet;
ldr.load(name, req, function(data) {
result = data;
resultSet = true;
if (resolveFn) {
resolveFn(data);
}
}, {isBuild:true});
if (resultSet) {
return result;
} else if (!async) {
throw new Error(name + ' unavailable');
}
result = new Promise(function(resolve) {
resolveFn = resolve;
});
});
};
result.__DOJO_WEBPACK_DEFINE_PROMISE__ = true;
return result;
};
});
Loading

0 comments on commit 226d2a8

Please sign in to comment.