Skip to content

Commit 149b014

Browse files
committed
Hoisted access to require.dynamic
1 parent c1c3c8e commit 149b014

File tree

5 files changed

+118
-75
lines changed

5 files changed

+118
-75
lines changed

lib/impl/NollupCodeGenerator.js

Lines changed: 74 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -377,7 +377,7 @@ class NollupCodeGenerator {
377377
) || config.context;
378378

379379
return `
380-
function (__c__, __r__, __d__, __e__) {
380+
function (__c__, __r__, __d__, __e__, require, module, __nollup__global__) {
381381
${this.liveBindings? 'var __i__ = {};' : ''}
382382
${this.liveBindings === 'with-scope'? 'with (__i__) {' : ''}
383383
@@ -443,7 +443,7 @@ class NollupCodeGenerator {
443443
return output;
444444
}).join(';');
445445
}).join('; ')}
446-
}, function (require, module, __nollup__global__) {
446+
}, function () {
447447
"use strict";
448448
eval('${code}');
449449
${syntheticNamedExports? getSyntheticExports(syntheticNamedExports) : ''}
@@ -479,13 +479,13 @@ class NollupCodeGenerator {
479479
*/
480480
onGenerateModulePreChunk (file, bundle, modules) {
481481
if (file.dynamicImports.length > 0) {
482-
return file.code.replace(/require\.dynamic\(\\\'(.*?)\\\'\)/g, (match, inner) => {
482+
return file.code.replace(/require\.dynamic\((\\)?\'(.*?)(\\)?\'\)/g, (match, escapeLeft, inner, escapeRight) => {
483483
let foundOutputChunk = bundle.find(b => {
484484
return normalizePathDelimiter(/** @type {RollupOutputChunk} */ (b).facadeModuleId) === inner
485485
});
486486

487487
let fileName = foundOutputChunk? foundOutputChunk.fileName : '';
488-
return 'require.dynamic(\\\'' + fileName + '\\\', ' + modules[path.normalize(inner)].index + ')';
488+
return 'require.dynamic(' + (escapeLeft? '\\' : '') + '\'' + fileName + (escapeRight? '\\' : '') +'\', ' + modules[path.normalize(inner)].index + ')';
489489
});
490490
}
491491

@@ -565,69 +565,6 @@ class NollupCodeGenerator {
565565
566566
${callNollupModuleInit(/** @type {NollupPlugin[]} */(plugins))}
567567
568-
modules[number](function (dep) {
569-
if (!instances[dep] || instances[dep].invalidate) {
570-
create_module(dep);
571-
}
572-
573-
if (instances[number].dependencies.indexOf(dep) === -1) {
574-
instances[number].dependencies.push(dep);
575-
}
576-
577-
return true;
578-
}, function (dep) {
579-
return get_exports(module, dep);
580-
}, function(binder, impl) {
581-
module.__binder = binder;
582-
module.__impl = impl;
583-
}, function (arg1, arg2) {
584-
var bindings = {};
585-
if (typeof arg1 === 'object') {
586-
bindings = arg1;
587-
} else {
588-
bindings[arg1] = arg2;
589-
}
590-
591-
for (var prop in bindings) {
592-
${this.liveBindings? `
593-
if (!module.exports.hasOwnProperty(prop) || prop === 'default') {
594-
Object.defineProperty(module.exports, prop, {
595-
get: bindings[prop],
596-
enumerable: true,
597-
configurable: true
598-
});
599-
` : `
600-
if (module.exports[prop] !== bindings[prop]()) {
601-
module.exports[prop] = bindings[prop]();
602-
`}
603-
604-
Object.keys(instances).forEach(key => {
605-
if (instances[key].dependencies.indexOf(number) > -1) {
606-
instances[key].__binder();
607-
}
608-
})
609-
}
610-
}
611-
});
612-
613-
// Initially this will bind nothing, unless
614-
// the module has been replaced by HMR
615-
module.__binder();
616-
};
617-
618-
var get_exports = function (parent, number) {
619-
return instances[number].exports;
620-
};
621-
622-
var resolve_module = function (parent, number) {
623-
var module = instances[number];
624-
625-
if (module.__resolved) {
626-
return;
627-
}
628-
629-
module.__resolving = true;
630-
631568
var localRequire = function (dep) {
632569
${format === 'cjs'? `
633570
if (typeof dep === 'string') {
@@ -659,13 +596,6 @@ class NollupCodeGenerator {
659596
}
660597
` : ''}
661598
662-
var executeModuleImpl = function (module) {
663-
${callNollupModuleWrap(/** @type {NollupPlugin[]} */ (plugins), `
664-
module.__resolved = true;
665-
module.__impl(localRequire, module, __nollup__global__);
666-
`)}
667-
};
668-
669599
localRequire.dynamic = function (file, entryIndex) {
670600
return new Promise(function (resolve) {
671601
var relative_file = getRelativePath('${path.dirname(chunk.fileName)}', file);
@@ -709,6 +639,76 @@ class NollupCodeGenerator {
709639
});
710640
};
711641
642+
modules[number](function (dep) {
643+
if (!instances[dep] || instances[dep].invalidate) {
644+
create_module(dep);
645+
}
646+
647+
if (instances[number].dependencies.indexOf(dep) === -1) {
648+
instances[number].dependencies.push(dep);
649+
}
650+
651+
return true;
652+
}, function (dep) {
653+
return get_exports(module, dep);
654+
}, function(binder, impl) {
655+
module.__binder = binder;
656+
module.__impl = impl;
657+
}, function (arg1, arg2) {
658+
var bindings = {};
659+
if (typeof arg1 === 'object') {
660+
bindings = arg1;
661+
} else {
662+
bindings[arg1] = arg2;
663+
}
664+
665+
for (var prop in bindings) {
666+
${this.liveBindings? `
667+
if (!module.exports.hasOwnProperty(prop) || prop === 'default') {
668+
Object.defineProperty(module.exports, prop, {
669+
get: bindings[prop],
670+
enumerable: true,
671+
configurable: true
672+
});
673+
` : `
674+
if (module.exports[prop] !== bindings[prop]()) {
675+
module.exports[prop] = bindings[prop]();
676+
`}
677+
678+
Object.keys(instances).forEach(key => {
679+
if (instances[key].dependencies.indexOf(number) > -1) {
680+
instances[key].__binder();
681+
}
682+
})
683+
}
684+
}
685+
}, localRequire, module, __nollup__global__);
686+
687+
// Initially this will bind nothing, unless
688+
// the module has been replaced by HMR
689+
module.__binder();
690+
};
691+
692+
var get_exports = function (parent, number) {
693+
return instances[number].exports;
694+
};
695+
696+
var resolve_module = function (parent, number) {
697+
var module = instances[number];
698+
699+
if (module.__resolved) {
700+
return;
701+
}
702+
703+
module.__resolving = true;
704+
705+
var executeModuleImpl = function (module) {
706+
${callNollupModuleWrap(/** @type {NollupPlugin[]} */ (plugins), `
707+
module.__resolved = true;
708+
module.__impl();
709+
`)}
710+
};
711+
712712
module.dependencies.forEach((dep) => {
713713
if (!instances[dep].__resolved && !instances[dep].__resolving) {
714714
resolve_module(module, dep);

test/cases/scenarios/simple.js

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,30 @@ async function createNollup (package, config) {
2828

2929
generate: async function () {
3030
let { output } = await bundle.generate(config.output);
31-
let code = (output && output[0].code) || '';
31+
32+
let _import = function (dep) {
33+
return new Promise(resolve => {
34+
let found = output.find(o => o.fileName === dep.substring(2));
35+
if (found) {
36+
eval(applyPolyfill(found.code));
37+
resolve();
38+
}
39+
})
40+
};
41+
42+
let applyPolyfill = function (code) {
43+
return code.replace(/import\(/g, '_import(');
44+
}
45+
46+
let code = applyPolyfill(output && output[0].code) || '';
3247
let module = undefined; // Shadow nodeJS module.exports
3348
let console = { log: (...args) => eval_console.push(args.join(' ')) }
49+
if (config.output.format === 'esm') {
50+
let mod = { exports : {} };
51+
eval(code.replace('export default ', 'mod.exports = ').replace('export var ', 'mod.exports.'));
52+
return mod.exports;
53+
}
54+
3455
return eval(code);
3556
}
3657
}
@@ -310,6 +331,14 @@ describe('Nollup', function () {
310331
expect(eval_console[0]).to.equal('hello');
311332
});
312333

334+
it ('Scenario: Circular Dependencies Function Using Require', async function () {
335+
let bundle = await createNollup('circular-hoist-fn-require', { output: { format: 'esm' }});
336+
let entry = await bundle.generate();
337+
await new Promise(resolve => setTimeout(resolve, 1000));
338+
expect(eval_console.length).to.equal(1);
339+
expect(eval_console[0]).to.equal('hello-dynamic');
340+
});
341+
313342
it ('Scenario: Circular Dependencies Shared Timing', async function () {
314343
let bundle = await createNollup('circular-shared-import-timing');
315344
let entry = await bundle.generate();
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export default 'dynamic';
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import { impl } from './other';
2+
3+
async function hello () {
4+
let dynamic = await import('./dynamic');
5+
console.log(impl + '-' + dynamic.default);
6+
}
7+
8+
export { hello };
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import { hello } from './index';
2+
3+
export const impl = 'hello';
4+
5+
hello();

0 commit comments

Comments
 (0)