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