Skip to content

Commit

Permalink
export error messages from c++ as constants
Browse files Browse the repository at this point in the history
  • Loading branch information
GeoffreyBooth committed Mar 18, 2024
1 parent 2c8e56f commit 20e1af7
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 16 deletions.
32 changes: 16 additions & 16 deletions lib/internal/modules/helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,15 @@ const {
} = require('internal/errors').codes;
const { BuiltinModule } = require('internal/bootstrap/realm');

const {
shouldRetryAsESM: contextifyShouldRetryAsESM,
constants: {
syntaxDetectionErrors: {
esmSyntaxErrorMessages,
throwsOnlyInCommonJSErrorMessages,
},
},
} = internalBinding('contextify');
const { validateString } = require('internal/validators');
const fs = require('fs'); // Import all of `fs` so that it can be monkey-patched.
const internalFS = require('internal/fs/utils');
Expand Down Expand Up @@ -320,31 +329,22 @@ function normalizeReferrerURL(referrerName) {
}


const esmSyntaxErrorMessages = new SafeSet([
'Cannot use import statement outside a module', // `import` statements
"Unexpected token 'export'", // `export` statements
"Cannot use 'import.meta' outside a module", // `import.meta` references
]);
const throwsOnlyInCommonJSErrorMessages = new SafeSet([
"Identifier 'module' has already been declared",
"Identifier 'exports' has already been declared",
"Identifier 'require' has already been declared",
"Identifier '__filename' has already been declared",
"Identifier '__dirname' has already been declared",
'await is only valid in async functions and the top level bodies of modules', // Top-level `await`
]);
let esmSyntaxErrorMessagesSet; // Declared lazily in shouldRetryAsESM
let throwsOnlyInCommonJSErrorMessagesSet; // Declared lazily in shouldRetryAsESM
/**
* After an attempt to parse a module as CommonJS throws an error, should we try again as ESM?
* @param {string} errorMessage The string message thrown by V8 when attempting to parse as CommonJS
* @param {string} source Module contents
*/
function shouldRetryAsESM(errorMessage, source) {
if (esmSyntaxErrorMessages.has(errorMessage)) {
esmSyntaxErrorMessagesSet ??= new SafeSet(esmSyntaxErrorMessages);
if (esmSyntaxErrorMessagesSet.has(errorMessage)) {
return true;
}

if (throwsOnlyInCommonJSErrorMessages.has(errorMessage)) {
return /** @type {boolean} */(internalBinding('contextify').shouldRetryAsESM(source));
throwsOnlyInCommonJSErrorMessagesSet ??= new SafeSet(throwsOnlyInCommonJSErrorMessages);
if (throwsOnlyInCommonJSErrorMessagesSet.has(errorMessage)) {
return /** @type {boolean} */(contextifyShouldRetryAsESM(source));
}

return false;
Expand Down
35 changes: 35 additions & 0 deletions src/node_contextify.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1728,6 +1728,7 @@ static void CreatePerContextProperties(Local<Object> target,
Local<Object> constants = Object::New(env->isolate());
Local<Object> measure_memory = Object::New(env->isolate());
Local<Object> memory_execution = Object::New(env->isolate());
Local<Object> syntax_detection_errors = Object::New(env->isolate());

{
Local<Object> memory_mode = Object::New(env->isolate());
Expand All @@ -1748,6 +1749,40 @@ static void CreatePerContextProperties(Local<Object> target,

READONLY_PROPERTY(constants, "measureMemory", measure_memory);

{
Local<Array> esm_syntax_error_messages_array =
Array::New(env->isolate(), esm_syntax_error_messages.size());
for (size_t i = 0; i < esm_syntax_error_messages.size(); i++) {
const char* message = esm_syntax_error_messages[i].data();
(void)esm_syntax_error_messages_array->Set(
context,
static_cast<uint32_t>(i),
String::NewFromUtf8(env->isolate(), message)
.ToLocalChecked());
}
READONLY_PROPERTY(syntax_detection_errors, "esmSyntaxErrorMessages",
esm_syntax_error_messages_array);
}

{
Local<Array> throws_only_in_cjs_error_messages_array =
Array::New(env->isolate(), throws_only_in_cjs_error_messages.size());
for (size_t i = 0; i < throws_only_in_cjs_error_messages.size(); i++) {
const char* message = throws_only_in_cjs_error_messages[i].data();
(void)throws_only_in_cjs_error_messages_array->Set(
context,
static_cast<uint32_t>(i),
String::NewFromUtf8(env->isolate(), message)
.ToLocalChecked());
}
READONLY_PROPERTY(syntax_detection_errors,
"throwsOnlyInCommonJSErrorMessages",
throws_only_in_cjs_error_messages_array);
}

READONLY_PROPERTY(constants, "syntaxDetectionErrors",
syntax_detection_errors);

target->Set(context, env->constants_string(), constants).Check();
}

Expand Down

0 comments on commit 20e1af7

Please sign in to comment.