Skip to content

Refine public API #40

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Aug 28, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -37,15 +37,15 @@ func expectEqual<T: Equatable>(
}
}

func expectObject(_ value: JSValue, file: StaticString = #file, line: UInt = #line, column: UInt = #column) throws -> JSObjectRef {
func expectObject(_ value: JSValue, file: StaticString = #file, line: UInt = #line, column: UInt = #column) throws -> JSObject {
switch value {
case let .object(ref): return ref
default:
throw MessageError("Type of \(value) should be \"object\"", file: file, line: line, column: column)
}
}

func expectArray(_ value: JSValue, file: StaticString = #file, line: UInt = #line, column: UInt = #column) throws -> JSArrayRef {
func expectArray(_ value: JSValue, file: StaticString = #file, line: UInt = #line, column: UInt = #column) throws -> JSArray {
guard let array = value.array else {
throw MessageError("Type of \(value) should be \"object\"", file: file, line: line, column: column)
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import JavaScriptKit

test("Literal Conversion") {
let global = JSObjectRef.global
let global = JSObject.global
let inputs: [JSValue] = [
.boolean(true),
.boolean(false),
Expand Down
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,8 @@ Can be written in Swift using JavaScriptKit
```swift
import JavaScriptKit

let alert = JSObjectRef.global.alert.function!
let document = JSObjectRef.global.document.object!
let alert = JSObject.global.alert.function!
let document = JSObject.global.document.object!

let divElement = document.createElement!("div").object!
divElement.innerText = "Hello, world"
Expand All @@ -64,7 +64,7 @@ struct Pet: Codable {
let owner: Owner
}

let jsPet = JSObjectRef.global.pet
let jsPet = JSObject.global.pet
let swiftPet: Pet = try JSValueDecoder().decode(from: jsPet)

alert("Swift is running on browser!")
Expand Down
Original file line number Diff line number Diff line change
@@ -1,30 +1,29 @@
public class JSArray {
static let classObject = JSObject.global.Array.function!

public class JSArrayRef {
static let classObject = JSObjectRef.global.Array.function!

static func isArray(_ object: JSObjectRef) -> Bool {
static func isArray(_ object: JSObject) -> Bool {
classObject.isArray!(object).boolean!
}

let ref: JSObjectRef
let ref: JSObject

public init?(_ ref: JSObjectRef) {
public init?(_ ref: JSObject) {
guard Self.isArray(ref) else { return nil }
self.ref = ref
}
}

extension JSArrayRef: RandomAccessCollection {
extension JSArray: RandomAccessCollection {
public typealias Element = JSValue

public func makeIterator() -> Iterator {
Iterator(ref: ref)
}

public class Iterator: IteratorProtocol {
let ref: JSObjectRef
let ref: JSObject
var index = 0
init(ref: JSObjectRef) {
init(ref: JSObject) {
self.ref = ref
}

Expand All @@ -46,3 +45,9 @@ extension JSArrayRef: RandomAccessCollection {

public var endIndex: Int { ref.length.number.map(Int.init) ?? 0 }
}

extension JSValue {
public var array: JSArray? {
object.flatMap(JSArray.init)
}
}
8 changes: 8 additions & 0 deletions Sources/JavaScriptKit/Deprecated.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
@available(*, deprecated, renamed: "JSObject")
public typealias JSObjectRef = JSObject

@available(*, deprecated, renamed: "JSArray")
public typealias JSArrayRef = JSArray

@available(*, deprecated, renamed: "JSFunction")
public typealias JSFunctionRef = JSFunction
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import _CJavaScriptKit

public class JSFunctionRef: JSObjectRef {
public class JSFunction: JSObject {
@discardableResult
public func callAsFunction(this: JSObjectRef? = nil, arguments: [JSValueConvertible]) -> JSValue {
public func callAsFunction(this: JSObject? = nil, arguments: [JSValueConvertible]) -> JSValue {
let result = arguments.withRawJSValues { rawValues in
rawValues.withUnsafeBufferPointer { bufferPointer -> RawJSValue in
let argv = bufferPointer.baseAddress
Expand All @@ -25,19 +25,19 @@ public class JSFunctionRef: JSObjectRef {
}

@discardableResult
public func callAsFunction(this: JSObjectRef? = nil, _ arguments: JSValueConvertible...) -> JSValue {
public func callAsFunction(this: JSObject? = nil, _ arguments: JSValueConvertible...) -> JSValue {
self(this: this, arguments: arguments)
}

public func new(_ arguments: JSValueConvertible...) -> JSObjectRef {
public func new(_ arguments: JSValueConvertible...) -> JSObject {
new(arguments: arguments)
}

// Guaranteed to return an object because either:
// a) the constructor explicitly returns an object, or
// b) the constructor returns nothing, which causes JS to return the `this` value, or
// c) the constructor returns undefined, null or a non-object, in which case JS also returns `this`.
public func new(arguments: [JSValueConvertible]) -> JSObjectRef {
public func new(arguments: [JSValueConvertible]) -> JSObject {
arguments.withRawJSValues { rawValues in
rawValues.withUnsafeBufferPointer { bufferPointer in
let argv = bufferPointer.baseAddress
Expand All @@ -47,13 +47,13 @@ public class JSFunctionRef: JSObjectRef {
self.id, argv, Int32(argc),
&resultObj
)
return JSObjectRef(id: resultObj)
return JSObject(id: resultObj)
}
}
}

@available(*, unavailable, message: "Please use JSClosure instead")
public static func from(_: @escaping ([JSValue]) -> JSValue) -> JSFunctionRef {
public static func from(_: @escaping ([JSValue]) -> JSValue) -> JSFunction {
fatalError("unavailable")
}

Expand All @@ -62,7 +62,7 @@ public class JSFunctionRef: JSObjectRef {
}
}

public class JSClosure: JSFunctionRef {
public class JSClosure: JSFunction {
static var sharedFunctions: [JavaScriptHostFuncRef: ([JSValue]) -> JSValue] = [:]

private var hostFuncRef: JavaScriptHostFuncRef = 0
Expand Down Expand Up @@ -128,6 +128,6 @@ public func _call_host_function(
$0.jsValue()
}
let result = hostFunc(arguments)
let callbackFuncRef = JSFunctionRef(id: callbackFuncRef)
let callbackFuncRef = JSFunction(id: callbackFuncRef)
_ = callbackFuncRef(result)
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import _CJavaScriptKit

@dynamicMemberLookup
public class JSObjectRef: Equatable {
public class JSObject: Equatable {
internal var id: UInt32
init(id: UInt32) {
self.id = id
Expand Down Expand Up @@ -30,16 +30,16 @@ public class JSObjectRef: Equatable {
set { setJSValue(this: self, index: Int32(index), value: newValue) }
}

public func isInstanceOf(_ constructor: JSFunctionRef) -> Bool {
public func isInstanceOf(_ constructor: JSFunction) -> Bool {
_instanceof(id, constructor.id)
}

static let _JS_Predef_Value_Global: UInt32 = 0
public static let global = JSObjectRef(id: _JS_Predef_Value_Global)
public static let global = JSObject(id: _JS_Predef_Value_Global)

deinit { _destroy_ref(id) }

public static func == (lhs: JSObjectRef, rhs: JSObjectRef) -> Bool {
public static func == (lhs: JSObject, rhs: JSObject) -> Bool {
return lhs.id == rhs.id
}

Expand Down
20 changes: 8 additions & 12 deletions Sources/JavaScriptKit/JSValue.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ public enum JSValue: Equatable {
case boolean(Bool)
case string(String)
case number(Double)
case object(JSObjectRef)
case object(JSObject)
case null
case undefined
case function(JSFunctionRef)
case function(JSFunction)

public var boolean: Bool? {
switch self {
Expand All @@ -30,20 +30,16 @@ public enum JSValue: Equatable {
}
}

public var object: JSObjectRef? {
public var object: JSObject? {
switch self {
case let .object(object): return object
default: return nil
}
}

public var array: JSArrayRef? {
object.flatMap { JSArrayRef($0) }
}

public var isNull: Bool { return self == .null }
public var isUndefined: Bool { return self == .undefined }
public var function: JSFunctionRef? {
public var function: JSFunction? {
switch self {
case let .function(function): return function
default: return nil
Expand All @@ -69,29 +65,29 @@ extension JSValue: ExpressibleByIntegerLiteral {
}
}

public func getJSValue(this: JSObjectRef, name: String) -> JSValue {
public func getJSValue(this: JSObject, name: String) -> JSValue {
var rawValue = RawJSValue()
_get_prop(this.id, name, Int32(name.count),
&rawValue.kind,
&rawValue.payload1, &rawValue.payload2, &rawValue.payload3)
return rawValue.jsValue()
}

public func setJSValue(this: JSObjectRef, name: String, value: JSValue) {
public func setJSValue(this: JSObject, name: String, value: JSValue) {
value.withRawJSValue { rawValue in
_set_prop(this.id, name, Int32(name.count), rawValue.kind, rawValue.payload1, rawValue.payload2, rawValue.payload3)
}
}

public func getJSValue(this: JSObjectRef, index: Int32) -> JSValue {
public func getJSValue(this: JSObject, index: Int32) -> JSValue {
var rawValue = RawJSValue()
_get_subscript(this.id, index,
&rawValue.kind,
&rawValue.payload1, &rawValue.payload2, &rawValue.payload3)
return rawValue.jsValue()
}

public func setJSValue(this: JSObjectRef, index: Int32, value: JSValue) {
public func setJSValue(this: JSObject, index: Int32, value: JSValue) {
value.withRawJSValue { rawValue in
_set_subscript(this.id, index,
rawValue.kind,
Expand Down
14 changes: 7 additions & 7 deletions Sources/JavaScriptKit/JSValueConvertible.swift
Original file line number Diff line number Diff line change
Expand Up @@ -52,12 +52,12 @@ extension String: JSValueConvertible {
public func jsValue() -> JSValue { .string(self) }
}

extension JSObjectRef: JSValueConvertible {
// `JSObjectRef.jsValue` is defined in JSObjectRef.swift to be able to overridden
// from `JSFunctionRef`
extension JSObject: JSValueConvertible {
// `JSObject.jsValue` is defined in JSObject.swift to be able to overridden
// from `JSFunction`
}

private let Object = JSObjectRef.global.Object.function!
private let Object = JSObject.global.Object.function!

extension Dictionary where Value: JSValueConvertible, Key == String {
public func jsValue() -> JSValue {
Expand All @@ -75,7 +75,7 @@ extension Dictionary: JSValueConvertible where Value == JSValueConvertible, Key
}
}

private let Array = JSObjectRef.global.Array.function!
private let Array = JSObject.global.Array.function!

extension Array where Element: JSValueConvertible {
public func jsValue() -> JSValue {
Expand Down Expand Up @@ -111,13 +111,13 @@ extension RawJSValue: JSValueConvertible {
let string = String(decodingCString: UnsafePointer(buffer), as: UTF8.self)
return .string(string)
case .object:
return .object(JSObjectRef(id: UInt32(payload1)))
return .object(JSObject(id: UInt32(payload1)))
case .null:
return .null
case .undefined:
return .undefined
case .function:
return .function(JSFunctionRef(id: UInt32(payload1)))
return .function(JSFunction(id: UInt32(payload1)))
default:
fatalError("unreachable")
}
Expand Down
16 changes: 8 additions & 8 deletions Sources/JavaScriptKit/JSValueDecoder.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,12 @@ private struct _Decoder: Decoder {
let userInfo: [CodingUserInfoKey: Any]

func container<Key>(keyedBy _: Key.Type) throws -> KeyedDecodingContainer<Key> where Key: CodingKey {
guard let ref = node.object else { throw _typeMismatch(at: codingPath, JSObjectRef.self, reality: node) }
guard let ref = node.object else { throw _typeMismatch(at: codingPath, JSObject.self, reality: node) }
return KeyedDecodingContainer(_KeyedDecodingContainer(decoder: self, ref: ref))
}

func unkeyedContainer() throws -> UnkeyedDecodingContainer {
guard let ref = node.object else { throw _typeMismatch(at: codingPath, JSObjectRef.self, reality: node) }
guard let ref = node.object else { throw _typeMismatch(at: codingPath, JSObject.self, reality: node) }
return _UnkeyedDecodingContainer(decoder: self, ref: ref)
}

Expand All @@ -34,8 +34,8 @@ private struct _Decoder: Decoder {
}

private enum Object {
static let ref = JSObjectRef.global.Object.object!
static func keys(_ object: JSObjectRef) -> [String] {
static let ref = JSObject.global.Object.object!
static func keys(_ object: JSObject) -> [String] {
let keys = ref.keys!(object).array!
return keys.map { $0.string! }
}
Expand Down Expand Up @@ -77,14 +77,14 @@ struct _JSCodingKey: CodingKey {

private struct _KeyedDecodingContainer<Key: CodingKey>: KeyedDecodingContainerProtocol {
private let decoder: _Decoder
private let ref: JSObjectRef
private let ref: JSObject

var codingPath: [CodingKey] { return decoder.codingPath }
var allKeys: [Key] {
Object.keys(ref).compactMap(Key.init(stringValue:))
}

init(decoder: _Decoder, ref: JSObjectRef) {
init(decoder: _Decoder, ref: JSObject) {
self.decoder = decoder
self.ref = ref
}
Expand Down Expand Up @@ -152,9 +152,9 @@ private struct _UnkeyedDecodingContainer: UnkeyedDecodingContainer {
private var currentKey: CodingKey { return _JSCodingKey(index: currentIndex) }

let decoder: _Decoder
let ref: JSObjectRef
let ref: JSObject

init(decoder: _Decoder, ref: JSObjectRef) {
init(decoder: _Decoder, ref: JSObject) {
self.decoder = decoder
count = ref.length.number.map(Int.init)
self.ref = ref
Expand Down