@checkly/playwright-core 1.48.24-maxi → 1.48.25-beta.0
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/lib/generated/bindingsControllerSource.js +7 -0
- package/lib/generated/storageScriptSource.js +7 -0
- package/lib/server/har/harRecorder.js +3 -1
- package/lib/server/trace/recorder/tracing.js +9 -20
- package/lib/utils/fileUtils.js +65 -2
- package/lib/vite/{traceViewer/assets/codeMirrorModule-tzBrK1V4.js → recorder/assets/codeMirrorModule-baozm8ur.js} +10 -10
- package/lib/vite/recorder/assets/{index-BcaUAUCW.js → index-2ElAIWFB.js} +2 -2
- package/lib/vite/recorder/index.html +1 -1
- package/lib/vite/traceViewer/assets/{codeMirrorModule-CB-2okZ8.js → codeMirrorModule-DblsdhjA.js} +2096 -2331
- package/lib/vite/{recorder/assets/codeMirrorModule-CR6kB851.js → traceViewer/assets/codeMirrorModule-lDjkI8Ax.js} +1 -1
- package/lib/vite/traceViewer/assets/{inspectorTab-BHcfR9dD.js → inspectorTab-BPzhNk9r.js} +2 -2
- package/lib/vite/traceViewer/assets/inspectorTab-DOc4D3cX.js +17361 -0
- package/lib/vite/traceViewer/assets/{defaultSettingsView-CBiB4avC.js → testServerConnection-D-tXL3sj.js} +49 -42
- package/lib/vite/traceViewer/assets/{workbench-DZqNXdoV.js → workbench-DLv_q9ji.js} +1 -1
- package/lib/vite/traceViewer/assets/workbench-DNolpp3y.js +1473 -0
- package/lib/vite/traceViewer/assets/xtermModule-DZP0glxx.js +5982 -0
- package/lib/vite/traceViewer/{embedded.DInvAijy.js → embedded.BIubxTi3.js} +1 -1
- package/lib/vite/traceViewer/{embedded.gzudoghF.js → embedded.DeCrOtlO.js} +4 -4
- package/lib/vite/traceViewer/embedded.html +3 -3
- package/lib/vite/traceViewer/{index.DilotR1h.js → index.CM_h9lHr.js} +7 -124
- package/lib/vite/traceViewer/{index.Dha3cgqs.js → index.DPD22sZn.js} +1 -1
- package/lib/vite/traceViewer/index.html +3 -3
- package/lib/vite/traceViewer/{inspectorTab.DnGm18kV.css → inspectorTab.DGJWXOSd.css} +1488 -1521
- package/lib/vite/traceViewer/{recorder.C88JDknq.js → recorder.BaRuS6Pc.js} +1 -1
- package/lib/vite/traceViewer/{recorder.DVrkq3Um.js → recorder.Fwf59ZKh.js} +3 -3
- package/lib/vite/traceViewer/recorder.html +2 -2
- package/lib/vite/traceViewer/{uiMode.2tr9k625.js → uiMode.B11wexdJ.js} +1 -1
- package/lib/vite/traceViewer/{uiMode.C9_OcpPU.js → uiMode.CYBsUhm_.js} +58 -90
- package/lib/vite/traceViewer/{uiMode.c5ORgcrX.css → uiMode.DRmgrHSk.css} +45 -7
- package/lib/vite/traceViewer/uiMode.html +3 -3
- package/lib/vite/traceViewer/{workbench.xUZSA8PY.css → workbench.BQNDbcQ0.css} +83 -320
- package/package.json +1 -1
- package/lib/client/clientStackTrace.js +0 -66
- package/lib/client/fileUtils.js +0 -33
- package/lib/client/platform.js +0 -72
- package/lib/client/timeoutSettings.js +0 -66
- package/lib/client/webSocket.js +0 -107
- package/lib/generated/recorderSource.js +0 -7
- package/lib/server/callLog.js +0 -80
- package/lib/server/harBackend.js +0 -158
- package/lib/server/localUtils.js +0 -204
- package/lib/server/recorder/chat.js +0 -178
- package/lib/server/recorder/codeGenerator.js +0 -154
- package/lib/server/recorder/csharp.js +0 -311
- package/lib/server/recorder/java.js +0 -249
- package/lib/server/recorder/javascript.js +0 -230
- package/lib/server/recorder/jsonl.js +0 -48
- package/lib/server/recorder/language.js +0 -45
- package/lib/server/recorder/python.js +0 -276
- package/lib/server/recorder/recorderActions.js +0 -6
- package/lib/server/recorder/utils.js +0 -46
- package/lib/server/storageScript.js +0 -161
- package/lib/server/timeoutSettings.js +0 -75
- package/lib/server/utils/ascii.js +0 -32
- package/lib/server/utils/comparators.js +0 -160
- package/lib/server/utils/crypto.js +0 -172
- package/lib/server/utils/debug.js +0 -39
- package/lib/server/utils/debugLogger.js +0 -94
- package/lib/server/utils/env.js +0 -54
- package/lib/server/utils/eventsHelper.js +0 -39
- package/lib/server/utils/expectUtils.js +0 -34
- package/lib/server/utils/fileUtils.js +0 -205
- package/lib/server/utils/happyEyeballs.js +0 -210
- package/lib/server/utils/hostPlatform.js +0 -146
- package/lib/server/utils/httpServer.js +0 -234
- package/lib/server/utils/image_tools/colorUtils.js +0 -99
- package/lib/server/utils/image_tools/compare.js +0 -109
- package/lib/server/utils/image_tools/imageChannel.js +0 -71
- package/lib/server/utils/image_tools/stats.js +0 -103
- package/lib/server/utils/linuxUtils.js +0 -59
- package/lib/server/utils/network.js +0 -161
- package/lib/server/utils/nodePlatform.js +0 -141
- package/lib/server/utils/pipeTransport.js +0 -83
- package/lib/server/utils/processLauncher.js +0 -249
- package/lib/server/utils/profiler.js +0 -53
- package/lib/server/utils/socksProxy.js +0 -571
- package/lib/server/utils/spawnAsync.js +0 -46
- package/lib/server/utils/task.js +0 -59
- package/lib/server/utils/userAgent.js +0 -92
- package/lib/server/utils/wsServer.js +0 -129
- package/lib/server/utils/zipFile.js +0 -76
- package/lib/server/utils/zones.js +0 -55
- package/lib/utils/glob.js +0 -84
- package/lib/utils/isomorphic/ariaSnapshot.js +0 -393
- package/lib/utils/isomorphic/assert.js +0 -26
- package/lib/utils/isomorphic/colors.js +0 -66
- package/lib/utils/isomorphic/headers.js +0 -53
- package/lib/utils/isomorphic/manualPromise.js +0 -108
- package/lib/utils/isomorphic/multimap.js +0 -74
- package/lib/utils/isomorphic/rtti.js +0 -42
- package/lib/utils/isomorphic/semaphore.js +0 -52
- package/lib/utils/isomorphic/stackTrace.js +0 -170
- package/lib/utils/isomorphic/time.js +0 -26
- package/lib/utils/isomorphic/timeoutRunner.js +0 -67
- package/lib/utils/isomorphic/types.js +0 -6
- package/lib/utils/mimeType.js +0 -30
- package/lib/utils.js +0 -448
- package/lib/vite/traceViewer/assets/codeMirrorModule-DZoSgqUd.js +0 -24
- package/lib/vite/traceViewer/assets/inspectorTab-BuJ3wAX_.js +0 -64
- package/lib/vite/traceViewer/assets/inspectorTab-CwgfffWb.js +0 -25143
- package/lib/vite/traceViewer/assets/workbench-CWZselvp.js +0 -2470
- package/lib/vite/traceViewer/assets/workbench-DdmJ9AJV.js +0 -9
- package/lib/vite/traceViewer/assets/xtermModule-Es_gt_u7.js +0 -5994
- package/lib/vite/traceViewer/defaultSettingsView.Dp3b_92q.css +0 -41
- package/lib/vite/traceViewer/embedded.Dxe2heQk.js +0 -2
- package/lib/vite/traceViewer/index.CB297BuW.js +0 -2
- package/lib/vite/traceViewer/recorder.DNMfnSiu.js +0 -2
- package/lib/vite/traceViewer/uiMode.Cr1tvTWS.js +0 -5
- /package/lib/vite/traceViewer/{codeMirrorModule.DuST8d_k.css → codeMirrorModule.Cy8X9Wtw.css} +0 -0
- /package/lib/vite/traceViewer/{embedded.BeldSa2G.css → embedded.DjZq4InJ.css} +0 -0
- /package/lib/vite/traceViewer/{index.QewjJ85u.css → index.QanXxRUb.css} +0 -0
- /package/lib/vite/traceViewer/{recorder.DLgqV9db.css → recorder.DBDpiNOK.css} +0 -0
- /package/lib/vite/traceViewer/{xtermModule.EsaqrrTX.css → xtermModule.4oRVGWQ-.css} +0 -0
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.source = void 0;
|
|
7
|
+
const source = exports.source = "\nvar __commonJS = obj => {\n let required = false;\n let result;\n return function __require() {\n if (!required) {\n required = true;\n let fn;\n for (const name in obj) { fn = obj[name]; break; }\n const module = { exports: {} };\n fn(module.exports, module);\n result = module.exports;\n }\n return result;\n }\n};\nvar __export = (target, all) => {for (var name in all) target[name] = all[name];};\nvar __toESM = mod => ({ ...mod, 'default': mod });\nvar __toCommonJS = mod => ({ ...mod, __esModule: true });\n\n\n// packages/injected/src/bindingsController.ts\nvar bindingsController_exports = {};\n__export(bindingsController_exports, {\n BindingsController: () => BindingsController\n});\nmodule.exports = __toCommonJS(bindingsController_exports);\n\n// packages/playwright-core/src/utils/isomorphic/utilityScriptSerializers.ts\nfunction isRegExp(obj) {\n try {\n return obj instanceof RegExp || Object.prototype.toString.call(obj) === \"[object RegExp]\";\n } catch (error) {\n return false;\n }\n}\nfunction isDate(obj) {\n try {\n return obj instanceof Date || Object.prototype.toString.call(obj) === \"[object Date]\";\n } catch (error) {\n return false;\n }\n}\nfunction isURL(obj) {\n try {\n return obj instanceof URL || Object.prototype.toString.call(obj) === \"[object URL]\";\n } catch (error) {\n return false;\n }\n}\nfunction isError(obj) {\n var _a;\n try {\n return obj instanceof Error || obj && ((_a = Object.getPrototypeOf(obj)) == null ? void 0 : _a.name) === \"Error\";\n } catch (error) {\n return false;\n }\n}\nfunction isTypedArray(obj, constructor) {\n try {\n return obj instanceof constructor || Object.prototype.toString.call(obj) === `[object ${constructor.name}]`;\n } catch (error) {\n return false;\n }\n}\nvar typedArrayConstructors = {\n i8: Int8Array,\n ui8: Uint8Array,\n ui8c: Uint8ClampedArray,\n i16: Int16Array,\n ui16: Uint16Array,\n i32: Int32Array,\n ui32: Uint32Array,\n // TODO: add Float16Array once it's in baseline\n f32: Float32Array,\n f64: Float64Array,\n bi64: BigInt64Array,\n bui64: BigUint64Array\n};\nfunction typedArrayToBase64(array) {\n if (\"toBase64\" in array)\n return array.toBase64();\n const binary = Array.from(new Uint8Array(array.buffer, array.byteOffset, array.byteLength)).map((b) => String.fromCharCode(b)).join(\"\");\n return btoa(binary);\n}\nfunction serializeAsCallArgument(value, handleSerializer) {\n return serialize(value, handleSerializer, { visited: /* @__PURE__ */ new Map(), lastId: 0 });\n}\nfunction serialize(value, handleSerializer, visitorInfo) {\n if (value && typeof value === \"object\") {\n if (typeof globalThis.Window === \"function\" && value instanceof globalThis.Window)\n return \"ref: <Window>\";\n if (typeof globalThis.Document === \"function\" && value instanceof globalThis.Document)\n return \"ref: <Document>\";\n if (typeof globalThis.Node === \"function\" && value instanceof globalThis.Node)\n return \"ref: <Node>\";\n }\n return innerSerialize(value, handleSerializer, visitorInfo);\n}\nfunction innerSerialize(value, handleSerializer, visitorInfo) {\n var _a;\n const result = handleSerializer(value);\n if (\"fallThrough\" in result)\n value = result.fallThrough;\n else\n return result;\n if (typeof value === \"symbol\")\n return { v: \"undefined\" };\n if (Object.is(value, void 0))\n return { v: \"undefined\" };\n if (Object.is(value, null))\n return { v: \"null\" };\n if (Object.is(value, NaN))\n return { v: \"NaN\" };\n if (Object.is(value, Infinity))\n return { v: \"Infinity\" };\n if (Object.is(value, -Infinity))\n return { v: \"-Infinity\" };\n if (Object.is(value, -0))\n return { v: \"-0\" };\n if (typeof value === \"boolean\")\n return value;\n if (typeof value === \"number\")\n return value;\n if (typeof value === \"string\")\n return value;\n if (typeof value === \"bigint\")\n return { bi: value.toString() };\n if (isError(value)) {\n let stack;\n if ((_a = value.stack) == null ? void 0 : _a.startsWith(value.name + \": \" + value.message)) {\n stack = value.stack;\n } else {\n stack = `${value.name}: ${value.message}\n${value.stack}`;\n }\n return { e: { n: value.name, m: value.message, s: stack } };\n }\n if (isDate(value))\n return { d: value.toJSON() };\n if (isURL(value))\n return { u: value.toJSON() };\n if (isRegExp(value))\n return { r: { p: value.source, f: value.flags } };\n for (const [k, ctor] of Object.entries(typedArrayConstructors)) {\n if (isTypedArray(value, ctor))\n return { ta: { b: typedArrayToBase64(value), k } };\n }\n const id = visitorInfo.visited.get(value);\n if (id)\n return { ref: id };\n if (Array.isArray(value)) {\n const a = [];\n const id2 = ++visitorInfo.lastId;\n visitorInfo.visited.set(value, id2);\n for (let i = 0; i < value.length; ++i)\n a.push(serialize(value[i], handleSerializer, visitorInfo));\n return { a, id: id2 };\n }\n if (typeof value === \"object\") {\n const o = [];\n const id2 = ++visitorInfo.lastId;\n visitorInfo.visited.set(value, id2);\n for (const name of Object.keys(value)) {\n let item;\n try {\n item = value[name];\n } catch (e) {\n continue;\n }\n if (name === \"toJSON\" && typeof item === \"function\")\n o.push({ k: name, v: { o: [], id: 0 } });\n else\n o.push({ k: name, v: serialize(item, handleSerializer, visitorInfo) });\n }\n let jsonWrapper;\n try {\n if (o.length === 0 && value.toJSON && typeof value.toJSON === \"function\")\n jsonWrapper = { value: value.toJSON() };\n } catch (e) {\n }\n if (jsonWrapper)\n return innerSerialize(jsonWrapper.value, handleSerializer, visitorInfo);\n return { o, id: id2 };\n }\n}\n\n// packages/injected/src/bindingsController.ts\nvar BindingsController = class {\n // eslint-disable-next-line no-restricted-globals\n constructor(global, globalBindingName) {\n this._bindings = /* @__PURE__ */ new Map();\n this._global = global;\n this._globalBindingName = globalBindingName;\n }\n addBinding(bindingName, needsHandle) {\n const data = {\n callbacks: /* @__PURE__ */ new Map(),\n lastSeq: 0,\n handles: /* @__PURE__ */ new Map(),\n removed: false\n };\n this._bindings.set(bindingName, data);\n this._global[bindingName] = (...args) => {\n if (data.removed)\n throw new Error(`binding \"${bindingName}\" has been removed`);\n if (needsHandle && args.slice(1).some((arg) => arg !== void 0))\n throw new Error(`exposeBindingHandle supports a single argument, ${args.length} received`);\n const seq = ++data.lastSeq;\n const promise = new Promise((resolve, reject) => data.callbacks.set(seq, { resolve, reject }));\n let payload;\n if (needsHandle) {\n data.handles.set(seq, args[0]);\n payload = { name: bindingName, seq };\n } else {\n const serializedArgs = [];\n for (let i = 0; i < args.length; i++) {\n serializedArgs[i] = serializeAsCallArgument(args[i], (v) => {\n return { fallThrough: v };\n });\n }\n payload = { name: bindingName, seq, serializedArgs };\n }\n this._global[this._globalBindingName](JSON.stringify(payload));\n return promise;\n };\n }\n removeBinding(bindingName) {\n const data = this._bindings.get(bindingName);\n if (data)\n data.removed = true;\n this._bindings.delete(bindingName);\n delete this._global[bindingName];\n }\n takeBindingHandle(arg) {\n const handles = this._bindings.get(arg.name).handles;\n const handle = handles.get(arg.seq);\n handles.delete(arg.seq);\n return handle;\n }\n deliverBindingResult(arg) {\n const callbacks = this._bindings.get(arg.name).callbacks;\n if (\"error\" in arg)\n callbacks.get(arg.seq).reject(arg.error);\n else\n callbacks.get(arg.seq).resolve(arg.result);\n callbacks.delete(arg.seq);\n }\n};\n";
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.source = void 0;
|
|
7
|
+
const source = exports.source = "\nvar __commonJS = obj => {\n let required = false;\n let result;\n return function __require() {\n if (!required) {\n required = true;\n let fn;\n for (const name in obj) { fn = obj[name]; break; }\n const module = { exports: {} };\n fn(module.exports, module);\n result = module.exports;\n }\n return result;\n }\n};\nvar __export = (target, all) => {for (var name in all) target[name] = all[name];};\nvar __toESM = mod => ({ ...mod, 'default': mod });\nvar __toCommonJS = mod => ({ ...mod, __esModule: true });\n\n\n// packages/injected/src/storageScript.ts\nvar storageScript_exports = {};\n__export(storageScript_exports, {\n StorageScript: () => StorageScript\n});\nmodule.exports = __toCommonJS(storageScript_exports);\n\n// packages/playwright-core/src/utils/isomorphic/utilityScriptSerializers.ts\nfunction isRegExp(obj) {\n try {\n return obj instanceof RegExp || Object.prototype.toString.call(obj) === \"[object RegExp]\";\n } catch (error) {\n return false;\n }\n}\nfunction isDate(obj) {\n try {\n return obj instanceof Date || Object.prototype.toString.call(obj) === \"[object Date]\";\n } catch (error) {\n return false;\n }\n}\nfunction isURL(obj) {\n try {\n return obj instanceof URL || Object.prototype.toString.call(obj) === \"[object URL]\";\n } catch (error) {\n return false;\n }\n}\nfunction isError(obj) {\n var _a;\n try {\n return obj instanceof Error || obj && ((_a = Object.getPrototypeOf(obj)) == null ? void 0 : _a.name) === \"Error\";\n } catch (error) {\n return false;\n }\n}\nfunction isTypedArray(obj, constructor) {\n try {\n return obj instanceof constructor || Object.prototype.toString.call(obj) === `[object ${constructor.name}]`;\n } catch (error) {\n return false;\n }\n}\nvar typedArrayConstructors = {\n i8: Int8Array,\n ui8: Uint8Array,\n ui8c: Uint8ClampedArray,\n i16: Int16Array,\n ui16: Uint16Array,\n i32: Int32Array,\n ui32: Uint32Array,\n // TODO: add Float16Array once it's in baseline\n f32: Float32Array,\n f64: Float64Array,\n bi64: BigInt64Array,\n bui64: BigUint64Array\n};\nfunction typedArrayToBase64(array) {\n if (\"toBase64\" in array)\n return array.toBase64();\n const binary = Array.from(new Uint8Array(array.buffer, array.byteOffset, array.byteLength)).map((b) => String.fromCharCode(b)).join(\"\");\n return btoa(binary);\n}\nfunction base64ToTypedArray(base64, TypedArrayConstructor) {\n const binary = atob(base64);\n const bytes = new Uint8Array(binary.length);\n for (let i = 0; i < binary.length; i++)\n bytes[i] = binary.charCodeAt(i);\n return new TypedArrayConstructor(bytes.buffer);\n}\nfunction parseEvaluationResultValue(value, handles = [], refs = /* @__PURE__ */ new Map()) {\n if (Object.is(value, void 0))\n return void 0;\n if (typeof value === \"object\" && value) {\n if (\"ref\" in value)\n return refs.get(value.ref);\n if (\"v\" in value) {\n if (value.v === \"undefined\")\n return void 0;\n if (value.v === \"null\")\n return null;\n if (value.v === \"NaN\")\n return NaN;\n if (value.v === \"Infinity\")\n return Infinity;\n if (value.v === \"-Infinity\")\n return -Infinity;\n if (value.v === \"-0\")\n return -0;\n return void 0;\n }\n if (\"d\" in value) {\n return new Date(value.d);\n }\n if (\"u\" in value)\n return new URL(value.u);\n if (\"bi\" in value)\n return BigInt(value.bi);\n if (\"e\" in value) {\n const error = new Error(value.e.m);\n error.name = value.e.n;\n error.stack = value.e.s;\n return error;\n }\n if (\"r\" in value)\n return new RegExp(value.r.p, value.r.f);\n if (\"a\" in value) {\n const result = [];\n refs.set(value.id, result);\n for (const a of value.a)\n result.push(parseEvaluationResultValue(a, handles, refs));\n return result;\n }\n if (\"o\" in value) {\n const result = {};\n refs.set(value.id, result);\n for (const { k, v } of value.o) {\n if (k === \"__proto__\")\n continue;\n result[k] = parseEvaluationResultValue(v, handles, refs);\n }\n return result;\n }\n if (\"h\" in value)\n return handles[value.h];\n if (\"ta\" in value)\n return base64ToTypedArray(value.ta.b, typedArrayConstructors[value.ta.k]);\n }\n return value;\n}\nfunction serializeAsCallArgument(value, handleSerializer) {\n return serialize(value, handleSerializer, { visited: /* @__PURE__ */ new Map(), lastId: 0 });\n}\nfunction serialize(value, handleSerializer, visitorInfo) {\n if (value && typeof value === \"object\") {\n if (typeof globalThis.Window === \"function\" && value instanceof globalThis.Window)\n return \"ref: <Window>\";\n if (typeof globalThis.Document === \"function\" && value instanceof globalThis.Document)\n return \"ref: <Document>\";\n if (typeof globalThis.Node === \"function\" && value instanceof globalThis.Node)\n return \"ref: <Node>\";\n }\n return innerSerialize(value, handleSerializer, visitorInfo);\n}\nfunction innerSerialize(value, handleSerializer, visitorInfo) {\n var _a;\n const result = handleSerializer(value);\n if (\"fallThrough\" in result)\n value = result.fallThrough;\n else\n return result;\n if (typeof value === \"symbol\")\n return { v: \"undefined\" };\n if (Object.is(value, void 0))\n return { v: \"undefined\" };\n if (Object.is(value, null))\n return { v: \"null\" };\n if (Object.is(value, NaN))\n return { v: \"NaN\" };\n if (Object.is(value, Infinity))\n return { v: \"Infinity\" };\n if (Object.is(value, -Infinity))\n return { v: \"-Infinity\" };\n if (Object.is(value, -0))\n return { v: \"-0\" };\n if (typeof value === \"boolean\")\n return value;\n if (typeof value === \"number\")\n return value;\n if (typeof value === \"string\")\n return value;\n if (typeof value === \"bigint\")\n return { bi: value.toString() };\n if (isError(value)) {\n let stack;\n if ((_a = value.stack) == null ? void 0 : _a.startsWith(value.name + \": \" + value.message)) {\n stack = value.stack;\n } else {\n stack = `${value.name}: ${value.message}\n${value.stack}`;\n }\n return { e: { n: value.name, m: value.message, s: stack } };\n }\n if (isDate(value))\n return { d: value.toJSON() };\n if (isURL(value))\n return { u: value.toJSON() };\n if (isRegExp(value))\n return { r: { p: value.source, f: value.flags } };\n for (const [k, ctor] of Object.entries(typedArrayConstructors)) {\n if (isTypedArray(value, ctor))\n return { ta: { b: typedArrayToBase64(value), k } };\n }\n const id = visitorInfo.visited.get(value);\n if (id)\n return { ref: id };\n if (Array.isArray(value)) {\n const a = [];\n const id2 = ++visitorInfo.lastId;\n visitorInfo.visited.set(value, id2);\n for (let i = 0; i < value.length; ++i)\n a.push(serialize(value[i], handleSerializer, visitorInfo));\n return { a, id: id2 };\n }\n if (typeof value === \"object\") {\n const o = [];\n const id2 = ++visitorInfo.lastId;\n visitorInfo.visited.set(value, id2);\n for (const name of Object.keys(value)) {\n let item;\n try {\n item = value[name];\n } catch (e) {\n continue;\n }\n if (name === \"toJSON\" && typeof item === \"function\")\n o.push({ k: name, v: { o: [], id: 0 } });\n else\n o.push({ k: name, v: serialize(item, handleSerializer, visitorInfo) });\n }\n let jsonWrapper;\n try {\n if (o.length === 0 && value.toJSON && typeof value.toJSON === \"function\")\n jsonWrapper = { value: value.toJSON() };\n } catch (e) {\n }\n if (jsonWrapper)\n return innerSerialize(jsonWrapper.value, handleSerializer, visitorInfo);\n return { o, id: id2 };\n }\n}\n\n// packages/injected/src/storageScript.ts\nvar StorageScript = class {\n constructor(isFirefox) {\n this._isFirefox = isFirefox;\n this._global = globalThis;\n }\n _idbRequestToPromise(request) {\n return new Promise((resolve, reject) => {\n request.addEventListener(\"success\", () => resolve(request.result));\n request.addEventListener(\"error\", () => reject(request.error));\n });\n }\n _isPlainObject(v) {\n const ctor = v == null ? void 0 : v.constructor;\n if (this._isFirefox) {\n const constructorImpl = ctor == null ? void 0 : ctor.toString();\n if ((constructorImpl == null ? void 0 : constructorImpl.startsWith(\"function Object() {\")) && (constructorImpl == null ? void 0 : constructorImpl.includes(\"[native code]\")))\n return true;\n }\n return ctor === Object;\n }\n _trySerialize(value) {\n let trivial = true;\n const encoded = serializeAsCallArgument(value, (v) => {\n const isTrivial = this._isPlainObject(v) || Array.isArray(v) || typeof v === \"string\" || typeof v === \"number\" || typeof v === \"boolean\" || Object.is(v, null);\n if (!isTrivial)\n trivial = false;\n return { fallThrough: v };\n });\n if (trivial)\n return { trivial: value };\n return { encoded };\n }\n async _collectDB(dbInfo) {\n if (!dbInfo.name)\n throw new Error(\"Database name is empty\");\n if (!dbInfo.version)\n throw new Error(\"Database version is unset\");\n const db = await this._idbRequestToPromise(indexedDB.open(dbInfo.name));\n if (db.objectStoreNames.length === 0)\n return { name: dbInfo.name, version: dbInfo.version, stores: [] };\n const transaction = db.transaction(db.objectStoreNames, \"readonly\");\n const stores = await Promise.all([...db.objectStoreNames].map(async (storeName) => {\n const objectStore = transaction.objectStore(storeName);\n const keys = await this._idbRequestToPromise(objectStore.getAllKeys());\n const records = await Promise.all(keys.map(async (key) => {\n const record = {};\n if (objectStore.keyPath === null) {\n const { encoded: encoded2, trivial: trivial2 } = this._trySerialize(key);\n if (trivial2)\n record.key = trivial2;\n else\n record.keyEncoded = encoded2;\n }\n const value = await this._idbRequestToPromise(objectStore.get(key));\n const { encoded, trivial } = this._trySerialize(value);\n if (trivial)\n record.value = trivial;\n else\n record.valueEncoded = encoded;\n return record;\n }));\n const indexes = [...objectStore.indexNames].map((indexName) => {\n const index = objectStore.index(indexName);\n return {\n name: index.name,\n keyPath: typeof index.keyPath === \"string\" ? index.keyPath : void 0,\n keyPathArray: Array.isArray(index.keyPath) ? index.keyPath : void 0,\n multiEntry: index.multiEntry,\n unique: index.unique\n };\n });\n return {\n name: storeName,\n records,\n indexes,\n autoIncrement: objectStore.autoIncrement,\n keyPath: typeof objectStore.keyPath === \"string\" ? objectStore.keyPath : void 0,\n keyPathArray: Array.isArray(objectStore.keyPath) ? objectStore.keyPath : void 0\n };\n }));\n return {\n name: dbInfo.name,\n version: dbInfo.version,\n stores\n };\n }\n async collect(recordIndexedDB) {\n const localStorage = Object.keys(this._global.localStorage).map((name) => ({ name, value: this._global.localStorage.getItem(name) }));\n if (!recordIndexedDB)\n return { localStorage };\n try {\n const databases = await this._global.indexedDB.databases();\n const indexedDB2 = await Promise.all(databases.map((db) => this._collectDB(db)));\n return { localStorage, indexedDB: indexedDB2 };\n } catch (e) {\n throw new Error(\"Unable to serialize IndexedDB: \" + e.message);\n }\n }\n async _restoreDB(dbInfo) {\n const openRequest = this._global.indexedDB.open(dbInfo.name, dbInfo.version);\n openRequest.addEventListener(\"upgradeneeded\", () => {\n var _a, _b;\n const db2 = openRequest.result;\n for (const store of dbInfo.stores) {\n const objectStore = db2.createObjectStore(store.name, { autoIncrement: store.autoIncrement, keyPath: (_a = store.keyPathArray) != null ? _a : store.keyPath });\n for (const index of store.indexes)\n objectStore.createIndex(index.name, (_b = index.keyPathArray) != null ? _b : index.keyPath, { unique: index.unique, multiEntry: index.multiEntry });\n }\n });\n const db = await this._idbRequestToPromise(openRequest);\n if (db.objectStoreNames.length === 0)\n return;\n const transaction = db.transaction(db.objectStoreNames, \"readwrite\");\n await Promise.all(dbInfo.stores.map(async (store) => {\n const objectStore = transaction.objectStore(store.name);\n await Promise.all(store.records.map(async (record) => {\n var _a, _b;\n await this._idbRequestToPromise(\n objectStore.add(\n (_a = record.value) != null ? _a : parseEvaluationResultValue(record.valueEncoded),\n (_b = record.key) != null ? _b : parseEvaluationResultValue(record.keyEncoded)\n )\n );\n }));\n }));\n }\n async restore(originState) {\n var _a;\n try {\n await Promise.all(((_a = originState.indexedDB) != null ? _a : []).map((dbInfo) => this._restoreDB(dbInfo)));\n } catch (e) {\n throw new Error(\"Unable to restore IndexedDB: \" + e.message);\n }\n for (const { name, value } of originState.localStorage || [])\n this._global.localStorage.setItem(name, value);\n }\n};\n";
|
|
@@ -7,6 +7,8 @@ exports.HarRecorder = void 0;
|
|
|
7
7
|
var _fs = _interopRequireDefault(require("fs"));
|
|
8
8
|
var _path = _interopRequireDefault(require("path"));
|
|
9
9
|
var _artifact = require("../artifact");
|
|
10
|
+
var _fileUtils = require("../../utils/fileUtils");
|
|
11
|
+
var _secretsFilter = require("../../checkly/secretsFilter");
|
|
10
12
|
var _harTracer = require("./harTracer");
|
|
11
13
|
var _zipBundle = require("../../zipBundle");
|
|
12
14
|
var _manualPromise = require("../../utils/manualPromise");
|
|
@@ -48,7 +50,7 @@ class HarRecorder {
|
|
|
48
50
|
waitForContentOnStop: true,
|
|
49
51
|
urlFilter: urlFilterRe !== null && urlFilterRe !== void 0 ? urlFilterRe : options.urlGlob
|
|
50
52
|
});
|
|
51
|
-
this._zipFile = content === 'attach' || expectsZip ? new _zipBundle.yazl.ZipFile() : null;
|
|
53
|
+
this._zipFile = content === 'attach' || expectsZip ? new (new _fileUtils.SecretSerializedFS((0, _secretsFilter.secretsFilter)()).createScrubbingZipFile(_zipBundle.yazl.ZipFile))() : null;
|
|
52
54
|
this._tracer.start({
|
|
53
55
|
omitScripts: false
|
|
54
56
|
});
|
|
@@ -45,7 +45,7 @@ const kScreencastOptions = {
|
|
|
45
45
|
class Tracing extends _instrumentation.SdkObject {
|
|
46
46
|
constructor(context, tracesDir) {
|
|
47
47
|
super(context, 'tracing');
|
|
48
|
-
this._fs =
|
|
48
|
+
this._fs = void 0;
|
|
49
49
|
this._snapshotter = void 0;
|
|
50
50
|
this._harTracer = void 0;
|
|
51
51
|
this._screencastListeners = [];
|
|
@@ -59,10 +59,10 @@ class Tracing extends _instrumentation.SdkObject {
|
|
|
59
59
|
this._allResources = new Set();
|
|
60
60
|
this._contextCreatedEvent = void 0;
|
|
61
61
|
this._pendingHarEntries = new Set();
|
|
62
|
-
this._secretsFilter = void 0;
|
|
63
62
|
this._context = context;
|
|
64
63
|
this._precreatedTracesDir = tracesDir;
|
|
65
|
-
|
|
64
|
+
// [Checkly] We use SecretSerializedFS to handle secret scrubbing before writing to files.
|
|
65
|
+
this._fs = new _utils.SecretSerializedFS((0, _secretsFilter.secretsFilter)());
|
|
66
66
|
this._harTracer = new _harTracer.HarTracer(context, null, this, {
|
|
67
67
|
content: 'attach',
|
|
68
68
|
includeTraceInfo: true,
|
|
@@ -333,7 +333,7 @@ class Tracing extends _instrumentation.SdkObject {
|
|
|
333
333
|
type: 'resource-snapshot',
|
|
334
334
|
snapshot: entry
|
|
335
335
|
};
|
|
336
|
-
const visited = visitTraceEvent(event, this._state.networkSha1s
|
|
336
|
+
const visited = visitTraceEvent(event, this._state.networkSha1s);
|
|
337
337
|
this._fs.appendFile(this._state.networkFile, JSON.stringify(visited) + '\n', true /* flush */);
|
|
338
338
|
}
|
|
339
339
|
flushHarEntries() {
|
|
@@ -343,7 +343,7 @@ class Tracing extends _instrumentation.SdkObject {
|
|
|
343
343
|
type: 'resource-snapshot',
|
|
344
344
|
snapshot: entry
|
|
345
345
|
};
|
|
346
|
-
const visited = visitTraceEvent(event, this._state.networkSha1s
|
|
346
|
+
const visited = visitTraceEvent(event, this._state.networkSha1s);
|
|
347
347
|
harLines.push(JSON.stringify(visited));
|
|
348
348
|
}
|
|
349
349
|
this._pendingHarEntries.clear();
|
|
@@ -466,7 +466,7 @@ class Tracing extends _instrumentation.SdkObject {
|
|
|
466
466
|
}));
|
|
467
467
|
}
|
|
468
468
|
_appendTraceEvent(event) {
|
|
469
|
-
const visited = visitTraceEvent(event, this._state.traceSha1s
|
|
469
|
+
const visited = visitTraceEvent(event, this._state.traceSha1s);
|
|
470
470
|
// Do not flush (console) events, they are too noisy, unless we are in ui mode (live).
|
|
471
471
|
const flush = this._state.options.live || event.type !== 'event' && event.type !== 'console' && event.type !== 'log';
|
|
472
472
|
this._fs.appendFile(this._state.traceFile, JSON.stringify(visited) + '\n', flush);
|
|
@@ -479,13 +479,8 @@ class Tracing extends _instrumentation.SdkObject {
|
|
|
479
479
|
}
|
|
480
480
|
}
|
|
481
481
|
exports.Tracing = Tracing;
|
|
482
|
-
function visitTraceEvent(object, sha1s
|
|
483
|
-
if (Array.isArray(object)) return object.map(o =>
|
|
484
|
-
if (typeof o === 'string' && new Date(o).toString() === 'Invalid Date') {
|
|
485
|
-
return secretsFilter(o);
|
|
486
|
-
}
|
|
487
|
-
return visitTraceEvent(o, sha1s, secretsFilter);
|
|
488
|
-
});
|
|
482
|
+
function visitTraceEvent(object, sha1s) {
|
|
483
|
+
if (Array.isArray(object)) return object.map(o => visitTraceEvent(o, sha1s));
|
|
489
484
|
if (object instanceof _dispatcher.Dispatcher) return `<${object._type}>`;
|
|
490
485
|
if (object instanceof Buffer) return `<Buffer>`;
|
|
491
486
|
if (object instanceof Date) return object;
|
|
@@ -496,13 +491,7 @@ function visitTraceEvent(object, sha1s, secretsFilter) {
|
|
|
496
491
|
if (key === 'sha1' || key === '_sha1' || key.endsWith('Sha1')) {
|
|
497
492
|
if (value) sha1s.add(value);
|
|
498
493
|
}
|
|
499
|
-
|
|
500
|
-
// Some values like numbers or certain strings shouldn't be scrubbed,
|
|
501
|
-
// Otherwise parts of the trace will be unreadable.
|
|
502
|
-
result[key] = key.endsWith('Sha1') || ['pageref', '_sha1', 'downloadsPath', 'tracesDir', 'pageId', 'sha1'].includes(key) ? value : secretsFilter(value);
|
|
503
|
-
} else {
|
|
504
|
-
result[key] = visitTraceEvent(value, sha1s, secretsFilter);
|
|
505
|
-
}
|
|
494
|
+
result[key] = visitTraceEvent(value, sha1s);
|
|
506
495
|
}
|
|
507
496
|
return result;
|
|
508
497
|
}
|
package/lib/utils/fileUtils.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
|
-
exports.SerializedFS = void 0;
|
|
6
|
+
exports.SerializedFS = exports.SecretSerializedFS = void 0;
|
|
7
7
|
exports.canAccessFile = canAccessFile;
|
|
8
8
|
exports.copyFileAndMakeWritable = copyFileAndMakeWritable;
|
|
9
9
|
exports.fileUploadSizeLimit = exports.existsAsync = void 0;
|
|
@@ -202,4 +202,67 @@ class SerializedFS {
|
|
|
202
202
|
}
|
|
203
203
|
}
|
|
204
204
|
}
|
|
205
|
-
|
|
205
|
+
|
|
206
|
+
// [Checkly] SecretSerializedFS extends SerializedFS to apply secret scrubbing to all file writes
|
|
207
|
+
exports.SerializedFS = SerializedFS;
|
|
208
|
+
class SecretSerializedFS extends SerializedFS {
|
|
209
|
+
constructor(secretsFilter) {
|
|
210
|
+
super();
|
|
211
|
+
this._secretsFilter = void 0;
|
|
212
|
+
this._secretsFilter = secretsFilter;
|
|
213
|
+
}
|
|
214
|
+
writeFile(file, content, skipIfExists) {
|
|
215
|
+
const scrubbedContent = this._scrubContent(content);
|
|
216
|
+
super.writeFile(file, scrubbedContent, skipIfExists);
|
|
217
|
+
}
|
|
218
|
+
appendFile(file, text, flush) {
|
|
219
|
+
const scrubbedText = this._scrubContent(text);
|
|
220
|
+
super.appendFile(file, scrubbedText, flush);
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
// [Checkly] Create a scrubbing-enabled zip file wrapper
|
|
224
|
+
createScrubbingZipFile(ZipFileClass) {
|
|
225
|
+
const scrubContent = this._scrubContent.bind(this);
|
|
226
|
+
return class ScrubbingZipFile extends ZipFileClass {
|
|
227
|
+
addBuffer(buffer, metadataPath) {
|
|
228
|
+
const scrubbedBuffer = scrubContent(buffer);
|
|
229
|
+
super.addBuffer(scrubbedBuffer, metadataPath);
|
|
230
|
+
}
|
|
231
|
+
};
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
// [Checkly] Apply secret scrubbing to any content being written
|
|
235
|
+
_scrubContent(content) {
|
|
236
|
+
if (Buffer.isBuffer(content)) {
|
|
237
|
+
// Handle buffer content - only scrub if it looks like text
|
|
238
|
+
try {
|
|
239
|
+
const text = content.toString('utf8');
|
|
240
|
+
if (this._isLikelyTextContent(text)) {
|
|
241
|
+
const scrubbedText = this._secretsFilter(text);
|
|
242
|
+
return Buffer.from(scrubbedText, 'utf8');
|
|
243
|
+
}
|
|
244
|
+
return content; // Return original buffer for non-text content
|
|
245
|
+
} catch {
|
|
246
|
+
return content; // Return original if can't decode as UTF-8
|
|
247
|
+
}
|
|
248
|
+
} else {
|
|
249
|
+
// Handle string content
|
|
250
|
+
return this._secretsFilter(content);
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
// [Checkly] Check if content looks like text that could contain secrets
|
|
255
|
+
_isLikelyTextContent(text) {
|
|
256
|
+
if (text.length === 0) return false;
|
|
257
|
+
|
|
258
|
+
// Check if the string contains mostly printable characters, but only sample the first 1000 chars
|
|
259
|
+
const sampleSize = Math.min(1000, text.length);
|
|
260
|
+
let printableCount = 0;
|
|
261
|
+
for (let i = 0; i < sampleSize; i++) {
|
|
262
|
+
const code = text.charCodeAt(i);
|
|
263
|
+
if (code >= 32 && code <= 126 || code === 9 || code === 10 || code === 13) printableCount++;
|
|
264
|
+
}
|
|
265
|
+
return printableCount / sampleSize > 0.8;
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
exports.SecretSerializedFS = SecretSerializedFS;
|