-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add package metadata files and get tests running
- Loading branch information
Showing
16 changed files
with
403 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
build/ | ||
dist/ | ||
**/*.js |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
{ | ||
"extends": "./node_modules/gts/", | ||
"rules": { | ||
"@typescript-eslint/explicit-function-return-type": [ | ||
"error", | ||
{"allowExpressions": true} | ||
], | ||
"func-style": ["error", "declaration"], | ||
"prefer-const": ["error", {"destructuring": "all"}], | ||
// It would be nice to sort import declaration order as well, but that's not | ||
// autofixable and it's not worth the effort of handling manually. | ||
"sort-imports": ["error", {"ignoreDeclarationSort": true}], | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
version: 2 | ||
updates: | ||
- package-ecosystem: "npm" | ||
directory: "/" | ||
schedule: | ||
interval: "weekly" | ||
- package-ecosystem: "github-actions" | ||
directory: "/" | ||
schedule: | ||
interval: "weekly" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
name: CI | ||
|
||
defaults: | ||
run: {shell: bash} | ||
|
||
env: | ||
PROTOC_VERSION: 3.x | ||
|
||
on: | ||
push: | ||
branches: [main, feature.*] | ||
tags: ['**'] | ||
pull_request: | ||
|
||
jobs: | ||
static_analysis: | ||
name: Static analysis | ||
runs-on: ubuntu-latest | ||
|
||
steps: | ||
- uses: actions/checkout@v4 | ||
- uses: actions/setup-node@v4 | ||
with: | ||
node-version: 'lts/*' | ||
check-latest: true | ||
- run: npm install | ||
- run: npm run check | ||
|
||
tests: | ||
name: 'Tests | Node ${{ matrix.node-version }} | ${{ matrix.os }}' | ||
runs-on: ${{ matrix.os }}-latest | ||
|
||
strategy: | ||
matrix: | ||
os: [ubuntu, macos, windows] | ||
node-version: ['lts/*', 'lts/-1', 'lts/-2'] | ||
fail-fast: false | ||
|
||
steps: | ||
- uses: actions/checkout@v4 | ||
- uses: actions/setup-node@v4 | ||
with: | ||
node-version: ${{ matrix.node-version }} | ||
check-latest: true | ||
- run: npm install | ||
- run: npm run test | ||
|
||
deploy: | ||
name: Deploy | ||
runs-on: ubuntu-latest | ||
if: "startsWith(github.ref, 'refs/tags/') && github.repository == 'sass/sync-message-channel'" | ||
needs: [static_analysis, tests, sass_spec] | ||
|
||
steps: | ||
- uses: actions/checkout@v4 | ||
- uses: actions/setup-node@v4 | ||
with: | ||
node-version: 'lts/*' | ||
check-latest: true | ||
registry-url: 'https://registry.npmjs.org' | ||
- run: npm install | ||
- run: npm publish | ||
env: | ||
NODE_AUTH_TOKEN: '${{ secrets.NPM_TOKEN }}' | ||
|
||
typedoc: | ||
runs-on: ubuntu-latest | ||
if: "startsWith(github.ref, 'refs/tags/') && github.repository == 'sass/sync-message-channel'" | ||
needs: [deploy] | ||
|
||
environment: | ||
name: github-pages | ||
url: ${{ steps.deployment.outputs.page_url }} | ||
|
||
permissions: | ||
pages: write | ||
id-token: write | ||
|
||
steps: | ||
- uses: actions/checkout@v4 | ||
- uses: actions/setup-node@v4 | ||
with: | ||
node-version: 'lts/*' | ||
check-latest: true | ||
registry-url: 'https://registry.npmjs.org' | ||
- run: npm install | ||
- run: npm run doc | ||
|
||
- name: Upload static files as artifact | ||
uses: actions/upload-pages-artifact@v3 | ||
with: {path: docs} | ||
|
||
- id: deployment | ||
uses: actions/deploy-pages@v4 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
.DS_Store | ||
build | ||
dist | ||
node_modules | ||
npm-debug.log* | ||
package-lock.json | ||
|
||
# Editors | ||
.idea | ||
.vscode | ||
*.njsproj | ||
*.ntvs* | ||
*.sln | ||
*.suo | ||
*.sw? |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
module.exports = { | ||
...require('gts/.prettierrc.json'), | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
Sass is more than a technology; Sass is driven by the community of individuals | ||
that power its development and use every day. As a community, we want to embrace | ||
the very differences that have made our collaboration so powerful, and work | ||
together to provide the best environment for learning, growing, and sharing of | ||
ideas. It is imperative that we keep Sass a fun, welcoming, challenging, and | ||
fair place to play. | ||
|
||
[The full community guidelines can be found on the Sass website.][link] | ||
|
||
[link]: http://sass-lang.com/community-guidelines |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
# How to Contribute | ||
|
||
We'd love to accept your patches and contributions to this project. There are | ||
just a few small guidelines you need to follow. | ||
|
||
* [Contributor License Agreement](#contributor-license-agreement) | ||
* [Code Reviews](#code-reviews) | ||
* [Large Language Models](#large-language-models) | ||
|
||
## Contributor License Agreement | ||
|
||
Contributions to this project must be accompanied by a Contributor License | ||
Agreement. You (or your employer) retain the copyright to your contribution; | ||
this simply gives us permission to use and redistribute your contributions as | ||
part of the project. Head over to <https://cla.developers.google.com/> to see | ||
your current agreements on file or to sign a new one. | ||
|
||
You generally only need to submit a CLA once, so if you've already submitted one | ||
(even if it was for a different project), you probably don't need to do it | ||
again. | ||
|
||
## Code Reviews | ||
|
||
All submissions, including submissions by project members, require review. We | ||
use GitHub pull requests for this purpose. Consult | ||
[GitHub Help](https://help.github.com/articles/about-pull-requests/) for more | ||
information on using pull requests. | ||
|
||
## Large Language Models | ||
|
||
Do not submit any code or prose written or modified by large language models or | ||
"artificial intelligence" such as GitHub Copilot or ChatGPT to this project. | ||
These tools produce code that looks plausible, which means that not only is it | ||
likely to contain bugs those bugs are likely to be difficult to notice on | ||
review. In addition, because these models were trained indiscriminately and | ||
non-consensually on open-source code with a variety of licenses, it's not | ||
obvious that we have the moral or legal right to redistribute code they | ||
generate. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
Copyright (c) 2024, Google LLC | ||
|
||
Permission is hereby granted, free of charge, to any person obtaining | ||
a copy of this software and associated documentation files (the | ||
"Software"), to deal in the Software without restriction, including | ||
without limitation the rights to use, copy, modify, merge, publish, | ||
distribute, sublicense, and/or sell copies of the Software, and to | ||
permit persons to whom the Software is furnished to do so, subject to | ||
the following conditions: | ||
|
||
The above copyright notice and this permission notice shall be | ||
included in all copies or substantial portions of the Software. | ||
|
||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | ||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | ||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE | ||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION | ||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION | ||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,124 @@ | ||
# `sync-message-port` | ||
|
||
This package exposes a utility class that encapsulates the ability to send and | ||
receive messages with arbitrary structure across Node.js worker boundaries. It | ||
can be used as the building block for synchronous versions of APIs that are | ||
traditionally only available asynchronously in the Node.js ecosystem by running | ||
the asynchronous APIs in a worker and accessing their results synchronously from | ||
the main thread. | ||
|
||
See [the `sync-process` package] for an example of `sync-message-channel` in | ||
action. | ||
|
||
[the `sync-process` package]: https://github.com/sass/sync-process | ||
|
||
## Usage | ||
|
||
1. Use `SyncMessagePort.createChanenl()` to create a message channel that's set | ||
up to be compatible iwth `SyncMessagePort`s. A normal `MessageChannel` won't | ||
work! | ||
|
||
2. You can send this `MessageChannel`'s ports across worker boundaries just like | ||
any other `MessagePort`. Send one to the worker you want to communicate with | ||
synchronously. | ||
|
||
3. Once you're ready to start sending and receiving messages, wrap *both* ports | ||
in `new SyncMessagePort()`, even if one is only ever going to be sending | ||
messages and not receiving them. | ||
|
||
4. Use `SyncMessagePort.postMessage()` to send messages and | ||
`SyncMessagePort.receiveMessage()` to receive them synchronously. | ||
|
||
```js | ||
import {Worker} from 'node:worker_threads'; | ||
import {SyncMessagePort} from 'sync-message-channel'; | ||
// or | ||
// const {SyncMessagePort} = require('sync-message-port'); | ||
|
||
// Channels must be created using this function. A MessageChannel created by | ||
// hand won't work. | ||
const channel = SyncMessagePort.createChannel(); | ||
const localPort = new SyncMessagePort(channel.port1); | ||
|
||
const worker = new Worker(` | ||
import {workerData} = require('node:worker_threads'); | ||
import {SyncMessagePort} from 'sync-message-channel'; | ||
const remotePort = new SyncMessagePort(workerData.port); | ||
setTimeout(() => { | ||
remotePort.postMessage("hello from worker!"); | ||
}, 2000); | ||
`, { | ||
workerData: {port: channel.port2}, | ||
transferList: [channel.port2], | ||
eval: true, | ||
}); | ||
|
||
// Note that because workers report errors asynchronously, this won't report an | ||
// error if the worker fails to load because the main thread will be | ||
// synchronously waiting for its first message. | ||
worker.on('error', console.error); | ||
|
||
console.log(localPort.receiveMessage()); | ||
``` | ||
|
||
## Why synchrony? | ||
|
||
Although JavaScript in general and Node.js in particular are typically designed | ||
to embrace asynchrony, there are a number of reasons why a synchronous API may | ||
be preferable or even necessary. | ||
|
||
### No a/synchronous polymorphism | ||
|
||
Although `async`/`await` and the `Promise` API has substantially improved the | ||
usability of writing asynchronous code in JavaScript, it doesn't address one | ||
core issue: there's no way to write code that's *polymorphic* over asynchrony. | ||
Put in simpler terms, there's no language-level way to write a complex function | ||
that takes a callback and to run that functions synchronously if the callback is | ||
synchronous and asynchronously otherwise. The only option is to write the | ||
function twice. | ||
|
||
This poses a real, practical problem when interacting with libraries. Suppose | ||
you have a library that takes a callback option—for example, an HTML | ||
sanitization library that takes a callback to determine how to handle a given | ||
`<a href="...">`. The library doesn't need to do any IO itself, so it's written | ||
synchronously. But what if your callback wants to make an HTTP request to | ||
determine how to handle a tag? You're stuck unless you can make that request | ||
synchronous. This library makes that possible. | ||
|
||
### Performance considerations | ||
|
||
Asynchrony is generally more performant in situations where there's a large | ||
amount of concurrent IO happening. But when performance is CPU-bound, it's often | ||
substantially worse due to the overhead of bouncing back and forth between the | ||
event loop and user code. | ||
|
||
As a real-world example, the Sass compiler API supports both synchronous and | ||
asynchronous code paths to work around the polymorphism problem described above. | ||
The logic of these paths is exactly the same—the only difference is that the | ||
asynchronous path's functions all return `Promise`s instead of synchronous | ||
values. Compiling with the asynchronous path often takes 2-3x longer than with | ||
the synchronous path. This means that being able to run plugins synchronously | ||
can provide a substantial overall performance gain, even if the plugins | ||
themselves lose the benefit of concurrency. | ||
|
||
## How does it work? | ||
|
||
This uses [`Atomics`] and [`SharedArrayBuffer`] under the covers to signal | ||
across threads when messages are available, and | ||
[`worker_threads.receiveMessageOnPort()`] to actually retrieve messages. | ||
|
||
[`Atomics`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Atomics | ||
[`SharedArrayBuffer`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/SharedArrayBuffer | ||
[`Worker.receiveMessageOnPort()`]: https://nodejs.org/api/worker_threads.html#workerreceivemessageonportport | ||
|
||
### Can I use this in a browser? | ||
|
||
Unfortunately, no. Browsers don't support any equivalent of | ||
`worker_threads.receiveMessageOnPort()`, even within worker threads. You could | ||
make a similar package that can transmit only binary data (or data that can be | ||
encoded as binary) using only `SharedArrayBuffer`, but that's outside the scope | ||
of this package. | ||
|
||
Disclaimer: this is not an official Google product. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
const config = { | ||
roots: ['<rootDir>/lib/'], | ||
preset: 'ts-jest', | ||
testEnvironment: 'node', | ||
}; | ||
|
||
export default config; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.