Skip to content

Commit

Permalink
module: wrap swc error in ERR_INVALID_TYPESCRIPT_SYNTAX
Browse files Browse the repository at this point in the history
PR-URL: #55316
Reviewed-By: Paolo Insogna <paolo@cowtech.it>
Reviewed-By: Jacob Smith <jacob@frende.me>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
  • Loading branch information
marco-ippolito authored and aduh95 committed Oct 11, 2024
1 parent 5ea8aa1 commit 6fcac73
Show file tree
Hide file tree
Showing 4 changed files with 47 additions and 30 deletions.
13 changes: 13 additions & 0 deletions doc/api/errors.md
Original file line number Diff line number Diff line change
Expand Up @@ -2107,6 +2107,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`

<!-- 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 @@ -4177,4 +4189,5 @@ An error occurred trying to allocate memory. This should never happen.
[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 @@ -1528,6 +1528,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 @@ -17,6 +17,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 @@ -315,44 +316,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'),
);

/**
* 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 @@ -367,14 +361,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);
});

0 comments on commit 6fcac73

Please sign in to comment.