diff --git a/.gitignore b/.gitignore index 6212642..54ef3fc 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,6 @@ .DS_Store /.build -/.swiftpm /Packages /*.xcodeproj /Package.resolved +/.vscode/ipch diff --git a/Package.swift b/Package.swift index ac0f503..1cb3b30 100644 --- a/Package.swift +++ b/Package.swift @@ -1,91 +1,28 @@ -// swift-tools-version:6.4 +// swift-tools-version:5.0 import PackageDescription let package = Package( name: "JavaScriptCore", - platforms: [ - .macOS(.v26), - ], products: [ - .library( - name: "SJavaScriptCore", - targets: ["SJavaScriptCore"] - ), + .library(name: "SJavaScriptCore", targets: ["SJavaScriptCore"]), ], dependencies: [ - .package(name: "JavaScript"), + .package( + url: "https://github.com/tris-code/javascript.git", + .branch("master")), + .package( + url: "https://github.com/tris-code/test.git", + .branch("master")) ], targets: [ .target( - name: "SJavaScriptCore", - dependencies: [ - .target( - name: "CJavaScriptCore", - condition: .when(platforms: [.linux]) - ), - .product( - name: "JavaScript", - package: "javascript" - ), - ], - path: "./Sources/JavaScriptCore" - ), - .systemLibrary( name: "CJavaScriptCore", - pkgConfig: "javascriptcoregtk-4.1", - providers: [.aptItem(["libjavascriptcoregtk-4.1-dev"])] - ), + dependencies: []), + .target( + name: "SJavaScriptCore", + dependencies: ["CJavaScriptCore", "JavaScript"]), .testTarget( - name: "Tests", - dependencies: [ - "SJavaScriptCore" - ] - ) + name: "SJavaScriptCoreTests", + dependencies: ["Test", "SJavaScriptCore"]), ] ) - -// MARK: - custom package source - -#if canImport(ObjectiveC) -import Darwin.C -#else -import Glibc -#endif - -extension Package.Dependency { - enum Source: String { - case local, remote, github - - static var `default`: Self { .github } - - var baseUrl: String { - switch self { - case .local: return "../../swiftstack/" - case .remote: return "https://swiftstack.io/" - case .github: return "https://github.com/swiftstack/" - } - } - - func url(for name: String) -> String { - return self == .local - ? baseUrl + name.lowercased() - : baseUrl + name.lowercased() + ".git" - } - } - - static func package(name: String) -> Package.Dependency { - guard let pointer = getenv("SWIFTSTACK") else { - return .package(name: name, source: .default) - } - guard let source = Source(rawValue: String(cString: pointer)) else { - fatalError("Invalid source. Use local, remote or github") - } - return .package(name: name, source: source) - } - - static func package(name: String, source: Source) -> Package.Dependency { - return source == .local - ? .package(name: name, path: source.url(for: name)) - : .package(url: source.url(for: name), branch: "dev") - } -} diff --git a/README.md b/README.md index 95fa1c9..6df5c3f 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ ## Package.swift ```swift -.package(url: "https://github.com/JavaScriptKit/JavaScriptCore.git", .branch("dev")) +.package(url: "https://github.com/JavaScriptKit/JavaScriptCore.git", .branch("master")) ``` ## Usage @@ -16,9 +16,9 @@ try context.createFunction(name: "getResult") { return .string("result string") } let result = try context.evaluate("getResult()") -expect(result.isString) -expect(try result.toString() == "result string") -expect("\(result)" == "result string") +assertTrue(result.isString) +assertEqual(try result.toString(), "result string") +assertEqual("\(result)", "result string") ``` ## Requirements @@ -30,5 +30,7 @@ Just works ### Linux ```bash -apt install -y libjavascriptcoregtk-4.1-dev +apt install -y libjavascriptcoregtk-4.0-dev +swift build -Xcc -I/usr/include/webkitgtk-4.0 +swift test -Xcc -I/usr/include/webkitgtk-4.0 ``` diff --git a/Sources/CJavaScriptCore/blank.c b/Sources/CJavaScriptCore/blank.c new file mode 100644 index 0000000..e69de29 diff --git a/Sources/CJavaScriptCore/include/include.h b/Sources/CJavaScriptCore/include/include.h new file mode 100644 index 0000000..2f77237 --- /dev/null +++ b/Sources/CJavaScriptCore/include/include.h @@ -0,0 +1,7 @@ + +#ifndef __JAVASCRIPTCORE_H__ +#define __JAVASCRIPTCORE_H__ + +#include + +#endif diff --git a/Sources/CJavaScriptCore/include/module.modulemap b/Sources/CJavaScriptCore/include/module.modulemap new file mode 100644 index 0000000..88dda56 --- /dev/null +++ b/Sources/CJavaScriptCore/include/module.modulemap @@ -0,0 +1,6 @@ + +module CJavaScriptCore [system] { + header "include.h" + link "javascriptcoregtk-4.0" + export * +} diff --git a/Sources/CJavaScriptCore/module.modulemap b/Sources/CJavaScriptCore/module.modulemap deleted file mode 100644 index 654928b..0000000 --- a/Sources/CJavaScriptCore/module.modulemap +++ /dev/null @@ -1,5 +0,0 @@ -module CJavaScriptCore [system] { - header "/usr/include/webkitgtk-4.1/JavaScriptCore/JavaScript.h" - link "javascriptcoregtk-4.1" - export * -} diff --git a/Sources/JavaScriptCore/JSContext+closure.swift b/Sources/SJavaScriptCore/JSContext+closure.swift similarity index 68% rename from Sources/JavaScriptCore/JSContext+closure.swift rename to Sources/SJavaScriptCore/JSContext+closure.swift index 2957649..44bd883 100644 --- a/Sources/JavaScriptCore/JSContext+closure.swift +++ b/Sources/SJavaScriptCore/JSContext+closure.swift @@ -1,37 +1,31 @@ + #if os(Linux) import CJavaScriptCore #else import JavaScriptCore #endif -import Synchronization - @_exported import JavaScript -private -let functions: Mutex<[OpaquePointer: ([JSValue]) throws -> Value]> = .init([:]) - -extension JSObjectRef: @unchecked @retroactive Sendable {} +private var functions: [OpaquePointer: ([JSValue]) throws -> Value] = [:] extension JSContext { public func createFunction( name: String, - _ body: @escaping @Sendable ([JSValue]) throws -> Value - ) throws { + _ body: @escaping ([JSValue]) throws -> Value) throws + { let function = try createFunction(name: name, callback: wrapper) - functions.withLock { $0[function] = body } + functions[function] = body } public func createFunction( name: String, - _ body: @escaping @Sendable ([JSValue]) throws -> Void - ) throws { + _ body: @escaping ([JSValue]) throws -> Void) throws + { let function = try createFunction(name: name, callback: wrapper) - functions.withLock { - $0[function] = { arguments in - try body(arguments) - return .undefined - } + functions[function] = { arguments in + try body(arguments) + return .undefined } } } @@ -39,8 +33,8 @@ extension JSContext { extension JSContext { public func createFunction( name: String, - _ body: @escaping @Sendable () throws -> Value - ) throws { + _ body: @escaping () throws -> Value) throws + { return try createFunction(name: name) { _ in return try body() } @@ -48,8 +42,8 @@ extension JSContext { public func createFunction( name: String, - _ body: @escaping @Sendable () throws -> Void - ) throws { + _ body: @escaping () throws -> Void) throws + { try createFunction(name: name) { _ in try body() } @@ -62,9 +56,9 @@ func wrapper( thisObject: JSObjectRef!, argumentCount: Int, arguments: UnsafePointer?, - exception: UnsafeMutablePointer? -) -> JSValueRef? { - guard let body = functions.withLock({ $0[function] }) else { + exception: UnsafeMutablePointer?) -> JSValueRef? +{ + guard let body = functions[function] else { if let exception = exception { let error = "swift error: unregistered function" exception.pointee = JSValue(string: error, in: ctx).pointer diff --git a/Sources/JavaScriptCore/JSContext.swift b/Sources/SJavaScriptCore/JSContext.swift similarity index 97% rename from Sources/JavaScriptCore/JSContext.swift rename to Sources/SJavaScriptCore/JSContext.swift index 47e5872..964e449 100644 --- a/Sources/JavaScriptCore/JSContext.swift +++ b/Sources/SJavaScriptCore/JSContext.swift @@ -1,3 +1,4 @@ + #if os(Linux) import CJavaScriptCore #else @@ -7,7 +8,7 @@ import JavaScriptCore public class JSContext { let group: JSContextGroupRef let context: JSGlobalContextRef - var exception: JSObjectRef? + var exception: JSObjectRef? = nil var global: JSObjectRef { return JSContextGetGlobalObject(context)! diff --git a/Sources/JavaScriptCore/JSError.swift b/Sources/SJavaScriptCore/JSError.swift similarity index 80% rename from Sources/JavaScriptCore/JSError.swift rename to Sources/SJavaScriptCore/JSError.swift index 09cda29..6014c46 100644 --- a/Sources/JavaScriptCore/JSError.swift +++ b/Sources/SJavaScriptCore/JSError.swift @@ -1,10 +1,11 @@ + #if os(Linux) import CJavaScriptCore #else import JavaScriptCore #endif -public struct JSError: Error, Equatable, CustomStringConvertible { +public struct JSError: Error, CustomStringConvertible { public var description: String init(context: JSContextRef, pointer: JSValueRef) { @@ -23,9 +24,4 @@ public struct JSError: Error, Equatable, CustomStringConvertible { self.description = "failed to convert JSError" } } - - // @testable - init(_ description: String) { - self.description = description - } } diff --git a/Sources/JavaScriptCore/JSValue.swift b/Sources/SJavaScriptCore/JSValue.swift similarity index 98% rename from Sources/JavaScriptCore/JSValue.swift rename to Sources/SJavaScriptCore/JSValue.swift index cf95f16..a94a045 100644 --- a/Sources/JavaScriptCore/JSValue.swift +++ b/Sources/SJavaScriptCore/JSValue.swift @@ -1,3 +1,4 @@ + #if os(Linux) import CJavaScriptCore #else @@ -78,7 +79,7 @@ extension JSValue { let property = JSStringCreateWithCharacters(bytes, bytes.count) defer { JSStringRelease(property) } - var exception: JSValueRef? + var exception: JSValueRef? = nil let result = JSObjectGetProperty(context, pointer, property, &exception) if exception != nil { @@ -88,6 +89,7 @@ extension JSValue { } } + extension JSValue { public var isNull: Bool { return JSValueIsNull(context, pointer) diff --git a/Sources/JavaScriptCore/shims.swift b/Sources/SJavaScriptCore/shims.swift similarity index 72% rename from Sources/JavaScriptCore/shims.swift rename to Sources/SJavaScriptCore/shims.swift index 2418ab5..909cdd5 100644 --- a/Sources/JavaScriptCore/shims.swift +++ b/Sources/SJavaScriptCore/shims.swift @@ -1,3 +1,4 @@ + #if os(Linux) import CJavaScriptCore #else @@ -8,7 +9,7 @@ public func JSValueToStringCopy( _ ctx: JSContextRef, _ value: JSValueRef ) throws -> JSStringRef { - var exception: JSValueRef? + var exception: JSValueRef? = nil let result = JSValueToStringCopy(ctx, value, &exception) if let exception = exception { throw JSError(context: ctx, pointer: exception) @@ -20,7 +21,7 @@ public func JSValueToNumber( _ ctx: JSContextRef, _ value: JSValueRef ) throws -> Double { - var exception: JSValueRef? + var exception: JSValueRef? = nil let result = JSValueToNumber(ctx, value, &exception) if let exception = exception { throw JSError(context: ctx, pointer: exception) @@ -36,7 +37,7 @@ public func JSEvaluateScript( _ sourceURL: JSStringRef!, _ startingLineNumber: Int32 ) throws -> JSValueRef { - var exception: JSValueRef? + var exception: JSValueRef? = nil let result = JSEvaluateScript( ctx, script, thisObject, sourceURL, startingLineNumber, &exception) if let exception = exception { @@ -46,7 +47,7 @@ public func JSEvaluateScript( return result! } -public struct JSPropertyAttributes: OptionSet, Sendable { +public struct JSPropertyAttributes: OptionSet { public let rawValue: UInt32 public init(rawValue: UInt32) { @@ -54,18 +55,13 @@ public struct JSPropertyAttributes: OptionSet, Sendable { } /// Specifies that a property has no special attributes. - static let none = JSPropertyAttributes( - rawValue: UInt32(kJSPropertyAttributeNone)) + static let none = JSPropertyAttributes(rawValue: UInt32(kJSPropertyAttributeNone)) /// Specifies that a property is read-only. - static let readOnly = JSPropertyAttributes( - rawValue: UInt32(kJSPropertyAttributeNone)) - /// Specifies that a property should not be enumerated by - /// JSPropertyEnumerators and JavaScript for...in loops. - static let dontEnum = JSPropertyAttributes( - rawValue: UInt32(kJSPropertyAttributeNone)) + static let readOnly = JSPropertyAttributes(rawValue: UInt32(kJSPropertyAttributeNone)) + /// Specifies that a property should not be enumerated by JSPropertyEnumerators and JavaScript for...in loops. + static let dontEnum = JSPropertyAttributes(rawValue: UInt32(kJSPropertyAttributeNone)) /// Specifies that the delete operation should fail on a property. - static let dontDelete = JSPropertyAttributes( - rawValue: UInt32(kJSPropertyAttributeNone)) + static let dontDelete = JSPropertyAttributes(rawValue: UInt32(kJSPropertyAttributeNone)) } public func JSObjectSetProperty( @@ -75,7 +71,7 @@ public func JSObjectSetProperty( _ value: JSValueRef!, _ attributes: JSPropertyAttributes ) throws { - var exception: JSValueRef? + var exception: JSValueRef? = nil JSObjectSetProperty( ctx, object, propertyName, value, attributes.rawValue, &exception) if let exception = exception { diff --git a/Tests/LinuxMain.swift b/Tests/LinuxMain.swift new file mode 100644 index 0000000..d94316b --- /dev/null +++ b/Tests/LinuxMain.swift @@ -0,0 +1,8 @@ +import XCTest + +import SJavaScriptCoreTests + +var tests = [XCTestCaseEntry]() +tests += SJavaScriptCoreTests.__allTests() + +XCTMain(tests) diff --git a/Tests/SJavaScriptCore/JSValue.swift b/Tests/SJavaScriptCore/JSValue.swift deleted file mode 100644 index 9045f01..0000000 --- a/Tests/SJavaScriptCore/JSValue.swift +++ /dev/null @@ -1,83 +0,0 @@ -import Testing -@testable import SJavaScriptCore - -@Test func isUndefined() async throws { - let context = JSContext() - - let result = try context.evaluate("undefined") - #expect(result.isUndefined) - #expect(!result.isNull) - #expect(!result.isBool) - #expect(!result.isNumber) - #expect(!result.isString) - #expect(try result.toString() == "undefined") -} - -@Test func isNull() async throws { - let context = JSContext() - let result = try context.evaluate("null") - #expect(!result.isUndefined) - #expect(result.isNull) - #expect(!result.isBool) - #expect(!result.isNumber) - #expect(!result.isString) - #expect(try result.toString() == "null") -} - -@Test func isBool() async throws { - let context = JSContext() - let result = try context.evaluate("true") - #expect(!result.isUndefined) - #expect(!result.isNull) - #expect(result.isBool) - #expect(!result.isNumber) - #expect(!result.isString) - #expect(try result.toString() == "true") - #expect(result.toBool() == true) -} - -@Test func isNumber() async throws { - let context = JSContext() - let result = try context.evaluate("3.14") - #expect(!result.isUndefined) - #expect(!result.isNull) - #expect(!result.isBool) - #expect(result.isNumber) - #expect(!result.isString) - #expect(try result.toString() == "3.14") - #expect(try result.toDouble() == 3.14) -} - -@Test func isString() async throws { - let context = JSContext() - let result = try context.evaluate("'success'") - #expect(!result.isUndefined) - #expect(!result.isNull) - #expect(!result.isBool) - #expect(!result.isNumber) - #expect(result.isString) - #expect(try result.toString() == "success") -} - -@Test func toInt() async throws { - let context = JSContext() - let result = try context.evaluate("40 + 2") - #expect(try result.toInt() == 42) -} - -@Test func toString() async throws { - let context = JSContext() - let result = try context.evaluate("40 + 2") - #expect(try result.toString() == "42") -} - -@Test func property() async throws { - let context = JSContext() - let result = try context.evaluate(""" - (function(){ - return { property: 'test' } - })() - """) - - #expect(try result["property"]?.toString() == "test") -} diff --git a/Tests/SJavaScriptCore/JavaScript.swift b/Tests/SJavaScriptCore/JavaScript.swift deleted file mode 100644 index 1300bf7..0000000 --- a/Tests/SJavaScriptCore/JavaScript.swift +++ /dev/null @@ -1,112 +0,0 @@ -import Testing -@testable import SJavaScriptCore - -@Test func evaluate() async throws { - let context = JSContext() - _ = try context.evaluate("40 + 2") -} - -@Test func exception() async throws { - let context = JSContext() - #expect(throws: JSError("Can't find variable: x")) { - try context.evaluate("x()") - } - - #expect(throws: JSError("Unexpected end of script")) { - try context.evaluate("{") - } -} - -@Test func function() async throws { - let context = JSContext() - try context.createFunction(name: "test") { (_) -> Value in - return .string("success") - } - let result = try context.evaluate("test()") - #expect(try result.toString() == "success") -} - -@Test func closure() async throws { - let context = JSContext() - - try context.createFunction(name: "testUndefined") { - return .undefined - } - let undefinedResult = try context.evaluate("testUndefined()") - #expect(undefinedResult.isUndefined) - - try context.createFunction(name: "testNull") { - return .null - } - let nullResult = try context.evaluate("testNull()") - #expect(nullResult.isNull) - - try context.createFunction(name: "testBool") { - return .bool(true) - } - let boolResult = try context.evaluate("testBool()") - #expect(boolResult.isBool) - - try context.createFunction(name: "testNumber") { - return .number(3.14) - } - let numberResult = try context.evaluate("testNumber()") - #expect(numberResult.isNumber) - - try context.createFunction(name: "testString") { - return .string("success") - } - let stringResult = try context.evaluate("testString()") - #expect(stringResult.isString) -} - -@Test func capture() async throws { - let context = JSContext() - final class Box: @unchecked Sendable { - var captured = false - } - let box = Box() - try context.createFunction(name: "test") { (_) -> Value in - box.captured = true - return .string("captured") - } - let result = try context.evaluate("test()") - #expect(box.captured == true) - #expect("\(result)" == "captured") -} - -@Test func arguments() async throws { - let context = JSContext() - try context.createFunction(name: "test") { (arguments) -> Void in - #expect(arguments.count == 2) - try #expect(arguments.first?.toString() == "one") - try #expect(arguments.last?.toInt() == 42) - } - try context.evaluate("test('one', 42)") -} - -@Test func `persistent context`() async throws { - let context = JSContext() - try context.evaluate("result = 'success'") - #expect(try context.evaluate("result").toString() == "success") - - try context.createFunction(name: "test") { (_) -> Value in - return .string("test ok") - } - - #expect(try context.evaluate("result").toString() == "success") -} - -@Test func sandbox() async throws { - try { - let context = JSContext() - try context.evaluate("test = 'hello'") - let result = try context.evaluate("test") - #expect(try result.toString() == "hello") - }() - - let context = JSContext() - #expect(throws: JSError("Can\'t find variable: test")) { - try context.evaluate("test") - } -} diff --git a/Tests/SJavaScriptCoreTests/JSValueTests.swift b/Tests/SJavaScriptCoreTests/JSValueTests.swift new file mode 100644 index 0000000..9d2cb5a --- /dev/null +++ b/Tests/SJavaScriptCoreTests/JSValueTests.swift @@ -0,0 +1,118 @@ + +import Test +@testable import SJavaScriptCore + +final class JSValueTests: TestCase { + func testIsUndefined() { + do { + let context = JSContext() + + let result = try context.evaluate("undefined") + assertTrue(result.isUndefined) + assertFalse(result.isNull) + assertFalse(result.isBool) + assertFalse(result.isNumber) + assertFalse(result.isString) + assertEqual(try result.toString(), "undefined") + } catch { + fail(String(describing: error)) + } + } + + func testIsNull() { + do { + let context = JSContext() + let result = try context.evaluate("null") + assertFalse(result.isUndefined) + assertTrue(result.isNull) + assertFalse(result.isBool) + assertFalse(result.isNumber) + assertFalse(result.isString) + assertEqual(try result.toString(), "null") + } catch { + fail(String(describing: error)) + } + } + + func testIsBool() { + do { + let context = JSContext() + let result = try context.evaluate("true") + assertFalse(result.isUndefined) + assertFalse(result.isNull) + assertTrue(result.isBool) + assertFalse(result.isNumber) + assertFalse(result.isString) + assertEqual(try result.toString(), "true") + assertEqual(result.toBool(), true) + } catch { + fail(String(describing: error)) + } + } + + func testIsNumber() { + do { + let context = JSContext() + let result = try context.evaluate("3.14") + assertFalse(result.isUndefined) + assertFalse(result.isNull) + assertFalse(result.isBool) + assertTrue(result.isNumber) + assertFalse(result.isString) + assertEqual(try result.toString(), "3.14") + assertEqual(try result.toDouble(), 3.14) + } catch { + fail(String(describing: error)) + } + } + + func testIsString() { + do { + let context = JSContext() + let result = try context.evaluate("'success'") + assertFalse(result.isUndefined) + assertFalse(result.isNull) + assertFalse(result.isBool) + assertFalse(result.isNumber) + assertTrue(result.isString) + assertEqual(try result.toString(), "success") + } catch { + fail(String(describing: error)) + } + } + + func testToInt() { + do { + let context = JSContext() + let result = try context.evaluate("40 + 2") + assertEqual(try result.toInt(), 42) + } catch { + fail(String(describing: error)) + } + } + + func testToString() { + do { + let context = JSContext() + let result = try context.evaluate("40 + 2") + assertEqual(try result.toString(), "42") + } catch { + fail(String(describing: error)) + } + } + + func testProperty() { + do { + let context = JSContext() + let result = try context.evaluate(""" + (function(){ + return { property: 'test' } + })() + """) + + assertEqual(try result["property"]?.toString(), "test") + } catch { + fail(String(describing: error)) + } + } +} diff --git a/Tests/SJavaScriptCoreTests/JavaScriptTests.swift b/Tests/SJavaScriptCoreTests/JavaScriptTests.swift new file mode 100644 index 0000000..232a0e1 --- /dev/null +++ b/Tests/SJavaScriptCoreTests/JavaScriptTests.swift @@ -0,0 +1,134 @@ + +import Test +@testable import SJavaScriptCore + +final class SJavaScriptCoreTests: TestCase { + func testEvaluate() { + let context = JSContext() + assertNoThrow(try context.evaluate("40 + 2")) + } + + func testException() { + let context = JSContext() + assertThrowsError(try context.evaluate("x()")) { error in + assertEqual("\(error)", "Can't find variable: x") + } + + assertThrowsError(try context.evaluate("{")) { error in + assertEqual("\(error)", "Unexpected end of script") + } + } + + func testFunction() { + do { + let context = JSContext() + try context.createFunction(name: "test") { (_) -> Value in + return .string("success") + } + let result = try context.evaluate("test()") + assertEqual(try result.toString(), "success") + } catch { + fail(String(describing: error)) + } + } + + func testClosure() { + do { + let context = JSContext() + + try context.createFunction(name: "testUndefined") { + return .undefined + } + let undefinedResult = try context.evaluate("testUndefined()") + assertTrue(undefinedResult.isUndefined) + + try context.createFunction(name: "testNull") { + return .null + } + let nullResult = try context.evaluate("testNull()") + assertTrue(nullResult.isNull) + + try context.createFunction(name: "testBool") { + return .bool(true) + } + let boolResult = try context.evaluate("testBool()") + assertTrue(boolResult.isBool) + + try context.createFunction(name: "testNumber") { + return .number(3.14) + } + let numberResult = try context.evaluate("testNumber()") + assertTrue(numberResult.isNumber) + + try context.createFunction(name: "testString") { + return .string("success") + } + let stringResult = try context.evaluate("testString()") + assertTrue(stringResult.isString) + } catch { + fail(String(describing: error)) + } + } + + func testCapture() { + do { + let context = JSContext() + + var captured = false + try context.createFunction(name: "test") { (_) -> Value in + captured = true + return .string("captured") + } + let result = try context.evaluate("test()") + assertTrue(captured) + assertEqual("\(result)", "captured") + } catch { + fail(String(describing: error)) + } + } + + func testArguments() { + do { + let context = JSContext() + try context.createFunction(name: "test") { (arguments) -> Void in + assertEqual(arguments.count, 2) + assertEqual(try arguments.first?.toString(), "one") + assertEqual(try arguments.last?.toInt(), 42) + } + try context.evaluate("test('one', 42)") + } catch { + fail(String(describing: error)) + } + } + + func testPersistentContext() { + do { + let context = JSContext() + try context.evaluate("result = 'success'") + assertEqual(try context.evaluate("result").toString(), "success") + + try context.createFunction(name: "test") { (arguments) -> Value in + return .string("test ok") + } + + assertEqual(try context.evaluate("result").toString(), "success") + } catch { + fail(String(describing: error)) + } + } + + func testSandbox() { + do { + let context = JSContext() + try context.evaluate("test = 'hello'") + let result = try context.evaluate("test") + assertEqual(try result.toString(), "hello") + } catch { + fail(String(describing: error)) + return + } + + let context = JSContext() + assertThrowsError(try context.evaluate("test")) + } +} diff --git a/Tests/SJavaScriptCoreTests/XCTestManifests.swift b/Tests/SJavaScriptCoreTests/XCTestManifests.swift new file mode 100644 index 0000000..6660ddf --- /dev/null +++ b/Tests/SJavaScriptCoreTests/XCTestManifests.swift @@ -0,0 +1,42 @@ +#if !canImport(ObjectiveC) +import XCTest + +extension JSValueTests { + // DO NOT MODIFY: This is autogenerated, use: + // `swift test --generate-linuxmain` + // to regenerate. + static let __allTests__JSValueTests = [ + ("testIsBool", testIsBool), + ("testIsNull", testIsNull), + ("testIsNumber", testIsNumber), + ("testIsString", testIsString), + ("testIsUndefined", testIsUndefined), + ("testProperty", testProperty), + ("testToInt", testToInt), + ("testToString", testToString), + ] +} + +extension SJavaScriptCoreTests { + // DO NOT MODIFY: This is autogenerated, use: + // `swift test --generate-linuxmain` + // to regenerate. + static let __allTests__SJavaScriptCoreTests = [ + ("testArguments", testArguments), + ("testCapture", testCapture), + ("testClosure", testClosure), + ("testEvaluate", testEvaluate), + ("testException", testException), + ("testFunction", testFunction), + ("testPersistentContext", testPersistentContext), + ("testSandbox", testSandbox), + ] +} + +public func __allTests() -> [XCTestCaseEntry] { + return [ + testCase(JSValueTests.__allTests__JSValueTests), + testCase(SJavaScriptCoreTests.__allTests__SJavaScriptCoreTests), + ] +} +#endif