Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 702dd89

Browse files
authored
Merge pull request #26 from j-f1/webidl
Add JSBridgedType and JSBridgedClass
2 parents 8cdc2d1 + 767d05d commit 702dd89

File tree

10 files changed

+266
-86
lines changed

10 files changed

+266
-86
lines changed

‎Sources/JavaScriptKit/BasicObjects/JSArray.swift‎

Lines changed: 28 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,54 +1,63 @@
11
/// A wrapper around [the JavaScript Array class](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array)
22
/// that exposes its properties in a type-safe and Swifty way.
3-
public class JSArray {
4-
static let classObject = JSObject.global.Array.function!
3+
public class JSArray:JSBridgedClass {
4+
publicstatic let constructor = JSObject.global.Array.function!
55

66
static func isArray(_ object: JSObject) -> Bool {
7-
classObject.isArray!(object).boolean!
7+
constructor.isArray!(object).boolean!
8+
}
9+
10+
public let jsObject: JSObject
11+
12+
public required convenience init?(from value: JSValue) {
13+
guard let object = value.object else { return nil }
14+
self.init(object)
815
}
916

10-
let ref: JSObject
11-
1217
/// Construct a `JSArray` from Array `JSObject`.
1318
/// Return `nil` if the object is not an Array.
1419
///
1520
/// - Parameter object: A `JSObject` expected to be a JavaScript Array
16-
public init?(_ ref: JSObject) {
17-
guard Self.isArray(ref) else { return nil }
18-
self.ref = ref
21+
public convenience init?(_ jsObject: JSObject) {
22+
guard Self.isArray(jsObject) else { return nil }
23+
self.init(unsafelyWrapping: jsObject)
24+
}
25+
26+
public required init(unsafelyWrapping jsObject: JSObject) {
27+
self.jsObject = jsObject
1928
}
2029
}
2130

2231
extension JSArray: RandomAccessCollection {
2332
public typealias Element = JSValue
2433

2534
public func makeIterator() -> Iterator {
26-
Iterator(ref: ref)
35+
Iterator(jsObject: jsObject)
2736
}
2837

2938
public class Iterator: IteratorProtocol {
30-
let ref: JSObject
31-
var index = 0
32-
init(ref: JSObject) {
33-
self.ref = ref
39+
privatelet jsObject: JSObject
40+
privatevar index = 0
41+
init(jsObject: JSObject) {
42+
self.jsObject = jsObject
3443
}
3544

3645
public func next() -> Element? {
3746
let currentIndex = index
38-
guard currentIndex < Int(ref.length.number!) else {
47+
guard currentIndex < Int(jsObject.length.number!) else {
3948
return nil
4049
}
4150
index += 1
42-
guard ref.hasOwnProperty!(currentIndex).boolean! else {
51+
guard jsObject.hasOwnProperty!(currentIndex).boolean! else {
4352
return next()
4453
}
45-
let value = ref[currentIndex]
54+
let value = jsObject[currentIndex]
4655
return value
4756
}
4857
}
4958

5059
public subscript(position: Int) -> JSValue {
51-
ref[position]
60+
jsObject[position]
5261
}
5362

5463
public var startIndex: Int { 0 }
@@ -68,14 +77,14 @@ extension JSArray: RandomAccessCollection {
6877
/// array.count // 2
6978
/// ```
7079
public var length: Int {
71-
returnInt(ref.length.number!)
80+
Int(jsObject.length.number!)
7281
}
7382

7483
/// The number of elements in that array **not** including empty hole.
7584
/// Note that `count` syncs with the number that `Iterator` can iterate.
7685
/// See also: `JSArray.length`
7786
public var count: Int {
78-
returngetObjectValuesLength(ref)
87+
getObjectValuesLength(jsObject)
7988
}
8089
}
8190

‎Sources/JavaScriptKit/BasicObjects/JSDate.swift‎

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@ in the naming. Parts of the JavaScript `Date` API that are not consistent across
66
implementations are not exposed in a type-safe manner, you should access the underlying `jsObject`
77
property if you need those.
88
*/
9-
public final class JSDate {
9+
public final class JSDate:JSBridgedClass {
1010
/// The constructor function used to create new `Date` objects.
11-
private static let constructor = JSObject.global.Date.function!
11+
public static let constructor = JSObject.global.Date.function!
1212

1313
/// The underlying JavaScript `Date` object.
1414
public let jsObject: JSObject
@@ -39,6 +39,10 @@ public final class JSDate {
3939
jsObject = Self.constructor.new(year, monthIndex, day, hours, minutes, seconds, milliseconds)
4040
}
4141

42+
public init(unsafelyWrapping jsObject: JSObject) {
43+
self.jsObject = jsObject
44+
}
45+
4246
/// Year of this date in local time zone.
4347
public var fullYear: Int {
4448
get {

‎Sources/JavaScriptKit/BasicObjects/JSError.swift‎

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@
22
class](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error) that
33
exposes its properties in a type-safe way.
44
*/
5-
public final class JSError: Error {
5+
public final class JSError: Error,JSBridgedClass {
66
/// The constructor function used to create new `Error` objects.
7-
private static let constructor = JSObject.global.Error.function!
7+
public static let constructor = JSObject.global.Error.function!
88

99
/// The underlying JavaScript `Error` object.
1010
public let jsObject: JSObject
@@ -14,6 +14,10 @@ public final class JSError: Error {
1414
jsObject = Self.constructor.new([message])
1515
}
1616

17+
public init(unsafelyWrapping jsObject: JSObject) {
18+
self.jsObject = jsObject
19+
}
20+
1721
/// The error message of the underlying `Error` object.
1822
public var message: String {
1923
jsObject.message.string!

‎Sources/JavaScriptKit/BasicObjects/JSTypedArray.swift‎

Lines changed: 17 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -4,53 +4,42 @@
44

55
import _CJavaScriptKit
66

7+
/// A protocol that allows a Swift numeric type to be mapped to the JavaScript TypedArray that holds integers of its type
78
public protocol TypedArrayElement: JSValueConvertible, JSValueConstructible {
9+
/// The constructor function for the TypedArray class for this particular kind of number
810
static var typedArrayClass: JSFunction { get }
911
}
1012

11-
/// A wrapper around [the JavaScript TypedArray class](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/TypedArray)
12-
/// that exposes its properties in a type-safe and Swifty way.
13-
public class JSTypedArray<Element>: JSValueConvertible, ExpressibleByArrayLiteral where Element: TypedArrayElement {
14-
let ref: JSObject
15-
public func jsValue() -> JSValue {
16-
.object(ref)
17-
}
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)
15+
public class JSTypedArray<Element>: JSBridgedClass, ExpressibleByArrayLiteral where Element: TypedArrayElement {
16+
public static var constructor: JSFunction { Element.typedArrayClass }
17+
public var jsObject: JSObject
1818

1919
public subscript(_ index: Int) -> Element {
2020
get {
21-
return Element.construct(from: getJSValue(this: ref,index:Int32(index)))!
21+
return Element.construct(from: jsObject[index])!
2222
}
2323
set {
24-
setJSValue(this: ref,index:Int32(index), value:newValue.jsValue())
24+
self.jsObject[index]=newValue.jsValue()
2525
}
2626
}
2727

28-
// This private initializer assumes that the passed object is TypedArray
29-
private init(unsafe object: JSObject) {
30-
self.ref = object
31-
}
32-
33-
/// Construct a `JSTypedArray` from TypedArray `JSObject`.
34-
/// Return `nil` if the object is not TypedArray.
28+
/// Initialize a new instance of TypedArray in JavaScript environment with given length.
29+
/// All the elements will be initialized to zero.
3530
///
36-
/// - Parameter object: A `JSObject` expected to be TypedArray
37-
public init?(_ object: JSObject) {
38-
guard object.isInstanceOf(Element.typedArrayClass) else { return nil }
39-
self.ref = object
31+
/// - Parameter length: The number of elements that will be allocated.
32+
public init(length: Int) {
33+
jsObject = Element.typedArrayClass.new(length)
4034
}
4135

42-
/// Initialize a new instance of TypedArray in JavaScript environment with given length zero value.
43-
///
44-
/// - Parameter length: The length of elements that will be allocated.
45-
public convenience init(length: Int) {
46-
let jsObject = Element.typedArrayClass.new(length)
47-
self.init(unsafe: jsObject)
36+
required public init(unsafelyWrapping jsObject: JSObject) {
37+
self.jsObject = jsObject
4838
}
4939

5040
required public convenience init(arrayLiteral elements: Element...) {
5141
self.init(elements)
5242
}
53-
5443
/// Initialize a new instance of TypedArray in JavaScript environment with given elements.
5544
///
5645
/// - Parameter array: The array that will be copied to create a new instance of TypedArray
@@ -59,7 +48,7 @@ public class JSTypedArray<Element>: JSValueConvertible, ExpressibleByArrayLitera
5948
array.withUnsafeBufferPointer { ptr in
6049
_create_typed_array(Element.typedArrayClass.id, ptr.baseAddress!, Int32(array.count), &resultObj)
6150
}
62-
self.init(unsafe: JSObject(id: resultObj))
51+
self.init(unsafelyWrapping: JSObject(id: resultObj))
6352
}
6453

6554
/// Convenience initializer for `Sequence`.
@@ -90,8 +79,6 @@ extension UInt: TypedArrayElement {
9079
valueForBitWidth(typeName: "UInt", bitWidth: Int.bitWidth, when32: JSObject.global.Uint32Array).function!
9180
}
9281

93-
// MARK: - Concrete TypedArray classes
94-
9582
extension Int8: TypedArrayElement {
9683
public static var typedArrayClass = JSObject.global.Int8Array.function!
9784
}

‎Sources/JavaScriptKit/FundamentalObjects/JSFunction.swift‎

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -62,10 +62,7 @@ public class JSFunction: JSObject {
6262
let argv = bufferPointer.baseAddress
6363
let argc = bufferPointer.count
6464
var resultObj = JavaScriptObjectRef()
65-
_call_new(
66-
self.id, argv, Int32(argc),
67-
&resultObj
68-
)
65+
_call_new(self.id, argv, Int32(argc), &resultObj)
6966
return JSObject(id: resultObj)
7067
}
7168
}
@@ -81,6 +78,10 @@ public class JSFunction: JSObject {
8178
fatalError("unavailable")
8279
}
8380

81+
public override class func construct(from value: JSValue) -> Self? {
82+
return value.function as? Self
83+
}
84+
8485
override public func jsValue() -> JSValue {
8586
.function(self)
8687
}

‎Sources/JavaScriptKit/FundamentalObjects/JSObject.swift‎

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,13 +32,20 @@ public class JSObject: Equatable {
3232
/// - Parameter name: The name of this object's member to access.
3333
/// - Returns: The `name` member method binding this object as `this` context.
3434
@_disfavoredOverload
35-
public subscript(dynamicMember name: String) -> ((JSValueConvertible...) -> JSValue)? {
35+
public subscript(_ name: String) -> ((JSValueConvertible...) -> JSValue)? {
3636
guard let function = self[name].function else { return nil }
3737
return { (arguments: JSValueConvertible...) in
3838
function(this: self, arguments: arguments)
3939
}
4040
}
4141

42+
/// A convenience method of `subscript(_ name: String) -> ((JSValueConvertible...) -> JSValue)?`
43+
/// to access the member through Dynamic Member Lookup.
44+
@_disfavoredOverload
45+
public subscript(dynamicMember name: String) -> ((JSValueConvertible...) -> JSValue)? {
46+
self[name]
47+
}
48+
4249
/// A convenience method of `subscript(_ name: String) -> JSValue`
4350
/// to access the member through Dynamic Member Lookup.
4451
public subscript(dynamicMember name: String) -> JSValue {
@@ -62,9 +69,9 @@ public class JSObject: Equatable {
6269
set { setJSValue(this: self, index: Int32(index), value: newValue) }
6370
}
6471

65-
/// Return `true` if this object is an instance of the `constructor`. Return `false`, if not.
72+
/// Return `true` if this value is an instance of the passed `constructor` function.
6673
/// - Parameter constructor: The constructor function to check.
67-
/// - Returns: The result of `instanceof` in JavaScript environment.
74+
/// - Returns: The result of `instanceof` in the JavaScript environment.
6875
public func isInstanceOf(_ constructor: JSFunction) -> Bool {
6976
_instanceof(id, constructor.id)
7077
}
@@ -86,6 +93,10 @@ public class JSObject: Equatable {
8693
return lhs.id == rhs.id
8794
}
8895

96+
public class func construct(from value: JSValue) -> Self? {
97+
return value.object as? Self
98+
}
99+
89100
public func jsValue() -> JSValue {
90101
.object(self)
91102
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
/// Use this protocol when your type has no single JavaScript class.
2+
/// For example, a union type of multiple classes or primitive values.
3+
public protocol JSBridgedType: JSValueCodable, CustomStringConvertible {
4+
/// This is the value your class wraps.
5+
var value: JSValue { get }
6+
7+
/// If your class is incompatible with the provided value, return `nil`.
8+
init?(from value: JSValue)
9+
}
10+
11+
extension JSBridgedType {
12+
public static func construct(from value: JSValue) -> Self? {
13+
return Self.init(from: value)
14+
}
15+
16+
public func jsValue() -> JSValue { value }
17+
18+
public var description: String { value.description }
19+
}
20+
21+
/// Conform to this protocol when your Swift class wraps a JavaScript class.
22+
public protocol JSBridgedClass: JSBridgedType {
23+
/// The constructor function for the JavaScript class
24+
static var constructor: JSFunction { get }
25+
26+
/// The JavaScript object wrapped by this instance.
27+
/// You may assume that `jsObject instanceof Self.constructor == true`
28+
var jsObject: JSObject { get }
29+
30+
/// Create an instannce wrapping the given JavaScript object.
31+
/// You may assume that `jsObject instanceof Self.constructor`
32+
init(unsafelyWrapping jsObject: JSObject)
33+
}
34+
35+
extension JSBridgedClass {
36+
public var value: JSValue { jsObject.jsValue() }
37+
public init?(from value: JSValue) {
38+
guard let object = value.object, object.isInstanceOf(Self.constructor) else { return nil }
39+
self.init(unsafelyWrapping: object)
40+
}
41+
}

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /