Skip to content
Closed
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
2 changes: 1 addition & 1 deletion Sources/JavaScriptKit/ConvertibleToJSValue.swift
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,7 @@ extension RawJSValue: ConvertibleToJSValue {
case .undefined:
return .undefined
case .function:
return .function(JSFunction(id: UInt32(payload1)))
return .object(JSFunction(id: UInt32(payload1)))
case .symbol:
return .symbol(JSSymbol(id: UInt32(payload1)))
case .bigInt:
Expand Down
9 changes: 8 additions & 1 deletion Sources/JavaScriptKit/FundamentalObjects/JSClosure.swift
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,10 @@ public class JSOneshotClosure: JSObject, JSClosureProtocol {
/// button.removeEventListener!("click", JSValue.function(eventListener))
/// ```
///
public class JSClosure: JSFunction, JSClosureProtocol {
/// - Note: JSClosure now inherits from JSObject directly instead of JSFunction,
/// providing a consistent and unified object model that aligns with JavaScript's
/// dynamic callability semantics.
public class JSClosure: JSObject, JSClosureProtocol {

class SharedJSClosure {
// Note: 6.0 compilers built with assertions enabled crash when calling
Expand Down Expand Up @@ -165,6 +168,10 @@ public class JSClosure: JSFunction, JSClosureProtocol {
fatalError("JSClosure does not support dictionary literal initialization")
}

override public var jsValue: JSValue {
.object(self)
}

#if compiler(>=5.5) && (!hasFeature(Embedded) || os(WASI))
/// Creates a new `JSClosure` that calls the given Swift function asynchronously.
///
Expand Down
136 changes: 39 additions & 97 deletions Sources/JavaScriptKit/FundamentalObjects/JSFunction.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ import _CJavaScriptKit
/// alert("Hello, world")
/// ```
///
/// - Note: In a future version, JSFunction will be unified with JSObject.
/// Consider using JSObject directly for new code, as all objects in JavaScript
/// can potentially be callable. JSFunction functionality is now available on JSObject.
public class JSFunction: JSObject {
#if !hasFeature(Embedded)
/// Call this function with given `arguments` and binding given `this` as context.
Expand All @@ -18,7 +21,7 @@ public class JSFunction: JSObject {
/// - arguments: Arguments to be passed to this function.
/// - Returns: The result of this call.
@discardableResult
public func callAsFunction(this: JSObject, arguments: [ConvertibleToJSValue]) -> JSValue {
override public func callAsFunction(this: JSObject, arguments: [ConvertibleToJSValue]) -> JSValue {
invokeNonThrowingJSFunction(arguments: arguments, this: this).jsValue
}

Expand All @@ -27,20 +30,20 @@ public class JSFunction: JSObject {
/// - arguments: Arguments to be passed to this function.
/// - Returns: The result of this call.
@discardableResult
public func callAsFunction(arguments: [ConvertibleToJSValue]) -> JSValue {
override public func callAsFunction(arguments: [ConvertibleToJSValue]) -> JSValue {
invokeNonThrowingJSFunction(arguments: arguments).jsValue
}

/// A variadic arguments version of `callAsFunction`.
@discardableResult
public func callAsFunction(this: JSObject, _ arguments: ConvertibleToJSValue...) -> JSValue {
self(this: this, arguments: arguments)
override public func callAsFunction(this: JSObject, _ arguments: ConvertibleToJSValue...) -> JSValue {
self.callAsFunction(this: this, arguments: arguments)
}

/// A variadic arguments version of `callAsFunction`.
@discardableResult
public func callAsFunction(_ arguments: ConvertibleToJSValue...) -> JSValue {
self(arguments: arguments)
override public func callAsFunction(_ arguments: ConvertibleToJSValue...) -> JSValue {
self.callAsFunction(arguments: arguments)
}

/// Instantiate an object from this function as a constructor.
Expand All @@ -53,7 +56,7 @@ public class JSFunction: JSObject {
///
/// - Parameter arguments: Arguments to be passed to this constructor function.
/// - Returns: A new instance of this constructor.
public func new(arguments: [ConvertibleToJSValue]) -> JSObject {
override public func new(arguments: [ConvertibleToJSValue]) -> JSObject {
arguments.withRawJSValues { rawValues in
rawValues.withUnsafeBufferPointer { bufferPointer in
JSObject(id: swjs_call_new(self.id, bufferPointer.baseAddress!, Int32(bufferPointer.count)))
Expand All @@ -62,7 +65,7 @@ public class JSFunction: JSObject {
}

/// A variadic arguments version of `new`.
public func new(_ arguments: ConvertibleToJSValue...) -> JSObject {
override public func new(_ arguments: ConvertibleToJSValue...) -> JSObject {
new(arguments: arguments)
}

Expand All @@ -87,11 +90,11 @@ public class JSFunction: JSObject {
#endif

@discardableResult
public func callAsFunction(arguments: [JSValue]) -> JSValue {
override public func callAsFunction(arguments: [JSValue]) -> JSValue {
invokeNonThrowingJSFunction(arguments: arguments).jsValue
}

public func new(arguments: [JSValue]) -> JSObject {
override public func new(arguments: [JSValue]) -> JSObject {
arguments.withRawJSValues { rawValues in
rawValues.withUnsafeBufferPointer { bufferPointer in
JSObject(id: swjs_call_new(self.id, bufferPointer.baseAddress!, Int32(bufferPointer.count)))
Expand All @@ -105,68 +108,7 @@ public class JSFunction: JSObject {
}

override public var jsValue: JSValue {
.function(self)
}

final func invokeNonThrowingJSFunction(arguments: [JSValue]) -> RawJSValue {
arguments.withRawJSValues { invokeNonThrowingJSFunction(rawValues: $0) }
}

final func invokeNonThrowingJSFunction(arguments: [JSValue], this: JSObject) -> RawJSValue {
arguments.withRawJSValues { invokeNonThrowingJSFunction(rawValues: $0, this: this) }
}

#if !hasFeature(Embedded)
final func invokeNonThrowingJSFunction(arguments: [ConvertibleToJSValue]) -> RawJSValue {
arguments.withRawJSValues { invokeNonThrowingJSFunction(rawValues: $0) }
}

final func invokeNonThrowingJSFunction(arguments: [ConvertibleToJSValue], this: JSObject) -> RawJSValue {
arguments.withRawJSValues { invokeNonThrowingJSFunction(rawValues: $0, this: this) }
}
#endif

final private func invokeNonThrowingJSFunction(rawValues: [RawJSValue]) -> RawJSValue {
rawValues.withUnsafeBufferPointer { [id] bufferPointer in
let argv = bufferPointer.baseAddress
let argc = bufferPointer.count
var payload1 = JavaScriptPayload1()
var payload2 = JavaScriptPayload2()
let resultBitPattern = swjs_call_function_no_catch(
id,
argv,
Int32(argc),
&payload1,
&payload2
)
let kindAndFlags = JavaScriptValueKindAndFlags(bitPattern: resultBitPattern)
assert(!kindAndFlags.isException)
let result = RawJSValue(kind: kindAndFlags.kind, payload1: payload1, payload2: payload2)
return result
}
}

final private func invokeNonThrowingJSFunction(rawValues: [RawJSValue], this: JSObject) -> RawJSValue {
rawValues.withUnsafeBufferPointer { [id] bufferPointer in
let argv = bufferPointer.baseAddress
let argc = bufferPointer.count
var payload1 = JavaScriptPayload1()
var payload2 = JavaScriptPayload2()
let resultBitPattern = swjs_call_function_with_this_no_catch(
this.id,
id,
argv,
Int32(argc),
&payload1,
&payload2
)
let kindAndFlags = JavaScriptValueKindAndFlags(bitPattern: resultBitPattern)
#if !hasFeature(Embedded)
assert(!kindAndFlags.isException)
#endif
let result = RawJSValue(kind: kindAndFlags.kind, payload1: payload1, payload2: payload2)
return result
}
.object(self)
}
}

Expand All @@ -182,17 +124,17 @@ public class JSFunction: JSObject {
extension JSFunction {

@discardableResult
public func callAsFunction(this: JSObject) -> JSValue {
override public func callAsFunction(this: JSObject) -> JSValue {
invokeNonThrowingJSFunction(arguments: [], this: this).jsValue
}

@discardableResult
public func callAsFunction(this: JSObject, _ arg0: some ConvertibleToJSValue) -> JSValue {
override public func callAsFunction(this: JSObject, _ arg0: some ConvertibleToJSValue) -> JSValue {
invokeNonThrowingJSFunction(arguments: [arg0.jsValue], this: this).jsValue
}

@discardableResult
public func callAsFunction(
override public func callAsFunction(
this: JSObject,
_ arg0: some ConvertibleToJSValue,
_ arg1: some ConvertibleToJSValue
Expand All @@ -201,7 +143,7 @@ extension JSFunction {
}

@discardableResult
public func callAsFunction(
override public func callAsFunction(
this: JSObject,
_ arg0: some ConvertibleToJSValue,
_ arg1: some ConvertibleToJSValue,
Expand All @@ -211,7 +153,7 @@ extension JSFunction {
}

@discardableResult
public func callAsFunction(
override public func callAsFunction(
this: JSObject,
_ arg0: some ConvertibleToJSValue,
_ arg1: some ConvertibleToJSValue,
Expand All @@ -223,7 +165,7 @@ extension JSFunction {
}

@discardableResult
public func callAsFunction(
override public func callAsFunction(
this: JSObject,
_ arg0: some ConvertibleToJSValue,
_ arg1: some ConvertibleToJSValue,
Expand All @@ -238,7 +180,7 @@ extension JSFunction {
}

@discardableResult
public func callAsFunction(
override public func callAsFunction(
this: JSObject,
_ arg0: some ConvertibleToJSValue,
_ arg1: some ConvertibleToJSValue,
Expand All @@ -254,7 +196,7 @@ extension JSFunction {
}

@discardableResult
public func callAsFunction(
override public func callAsFunction(
this: JSObject,
_ arg0: some ConvertibleToJSValue,
_ arg1: some ConvertibleToJSValue,
Expand All @@ -273,30 +215,30 @@ extension JSFunction {
}

@discardableResult
public func callAsFunction(this: JSObject, arguments: [JSValue]) -> JSValue {
override public func callAsFunction(this: JSObject, arguments: [JSValue]) -> JSValue {
invokeNonThrowingJSFunction(arguments: arguments, this: this).jsValue
}

@discardableResult
public func callAsFunction() -> JSValue {
override public func callAsFunction() -> JSValue {
invokeNonThrowingJSFunction(arguments: []).jsValue
}

@discardableResult
public func callAsFunction(_ arg0: some ConvertibleToJSValue) -> JSValue {
override public func callAsFunction(_ arg0: some ConvertibleToJSValue) -> JSValue {
invokeNonThrowingJSFunction(arguments: [arg0.jsValue]).jsValue
}

@discardableResult
public func callAsFunction(
override public func callAsFunction(
_ arg0: some ConvertibleToJSValue,
_ arg1: some ConvertibleToJSValue
) -> JSValue {
invokeNonThrowingJSFunction(arguments: [arg0.jsValue, arg1.jsValue]).jsValue
}

@discardableResult
public func callAsFunction(
override public func callAsFunction(
_ arg0: some ConvertibleToJSValue,
_ arg1: some ConvertibleToJSValue,
_ arg2: some ConvertibleToJSValue
Expand All @@ -305,7 +247,7 @@ extension JSFunction {
}

@discardableResult
public func callAsFunction(
override public func callAsFunction(
_ arg0: some ConvertibleToJSValue,
_ arg1: some ConvertibleToJSValue,
_ arg2: some ConvertibleToJSValue,
Expand All @@ -315,7 +257,7 @@ extension JSFunction {
}

@discardableResult
public func callAsFunction(
override public func callAsFunction(
_ arg0: some ConvertibleToJSValue,
_ arg1: some ConvertibleToJSValue,
_ arg2: some ConvertibleToJSValue,
Expand All @@ -327,7 +269,7 @@ extension JSFunction {
}

@discardableResult
public func callAsFunction(
override public func callAsFunction(
_ arg0: some ConvertibleToJSValue,
_ arg1: some ConvertibleToJSValue,
_ arg2: some ConvertibleToJSValue,
Expand All @@ -341,7 +283,7 @@ extension JSFunction {
}

@discardableResult
public func callAsFunction(
override public func callAsFunction(
_ arg0: some ConvertibleToJSValue,
_ arg1: some ConvertibleToJSValue,
_ arg2: some ConvertibleToJSValue,
Expand All @@ -355,30 +297,30 @@ extension JSFunction {
]).jsValue
}

public func new() -> JSObject {
override public func new() -> JSObject {
new(arguments: [])
}

public func new(_ arg0: some ConvertibleToJSValue) -> JSObject {
override public func new(_ arg0: some ConvertibleToJSValue) -> JSObject {
new(arguments: [arg0.jsValue])
}

public func new(
override public func new(
_ arg0: some ConvertibleToJSValue,
_ arg1: some ConvertibleToJSValue
) -> JSObject {
new(arguments: [arg0.jsValue, arg1.jsValue])
}

public func new(
override public func new(
_ arg0: some ConvertibleToJSValue,
_ arg1: some ConvertibleToJSValue,
_ arg2: some ConvertibleToJSValue
) -> JSObject {
new(arguments: [arg0.jsValue, arg1.jsValue, arg2.jsValue])
}

public func new(
override public func new(
_ arg0: some ConvertibleToJSValue,
_ arg1: some ConvertibleToJSValue,
_ arg2: some ConvertibleToJSValue,
Expand All @@ -387,7 +329,7 @@ extension JSFunction {
new(arguments: [arg0.jsValue, arg1.jsValue, arg2.jsValue, arg3.jsValue])
}

public func new(
override public func new(
_ arg0: some ConvertibleToJSValue,
_ arg1: some ConvertibleToJSValue,
_ arg2: some ConvertibleToJSValue,
Expand All @@ -397,7 +339,7 @@ extension JSFunction {
new(arguments: [arg0.jsValue, arg1.jsValue, arg2.jsValue, arg3.jsValue, arg4.jsValue])
}

public func new(
override public func new(
_ arg0: some ConvertibleToJSValue,
_ arg1: some ConvertibleToJSValue,
_ arg2: some ConvertibleToJSValue,
Expand All @@ -408,7 +350,7 @@ extension JSFunction {
new(arguments: [arg0.jsValue, arg1.jsValue, arg2.jsValue, arg3.jsValue, arg4.jsValue, arg5.jsValue])
}

public func new(
override public func new(
_ arg0: some ConvertibleToJSValue,
_ arg1: some ConvertibleToJSValue,
_ arg2: some ConvertibleToJSValue,
Expand Down
Loading
Loading