Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
61 commits
Select commit Hold shift + click to select a range
7233623
meta: move MoLow to TSC regular member
MoLow Dec 18, 2024
46fb69d
build: build v8 with -fvisibility=hidden on macOS
joyeecheung Dec 19, 2024
4c978b4
doc: fix links in `module.md`
aduh95 Dec 19, 2024
c1627e9
test: make `test-permission-sqlite-load-extension` more robust
aduh95 Dec 19, 2024
db83d2f
Revert "events: add hasEventListener util for validate"
origranot Dec 17, 2024
e9762bf
test: add test case for listeners
origranot Dec 17, 2024
7819bfe
test: deflake test-esm-loader-hooks-inspect-brk
lpinca Dec 19, 2024
d1b009b
lib: suppress source map lookup exceptions
legendecas Dec 17, 2024
e4b795e
lib: optimize `prepareStackTrace` on builtin frames
legendecas Dec 17, 2024
97d854e
test_runner,cli: mark test isolation as stable
cjihrig Dec 20, 2024
4930244
test: remove async-hooks/test-writewrap flaky designation
lpinca Dec 20, 2024
3a3f5c9
stream: validate undefined sizeAlgorithm in WritableStream
jazelly Dec 20, 2024
cdb631e
esm: add experimental support for addon modules
legendecas Dec 20, 2024
417a8eb
node-api: remove deprecated attribute from napi_module_register
vmoroz Dec 20, 2024
ab3e646
build: test macos-13 on GitHub actions
targos Dec 20, 2024
717cfa4
module: use buffer.toString base64
legendecas Dec 21, 2024
dc3dafc
tools: add release line label when opening release proposal
aduh95 Dec 21, 2024
710b8fc
doc: add entry to changelog about SQLite Session Extension
louwers Dec 21, 2024
0ec2ed0
build: fix GN build for ngtcp2
zcbenz Dec 18, 2024
a4f336f
tools: fix `require-common-first` lint rule from subfolder
aduh95 Dec 22, 2024
9369942
test: check typescript loader
marco-ippolito Dec 23, 2024
06de0c6
deps: update simdutf to 5.7.0
nodejs-github-bot Dec 24, 2024
eaefd90
deps: update ngtcp2 to 1.10.0
nodejs-github-bot Dec 24, 2024
d4404f0
test: migrate message eval tests from Python to JS
yiyunlei Oct 31, 2023
c062ffc
test: add coverage for pipeline
jakecastelli Dec 17, 2024
96a3804
test: increase spin for eventloop test on s390
mhdawson Dec 10, 2024
959f133
module: support eval with ts syntax detection
marco-ippolito Dec 24, 2024
079cee0
test: skip `test-sqlite-extensions` when SQLite is not built by us
aduh95 Dec 24, 2024
3943986
doc: fix the `crc32` documentation
kevinuehara Dec 24, 2024
2a5543b
src: use starts_with in fs_permission.cc
IlyasShabi Dec 25, 2024
384ccba
doc: update macOS and Xcode versions for releases
targos Dec 25, 2024
4188ee0
test: deflake test-watch-file-shared-dependency
lpinca Dec 25, 2024
3db4809
doc: clarify that WASM is trusted
mcollina Dec 25, 2024
ecc718c
doc: use `<ul>` instead of `<ol>` in `SECURITY.md`
aduh95 Dec 23, 2024
c2837f0
meta: move one or more collaborators to emeritus
nodejs-github-bot Dec 25, 2024
2a5ac93
url: use resolved path to convert UNC paths to URL
aduh95 Dec 25, 2024
accbdad
test: enable ts test on win arm64
marco-ippolito Dec 26, 2024
64556ba
test: improve abort signal dropping test
geeksilva97 Dec 26, 2024
e5ba216
module: unflag --experimental-strip-types
marco-ippolito Dec 26, 2024
38ce249
doc: expand description of `parseArg`'s `default`
bakkot Dec 27, 2024
b757e40
test: remove test-net-write-fully-async-hex-string flaky designation
lpinca Dec 28, 2024
20ace0b
test: remove test-worker-arraybuffer-zerofill flaky designation
lpinca Dec 28, 2024
7b4d288
assert: make partialDeepStrictEqual throw when comparing [0] with [-0]
puskin Dec 12, 2024
b9c0852
deps: update googletest to e54519b
nodejs-github-bot Dec 28, 2024
54f6d68
test: remove flaky designation
lpinca Dec 28, 2024
d194f1a
sqlite: pass conflict type to conflict resolution handler
louwers Dec 29, 2024
c102328
lib: add typescript support to STDIN eval
marco-ippolito Dec 29, 2024
510649f
test: use unusual chars in the path to ensure our tests are robust
aduh95 Dec 30, 2024
8a87e39
test: remove empty lines from snapshots
marco-ippolito Dec 24, 2024
c2baae8
lib: refactor execution.js
marco-ippolito Dec 24, 2024
6e6f6b0
test: add ts eval snapshots
marco-ippolito Dec 25, 2024
195990a
deps: update googletest to 7d76a23
nodejs-github-bot Dec 31, 2024
6afe363
deps: update amaro to 0.2.1
nodejs-github-bot Dec 31, 2024
4f77920
module: fix async resolution error within the sync `findPackageJSON`
JakobJingleheimer Dec 31, 2024
c2f4d8d
node-api: define version 10
gabrielschulhof Dec 31, 2024
8dc39e5
process: add process.ref() and process.unref() methods
jasnell Dec 29, 2024
03df76c
doc: add example for piping ReadableStream
gabrielschulhof Jan 1, 2025
29f5d70
src: use v8::LocalVector consistently with other minor cleanups
jasnell Dec 31, 2024
9d4930b
deps: update simdutf to 5.7.2
nodejs-github-bot Jan 2, 2025
8b20cc2
worker: add eval ts input
marco-ippolito Jan 3, 2025
9fa6aeb
2025-01-07, Version 23.6.0 (Current)
nodejs-github-bot Jan 3, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
module: support eval with ts syntax detection
PR-URL: #56285
Refs: nodejs/typescript#17
Reviewed-By: Pietro Marchini <pietro.marchini94@gmail.com>
Reviewed-By: Geoffrey Booth <webadmin@geoffreybooth.com>
  • Loading branch information
marco-ippolito authored and aduh95 committed Jan 2, 2025
commit 959f133a22c4addf0990d81214eac765b22ef07b
20 changes: 18 additions & 2 deletions doc/api/cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -1381,8 +1381,23 @@ added: v12.0.0
-->

This configures Node.js to interpret `--eval` or `STDIN` input as CommonJS or
as an ES module. Valid values are `"commonjs"` or `"module"`. The default is
`"commonjs"`.
as an ES module. Valid values are `"commonjs"`, `"module"`, `"module-typescript"` and `"commonjs-typescript"`.
The `"-typescript"` values are available only in combination with the flag `--experimental-strip-types`.
The default is `"commonjs"`.

If `--experimental-strip-types` is enabled and `--input-type` is not provided,
Node.js will try to detect the syntax with the following steps:

1. Run the input as CommonJS.
2. If step 1 fails, run the input as an ES module.
3. If step 2 fails with a SyntaxError, strip the types.
4. If step 3 fails with an error code [`ERR_INVALID_TYPESCRIPT_SYNTAX`][],
throw the error from step 2, including the TypeScript error in the message,
else run as CommonJS.
5. If step 4 fails, run the input as an ES module.

To avoid the delay of multiple syntax detection passes, the `--input-type=type` flag can be used to specify
how the `--eval` input should be interpreted.

The REPL does not support this option. Usage of `--input-type=module` with
[`--print`][] will throw an error, as `--print` does not support ES module
Expand Down Expand Up @@ -3645,6 +3660,7 @@ node --stack-trace-limit=12 -p -e "Error.stackTraceLimit" # prints 12
[`AsyncLocalStorage`]: async_context.md#class-asynclocalstorage
[`Buffer`]: buffer.md#class-buffer
[`CRYPTO_secure_malloc_init`]: https://www.openssl.org/docs/man3.0/man3/CRYPTO_secure_malloc_init.html
[`ERR_INVALID_TYPESCRIPT_SYNTAX`]: errors.md#err_invalid_typescript_syntax
[`NODE_OPTIONS`]: #node_optionsoptions
[`NO_COLOR`]: https://no-color.org
[`SlowBuffer`]: buffer.md#class-slowbuffer
Expand Down
49 changes: 34 additions & 15 deletions lib/internal/main/eval_string.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,28 +13,34 @@ const {
prepareMainThreadExecution,
markBootstrapComplete,
} = require('internal/process/pre_execution');
const { evalModuleEntryPoint, evalScript } = require('internal/process/execution');
const {
evalModuleEntryPoint,
evalTypeScript,
parseAndEvalCommonjsTypeScript,
parseAndEvalModuleTypeScript,
evalScript,
} = require('internal/process/execution');
const { addBuiltinLibsToObject } = require('internal/modules/helpers');
const { stripTypeScriptModuleTypes } = require('internal/modules/typescript');
const { getOptionValue } = require('internal/options');

prepareMainThreadExecution();
addBuiltinLibsToObject(globalThis, '<eval>');
markBootstrapComplete();

const code = getOptionValue('--eval');
const source = getOptionValue('--experimental-strip-types') ?
stripTypeScriptModuleTypes(code) :
code;

const print = getOptionValue('--print');
const shouldLoadESM = getOptionValue('--import').length > 0 || getOptionValue('--experimental-loader').length > 0;
if (getOptionValue('--input-type') === 'module') {
evalModuleEntryPoint(source, print);
const inputType = getOptionValue('--input-type');
const tsEnabled = getOptionValue('--experimental-strip-types');
if (inputType === 'module') {
evalModuleEntryPoint(code, print);
} else if (inputType === 'module-typescript' && tsEnabled) {
parseAndEvalModuleTypeScript(code, print);
} else {
// For backward compatibility, we want the identifier crypto to be the
// `node:crypto` module rather than WebCrypto.
const isUsingCryptoIdentifier = RegExpPrototypeExec(/\bcrypto\b/, source) !== null;
const isUsingCryptoIdentifier = RegExpPrototypeExec(/\bcrypto\b/, code) !== null;
const shouldDefineCrypto = isUsingCryptoIdentifier && internalBinding('config').hasOpenSSL;

if (isUsingCryptoIdentifier && !shouldDefineCrypto) {
Expand All @@ -49,11 +55,24 @@ if (getOptionValue('--input-type') === 'module') {
};
ObjectDefineProperty(object, name, { __proto__: null, set: setReal });
}
evalScript('[eval]',
shouldDefineCrypto ? (
print ? `let crypto=require("node:crypto");{${source}}` : `(crypto=>{{${source}}})(require('node:crypto'))`
) : source,
getOptionValue('--inspect-brk'),
print,
shouldLoadESM);

let evalFunction;
if (inputType === 'commonjs') {
evalFunction = evalScript;
} else if (inputType === 'commonjs-typescript' && tsEnabled) {
evalFunction = parseAndEvalCommonjsTypeScript;
} else if (tsEnabled) {
evalFunction = evalTypeScript;
} else {
// Default to commonjs.
evalFunction = evalScript;
}

evalFunction('[eval]',
shouldDefineCrypto ? (
print ? `let crypto=require("node:crypto");{${code}}` : `(crypto=>{{${code}}})(require('node:crypto'))`
) : code,
getOptionValue('--inspect-brk'),
print,
shouldLoadESM);
}
1 change: 0 additions & 1 deletion lib/internal/modules/cjs/loader.js
Original file line number Diff line number Diff line change
Expand Up @@ -449,7 +449,6 @@ function initializeCJS() {

const tsEnabled = getOptionValue('--experimental-strip-types');
if (tsEnabled) {
emitExperimentalWarning('Type Stripping');
Module._extensions['.cts'] = loadCTS;
Module._extensions['.ts'] = loadTS;
}
Expand Down
32 changes: 30 additions & 2 deletions lib/internal/modules/esm/loader.js
Original file line number Diff line number Diff line change
Expand Up @@ -213,9 +213,25 @@ class ModuleLoader {
}
}

async eval(source, url, isEntryPoint = false) {
/**
*
* @param {string} source Source code of the module.
* @param {string} url URL of the module.
* @returns {object} The module wrap object.
*/
createModuleWrap(source, url) {
return compileSourceTextModule(url, source, this);
}

/**
*
* @param {string} url URL of the module.
* @param {object} wrap Module wrap object.
* @param {boolean} isEntryPoint Whether the module is the entry point.
* @returns {Promise<object>} The module object.
*/
async executeModuleJob(url, wrap, isEntryPoint = false) {
const { ModuleJob } = require('internal/modules/esm/module_job');
const wrap = compileSourceTextModule(url, source, this);
const module = await onImport.tracePromise(async () => {
const job = new ModuleJob(
this, url, undefined, wrap, false, false);
Expand All @@ -235,6 +251,18 @@ class ModuleLoader {
};
}

/**
*
* @param {string} source Source code of the module.
* @param {string} url URL of the module.
* @param {boolean} isEntryPoint Whether the module is the entry point.
* @returns {Promise<object>} The module object.
*/
eval(source, url, isEntryPoint = false) {
const wrap = this.createModuleWrap(source, url);
return this.executeModuleJob(url, wrap, isEntryPoint);
}

/**
* Get a (possibly not yet fully linked) module job from the cache, or create one and return its Promise.
* @param {string} specifier The module request of the module to be resolved. Typically, what's
Expand Down
3 changes: 0 additions & 3 deletions lib/internal/modules/esm/translators.js
Original file line number Diff line number Diff line change
Expand Up @@ -291,7 +291,6 @@ translators.set('require-commonjs', (url, source, isMain) => {
// Handle CommonJS modules referenced by `require` calls.
// This translator function must be sync, as `require` is sync.
translators.set('require-commonjs-typescript', (url, source, isMain) => {
emitExperimentalWarning('Type Stripping');
assert(cjsParse);
const code = stripTypeScriptModuleTypes(stringify(source), url);
return createCJSModuleWrap(url, code, isMain, 'commonjs-typescript');
Expand Down Expand Up @@ -536,7 +535,6 @@ translators.set('addon', function translateAddon(url, source, isMain) {

// Strategy for loading a commonjs TypeScript module
translators.set('commonjs-typescript', function(url, source) {
emitExperimentalWarning('Type Stripping');
assertBufferSource(source, true, 'load');
const code = stripTypeScriptModuleTypes(stringify(source), url);
debug(`Translating TypeScript ${url}`);
Expand All @@ -545,7 +543,6 @@ translators.set('commonjs-typescript', function(url, source) {

// Strategy for loading an esm TypeScript module
translators.set('module-typescript', function(url, source) {
emitExperimentalWarning('Type Stripping');
assertBufferSource(source, true, 'load');
const code = stripTypeScriptModuleTypes(stringify(source), url);
debug(`Translating TypeScript ${url}`);
Expand Down
6 changes: 5 additions & 1 deletion lib/internal/modules/typescript.js
Original file line number Diff line number Diff line change
Expand Up @@ -113,9 +113,13 @@ function processTypeScriptCode(code, options) {
* It is used by internal loaders.
* @param {string} source TypeScript code to parse.
* @param {string} filename The filename of the source code.
* @param {boolean} emitWarning Whether to emit a warning.
* @returns {TransformOutput} The stripped TypeScript code.
*/
function stripTypeScriptModuleTypes(source, filename) {
function stripTypeScriptModuleTypes(source, filename, emitWarning = true) {
if (emitWarning) {
emitExperimentalWarning('Type Stripping');
}
assert(typeof source === 'string');
if (isUnderNodeModules(filename)) {
throw new ERR_UNSUPPORTED_NODE_MODULES_TYPE_STRIPPING(filename);
Expand Down
Loading