From 032ffe6ae1e81c344377cafde58d47784aefdd9c Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Thu, 15 Aug 2019 14:03:14 +0200 Subject: [PATCH] better exports trapping --- .../api/worker/extHostExtensionService.ts | 82 +++++++++++++++---- 1 file changed, 68 insertions(+), 14 deletions(-) diff --git a/src/vs/workbench/api/worker/extHostExtensionService.ts b/src/vs/workbench/api/worker/extHostExtensionService.ts index ada9786cd0f..d3d36327339 100644 --- a/src/vs/workbench/api/worker/extHostExtensionService.ts +++ b/src/vs/workbench/api/worker/extHostExtensionService.ts @@ -43,6 +43,69 @@ class ApiInstances { } } +class ExportsTrap { + + static readonly Instance = new ExportsTrap(); + + private readonly _names: string[] = []; + private readonly _exports = new Map(); + + private constructor() { + + const exportsProxy = new Proxy({}, { + set: (target: any, p: PropertyKey, value: any, receiver: any) => { + // store in target + target[p] = value; + // store in named-bucket + const name = this._names[this._names.length - 1]; + this._exports.get(name)![p] = value; + return true; + } + }); + + + const moduleProxy = new Proxy({}, { + + get: (target: any, p: PropertyKey) => { + if (p === 'exports') { + return exportsProxy; + } + + return target[p]; + }, + + set: (target: any, p: PropertyKey, value: any, receiver: any) => { + // store in target + target[p] = value; + + // override bucket + if (p === 'exports') { + const name = this._names[this._names.length - 1]; + this._exports.set(name, value); + } + return true; + } + }); + + (self).exports = exportsProxy; + (self).module = moduleProxy; + } + + add(name: string) { + this._exports.set(name, Object.create(null)); + this._names.push(name); + + return { + claim: () => { + const result = this._exports.get(name); + this._exports.delete(name); + this._names.pop(); + return result; + } + }; + } +} + export class ExtHostExtensionService extends AbstractExtHostExtensionService { private _apiInstances?: ApiInstances; @@ -57,7 +120,6 @@ export class ExtHostExtensionService extends AbstractExtHostExtensionService { protected _loadCommonJSModule(module: URI, activationTimesBuilder: ExtensionActivationTimesBuilder): Promise { - interface FakeCommonJSSelf { module?: object; exports?: object; @@ -82,38 +144,30 @@ export class ExtHostExtensionService extends AbstractExtHostExtensionService { throw new Error(`Cannot load module '${mod}'`); } - const moduleExportsTrap = { exports: Object.create(null) }; - patchSelf.module = moduleExportsTrap; - patchSelf.exports = moduleExportsTrap.exports; - const next = joinPath(parent, '..', ensureSuffix(mod, '.js')); moduleStack.push(next); + const trap = ExportsTrap.Instance.add(next.toString()); importScripts(asDomUri(next).toString(true)); moduleStack.pop(); - return moduleExportsTrap.exports; + return trap.claim(); }; try { activationTimesBuilder.codeLoadingStart(); - - const moduleExportsTrap = { exports: Object.create(null) }; - patchSelf.module = moduleExportsTrap; - patchSelf.exports = moduleExportsTrap.exports; - module = module.with({ path: ensureSuffix(module.path, '.js') }); moduleStack.push(module); - + const trap = ExportsTrap.Instance.add(module.toString()); importScripts(asDomUri(module).toString(true)); moduleStack.pop(); - return Promise.resolve(moduleExportsTrap.exports); + return Promise.resolve(trap.claim()); } finally { activationTimesBuilder.codeLoadingStop(); } } - async $setRemoteEnvironment(env: { [key: string]: string | null }): Promise { + async $setRemoteEnvironment(_env: { [key: string]: string | null }): Promise { throw new Error('Not supported'); } }