Skip to content

Commit e069209

Browse files
committed
Add NodeModuleRequireInterceptor
1 parent 6ed5ceb commit e069209

1 file changed

Lines changed: 56 additions & 20 deletions

File tree

src/vs/workbench/api/node/extHost.api.impl.ts

Lines changed: 56 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -877,41 +877,77 @@ class Extension<T> implements vscode.Extension<T> {
877877
}
878878
}
879879

880+
interface INodeModuleFactory {
881+
readonly nodeModuleName: string;
882+
load(request: string, parent: { filename: string; }): any;
883+
}
884+
885+
class NodeModuleRequireInterceptor {
886+
public static INSTANCE = new NodeModuleRequireInterceptor();
887+
888+
private readonly _factories: Map<string, INodeModuleFactory>;
889+
890+
constructor() {
891+
this._factories = new Map<string, INodeModuleFactory>();
892+
this._installInterceptor(this._factories);
893+
}
894+
895+
private _installInterceptor(factories: Map<string, INodeModuleFactory>): void {
896+
const node_module = <any>require.__$__nodeRequire('module');
897+
const original = node_module._load;
898+
node_module._load = function load(request: string, parent: { filename: string; }, isMain: any) {
899+
if (!factories.has(request)) {
900+
return original.apply(this, arguments);
901+
}
902+
return factories.get(request)!.load(request, parent);
903+
};
904+
}
905+
906+
public register(interceptor: INodeModuleFactory): void {
907+
this._factories.set(interceptor.nodeModuleName, interceptor);
908+
}
909+
}
910+
880911
export function initializeExtensionApi(extensionService: ExtHostExtensionService, apiFactory: IExtensionApiFactory, extensionRegistry: ExtensionDescriptionRegistry, configProvider: ExtHostConfigProvider): Promise<void> {
881-
return extensionService.getExtensionPathIndex().then(trie => defineAPI(apiFactory, trie, extensionRegistry, configProvider));
912+
return extensionService.getExtensionPathIndex().then(extensionPaths => {
913+
NodeModuleRequireInterceptor.INSTANCE.register(new VSCodeNodeModuleFactory(apiFactory, extensionPaths, extensionRegistry, configProvider));
914+
});
882915
}
883916

884-
function defineAPI(factory: IExtensionApiFactory, extensionPaths: TernarySearchTree<IExtensionDescription>, extensionRegistry: ExtensionDescriptionRegistry, configProvider: ExtHostConfigProvider): void {
917+
class VSCodeNodeModuleFactory implements INodeModuleFactory {
918+
public readonly nodeModuleName = 'vscode';
885919

886-
// each extension is meant to get its own api implementation
887-
const extApiImpl = new Map<string, typeof vscode>();
888-
let defaultApiImpl: typeof vscode;
920+
private readonly _extApiImpl = new Map<string, typeof vscode>();
921+
private _defaultApiImpl: typeof vscode;
889922

890-
const node_module = <any>require.__$__nodeRequire('module');
891-
const original = node_module._load;
892-
node_module._load = function load(request: string, parent: any, isMain: any) {
893-
if (request !== 'vscode') {
894-
return original.apply(this, arguments);
895-
}
923+
constructor(
924+
private readonly _apiFactory: IExtensionApiFactory,
925+
private readonly _extensionPaths: TernarySearchTree<IExtensionDescription>,
926+
private readonly _extensionRegistry: ExtensionDescriptionRegistry,
927+
private readonly _configProvider: ExtHostConfigProvider
928+
) {
929+
}
930+
931+
public load(request: string, parent: { filename: string; }): any {
896932

897933
// get extension id from filename and api for extension
898-
const ext = extensionPaths.findSubstr(URI.file(parent.filename).fsPath);
934+
const ext = this._extensionPaths.findSubstr(URI.file(parent.filename).fsPath);
899935
if (ext) {
900-
let apiImpl = extApiImpl.get(ExtensionIdentifier.toKey(ext.identifier));
936+
let apiImpl = this._extApiImpl.get(ExtensionIdentifier.toKey(ext.identifier));
901937
if (!apiImpl) {
902-
apiImpl = factory(ext, extensionRegistry, configProvider);
903-
extApiImpl.set(ExtensionIdentifier.toKey(ext.identifier), apiImpl);
938+
apiImpl = this._apiFactory(ext, this._extensionRegistry, this._configProvider);
939+
this._extApiImpl.set(ExtensionIdentifier.toKey(ext.identifier), apiImpl);
904940
}
905941
return apiImpl;
906942
}
907943

908944
// fall back to a default implementation
909-
if (!defaultApiImpl) {
945+
if (!this._defaultApiImpl) {
910946
let extensionPathsPretty = '';
911-
extensionPaths.forEach((value, index) => extensionPathsPretty += `\t${index} -> ${value.identifier.value}\n`);
947+
this._extensionPaths.forEach((value, index) => extensionPathsPretty += `\t${index} -> ${value.identifier.value}\n`);
912948
console.warn(`Could not identify extension for 'vscode' require call from ${parent.filename}. These are the extension path mappings: \n${extensionPathsPretty}`);
913-
defaultApiImpl = factory(nullExtensionDescription, extensionRegistry, configProvider);
949+
this._defaultApiImpl = this._apiFactory(nullExtensionDescription, this._extensionRegistry, this._configProvider);
914950
}
915-
return defaultApiImpl;
916-
};
951+
return this._defaultApiImpl;
952+
}
917953
}

0 commit comments

Comments
 (0)