diff --git a/Sources/JavaScriptKit/BasicObjects/JSTypedArray.swift b/Sources/JavaScriptKit/BasicObjects/JSTypedArray.swift index c22e6c8cc..52b5f0b20 100644 --- a/Sources/JavaScriptKit/BasicObjects/JSTypedArray.swift +++ b/Sources/JavaScriptKit/BasicObjects/JSTypedArray.swift @@ -52,6 +52,14 @@ public class JSTypedArray: JSBridgedClass, ExpressibleByArrayLiteral wh self.init(unsafelyWrapping: JSObject(id: jsArrayRef)) } + /// Initialize a new instance of TypedArray in JavaScript environment with given buffer elements. + /// + /// - Parameter buffer: The buffer that will be copied to create a new instance of TypedArray + public convenience init(buffer: UnsafeBufferPointer) { + let jsArrayRef = _create_typed_array(Self.constructor!.id, buffer.baseAddress!, Int32(buffer.count)) + self.init(unsafelyWrapping: JSObject(id: jsArrayRef)) + } + /// Convenience initializer for `Sequence`. public convenience init(_ sequence: S) where S.Element == Element { self.init(Array(sequence)) diff --git a/Sources/JavaScriptKit/JSValueDecoder.swift b/Sources/JavaScriptKit/JSValueDecoder.swift index b1d59af63..24517c063 100644 --- a/Sources/JavaScriptKit/JSValueDecoder.swift +++ b/Sources/JavaScriptKit/JSValueDecoder.swift @@ -118,7 +118,12 @@ private struct _KeyedDecodingContainer: KeyedDecodingContainerPr } func decode(_: T.Type, forKey key: Key) throws -> T where T: Decodable { - return try T(from: _decoder(forKey: key)) + let jsValue = try _decode(forKey: key) + if let jsType = T.self as? ConstructibleFromJSValue.Type { + let maybeValue = jsType.construct(from: jsValue) + if let value = maybeValue { return value as! T } + } + return try T(from: _decoder(forKey: key, value: jsValue)) } func nestedContainer(keyedBy _: NestedKey.Type, forKey key: Key) throws -> KeyedDecodingContainer where NestedKey: CodingKey { @@ -139,6 +144,10 @@ private struct _KeyedDecodingContainer: KeyedDecodingContainerPr func _decoder(forKey key: CodingKey) throws -> Decoder { let value = try _decode(forKey: key) + return _decoder(forKey: key, value: value) + } + + func _decoder(forKey key: CodingKey, value: JSValue) -> Decoder { return decoder.decoder(referencing: value, with: key) } } @@ -182,7 +191,12 @@ private struct _UnkeyedDecodingContainer: UnkeyedDecodingContainer { } mutating func decode(_: T.Type) throws -> T where T: Decodable { - return try T(from: _decoder()) + let jsValue = _currentValue() + if let jsType = T.self as? ConstructibleFromJSValue.Type { + let maybeValue = jsType.construct(from: jsValue) + if let value = maybeValue { return value as! T } + } + return try T(from: _decoder(value: jsValue)) } mutating func nestedContainer(keyedBy _: NestedKey.Type) throws -> KeyedDecodingContainer where NestedKey: CodingKey { @@ -198,7 +212,11 @@ private struct _UnkeyedDecodingContainer: UnkeyedDecodingContainer { } mutating func _decoder() -> Decoder { - decoder.decoder(referencing: _currentValue(), with: currentKey) + _decoder(value: _currentValue()) + } + + func _decoder(value: JSValue) -> Decoder { + decoder.decoder(referencing: value, with: currentKey) } } @@ -244,6 +262,10 @@ public class JSValueDecoder { from value: JSValue, userInfo: [CodingUserInfoKey: Any] = [:] ) throws -> T where T: Decodable { + if let jsType = T.self as? ConstructibleFromJSValue.Type { + let maybeValue = jsType.construct(from: value) + if let value = maybeValue { return value as! T } + } let decoder = _Decoder(referencing: value, userInfo: userInfo) return try T(from: decoder) }