Skip to content

Commit 4ac378c

Browse files
LiedtkeV8-internal LUCI CQ
authored andcommitted
[parser] Support rest parameters on transpiling JS -> FuzzIL
This fixes #546 Change-Id: I8331dd909c05a51bfe73749e8677b18501e261bd Reviewed-on: https://chrome-internal-review.googlesource.com/c/v8/fuzzilli/+/8956179 Reviewed-by: Michael Achenbach <machenbach@google.com> Commit-Queue: Matthias Liedtke <mliedtke@google.com> Auto-Submit: Matthias Liedtke <mliedtke@google.com>
1 parent 948c97b commit 4ac378c

File tree

6 files changed

+213
-60
lines changed

6 files changed

+213
-60
lines changed

Sources/Fuzzilli/Compiler/Compiler.swift

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -238,7 +238,8 @@ public class JavaScriptCompiler {
238238
try enterNewScope {
239239
var parameters = head.innerOutputs
240240
map("this", to: parameters.removeFirst())
241-
mapParameters([setter.parameter], to: parameters)
241+
map(setter.parameter.name, to: parameters.removeFirst())
242+
assert(parameters.isEmpty)
242243
for statement in setter.body {
243244
try compileStatement(statement)
244245
}
@@ -511,7 +512,7 @@ public class JavaScriptCompiler {
511512
emit(EndForOfLoop())
512513

513514
case .breakStatement:
514-
// If we're in both .loop and .switch context, then the loop must be the most recent context
515+
// If we're in both .loop and .switch context, then the loop must be the most recent context
515516
// (switch blocks don't propagate an outer .loop context) so we just need to check for .loop here
516517
if contextAnalyzer.context.contains(.loop){
517518
emit(LoopBreak())
@@ -565,14 +566,14 @@ public class JavaScriptCompiler {
565566
emit(EndWith())
566567
case .switchStatement(let switchStatement):
567568
// TODO Replace the precomputation of tests with compilation of the test expressions in the cases.
568-
// To do this, we would need to redesign Switch statements in FuzzIL to (for example) have a BeginSwitchCaseHead, BeginSwitchCaseBody, and EndSwitchCase.
569+
// To do this, we would need to redesign Switch statements in FuzzIL to (for example) have a BeginSwitchCaseHead, BeginSwitchCaseBody, and EndSwitchCase.
569570
// Then the expression would go inside the header.
570571
var precomputedTests = [Variable]()
571572
for caseStatement in switchStatement.cases {
572573
if caseStatement.hasTest {
573574
let test = try compileExpression(caseStatement.test)
574575
precomputedTests.append(test)
575-
}
576+
}
576577
}
577578
let discriminant = try compileExpression(switchStatement.discriminant)
578579
emit(BeginSwitch(), withInputs: [discriminant])
@@ -589,7 +590,7 @@ public class JavaScriptCompiler {
589590
}
590591
// We could also do an optimization here where we check if the last statement in the case is a break, and if so, we drop the last instruction
591592
// and set the fallsThrough flag to false.
592-
emit(EndSwitchCase(fallsThrough: true))
593+
emit(EndSwitchCase(fallsThrough: true))
593594
}
594595
emit(EndSwitch())
595596
}
@@ -896,7 +897,8 @@ public class JavaScriptCompiler {
896897
try enterNewScope {
897898
var parameters = instr.innerOutputs
898899
map("this", to: parameters.removeFirst())
899-
mapParameters([setter.parameter], to: parameters)
900+
map(setter.parameter.name, to: parameters.removeFirst())
901+
assert(parameters.isEmpty)
900902
for statement in setter.body {
901903
try compileStatement(statement)
902904
}
@@ -1251,15 +1253,15 @@ public class JavaScriptCompiler {
12511253
scopes.top[identifier] = v
12521254
}
12531255

1254-
private func mapParameters(_ parameters: [Compiler_Protobuf_Parameter], to variables: ArraySlice<Variable>) {
1255-
assert(parameters.count == variables.count)
1256-
for (param, v) in zip(parameters, variables) {
1256+
private func mapParameters(_ parameters: Compiler_Protobuf_Parameters, to variables: ArraySlice<Variable>) {
1257+
assert(parameters.parameters.count == variables.count)
1258+
for (param, v) in zip(parameters.parameters, variables) {
12571259
map(param.name, to: v)
12581260
}
12591261
}
12601262

1261-
private func convertParameters(_ parameters: [Compiler_Protobuf_Parameter]) -> Parameters {
1262-
return Parameters(count: parameters.count)
1263+
private func convertParameters(_ parameters: Compiler_Protobuf_Parameters) -> Parameters {
1264+
return Parameters(count: parameters.parameters.count, hasRestParameter: parameters.hasRestElement_p)
12631265
}
12641266

12651267
/// Convenience accessor for the currently active scope.

Sources/Fuzzilli/Compiler/Parser/parser.js

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -84,13 +84,22 @@ function parse(script, proto) {
8484
}
8585

8686
function visitParameter(param) {
87-
assert(param.type == 'Identifier', "Expected parameter type to have type 'Identifier', found " + param.type);
88-
return make('Parameter', { name: param.name });
87+
switch (param.type) {
88+
case 'Identifier':
89+
return make('Parameter', { name: param.name });
90+
case 'RestElement':
91+
return make('Parameter', { name: param.argument.name });
92+
default:
93+
assert(false, "Unknown parameter type: " + param.type);
94+
}
8995
}
9096

9197
function visitParameters(params) {
92-
return params.map(visitParameter)
93-
}
98+
return make('Parameters', {
99+
parameters: params.map(visitParameter),
100+
hasRestElement: params.some(param => param.type === 'RestElement'),
101+
});
102+
};
94103

95104
// Processes the body of a block statement node and returns a list of statements.
96105
function visitBody(node) {

0 commit comments

Comments
 (0)