diff --git a/lib/internal/bootstrap/loaders.js b/lib/internal/bootstrap/loaders.js index 7a98e4c96c87d4..83a3bafeba7bad 100644 --- a/lib/internal/bootstrap/loaders.js +++ b/lib/internal/bootstrap/loaders.js @@ -140,7 +140,8 @@ let internalBinding; const loaderExports = { internalBinding, NativeModule, - require: nativeModuleRequire + require: nativeModuleRequire, + cjsContext: { __proto__: null, process: undefined, Buffer: undefined } }; const loaderId = 'internal/bootstrap/loaders'; diff --git a/lib/internal/bootstrap/pre_execution.js b/lib/internal/bootstrap/pre_execution.js index 1948c4e29e6a30..05c637a5f08eef 100644 --- a/lib/internal/bootstrap/pre_execution.js +++ b/lib/internal/bootstrap/pre_execution.js @@ -263,28 +263,27 @@ function initializeDeprecations() { 'Please use public APIs instead.', 'DEP0111'); } - // Create global.process and global.Buffer as getters so that we have a - // deprecation path for these in ES Modules. - // See https://github.com/nodejs/node/pull/26334. - let _process = process; + // Create global.process and global.Buffer as getters to allow deprecation. + const { cjsContext } = require('internal/bootstrap/loaders'); + cjsContext.process = process; + cjsContext.Buffer = Buffer; Object.defineProperty(global, 'process', { get() { - return _process; + return cjsContext.process; }, set(value) { - _process = value; + cjsContext.process = value; }, enumerable: false, configurable: true }); - let _Buffer = Buffer; Object.defineProperty(global, 'Buffer', { get() { - return _Buffer; + return cjsContext.Buffer; }, set(value) { - _Buffer = value; + cjsContext.Buffer = value; }, enumerable: false, configurable: true diff --git a/lib/internal/modules/cjs/loader.js b/lib/internal/modules/cjs/loader.js index 199405b0e24457..b2d8753a633c21 100644 --- a/lib/internal/modules/cjs/loader.js +++ b/lib/internal/modules/cjs/loader.js @@ -23,7 +23,7 @@ const { JSON, Object, Reflect } = primordials; -const { NativeModule } = require('internal/bootstrap/loaders'); +const { NativeModule, cjsContext } = require('internal/bootstrap/loaders'); const { pathToFileURL, fileURLToPath, URL } = require('internal/url'); const { deprecate } = require('internal/util'); const vm = require('vm'); @@ -713,7 +713,7 @@ function wrapSafe(filename, content) { undefined, false, undefined, - [], + [cjsContext], [ 'exports', 'require', diff --git a/lib/internal/modules/esm/deprecate_process_buffer.js b/lib/internal/modules/esm/deprecate_process_buffer.js new file mode 100644 index 00000000000000..56cbd1e1c1b1bd --- /dev/null +++ b/lib/internal/modules/esm/deprecate_process_buffer.js @@ -0,0 +1,45 @@ +'use strict'; + +const { cjsContext } = require('internal/bootstrap/loaders'); +const { getStackSourceName } = internalBinding('contextify'); +const { deprecate } = require('internal/util'); +const { Object } = primordials; + +module.exports = () => { + // Deprecate global.process and global.Buffer access in ES Modules. + const processGetter = deprecate( + () => cjsContext.process, + 'global.process is deprecated in ECMAScript Modules. ' + + 'Please use `import process from \'process\'` instead.', 'DEP0XXX'); + Object.defineProperty(global, 'process', { + get() { + const sourceName = getStackSourceName(1); + if (sourceName && sourceName.startsWith('file://')) + return processGetter(); + return cjsContext.process; + }, + set(value) { + cjsContext.process = value; + }, + enumerable: false, + configurable: true + }); + + const bufferGetter = deprecate( + () => cjsContext.Buffer, + 'global.Buffer is deprecated in ECMAScript Modules. ' + + 'Please use `import { Buffer } from \'buffer\'` instead.', 'DEP0YYY'); + Object.defineProperty(global, 'Buffer', { + get() { + const sourceName = getStackSourceName(1); + if (sourceName && sourceName.startsWith('file://')) + return bufferGetter(); + return cjsContext.Buffer; + }, + set(value) { + cjsContext.Buffer = value; + }, + enumerable: false, + configurable: true + }); +}; diff --git a/lib/internal/modules/esm/translators.js b/lib/internal/modules/esm/translators.js index b1f2c9f2595fc7..b04296e64c4d93 100644 --- a/lib/internal/modules/esm/translators.js +++ b/lib/internal/modules/esm/translators.js @@ -21,6 +21,8 @@ const fs = require('fs'); const { fileURLToPath, URL } = require('url'); const { debuglog } = require('internal/util/debuglog'); const { promisify } = require('internal/util'); +const deprecateProcessBufferAccess = + require('internal/modules/esm/deprecate_process_buffer'); const esmLoader = require('internal/process/esm_loader'); const { ERR_UNKNOWN_BUILTIN_MODULE @@ -43,7 +45,12 @@ async function importModuleDynamically(specifier, { url }) { } // Strategy for loading a standard JavaScript module +let firstModule = true; translators.set('module', async function moduleStrategy(url) { + if (firstModule) { + deprecateProcessBufferAccess(); + firstModule = false; + } const source = `${await readFileAsync(new URL(url))}`; debug(`Translating StandardModule ${url}`); const { ModuleWrap, callbackMap } = internalBinding('module_wrap'); diff --git a/node.gyp b/node.gyp index 55b7da02ccaf18..5262e2dae190f1 100644 --- a/node.gyp +++ b/node.gyp @@ -149,6 +149,7 @@ 'lib/internal/modules/esm/loader.js', 'lib/internal/modules/esm/create_dynamic_module.js', 'lib/internal/modules/esm/default_resolve.js', + 'lib/internal/modules/esm/deprecate_process_buffer.js', 'lib/internal/modules/esm/module_job.js', 'lib/internal/modules/esm/module_map.js', 'lib/internal/modules/esm/translators.js', diff --git a/src/node_contextify.cc b/src/node_contextify.cc index 69c110d6be2d22..c9a0ae370e94aa 100644 --- a/src/node_contextify.cc +++ b/src/node_contextify.cc @@ -67,6 +67,8 @@ using v8::Script; using v8::ScriptCompiler; using v8::ScriptOrigin; using v8::ScriptOrModule; +using v8::StackFrame; +using v8::StackTrace; using v8::String; using v8::Symbol; using v8::Uint32; @@ -235,6 +237,7 @@ void ContextifyContext::Init(Environment* env, Local target) { env->SetMethod(target, "makeContext", MakeContext); env->SetMethod(target, "isContext", IsContext); env->SetMethod(target, "compileFunction", CompileFunction); + env->SetMethod(target, "getStackSourceName", GetStackSourceName); } @@ -299,6 +302,30 @@ void ContextifyContext::IsContext(const FunctionCallbackInfo& args) { args.GetReturnValue().Set(result.FromJust()); } +void ContextifyContext::GetStackSourceName( + const FunctionCallbackInfo& args) { + Environment* env = Environment::GetCurrent(args); + + CHECK_EQ(args.Length(), 1); + CHECK(args[0]->IsNumber()); + + int32_t stack_depth = args[0].As()->Value(); + + Local frame; + do { + Local stack = + StackTrace::CurrentStackTrace(env->isolate(), + stack_depth + 1); + if (stack_depth >= stack->GetFrameCount()) { + return; + } + frame = stack->GetFrame(env->isolate(), stack_depth++); + } while (frame->IsEval()); + + Local script_name = frame->GetScriptName(); + + args.GetReturnValue().Set(script_name); +} void ContextifyContext::WeakCallback( const WeakCallbackInfo& data) { diff --git a/src/node_contextify.h b/src/node_contextify.h index cf1e8475075fcb..1efb574940fc38 100644 --- a/src/node_contextify.h +++ b/src/node_contextify.h @@ -59,6 +59,8 @@ class ContextifyContext { private: static void MakeContext(const v8::FunctionCallbackInfo& args); static void IsContext(const v8::FunctionCallbackInfo& args); + static void GetStackSourceName( + const v8::FunctionCallbackInfo& args); static void CompileFunction( const v8::FunctionCallbackInfo& args); static void WeakCallback( diff --git a/test/common/index.mjs b/test/common/index.mjs index 47587044020fcc..f747ee327913a5 100644 --- a/test/common/index.mjs +++ b/test/common/index.mjs @@ -1,12 +1,7 @@ // Flags: --experimental-modules /* eslint-disable node-core/require-common-first, node-core/required-modules */ -import { createRequireFromPath } from 'module'; -import { fileURLToPath as toPath } from 'url'; - -function createRequire(metaUrl) { - return createRequireFromPath(toPath(metaUrl)); -} +import { createRequire } from 'module'; const require = createRequire(import.meta.url); const common = require('./index.js'); diff --git a/test/message/async_error_sync_esm.out b/test/message/async_error_sync_esm.out index 544916e24866e2..f34628ef44e52a 100644 --- a/test/message/async_error_sync_esm.out +++ b/test/message/async_error_sync_esm.out @@ -5,4 +5,3 @@ Error: test at async three (*fixtures*async-error.js:20:3) at async four (*fixtures*async-error.js:24:3) at async main (*message*async_error_sync_esm.mjs:7:5) -(node:*) [DEP0130] DeprecationWarning: Module.createRequireFromPath() is deprecated. Use Module.createRequire() instead. diff --git a/test/parallel/test-global-buffer-dep.mjs b/test/parallel/test-global-buffer-dep.mjs new file mode 100644 index 00000000000000..5b55402987f3e0 --- /dev/null +++ b/test/parallel/test-global-buffer-dep.mjs @@ -0,0 +1,9 @@ +// Flags: --experimental-modules +import { expectWarning } from '../common/index.mjs'; + +global.Buffer; + +expectWarning('DeprecationWarning', + 'global.Buffer is deprecated in ECMAScript Modules. ' + + 'Please use `import { Buffer } from \'buffer\'` instead.', + 'DEP0YYY'); diff --git a/test/parallel/test-global-process-dep-eval.mjs b/test/parallel/test-global-process-dep-eval.mjs new file mode 100644 index 00000000000000..192df74dcab47c --- /dev/null +++ b/test/parallel/test-global-process-dep-eval.mjs @@ -0,0 +1,9 @@ +// Flags: --experimental-modules +import { expectWarning } from '../common/index.mjs'; + +(0, eval)('process'); + +expectWarning('DeprecationWarning', + 'global.process is deprecated in ECMAScript Modules. ' + + 'Please use `import process from \'process\'` instead.', + 'DEP0XXX'); diff --git a/test/parallel/test-global-process-dep-nested-eval.mjs b/test/parallel/test-global-process-dep-nested-eval.mjs new file mode 100644 index 00000000000000..60282fdbbee9ca --- /dev/null +++ b/test/parallel/test-global-process-dep-nested-eval.mjs @@ -0,0 +1,9 @@ +// Flags: --experimental-modules +import { expectWarning } from '../common/index.mjs'; + +new Function('return new Function("eval(process)")')()(); + +expectWarning('DeprecationWarning', + 'global.process is deprecated in ECMAScript Modules. ' + + 'Please use `import process from \'process\'` instead.', + 'DEP0XXX'); diff --git a/test/parallel/test-global-process-dep.mjs b/test/parallel/test-global-process-dep.mjs new file mode 100644 index 00000000000000..f521c7d18bb96f --- /dev/null +++ b/test/parallel/test-global-process-dep.mjs @@ -0,0 +1,9 @@ +// Flags: --experimental-modules +import { expectWarning } from '../common/index.mjs'; + +process; + +expectWarning('DeprecationWarning', + 'global.process is deprecated in ECMAScript Modules. ' + + 'Please use `import process from \'process\'` instead.', + 'DEP0XXX');