Skip to content

Commit 06a828e

Browse files
Merge pull request swiftwasm#98 from swiftwasm/katei/jsvalue-convenience-methods
[Proposal] Add unsafe convenience methods for JSValue
2 parents 4b7981b + 8f6a572 commit 06a828e

File tree

3 files changed

+47
-0
lines changed

3 files changed

+47
-0
lines changed

IntegrationTests/TestSuites/Sources/PrimaryTests/main.swift

+21
Original file line numberDiff line numberDiff line change
@@ -268,14 +268,26 @@ try test("Call Function With This") {
268268
// ```
269269
let objectConstructor = try expectFunction(getJSValue(this: .global, name: "Animal"))
270270
let cat1 = objectConstructor.new("Tama", 3, true)
271+
let cat1Value = JSValue.object(cat1)
271272
let getIsCat = try expectFunction(getJSValue(this: cat1, name: "getIsCat"))
273+
let setName = try expectFunction(getJSValue(this: cat1, name: "setName"))
272274

273275
// Direct call without this
274276
try expectEqual(getIsCat(), .undefined)
275277

276278
// Call with this
277279
let gotIsCat = getIsCat(this: cat1)
278280
try expectEqual(gotIsCat, .boolean(true))
281+
try expectEqual(cat1.getIsCat!(), .boolean(true))
282+
try expectEqual(cat1Value.getIsCat(), .boolean(true))
283+
284+
// Call with this and argument
285+
setName(this: cat1, JSValue.string("Shiro"))
286+
try expectEqual(getJSValue(this: cat1, name: "name"), .string("Shiro"))
287+
_ = cat1.setName!("Tora")
288+
try expectEqual(getJSValue(this: cat1, name: "name"), .string("Tora"))
289+
_ = cat1Value.setName("Chibi")
290+
try expectEqual(getJSValue(this: cat1, name: "name"), .string("Chibi"))
279291
}
280292

281293
try test("Object Conversion") {
@@ -496,3 +508,12 @@ try test("Error") {
496508
try expectEqual(JSError(from: .string("error"))?.description, nil)
497509
try expectEqual(JSError(from: .object(error.jsObject))?.description, expectedDescription)
498510
}
511+
512+
try test("JSValue accessor") {
513+
let globalObject1 = JSObject.global.globalObject1
514+
try expectEqual(globalObject1.prop_1.nested_prop, .number(1))
515+
try expectEqual(globalObject1.object!.prop_1.object!.nested_prop, .number(1))
516+
517+
try expectEqual(globalObject1.prop_4[0], .number(3))
518+
try expectEqual(globalObject1.prop_4[1], .number(4))
519+
}

IntegrationTests/bin/primary-tests.js

+3
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,9 @@ global.Animal = function (name, age, isCat) {
4848
this.getIsCat = function () {
4949
return this.isCat;
5050
};
51+
this.setName = function (name) {
52+
this.name = name;
53+
}
5154
};
5255

5356
const { startWasiTask } = require("../lib");

Sources/JavaScriptKit/JSValue.swift

+23
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import _CJavaScriptKit
22

33
/// `JSValue` represents a value in JavaScript.
4+
@dynamicMemberLookup
45
public enum JSValue: Equatable {
56
case boolean(Bool)
67
case string(JSString)
@@ -79,6 +80,28 @@ public enum JSValue: Equatable {
7980
}
8081
}
8182

83+
extension JSValue {
84+
/// An unsafe convenience method of `JSObject.subscript(_ name: String) -> ((ConvertibleToJSValue...) -> JSValue)?`
85+
/// - Precondition: `self` must be a JavaScript Object and specified member should be a callable object.
86+
public subscript(dynamicMember name: String) -> ((ConvertibleToJSValue...) -> JSValue) {
87+
object![dynamicMember: name]!
88+
}
89+
90+
/// An unsafe convenience method of `JSObject.subscript(_ index: Int) -> JSValue`
91+
/// - Precondition: `self` must be a JavaScript Object.
92+
public subscript(dynamicMember name: String) -> JSValue {
93+
get { self.object![name] }
94+
set { self.object![name] = newValue }
95+
}
96+
97+
/// An unsafe convenience method of `JSObject.subscript(_ index: Int) -> JSValue`
98+
/// - Precondition: `self` must be a JavaScript Object.
99+
public subscript(_ index: Int) -> JSValue {
100+
get { object![index] }
101+
set { object![index] = newValue }
102+
}
103+
}
104+
82105
extension JSValue {
83106
public func fromJSValue<Type>() -> Type? where Type: ConstructibleFromJSValue {
84107
return Type.construct(from: self)

0 commit comments

Comments
 (0)