From 1d5a01b7522ec51398890b0e9d13d1ef9b7bcb77 Mon Sep 17 00:00:00 2001 From: Jasper De Moor Date: Wed, 6 Apr 2022 17:11:59 +0200 Subject: [PATCH 1/4] fix: transpile vue deps in setup script (#6605) --- packages/app/src/sandbox/eval/presets/vue-cli/index.ts | 5 ++--- .../src/transpiled-module/transpiled-module.ts | 7 +++++++ 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/packages/app/src/sandbox/eval/presets/vue-cli/index.ts b/packages/app/src/sandbox/eval/presets/vue-cli/index.ts index e048690b241..38b195a839e 100644 --- a/packages/app/src/sandbox/eval/presets/vue-cli/index.ts +++ b/packages/app/src/sandbox/eval/presets/vue-cli/index.ts @@ -63,9 +63,8 @@ export default function initialize() { try { const vueModule = await manager.resolveTranspiledModule('vue', '/'); - if (!vueModule.source) { - await vueModule.transpile(manager); - } + await vueModule.transpileTree(manager); + const Vue = vueModule.evaluate(manager); if (Vue) { diff --git a/packages/sandpack-core/src/transpiled-module/transpiled-module.ts b/packages/sandpack-core/src/transpiled-module/transpiled-module.ts index bdf04c9d7de..fb2bba79081 100644 --- a/packages/sandpack-core/src/transpiled-module/transpiled-module.ts +++ b/packages/sandpack-core/src/transpiled-module/transpiled-module.ts @@ -749,6 +749,13 @@ export class TranspiledModule { ); } + /** Transpile current module and ensure the surrounding tree (dependencies and initiators) are also transpiled */ + async transpileTree(manager: Manager): Promise { + await this.transpile(manager); + await manager.verifyTreeTranspiled(); + return this; + } + logWarnings = () => { if (this.warnings.length) { this.warnings.forEach(warning => { From 206da7c0528839812caa874e95f4ee4e0e9a0e48 Mon Sep 17 00:00:00 2001 From: Jasper De Moor Date: Wed, 6 Apr 2022 17:33:35 +0200 Subject: [PATCH 2/4] fix: use custom set in transpiled module to bypass polyfill of Array,from (#6604) --- packages/sandpack-core/src/manager.ts | 12 ++-- .../src/transpiled-module/CustomSet.ts | 32 +++++++++ .../transpiled-module/transpiled-module.ts | 72 ++++++++++--------- 3 files changed, 79 insertions(+), 37 deletions(-) create mode 100644 packages/sandpack-core/src/transpiled-module/CustomSet.ts diff --git a/packages/sandpack-core/src/manager.ts b/packages/sandpack-core/src/manager.ts index 3f3bba733dc..8c9ca7c5f4d 100644 --- a/packages/sandpack-core/src/manager.ts +++ b/packages/sandpack-core/src/manager.ts @@ -626,11 +626,13 @@ export default class Manager implements IEvaluator { } verifyTreeTranspiled() { - return Promise.all( - this.getTranspiledModules() - .filter(tModule => tModule.shouldTranspile()) - .map(tModule => tModule.transpile(this)) - ); + const promises = []; + for (const tModule of this.getTranspiledModules()) { + if (tModule.shouldTranspile()) { + promises.push(tModule.transpile(this)); + } + } + return Promise.all(promises); } clearCompiledCache() { diff --git a/packages/sandpack-core/src/transpiled-module/CustomSet.ts b/packages/sandpack-core/src/transpiled-module/CustomSet.ts new file mode 100644 index 00000000000..57ee9e78bff --- /dev/null +++ b/packages/sandpack-core/src/transpiled-module/CustomSet.ts @@ -0,0 +1,32 @@ +// This is a hack to work around some polyfills +export class CustomSet { + private internalSet: Set; + + constructor() { + this.internalSet = new Set(); + } + + size(): number { + return this.internalSet.size; + } + + clear() { + this.internalSet.clear(); + } + + add(val: T): void { + this.internalSet.add(val); + } + + delete(val: T): void { + this.internalSet.delete(val); + } + + values(): Array { + const result = []; + for (const val of this.internalSet) { + result.push(val); + } + return result; + } +} diff --git a/packages/sandpack-core/src/transpiled-module/transpiled-module.ts b/packages/sandpack-core/src/transpiled-module/transpiled-module.ts index fb2bba79081..939846976e8 100644 --- a/packages/sandpack-core/src/transpiled-module/transpiled-module.ts +++ b/packages/sandpack-core/src/transpiled-module/transpiled-module.ts @@ -23,6 +23,7 @@ import HMR from './hmr'; import { splitQueryFromPath } from './utils/query-path'; import { getModuleUrl } from './module-url'; import delay from '../utils/delay'; +import { CustomSet } from './CustomSet'; declare const BrowserFS: any; @@ -163,11 +164,11 @@ export class TranspiledModule { errors: Array; warnings: Array; compilation: Compilation | null = null; - initiators: Set; // eslint-disable-line no-use-before-define - dependencies: Set; // eslint-disable-line no-use-before-define + initiators: CustomSet; // eslint-disable-line no-use-before-define + dependencies: CustomSet; // eslint-disable-line no-use-before-define asyncDependencies: Array>; // eslint-disable-line no-use-before-define - transpilationDependencies: Set; - transpilationInitiators: Set; + transpilationDependencies: CustomSet; + transpilationInitiators: CustomSet; // Unique identifier hash: string; @@ -196,11 +197,11 @@ export class TranspiledModule { this.errors = []; this.warnings = []; this.childModules = []; - this.transpilationDependencies = new Set(); - this.dependencies = new Set(); + this.transpilationDependencies = new CustomSet(); + this.dependencies = new CustomSet(); this.asyncDependencies = []; - this.transpilationInitiators = new Set(); - this.initiators = new Set(); + this.transpilationInitiators = new CustomSet(); + this.initiators = new CustomSet(); this.isEntry = false; this.isTestFile = false; @@ -220,7 +221,7 @@ export class TranspiledModule { this.reset(); // Reset parents - this.initiators.forEach(tModule => { + this.initiators.values().forEach(tModule => { tModule.resetTranspilation(); }); @@ -251,7 +252,8 @@ export class TranspiledModule { } resetTranspilation() { - Array.from(this.transpilationInitiators) + this.transpilationInitiators + .values() .filter(t => t.source) .forEach(dep => { dep.resetTranspilation(); @@ -263,7 +265,7 @@ export class TranspiledModule { this.errors = []; this.warnings = []; - Array.from(this.dependencies).forEach(t => { + this.dependencies.values().forEach(t => { t.initiators.delete(this); }); // Don't do it for transpilation dependencies, since those cannot be traced back since we also reset transpilation of them. @@ -281,13 +283,15 @@ export class TranspiledModule { if (this.hmrConfig && this.hmrConfig.isHot()) { this.hmrConfig.setDirty(true); } else { - Array.from(this.initiators) + this.initiators + .values() .filter(t => t.compilation) .forEach(initiator => { initiator.resetCompilation(); }); - Array.from(this.transpilationInitiators) + this.transpilationInitiators + .values() .filter(t => t.compilation) .forEach(dep => { dep.resetCompilation(); @@ -296,7 +300,8 @@ export class TranspiledModule { // If this is an entry we want all direct entries to be reset as well. // Entries generally have side effects if (this.isEntry) { - Array.from(this.dependencies) + this.dependencies + .values() .filter(t => t.compilation && t.isEntry) .forEach(dep => { dep.resetCompilation(); @@ -313,7 +318,7 @@ export class TranspiledModule { return ( !this.source && !this.isTestFile && - !(this.initiators.size === 0 && this.transpilationInitiators.size > 0) + !(this.initiators.size() === 0 && this.transpilationInitiators.size() > 0) ); } @@ -561,15 +566,16 @@ export class TranspiledModule { // Remove this module from the initiators of old deps, so we can populate a // fresh cache - this.dependencies.forEach(tModule => { + this.dependencies.values().forEach(tModule => { tModule.initiators.delete(this); }); - this.transpilationDependencies.forEach(tModule => { + this.transpilationDependencies.values().forEach(tModule => { tModule.transpilationInitiators.delete(this); }); this.childModules.forEach(tModule => { tModule.dispose(manager); }); + this.dependencies.clear(); this.transpilationDependencies.clear(); this.childModules.length = 0; @@ -691,10 +697,8 @@ export class TranspiledModule { this.asyncDependencies = []; await Promise.all([ - ...Array.from(this.transpilationInitiators).map(t => - t.transpile(manager) - ), - ...Array.from(this.dependencies).map(t => t.transpile(manager)), + ...this.transpilationInitiators.values().map(t => t.transpile(manager)), + ...this.dependencies.values().map(t => t.transpile(manager)), ]); return this; @@ -947,7 +951,8 @@ export class TranspiledModule { this.hmrConfig = this.hmrConfig || new HMR(); // We have to bubble up, so reset compilation of parents - Array.from(this.initiators) + this.initiators + .values() .filter(t => t.compilation) .forEach(dep => { dep.resetCompilation(); @@ -1093,8 +1098,8 @@ export class TranspiledModule { postTranspile(manager: Manager) { if ( - this.initiators.size === 0 && - this.transpilationInitiators.size === 0 && + this.initiators.size() === 0 && + this.transpilationInitiators.size() === 0 && !this.isEntry && !manager.isFirstLoad && // Don't delete stubbed modules, they are here for a reason, most probably @@ -1128,6 +1133,7 @@ export class TranspiledModule { const sourceEqualsCompiled = Boolean( this.source && this.source.sourceEqualsCompiled ); + const serializableObject: SerializedTranspiledModule = { query: this.query, module: this.module, @@ -1136,14 +1142,16 @@ export class TranspiledModule { sourceEqualsCompiled, childModules: this.childModules.map(m => m.getId()), - dependencies: Array.from(this.dependencies).map(m => m.getId()), - initiators: Array.from(this.initiators).map(m => m.getId()), - transpilationDependencies: Array.from( - this.transpilationDependencies - ).map(m => m.getId()), - transpilationInitiators: Array.from(this.transpilationInitiators).map(m => - m.getId() - ), + dependencies: this.dependencies.values().map(m => { + return m.getId(); + }), + initiators: this.initiators.values().map(m => m.getId()), + transpilationDependencies: this.transpilationDependencies + .values() + .map(m => m.getId()), + transpilationInitiators: this.transpilationInitiators + .values() + .map(m => m.getId()), asyncDependencies: await Promise.all( Array.from(this.asyncDependencies).map(m => m.then(x => x.getId())) ), From cbe037f4771d5a7d3bd4cffe24857be8e98b9163 Mon Sep 17 00:00:00 2001 From: Jasper De Moor Date: Wed, 6 Apr 2022 20:01:45 +0200 Subject: [PATCH 3/4] Revert "fix: use custom set in transpiled module to bypass polyfill of Array,from (#6604)" This reverts commit 206da7c0528839812caa874e95f4ee4e0e9a0e48. --- packages/sandpack-core/src/manager.ts | 12 ++-- .../src/transpiled-module/CustomSet.ts | 32 --------- .../transpiled-module/transpiled-module.ts | 72 +++++++++---------- 3 files changed, 37 insertions(+), 79 deletions(-) delete mode 100644 packages/sandpack-core/src/transpiled-module/CustomSet.ts diff --git a/packages/sandpack-core/src/manager.ts b/packages/sandpack-core/src/manager.ts index 8c9ca7c5f4d..3f3bba733dc 100644 --- a/packages/sandpack-core/src/manager.ts +++ b/packages/sandpack-core/src/manager.ts @@ -626,13 +626,11 @@ export default class Manager implements IEvaluator { } verifyTreeTranspiled() { - const promises = []; - for (const tModule of this.getTranspiledModules()) { - if (tModule.shouldTranspile()) { - promises.push(tModule.transpile(this)); - } - } - return Promise.all(promises); + return Promise.all( + this.getTranspiledModules() + .filter(tModule => tModule.shouldTranspile()) + .map(tModule => tModule.transpile(this)) + ); } clearCompiledCache() { diff --git a/packages/sandpack-core/src/transpiled-module/CustomSet.ts b/packages/sandpack-core/src/transpiled-module/CustomSet.ts deleted file mode 100644 index 57ee9e78bff..00000000000 --- a/packages/sandpack-core/src/transpiled-module/CustomSet.ts +++ /dev/null @@ -1,32 +0,0 @@ -// This is a hack to work around some polyfills -export class CustomSet { - private internalSet: Set; - - constructor() { - this.internalSet = new Set(); - } - - size(): number { - return this.internalSet.size; - } - - clear() { - this.internalSet.clear(); - } - - add(val: T): void { - this.internalSet.add(val); - } - - delete(val: T): void { - this.internalSet.delete(val); - } - - values(): Array { - const result = []; - for (const val of this.internalSet) { - result.push(val); - } - return result; - } -} diff --git a/packages/sandpack-core/src/transpiled-module/transpiled-module.ts b/packages/sandpack-core/src/transpiled-module/transpiled-module.ts index 939846976e8..fb2bba79081 100644 --- a/packages/sandpack-core/src/transpiled-module/transpiled-module.ts +++ b/packages/sandpack-core/src/transpiled-module/transpiled-module.ts @@ -23,7 +23,6 @@ import HMR from './hmr'; import { splitQueryFromPath } from './utils/query-path'; import { getModuleUrl } from './module-url'; import delay from '../utils/delay'; -import { CustomSet } from './CustomSet'; declare const BrowserFS: any; @@ -164,11 +163,11 @@ export class TranspiledModule { errors: Array; warnings: Array; compilation: Compilation | null = null; - initiators: CustomSet; // eslint-disable-line no-use-before-define - dependencies: CustomSet; // eslint-disable-line no-use-before-define + initiators: Set; // eslint-disable-line no-use-before-define + dependencies: Set; // eslint-disable-line no-use-before-define asyncDependencies: Array>; // eslint-disable-line no-use-before-define - transpilationDependencies: CustomSet; - transpilationInitiators: CustomSet; + transpilationDependencies: Set; + transpilationInitiators: Set; // Unique identifier hash: string; @@ -197,11 +196,11 @@ export class TranspiledModule { this.errors = []; this.warnings = []; this.childModules = []; - this.transpilationDependencies = new CustomSet(); - this.dependencies = new CustomSet(); + this.transpilationDependencies = new Set(); + this.dependencies = new Set(); this.asyncDependencies = []; - this.transpilationInitiators = new CustomSet(); - this.initiators = new CustomSet(); + this.transpilationInitiators = new Set(); + this.initiators = new Set(); this.isEntry = false; this.isTestFile = false; @@ -221,7 +220,7 @@ export class TranspiledModule { this.reset(); // Reset parents - this.initiators.values().forEach(tModule => { + this.initiators.forEach(tModule => { tModule.resetTranspilation(); }); @@ -252,8 +251,7 @@ export class TranspiledModule { } resetTranspilation() { - this.transpilationInitiators - .values() + Array.from(this.transpilationInitiators) .filter(t => t.source) .forEach(dep => { dep.resetTranspilation(); @@ -265,7 +263,7 @@ export class TranspiledModule { this.errors = []; this.warnings = []; - this.dependencies.values().forEach(t => { + Array.from(this.dependencies).forEach(t => { t.initiators.delete(this); }); // Don't do it for transpilation dependencies, since those cannot be traced back since we also reset transpilation of them. @@ -283,15 +281,13 @@ export class TranspiledModule { if (this.hmrConfig && this.hmrConfig.isHot()) { this.hmrConfig.setDirty(true); } else { - this.initiators - .values() + Array.from(this.initiators) .filter(t => t.compilation) .forEach(initiator => { initiator.resetCompilation(); }); - this.transpilationInitiators - .values() + Array.from(this.transpilationInitiators) .filter(t => t.compilation) .forEach(dep => { dep.resetCompilation(); @@ -300,8 +296,7 @@ export class TranspiledModule { // If this is an entry we want all direct entries to be reset as well. // Entries generally have side effects if (this.isEntry) { - this.dependencies - .values() + Array.from(this.dependencies) .filter(t => t.compilation && t.isEntry) .forEach(dep => { dep.resetCompilation(); @@ -318,7 +313,7 @@ export class TranspiledModule { return ( !this.source && !this.isTestFile && - !(this.initiators.size() === 0 && this.transpilationInitiators.size() > 0) + !(this.initiators.size === 0 && this.transpilationInitiators.size > 0) ); } @@ -566,16 +561,15 @@ export class TranspiledModule { // Remove this module from the initiators of old deps, so we can populate a // fresh cache - this.dependencies.values().forEach(tModule => { + this.dependencies.forEach(tModule => { tModule.initiators.delete(this); }); - this.transpilationDependencies.values().forEach(tModule => { + this.transpilationDependencies.forEach(tModule => { tModule.transpilationInitiators.delete(this); }); this.childModules.forEach(tModule => { tModule.dispose(manager); }); - this.dependencies.clear(); this.transpilationDependencies.clear(); this.childModules.length = 0; @@ -697,8 +691,10 @@ export class TranspiledModule { this.asyncDependencies = []; await Promise.all([ - ...this.transpilationInitiators.values().map(t => t.transpile(manager)), - ...this.dependencies.values().map(t => t.transpile(manager)), + ...Array.from(this.transpilationInitiators).map(t => + t.transpile(manager) + ), + ...Array.from(this.dependencies).map(t => t.transpile(manager)), ]); return this; @@ -951,8 +947,7 @@ export class TranspiledModule { this.hmrConfig = this.hmrConfig || new HMR(); // We have to bubble up, so reset compilation of parents - this.initiators - .values() + Array.from(this.initiators) .filter(t => t.compilation) .forEach(dep => { dep.resetCompilation(); @@ -1098,8 +1093,8 @@ export class TranspiledModule { postTranspile(manager: Manager) { if ( - this.initiators.size() === 0 && - this.transpilationInitiators.size() === 0 && + this.initiators.size === 0 && + this.transpilationInitiators.size === 0 && !this.isEntry && !manager.isFirstLoad && // Don't delete stubbed modules, they are here for a reason, most probably @@ -1133,7 +1128,6 @@ export class TranspiledModule { const sourceEqualsCompiled = Boolean( this.source && this.source.sourceEqualsCompiled ); - const serializableObject: SerializedTranspiledModule = { query: this.query, module: this.module, @@ -1142,16 +1136,14 @@ export class TranspiledModule { sourceEqualsCompiled, childModules: this.childModules.map(m => m.getId()), - dependencies: this.dependencies.values().map(m => { - return m.getId(); - }), - initiators: this.initiators.values().map(m => m.getId()), - transpilationDependencies: this.transpilationDependencies - .values() - .map(m => m.getId()), - transpilationInitiators: this.transpilationInitiators - .values() - .map(m => m.getId()), + dependencies: Array.from(this.dependencies).map(m => m.getId()), + initiators: Array.from(this.initiators).map(m => m.getId()), + transpilationDependencies: Array.from( + this.transpilationDependencies + ).map(m => m.getId()), + transpilationInitiators: Array.from(this.transpilationInitiators).map(m => + m.getId() + ), asyncDependencies: await Promise.all( Array.from(this.asyncDependencies).map(m => m.then(x => x.getId())) ), From 03e2d25addef2d856346b2a7493abfd6d7f292be Mon Sep 17 00:00:00 2001 From: Jasper De Moor Date: Wed, 6 Apr 2022 20:31:33 +0200 Subject: [PATCH 4/4] chore: Tweak verify tree (#6608) --- packages/sandpack-core/src/manager.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/sandpack-core/src/manager.ts b/packages/sandpack-core/src/manager.ts index 3f3bba733dc..7230fcfa195 100644 --- a/packages/sandpack-core/src/manager.ts +++ b/packages/sandpack-core/src/manager.ts @@ -626,11 +626,11 @@ export default class Manager implements IEvaluator { } verifyTreeTranspiled() { - return Promise.all( - this.getTranspiledModules() - .filter(tModule => tModule.shouldTranspile()) - .map(tModule => tModule.transpile(this)) - ); + const promises: Promise[] = []; + for (const tModule of this.getTranspiledModules()) { + promises.push(tModule.transpile(this)); + } + return Promise.all(promises); } clearCompiledCache() {