generated from tc39/template-for-proposals
-
Notifications
You must be signed in to change notification settings - Fork 63
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
chore: set up basic package config and readme
- Loading branch information
1 parent
31a326e
commit d75f64e
Showing
2 changed files
with
81 additions
and
0 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,14 @@ | ||
{ | ||
"name": "signal-polyfill", | ||
"version": "0.1.0", | ||
"description": "A polyfill for the TC39 Signals proposal.", | ||
"main": "dist/index.js", | ||
"type": "module", | ||
"types": "dist/index.d.ts", | ||
"scripts": { | ||
"build": "tsc -b tsconfig.json", | ||
"watch": "tsc -b tsconfig.json -watch" | ||
}, | ||
"author": "EisenbergEffect", | ||
"license": "MIT" | ||
} |
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,67 @@ | ||
# Signal Polyfill | ||
|
||
A "signal" is a proposed first-class JavaScript data type that enables one-way data flow through cells of state or computations derived from other data. | ||
|
||
This is a polyfill for the `Signal` API that makes these capabilities available in browsers that don't yet support them natively. | ||
|
||
# Examples | ||
|
||
## Using signals | ||
|
||
```js | ||
import { Signal } from "signal-polyfill"; | ||
import { effect } from "./effect.js"; | ||
|
||
const counter = new Signal.State(0); | ||
const isEven = new Signal.Computed(() => (counter.get() & 1) == 0); | ||
const parity = new Signal.Computed(() => isEven.get() ? "even" : "odd"); | ||
|
||
effect(() => console.log(parity.get())); | ||
|
||
setInterval(() => counter.set(counter.get() + 1), 1000); | ||
``` | ||
|
||
> [!NOTE] | ||
> The signal proposal does not include an `effect` API, since such APIs are often deeply integrated with rendering and batch strategies that are highly framework/library dependent. However, the proposal does seek to define a set of primitives that library authors can use to implement their own effects. | ||
### Creating a simple effect | ||
|
||
```js | ||
import { Signal } from "signal-polyfill"; | ||
|
||
let needsEnqueue = false; | ||
|
||
const w = new Signal.subtle.Watcher(() => { | ||
if (needsEnqueue) { | ||
needsEnqueue = false; | ||
queueMicrotask.enqueue(processPending); | ||
} | ||
}); | ||
|
||
function processPending() { | ||
needsEnqueue = true; | ||
|
||
for (const s of w.getPending()) { | ||
s.get(); | ||
} | ||
|
||
w.watch(); | ||
} | ||
|
||
export function effect(callback) { | ||
let onUnwatch; | ||
const computed = new Signal.Computed(() => onUnwatch = callback(), { | ||
[Signal.subtle.unwatched]() { | ||
typeof onUnwatch === "function" && onUnwatch(); | ||
} | ||
}); | ||
|
||
w.watch(computed); | ||
computed.get(); | ||
|
||
return () => w.unwatch(computed); | ||
} | ||
``` | ||
|
||
> [!IMPORTANT] | ||
> The `Signal.subtle` APIs are so named in order to communicate that their correct use requires careful attention to detail. These APIs are not targeted at application-level code, but rather at framework/library authors. |