Skip to content

Commit eeb4261

Browse files
committed
support quine cheating objects and arrays
1 parent 0c5a5da commit eeb4261

1 file changed

Lines changed: 72 additions & 0 deletions

File tree

src/processScript.ts

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -291,6 +291,20 @@ export async function processScript(script: string) {
291291
const file = await babel.parseAsync(script) as babel.types.File
292292

293293
babel.traverse(file, {
294+
ObjectExpression(path) {
295+
const o: Record<string, unknown> = {}
296+
297+
if (parseObjectExpression(path.node, o))
298+
path.replaceWith(babel.types.identifier(`_JSON_VALUE_${jsonValues.push(o) - 1}_${randomString}_`))
299+
},
300+
301+
ArrayExpression(path) {
302+
const o: unknown[] = []
303+
304+
if (parseArrayExpression(path.node, o))
305+
path.replaceWith(babel.types.identifier(`_JSON_VALUE_${jsonValues.push(o) - 1}_${randomString}_`))
306+
},
307+
294308
TemplateLiteral(path) {
295309
const templateLiteral = path.node
296310
let replacement: babel.Node = babel.types.stringLiteral(templateLiteral.quasis[0].value.cooked!)
@@ -595,3 +609,61 @@ function getFunctionBodyStart(code: string) {
595609
}
596610

597611
export default processScript
612+
613+
function parseObjectExpression(node: babel.types.ObjectExpression, o: Record<string, unknown>) {
614+
for (const property of node.properties) {
615+
if (property.type != "ObjectProperty" || property.computed)
616+
return false
617+
618+
assert(property.key.type == "Identifier" || property.key.type == "NumericLiteral" || property.key.type == "StringLiteral")
619+
620+
if (property.value.type == "ArrayExpression") {
621+
const childArray: unknown[] = []
622+
623+
if (parseArrayExpression(property.value, childArray))
624+
o[property.key.type == "Identifier" ? property.key.name : property.key.value] = childArray
625+
} else if (property.value.type == "ObjectExpression") {
626+
const childObject: Record<string, unknown> = {}
627+
628+
if (parseObjectExpression(property.value, childObject))
629+
o[property.key.type == "Identifier" ? property.key.name : property.key.value] = childObject
630+
} else if (property.value.type == "NullLiteral")
631+
o[property.key.type == "Identifier" ? property.key.name : property.key.value] = null
632+
else if (property.value.type == "BooleanLiteral" || property.value.type == "NumericLiteral" || property.value.type == "StringLiteral")
633+
o[property.key.type == "Identifier" ? property.key.name : property.key.value] = property.value.value
634+
else
635+
return false
636+
}
637+
638+
return true
639+
}
640+
641+
function parseArrayExpression(node: babel.types.ArrayExpression, o: unknown[]) {
642+
for (const element of node.elements) {
643+
if (!element)
644+
return false
645+
646+
if (element.type == "ArrayExpression") {
647+
const childArray: unknown[] = []
648+
649+
if (parseArrayExpression(element, childArray))
650+
childArray.push(childArray)
651+
else
652+
return false
653+
} else if (element.type == "ObjectExpression") {
654+
const childObject: Record<string, unknown> = {}
655+
656+
if (parseObjectExpression(element, childObject))
657+
o.push(childObject)
658+
else
659+
return false
660+
} else if (element.type == "NullLiteral")
661+
o.push(null)
662+
else if (element.type == "BooleanLiteral" || element.type == "NumericLiteral" || element.type == "StringLiteral")
663+
o.push(element.value)
664+
else
665+
return false
666+
}
667+
668+
return true
669+
}

0 commit comments

Comments
 (0)