Skip to content

Commit fc991c2

Browse files
mjburghardj-f1
authored andcommitted
Changes related to WebIDL support.
1 parent 0311620 commit fc991c2

File tree

6 files changed

+267
-36
lines changed

6 files changed

+267
-36
lines changed

IntegrationTests/TestSuites/Sources/PrimaryTests/main.swift

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -281,26 +281,26 @@ Call_Function_With_This: do {
281281
}
282282

283283
Object_Conversion: do {
284-
let array1 = [1, 2, 3]
285-
let jsArray1 = array1.jsValue().object!
286-
try expectEqual(jsArray1.length, .number(3))
287-
try expectEqual(jsArray1[0], .number(1))
288-
try expectEqual(jsArray1[1], .number(2))
289-
try expectEqual(jsArray1[2], .number(3))
290-
291-
let array2: [JSValueConvertible] = [1, "str", false]
284+
let array1 = [1, 2, 3]
285+
let jsArray1 = array1.jsValue().object!
286+
try expectEqual(jsArray1.length, .number(3))
287+
try expectEqual(jsArray1[0], .number(1))
288+
try expectEqual(jsArray1[1], .number(2))
289+
try expectEqual(jsArray1[2], .number(3))
290+
291+
let array2: [JSValueCodable] = [1, "str", false]
292292
let jsArray2 = array2.jsValue().object!
293293
try expectEqual(jsArray2.length, .number(3))
294294
try expectEqual(jsArray2[0], .number(1))
295295
try expectEqual(jsArray2[1], .string("str"))
296296
try expectEqual(jsArray2[2], .boolean(false))
297297
_ = jsArray2.push!(5)
298298
try expectEqual(jsArray2.length, .number(4))
299-
_ = jsArray2.push!(jsArray1)
299+
_ = jsArray2.push!(jsArray1)
300300

301-
try expectEqual(jsArray2[4], .object(jsArray1))
301+
try expectEqual(jsArray2[4], .object(jsArray1))
302302

303-
let dict1: [String: JSValueConvertible] = [
303+
let dict1: [String: JSValueCodable] = [
304304
"prop1": 1,
305305
"prop2": "foo",
306306
]

Sources/JavaScriptKit/JSFunction.swift

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -43,10 +43,7 @@ public class JSFunctionRef: JSObjectRef {
4343
let argv = bufferPointer.baseAddress
4444
let argc = bufferPointer.count
4545
var resultObj = JavaScriptObjectRef()
46-
_call_new(
47-
self.id, argv, Int32(argc),
48-
&resultObj
49-
)
46+
_call_new(self.id, argv, Int32(argc), &resultObj)
5047
return JSObjectRef(id: resultObj)
5148
}
5249
}
@@ -57,6 +54,10 @@ public class JSFunctionRef: JSObjectRef {
5754
fatalError("unavailable")
5855
}
5956

57+
public override class func construct(from value: JSValue) -> Self? {
58+
return value.function as? Self
59+
}
60+
6061
override public func jsValue() -> JSValue {
6162
.function(self)
6263
}
@@ -89,6 +90,15 @@ public class JSClosure: JSFunctionRef {
8990
}
9091
}
9192

93+
public required convenience init(jsValue: JSValue) {
94+
switch jsValue {
95+
case let .function(fun):
96+
self.init { fun(arguments: $0) }
97+
default:
98+
fatalError()
99+
}
100+
}
101+
92102
public func release() {
93103
Self.sharedFunctions[hostFuncRef] = nil
94104
isReleased = true

Sources/JavaScriptKit/JSObject.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,10 @@ public class JSObjectRef: Equatable {
4343
return lhs.id == rhs.id
4444
}
4545

46+
public class func construct(from value: JSValue) -> Self? {
47+
return value.object as? Self
48+
}
49+
4650
public func jsValue() -> JSValue {
4751
.object(self)
4852
}

Sources/JavaScriptKit/JSValue.swift

Lines changed: 61 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,14 +41,51 @@ public enum JSValue: Equatable {
4141
object.flatMap { JSArrayRef($0) }
4242
}
4343

44-
public var isNull: Bool { return self == .null }
45-
public var isUndefined: Bool { return self == .undefined }
4644
public var function: JSFunctionRef? {
4745
switch self {
4846
case let .function(function): return function
4947
default: return nil
5048
}
5149
}
50+
51+
public var isBoolean: Bool {
52+
guard case .boolean = self else { return false }
53+
return true
54+
}
55+
56+
public var isString: Bool {
57+
guard case .string = self else { return false }
58+
return true
59+
}
60+
61+
public var isNumber: Bool {
62+
guard case .number = self else { return false }
63+
return true
64+
}
65+
66+
public var isObject: Bool {
67+
guard case .object = self else { return false }
68+
return true
69+
}
70+
71+
public var isNull: Bool {
72+
return self == .null
73+
}
74+
75+
public var isUndefined: Bool {
76+
return self == .undefined
77+
}
78+
79+
public var isFunction: Bool {
80+
guard case .function = self else { return false }
81+
return true
82+
}
83+
}
84+
85+
extension JSValue {
86+
public func fromJSValue<Type>() -> Type? where Type: JSValueConstructible {
87+
return Type.construct(from: self)
88+
}
5289
}
5390

5491
extension JSValue {
@@ -64,7 +101,13 @@ extension JSValue: ExpressibleByStringLiteral {
64101
}
65102

66103
extension JSValue: ExpressibleByIntegerLiteral {
67-
public init(integerLiteral value: Double) {
104+
public init(integerLiteral value: Int32) {
105+
self = .number(Double(value))
106+
}
107+
}
108+
109+
extension JSValue: ExpressibleByFloatLiteral {
110+
public init(floatLiteral value: Double) {
68111
self = .number(value)
69112
}
70113
}
@@ -98,3 +141,18 @@ public func setJSValue(this: JSObjectRef, index: Int32, value: JSValue) {
98141
rawValue.payload1, rawValue.payload2, rawValue.payload3)
99142
}
100143
}
144+
145+
extension JSValue {
146+
public func isInstanceOf(_ constructor: JSFunctionRef) -> Bool {
147+
switch self {
148+
case .boolean, .string, .number:
149+
return false
150+
case let .object(ref):
151+
return ref.isInstanceOf(constructor)
152+
case let .function(ref):
153+
return ref.isInstanceOf(constructor)
154+
case .null, .undefined:
155+
fatalError()
156+
}
157+
}
158+
}

Sources/JavaScriptKit/JSValueConvertible.swift

Lines changed: 120 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,47 @@
11
import _CJavaScriptKit
22

3+
public protocol JSBridgedType: JSValueCodable, CustomStringConvertible {
4+
static var constructor: JSFunctionRef? { get }
5+
6+
var objectRef: JSObjectRef { get }
7+
init(objectRef: JSObjectRef)
8+
}
9+
10+
extension JSBridgedType {
11+
public var description: String {
12+
return objectRef.toString!().fromJSValue()!
13+
}
14+
}
15+
316
public protocol JSValueConvertible {
417
func jsValue() -> JSValue
518
}
619

7-
extension JSValue: JSValueConvertible {
20+
public typealias JSValueCodable = JSValueConvertible & JSValueConstructible
21+
22+
extension JSBridgedType {
23+
public static func canDecode(from jsValue: JSValue) -> Bool {
24+
if let constructor = Self.constructor {
25+
return jsValue.isInstanceOf(constructor)
26+
} else {
27+
return jsValue.isObject
28+
}
29+
}
30+
31+
public init(jsValue: JSValue) {
32+
self.init(objectRef: jsValue.object!)
33+
}
34+
35+
public func jsValue() -> JSValue {
36+
return JSValue.object(objectRef)
37+
}
38+
}
39+
40+
extension JSValue: JSValueCodable {
41+
public static func construct(from value: JSValue) -> Self? {
42+
return value
43+
}
44+
845
public func jsValue() -> JSValue { self }
946
}
1047

@@ -16,48 +53,56 @@ extension Int: JSValueConvertible {
1653
public func jsValue() -> JSValue { .number(Double(self)) }
1754
}
1855

19-
extension Int8: JSValueConvertible {
56+
extension Double: JSValueConvertible {
57+
public func jsValue() -> JSValue { .number(self) }
58+
}
59+
60+
extension String: JSValueConvertible {
61+
public func jsValue() -> JSValue { .string(self) }
62+
}
63+
64+
extension UInt8: JSValueConvertible {
2065
public func jsValue() -> JSValue { .number(Double(self)) }
2166
}
2267

23-
extension Int16: JSValueConvertible {
68+
extension UInt16: JSValueConvertible {
2469
public func jsValue() -> JSValue { .number(Double(self)) }
2570
}
2671

27-
extension Int32: JSValueConvertible {
72+
extension UInt32: JSValueConvertible {
2873
public func jsValue() -> JSValue { .number(Double(self)) }
2974
}
3075

31-
extension UInt: JSValueConvertible {
76+
extension UInt64: JSValueConvertible {
3277
public func jsValue() -> JSValue { .number(Double(self)) }
3378
}
3479

35-
extension UInt8: JSValueConvertible {
80+
extension Int8: JSValueConvertible {
3681
public func jsValue() -> JSValue { .number(Double(self)) }
3782
}
3883

39-
extension UInt16: JSValueConvertible {
84+
extension Int16: JSValueConvertible {
4085
public func jsValue() -> JSValue { .number(Double(self)) }
4186
}
4287

43-
extension Float: JSValueConvertible {
88+
extension Int32: JSValueConvertible {
4489
public func jsValue() -> JSValue { .number(Double(self)) }
4590
}
4691

47-
extension Double: JSValueConvertible {
48-
public func jsValue() -> JSValue { .number(self) }
92+
extension Int64: JSValueConvertible {
93+
public func jsValue() -> JSValue { .number(Double(self)) }
4994
}
5095

51-
extension String: JSValueConvertible {
52-
public func jsValue() -> JSValue { .string(self) }
96+
extension Float: JSValueConvertible {
97+
public func jsValue() -> JSValue { .number(Double(self)) }
5398
}
5499

55-
extension JSObjectRef: JSValueConvertible {
100+
extension JSObjectRef: JSValueCodable {
56101
// `JSObjectRef.jsValue` is defined in JSObjectRef.swift to be able to overridden
57102
// from `JSFunctionRef`
58103
}
59104

60-
private let Object = JSObjectRef.global.Object.function!
105+
private let JSObject = JSObjectRef.global.Object.function!
61106

62107
extension Dictionary where Value: JSValueConvertible, Key == String {
63108
public func jsValue() -> JSValue {
@@ -67,15 +112,53 @@ extension Dictionary where Value: JSValueConvertible, Key == String {
67112

68113
extension Dictionary: JSValueConvertible where Value == JSValueConvertible, Key == String {
69114
public func jsValue() -> JSValue {
70-
let object = Object.new()
115+
let object = JSObject.new()
71116
for (key, value) in self {
72117
object[key] = value.jsValue()
73118
}
74119
return .object(object)
75120
}
76121
}
77122

78-
private let Array = JSObjectRef.global.Array.function!
123+
extension Dictionary: JSValueConstructible where Value: JSValueConstructible, Key == String {
124+
public static func construct(from value: JSValue) -> Self? {
125+
if let objectRef = value.object,
126+
let keys: [String] = JSObject.keys!(objectRef.jsValue()).fromJSValue() {
127+
var entries = [(String, Value)]()
128+
entries.reserveCapacity(keys.count)
129+
for key in keys {
130+
guard let value: Value = objectRef[key].fromJSValue() else {
131+
return nil
132+
}
133+
entries.append((key, value))
134+
}
135+
return Dictionary(uniqueKeysWithValues: entries)
136+
}
137+
return nil
138+
}
139+
}
140+
141+
extension Optional: JSValueConstructible where Wrapped: JSValueConstructible {
142+
public static func construct(from value: JSValue) -> Self? {
143+
switch value {
144+
case .null, .undefined:
145+
return nil
146+
default:
147+
return Wrapped.construct(from: value)
148+
}
149+
}
150+
}
151+
152+
extension Optional: JSValueConvertible where Wrapped: JSValueConvertible {
153+
public func jsValue() -> JSValue {
154+
switch self {
155+
case .none: return .null
156+
case let .some(wrapped): return wrapped.jsValue()
157+
}
158+
}
159+
}
160+
161+
private let JSArray = JSObjectRef.global.Array.function!
79162

80163
extension Array where Element: JSValueConvertible {
81164
public func jsValue() -> JSValue {
@@ -85,14 +168,33 @@ extension Array where Element: JSValueConvertible {
85168

86169
extension Array: JSValueConvertible where Element == JSValueConvertible {
87170
public func jsValue() -> JSValue {
88-
let array = Array.new(count)
171+
let array = JSArray.new(count)
89172
for (index, element) in enumerated() {
90173
array[index] = element.jsValue()
91174
}
92175
return .object(array)
93176
}
94177
}
95178

179+
extension Array: JSValueConstructible where Element: JSValueConstructible {
180+
public static func construct(from value: JSValue) -> [Element]? {
181+
if let objectRef = value.object,
182+
objectRef.isInstanceOf(JSObjectRef.global.Array.function!) {
183+
let count: Int = objectRef.length.fromJSValue()!
184+
var array = [Element]()
185+
array.reserveCapacity(count)
186+
187+
for i in 0 ..< count {
188+
guard let value: Element = objectRef[i].fromJSValue() else { return nil }
189+
array.append(value)
190+
}
191+
192+
return array
193+
}
194+
return nil
195+
}
196+
}
197+
96198
extension RawJSValue: JSValueConvertible {
97199
public func jsValue() -> JSValue {
98200
switch kind {
@@ -188,6 +290,6 @@ extension Array where Element == JSValueConvertible {
188290

189291
extension Array where Element: JSValueConvertible {
190292
func withRawJSValues<T>(_ body: ([RawJSValue]) -> T) -> T {
191-
Swift.Array<JSValueConvertible>.withRawJSValues(self)(body)
293+
Array<JSValueConvertible>.withRawJSValues(self)(body)
192294
}
193295
}

0 commit comments

Comments
 (0)