Skip to content

Commit ec0bbe6

Browse files
Make JSObject conform to ExpressibleByDictionaryLiteral directly
1 parent 0d7d3de commit ec0bbe6

File tree

5 files changed

+57
-35
lines changed

5 files changed

+57
-35
lines changed

Sources/JavaScriptKit/FundamentalObjects/JSClosure.swift

+10
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,11 @@ public class JSOneshotClosure: JSObject, JSClosureProtocol {
3535
)
3636
}
3737

38+
@available(*, unavailable, message: "JSOneshotClosure does not support dictionary literal initialization")
39+
public required init(dictionaryLiteral elements: (String, JSValue)...) {
40+
fatalError("JSOneshotClosure does not support dictionary literal initialization")
41+
}
42+
3843
#if compiler(>=5.5) && !hasFeature(Embedded)
3944
@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)
4045
public static func async(_ body: sending @escaping (sending [JSValue]) async throws -> JSValue) -> JSOneshotClosure
@@ -122,6 +127,11 @@ public class JSClosure: JSFunction, JSClosureProtocol {
122127
Self.sharedClosures.wrappedValue[hostFuncRef] = (self, body)
123128
}
124129

130+
@available(*, unavailable, message: "JSClosure does not support dictionary literal initialization")
131+
public required init(dictionaryLiteral elements: (String, JSValue)...) {
132+
fatalError("JSClosure does not support dictionary literal initialization")
133+
}
134+
125135
#if compiler(>=5.5) && !hasFeature(Embedded)
126136
@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)
127137
public static func async(_ body: @Sendable @escaping (sending [JSValue]) async throws -> JSValue) -> JSClosure {

Sources/JavaScriptKit/FundamentalObjects/JSDictionary.swift

-34
This file was deleted.

Sources/JavaScriptKit/FundamentalObjects/JSObject.swift

+14-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import _CJavaScriptKit
1515
/// The lifetime of this object is managed by the JavaScript and Swift runtime bridge library with
1616
/// reference counting system.
1717
@dynamicMemberLookup
18-
public class JSObject: Equatable {
18+
public class JSObject: Equatable, ExpressibleByDictionaryLiteral {
1919
internal static var constructor: JSFunction { _constructor.wrappedValue }
2020
private static let _constructor = LazyThreadLocal(initialize: { JSObject.global.Object.function! })
2121

@@ -38,6 +38,19 @@ public class JSObject: Equatable {
3838
#endif
3939
}
4040

41+
/// Creates an empty JavaScript object.
42+
public convenience init() {
43+
self.init(id: swjs_create_object())
44+
}
45+
46+
/// Creates a new object with the key-value pairs in the dictionary literal.
47+
///
48+
/// - Parameter elements: A variadic list of key-value pairs where all keys are strings
49+
public convenience required init(dictionaryLiteral elements: (String, JSValue)...) {
50+
self.init()
51+
for (key, value) in elements { self[key] = value }
52+
}
53+
4154
/// Asserts that the object is being accessed from the owner thread.
4255
///
4356
/// - Parameter hint: A string to provide additional context for debugging.

Sources/JavaScriptKit/FundamentalObjects/JSSymbol.swift

+5
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,11 @@ public class JSSymbol: JSObject {
2424
super.init(id: id)
2525
}
2626

27+
@available(*, unavailable, message: "JSSymbol does not support dictionary literal initialization")
28+
public required init(dictionaryLiteral elements: (String, JSValue)...) {
29+
fatalError("JSSymbol does not support dictionary literal initialization")
30+
}
31+
2732
public static func `for`(key: JSString) -> JSSymbol {
2833
Symbol.for!(key).symbol!
2934
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import JavaScriptKit
2+
import XCTest
3+
4+
final class JSObjectTests: XCTestCase {
5+
func testEmptyObject() {
6+
let object = JSObject()
7+
let keys = JSObject.global.Object.function!.keys.function!(object)
8+
XCTAssertEqual(keys.array?.count, 0)
9+
}
10+
11+
func testInitWithDictionaryLiteral() {
12+
let object: JSObject = [
13+
"key1": 1,
14+
"key2": "value2",
15+
"key3": .boolean(true),
16+
"key4": .object(JSObject()),
17+
"key5": [1, 2, 3].jsValue,
18+
"key6": ["key": "value"].jsValue,
19+
]
20+
XCTAssertEqual(object.key1, .number(1))
21+
XCTAssertEqual(object.key2, "value2")
22+
XCTAssertEqual(object.key3, .boolean(true))
23+
let getKeys = JSObject.global.Object.function!.keys.function!
24+
XCTAssertEqual(getKeys(object.key4).array?.count, 0)
25+
XCTAssertEqual(object.key5.array.map(Array.init), [1, 2, 3])
26+
XCTAssertEqual(object.key6.object?.key, "value")
27+
}
28+
}

0 commit comments

Comments
 (0)