# @stackline/source-map-support Compatibility-first continuation of `source-map-support@0.5.21` for the residual integrations that native Node source maps do not fully replace: `vm.runInThisContext()`, browser delivery, historical register entries, and synchronous custom file or source-map retrieval. The package targets Node.js 14.15.1 and newer. For ordinary modern Node.js files, prefer native source maps. Introduce this package only where its verified compatibility surface is required, and test the complete process because installation changes global stack behavior. ## Install ```sh npm install @stackline/source-map-support ``` The root does not install itself: ```js const sourceMapSupport = require('@stackline/source-map-support') sourceMapSupport.install({ handleUncaughtExceptions: false }) ``` The ESM entry is a host facade over that same CommonJS object: ```js import sourceMapSupport, { install } from '@stackline/source-map-support' install({ handleUncaughtExceptions: false }) console.log(sourceMapSupport.install === install) // true ``` ## Native Node or this package? Use native source maps for ordinary modern Node entrypoints. They avoid a userland `Error.prepareStackTrace` owner and are the platform path. Use this package after verifying that the application depends on one or more of these contracts: - mapping generated code evaluated through `vm.runInThisContext()`; - `source-map-support/register` or `register-hook-require` side effects; - browser global or named AMD delivery; - custom synchronous `retrieveFile` or `retrieveSourceMap` providers; - `hookRequire`, `handleUncaughtExceptions`, or explicit environment options; - direct `mapSourcePosition`, `wrapCallSite`, or `getErrorSource` calls. The intake differential on Node.js 26.8.1 mapped an ordinary file with native source maps but did not map the equivalent `vm.runInThisContext()` frame, including when the available runtime source-map control was enabled for generated code. The package mapped that verified case. This is a bounded VM compatibility reason, not a recommendation to replace native mapping in every Node process. ## Package entries | Entry | Behavior | | --- | --- | | `@stackline/source-map-support` | Node CommonJS/ESM host; browser-aware bundlers select UMD for require and a companion browser ESM host for import; no install side effect | | `@stackline/source-map-support/source-map-support` | Explicit CommonJS implementation entry | | `@stackline/source-map-support/register` | Calls `install()` immediately | | `@stackline/source-map-support/register-hook-require` | Calls `install({ hookRequire: true })` immediately | | `@stackline/source-map-support/browser-source-map-support` | Standalone UMD bundle for CommonJS, named AMD, or `globalThis.sourceMapSupport` | | `@stackline/source-map-support/package.json` | Package metadata | The `.js` form of each historical JavaScript deep entry is also exported. `register` and `register-hook-require` are marked as side effects so bundlers must not remove them. ## API The CommonJS root has exactly six enumerable function properties, in order: ```text wrapCallSite getErrorSource mapSourcePosition retrieveSourceMap install resetRetrieveHandlers ``` See [API.md](./API.md) for complete signatures, install options, coordinate conventions, entry behavior, and TypeScript declarations. ### `install(options?)` `install()` sets the process or realm's `Error.prepareStackTrace`. Options are: | Option | Meaning | | --- | --- | | `environment` | `'auto'`, `'node'`, or `'browser'`; other values throw | | `retrieveFile(path)` | Synchronously return generated or original source text, or a nullish miss | | `overrideRetrieveFile` | Replace the default file provider instead of adding priority | | `retrieveSourceMap(source)` | Synchronously return `{ map, url? }`, or a nullish miss | | `overrideRetrieveSourceMap` | Replace the default map provider instead of adding priority | | `hookRequire` | Wrap Node's `Module.prototype._compile` to retain runtime-transpiler content | | `emptyCacheBetweenOperations` | Clear source and map caches before each stack-format operation | | `handleUncaughtExceptions` | Install the historical uncaught-exception shim; defaults to true outside worker threads | Custom providers run synchronously during mapping. They must be trusted, bounded, and responsible for their own errors. ### `mapSourcePosition(position)` ```js const mapped = sourceMapSupport.mapSourcePosition({ source: 'https://example.test/generated.js', line: 1, // one-based column: 0 // zero-based }) ``` The returned position can also contain a mapped `name`. A miss, gap, malformed map, or mapping lookup failure returns the generated position. ### Other functions - `wrapCallSite(frame, state?)` maps one V8-compatible CallSite; direct callers normally omit the formatter-coordination state. - `getErrorSource(error)` returns a mapped source excerpt and caret, or null. - `retrieveSourceMap(source)` runs the current source-map providers. - `resetRetrieveHandlers()` restores the default retrieval lists. It does not uninstall global stack, process, or CommonJS compiler hooks. ## VM-generated code Give the VM code a stable filename and provide an inline, external, or custom map for that name: ```js const vm = require('node:vm') const sourceMapSupport = require('@stackline/source-map-support') sourceMapSupport.install({ handleUncaughtExceptions: false }) try { vm.runInThisContext(generatedCode, { filename: 'file:///virtual/generated.js' }) } catch (error) { console.error(error.stack) } ``` The runnable [VM example](./examples/vm.cjs) embeds a complete map. ## Custom retrieval Virtual files, Electron integrations, archives, and build systems can preload maps and return them synchronously: ```js sourceMapSupport.install({ handleUncaughtExceptions: false, overrideRetrieveSourceMap: true, retrieveSourceMap(source) { return source === generatedUrl ? { url: generatedUrl, map } : null } }) ``` Without an override flag, each newly installed custom handler takes priority and a nullish result can fall through to earlier handlers. With the flag, the corresponding provider list is cleared first. ## Browser bundle Copy `browser-source-map-support.js` from the installed package into the application's assets. It is an ES2015-targeted self-contained UMD bundle that exposes: - `module.exports` in CommonJS-like loaders; - named AMD module `browser-source-map-support`; - `globalThis.sourceMapSupport` otherwise. Browser-aware bundlers can also use the ordinary root import. The root `browser` plus `import` condition selects `browser-source-map-support.mjs`; the root `browser` plus `require` condition selects the UMD implementation. The legacy package `browser` remap also maps `./source-map-support.js` to that UMD file. Explicit `browser-source-map-support` deep imports retain the historical UMD contract. Set `environment: 'browser'` when selection must be explicit. The default browser providers use synchronous `XMLHttpRequest` and honor `SourceMap` or `X-SourceMap` response headers. Origin and CORS policy still apply. A preloaded custom provider avoids implicit network reads. The mapping functions, browser ESM host, root bundler remap, and three UMD delivery forms are tested. Automatic stack rewriting also requires a browser engine with compatible V8-style `Error.prepareStackTrace` and CallSite behavior; the bundle is not a universal promise for every JavaScript engine. Both browser artifacts carry a bundled path implementation, so relative map and source resolution does not depend on a Node `process` global. Malformed inline base64 map data is a retrieval miss rather than an `atob()` exception that replaces the generated stack. ## Preserved map behavior - The final line or block `sourceMappingURL` comment wins. - Inline base64 and external maps remain supported. - Regular Source Map v3 payloads and indexed maps with `sections` are accepted; section offsets, mapped names, and embedded `sourcesContent` are retained. - `sourceRoot`, map URLs, source URLs, Windows file URLs, mapped names, and `sourcesContent` are resolved. - Runtime-transpiler inline maps can be retained with `hookRequire`. - Eval and native CallSite formatting remain part of the compatibility suite, including current V8 differently-named property aliases such as `Object.doSomething [as customMethod]`. - Browser `SourceMap` and `X-SourceMap` response headers remain recognized. ## Maintained corrections - Exact `@jridgewell/trace-mapping@0.3.31` replaces the historical `source-map` and `buffer-from` production graph. Its `AnyMap` constructor covers both regular and indexed/sectioned Source Map v3 payloads. - URL sources resolve through URL semantics instead of treating the host as a local path segment. - Generated files with no map are released after discovery rather than kept indefinitely in the file-content cache. - Malformed maps fail back to the generated position and cache the miss. - Cache tables do not inherit special keys such as `__proto__`. - Inline browser maps decode UTF-8 without requiring a Buffer polyfill; malformed base64 fails back without escaping from `atob()`. - Uncaught `Error.cause` output is retained and an existing nonzero exit code is preserved. See [COMPATIBILITY_CONTRACT.md](./COMPATIBILITY_CONTRACT.md) for the exact preserved, corrected, additive, and excluded behavior. ## Global lifecycle Installation can affect three global surfaces: 1. `Error.prepareStackTrace` is set once by the package. 2. The uncaught-exception option can wrap `process.emit` once in the main thread. 3. `hookRequire` can wrap `Module.prototype._compile` once. `resetRetrieveHandlers()` only resets provider lists. It is not an uninstall operation. If another library, profiler, test runner, or Electron subsystem owns stack formatting, coordinate ownership explicitly and preserve any prior formatter that the integration needs. ## Security and production maps Source and map retrieval is synchronous and has no built-in byte, nesting, source-count, filesystem-root, URL, or network limit. Bound inputs and custom providers at the application boundary. Source maps and `sourcesContent` can expose original code or embedded secrets, so decide separately whether to publish production maps. Malformed-input and memory-retention corrections are defense-in-depth. They must not be described as an assigned vulnerability, advisory, or CVE. Read [SECURITY.md](./SECURITY.md) before enabling default retrieval for untrusted source names. ## TypeScript The package includes TypeScript 3.9-compatible CommonJS namespace declarations, modern `.d.cts` and `.d.mts` routing, option and map payload types, the CallSite surface, side-effect entry declarations, and a browser-entry declaration. Modern ESM consumers receive a default namespace plus six named functions. ## License and independence The source-map-support runtime is Copyright (c) 2014 Evan Wallace and remains MIT-licensed. `CallSiteToString` contains code copied almost verbatim from V8 4.3.49 and retains the applicable V8 BSD 3-Clause terms. The exact three-package installed production graph is MIT-licensed. The packed browser artifacts bundle those three @jridgewell packages plus `path-browserify@1.0.1`; all four exact MIT texts are retained. See [LICENSE](./LICENSE), [NOTICE](./NOTICE), and [THIRD_PARTY_LICENSES.md](./THIRD_PARTY_LICENSES.md). This is an independent maintained continuation. It is not affiliated with or endorsed by Evan Wallace, the upstream source-map-support project, V8, Google, Justin Ridgewell, or the @jridgewell projects.