Uh oh!
There was an error while loading. Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork 34.4k
module: use compileFunction over Module.wrap#21573
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Uh oh!
There was an error while loading. Please reload this page.
Changes from all commits
113d0b77cf60fbc3529063146e1915db986ed4af458008e59687d82c9a152a3cb604f29fbbd2709cc84535e209e9284715ba89f2db35b5eeFile filter
Filter by extension
Conversations
Uh oh!
There was an error while loading. Please reload this page.
Jump to
Uh oh!
There was an error while loading. Please reload this page.
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -29,14 +29,14 @@ const assert = require('assert').ok; | ||
| const fs = require('fs'); | ||
| const internalFS = require('internal/fs/utils'); | ||
| const path = require('path'); | ||
| const{URL } = require('url'); | ||
| const{ | ||
| internalModuleReadJSON, | ||
| internalModuleStat | ||
| } = internalBinding('fs'); | ||
| const{safeGetenv } = internalBinding('credentials'); | ||
| const{ | ||
| makeRequireFunction, | ||
| normalizeReferrerURL, | ||
| requireDepth, | ||
| stripBOM, | ||
| stripShebang | ||
| @@ -48,6 +48,7 @@ const experimentalModules = getOptionValue('--experimental-modules'); | ||
| const manifest = getOptionValue('--experimental-policy') ? | ||
| require('internal/process/policy').manifest : | ||
| null; | ||
| const{compileFunction } = internalBinding('contextify'); | ||
| const{ | ||
| ERR_INVALID_ARG_VALUE, | ||
| @@ -131,15 +132,52 @@ Module._extensions = Object.create(null); | ||
| var modulePaths = []; | ||
| Module.globalPaths = []; | ||
| Module.wrap = function(script){ | ||
| let patched = false; | ||
| // eslint-disable-next-line func-style | ||
| let wrap = function(script){ | ||
| return Module.wrapper[0] + script + Module.wrapper[1]; | ||
| }; | ||
| Module.wrapper = [ | ||
| const wrapper = [ | ||
| '(function (exports, require, module, __filename, __dirname){', | ||
| '\n});' | ||
| ]; | ||
| let wrapperProxy = new Proxy(wrapper,{ | ||
| set(target, property, value, receiver){ | ||
| patched = true; | ||
| return Reflect.set(target, property, value, receiver); | ||
| }, | ||
| defineProperty(target, property, descriptor){ | ||
| patched = true; | ||
| return Object.defineProperty(target, property, descriptor); | ||
| } | ||
| }); | ||
| Object.defineProperty(Module, 'wrap',{ | ||
| get(){ | ||
| return wrap; | ||
| }, | ||
| set(value){ | ||
| patched = true; | ||
| wrap = value; | ||
| } | ||
| }); | ||
| Object.defineProperty(Module, 'wrapper',{ | ||
| get(){ | ||
| return wrapperProxy; | ||
| }, | ||
| set(value){ | ||
| patched = true; | ||
| wrapperProxy = value; | ||
| } | ||
| }); | ||
| const debug = util.debuglog('module'); | ||
ryzokuken marked this conversation as resolved. Outdated Show resolvedHide resolvedUh oh!There was an error while loading. Please reload this page. | ||
| Module._debug = util.deprecate(debug, 'Module._debug is deprecated.', | ||
| @@ -671,13 +709,6 @@ Module.prototype.require = function(id){ | ||
| // (needed for setting breakpoint when called with --inspect-brk) | ||
| var resolvedArgv; | ||
| function normalizeReferrerURL(referrer){ | ||
| if (typeof referrer === 'string' && path.isAbsolute(referrer)){ | ||
| return pathToFileURL(referrer).href; | ||
| } | ||
| return new URL(referrer).href; | ||
| } | ||
| // Run the file contents in the correct scope or sandbox. Expose | ||
| // the correct helper variables (require, module, exports) to | ||
| @@ -691,19 +722,48 @@ Module.prototype._compile = function(content, filename){ | ||
| content = stripShebang(content); | ||
| // create wrapper function | ||
| var wrapper = Module.wrap(content); | ||
| var compiledWrapper = vm.runInThisContext(wrapper,{ | ||
| filename: filename, | ||
| lineOffset: 0, | ||
| displayErrors: true, | ||
| importModuleDynamically: experimentalModules ? async (specifier) =>{ | ||
| if (asyncESM === undefined) lazyLoadESM(); | ||
| const loader = await asyncESM.loaderPromise; | ||
| return loader.import(specifier, normalizeReferrerURL(filename)); | ||
| } : undefined, | ||
| }); | ||
| let compiledWrapper; | ||
| if (patched){ | ||
| const wrapper = Module.wrap(content); | ||
| compiledWrapper = vm.runInThisContext(wrapper,{ | ||
| filename, | ||
| lineOffset: 0, | ||
| displayErrors: true, | ||
| importModuleDynamically: experimentalModules ? async (specifier) =>{ | ||
| if (asyncESM === undefined) lazyLoadESM(); | ||
| const loader = await asyncESM.loaderPromise; | ||
| return loader.import(specifier, normalizeReferrerURL(filename)); | ||
| } : undefined, | ||
| }); | ||
| } else{ | ||
| compiledWrapper = compileFunction( | ||
| content, | ||
| filename, | ||
| 0, | ||
| 0, | ||
| undefined, | ||
| false, | ||
| undefined, | ||
| [], | ||
| [ | ||
| 'exports', | ||
| 'require', | ||
| 'module', | ||
| '__filename', | ||
| '__dirname', | ||
| ] | ||
| ); | ||
| if (experimentalModules){ | ||
| const{callbackMap } = internalBinding('module_wrap'); | ||
| callbackMap.set(compiledWrapper,{ | ||
| importModuleDynamically: async (specifier) =>{ | ||
| if (asyncESM === undefined) lazyLoadESM(); | ||
| const loader = await asyncESM.loaderPromise; | ||
| return loader.import(specifier, normalizeReferrerURL(filename)); | ||
| } | ||
| }); | ||
| } | ||
| } | ||
| var inspectorWrapper = null; | ||
| if (process._breakFirstLine && process._eval == null){ | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -286,6 +286,15 @@ void ContextifyContext::WeakCallback( | ||
| delete context; | ||
| } | ||
| void ContextifyContext::WeakCallbackCompileFn( | ||
| const WeakCallbackInfo<CompileFnEntry>& data){ | ||
| CompileFnEntry* entry = data.GetParameter(); | ||
| if (entry->env->compile_fn_entries.erase(entry) != 0){ | ||
| entry->env->id_to_function_map.erase(entry->id); | ||
| delete entry; | ||
guybedford marked this conversation as resolved. Show resolvedHide resolvedUh oh!There was an error while loading. Please reload this page. | ||
| } | ||
| } | ||
| // static | ||
| ContextifyContext* ContextifyContext::ContextFromContextifiedSandbox( | ||
| Environment* env, | ||
| @@ -1007,7 +1016,30 @@ void ContextifyContext::CompileFunction( | ||
| data + cached_data_buf->ByteOffset(), cached_data_buf->ByteLength()); | ||
| } | ||
| ScriptOrigin origin(filename, line_offset, column_offset, True(isolate)); | ||
| // Get the function id | ||
| uint32_t id = env->get_next_function_id(); | ||
| // Set host_defined_options | ||
| Local<PrimitiveArray> host_defined_options = | ||
| PrimitiveArray::New(isolate, loader::HostDefinedOptions::kLength); | ||
| host_defined_options->Set( | ||
| isolate, | ||
| loader::HostDefinedOptions::kType, | ||
| Number::New(isolate, loader::ScriptType::kFunction)); | ||
| host_defined_options->Set( | ||
| isolate, loader::HostDefinedOptions::kID, Number::New(isolate, id)); | ||
guybedford marked this conversation as resolved. Outdated Show resolvedHide resolvedUh oh!There was an error while loading. Please reload this page. | ||
| ScriptOrigin origin(filename, | ||
| line_offset, // line offset | ||
| column_offset, // column offset | ||
| True(isolate), // is cross origin | ||
| Local<Integer>(), // script id | ||
| Local<Value>(), // source map URL | ||
| False(isolate), // is opaque (?) | ||
| False(isolate), // is WASM | ||
| False(isolate), // is ES Module | ||
| host_defined_options); | ||
| ScriptCompiler::Source source(code, origin, cached_data); | ||
| ScriptCompiler::CompileOptions options; | ||
| if (source.GetCachedData() == nullptr){ | ||
| @@ -1041,38 +1073,45 @@ void ContextifyContext::CompileFunction( | ||
| } | ||
| } | ||
| MaybeLocal<Function> maybe_fun = ScriptCompiler::CompileFunctionInContext( | ||
| ||
| MaybeLocal<Function> maybe_fn = ScriptCompiler::CompileFunctionInContext( | ||
| parsing_context, &source, params.size(), params.data(), | ||
| context_extensions.size(), context_extensions.data(), options); | ||
| Local<Function> fun; | ||
| if (maybe_fun.IsEmpty() || !maybe_fun.ToLocal(&fun)){ | ||
| if (maybe_fn.IsEmpty()){ | ||
| DecorateErrorStack(env, try_catch); | ||
| try_catch.ReThrow(); | ||
| return; | ||
| } | ||
| Local<Function> fn = maybe_fn.ToLocalChecked(); | ||
| ||
| env->id_to_function_map.emplace(std::piecewise_construct, | ||
| std::make_tuple(id), | ||
| std::make_tuple(isolate, fn)); | ||
| CompileFnEntry* gc_entry = new CompileFnEntry(env, id); | ||
| env->id_to_function_map[id].SetWeak(gc_entry, | ||
| WeakCallbackCompileFn, | ||
| v8::WeakCallbackType::kParameter); | ||
| if (produce_cached_data){ | ||
| const std::unique_ptr<ScriptCompiler::CachedData> cached_data( | ||
| ScriptCompiler::CreateCodeCacheForFunction(fun)); | ||
| ScriptCompiler::CreateCodeCacheForFunction(fn)); | ||
| bool cached_data_produced = cached_data != nullptr; | ||
| if (cached_data_produced){ | ||
| MaybeLocal<Object> buf = Buffer::Copy( | ||
| env, | ||
| reinterpret_cast<const char*>(cached_data->data), | ||
| cached_data->length); | ||
| if (fun->Set( | ||
| if (fn->Set( | ||
| parsing_context, | ||
| env->cached_data_string(), | ||
| buf.ToLocalChecked()).IsNothing()) return; | ||
| } | ||
| if (fun->Set( | ||
| if (fn->Set( | ||
| parsing_context, | ||
| env->cached_data_produced_string(), | ||
| Boolean::New(isolate, cached_data_produced)).IsNothing()) return; | ||
| } | ||
| args.GetReturnValue().Set(fun); | ||
| args.GetReturnValue().Set(fn); | ||
| } | ||
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This part would still be important in case
wraporwrapperget monkey patched since the line would then not start at an offset of zero. It won't be a big issue though as the assertion will just fall back to the messagefalse != true.