@webqit/fetch-plus 0.1.12 → 0.1.14

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/package.json CHANGED
@@ -11,7 +11,7 @@
11
11
  ],
12
12
  "homepage": "https://fetch-plus.netlify.app/",
13
13
  "icon": "https://webqit.io/icon.svg",
14
- "version": "0.1.12",
14
+ "version": "0.1.14",
15
15
  "license": "MIT",
16
16
  "repository": {
17
17
  "type": "git",
@@ -6,16 +6,26 @@ import { ResponsePlus } from './ResponsePlus.js';
6
6
 
7
7
  export class LiveResponse extends EventTarget {
8
8
 
9
+ get [Symbol.toStringTag]() {
10
+ return 'LiveResponse';
11
+ }
12
+
13
+ static [Symbol.hasInstance](instance) {
14
+ return instance instanceof EventTarget
15
+ && instance?.[Symbol.toStringTag] === 'LiveResponse'
16
+ && typeof instance.replaceWith === 'function'
17
+ && typeof instance.now === 'function';
18
+ }
19
+
9
20
  static get xHeaderName() {
10
21
  return 'X-Message-Port';
11
22
  }
12
23
 
13
24
  static test(unknown) {
14
- if (unknown instanceof LiveResponse
15
- || unknown?.[Symbol.toStringTag] === 'LiveResponse') {
25
+ if (unknown instanceof LiveResponse) {
16
26
  return 'LiveResponse';
17
27
  }
18
- if (unknown?.[Symbol.toStringTag] === 'LiveProgramHandle') {
28
+ if (unknown instanceof LiveProgramHandleX) {
19
29
  return 'LiveProgramHandle';
20
30
  }
21
31
  if (unknown instanceof Response) {
@@ -34,7 +44,8 @@ export class LiveResponse extends EventTarget {
34
44
  }
35
45
 
36
46
  static getPort(respone, { handshake = 1 } = {}) {
37
- if (!/Response/.test(this.test(respone))) {
47
+ if (!(respone instanceof Response
48
+ || respone instanceof LiveResponse)) {
38
49
  return;
39
50
  }
40
51
 
@@ -63,12 +74,16 @@ export class LiveResponse extends EventTarget {
63
74
  if (port && !(port instanceof MessagePortPlus)) {
64
75
  throw new Error('Client must be a MessagePortPlus interface');
65
76
  }
77
+ if (respone instanceof LiveResponse) {
78
+ respone.#port = port;
79
+ return;
80
+ }
66
81
  const responseMeta = _meta(respone);
67
82
  responseMeta.set('port', port);
68
83
  }
69
84
 
70
85
  static from(data, ...args) {
71
- if (this.test(data) === 'LiveResponse') {
86
+ if (data instanceof LiveResponse) {
72
87
  return data.clone(...args);
73
88
  }
74
89
  return new this(data, ...args);
@@ -76,17 +91,32 @@ export class LiveResponse extends EventTarget {
76
91
 
77
92
  /* INSTANCE */
78
93
 
79
- [Symbol.toStringTag] = 'LiveResponse';
80
-
81
94
  #listenersRegistry;
95
+ #readyStates;
96
+
97
+ #abortController = new AbortController;
98
+ #concurrencyAbortController = new AbortController;
82
99
 
83
100
  constructor(body, ...args) {
84
101
  super();
85
102
  this.#listenersRegistry = ListenerRegistry.getInstance(this, true);
86
103
 
87
- const readyStateInternals = getReadyStateInternals.call(this);
88
- const frame = readyStateInternals.now;
104
+ const $ref = (o) => {
105
+ o.promise = new Promise((res, rej) => (o.resolve = res, o.reject = rej));
106
+ return o;
107
+ };
108
+ this.#readyStates = {
109
+ live: $ref({}),
110
+ done: $ref({}),
111
+ };
112
+ const readyStates = this.#readyStates;
113
+ (function refresh() {
114
+ readyStates.now = $ref({});
115
+ readyStates.now.refresh = refresh;
116
+ return readyStates.now;
117
+ })();
89
118
 
119
+ const frame = this.#readyStates.now;
90
120
  this.#replaceWith(frame, body, ...args).catch((e) => {
91
121
  frame.reject(e);
92
122
  });
@@ -124,11 +154,6 @@ export class LiveResponse extends EventTarget {
124
154
 
125
155
  get ok() { return !!(this.#status >= 200 && this.#status < 299); }
126
156
 
127
- async now() {
128
- const readyStateInternals = getReadyStateInternals.call(this);
129
- return readyStateInternals.now.promise;
130
- }
131
-
132
157
  /* Level 3 props */
133
158
 
134
159
  #port;
@@ -136,21 +161,16 @@ export class LiveResponse extends EventTarget {
136
161
 
137
162
  // Lifecycle
138
163
 
139
- #abortController = new AbortController;
140
- #concurrencyAbortController = new AbortController;
141
-
142
164
  get readyState() {
143
- const readyStateInternals = getReadyStateInternals.call(this);
144
- return readyStateInternals.done.state ? 'done'
145
- : (readyStateInternals.live.state ? 'live' : 'waiting');
165
+ return this.#readyStates.done.state ? 'done'
166
+ : (this.#readyStates.live.state ? 'live' : 'waiting');
146
167
  }
147
168
 
148
169
  readyStateChange(query) {
149
170
  if (!['live', 'now', 'done'].includes(query)) {
150
171
  throw new Error(`Invalid readyState query "${query}"`);
151
172
  }
152
- const readyStateInternals = getReadyStateInternals.call(this);
153
- return readyStateInternals[query].promise;
173
+ return this.#readyStates[query].promise;
154
174
  }
155
175
 
156
176
  disconnect(dispose = false) {
@@ -164,27 +184,28 @@ export class LiveResponse extends EventTarget {
164
184
 
165
185
  #currentFramePromise;
166
186
  #extendLifecycle(promise) {
167
- const readyStateInternals = getReadyStateInternals.call(this);
168
- if (readyStateInternals.done.state) {
187
+ if (this.#readyStates.done.state) {
169
188
  throw new Error('Response already done.');
170
189
  }
171
190
  this.#currentFramePromise = promise;
172
191
  promise.then((value) => {
173
192
  if (this.#currentFramePromise === promise) {
174
193
  this.#currentFramePromise = null;
175
- readyStateInternals.done.state = true;
176
- readyStateInternals.done.resolve(value);
194
+ this.#readyStates.done.state = true;
195
+ this.#readyStates.done.resolve(value);
177
196
  }
178
197
  }).catch((e) => {
179
198
  if (this.#currentFramePromise === promise) {
180
199
  this.#currentFramePromise = null;
181
- readyStateInternals.done.state = true;
182
- readyStateInternals.done.reject(e);
200
+ this.#readyStates.done.state = true;
201
+ this.#readyStates.done.reject(e);
183
202
  }
184
203
  });
185
204
  return promise;
186
205
  }
187
206
 
207
+ async now() { return this.#readyStates.now.promise; }
208
+
188
209
  async replaceWith(body, ...args) {
189
210
  if (this.readyState === 'done') {
190
211
  throw new Error('Response already done.');
@@ -194,8 +215,7 @@ export class LiveResponse extends EventTarget {
194
215
  }
195
216
 
196
217
  async #replaceWith(__frame, body, ...args) {
197
- const readyStateInternals = getReadyStateInternals.call(this);
198
- const frame = __frame || readyStateInternals.now.refresh();
218
+ const frame = __frame || this.#readyStates.now.refresh();
199
219
 
200
220
  // ----------- Promise input
201
221
 
@@ -227,7 +247,7 @@ export class LiveResponse extends EventTarget {
227
247
  return;
228
248
  }
229
249
 
230
- const frame = __frame || readyStateInternals.now.refresh();
250
+ const frame = __frame || this.#readyStates.now.refresh();
231
251
 
232
252
  const $body = responseFrame.body;
233
253
 
@@ -269,8 +289,8 @@ export class LiveResponse extends EventTarget {
269
289
 
270
290
  // Must come first so that observers below here see this state
271
291
 
272
- readyStateInternals.live.state = true;
273
- readyStateInternals.live.resolve(this);
292
+ this.#readyStates.live.state = true;
293
+ this.#readyStates.live.resolve(this);
274
294
 
275
295
  // May trigger "done" ready state
276
296
  frame.resolve(responseFrame);
@@ -322,7 +342,7 @@ export class LiveResponse extends EventTarget {
322
342
  url: response.url,
323
343
  });
324
344
 
325
- if (this.constructor.test(response) === 'LiveResponse') {
345
+ if (response instanceof LiveResponse) {
326
346
  const replaceHandler = () => {
327
347
  wrapReplaceWith(null, response.body, response);
328
348
  };
@@ -425,17 +445,18 @@ export class LiveResponse extends EventTarget {
425
445
 
426
446
  // ----------- Dispatch time
427
447
 
428
- if (/Response/.test(this.constructor.test(body))) {
448
+ if (body instanceof Response
449
+ || body instanceof LiveResponse) {
429
450
  if (frameClosure) {
430
451
  throw new Error(`frameClosure is not supported for responses.`);
431
452
  }
432
453
  frame.donePromise = execReplaceWithResponse(frame, body, frameOptions);
433
- } else if (this.constructor.test(body) === 'Generator') {
454
+ } else if (isGenerator(body)) {
434
455
  if (frameClosure) {
435
456
  throw new Error(`frameClosure is not supported for generators.`);
436
457
  }
437
458
  frame.donePromise = execReplaceWithGenerator(frame, body, frameOptions);
438
- } else if (this.constructor.test(body) === 'LiveProgramHandle') {
459
+ } else if (body instanceof LiveProgramHandleX) {
439
460
  if (frameClosure) {
440
461
  throw new Error(`frameClosure is not supported for live program handles.`);
441
462
  }
@@ -550,29 +571,15 @@ export const isGenerator = (obj) => {
550
571
  typeof obj?.return === 'function';
551
572
  };
552
573
 
553
- export function getReadyStateInternals() {
554
- const portPlusMeta = _meta(this);
555
- if (!portPlusMeta.has('readystate_registry')) {
556
- const $ref = (o) => {
557
- o.promise = new Promise((res, rej) => (o.resolve = res, o.reject = rej));
558
- return o;
559
- };
560
- const states = {
561
- live: $ref({}),
562
- done: $ref({}),
563
- };
564
- (function refresh() {
565
- states.now = $ref({});
566
- states.now.refresh = refresh;
567
- return states.now;
568
- })();
569
- portPlusMeta.set('readystate_registry', states);
570
- }
571
- return portPlusMeta.get('readystate_registry');
572
- }
573
-
574
574
  export class ReplaceEvent extends Event {
575
575
 
576
+ [Symbol.toStringTag] = 'ReplaceEvent';
577
+
578
+ static [Symbol.hasInstance](instance) {
579
+ return instance instanceof Event
580
+ && instance[Symbol.toStringTag] === 'ReplaceEvent';
581
+ }
582
+
576
583
  #data;
577
584
  get data() { return this.#data; }
578
585
 
@@ -584,5 +591,10 @@ export class ReplaceEvent extends Event {
584
591
 
585
592
  export class LiveProgramHandleX {
586
593
  [Symbol.toStringTag] = 'LiveProgramHandle';
594
+
595
+ static [Symbol.hasInstance](instance) {
596
+ return instance?.[Symbol.toStringTag] === 'LiveProgramHandle';
597
+ }
598
+
587
599
  abort() { }
588
600
  }