1'use strict'; 2 3const { 4 ObjectDefineProperty, 5 SafeMap, 6} = primordials; 7const { 8 ERR_MANIFEST_DEPENDENCY_MISSING, 9 ERR_UNKNOWN_BUILTIN_MODULE 10} = require('internal/errors').codes; 11const { NativeModule } = require('internal/bootstrap/loaders'); 12 13const { validateString } = require('internal/validators'); 14const path = require('path'); 15const { pathToFileURL, fileURLToPath } = require('internal/url'); 16const { URL } = require('url'); 17 18let debug = require('internal/util/debuglog').debuglog('module', (fn) => { 19 debug = fn; 20}); 21 22function loadNativeModule(filename, request) { 23 const mod = NativeModule.map.get(filename); 24 if (mod) { 25 debug('load native module %s', request); 26 mod.compileForPublicLoader(); 27 return mod; 28 } 29} 30 31// Invoke with makeRequireFunction(module) where |module| is the Module object 32// to use as the context for the require() function. 33// Use redirects to set up a mapping from a policy and restrict dependencies 34const urlToFileCache = new SafeMap(); 35function makeRequireFunction(mod, redirects) { 36 const Module = mod.constructor; 37 38 let require; 39 if (redirects) { 40 const { resolve, reaction } = redirects; 41 const id = mod.filename || mod.id; 42 require = function require(path) { 43 let missing = true; 44 const destination = resolve(path); 45 if (destination === true) { 46 missing = false; 47 } else if (destination) { 48 const href = destination.href; 49 if (destination.protocol === 'node:') { 50 const specifier = destination.pathname; 51 const mod = loadNativeModule(specifier, href); 52 if (mod && mod.canBeRequiredByUsers) { 53 return mod.exports; 54 } 55 throw new ERR_UNKNOWN_BUILTIN_MODULE(specifier); 56 } else if (destination.protocol === 'file:') { 57 let filepath; 58 if (urlToFileCache.has(href)) { 59 filepath = urlToFileCache.get(href); 60 } else { 61 filepath = fileURLToPath(destination); 62 urlToFileCache.set(href, filepath); 63 } 64 return mod.require(filepath); 65 } 66 } 67 if (missing) { 68 reaction(new ERR_MANIFEST_DEPENDENCY_MISSING(id, path)); 69 } 70 return mod.require(path); 71 }; 72 } else { 73 require = function require(path) { 74 return mod.require(path); 75 }; 76 } 77 78 function resolve(request, options) { 79 validateString(request, 'request'); 80 return Module._resolveFilename(request, mod, false, options); 81 } 82 83 require.resolve = resolve; 84 85 function paths(request) { 86 validateString(request, 'request'); 87 return Module._resolveLookupPaths(request, mod); 88 } 89 90 resolve.paths = paths; 91 92 require.main = process.mainModule; 93 94 // Enable support to add extra extension types. 95 require.extensions = Module._extensions; 96 97 require.cache = Module._cache; 98 99 return require; 100} 101 102/** 103 * Remove byte order marker. This catches EF BB BF (the UTF-8 BOM) 104 * because the buffer-to-string conversion in `fs.readFileSync()` 105 * translates it to FEFF, the UTF-16 BOM. 106 */ 107function stripBOM(content) { 108 if (content.charCodeAt(0) === 0xFEFF) { 109 content = content.slice(1); 110 } 111 return content; 112} 113 114const builtinLibs = [ 115 'assert', 116 'async_hooks', 117 'buffer', 118 'child_process', 119 'cluster', 120 'crypto', 121 'dgram', 122 'dns', 123 'domain', 124 'events', 125 'fs', 126 'http', 127 'http2', 128 'https', 129 'net', 130 'os', 131 'path', 132 'perf_hooks', 133 'punycode', 134 'querystring', 135 'readline', 136 'repl', 137 'stream', 138 'string_decoder', 139 'tls', 140 'trace_events', 141 'tty', 142 'url', 143 'util', 144 'v8', 145 'vm', 146 'worker_threads', 147 'zlib', 148]; 149 150if (internalBinding('config').experimentalWasi) { 151 builtinLibs.push('wasi'); 152 builtinLibs.sort(); 153} 154 155if (typeof internalBinding('inspector').open === 'function') { 156 builtinLibs.push('inspector'); 157 builtinLibs.sort(); 158} 159 160function addBuiltinLibsToObject(object) { 161 // Make built-in modules available directly (loaded lazily). 162 builtinLibs.forEach((name) => { 163 // Goals of this mechanism are: 164 // - Lazy loading of built-in modules 165 // - Having all built-in modules available as non-enumerable properties 166 // - Allowing the user to re-assign these variables as if there were no 167 // pre-existing globals with the same name. 168 169 const setReal = (val) => { 170 // Deleting the property before re-assigning it disables the 171 // getter/setter mechanism. 172 delete object[name]; 173 object[name] = val; 174 }; 175 176 ObjectDefineProperty(object, name, { 177 get: () => { 178 const lib = require(name); 179 180 // Disable the current getter/setter and set up a new 181 // non-enumerable property. 182 delete object[name]; 183 ObjectDefineProperty(object, name, { 184 get: () => lib, 185 set: setReal, 186 configurable: true, 187 enumerable: false 188 }); 189 190 return lib; 191 }, 192 set: setReal, 193 configurable: true, 194 enumerable: false 195 }); 196 }); 197} 198 199function normalizeReferrerURL(referrer) { 200 if (typeof referrer === 'string' && path.isAbsolute(referrer)) { 201 return pathToFileURL(referrer).href; 202 } 203 return new URL(referrer).href; 204} 205 206module.exports = { 207 addBuiltinLibsToObject, 208 builtinLibs, 209 loadNativeModule, 210 makeRequireFunction, 211 normalizeReferrerURL, 212 stripBOM, 213}; 214