From 449c04192bb5530895f4ce0c79167180c417820f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 29 Aug 2022 12:01:20 +0900 Subject: [PATCH 01/14] Bump @actions/core from 1.2.6 to 1.9.1 in /ci/perf-tester (#209) Bumps [@actions/core](https://github.com/actions/toolkit/tree/HEAD/packages/core) from 1.2.6 to 1.9.1. - [Release notes](https://github.com/actions/toolkit/releases) - [Changelog](https://github.com/actions/toolkit/blob/main/packages/core/RELEASES.md) - [Commits](https://github.com/actions/toolkit/commits/HEAD/packages/core) --- updated-dependencies: - dependency-name: "@actions/core" dependency-type: direct:development ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- ci/perf-tester/package-lock.json | 74 ++++++++++++++++++++++++++++---- ci/perf-tester/package.json | 2 +- 2 files changed, 66 insertions(+), 10 deletions(-) diff --git a/ci/perf-tester/package-lock.json b/ci/perf-tester/package-lock.json index c0cbbbdb2..82918bd59 100644 --- a/ci/perf-tester/package-lock.json +++ b/ci/perf-tester/package-lock.json @@ -5,16 +5,20 @@ "packages": { "": { "devDependencies": { - "@actions/core": "^1.2.6", + "@actions/core": "^1.9.1", "@actions/exec": "^1.0.3", "@actions/github": "^2.0.1" } }, "node_modules/@actions/core": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/@actions/core/-/core-1.2.6.tgz", - "integrity": "sha512-ZQYitnqiyBc3D+k7LsgSBmMDVkOVidaagDG7j3fOym77jNunWRuYx7VSHa9GNfFZh+zh61xsCjRj4JxMZlDqTA==", - "dev": true + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/@actions/core/-/core-1.9.1.tgz", + "integrity": "sha512-5ad+U2YGrmmiw6du20AQW5XuWo7UKN2052FjSV7MX+Wfjf8sCqcsZe62NfgHys4QI4/Y+vQvLKYL8jWtA1ZBTA==", + "dev": true, + "dependencies": { + "@actions/http-client": "^2.0.1", + "uuid": "^8.3.2" + } }, "node_modules/@actions/exec": { "version": "1.0.3", @@ -35,6 +39,15 @@ "@octokit/rest": "^16.15.0" } }, + "node_modules/@actions/http-client": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-2.0.1.tgz", + "integrity": "sha512-PIXiMVtz6VvyaRsGY268qvj57hXQEpsYogYOu2nrQhlf+XCGmZstmuZBbAybUl1nQGnvS1k1eEsQ69ZoD7xlSw==", + "dev": true, + "dependencies": { + "tunnel": "^0.0.6" + } + }, "node_modules/@actions/io": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/@actions/io/-/io-1.0.2.tgz", @@ -412,6 +425,15 @@ "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=", "dev": true }, + "node_modules/tunnel": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz", + "integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==", + "dev": true, + "engines": { + "node": ">=0.6.11 <=0.7.0 || >=0.7.3" + } + }, "node_modules/universal-user-agent": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-4.0.0.tgz", @@ -421,6 +443,15 @@ "os-name": "^3.1.0" } }, + "node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "dev": true, + "bin": { + "uuid": "dist/bin/uuid" + } + }, "node_modules/webidl-conversions": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", @@ -470,10 +501,14 @@ }, "dependencies": { "@actions/core": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/@actions/core/-/core-1.2.6.tgz", - "integrity": "sha512-ZQYitnqiyBc3D+k7LsgSBmMDVkOVidaagDG7j3fOym77jNunWRuYx7VSHa9GNfFZh+zh61xsCjRj4JxMZlDqTA==", - "dev": true + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/@actions/core/-/core-1.9.1.tgz", + "integrity": "sha512-5ad+U2YGrmmiw6du20AQW5XuWo7UKN2052FjSV7MX+Wfjf8sCqcsZe62NfgHys4QI4/Y+vQvLKYL8jWtA1ZBTA==", + "dev": true, + "requires": { + "@actions/http-client": "^2.0.1", + "uuid": "^8.3.2" + } }, "@actions/exec": { "version": "1.0.3", @@ -494,6 +529,15 @@ "@octokit/rest": "^16.15.0" } }, + "@actions/http-client": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-2.0.1.tgz", + "integrity": "sha512-PIXiMVtz6VvyaRsGY268qvj57hXQEpsYogYOu2nrQhlf+XCGmZstmuZBbAybUl1nQGnvS1k1eEsQ69ZoD7xlSw==", + "dev": true, + "requires": { + "tunnel": "^0.0.6" + } + }, "@actions/io": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/@actions/io/-/io-1.0.2.tgz", @@ -815,6 +859,12 @@ "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=", "dev": true }, + "tunnel": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz", + "integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==", + "dev": true + }, "universal-user-agent": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-4.0.0.tgz", @@ -824,6 +874,12 @@ "os-name": "^3.1.0" } }, + "uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "dev": true + }, "webidl-conversions": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", diff --git a/ci/perf-tester/package.json b/ci/perf-tester/package.json index 97718ab9a..7a00de44d 100644 --- a/ci/perf-tester/package.json +++ b/ci/perf-tester/package.json @@ -2,7 +2,7 @@ "private": true, "main": "src/index.js", "devDependencies": { - "@actions/core": "^1.2.6", + "@actions/core": "^1.9.1", "@actions/exec": "^1.0.3", "@actions/github": "^2.0.1" } From 73cdff2ec2d42ba37b82b6cb18cd7a9d90822f29 Mon Sep 17 00:00:00 2001 From: Jed Fox Date: Mon, 19 Sep 2022 21:12:59 -0400 Subject: [PATCH 02/14] =?UTF-8?q?Remove=20baseline=20tests=20(e.g.=20?= =?UTF-8?q?=E2=80=9CCall=20JavaScript=20function=20directly=E2=80=9D)=20fr?= =?UTF-8?q?om=20comparison=20(#211)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Remove baseline tests (e.g. “Call JavaScript function directly”) from comparison * ) --- ci/perf-tester/src/utils.js | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/ci/perf-tester/src/utils.js b/ci/perf-tester/src/utils.js index a4b717ab7..c7ecd662b 100644 --- a/ci/perf-tester/src/utils.js +++ b/ci/perf-tester/src/utils.js @@ -168,6 +168,7 @@ exports.diffTable = ( ) => { let changedRows = []; let unChangedRows = []; + let baselineRows = []; let totalTime = 0; let totalDelta = 0; @@ -187,7 +188,9 @@ exports.diffTable = ( getDeltaText(delta, difference), iconForDifference(difference), ]; - if (isUnchanged && collapseUnchanged) { + if (name.includes('directly')) { + baselineRows.push(columns); + } else if (isUnchanged && collapseUnchanged) { unChangedRows.push(columns); } else { changedRows.push(columns); @@ -200,6 +203,11 @@ exports.diffTable = ( const outUnchanged = markdownTable(unChangedRows); out += `\n\n
View Unchanged\n\n${outUnchanged}\n\n
\n\n`; } + + if (baselineRows.length !== 0) { + const outBaseline = markdownTable(baselineRows.map(line => line.slice(0, 2))); + out += `\n\n
View Baselines\n\n${outBaseline}\n\n
\n\n`; + } if (showTotal) { const totalDifference = ((totalDelta / totalTime) * 100) | 0; From e9422fecd4523288fb70be92759009c119bc9db4 Mon Sep 17 00:00:00 2001 From: Yuta Saito Date: Tue, 27 Sep 2022 14:22:55 +0900 Subject: [PATCH 03/14] Add 5.7 toolchain matrix (#210) * Add 5.7 toolchain matrix * Reduce 5.5 toolchain matrix entries * Use stable version --- .github/workflows/test.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 454d580fd..96c36e547 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -18,10 +18,11 @@ jobs: # Ensure that test succeeds with all toolchains and wasi backend combinations - { os: ubuntu-20.04, toolchain: wasm-5.5.0-RELEASE, wasi-backend: Node } - { os: ubuntu-20.04, toolchain: wasm-5.6.0-RELEASE, wasi-backend: Node } - - { os: ubuntu-20.04, toolchain: wasm-5.5.0-RELEASE, wasi-backend: Wasmer } + - { os: ubuntu-20.04, toolchain: wasm-5.7.1-RELEASE, wasi-backend: Node } - { os: ubuntu-20.04, toolchain: wasm-5.6.0-RELEASE, wasi-backend: Wasmer } - - { os: ubuntu-20.04, toolchain: wasm-5.5.0-RELEASE, wasi-backend: MicroWASI } + - { os: ubuntu-20.04, toolchain: wasm-5.7.1-RELEASE, wasi-backend: Wasmer } - { os: ubuntu-20.04, toolchain: wasm-5.6.0-RELEASE, wasi-backend: MicroWASI } + - { os: ubuntu-20.04, toolchain: wasm-5.7.1-RELEASE, wasi-backend: MicroWASI } runs-on: ${{ matrix.entry.os }} steps: From f72b207dc4f330114688861e0ea3922b2480b4b1 Mon Sep 17 00:00:00 2001 From: Yuta Saito Date: Tue, 27 Sep 2022 05:26:54 +0000 Subject: [PATCH 04/14] Add JavaScriptEventLoopTestSupport module to install executor --- Package.swift | 8 ++++++++ .../JavaScriptEventLoopTestSupport.swift | 9 +++++++++ .../_CJavaScriptEventLoopTestSupport.c | 19 +++++++++++++++++++ .../include/dummy.h | 0 4 files changed, 36 insertions(+) create mode 100644 Sources/JavaScriptEventLoopTestSupport/JavaScriptEventLoopTestSupport.swift create mode 100644 Sources/_CJavaScriptEventLoopTestSupport/_CJavaScriptEventLoopTestSupport.c create mode 100644 Sources/_CJavaScriptEventLoopTestSupport/include/dummy.h diff --git a/Package.swift b/Package.swift index d278e5ab9..5902bc9b5 100644 --- a/Package.swift +++ b/Package.swift @@ -26,5 +26,13 @@ let package = Package( dependencies: ["JavaScriptKit", "_CJavaScriptEventLoop"] ), .target(name: "_CJavaScriptEventLoop"), + .target( + name: "JavaScriptEventLoopTestSupport", + dependencies: [ + "_CJavaScriptEventLoopTestSupport", + .product(name: "JavaScriptEventLoop", package: "JavaScriptKit"), + ] + ), + .target(name: "_CJavaScriptEventLoopTestSupport"), ] ) diff --git a/Sources/JavaScriptEventLoopTestSupport/JavaScriptEventLoopTestSupport.swift b/Sources/JavaScriptEventLoopTestSupport/JavaScriptEventLoopTestSupport.swift new file mode 100644 index 000000000..368639304 --- /dev/null +++ b/Sources/JavaScriptEventLoopTestSupport/JavaScriptEventLoopTestSupport.swift @@ -0,0 +1,9 @@ +// This module just expose 'JavaScriptEventLoop.installGlobalExecutor' to C ABI +// See _CJavaScriptEventLoopTestSupport.c for why this is needed + +import JavaScriptEventLoop + +@_cdecl("swift_javascriptkit_activate_js_executor_impl") +func swift_javascriptkit_activate_js_executor_impl() { + JavaScriptEventLoop.installGlobalExecutor() +} diff --git a/Sources/_CJavaScriptEventLoopTestSupport/_CJavaScriptEventLoopTestSupport.c b/Sources/_CJavaScriptEventLoopTestSupport/_CJavaScriptEventLoopTestSupport.c new file mode 100644 index 000000000..7dfdbe2e8 --- /dev/null +++ b/Sources/_CJavaScriptEventLoopTestSupport/_CJavaScriptEventLoopTestSupport.c @@ -0,0 +1,19 @@ +// This 'ctor' function is called at startup time of this program. +// It's invoked by '_start' of command-line or '_initialize' of reactor. +// This ctor activate the event loop based global executor automatically +// before running the test cases. For general applications, applications +// have to activate the event loop manually on their responsibility. +// However, XCTest framework doesn't provide a way to run arbitrary code +// before running all of the test suites. So, we have to do it here. +// +// See also: https://github.com/WebAssembly/WASI/blob/main/legacy/application-abi.md#current-unstable-abi + +extern void swift_javascriptkit_activate_js_executor_impl(void); + +// priority 0~100 is reserved by wasi-libc +// https://github.com/WebAssembly/wasi-libc/blob/30094b6ed05f19cee102115215863d185f2db4f0/libc-bottom-half/sources/environ.c#L20 +__attribute__((constructor(/* priority */ 200))) +void swift_javascriptkit_activate_js_executor(void) { + swift_javascriptkit_activate_js_executor_impl(); +} + diff --git a/Sources/_CJavaScriptEventLoopTestSupport/include/dummy.h b/Sources/_CJavaScriptEventLoopTestSupport/include/dummy.h new file mode 100644 index 000000000..e69de29bb From 6fea6e5d18ae8e62f0576c19d60079c44f30eee7 Mon Sep 17 00:00:00 2001 From: Yuta Saito Date: Fri, 30 Sep 2022 12:47:20 +0000 Subject: [PATCH 05/14] Add short document about JavaScriptEventLoopTestSupport --- README.md | 17 ++++++++++++++++ .../JavaScriptEventLoopTestSupport.swift | 20 +++++++++++++++++-- 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 42af64320..0c2c6988c 100644 --- a/README.md +++ b/README.md @@ -125,6 +125,23 @@ asyncButtonElement.onclick = .object(JSClosure { _ in _ = document.body.appendChild(asyncButtonElement) ``` +### `JavaScriptEventLoop` activation in XCTest suites + +If you need to execute Swift async functions that can be resumed by JS event loop in your XCTest suites, please add `JavaScriptEventLoopTestSupport` to your test target dependencies. + +```diff + .testTarget( + name: "MyAppTests", + dependencies: [ + "MyApp", ++ "JavaScriptEventLoopTestSupport", + ] + ) +``` + +Linking this module automatically activates JS event loop based global executor by calling `JavaScriptEventLoop.installGlobalExecutor()` + + ## Requirements ### For developers diff --git a/Sources/JavaScriptEventLoopTestSupport/JavaScriptEventLoopTestSupport.swift b/Sources/JavaScriptEventLoopTestSupport/JavaScriptEventLoopTestSupport.swift index 368639304..d62979dd9 100644 --- a/Sources/JavaScriptEventLoopTestSupport/JavaScriptEventLoopTestSupport.swift +++ b/Sources/JavaScriptEventLoopTestSupport/JavaScriptEventLoopTestSupport.swift @@ -1,8 +1,24 @@ -// This module just expose 'JavaScriptEventLoop.installGlobalExecutor' to C ABI -// See _CJavaScriptEventLoopTestSupport.c for why this is needed +/// If you need to execute Swift async functions that can be resumed by JS +/// event loop in your XCTest suites, please add `JavaScriptEventLoopTestSupport` +/// to your test target dependencies. +/// +/// ```diff +/// .testTarget( +/// name: "MyAppTests", +/// dependencies: [ +/// "MyApp", +/// + "JavaScriptEventLoopTestSupport", +/// ] +/// ) +/// ``` +/// +/// Linking this module automatically activates JS event loop based global +/// executor by calling `JavaScriptEventLoop.installGlobalExecutor()` import JavaScriptEventLoop +// This module just expose 'JavaScriptEventLoop.installGlobalExecutor' to C ABI +// See _CJavaScriptEventLoopTestSupport.c for why this is needed @_cdecl("swift_javascriptkit_activate_js_executor_impl") func swift_javascriptkit_activate_js_executor_impl() { JavaScriptEventLoop.installGlobalExecutor() From d82c70f3592b4813eae90dd4833d8dcf231c8b02 Mon Sep 17 00:00:00 2001 From: Yuta Saito Date: Fri, 30 Sep 2022 12:50:21 +0000 Subject: [PATCH 06/14] Publish JavaScriptEventLoopTestSupport as a product --- Package.swift | 1 + 1 file changed, 1 insertion(+) diff --git a/Package.swift b/Package.swift index 5902bc9b5..b0b0520de 100644 --- a/Package.swift +++ b/Package.swift @@ -8,6 +8,7 @@ let package = Package( .library(name: "JavaScriptKit", targets: ["JavaScriptKit"]), .library(name: "JavaScriptEventLoop", targets: ["JavaScriptEventLoop"]), .library(name: "JavaScriptBigIntSupport", targets: ["JavaScriptBigIntSupport"]), + .library(name: "JavaScriptEventLoopTestSupport", targets: ["JavaScriptEventLoopTestSupport"]), ], targets: [ .target( From eb9d9f29fa92d277f4db065730a78b85804368d2 Mon Sep 17 00:00:00 2001 From: Yuta Saito Date: Fri, 30 Sep 2022 13:38:11 +0000 Subject: [PATCH 07/14] Add arg0 to wasi arguments because XCTest reads process arguments and it expects at least having one argument --- IntegrationTests/lib.js | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/IntegrationTests/lib.js b/IntegrationTests/lib.js index a0af77527..347348fb9 100644 --- a/IntegrationTests/lib.js +++ b/IntegrationTests/lib.js @@ -9,7 +9,7 @@ const fs = require("fs"); const readFile = promisify(fs.readFile); const WASI = { - Wasmer: () => { + Wasmer: ({ programName }) => { // Instantiate a new WASI Instance const wasmFs = new WasmFs(); // Output stdout and stderr to console @@ -27,7 +27,7 @@ const WASI = { return originalWriteSync(fd, buffer, offset, length, position); }; const wasi = new WasmerWASI({ - args: [], + args: [programName], env: {}, bindings: { ...WasmerWASI.defaultBindings, @@ -44,9 +44,9 @@ const WASI = { } } }, - MicroWASI: () => { + MicroWASI: ({ programName }) => { const wasi = new MicroWASI({ - args: [], + args: [programName], env: {}, features: [useAll()], }) @@ -59,9 +59,9 @@ const WASI = { } } }, - Node: () => { + Node: ({ programName }) => { const wasi = new NodeWASI({ - args: [], + args: [programName], env: {}, returnOnExit: true, }) @@ -91,7 +91,7 @@ const startWasiTask = async (wasmPath, wasiConstructor = selectWASIBackend()) => const swift = new SwiftRuntime(); // Fetch our Wasm File const wasmBinary = await readFile(wasmPath); - const wasi = wasiConstructor(); + const wasi = wasiConstructor({ programName: wasmPath }); // Instantiate the WebAssembly file let { instance } = await WebAssembly.instantiate(wasmBinary, { From 28bb7f2bfed89c781d267b289575a9ce31f52d80 Mon Sep 17 00:00:00 2001 From: Yuta Saito Date: Fri, 30 Sep 2022 13:38:48 +0000 Subject: [PATCH 08/14] Exit process when proc_exit is called on Node.js WASI because Node.js's WASI implementatin does't supprot proc_exit in async reactor model. See https://github.com/nodejs/node/blob/2a4452a53af65a13db4efae474162a7dcfd38dd5/lib/wasi.js#L121 --- IntegrationTests/lib.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/IntegrationTests/lib.js b/IntegrationTests/lib.js index 347348fb9..e708816cb 100644 --- a/IntegrationTests/lib.js +++ b/IntegrationTests/lib.js @@ -63,7 +63,7 @@ const WASI = { const wasi = new NodeWASI({ args: [programName], env: {}, - returnOnExit: true, + returnOnExit: false, }) return { From 08c36d2601b9e21da028115cfffe060d8b406d53 Mon Sep 17 00:00:00 2001 From: Yuta Saito Date: Fri, 30 Sep 2022 13:40:33 +0000 Subject: [PATCH 09/14] Add unit test target for JavaScriptEventLoopTestSupport --- Package.swift | 9 ++++++++- .../JavaScriptEventLoopTestSupportTests.swift | 15 +++++++++++++++ scripts/test-harness.js | 10 ++++++++++ 3 files changed, 33 insertions(+), 1 deletion(-) create mode 100644 Tests/JavaScriptEventLoopTestSupportTests/JavaScriptEventLoopTestSupportTests.swift create mode 100644 scripts/test-harness.js diff --git a/Package.swift b/Package.swift index b0b0520de..c8f55dd0b 100644 --- a/Package.swift +++ b/Package.swift @@ -31,9 +31,16 @@ let package = Package( name: "JavaScriptEventLoopTestSupport", dependencies: [ "_CJavaScriptEventLoopTestSupport", - .product(name: "JavaScriptEventLoop", package: "JavaScriptKit"), + "JavaScriptEventLoop", ] ), .target(name: "_CJavaScriptEventLoopTestSupport"), + .testTarget( + name: "JavaScriptEventLoopTestSupportTests", + dependencies: [ + "JavaScriptKit", + "JavaScriptEventLoopTestSupport" + ] + ), ] ) diff --git a/Tests/JavaScriptEventLoopTestSupportTests/JavaScriptEventLoopTestSupportTests.swift b/Tests/JavaScriptEventLoopTestSupportTests/JavaScriptEventLoopTestSupportTests.swift new file mode 100644 index 000000000..cca303a09 --- /dev/null +++ b/Tests/JavaScriptEventLoopTestSupportTests/JavaScriptEventLoopTestSupportTests.swift @@ -0,0 +1,15 @@ +import XCTest +import JavaScriptKit + +final class JavaScriptEventLoopTestSupportTests: XCTestCase { + func testAwaitMicrotask() async { + let _: () = await withCheckedContinuation { cont in + JSObject.global.queueMicrotask.function!( + JSOneshotClosure { _ in + cont.resume(returning: ()) + return .undefined + } + ) + } + } +} diff --git a/scripts/test-harness.js b/scripts/test-harness.js new file mode 100644 index 000000000..39a7dbe9a --- /dev/null +++ b/scripts/test-harness.js @@ -0,0 +1,10 @@ +Error.stackTraceLimit = Infinity; + +const { startWasiTask, WASI } = require("../IntegrationTests/lib"); + +const handleExitOrError = (error) => { + console.log(error); + process.exit(1); +} + +startWasiTask(process.argv[2]).catch(handleExitOrError); From 0c39b24267aa3fa2095cc9e9c34e0ff0e6cd9ca5 Mon Sep 17 00:00:00 2001 From: Yuta Saito Date: Fri, 30 Sep 2022 13:44:28 +0000 Subject: [PATCH 10/14] Add unit test job in Makefile --- Makefile | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Makefile b/Makefile index bd93f2e60..58ccccdd5 100644 --- a/Makefile +++ b/Makefile @@ -12,6 +12,10 @@ build: .PHONY: test test: + @echo Running unit tests + swift build --build-tests --triple wasm32-unknown-wasi -Xswiftc -Xclang-linker -Xswiftc -mexec-model=reactor -Xlinker --export=main + node --experimental-wasi-unstable-preview1 scripts/test-harness.js ./.build/wasm32-unknown-wasi/debug/JavaScriptKitPackageTests.wasm + @echo Running integration tests cd IntegrationTests && \ CONFIGURATION=debug make test && \ CONFIGURATION=debug SWIFT_BUILD_FLAGS="-Xswiftc -DJAVASCRIPTKIT_WITHOUT_WEAKREFS" make test && \ From 3e94df2cead0ebfa335246414a9a3652dfb4cd49 Mon Sep 17 00:00:00 2001 From: Yuta Saito Date: Fri, 30 Sep 2022 13:48:02 +0000 Subject: [PATCH 11/14] Add API guard directives for native build --- .../JavaScriptEventLoopTestSupport.swift | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Sources/JavaScriptEventLoopTestSupport/JavaScriptEventLoopTestSupport.swift b/Sources/JavaScriptEventLoopTestSupport/JavaScriptEventLoopTestSupport.swift index d62979dd9..9922de945 100644 --- a/Sources/JavaScriptEventLoopTestSupport/JavaScriptEventLoopTestSupport.swift +++ b/Sources/JavaScriptEventLoopTestSupport/JavaScriptEventLoopTestSupport.swift @@ -19,7 +19,13 @@ import JavaScriptEventLoop // This module just expose 'JavaScriptEventLoop.installGlobalExecutor' to C ABI // See _CJavaScriptEventLoopTestSupport.c for why this is needed + +#if compiler(>=5.5) + +@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *) @_cdecl("swift_javascriptkit_activate_js_executor_impl") func swift_javascriptkit_activate_js_executor_impl() { JavaScriptEventLoop.installGlobalExecutor() } + +#endif From b34c15f8e630dd7e85f8a073fcc05305c6efcd36 Mon Sep 17 00:00:00 2001 From: Yuta Saito Date: Fri, 30 Sep 2022 14:01:07 +0000 Subject: [PATCH 12/14] Run async unit tests only with 5.7 toolchain --- .github/workflows/test.yml | 15 ++++++++++----- Makefile | 9 ++++++--- 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 96c36e547..e6b0db563 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -25,22 +25,27 @@ jobs: - { os: ubuntu-20.04, toolchain: wasm-5.7.1-RELEASE, wasi-backend: MicroWASI } runs-on: ${{ matrix.entry.os }} + env: + JAVASCRIPTKIT_WASI_BACKEND: ${{ matrix.entry.wasi-backend }} + SWIFT_VERSION: ${{ matrix.entry.toolchain }} steps: - name: Checkout uses: actions/checkout@master with: fetch-depth: 1 - - name: Run Test - env: - JAVASCRIPTKIT_WASI_BACKEND: ${{ matrix.entry.wasi-backend }} + - name: Install swiftenv run: | git clone https://github.com/kylef/swiftenv.git ~/.swiftenv export SWIFTENV_ROOT="$HOME/.swiftenv" export PATH="$SWIFTENV_ROOT/bin:$PATH" eval "$(swiftenv init -)" - SWIFT_VERSION=${{ matrix.entry.toolchain }} make bootstrap + echo $PATH >> $GITHUB_PATH + env >> $GITHUB_ENV echo ${{ matrix.entry.toolchain }} > .swift-version - make test + - run: make bootstrap + - run: make test + - run: make unittest + if: ${{ startsWith(matrix.toolchain, 'wasm-5.7.') }} - name: Check if SwiftPM resources are stale run: | make regenerate_swiftpm_resources diff --git a/Makefile b/Makefile index 58ccccdd5..7b8736221 100644 --- a/Makefile +++ b/Makefile @@ -12,9 +12,6 @@ build: .PHONY: test test: - @echo Running unit tests - swift build --build-tests --triple wasm32-unknown-wasi -Xswiftc -Xclang-linker -Xswiftc -mexec-model=reactor -Xlinker --export=main - node --experimental-wasi-unstable-preview1 scripts/test-harness.js ./.build/wasm32-unknown-wasi/debug/JavaScriptKitPackageTests.wasm @echo Running integration tests cd IntegrationTests && \ CONFIGURATION=debug make test && \ @@ -22,6 +19,12 @@ test: CONFIGURATION=release make test && \ CONFIGURATION=release SWIFT_BUILD_FLAGS="-Xswiftc -DJAVASCRIPTKIT_WITHOUT_WEAKREFS" make test +.PHONY: unittest +unittest: + @echo Running unit tests + swift build --build-tests --triple wasm32-unknown-wasi -Xswiftc -Xclang-linker -Xswiftc -mexec-model=reactor -Xlinker --export=main + node --experimental-wasi-unstable-preview1 scripts/test-harness.js ./.build/wasm32-unknown-wasi/debug/JavaScriptKitPackageTests.wasm + .PHONY: benchmark_setup benchmark_setup: cd IntegrationTests && CONFIGURATION=release make benchmark_setup From d0f49adff30ba0bfef2117a33dc6501341264a41 Mon Sep 17 00:00:00 2001 From: Yuta Saito Date: Mon, 3 Oct 2022 12:06:07 +0000 Subject: [PATCH 13/14] Expose JavaScriptEventLoop.queueMicrotask and .setTimeout This allows users to have more flexibility to customize. For example, this allows inserting operations before/after single job execution loop. e.g. It's useful to enable React batch rendering per job execution loop by `ReactDOM.unstable_batchedUpdates`. ```swift let original = JavaScriptEventLoop.shared.queueMicrotask JavaScriptEventLoop.shared.queueMicrotask = (job) => { ReactDOM.unstable_batchedUpdates(() => { original(job) }) } ``` --- Sources/JavaScriptEventLoop/JavaScriptEventLoop.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Sources/JavaScriptEventLoop/JavaScriptEventLoop.swift b/Sources/JavaScriptEventLoop/JavaScriptEventLoop.swift index d8f4ad0ad..7c4a1c905 100644 --- a/Sources/JavaScriptEventLoop/JavaScriptEventLoop.swift +++ b/Sources/JavaScriptEventLoop/JavaScriptEventLoop.swift @@ -39,9 +39,9 @@ public final class JavaScriptEventLoop: SerialExecutor, @unchecked Sendable { /// A function that queues a given closure as a microtask into JavaScript event loop. /// See also: https://developer.mozilla.org/en-US/docs/Web/API/HTML_DOM_API/Microtask_guide - let queueMicrotask: @Sendable (@escaping () -> Void) -> Void + public var queueMicrotask: @Sendable (@escaping () -> Void) -> Void /// A function that invokes a given closure after a specified number of milliseconds. - let setTimeout: @Sendable (Double, @escaping () -> Void) -> Void + public var setTimeout: @Sendable (Double, @escaping () -> Void) -> Void /// A mutable state to manage internal job queue /// Note that this should be guarded atomically when supporting multi-threaded environment. From dac9d7b0342c5027fc74c8d2f212f10624123a7b Mon Sep 17 00:00:00 2001 From: Yuta Saito Date: Mon, 3 Oct 2022 17:45:34 +0000 Subject: [PATCH 14/14] Bump version to 0.17.0, update `CHANGELOG.md` --- CHANGELOG.md | 18 ++++++++++++++++++ Example/package-lock.json | 2 +- package-lock.json | 4 ++-- package.json | 2 +- 4 files changed, 22 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 17f460cd5..d0d336ed5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,21 @@ +# 0.17.0 (4 Oct 2022) + +This release introduces testing support module, minor API enhancements for `JavaScriptEventLoop`. + +Linking the new `JavaScriptEventLoopTestSupport` module automatically activates JS event loop based global executor. +This automatic activation is just for XCTest integration since XCTest with SwiftPM doesn't allow to call `JavaScriptEventLoop.installGlobalExecutor()` at first. + +## What's Changed + +* Bump @actions/core from 1.2.6 to 1.9.1 in /ci/perf-tester by @dependabot in https://github.com/swiftwasm/JavaScriptKit/pull/209 +* Remove baseline tests (e.g. “Call JavaScript function directly”) from comparison by @j-f1 in https://github.com/swiftwasm/JavaScriptKit/pull/211 +* Add 5.7 toolchain matrix by @kateinoigakukun in https://github.com/swiftwasm/JavaScriptKit/pull/210 +* Add JavaScriptEventLoopTestSupport module to install executor by @kateinoigakukun in https://github.com/swiftwasm/JavaScriptKit/pull/213 +* Expose `JavaScriptEventLoop.queueMicrotask` and `.setTimeout` by @kateinoigakukun in https://github.com/swiftwasm/JavaScriptKit/pull/214 + + +**Full Changelog**: https://github.com/swiftwasm/JavaScriptKit/compare/0.16.0...0.17.0 + # 0.16.0 (22 Aug 2022) This release contains significant performance improvements, API enhancements for `JSPromise` / `JSBigInt` / `JSClosure`, and documentation improvements. diff --git a/Example/package-lock.json b/Example/package-lock.json index b112f5885..24b287a21 100644 --- a/Example/package-lock.json +++ b/Example/package-lock.json @@ -21,7 +21,7 @@ }, "..": { "name": "javascript-kit-swift", - "version": "0.16.0", + "version": "0.17.0", "license": "MIT", "devDependencies": { "@rollup/plugin-typescript": "^8.3.1", diff --git a/package-lock.json b/package-lock.json index 7d66e97ec..dcc23dc1b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "javascript-kit-swift", - "version": "0.16.0", + "version": "0.17.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "javascript-kit-swift", - "version": "0.16.0", + "version": "0.17.0", "license": "MIT", "devDependencies": { "@rollup/plugin-typescript": "^8.3.1", diff --git a/package.json b/package.json index c4d459201..8bd772b21 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "javascript-kit-swift", - "version": "0.16.0", + "version": "0.17.0", "description": "A runtime library of JavaScriptKit which is Swift framework to interact with JavaScript through WebAssembly.", "main": "Runtime/lib/index.js", "module": "Runtime/lib/index.mjs",