@wcstack/wakelock 1.12.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.ja.md +173 -0
- package/README.md +175 -0
- package/dist/auto.js +3 -0
- package/dist/auto.min.js +1 -0
- package/dist/index.d.ts +250 -0
- package/dist/index.esm.js +524 -0
- package/dist/index.esm.js.map +1 -0
- package/dist/index.esm.min.js +2 -0
- package/dist/index.esm.min.js.map +1 -0
- package/package.json +71 -0
|
@@ -0,0 +1,524 @@
|
|
|
1
|
+
const _config = {
|
|
2
|
+
tagNames: {
|
|
3
|
+
wakelock: "wcs-wakelock",
|
|
4
|
+
},
|
|
5
|
+
};
|
|
6
|
+
function deepFreeze(obj) {
|
|
7
|
+
if (obj === null || typeof obj !== "object")
|
|
8
|
+
return obj;
|
|
9
|
+
Object.freeze(obj);
|
|
10
|
+
for (const key of Object.keys(obj)) {
|
|
11
|
+
deepFreeze(obj[key]);
|
|
12
|
+
}
|
|
13
|
+
return obj;
|
|
14
|
+
}
|
|
15
|
+
function deepClone(obj) {
|
|
16
|
+
if (obj === null || typeof obj !== "object")
|
|
17
|
+
return obj;
|
|
18
|
+
const clone = {};
|
|
19
|
+
for (const key of Object.keys(obj)) {
|
|
20
|
+
clone[key] = deepClone(obj[key]);
|
|
21
|
+
}
|
|
22
|
+
return clone;
|
|
23
|
+
}
|
|
24
|
+
let frozenConfig = null;
|
|
25
|
+
// Note: this is the live, mutable internal config. It is not part of the public
|
|
26
|
+
// package exports (see exports.ts) — only `getConfig()` (frozen snapshot) and
|
|
27
|
+
// `setConfig()` are surfaced — but a deep path import (`.../src/config.js`) can still
|
|
28
|
+
// reach and mutate it. Accepted as-is for cross-package consistency: every @wcstack
|
|
29
|
+
// package follows this same shape. Use `getConfig()` for a frozen, safe read.
|
|
30
|
+
const config = _config;
|
|
31
|
+
function getConfig() {
|
|
32
|
+
if (!frozenConfig) {
|
|
33
|
+
frozenConfig = deepFreeze(deepClone(_config));
|
|
34
|
+
}
|
|
35
|
+
return frozenConfig;
|
|
36
|
+
}
|
|
37
|
+
function setConfig(partialConfig) {
|
|
38
|
+
if (partialConfig.tagNames) {
|
|
39
|
+
Object.assign(_config.tagNames, partialConfig.tagNames);
|
|
40
|
+
}
|
|
41
|
+
frozenConfig = null;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Headless screen-wake-lock primitive — a thin, framework-agnostic wrapper around
|
|
46
|
+
* the Screen Wake Lock API exposed through the wc-bindable protocol.
|
|
47
|
+
*
|
|
48
|
+
* Unlike the other @wcstack sensors (geolocation / intersection), the wake lock is
|
|
49
|
+
* a pure *sink*: nothing is read from the device. A bound state drives the desired
|
|
50
|
+
* intent (`request()` / `release()`), and the only observable outputs are `held`
|
|
51
|
+
* (whether a sentinel is actually held) and `error`.
|
|
52
|
+
*
|
|
53
|
+
* The OS releases the lock whenever the page stops being visible (tab hidden,
|
|
54
|
+
* window minimized). To honor the declarative intent ("keep awake *while* active"),
|
|
55
|
+
* the Core keeps the desired flag (`_active`) and re-acquires the lock on the next
|
|
56
|
+
* `visibilitychange` back to visible. So `_active` (desired) and `held` (actual)
|
|
57
|
+
* diverge across an auto-release — and only `held` is published, because desired
|
|
58
|
+
* does not change when the OS drops the lock.
|
|
59
|
+
*
|
|
60
|
+
* Never-throw: `request()` never rejects (a failure surfaces via `error`), and an
|
|
61
|
+
* unsupported environment is a silent no-op (`held` stays false), consistent with
|
|
62
|
+
* the other @wcstack sensors.
|
|
63
|
+
*/
|
|
64
|
+
class WakeLockCore extends EventTarget {
|
|
65
|
+
static wcBindable = {
|
|
66
|
+
protocol: "wc-bindable",
|
|
67
|
+
version: 1,
|
|
68
|
+
properties: [
|
|
69
|
+
{ name: "held", event: "wcs-wakelock:held-changed" },
|
|
70
|
+
{ name: "error", event: "wcs-wakelock:error" },
|
|
71
|
+
],
|
|
72
|
+
commands: [
|
|
73
|
+
{ name: "request", async: true },
|
|
74
|
+
{ name: "release" },
|
|
75
|
+
],
|
|
76
|
+
};
|
|
77
|
+
_target;
|
|
78
|
+
_type;
|
|
79
|
+
// `_active` is the desired intent (input); `_held` is whether a sentinel is
|
|
80
|
+
// actually held right now (output). They diverge across an OS auto-release.
|
|
81
|
+
_active = false;
|
|
82
|
+
_held = false;
|
|
83
|
+
_error = null;
|
|
84
|
+
_sentinel = null;
|
|
85
|
+
// Bumped on every release()/new acquire so an in-flight async request() that
|
|
86
|
+
// resolves late can detect it was superseded and drop its sentinel (mirrors the
|
|
87
|
+
// generation guards in GeolocationCore).
|
|
88
|
+
_gen = 0;
|
|
89
|
+
// True while an `_acquire()` is awaiting `navigator.wakeLock.request()`. The
|
|
90
|
+
// `_held` flag is only set *after* that await resolves, so it cannot guard
|
|
91
|
+
// against concurrent entry: two rapid visibilitychange events (or a Shell toggle
|
|
92
|
+
// overlapping an in-flight request) would both pass `!this._held` and each call
|
|
93
|
+
// `request()`. This in-flight flag closes that window — a re-entrant acquire is a
|
|
94
|
+
// no-op. The `_gen` guard still ensures the *final* state is correct; this just
|
|
95
|
+
// avoids the redundant `request()` call (and its duplicate error path on a denied
|
|
96
|
+
// environment).
|
|
97
|
+
_acquiring = false;
|
|
98
|
+
_visibilityBound = false;
|
|
99
|
+
constructor(target, type = "screen") {
|
|
100
|
+
super();
|
|
101
|
+
this._target = target ?? this;
|
|
102
|
+
this._type = type;
|
|
103
|
+
}
|
|
104
|
+
get held() {
|
|
105
|
+
return this._held;
|
|
106
|
+
}
|
|
107
|
+
get error() {
|
|
108
|
+
return this._error;
|
|
109
|
+
}
|
|
110
|
+
/** The desired intent. Read-only reflection; not a wc-bindable property (it does
|
|
111
|
+
* not change on an OS auto-release, so there is nothing to observe). */
|
|
112
|
+
get active() {
|
|
113
|
+
return this._active;
|
|
114
|
+
}
|
|
115
|
+
get type() {
|
|
116
|
+
return this._type;
|
|
117
|
+
}
|
|
118
|
+
set type(value) {
|
|
119
|
+
// Currently effectively a no-op: "screen" is the only standardized lock type,
|
|
120
|
+
// so `WakeLockKind` is a single value and this setter never observes a real
|
|
121
|
+
// change. Kept as a forward-compatible seam for when the spec adds lock types.
|
|
122
|
+
//
|
|
123
|
+
// Takes effect on the next acquire. Changing the type mid-hold deliberately does
|
|
124
|
+
// NOT re-acquire — the live sentinel is left as is, so a type change applies only
|
|
125
|
+
// from the following acquire. If multiple lock types are ever added this becomes
|
|
126
|
+
// an observable behavior gap (a held lock keeps its old type until release/re-
|
|
127
|
+
// acquire) and must be re-examined — likely re-acquire here when held.
|
|
128
|
+
this._type = value;
|
|
129
|
+
}
|
|
130
|
+
// --- State setters with event dispatch ---
|
|
131
|
+
_setHeld(held) {
|
|
132
|
+
if (this._held === held)
|
|
133
|
+
return;
|
|
134
|
+
this._held = held;
|
|
135
|
+
this._target.dispatchEvent(new CustomEvent("wcs-wakelock:held-changed", {
|
|
136
|
+
detail: held,
|
|
137
|
+
bubbles: true,
|
|
138
|
+
}));
|
|
139
|
+
}
|
|
140
|
+
_setError(error) {
|
|
141
|
+
// Value guard, not just reference: a denied request rejects with a *fresh*
|
|
142
|
+
// Error on every visibility-driven retry, so a reference compare would let a
|
|
143
|
+
// permanently-denied environment re-dispatch the same failure on each
|
|
144
|
+
// hidden→visible toggle. Compare name+message too. Transitions through null (a
|
|
145
|
+
// success clears the error) always re-fire, so a genuinely new failure is seen.
|
|
146
|
+
if (this._sameError(this._error, error))
|
|
147
|
+
return;
|
|
148
|
+
this._error = error;
|
|
149
|
+
this._target.dispatchEvent(new CustomEvent("wcs-wakelock:error", {
|
|
150
|
+
detail: error,
|
|
151
|
+
bubbles: true,
|
|
152
|
+
}));
|
|
153
|
+
}
|
|
154
|
+
_sameError(a, b) {
|
|
155
|
+
if (a === b)
|
|
156
|
+
return true;
|
|
157
|
+
if (a !== null && b !== null)
|
|
158
|
+
return a.name === b.name && a.message === b.message;
|
|
159
|
+
return false;
|
|
160
|
+
}
|
|
161
|
+
// --- Public API ---
|
|
162
|
+
/**
|
|
163
|
+
* Mark the lock as desired and acquire it. Idempotent while already held. If the
|
|
164
|
+
* API is unavailable or the page is currently hidden, the desired flag is still
|
|
165
|
+
* set (so the lock is acquired on the next return to visibility) but nothing is
|
|
166
|
+
* acquired now. Never rejects — a request failure surfaces via `error`.
|
|
167
|
+
*/
|
|
168
|
+
async request() {
|
|
169
|
+
this._active = true;
|
|
170
|
+
this._ensureVisibilityListener();
|
|
171
|
+
await this._acquire();
|
|
172
|
+
}
|
|
173
|
+
/** Mark the lock as no longer desired and release any held sentinel. */
|
|
174
|
+
release() {
|
|
175
|
+
this._active = false;
|
|
176
|
+
// Invalidate any in-flight acquire so a late-resolving request() drops its
|
|
177
|
+
// sentinel instead of leaving a lock held after release.
|
|
178
|
+
this._gen++;
|
|
179
|
+
const sentinel = this._sentinel;
|
|
180
|
+
if (sentinel) {
|
|
181
|
+
this._sentinel = null;
|
|
182
|
+
sentinel.removeEventListener("release", this._onRelease);
|
|
183
|
+
void sentinel.release().catch(() => { });
|
|
184
|
+
}
|
|
185
|
+
this._setHeld(false);
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* Full teardown: remove the visibility listener and release any held sentinel.
|
|
189
|
+
* Call from the Shell's `disconnectedCallback`.
|
|
190
|
+
*
|
|
191
|
+
* Semantics: this is a terminal teardown, not a pause. After `dispose()` the Core
|
|
192
|
+
* is meant to be discarded — there is no re-arm step, and the visibility listener
|
|
193
|
+
* is gone, so an OS auto-release will no longer be followed by a re-acquire. A
|
|
194
|
+
* later `request()` would still work in isolation (it re-attaches the listener via
|
|
195
|
+
* `_ensureVisibilityListener`), but reusing a disposed Core is not an intended path;
|
|
196
|
+
* the Shell always constructs a fresh Core per element instead.
|
|
197
|
+
*/
|
|
198
|
+
dispose() {
|
|
199
|
+
if (this._visibilityBound) {
|
|
200
|
+
document.removeEventListener("visibilitychange", this._onVisibilityChange);
|
|
201
|
+
this._visibilityBound = false;
|
|
202
|
+
}
|
|
203
|
+
this.release();
|
|
204
|
+
}
|
|
205
|
+
// --- Internal ---
|
|
206
|
+
async _acquire() {
|
|
207
|
+
if (this._held)
|
|
208
|
+
return; // idempotent: already holding a sentinel
|
|
209
|
+
if (this._acquiring)
|
|
210
|
+
return; // an acquire is already in flight — don't double-request
|
|
211
|
+
const wakeLock = this._wakeLock();
|
|
212
|
+
if (!wakeLock)
|
|
213
|
+
return; // unsupported — stay active, never acquire (silent no-op)
|
|
214
|
+
if (!this._isVisible())
|
|
215
|
+
return; // hidden — defer to the next visibilitychange
|
|
216
|
+
const gen = ++this._gen;
|
|
217
|
+
this._acquiring = true;
|
|
218
|
+
// Flag management is centralized in `finally` and the coalesced retry is invoked
|
|
219
|
+
// exactly once, AFTER the try/catch/finally settles. This keeps the reject and
|
|
220
|
+
// resolve paths symmetric: neither calls `_retryIfStillDesired()` from inside the
|
|
221
|
+
// try/catch (which would let `finally` re-clear the `_acquiring=true` the retry's
|
|
222
|
+
// synchronous re-entry just set, reopening the double-request window). `superseded`
|
|
223
|
+
// records that a newer release()/request() bumped `_gen` mid-flight so its still-
|
|
224
|
+
// live intent — blocked by the in-flight guard at the time — gets one retry here.
|
|
225
|
+
// NOTE: no early `return` inside the try/catch below — every branch must fall
|
|
226
|
+
// through to the post-`finally` retry. A `return` from inside the try would run
|
|
227
|
+
// `finally` and then exit the function, skipping the `if (superseded)` retry.
|
|
228
|
+
let superseded = false;
|
|
229
|
+
let sentinel = null;
|
|
230
|
+
let failed = null;
|
|
231
|
+
try {
|
|
232
|
+
sentinel = await wakeLock.request(this._type);
|
|
233
|
+
}
|
|
234
|
+
catch (e) {
|
|
235
|
+
if (gen !== this._gen) {
|
|
236
|
+
// Superseded while awaiting — drop this stale failure (do not clobber the
|
|
237
|
+
// newer state) and let the post-finally retry honor the live intent.
|
|
238
|
+
superseded = true;
|
|
239
|
+
}
|
|
240
|
+
else {
|
|
241
|
+
failed = this._normalizeError(e);
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
finally {
|
|
245
|
+
// The sole owner of the flag clears it here — on every exit path. A concurrent
|
|
246
|
+
// re-entrant `_acquire()` was a no-op at the `_acquiring` guard, so it never owns
|
|
247
|
+
// the flag; a superseding release()/acquire only bumps `_gen` and does not start
|
|
248
|
+
// its own in-flight cycle until this clears the flag. Because this runs before
|
|
249
|
+
// the retry below, the retry's `_acquiring=true` is never clobbered.
|
|
250
|
+
this._acquiring = false;
|
|
251
|
+
}
|
|
252
|
+
if (sentinel !== null && gen !== this._gen) {
|
|
253
|
+
// release() (or a newer acquire) ran while we awaited — this sentinel is
|
|
254
|
+
// unwanted; drop it so no lock lingers, and retry the newer intent below.
|
|
255
|
+
void sentinel.release().catch(() => { });
|
|
256
|
+
superseded = true;
|
|
257
|
+
}
|
|
258
|
+
else if (sentinel !== null) {
|
|
259
|
+
this._sentinel = sentinel;
|
|
260
|
+
sentinel.addEventListener("release", this._onRelease);
|
|
261
|
+
this._setError(null);
|
|
262
|
+
this._setHeld(true);
|
|
263
|
+
}
|
|
264
|
+
else if (failed !== null) {
|
|
265
|
+
// A live (non-superseded) failure: surface it. Never retried — the intent is
|
|
266
|
+
// honored but the environment denied it, so looping would spin.
|
|
267
|
+
this._setError(failed);
|
|
268
|
+
this._setHeld(false);
|
|
269
|
+
}
|
|
270
|
+
// Coalesced retry: at most one re-attempt per supersession, after the flag is
|
|
271
|
+
// clear. The `_acquiring` guard inside still protects any concurrent re-entry that
|
|
272
|
+
// overlaps THIS retry's own in-flight window (reject- and resolve-retry alike).
|
|
273
|
+
if (superseded)
|
|
274
|
+
this._retryIfStillDesired();
|
|
275
|
+
}
|
|
276
|
+
/**
|
|
277
|
+
* Re-attempt an acquire after an in-flight one was *superseded* (its generation no
|
|
278
|
+
* longer matches), but only if the lock is still desired, not already held, and the
|
|
279
|
+
* page is visible. This recovers a request() that was coalesced away by the
|
|
280
|
+
* in-flight `_acquiring` guard: during a release()→request() overlap, the second
|
|
281
|
+
* request() bumps `_gen` and is a no-op at the guard, so without this retry its
|
|
282
|
+
* still-live intent would be lost until the next visibilitychange or manual call.
|
|
283
|
+
*
|
|
284
|
+
* Bounded — cannot loop forever: a retry runs ONLY on supersession, and a
|
|
285
|
+
* supersession requires an external release()/request() to bump `_gen` mid-flight.
|
|
286
|
+
* A retry's own `_acquire()`, if it is itself not superseded, terminates by either
|
|
287
|
+
* acquiring (held=true) or recording the live failure (held=false, error set) —
|
|
288
|
+
* neither path retries. So a denied environment that keeps rejecting does not
|
|
289
|
+
* recurse; the retry chain length is bounded by the number of external overlaps.
|
|
290
|
+
*/
|
|
291
|
+
_retryIfStillDesired() {
|
|
292
|
+
if (this._active && !this._held && this._isVisible()) {
|
|
293
|
+
void this._acquire();
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
// Fired for an OS release of a held sentinel — which the spec allows for several
|
|
297
|
+
// reasons, NOT only a visibility change: tab hidden / window minimized, but also
|
|
298
|
+
// battery-low, power-saver mode, etc. while the page stays visible. We reflect
|
|
299
|
+
// held=false, then (lease renewal) re-acquire immediately IF the page is still
|
|
300
|
+
// visible and the lock is still desired — because a visible-context release emits no
|
|
301
|
+
// `visibilitychange`, so the visibilitychange listener (②) would never fire and the
|
|
302
|
+
// lock would stay stuck at desired=true / held=false. The hidden case is the no-op
|
|
303
|
+
// here: re-acquire is gated on `_isVisible()`, so a hide-driven release defers to ②
|
|
304
|
+
// (re-acquire on the return to visibility), avoiding a release→acquire loop while
|
|
305
|
+
// hidden.
|
|
306
|
+
_onRelease = () => {
|
|
307
|
+
// The `if (this._sentinel)` false branch is defensive and unreachable in practice:
|
|
308
|
+
// this listener is only ever attached to the live `_sentinel`, and the only paths
|
|
309
|
+
// that null `_sentinel` (this handler itself, and release()) remove this listener
|
|
310
|
+
// in the same step — so the listener and a non-null `_sentinel` are coupled and
|
|
311
|
+
// this never fires with `_sentinel === null`. Guarded anyway in case a host
|
|
312
|
+
// dispatches a spurious second "release". (c8 ignore the unhittable else.)
|
|
313
|
+
/* c8 ignore next */
|
|
314
|
+
if (this._sentinel) {
|
|
315
|
+
this._sentinel.removeEventListener("release", this._onRelease);
|
|
316
|
+
this._sentinel = null;
|
|
317
|
+
}
|
|
318
|
+
this._setHeld(false);
|
|
319
|
+
this._reacquireAfterRelease();
|
|
320
|
+
};
|
|
321
|
+
/**
|
|
322
|
+
* Lease renewal after an OS release while the page is still visible. Honors the
|
|
323
|
+
* "keep awake *while* active" promise for releases that do NOT coincide with a
|
|
324
|
+
* visibility change (battery-low / power-saver), which otherwise leave the lock
|
|
325
|
+
* stuck at desired=true / held=false until the next hide→show cycle.
|
|
326
|
+
*
|
|
327
|
+
* Bounded on failure: this only runs from `_onRelease`, which only fires when a
|
|
328
|
+
* sentinel was genuinely acquired and then released. A re-acquire that FAILS takes
|
|
329
|
+
* `_acquire()`'s live-failure path (error recorded, held=false) and attaches no
|
|
330
|
+
* listener, so it cannot re-enter `_onRelease` — a denied environment records the
|
|
331
|
+
* error once and stops. This is the dominant real path: per the Wake Lock spec a
|
|
332
|
+
* re-request under battery-low / power-saver is rejected (`NotAllowedError`), so the
|
|
333
|
+
* renewal terminates there.
|
|
334
|
+
*
|
|
335
|
+
* The one path NOT bounded by a counter is a pathological host that keeps GRANTING
|
|
336
|
+
* the re-request and then immediately auto-releasing it (grant→release reflux). Each
|
|
337
|
+
* iteration yields to the event loop and consumes a real OS grant, so it is not a
|
|
338
|
+
* tight/synchronous loop, but it would churn request() calls. We deliberately do NOT
|
|
339
|
+
* add a debounce or renewal cap: that reflux is not documented browser behavior
|
|
340
|
+
* (real browsers reject, not grant-then-revoke), and the extra timing state would
|
|
341
|
+
* complicate the pure-sink design to defend a case that does not occur in practice.
|
|
342
|
+
*
|
|
343
|
+
* The `_isVisible()` / `!_acquiring` guards (doubled by `_acquire()`'s own in-flight
|
|
344
|
+
* and held guards) prevent re-entry during an in-flight acquire and while hidden.
|
|
345
|
+
*/
|
|
346
|
+
_reacquireAfterRelease() {
|
|
347
|
+
if (this._active && this._isVisible() && !this._acquiring) {
|
|
348
|
+
void this._acquire();
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
// ② Re-acquire when the page becomes visible again while the lock is still
|
|
352
|
+
// desired but was auto-released. This is what makes `active` a durable intent.
|
|
353
|
+
_onVisibilityChange = () => {
|
|
354
|
+
if (this._isVisible() && this._active && !this._held) {
|
|
355
|
+
void this._acquire();
|
|
356
|
+
}
|
|
357
|
+
};
|
|
358
|
+
_ensureVisibilityListener() {
|
|
359
|
+
if (this._visibilityBound)
|
|
360
|
+
return;
|
|
361
|
+
document.addEventListener("visibilitychange", this._onVisibilityChange);
|
|
362
|
+
this._visibilityBound = true;
|
|
363
|
+
}
|
|
364
|
+
_wakeLock() {
|
|
365
|
+
return navigator.wakeLock ?? null;
|
|
366
|
+
}
|
|
367
|
+
_isVisible() {
|
|
368
|
+
return document.visibilityState === "visible";
|
|
369
|
+
}
|
|
370
|
+
_normalizeError(e) {
|
|
371
|
+
return e instanceof Error ? e : new Error(String(e));
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
/**
|
|
376
|
+
* `<wcs-wakelock>` — declarative Screen Wake Lock.
|
|
377
|
+
*
|
|
378
|
+
* The first @wcstack tag that is a pure *sink*: every other sensor is an
|
|
379
|
+
* element→state producer, but the wake lock is state→element. The headline
|
|
380
|
+
* binding is `active@isPlaying` — hold the screen awake while a bound boolean is
|
|
381
|
+
* true. `active` is the single input knob (a mirrored attribute); `held` and
|
|
382
|
+
* `error` are the observable outputs.
|
|
383
|
+
*
|
|
384
|
+
* The OS auto-releases the lock when the page is hidden; the Core re-acquires it
|
|
385
|
+
* on the next return to visibility while `active` is still set, so the binding
|
|
386
|
+
* means "keep awake *while* active", not just "acquire once".
|
|
387
|
+
*/
|
|
388
|
+
class WcsWakeLock extends HTMLElement {
|
|
389
|
+
// SSR contract (@wcstack/server): the renderer awaits elements declaring
|
|
390
|
+
// `hasConnectedCallbackPromise = true` before snapshotting. The wake lock has no
|
|
391
|
+
// connect-time async fix to await (acquire is fire-and-forget and meaningless
|
|
392
|
+
// server-side), so this is `false` — same as the other synchronous sensor Shells
|
|
393
|
+
// (sse / intersection / worker). Kept (not deleted) because it is the protocol
|
|
394
|
+
// contract surface the server renderer reads via `ctor.hasConnectedCallbackPromise`.
|
|
395
|
+
static hasConnectedCallbackPromise = false;
|
|
396
|
+
// `active` drives request/release; `type` propagates to the Core's next acquire.
|
|
397
|
+
// `manual` is intentionally excluded: it is a connect-time policy ("don't auto-
|
|
398
|
+
// acquire on connect"), not a live switch.
|
|
399
|
+
static observedAttributes = ["active", "type"];
|
|
400
|
+
static wcBindable = {
|
|
401
|
+
...WakeLockCore.wcBindable,
|
|
402
|
+
// Settable surface. `active` is the declarative intent; `type` selects the lock
|
|
403
|
+
// kind; `manual` opts out of auto-acquire on connect. The request / release
|
|
404
|
+
// commands are inherited from the Core via the spread above.
|
|
405
|
+
inputs: [
|
|
406
|
+
{ name: "active", attribute: "active" },
|
|
407
|
+
{ name: "type", attribute: "type" },
|
|
408
|
+
{ name: "manual", attribute: "manual" },
|
|
409
|
+
],
|
|
410
|
+
// Core の commands をそのまま継承(単一情報源)。<wcs-intersect>/<wcs-sse> と同型。
|
|
411
|
+
// spread でも継承されるが、Core に command 追加時の追従漏れを防ぐため明示参照する。
|
|
412
|
+
commands: WakeLockCore.wcBindable.commands,
|
|
413
|
+
};
|
|
414
|
+
_core;
|
|
415
|
+
constructor() {
|
|
416
|
+
super();
|
|
417
|
+
this._core = new WakeLockCore(this);
|
|
418
|
+
}
|
|
419
|
+
// --- Attribute accessors ---
|
|
420
|
+
get active() {
|
|
421
|
+
// Reflects the *attribute*, not the Core's desired intent (`_core.active`). These
|
|
422
|
+
// can diverge: invoking the `request` / `release` commands directly (e.g. via a
|
|
423
|
+
// command-token binding) flips the Core's desired flag without touching the
|
|
424
|
+
// attribute, so `el.active` may read false while `el.held` is true (or vice
|
|
425
|
+
// versa). The attribute is the declarative input surface; the commands are an
|
|
426
|
+
// imperative side door. Bind via `active@...` for a single source of truth.
|
|
427
|
+
return this.hasAttribute("active");
|
|
428
|
+
}
|
|
429
|
+
set active(value) {
|
|
430
|
+
if (value) {
|
|
431
|
+
this.setAttribute("active", "");
|
|
432
|
+
}
|
|
433
|
+
else {
|
|
434
|
+
this.removeAttribute("active");
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
get type() {
|
|
438
|
+
// Only "screen" is standardized; an absent/empty attribute defaults to it.
|
|
439
|
+
return this.getAttribute("type") || "screen";
|
|
440
|
+
}
|
|
441
|
+
set type(value) {
|
|
442
|
+
this.setAttribute("type", value);
|
|
443
|
+
}
|
|
444
|
+
get manual() {
|
|
445
|
+
return this.hasAttribute("manual");
|
|
446
|
+
}
|
|
447
|
+
set manual(value) {
|
|
448
|
+
if (value) {
|
|
449
|
+
this.setAttribute("manual", "");
|
|
450
|
+
}
|
|
451
|
+
else {
|
|
452
|
+
this.removeAttribute("manual");
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
// --- Core delegated getters ---
|
|
456
|
+
get held() {
|
|
457
|
+
return this._core.held;
|
|
458
|
+
}
|
|
459
|
+
get error() {
|
|
460
|
+
return this._core.error;
|
|
461
|
+
}
|
|
462
|
+
// --- Commands ---
|
|
463
|
+
/** Acquire (and keep) the wake lock. Never rejects — see the `error` property. */
|
|
464
|
+
request() {
|
|
465
|
+
return this._core.request();
|
|
466
|
+
}
|
|
467
|
+
/** Release the wake lock and stop re-acquiring it. */
|
|
468
|
+
release() {
|
|
469
|
+
this._core.release();
|
|
470
|
+
}
|
|
471
|
+
// --- Lifecycle ---
|
|
472
|
+
connectedCallback() {
|
|
473
|
+
// Headless resource: no layout box (mirrors the @wcstack sensor convention).
|
|
474
|
+
this.style.display = "none";
|
|
475
|
+
// Propagate the requested lock type to the Core. Currently a no-op in effect:
|
|
476
|
+
// "screen" is the only standardized type, so `type` is always "screen". Wired
|
|
477
|
+
// up as a forward-compatible seam (observedAttributes + setter + this line) for
|
|
478
|
+
// when the spec adds lock types; until then it carries a constant.
|
|
479
|
+
this._core.type = this.type;
|
|
480
|
+
if (!this.manual && this.active) {
|
|
481
|
+
void this._core.request();
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
disconnectedCallback() {
|
|
485
|
+
this._core.dispose();
|
|
486
|
+
}
|
|
487
|
+
attributeChangedCallback(name, oldValue, newValue) {
|
|
488
|
+
if (oldValue === newValue)
|
|
489
|
+
return;
|
|
490
|
+
// Ignore changes applied before connect (e.g. createElement + setAttribute);
|
|
491
|
+
// connectedCallback applies the initial state. Acquiring a lock for a detached
|
|
492
|
+
// element would be wrong.
|
|
493
|
+
if (!this.isConnected)
|
|
494
|
+
return;
|
|
495
|
+
if (name === "type") {
|
|
496
|
+
this._core.type = this.type;
|
|
497
|
+
return;
|
|
498
|
+
}
|
|
499
|
+
// name === "active": a live toggle always drives request/release. `manual` only
|
|
500
|
+
// gates the connect-time auto-acquire, not an explicit author toggle.
|
|
501
|
+
if (this.active) {
|
|
502
|
+
void this._core.request();
|
|
503
|
+
}
|
|
504
|
+
else {
|
|
505
|
+
this._core.release();
|
|
506
|
+
}
|
|
507
|
+
}
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
function registerComponents() {
|
|
511
|
+
if (!customElements.get(config.tagNames.wakelock)) {
|
|
512
|
+
customElements.define(config.tagNames.wakelock, WcsWakeLock);
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
function bootstrapWakeLock(userConfig) {
|
|
517
|
+
if (userConfig) {
|
|
518
|
+
setConfig(userConfig);
|
|
519
|
+
}
|
|
520
|
+
registerComponents();
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
export { WakeLockCore, WcsWakeLock, bootstrapWakeLock, getConfig };
|
|
524
|
+
//# sourceMappingURL=index.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.esm.js","sources":["../src/config.ts","../src/core/WakeLockCore.ts","../src/components/WakeLock.ts","../src/registerComponents.ts","../src/bootstrapWakeLock.ts"],"sourcesContent":["import { IConfig, IWritableConfig } from \"./types.js\";\n\ninterface IInternalConfig extends IConfig {\n tagNames: {\n wakelock: string;\n };\n}\n\nconst _config: IInternalConfig = {\n tagNames: {\n wakelock: \"wcs-wakelock\",\n },\n};\n\nfunction deepFreeze<T>(obj: T): T {\n if (obj === null || typeof obj !== \"object\") return obj;\n Object.freeze(obj);\n for (const key of Object.keys(obj)) {\n deepFreeze((obj as Record<string, unknown>)[key]);\n }\n return obj;\n}\n\nfunction deepClone<T>(obj: T): T {\n if (obj === null || typeof obj !== \"object\") return obj;\n const clone: Record<string, unknown> = {};\n for (const key of Object.keys(obj)) {\n clone[key] = deepClone((obj as Record<string, unknown>)[key]);\n }\n return clone as T;\n}\n\nlet frozenConfig: IConfig | null = null;\n\n// Note: this is the live, mutable internal config. It is not part of the public\n// package exports (see exports.ts) — only `getConfig()` (frozen snapshot) and\n// `setConfig()` are surfaced — but a deep path import (`.../src/config.js`) can still\n// reach and mutate it. Accepted as-is for cross-package consistency: every @wcstack\n// package follows this same shape. Use `getConfig()` for a frozen, safe read.\nexport const config: IConfig = _config as IConfig;\n\nexport function getConfig(): IConfig {\n if (!frozenConfig) {\n frozenConfig = deepFreeze(deepClone(_config));\n }\n return frozenConfig;\n}\n\nexport function setConfig(partialConfig: IWritableConfig): void {\n if (partialConfig.tagNames) {\n Object.assign(_config.tagNames, partialConfig.tagNames);\n }\n frozenConfig = null;\n}\n","import { IWcBindable, WakeLockKind } from \"../types.js\";\n\n/**\n * Minimal structural views of the Screen Wake Lock API. Declared locally (rather\n * than relying on `lib.dom`'s experimental `WakeLock` types) so the package type-\n * checks the same across TypeScript lib versions, and so a runtime where\n * `navigator.wakeLock` is absent is just a value check, never a type error.\n */\ninterface WakeLockSentinelLike extends EventTarget {\n readonly released: boolean;\n readonly type: string;\n release(): Promise<void>;\n}\ninterface WakeLockLike {\n request(type?: string): Promise<WakeLockSentinelLike>;\n}\n\n/**\n * Headless screen-wake-lock primitive — a thin, framework-agnostic wrapper around\n * the Screen Wake Lock API exposed through the wc-bindable protocol.\n *\n * Unlike the other @wcstack sensors (geolocation / intersection), the wake lock is\n * a pure *sink*: nothing is read from the device. A bound state drives the desired\n * intent (`request()` / `release()`), and the only observable outputs are `held`\n * (whether a sentinel is actually held) and `error`.\n *\n * The OS releases the lock whenever the page stops being visible (tab hidden,\n * window minimized). To honor the declarative intent (\"keep awake *while* active\"),\n * the Core keeps the desired flag (`_active`) and re-acquires the lock on the next\n * `visibilitychange` back to visible. So `_active` (desired) and `held` (actual)\n * diverge across an auto-release — and only `held` is published, because desired\n * does not change when the OS drops the lock.\n *\n * Never-throw: `request()` never rejects (a failure surfaces via `error`), and an\n * unsupported environment is a silent no-op (`held` stays false), consistent with\n * the other @wcstack sensors.\n */\nexport class WakeLockCore extends EventTarget {\n static wcBindable: IWcBindable = {\n protocol: \"wc-bindable\",\n version: 1,\n properties: [\n { name: \"held\", event: \"wcs-wakelock:held-changed\" },\n { name: \"error\", event: \"wcs-wakelock:error\" },\n ],\n commands: [\n { name: \"request\", async: true },\n { name: \"release\" },\n ],\n };\n\n private _target: EventTarget;\n private _type: WakeLockKind;\n\n // `_active` is the desired intent (input); `_held` is whether a sentinel is\n // actually held right now (output). They diverge across an OS auto-release.\n private _active: boolean = false;\n private _held: boolean = false;\n private _error: Error | null = null;\n private _sentinel: WakeLockSentinelLike | null = null;\n\n // Bumped on every release()/new acquire so an in-flight async request() that\n // resolves late can detect it was superseded and drop its sentinel (mirrors the\n // generation guards in GeolocationCore).\n private _gen: number = 0;\n // True while an `_acquire()` is awaiting `navigator.wakeLock.request()`. The\n // `_held` flag is only set *after* that await resolves, so it cannot guard\n // against concurrent entry: two rapid visibilitychange events (or a Shell toggle\n // overlapping an in-flight request) would both pass `!this._held` and each call\n // `request()`. This in-flight flag closes that window — a re-entrant acquire is a\n // no-op. The `_gen` guard still ensures the *final* state is correct; this just\n // avoids the redundant `request()` call (and its duplicate error path on a denied\n // environment).\n private _acquiring: boolean = false;\n private _visibilityBound: boolean = false;\n\n constructor(target?: EventTarget, type: WakeLockKind = \"screen\") {\n super();\n this._target = target ?? this;\n this._type = type;\n }\n\n get held(): boolean {\n return this._held;\n }\n\n get error(): Error | null {\n return this._error;\n }\n\n /** The desired intent. Read-only reflection; not a wc-bindable property (it does\n * not change on an OS auto-release, so there is nothing to observe). */\n get active(): boolean {\n return this._active;\n }\n\n get type(): WakeLockKind {\n return this._type;\n }\n\n set type(value: WakeLockKind) {\n // Currently effectively a no-op: \"screen\" is the only standardized lock type,\n // so `WakeLockKind` is a single value and this setter never observes a real\n // change. Kept as a forward-compatible seam for when the spec adds lock types.\n //\n // Takes effect on the next acquire. Changing the type mid-hold deliberately does\n // NOT re-acquire — the live sentinel is left as is, so a type change applies only\n // from the following acquire. If multiple lock types are ever added this becomes\n // an observable behavior gap (a held lock keeps its old type until release/re-\n // acquire) and must be re-examined — likely re-acquire here when held.\n this._type = value;\n }\n\n // --- State setters with event dispatch ---\n\n private _setHeld(held: boolean): void {\n if (this._held === held) return;\n this._held = held;\n this._target.dispatchEvent(new CustomEvent(\"wcs-wakelock:held-changed\", {\n detail: held,\n bubbles: true,\n }));\n }\n\n private _setError(error: Error | null): void {\n // Value guard, not just reference: a denied request rejects with a *fresh*\n // Error on every visibility-driven retry, so a reference compare would let a\n // permanently-denied environment re-dispatch the same failure on each\n // hidden→visible toggle. Compare name+message too. Transitions through null (a\n // success clears the error) always re-fire, so a genuinely new failure is seen.\n if (this._sameError(this._error, error)) return;\n this._error = error;\n this._target.dispatchEvent(new CustomEvent(\"wcs-wakelock:error\", {\n detail: error,\n bubbles: true,\n }));\n }\n\n private _sameError(a: Error | null, b: Error | null): boolean {\n if (a === b) return true;\n if (a !== null && b !== null) return a.name === b.name && a.message === b.message;\n return false;\n }\n\n // --- Public API ---\n\n /**\n * Mark the lock as desired and acquire it. Idempotent while already held. If the\n * API is unavailable or the page is currently hidden, the desired flag is still\n * set (so the lock is acquired on the next return to visibility) but nothing is\n * acquired now. Never rejects — a request failure surfaces via `error`.\n */\n async request(): Promise<void> {\n this._active = true;\n this._ensureVisibilityListener();\n await this._acquire();\n }\n\n /** Mark the lock as no longer desired and release any held sentinel. */\n release(): void {\n this._active = false;\n // Invalidate any in-flight acquire so a late-resolving request() drops its\n // sentinel instead of leaving a lock held after release.\n this._gen++;\n const sentinel = this._sentinel;\n if (sentinel) {\n this._sentinel = null;\n sentinel.removeEventListener(\"release\", this._onRelease);\n void sentinel.release().catch(() => { /* never-throw */ });\n }\n this._setHeld(false);\n }\n\n /**\n * Full teardown: remove the visibility listener and release any held sentinel.\n * Call from the Shell's `disconnectedCallback`.\n *\n * Semantics: this is a terminal teardown, not a pause. After `dispose()` the Core\n * is meant to be discarded — there is no re-arm step, and the visibility listener\n * is gone, so an OS auto-release will no longer be followed by a re-acquire. A\n * later `request()` would still work in isolation (it re-attaches the listener via\n * `_ensureVisibilityListener`), but reusing a disposed Core is not an intended path;\n * the Shell always constructs a fresh Core per element instead.\n */\n dispose(): void {\n if (this._visibilityBound) {\n document.removeEventListener(\"visibilitychange\", this._onVisibilityChange);\n this._visibilityBound = false;\n }\n this.release();\n }\n\n // --- Internal ---\n\n private async _acquire(): Promise<void> {\n if (this._held) return; // idempotent: already holding a sentinel\n if (this._acquiring) return; // an acquire is already in flight — don't double-request\n const wakeLock = this._wakeLock();\n if (!wakeLock) return; // unsupported — stay active, never acquire (silent no-op)\n if (!this._isVisible()) return; // hidden — defer to the next visibilitychange\n const gen = ++this._gen;\n this._acquiring = true;\n // Flag management is centralized in `finally` and the coalesced retry is invoked\n // exactly once, AFTER the try/catch/finally settles. This keeps the reject and\n // resolve paths symmetric: neither calls `_retryIfStillDesired()` from inside the\n // try/catch (which would let `finally` re-clear the `_acquiring=true` the retry's\n // synchronous re-entry just set, reopening the double-request window). `superseded`\n // records that a newer release()/request() bumped `_gen` mid-flight so its still-\n // live intent — blocked by the in-flight guard at the time — gets one retry here.\n // NOTE: no early `return` inside the try/catch below — every branch must fall\n // through to the post-`finally` retry. A `return` from inside the try would run\n // `finally` and then exit the function, skipping the `if (superseded)` retry.\n let superseded = false;\n let sentinel: WakeLockSentinelLike | null = null;\n let failed: Error | null = null;\n try {\n sentinel = await wakeLock.request(this._type);\n } catch (e) {\n if (gen !== this._gen) {\n // Superseded while awaiting — drop this stale failure (do not clobber the\n // newer state) and let the post-finally retry honor the live intent.\n superseded = true;\n } else {\n failed = this._normalizeError(e);\n }\n } finally {\n // The sole owner of the flag clears it here — on every exit path. A concurrent\n // re-entrant `_acquire()` was a no-op at the `_acquiring` guard, so it never owns\n // the flag; a superseding release()/acquire only bumps `_gen` and does not start\n // its own in-flight cycle until this clears the flag. Because this runs before\n // the retry below, the retry's `_acquiring=true` is never clobbered.\n this._acquiring = false;\n }\n\n if (sentinel !== null && gen !== this._gen) {\n // release() (or a newer acquire) ran while we awaited — this sentinel is\n // unwanted; drop it so no lock lingers, and retry the newer intent below.\n void sentinel.release().catch(() => { /* never-throw */ });\n superseded = true;\n } else if (sentinel !== null) {\n this._sentinel = sentinel;\n sentinel.addEventListener(\"release\", this._onRelease);\n this._setError(null);\n this._setHeld(true);\n } else if (failed !== null) {\n // A live (non-superseded) failure: surface it. Never retried — the intent is\n // honored but the environment denied it, so looping would spin.\n this._setError(failed);\n this._setHeld(false);\n }\n\n // Coalesced retry: at most one re-attempt per supersession, after the flag is\n // clear. The `_acquiring` guard inside still protects any concurrent re-entry that\n // overlaps THIS retry's own in-flight window (reject- and resolve-retry alike).\n if (superseded) this._retryIfStillDesired();\n }\n\n /**\n * Re-attempt an acquire after an in-flight one was *superseded* (its generation no\n * longer matches), but only if the lock is still desired, not already held, and the\n * page is visible. This recovers a request() that was coalesced away by the\n * in-flight `_acquiring` guard: during a release()→request() overlap, the second\n * request() bumps `_gen` and is a no-op at the guard, so without this retry its\n * still-live intent would be lost until the next visibilitychange or manual call.\n *\n * Bounded — cannot loop forever: a retry runs ONLY on supersession, and a\n * supersession requires an external release()/request() to bump `_gen` mid-flight.\n * A retry's own `_acquire()`, if it is itself not superseded, terminates by either\n * acquiring (held=true) or recording the live failure (held=false, error set) —\n * neither path retries. So a denied environment that keeps rejecting does not\n * recurse; the retry chain length is bounded by the number of external overlaps.\n */\n private _retryIfStillDesired(): void {\n if (this._active && !this._held && this._isVisible()) {\n void this._acquire();\n }\n }\n\n // Fired for an OS release of a held sentinel — which the spec allows for several\n // reasons, NOT only a visibility change: tab hidden / window minimized, but also\n // battery-low, power-saver mode, etc. while the page stays visible. We reflect\n // held=false, then (lease renewal) re-acquire immediately IF the page is still\n // visible and the lock is still desired — because a visible-context release emits no\n // `visibilitychange`, so the visibilitychange listener (②) would never fire and the\n // lock would stay stuck at desired=true / held=false. The hidden case is the no-op\n // here: re-acquire is gated on `_isVisible()`, so a hide-driven release defers to ②\n // (re-acquire on the return to visibility), avoiding a release→acquire loop while\n // hidden.\n private _onRelease = (): void => {\n // The `if (this._sentinel)` false branch is defensive and unreachable in practice:\n // this listener is only ever attached to the live `_sentinel`, and the only paths\n // that null `_sentinel` (this handler itself, and release()) remove this listener\n // in the same step — so the listener and a non-null `_sentinel` are coupled and\n // this never fires with `_sentinel === null`. Guarded anyway in case a host\n // dispatches a spurious second \"release\". (c8 ignore the unhittable else.)\n /* c8 ignore next */\n if (this._sentinel) {\n this._sentinel.removeEventListener(\"release\", this._onRelease);\n this._sentinel = null;\n }\n this._setHeld(false);\n this._reacquireAfterRelease();\n };\n\n /**\n * Lease renewal after an OS release while the page is still visible. Honors the\n * \"keep awake *while* active\" promise for releases that do NOT coincide with a\n * visibility change (battery-low / power-saver), which otherwise leave the lock\n * stuck at desired=true / held=false until the next hide→show cycle.\n *\n * Bounded on failure: this only runs from `_onRelease`, which only fires when a\n * sentinel was genuinely acquired and then released. A re-acquire that FAILS takes\n * `_acquire()`'s live-failure path (error recorded, held=false) and attaches no\n * listener, so it cannot re-enter `_onRelease` — a denied environment records the\n * error once and stops. This is the dominant real path: per the Wake Lock spec a\n * re-request under battery-low / power-saver is rejected (`NotAllowedError`), so the\n * renewal terminates there.\n *\n * The one path NOT bounded by a counter is a pathological host that keeps GRANTING\n * the re-request and then immediately auto-releasing it (grant→release reflux). Each\n * iteration yields to the event loop and consumes a real OS grant, so it is not a\n * tight/synchronous loop, but it would churn request() calls. We deliberately do NOT\n * add a debounce or renewal cap: that reflux is not documented browser behavior\n * (real browsers reject, not grant-then-revoke), and the extra timing state would\n * complicate the pure-sink design to defend a case that does not occur in practice.\n *\n * The `_isVisible()` / `!_acquiring` guards (doubled by `_acquire()`'s own in-flight\n * and held guards) prevent re-entry during an in-flight acquire and while hidden.\n */\n private _reacquireAfterRelease(): void {\n if (this._active && this._isVisible() && !this._acquiring) {\n void this._acquire();\n }\n }\n\n // ② Re-acquire when the page becomes visible again while the lock is still\n // desired but was auto-released. This is what makes `active` a durable intent.\n private _onVisibilityChange = (): void => {\n if (this._isVisible() && this._active && !this._held) {\n void this._acquire();\n }\n };\n\n private _ensureVisibilityListener(): void {\n if (this._visibilityBound) return;\n document.addEventListener(\"visibilitychange\", this._onVisibilityChange);\n this._visibilityBound = true;\n }\n\n private _wakeLock(): WakeLockLike | null {\n return (navigator as Navigator & { wakeLock?: WakeLockLike }).wakeLock ?? null;\n }\n\n private _isVisible(): boolean {\n return document.visibilityState === \"visible\";\n }\n\n private _normalizeError(e: unknown): Error {\n return e instanceof Error ? e : new Error(String(e));\n }\n}\n","import { IWcBindable, WakeLockKind } from \"../types.js\";\nimport { WakeLockCore } from \"../core/WakeLockCore.js\";\n\n/**\n * `<wcs-wakelock>` — declarative Screen Wake Lock.\n *\n * The first @wcstack tag that is a pure *sink*: every other sensor is an\n * element→state producer, but the wake lock is state→element. The headline\n * binding is `active@isPlaying` — hold the screen awake while a bound boolean is\n * true. `active` is the single input knob (a mirrored attribute); `held` and\n * `error` are the observable outputs.\n *\n * The OS auto-releases the lock when the page is hidden; the Core re-acquires it\n * on the next return to visibility while `active` is still set, so the binding\n * means \"keep awake *while* active\", not just \"acquire once\".\n */\nexport class WcsWakeLock extends HTMLElement {\n // SSR contract (@wcstack/server): the renderer awaits elements declaring\n // `hasConnectedCallbackPromise = true` before snapshotting. The wake lock has no\n // connect-time async fix to await (acquire is fire-and-forget and meaningless\n // server-side), so this is `false` — same as the other synchronous sensor Shells\n // (sse / intersection / worker). Kept (not deleted) because it is the protocol\n // contract surface the server renderer reads via `ctor.hasConnectedCallbackPromise`.\n static hasConnectedCallbackPromise = false;\n // `active` drives request/release; `type` propagates to the Core's next acquire.\n // `manual` is intentionally excluded: it is a connect-time policy (\"don't auto-\n // acquire on connect\"), not a live switch.\n static observedAttributes = [\"active\", \"type\"];\n\n static wcBindable: IWcBindable = {\n ...WakeLockCore.wcBindable,\n // Settable surface. `active` is the declarative intent; `type` selects the lock\n // kind; `manual` opts out of auto-acquire on connect. The request / release\n // commands are inherited from the Core via the spread above.\n inputs: [\n { name: \"active\", attribute: \"active\" },\n { name: \"type\", attribute: \"type\" },\n { name: \"manual\", attribute: \"manual\" },\n ],\n // Core の commands をそのまま継承(単一情報源)。<wcs-intersect>/<wcs-sse> と同型。\n // spread でも継承されるが、Core に command 追加時の追従漏れを防ぐため明示参照する。\n commands: WakeLockCore.wcBindable.commands,\n };\n\n private _core: WakeLockCore;\n\n constructor() {\n super();\n this._core = new WakeLockCore(this);\n }\n\n // --- Attribute accessors ---\n\n get active(): boolean {\n // Reflects the *attribute*, not the Core's desired intent (`_core.active`). These\n // can diverge: invoking the `request` / `release` commands directly (e.g. via a\n // command-token binding) flips the Core's desired flag without touching the\n // attribute, so `el.active` may read false while `el.held` is true (or vice\n // versa). The attribute is the declarative input surface; the commands are an\n // imperative side door. Bind via `active@...` for a single source of truth.\n return this.hasAttribute(\"active\");\n }\n\n set active(value: boolean) {\n if (value) {\n this.setAttribute(\"active\", \"\");\n } else {\n this.removeAttribute(\"active\");\n }\n }\n\n get type(): WakeLockKind {\n // Only \"screen\" is standardized; an absent/empty attribute defaults to it.\n return (this.getAttribute(\"type\") as WakeLockKind) || \"screen\";\n }\n\n set type(value: WakeLockKind) {\n this.setAttribute(\"type\", value);\n }\n\n get manual(): boolean {\n return this.hasAttribute(\"manual\");\n }\n\n set manual(value: boolean) {\n if (value) {\n this.setAttribute(\"manual\", \"\");\n } else {\n this.removeAttribute(\"manual\");\n }\n }\n\n // --- Core delegated getters ---\n\n get held(): boolean {\n return this._core.held;\n }\n\n get error(): Error | null {\n return this._core.error;\n }\n\n // --- Commands ---\n\n /** Acquire (and keep) the wake lock. Never rejects — see the `error` property. */\n request(): Promise<void> {\n return this._core.request();\n }\n\n /** Release the wake lock and stop re-acquiring it. */\n release(): void {\n this._core.release();\n }\n\n // --- Lifecycle ---\n\n connectedCallback(): void {\n // Headless resource: no layout box (mirrors the @wcstack sensor convention).\n this.style.display = \"none\";\n // Propagate the requested lock type to the Core. Currently a no-op in effect:\n // \"screen\" is the only standardized type, so `type` is always \"screen\". Wired\n // up as a forward-compatible seam (observedAttributes + setter + this line) for\n // when the spec adds lock types; until then it carries a constant.\n this._core.type = this.type;\n if (!this.manual && this.active) {\n void this._core.request();\n }\n }\n\n disconnectedCallback(): void {\n this._core.dispose();\n }\n\n attributeChangedCallback(name: string, oldValue: string | null, newValue: string | null): void {\n if (oldValue === newValue) return;\n // Ignore changes applied before connect (e.g. createElement + setAttribute);\n // connectedCallback applies the initial state. Acquiring a lock for a detached\n // element would be wrong.\n if (!this.isConnected) return;\n if (name === \"type\") {\n this._core.type = this.type;\n return;\n }\n // name === \"active\": a live toggle always drives request/release. `manual` only\n // gates the connect-time auto-acquire, not an explicit author toggle.\n if (this.active) {\n void this._core.request();\n } else {\n this._core.release();\n }\n }\n}\n","import { WcsWakeLock } from \"./components/WakeLock.js\";\nimport { config } from \"./config.js\";\n\nexport function registerComponents(): void {\n if (!customElements.get(config.tagNames.wakelock)) {\n customElements.define(config.tagNames.wakelock, WcsWakeLock);\n }\n}\n","import { setConfig } from \"./config.js\";\nimport { registerComponents } from \"./registerComponents.js\";\nimport { IWritableConfig } from \"./types.js\";\n\nexport function bootstrapWakeLock(userConfig?: IWritableConfig): void {\n if (userConfig) {\n setConfig(userConfig);\n }\n registerComponents();\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
const e={tagNames:{wakelock:"wcs-wakelock"}};function t(e){if(null===e||"object"!=typeof e)return e;Object.freeze(e);for(const i of Object.keys(e))t(e[i]);return e}function i(e){if(null===e||"object"!=typeof e)return e;const t={};for(const s of Object.keys(e))t[s]=i(e[s]);return t}let s=null;const r=e;function n(){return s||(s=t(i(e))),s}class a extends EventTarget{static wcBindable={protocol:"wc-bindable",version:1,properties:[{name:"held",event:"wcs-wakelock:held-changed"},{name:"error",event:"wcs-wakelock:error"}],commands:[{name:"request",async:!0},{name:"release"}]};_target;_type;_active=!1;_held=!1;_error=null;_sentinel=null;_gen=0;_acquiring=!1;_visibilityBound=!1;constructor(e,t="screen"){super(),this._target=e??this,this._type=t}get held(){return this._held}get error(){return this._error}get active(){return this._active}get type(){return this._type}set type(e){this._type=e}_setHeld(e){this._held!==e&&(this._held=e,this._target.dispatchEvent(new CustomEvent("wcs-wakelock:held-changed",{detail:e,bubbles:!0})))}_setError(e){this._sameError(this._error,e)||(this._error=e,this._target.dispatchEvent(new CustomEvent("wcs-wakelock:error",{detail:e,bubbles:!0})))}_sameError(e,t){return e===t||null!==e&&null!==t&&(e.name===t.name&&e.message===t.message)}async request(){this._active=!0,this._ensureVisibilityListener(),await this._acquire()}release(){this._active=!1,this._gen++;const e=this._sentinel;e&&(this._sentinel=null,e.removeEventListener("release",this._onRelease),e.release().catch(()=>{})),this._setHeld(!1)}dispose(){this._visibilityBound&&(document.removeEventListener("visibilitychange",this._onVisibilityChange),this._visibilityBound=!1),this.release()}async _acquire(){if(this._held)return;if(this._acquiring)return;const e=this._wakeLock();if(!e)return;if(!this._isVisible())return;const t=++this._gen;this._acquiring=!0;let i=!1,s=null,r=null;try{s=await e.request(this._type)}catch(e){t!==this._gen?i=!0:r=this._normalizeError(e)}finally{this._acquiring=!1}null!==s&&t!==this._gen?(s.release().catch(()=>{}),i=!0):null!==s?(this._sentinel=s,s.addEventListener("release",this._onRelease),this._setError(null),this._setHeld(!0)):null!==r&&(this._setError(r),this._setHeld(!1)),i&&this._retryIfStillDesired()}_retryIfStillDesired(){this._active&&!this._held&&this._isVisible()&&this._acquire()}_onRelease=()=>{this._sentinel&&(this._sentinel.removeEventListener("release",this._onRelease),this._sentinel=null),this._setHeld(!1),this._reacquireAfterRelease()};_reacquireAfterRelease(){this._active&&this._isVisible()&&!this._acquiring&&this._acquire()}_onVisibilityChange=()=>{this._isVisible()&&this._active&&!this._held&&this._acquire()};_ensureVisibilityListener(){this._visibilityBound||(document.addEventListener("visibilitychange",this._onVisibilityChange),this._visibilityBound=!0)}_wakeLock(){return navigator.wakeLock??null}_isVisible(){return"visible"===document.visibilityState}_normalizeError(e){return e instanceof Error?e:new Error(String(e))}}class l extends HTMLElement{static hasConnectedCallbackPromise=!1;static observedAttributes=["active","type"];static wcBindable={...a.wcBindable,inputs:[{name:"active",attribute:"active"},{name:"type",attribute:"type"},{name:"manual",attribute:"manual"}],commands:a.wcBindable.commands};_core;constructor(){super(),this._core=new a(this)}get active(){return this.hasAttribute("active")}set active(e){e?this.setAttribute("active",""):this.removeAttribute("active")}get type(){return this.getAttribute("type")||"screen"}set type(e){this.setAttribute("type",e)}get manual(){return this.hasAttribute("manual")}set manual(e){e?this.setAttribute("manual",""):this.removeAttribute("manual")}get held(){return this._core.held}get error(){return this._core.error}request(){return this._core.request()}release(){this._core.release()}connectedCallback(){this.style.display="none",this._core.type=this.type,!this.manual&&this.active&&this._core.request()}disconnectedCallback(){this._core.dispose()}attributeChangedCallback(e,t,i){t!==i&&this.isConnected&&("type"!==e?this.active?this._core.request():this._core.release():this._core.type=this.type)}}function c(t){var i;t&&((i=t).tagNames&&Object.assign(e.tagNames,i.tagNames),s=null),customElements.get(r.tagNames.wakelock)||customElements.define(r.tagNames.wakelock,l)}export{a as WakeLockCore,l as WcsWakeLock,c as bootstrapWakeLock,n as getConfig};
|
|
2
|
+
//# sourceMappingURL=index.esm.min.js.map
|