ess. * @param {TypeScriptOptions} options The configuration object. * @returns {string} The processed code. */ function processTypeScriptCode(code, options) { const { code: transformedCode, map } = parseTypeScript(code, options); if (map) { return addSourceMap(transformedCode, map); } if (options.filename) { return `${transformedCode}\n\n//# sourceURL=${options.filename}`; } return transformedCode; } /** * Get the type enum used for compile cache. * @param {TypeScriptMode} mode Mode of transpilation. * @param {boolean} sourceMap Whether source maps are enabled. * @returns {number} */ function getCachedCodeType(mode, sourceMap) { if (mode === 'transform') { if (sourceMap) { return kTransformedTypeScriptWithSourceMaps; } return kTransformedTypeScript; } return kStrippedTypeScript; } /** * Performs type-stripping to TypeScript source code internally. * It is used by internal loaders. * @param {string} source TypeScript code to parse. * @param {string} filename The filename of the source code. * @param {boolean} emitWarning Whether to emit a warning. * @returns {TransformOutput} The stripped TypeScript code. */ function stripTypeScriptModuleTypes(source, filename, emitWarning = true) { if (emitWarning) { emitExperimentalWarning('Type Stripping'); } assert(typeof source === 'string'); if (isUnderNodeModules(filename)) { throw new ERR_UNSUPPORTED_NODE_MODULES_TYPE_STRIPPING(filename); } const sourceMap = getOptionValue('--enable-source-maps'); const mode = getTypeScriptParsingMode(); // Instead of caching the compile cache status, just go into C++ to fetch it, // as checking process.env equally involves calling into C++ anyway, and // the compile cache can be enabled dynamically. const type = getCachedCodeType(mode, sourceMap); // Get a compile cache entry into the native compile cache store, // keyed by the filename. If the cache can already be loaded on disk, // cached.transpiled contains the cached string. Otherwise we should do // the transpilation and save it in the native store later using // saveCompileCacheEntry(). const cached = (filename ? getCompileCacheEntry(source, filename, type) : undefined); if (cached?.transpiled) { // TODO(joyeecheung): return Buffer here. return cached.transpiled; } const options = { mode, sourceMap, filename, }; const transpiled = processTypeScriptCode(source, options); if (cached) { // cached.external contains a pointer to the native cache entry. // The cached object would be unreachable once it's out of scope, // but the pointer inside cached.external would stay around for reuse until // environment shutdown or when the cache is manually flushed // to disk. Unwrap it in JS before passing into C++ since it's faster. saveCompileCacheEntry(cached.external, transpiled); } return transpiled; } /** * * @param {string} code The compiled code. * @param {string} sourceMap The source map. * @returns {string} The code with the source map attached. */ function addSourceMap(code, sourceMap) { // The base64 encoding should be https://datatracker.ietf.org/doc/html/rfc4648#section-4, // not base64url https://datatracker.ietf.org/doc/html/rfc4648#section-5. See data url // spec https://tools.ietf.org/html/rfc2397#section-2. const base64SourceMap = Buffer.from(sourceMap).toString('base64'); return `${code}\n\n//# sourceMappingURL=data:application/json;base64,${base64SourceMap}`; } module.exports = { stripTypeScriptModuleTypes, stripTypeScriptTypes, };