@@ -22,6 +22,9 @@ import {
2222 JSONLiteral ,
2323 JSONIdentifier ,
2424 Locations ,
25+ JSONUnaryExpression ,
26+ JSONNumberIdentifier ,
27+ JSONNumberLiteral ,
2528} from "./ast"
2629import { getKeys , getNodes } from "./traverse"
2730import {
@@ -45,9 +48,12 @@ export function convertNode(node: Node, tokens: AST.Token[]): JSONNode {
4548 if ( node . type === "ArrayExpression" ) {
4649 return convertArrayExpressionNode ( node , tokens )
4750 }
48- if ( node . type === "Literal" || node . type === "UnaryExpression" ) {
51+ if ( node . type === "Literal" ) {
4952 return convertLiteralNode ( node , tokens )
5053 }
54+ if ( node . type === "UnaryExpression" ) {
55+ return convertUnaryExpressionNode ( node , tokens )
56+ }
5157 if ( node . type === "Identifier" ) {
5258 return convertIdentifierNode ( node , tokens )
5359 }
@@ -84,7 +90,9 @@ function convertProgramNode(node: Program, tokens: AST.Token[]): JSONProgram {
8490 }
8591 const expression = bodyNode . expression
8692 if ( expression . type === "Identifier" ) {
87- return throwUnexpectedNodeError ( expression , tokens )
93+ if ( ! isNumIdentifier ( expression ) ) {
94+ return throwUnexpectedNodeError ( expression , tokens )
95+ }
8896 }
8997 const body : JSONExpressionStatement = {
9098 type : "JSONExpressionStatement" ,
@@ -156,7 +164,9 @@ function convertPropertyNode(
156164 return throwUnexpectedNodeError ( node . key , tokens )
157165 }
158166 if ( node . value . type === "Identifier" ) {
159- return throwUnexpectedNodeError ( node . value , tokens )
167+ if ( ! isNumIdentifier ( node . value ) ) {
168+ return throwUnexpectedNodeError ( node . value , tokens )
169+ }
160170 }
161171 const nn : JSONProperty = {
162172 type : "JSONProperty" ,
@@ -192,7 +202,9 @@ function convertArrayExpressionNode(
192202 )
193203 }
194204 if ( child . type === "Identifier" ) {
195- return throwUnexpectedNodeError ( child , tokens )
205+ if ( ! isNumIdentifier ( child ) ) {
206+ return throwUnexpectedNodeError ( child , tokens )
207+ }
196208 }
197209 return convertNode ( child , tokens ) as JSONExpression
198210 } ) ,
@@ -205,56 +217,80 @@ function convertArrayExpressionNode(
205217/**
206218 * Convert Literal node to JSONLiteral node
207219 */
208- function convertLiteralNode (
209- node : Literal | UnaryExpression ,
210- tokens : AST . Token [ ] ,
211- ) : JSONLiteral {
220+ function convertLiteralNode ( node : Literal , tokens : AST . Token [ ] ) : JSONLiteral {
212221 /* istanbul ignore next */
213- if ( node . type !== "Literal" && node . type !== "UnaryExpression" ) {
222+ if ( node . type !== "Literal" ) {
214223 return throwUnexpectedNodeError ( node , tokens )
215224 }
216- let literal : Literal
217- let value : number | string | null | boolean | RegExp | undefined
218- if ( node . type === "UnaryExpression" ) {
219- if ( node . operator !== "-" && node . operator !== "+" ) {
220- return throwUnexpectedNodeError ( node , tokens )
221- }
222- const argument = node . argument
223- if ( argument . type !== "Literal" || typeof argument . value !== "number" ) {
224- return throwUnexpectedNodeError ( node . argument , tokens )
225- }
226- if ( node . range ! [ 0 ] + 1 !== argument . range ! [ 0 ] ) {
227- return throwUnexpectedTokenError ( " " , argument )
228- }
229- literal = argument
230- value = node . operator === "-" ? - argument . value : argument . value
231- } else {
232- literal = node
233- value = node . value
234- }
225+ const value = node . value
235226
236- if ( ( literal as RegExpLiteral ) . regex ) {
237- return throwUnexpectedNodeError ( literal , tokens )
227+ if ( ( node as RegExpLiteral ) . regex ) {
228+ return throwUnexpectedNodeError ( node , tokens )
238229 }
239- if ( ( literal as any ) . bigint ) {
240- return throwUnexpectedNodeError ( literal , tokens )
230+ if ( ( node as any ) . bigint ) {
231+ return throwUnexpectedNodeError ( node , tokens )
241232 }
242233 if ( value !== null ) {
243234 if (
244235 typeof value !== "string" &&
245236 typeof value !== "number" &&
246237 typeof value !== "boolean"
247238 ) {
248- return throwUnexpectedNodeError ( literal , tokens )
239+ return throwUnexpectedNodeError ( node , tokens )
249240 }
250241 }
251242 const nn : JSONLiteral = {
252243 type : "JSONLiteral" ,
253244 value,
254- raw : literal . raw ! ,
245+ raw : node . raw ! ,
255246 ...getFixLocation ( node ) ,
256247 }
257- checkUnexpectKeys ( literal , tokens , nn )
248+ checkUnexpectKeys ( node , tokens , nn )
249+ return nn
250+ }
251+
252+ /**
253+ * Convert UnaryExpression node to JSONUnaryExpression node
254+ */
255+ function convertUnaryExpressionNode (
256+ node : UnaryExpression ,
257+ tokens : AST . Token [ ] ,
258+ ) : JSONUnaryExpression {
259+ /* istanbul ignore next */
260+ if ( node . type !== "UnaryExpression" ) {
261+ return throwUnexpectedNodeError ( node , tokens )
262+ }
263+ const operator = node . operator
264+
265+ if ( operator !== "-" && operator !== "+" ) {
266+ return throwUnexpectedNodeError ( node , tokens )
267+ }
268+ const argument = node . argument
269+ if ( argument . type === "Literal" ) {
270+ if ( typeof argument . value !== "number" ) {
271+ return throwUnexpectedNodeError ( argument , tokens )
272+ }
273+ } else if ( argument . type === "Identifier" ) {
274+ if ( ! isNumIdentifier ( argument ) ) {
275+ return throwUnexpectedNodeError ( argument , tokens )
276+ }
277+ } else {
278+ return throwUnexpectedNodeError ( argument , tokens )
279+ }
280+ if ( node . range ! [ 0 ] + 1 !== argument . range ! [ 0 ] ) {
281+ return throwUnexpectedTokenError ( " " , argument )
282+ }
283+
284+ const nn : JSONUnaryExpression = {
285+ type : "JSONUnaryExpression" ,
286+ operator,
287+ prefix : true ,
288+ argument : convertNode ( argument , tokens ) as
289+ | JSONNumberLiteral
290+ | JSONNumberIdentifier ,
291+ ...getFixLocation ( node ) ,
292+ }
293+ checkUnexpectKeys ( node , tokens , nn )
258294 return nn
259295}
260296
@@ -278,6 +314,15 @@ function convertIdentifierNode(
278314 return nn
279315}
280316
317+ /**
318+ * Check if given node is NaN or Infinity
319+ */
320+ function isNumIdentifier (
321+ node : Identifier ,
322+ ) : node is Identifier & { name : "NaN" | "Infinity" } {
323+ return node . name === "NaN" || node . name === "Infinity"
324+ }
325+
281326/**
282327 * Check unknown keys
283328 */
0 commit comments