Skip to content

Commit 7e36725

Browse files
authored
Fix dynamic dependency resolving (codesandbox#526)
1 parent 44e3229 commit 7e36725

File tree

5 files changed

+53
-17
lines changed

5 files changed

+53
-17
lines changed

packages/app/src/sandbox/eval/loaders/eval.js

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@ export default function(
77
require: Function,
88
module: Object,
99
env: Object = {},
10-
globals: Object = {}
10+
globals: Object = {},
11+
{ asUMD = false }: { asUMD: boolean } = {}
1112
) {
1213
const g = typeof window === 'undefined' ? self : window;
1314
const exports = module.exports;
@@ -26,12 +27,12 @@ export default function(
2627
// eslint-disable-next-line no-eval
2728
(0, eval)(newCode).apply(this, [
2829
require,
29-
module,
30-
exports,
30+
asUMD ? undefined : module,
31+
asUMD ? undefined : exports,
3132
process,
3233
setImmediate,
3334
Buffer,
34-
global,
35+
asUMD ? undefined : global,
3536
...globalsValues,
3637
]);
3738

packages/app/src/sandbox/eval/manager.js

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -474,6 +474,7 @@ export default class Manager {
474474
this.manifest.dependencies.find(d => d.name === dependencyName) ||
475475
this.manifest.dependencyDependencies[dependencyName]
476476
) {
477+
this.downloadDependency(connectedPath, currentPath);
477478
throw new ModuleNotFoundError(connectedPath, true);
478479
} else {
479480
throw new DependencyNotFoundError(connectedPath);
@@ -502,6 +503,21 @@ export default class Manager {
502503
});
503504
}
504505

506+
resolveTranspiledModuleAsync = async (
507+
path: string,
508+
currentPath: string
509+
): Promise<TranspiledModule> => {
510+
try {
511+
return this.resolveTranspiledModule(path, currentPath);
512+
} catch (e) {
513+
if (e.type === 'module-not-found' && e.isDependency) {
514+
return this.downloadDependency(e.path, currentPath);
515+
}
516+
517+
throw e;
518+
}
519+
};
520+
505521
/**
506522
* Resolve the transpiled module from the path, note that the path can actually
507523
* include loaders. That's why we're focussing on first extracting this query

packages/app/src/sandbox/eval/npm/fetch-npm-module.js

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -105,8 +105,6 @@ function downloadDependency(depName: string, depVersion: string, path: string) {
105105
return packages[path];
106106
}
107107

108-
const requestedPaths = [];
109-
110108
function resolvePath(
111109
path: string,
112110
currentPath: string,
@@ -148,16 +146,14 @@ function resolvePath(
148146
const depName = getDependencyName(depPath);
149147

150148
// To prevent infinite loops we keep track of which dependencies have been requested before.
151-
if (requestedPaths.includes(depPath)) {
149+
if (!manager.transpiledModules[p] && !meta[p]) {
152150
const err = new Error('Could not find ' + p);
153151
err.code = 'ENOENT';
154152

155153
callback(err);
156154
return null;
157155
}
158156

159-
requestedPaths.push(depPath);
160-
161157
// eslint-disable-next-line
162158
const subDepVersionVersionInfo = await findDependencyVersion(
163159
currentPath,

packages/app/src/sandbox/eval/presets/angular-cli/index.js

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -47,16 +47,38 @@ export default function initialize() {
4747

4848
const { styles = [], scripts = [] } = app;
4949

50-
await Promise.all(
51-
[...styles, ...scripts].map(async p => {
52-
const finalPath = absolute(join(app.root || 'src', p));
50+
/* eslint-disable no-await-in-loop */
51+
for (let i = 0; i < styles.length; i++) {
52+
const p = styles[i];
53+
const finalPath = absolute(join(app.root || 'src', p));
54+
55+
const tModule = await manager.resolveTranspiledModuleAsync(
56+
finalPath,
57+
'/'
58+
);
59+
60+
await tModule.transpile(manager);
61+
tModule.setIsEntry(true);
62+
tModule.evaluate(manager);
63+
}
64+
/* eslint-enable no-await-in-loop */
5365

54-
const module = manager.resolveModule(finalPath, '/');
55-
await manager.transpileModules(module);
56-
manager.evaluateModule(module);
66+
const scriptTModules = await Promise.all(
67+
scripts.map(async p => {
68+
const finalPath = absolute(join(app.root || 'src', p));
69+
const tModule = await manager.resolveTranspiledModuleAsync(
70+
finalPath,
71+
'/'
72+
);
73+
tModule.setIsEntry(true);
74+
return tModule.transpile(manager);
5775
})
5876
);
5977

78+
scriptTModules.forEach(t => {
79+
t.evaluate(manager, { asUMD: true });
80+
});
81+
6082
if (
6183
app.environmentSource &&
6284
app.environments &&

packages/app/src/sandbox/eval/transpiled-module.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -584,7 +584,7 @@ export default class TranspiledModule {
584584
return this;
585585
}
586586

587-
evaluate(manager: Manager) {
587+
evaluate(manager: Manager, { asUMD = false }: { asUMD: boolean } = {}) {
588588
if (this.source == null) {
589589
// This scenario only happens when we are in an inconsistent state, the quickest way to solve
590590
// this state is to just hard reload everything.
@@ -725,7 +725,8 @@ export default class TranspiledModule {
725725
require,
726726
this.compilation,
727727
manager.envVariables,
728-
manager.testRunner.testGlobals(this.module)
728+
manager.testRunner.testGlobals(this.module),
729+
{ asUMD }
729730
);
730731

731732
const hmrConfig = this.hmrConfig;

0 commit comments

Comments
 (0)