Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit d0da61a

Browse files
committed
Merge branch 'master' into webidl
2 parents cabda58 + 6652885 commit d0da61a

File tree

12 files changed

+209
-98
lines changed

12 files changed

+209
-98
lines changed

[email protected]

-4
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,5 @@ let package = Package(
3737
),
3838
]
3939
),
40-
.testTarget(
41-
name: "JavaScriptKitTests",
42-
dependencies: ["JavaScriptKit"]
43-
),
4440
]
4541
)

Runtime/src/index.ts

+3-16
Original file line numberDiff line numberDiff line change
@@ -42,19 +42,6 @@ enum JavaScriptValueKind {
4242
Function = 6,
4343
}
4444

45-
enum JavaScriptTypedArrayKind {
46-
Int8 = 0,
47-
Uint8 = 1,
48-
Int16 = 2,
49-
Uint16 = 3,
50-
Int32 = 4,
51-
Uint32 = 5,
52-
BigInt64 = 6,
53-
BigUint64 = 7,
54-
Float32 = 8,
55-
Float64 = 9,
56-
}
57-
5845
type TypedArray =
5946
| Int8ArrayConstructor
6047
| Uint8ArrayConstructor
@@ -130,7 +117,7 @@ class SwiftRuntimeHeap {
130117
export class SwiftRuntime {
131118
private instance: WebAssembly.Instance | null;
132119
private heap: SwiftRuntimeHeap
133-
private version: number = 600
120+
private version: number = 610
134121

135122
constructor() {
136123
this.instance = null;
@@ -405,11 +392,11 @@ export class SwiftRuntime {
405392
return obj instanceof constructor
406393
},
407394
swjs_create_typed_array: (
408-
kind: JavaScriptTypedArrayKind,
395+
constructor_ref: ref,
409396
elementsPtr: pointer, length: number,
410397
result_obj: pointer
411398
) => {
412-
const ArrayType: TypedArray = globalVariable[JavaScriptTypedArrayKind[kind] + 'Array']
399+
const ArrayType: TypedArray = this.heap.referenceHeap(constructor_ref);
413400
const array = new ArrayType(memory().buffer, elementsPtr, length);
414401
// Call `.slice()` to copy the memory
415402
writeUint32(result_obj, this.heap.retain(array.slice()));

Sources/JavaScriptKit/BasicObjects/JSArray.swift

+7
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
/// A wrapper around [the JavaScript Array class](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array)
2+
/// that exposes its properties in a type-safe and Swifty way.
13
public class JSArray: JSBridgedClass {
24
public static let constructor = JSObject.global.Array.function!
35

@@ -12,10 +14,15 @@ public class JSArray: JSBridgedClass {
1214
self.init(object)
1315
}
1416

17+
/// Construct a `JSArray` from Array `JSObject`.
18+
/// Return `nil` if the object is not an Array.
19+
///
20+
/// - Parameter object: A `JSObject` expected to be a JavaScript Array
1521
public convenience init?(_ jsObject: JSObject) {
1622
guard Self.isArray(jsObject) else { return nil }
1723
self.init(withCompatibleObject: jsObject)
1824
}
25+
1926
public required init(withCompatibleObject jsObject: JSObject) {
2027
self.jsObject = jsObject
2128
}

Sources/JavaScriptKit/BasicObjects/JSTypedArray.swift

+26-42
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,12 @@ import _CJavaScriptKit
66

77
/// A protocol that allows a Swift numeric type to be mapped to the JavaScript TypedArray that holds integers of its type
88
public protocol TypedArrayElement: JSValueConvertible, JSValueConstructible {
9-
/// The kind of typed array that should be created on the JS side
10-
static var typedArrayKind: JavaScriptTypedArrayKind { get }
119
/// The constructor function for the TypedArray class for this particular kind of number
1210
static var typedArrayClass: JSFunction { get }
1311
}
1412

15-
/// A wrapper around all JavaScript [`TypedArray`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray) classes that exposes their properties in a type-safe way.
13+
/// A wrapper around all JavaScript [TypedArray](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray) classes that exposes their properties in a type-safe way.
14+
/// FIXME: the BigInt-based TypedArrays are not supported (https://github.com/swiftwasm/JavaScriptKit/issues/56)
1615
public class JSTypedArray<Element>: JSBridgedClass, ExpressibleByArrayLiteral where Element: TypedArrayElement {
1716
public static var constructor: JSFunction { Element.typedArrayClass }
1817
public var jsObject: JSObject
@@ -26,7 +25,10 @@ public class JSTypedArray<Element>: JSBridgedClass, ExpressibleByArrayLiteral wh
2625
}
2726
}
2827

29-
/// Create a TypedArray with the provided number of elements allocated. All the elements will be initialized to zero.
28+
/// Initialize a new instance of TypedArray in JavaScript environment with given length.
29+
/// All the elements will be initialized to zero.
30+
///
31+
/// - Parameter length: The number of elements that will be allocated.
3032
public init(length: Int) {
3133
jsObject = Element.typedArrayClass.new(length)
3234
}
@@ -38,18 +40,20 @@ public class JSTypedArray<Element>: JSBridgedClass, ExpressibleByArrayLiteral wh
3840
required public convenience init(arrayLiteral elements: Element...) {
3941
self.init(elements)
4042
}
41-
42-
/// Convert an array of numbers into a JavaScript TypedArray
43+
/// Initialize a new instance of TypedArray in JavaScript environment with given elements.
44+
///
45+
/// - Parameter array: The array that will be copied to create a new instance of TypedArray
4346
public convenience init(_ array: [Element]) {
4447
var resultObj = JavaScriptObjectRef()
4548
array.withUnsafeBufferPointer { ptr in
46-
_create_typed_array(Element.typedArrayKind, ptr.baseAddress!, Int32(array.count), &resultObj)
49+
_create_typed_array(Element.typedArrayClass.id, ptr.baseAddress!, Int32(array.count), &resultObj)
4750
}
4851
self.init(withCompatibleObject: JSObject(id: resultObj))
4952
}
50-
51-
public convenience init(_ stride: StrideTo<Element>) where Element: Strideable {
52-
self.init(stride.map({ $0 }))
53+
54+
/// Convenience initializer for `Sequence`.
55+
public convenience init<S: Sequence>(_ sequence: S) {
56+
self.init(sequence.map({ $0 }))
5357
}
5458
}
5559

@@ -67,67 +71,47 @@ func valueForBitWidth<T>(typeName: String, bitWidth: Int, when32: T) -> T {
6771
}
6872

6973
extension Int: TypedArrayElement {
70-
public static var typedArrayClass: JSFunction {
74+
public static var typedArrayClass: JSFunction =
7175
valueForBitWidth(typeName: "Int", bitWidth: Int.bitWidth, when32: JSObject.global.Int32Array).function!
72-
}
73-
public static var typedArrayKind: JavaScriptTypedArrayKind {
74-
valueForBitWidth(typeName: "Int", bitWidth: Int.bitWidth, when32: .int32)
75-
}
7676
}
7777
extension UInt: TypedArrayElement {
78-
public static var typedArrayClass: JSFunction {
78+
public static var typedArrayClass: JSFunction =
7979
valueForBitWidth(typeName: "UInt", bitWidth: Int.bitWidth, when32: JSObject.global.Uint32Array).function!
80-
}
81-
public static var typedArrayKind: JavaScriptTypedArrayKind {
82-
valueForBitWidth(typeName: "UInt", bitWidth: UInt.bitWidth, when32: .uint32)
83-
}
8480
}
8581

86-
// MARK: - Concrete TypedArray classes
87-
8882
extension Int8: TypedArrayElement {
89-
public static var typedArrayClass: JSFunction { JSObject.global.Int8Array.function! }
90-
public static var typedArrayKind: JavaScriptTypedArrayKind { .int8 }
83+
public static var typedArrayClass = JSObject.global.Int8Array.function!
9184
}
9285
extension UInt8: TypedArrayElement {
93-
public static var typedArrayClass: JSFunction { JSObject.global.Uint8Array.function! }
94-
public static var typedArrayKind: JavaScriptTypedArrayKind { .uint8 }
86+
public static var typedArrayClass = JSObject.global.Uint8Array.function!
9587
}
9688
// TODO: Support Uint8ClampedArray?
9789

9890
extension Int16: TypedArrayElement {
99-
public static var typedArrayClass: JSFunction { JSObject.global.Int16Array.function! }
100-
public static var typedArrayKind: JavaScriptTypedArrayKind { .int16 }
91+
public static var typedArrayClass = JSObject.global.Int16Array.function!
10192
}
10293
extension UInt16: TypedArrayElement {
103-
public static var typedArrayClass: JSFunction { JSObject.global.Uint16Array.function! }
104-
public static var typedArrayKind: JavaScriptTypedArrayKind { .uint16 }
94+
public static var typedArrayClass = JSObject.global.Uint16Array.function!
10595
}
10696

10797
extension Int32: TypedArrayElement {
108-
public static var typedArrayClass: JSFunction { JSObject.global.Int32Array.function! }
109-
public static var typedArrayKind: JavaScriptTypedArrayKind { .int32 }
98+
public static var typedArrayClass = JSObject.global.Int32Array.function!
11099
}
111100
extension UInt32: TypedArrayElement {
112-
public static var typedArrayClass: JSFunction { JSObject.global.Uint32Array.function! }
113-
public static var typedArrayKind: JavaScriptTypedArrayKind { .uint32 }
101+
public static var typedArrayClass = JSObject.global.Uint32Array.function!
114102
}
115103

116104
// FIXME: Support passing BigInts across the bridge
117105
//extension Int64: TypedArrayElement {
118-
// public static var typedArrayClass: JSFunction { JSObject.global.BigInt64Array.function! }
119-
// public static var type: JavaScriptTypedArrayKind { .bigInt64 }
106+
// public static var typedArrayClass = JSObject.global.BigInt64Array.function!
120107
//}
121108
//extension UInt64: TypedArrayElement {
122-
// public static var typedArrayClass: JSFunction { JSObject.global.BigUint64Array.function! }
123-
// public static var type: JavaScriptTypedArrayKind { .bigUint64 }
109+
// public static var typedArrayClass = JSObject.global.BigUint64Array.function!
124110
//}
125111

126112
extension Float32: TypedArrayElement {
127-
public static var typedArrayClass: JSFunction { JSObject.global.Float32Array.function! }
128-
public static var typedArrayKind: JavaScriptTypedArrayKind { .float32 }
113+
public static var typedArrayClass = JSObject.global.Float32Array.function!
129114
}
130115
extension Float64: TypedArrayElement {
131-
public static var typedArrayClass: JSFunction { JSObject.global.Float64Array.function! }
132-
public static var typedArrayKind: JavaScriptTypedArrayKind { .float64 }
116+
public static var typedArrayClass = JSObject.global.Float64Array.function!
133117
}
+4-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1+
/// The compatibility runtime library version.
2+
/// Notes: If you change any interface of runtime library, please increment
3+
/// this and `SwiftRuntime.version` in `./Runtime/src/index.ts`.
14
@_cdecl("swjs_library_version")
25
func _library_version() -> Double {
3-
return 600
6+
return 610
47
}

Sources/JavaScriptKit/FundamentalObjects/JSFunction.swift

+62-12
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,22 @@
11
import _CJavaScriptKit
22

3+
/// `JSFunction` represents a function in JavaScript and supports new object instantiation.
4+
/// This type can be callable as a function using `callAsFunction`.
5+
///
6+
/// e.g.
7+
/// ```swift
8+
/// let alert: JSFunction = JSObject.global.alert.function!
9+
/// // Call `JSFunction` as a function
10+
/// alert("Hello, world")
11+
/// ```
12+
///
313
public class JSFunction: JSObject {
14+
15+
/// Call this function with given `arguments` and binding given `this` as context.
16+
/// - Parameters:
17+
/// - this: The value to be passed as the `this` parameter to this function.
18+
/// - arguments: Arguments to be passed to this function.
19+
/// - Returns: The result of this call.
420
@discardableResult
521
public func callAsFunction(this: JSObject? = nil, arguments: [JSValueConvertible]) -> JSValue {
622
let result = arguments.withRawJSValues { rawValues in
@@ -24,19 +40,22 @@ public class JSFunction: JSObject {
2440
return result.jsValue()
2541
}
2642

43+
/// A variadic arguments version of `callAsFunction`.
2744
@discardableResult
2845
public func callAsFunction(this: JSObject? = nil, _ arguments: JSValueConvertible...) -> JSValue {
2946
self(this: this, arguments: arguments)
3047
}
3148

32-
public func new(_ arguments: JSValueConvertible...) -> JSObject {
33-
new(arguments: arguments)
34-
}
35-
36-
// Guaranteed to return an object because either:
37-
// a) the constructor explicitly returns an object, or
38-
// b) the constructor returns nothing, which causes JS to return the `this` value, or
39-
// c) the constructor returns undefined, null or a non-object, in which case JS also returns `this`.
49+
/// Instantiate an object from this function as a constructor.
50+
///
51+
/// Guaranteed to return an object because either:
52+
///
53+
/// - a. the constructor explicitly returns an object, or
54+
/// - b. the constructor returns nothing, which causes JS to return the `this` value, or
55+
/// - c. the constructor returns undefined, null or a non-object, in which case JS also returns `this`.
56+
///
57+
/// - Parameter arguments: Arguments to be passed to this constructor function.
58+
/// - Returns: A new instance of this constructor.
4059
public func new(arguments: [JSValueConvertible]) -> JSObject {
4160
arguments.withRawJSValues { rawValues in
4261
rawValues.withUnsafeBufferPointer { bufferPointer in
@@ -49,6 +68,11 @@ public class JSFunction: JSObject {
4968
}
5069
}
5170

71+
/// A variadic arguments version of `new`.
72+
public func new(_ arguments: JSValueConvertible...) -> JSObject {
73+
new(arguments: arguments)
74+
}
75+
5276
@available(*, unavailable, message: "Please use JSClosure instead")
5377
public static func from(_: @escaping ([JSValue]) -> JSValue) -> JSFunction {
5478
fatalError("unavailable")
@@ -63,33 +87,59 @@ public class JSFunction: JSObject {
6387
}
6488
}
6589

90+
/// `JSClosure` represents a JavaScript function the body of which is written in Swift.
91+
/// This type can be passed as a callback handler to JavaScript functions.
92+
/// Note that the lifetime of `JSClosure` should be managed by users manually
93+
/// due to GC boundary between Swift and JavaScript.
94+
/// For further discussion, see also [swiftwasm/JavaScriptKit #33](https://github.com/swiftwasm/JavaScriptKit/pull/33)
95+
///
96+
/// e.g.
97+
/// ```swift
98+
/// let eventListenter = JSClosure { _ in
99+
/// ...
100+
/// return JSValue.undefined
101+
/// }
102+
///
103+
/// button.addEventListener!("click", JSValue.function(eventListenter))
104+
/// ...
105+
/// button.removeEventListener!("click", JSValue.function(eventListenter))
106+
/// eventListenter.release()
107+
/// ```
108+
///
66109
public class JSClosure: JSFunction {
67110
static var sharedFunctions: [JavaScriptHostFuncRef: ([JSValue]) -> JSValue] = [:]
68111

69112
private var hostFuncRef: JavaScriptHostFuncRef = 0
70113

71114
private var isReleased = false
72-
115+
116+
/// Instantiate a new `JSClosure` with given function body.
117+
/// - Parameter body: The body of this function.
73118
public init(_ body: @escaping ([JSValue]) -> JSValue) {
119+
// 1. Fill `id` as zero at first to access `self` to get `ObjectIdentifier`.
74120
super.init(id: 0)
75121
let objectId = ObjectIdentifier(self)
76122
let funcRef = JavaScriptHostFuncRef(bitPattern: Int32(objectId.hashValue))
123+
// 2. Retain the given body in static storage by `funcRef`.
77124
Self.sharedFunctions[funcRef] = body
78-
125+
// 3. Create a new JavaScript function which calls the given Swift function.
79126
var objectRef: JavaScriptObjectRef = 0
80127
_create_function(funcRef, &objectRef)
81128

82129
hostFuncRef = funcRef
83130
id = objectRef
84131
}
85-
132+
133+
/// A convenience initializer which assumes that the given body function returns `JSValue.undefined`
86134
convenience public init(_ body: @escaping ([JSValue]) -> ()) {
87135
self.init { (arguments: [JSValue]) -> JSValue in
88136
body(arguments)
89137
return .undefined
90138
}
91139
}
92-
140+
141+
/// Release this function resource.
142+
/// After calling `release`, calling this function from JavaScript will fail.
93143
public func release() {
94144
Self.sharedFunctions[hostFuncRef] = nil
95145
isReleased = true

0 commit comments

Comments
 (0)