Skip to content

Commit

Permalink
fix(ast/estree): set value for BigIntLiterals and RegExpLiteral
Browse files Browse the repository at this point in the history
…s on JS side
  • Loading branch information
overlookmotel committed Feb 11, 2025
1 parent ef553b9 commit 7a0d537
Show file tree
Hide file tree
Showing 2 changed files with 85 additions and 1 deletion.
21 changes: 20 additions & 1 deletion napi/parser/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,26 @@ function wrap(result) {
let program, module, comments, errors, magicString;
return {
get program() {
if (!program) program = JSON.parse(result.program);
if (!program) {
program = JSON.parse(result.program, function(key, value) {
// Set `value` field of `Literal`s for `BigInt`s and `RegExp`s.
// This is not possible to do on Rust side, as neither can be represented correctly in JSON.
if (value === null && key === 'value' && Object.hasOwn(this, 'type') && this.type === 'Literal') {
if (Object.hasOwn(this, 'bigint')) {
return BigInt(this.bigint);
}
if (Object.hasOwn(this, 'regex')) {
const { regex } = this;
try {
return RegExp(regex.pattern, regex.flags);
} catch (_err) {
// Invalid regexp, or valid regexp using syntax not supported by this version of NodeJS
}
}
}
return value;
});
}
return program;
},
get module() {
Expand Down
65 changes: 65 additions & 0 deletions napi/parser/test/parse.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,71 @@ describe('parse', () => {
});
expect(code.substring(comment.start, comment.end)).toBe('/*' + comment.value + '*/');
});

it('`BigIntLiteral` has `value` as `BigInt`', () => {
const ret = parseSync('test.js', '123_456n');
expect(ret.errors.length).toBe(0);
expect(ret.program.body.length).toBe(1);
expect(ret.program.body[0]).toEqual({
type: 'ExpressionStatement',
start: 0,
end: 8,
expression: {
type: 'Literal',
start: 0,
end: 8,
value: 123456n,
raw: '123_456n',
bigint: '123456',
},
});
});

describe('`RegExpLiteral`', () => {
it('has `value` as `RegExp` when valid regexp', () => {
const ret = parseSync('test.js', '/abc/gu');
expect(ret.errors.length).toBe(0);
expect(ret.program.body.length).toBe(1);
expect(ret.program.body[0]).toEqual({
type: 'ExpressionStatement',
start: 0,
end: 7,
expression: {
type: 'Literal',
start: 0,
end: 7,
value: /abc/gu,
raw: '/abc/gu',
regex: {
pattern: 'abc',
flags: 'gu',
},
},
});
});

it('has `value` as `null` when invalid regexp', () => {
const ret = parseSync('test.js', '/+/');
expect(ret.errors.length).toBe(0);
expect(ret.program.body.length).toBe(1);
expect(ret.program.body[0]).toEqual({
type: 'ExpressionStatement',
start: 0,
end: 3,
expression: {
type: 'Literal',
start: 0,
end: 3,
value: null,
raw: '/+/',
regex: {
pattern: '+',
flags: '',
},
},
});
});
});
});

it('utf16 span', async () => {
Expand Down

0 comments on commit 7a0d537

Please sign in to comment.