Skip to content

Commit 4f08784

Browse files
Liedtkev8-internal-scoped@luci-project-accounts.iam.gserviceaccount.com
authored andcommitted
[js] Register globalThis as a root of all builtins
Change-Id: Iafffa816f1283db25c5254a9229d21b8deb7191d Reviewed-on: https://chrome-internal-review.googlesource.com/c/v8/fuzzilli/+/9645495 Reviewed-by: Olivier Flückiger <olivf@google.com> Reviewed-by: Leon Bettscheider <bettscheider@chromium.org> Commit-Queue: Matthias Liedtke <mliedtke@google.com>
1 parent 6066baf commit 4f08784

2 files changed

Lines changed: 94 additions & 2 deletions

File tree

Sources/Fuzzilli/Environment/JavaScriptEnvironment.swift

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -324,6 +324,7 @@ public class JavaScriptEnvironment: ComponentBase {
324324
private var builtinTypes: [String: ILType] = [:]
325325
private var groups: [String: ObjectGroup] = [:]
326326
private var enums: [String: ILType] = [:]
327+
private var globalThisGroup: ObjectGroup
327328

328329
// Producing generators, keyed on `type.group`
329330
private var producingGenerators:
@@ -361,7 +362,7 @@ public class JavaScriptEnvironment: ComponentBase {
361362
additionalBuiltins: [String: ILType] = [:], additionalObjectGroups: [ObjectGroup] = [],
362363
additionalEnumerations: [ILType] = [], additionalOptionsBags: [OptionsBag] = []
363364
) {
364-
365+
self.globalThisGroup = ObjectGroup.jsGlobalThis
365366
super.init(name: "JavaScriptEnvironment")
366367

367368
// Build model of the JavaScript environment
@@ -767,6 +768,8 @@ public class JavaScriptEnvironment: ComponentBase {
767768
registerBuiltin(builtin, ofType: type)
768769
}
769770

771+
finalizeGlobalThisGroup()
772+
770773
// Add some well-known builtin properties and methods.
771774
builtinProperties.insert("__proto__")
772775
builtinProperties.insert("constructor")
@@ -977,11 +980,21 @@ public class JavaScriptEnvironment: ComponentBase {
977980
})
978981
}
979982

980-
public func registerBuiltin(_ name: String, ofType type: ILType) {
983+
private func registerBuiltin(_ name: String, ofType type: ILType) {
981984
assert(builtinTypes[name] == nil)
982985
builtinTypes[name] = type
983986
builtins.insert(name)
984987

988+
globalThisGroup.properties[name] = type
989+
if let sig = type.functionSignature ?? type.signature {
990+
globalThisGroup.methods[name] = [sig]
991+
}
992+
993+
builtinProperties.insert(name)
994+
if type.functionSignature != nil || type.signature != nil {
995+
builtinMethods.insert(name)
996+
}
997+
985998
let producedType = addProducingProperty(forType: type, by: name, on: "")
986999
if let groupName = producedType.group {
9871000
if var current = groups[groupName] {
@@ -993,6 +1006,17 @@ public class JavaScriptEnvironment: ComponentBase {
9931006
}
9941007
}
9951008

1009+
private func finalizeGlobalThisGroup() {
1010+
globalThisGroup.instanceType = .object(
1011+
ofGroup: "GlobalThis",
1012+
// Sort to ensure deterministic printing of this type.
1013+
withProperties: Array(globalThisGroup.properties.keys).sorted(),
1014+
withMethods: Array(globalThisGroup.methods.keys).sorted()
1015+
)
1016+
registerBuiltin("globalThis", ofType: globalThisGroup.instanceType)
1017+
registerObjectGroup(globalThisGroup)
1018+
}
1019+
9961020
public func registerOptionsBag(_ bag: OptionsBag) {
9971021
registerObjectGroup(bag.group)
9981022

@@ -2053,6 +2077,15 @@ extension ObjectGroup {
20532077
// * "output" type information (properties and return values) should be as precise as possible
20542078
// * "input" type information (function parameters) should be as broad as possible
20552079
extension ObjectGroup {
2080+
/// Object group modelling the JavaScript globalThis object.
2081+
/// Note: The properties and methods are registered dynamically.
2082+
public static let jsGlobalThis = ObjectGroup(
2083+
name: "GlobalThis",
2084+
instanceType: nil,
2085+
properties: [:],
2086+
overloads: [:]
2087+
)
2088+
20562089
/// Object group modelling JavaScript strings
20572090
public static let jsStrings = ObjectGroup(
20582091
name: "String",

Tests/FuzzilliTests/JSTyperTests.swift

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -984,6 +984,65 @@ struct JSTyperTests {
984984
}
985985
}
986986

987+
@Test func testGlobalThisTypeInference() {
988+
let env = JavaScriptEnvironment()
989+
let fuzzer = makeMockFuzzer(environment: env)
990+
fuzzer.sync {
991+
let b = fuzzer.makeBuilder()
992+
let globalThis = b.createNamedVariable(forBuiltin: "globalThis")
993+
#expect(b.type(of: globalThis).properties.contains("Number"))
994+
#expect(b.type(of: globalThis).methods.contains("Number"))
995+
996+
// Property lookups on globalThis
997+
let number = b.getProperty("Number", of: globalThis)
998+
#expect(b.type(of: number) == .jsNumberConstructor)
999+
let math = b.getProperty("Math", of: globalThis)
1000+
#expect(b.type(of: math) == .jsMathObject)
1001+
let undefined = b.getProperty("undefined", of: globalThis)
1002+
#expect(b.type(of: undefined) == .undefined)
1003+
let isNaNProp = b.getProperty("isNaN", of: globalThis)
1004+
#expect(b.type(of: isNaNProp) == .jsIsNaNFunction)
1005+
// globalThis is recursive.
1006+
let g = b.getProperty("globalThis", of: globalThis)
1007+
#expect(b.type(of: g) == b.type(of: globalThis))
1008+
1009+
// Calling methods on globalThis
1010+
let res = b.callMethod("isNaN", on: globalThis, withArgs: [b.loadInt(42)])
1011+
#expect(b.type(of: res) == .boolean)
1012+
}
1013+
}
1014+
1015+
@Test func testGlobalThisWithAdditionalBuiltins() {
1016+
let builtinAType = ILType.integer
1017+
let builtinBType = ILType.object(
1018+
ofGroup: "B", withProperties: ["foo", "bar"], withMethods: ["m1", "m2"])
1019+
let builtinCType = ILType.function([] => .number)
1020+
1021+
let env = JavaScriptEnvironment(additionalBuiltins: [
1022+
"A": builtinAType,
1023+
"B": builtinBType,
1024+
"C": builtinCType,
1025+
])
1026+
1027+
let fuzzer = makeMockFuzzer(environment: env)
1028+
fuzzer.sync {
1029+
let b = fuzzer.makeBuilder()
1030+
let globalThis = b.createNamedVariable(forBuiltin: "globalThis")
1031+
1032+
let a = b.getProperty("A", of: globalThis)
1033+
#expect(b.type(of: a) == builtinAType)
1034+
let bObj = b.getProperty("B", of: globalThis)
1035+
#expect(b.type(of: bObj) == builtinBType)
1036+
let cFunc = b.getProperty("C", of: globalThis)
1037+
#expect(b.type(of: cFunc) == builtinCType)
1038+
let cCall = b.callMethod("C", on: globalThis, withArgs: [])
1039+
#expect(b.type(of: cCall) == .number)
1040+
// globalThis is recursive including the additional properties.
1041+
let g = b.getProperty("globalThis", of: globalThis)
1042+
#expect(b.type(of: g) == b.type(of: globalThis))
1043+
}
1044+
}
1045+
9871046
@Test func testPropertyTypeInference() {
9881047
let propFooType = ILType.float
9891048
let propBarType = ILType.function([] => .jsAnything)

0 commit comments

Comments
 (0)