@whitesev/domutils 1.5.9 → 1.5.11

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.
@@ -103,155 +103,168 @@ System.register('DOMUtils', [], (function (exports) {
103
103
  const cache = createCache(LAST_NUMBER_WEAK_MAP);
104
104
  const generateUniqueNumber = createGenerateUniqueNumber(cache, LAST_NUMBER_WEAK_MAP);
105
105
 
106
- const isCallNotification = (message) => {
107
- return message.method !== undefined && message.method === 'call';
106
+ const isMessagePort = (sender) => {
107
+ return typeof sender.start === 'function';
108
108
  };
109
109
 
110
- const isClearResponse = (message) => {
111
- return typeof message.id === 'number' && typeof message.result === 'boolean';
112
- };
110
+ const PORT_MAP = new WeakMap();
113
111
 
114
- const load = (url) => {
115
- // Prefilling the Maps with a function indexed by zero is necessary to be compliant with the specification.
116
- const scheduledIntervalFunctions = new Map([[0, () => { }]]); // tslint:disable-line no-empty
117
- const scheduledTimeoutFunctions = new Map([[0, () => { }]]); // tslint:disable-line no-empty
118
- const unrespondedRequests = new Map();
119
- const worker = new Worker(url);
120
- worker.addEventListener('message', ({ data }) => {
121
- if (isCallNotification(data)) {
122
- const { params: { timerId, timerType } } = data;
123
- if (timerType === 'interval') {
124
- const idOrFunc = scheduledIntervalFunctions.get(timerId);
125
- if (typeof idOrFunc === undefined) {
126
- throw new Error('The timer is in an undefined state.');
127
- }
128
- if (typeof idOrFunc === 'number') {
129
- const timerIdAndTimerType = unrespondedRequests.get(idOrFunc);
130
- if (timerIdAndTimerType === undefined ||
131
- timerIdAndTimerType.timerId !== timerId ||
132
- timerIdAndTimerType.timerType !== timerType) {
133
- throw new Error('The timer is in an undefined state.');
134
- }
135
- }
136
- else if (typeof idOrFunc === 'function') {
137
- idOrFunc();
138
- }
112
+ const extendBrokerImplementation = (partialBrokerImplementation) => ({
113
+ ...partialBrokerImplementation,
114
+ connect: ({ call }) => {
115
+ return async () => {
116
+ const { port1, port2 } = new MessageChannel();
117
+ const portId = await call('connect', { port: port1 }, [port1]);
118
+ PORT_MAP.set(port2, portId);
119
+ return port2;
120
+ };
121
+ },
122
+ disconnect: ({ call }) => {
123
+ return async (port) => {
124
+ const portId = PORT_MAP.get(port);
125
+ if (portId === undefined) {
126
+ throw new Error('The given port is not connected.');
139
127
  }
140
- else if (timerType === 'timeout') {
141
- const idOrFunc = scheduledTimeoutFunctions.get(timerId);
142
- if (typeof idOrFunc === undefined) {
143
- throw new Error('The timer is in an undefined state.');
144
- }
145
- if (typeof idOrFunc === 'number') {
146
- const timerIdAndTimerType = unrespondedRequests.get(idOrFunc);
147
- if (timerIdAndTimerType === undefined ||
148
- timerIdAndTimerType.timerId !== timerId ||
149
- timerIdAndTimerType.timerType !== timerType) {
150
- throw new Error('The timer is in an undefined state.');
151
- }
128
+ await call('disconnect', { portId });
129
+ };
130
+ },
131
+ isSupported: ({ call }) => {
132
+ return () => call('isSupported');
133
+ }
134
+ });
135
+
136
+ const ONGOING_REQUESTS = new WeakMap();
137
+ const createOrGetOngoingRequests = (sender) => {
138
+ if (ONGOING_REQUESTS.has(sender)) {
139
+ // @todo TypeScript needs to be convinced that has() works as expected.
140
+ return ONGOING_REQUESTS.get(sender);
141
+ }
142
+ const ongoingRequests = new Map();
143
+ ONGOING_REQUESTS.set(sender, ongoingRequests);
144
+ return ongoingRequests;
145
+ };
146
+ const createBroker = (brokerImplementation) => {
147
+ const fullBrokerImplementation = extendBrokerImplementation(brokerImplementation);
148
+ return (sender) => {
149
+ const ongoingRequests = createOrGetOngoingRequests(sender);
150
+ sender.addEventListener('message', (({ data: message }) => {
151
+ const { id } = message;
152
+ if (id !== null && ongoingRequests.has(id)) {
153
+ const { reject, resolve } = ongoingRequests.get(id);
154
+ ongoingRequests.delete(id);
155
+ if (message.error === undefined) {
156
+ resolve(message.result);
152
157
  }
153
- else if (typeof idOrFunc === 'function') {
154
- idOrFunc();
155
- // A timeout can be savely deleted because it is only called once.
156
- scheduledTimeoutFunctions.delete(timerId);
158
+ else {
159
+ reject(new Error(message.error.message));
157
160
  }
158
161
  }
162
+ }));
163
+ if (isMessagePort(sender)) {
164
+ sender.start();
159
165
  }
160
- else if (isClearResponse(data)) {
161
- const { id } = data;
162
- const timerIdAndTimerType = unrespondedRequests.get(id);
163
- if (timerIdAndTimerType === undefined) {
164
- throw new Error('The timer is in an undefined state.');
165
- }
166
- const { timerId, timerType } = timerIdAndTimerType;
167
- unrespondedRequests.delete(id);
168
- if (timerType === 'interval') {
169
- scheduledIntervalFunctions.delete(timerId);
170
- }
171
- else {
172
- scheduledTimeoutFunctions.delete(timerId);
173
- }
174
- }
175
- else {
176
- const { error: { message } } = data;
177
- throw new Error(message);
178
- }
179
- });
180
- const clearInterval = (timerId) => {
181
- if (typeof scheduledIntervalFunctions.get(timerId) === 'function') {
182
- const id = generateUniqueNumber(unrespondedRequests);
183
- unrespondedRequests.set(id, { timerId, timerType: 'interval' });
184
- scheduledIntervalFunctions.set(timerId, id);
185
- worker.postMessage({
186
- id,
187
- method: 'clear',
188
- params: { timerId, timerType: 'interval' }
189
- });
190
- }
191
- };
192
- const clearTimeout = (timerId) => {
193
- if (typeof scheduledTimeoutFunctions.get(timerId) === 'function') {
194
- const id = generateUniqueNumber(unrespondedRequests);
195
- unrespondedRequests.set(id, { timerId, timerType: 'timeout' });
196
- scheduledTimeoutFunctions.set(timerId, id);
197
- worker.postMessage({
198
- id,
199
- method: 'clear',
200
- params: { timerId, timerType: 'timeout' }
166
+ const call = (method, params = null, transferables = []) => {
167
+ return new Promise((resolve, reject) => {
168
+ const id = generateUniqueNumber(ongoingRequests);
169
+ ongoingRequests.set(id, { reject, resolve });
170
+ if (params === null) {
171
+ sender.postMessage({ id, method }, transferables);
172
+ }
173
+ else {
174
+ sender.postMessage({ id, method, params }, transferables);
175
+ }
201
176
  });
177
+ };
178
+ const notify = (method, params, transferables = []) => {
179
+ sender.postMessage({ id: null, method, params }, transferables);
180
+ };
181
+ let functions = {};
182
+ for (const [key, handler] of Object.entries(fullBrokerImplementation)) {
183
+ functions = { ...functions, [key]: handler({ call, notify }) };
202
184
  }
185
+ return { ...functions };
203
186
  };
204
- const setInterval = (func, delay = 0, ...args) => {
205
- const timerId = generateUniqueNumber(scheduledIntervalFunctions);
206
- scheduledIntervalFunctions.set(timerId, () => {
207
- func(...args);
208
- // Doublecheck if the interval should still be rescheduled because it could have been cleared inside of func().
209
- if (typeof scheduledIntervalFunctions.get(timerId) === 'function') {
210
- worker.postMessage({
211
- id: null,
212
- method: 'set',
213
- params: {
214
- delay,
215
- now: performance.timeOrigin + performance.now(),
216
- timerId,
217
- timerType: 'interval'
218
- }
187
+ };
188
+
189
+ // Prefilling the Maps with a function indexed by zero is necessary to be compliant with the specification.
190
+ const scheduledIntervalsState = new Map([[0, null]]); // tslint:disable-line no-empty
191
+ const scheduledTimeoutsState = new Map([[0, null]]); // tslint:disable-line no-empty
192
+ const wrap = createBroker({
193
+ clearInterval: ({ call }) => {
194
+ return (timerId) => {
195
+ if (typeof scheduledIntervalsState.get(timerId) === 'symbol') {
196
+ scheduledIntervalsState.set(timerId, null);
197
+ call('clear', { timerId, timerType: 'interval' }).then(() => {
198
+ scheduledIntervalsState.delete(timerId);
219
199
  });
220
200
  }
221
- });
222
- worker.postMessage({
223
- id: null,
224
- method: 'set',
225
- params: {
201
+ };
202
+ },
203
+ clearTimeout: ({ call }) => {
204
+ return (timerId) => {
205
+ if (typeof scheduledTimeoutsState.get(timerId) === 'symbol') {
206
+ scheduledTimeoutsState.set(timerId, null);
207
+ call('clear', { timerId, timerType: 'timeout' }).then(() => {
208
+ scheduledTimeoutsState.delete(timerId);
209
+ });
210
+ }
211
+ };
212
+ },
213
+ setInterval: ({ call }) => {
214
+ return (func, delay = 0, ...args) => {
215
+ const symbol = Symbol();
216
+ const timerId = generateUniqueNumber(scheduledIntervalsState);
217
+ scheduledIntervalsState.set(timerId, symbol);
218
+ const schedule = () => call('set', {
226
219
  delay,
227
220
  now: performance.timeOrigin + performance.now(),
228
221
  timerId,
229
222
  timerType: 'interval'
230
- }
231
- });
232
- return timerId;
233
- };
234
- const setTimeout = (func, delay = 0, ...args) => {
235
- const timerId = generateUniqueNumber(scheduledTimeoutFunctions);
236
- scheduledTimeoutFunctions.set(timerId, () => func(...args));
237
- worker.postMessage({
238
- id: null,
239
- method: 'set',
240
- params: {
223
+ }).then(() => {
224
+ const state = scheduledIntervalsState.get(timerId);
225
+ if (state === undefined) {
226
+ throw new Error('The timer is in an undefined state.');
227
+ }
228
+ if (state === symbol) {
229
+ func(...args);
230
+ // Doublecheck if the interval should still be rescheduled because it could have been cleared inside of func().
231
+ if (scheduledIntervalsState.get(timerId) === symbol) {
232
+ schedule();
233
+ }
234
+ }
235
+ });
236
+ schedule();
237
+ return timerId;
238
+ };
239
+ },
240
+ setTimeout: ({ call }) => {
241
+ return (func, delay = 0, ...args) => {
242
+ const symbol = Symbol();
243
+ const timerId = generateUniqueNumber(scheduledTimeoutsState);
244
+ scheduledTimeoutsState.set(timerId, symbol);
245
+ call('set', {
241
246
  delay,
242
247
  now: performance.timeOrigin + performance.now(),
243
248
  timerId,
244
249
  timerType: 'timeout'
245
- }
246
- });
247
- return timerId;
248
- };
249
- return {
250
- clearInterval,
251
- clearTimeout,
252
- setInterval,
253
- setTimeout
254
- };
250
+ }).then(() => {
251
+ const state = scheduledTimeoutsState.get(timerId);
252
+ if (state === undefined) {
253
+ throw new Error('The timer is in an undefined state.');
254
+ }
255
+ if (state === symbol) {
256
+ // A timeout can be savely deleted because it is only called once.
257
+ scheduledTimeoutsState.delete(timerId);
258
+ func(...args);
259
+ }
260
+ });
261
+ return timerId;
262
+ };
263
+ }
264
+ });
265
+ const load = (url) => {
266
+ const worker = new Worker(url);
267
+ return wrap(worker);
255
268
  };
256
269
 
257
270
  const createLoadOrReturnBroker = (loadBroker, worker) => {
@@ -270,7 +283,7 @@ System.register('DOMUtils', [], (function (exports) {
270
283
  };
271
284
 
272
285
  // This is the minified and stringified code of the worker-timers-worker package.
273
- const worker = `(()=>{"use strict";const e=new Map,t=new Map,r=t=>{const r=e.get(t);return void 0!==r&&(clearTimeout(r),e.delete(t),!0)},s=e=>{const r=t.get(e);return void 0!==r&&(clearTimeout(r),t.delete(e),!0)},o=(e,t)=>{const r=performance.now(),s=e+t-r-performance.timeOrigin;return{expected:r+s,remainingDelay:s}},i=(e,t,r,s)=>{const o=r-performance.now();o>0?e.set(t,setTimeout(i,o,e,t,r,s)):(e.delete(t),postMessage({id:null,method:"call",params:{timerId:t,timerType:s}}))};addEventListener("message",(({data:n})=>{try{if("clear"===n.method){const{id:e,params:{timerId:t,timerType:o}}=n;if("interval"===o)postMessage({id:e,result:r(t)});else{if("timeout"!==o)throw new Error('The given type "'.concat(o,'" is not supported'));postMessage({id:e,result:s(t)})}}else{if("set"!==n.method)throw new Error('The given method "'.concat(n.method,'" is not supported'));{const{params:{delay:r,now:s,timerId:a,timerType:m}}=n;if("interval"===m)((t,r,s)=>{const{expected:n,remainingDelay:a}=o(t,s);e.set(r,setTimeout(i,a,e,r,n,"interval"))})(r,a,s);else{if("timeout"!==m)throw new Error('The given type "'.concat(m,'" is not supported'));((e,r,s)=>{const{expected:n,remainingDelay:a}=o(e,s);t.set(r,setTimeout(i,a,t,r,n,"timeout"))})(r,a,s)}}}}catch(e){postMessage({error:{message:e.message},id:n.id,result:null})}}))})();`; // tslint:disable-line:max-line-length
286
+ const worker = `(()=>{var e={455:function(e,t){!function(e){"use strict";var t=function(e){return function(t){var r=e(t);return t.add(r),r}},r=function(e){return function(t,r){return e.set(t,r),r}},n=void 0===Number.MAX_SAFE_INTEGER?9007199254740991:Number.MAX_SAFE_INTEGER,o=536870912,s=2*o,a=function(e,t){return function(r){var a=t.get(r),i=void 0===a?r.size:a<s?a+1:0;if(!r.has(i))return e(r,i);if(r.size<o){for(;r.has(i);)i=Math.floor(Math.random()*s);return e(r,i)}if(r.size>n)throw new Error("Congratulations, you created a collection of unique numbers which uses all available integers!");for(;r.has(i);)i=Math.floor(Math.random()*n);return e(r,i)}},i=new WeakMap,u=r(i),c=a(u,i),d=t(c);e.addUniqueNumber=d,e.generateUniqueNumber=c}(t)}},t={};function r(n){var o=t[n];if(void 0!==o)return o.exports;var s=t[n]={exports:{}};return e[n].call(s.exports,s,s.exports,r),s.exports}(()=>{"use strict";const e=-32603,t=-32602,n=-32601,o=(e,t)=>Object.assign(new Error(e),{status:t}),s=t=>o('The handler of the method called "'.concat(t,'" returned an unexpected result.'),e),a=(t,r)=>async({data:{id:a,method:i,params:u}})=>{const c=r[i];try{if(void 0===c)throw(e=>o('The requested method called "'.concat(e,'" is not supported.'),n))(i);const r=void 0===u?c():c(u);if(void 0===r)throw(t=>o('The handler of the method called "'.concat(t,'" returned no required result.'),e))(i);const d=r instanceof Promise?await r:r;if(null===a){if(void 0!==d.result)throw s(i)}else{if(void 0===d.result)throw s(i);const{result:e,transferables:r=[]}=d;t.postMessage({id:a,result:e},r)}}catch(e){const{message:r,status:n=-32603}=e;t.postMessage({error:{code:n,message:r},id:a})}};var i=r(455);const u=new Map,c=(e,r,n)=>({...r,connect:({port:t})=>{t.start();const n=e(t,r),o=(0,i.generateUniqueNumber)(u);return u.set(o,(()=>{n(),t.close(),u.delete(o)})),{result:o}},disconnect:({portId:e})=>{const r=u.get(e);if(void 0===r)throw(e=>o('The specified parameter called "portId" with the given value "'.concat(e,'" does not identify a port connected to this worker.'),t))(e);return r(),{result:null}},isSupported:async()=>{if(await new Promise((e=>{const t=new ArrayBuffer(0),{port1:r,port2:n}=new MessageChannel;r.onmessage=({data:t})=>e(null!==t),n.postMessage(t,[t])}))){const e=n();return{result:e instanceof Promise?await e:e}}return{result:!1}}}),d=(e,t,r=()=>!0)=>{const n=c(d,t,r),o=a(e,n);return e.addEventListener("message",o),()=>e.removeEventListener("message",o)},l=e=>t=>{const r=e.get(t);if(void 0===r)return Promise.resolve(!1);const[n,o]=r;return clearTimeout(n),e.delete(t),o(!1),Promise.resolve(!0)},f=(e,t,r)=>(n,o,s)=>{const{expected:a,remainingDelay:i}=e(n,o);return new Promise((e=>{t.set(s,[setTimeout(r,i,a,t,e,s),e])}))},m=(e,t)=>{const r=performance.now(),n=e+t-r-performance.timeOrigin;return{expected:r+n,remainingDelay:n}},p=(e,t,r,n)=>{const o=e-performance.now();o>0?t.set(n,[setTimeout(p,o,e,t,r,n),r]):(t.delete(n),r(!0))},h=new Map,v=l(h),w=new Map,g=l(w),M=f(m,h,p),y=f(m,w,p);d(self,{clear:async({timerId:e,timerType:t})=>({result:await("interval"===t?v(e):g(e))}),set:async({delay:e,now:t,timerId:r,timerType:n})=>({result:await("interval"===n?M:y)(e,t,r)})})})()})();`; // tslint:disable-line:max-line-length
274
287
 
275
288
  const loadOrReturnBroker = createLoadOrReturnBroker(load, worker);
276
289
  const clearInterval = (timerId) => loadOrReturnBroker().clearInterval(timerId);
@@ -1297,16 +1310,17 @@ System.register('DOMUtils', [], (function (exports) {
1297
1310
  },
1298
1311
  };
1299
1312
  }
1300
- selector(selector) {
1301
- return this.selectorAll(selector)[0];
1313
+ selector(selector, parent) {
1314
+ return this.selectorAll(selector, parent)[0];
1302
1315
  }
1303
- selectorAll(selector) {
1316
+ selectorAll(selector, parent) {
1304
1317
  const context = this;
1318
+ parent = parent || context.windowApi.document;
1305
1319
  selector = selector.trim();
1306
1320
  if (selector.match(/[^\s]{1}:empty$/gi)) {
1307
1321
  // empty 语法
1308
1322
  selector = selector.replace(/:empty$/gi, "");
1309
- return Array.from(context.windowApi.document.querySelectorAll(selector)).filter(($ele) => {
1323
+ return Array.from(parent.querySelectorAll(selector)).filter(($ele) => {
1310
1324
  return $ele?.innerHTML?.trim() === "";
1311
1325
  });
1312
1326
  }
@@ -1316,7 +1330,7 @@ System.register('DOMUtils', [], (function (exports) {
1316
1330
  let textMatch = selector.match(/:contains\(("|')(.*)("|')\)$/i);
1317
1331
  let text = textMatch[2];
1318
1332
  selector = selector.replace(/:contains\(("|')(.*)("|')\)$/gi, "");
1319
- return Array.from(context.windowApi.document.querySelectorAll(selector)).filter(($ele) => {
1333
+ return Array.from(parent.querySelectorAll(selector)).filter(($ele) => {
1320
1334
  // @ts-ignore
1321
1335
  return ($ele?.textContent || $ele?.innerText)?.includes(text);
1322
1336
  });
@@ -1334,14 +1348,14 @@ System.register('DOMUtils', [], (function (exports) {
1334
1348
  }
1335
1349
  let regexp = new RegExp(pattern, flags);
1336
1350
  selector = selector.replace(/:regexp\(("|')(.*)("|')\)$/gi, "");
1337
- return Array.from(context.windowApi.document.querySelectorAll(selector)).filter(($ele) => {
1351
+ return Array.from(parent.querySelectorAll(selector)).filter(($ele) => {
1338
1352
  // @ts-ignore
1339
1353
  return Boolean(($ele?.textContent || $ele?.innerText)?.match(regexp));
1340
1354
  });
1341
1355
  }
1342
1356
  else {
1343
1357
  // 普通语法
1344
- return Array.from(context.windowApi.document.querySelectorAll(selector));
1358
+ return Array.from(parent.querySelectorAll(selector));
1345
1359
  }
1346
1360
  }
1347
1361
  /**
@@ -1476,7 +1490,7 @@ System.register('DOMUtils', [], (function (exports) {
1476
1490
  super(option);
1477
1491
  }
1478
1492
  /** 版本号 */
1479
- version = "2025.6.6";
1493
+ version = "2025.6.26";
1480
1494
  attr(element, attrName, attrValue) {
1481
1495
  let DOMUtilsContext = this;
1482
1496
  if (typeof element === "string") {
@@ -2441,10 +2455,10 @@ System.register('DOMUtils', [], (function (exports) {
2441
2455
  if (typeof duration !== "number" || duration <= 0) {
2442
2456
  throw new TypeError("duration must be a positive number");
2443
2457
  }
2444
- if (typeof callback !== "function" && callback !== undefined) {
2458
+ if (typeof callback !== "function" && callback !== void 0) {
2445
2459
  throw new TypeError("callback must be a function or null");
2446
2460
  }
2447
- if (typeof styles !== "object" || styles === undefined) {
2461
+ if (typeof styles !== "object" || styles === void 0) {
2448
2462
  throw new TypeError("styles must be an object");
2449
2463
  }
2450
2464
  if (Object.keys(styles).length === 0) {