magpie-html 0.1.1 → 0.1.3

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/dist/index.js CHANGED
@@ -1,5 +1,7 @@
1
1
  import { Readability } from '@mozilla/readability';
2
2
  import { parseHTML as parseHTML$1 } from 'linkedom';
3
+ import vm4 from 'vm';
4
+ import { setTimeout as setTimeout$1, clearTimeout as clearTimeout$1, setInterval, clearInterval, setImmediate, clearImmediate } from 'timers';
3
5
 
4
6
  // src/content/quality.ts
5
7
  function countWords(text) {
@@ -5046,6 +5048,1718 @@ function extractVerification(doc) {
5046
5048
  Object.entries(metadata).filter(([_, value]) => value !== void 0)
5047
5049
  );
5048
5050
  }
5051
+
5052
+ // src/swoop/errors.ts
5053
+ var SwoopError = class extends Error {
5054
+ name = "SwoopError";
5055
+ };
5056
+ var SwoopEnvironmentError = class extends SwoopError {
5057
+ name = "SwoopEnvironmentError";
5058
+ };
5059
+ var SwoopTimeoutError = class extends SwoopError {
5060
+ name = "SwoopTimeoutError";
5061
+ };
5062
+ var SwoopExecutionError = class extends SwoopError {
5063
+ name = "SwoopExecutionError";
5064
+ };
5065
+ var SwoopSecurityError = class extends SwoopError {
5066
+ name = "SwoopSecurityError";
5067
+ };
5068
+
5069
+ // src/swoop/console.ts
5070
+ function createConsoleCapture(now = () => Date.now()) {
5071
+ const entries = [];
5072
+ const formatError = (err) => {
5073
+ const parts = [];
5074
+ parts.push(`${err.name}: ${err.message}${err.stack ? `
5075
+ ${err.stack}` : ""}`.trim());
5076
+ try {
5077
+ const props = {};
5078
+ for (const key of Object.getOwnPropertyNames(err)) {
5079
+ if (key === "name" || key === "message" || key === "stack") continue;
5080
+ props[key] = err[key];
5081
+ }
5082
+ if (Object.keys(props).length > 0) {
5083
+ parts.push(`props: ${JSON.stringify(props)}`);
5084
+ }
5085
+ } catch {
5086
+ }
5087
+ return parts.join("\n");
5088
+ };
5089
+ const record = (level, args) => {
5090
+ const msg = args.map((a) => {
5091
+ try {
5092
+ if (a instanceof Error) return formatError(a);
5093
+ if (typeof a === "string") return a;
5094
+ return String(a);
5095
+ } catch {
5096
+ return "[unstringifiable]";
5097
+ }
5098
+ }).join(" ");
5099
+ const argStrings = args.map((a) => {
5100
+ try {
5101
+ if (a instanceof Error) return formatError(a);
5102
+ if (typeof a === "string") return a;
5103
+ return String(a);
5104
+ } catch {
5105
+ return "[unstringifiable]";
5106
+ }
5107
+ });
5108
+ entries.push({ level, message: msg, args: argStrings, time: now() });
5109
+ };
5110
+ return { entries, record };
5111
+ }
5112
+ function installAsyncEnv(init) {
5113
+ const { globalObj } = init;
5114
+ const hostSetTimeout = setTimeout$1;
5115
+ const hostClearTimeout = clearTimeout$1;
5116
+ const hostSetInterval = setInterval;
5117
+ const hostClearInterval = clearInterval;
5118
+ const hostSetImmediate = setImmediate;
5119
+ const hostClearImmediate = clearImmediate;
5120
+ const activeTimeouts = /* @__PURE__ */ new Set();
5121
+ const activeIntervals = /* @__PURE__ */ new Set();
5122
+ const activeImmediates = /* @__PURE__ */ new Set();
5123
+ let lastAsyncActivityAt = Date.now();
5124
+ const noteAsyncActivity = () => {
5125
+ lastAsyncActivityAt = Date.now();
5126
+ if (init.debugProbes) {
5127
+ try {
5128
+ globalObj.__swoopStats.lastAsyncActivityAt = lastAsyncActivityAt;
5129
+ } catch {
5130
+ }
5131
+ }
5132
+ };
5133
+ globalObj.__swoop_requestIdleCallback = (cb, _opts) => {
5134
+ return hostSetTimeout(() => {
5135
+ try {
5136
+ noteAsyncActivity();
5137
+ cb({
5138
+ didTimeout: false,
5139
+ timeRemaining: () => 0
5140
+ });
5141
+ } catch {
5142
+ }
5143
+ }, 0);
5144
+ };
5145
+ globalObj.__swoop_cancelIdleCallback = (handle) => hostClearTimeout(handle);
5146
+ globalObj.__swoop_setTimeout = (...args) => {
5147
+ const handle = hostSetTimeout(() => {
5148
+ activeTimeouts.delete(handle);
5149
+ noteAsyncActivity();
5150
+ if (init.debugProbes) {
5151
+ try {
5152
+ globalObj.__swoopStats.timers.timeoutFired++;
5153
+ } catch {
5154
+ }
5155
+ }
5156
+ args[0]?.call?.(globalObj);
5157
+ }, args[1]);
5158
+ activeTimeouts.add(handle);
5159
+ if (init.debugProbes) {
5160
+ try {
5161
+ globalObj.__swoopStats.timers.timeoutScheduled++;
5162
+ } catch {
5163
+ }
5164
+ }
5165
+ return handle;
5166
+ };
5167
+ globalObj.__swoop_clearTimeout = (handle) => {
5168
+ activeTimeouts.delete(handle);
5169
+ hostClearTimeout(handle);
5170
+ };
5171
+ globalObj.__swoop_setInterval = (...args) => {
5172
+ const handle = hostSetInterval(() => {
5173
+ noteAsyncActivity();
5174
+ if (init.debugProbes) {
5175
+ try {
5176
+ globalObj.__swoopStats.timers.intervalFired++;
5177
+ } catch {
5178
+ }
5179
+ }
5180
+ args[0]?.call?.(globalObj);
5181
+ }, args[1]);
5182
+ activeIntervals.add(handle);
5183
+ if (init.debugProbes) {
5184
+ try {
5185
+ globalObj.__swoopStats.timers.intervalScheduled++;
5186
+ } catch {
5187
+ }
5188
+ }
5189
+ return handle;
5190
+ };
5191
+ globalObj.__swoop_clearInterval = (handle) => {
5192
+ activeIntervals.delete(handle);
5193
+ hostClearInterval(handle);
5194
+ };
5195
+ globalObj.__swoop_queueMicrotask = (cb) => {
5196
+ try {
5197
+ process.nextTick(() => {
5198
+ noteAsyncActivity();
5199
+ cb.call(globalObj);
5200
+ });
5201
+ } catch {
5202
+ hostSetTimeout(() => {
5203
+ noteAsyncActivity();
5204
+ cb.call(globalObj);
5205
+ }, 0);
5206
+ }
5207
+ };
5208
+ globalObj.__swoop_setImmediate = (cb, ...args) => {
5209
+ const handle = hostSetImmediate(() => {
5210
+ activeImmediates.delete(handle);
5211
+ try {
5212
+ noteAsyncActivity();
5213
+ cb.call(globalObj, ...args);
5214
+ } catch {
5215
+ }
5216
+ });
5217
+ activeImmediates.add(handle);
5218
+ return handle;
5219
+ };
5220
+ globalObj.__swoop_clearImmediate = (handle) => {
5221
+ activeImmediates.delete(handle);
5222
+ hostClearImmediate(handle);
5223
+ };
5224
+ globalObj.__swoop_requestAnimationFrame = (cb) => {
5225
+ if (init.debugProbes) {
5226
+ try {
5227
+ globalObj.__swoopStats.timers.rafScheduled++;
5228
+ } catch {
5229
+ }
5230
+ }
5231
+ const id = hostSetTimeout(() => {
5232
+ if (init.debugProbes) {
5233
+ try {
5234
+ globalObj.__swoopStats.timers.rafFired++;
5235
+ } catch {
5236
+ }
5237
+ }
5238
+ noteAsyncActivity();
5239
+ cb.call(globalObj, Date.now());
5240
+ }, 16);
5241
+ return id;
5242
+ };
5243
+ globalObj.__swoop_cancelAnimationFrame = (id) => hostClearTimeout(id);
5244
+ const cleanup = () => {
5245
+ for (const h of activeTimeouts) hostClearTimeout(h);
5246
+ for (const h of activeIntervals) hostClearInterval(h);
5247
+ for (const h of activeImmediates) hostClearImmediate(h);
5248
+ };
5249
+ return {
5250
+ hostSetTimeout,
5251
+ hostClearTimeout,
5252
+ hostSetInterval,
5253
+ hostClearInterval,
5254
+ hostSetImmediate,
5255
+ hostClearImmediate,
5256
+ noteAsyncActivity,
5257
+ getLastAsyncActivityAt: () => lastAsyncActivityAt,
5258
+ cleanup
5259
+ };
5260
+ }
5261
+
5262
+ // src/swoop/env/base.ts
5263
+ function computeBaseForResolve(finalUrl, document) {
5264
+ const pageUrl = new URL(finalUrl);
5265
+ const baseEl = document?.querySelector?.("base") ?? null;
5266
+ const baseTagHref = baseEl?.getAttribute?.("href") ?? null;
5267
+ const baseForResolve = (() => {
5268
+ try {
5269
+ return baseTagHref ? new URL(String(baseTagHref), finalUrl) : pageUrl;
5270
+ } catch {
5271
+ return pageUrl;
5272
+ }
5273
+ })();
5274
+ return { baseForResolve, baseTagHref, baseEl };
5275
+ }
5276
+ function patchDocumentBaseURI(document, baseForResolve) {
5277
+ try {
5278
+ Object.defineProperty(document, "baseURI", {
5279
+ configurable: true,
5280
+ get: () => baseForResolve.href
5281
+ });
5282
+ } catch {
5283
+ }
5284
+ }
5285
+ function patchBaseElementHref(baseEl, baseForResolve) {
5286
+ try {
5287
+ if (baseEl) {
5288
+ Object.defineProperty(baseEl, "href", {
5289
+ configurable: true,
5290
+ get: () => baseForResolve.href,
5291
+ set: (_v) => {
5292
+ }
5293
+ });
5294
+ }
5295
+ } catch {
5296
+ }
5297
+ }
5298
+
5299
+ // src/swoop/env/browser.ts
5300
+ function installBrowserShims(init) {
5301
+ const { globalObj, domWindow, documentBaseUriForDom } = init;
5302
+ const doc = init.document ?? globalObj.document;
5303
+ try {
5304
+ if (doc && doc.defaultView == null) doc.defaultView = globalObj;
5305
+ } catch {
5306
+ }
5307
+ try {
5308
+ if (doc && doc.baseURI == null) doc.baseURI = documentBaseUriForDom;
5309
+ } catch {
5310
+ }
5311
+ globalObj.navigator ??= {};
5312
+ globalObj.navigator.language ??= "en";
5313
+ globalObj.navigator.languages ??= [globalObj.navigator.language];
5314
+ globalObj.navigator.onLine ??= true;
5315
+ globalObj.screen ??= {
5316
+ width: 1280,
5317
+ height: 720,
5318
+ availWidth: 1280,
5319
+ availHeight: 720,
5320
+ colorDepth: 24
5321
+ };
5322
+ globalObj.devicePixelRatio ??= 1;
5323
+ globalObj.innerWidth ??= globalObj.screen.width ?? 1280;
5324
+ globalObj.innerHeight ??= globalObj.screen.height ?? 720;
5325
+ globalObj.MessageChannel ??= globalThis.MessageChannel;
5326
+ globalObj.MessagePort ??= globalThis.MessagePort;
5327
+ globalObj.MessageEvent ??= globalThis.MessageEvent;
5328
+ globalObj.BroadcastChannel ??= globalThis.BroadcastChannel;
5329
+ globalObj.getComputedStyle ??= (el) => {
5330
+ const style = el?.style ?? {};
5331
+ return new Proxy(style, {
5332
+ get(target, prop) {
5333
+ if (prop === "getPropertyValue") return (name) => target?.[name] ?? "";
5334
+ return target[prop] ?? "";
5335
+ }
5336
+ });
5337
+ };
5338
+ globalObj.PopStateEvent ??= class PopStateEvent extends (globalObj.Event ?? Event) {
5339
+ state;
5340
+ constructor(type, init2) {
5341
+ super(type, init2);
5342
+ this.state = init2?.state;
5343
+ }
5344
+ };
5345
+ globalObj.HashChangeEvent ??= class HashChangeEvent extends (globalObj.Event ?? Event) {
5346
+ oldURL;
5347
+ newURL;
5348
+ constructor(type, init2) {
5349
+ super(type, init2);
5350
+ this.oldURL = init2?.oldURL ?? "";
5351
+ this.newURL = init2?.newURL ?? "";
5352
+ }
5353
+ };
5354
+ globalObj.matchMedia ??= (query) => {
5355
+ const listeners = /* @__PURE__ */ new Set();
5356
+ const mql = {
5357
+ matches: false,
5358
+ media: String(query ?? ""),
5359
+ onchange: null,
5360
+ addListener: (cb) => {
5361
+ if (typeof cb === "function") listeners.add(cb);
5362
+ },
5363
+ removeListener: (cb) => {
5364
+ listeners.delete(cb);
5365
+ },
5366
+ addEventListener: (type, cb) => {
5367
+ if (String(type) === "change" && typeof cb === "function") listeners.add(cb);
5368
+ },
5369
+ removeEventListener: (type, cb) => {
5370
+ if (String(type) === "change") listeners.delete(cb);
5371
+ },
5372
+ dispatchEvent: (evt) => {
5373
+ try {
5374
+ for (const cb of listeners) cb.call(mql, evt);
5375
+ if (typeof mql.onchange === "function") mql.onchange.call(mql, evt);
5376
+ } catch {
5377
+ }
5378
+ return true;
5379
+ }
5380
+ };
5381
+ return mql;
5382
+ };
5383
+ globalObj.IntersectionObserver ??= class IntersectionObserver {
5384
+ observe(_el) {
5385
+ }
5386
+ unobserve(_el) {
5387
+ }
5388
+ disconnect() {
5389
+ }
5390
+ takeRecords() {
5391
+ return [];
5392
+ }
5393
+ };
5394
+ globalObj.ResizeObserver ??= class ResizeObserver {
5395
+ observe(_el) {
5396
+ }
5397
+ unobserve(_el) {
5398
+ }
5399
+ disconnect() {
5400
+ }
5401
+ };
5402
+ globalObj.MutationObserver ??= class MutationObserver {
5403
+ observe(_target, _options) {
5404
+ }
5405
+ disconnect() {
5406
+ }
5407
+ takeRecords() {
5408
+ return [];
5409
+ }
5410
+ };
5411
+ globalObj.URL ??= URL;
5412
+ globalObj.URLSearchParams ??= URLSearchParams;
5413
+ globalObj.WebAssembly ??= WebAssembly;
5414
+ globalObj.TextEncoder ??= TextEncoder;
5415
+ globalObj.TextDecoder ??= TextDecoder;
5416
+ globalObj.Headers ??= globalThis.Headers;
5417
+ globalObj.Request ??= globalThis.Request;
5418
+ globalObj.Response ??= globalThis.Response;
5419
+ globalObj.crypto ??= globalThis.crypto;
5420
+ globalObj.performance ??= globalThis.performance;
5421
+ globalObj.structuredClone ??= globalThis.structuredClone;
5422
+ globalObj.Blob ??= globalThis.Blob;
5423
+ globalObj.FormData ??= globalThis.FormData;
5424
+ globalObj.File ??= globalThis.File;
5425
+ globalObj.ReadableStream ??= globalThis.ReadableStream;
5426
+ globalObj.atob ??= (data) => Buffer.from(data, "base64").toString("binary");
5427
+ globalObj.btoa ??= (data) => Buffer.from(data, "binary").toString("base64");
5428
+ globalObj.WebSocket ??= class WebSocket {
5429
+ constructor() {
5430
+ throw new Error("swoop: WebSocket is not implemented");
5431
+ }
5432
+ };
5433
+ globalObj.EventSource ??= class EventSource {
5434
+ constructor() {
5435
+ throw new Error("swoop: EventSource is not implemented");
5436
+ }
5437
+ };
5438
+ globalObj.Worker ??= class Worker {
5439
+ constructor() {
5440
+ throw new Error("swoop: Worker is not implemented");
5441
+ }
5442
+ };
5443
+ globalObj.SharedWorker ??= class SharedWorker {
5444
+ constructor() {
5445
+ throw new Error("swoop: SharedWorker is not implemented");
5446
+ }
5447
+ };
5448
+ globalObj.indexedDB ??= void 0;
5449
+ globalObj.caches ??= void 0;
5450
+ globalObj.Notification ??= void 0;
5451
+ globalObj.Document ??= domWindow.Document;
5452
+ globalObj.HTMLDocument ??= domWindow.HTMLDocument ?? init.document?.constructor;
5453
+ globalObj.Element ??= domWindow.Element;
5454
+ globalObj.HTMLElement ??= domWindow.HTMLElement;
5455
+ globalObj.Node ??= domWindow.Node;
5456
+ globalObj.NodeFilter ??= domWindow.NodeFilter ?? {
5457
+ FILTER_ACCEPT: 1,
5458
+ FILTER_REJECT: 2,
5459
+ FILTER_SKIP: 3,
5460
+ SHOW_ALL: 4294967295,
5461
+ SHOW_ELEMENT: 1,
5462
+ SHOW_ATTRIBUTE: 2,
5463
+ SHOW_TEXT: 4,
5464
+ SHOW_CDATA_SECTION: 8,
5465
+ SHOW_ENTITY_REFERENCE: 16,
5466
+ SHOW_ENTITY: 32,
5467
+ SHOW_PROCESSING_INSTRUCTION: 64,
5468
+ SHOW_COMMENT: 128,
5469
+ SHOW_DOCUMENT: 256,
5470
+ SHOW_DOCUMENT_TYPE: 512,
5471
+ SHOW_DOCUMENT_FRAGMENT: 1024,
5472
+ SHOW_NOTATION: 2048
5473
+ };
5474
+ }
5475
+
5476
+ // src/swoop/env/cookie.ts
5477
+ function installCookieJar(document) {
5478
+ let cookieJar = "";
5479
+ try {
5480
+ Object.defineProperty(document, "cookie", {
5481
+ configurable: true,
5482
+ get() {
5483
+ return cookieJar;
5484
+ },
5485
+ set(value) {
5486
+ if (typeof value === "string" && value.length > 0) {
5487
+ cookieJar = cookieJar ? `${cookieJar}; ${value}` : value;
5488
+ }
5489
+ }
5490
+ });
5491
+ } catch {
5492
+ }
5493
+ }
5494
+
5495
+ // src/swoop/env/fetch.ts
5496
+ function installFetchShim(init) {
5497
+ let pendingFetches = 0;
5498
+ init.globalObj.__swoop_fetch = typeof init.hostFetch === "function" ? (...args) => {
5499
+ init.noteAsyncActivity();
5500
+ pendingFetches++;
5501
+ try {
5502
+ const input = args[0];
5503
+ const initReq = args[1];
5504
+ let resolvedInput = input;
5505
+ if (typeof input === "string") {
5506
+ resolvedInput = new URL(input, init.baseForResolveHref).href;
5507
+ } else if (input instanceof URL) {
5508
+ resolvedInput = input.href;
5509
+ } else if (typeof input.url === "string") {
5510
+ try {
5511
+ resolvedInput = new URL(input.url, init.baseForResolveHref).href;
5512
+ } catch {
5513
+ }
5514
+ }
5515
+ if (init.debugFetch) {
5516
+ init.recordDebug(["[fetch]", resolvedInput]);
5517
+ }
5518
+ const controller = new AbortController();
5519
+ const timeoutHandle = init.hostSetTimeout(() => controller.abort(), init.remainingMs());
5520
+ const mergedInit = { ...initReq, signal: controller.signal };
5521
+ const p = init.hostFetch(resolvedInput, mergedInit).finally(() => {
5522
+ init.hostClearTimeout(timeoutHandle);
5523
+ });
5524
+ return p.finally(() => {
5525
+ try {
5526
+ init.queueMicrotask(() => {
5527
+ pendingFetches--;
5528
+ init.noteAsyncActivity();
5529
+ });
5530
+ } catch {
5531
+ pendingFetches--;
5532
+ init.noteAsyncActivity();
5533
+ }
5534
+ });
5535
+ } catch (err) {
5536
+ pendingFetches--;
5537
+ init.noteAsyncActivity();
5538
+ throw err;
5539
+ }
5540
+ } : void 0;
5541
+ return {
5542
+ getPendingFetches: () => pendingFetches
5543
+ };
5544
+ }
5545
+
5546
+ // src/swoop/env/navigation.ts
5547
+ function createNavigationShims(init) {
5548
+ const { pageUrl } = init;
5549
+ const resolveAndSetHref = (href) => {
5550
+ try {
5551
+ const next = new URL(href, pageUrl.href);
5552
+ pageUrl.href = next.href;
5553
+ init.onNavigate?.(pageUrl.href);
5554
+ } catch {
5555
+ }
5556
+ };
5557
+ const location = {};
5558
+ try {
5559
+ Object.defineProperties(location, {
5560
+ href: { get: () => pageUrl.href, set: (v) => resolveAndSetHref(String(v)) },
5561
+ origin: { get: () => pageUrl.origin },
5562
+ protocol: {
5563
+ get: () => pageUrl.protocol,
5564
+ set: (v) => {
5565
+ pageUrl.protocol = String(v);
5566
+ }
5567
+ },
5568
+ host: {
5569
+ get: () => pageUrl.host,
5570
+ set: (v) => {
5571
+ pageUrl.host = String(v);
5572
+ }
5573
+ },
5574
+ hostname: {
5575
+ get: () => pageUrl.hostname,
5576
+ set: (v) => {
5577
+ pageUrl.hostname = String(v);
5578
+ }
5579
+ },
5580
+ port: {
5581
+ get: () => pageUrl.port,
5582
+ set: (v) => {
5583
+ pageUrl.port = String(v);
5584
+ }
5585
+ },
5586
+ pathname: { get: () => pageUrl.pathname, set: (v) => resolveAndSetHref(String(v)) },
5587
+ search: {
5588
+ get: () => pageUrl.search,
5589
+ set: (v) => {
5590
+ pageUrl.search = String(v);
5591
+ }
5592
+ },
5593
+ hash: {
5594
+ get: () => pageUrl.hash,
5595
+ set: (v) => {
5596
+ pageUrl.hash = String(v);
5597
+ }
5598
+ }
5599
+ });
5600
+ } catch {
5601
+ }
5602
+ location.toString = () => pageUrl.href;
5603
+ location.assign = (href) => resolveAndSetHref(href);
5604
+ location.replace = (href) => resolveAndSetHref(href);
5605
+ location.reload = () => {
5606
+ };
5607
+ let historyState = null;
5608
+ const history = {
5609
+ get state() {
5610
+ return historyState;
5611
+ },
5612
+ pushState: (state, _title, url) => {
5613
+ historyState = state;
5614
+ if (url != null) resolveAndSetHref(String(url));
5615
+ try {
5616
+ init.onPopState?.(state);
5617
+ } catch {
5618
+ }
5619
+ },
5620
+ replaceState: (state, _title, url) => {
5621
+ historyState = state;
5622
+ if (url != null) resolveAndSetHref(String(url));
5623
+ },
5624
+ back: () => {
5625
+ },
5626
+ forward: () => {
5627
+ },
5628
+ go: (_delta) => {
5629
+ }
5630
+ };
5631
+ return { location, history };
5632
+ }
5633
+
5634
+ // src/swoop/env/permissive.ts
5635
+ function installPermissiveShims(globalObj) {
5636
+ const makeStorage = () => {
5637
+ const store = /* @__PURE__ */ new Map();
5638
+ return {
5639
+ get length() {
5640
+ return store.size;
5641
+ },
5642
+ clear() {
5643
+ store.clear();
5644
+ },
5645
+ getItem(key) {
5646
+ return store.has(String(key)) ? store.get(String(key)) : null;
5647
+ },
5648
+ key(index) {
5649
+ return Array.from(store.keys())[index] ?? null;
5650
+ },
5651
+ removeItem(key) {
5652
+ store.delete(String(key));
5653
+ },
5654
+ setItem(key, value) {
5655
+ store.set(String(key), String(value));
5656
+ }
5657
+ };
5658
+ };
5659
+ globalObj.localStorage ??= makeStorage();
5660
+ globalObj.sessionStorage ??= makeStorage();
5661
+ globalObj.scrollTo ??= () => {
5662
+ };
5663
+ try {
5664
+ if (globalObj.HTMLElement?.prototype && !globalObj.HTMLElement.prototype.getBoundingClientRect) {
5665
+ globalObj.HTMLElement.prototype.getBoundingClientRect = () => ({
5666
+ x: 0,
5667
+ y: 0,
5668
+ width: 0,
5669
+ height: 0,
5670
+ top: 0,
5671
+ left: 0,
5672
+ right: 0,
5673
+ bottom: 0,
5674
+ toJSON() {
5675
+ }
5676
+ });
5677
+ }
5678
+ } catch {
5679
+ }
5680
+ globalObj.process ??= { env: { NODE_ENV: "production" } };
5681
+ }
5682
+
5683
+ // src/swoop/env/xhr.ts
5684
+ function installXMLHttpRequest(init) {
5685
+ const g = init.globalObj;
5686
+ if (g.XMLHttpRequest) return;
5687
+ class Xhr {
5688
+ // readyState constants
5689
+ static UNSENT = 0;
5690
+ static OPENED = 1;
5691
+ static HEADERS_RECEIVED = 2;
5692
+ static LOADING = 3;
5693
+ static DONE = 4;
5694
+ UNSENT = 0;
5695
+ OPENED = 1;
5696
+ HEADERS_RECEIVED = 2;
5697
+ LOADING = 3;
5698
+ DONE = 4;
5699
+ readyState = 0;
5700
+ status = 0;
5701
+ statusText = "";
5702
+ responseType = "";
5703
+ response = null;
5704
+ responseText = "";
5705
+ timeout = 0;
5706
+ withCredentials = false;
5707
+ onreadystatechange = null;
5708
+ onload = null;
5709
+ onerror = null;
5710
+ ontimeout = null;
5711
+ onabort = null;
5712
+ _method = "GET";
5713
+ _url = "";
5714
+ _headers = /* @__PURE__ */ new Map();
5715
+ _respHeaders = null;
5716
+ _listeners = /* @__PURE__ */ new Map();
5717
+ _controller = null;
5718
+ addEventListener(type, cb) {
5719
+ const t = String(type);
5720
+ const set = this._listeners.get(t) ?? /* @__PURE__ */ new Set();
5721
+ set.add(cb);
5722
+ this._listeners.set(t, set);
5723
+ }
5724
+ removeEventListener(type, cb) {
5725
+ const t = String(type);
5726
+ this._listeners.get(t)?.delete(cb);
5727
+ }
5728
+ _dispatch(type) {
5729
+ const ev = { type, target: this, currentTarget: this };
5730
+ this._listeners.get(type)?.forEach((cb) => {
5731
+ try {
5732
+ cb(ev);
5733
+ } catch {
5734
+ }
5735
+ });
5736
+ }
5737
+ _setReadyState(n) {
5738
+ this.readyState = n;
5739
+ try {
5740
+ this.onreadystatechange?.();
5741
+ } catch {
5742
+ }
5743
+ this._dispatch("readystatechange");
5744
+ }
5745
+ open(method, url, async = true) {
5746
+ this._method = String(method ?? "GET").toUpperCase();
5747
+ this._url = String(url ?? "");
5748
+ this._headers.clear();
5749
+ this._respHeaders = null;
5750
+ this._controller = null;
5751
+ this._setReadyState(1);
5752
+ }
5753
+ setRequestHeader(name, value) {
5754
+ this._headers.set(String(name), String(value));
5755
+ }
5756
+ getResponseHeader(name) {
5757
+ try {
5758
+ return this._respHeaders?.get(String(name)) ?? null;
5759
+ } catch {
5760
+ return null;
5761
+ }
5762
+ }
5763
+ getAllResponseHeaders() {
5764
+ try {
5765
+ if (!this._respHeaders) return "";
5766
+ let out = "";
5767
+ this._respHeaders.forEach((v, k) => {
5768
+ out += `${k}: ${v}\r
5769
+ `;
5770
+ });
5771
+ return out;
5772
+ } catch {
5773
+ return "";
5774
+ }
5775
+ }
5776
+ overrideMimeType(_mime) {
5777
+ }
5778
+ abort() {
5779
+ try {
5780
+ this._controller?.abort();
5781
+ } catch {
5782
+ }
5783
+ try {
5784
+ this.onabort?.();
5785
+ } catch {
5786
+ }
5787
+ this._dispatch("abort");
5788
+ }
5789
+ send(body) {
5790
+ const doFetch = async () => {
5791
+ const url = init.resolveUrl(this._url);
5792
+ const controller = new AbortController();
5793
+ this._controller = controller;
5794
+ let timeoutHandle;
5795
+ const ms = Math.min(this.timeout || 0, init.remainingMs());
5796
+ if (ms > 0) {
5797
+ timeoutHandle = init.hostSetTimeout(() => controller.abort(), ms);
5798
+ }
5799
+ try {
5800
+ const headers = {};
5801
+ for (const [k, v] of this._headers.entries()) headers[k] = v;
5802
+ if (!init.fetch) throw new Error("swoop: host fetch is unavailable in this Node runtime");
5803
+ const resp = await init.fetch(url, {
5804
+ method: this._method,
5805
+ headers,
5806
+ body,
5807
+ signal: controller.signal
5808
+ // credentials/withCredentials ignored (Node fetch differs); best-effort.
5809
+ });
5810
+ this._respHeaders = resp.headers;
5811
+ this.status = resp.status;
5812
+ this.statusText = resp.statusText ?? "";
5813
+ this._setReadyState(2);
5814
+ this._setReadyState(3);
5815
+ if (this.responseType === "arraybuffer") {
5816
+ this.response = await resp.arrayBuffer();
5817
+ this.responseText = "";
5818
+ } else if (this.responseType === "blob") {
5819
+ this.response = resp.blob ? await resp.blob() : await resp.arrayBuffer();
5820
+ this.responseText = "";
5821
+ } else {
5822
+ const text = await resp.text();
5823
+ this.responseText = text;
5824
+ if (this.responseType === "json") {
5825
+ try {
5826
+ this.response = JSON.parse(text);
5827
+ } catch {
5828
+ this.response = null;
5829
+ }
5830
+ } else {
5831
+ this.response = text;
5832
+ }
5833
+ }
5834
+ this._setReadyState(4);
5835
+ try {
5836
+ this.onload?.();
5837
+ } catch {
5838
+ }
5839
+ this._dispatch("load");
5840
+ this._dispatch("loadend");
5841
+ } catch {
5842
+ this._setReadyState(4);
5843
+ const aborted = this._controller?.signal?.aborted;
5844
+ if (aborted) {
5845
+ try {
5846
+ this.ontimeout?.();
5847
+ } catch {
5848
+ }
5849
+ this._dispatch("timeout");
5850
+ } else {
5851
+ try {
5852
+ this.onerror?.();
5853
+ } catch {
5854
+ }
5855
+ this._dispatch("error");
5856
+ }
5857
+ this._dispatch("loadend");
5858
+ } finally {
5859
+ if (timeoutHandle) init.hostClearTimeout(timeoutHandle);
5860
+ }
5861
+ };
5862
+ void doFetch();
5863
+ }
5864
+ }
5865
+ g.XMLHttpRequest = Xhr;
5866
+ }
5867
+ function synthesizeLifecycle(context, timeoutMs = 50) {
5868
+ vm4.runInContext(
5869
+ `
5870
+ try {
5871
+ const EventCtor = (globalThis.Event || (globalThis.window && globalThis.window.Event));
5872
+ const dispatchDoc = (type) => { try { document.dispatchEvent(new EventCtor(type)); } catch {} };
5873
+ const dispatchWin = (type) => { try { window.dispatchEvent(new EventCtor(type)); } catch {} };
5874
+
5875
+ if (typeof document.readyState !== "string") {
5876
+ try { document.readyState = "loading"; } catch {}
5877
+ }
5878
+
5879
+ dispatchDoc("readystatechange");
5880
+ try { document.readyState = "interactive"; } catch {}
5881
+ dispatchDoc("readystatechange");
5882
+ dispatchDoc("DOMContentLoaded");
5883
+ try { document.readyState = "complete"; } catch {}
5884
+ dispatchDoc("readystatechange");
5885
+
5886
+ try {
5887
+ if (typeof document.visibilityState !== "string") document.visibilityState = "visible";
5888
+ if (typeof document.hidden !== "boolean") document.hidden = false;
5889
+ if (typeof document.hasFocus !== "function") document.hasFocus = () => true;
5890
+ } catch {}
5891
+ dispatchDoc("visibilitychange");
5892
+
5893
+ dispatchWin("pageshow");
5894
+ dispatchWin("load");
5895
+
5896
+ try { window.dispatchEvent(new PopStateEvent("popstate", { state: (history && history.state) })); } catch {}
5897
+ try {
5898
+ const href = String((location && location.href) || "");
5899
+ window.dispatchEvent(new HashChangeEvent("hashchange", { oldURL: href, newURL: href }));
5900
+ } catch {}
5901
+ } catch {}
5902
+ `,
5903
+ context,
5904
+ { timeout: timeoutMs }
5905
+ );
5906
+ }
5907
+
5908
+ // src/swoop/probes.ts
5909
+ function installDebugProbes(init) {
5910
+ const { globalObj, hostSetTimeout } = init;
5911
+ globalObj.__swoopStats = {
5912
+ startedAt: Date.now(),
5913
+ domOps: /* @__PURE__ */ Object.create(null),
5914
+ mutations: 0,
5915
+ lastDomActivityAt: 0,
5916
+ listeners: /* @__PURE__ */ Object.create(null),
5917
+ timers: {
5918
+ timeoutScheduled: 0,
5919
+ timeoutFired: 0,
5920
+ intervalScheduled: 0,
5921
+ intervalFired: 0,
5922
+ rafScheduled: 0,
5923
+ rafFired: 0
5924
+ },
5925
+ nav: {
5926
+ pushState: 0,
5927
+ replaceState: 0,
5928
+ lastHref: null
5929
+ },
5930
+ appRootSamples: []
5931
+ };
5932
+ const bump = (name) => {
5933
+ const s = globalObj.__swoopStats;
5934
+ s.domOps[name] = (s.domOps[name] ?? 0) + 1;
5935
+ s.lastDomActivityAt = Date.now();
5936
+ };
5937
+ const bumpListener = (type) => {
5938
+ const s = globalObj.__swoopStats;
5939
+ s.listeners[type] = (s.listeners[type] ?? 0) + 1;
5940
+ };
5941
+ const wrapProto = (proto, fn) => {
5942
+ const orig = proto?.[fn];
5943
+ if (typeof orig !== "function") return;
5944
+ proto[fn] = function(...args) {
5945
+ bump(fn);
5946
+ return orig.apply(this, args);
5947
+ };
5948
+ };
5949
+ wrapProto(globalObj.Node?.prototype, "appendChild");
5950
+ wrapProto(globalObj.Node?.prototype, "insertBefore");
5951
+ wrapProto(globalObj.Node?.prototype, "removeChild");
5952
+ wrapProto(globalObj.Element?.prototype, "setAttribute");
5953
+ wrapProto(globalObj.Element?.prototype, "removeAttribute");
5954
+ wrapProto(globalObj.Element?.prototype, "append");
5955
+ wrapProto(globalObj.Element?.prototype, "prepend");
5956
+ const wrapAddListener = (target, label) => {
5957
+ const orig = target?.addEventListener;
5958
+ if (typeof orig !== "function") return;
5959
+ target.addEventListener = function(type, listener, options) {
5960
+ try {
5961
+ bumpListener(`${label}:${String(type)}`);
5962
+ } catch {
5963
+ }
5964
+ return orig.call(this, type, listener, options);
5965
+ };
5966
+ };
5967
+ wrapAddListener(globalObj, "window");
5968
+ wrapAddListener(globalObj.document, "document");
5969
+ const MO = globalObj.MutationObserver;
5970
+ if (typeof MO === "function") {
5971
+ const mo = new MO(() => {
5972
+ globalObj.__swoopStats.mutations++;
5973
+ globalObj.__swoopStats.lastDomActivityAt = Date.now();
5974
+ });
5975
+ try {
5976
+ mo.observe(globalObj.document?.documentElement, {
5977
+ subtree: true,
5978
+ childList: true,
5979
+ attributes: true,
5980
+ characterData: true
5981
+ });
5982
+ } catch {
5983
+ }
5984
+ }
5985
+ const sample = () => {
5986
+ try {
5987
+ const el = globalObj.document?.querySelector?.("app-root");
5988
+ const len = el?.innerHTML?.length ?? 0;
5989
+ const opacity = el?.getAttribute?.("style")?.includes("opacity") ? String(el.getAttribute("style")) : null;
5990
+ globalObj.__swoopStats.appRootSamples.push({ t: Date.now(), len, opacity });
5991
+ } catch {
5992
+ }
5993
+ };
5994
+ sample();
5995
+ hostSetTimeout(sample, 250);
5996
+ hostSetTimeout(sample, 1e3);
5997
+ hostSetTimeout(sample, 2500);
5998
+ hostSetTimeout(sample, 4500);
5999
+ }
6000
+ function emitDebugProbes(globalObj, recordDebug, now = () => Date.now()) {
6001
+ const stats = globalObj.__swoopStats;
6002
+ if (!stats) return;
6003
+ const appRootHtml = (() => {
6004
+ try {
6005
+ const el = globalObj.document?.querySelector?.("app-root");
6006
+ const raw = el?.innerHTML ?? "";
6007
+ return String(raw).slice(0, 400);
6008
+ } catch {
6009
+ return null;
6010
+ }
6011
+ })();
6012
+ recordDebug([
6013
+ "[swoop probes]",
6014
+ JSON.stringify({
6015
+ mutations: stats.mutations ?? 0,
6016
+ lastDomActivityMsAgo: stats.lastDomActivityAt && typeof stats.lastDomActivityAt === "number" ? now() - stats.lastDomActivityAt : null,
6017
+ topDomOps: Object.entries(stats.domOps ?? {}).sort((a, b) => b[1] - a[1]).slice(0, 15),
6018
+ topListeners: Object.entries(stats.listeners ?? {}).sort((a, b) => b[1] - a[1]).slice(0, 20),
6019
+ timers: stats.timers ?? null,
6020
+ lastAsyncActivityMsAgo: stats.lastAsyncActivityAt && typeof stats.lastAsyncActivityAt === "number" ? now() - stats.lastAsyncActivityAt : null,
6021
+ nav: stats.nav ?? null,
6022
+ location: (() => {
6023
+ try {
6024
+ return {
6025
+ href: String(globalObj.location?.href ?? ""),
6026
+ pathname: String(globalObj.location?.pathname ?? ""),
6027
+ search: String(globalObj.location?.search ?? ""),
6028
+ hash: String(globalObj.location?.hash ?? ""),
6029
+ baseURI: String(globalObj.document?.baseURI ?? "")
6030
+ };
6031
+ } catch {
6032
+ return null;
6033
+ }
6034
+ })(),
6035
+ appRootSamples: stats.appRootSamples ?? [],
6036
+ appRootHtmlHead: appRootHtml
6037
+ })
6038
+ ]);
6039
+ }
6040
+
6041
+ // src/swoop/scripts/loader.ts
6042
+ function isScriptEl(node) {
6043
+ return node?.tagName?.toLowerCase?.() === "script";
6044
+ }
6045
+ function createScriptLoader(init) {
6046
+ const loadedScriptSrcs = /* @__PURE__ */ new Set();
6047
+ let pendingScriptLoads = 0;
6048
+ let debugScriptEvents = 0;
6049
+ const debugScript = (...args) => {
6050
+ if (debugScriptEvents++ > init.maxDebugEvents) return;
6051
+ init.debug(args);
6052
+ };
6053
+ const loadScriptElement = async (scriptEl, parentUrlForResolve) => {
6054
+ const rawSrc = scriptEl?.src || scriptEl?.getAttribute?.("src");
6055
+ if (!rawSrc) return;
6056
+ let resolvedSrc;
6057
+ try {
6058
+ resolvedSrc = new URL(String(rawSrc), init.baseForResolveHref).href;
6059
+ } catch {
6060
+ return;
6061
+ }
6062
+ if (loadedScriptSrcs.has(resolvedSrc)) return;
6063
+ loadedScriptSrcs.add(resolvedSrc);
6064
+ init.noteAsyncActivity();
6065
+ pendingScriptLoads++;
6066
+ const type = (scriptEl?.type || scriptEl?.getAttribute?.("type") || "").toString().trim().toLowerCase();
6067
+ const isModule = type === "module";
6068
+ debugScript("[swoop] load <script>", resolvedSrc, isModule ? "module" : "classic");
6069
+ try {
6070
+ if (isModule) {
6071
+ await init.runModuleScript(resolvedSrc, parentUrlForResolve);
6072
+ } else {
6073
+ const code = await init.fetchText(resolvedSrc);
6074
+ init.runClassicScript(code, resolvedSrc);
6075
+ }
6076
+ try {
6077
+ if (typeof scriptEl?.onload === "function")
6078
+ scriptEl.onload(new (init.globalObj.Event ?? Event)("load"));
6079
+ } catch {
6080
+ try {
6081
+ scriptEl.onload?.();
6082
+ } catch {
6083
+ }
6084
+ }
6085
+ try {
6086
+ scriptEl?.dispatchEvent?.(new (init.globalObj.Event ?? Event)("load"));
6087
+ } catch {
6088
+ }
6089
+ } catch (e) {
6090
+ try {
6091
+ init.onError?.(resolvedSrc, e);
6092
+ } catch {
6093
+ }
6094
+ try {
6095
+ if (typeof scriptEl?.onerror === "function") scriptEl.onerror(e);
6096
+ } catch {
6097
+ try {
6098
+ scriptEl.onerror?.();
6099
+ } catch {
6100
+ }
6101
+ }
6102
+ try {
6103
+ scriptEl?.dispatchEvent?.(new (init.globalObj.Event ?? Event)("error"));
6104
+ } catch {
6105
+ }
6106
+ } finally {
6107
+ pendingScriptLoads--;
6108
+ init.noteAsyncActivity();
6109
+ }
6110
+ };
6111
+ const scheduleScriptLoad = (node, label) => {
6112
+ init.hostSetTimeout(() => {
6113
+ void loadScriptElement(node, `${init.pageUrlHref}#${label}`);
6114
+ }, 0);
6115
+ };
6116
+ const patchScriptInsertion = (container, label) => {
6117
+ if (!container) return;
6118
+ const origAppendChild = container.appendChild?.bind(container);
6119
+ const origInsertBefore = container.insertBefore?.bind(container);
6120
+ const origAppend = container.append?.bind(container);
6121
+ const origPrepend = container.prepend?.bind(container);
6122
+ if (typeof origAppendChild === "function") {
6123
+ container.appendChild = (node) => {
6124
+ const ret = origAppendChild(node);
6125
+ if (isScriptEl(node)) scheduleScriptLoad(node, `${label}.appendChild`);
6126
+ return ret;
6127
+ };
6128
+ }
6129
+ if (typeof origInsertBefore === "function") {
6130
+ container.insertBefore = (node, ref) => {
6131
+ const ret = origInsertBefore(node, ref);
6132
+ if (isScriptEl(node)) scheduleScriptLoad(node, `${label}.insertBefore`);
6133
+ return ret;
6134
+ };
6135
+ }
6136
+ if (typeof origAppend === "function") {
6137
+ container.append = (...nodes) => {
6138
+ const ret = origAppend(...nodes);
6139
+ for (const n of nodes) if (isScriptEl(n)) scheduleScriptLoad(n, `${label}.append`);
6140
+ return ret;
6141
+ };
6142
+ }
6143
+ if (typeof origPrepend === "function") {
6144
+ container.prepend = (...nodes) => {
6145
+ const ret = origPrepend(...nodes);
6146
+ for (const n of nodes) if (isScriptEl(n)) scheduleScriptLoad(n, `${label}.prepend`);
6147
+ return ret;
6148
+ };
6149
+ }
6150
+ };
6151
+ const install = () => {
6152
+ patchScriptInsertion(init.globalObj.document?.head, "head");
6153
+ patchScriptInsertion(init.globalObj.document?.body, "body");
6154
+ try {
6155
+ const elProto = init.globalObj.Element?.prototype;
6156
+ const origSetAttr = elProto?.setAttribute;
6157
+ if (typeof origSetAttr === "function") {
6158
+ elProto.setAttribute = function(name, value) {
6159
+ const ret = origSetAttr.call(this, name, value);
6160
+ try {
6161
+ if (this?.tagName?.toLowerCase?.() === "script" && typeof name === "string" && name.toLowerCase() === "src") {
6162
+ scheduleScriptLoad(this, "script.setAttribute(src)");
6163
+ }
6164
+ } catch {
6165
+ }
6166
+ return ret;
6167
+ };
6168
+ }
6169
+ } catch {
6170
+ }
6171
+ try {
6172
+ const doc = init.globalObj.document;
6173
+ const origCreateElement = doc?.createElement?.bind(doc);
6174
+ if (typeof origCreateElement === "function") {
6175
+ doc.createElement = (tagName, ...rest) => {
6176
+ const el = origCreateElement(tagName, ...rest);
6177
+ try {
6178
+ if (typeof tagName === "string" && tagName.toLowerCase() === "script") {
6179
+ const desc = Object.getOwnPropertyDescriptor(el, "src");
6180
+ if (!desc || desc.configurable) {
6181
+ let _src = el.getAttribute?.("src") ?? "";
6182
+ Object.defineProperty(el, "src", {
6183
+ configurable: true,
6184
+ enumerable: true,
6185
+ get: () => _src,
6186
+ set: (v) => {
6187
+ _src = String(v);
6188
+ try {
6189
+ el.setAttribute?.("src", _src);
6190
+ } catch {
6191
+ }
6192
+ scheduleScriptLoad(el, "script.src=");
6193
+ }
6194
+ });
6195
+ }
6196
+ }
6197
+ } catch {
6198
+ }
6199
+ return el;
6200
+ };
6201
+ }
6202
+ } catch {
6203
+ }
6204
+ };
6205
+ return {
6206
+ getPendingScriptLoads: () => pendingScriptLoads,
6207
+ install
6208
+ };
6209
+ }
6210
+ function isNodeRuntime() {
6211
+ return typeof process !== "undefined" && typeof process.versions === "object" && typeof process.versions.node === "string";
6212
+ }
6213
+ function sleep(ms) {
6214
+ return new Promise((resolve) => setTimeout$1(resolve, ms));
6215
+ }
6216
+ function normalizeInit(init) {
6217
+ return {
6218
+ engine: init?.engine ?? "vm",
6219
+ pluck: init?.pluck ?? {},
6220
+ executeScripts: init?.executeScripts ?? true,
6221
+ timeout: init?.timeout ?? 3e3,
6222
+ waitStrategy: init?.waitStrategy ?? "networkidle",
6223
+ idleTime: init?.idleTime ?? 250,
6224
+ pollInterval: init?.pollInterval ?? 25,
6225
+ maxScripts: init?.maxScripts ?? 64,
6226
+ forwardConsole: init?.forwardConsole ?? false,
6227
+ permissiveShims: init?.permissiveShims ?? true,
6228
+ debugFetch: init?.debugFetch ?? false,
6229
+ debugProbes: init?.debugProbes ?? false
6230
+ };
6231
+ }
6232
+ function defineWindowInContext(context, timeoutMs = 50) {
6233
+ vm4.runInContext(
6234
+ `
6235
+ globalThis.Window ??= function Window() {};
6236
+ try { globalThis.Window.prototype = Object.getPrototypeOf(globalThis); } catch {}
6237
+ `,
6238
+ context,
6239
+ { timeout: timeoutMs }
6240
+ );
6241
+ }
6242
+ function ensureRealmFunctionIntrinsic(context, timeoutMs = 50) {
6243
+ vm4.runInContext(
6244
+ `
6245
+ try { globalThis.Function = (function(){}).constructor; } catch {}
6246
+ `,
6247
+ context,
6248
+ { timeout: timeoutMs }
6249
+ );
6250
+ }
6251
+ function installRealmWrappers(context, timeoutMs = 50) {
6252
+ vm4.runInContext(
6253
+ `
6254
+ // timers
6255
+ if (typeof globalThis.__swoop_setTimeout === "function") {
6256
+ globalThis.setTimeout = (...args) => globalThis.__swoop_setTimeout(...args);
6257
+ }
6258
+ if (typeof globalThis.__swoop_clearTimeout === "function") {
6259
+ globalThis.clearTimeout = (...args) => globalThis.__swoop_clearTimeout(...args);
6260
+ }
6261
+ if (typeof globalThis.__swoop_setInterval === "function") {
6262
+ globalThis.setInterval = (...args) => globalThis.__swoop_setInterval(...args);
6263
+ }
6264
+ if (typeof globalThis.__swoop_clearInterval === "function") {
6265
+ globalThis.clearInterval = (...args) => globalThis.__swoop_clearInterval(...args);
6266
+ }
6267
+ if (typeof globalThis.__swoop_setImmediate === "function") {
6268
+ globalThis.setImmediate = (...args) => globalThis.__swoop_setImmediate(...args);
6269
+ }
6270
+ if (typeof globalThis.__swoop_clearImmediate === "function") {
6271
+ globalThis.clearImmediate = (...args) => globalThis.__swoop_clearImmediate(...args);
6272
+ }
6273
+
6274
+ // microtasks / raf / idle
6275
+ if (typeof globalThis.__swoop_queueMicrotask === "function") {
6276
+ globalThis.queueMicrotask = (...args) => globalThis.__swoop_queueMicrotask(...args);
6277
+ }
6278
+ if (typeof globalThis.__swoop_requestAnimationFrame === "function") {
6279
+ globalThis.requestAnimationFrame = (...args) => globalThis.__swoop_requestAnimationFrame(...args);
6280
+ }
6281
+ if (typeof globalThis.__swoop_cancelAnimationFrame === "function") {
6282
+ globalThis.cancelAnimationFrame = (...args) => globalThis.__swoop_cancelAnimationFrame(...args);
6283
+ }
6284
+ if (typeof globalThis.__swoop_requestIdleCallback === "function") {
6285
+ globalThis.requestIdleCallback = (...args) => globalThis.__swoop_requestIdleCallback(...args);
6286
+ }
6287
+ if (typeof globalThis.__swoop_cancelIdleCallback === "function") {
6288
+ globalThis.cancelIdleCallback = (...args) => globalThis.__swoop_cancelIdleCallback(...args);
6289
+ }
6290
+
6291
+ // fetch
6292
+ if (typeof globalThis.__swoop_fetch === "function") {
6293
+ globalThis.fetch = (...args) => globalThis.__swoop_fetch(...args);
6294
+ }
6295
+ `,
6296
+ context,
6297
+ { timeout: timeoutMs }
6298
+ );
6299
+ }
6300
+ function createModuleLoader(init) {
6301
+ const SourceTextModule = vm4.SourceTextModule;
6302
+ const moduleCache = /* @__PURE__ */ new Map();
6303
+ const pluckFn = init.pluckFn ?? pluck;
6304
+ const loadModule = async (specifier, referencingUrl) => {
6305
+ if (init.remainingMs() <= 0)
6306
+ throw new Error("swoop() time budget exhausted while loading modules");
6307
+ const resolved = new URL(specifier, referencingUrl).href;
6308
+ const cached = moduleCache.get(resolved);
6309
+ if (cached) return cached;
6310
+ if (!SourceTextModule) {
6311
+ throw new Error(
6312
+ "Module scripts require Node `--experimental-vm-modules` (vm.SourceTextModule is unavailable)."
6313
+ );
6314
+ }
6315
+ const modRes = await pluckFn(resolved, {
6316
+ ...init.pluckInit,
6317
+ timeout: Math.min(init.pluckInit.timeout ?? 3e4, init.remainingMs()),
6318
+ strictContentType: false,
6319
+ throwOnHttpError: true
6320
+ });
6321
+ const rawSource = await modRes.textUtf8();
6322
+ const mod = new SourceTextModule(rawSource, {
6323
+ context: init.context,
6324
+ identifier: resolved,
6325
+ initializeImportMeta: (meta) => {
6326
+ meta.url = resolved;
6327
+ },
6328
+ importModuleDynamically: async (spec) => {
6329
+ const child = await loadModule(spec, resolved);
6330
+ await child.link(linkerFor(resolved));
6331
+ await child.evaluate();
6332
+ return child;
6333
+ }
6334
+ });
6335
+ moduleCache.set(resolved, mod);
6336
+ return mod;
6337
+ };
6338
+ const linkerFor = (referencingUrl) => async (specifier) => {
6339
+ return await loadModule(specifier, referencingUrl);
6340
+ };
6341
+ return { loadModule, linkerFor };
6342
+ }
6343
+
6344
+ // src/swoop/wait.ts
6345
+ async function waitForSettle(init) {
6346
+ if (init.strategy === "timeout") {
6347
+ await init.sleep(Math.max(0, init.deadlineMs - init.now()));
6348
+ return { timedOut: init.now() >= init.deadlineMs };
6349
+ }
6350
+ while (init.now() < init.deadlineMs) {
6351
+ if (init.getPendingFetches() === 0 && init.getPendingScriptLoads() === 0 && init.now() - init.getLastAsyncActivityAt() >= init.idleTimeMs) {
6352
+ return { timedOut: false };
6353
+ }
6354
+ await init.sleep(init.pollIntervalMs);
6355
+ }
6356
+ return { timedOut: true };
6357
+ }
6358
+
6359
+ // src/swoop/engines/vm.ts
6360
+ async function runVmEngine(args) {
6361
+ const { entries: realmConsole, record } = createConsoleCapture();
6362
+ const remainingMs = () => Math.max(0, args.deadline - Date.now());
6363
+ const { window, document } = parseHTML$1(args.html, { url: args.finalUrl });
6364
+ const pageUrl = new URL(args.finalUrl);
6365
+ const { baseForResolve, baseEl } = computeBaseForResolve(args.finalUrl, document);
6366
+ patchDocumentBaseURI(document, baseForResolve);
6367
+ patchBaseElementHref(baseEl, baseForResolve);
6368
+ const documentBaseUriForDom = baseForResolve.href;
6369
+ try {
6370
+ document.readyState ??= "loading";
6371
+ } catch {
6372
+ }
6373
+ const domWindow = window;
6374
+ const globalObj = Object.create(domWindow);
6375
+ globalObj.window = globalObj;
6376
+ globalObj.self = globalObj;
6377
+ globalObj.globalThis = globalObj;
6378
+ globalObj.document = document;
6379
+ try {
6380
+ Object.defineProperty(document, "defaultView", { value: globalObj, configurable: true });
6381
+ } catch {
6382
+ }
6383
+ const { location: locationShim, history: historyShim } = createNavigationShims({
6384
+ pageUrl,
6385
+ onNavigate: (href) => {
6386
+ if (!args.options.debugProbes) return;
6387
+ try {
6388
+ globalObj.__swoopStats.nav.lastHref = String(href);
6389
+ } catch {
6390
+ }
6391
+ },
6392
+ onPopState: (state) => {
6393
+ if (args.options.debugProbes) {
6394
+ try {
6395
+ globalObj.__swoopStats.nav.pushState++;
6396
+ } catch {
6397
+ }
6398
+ }
6399
+ try {
6400
+ globalObj.dispatchEvent?.(new (globalObj.PopStateEvent ?? Event)("popstate", { state }));
6401
+ } catch {
6402
+ }
6403
+ }
6404
+ });
6405
+ try {
6406
+ Object.defineProperty(document, "location", {
6407
+ configurable: true,
6408
+ get: () => locationShim,
6409
+ set: (v) => {
6410
+ try {
6411
+ locationShim.href = String(v);
6412
+ } catch {
6413
+ }
6414
+ }
6415
+ });
6416
+ } catch {
6417
+ }
6418
+ globalObj.location = locationShim;
6419
+ globalObj.history = historyShim;
6420
+ installBrowserShims({ globalObj, domWindow, document, documentBaseUriForDom });
6421
+ installCookieJar(document);
6422
+ const asyncEnv = installAsyncEnv({ globalObj, debugProbes: args.options.debugProbes });
6423
+ const noteAsyncActivity = asyncEnv.noteAsyncActivity;
6424
+ const hostSetTimeout = asyncEnv.hostSetTimeout;
6425
+ const hostClearTimeout = asyncEnv.hostClearTimeout;
6426
+ if (args.options.debugProbes) {
6427
+ try {
6428
+ installDebugProbes({ globalObj, hostSetTimeout });
6429
+ } catch {
6430
+ }
6431
+ }
6432
+ const fetchShim = installFetchShim({
6433
+ globalObj,
6434
+ hostFetch: args.hostFetch,
6435
+ baseForResolveHref: baseForResolve.href,
6436
+ remainingMs,
6437
+ hostSetTimeout,
6438
+ hostClearTimeout,
6439
+ noteAsyncActivity,
6440
+ debugFetch: args.options.debugFetch,
6441
+ recordDebug: (a) => record("debug", a),
6442
+ queueMicrotask: (cb) => globalObj.__swoop_queueMicrotask(cb)
6443
+ });
6444
+ const addEventListener = domWindow.addEventListener?.bind(domWindow);
6445
+ const removeEventListener = domWindow.removeEventListener?.bind(domWindow);
6446
+ const dispatchEvent = domWindow.dispatchEvent?.bind(domWindow);
6447
+ if (typeof addEventListener === "function") globalObj.addEventListener = addEventListener;
6448
+ if (typeof removeEventListener === "function")
6449
+ globalObj.removeEventListener = removeEventListener;
6450
+ if (typeof dispatchEvent === "function") globalObj.dispatchEvent = dispatchEvent;
6451
+ globalObj.console = {
6452
+ debug: (...a) => record("debug", a),
6453
+ info: (...a) => record("info", a),
6454
+ warn: (...a) => record("warn", a),
6455
+ error: (...a) => record("error", a),
6456
+ log: (...a) => record("log", a)
6457
+ };
6458
+ if (args.options.forwardConsole) {
6459
+ for (const level of ["debug", "info", "warn", "error", "log"]) {
6460
+ const original = console[level]?.bind(console);
6461
+ if (typeof original === "function") {
6462
+ const wrapped = globalObj.console[level];
6463
+ globalObj.console[level] = (...a) => {
6464
+ wrapped(...a);
6465
+ original(...a);
6466
+ };
6467
+ }
6468
+ }
6469
+ }
6470
+ try {
6471
+ globalObj.onerror = (message, source, line, col, error) => {
6472
+ record("error", ["[window.onerror]", message, source, line, col, error]);
6473
+ };
6474
+ } catch {
6475
+ }
6476
+ try {
6477
+ globalObj.onunhandledrejection = (event) => {
6478
+ record("error", ["[unhandledrejection]", event?.reason]);
6479
+ };
6480
+ } catch {
6481
+ }
6482
+ try {
6483
+ globalObj.addEventListener?.("error", (event) => {
6484
+ record("error", [
6485
+ "[error event]",
6486
+ event?.message,
6487
+ event?.filename,
6488
+ event?.lineno,
6489
+ event?.colno,
6490
+ event?.error instanceof Error ? `${event.error.name}: ${event.error.message}
6491
+ ${event.error.stack ?? ""}`.trim() : event?.error
6492
+ ]);
6493
+ });
6494
+ } catch {
6495
+ }
6496
+ if (args.options.permissiveShims) {
6497
+ installPermissiveShims(globalObj);
6498
+ if (!globalObj.XMLHttpRequest) {
6499
+ installXMLHttpRequest({
6500
+ globalObj,
6501
+ resolveUrl: (u) => {
6502
+ try {
6503
+ return new URL(u, baseForResolve.href).href;
6504
+ } catch {
6505
+ return u;
6506
+ }
6507
+ },
6508
+ remainingMs,
6509
+ hostSetTimeout,
6510
+ hostClearTimeout,
6511
+ fetch: args.hostFetch
6512
+ });
6513
+ }
6514
+ }
6515
+ const context = vm4.createContext(globalObj, { name: "magpie-html/swoop" });
6516
+ defineWindowInContext(context);
6517
+ ensureRealmFunctionIntrinsic(context);
6518
+ installRealmWrappers(context);
6519
+ const { loadModule, linkerFor } = createModuleLoader({
6520
+ context,
6521
+ remainingMs,
6522
+ pluckInit: args.options.pluck
6523
+ });
6524
+ const scriptLoader = createScriptLoader({
6525
+ globalObj,
6526
+ pageUrlHref: pageUrl.href,
6527
+ baseForResolveHref: baseForResolve.href,
6528
+ remainingMs,
6529
+ hostSetTimeout,
6530
+ totalBudgetMs: args.totalBudgetMs,
6531
+ maxDebugEvents: args.options.debugProbes ? 80 : 0,
6532
+ debug: (a) => {
6533
+ if (!args.options.debugProbes) return;
6534
+ record("debug", a);
6535
+ },
6536
+ onError: (resolvedSrc, err) => {
6537
+ const e = err;
6538
+ record("error", ["[swoop] script load failed", resolvedSrc, e?.message || String(e)]);
6539
+ },
6540
+ noteAsyncActivity,
6541
+ fetchText: async (url) => {
6542
+ const sres = await pluck(url, {
6543
+ ...args.options.pluck,
6544
+ timeout: Math.min(args.options.pluck.timeout ?? 3e4, remainingMs()),
6545
+ strictContentType: false,
6546
+ throwOnHttpError: true
6547
+ });
6548
+ return await sres.textUtf8();
6549
+ },
6550
+ runClassicScript: (code, filename) => {
6551
+ const script = new vm4.Script(code, { filename });
6552
+ script.runInContext(context, { timeout: args.totalBudgetMs });
6553
+ },
6554
+ runModuleScript: async (resolvedSrc, parentUrlForResolve) => {
6555
+ const mod = await loadModule(resolvedSrc, parentUrlForResolve);
6556
+ await mod.link(linkerFor(resolvedSrc));
6557
+ await mod.evaluate();
6558
+ }
6559
+ });
6560
+ scriptLoader.install();
6561
+ const getPendingScriptLoads = () => scriptLoader.getPendingScriptLoads();
6562
+ const engineErrors = [];
6563
+ const classicScripts = args.scripts.filter((s) => !s.isModule);
6564
+ const moduleScriptsInOrder = args.scripts.filter((s) => s.isModule);
6565
+ for (const s of [...classicScripts, ...moduleScriptsInOrder]) {
6566
+ if (remainingMs() <= 0) {
6567
+ engineErrors.push({
6568
+ stage: "wait",
6569
+ message: `Hard time budget (${args.totalBudgetMs}ms) exceeded while executing scripts; returning snapshot.`
6570
+ });
6571
+ break;
6572
+ }
6573
+ const scriptUrl = s.kind === "external" ? s.url : `${args.finalUrl}#inline`;
6574
+ try {
6575
+ if (s.isModule) {
6576
+ const modCode = s.code;
6577
+ const SourceTextModule = vm4.SourceTextModule;
6578
+ if (!SourceTextModule) {
6579
+ throw new Error(
6580
+ "Module scripts require Node `--experimental-vm-modules` (vm.SourceTextModule is unavailable)."
6581
+ );
6582
+ }
6583
+ const mod = new SourceTextModule(modCode, {
6584
+ context,
6585
+ identifier: scriptUrl,
6586
+ initializeImportMeta: (meta) => {
6587
+ meta.url = scriptUrl;
6588
+ },
6589
+ importModuleDynamically: async (spec) => {
6590
+ const child = await loadModule(spec, scriptUrl);
6591
+ await child.link(linkerFor(scriptUrl));
6592
+ await child.evaluate();
6593
+ return child;
6594
+ }
6595
+ });
6596
+ const timeoutP = (label) => sleep(remainingMs()).then(() => {
6597
+ throw new Error(`swoop() time budget exhausted during ${label}`);
6598
+ });
6599
+ const linkP = mod.link(linkerFor(scriptUrl));
6600
+ try {
6601
+ await Promise.race([linkP, timeoutP("module link")]);
6602
+ } catch (e) {
6603
+ void linkP.catch?.(() => {
6604
+ });
6605
+ throw e;
6606
+ }
6607
+ const evalP = mod.evaluate();
6608
+ try {
6609
+ await Promise.race([evalP, timeoutP("module evaluate")]);
6610
+ } catch (e) {
6611
+ void evalP.catch?.(() => {
6612
+ });
6613
+ throw e;
6614
+ }
6615
+ } else {
6616
+ const script = new vm4.Script(s.code, { filename: scriptUrl });
6617
+ script.runInContext(context, { timeout: args.totalBudgetMs });
6618
+ }
6619
+ } catch (err) {
6620
+ const e = err;
6621
+ engineErrors.push({
6622
+ stage: "script",
6623
+ scriptUrl: s.kind === "external" ? s.url : void 0,
6624
+ message: e.message || String(e),
6625
+ stack: e.stack
6626
+ });
6627
+ }
6628
+ }
6629
+ try {
6630
+ synthesizeLifecycle(context, Math.min(50, remainingMs()));
6631
+ } catch {
6632
+ }
6633
+ const settle = await waitForSettle({
6634
+ strategy: args.options.waitStrategy === "timeout" || typeof globalObj.fetch !== "function" ? "timeout" : "networkidle",
6635
+ deadlineMs: args.deadline,
6636
+ idleTimeMs: args.options.idleTime,
6637
+ pollIntervalMs: args.options.pollInterval,
6638
+ sleep,
6639
+ now: () => Date.now(),
6640
+ getPendingFetches: () => fetchShim.getPendingFetches(),
6641
+ getPendingScriptLoads,
6642
+ getLastAsyncActivityAt: () => asyncEnv.getLastAsyncActivityAt()
6643
+ });
6644
+ if (settle.timedOut && args.options.waitStrategy === "networkidle" && typeof globalObj.fetch === "function") {
6645
+ engineErrors.push({
6646
+ stage: "wait",
6647
+ message: `Hard time budget (${args.totalBudgetMs}ms) exceeded waiting for network idle; returning snapshot.`
6648
+ });
6649
+ }
6650
+ const snapshot = document.documentElement?.outerHTML ?? "";
6651
+ if (args.options.debugProbes) {
6652
+ try {
6653
+ emitDebugProbes(globalObj, (a) => record("debug", a));
6654
+ } catch {
6655
+ }
6656
+ }
6657
+ asyncEnv.cleanup();
6658
+ return { snapshot, consoleEntries: realmConsole, engineErrors };
6659
+ }
6660
+
6661
+ // src/swoop/scripts/discover.ts
6662
+ function isExecutableScriptType(type) {
6663
+ if (!type) return true;
6664
+ const t = type.trim().toLowerCase();
6665
+ if (t === "") return true;
6666
+ if (t === "text/javascript") return true;
6667
+ if (t === "application/javascript") return true;
6668
+ if (t === "application/ecmascript") return true;
6669
+ if (t === "text/ecmascript") return true;
6670
+ return false;
6671
+ }
6672
+ function isModuleScript(type) {
6673
+ return (type ?? "").trim().toLowerCase() === "module";
6674
+ }
6675
+ async function discoverAndFetchScripts(html, finalUrl, init, pluckFn = pluck) {
6676
+ const errors = [];
6677
+ const scripts = [];
6678
+ if (!init.executeScripts) return { scripts, errors };
6679
+ const doc = parseHTML(html, finalUrl);
6680
+ const baseHref = doc.querySelector("base[href]")?.getAttribute("href") ?? null;
6681
+ const baseUrl = baseHref ? new URL(baseHref, finalUrl).href : finalUrl;
6682
+ const scriptEls = Array.from(doc.querySelectorAll("script"));
6683
+ for (const el of scriptEls.slice(0, init.maxScripts)) {
6684
+ const type = el.getAttribute("type");
6685
+ const isModule = isModuleScript(type);
6686
+ if (!isModule && !isExecutableScriptType(type)) continue;
6687
+ const src = el.getAttribute("src");
6688
+ if (src) {
6689
+ const scriptUrl = new URL(src, baseUrl).href;
6690
+ try {
6691
+ const res = await pluckFn(scriptUrl, {
6692
+ ...init.pluck,
6693
+ strictContentType: false,
6694
+ throwOnHttpError: true
6695
+ });
6696
+ const code2 = await res.textUtf8();
6697
+ scripts.push({ kind: "external", url: scriptUrl, code: code2, isModule });
6698
+ } catch (err) {
6699
+ const e = err;
6700
+ errors.push({
6701
+ stage: "script",
6702
+ scriptUrl,
6703
+ message: `Failed to fetch external script: ${e.message || String(e)}`,
6704
+ stack: e.stack
6705
+ });
6706
+ }
6707
+ continue;
6708
+ }
6709
+ const code = el.textContent ?? "";
6710
+ if (code.trim().length === 0) continue;
6711
+ scripts.push({ kind: "inline", code, isModule });
6712
+ }
6713
+ return { scripts, errors };
6714
+ }
6715
+
6716
+ // src/swoop/swoop.ts
6717
+ var HOST_FETCH = typeof globalThis.fetch === "function" ? globalThis.fetch.bind(globalThis) : void 0;
6718
+ async function swoop(url, init) {
6719
+ const start = Date.now();
6720
+ const options = normalizeInit(init);
6721
+ const totalBudgetMs = Math.min(options.timeout, 5e3);
6722
+ const deadline = start + totalBudgetMs;
6723
+ if (!isNodeRuntime()) {
6724
+ throw new SwoopEnvironmentError("swoop() is currently Node.js-only.");
6725
+ }
6726
+ const res = await pluck(String(url), {
6727
+ ...options.pluck,
6728
+ timeout: Math.min(options.pluck.timeout ?? 3e4, totalBudgetMs),
6729
+ strictContentType: false,
6730
+ throwOnHttpError: true
6731
+ });
6732
+ const html = await res.textUtf8();
6733
+ const finalUrl = res.finalUrl;
6734
+ const { scripts, errors: preErrors } = await discoverAndFetchScripts(html, finalUrl, options);
6735
+ let snapshot = "";
6736
+ let consoleEntries = [];
6737
+ let engineErrors = [];
6738
+ const r = await runVmEngine({
6739
+ finalUrl,
6740
+ html,
6741
+ scripts,
6742
+ options,
6743
+ totalBudgetMs,
6744
+ deadline,
6745
+ hostFetch: HOST_FETCH
6746
+ });
6747
+ snapshot = r.snapshot;
6748
+ consoleEntries = r.consoleEntries;
6749
+ engineErrors = r.engineErrors;
6750
+ const end = Date.now();
6751
+ return {
6752
+ url: finalUrl,
6753
+ html: snapshot,
6754
+ console: consoleEntries,
6755
+ errors: [...preErrors, ...engineErrors],
6756
+ timing: {
6757
+ start,
6758
+ end,
6759
+ duration: end - start
6760
+ }
6761
+ };
6762
+ }
5049
6763
  /**
5050
6764
  * Enhanced fetch types for web scraping.
5051
6765
  *
@@ -5144,6 +6858,6 @@ function extractVerification(doc) {
5144
6858
  * @packageDocumentation
5145
6859
  */
5146
6860
 
5147
- export { PluckContentTypeError, PluckEncodingError, PluckError, PluckHttpError, PluckNetworkError, PluckRedirectError, PluckSizeError, PluckTimeoutError, assessContentQuality, calculateReadingTime, countWords, detectFormat, extractAnalytics, extractAssets, extractCanonical, extractContent, extractCopyright, extractDublinCore, extractFeedDiscovery, extractGeo, extractIcons, extractLanguage, extractLinks3 as extractLinks, extractMonetization, extractNews, extractOpenGraph, extractPagination, extractRobots, extractSEO, extractSchemaOrg, extractSecurity, extractSitemapDiscovery, extractSocialProfiles, extractTwitterCard, extractVerification, gatherArticle, gatherFeed, gatherWebsite, htmlToText, isAtom, isFeed, isJSONFeed, isProbablyReaderable, isRSS, parseFeed, parseHTML, pluck };
6861
+ export { PluckContentTypeError, PluckEncodingError, PluckError, PluckHttpError, PluckNetworkError, PluckRedirectError, PluckSizeError, PluckTimeoutError, SwoopEnvironmentError, SwoopError, SwoopExecutionError, SwoopSecurityError, SwoopTimeoutError, assessContentQuality, calculateReadingTime, countWords, detectFormat, extractAnalytics, extractAssets, extractCanonical, extractContent, extractCopyright, extractDublinCore, extractFeedDiscovery, extractGeo, extractIcons, extractLanguage, extractLinks3 as extractLinks, extractMonetization, extractNews, extractOpenGraph, extractPagination, extractRobots, extractSEO, extractSchemaOrg, extractSecurity, extractSitemapDiscovery, extractSocialProfiles, extractTwitterCard, extractVerification, gatherArticle, gatherFeed, gatherWebsite, htmlToText, isAtom, isFeed, isJSONFeed, isProbablyReaderable, isRSS, parseFeed, parseHTML, pluck, swoop };
5148
6862
  //# sourceMappingURL=index.js.map
5149
6863
  //# sourceMappingURL=index.js.map