diff --git a/Sources/Fuzzilli/Compiler/Compiler.swift b/Sources/Fuzzilli/Compiler/Compiler.swift index 43e8e58ff..0da0f5c7b 100644 --- a/Sources/Fuzzilli/Compiler/Compiler.swift +++ b/Sources/Fuzzilli/Compiler/Compiler.swift @@ -1160,13 +1160,10 @@ public class JavaScriptCompiler { fatalError("V8IntrinsicIdentifiers must be handled as part of their surrounding CallExpression") case .awaitExpression(let awaitExpression): - // TODO await is also allowed at the top level of a module - if !contextAnalyzer.context.contains(.asyncFunction) { - throw CompilerError.invalidNodeError("`await` is currently only supported in async functions") - } + // Await is also allowed at the top level of a module + // workerd requires that support let argument = try compileExpression(awaitExpression.argument) return emit(Await(), withInputs: [argument]).output - } } diff --git a/Sources/Fuzzilli/Compiler/Parser/parser.js b/Sources/Fuzzilli/Compiler/Parser/parser.js index f42fe00dd..211054bee 100644 --- a/Sources/Fuzzilli/Compiler/Parser/parser.js +++ b/Sources/Fuzzilli/Compiler/Parser/parser.js @@ -34,7 +34,7 @@ function tryReadFile(path) { // Parse the given JavaScript script and return an AST compatible with Fuzzilli's protobuf-based AST format. function parse(script, proto) { - let ast = Parser.parse(script, { plugins: ["v8intrinsic"] }); + let ast = Parser.parse(script, { allowAwaitOutsideFunction: true, plugins: ["topLevelAwait","v8intrinsic"] }); function assertNoError(err) { if (err) throw err; diff --git a/Sources/Fuzzilli/FuzzIL/Code.swift b/Sources/Fuzzilli/FuzzIL/Code.swift index 1e63b0ff9..6411a1e9f 100644 --- a/Sources/Fuzzilli/FuzzIL/Code.swift +++ b/Sources/Fuzzilli/FuzzIL/Code.swift @@ -239,9 +239,12 @@ public struct Code: Collection { throw FuzzilliError.codeVerificationError("variable \(input) is not visible anymore") } } - - guard instr.op.requiredContext.isSubset(of: contextAnalyzer.context) else { - throw FuzzilliError.codeVerificationError("operation \(instr.op.name) inside an invalid context") + + // allow top-level await + if !(instr.op is Await) { + guard instr.op.requiredContext.isSubset(of: contextAnalyzer.context) else { + throw FuzzilliError.codeVerificationError("operation \(instr.op.name) inside an invalid context") + } } // Ensure that the instruction exists in the right context