@@ -26,11 +26,20 @@ function isNode(node: unknown): node is Node {
2626 return typeof node === 'object' && node !== null && 'type' in node ;
2727}
2828
29+ function unwrapParentheses ( node : unknown ) : unknown {
30+ while ( isNode ( node ) && node . type === 'ParenthesizedExpression' ) {
31+ node = ( node as { expression : unknown } ) . expression ;
32+ }
33+
34+ return node ;
35+ }
36+
2937/**
3038 * An implementation of `AstHost` that queries information from `oxc-parser` AST nodes.
3139 */
3240export class OxcAstHost implements AstHost < unknown > {
3341 getSymbolName ( node : unknown ) : string | null {
42+ node = unwrapParentheses ( node ) ;
3443 if ( ! isNode ( node ) ) {
3544 return null ;
3645 }
@@ -47,10 +56,13 @@ export class OxcAstHost implements AstHost<unknown> {
4756 }
4857
4958 isStringLiteral ( node : unknown ) : node is StringLiteral {
59+ node = unwrapParentheses ( node ) ;
60+
5061 return isNode ( node ) && node . type === 'Literal' && typeof node . value === 'string' ;
5162 }
5263
5364 parseStringLiteral ( str : unknown ) : string {
65+ str = unwrapParentheses ( str ) ;
5466 if ( ! this . isStringLiteral ( str ) ) {
5567 throw new FatalLinkerError ( str as object , 'Unsupported syntax, expected a string literal.' ) ;
5668 }
@@ -59,10 +71,13 @@ export class OxcAstHost implements AstHost<unknown> {
5971 }
6072
6173 isNumericLiteral ( node : unknown ) : node is NumericLiteral {
74+ node = unwrapParentheses ( node ) ;
75+
6276 return isNode ( node ) && node . type === 'Literal' && typeof node . value === 'number' ;
6377 }
6478
6579 parseNumericLiteral ( num : unknown ) : number {
80+ num = unwrapParentheses ( num ) ;
6681 if ( ! this . isNumericLiteral ( num ) ) {
6782 throw new FatalLinkerError ( num as object , 'Unsupported syntax, expected a numeric literal.' ) ;
6883 }
@@ -71,6 +86,7 @@ export class OxcAstHost implements AstHost<unknown> {
7186 }
7287
7388 isBooleanLiteral ( node : unknown ) : node is BooleanLiteral | UnaryExpression {
89+ node = unwrapParentheses ( node ) ;
7490 if ( ! isNode ( node ) ) {
7591 return false ;
7692 }
@@ -81,27 +97,35 @@ export class OxcAstHost implements AstHost<unknown> {
8197 }
8298
8399 parseBooleanLiteral ( bool : unknown ) : boolean {
100+ bool = unwrapParentheses ( bool ) ;
84101 if ( isNode ( bool ) ) {
85102 if ( bool . type === 'Literal' && typeof bool . value === 'boolean' ) {
86103 return bool . value ;
87104 }
88105 if ( isMinifiedBooleanLiteral ( bool ) ) {
89- return ! bool . argument . value ;
106+ const arg = unwrapParentheses ( bool . argument ) as NumericLiteral ;
107+
108+ return ! arg . value ;
90109 }
91110 }
92111
93112 throw new FatalLinkerError ( bool as object , 'Unsupported syntax, expected a boolean literal.' ) ;
94113 }
95114
96115 isNull ( node : unknown ) : node is NullLiteral {
116+ node = unwrapParentheses ( node ) ;
117+
97118 return isNode ( node ) && node . type === 'Literal' && node . value === null ;
98119 }
99120
100121 isArrayLiteral ( node : unknown ) : node is ArrayExpression {
122+ node = unwrapParentheses ( node ) ;
123+
101124 return isNode ( node ) && node . type === 'ArrayExpression' ;
102125 }
103126
104127 parseArrayLiteral ( array : unknown ) : unknown [ ] {
128+ array = unwrapParentheses ( array ) ;
105129 if ( ! this . isArrayLiteral ( array ) ) {
106130 throw new FatalLinkerError ( array as object , 'Unsupported syntax, expected an array literal.' ) ;
107131 }
@@ -115,23 +139,27 @@ export class OxcAstHost implements AstHost<unknown> {
115139 'Unsupported syntax, element in array not to be empty.' ,
116140 ) ;
117141 }
118- if ( element . type === 'SpreadElement' ) {
142+ const unwrappedElement = unwrapParentheses ( element ) ;
143+ if ( isNode ( unwrappedElement ) && unwrappedElement . type === 'SpreadElement' ) {
119144 throw new FatalLinkerError (
120- element as object ,
145+ unwrappedElement as object ,
121146 'Unsupported syntax, element in array not to use spread syntax.' ,
122147 ) ;
123148 }
124- result . push ( element ) ;
149+ result . push ( unwrappedElement ) ;
125150 }
126151
127152 return result ;
128153 }
129154
130155 isObjectLiteral ( node : unknown ) : node is ObjectExpression {
156+ node = unwrapParentheses ( node ) ;
157+
131158 return isNode ( node ) && node . type === 'ObjectExpression' ;
132159 }
133160
134161 parseObjectLiteral ( obj : unknown ) : Map < string , unknown > {
162+ obj = unwrapParentheses ( obj ) ;
135163 if ( ! this . isObjectLiteral ( obj ) ) {
136164 throw new FatalLinkerError ( obj as object , 'Unsupported syntax, expected an object literal.' ) ;
137165 }
@@ -146,7 +174,13 @@ export class OxcAstHost implements AstHost<unknown> {
146174 ) ;
147175 }
148176
149- const keyNode = property . key ;
177+ const keyNode = unwrapParentheses ( property . key ) ;
178+ if ( ! isNode ( keyNode ) ) {
179+ throw new FatalLinkerError (
180+ property . key as object ,
181+ 'Unsupported syntax, expected a property name.' ,
182+ ) ;
183+ }
150184
151185 let key : string ;
152186 if ( keyNode . type === 'Identifier' ) {
@@ -162,13 +196,14 @@ export class OxcAstHost implements AstHost<unknown> {
162196 ) ;
163197 }
164198
165- result . set ( key , property . value ) ;
199+ result . set ( key , unwrapParentheses ( property . value ) ) ;
166200 }
167201
168202 return result ;
169203 }
170204
171205 isFunctionExpression ( node : unknown ) : node is FunctionNode | ArrowFunctionExpression {
206+ node = unwrapParentheses ( node ) ;
172207 if ( ! isNode ( node ) ) {
173208 return false ;
174209 }
@@ -181,6 +216,7 @@ export class OxcAstHost implements AstHost<unknown> {
181216 }
182217
183218 parseReturnValue ( fn : unknown ) : unknown {
219+ fn = unwrapParentheses ( fn ) ;
184220 if ( ! this . isFunctionExpression ( fn ) ) {
185221 throw new FatalLinkerError ( fn as object , 'Unsupported syntax, expected a function.' ) ;
186222 }
@@ -191,7 +227,7 @@ export class OxcAstHost implements AstHost<unknown> {
191227 }
192228
193229 if ( body . type !== 'BlockStatement' ) {
194- return body ;
230+ return unwrapParentheses ( body ) ;
195231 }
196232
197233 const statements = body . body ;
@@ -217,10 +253,11 @@ export class OxcAstHost implements AstHost<unknown> {
217253 ) ;
218254 }
219255
220- return stmt . argument ;
256+ return unwrapParentheses ( stmt . argument ) ;
221257 }
222258
223259 parseParameters ( fn : unknown ) : unknown [ ] {
260+ fn = unwrapParentheses ( fn ) ;
224261 if ( ! this . isFunctionExpression ( fn ) ) {
225262 throw new FatalLinkerError ( fn as object , 'Unsupported syntax, expected a function.' ) ;
226263 }
@@ -229,38 +266,44 @@ export class OxcAstHost implements AstHost<unknown> {
229266 }
230267
231268 isCallExpression ( node : unknown ) : node is CallExpression {
269+ node = unwrapParentheses ( node ) ;
270+
232271 return isNode ( node ) && node . type === 'CallExpression' ;
233272 }
234273
235274 parseCallee ( call : unknown ) : unknown {
275+ call = unwrapParentheses ( call ) ;
236276 if ( ! this . isCallExpression ( call ) ) {
237277 throw new FatalLinkerError ( call as object , 'Unsupported syntax, expected a call expression.' ) ;
238278 }
239279
240- return call . callee ;
280+ return unwrapParentheses ( call . callee ) ;
241281 }
242282
243283 parseArguments ( call : unknown ) : unknown [ ] {
284+ call = unwrapParentheses ( call ) ;
244285 if ( ! this . isCallExpression ( call ) ) {
245286 throw new FatalLinkerError ( call as object , 'Unsupported syntax, expected a call expression.' ) ;
246287 }
247288
248289 const result : unknown [ ] = [ ] ;
249290
250291 for ( const arg of call . arguments ) {
251- if ( arg . type === 'SpreadElement' ) {
292+ const unwrappedArg = unwrapParentheses ( arg ) ;
293+ if ( isNode ( unwrappedArg ) && unwrappedArg . type === 'SpreadElement' ) {
252294 throw new FatalLinkerError (
253- arg as object ,
295+ unwrappedArg as object ,
254296 'Unsupported syntax, argument not to use spread syntax.' ,
255297 ) ;
256298 }
257- result . push ( arg ) ;
299+ result . push ( unwrappedArg ) ;
258300 }
259301
260302 return result ;
261303 }
262304
263305 getRange ( node : unknown ) : Range {
306+ node = unwrapParentheses ( node ) ;
264307 if ( ! isNode ( node ) || typeof node . start !== 'number' || typeof node . end !== 'number' ) {
265308 throw new FatalLinkerError (
266309 node as object ,
@@ -284,11 +327,12 @@ function isMinifiedBooleanLiteral(
284327 return false ;
285328 }
286329
287- const arg = node . argument ;
330+ const arg = unwrapParentheses ( node . argument ) ;
288331
289332 return (
290333 node . prefix === true &&
291334 node . operator === '!' &&
335+ isNode ( arg ) &&
292336 arg . type === 'Literal' &&
293337 typeof arg . value === 'number' &&
294338 ( arg . value === 0 || arg . value === 1 )
0 commit comments