Skip to content

Follow-up adjustment for Embedded support #265

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 4 commits into from
Oct 15, 2024
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
16 changes: 16 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -86,3 +86,19 @@ jobs:
- run: swift build
env:
DEVELOPER_DIR: /Applications/${{ matrix.xcode }}.app/Contents/Developer/

embedded-build:
name: Build for embedded target
runs-on: ubuntu-22.04
strategy:
matrix:
entry:
- os: ubuntu-22.04
toolchain: DEVELOPMENT-SNAPSHOT-2024-09-25-a
steps:
- uses: actions/checkout@v4
- uses: ./.github/actions/install-swift
with:
swift-dir: development/ubuntu2204
swift-version: swift-${{ matrix.entry.toolchain }}
- run: ./Examples/Embedded/build.sh
21 changes: 19 additions & 2 deletions Examples/Embedded/Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,31 @@ let package = Package(
name: "Embedded",
dependencies: [
.package(name: "JavaScriptKit", path: "../../"),
.package(url: "https://github.com/swifweb/EmbeddedFoundation", branch: "0.1.0")
.package(url: "https://github.com/swiftwasm/swift-dlmalloc", branch: "0.1.0")
],
targets: [
.executableTarget(
name: "EmbeddedApp",
dependencies: [
"JavaScriptKit",
.product(name: "Foundation", package: "EmbeddedFoundation")
.product(name: "dlmalloc", package: "swift-dlmalloc")
],
cSettings: [
.unsafeFlags(["-fdeclspec"])
],
swiftSettings: [
.enableExperimentalFeature("Embedded"),
.enableExperimentalFeature("Extern"),
.unsafeFlags([
"-Xfrontend", "-gnone",
"-Xfrontend", "-disable-stack-protector",
]),
],
linkerSettings: [
.unsafeFlags([
"-Xclang-linker", "-nostdlib",
"-Xlinker", "--no-entry"
])
]
)
]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,9 @@ func strlen(_ s: UnsafePointer<Int8>) -> Int {
return p - s
}

// TODO: why do I need this? and surely this is not ideal... figure this out, or at least have this come from a C lib
@_cdecl("memmove")
func memmove(_ dest: UnsafeMutableRawPointer, _ src: UnsafeRawPointer, _ n: Int) -> UnsafeMutableRawPointer {
let d = dest.assumingMemoryBound(to: UInt8.self)
let s = src.assumingMemoryBound(to: UInt8.self)
for i in 0..<n {
d[i] = s[i]
@_cdecl("arc4random_buf")
public func arc4random_buf(_ buffer: UnsafeMutableRawPointer, _ size: Int) {
for i in 0..<size {
buffer.storeBytes(of: UInt8.random(in: 0...255), toByteOffset: i, as: UInt8.self)
}
return dest
}
}
10 changes: 4 additions & 6 deletions Examples/Embedded/build.sh
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
EXPERIMENTAL_EMBEDDED_WASM=true swift build -c release --product EmbeddedApp \
#!/bin/bash
package_dir="$(cd "$(dirname "$0")" && pwd)"
JAVASCRIPTKIT_EXPERIMENTAL_EMBEDDED_WASM=true swift build --package-path "$package_dir" -c release --product EmbeddedApp \
--triple wasm32-unknown-none-wasm \
-Xswiftc -enable-experimental-feature -Xswiftc Embedded \
-Xswiftc -enable-experimental-feature -Xswiftc Extern \
-Xswiftc -wmo -Xswiftc -disable-cmo \
-Xswiftc -Xfrontend -Xswiftc -gnone \
-Xswiftc -Xfrontend -Xswiftc -disable-stack-protector \
-Xswiftc -cxx-interoperability-mode=default \
-Xcc -D__Embedded -Xcc -fdeclspec \
-Xlinker --export-if-defined=__main_argc_argv \
-Xlinker --export-if-defined=swjs_call_host_function \
-Xswiftc -Xclang-linker -Xswiftc -mexec-model=reactor
-Xswiftc -Xclang-linker -Xswiftc -mexec-model=reactor
2 changes: 1 addition & 1 deletion Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import PackageDescription
import Foundation

// NOTE: needed for embedded customizations, ideally this will not be necessary at all in the future, or can be replaced with traits
let shouldBuildForEmbedded = ProcessInfo.processInfo.environment["EXPERIMENTAL_EMBEDDED_WASM"].flatMap(Bool.init) ?? false
let shouldBuildForEmbedded = ProcessInfo.processInfo.environment["JAVASCRIPTKIT_EXPERIMENTAL_EMBEDDED_WASM"].flatMap(Bool.init) ?? false

let package = Package(
name: "JavaScriptKit",
Expand Down
12 changes: 8 additions & 4 deletions Sources/JavaScriptKit/ConstructibleFromJSValue.swift
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ extension SignedInteger where Self: ConstructibleFromJSValue {
/// If the value is too large to fit in the `Self` type, `nil` is returned.
///
/// - Parameter bigInt: The `JSBigIntExtended` to decode
public init?(exactly bigInt: JSBigIntExtended) {
public init?(exactly bigInt: some JSBigIntExtended) {
self.init(exactly: bigInt.int64Value)
}

Expand All @@ -49,7 +49,7 @@ extension SignedInteger where Self: ConstructibleFromJSValue {
/// Crash if the value is too large to fit in the `Self` type.
///
/// - Parameter bigInt: The `JSBigIntExtended` to decode
public init(_ bigInt: JSBigIntExtended) {
public init(_ bigInt: some JSBigIntExtended) {
self.init(bigInt.int64Value)
}

Expand All @@ -68,9 +68,11 @@ extension SignedInteger where Self: ConstructibleFromJSValue {
if let number = value.number {
return Self(exactly: number.rounded(.towardZero))
}
#if !hasFeature(Embedded)
if let bigInt = value.bigInt as? JSBigIntExtended {
return Self(exactly: bigInt)
}
#endif
return nil
}
}
Expand All @@ -87,7 +89,7 @@ extension UnsignedInteger where Self: ConstructibleFromJSValue {
/// Returns `nil` if the value is negative or too large to fit in the `Self` type.
///
/// - Parameter bigInt: The `JSBigIntExtended` to decode
public init?(exactly bigInt: JSBigIntExtended) {
public init?(exactly bigInt: some JSBigIntExtended) {
self.init(exactly: bigInt.uInt64Value)
}

Expand All @@ -96,7 +98,7 @@ extension UnsignedInteger where Self: ConstructibleFromJSValue {
/// Crash if the value is negative or too large to fit in the `Self` type.
///
/// - Parameter bigInt: The `JSBigIntExtended` to decode
public init(_ bigInt: JSBigIntExtended) {
public init(_ bigInt: some JSBigIntExtended) {
self.init(bigInt.uInt64Value)
}

Expand All @@ -114,9 +116,11 @@ extension UnsignedInteger where Self: ConstructibleFromJSValue {
if let number = value.number {
return Self(exactly: number.rounded(.towardZero))
}
#if !hasFeature(Embedded)
if let bigInt = value.bigInt as? JSBigIntExtended {
return Self(exactly: bigInt)
}
#endif
return nil
}
}
Expand Down
24 changes: 7 additions & 17 deletions Sources/JavaScriptKit/FundamentalObjects/JSFunction.swift
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ public class JSFunction: JSObject, _JSFunctionProtocol {
id, argv, Int32(argc),
&payload1, &payload2
)
let kindAndFlags = valueKindAndFlagsFromBits(resultBitPattern)
let kindAndFlags = JavaScriptValueKindAndFlags(bitPattern: resultBitPattern)
assert(!kindAndFlags.isException)
let result = RawJSValue(kind: kindAndFlags.kind, payload1: payload1, payload2: payload2)
return result
Expand All @@ -153,7 +153,7 @@ public class JSFunction: JSObject, _JSFunctionProtocol {
id, argv, Int32(argc),
&payload1, &payload2
)
let kindAndFlags = valueKindAndFlagsFromBits(resultBitPattern)
let kindAndFlags = JavaScriptValueKindAndFlags(bitPattern: resultBitPattern)
#if !hasFeature(Embedded)
assert(!kindAndFlags.isException)
#endif
Expand Down Expand Up @@ -241,25 +241,15 @@ public extension _JSFunctionProtocol {
new(arguments: [arg0.jsValue, arg1.jsValue, arg2.jsValue, arg3.jsValue, arg4.jsValue, arg5.jsValue, arg6.jsValue])
}
}
#endif

// C bit fields seem to not work with Embedded
// in "normal mode" this is defined as a C struct
private struct JavaScriptValueKindAndFlags {
let errorBit: UInt32 = 1 << 32
internal struct JavaScriptValueKindAndFlags {
static var errorBit: UInt32 { 1 << 31 }
let kind: JavaScriptValueKind
let isException: Bool

init(bitPattern: UInt32) {
self.kind = JavaScriptValueKind(rawValue: bitPattern & ~errorBit)!
self.isException = (bitPattern & errorBit) != 0
self.kind = JavaScriptValueKind(rawValue: bitPattern & ~Self.errorBit)!
self.isException = (bitPattern & Self.errorBit) != 0
}
}
#endif

private func valueKindAndFlagsFromBits(_ bits: UInt32) -> JavaScriptValueKindAndFlags {
#if hasFeature(Embedded)
JavaScriptValueKindAndFlags(bitPattern: bits)
#else
unsafeBitCast(bits, to: JavaScriptValueKindAndFlags.self)
#endif
}
Original file line number Diff line number Diff line change
Expand Up @@ -42,13 +42,14 @@ public class JSThrowingFunction {
let argv = bufferPointer.baseAddress
let argc = bufferPointer.count

var exceptionKind = JavaScriptValueKindAndFlags()
var exceptionRawKind = JavaScriptRawValueKindAndFlags()
var exceptionPayload1 = JavaScriptPayload1()
var exceptionPayload2 = JavaScriptPayload2()
let resultObj = swjs_call_throwing_new(
self.base.id, argv, Int32(argc),
&exceptionKind, &exceptionPayload1, &exceptionPayload2
&exceptionRawKind, &exceptionPayload1, &exceptionPayload2
)
let exceptionKind = JavaScriptValueKindAndFlags(bitPattern: exceptionRawKind)
if exceptionKind.isException {
let exception = RawJSValue(kind: exceptionKind.kind, payload1: exceptionPayload1, payload2: exceptionPayload2)
return .failure(exception.jsValue)
Expand All @@ -70,21 +71,21 @@ private func invokeJSFunction(_ jsFunc: JSFunction, arguments: [ConvertibleToJSV
rawValues.withUnsafeBufferPointer { bufferPointer -> (JSValue, Bool) in
let argv = bufferPointer.baseAddress
let argc = bufferPointer.count
var kindAndFlags = JavaScriptValueKindAndFlags()
let kindAndFlags: JavaScriptValueKindAndFlags
var payload1 = JavaScriptPayload1()
var payload2 = JavaScriptPayload2()
if let thisId = this?.id {
let resultBitPattern = swjs_call_function_with_this(
thisId, id, argv, Int32(argc),
&payload1, &payload2
)
kindAndFlags = unsafeBitCast(resultBitPattern, to: JavaScriptValueKindAndFlags.self)
kindAndFlags = JavaScriptValueKindAndFlags(bitPattern: resultBitPattern)
} else {
let resultBitPattern = swjs_call_function(
id, argv, Int32(argc),
&payload1, &payload2
)
kindAndFlags = unsafeBitCast(resultBitPattern, to: JavaScriptValueKindAndFlags.self)
kindAndFlags = JavaScriptValueKindAndFlags(bitPattern: resultBitPattern)
}
let result = RawJSValue(kind: kindAndFlags.kind, payload1: payload1, payload2: payload2)
return (result.jsValue, kindAndFlags.isException)
Expand All @@ -95,4 +96,4 @@ private func invokeJSFunction(_ jsFunc: JSFunction, arguments: [ConvertibleToJSV
}
return result
}
#endif
#endif
12 changes: 2 additions & 10 deletions Sources/_CJavaScriptKit/include/_CJavaScriptKit.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,15 +29,7 @@ typedef enum __attribute__((enum_extensibility(closed))) {
JavaScriptValueKindBigInt = 8,
} JavaScriptValueKind;

#if __Embedded
// something about the bit field widths is not working with embedded
typedef unsigned short JavaScriptValueKindAndFlags;
#else
typedef struct {
JavaScriptValueKind kind: 31;
bool isException: 1;
} JavaScriptValueKindAndFlags;
#endif
typedef uint32_t JavaScriptRawValueKindAndFlags;

typedef unsigned JavaScriptPayload1;
typedef double JavaScriptPayload2;
Expand Down Expand Up @@ -253,7 +245,7 @@ IMPORT_JS_FUNCTION(swjs_call_new, JavaScriptObjectRef, (const JavaScriptObjectRe
IMPORT_JS_FUNCTION(swjs_call_throwing_new, JavaScriptObjectRef, (const JavaScriptObjectRef ref,
const RawJSValue *argv,
const int argc,
JavaScriptValueKindAndFlags *exception_kind,
JavaScriptRawValueKindAndFlags *exception_kind,
JavaScriptPayload1 *exception_payload1,
JavaScriptPayload2 *exception_payload2))

Expand Down
Loading