-
Notifications
You must be signed in to change notification settings - Fork 15
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #35 from tildeio/peer-dep-not-required
Remove the need to install @starbeam/peer as a peer
- Loading branch information
Showing
6 changed files
with
96 additions
and
37 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
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 |
---|---|---|
@@ -1,2 +1,2 @@ | ||
export { REACTIVE, UNINITIALIZED } from "./src/constants.js"; | ||
export { NOW, REACTIVE, UNINITIALIZED } from "./src/constants.js"; | ||
export { bump, now } from "./src/now.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 |
---|---|---|
@@ -1,7 +1,24 @@ | ||
/** | ||
* The `UNINITIALIZED` symbol represents a special internal value that can be used to differentiate | ||
* between any user-supplied value and the state of being uninitialized. | ||
* | ||
* You do not **need** to import `@starbeam/peer` to get this symbol, as it is specified using | ||
* `Symbol.for`. | ||
*/ | ||
const UNINITIALIZED = Symbol.for("starbeam.UNINITIALIZED"); | ||
type UNINITIALIZED = typeof UNINITIALIZED; | ||
|
||
/** | ||
* The `REACTIVE` symbol is the protocol entry point for reactive values. Implementations of | ||
* the `ReactiveProtocol` interface specify their reactive behavior under this symbol. | ||
*/ | ||
const REACTIVE: unique symbol = Symbol.for("starbeam.REACTIVE"); | ||
type REACTIVE = typeof REACTIVE; | ||
|
||
export { REACTIVE, UNINITIALIZED }; | ||
/** | ||
* The `NOW` symbol is the name on `globalThis` that is used to store the current timestamp. | ||
*/ | ||
const NOW: unique symbol = Symbol.for("starbeam.NOW"); | ||
type NOW = typeof NOW; | ||
|
||
export { NOW, REACTIVE, UNINITIALIZED }; |
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,11 @@ | ||
import type { NOW } from "./constants.js"; | ||
|
||
export interface Clock { | ||
timestamp: number; | ||
} | ||
|
||
export interface GlobalWithNow { | ||
[NOW]: { | ||
timestamp: number; | ||
}; | ||
} |
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 |
---|---|---|
@@ -1,12 +1,33 @@ | ||
const NOW = { | ||
timestamp: 0, | ||
}; | ||
import { NOW } from "./constants.js"; | ||
import type { GlobalWithNow } from "./env.js"; | ||
|
||
/** | ||
* The `CLOCK` constant is a universal monotonically increasing clock. The `Timestamp` class is used | ||
* in `@starbeam/timeline` and `@starbeam/core`, but `Timestamp` defers to this constant. This means | ||
* that multiple copies of `@starbeam/timeline` will still see the same monotonically increasing clock. | ||
* | ||
* The term "timestamp" is used in this context to refer to a monotonically increasing number, where | ||
* each number represents a different moment in time. | ||
*/ | ||
let CLOCK = (globalThis as unknown as GlobalWithNow)[NOW]; | ||
|
||
if (!CLOCK) { | ||
CLOCK = (globalThis as unknown as GlobalWithNow)[NOW] = { | ||
timestamp: 0, | ||
}; | ||
} | ||
|
||
/** | ||
* Get the current timestamp. | ||
*/ | ||
export function now(): number { | ||
return NOW.timestamp; | ||
return CLOCK.timestamp; | ||
} | ||
|
||
/** | ||
* Increment the current timestamp, and return the new one. | ||
*/ | ||
export function bump(): number { | ||
NOW.timestamp = NOW.timestamp + 1; | ||
CLOCK.timestamp = CLOCK.timestamp + 1; | ||
return now(); | ||
} |
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 |
---|---|---|
@@ -1,46 +1,52 @@ | ||
import { UNINITIALIZED } from "@starbeam/peer"; | ||
import { NOW, REACTIVE, UNINITIALIZED } from "@starbeam/peer"; | ||
import { describe, expect, test } from "vitest"; | ||
|
||
describe("UNINITALIZED", () => { | ||
testSymbol(UNINITIALIZED, "UNINITIALIZED"); | ||
testSymbol(REACTIVE, "REACTIVE"); | ||
testSymbol(NOW, "NOW"); | ||
}); | ||
|
||
function testSymbol(symbol: symbol, description: string) { | ||
test("is a symbol", () => { | ||
expect(typeof UNINITIALIZED).toBe("symbol"); | ||
expect(UNINITIALIZED.description).toBe("starbeam.UNINITIALIZED"); | ||
expect(typeof symbol).toBe("symbol"); | ||
expect(symbol.description).toBe(`starbeam.${description}`); | ||
}); | ||
|
||
test("is the same value each time (i.e. not an export let)", () => { | ||
expect(UNINITIALIZED).toBe(UNINITIALIZED); | ||
expect(symbol).toBe(symbol); | ||
}); | ||
|
||
test("is registered at Symbol.for('starbeam.UNINITIALIZED')", () => { | ||
expect(Symbol.for("starbeam.UNINITIALIZED")).toBe(UNINITIALIZED); | ||
test(`is registered at Symbol.for('starbeam.${description}')`, () => { | ||
expect(Symbol.for(`starbeam.${description}`)).toBe(symbol); | ||
}); | ||
|
||
test("isn't one of the builtin symbols", () => { | ||
expect(UNINITIALIZED).not.toBe(Symbol.iterator); | ||
expect(UNINITIALIZED).not.toBe(Symbol.toStringTag); | ||
expect(UNINITIALIZED).not.toBe(Symbol.unscopables); | ||
expect(UNINITIALIZED).not.toBe(Symbol.hasInstance); | ||
expect(UNINITIALIZED).not.toBe(Symbol.isConcatSpreadable); | ||
expect(UNINITIALIZED).not.toBe(Symbol.match); | ||
expect(UNINITIALIZED).not.toBe(Symbol.replace); | ||
expect(UNINITIALIZED).not.toBe(Symbol.search); | ||
expect(UNINITIALIZED).not.toBe(Symbol.species); | ||
expect(UNINITIALIZED).not.toBe(Symbol.split); | ||
expect(UNINITIALIZED).not.toBe(Symbol.toPrimitive); | ||
expect(symbol).not.toBe(Symbol.iterator); | ||
expect(symbol).not.toBe(Symbol.toStringTag); | ||
expect(symbol).not.toBe(Symbol.unscopables); | ||
expect(symbol).not.toBe(Symbol.hasInstance); | ||
expect(symbol).not.toBe(Symbol.isConcatSpreadable); | ||
expect(symbol).not.toBe(Symbol.match); | ||
expect(symbol).not.toBe(Symbol.replace); | ||
expect(symbol).not.toBe(Symbol.search); | ||
expect(symbol).not.toBe(Symbol.species); | ||
expect(symbol).not.toBe(Symbol.split); | ||
expect(symbol).not.toBe(Symbol.toPrimitive); | ||
|
||
// it's not node's inspect symbol | ||
expect(UNINITIALIZED).not.toBe(Symbol.for("nodejs.util.inspect.custom")); | ||
expect(symbol).not.toBe(Symbol.for("nodejs.util.inspect.custom")); | ||
|
||
// other react symbols | ||
expect(UNINITIALIZED).not.toBe(Symbol.for("react.element")); | ||
expect(UNINITIALIZED).not.toBe(Symbol.for("react.forward_ref")); | ||
expect(UNINITIALIZED).not.toBe(Symbol.for("react.fragment")); | ||
expect(UNINITIALIZED).not.toBe(Symbol.for("react.profiler")); | ||
expect(UNINITIALIZED).not.toBe(Symbol.for("react.provider")); | ||
expect(UNINITIALIZED).not.toBe(Symbol.for("react.context")); | ||
expect(UNINITIALIZED).not.toBe(Symbol.for("react.concurrent_mode")); | ||
expect(symbol).not.toBe(Symbol.for("react.element")); | ||
expect(symbol).not.toBe(Symbol.for("react.forward_ref")); | ||
expect(symbol).not.toBe(Symbol.for("react.fragment")); | ||
expect(symbol).not.toBe(Symbol.for("react.profiler")); | ||
expect(symbol).not.toBe(Symbol.for("react.provider")); | ||
expect(symbol).not.toBe(Symbol.for("react.context")); | ||
expect(symbol).not.toBe(Symbol.for("react.concurrent_mode")); | ||
|
||
// observable symbol, casting Symbol to avoid TS error | ||
expect(UNINITIALIZED).not.toBe(Symbol.for("rxjs.internal.observable")); | ||
expect(symbol).not.toBe(Symbol.for("rxjs.internal.observable")); | ||
}); | ||
}); | ||
} |