Skip to content
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

module: wrap swc error in ERR_INVALID_TYPESCRIPT_SYNTAX #55316

Merged
merged 1 commit into from
Oct 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
13 changes: 13 additions & 0 deletions doc/api/errors.md
Original file line number Diff line number Diff line change
Expand Up @@ -2094,6 +2094,18 @@ An element in the `iterable` provided to the [WHATWG][WHATWG URL API]
represent a `[name, value]` tuple – that is, if an element is not iterable, or
does not consist of exactly two elements.

<a id="ERR_INVALID_TYPESCRIPT_SYNTAX"></a>

### `ERR_INVALID_TYPESCRIPT_SYNTAX`
marco-ippolito marked this conversation as resolved.
Show resolved Hide resolved

<!-- YAML
added: REPLACEME
-->

The provided TypeScript syntax is not valid or unsupported.
This could happen when using TypeScript syntax that requires
transformation with [type-stripping][].

<a id="ERR_INVALID_URI"></a>

### `ERR_INVALID_URI`
Expand Down Expand Up @@ -4197,4 +4209,5 @@ Type stripping is not supported for files descendent of a `node_modules` directo
[stream-based]: stream.md
[syscall]: https://man7.org/linux/man-pages/man2/syscalls.2.html
[try-catch]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/try...catch
[type-stripping]: typescript.md#type-stripping
[vm]: vm.md
1 change: 1 addition & 0 deletions lib/internal/errors.js
Original file line number Diff line number Diff line change
Expand Up @@ -1524,6 +1524,7 @@ E('ERR_INVALID_SYNC_FORK_INPUT',
TypeError);
E('ERR_INVALID_THIS', 'Value of "this" must be of type %s', TypeError);
E('ERR_INVALID_TUPLE', '%s must be an iterable %s tuple', TypeError);
E('ERR_INVALID_TYPESCRIPT_SYNTAX', '%s', SyntaxError);
E('ERR_INVALID_URI', 'URI malformed', URIError);
E('ERR_INVALID_URL', function(input, base = null) {
this.input = input;
Expand Down
53 changes: 23 additions & 30 deletions lib/internal/modules/helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ const {
const {
ERR_INVALID_ARG_TYPE,
ERR_INVALID_RETURN_PROPERTY_VALUE,
ERR_INVALID_TYPESCRIPT_SYNTAX,
} = require('internal/errors').codes;
const { BuiltinModule } = require('internal/bootstrap/realm');

Expand Down Expand Up @@ -313,44 +314,37 @@ function getBuiltinModule(id) {
return normalizedId ? require(normalizedId) : undefined;
}

/**
* TypeScript parsing function, by default Amaro.transformSync.
* @type {Function}
*/
let typeScriptParser;
/**
* The TypeScript parsing mode, either 'strip-only' or 'transform'.
* @type {string}
*/
let typeScriptParsingMode;
/**
* Whether source maps are enabled for TypeScript parsing.
* @type {boolean}
*/
let sourceMapEnabled;
const getTypeScriptParsingMode = getLazy(() =>
(getOptionValue('--experimental-transform-types') ? 'transform' : 'strip-only'),
);
marco-ippolito marked this conversation as resolved.
Show resolved Hide resolved

/**
* Load the TypeScript parser.
* @param {Function} parser - A function that takes a string of TypeScript code
* and returns an object with a `code` property.
* @returns {Function} The TypeScript parser function.
*/
function loadTypeScriptParser(parser) {
if (typeScriptParser) {
return typeScriptParser;
}
const loadTypeScriptParser = getLazy(() => {
const amaro = require('internal/deps/amaro/dist/index');
return amaro.transformSync;
});

if (parser) {
typeScriptParser = parser;
} else {
const amaro = require('internal/deps/amaro/dist/index');
// Default option for Amaro is to perform Type Stripping only.
typeScriptParsingMode = getOptionValue('--experimental-transform-types') ? 'transform' : 'strip-only';
sourceMapEnabled = getOptionValue('--enable-source-maps');
// Curry the transformSync function with the default options.
typeScriptParser = amaro.transformSync;
/**
*
* @param {string} source the source code
* @param {object} options the options to pass to the parser
* @returns {TransformOutput} an object with a `code` property.
*/
function parseTypeScript(source, options) {
const parse = loadTypeScriptParser();
try {
return parse(source, options);
} catch (error) {
throw new ERR_INVALID_TYPESCRIPT_SYNTAX(error);
}
return typeScriptParser;
}

/**
Expand All @@ -365,14 +359,13 @@ function loadTypeScriptParser(parser) {
*/
function stripTypeScriptTypes(source, filename) {
assert(typeof source === 'string');
const parse = loadTypeScriptParser();
const options = {
__proto__: null,
mode: typeScriptParsingMode,
sourceMap: sourceMapEnabled,
mode: getTypeScriptParsingMode(),
sourceMap: getOptionValue('--enable-source-maps'),
filename,
};
const { code, map } = parse(source, options);
const { code, map } = parseTypeScript(source, options);
if (map) {
// TODO(@marco-ippolito) When Buffer.transcode supports utf8 to
// base64 transformation, we should change this line.
Expand Down
10 changes: 10 additions & 0 deletions test/es-module/test-typescript-eval.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -110,3 +110,13 @@ test('expect fail eval TypeScript ESM syntax with input-type commonjs', async ()
match(result.stderr, /Cannot use import statement outside a module/);
strictEqual(result.code, 1);
});

test('check syntax error is thrown when passing invalid syntax', async () => {
const result = await spawnPromisified(process.execPath, [
'--experimental-strip-types',
'--eval',
'enum Foo { A, B, C }']);
strictEqual(result.stdout, '');
match(result.stderr, /ERR_INVALID_TYPESCRIPT_SYNTAX/);
strictEqual(result.code, 1);
});
Loading