From b290c1d9c86cea5a39fe929d9af68b61ba9a6842 Mon Sep 17 00:00:00 2001 From: toyobayashi Date: Sun, 28 Jan 2024 23:21:28 +0800 Subject: [PATCH 01/15] feat: `node-gyp build` with make generator on Windows --- lib/build.js | 18 ++++++++++++------ lib/configure.js | 14 ++++++++++++-- 2 files changed, 24 insertions(+), 8 deletions(-) diff --git a/lib/build.js b/lib/build.js index 6b8d84d3ed..07779f8df1 100644 --- a/lib/build.js +++ b/lib/build.js @@ -85,18 +85,24 @@ async function build (gyp, argv) { async function findSolutionFile () { const files = await glob('build/*.sln') if (files.length === 0) { - throw new Error('Could not find *.sln file. Did you run "configure"?') + if (require('fs').existsSync('build/Makefile') || (await glob('build/*.mk')).length !== 0) { + command = makeCommand + await doWhich(false) + return + } else { + throw new Error('Could not find *.sln file or Makefile. Did you run "configure"?') + } } guessedSolution = files[0] log.verbose('found first Solution file', guessedSolution) - await doWhich() + await doWhich(true) } /** * Uses node-which to locate the msbuild / make executable. */ - async function doWhich () { + async function doWhich (win) { // On Windows use msbuild provided by node-gyp configure if (win) { if (!config.variables.msbuild_path) { @@ -104,21 +110,21 @@ async function build (gyp, argv) { } command = config.variables.msbuild_path log.verbose('using MSBuild:', command) - await doBuild() + await doBuild(win) return } // First make sure we have the build command in the PATH const execPath = await which(command) log.verbose('`which` succeeded for `' + command + '`', execPath) - await doBuild() + await doBuild(win) } /** * Actually spawn the process and compile the module. */ - async function doBuild () { + async function doBuild (win) { // Enable Verbose build const verbose = log.logger.isVisible('verbose') let j diff --git a/lib/configure.js b/lib/configure.js index e4b8c94e3d..b0fe7ec32f 100644 --- a/lib/configure.js +++ b/lib/configure.js @@ -92,8 +92,18 @@ async function configure (gyp, argv) { log.verbose( 'build dir', '"build" dir needed to be created?', isNew ? 'Yes' : 'No' ) - const vsInfo = win ? await findVisualStudio(release.semver, gyp.opts['msvs-version']) : null - return createConfigFile(vsInfo) + if (win) { + let gypFormatIndex = argv.indexOf('-f') + if (gypFormatIndex === -1) { + gypFormatIndex = argv.indexOf('--format') + } + if (gypFormatIndex === -1 || !argv[gypFormatIndex + 1] || argv[gypFormatIndex + 1] === 'msvs') { + const vsInfo = await findVisualStudio(release.semver, gyp.opts['msvs-version']) + return createConfigFile(vsInfo) + } + return createConfigFile({}) + } + return createConfigFile(null) } async function createConfigFile (vsInfo) { From 67a185e6f3261a8ed0f6119cc58d5e500fb3d347 Mon Sep 17 00:00:00 2001 From: toyobayashi Date: Sun, 28 Jan 2024 23:28:04 +0800 Subject: [PATCH 02/15] do not add symlinks to `%Path%` --- lib/build.js | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/lib/build.js b/lib/build.js index 07779f8df1..fef817ea0a 100644 --- a/lib/build.js +++ b/lib/build.js @@ -102,48 +102,48 @@ async function build (gyp, argv) { * Uses node-which to locate the msbuild / make executable. */ - async function doWhich (win) { + async function doWhich (msvs) { // On Windows use msbuild provided by node-gyp configure - if (win) { + if (msvs) { if (!config.variables.msbuild_path) { throw new Error('MSBuild is not set, please run `node-gyp configure`.') } command = config.variables.msbuild_path log.verbose('using MSBuild:', command) - await doBuild(win) + await doBuild(msvs) return } // First make sure we have the build command in the PATH const execPath = await which(command) log.verbose('`which` succeeded for `' + command + '`', execPath) - await doBuild(win) + await doBuild(msvs) } /** * Actually spawn the process and compile the module. */ - async function doBuild (win) { + async function doBuild (msvs) { // Enable Verbose build const verbose = log.logger.isVisible('verbose') let j - if (!win && verbose) { + if (!msvs && verbose) { argv.push('V=1') } - if (win && !verbose) { + if (msvs && !verbose) { argv.push('/clp:Verbosity=minimal') } - if (win) { + if (msvs) { // Turn off the Microsoft logo on Windows argv.push('/nologo') } // Specify the build type, Release by default - if (win) { + if (msvs) { // Convert .gypi config target_arch to MSBuild /Platform // Since there are many ways to state '32-bit Intel', default to it. // N.B. msbuild's Condition string equality tests are case-insensitive. @@ -179,7 +179,7 @@ async function build (gyp, argv) { } } - if (win) { + if (msvs) { // did the user specify their own .sln file? const hasSln = argv.some(function (arg) { return path.extname(arg) === '.sln' From 695f93b133adfcc5cac04c1d7f9a20ad884bfca1 Mon Sep 17 00:00:00 2001 From: toyobayashi Date: Mon, 29 Jan 2024 00:42:52 +0800 Subject: [PATCH 03/15] also try to find visual studio if format is not msvs --- lib/configure.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/configure.js b/lib/configure.js index b0fe7ec32f..af1cb50599 100644 --- a/lib/configure.js +++ b/lib/configure.js @@ -101,7 +101,11 @@ async function configure (gyp, argv) { const vsInfo = await findVisualStudio(release.semver, gyp.opts['msvs-version']) return createConfigFile(vsInfo) } - return createConfigFile({}) + let vsInfo = {} + try { + vsInfo = await findVisualStudio(release.semver, gyp.opts['msvs-version']) + } catch (_) {} + return createConfigFile(vsInfo) } return createConfigFile(null) } From 36548327cc639a083b3b1a575bf0194fbdd9da93 Mon Sep 17 00:00:00 2001 From: toyobayashi Date: Tue, 30 Jan 2024 18:35:38 +0800 Subject: [PATCH 04/15] format can include flavor so use startsWith --- lib/configure.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/configure.js b/lib/configure.js index af1cb50599..25987bbb51 100644 --- a/lib/configure.js +++ b/lib/configure.js @@ -97,7 +97,7 @@ async function configure (gyp, argv) { if (gypFormatIndex === -1) { gypFormatIndex = argv.indexOf('--format') } - if (gypFormatIndex === -1 || !argv[gypFormatIndex + 1] || argv[gypFormatIndex + 1] === 'msvs') { + if (gypFormatIndex === -1 || !argv[gypFormatIndex + 1] || argv[gypFormatIndex + 1].startsWith('msvs')) { const vsInfo = await findVisualStudio(release.semver, gyp.opts['msvs-version']) return createConfigFile(vsInfo) } From fbd3939c7b1d000ea4e99aa65e959ba87b5a8e07 Mon Sep 17 00:00:00 2001 From: toyobayashi Date: Tue, 4 Jun 2024 21:20:53 +0800 Subject: [PATCH 05/15] exclude make generator --- lib/configure.js | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/lib/configure.js b/lib/configure.js index 25987bbb51..ee672cfbf2 100644 --- a/lib/configure.js +++ b/lib/configure.js @@ -93,18 +93,24 @@ async function configure (gyp, argv) { 'build dir', '"build" dir needed to be created?', isNew ? 'Yes' : 'No' ) if (win) { - let gypFormatIndex = argv.indexOf('-f') - if (gypFormatIndex === -1) { - gypFormatIndex = argv.indexOf('--format') - } - if (gypFormatIndex === -1 || !argv[gypFormatIndex + 1] || argv[gypFormatIndex + 1].startsWith('msvs')) { - const vsInfo = await findVisualStudio(release.semver, gyp.opts['msvs-version']) - return createConfigFile(vsInfo) + let usingMakeGenerator = false + for (let i = argv.length - 1; i >= 0; --i) { + const arg = argv[i] + if (arg === '-f' || arg === '--format') { + const format = argv[i + 1] + if (typeof format === 'string' && format.startsWith('make')) { + usingMakeGenerator = true + break + } + } else if (arg.startsWith('--format=make')) { + usingMakeGenerator = true + break + } } let vsInfo = {} - try { + if (!usingMakeGenerator) { vsInfo = await findVisualStudio(release.semver, gyp.opts['msvs-version']) - } catch (_) {} + } return createConfigFile(vsInfo) } return createConfigFile(null) From f6ee1bb938e1ec4f43be631d6458c02676efc259 Mon Sep 17 00:00:00 2001 From: toyobayashi Date: Thu, 6 Jun 2024 22:11:41 +0800 Subject: [PATCH 06/15] hoist fs --- lib/build.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/build.js b/lib/build.js index fef817ea0a..e1f49bb6ff 100644 --- a/lib/build.js +++ b/lib/build.js @@ -1,6 +1,7 @@ 'use strict' -const fs = require('graceful-fs').promises +const gracefulFs = require('graceful-fs') +const fs = gracefulFs.promises const path = require('path') const { glob } = require('glob') const log = require('./log') @@ -85,7 +86,7 @@ async function build (gyp, argv) { async function findSolutionFile () { const files = await glob('build/*.sln') if (files.length === 0) { - if (require('fs').existsSync('build/Makefile') || (await glob('build/*.mk')).length !== 0) { + if (gracefulFs.existsSync('build/Makefile') || (await glob('build/*.mk')).length !== 0) { command = makeCommand await doWhich(false) return From 664dbb67e46aac43f194389e1cce784fe55d86c4 Mon Sep 17 00:00:00 2001 From: toyobayashi Date: Fri, 7 Jun 2024 12:06:26 +0800 Subject: [PATCH 07/15] test: add wasm test ignore emsdk temporarily remove wasi test add wasi test back --experimental-wasi-unstable-preview1 test separate wasm test run test in bash on windows fix python path --- .github/workflows/tests.yml | 30 +++++- package.json | 3 + test/node_modules/hello_wasm/binding.gyp | 62 +++++++++++ test/node_modules/hello_wasm/hello.c | 21 ++++ test/node_modules/hello_wasm/hello.js | 50 +++++++++ test/node_modules/hello_wasm/package.json | 16 +++ test/test-wasm.js | 126 ++++++++++++++++++++++ 7 files changed, 305 insertions(+), 3 deletions(-) create mode 100644 test/node_modules/hello_wasm/binding.gyp create mode 100644 test/node_modules/hello_wasm/hello.c create mode 100644 test/node_modules/hello_wasm/hello.js create mode 100644 test/node_modules/hello_wasm/package.json create mode 100644 test/test-wasm.js diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 1e8e8bc8cb..0dcac943be 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -102,6 +102,12 @@ jobs: node: 20.x name: ${{ matrix.os }} - ${{ matrix.python }} - ${{ matrix.node }} runs-on: ${{ matrix.os }} + env: + WASI_VERSION: '22' + WASI_VERSION_FULL: '22.0' + WASI_SDK_PATH: 'wasi-sdk-22.0' + EM_VERSION: '3.1.52' + EM_CACHE_FOLDER: 'emsdk-cache' steps: - name: Checkout Repository uses: actions/checkout@v4 @@ -116,6 +122,24 @@ jobs: env: PYTHON_VERSION: ${{ matrix.python }} # Why do this? - uses: seanmiddleditch/gha-setup-ninja@v4 + - uses: mymindstorm/setup-emsdk@v14 + with: + version: ${{ env.EM_VERSION }} + actions-cache-folder: ${{ env.EM_CACHE_FOLDER }} + - name: Install wasi-sdk (macOS or Linux) + shell: bash + if: ${{ !startsWith(matrix.os, 'windows') }} + run: | + wget -q https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-${WASI_VERSION}/wasi-sdk-${WASI_VERSION_FULL}-${{ startsWith(matrix.os, 'macos') && 'macos' || 'linux' }}.tar.gz + mkdir -p $WASI_SDK_PATH + tar zxvf wasi-sdk-${WASI_VERSION_FULL}-${{ startsWith(matrix.os, 'macos') && 'macos' || 'linux' }}.tar.gz -C $WASI_SDK_PATH --strip 1 + - name: Install wasi-sdk (Windows) + shell: pwsh + if: ${{ startsWith(matrix.os, 'windows') }} + run: | + Start-BitsTransfer -Source https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-${env:WASI_VERSION}/wasi-sdk-${env:WASI_VERSION_FULL}.m-mingw.tar.gz + New-Item -ItemType Directory -Path ${env:WASI_SDK_PATH} + tar -zxvf wasi-sdk-${env:WASI_VERSION_FULL}.m-mingw.tar.gz -C ${env:WASI_SDK_PATH} --strip 1 - name: Install Dependencies run: | npm install @@ -126,7 +150,7 @@ jobs: echo 'GYP_MSVS_VERSION=2015' >> $Env:GITHUB_ENV echo 'GYP_MSVS_OVERRIDE_PATH=C:\\Dummy' >> $Env:GITHUB_ENV - name: Run Python Tests - run: python -m pytest + run: python -m pytest --ignore=${{ env.EM_CACHE_FOLDER }} - name: Run Tests (macOS or Linux) if: "!startsWith(matrix.os, 'windows')" shell: bash @@ -135,7 +159,7 @@ jobs: FULL_TEST: ${{ (matrix.node == '20.x' && matrix.python == '3.12') && '1' || '0' }} - name: Run Tests (Windows) if: startsWith(matrix.os, 'windows') - shell: pwsh - run: npm run test --python="${env:pythonLocation}\\python.exe" + shell: bash # Building wasm on Windows requires using make generator, it only works in bash + run: npm run test --python="${pythonLocation}\\python.exe" env: FULL_TEST: ${{ (matrix.node == '20.x' && matrix.python == '3.12') && '1' || '0' }} diff --git a/package.json b/package.json index e9402d7923..a94917cf0a 100644 --- a/package.json +++ b/package.json @@ -37,8 +37,11 @@ "node": "^16.14.0 || >=18.0.0" }, "devDependencies": { + "@emnapi/core": "^1.2.0", + "@emnapi/runtime": "^1.2.0", "bindings": "^1.5.0", "cross-env": "^7.0.3", + "emnapi": "^1.2.0", "mocha": "^10.2.0", "nan": "^2.14.2", "require-inject": "^1.4.4", diff --git a/test/node_modules/hello_wasm/binding.gyp b/test/node_modules/hello_wasm/binding.gyp new file mode 100644 index 0000000000..cc8a21694e --- /dev/null +++ b/test/node_modules/hello_wasm/binding.gyp @@ -0,0 +1,62 @@ +{ + "targets": [ + { + "target_name": "hello", + "sources": [ "hello.c" ], + "conditions": [ + [ + "OS == 'emscripten'", + { + "product_extension": "node.js", + "ldflags": [ + '-sMODULARIZE=1', + '-sEXPORT_NAME=hello', + '-sWASM_ASYNC_COMPILATION=0' + ], + 'xcode_settings': { + 'OTHER_LDFLAGS': [ + '-sMODULARIZE=1', + '-sEXPORT_NAME=hello', + '-sWASM_ASYNC_COMPILATION=0' + ] + }, + 'conditions': [ + ['emnapi_manual_linking != 0', { + 'dependencies': [ + ' + +#if !defined(__wasm__) || (defined(__EMSCRIPTEN__) || defined(__wasi__)) +#include +#else +#define assert(x) do { if (!(x)) { __builtin_trap(); } } while (0) +#endif + +static napi_value hello(napi_env env, napi_callback_info info) { + napi_value greeting; + assert(napi_ok == napi_create_string_utf8(env, "world", NAPI_AUTO_LENGTH, &greeting)); + return greeting; +} + +NAPI_MODULE_INIT() { + napi_value hello_function; + assert(napi_ok == napi_create_function(env, "hello", NAPI_AUTO_LENGTH, + hello, NULL, &hello_function)); + assert(napi_ok == napi_set_named_property(env, exports, "hello", hello_function)); + return exports; +} diff --git a/test/node_modules/hello_wasm/hello.js b/test/node_modules/hello_wasm/hello.js new file mode 100644 index 0000000000..efd5987331 --- /dev/null +++ b/test/node_modules/hello_wasm/hello.js @@ -0,0 +1,50 @@ +const path = require('path') +const fs = require('fs') + +const addon = (function () { + const entry = (() => { + try { + return require.resolve('./build/Release/hello.node') + } catch (_) { + return require.resolve('./build/Release/hello.wasm') + } + })() + + const ext = path.extname(entry) + if (ext === '.node') { + return require(entry) + } + + const emnapi = require('@emnapi/runtime') + if (ext === '.js') { + return require(entry)().emnapiInit({ + context: emnapi.getDefaultContext() + }) + } + + if (ext === '.wasm') { + const { instantiateNapiModuleSync } = require('@emnapi/core') + const { napiModule } = instantiateNapiModuleSync(fs.readFileSync(entry), { + context: emnapi.getDefaultContext(), + wasi: new (require('wasi').WASI)({ version: 'preview1' }), + asyncWorkPoolSize: process.env.UV_THREADPOOL_SIZE || 4, + overwriteImports (imports) { + imports.env.memory = new WebAssembly.Memory({ + initial: 16777216 / 65536, + maximum: 2147483648 / 65536, + shared: true + }) + }, + onCreateWorker () { + return new (require('worker_threads').Worker)(path.join(__dirname, './worker.js'), { + env: process.env, + execArgv: ['--experimental-wasi-unstable-preview1'] + }) + } + }) + return napiModule.exports + } + throw new Error('Failed to initialize Node-API wasm module') +})() + +exports.hello = function() { return addon.hello() } diff --git a/test/node_modules/hello_wasm/package.json b/test/node_modules/hello_wasm/package.json new file mode 100644 index 0000000000..c525fb67ad --- /dev/null +++ b/test/node_modules/hello_wasm/package.json @@ -0,0 +1,16 @@ +{ + "name": "hello_wasm", + "version": "0.0.0", + "description": "Node.js Addons Example #2", + "main": "hello.js", + "private": true, + "dependencies": { + "@emnapi/core": "^1.2.0", + "@emnapi/runtime": "^1.2.0", + "emnapi": "^1.2.0" + }, + "scripts": { + "test": "node hello.js" + }, + "gypfile": true +} diff --git a/test/test-wasm.js b/test/test-wasm.js new file mode 100644 index 0000000000..3673cd846f --- /dev/null +++ b/test/test-wasm.js @@ -0,0 +1,126 @@ +'use strict' + +const { describe, it } = require('mocha') +const assert = require('assert') +const path = require('path') +const cp = require('child_process') +const util = require('../lib/util') +const { platformTimeout } = require('./common') + +const wasmAddonPath = path.resolve(__dirname, 'node_modules', 'hello_wasm') +const nodeGyp = path.resolve(__dirname, '..', 'bin', 'node-gyp.js') + +const execFileSync = (...args) => cp.execFileSync(...args).toString().trim() + +const execFile = async (cmd, env) => { + const [err,, stderr] = await util.execFile(process.execPath, cmd, { + env: { + ...process.env, + NODE_GYP_NULL_LOGGER: undefined, + ...env + }, + encoding: 'utf-8' + }) + return [err, stderr.toString().trim().split(/\r?\n/)] +} + +function runWasm (hostProcess = process.execPath) { + const testCode = "console.log(require('hello_wasm').hello())" + return execFileSync(hostProcess, ['--experimental-wasi-unstable-preview1', '-e', testCode], { cwd: __dirname }) +} + +function executable (name) { + return name + (process.platform === 'win32' ? '.exe' : '') +} + +function getWasmEnv (target) { + const env = { + GYP_CROSSCOMPILE: '1', + AR_host: 'ar', + CC_host: 'clang', + CXX_host: 'clang++' + } + if (target === 'emscripten') { + env.AR_target = 'emar' + env.CC_target = 'emcc' + env.CXX_target = 'em++' + } else if (target === 'wasi') { + env.AR_target = path.resolve(__dirname, '..', process.env.WASI_SDK_PATH, 'bin', executable('ar')) + env.CC_target = path.resolve(__dirname, '..', process.env.WASI_SDK_PATH, 'bin', executable('clang')) + env.CXX_target = path.resolve(__dirname, '..', process.env.WASI_SDK_PATH, 'bin', executable('clang++')) + } else if (target === 'wasm') { + env.AR_target = path.resolve(__dirname, '..', process.env.WASI_SDK_PATH, 'bin', executable('ar')) + env.CC_target = path.resolve(__dirname, '..', process.env.WASI_SDK_PATH, 'bin', executable('clang')) + env.CXX_target = path.resolve(__dirname, '..', process.env.WASI_SDK_PATH, 'bin', executable('clang++')) + env.CFLAGS = '--target=wasm32' + } + return env +} + +describe('wasm', function () { + it('build simple node-api addon to wasm (wasm32-emscripten)', async function () { + if (!process.env.EMSDK) { + return this.skip('emsdk not found') + } + this.timeout(platformTimeout(1, { win32: 5 })) + + const cmd = [ + nodeGyp, + 'rebuild', + '-C', wasmAddonPath, + '--loglevel=verbose', + '--arch=wasm32', + `--nodedir=${path.dirname(require.resolve('emnapi'))}`, + '--', '-f', 'make' + ] + const [err, logLines] = await execFile(cmd, getWasmEnv('emscripten')) + const lastLine = logLines[logLines.length - 1] + assert.strictEqual(err, null) + assert.strictEqual(lastLine, 'gyp info ok', 'should end in ok') + assert.strictEqual(runWasm(), 'world') + }) + + it('build simple node-api addon to wasm (wasm32-wasip1)', async function () { + if (!process.env.WASI_SDK_PATH) { + return this.skip('wasi-sdk not found') + } + this.timeout(platformTimeout(1, { win32: 5 })) + + const cmd = [ + nodeGyp, + 'rebuild', + '-C', wasmAddonPath, + '--loglevel=verbose', + '--arch=wasm32', + `--nodedir=${path.dirname(require.resolve('emnapi'))}`, + '--', '-f', 'make' + ] + const [err, logLines] = await execFile(cmd, getWasmEnv('wasi')) + const lastLine = logLines[logLines.length - 1] + assert.strictEqual(err, null) + assert.strictEqual(lastLine, 'gyp info ok', 'should end in ok') + assert.strictEqual(runWasm(), 'world') + }) + + it('build simple node-api addon to wasm (wasm32-unknown-unknown)', async function () { + if (!process.env.WASI_SDK_PATH) { + return this.skip('wasi-sdk not found') + } + this.timeout(platformTimeout(1, { win32: 5 })) + + const cmd = [ + nodeGyp, + 'rebuild', + '-C', wasmAddonPath, + '--loglevel=verbose', + '--arch=wasm32', + `--nodedir=${path.dirname(require.resolve('emnapi'))}`, + '--', '-f', 'make' + ] + const [err, logLines] = await execFile(cmd, getWasmEnv('wasm')) + const lastLine = logLines[logLines.length - 1] + assert.strictEqual(err, null) + assert.strictEqual(lastLine, 'gyp info ok', 'should end in ok') + assert.strictEqual(runWasm(), 'world') + }) +}) From 8e467dcfbf61b0a60375cc1c5cf4bf9b797ee3be Mon Sep 17 00:00:00 2001 From: toyobayashi Date: Wed, 12 Jun 2024 21:37:21 +0800 Subject: [PATCH 08/15] use vs clang to test --- .github/workflows/tests.yml | 26 +------ package.json | 3 - .../{hello_wasm => hello_napi}/binding.gyp | 0 .../{hello_wasm => hello_napi}/hello.c | 0 .../{hello_wasm => hello_napi}/hello.js | 0 .../{hello_wasm => hello_napi}/package.json | 7 +- test/{test-wasm.js => test-windows-make.js} | 76 +++++-------------- 7 files changed, 21 insertions(+), 91 deletions(-) rename test/node_modules/{hello_wasm => hello_napi}/binding.gyp (100%) rename test/node_modules/{hello_wasm => hello_napi}/hello.c (100%) rename test/node_modules/{hello_wasm => hello_napi}/hello.js (100%) rename test/node_modules/{hello_wasm => hello_napi}/package.json (57%) rename test/{test-wasm.js => test-windows-make.js} (50%) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 0dcac943be..96b08ae3e1 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -102,12 +102,6 @@ jobs: node: 20.x name: ${{ matrix.os }} - ${{ matrix.python }} - ${{ matrix.node }} runs-on: ${{ matrix.os }} - env: - WASI_VERSION: '22' - WASI_VERSION_FULL: '22.0' - WASI_SDK_PATH: 'wasi-sdk-22.0' - EM_VERSION: '3.1.52' - EM_CACHE_FOLDER: 'emsdk-cache' steps: - name: Checkout Repository uses: actions/checkout@v4 @@ -122,24 +116,6 @@ jobs: env: PYTHON_VERSION: ${{ matrix.python }} # Why do this? - uses: seanmiddleditch/gha-setup-ninja@v4 - - uses: mymindstorm/setup-emsdk@v14 - with: - version: ${{ env.EM_VERSION }} - actions-cache-folder: ${{ env.EM_CACHE_FOLDER }} - - name: Install wasi-sdk (macOS or Linux) - shell: bash - if: ${{ !startsWith(matrix.os, 'windows') }} - run: | - wget -q https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-${WASI_VERSION}/wasi-sdk-${WASI_VERSION_FULL}-${{ startsWith(matrix.os, 'macos') && 'macos' || 'linux' }}.tar.gz - mkdir -p $WASI_SDK_PATH - tar zxvf wasi-sdk-${WASI_VERSION_FULL}-${{ startsWith(matrix.os, 'macos') && 'macos' || 'linux' }}.tar.gz -C $WASI_SDK_PATH --strip 1 - - name: Install wasi-sdk (Windows) - shell: pwsh - if: ${{ startsWith(matrix.os, 'windows') }} - run: | - Start-BitsTransfer -Source https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-${env:WASI_VERSION}/wasi-sdk-${env:WASI_VERSION_FULL}.m-mingw.tar.gz - New-Item -ItemType Directory -Path ${env:WASI_SDK_PATH} - tar -zxvf wasi-sdk-${env:WASI_VERSION_FULL}.m-mingw.tar.gz -C ${env:WASI_SDK_PATH} --strip 1 - name: Install Dependencies run: | npm install @@ -150,7 +126,7 @@ jobs: echo 'GYP_MSVS_VERSION=2015' >> $Env:GITHUB_ENV echo 'GYP_MSVS_OVERRIDE_PATH=C:\\Dummy' >> $Env:GITHUB_ENV - name: Run Python Tests - run: python -m pytest --ignore=${{ env.EM_CACHE_FOLDER }} + run: python -m pytest - name: Run Tests (macOS or Linux) if: "!startsWith(matrix.os, 'windows')" shell: bash diff --git a/package.json b/package.json index a94917cf0a..e9402d7923 100644 --- a/package.json +++ b/package.json @@ -37,11 +37,8 @@ "node": "^16.14.0 || >=18.0.0" }, "devDependencies": { - "@emnapi/core": "^1.2.0", - "@emnapi/runtime": "^1.2.0", "bindings": "^1.5.0", "cross-env": "^7.0.3", - "emnapi": "^1.2.0", "mocha": "^10.2.0", "nan": "^2.14.2", "require-inject": "^1.4.4", diff --git a/test/node_modules/hello_wasm/binding.gyp b/test/node_modules/hello_napi/binding.gyp similarity index 100% rename from test/node_modules/hello_wasm/binding.gyp rename to test/node_modules/hello_napi/binding.gyp diff --git a/test/node_modules/hello_wasm/hello.c b/test/node_modules/hello_napi/hello.c similarity index 100% rename from test/node_modules/hello_wasm/hello.c rename to test/node_modules/hello_napi/hello.c diff --git a/test/node_modules/hello_wasm/hello.js b/test/node_modules/hello_napi/hello.js similarity index 100% rename from test/node_modules/hello_wasm/hello.js rename to test/node_modules/hello_napi/hello.js diff --git a/test/node_modules/hello_wasm/package.json b/test/node_modules/hello_napi/package.json similarity index 57% rename from test/node_modules/hello_wasm/package.json rename to test/node_modules/hello_napi/package.json index c525fb67ad..6cdb71b21f 100644 --- a/test/node_modules/hello_wasm/package.json +++ b/test/node_modules/hello_napi/package.json @@ -1,14 +1,9 @@ { - "name": "hello_wasm", + "name": "hello_napi", "version": "0.0.0", "description": "Node.js Addons Example #2", "main": "hello.js", "private": true, - "dependencies": { - "@emnapi/core": "^1.2.0", - "@emnapi/runtime": "^1.2.0", - "emnapi": "^1.2.0" - }, "scripts": { "test": "node hello.js" }, diff --git a/test/test-wasm.js b/test/test-windows-make.js similarity index 50% rename from test/test-wasm.js rename to test/test-windows-make.js index 3673cd846f..cd7bebc7d1 100644 --- a/test/test-wasm.js +++ b/test/test-windows-make.js @@ -3,11 +3,12 @@ const { describe, it } = require('mocha') const assert = require('assert') const path = require('path') +const gracefulFs = require('graceful-fs') const cp = require('child_process') const util = require('../lib/util') const { platformTimeout } = require('./common') -const wasmAddonPath = path.resolve(__dirname, 'node_modules', 'hello_wasm') +const addonPath = path.resolve(__dirname, 'node_modules', 'hello_napi') const nodeGyp = path.resolve(__dirname, '..', 'bin', 'node-gyp.js') const execFileSync = (...args) => cp.execFileSync(...args).toString().trim() @@ -24,8 +25,8 @@ const execFile = async (cmd, env) => { return [err, stderr.toString().trim().split(/\r?\n/)] } -function runWasm (hostProcess = process.execPath) { - const testCode = "console.log(require('hello_wasm').hello())" +function runHello (hostProcess = process.execPath) { + const testCode = "console.log(require('hello_napi').hello())" return execFileSync(hostProcess, ['--experimental-wasi-unstable-preview1', '-e', testCode], { cwd: __dirname }) } @@ -33,7 +34,7 @@ function executable (name) { return name + (process.platform === 'win32' ? '.exe' : '') } -function getWasmEnv (target) { +function getEnv (target) { const env = { GYP_CROSSCOMPILE: '1', AR_host: 'ar', @@ -53,74 +54,35 @@ function getWasmEnv (target) { env.CC_target = path.resolve(__dirname, '..', process.env.WASI_SDK_PATH, 'bin', executable('clang')) env.CXX_target = path.resolve(__dirname, '..', process.env.WASI_SDK_PATH, 'bin', executable('clang++')) env.CFLAGS = '--target=wasm32' + } else if (target === 'win-clang') { + env.AR_target = 'C:\\Program Files\\Microsoft Visual Studio\\2022\\Enterprise\\VC\\Tools\\Llvm\\x64\\bin\\llvm-ar.exe' + env.CC_target = 'C:\\Program Files\\Microsoft Visual Studio\\2022\\Enterprise\\VC\\Tools\\Llvm\\x64\\bin\\clang.exe' + env.CXX_target = 'C:\\Program Files\\Microsoft Visual Studio\\2022\\Enterprise\\VC\\Tools\\Llvm\\x64\\bin\\clang++.exe' } return env } -describe('wasm', function () { - it('build simple node-api addon to wasm (wasm32-emscripten)', async function () { - if (!process.env.EMSDK) { - return this.skip('emsdk not found') +describe('windows-cross-compile', function () { + it('build simple node-api addon', async function () { + if (process.platform !== 'win32') { + return this.skip('This test is only for windows') } - this.timeout(platformTimeout(1, { win32: 5 })) - - const cmd = [ - nodeGyp, - 'rebuild', - '-C', wasmAddonPath, - '--loglevel=verbose', - '--arch=wasm32', - `--nodedir=${path.dirname(require.resolve('emnapi'))}`, - '--', '-f', 'make' - ] - const [err, logLines] = await execFile(cmd, getWasmEnv('emscripten')) - const lastLine = logLines[logLines.length - 1] - assert.strictEqual(err, null) - assert.strictEqual(lastLine, 'gyp info ok', 'should end in ok') - assert.strictEqual(runWasm(), 'world') - }) - - it('build simple node-api addon to wasm (wasm32-wasip1)', async function () { - if (!process.env.WASI_SDK_PATH) { - return this.skip('wasi-sdk not found') - } - this.timeout(platformTimeout(1, { win32: 5 })) - - const cmd = [ - nodeGyp, - 'rebuild', - '-C', wasmAddonPath, - '--loglevel=verbose', - '--arch=wasm32', - `--nodedir=${path.dirname(require.resolve('emnapi'))}`, - '--', '-f', 'make' - ] - const [err, logLines] = await execFile(cmd, getWasmEnv('wasi')) - const lastLine = logLines[logLines.length - 1] - assert.strictEqual(err, null) - assert.strictEqual(lastLine, 'gyp info ok', 'should end in ok') - assert.strictEqual(runWasm(), 'world') - }) - - it('build simple node-api addon to wasm (wasm32-unknown-unknown)', async function () { - if (!process.env.WASI_SDK_PATH) { - return this.skip('wasi-sdk not found') + if (!gracefulFs.existsSync('C:\\Program Files\\Microsoft Visual Studio\\2022\\Enterprise\\VC\\Tools\\Llvm\\x64\\bin\\clang.exe')) { + return this.skip('Visual Studio Clang is not installed') } this.timeout(platformTimeout(1, { win32: 5 })) const cmd = [ nodeGyp, 'rebuild', - '-C', wasmAddonPath, + '-C', addonPath, '--loglevel=verbose', - '--arch=wasm32', - `--nodedir=${path.dirname(require.resolve('emnapi'))}`, - '--', '-f', 'make' + '--', '-f', 'make-linux' ] - const [err, logLines] = await execFile(cmd, getWasmEnv('wasm')) + const [err, logLines] = await execFile(cmd, getEnv('win-clang')) const lastLine = logLines[logLines.length - 1] assert.strictEqual(err, null) assert.strictEqual(lastLine, 'gyp info ok', 'should end in ok') - assert.strictEqual(runWasm(), 'world') + assert.strictEqual(runHello(), 'world') }) }) From 8ca18c57cae482bd99f9077cd0209c00d7389fce Mon Sep 17 00:00:00 2001 From: toyobayashi Date: Thu, 13 Jun 2024 00:01:02 +0800 Subject: [PATCH 09/15] minimum wasm test --- test/node_modules/hello_napi/common.gypi | 111 +++++++++++++++++++++++ test/node_modules/hello_napi/hello.c | 43 +++++++-- test/node_modules/hello_napi/hello.js | 55 +++++++---- test/test-windows-make.js | 32 +++++-- 4 files changed, 209 insertions(+), 32 deletions(-) create mode 100644 test/node_modules/hello_napi/common.gypi diff --git a/test/node_modules/hello_napi/common.gypi b/test/node_modules/hello_napi/common.gypi new file mode 100644 index 0000000000..d67048d23c --- /dev/null +++ b/test/node_modules/hello_napi/common.gypi @@ -0,0 +1,111 @@ +{ + 'variables': { + # OS: 'emscripten' | 'wasi' | 'unknown' | 'wasm' + 'clang': 1, + 'target_arch%': 'wasm32', + 'stack_size%': 1048576, + 'initial_memory%': 16777216, + 'max_memory%': 2147483648, + 'emnapi_manual_linking%': 0, + }, + + 'target_defaults': { + 'type': 'executable', + + 'defines': [ + 'BUILDING_NODE_EXTENSION', + '__STDC_FORMAT_MACROS', + ], + + 'cflags': [ + '-Wall', + '-Wextra', + '-Wno-unused-parameter', + '--target=wasm32-unknown-unknown', + ], + 'cflags_cc': [ + '-fno-rtti', + '-fno-exceptions', + '-std=c++17' + ], + 'ldflags': [ + '--target=wasm32-unknown-unknown', + ], + + 'xcode_settings': { + # WARNING_CFLAGS == cflags + # OTHER_CFLAGS == cflags_c + # OTHER_CPLUSPLUSFLAGS == cflags_cc + # OTHER_LDFLAGS == ldflags + + 'CLANG_CXX_LANGUAGE_STANDARD': 'c++17', + 'GCC_ENABLE_CPP_RTTI': 'NO', + 'GCC_ENABLE_CPP_EXCEPTIONS': 'NO', + 'WARNING_CFLAGS': [ + '-Wall', + '-Wextra', + '-Wno-unused-parameter', + '--target=wasm32-unknown-unknown' + ], + 'OTHER_LDFLAGS': [ '--target=wasm32-unknown-unknown' ], + }, + + 'default_configuration': 'Release', + 'configurations': { + 'Debug': { + 'defines': [ 'DEBUG', '_DEBUG' ], + 'cflags': [ '-g', '-O0' ], + 'ldflags': [ '-g', '-O0' ], + 'xcode_settings': { + 'WARNING_CFLAGS': [ '-g', '-O0' ], + 'OTHER_LDFLAGS': [ '-g', '-O0' ], + }, + }, + 'Release': { + 'cflags': [ '-O3' ], + 'ldflags': [ '-O3', '-Wl,--strip-debug' ], + 'xcode_settings': { + 'WARNING_CFLAGS': [ '-O3' ], + 'OTHER_LDFLAGS': [ '-O3', '-Wl,--strip-debug' ], + }, + } + }, + + 'target_conditions': [ + ['_type=="executable"', { + + 'product_extension': 'wasm', + + 'ldflags': [ + '-Wl,--export-dynamic', + '-Wl,--export=napi_register_wasm_v1', + '-Wl,--export-if-defined=node_api_module_get_api_version_v1', + '-Wl,--import-undefined', + '-Wl,--export-table', + '-Wl,-zstack-size=<(stack_size)', + '-Wl,--initial-memory=<(initial_memory)', + '-Wl,--max-memory=<(max_memory)', + '-nostdlib', + '-Wl,--no-entry', + ], + 'xcode_settings': { + 'OTHER_LDFLAGS': [ + '-Wl,--export-dynamic', + '-Wl,--export=napi_register_wasm_v1', + '-Wl,--export-if-defined=node_api_module_get_api_version_v1', + '-Wl,--import-undefined', + '-Wl,--export-table', + '-Wl,-zstack-size=<(stack_size)', + '-Wl,--initial-memory=<(initial_memory)', + '-Wl,--max-memory=<(max_memory)', + '-nostdlib', + '-Wl,--no-entry', + ], + }, + 'defines': [ + 'PAGESIZE=65536' + ], + }], + ], + } +} diff --git a/test/node_modules/hello_napi/hello.c b/test/node_modules/hello_napi/hello.c index 8d52eef456..9bd8b129e7 100644 --- a/test/node_modules/hello_napi/hello.c +++ b/test/node_modules/hello_napi/hello.c @@ -1,21 +1,50 @@ -#include +#include #if !defined(__wasm__) || (defined(__EMSCRIPTEN__) || defined(__wasi__)) #include +#include #else #define assert(x) do { if (!(x)) { __builtin_trap(); } } while (0) + + +__attribute__((__import_module__("napi"))) +int napi_create_string_utf8(void* env, + const char* str, + size_t length, + void** result); + +__attribute__((__import_module__("napi"))) +int napi_create_function(void* env, + const char* utf8name, + size_t length, + void* cb, + void* data, + void** result); + +__attribute__((__import_module__("napi"))) +int napi_set_named_property(void* env, + void* object, + const char* utf8name, + void* value); +#ifdef __cplusplus +#define EXTERN_C extern "C" { +#else +#define EXTERN_C +#endif +#define NAPI_MODULE_INIT() \ + EXTERN_C __attribute__((visibility("default"))) void* napi_register_wasm_v1(void* env, void* exports) #endif -static napi_value hello(napi_env env, napi_callback_info info) { - napi_value greeting; - assert(napi_ok == napi_create_string_utf8(env, "world", NAPI_AUTO_LENGTH, &greeting)); +static void* hello(void* env, void* info) { + void* greeting = NULL; + assert(0 == napi_create_string_utf8(env, "world", -1, &greeting)); return greeting; } NAPI_MODULE_INIT() { - napi_value hello_function; - assert(napi_ok == napi_create_function(env, "hello", NAPI_AUTO_LENGTH, + void* hello_function = NULL; + assert(0 == napi_create_function(env, "hello", -1, hello, NULL, &hello_function)); - assert(napi_ok == napi_set_named_property(env, exports, "hello", hello_function)); + assert(0 == napi_set_named_property(env, exports, "hello", hello_function)); return exports; } diff --git a/test/node_modules/hello_napi/hello.js b/test/node_modules/hello_napi/hello.js index efd5987331..80cc3d337c 100644 --- a/test/node_modules/hello_napi/hello.js +++ b/test/node_modules/hello_napi/hello.js @@ -15,34 +15,51 @@ const addon = (function () { return require(entry) } - const emnapi = require('@emnapi/runtime') if (ext === '.js') { + const emnapi = require('@emnapi/runtime') return require(entry)().emnapiInit({ context: emnapi.getDefaultContext() }) } if (ext === '.wasm') { - const { instantiateNapiModuleSync } = require('@emnapi/core') - const { napiModule } = instantiateNapiModuleSync(fs.readFileSync(entry), { - context: emnapi.getDefaultContext(), - wasi: new (require('wasi').WASI)({ version: 'preview1' }), - asyncWorkPoolSize: process.env.UV_THREADPOOL_SIZE || 4, - overwriteImports (imports) { - imports.env.memory = new WebAssembly.Memory({ - initial: 16777216 / 65536, - maximum: 2147483648 / 65536, - shared: true - }) - }, - onCreateWorker () { - return new (require('worker_threads').Worker)(path.join(__dirname, './worker.js'), { - env: process.env, - execArgv: ['--experimental-wasi-unstable-preview1'] - }) + const module = new WebAssembly.Module(fs.readFileSync(entry)) + const instance = new WebAssembly.Instance(module, { + napi: { + napi_create_string_utf8: (env, str, len, ret) => { + return 0 + }, + napi_create_function: (env, name, len, fn, data, ret) => { + return 0 + }, + napi_set_named_property: (env, obj, key, val) => { + return 0 + } } }) - return napiModule.exports + return { hello() { return 'world' } } + // const emnapi = require('@emnapi/runtime') + // const emnapiCore = require('@emnapi/core') + // const { instantiateNapiModuleSync } = emnapiCore + // const { napiModule } = instantiateNapiModuleSync(fs.readFileSync(entry), { + // context: emnapi.getDefaultContext(), + // wasi: new (require('wasi').WASI)({ version: 'preview1' }), + // asyncWorkPoolSize: process.env.UV_THREADPOOL_SIZE || 4, + // overwriteImports (imports) { + // imports.env.memory = new WebAssembly.Memory({ + // initial: 16777216 / 65536, + // maximum: 2147483648 / 65536, + // shared: true + // }) + // }, + // onCreateWorker () { + // return new (require('worker_threads').Worker)(path.join(__dirname, './worker.js'), { + // env: process.env, + // execArgv: ['--experimental-wasi-unstable-preview1'] + // }) + // } + // }) + // return napiModule.exports } throw new Error('Failed to initialize Node-API wasm module') })() diff --git a/test/test-windows-make.js b/test/test-windows-make.js index cd7bebc7d1..41cefc3035 100644 --- a/test/test-windows-make.js +++ b/test/test-windows-make.js @@ -55,21 +55,39 @@ function getEnv (target) { env.CXX_target = path.resolve(__dirname, '..', process.env.WASI_SDK_PATH, 'bin', executable('clang++')) env.CFLAGS = '--target=wasm32' } else if (target === 'win-clang') { - env.AR_target = 'C:\\Program Files\\Microsoft Visual Studio\\2022\\Enterprise\\VC\\Tools\\Llvm\\x64\\bin\\llvm-ar.exe' - env.CC_target = 'C:\\Program Files\\Microsoft Visual Studio\\2022\\Enterprise\\VC\\Tools\\Llvm\\x64\\bin\\clang.exe' - env.CXX_target = 'C:\\Program Files\\Microsoft Visual Studio\\2022\\Enterprise\\VC\\Tools\\Llvm\\x64\\bin\\clang++.exe' + let vsdir = 'C:\\Program Files\\Microsoft Visual Studio\\2022\\Enterprise' + if (!gracefulFs.existsSync(vsdir)) { + vsdir = 'C:\\Program Files\\Microsoft Visual Studio\\2022\\Community' + } + const llvmBin = 'VC\\Tools\\Llvm\\x64\\bin' + env.AR_target = path.join(vsdir, llvmBin, 'llvm-ar.exe') + env.CC_target = path.join(vsdir, llvmBin, 'clang.exe') + env.CXX_target = path.join(vsdir, llvmBin, 'clang++.exe') + env.CFLAGS = '--target=wasm32' } return env } +function quote (path) { + if (path.includes(' ')) { + return `"${path}"` + } +} + describe('windows-cross-compile', function () { it('build simple node-api addon', async function () { if (process.platform !== 'win32') { return this.skip('This test is only for windows') } - if (!gracefulFs.existsSync('C:\\Program Files\\Microsoft Visual Studio\\2022\\Enterprise\\VC\\Tools\\Llvm\\x64\\bin\\clang.exe')) { + const env = getEnv('win-clang') + if (!gracefulFs.existsSync(env.CC_target)) { return this.skip('Visual Studio Clang is not installed') } + + // handle bash whitespace + env.AR_target = quote(env.AR_target) + env.CC_target = quote(env.CC_target) + env.CXX_target = quote(env.CXX_target) this.timeout(platformTimeout(1, { win32: 5 })) const cmd = [ @@ -77,9 +95,11 @@ describe('windows-cross-compile', function () { 'rebuild', '-C', addonPath, '--loglevel=verbose', - '--', '-f', 'make-linux' + `--nodedir=${addonPath}`, + '--arch=wasm32', + '--', '-f', 'make' ] - const [err, logLines] = await execFile(cmd, getEnv('win-clang')) + const [err, logLines] = await execFile(cmd, env) const lastLine = logLines[logLines.length - 1] assert.strictEqual(err, null) assert.strictEqual(lastLine, 'gyp info ok', 'should end in ok') From 9a3290825bc2e244e8b0d251af58c191a69eeacb Mon Sep 17 00:00:00 2001 From: toyobayashi Date: Thu, 13 Jun 2024 00:37:39 +0800 Subject: [PATCH 10/15] more real test --- test/node_modules/hello_napi/hello.js | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/test/node_modules/hello_napi/hello.js b/test/node_modules/hello_napi/hello.js index 80cc3d337c..221b74559e 100644 --- a/test/node_modules/hello_napi/hello.js +++ b/test/node_modules/hello_napi/hello.js @@ -23,21 +23,40 @@ const addon = (function () { } if (ext === '.wasm') { + const values = [undefined, undefined, null, false, true, global, {}] const module = new WebAssembly.Module(fs.readFileSync(entry)) const instance = new WebAssembly.Instance(module, { napi: { napi_create_string_utf8: (env, str, len, ret) => { + let end = str + const buffer = new Uint8Array(instance.exports.memory.buffer) + while (buffer[end]) end++ + values.push(new TextDecoder().decode(buffer.slice(str, end))) + new DataView(instance.exports.memory.buffer).setInt32(ret, values.length - 1, true) return 0 }, napi_create_function: (env, name, len, fn, data, ret) => { + values.push(function () { + return values[instance.exports.__indirect_function_table.get(fn)(env, 0)] + }) + new DataView(instance.exports.memory.buffer).setInt32(ret, values.length - 1, true) return 0 }, napi_set_named_property: (env, obj, key, val) => { + const buffer = new Uint8Array(instance.exports.memory.buffer) + let end = key + while (buffer[end]) end++ + const k = new TextDecoder().decode(buffer.slice(key, end)) + values[obj][k] = values[val] return 0 } } }) - return { hello() { return 'world' } } + const newExports = values[instance.exports.napi_register_wasm_v1(1, 6)] + if (newExports) { + values[6] = values[instance.exports.napi_register_wasm_v1(1, 6)] + } + return values[6] // const emnapi = require('@emnapi/runtime') // const emnapiCore = require('@emnapi/core') // const { instantiateNapiModuleSync } = emnapiCore From 78abf6798912a20d684416fe4a544f9d690ccd99 Mon Sep 17 00:00:00 2001 From: toyobayashi Date: Thu, 13 Jun 2024 00:38:46 +0800 Subject: [PATCH 11/15] fix test --- test/node_modules/hello_napi/hello.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/node_modules/hello_napi/hello.js b/test/node_modules/hello_napi/hello.js index 221b74559e..81b7880e96 100644 --- a/test/node_modules/hello_napi/hello.js +++ b/test/node_modules/hello_napi/hello.js @@ -54,7 +54,7 @@ const addon = (function () { }) const newExports = values[instance.exports.napi_register_wasm_v1(1, 6)] if (newExports) { - values[6] = values[instance.exports.napi_register_wasm_v1(1, 6)] + values[6] = newExports } return values[6] // const emnapi = require('@emnapi/runtime') From ca4acefbc09d96be589dd4e0f73876bde6c5991f Mon Sep 17 00:00:00 2001 From: toyobayashi Date: Mon, 17 Jun 2024 18:11:27 +0800 Subject: [PATCH 12/15] clean test --- test/node_modules/hello_napi/hello.js | 29 --------------------------- 1 file changed, 29 deletions(-) diff --git a/test/node_modules/hello_napi/hello.js b/test/node_modules/hello_napi/hello.js index 81b7880e96..00084f851b 100644 --- a/test/node_modules/hello_napi/hello.js +++ b/test/node_modules/hello_napi/hello.js @@ -15,13 +15,6 @@ const addon = (function () { return require(entry) } - if (ext === '.js') { - const emnapi = require('@emnapi/runtime') - return require(entry)().emnapiInit({ - context: emnapi.getDefaultContext() - }) - } - if (ext === '.wasm') { const values = [undefined, undefined, null, false, true, global, {}] const module = new WebAssembly.Module(fs.readFileSync(entry)) @@ -57,28 +50,6 @@ const addon = (function () { values[6] = newExports } return values[6] - // const emnapi = require('@emnapi/runtime') - // const emnapiCore = require('@emnapi/core') - // const { instantiateNapiModuleSync } = emnapiCore - // const { napiModule } = instantiateNapiModuleSync(fs.readFileSync(entry), { - // context: emnapi.getDefaultContext(), - // wasi: new (require('wasi').WASI)({ version: 'preview1' }), - // asyncWorkPoolSize: process.env.UV_THREADPOOL_SIZE || 4, - // overwriteImports (imports) { - // imports.env.memory = new WebAssembly.Memory({ - // initial: 16777216 / 65536, - // maximum: 2147483648 / 65536, - // shared: true - // }) - // }, - // onCreateWorker () { - // return new (require('worker_threads').Worker)(path.join(__dirname, './worker.js'), { - // env: process.env, - // execArgv: ['--experimental-wasi-unstable-preview1'] - // }) - // } - // }) - // return napiModule.exports } throw new Error('Failed to initialize Node-API wasm module') })() From be79873a9fba1c38caa0d65b001296ba3c23cb20 Mon Sep 17 00:00:00 2001 From: toyobayashi Date: Mon, 17 Jun 2024 18:21:57 +0800 Subject: [PATCH 13/15] test: use typedef --- test/node_modules/hello_napi/hello.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/test/node_modules/hello_napi/hello.c b/test/node_modules/hello_napi/hello.c index 9bd8b129e7..2c03dc156f 100644 --- a/test/node_modules/hello_napi/hello.c +++ b/test/node_modules/hello_napi/hello.c @@ -33,16 +33,20 @@ int napi_set_named_property(void* env, #endif #define NAPI_MODULE_INIT() \ EXTERN_C __attribute__((visibility("default"))) void* napi_register_wasm_v1(void* env, void* exports) + +typedef void* napi_env; +typedef void* napi_value; +typedef void* napi_callback_info; #endif -static void* hello(void* env, void* info) { - void* greeting = NULL; +static napi_value hello(napi_env env, napi_callback_info info) { + napi_value greeting = NULL; assert(0 == napi_create_string_utf8(env, "world", -1, &greeting)); return greeting; } NAPI_MODULE_INIT() { - void* hello_function = NULL; + napi_value hello_function = NULL; assert(0 == napi_create_function(env, "hello", -1, hello, NULL, &hello_function)); assert(0 == napi_set_named_property(env, exports, "hello", hello_function)); From 3d3933515114de50018ae1c917b09d941355923d Mon Sep 17 00:00:00 2001 From: toyobayashi Date: Mon, 17 Jun 2024 18:22:31 +0800 Subject: [PATCH 14/15] clean gyp config in test --- test/node_modules/hello_napi/binding.gyp | 38 ++---------------------- test/node_modules/hello_napi/common.gypi | 1 - 2 files changed, 2 insertions(+), 37 deletions(-) diff --git a/test/node_modules/hello_napi/binding.gyp b/test/node_modules/hello_napi/binding.gyp index cc8a21694e..43773ef0ff 100644 --- a/test/node_modules/hello_napi/binding.gyp +++ b/test/node_modules/hello_napi/binding.gyp @@ -19,43 +19,9 @@ '-sEXPORT_NAME=hello', '-sWASM_ASYNC_COMPILATION=0' ] - }, - 'conditions': [ - ['emnapi_manual_linking != 0', { - 'dependencies': [ - ' Date: Mon, 17 Jun 2024 18:27:55 +0800 Subject: [PATCH 15/15] clean gyp config in test (2) --- test/node_modules/hello_napi/binding.gyp | 20 -------------------- 1 file changed, 20 deletions(-) diff --git a/test/node_modules/hello_napi/binding.gyp b/test/node_modules/hello_napi/binding.gyp index 43773ef0ff..cb6a3bdc22 100644 --- a/test/node_modules/hello_napi/binding.gyp +++ b/test/node_modules/hello_napi/binding.gyp @@ -3,26 +3,6 @@ { "target_name": "hello", "sources": [ "hello.c" ], - "conditions": [ - [ - "OS == 'emscripten'", - { - "product_extension": "node.js", - "ldflags": [ - '-sMODULARIZE=1', - '-sEXPORT_NAME=hello', - '-sWASM_ASYNC_COMPILATION=0' - ], - 'xcode_settings': { - 'OTHER_LDFLAGS': [ - '-sMODULARIZE=1', - '-sEXPORT_NAME=hello', - '-sWASM_ASYNC_COMPILATION=0' - ] - } - }, - ] - ] } ] }