Skip to content

Commit a3587ba

Browse files
authored
Merge pull request #235 from PepsRyuu/plugin-context-this-load
Added load to plugin context
2 parents a3f4a73 + 7feb81b commit a3587ba

21 files changed

+1228
-377
lines changed

examples/example-multi-bundle/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
},
77
"devDependencies": {
88
"cross-env": "^7.0.3",
9-
"rollup": "^2.44.0",
9+
"rollup": "^2.73.0",
1010
"rollup-plugin-terser": "^7.0.2"
1111
}
1212
}

lib/impl/NollupCodeGenerator.js

Lines changed: 57 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -80,11 +80,7 @@ function getSyntheticExports (synthetic) {
8080
}`
8181
}
8282

83-
/** @type {MagicString} */
84-
let activeESMOutput;
85-
86-
/** @type {string} */
87-
let activeESMCode;
83+
let activeModules = {};
8884

8985
/**
9086
* @param {string} namespace
@@ -199,8 +195,8 @@ function callNollupBundleInit (plugins) {
199195

200196
class NollupCodeGenerator {
201197

202-
constructor (options = {}) {
203-
this.liveBindings = options.liveBindings || false;
198+
constructor (context) {
199+
this.context = context;
204200
}
205201

206202
/**
@@ -209,33 +205,37 @@ class NollupCodeGenerator {
209205
* @param {ESTree} ast
210206
*/
211207
onESMEnter (code, filePath, ast) {
212-
activeESMOutput = new MagicString(code);
213-
activeESMCode = code;
208+
activeModules[filePath] = {
209+
output: new MagicString(code),
210+
code: code
211+
};
214212
}
215213

216214
/**
215+
* @param {string} filePath
217216
* @param {ESTree} node
218217
* @param {any} args
219218
*/
220-
onESMNodeFound (node, args) {
219+
onESMNodeFound (filePath, node, args) {
220+
let { output, code } = activeModules[filePath];
221221
if (node.type === 'ImportDeclaration' || (args && args.source)) {
222-
activeESMOutput.overwrite(node.start, node.end, blanker(activeESMCode, node.start, node.end));
222+
output.overwrite(node.start, node.end, blanker(code, node.start, node.end));
223223
return;
224224
}
225225

226226
if (node.type === 'ExportDefaultDeclaration') {
227227
// Account for "export default function" and "export default(()=>{})"
228-
let offset = activeESMCode[node.start + 14] === ' '? 15 : 14;
228+
let offset = code[node.start + 14] === ' '? 15 : 14;
229229

230230
if (node.declaration && node.declaration.id) {
231231
// Using + 15 to avoid "export default (() => {})" being converted
232232
// to "module.exports.default = () => {})"
233-
activeESMOutput.overwrite(node.start, node.start + offset, '', { contentOnly: true });
234-
activeESMOutput.appendRight(node.declaration.end, `; __e__('default', function () { return ${node.declaration.id.name} });`);
233+
output.overwrite(node.start, node.start + offset, '', { contentOnly: true });
234+
output.appendRight(node.declaration.end, `; __e__('default', function () { return ${node.declaration.id.name} });`);
235235
} else {
236-
activeESMOutput.overwrite(node.start, node.start + offset, `var __ex_default__ = `, { contentOnly: true });
237-
let end = activeESMCode[node.end - 1] === ';'? node.end - 1 : node.end;
238-
activeESMOutput.appendRight(end, `; __e__('default', function () { return __ex_default__ });`);
236+
output.overwrite(node.start, node.start + offset, `var __ex_default__ = `, { contentOnly: true });
237+
let end = code[node.end - 1] === ';'? node.end - 1 : node.end;
238+
output.appendRight(end, `; __e__('default', function () { return __ex_default__ });`);
239239
}
240240

241241
return;
@@ -244,31 +244,31 @@ class NollupCodeGenerator {
244244
if (node.type === 'ExportNamedDeclaration') {
245245
if (node.declaration) {
246246
// Remove 'export' keyword.
247-
activeESMOutput.overwrite(node.start, node.start + 7, '', { contentOnly: true });
247+
output.overwrite(node.start, node.start + 7, '', { contentOnly: true });
248248
let specifiers = '; ' + args.map(e => `__e__('${e.exported}', function () { return ${e.local} });`).join('');
249-
activeESMOutput.appendRight(node.end, specifiers);
249+
output.appendRight(node.end, specifiers);
250250
}
251251

252252
if (!node.declaration && node.specifiers) {
253253
if (!node.source) {
254254
// Export from statements are already blanked by the import section.
255-
activeESMOutput.overwrite(node.start, node.start + 6, '__e__(', { contentOnly: true });
255+
output.overwrite(node.start, node.start + 6, '__e__(', { contentOnly: true });
256256
node.specifiers.forEach(spec => {
257257
// { a as b, c }, need to preserve the variable incase it's from an import statement
258258
// This is important for live bindings to be able to be transformed.
259-
activeESMOutput.prependLeft(spec.local.start, spec.exported.name + ': function () { return ');
259+
output.prependLeft(spec.local.start, spec.exported.name + ': function () { return ');
260260

261261
if (spec.local.start !== spec.exported.start) {
262-
activeESMOutput.overwrite(spec.local.end, spec.exported.end, '', { contentOnly: true });
262+
output.overwrite(spec.local.end, spec.exported.end, '', { contentOnly: true });
263263
}
264264

265-
activeESMOutput.appendRight(spec.exported.end, ' }');
265+
output.appendRight(spec.exported.end, ' }');
266266
});
267267

268-
if (activeESMCode[node.end - 1] === ';') {
269-
activeESMOutput.prependLeft(node.end - 1, ')');
268+
if (code[node.end - 1] === ';') {
269+
output.prependLeft(node.end - 1, ')');
270270
} else {
271-
activeESMOutput.appendRight(node.end, ');')
271+
output.appendRight(node.end, ');')
272272

273273
}
274274

@@ -280,32 +280,34 @@ class NollupCodeGenerator {
280280

281281
if (node.type === 'ImportExpression') {
282282
if (!args.external) {
283-
if (typeof args.resolved.id === 'string' && path.isAbsolute(args.resolved.id)) {
283+
if (typeof args.resolved.id === 'string' && path.isAbsolute(args.resolved.id.split(':').pop())) {
284284
// import('hello') --> require.dynamic('/hello.js');
285-
activeESMOutput.overwrite(node.start, node.start + 6, 'require.dynamic', { contentOnly: true });
286-
activeESMOutput.overwrite(node.source.start, node.source.end, '\'' + normalizePathDelimiter(args.resolved.id) + '\'', { contentOnly: true });
285+
output.overwrite(node.start, node.start + 6, 'require.dynamic', { contentOnly: true });
286+
output.overwrite(node.source.start, node.source.end, '\'' + normalizePathDelimiter(args.resolved.id) + '\'', { contentOnly: true });
287287
}
288288
}
289289
}
290290
}
291291

292-
onESMImportLiveBinding (node, ancestors) {
292+
onESMImportLiveBinding (filePath, node, ancestors) {
293+
let { output, code } = activeModules[filePath];
293294
let parent = ancestors[ancestors.length - 1];
294295
if (parent.type === 'Property' && parent.shorthand) {
295-
activeESMOutput.prependLeft(node.start, node.name + ': ');
296+
output.prependLeft(node.start, node.name + ': ');
296297
}
297298

298-
activeESMOutput.overwrite(node.start, node.end, '__i__.' + node.name, { contentOnly: true })
299+
output.overwrite(node.start, node.end, '__i__.' + node.name, { contentOnly: true })
299300

300301
}
301302

302303
/**
303304
* @param {ESTree} node
304305
* @param {string[]} found
305306
*/
306-
onESMLateInitFound (node, found) {
307+
onESMLateInitFound (filePath, node, found) {
308+
let { output, code } = activeModules[filePath];
307309
let transpiled = ';' + found.map(name => `__e__('${name}', function () { return typeof ${name} !== 'undefined' && ${name} })`).join(';') + ';';
308-
activeESMOutput.appendRight(node.end, transpiled);
310+
output.appendRight(node.end, transpiled);
309311
}
310312

311313
/**
@@ -315,10 +317,16 @@ class NollupCodeGenerator {
315317
* @return {{ code: string, map: RollupSourceMap }}
316318
*/
317319
onESMLeave (code, filePath, ast) {
318-
return {
319-
code: activeESMOutput.toString(),
320-
map: activeESMOutput.generateMap({ source: filePath })
320+
let { output } = activeModules[filePath];
321+
322+
let payload = {
323+
code: output.toString(),
324+
map: output.generateMap({ source: filePath })
321325
};
326+
327+
delete activeModules[filePath];
328+
329+
return payload;
322330
}
323331

324332

@@ -329,7 +337,7 @@ class NollupCodeGenerator {
329337
* @return {string}
330338
*/
331339
onGenerateModule (modules, filePath, config) {
332-
let { transformed: code, map, imports, exports, externalImports, dynamicImports, syntheticNamedExports, hoist } = modules[filePath];
340+
let { esmTransformedCode: code, map, imports, exports, externalImports, dynamicImports, syntheticNamedExports, hoist } = modules[filePath];
333341

334342
// Validate dependencies exist.
335343
imports.forEach(dep => {
@@ -409,12 +417,12 @@ class NollupCodeGenerator {
409417

410418
return `
411419
function (__c__, __r__, __d__, __e__, require, module, __m__, __nollup__global__) {
412-
${this.liveBindings? 'var __i__ = {};' : ''}
413-
${this.liveBindings === 'with-scope'? 'with (__i__) {' : ''}
420+
${this.context.liveBindings? 'var __i__ = {};' : ''}
421+
${this.context.liveBindings === 'with-scope'? 'with (__i__) {' : ''}
414422
415423
${imports.map((i, index) => {
416424
let namespace = `_i${index}`;
417-
return `var ${namespace}; ${this.liveBindings? '' : (!i.export? i.specifiers.map(s => 'var ' + s.local).join(';') : '')};`
425+
return `var ${namespace}; ${this.context.liveBindings? '' : (!i.export? i.specifiers.map(s => 'var ' + s.local).join(';') : '')};`
418426
}).join('; ')}
419427
420428
${externalImports.map(i => {
@@ -451,7 +459,7 @@ class NollupCodeGenerator {
451459
452460
if (!i.export) {
453461
let value = `${namespace}${s.imported === '*'? '' : `.${s.imported}`}`;
454-
if (this.liveBindings) {
462+
if (this.context.liveBindings) {
455463
output = `!__i__.hasOwnProperty("${s.local}") && Object.defineProperty(__i__, "${s.local}", { get: function () { return ${value}}});`;
456464
} else {
457465
output = `${s.local} = ${value};`;
@@ -468,7 +476,7 @@ class NollupCodeGenerator {
468476
469477
let import_exported = exports.find(e => e.local === s.local);
470478
if (!i.export && import_exported) {
471-
let local = this.liveBindings? `__i__["${import_exported.local}"]` : import_exported.local;
479+
let local = this.context.liveBindings? `__i__["${import_exported.local}"]` : import_exported.local;
472480
output += `__e__("${import_exported.exported}", function () { return ${local} });`;
473481
}
474482
@@ -481,7 +489,7 @@ class NollupCodeGenerator {
481489
${syntheticNamedExports? getSyntheticExports(syntheticNamedExports) : ''}
482490
}.bind(${context}));
483491
484-
${this.liveBindings === 'with-scope'? '}' : ''}
492+
${this.context.liveBindings === 'with-scope'? '}' : ''}
485493
${imports.map((i, index) => {
486494
let id = `_i${index}`;
487495
return `${id} = __c__(${modules[i.source].index}) && function () { return __r__(${modules[i.source].index}) }`;
@@ -492,7 +500,7 @@ class NollupCodeGenerator {
492500

493501

494502
/**
495-
* @param {NollupInternalModule} module
503+
* @param {NollupOutputModule} module
496504
* @return {string}
497505
*/
498506
onGenerateModuleChange (module) {
@@ -511,7 +519,7 @@ class NollupCodeGenerator {
511519
*/
512520
onGenerateModulePreChunk (file, bundle, modules) {
513521
if (file.dynamicImports.length > 0) {
514-
return file.code.replace(/require\.dynamic\((\\)?\'(.*?)(\\)?\'\)/g, (match, escapeLeft, inner, escapeRight) => {
522+
return file.generatedCode.replace(/require\.dynamic\((\\)?\'(.*?)(\\)?\'\)/g, (match, escapeLeft, inner, escapeRight) => {
515523
let foundOutputChunk = bundle.find(b => {
516524
// Look for chunks only, not assets
517525
let facadeModuleId = /** @type {RollupOutputChunk} */ (b).facadeModuleId;
@@ -525,7 +533,7 @@ class NollupCodeGenerator {
525533
});
526534
}
527535

528-
return file.code;
536+
return file.generatedCode;
529537
}
530538

531539
/**
@@ -666,7 +674,7 @@ class NollupCodeGenerator {
666674
cb();
667675
} else {
668676
${format === 'es'? (`
669-
${this.liveBindings === 'with-scope'? `
677+
${this.context.liveBindings === 'with-scope'? `
670678
return fetch(file).then(res => {
671679
return res.text();
672680
}).then(res => {
@@ -713,7 +721,7 @@ class NollupCodeGenerator {
713721
}
714722
715723
for (var prop in bindings) {
716-
${this.liveBindings? `
724+
${this.context.liveBindings? `
717725
if (!module.exports.hasOwnProperty(prop) || prop === 'default') {
718726
Object.defineProperty(module.exports, prop, {
719727
get: bindings[prop],

lib/impl/NollupCompiler.js

Lines changed: 9 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -98,8 +98,6 @@ async function compileModule (context, filePath, parentFilePath, depth, emitted,
9898
throw new Error('Maximum parse call stack exceeded.');
9999
}
100100

101-
let file = context.files[filePath];
102-
103101
if (emitted.modules[filePath]) {
104102
// Circular check
105103
if (circularTrace.indexOf(filePath) !== circularTrace.length - 1) {
@@ -114,56 +112,7 @@ async function compileModule (context, filePath, parentFilePath, depth, emitted,
114112
emitted.modules[filePath] = true;
115113
bundleModuleIds.add(filePath);
116114

117-
// If the file hasn't been encountered before, create an entry for it.
118-
if (!file) {
119-
file = {
120-
id: filePath,
121-
index: context.indexGenerator++,
122-
invalidate: true,
123-
isEntry: isEntry,
124-
code: '',
125-
map: null,
126-
imports: [],
127-
externalImports: [],
128-
dynamicImports: [],
129-
externalDynamicImports: [],
130-
exports: [],
131-
emittedAssetsCache: {},
132-
emittedChunksCache: {},
133-
metaProperties: [],
134-
syntheticNamedExports: false,
135-
hoist: false,
136-
transformed: ''
137-
};
138-
139-
context.files[filePath] = file;
140-
}
141-
142-
if (file.invalidate) {
143-
let emittedAssetsCache = /** @type Object<string, RollupEmittedAsset>} */ ({});
144-
let emittedChunksCache = /** @type Object<String, RollupEmittedChunk>} */ ({});
145-
146-
context.currentModuleEmittedAssetsCache = emittedAssetsCache
147-
context.currentModuleEmittedChunksCache = emittedChunksCache;
148-
149-
let loaded = await context.plugins.hooks.load(filePath, parentFilePath);
150-
let transformed = await context.plugins.hooks.transform( loaded.code, filePath, loaded.map);
151-
let resolved = await ImportExportResolver(context.plugins, transformed.code, filePath, generator, context.liveBindings);
152-
153-
file.transformed = resolved.code;
154-
file.imports = resolved.imports;
155-
file.externalImports = resolved.externalImports;
156-
file.dynamicImports = resolved.dynamicImports;
157-
file.externalDynamicImports = resolved.externalDynamicImports;
158-
file.exports = resolved.exports;
159-
file.map = transformed.map;
160-
file.emittedAssetsCache = emittedAssetsCache;
161-
file.emittedChunksCache = emittedChunksCache;
162-
file.metaProperties = resolved.metaProperties;
163-
file.syntheticNamedExports = loaded.syntheticNamedExports || transformed.syntheticNamedExports || syntheticNamedExports || false;
164-
}
165-
166-
await context.plugins.hooks.moduleParsed(filePath);
115+
let file = await context.load(filePath, parentFilePath, isEntry, syntheticNamedExports, true);
167116

168117
file.dynamicImports.forEach(di => {
169118
if (emitted.dynamicImports.indexOf(di) === -1) {
@@ -260,7 +209,7 @@ async function compileInputTarget (context, filePath, bundleModuleIds, generator
260209
});
261210

262211
emitted.invalidate.forEach(file => {
263-
file.code = generator.onGenerateModule(context.files, file.id, context.config);
212+
file.generatedCode = generator.onGenerateModule(context.files, file.id, context.config);
264213
file.invalidate = false;
265214
});
266215

@@ -270,10 +219,10 @@ async function compileInputTarget (context, filePath, bundleModuleIds, generator
270219
module.exports = {
271220
/**
272221
* @param {NollupContext} context
273-
* @param {NollupCodeGenerator} generator
274222
* @return {Promise<NollupCompileOutput>}
275223
*/
276-
async compile (context, generator) {
224+
async compile (context) {
225+
let generator = context.generator;
277226
context.plugins.start();
278227

279228
let bundle = /** @type {RollupOutputFile[]} */ ([]);
@@ -340,8 +289,10 @@ module.exports = {
340289

341290
context.currentPhase = 'build';
342291

343-
for (let i = 0; i < context.input.length; i++) {
344-
let { name, file } = context.input[i];
292+
let inputs = await context.input();
293+
294+
for (let i = 0; i < inputs.length; i++) {
295+
let { name, file } = inputs[i];
345296
let emitted = await compileInputTarget(context, file, bundleModuleIds, generator, bundleEmittedAssets, true);
346297

347298
bundle.push({
@@ -438,7 +389,7 @@ module.exports = {
438389
emitAssetToBundle(context.config.output, bundle, asset, bundleReferenceIdMap);
439390
});
440391

441-
let modules;
392+
let modules = /** @type {Object<String, NollupOutputModule>} */(null);
442393

443394
try {
444395
await context.plugins.hooks.renderStart(context.config.output, context.config);

0 commit comments

Comments
 (0)