From eedab933e3131ec164a697bf85bf33a99299e62b Mon Sep 17 00:00:00 2001
From: Daniel Meyer <8926560+pubkey@users.noreply.github.com>
Date: Mon, 30 Oct 2023 03:22:02 +0100
Subject: [PATCH] Feature/deno (#1288)
* ADD deno support
* ADD deno support
* ADD docs
* FIX lint
* FIX test
* UPDATE node
* FIX check
* FIX tests
* CLEAR cache
* PIN node version
---
.github/README.md | 8 ++--
.github/workflows/main.yml | 75 +++++++++++++++++++++++++++++++++++---
CHANGELOG.md | 2 +
README.md | 2 +-
package.json | 12 +++++-
src/methods/native.js | 9 +++++
test/test-deno.js | 34 +++++++++++++++++
7 files changed, 129 insertions(+), 13 deletions(-)
create mode 100644 test/test-deno.js
diff --git a/.github/README.md b/.github/README.md
index f48a3b00..06f8a1b5 100644
--- a/.github/README.md
+++ b/.github/README.md
@@ -7,7 +7,7 @@
BroadcastChannel
- A BroadcastChannel to send data across multiple browser-tabs or nodejs-processes
+ A BroadcastChannel to send data across multiple browser-tabs or nodejs-processes or Deno-Deploy-Instances
+ LeaderElection over the channels
@@ -22,7 +22,7 @@
* * *
-A BroadcastChannel that allows you to send data between different browser-tabs or nodejs-processes.
+A BroadcastChannel that allows you to send data between different browser-tabs or nodejs-processes or Deno-Deploy-Instances.
- It works completely **client-side** and **offline**,
- Tested on **old browsers**, **new browsers**, **WebWorkers**, **Iframes** and **NodeJs**.
@@ -188,7 +188,7 @@ Depending in which environment this is used, a proper method is automatically se
| Method | Used in | Description |
| ---------------- | --------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| **Native** | [Modern Browsers](https://caniuse.com/broadcastchannel) | If the browser supports the BroadcastChannel-API, this method will be used because it is the fastest |
+| **Native** | [Modern Browsers](https://caniuse.com/broadcastchannel) | If the browser supports the BroadcastChannel-API, this method will be used because it is the fastest. This is also used in Deno runtimes. |
| **IndexedDB** | [Browsers with WebWorkers](https://caniuse.com/#feat=indexeddb) | If there is no native BroadcastChannel support, the IndexedDB method is used because it supports messaging between browser-tabs, iframes and WebWorkers |
| **LocalStorage** | [Older Browsers](https://caniuse.com/#feat=namevalue-storage) | In older browsers that do not support IndexedDb, a localstorage-method is used |
| **Sockets** | NodeJs | In NodeJs the communication is handled by sockets that send each other messages |
@@ -282,7 +282,7 @@ This module is optimised for:
- This is not a polyfill. Do not set this module to `window.BroadcastChannel`. This implementation behaves similiar to the [BroadcastChannel-Standard](https://developer.mozilla.org/en-US/docs/Web/API/Broadcast_Channel_API) with these limitations:
- You can only send data that can be `JSON.stringify`-ed,
- While the offical API emits [onmessage-events](https://developer.mozilla.org/en-US/docs/Web/API/BroadcastChannel/onmessage), this module directly emitts the data which was posted.
-- This is not a replacement for a message queue. If you use this in NodeJs and want send more than 50 messages per second, you should use proper [IPC-Tooling](https://en.wikipedia.org/wiki/Message_queue).
+- This is not a replacement for a message queue. If you use this in NodeJs or Deno and want send more than 50 messages per second, you should use proper [IPC-Tooling](https://en.wikipedia.org/wiki/Message_queue).
## Browser Support
diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
index 20949a2f..105b77a1 100644
--- a/.github/workflows/main.yml
+++ b/.github/workflows/main.yml
@@ -13,6 +13,11 @@ on:
# Allows you to run this workflow manually from the Actions tab
workflow_dispatch:
+# https://stackoverflow.com/a/72408109/3443137
+concurrency:
+ group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
+ cancel-in-progress: true
+
# A workflow run is made up of one or more jobs that can run sequentially or in parallel
jobs:
# This workflow contains a single job called "build"
@@ -24,6 +29,10 @@ jobs:
steps:
# Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
- uses: actions/checkout@v4
+ - name: Setup Node.js environment
+ uses: actions/setup-node@v4.0.0
+ with:
+ node-version: '20.9.0'
# https://docs.github.com/en/free-pro-team@latest/actions/guides/caching-dependencies-to-speed-up-workflows
- name: Reuse npm cache folder
@@ -37,10 +46,10 @@ jobs:
./node_modules
./test-electron/node_modules
# invalidate cache when any package.json changes
- key: ${{ runner.os }}-npm-x1-${{ env.cache-name }}-${{ hashFiles('**/package.json') }}
+ key: ${{ runner.os }}-npm-x2-${{ env.cache-name }}-${{ hashFiles('**/package.json') }}
restore-keys: |
- ${{ runner.os }}-npm-x1-${{ env.cache-name }}-
- ${{ runner.os }}-npm-x1-
+ ${{ runner.os }}-npm-x2-${{ env.cache-name }}-
+ ${{ runner.os }}-npm-x2-
${{ runner.os }}-
# install
@@ -89,7 +98,7 @@ jobs:
runs-on: ubuntu-22.04
strategy:
matrix:
- node: ['17.3.0', '18.12.1']
+ node: ['18.18.2', '20.9.0']
steps:
- uses: actions/checkout@v4
- name: Setup Node.js environment
@@ -108,9 +117,9 @@ jobs:
./node_modules
./test-electron/node_modules
# invalidate cache when any package.json changes
- key: ${{ runner.os }}-npm-test-node-x1-${{ matrix.node }}-${{ env.cache-name }}-${{ hashFiles('**/package.json') }}
+ key: ${{ runner.os }}-npm-test-node-x2-${{ matrix.node }}-${{ env.cache-name }}-${{ hashFiles('**/package.json') }}
restore-keys: |
- ${{ runner.os }}-npm-test-node-x1-${{ matrix.node }}-${{ env.cache-name }}-
+ ${{ runner.os }}-npm-test-node-x2-${{ matrix.node }}-${{ env.cache-name }}-
${{ runner.os }}-npm-test-node
${{ runner.os }}-test-node
@@ -124,6 +133,60 @@ jobs:
run: npm run test:node
+ test-deno:
+ runs-on: ubuntu-22.04
+ steps:
+ - uses: actions/checkout@v4
+ - name: Setup Node.js environment
+ uses: actions/setup-node@v4.0.0
+ with:
+ node-version: '20.9.0'
+
+ # https://docs.github.com/en/free-pro-team@latest/actions/guides/caching-dependencies-to-speed-up-workflows
+ - name: Reuse npm cache folder
+ uses: actions/cache@v3
+ env:
+ cache-name: cache-node-modules
+ with:
+ path: |
+ ~/.npm
+ ./node_modules
+ ./test-electron/node_modules
+ # invalidate cache when any package.json changes
+ key: ${{ runner.os }}-npm-test-deno-x2-${{ env.cache-name }}-${{ hashFiles('**/package.json') }}
+ restore-keys: |
+ ${{ runner.os }}-npm-test-deno-x2-${{ env.cache-name }}-
+ ${{ runner.os }}-npm-test-deno
+ ${{ runner.os }}-test-deno
+
+ - name: install node modules
+ run: npm install --legacy-peer-deps
+
+ - name: build
+ run: npm run build
+
+ - name: Reuse deno cache folder
+ uses: actions/cache@v3
+ env:
+ cache-name: cache-deno-modules
+ with:
+ path: |
+ /home/runner/.cache/deno
+ # do not cache based on package.json because deno install randomly fails
+ # and it would then never succeed on the first run on dependency updateds
+ key: ${{ runner.os }}-deno-x2-
+
+ - uses: denoland/setup-deno@v1
+ with:
+ # https://github.com/denoland/deno/releases
+ deno-version: "1.37.2"
+ - name: run deno tests
+ run: |
+ sudo npm i -g cross-env
+ deno info
+ npm run test:deno
+
+
# TODO this does not work atm. fix this.
# - name: test electron
# uses: GabrielBB/xvfb-action@v1
diff --git a/CHANGELOG.md b/CHANGELOG.md
index e38c004d..438b758c 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -3,6 +3,8 @@
## X.X.X (comming soon)
+- ADD support for the Deno runtime
+
## 5.5.1 (23 October 2023)
- REPLACE `new Date().getTime()` with `Date.now()` which is faster
diff --git a/README.md b/README.md
index 6727879d..2dd9184d 100644
--- a/README.md
+++ b/README.md
@@ -15,7 +15,7 @@
BroadcastChannel
- A BroadcastChannel that works in old browsers, new browsers, WebWorkers and NodeJs
+ A BroadcastChannel that works in old browsers, new browsers, WebWorkers and NodeJs and Deno
+ LeaderElection over the channels
diff --git a/package.json b/package.json
index c7631288..17491ae6 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
{
"name": "broadcast-channel",
"version": "5.5.1",
- "description": "A BroadcastChannel that works in New Browsers, Old Browsers, WebWorkers and NodeJs and iframes",
+ "description": "A BroadcastChannel that works in New Browsers, Old Browsers, WebWorkers, NodeJs, Deno and iframes",
"exports": {
".": {
"node": {
@@ -9,6 +9,11 @@
"import": "./dist/esnode/index.js",
"default": "./dist/es5node/index.js"
},
+ "deno": {
+ "types": "./types/index.d.ts",
+ "import": "./dist/esbrowser/index.js",
+ "default": "./dist/lib/index.js"
+ },
"browser": {
"types": "./types/index.d.ts",
"import": "./dist/esbrowser/index.js",
@@ -34,7 +39,9 @@
"postMessage",
"crosstab",
"ipc",
- "leader-election"
+ "leader-election",
+ "queue",
+ "inter-process"
],
"repository": {
"type": "git",
@@ -58,6 +65,7 @@
"test:module:cjs": "npm run build:es5node && mocha ./test/module.cjs.test.js -b --timeout 6000 --exit",
"test:node": "npm run build:es5node && mocha ./test/index.test.js -b --timeout 6000 --exit",
"test:node:loop": "npm run test:node && npm run test:node:loop",
+ "test:deno": "deno run --allow-env --unstable ./test/test-deno.js",
"test:browser": "npm run build && karma start ./config/karma.conf.js --single-run",
"test:e2e": "concurrently \"npm run docs:serve\" \"sleep 20 && testcafe -b && testcafe chrome -e test/e2e.test.js --hostname localhost\" --kill-others --success first",
"test:typings": "npm run build && mocha ./test/typings.test.js -b --timeout 12000 --exit",
diff --git a/src/methods/native.js b/src/methods/native.js
index d06862b7..fa14d229 100644
--- a/src/methods/native.js
+++ b/src/methods/native.js
@@ -1,3 +1,4 @@
+
import {
microSeconds as micro,
PROMISE_RESOLVED_VOID
@@ -42,6 +43,14 @@ export function onMessage(channelState, fn) {
}
export function canBeUsed() {
+
+ // Deno runtime
+ // eslint-disable-next-line
+ if (typeof globalThis !== 'undefined' && globalThis.Deno && globalThis.Deno.args) {
+ return true;
+ }
+
+ // Browser runtime
if (
(typeof window !== 'undefined' || typeof self !== 'undefined') &&
typeof BroadcastChannel === 'function'
diff --git a/test/test-deno.js b/test/test-deno.js
new file mode 100644
index 00000000..9aa974fb
--- /dev/null
+++ b/test/test-deno.js
@@ -0,0 +1,34 @@
+import { BroadcastChannel } from '../dist/esbrowser/index.js';
+import { randomString } from 'async-test-util';
+import assert from 'assert';
+export async function run() {
+
+ console.log('--- 1');
+
+ console.dir({
+ // eslint-disable-next-line
+ 'globalThis.Deno': !!globalThis.Deno,
+ // eslint-disable-next-line
+ 'globalThis.Deno.args': !!globalThis.Deno.args
+ });
+ console.log('--- 2');
+ // eslint-disable-next-line
+ console.log(Object.keys(Deno).sort().join(', '));
+
+ console.log('--- 3');
+
+
+ const bc = new BroadcastChannel(randomString());
+ console.log('bc.type: ' + bc.type);
+
+
+ /**
+ * Deno should use its global native BroadcastChannel
+ * @link https://docs.deno.com/deploy/api/runtime-broadcast-channel
+ */
+ assert.strictEqual(bc.type, 'native');
+
+ await bc.postMessage({ foo: 'bar' });
+ await bc.close();
+}
+run();