Skip to content

Commit 44aa272

Browse files
committed
lib: cache source maps in vm sources
Cache source maps found in sources parsed with `vm.Script`, `vm.compileFunction`, and `vm.SourceTextModule`. Also, retrieve source url from V8 parsing results. Not like filenames returned by `CallSite.getFileName()` in translating stack traces, when generating source lines prepended to exceptions, only resource names can be used as an index to find source maps, which can be source url magic comments instead. Source url magic comments can be either a file path or a URL. To verify that source urls with absolute file paths in the source lines are correctly translated, snapshots should include the full snapshot urls rather than neutralizing all the path strings in the stack traces.
1 parent bae14b7 commit 44aa272

35 files changed

+284
-101
lines changed

lib/internal/modules/cjs/loader.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1308,9 +1308,9 @@ function wrapSafe(filename, content, cjsModuleInstance, codeCache) {
13081308
);
13091309

13101310
// Cache the source map for the module if present.
1311-
const { sourceMapURL } = script;
1311+
const { sourceMapURL, sourceURL } = script;
13121312
if (sourceMapURL) {
1313-
maybeCacheSourceMap(filename, content, this, false, undefined, sourceMapURL);
1313+
maybeCacheSourceMap(filename, content, this, false, sourceURL, sourceMapURL);
13141314
}
13151315

13161316
return {
@@ -1332,7 +1332,7 @@ function wrapSafe(filename, content, cjsModuleInstance, codeCache) {
13321332

13331333
// Cache the source map for the module if present.
13341334
if (result.sourceMapURL) {
1335-
maybeCacheSourceMap(filename, content, this, false, undefined, result.sourceMapURL);
1335+
maybeCacheSourceMap(filename, content, this, false, result.sourceURL, result.sourceMapURL);
13361336
}
13371337

13381338
return result;

lib/internal/modules/esm/loader.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -280,7 +280,7 @@ class ModuleLoader {
280280
const wrap = new ModuleWrap(url, undefined, source, 0, 0);
281281
// Cache the source map for the module if present.
282282
if (wrap.sourceMapURL) {
283-
maybeCacheSourceMap(url, source, null, false, undefined, wrap.sourceMapURL);
283+
maybeCacheSourceMap(url, source, null, false, wrap.sourceURL, wrap.sourceMapURL);
284284
}
285285
const { registerModule } = require('internal/modules/esm/utils');
286286
// TODO(joyeecheung): refactor so that the default options are shared across

lib/internal/modules/esm/translators.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,7 @@ translators.set('module', function moduleStrategy(url, source, isMain) {
177177
const module = new ModuleWrap(url, undefined, source, 0, 0);
178178
// Cache the source map for the module if present.
179179
if (module.sourceMapURL) {
180-
maybeCacheSourceMap(url, source, null, false, undefined, module.sourceMapURL);
180+
maybeCacheSourceMap(url, source, null, false, module.sourceURL, module.sourceMapURL);
181181
}
182182
const { registerModule } = require('internal/modules/esm/utils');
183183
registerModule(module, {
@@ -227,7 +227,7 @@ function loadCJSModule(module, source, url, filename) {
227227
}
228228
// Cache the source map for the cjs module if present.
229229
if (compileResult.sourceMapURL) {
230-
maybeCacheSourceMap(url, source, null, false, undefined, compileResult.sourceMapURL);
230+
maybeCacheSourceMap(url, source, null, false, compileResult.sourceURL, compileResult.sourceMapURL);
231231
}
232232

233233
const compiledWrapper = compileResult.function;

lib/internal/source_map/source_map_cache.js

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -123,10 +123,10 @@ function maybeCacheSourceMap(filename, content, cjsModuleInstance, isGeneratedSo
123123
return;
124124
}
125125

126-
// FIXME: callers should obtain sourceURL from v8 and pass it
127-
// rather than leaving it undefined and extract by regex.
128-
if (sourceURL === undefined) {
129-
sourceURL = extractSourceURLMagicComment(content);
126+
if (sourceURL !== undefined) {
127+
// SourceURL magic comment content might be a file path or URL.
128+
// Normalize the sourceURL to be a file URL if it is a file path.
129+
sourceURL = normalizeReferrerURL(sourceURL);
130130
}
131131

132132
const data = dataFromUrl(filename, sourceMapURL);
@@ -149,9 +149,6 @@ function maybeCacheSourceMap(filename, content, cjsModuleInstance, isGeneratedSo
149149
sourceURL,
150150
};
151151
generatedSourceMapCache.set(filename, entry);
152-
if (sourceURL) {
153-
generatedSourceMapCache.set(sourceURL, entry);
154-
}
155152
} else {
156153
// If there is no cjsModuleInstance and is not generated source assume we are in a
157154
// "modules/esm" context.
@@ -178,7 +175,7 @@ function maybeCacheGeneratedSourceMap(content) {
178175
return;
179176
}
180177
try {
181-
maybeCacheSourceMap(sourceURL, content, null, true, sourceURL);
178+
maybeCacheSourceMap(sourceURL, content, null, true);
182179
} catch (err) {
183180
// This can happen if the filename is not a valid URL.
184181
// If we fail to cache the source map, we should not fail the whole process.

lib/internal/vm.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ const {
2525
const {
2626
getOptionValue,
2727
} = require('internal/options');
28+
const { maybeCacheSourceMap } = require('internal/source_map/source_map_cache');
2829
const {
2930
privateSymbols: {
3031
contextify_context_private_symbol,
@@ -151,6 +152,7 @@ function internalCompileFunction(
151152
}
152153

153154
registerImportModuleDynamically(result.function, importModuleDynamically);
155+
maybeCacheSourceMap(filename, code, result.function, false, result.sourceURL, result.sourceMapURL);
154156

155157
return result;
156158
}

lib/internal/vm/module.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ const kPerContextModuleId = Symbol('kPerContextModuleId');
7777
const kLink = Symbol('kLink');
7878

7979
const { isContext } = require('internal/vm');
80+
const { maybeCacheSourceMap } = require('internal/source_map/source_map_cache');
8081

8182
function isModule(object) {
8283
if (typeof object !== 'object' || object === null || !ObjectPrototypeHasOwnProperty(object, kWrap)) {
@@ -141,6 +142,7 @@ class Module {
141142
importModuleDynamicallyWrap(options.importModuleDynamically) :
142143
undefined,
143144
};
145+
maybeCacheSourceMap(identifier, sourceText, this, false, this[kWrap].sourceURL, this[kWrap].sourceMapURL);
144146
} else {
145147
assert(syntheticEvaluationSteps);
146148
this[kWrap] = new ModuleWrap(identifier, context,

lib/vm.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ const {
6363
isContext: _isContext,
6464
registerImportModuleDynamically,
6565
} = require('internal/vm');
66+
const { maybeCacheSourceMap } = require('internal/source_map/source_map_cache');
6667
const {
6768
vm_dynamic_import_main_context_default,
6869
} = internalBinding('symbols');
@@ -126,6 +127,7 @@ class Script extends ContextifyScript {
126127
}
127128

128129
registerImportModuleDynamically(this, importModuleDynamically);
130+
maybeCacheSourceMap(filename, code, this, false, this.sourceURL, this.sourceMapURL);
129131
}
130132

131133
runInThisContext(options) {

src/env_properties.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -300,6 +300,7 @@
300300
V(sni_context_string, "sni_context") \
301301
V(source_string, "source") \
302302
V(source_map_url_string, "sourceMapURL") \
303+
V(source_url_string, "sourceURL") \
303304
V(stack_string, "stack") \
304305
V(standard_name_string, "standardName") \
305306
V(start_time_string, "startTime") \

src/module_wrap.cc

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,13 @@ void ModuleWrap::New(const FunctionCallbackInfo<Value>& args) {
265265
return;
266266
}
267267

268+
if (that->Set(context,
269+
realm->env()->source_url_string(),
270+
module->GetUnboundModuleScript()->GetSourceURL())
271+
.IsNothing()) {
272+
return;
273+
}
274+
268275
if (that->Set(context,
269276
realm->env()->source_map_url_string(),
270277
module->GetUnboundModuleScript()->GetSourceMappingURL())

src/node_contextify.cc

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -905,6 +905,13 @@ void ContextifyScript::New(const FunctionCallbackInfo<Value>& args) {
905905
return;
906906
}
907907

908+
if (args.This()
909+
->Set(env->context(),
910+
env->source_url_string(),
911+
v8_script->GetSourceURL())
912+
.IsNothing())
913+
return;
914+
908915
if (args.This()
909916
->Set(env->context(),
910917
env->source_map_url_string(),
@@ -1373,6 +1380,15 @@ Local<Object> ContextifyContext::CompileFunctionAndCacheResult(
13731380
Local<Object> result = Object::New(isolate);
13741381
if (result->Set(parsing_context, env->function_string(), fn).IsNothing())
13751382
return Object::New(env->isolate());
1383+
1384+
// ScriptOrigin::ResourceName() returns SourceURL magic comment content if
1385+
// present.
1386+
if (result
1387+
->Set(parsing_context,
1388+
env->source_url_string(),
1389+
fn->GetScriptOrigin().ResourceName())
1390+
.IsNothing())
1391+
return Object::New(env->isolate());
13761392
if (result
13771393
->Set(parsing_context,
13781394
env->source_map_url_string(),
@@ -1650,11 +1666,15 @@ static void CompileFunctionForCJSLoader(
16501666
std::vector<Local<Name>> names = {
16511667
env->cached_data_rejected_string(),
16521668
env->source_map_url_string(),
1669+
env->source_url_string(),
16531670
env->function_string(),
16541671
};
16551672
std::vector<Local<Value>> values = {
16561673
Boolean::New(isolate, cache_rejected),
16571674
fn->GetScriptOrigin().SourceMapUrl(),
1675+
// ScriptOrigin::ResourceName() returns SourceURL magic comment content if
1676+
// present.
1677+
fn->GetScriptOrigin().ResourceName(),
16581678
fn,
16591679
};
16601680
Local<Object> result = Object::New(

0 commit comments

Comments
 (0)