| import * as resolve from 'resolve'; |
| import * as path from 'path'; |
| import { getCaller, getCallSites } from './stubs/resolve-caller'; |
|
|
| function getConstants() { |
| const constants = require('constants-browserify'); |
| constants.FS = BrowserFS.BFSRequire('fs'); |
|
|
| return constants; |
| } |
|
|
| function updateChildren( |
| parent: Module | undefined, |
| child: Module, |
| scan: boolean |
| ) { |
| const children = parent && parent.children; |
| if (children && !(scan && children.includes(child))) children.push(child); |
| } |
|
|
| export default class Module { |
| id: string; |
| exports: any; |
| parent: Module | undefined; |
| children: Module[]; |
| filename: string | null; |
| loaded: boolean; |
| static _extensions: { |
| [ext: string]: (module: Module, filename: string) => void; |
| } = { |
| '.js': function(module: Module, filename: string) { |
| const fs = BrowserFS.BFSRequire('fs'); |
| const content = fs.readFileSync(filename, 'utf8'); |
|
|
| module._compile(content, filename); |
| }, |
| '.json': function(module: Module, filename: string) { |
| const fs = BrowserFS.BFSRequire('fs'); |
| const content = fs.readFileSync(filename, 'utf8'); |
|
|
| try { |
| module.exports = JSON.parse(content); |
| } catch (err: any) { |
| err.message = filename + ': ' + err.message; |
| throw err; |
| } |
| }, |
| }; |
|
|
| static globalPaths = []; |
|
|
| static _cache: { |
| [filename: string]: Module; |
| } = {}; |
|
|
| constructor(id: string, parent?: Module) { |
| this.id = id; |
| this.exports = {}; |
| this.parent = parent; |
| updateChildren(parent, this, false); |
|
|
| this.filename = null; |
| this.loaded = false; |
| this.children = []; |
| } |
|
|
| load(filename: string) { |
| if (this.loaded) { |
| throw new Error('Loaded already'); |
| } |
|
|
| this.filename = filename; |
|
|
| let extension = path.extname(filename) || '.js'; |
| if (!Module._extensions[extension]) extension = '.js'; |
|
|
| Module._extensions[extension](this, filename); |
|
|
| this.loaded = true; |
| } |
|
|
| require(path: string) { |
| return Module._load(path, this); |
| } |
|
|
| _compile(content: string, filename: string) { |
| const _self = this; |
| |
| content = content.replace(/^\#\!.*/, ''); |
|
|
| function require(path: string) { |
| return _self.require(path); |
| } |
|
|
| require.cache = Module._cache; |
|
|
| require.resolve = function(request: string) { |
| return Module._resolveFilename(request, _self); |
| }; |
|
|
| const global: any = { |
| require, |
| exports: _self.exports, |
| __filename: filename, |
| __dirname: path.dirname(filename), |
| module: _self, |
| }; |
| global.global = self; |
|
|
| Module.evaluate( |
| global, |
| [content, `//# sourceURL=${location.origin}${filename}`].join('\n') |
| ); |
| } |
|
|
| static evaluate(global: any, content: string) { |
| |
| const oldamd = (self as any).define; |
| (self as any).define = null; |
|
|
| const globalParams = Object.keys(global).join(', '); |
| const newCode = [`(function(${globalParams}) {`, content, `})`].join('\n'); |
|
|
| const result = (0, eval)(newCode).apply( |
| this, |
| Object.keys(global).map(m => global[m]) |
| ); |
|
|
| (self as any).define = oldamd; |
| return result; |
| } |
|
|
| static _resolveFilename(request: string, parent: Module): string { |
| return resolve.sync(request, { |
| basedir: parent.filename ? path.dirname(parent.filename) : undefined, |
| extensions: ['.js', '.json'], |
| }); |
| } |
|
|
| static createRequire(fromPath: string) { |
| const module = new Module(fromPath); |
| module.filename = fromPath; |
|
|
| return module._createRequire(); |
| } |
|
|
| _createRequire() { |
| const require = (p: string) => this.require(p); |
|
|
| require.resolve = (request: string) => { |
| return Module._resolveFilename(request, this); |
| }; |
|
|
| return require; |
| } |
|
|
| static _load(request: string, parent: Module, isMain?: boolean) { |
| if (request === 'module') { |
| return Module; |
| } |
|
|
| if (request === 'child_process') { |
| return require('./child_process'); |
| } |
|
|
| if (request === 'net') { |
| return require('./net'); |
| } |
|
|
| if (request === 'assert') { |
| return require('assert'); |
| } |
|
|
| if (request === 'string_decoder') { |
| return require('string_decoder'); |
| } |
|
|
| if (request === 'diagnostics') { |
| return require('debug'); |
| } |
|
|
| if (request === '/vscode/node_modules.asar/vscode-textmate') { |
| return require('vscode-textmate/out/main'); |
| } |
|
|
| if (request === 'zlib') { |
| return require('browserify-zlib'); |
| } |
|
|
| if (request === 'punycode') { |
| return require('punycode'); |
| } |
|
|
| if (request === 'execa') { |
| return {}; |
| } |
|
|
| if (request === 'tty') { |
| return { isatty: () => false }; |
| } |
|
|
| if (request === 'stream') { |
| return require('stream-browserify'); |
| } |
|
|
| if (request === 'http') { |
| |
| self.window = self; |
| return require('http-browserify'); |
| } |
|
|
| if (request === 'https') { |
| |
| self.window = self; |
| return require('https-browserify'); |
| } |
|
|
| if (request === 'constants') { |
| return getConstants(); |
| } |
|
|
| if (request.startsWith('vscode-extension-telemetry')) { |
| return { |
| default: class TelemetryService { |
| constructor( |
| extensionId: string, |
| extensionVersion: string, |
| key: string |
| ) {} |
|
|
| sendTelemetryEvent( |
| eventName: string, |
| properties?: { |
| [key: string]: string; |
| }, |
| measurements?: { |
| [key: string]: number; |
| } |
| ) {} |
|
|
| dispose() {} |
| }, |
| }; |
| } |
|
|
| if (request === 'url') { |
| return require('url'); |
| } |
|
|
| if (request === 'crypto') { |
| return require('crypto'); |
| } |
|
|
| if (request === 'util') { |
| |
| return require('../node_modules/util'); |
| } |
|
|
| if (request === 'os') { |
| return require('os'); |
| } |
|
|
| if (request === 'events') { |
| return require('events'); |
| } |
|
|
| if (request === 'readline') { |
| return require('./readline'); |
| } |
|
|
| if (request === 'stream') { |
| return require('stream'); |
| } |
|
|
| if (request === 'https-proxy-agent') { |
| return {}; |
| } |
|
|
| if (request === 'http-proxy-agent') { |
| return {}; |
| } |
|
|
| if (request === 'tls') { |
| return {}; |
| } |
|
|
| if (request === 'fs' || request === 'graceful-fs') { |
| const fs = BrowserFS.BFSRequire('fs'); |
| fs.constants = getConstants(); |
|
|
| |
| |
| fs.accessSync = (_path: any, _type: any) => { |
| if (fs.existsSync(_path)) { |
| return true; |
| } |
| throw new Error('File not found'); |
| }; |
| fs.access = (_path: any, cb1: any, cb: (err?: Error) => void) => { |
| const callback = cb || cb1; |
|
|
| |
| if (fs.existsSync(_path)) { |
| return callback(); |
| } |
| callback(new Error('File not found')); |
| }; |
|
|
| return fs; |
| } |
|
|
| |
| if (BrowserFS.BFSRequire(request)) { |
| return BrowserFS.BFSRequire(request); |
| } |
|
|
| const filename = Module._resolveFilename(request, parent); |
| const cachedModule = Module._cache[filename]; |
| if (cachedModule) { |
| updateChildren(parent, cachedModule, true); |
| return cachedModule.exports; |
| } |
|
|
| if (filename === 'callsites') { |
| return getCallSites; |
| } |
|
|
| if (filename.endsWith('resolve/lib/caller.js')) { |
| return getCaller; |
| } |
|
|
| const module = new Module(filename, parent); |
|
|
| if (isMain) { |
| |
| process.mainModule = module; |
| module.id = '.'; |
| } |
|
|
| Module._cache[filename] = module; |
|
|
| let threw = true; |
| try { |
| module.load(filename); |
| threw = false; |
| } finally { |
| if (threw) { |
| delete Module._cache[filename]; |
| console.error(module, 'had trouble loading...'); |
| } |
| } |
|
|
| return module.exports; |
| } |
| } |
|
|