Skip to content

Commit d98df52

Browse files
committed
added System.import API and async context
1 parent 69b5e54 commit d98df52

21 files changed

Lines changed: 417 additions & 79 deletions

examples/harmony/README.md

Lines changed: 124 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,11 @@
55
import { increment as inc } from './increment';
66
var a = 1;
77
inc(a); // 2
8+
9+
// async loading
10+
System.import("./async-loaded").then((asyncLoaded) => {
11+
console.log(asyncLoaded);
12+
});
813
```
914

1015
# increment.js
@@ -20,73 +25,130 @@ export function increment(val) {
2025

2126
``` javascript
2227
/******/ (function(modules) { // webpackBootstrap
28+
/******/ // install a JSONP callback for chunk loading
29+
/******/ var parentJsonpFunction = window["webpackJsonp"];
30+
/******/ window["webpackJsonp"] = function webpackJsonpCallback(chunkIds, moreModules, executeModule) {
31+
/******/ // add "moreModules" to the modules object,
32+
/******/ // then flag all "chunkIds" as loaded and fire callback
33+
/******/ var moduleId, chunkId, i = 0, resolves = [];
34+
/******/ for(;i < chunkIds.length; i++) {
35+
/******/ chunkId = chunkIds[i];
36+
/******/ if(installedChunks[chunkId])
37+
/******/ resolves.push(installedChunks[chunkId][0]);
38+
/******/ installedChunks[chunkId] = 0;
39+
/******/ }
40+
/******/ for(moduleId in moreModules) {
41+
/******/ modules[moduleId] = moreModules[moduleId];
42+
/******/ }
43+
/******/ if(parentJsonpFunction) parentJsonpFunction(chunkIds, moreModules);
44+
/******/ while(resolves.length)
45+
/******/ resolves.shift()();
46+
47+
/******/ };
48+
2349
/******/ // The module cache
2450
/******/ var installedModules = {};
25-
/******/
51+
52+
/******/ // objects to store loaded and loading chunks
53+
/******/ var installedChunks = {
54+
/******/ 0: 0
55+
/******/ };
56+
2657
/******/ // The require function
2758
/******/ function __webpack_require__(moduleId) {
28-
/******/
59+
2960
/******/ // Check if module is in cache
3061
/******/ if(installedModules[moduleId])
3162
/******/ return installedModules[moduleId].exports;
32-
/******/
63+
3364
/******/ // Create a new module (and put it into the cache)
3465
/******/ var module = installedModules[moduleId] = {
3566
/******/ exports: {},
3667
/******/ id: moduleId,
3768
/******/ loaded: false
3869
/******/ };
39-
/******/
70+
4071
/******/ // Execute the module function
4172
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
42-
/******/
73+
4374
/******/ // Flag the module as loaded
4475
/******/ module.loaded = true;
45-
/******/
76+
4677
/******/ // Return the exports of the module
4778
/******/ return module.exports;
4879
/******/ }
49-
/******/
50-
/******/
80+
81+
/******/ // This file contains only the entry chunk.
82+
/******/ // The chunk loading function for additional chunks
83+
/******/ __webpack_require__.e = function requireEnsure(chunkId) {
84+
/******/ if(installedChunks[chunkId] === 0)
85+
/******/ return Promise.resolve()
86+
87+
/******/ // an Promise means "currently loading".
88+
/******/ if(installedChunks[chunkId]) {
89+
/******/ return installedChunks[chunkId][2];
90+
/******/ }
91+
/******/ // start chunk loading
92+
/******/ var head = document.getElementsByTagName('head')[0];
93+
/******/ var script = document.createElement('script');
94+
/******/ script.type = 'text/javascript';
95+
/******/ script.charset = 'utf-8';
96+
/******/ script.async = true;
97+
98+
/******/ script.src = __webpack_require__.p + "" + chunkId + ".output.js";
99+
/******/ head.appendChild(script);
100+
101+
/******/ var promise = new Promise(function(resolve, reject) {
102+
/******/ installedChunks[chunkId] = [resolve, reject];
103+
/******/ });
104+
/******/ return installedChunks[chunkId][2] = promise;
105+
/******/ };
106+
51107
/******/ // expose the modules object (__webpack_modules__)
52108
/******/ __webpack_require__.m = modules;
53-
/******/
109+
54110
/******/ // expose the module cache
55111
/******/ __webpack_require__.c = installedModules;
56-
/******/
112+
57113
/******/ // __webpack_public_path__
58114
/******/ __webpack_require__.p = "js/";
59-
/******/
60115
/******/ // Load entry module and return exports
61-
/******/ return __webpack_require__(0);
116+
/******/ return __webpack_require__(__webpack_require__.s = 2);
62117
/******/ })
63118
/************************************************************************/
64119
/******/ ([
65120
/* 0 */
66-
/*!********************!*\
67-
!*** ./example.js ***!
68-
\********************/
69-
/***/ function(module, exports, __webpack_require__) {
70-
71-
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__increment__ = __webpack_require__(/*! ./increment */ 1);
72-
var a = 1;
73-
/* harmony import */ __WEBPACK_IMPORTED_MODULE_0__increment__["increment"](a); // 2
74-
75-
/***/ },
76-
/* 1 */
77121
/*!**********************!*\
78122
!*** ./increment.js ***!
79123
\**********************/
80124
/***/ function(module, exports, __webpack_require__) {
81125

82-
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__math__ = __webpack_require__(/*! ./math */ 2);
126+
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__math__ = __webpack_require__(/*! ./math */ 3);
83127
/* harmony export declaration */function increment(val) {
84128
return /* harmony import */ __WEBPACK_IMPORTED_MODULE_0__math__["add"](val, 1);
85129
}/* harmony export */ Object.defineProperty(exports, "increment", {configurable: false, enumerable: true, get: function() { return increment; }});;
86130

87131

88132
/***/ },
133+
/* 1 */,
89134
/* 2 */
135+
/*!********************!*\
136+
!*** ./example.js ***!
137+
\********************/
138+
/***/ function(module, exports, __webpack_require__) {
139+
140+
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__increment__ = __webpack_require__(/*! ./increment */ 0);
141+
var a = 1;
142+
/* harmony import */ __WEBPACK_IMPORTED_MODULE_0__increment__["increment"](a); // 2
143+
144+
// async loading
145+
__webpack_require__.e/* System.import */(1).then(__webpack_require__.bind(null, /*! ./async-loaded */ 1)).then((asyncLoaded) => {
146+
console.log(asyncLoaded);
147+
});
148+
149+
150+
/***/ },
151+
/* 3 */
90152
/*!*****************!*\
91153
!*** ./math.js ***!
92154
\*****************/
@@ -102,41 +164,54 @@ export function increment(val) {
102164

103165

104166
/***/ }
105-
/******/ ])
167+
/******/ ]);
106168
```
107169

108170
# Info
109171

110172
## Uncompressed
111173

112174
```
113-
Hash: 2cddb2c302ef93d23ea9
114-
Version: webpack 1.4.15
115-
Time: 47ms
116-
Asset Size Chunks Chunk Names
117-
output.js 2792 0 [emitted] main
118-
chunk {0} output.js (main) 309 [rendered]
119-
> main [0] ./example.js
120-
[0] ./example.js 73 {0} [built]
121-
[1] ./increment.js 94 {0} [built]
122-
harmony import ./increment [0] ./example.js 1:0-47
123-
[2] ./math.js 142 {0} [built]
124-
harmony import ./math [1] ./increment.js 1:0-29
175+
Hash: 12b612cd4c0d16b8de76
176+
Version: webpack 1.9.10
177+
Time: 99ms
178+
Asset Size Chunks Chunk Names
179+
output.js 4.96 kB 0 [emitted] main
180+
1.output.js 387 bytes 1 [emitted]
181+
chunk {0} output.js (main) 421 bytes [rendered]
182+
> main [2] ./example.js
183+
[0] ./increment.js 94 bytes {0} [built]
184+
harmony import ./increment [2] ./example.js 1:0-47
185+
[2] ./example.js 185 bytes {0} [built]
186+
[3] ./math.js 142 bytes {0} [built]
187+
harmony import ./math [0] ./increment.js 1:0-29
188+
chunk {1} 1.output.js 25 bytes {0} [rendered]
189+
> [2] ./example.js 6:0-31
190+
[1] ./async-loaded.js 25 bytes {1} [built]
191+
./async-loaded [2] ./example.js 6:0-31
125192
```
126193

127194
## Minimized (uglify-js, no zip)
128195

129196
```
130-
Hash: 810b804d71afd4672772
131-
Version: webpack 1.4.15
132-
Time: 141ms
133-
Asset Size Chunks Chunk Names
134-
output.js 585 0 [emitted] main
135-
chunk {0} output.js (main) 309 [rendered]
136-
> main [0] ./example.js
137-
[0] ./example.js 73 {0} [built]
138-
[1] ./increment.js 94 {0} [built]
139-
harmony import ./increment [0] ./example.js 1:0-47
140-
[2] ./math.js 142 {0} [built]
141-
harmony import ./math [1] ./increment.js 1:0-29
197+
Hash: 12b612cd4c0d16b8de76
198+
Version: webpack 1.9.10
199+
Time: 171ms
200+
Asset Size Chunks Chunk Names
201+
output.js 4.81 kB 0 [emitted] main
202+
1.output.js 138 bytes 1 [emitted]
203+
chunk {0} output.js (main) 421 bytes [rendered]
204+
> main [2] ./example.js
205+
[0] ./increment.js 94 bytes {0} [built]
206+
harmony import ./increment [2] ./example.js 1:0-47
207+
[2] ./example.js 185 bytes {0} [built]
208+
[3] ./math.js 142 bytes {0} [built]
209+
harmony import ./math [0] ./increment.js 1:0-29
210+
chunk {1} 1.output.js 25 bytes {0} [rendered]
211+
> [2] ./example.js 6:0-31
212+
[1] ./async-loaded.js 25 bytes {1} [built]
213+
./async-loaded [2] ./example.js 6:0-31
214+
215+
ERROR in output.js from UglifyJs
216+
Unexpected token: operator (>) [./example.js:6,0]
142217
```

examples/harmony/async-loaded.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export var answer = 42;

examples/harmony/example.js

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
11
import { increment as inc } from './increment';
22
var a = 1;
3-
inc(a); // 2
3+
inc(a); // 2
4+
5+
// async loading
6+
System.import("./async-loaded").then((asyncLoaded) => {
7+
console.log(asyncLoaded);
8+
});

lib/ContextModule.js

Lines changed: 65 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,16 @@
55
var Module = require("./Module");
66
var OriginalSource = require("webpack-core/lib/OriginalSource");
77
var RawSource = require("webpack-core/lib/RawSource");
8+
var DependenciesBlock = require("./DependenciesBlock");
89

9-
function ContextModule(resolveDependencies, context, recursive, regExp, addon) {
10+
function ContextModule(resolveDependencies, context, recursive, regExp, addon, async) {
1011
Module.call(this);
1112
this.resolveDependencies = resolveDependencies;
1213
this.context = context;
1314
this.recursive = recursive;
1415
this.regExp = regExp;
1516
this.addon = addon;
17+
this.async = !!async;
1618
this.cacheable = true;
1719
this.contextDependencies = [context];
1820
this.built = false;
@@ -24,6 +26,8 @@ ContextModule.prototype = Object.create(Module.prototype);
2426
ContextModule.prototype.identifier = function() {
2527
var identifier = "";
2628
identifier += this.context + " ";
29+
if(this.async)
30+
identifier += "async ";
2731
if(!this.recursive)
2832
identifier += "nonrecursive ";
2933
if(this.addon)
@@ -40,6 +44,8 @@ function prettyRegExp(str) {
4044
ContextModule.prototype.readableIdentifier = function(requestShortener) {
4145
var identifier = "";
4246
identifier += requestShortener.shorten(this.context) + " ";
47+
if(this.asnyc)
48+
identifier += "asnyc ";
4349
if(!this.recursive)
4450
identifier += "nonrecursive ";
4551
if(this.addon)
@@ -73,15 +79,23 @@ ContextModule.prototype.build = function(options, compilation, resolver, fs, cal
7379
dep.request = addon + dep.userRequest;
7480
});
7581
}
76-
this.dependencies = dependencies;
82+
if(this.async) {
83+
this.blocks = dependencies && dependencies.map(function(dep) {
84+
var block = new DependenciesBlock();
85+
block.dependencies = [dep];
86+
return block;
87+
});
88+
} else {
89+
this.dependencies = dependencies;
90+
}
7791
callback();
7892
}.bind(this));
7993
};
8094

8195
ContextModule.prototype.source = function() {
8296
var str;
97+
var map = {};
8398
if(this.dependencies && this.dependencies.length > 0) {
84-
var map = {};
8599
this.dependencies.slice().sort(function(a, b) {
86100
if(a.userRequest === b.userRequest) return 0;
87101
return a.userRequest < b.userRequest ? -1 : 1;
@@ -107,15 +121,58 @@ ContextModule.prototype.source = function() {
107121
"module.exports = webpackContext;\n",
108122
"webpackContext.id = " + this.id + ";\n"
109123
];
124+
} else if(this.blocks && this.blocks.length > 0) {
125+
var items = this.blocks.map(function(block) {
126+
return {
127+
dependency: block.dependencies[0],
128+
block: block,
129+
userRequest: block.dependencies[0].userRequest
130+
};
131+
}).filter(function(item) {
132+
return item.dependency.module;
133+
});
134+
var hasMultipleChunks = false;
135+
items.sort(function(a, b) {
136+
if(a.userRequest === b.userRequest) return 0;
137+
return a.userRequest < b.userRequest ? -1 : 1;
138+
}).forEach(function(item) {
139+
if(item.dependency.module) {
140+
if(item.block.chunks.length > 1)
141+
hasMultipleChunks = true;
142+
map[item.userRequest] = [item.dependency.module.id].concat(item.block.chunks.map(function(chunk) {
143+
return chunk.id;
144+
}));
145+
}
146+
});
147+
str = [
148+
"var map = ", JSON.stringify(map, null, "\t"), ";\n",
149+
"function webpackAsyncContext(req) {\n",
150+
"\tvar ids = map[req];",
151+
"\tif(!ids)\n",
152+
"\t\tthrow new Error(\"Cannot find module '\" + req + \"'.\");\n",
153+
"\treturn ",
154+
hasMultipleChunks ?
155+
"Promise.all(ids.slice(1).map(__webpack_require__.e))" :
156+
"__webpack_require__.e(ids[1])",
157+
".then(function() {\n",
158+
"\t\treturn __webpack_require__(ids[0]);\n",
159+
"\t});\n",
160+
"};\n",
161+
"webpackAsyncContext.keys = function webpackAsyncContextKeys() {\n",
162+
"\treturn Object.keys(map);\n",
163+
"};\n",
164+
"module.exports = webpackAsyncContext;\n",
165+
"webpackAsyncContext.id = " + this.id + ";\n"
166+
];
110167
} else {
111168
str = [
112-
"function webpackContext(req) {\n",
169+
"function webpackEmptyContext(req) {\n",
113170
"\tthrow new Error(\"Cannot find module '\" + req + \"'.\");\n",
114171
"}\n",
115-
"webpackContext.keys = function() { return []; };\n",
116-
"webpackContext.resolve = webpackContext;\n",
117-
"module.exports = webpackContext;\n",
118-
"webpackContext.id = " + this.id + ";\n"
172+
"webpackEmptyContext.keys = function() { return []; };\n",
173+
"webpackEmptyContext.resolve = webpackEmptyContext;\n",
174+
"module.exports = webpackEmptyContext;\n",
175+
"webpackEmptyContext.id = " + this.id + ";\n"
119176
];
120177
}
121178
if(this.useSourceMap) {

0 commit comments

Comments
 (0)