diff --git a/.github/workflows/browser.yml b/.github/workflows/browser.yml new file mode 100644 index 0000000..3e17efe --- /dev/null +++ b/.github/workflows/browser.yml @@ -0,0 +1,28 @@ +name: Browser CI + +on: + push: + branches: [main] + workflow_dispatch: + +permissions: + contents: read + +concurrency: + group: browser-${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + browser: + runs-on: ubuntu-latest + timeout-minutes: 5 + + steps: + - uses: actions/checkout@v7 + + - uses: actions/setup-node@v7 + with: + node-version: "24" + + - run: make -C browser install + - run: make -C browser test diff --git a/.gitignore b/.gitignore index fb3a416..ace8864 100644 --- a/.gitignore +++ b/.gitignore @@ -5,7 +5,8 @@ ._* .idea/ .vscode/ -node_modules/ +browser/tests/ +node_modules npm-debug.log* package-lock.json ~$* @@ -13,3 +14,4 @@ package-lock.json *.js.gz gh-pages/ *.log +!browser/tests.cli.mjs diff --git a/.npmrc b/.npmrc deleted file mode 100644 index d373ccb..0000000 --- a/.npmrc +++ /dev/null @@ -1 +0,0 @@ -omit=optional diff --git a/browser/Makefile b/browser/Makefile new file mode 100755 index 0000000..506959e --- /dev/null +++ b/browser/Makefile @@ -0,0 +1,61 @@ +# Force bash so `set -o pipefail` works in the recipes below. +SHELL := bash +.SHELLFLAGS := -eo pipefail -c + +PLAYWRIGHT_VERSION := 1.62.1 + +TEST_SRC := ../test/[12]*.js ../test/6[12]*.js +TEST_DST := tests/bundled.js +BUFFER_SRC := ../node_modules/buffer/index.js +BUFFER_DST := tests/buffer.shim.js +ASSERT_SRC := ../node_modules/assert/assert.js +ASSERT_DST := tests/assert.shim.js + +ALL := $(TEST_DST) $(BUFFER_DST) $(ASSERT_DST) + +all: dist $(ALL) + +bundled: all + +# Keep Playwright out of package.json. CI installs it transiently alongside +# the project's build dependencies, then downloads only the headless shell. +install: + cd .. && PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD=1 npm install playwright@$(PLAYWRIGHT_VERSION) --no-save --ignore-scripts --no-audit --no-fund + cd .. && npx --no-install playwright install --with-deps --only-shell chromium + +# tests.html loads the shipped bundle, so ask the root Makefile for it +# first; whether it rebuilds stays the root Makefile's decision. +dist: + $(MAKE) -C .. dist/msgpack.min.js + +test: all + cd .. && node browser/tests.cli.mjs + +$(TEST_DST): $(TEST_SRC) Makefile + mkdir -p $(dir $@) + ../node_modules/.bin/rollup $(TEST_SRC) --format iife \ + --plugin @rollup/plugin-commonjs \ + --plugin @rollup/plugin-multi-entry \ + --plugin @rollup/plugin-node-resolve \ + --external 'assert,../index' |\ + perl -pe 's#^}\)\(require.*\);#})(assert, msgpack)#' > $@ + +$(BUFFER_DST): $(BUFFER_SRC) Makefile + mkdir -p $(dir $@) + ../node_modules/.bin/rollup $< --format iife \ + --plugin @rollup/plugin-commonjs \ + --plugin @rollup/plugin-node-resolve \ + --name "__BUFFER__" | \ + perl -pe 's#^var __BUFFER__#const {Buffer}#' > $@ + +$(ASSERT_DST): $(ASSERT_SRC) Makefile + mkdir -p $(dir $@) + ../node_modules/.bin/rollup $< --format iife \ + --plugin @rollup/plugin-commonjs \ + --plugin @rollup/plugin-node-resolve \ + --name "assert" > $@ + +clean: + /bin/rm -fr $(ALL) + +.PHONY: all bundled dist install test clean diff --git a/browser/tests.cli.mjs b/browser/tests.cli.mjs new file mode 100644 index 0000000..b5a3def --- /dev/null +++ b/browser/tests.cli.mjs @@ -0,0 +1,40 @@ +import {chromium} from "playwright" +import {fileURLToPath, pathToFileURL} from "node:url" + +const html = fileURLToPath(new URL("./tests.html", import.meta.url)) + +const run = async () => { + const browser = await chromium.launch() + + try { + const page = await browser.newPage() + const pageErrors = [] + page.on("pageerror", error => pageErrors.push(error)) + + await page.goto(pathToFileURL(html).href) + + // Completion is a state, not a promise: mocha.run() publishes its + // stats on window when done, and an unfinished or broken page just + // never does -- so this times out instead of passing. + await page.waitForFunction(() => window.mochaStats !== undefined, null, {timeout: 60_000}) + const {tests, passes, pending, failures, duration} = await page.evaluate(() => window.mochaStats) + console.log(`${passes} passing, ${failures} failing, ${pending} pending (${tests} tests, ${duration}ms)`) + + if (pageErrors.length) { + throw new AggregateError(pageErrors, "Browser page errors occurred") + } + if (failures) { + throw new Error(`Mocha reported ${failures} failed test(s)`) + } + if (!tests) { + throw new Error("Mocha ran no tests") + } + } finally { + await browser.close() + } +} + +run().catch(error => { + console.error(error) + process.exitCode = 1 +}) diff --git a/browser/tests.html b/browser/tests.html new file mode 100644 index 0000000..bc79416 --- /dev/null +++ b/browser/tests.html @@ -0,0 +1,22 @@ + + + + + msgpack-lite browser test + + + + +
+ + + + + + + + + diff --git a/package.json b/package.json index 2cb7b3c..9af9244 100644 --- a/package.json +++ b/package.json @@ -3,6 +3,9 @@ "description": "Fast Pure JavaScript MessagePack Encoder and Decoder", "version": "0.2.1", "author": "@kawanet", + "allowScripts": { + "msgpackr-extract": false + }, "bin": { "msgpack": "./bin/msgpack" }, @@ -29,6 +32,10 @@ }, "devDependencies": { "@msgpack/msgpack": "^3.1.3", + "@rollup/plugin-commonjs": "^29.0.3", + "@rollup/plugin-multi-entry": "^7.1.0", + "@rollup/plugin-node-resolve": "^16.0.3", + "assert": "^1.5.1", "browserify": "^17.0.1", "concat-stream": "^2.0.0", "jshint": "^2.13.6", @@ -36,8 +43,16 @@ "msgpack5": "^6.0.2", "msgpackr": "^2.0.6", "notepack.io": "^3.0.1", + "rollup": "^4.63.1", "uglify-js": "^3.19.3" }, + "devEngines": { + "runtime": { + "name": "node", + "version": ">=22.18.0", + "onFail": "warn" + } + }, "files": [ "LICENSE", "README.md", @@ -85,5 +100,6 @@ "make": "make", "size": "make clean dist/msgpack.min.js && gzip -9fkv dist/msgpack.min.js && ls -l dist", "test": "make test" - } + }, + "type": "commonjs" } diff --git a/test/10.encode.js b/test/10.encode.js index 1881a8f..148615e 100755 --- a/test/10.encode.js +++ b/test/10.encode.js @@ -1,10 +1,8 @@ #!/usr/bin/env mocha -R spec var assert = require("assert"); -var msgpackJS = "../index"; -var isBrowser = ("undefined" !== typeof window); -var msgpack = isBrowser && window.msgpack || require(msgpackJS); -var TITLE = __filename.replace(/^.*\//, ""); +var msgpack = require("../index"); +var TITLE = "10.encode.js"; var HAS_UINT8ARRAY = ("undefined" !== typeof Uint8Array); diff --git a/test/11.decode.js b/test/11.decode.js index 8052c0d..248ece5 100755 --- a/test/11.decode.js +++ b/test/11.decode.js @@ -1,10 +1,8 @@ #!/usr/bin/env mocha -R spec var assert = require("assert"); -var msgpackJS = "../index"; -var isBrowser = ("undefined" !== typeof window); -var msgpack = isBrowser && window.msgpack || require(msgpackJS); -var TITLE = __filename.replace(/^.*\//, ""); +var msgpack = require("../index"); +var TITLE = "11.decode.js"; var HAS_UINT8ARRAY = ("undefined" !== typeof Uint8Array); diff --git a/test/12.encoder.js b/test/12.encoder.js index 3a1e48c..2bcb758 100755 --- a/test/12.encoder.js +++ b/test/12.encoder.js @@ -1,10 +1,8 @@ #!/usr/bin/env mocha -R spec var assert = require("assert"); -var msgpackJS = "../index"; -var isBrowser = ("undefined" !== typeof window); -var msgpack = isBrowser && window.msgpack || require(msgpackJS); -var TITLE = __filename.replace(/^.*\//, ""); +var msgpack = require("../index"); +var TITLE = "12.encoder.js"; var source = {"foo": "bar"}; var packed = toArray(msgpack.encode(source)); diff --git a/test/13.decoder.js b/test/13.decoder.js index 6683ac8..f1d1505 100755 --- a/test/13.decoder.js +++ b/test/13.decoder.js @@ -1,10 +1,8 @@ #!/usr/bin/env mocha -R spec var assert = require("assert"); -var msgpackJS = "../index"; -var isBrowser = ("undefined" !== typeof window); -var msgpack = isBrowser && window.msgpack || require(msgpackJS); -var TITLE = __filename.replace(/^.*\//, ""); +var msgpack = require("../index"); +var TITLE = "13.decoder.js"; var source = {"foo": "bar"}; var packed = msgpack.encode(source); diff --git a/test/14.codec.js b/test/14.codec.js index af7fe83..47024a4 100755 --- a/test/14.codec.js +++ b/test/14.codec.js @@ -1,10 +1,8 @@ #!/usr/bin/env mocha -R spec var assert = require("assert"); -var msgpackJS = "../index"; -var isBrowser = ("undefined" !== typeof window); -var msgpack = isBrowser && window.msgpack || require(msgpackJS); -var TITLE = __filename.replace(/^.*\//, ""); +var msgpack = require("../index"); +var TITLE = "14.codec.js"; var HAS_UINT8ARRAY = ("undefined" !== typeof Uint8Array); diff --git a/test/15.useraw.js b/test/15.useraw.js index c9e445e..0cade20 100755 --- a/test/15.useraw.js +++ b/test/15.useraw.js @@ -1,10 +1,8 @@ #!/usr/bin/env mocha -R spec var assert = require("assert"); -var msgpackJS = "../index"; -var isBrowser = ("undefined" !== typeof window); -var msgpack = isBrowser && window.msgpack || require(msgpackJS); -var TITLE = __filename.replace(/^.*\//, ""); +var msgpack = require("../index"); +var TITLE = "15.useraw.js"; var TESTS = [0, 1, 31, 32, 255, 256, 65535, 65536]; diff --git a/test/16.binarraybuffer.js b/test/16.binarraybuffer.js index cdc78e5..25fef5e 100755 --- a/test/16.binarraybuffer.js +++ b/test/16.binarraybuffer.js @@ -1,10 +1,8 @@ #!/usr/bin/env mocha -R spec var assert = require("assert"); -var msgpackJS = "../index"; -var isBrowser = ("undefined" !== typeof window); -var msgpack = isBrowser && window.msgpack || require(msgpackJS); -var TITLE = __filename.replace(/^.*\//, ""); +var msgpack = require("../index"); +var TITLE = "16.binarraybuffer.js"; var HAS_UINT8ARRAY = ("undefined" !== typeof Uint8Array); var TESTS = [0, 1, 31, 32, 255, 256, 65535, 65536]; diff --git a/test/17.uint8array.js b/test/17.uint8array.js index 423643d..797e5e8 100755 --- a/test/17.uint8array.js +++ b/test/17.uint8array.js @@ -2,10 +2,8 @@ var assert = require("assert"); var Bufferish = require("../lib/bufferish"); -var msgpackJS = "../index"; -var isBrowser = ("undefined" !== typeof window); -var msgpack = isBrowser && window.msgpack || require(msgpackJS); -var TITLE = __filename.replace(/^.*\//, ""); +var msgpack = require("../index"); +var TITLE = "17.uint8array.js"; var HAS_UINT8ARRAY = ("undefined" !== typeof Uint8Array); diff --git a/test/18.utf8.js b/test/18.utf8.js index 5398735..94de5fe 100755 --- a/test/18.utf8.js +++ b/test/18.utf8.js @@ -1,10 +1,8 @@ #!/usr/bin/env mocha -R spec var assert = require("assert"); -var msgpackJS = "../index"; -var isBrowser = ("undefined" !== typeof window); -var msgpack = isBrowser && window.msgpack || require(msgpackJS); -var TITLE = __filename.replace(/^.*\//, ""); +var msgpack = require("../index"); +var TITLE = "18.utf8.js"; var OPTIONS = [{}, {safe: true}]; diff --git a/test/20.roundtrip.js b/test/20.roundtrip.js index 909329d..bc1fd93 100755 --- a/test/20.roundtrip.js +++ b/test/20.roundtrip.js @@ -1,10 +1,8 @@ #!/usr/bin/env mocha -R spec var assert = require("assert"); -var msgpackJS = "../index"; -var isBrowser = ("undefined" !== typeof window); -var msgpack = isBrowser && window.msgpack || require(msgpackJS); -var TITLE = __filename.replace(/^.*\//, ""); +var msgpack = require("../index"); +var TITLE = "20.roundtrip.js"; var STRING_ASCII = "a"; var STRING_GREEK = "α"; diff --git a/test/21.ext.js b/test/21.ext.js index 401693b..c913ab7 100755 --- a/test/21.ext.js +++ b/test/21.ext.js @@ -3,10 +3,8 @@ /*jshint -W053 */ var assert = require("assert"); -var msgpackJS = "../index"; -var isBrowser = ("undefined" !== typeof window); -var msgpack = isBrowser && window.msgpack || require(msgpackJS); -var TITLE = __filename.replace(/^.*\//, ""); +var msgpack = require("../index"); +var TITLE = "21.ext.js"; describe(TITLE, function() { it("Boolean", function() { diff --git a/test/22.typedarray.js b/test/22.typedarray.js index b536a88..96afdbc 100755 --- a/test/22.typedarray.js +++ b/test/22.typedarray.js @@ -3,10 +3,8 @@ /*jshint -W053 */ var assert = require("assert"); -var msgpackJS = "../index"; -var isBrowser = ("undefined" !== typeof window); -var msgpack = isBrowser && window.msgpack || require(msgpackJS); -var TITLE = __filename.replace(/^.*\//, ""); +var msgpack = require("../index"); +var TITLE = "22.typedarray.js"; var TYPED_ARRAY = { "Int8Array": [0, 1, 2, 126, 127, -128, -127, -2, -1], diff --git a/test/23.extbuffer.js b/test/23.extbuffer.js index 983b762..35d9e63 100755 --- a/test/23.extbuffer.js +++ b/test/23.extbuffer.js @@ -3,10 +3,8 @@ /*jshint -W053 */ var assert = require("assert"); -var msgpackJS = "../index"; -var isBrowser = ("undefined" !== typeof window); -var msgpack = isBrowser && window.msgpack || require(msgpackJS); -var TITLE = __filename.replace(/^.*\//, ""); +var msgpack = require("../index"); +var TITLE = "23.extbuffer.js"; var HAS_UINT8ARRAY = ("undefined" !== typeof Uint8Array); diff --git a/test/24.int64.js b/test/24.int64.js index bb8810b..cc02e59 100755 --- a/test/24.int64.js +++ b/test/24.int64.js @@ -7,10 +7,8 @@ var Uint64BE = Int64Buffer.Uint64BE; var Int64BE = Int64Buffer.Int64BE; var assert = require("assert"); -var msgpackJS = "../index"; -var isBrowser = ("undefined" !== typeof window); -var msgpack = isBrowser && window.msgpack || require(msgpackJS); -var TITLE = __filename.replace(/^.*\//, ""); +var msgpack = require("../index"); +var TITLE = "24.int64.js"; describe(TITLE, function() { var options = {}; diff --git a/test/26.es6.js b/test/26.es6.js index 432a8a9..3667198 100755 --- a/test/26.es6.js +++ b/test/26.es6.js @@ -1,10 +1,8 @@ #!/usr/bin/env mocha -R spec var assert = require("assert"); -var msgpackJS = "../index"; -var isBrowser = ("undefined" !== typeof window); -var msgpack = isBrowser && window.msgpack || require(msgpackJS); -var TITLE = __filename.replace(/^.*\//, ""); +var msgpack = require("../index"); +var TITLE = "26.es6.js"; describe(TITLE, function() { diff --git a/test/27.usemap.js b/test/27.usemap.js index 7533fa9..bcc77c6 100755 --- a/test/27.usemap.js +++ b/test/27.usemap.js @@ -1,11 +1,9 @@ #!/usr/bin/env mocha -R spec var assert = require("assert"); -var msgpackJS = "../index"; -var isBrowser = ("undefined" !== typeof window); var HAS_MAP = ("undefined" !== typeof Map); -var msgpack = isBrowser && window.msgpack || require(msgpackJS); -var TITLE = __filename.replace(/^.*\//, ""); +var msgpack = require("../index"); +var TITLE = "27.usemap.js"; function pattern(min, max, offset) { var array = []; diff --git a/test/30.stream.js b/test/30.stream.js index b7a7986..d37f86c 100755 --- a/test/30.stream.js +++ b/test/30.stream.js @@ -5,7 +5,7 @@ var Stream = require("stream"); var concat = require("concat-stream"); var msgpack = require("../index"); -var TITLE = __filename.replace(/^.*\//, ""); +var TITLE = "30.stream.js"; var example = require("./example.json"); var src = [ diff --git a/test/50.compat.js b/test/50.compat.js index e07eb2c..ba23f94 100755 --- a/test/50.compat.js +++ b/test/50.compat.js @@ -3,7 +3,7 @@ var assert = require("assert"); var msgpack = require("../index"); -var TITLE = __filename.replace(/^.*\//, ""); +var TITLE = "50.compat.js"; var data = require("./example.json"); diff --git a/test/61.encode-only.js b/test/61.encode-only.js index 1078352..c779259 100755 --- a/test/61.encode-only.js +++ b/test/61.encode-only.js @@ -4,7 +4,7 @@ var assert = require("assert"); var encode = require("../lib/encode").encode; var ExtBuffer = require("../lib/ext-buffer").ExtBuffer; -var TITLE = __filename.replace(/^.*\//, ""); +var TITLE = "61.encode-only.js"; describe(TITLE, function() { it("encode", function() { diff --git a/test/62.decode-only.js b/test/62.decode-only.js index 057e1a5..5b68a14 100755 --- a/test/62.decode-only.js +++ b/test/62.decode-only.js @@ -4,7 +4,7 @@ var assert = require("assert"); var decode = require("../lib/decode").decode; var ExtBuffer = require("../lib/ext-buffer").ExtBuffer; -var TITLE = __filename.replace(/^.*\//, ""); +var TITLE = "62.decode-only.js"; describe(TITLE, function() { it("decode", function() { diff --git a/test/64.decode-limit.js b/test/64.decode-limit.js index 32cd9d1..7dacce2 100644 --- a/test/64.decode-limit.js +++ b/test/64.decode-limit.js @@ -1,10 +1,8 @@ #!/usr/bin/env mocha -R spec var assert = require("assert"); -var msgpackJS = "../index"; -var isBrowser = ("undefined" !== typeof window); -var msgpack = isBrowser && window.msgpack || require(msgpackJS); -var TITLE = __filename.replace(/^.*\//, ""); +var msgpack = require("../index"); +var TITLE = "64.decode-limit.js"; describe(TITLE, function() { // An array32/map32 header may declare up to 2^32-1 elements. Decoding a