Skip to content

Commit

Permalink
helpers for calling methods on JS objects
Browse files Browse the repository at this point in the history
  • Loading branch information
gregcotten committed Dec 1, 2022
1 parent e7c2679 commit b3a8a89
Show file tree
Hide file tree
Showing 8 changed files with 415 additions and 24 deletions.
314 changes: 314 additions & 0 deletions Sources/Napoli/Generated/ObjectReferenceMethods.generated.swift

Large diffs are not rendered by default.

21 changes: 12 additions & 9 deletions Sources/Napoli/Global.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,32 +3,35 @@ import NAPIC

public extension Environment {
final class Global: ObjectReference {
public convenience init(_ env: Environment) throws {
@available(*, noasync)
fileprivate convenience init(_ env: Environment) throws {
var global: napi_value?
try napi_get_global(env.env, &global).throwIfError()
try self.init(env, from: global!)
}
}

@available(*, noasync)
func global() throws -> Global {
try Global(self)
}
}

public extension Environment.Global {
final class JSON: ObjectReference {
public func stringify<V: ValueConvertible>(_ value: V) throws -> String {
let function: TypedFunction1<String, V> = try get(storedEnvironment, "stringify")
return try function.call(storedEnvironment, value)
@available(*, noasync)
public func stringify<V: ValueConvertible>(env: Environment? = nil, _ value: V) throws -> String {
try call(env, "stringify", value)
}

public func parse<V: ValueConvertible>(_ string: String) throws -> V {
let function: TypedFunction1<V, String> = try get(storedEnvironment, "parse")
return try function.call(storedEnvironment, string)
@available(*, noasync)
public func parse<V: ValueConvertible>(env: Environment? = nil, _ string: String) throws -> V {
try call(env, "parse", string)
}
}

func json() throws -> JSON {
try get(storedEnvironment, "JSON")
@available(*, noasync)
func json(_ env: Environment? = nil) throws -> JSON {
try get(env, "JSON")
}
}
22 changes: 10 additions & 12 deletions Sources/Napoli/Promise.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,22 +9,20 @@ private class JSPromise: ObjectReference {
try attachDummyCatch(env)
}

@available(*, noasync)
func attachDummyCatch(_ env: Environment? = nil) throws {
let env = env ?? storedEnvironment
let catchFunction: TypedFunction1<Undefined, TypedFunction1<Null, JSError>> = try get(env, "catch")
try catchFunction.call(env, this: self, .init(named: "dummy") { _, _ in
Null.default
})
typealias CatchCallback = TypedFunction1<Undefined, JSError>
try callThis(env, "catch", CatchCallback(named: "dummyCatch", { _, _ in }))
}

@available(*, noasync)
func then<V: ValueConvertible>(_ env: Environment? = nil, onFulfilled: @escaping (Environment, V) -> Void, onReject: @escaping (Environment, JSError) -> Void) throws {
let env = env ?? storedEnvironment
let function: TypedFunction2<Undefined, TypedFunction1<Undefined, V>, TypedFunction1<Undefined, JSError>> = try get(env, "then")

try function.call(env,
this: self,
.init(named: "onFulfilled", onFulfilled),
.init(named: "onReject", onReject))
typealias OnFullfillCallback = TypedFunction1<Undefined, V>
typealias OnRejectCallback = TypedFunction1<Undefined, JSError>
try callThis(env,
"then",
OnFullfillCallback(named: "onFulfilled", onFulfilled),
OnRejectCallback(named: "onReject", onReject))
}

func getValue<V: ValueConvertible>() async throws -> V {
Expand Down
4 changes: 3 additions & 1 deletion bin/codegen
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#!/usr/bin/env bash

set -e

SCRIPT_DIR="$(cd "$(dirname "$0")"; pwd)"

cd "$SCRIPT_DIR/../codegen/"
Expand All @@ -9,4 +11,4 @@ mkdir -p "${SCRIPT_DIR}/../Sources/Napoli/Generated"

swift run codegen "${SCRIPT_DIR}/../Sources/Napoli/Generated"
cd "${SCRIPT_DIR}/../Sources/Napoli/Generated"
swiftformat *.generated.swift
swiftformat *.generated.swift
1 change: 1 addition & 0 deletions codegen/Sources/codegen/Codegen.swift
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ struct Codegen: ParsableCommand {
try ThreadsafeTypedFunction.generate(maxParams: params).result().write(to: generatedFile(named: "ThreadsafeTypedFunction"), atomically: true, encoding: .utf8)
try Method.generate(maxParams: params).result().write(to: generatedFile(named: "MethodDescriptor"), atomically: true, encoding: .utf8)
try InstanceMethod.generate(maxParams: params).result().write(to: generatedFile(named: "InstanceMethodDescriptor"), atomically: true, encoding: .utf8)
try ObjectReferenceMethods.generate(maxParams: params).result().write(to: generatedFile(named: "ObjectReferenceMethods"), atomically: true, encoding: .utf8)
}
}

Expand Down
72 changes: 72 additions & 0 deletions codegen/Sources/codegen/Generators/ObjectReferenceMethods.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import Foundation

enum ObjectReferenceMethods {
static func generate(maxParams: Int) throws -> Source {
var source = Source()
source.add("""
// swiftformat:disable opaqueGenericParameters
import Foundation
import NAPIC
""")
source.newline()

for i in (0 ..< maxParams).reversed() {
try generateExtension(source: &source, paramCount: i)
}

return source
}

static func generateExtension(source: inout Source, paramCount: Int) throws {
let resultGeneric = Generic(type: "Result")
let inGenerics = [Generic](prefix: "P", count: paramCount)
let allGenerics = [resultGeneric] + inGenerics
let allWheres = allGenerics.conforming(to: Types.valueConvertible).value
let inWheres = inGenerics.conforming(to: Types.valueConvertible).value

let commaSeparatedInGenerics = inGenerics.map(\.type).commaSeparated

let inGenericsAsArgs: String
if paramCount > 0 {
inGenericsAsArgs = ", " + inGenerics.map { "_ \($0.type.lowercased()): \($0.type)" }.commaSeparated
} else {
inGenericsAsArgs = ""
}

let inGenericsAsCallArgs = inGenerics.map { $0.type.lowercased() }.commaSeparated.prefixCommaIfNotEmpty()

source.add("""
// \(paramCount) param methods
public extension ObjectReference {
@available(*, noasync)
func callThis\(allGenerics.bracketedOrNone)(_ env: Environment? = nil, _ name: String\(inGenericsAsArgs)) throws -> Result\(allWheres.backspaceIfNotEmpty()) {
let env = env ?? storedEnvironment
let function: TypedFunction\(paramCount)\(allGenerics.bracketedOrNone) = try get(env, name)
return try function.call(env, this: self\(inGenericsAsCallArgs))
}
@available(*, noasync)
func call\(allGenerics.bracketedOrNone)(_ env: Environment? = nil, _ name: String\(inGenericsAsArgs)) throws -> Result\(allWheres.backspaceIfNotEmpty()) {
let env = env ?? storedEnvironment
let function: TypedFunction\(paramCount)\(allGenerics.bracketedOrNone) = try get(env, name)
return try function.call(env, this: Undefined.default\(inGenericsAsCallArgs))
}
@available(*, noasync)
func callThis\(inGenerics.bracketedOrNone)(_ env: Environment? = nil, _ name: String\(inGenericsAsArgs)) throws \(inWheres.backspaceIfNotEmpty()) {
let env = env ?? storedEnvironment
let function: TypedFunction\(paramCount)<Undefined\(commaSeparatedInGenerics.prefixCommaIfNotEmpty())> = try get(env, name)
return try function.call(env, this: self\(inGenericsAsCallArgs))
}
@available(*, noasync)
func call\(inGenerics.bracketedOrNone)(_ env: Environment? = nil, _ name: String\(inGenericsAsArgs)) throws \(inWheres.backspaceIfNotEmpty()) {
let env = env ?? storedEnvironment
let function: TypedFunction\(paramCount)<Undefined\(commaSeparatedInGenerics.prefixCommaIfNotEmpty())> = try get(env, name)
return try function.call(env, this: Undefined.default\(inGenericsAsCallArgs))
}
}
""")
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,8 @@ enum ThreadsafeTypedFunction {
if try! exceptionIsPending(env) {
var errorResult: napi_value!
try! napi_get_and_clear_last_exception(env.env, &errorResult).throwIfError()
callbackData.continuation.resume(throwing: JSException(value: errorResult))
let error = try! JSError(env, from: errorResult)
callbackData.continuation.resume(throwing: error)
} else {
callbackData.continuation.resume(throwing: error)
}
Expand Down
2 changes: 1 addition & 1 deletion codegen/Sources/codegen/Generators/TypedFunction.swift
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ enum TypedFunction {
}
return try data.callback(env, this, usedArgs).napiValue(env)
} catch Napoli.Error.pendingException {
} catch NAPIError.pendingException {
return nil
} catch {
if try! exceptionIsPending(env) == false { try! throwError(env, error) }
Expand Down

0 comments on commit b3a8a89

Please sign in to comment.