Created
February 14, 2018 23:40
-
-
Save tjw/7a1762612527a5be6b5fdc41d7d50fa9 to your computer and use it in GitHub Desktop.
Regression in JSObjectSetPrototype for the global object in a context.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
swift SetPrototype.swift | |
On 10.13.4, the result is 'undefined', but it should be '5'. | |
*/ | |
import Foundation | |
import JavaScriptCore | |
var definition:JSClassDefinition = kJSClassDefinitionEmpty | |
definition.attributes = JSClassAttributes(kJSClassAttributeNoAutomaticPrototype) | |
definition.className = ("Foo" as NSString).utf8String | |
let classRef = JSClassCreate(&definition)! | |
let ctx = JSGlobalContextCreate(classRef) | |
let originalGlobalObject = JSContextGetGlobalObject(ctx)! | |
let prototype = JSObjectMake(ctx, nil, nil)! | |
JSObjectSetPrototype(ctx, originalGlobalObject, prototype) | |
// In 10.13.3 and earlier, setting the prototype on the global object made the context return a new global object | |
let updatedGlobalObject = JSContextGetGlobalObject(ctx)! | |
if originalGlobalObject != updatedGlobalObject { | |
print("global object changed from \(originalGlobalObject) to \(updatedGlobalObject))") | |
} | |
// Add a property to the prototype | |
let valueName = JSStringCreateWithCFString("value" as CFString); | |
do { | |
var exception: JSValueRef? = nil | |
JSObjectSetProperty(ctx, prototype, valueName, JSValueMakeNumber(ctx, 5.0), UInt32(kJSPropertyAttributeNone), &exception) | |
guard exception == nil else { | |
fatalError("Unable to set property") | |
} | |
} | |
// Get the property via a script that should find the property via the prototype chain from the global object. | |
let scriptString = JSStringCreateWithCFString("this.value;" as CFString) | |
var scriptException: JSValueRef? = nil | |
guard let resultRef = JSEvaluateScript(ctx, scriptString, updatedGlobalObject, nil, 0, &scriptException) else { | |
if let exc = scriptException { | |
let excString = JSValueToStringCopy(ctx, exc, nil) | |
fatalError("execution failed: \(JSStringCopyCFString(kCFAllocatorDefault, excString)!)") | |
} else { | |
fatalError("execution failed") | |
} | |
} | |
// Should find the `5` in the prototype chain. Does before 10.13.4 beta. | |
if let resultString = JSValueToStringCopy(ctx, resultRef, nil) { | |
print("resultString: \(JSStringCopyCFString(kCFAllocatorDefault, resultString)!)") | |
} else { | |
print("failed to get resultString") | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment