Skip to content

Updates for DOMKit #174

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

Merged
merged 19 commits into from
Apr 4, 2022
Merged
Show file tree
Hide file tree
Changes from all 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
24 changes: 12 additions & 12 deletions IntegrationTests/TestSuites/Sources/PrimaryTests/main.swift
Original file line number Diff line number Diff line change
Expand Up @@ -356,14 +356,14 @@ try test("Call Function With This") {

try test("Object Conversion") {
let array1 = [1, 2, 3]
let jsArray1 = array1.jsValue().object!
let jsArray1 = array1.jsValue.object!
try expectEqual(jsArray1.length, .number(3))
try expectEqual(jsArray1[0], .number(1))
try expectEqual(jsArray1[1], .number(2))
try expectEqual(jsArray1[2], .number(3))

let array2: [ConvertibleToJSValue] = [1, "str", false]
let jsArray2 = array2.jsValue().object!
let jsArray2 = array2.jsValue.object!
try expectEqual(jsArray2.length, .number(3))
try expectEqual(jsArray2[0], .number(1))
try expectEqual(jsArray2[1], .string("str"))
Expand All @@ -374,11 +374,11 @@ try test("Object Conversion") {

try expectEqual(jsArray2[4], .object(jsArray1))

let dict1: [String: ConvertibleToJSValue] = [
"prop1": 1,
"prop2": "foo",
let dict1: [String: JSValue] = [
"prop1": 1.jsValue,
"prop2": "foo".jsValue,
]
let jsDict1 = dict1.jsValue().object!
let jsDict1 = dict1.jsValue.object!
try expectEqual(jsDict1.prop1, .number(1))
try expectEqual(jsDict1.prop2, .string("foo"))
}
Expand Down Expand Up @@ -425,7 +425,7 @@ try test("Closure Identifiers") {
#endif

func checkArray<T>(_ array: [T]) throws where T: TypedArrayElement & Equatable {
try expectEqual(toString(JSTypedArray(array).jsValue().object!), jsStringify(array))
try expectEqual(toString(JSTypedArray(array).jsValue.object!), jsStringify(array))
try checkArrayUnsafeBytes(array)
}

Expand Down Expand Up @@ -488,7 +488,7 @@ try test("TypedArray_Mutation") {
for i in 0..<100 {
try expectEqual(i, array[i])
}
try expectEqual(toString(array.jsValue().object!), jsStringify(Array(0..<100)))
try expectEqual(toString(array.jsValue.object!), jsStringify(Array(0..<100)))
}

try test("Date") {
Expand Down Expand Up @@ -797,9 +797,9 @@ try test("Hashable Conformance") {

let objectConstructor = JSObject.global.Object.function!
let obj = objectConstructor.new()
obj.a = 1.jsValue()
obj.a = 1.jsValue
let firstHash = obj.hashValue
obj.b = 2.jsValue()
obj.b = 2.jsValue
let secondHash = obj.hashValue
try expectEqual(firstHash, secondHash)
}
Expand All @@ -819,11 +819,11 @@ try test("Symbols") {
// })
// }.prop
let hasInstanceObject = JSObject.global.Object.function!.new()
hasInstanceObject.prop = JSClosure { _ in .undefined }.jsValue()
hasInstanceObject.prop = JSClosure { _ in .undefined }.jsValue
let hasInstanceClass = hasInstanceObject.prop.function!
hasInstanceClass[JSSymbol.hasInstance] = JSClosure { _ in
return .boolean(true)
}.jsValue()
}.jsValue
try expectEqual(hasInstanceClass[JSSymbol.hasInstance].function!().boolean, true)
try expectEqual(JSObject.global.Object.isInstanceOf(hasInstanceClass), true)
}
Expand Down
4 changes: 2 additions & 2 deletions Sources/JavaScriptEventLoop/JavaScriptEventLoop.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import _CJavaScriptEventLoop

#if compiler(>=5.5)

@available(macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0, *)
@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)
public final class JavaScriptEventLoop: SerialExecutor, @unchecked Sendable {

/// A function that queues a given closure as a microtask into JavaScript event loop.
Expand Down Expand Up @@ -97,7 +97,7 @@ public final class JavaScriptEventLoop: SerialExecutor, @unchecked Sendable {
}
}

@available(macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0, *)
@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)
public extension JSPromise {
/// Wait for the promise to complete, returning (or throwing) its result.
var value: JSValue {
Expand Down
6 changes: 3 additions & 3 deletions Sources/JavaScriptEventLoop/JobQueue.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,13 @@ import _CJavaScriptEventLoop

#if compiler(>=5.5)

@available(macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0, *)
@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)
struct QueueState: Sendable {
fileprivate var headJob: UnownedJob? = nil
fileprivate var isSpinning: Bool = false
}

@available(macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0, *)
@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)
extension JavaScriptEventLoop {

func insertJobQueue(job newJob: UnownedJob) {
Expand Down Expand Up @@ -58,7 +58,7 @@ extension JavaScriptEventLoop {
}
}

@available(macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0, *)
@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)
fileprivate extension UnownedJob {
private func asImpl() -> UnsafeMutablePointer<_CJavaScriptEventLoop.Job> {
unsafeBitCast(self, to: UnsafeMutablePointer<_CJavaScriptEventLoop.Job>.self)
Expand Down
2 changes: 1 addition & 1 deletion Sources/JavaScriptKit/BasicObjects/JSError.swift
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ public final class JSError: Error, JSBridgedClass {
}

/// Creates a new `JSValue` from this `JSError` instance.
public func jsValue() -> JSValue {
public var jsValue: JSValue {
.object(jsObject)
}
}
Expand Down
8 changes: 4 additions & 4 deletions Sources/JavaScriptKit/BasicObjects/JSPromise.swift
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ public final class JSPromise: JSBridgedClass {
@discardableResult
public func then(success: @escaping (JSValue) -> ConvertibleToJSValue) -> JSPromise {
let closure = JSOneshotClosure {
return success($0[0]).jsValue()
success($0[0]).jsValue
}
return JSPromise(unsafelyWrapping: jsObject.then!(closure).object!)
}
Expand All @@ -90,10 +90,10 @@ public final class JSPromise: JSBridgedClass {
public func then(success: @escaping (JSValue) -> ConvertibleToJSValue,
failure: @escaping (JSValue) -> ConvertibleToJSValue) -> JSPromise {
let successClosure = JSOneshotClosure {
return success($0[0]).jsValue()
success($0[0]).jsValue
}
let failureClosure = JSOneshotClosure {
return failure($0[0]).jsValue()
failure($0[0]).jsValue
}
return JSPromise(unsafelyWrapping: jsObject.then!(successClosure, failureClosure).object!)
}
Expand All @@ -103,7 +103,7 @@ public final class JSPromise: JSBridgedClass {
@discardableResult
public func `catch`(failure: @escaping (JSValue) -> ConvertibleToJSValue) -> JSPromise {
let closure = JSOneshotClosure {
return failure($0[0]).jsValue()
failure($0[0]).jsValue
}
return .init(unsafelyWrapping: jsObject.catch!(closure).object!)
}
Expand Down
13 changes: 8 additions & 5 deletions Sources/JavaScriptKit/BasicObjects/JSTypedArray.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,15 @@ public protocol TypedArrayElement: ConvertibleToJSValue, ConstructibleFromJSValu
/// A wrapper around all JavaScript [TypedArray](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/TypedArray) classes that exposes their properties in a type-safe way.
/// FIXME: [BigInt-based TypedArrays are currently not supported](https://github.com/swiftwasm/JavaScriptKit/issues/56).
public class JSTypedArray<Element>: JSBridgedClass, ExpressibleByArrayLiteral where Element: TypedArrayElement {
public static var constructor: JSFunction { Element.typedArrayClass }
public class var constructor: JSFunction { Element.typedArrayClass }
public var jsObject: JSObject

public subscript(_ index: Int) -> Element {
get {
return Element.construct(from: jsObject[index])!
}
set {
self.jsObject[index] = newValue.jsValue()
self.jsObject[index] = newValue.jsValue
}
}

Expand All @@ -30,7 +30,7 @@ public class JSTypedArray<Element>: JSBridgedClass, ExpressibleByArrayLiteral wh
///
/// - Parameter length: The number of elements that will be allocated.
public init(length: Int) {
jsObject = Element.typedArrayClass.new(length)
jsObject = Self.constructor.new(length)
}

required public init(unsafelyWrapping jsObject: JSObject) {
Expand All @@ -45,7 +45,7 @@ public class JSTypedArray<Element>: JSBridgedClass, ExpressibleByArrayLiteral wh
/// - Parameter array: The array that will be copied to create a new instance of TypedArray
public convenience init(_ array: [Element]) {
let jsArrayRef = array.withUnsafeBufferPointer { ptr in
_create_typed_array(Element.typedArrayClass.id, ptr.baseAddress!, Int32(array.count))
_create_typed_array(Self.constructor.id, ptr.baseAddress!, Int32(array.count))
}
self.init(unsafelyWrapping: JSObject(id: jsArrayRef))
}
Expand Down Expand Up @@ -116,7 +116,10 @@ extension Int8: TypedArrayElement {
extension UInt8: TypedArrayElement {
public static var typedArrayClass = JSObject.global.Uint8Array.function!
}
// TODO: Support Uint8ClampedArray?

public class JSUInt8ClampedArray: JSTypedArray<UInt8> {
public class override var constructor: JSFunction { JSObject.global.Uint8ClampedArray.function! }
}

extension Int16: TypedArrayElement {
public static var typedArrayClass = JSObject.global.Int16Array.function!
Expand Down
81 changes: 47 additions & 34 deletions Sources/JavaScriptKit/ConvertibleToJSValue.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,12 @@ import _CJavaScriptKit
/// Objects that can be converted to a JavaScript value, preferably in a lossless manner.
public protocol ConvertibleToJSValue {
/// Create a JSValue that represents this object
func jsValue() -> JSValue
var jsValue: JSValue { get }
}

extension ConvertibleToJSValue {
@available(*, deprecated, message: "Use the .jsValue property instead")
public func jsValue() -> JSValue { jsValue }
}

public typealias JSValueCompatible = ConvertibleToJSValue & ConstructibleFromJSValue
Expand All @@ -13,67 +18,67 @@ extension JSValue: JSValueCompatible {
return value
}

public func jsValue() -> JSValue { self }
public var jsValue: JSValue { self }
}

extension Bool: ConvertibleToJSValue {
public func jsValue() -> JSValue { .boolean(self) }
public var jsValue: JSValue { .boolean(self) }
}

extension Int: ConvertibleToJSValue {
public func jsValue() -> JSValue { .number(Double(self)) }
public var jsValue: JSValue { .number(Double(self)) }
}

extension UInt: ConvertibleToJSValue {
public func jsValue() -> JSValue { .number(Double(self)) }
public var jsValue: JSValue { .number(Double(self)) }
}

extension Float: ConvertibleToJSValue {
public func jsValue() -> JSValue { .number(Double(self)) }
public var jsValue: JSValue { .number(Double(self)) }
}

extension Double: ConvertibleToJSValue {
public func jsValue() -> JSValue { .number(self) }
public var jsValue: JSValue { .number(self) }
}

extension String: ConvertibleToJSValue {
public func jsValue() -> JSValue { .string(JSString(self)) }
public var jsValue: JSValue { .string(JSString(self)) }
}

extension UInt8: ConvertibleToJSValue {
public func jsValue() -> JSValue { .number(Double(self)) }
public var jsValue: JSValue { .number(Double(self)) }
}

extension UInt16: ConvertibleToJSValue {
public func jsValue() -> JSValue { .number(Double(self)) }
public var jsValue: JSValue { .number(Double(self)) }
}

extension UInt32: ConvertibleToJSValue {
public func jsValue() -> JSValue { .number(Double(self)) }
public var jsValue: JSValue { .number(Double(self)) }
}

extension UInt64: ConvertibleToJSValue {
public func jsValue() -> JSValue { .number(Double(self)) }
public var jsValue: JSValue { .number(Double(self)) }
}

extension Int8: ConvertibleToJSValue {
public func jsValue() -> JSValue { .number(Double(self)) }
public var jsValue: JSValue { .number(Double(self)) }
}

extension Int16: ConvertibleToJSValue {
public func jsValue() -> JSValue { .number(Double(self)) }
public var jsValue: JSValue { .number(Double(self)) }
}

extension Int32: ConvertibleToJSValue {
public func jsValue() -> JSValue { .number(Double(self)) }
public var jsValue: JSValue { .number(Double(self)) }
}

extension Int64: ConvertibleToJSValue {
public func jsValue() -> JSValue { .number(Double(self)) }
public var jsValue: JSValue { .number(Double(self)) }
}

extension JSString: ConvertibleToJSValue {
public func jsValue() -> JSValue { .string(self) }
public var jsValue: JSValue { .string(self) }
}

extension JSObject: JSValueCompatible {
Expand All @@ -84,17 +89,21 @@ extension JSObject: JSValueCompatible {
private let objectConstructor = JSObject.global.Object.function!
private let arrayConstructor = JSObject.global.Array.function!

extension Dictionary where Value: ConvertibleToJSValue, Key == String {
public func jsValue() -> JSValue {
Swift.Dictionary<Key, ConvertibleToJSValue>.jsValue(self)()
extension Dictionary where Value == ConvertibleToJSValue, Key == String {
public var jsValue: JSValue {
let object = objectConstructor.new()
for (key, value) in self {
object[key] = value.jsValue
}
return .object(object)
}
}

extension Dictionary: ConvertibleToJSValue where Value == ConvertibleToJSValue, Key == String {
public func jsValue() -> JSValue {
extension Dictionary: ConvertibleToJSValue where Value: ConvertibleToJSValue, Key == String {
public var jsValue: JSValue {
let object = objectConstructor.new()
for (key, value) in self {
object[key] = value.jsValue()
object[key] = value.jsValue
}
return .object(object)
}
Expand All @@ -104,7 +113,7 @@ extension Dictionary: ConstructibleFromJSValue where Value: ConstructibleFromJSV
public static func construct(from value: JSValue) -> Self? {
guard
let objectRef = value.object,
let keys: [String] = objectConstructor.keys!(objectRef.jsValue()).fromJSValue()
let keys: [String] = objectConstructor.keys!(objectRef.jsValue).fromJSValue()
else { return nil }

var entries = [(String, Value)]()
Expand All @@ -131,25 +140,29 @@ extension Optional: ConstructibleFromJSValue where Wrapped: ConstructibleFromJSV
}

extension Optional: ConvertibleToJSValue where Wrapped: ConvertibleToJSValue {
public func jsValue() -> JSValue {
public var jsValue: JSValue {
switch self {
case .none: return .null
case let .some(wrapped): return wrapped.jsValue()
case let .some(wrapped): return wrapped.jsValue
}
}
}

extension Array where Element: ConvertibleToJSValue {
public func jsValue() -> JSValue {
Array<ConvertibleToJSValue>.jsValue(self)()
extension Array: ConvertibleToJSValue where Element: ConvertibleToJSValue {
public var jsValue: JSValue {
let array = arrayConstructor.new(count)
for (index, element) in enumerated() {
array[index] = element.jsValue
}
return .object(array)
}
}

extension Array: ConvertibleToJSValue where Element == ConvertibleToJSValue {
public func jsValue() -> JSValue {
extension Array where Element == ConvertibleToJSValue {
public var jsValue: JSValue {
let array = arrayConstructor.new(count)
for (index, element) in enumerated() {
array[index] = element.jsValue()
array[index] = element.jsValue
}
return .object(array)
}
Expand All @@ -176,7 +189,7 @@ extension Array: ConstructibleFromJSValue where Element: ConstructibleFromJSValu
}

extension RawJSValue: ConvertibleToJSValue {
public func jsValue() -> JSValue {
public var jsValue: JSValue {
switch kind {
case .invalid:
fatalError()
Expand Down Expand Up @@ -243,7 +256,7 @@ extension Array where Element == ConvertibleToJSValue {
_ results: inout [RawJSValue], _ body: ([RawJSValue]) -> T
) -> T {
if index == values.count { return body(results) }
return values[index].jsValue().withRawJSValue { (rawValue) -> T in
return values[index].jsValue.withRawJSValue { (rawValue) -> T in
results.append(rawValue)
return _withRawJSValues(values, index + 1, &results, body)
}
Expand Down
Loading