Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/with statement js compiler #439

Merged
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions Sources/Fuzzilli/Compiler/Compiler.swift
Original file line number Diff line number Diff line change
Expand Up @@ -479,6 +479,16 @@ public class JavaScriptCompiler {
let value = try compileExpression(throwStatement.argument)
emit(ThrowException(), withInputs: [value])

case .withStatement(let withStatement):
let object = try compileExpression(withStatement.object)
let beginWith = BeginWith()
emit(beginWith, withInputs: [object])
try enterNewScope {
for statement in withStatement.body.blockStatement.body {
try compileStatement(statement)
}
}
emit(EndWith())
}
}

Expand Down
6 changes: 6 additions & 0 deletions Sources/Fuzzilli/Compiler/Parser/parser.js
Original file line number Diff line number Diff line change
Expand Up @@ -320,6 +320,12 @@ function parse(script, proto) {
case 'ThrowStatement': {
return makeStatement('ThrowStatement', { argument: visitExpression(node.argument) });
}
case 'WithStatement': {
let withStatement = {};
withStatement.object = visitExpression(node.object);
withStatement.body = visitStatement(node.body);
return makeStatement('WithStatement', withStatement);
}
default: {
throw "Unhandled node type " + node.type;
}
Expand Down
141 changes: 141 additions & 0 deletions Sources/Fuzzilli/Protobuf/ast.pb.swift
Original file line number Diff line number Diff line change
Expand Up @@ -875,6 +875,36 @@ public struct Compiler_Protobuf_ThrowStatement: @unchecked Sendable {
fileprivate var _storage = _StorageClass.defaultInstance
}

public struct Compiler_Protobuf_WithStatement: @unchecked Sendable {
// SwiftProtobuf.Message conformance is added in an extension below. See the
// `Message` and `Message+*Additions` files in the SwiftProtobuf library for
// methods supported on all messages.

public var object: Compiler_Protobuf_Expression {
get {return _storage._object ?? Compiler_Protobuf_Expression()}
set {_uniqueStorage()._object = newValue}
}
/// Returns true if `object` has been explicitly set.
public var hasObject: Bool {return _storage._object != nil}
/// Clears the value of `object`. Subsequent reads from it will return its default value.
public mutating func clearObject() {_uniqueStorage()._object = nil}

public var body: Compiler_Protobuf_Statement {
get {return _storage._body ?? Compiler_Protobuf_Statement()}
set {_uniqueStorage()._body = newValue}
}
/// Returns true if `body` has been explicitly set.
public var hasBody: Bool {return _storage._body != nil}
/// Clears the value of `body`. Subsequent reads from it will return its default value.
public mutating func clearBody() {_uniqueStorage()._body = nil}

public var unknownFields = SwiftProtobuf.UnknownStorage()

public init() {}

fileprivate var _storage = _StorageClass.defaultInstance
}

public struct Compiler_Protobuf_Statement: @unchecked Sendable {
// SwiftProtobuf.Message conformance is added in an extension below. See the
// `Message` and `Message+*Additions` files in the SwiftProtobuf library for
Expand Down Expand Up @@ -1021,6 +1051,14 @@ public struct Compiler_Protobuf_Statement: @unchecked Sendable {
set {_uniqueStorage()._statement = .throwStatement(newValue)}
}

public var withStatement: Compiler_Protobuf_WithStatement {
get {
if case .withStatement(let v)? = _storage._statement {return v}
return Compiler_Protobuf_WithStatement()
}
set {_uniqueStorage()._statement = .withStatement(newValue)}
}

public var unknownFields = SwiftProtobuf.UnknownStorage()

public enum OneOf_Statement: Equatable, Sendable {
Expand All @@ -1041,6 +1079,7 @@ public struct Compiler_Protobuf_Statement: @unchecked Sendable {
case continueStatement(Compiler_Protobuf_ContinueStatement)
case tryStatement(Compiler_Protobuf_TryStatement)
case throwStatement(Compiler_Protobuf_ThrowStatement)
case withStatement(Compiler_Protobuf_WithStatement)

}

Expand Down Expand Up @@ -3896,6 +3935,90 @@ extension Compiler_Protobuf_ThrowStatement: SwiftProtobuf.Message, SwiftProtobuf
}
}

extension Compiler_Protobuf_WithStatement: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
public static let protoMessageName: String = _protobuf_package + ".WithStatement"
public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
1: .same(proto: "object"),
2: .same(proto: "body"),
]

fileprivate class _StorageClass {
var _object: Compiler_Protobuf_Expression? = nil
var _body: Compiler_Protobuf_Statement? = nil

#if swift(>=5.10)
// This property is used as the initial default value for new instances of the type.
// The type itself is protecting the reference to its storage via CoW semantics.
// This will force a copy to be made of this reference when the first mutation occurs;
// hence, it is safe to mark this as `nonisolated(unsafe)`.
static nonisolated(unsafe) let defaultInstance = _StorageClass()
#else
static let defaultInstance = _StorageClass()
#endif

private init() {}

init(copying source: _StorageClass) {
_object = source._object
_body = source._body
}
}

fileprivate mutating func _uniqueStorage() -> _StorageClass {
if !isKnownUniquelyReferenced(&_storage) {
_storage = _StorageClass(copying: _storage)
}
return _storage
}

public mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
_ = _uniqueStorage()
try withExtendedLifetime(_storage) { (_storage: _StorageClass) in
while let fieldNumber = try decoder.nextFieldNumber() {
// The use of inline closures is to circumvent an issue where the compiler
// allocates stack space for every case branch when no optimizations are
// enabled. https://github.com/apple/swift-protobuf/issues/1034
switch fieldNumber {
case 1: try { try decoder.decodeSingularMessageField(value: &_storage._object) }()
case 2: try { try decoder.decodeSingularMessageField(value: &_storage._body) }()
default: break
}
}
}
}

public func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
try withExtendedLifetime(_storage) { (_storage: _StorageClass) in
// The use of inline closures is to circumvent an issue where the compiler
// allocates stack space for every if/case branch local when no optimizations
// are enabled. https://github.com/apple/swift-protobuf/issues/1034 and
// https://github.com/apple/swift-protobuf/issues/1182
try { if let v = _storage._object {
try visitor.visitSingularMessageField(value: v, fieldNumber: 1)
} }()
try { if let v = _storage._body {
try visitor.visitSingularMessageField(value: v, fieldNumber: 2)
} }()
}
try unknownFields.traverse(visitor: &visitor)
}

public static func ==(lhs: Compiler_Protobuf_WithStatement, rhs: Compiler_Protobuf_WithStatement) -> Bool {
if lhs._storage !== rhs._storage {
let storagesAreEqual: Bool = withExtendedLifetime((lhs._storage, rhs._storage)) { (_args: (_StorageClass, _StorageClass)) in
let _storage = _args.0
let rhs_storage = _args.1
if _storage._object != rhs_storage._object {return false}
if _storage._body != rhs_storage._body {return false}
return true
}
if !storagesAreEqual {return false}
}
if lhs.unknownFields != rhs.unknownFields {return false}
return true
}
}

extension Compiler_Protobuf_Statement: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
public static let protoMessageName: String = _protobuf_package + ".Statement"
public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
Expand All @@ -3916,6 +4039,7 @@ extension Compiler_Protobuf_Statement: SwiftProtobuf.Message, SwiftProtobuf._Mes
15: .same(proto: "continueStatement"),
16: .same(proto: "tryStatement"),
17: .same(proto: "throwStatement"),
18: .same(proto: "withStatement"),
]

fileprivate class _StorageClass {
Expand Down Expand Up @@ -4174,6 +4298,19 @@ extension Compiler_Protobuf_Statement: SwiftProtobuf.Message, SwiftProtobuf._Mes
_storage._statement = .throwStatement(v)
}
}()
case 18: try {
var v: Compiler_Protobuf_WithStatement?
var hadOneofValue = false
if let current = _storage._statement {
hadOneofValue = true
if case .withStatement(let m) = current {v = m}
}
try decoder.decodeSingularMessageField(value: &v)
if let v = v {
if hadOneofValue {try decoder.handleConflictingOneOf()}
_storage._statement = .withStatement(v)
}
}()
default: break
}
}
Expand Down Expand Up @@ -4255,6 +4392,10 @@ extension Compiler_Protobuf_Statement: SwiftProtobuf.Message, SwiftProtobuf._Mes
guard case .throwStatement(let v)? = _storage._statement else { preconditionFailure() }
try visitor.visitSingularMessageField(value: v, fieldNumber: 17)
}()
case .withStatement?: try {
guard case .withStatement(let v)? = _storage._statement else { preconditionFailure() }
try visitor.visitSingularMessageField(value: v, fieldNumber: 18)
}()
case nil: break
}
}
Expand Down
6 changes: 6 additions & 0 deletions Sources/Fuzzilli/Protobuf/ast.proto
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,11 @@ message ThrowStatement {
Expression argument = 1;
}

message WithStatement {
Expression object = 1;
Statement body = 2;
}

message Statement {
oneof statement {
EmptyStatement emptyStatement = 1;
Expand All @@ -221,6 +226,7 @@ message Statement {
ContinueStatement continueStatement = 15;
TryStatement tryStatement = 16;
ThrowStatement throwStatement = 17;
WithStatement withStatement = 18;
}
}

Expand Down
8 changes: 8 additions & 0 deletions Tests/FuzzilliTests/CompilerTests/basic_object_access.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,11 @@ o[2] = o[1] + o[0];
o[3] = o[2] + o[1];

output(JSON.stringify(o));

with(o) {
a = 3;
b = 4;
c = a + b;
}

output(JSON.stringify(o));
7 changes: 7 additions & 0 deletions Tests/FuzzilliTests/CompilerTests/basic_scoping.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,12 @@ function foo(x) {
}
output(x);
output(y);
let obj = { x: 45, y: 9001 };
with (obj) {
output(x);
output(y);
}
output(x);
output(y);
}
foo(44);
Loading