@opensteer/browser-core 0.7.0 → 0.7.2
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.cjs +285 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +45 -1
- package/dist/index.d.ts +45 -1
- package/dist/index.js +277 -1
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -2843,7 +2843,287 @@ function sleep(ms) {
|
|
|
2843
2843
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
2844
2844
|
}
|
|
2845
2845
|
|
|
2846
|
+
// src/post-load-tracker.ts
|
|
2847
|
+
var DEFAULT_POST_LOAD_TRACKER_QUIET_WINDOW_MS = 400;
|
|
2848
|
+
var DEFAULT_ACTION_BOUNDARY_POLL_INTERVAL_MS = 100;
|
|
2849
|
+
function isRecord(value) {
|
|
2850
|
+
return typeof value === "object" && value !== null;
|
|
2851
|
+
}
|
|
2852
|
+
function readFiniteNumber(value) {
|
|
2853
|
+
return typeof value === "number" && Number.isFinite(value) ? value : void 0;
|
|
2854
|
+
}
|
|
2855
|
+
function readNonNegativeNumber(value) {
|
|
2856
|
+
const parsed = readFiniteNumber(value);
|
|
2857
|
+
return parsed === void 0 || parsed < 0 ? 0 : parsed;
|
|
2858
|
+
}
|
|
2859
|
+
function normalizePostLoadTrackerState(value) {
|
|
2860
|
+
if (!isRecord(value)) {
|
|
2861
|
+
return void 0;
|
|
2862
|
+
}
|
|
2863
|
+
const installedAt = readFiniteNumber(value.installedAt);
|
|
2864
|
+
const lastMutationAt = readFiniteNumber(value.lastMutationAt);
|
|
2865
|
+
const lastNetworkActivityAt = readFiniteNumber(value.lastNetworkActivityAt);
|
|
2866
|
+
const now = readFiniteNumber(value.now);
|
|
2867
|
+
const readyState = typeof value.readyState === "string" ? value.readyState : void 0;
|
|
2868
|
+
if (installedAt === void 0 || lastMutationAt === void 0 || lastNetworkActivityAt === void 0 || now === void 0 || readyState === void 0) {
|
|
2869
|
+
return void 0;
|
|
2870
|
+
}
|
|
2871
|
+
return {
|
|
2872
|
+
installedAt,
|
|
2873
|
+
lastMutationAt,
|
|
2874
|
+
lastNetworkActivityAt,
|
|
2875
|
+
now,
|
|
2876
|
+
pendingFetches: readNonNegativeNumber(value.pendingFetches),
|
|
2877
|
+
pendingTimeouts: readNonNegativeNumber(value.pendingTimeouts),
|
|
2878
|
+
pendingXhrs: readNonNegativeNumber(value.pendingXhrs),
|
|
2879
|
+
readyState
|
|
2880
|
+
};
|
|
2881
|
+
}
|
|
2882
|
+
function buildPostLoadTrackerInstallScript() {
|
|
2883
|
+
return `(() => {
|
|
2884
|
+
const globalObject = globalThis;
|
|
2885
|
+
if (globalObject.__opensteerActionBoundaryTrackerInstalled) {
|
|
2886
|
+
return true;
|
|
2887
|
+
}
|
|
2888
|
+
|
|
2889
|
+
const tracker = {
|
|
2890
|
+
installedAt: performance.now(),
|
|
2891
|
+
lastMutationAt: performance.now(),
|
|
2892
|
+
lastNetworkActivityAt: performance.now(),
|
|
2893
|
+
pendingFetches: 0,
|
|
2894
|
+
pendingTimeouts: 0,
|
|
2895
|
+
pendingXhrs: 0,
|
|
2896
|
+
readyState: document.readyState,
|
|
2897
|
+
timeoutIds: new Set(),
|
|
2898
|
+
};
|
|
2899
|
+
globalObject.__opensteerActionBoundaryTrackerInstalled = true;
|
|
2900
|
+
globalObject.__opensteerActionBoundaryTracker = tracker;
|
|
2901
|
+
|
|
2902
|
+
const markMutation = () => {
|
|
2903
|
+
tracker.lastMutationAt = performance.now();
|
|
2904
|
+
tracker.readyState = document.readyState;
|
|
2905
|
+
};
|
|
2906
|
+
const markNetwork = () => {
|
|
2907
|
+
tracker.lastNetworkActivityAt = performance.now();
|
|
2908
|
+
tracker.readyState = document.readyState;
|
|
2909
|
+
};
|
|
2910
|
+
|
|
2911
|
+
const startObserver = () => {
|
|
2912
|
+
const target = document.documentElement ?? document;
|
|
2913
|
+
if (!(target instanceof Node)) {
|
|
2914
|
+
return;
|
|
2915
|
+
}
|
|
2916
|
+
const observer = new MutationObserver(markMutation);
|
|
2917
|
+
observer.observe(target, {
|
|
2918
|
+
subtree: true,
|
|
2919
|
+
childList: true,
|
|
2920
|
+
characterData: true,
|
|
2921
|
+
attributes: true,
|
|
2922
|
+
});
|
|
2923
|
+
markMutation();
|
|
2924
|
+
};
|
|
2925
|
+
|
|
2926
|
+
if (document.documentElement) {
|
|
2927
|
+
startObserver();
|
|
2928
|
+
} else {
|
|
2929
|
+
document.addEventListener("DOMContentLoaded", startObserver, { once: true });
|
|
2930
|
+
}
|
|
2931
|
+
|
|
2932
|
+
document.addEventListener("readystatechange", markMutation);
|
|
2933
|
+
addEventListener("load", markMutation, { once: true });
|
|
2934
|
+
|
|
2935
|
+
const nativeSetTimeout = globalObject.setTimeout.bind(globalObject);
|
|
2936
|
+
const nativeClearTimeout = globalObject.clearTimeout.bind(globalObject);
|
|
2937
|
+
globalObject.setTimeout = function(callback, delay, ...args) {
|
|
2938
|
+
tracker.pendingTimeouts += 1;
|
|
2939
|
+
markNetwork();
|
|
2940
|
+
let handle;
|
|
2941
|
+
const wrapped =
|
|
2942
|
+
typeof callback === "function"
|
|
2943
|
+
? (...callbackArgs) => {
|
|
2944
|
+
if (tracker.timeoutIds.delete(handle)) {
|
|
2945
|
+
tracker.pendingTimeouts = Math.max(0, tracker.pendingTimeouts - 1);
|
|
2946
|
+
}
|
|
2947
|
+
try {
|
|
2948
|
+
return callback(...callbackArgs);
|
|
2949
|
+
} finally {
|
|
2950
|
+
markMutation();
|
|
2951
|
+
}
|
|
2952
|
+
}
|
|
2953
|
+
: callback;
|
|
2954
|
+
handle = nativeSetTimeout(wrapped, delay, ...args);
|
|
2955
|
+
tracker.timeoutIds.add(handle);
|
|
2956
|
+
return handle;
|
|
2957
|
+
};
|
|
2958
|
+
globalObject.clearTimeout = function(handle) {
|
|
2959
|
+
if (tracker.timeoutIds.delete(handle)) {
|
|
2960
|
+
tracker.pendingTimeouts = Math.max(0, tracker.pendingTimeouts - 1);
|
|
2961
|
+
}
|
|
2962
|
+
return nativeClearTimeout(handle);
|
|
2963
|
+
};
|
|
2964
|
+
|
|
2965
|
+
if (typeof globalObject.fetch === "function") {
|
|
2966
|
+
const nativeFetch = globalObject.fetch.bind(globalObject);
|
|
2967
|
+
globalObject.fetch = (...args) => {
|
|
2968
|
+
tracker.pendingFetches += 1;
|
|
2969
|
+
markNetwork();
|
|
2970
|
+
return nativeFetch(...args)
|
|
2971
|
+
.finally(() => {
|
|
2972
|
+
tracker.pendingFetches = Math.max(0, tracker.pendingFetches - 1);
|
|
2973
|
+
markNetwork();
|
|
2974
|
+
});
|
|
2975
|
+
};
|
|
2976
|
+
}
|
|
2977
|
+
|
|
2978
|
+
if (typeof globalObject.XMLHttpRequest === "function") {
|
|
2979
|
+
const NativeXMLHttpRequest = globalObject.XMLHttpRequest;
|
|
2980
|
+
const nativeSend = NativeXMLHttpRequest.prototype.send;
|
|
2981
|
+
NativeXMLHttpRequest.prototype.send = function(...args) {
|
|
2982
|
+
tracker.pendingXhrs += 1;
|
|
2983
|
+
markNetwork();
|
|
2984
|
+
const finalize = () => {
|
|
2985
|
+
this.removeEventListener("loadend", finalize);
|
|
2986
|
+
tracker.pendingXhrs = Math.max(0, tracker.pendingXhrs - 1);
|
|
2987
|
+
markNetwork();
|
|
2988
|
+
};
|
|
2989
|
+
this.addEventListener("loadend", finalize, { once: true });
|
|
2990
|
+
return nativeSend.apply(this, args);
|
|
2991
|
+
};
|
|
2992
|
+
}
|
|
2993
|
+
|
|
2994
|
+
return true;
|
|
2995
|
+
})()`;
|
|
2996
|
+
}
|
|
2997
|
+
function buildPostLoadTrackerReadExpression() {
|
|
2998
|
+
return `(() => {
|
|
2999
|
+
const tracker = globalThis.__opensteerActionBoundaryTracker;
|
|
3000
|
+
if (!tracker) {
|
|
3001
|
+
return null;
|
|
3002
|
+
}
|
|
3003
|
+
|
|
3004
|
+
return {
|
|
3005
|
+
installedAt: Number(tracker.installedAt ?? 0),
|
|
3006
|
+
lastMutationAt: Number(tracker.lastMutationAt ?? 0),
|
|
3007
|
+
lastNetworkActivityAt: Number(tracker.lastNetworkActivityAt ?? 0),
|
|
3008
|
+
now: Number(performance.now()),
|
|
3009
|
+
pendingFetches: Number(tracker.pendingFetches ?? 0),
|
|
3010
|
+
pendingTimeouts: Number(tracker.pendingTimeouts ?? 0),
|
|
3011
|
+
pendingXhrs: Number(tracker.pendingXhrs ?? 0),
|
|
3012
|
+
readyState: String(document.readyState),
|
|
3013
|
+
};
|
|
3014
|
+
})()`;
|
|
3015
|
+
}
|
|
3016
|
+
function postLoadTrackerIsSettled(tracker, quietWindowMs = DEFAULT_POST_LOAD_TRACKER_QUIET_WINDOW_MS) {
|
|
3017
|
+
if (!tracker) {
|
|
3018
|
+
return false;
|
|
3019
|
+
}
|
|
3020
|
+
if (tracker.readyState !== "complete") {
|
|
3021
|
+
return false;
|
|
3022
|
+
}
|
|
3023
|
+
if (tracker.pendingFetches > 0 || tracker.pendingTimeouts > 0 || tracker.pendingXhrs > 0) {
|
|
3024
|
+
return false;
|
|
3025
|
+
}
|
|
3026
|
+
const lastActivityAt = Math.max(
|
|
3027
|
+
tracker.installedAt,
|
|
3028
|
+
tracker.lastMutationAt,
|
|
3029
|
+
tracker.lastNetworkActivityAt
|
|
3030
|
+
);
|
|
3031
|
+
return tracker.now - lastActivityAt >= quietWindowMs;
|
|
3032
|
+
}
|
|
3033
|
+
|
|
3034
|
+
// src/action-boundary.ts
|
|
3035
|
+
var CROSS_DOCUMENT_INTERACTION_TIMEOUT_MS = 3e4;
|
|
3036
|
+
var CROSS_DOCUMENT_DETECTION_WINDOW_MS = 500;
|
|
3037
|
+
async function waitForActionBoundary(input) {
|
|
3038
|
+
if (input.timeoutMs <= 0) {
|
|
3039
|
+
return {
|
|
3040
|
+
trigger: "dom-action",
|
|
3041
|
+
crossDocument: false,
|
|
3042
|
+
bootstrapSettled: false,
|
|
3043
|
+
timedOutPhase: "bootstrap"
|
|
3044
|
+
};
|
|
3045
|
+
}
|
|
3046
|
+
const deadline = Date.now() + input.timeoutMs;
|
|
3047
|
+
const crossDocumentDetectionDeadline = input.snapshot === void 0 ? void 0 : Math.min(deadline, Date.now() + CROSS_DOCUMENT_DETECTION_WINDOW_MS);
|
|
3048
|
+
const pollIntervalMs = input.pollIntervalMs ?? DEFAULT_ACTION_BOUNDARY_POLL_INTERVAL_MS;
|
|
3049
|
+
let trigger = "dom-action";
|
|
3050
|
+
let crossDocument = false;
|
|
3051
|
+
let waitedForNavigationContentLoaded = false;
|
|
3052
|
+
while (Date.now() < deadline) {
|
|
3053
|
+
input.throwBackgroundError();
|
|
3054
|
+
if (input.isPageClosed()) {
|
|
3055
|
+
return {
|
|
3056
|
+
trigger,
|
|
3057
|
+
crossDocument,
|
|
3058
|
+
bootstrapSettled: true
|
|
3059
|
+
};
|
|
3060
|
+
}
|
|
3061
|
+
if (input.signal?.aborted) {
|
|
3062
|
+
if (isTimeoutAbort(input.signal.reason) && Date.now() >= deadline) {
|
|
3063
|
+
return {
|
|
3064
|
+
trigger,
|
|
3065
|
+
crossDocument,
|
|
3066
|
+
bootstrapSettled: false,
|
|
3067
|
+
timedOutPhase: "bootstrap"
|
|
3068
|
+
};
|
|
3069
|
+
}
|
|
3070
|
+
throw abortError(input.signal);
|
|
3071
|
+
}
|
|
3072
|
+
const currentDocumentRef = input.getCurrentMainFrameDocumentRef();
|
|
3073
|
+
if (input.snapshot !== void 0 && currentDocumentRef !== void 0 && currentDocumentRef !== input.snapshot.documentRef) {
|
|
3074
|
+
trigger = "navigation";
|
|
3075
|
+
crossDocument = true;
|
|
3076
|
+
if (!waitedForNavigationContentLoaded) {
|
|
3077
|
+
waitedForNavigationContentLoaded = true;
|
|
3078
|
+
const remaining = Math.max(0, deadline - Date.now());
|
|
3079
|
+
if (remaining > 0) {
|
|
3080
|
+
await input.waitForNavigationContentLoaded(remaining);
|
|
3081
|
+
}
|
|
3082
|
+
}
|
|
3083
|
+
}
|
|
3084
|
+
if (!crossDocument && crossDocumentDetectionDeadline !== void 0 && Date.now() >= crossDocumentDetectionDeadline) {
|
|
3085
|
+
return {
|
|
3086
|
+
trigger,
|
|
3087
|
+
crossDocument,
|
|
3088
|
+
bootstrapSettled: true
|
|
3089
|
+
};
|
|
3090
|
+
}
|
|
3091
|
+
if (crossDocument && postLoadTrackerIsSettled(await input.readTrackerState())) {
|
|
3092
|
+
return {
|
|
3093
|
+
trigger,
|
|
3094
|
+
crossDocument,
|
|
3095
|
+
bootstrapSettled: true
|
|
3096
|
+
};
|
|
3097
|
+
}
|
|
3098
|
+
await delay(Math.min(pollIntervalMs, Math.max(0, deadline - Date.now())));
|
|
3099
|
+
}
|
|
3100
|
+
return {
|
|
3101
|
+
trigger,
|
|
3102
|
+
crossDocument,
|
|
3103
|
+
bootstrapSettled: false,
|
|
3104
|
+
timedOutPhase: "bootstrap"
|
|
3105
|
+
};
|
|
3106
|
+
}
|
|
3107
|
+
function abortError(signal) {
|
|
3108
|
+
return signal.reason ?? new DOMException("The operation was aborted", "AbortError");
|
|
3109
|
+
}
|
|
3110
|
+
async function delay(ms) {
|
|
3111
|
+
if (ms <= 0) {
|
|
3112
|
+
return;
|
|
3113
|
+
}
|
|
3114
|
+
await new Promise((resolve) => {
|
|
3115
|
+
setTimeout(resolve, ms);
|
|
3116
|
+
});
|
|
3117
|
+
}
|
|
3118
|
+
function isTimeoutAbort(reason) {
|
|
3119
|
+
return typeof reason === "object" && reason !== null && "code" in reason && reason.code === "timeout";
|
|
3120
|
+
}
|
|
3121
|
+
|
|
2846
3122
|
exports.BrowserCoreError = BrowserCoreError;
|
|
3123
|
+
exports.CROSS_DOCUMENT_DETECTION_WINDOW_MS = CROSS_DOCUMENT_DETECTION_WINDOW_MS;
|
|
3124
|
+
exports.CROSS_DOCUMENT_INTERACTION_TIMEOUT_MS = CROSS_DOCUMENT_INTERACTION_TIMEOUT_MS;
|
|
3125
|
+
exports.DEFAULT_ACTION_BOUNDARY_POLL_INTERVAL_MS = DEFAULT_ACTION_BOUNDARY_POLL_INTERVAL_MS;
|
|
3126
|
+
exports.DEFAULT_POST_LOAD_TRACKER_QUIET_WINDOW_MS = DEFAULT_POST_LOAD_TRACKER_QUIET_WINDOW_MS;
|
|
2847
3127
|
exports.DEFAULT_VISUAL_STABILITY_SETTLE_MS = DEFAULT_VISUAL_STABILITY_SETTLE_MS;
|
|
2848
3128
|
exports.DEFAULT_VISUAL_STABILITY_TIMEOUT_MS = DEFAULT_VISUAL_STABILITY_TIMEOUT_MS;
|
|
2849
3129
|
exports.DOM_SNAPSHOT_COMPUTED_STYLE_NAMES = DOM_SNAPSHOT_COMPUTED_STYLE_NAMES;
|
|
@@ -2853,6 +3133,8 @@ exports.bodyPayloadFromUtf8 = bodyPayloadFromUtf8;
|
|
|
2853
3133
|
exports.brand = brand;
|
|
2854
3134
|
exports.buildCdpShadowBoundaryIndex = buildCdpShadowBoundaryIndex;
|
|
2855
3135
|
exports.buildDomSnapshotFromCdpCapture = buildDomSnapshotFromCdpCapture;
|
|
3136
|
+
exports.buildPostLoadTrackerInstallScript = buildPostLoadTrackerInstallScript;
|
|
3137
|
+
exports.buildPostLoadTrackerReadExpression = buildPostLoadTrackerReadExpression;
|
|
2856
3138
|
exports.closedPageError = closedPageError;
|
|
2857
3139
|
exports.closedSessionError = closedSessionError;
|
|
2858
3140
|
exports.createBodyPayload = createBodyPayload;
|
|
@@ -2899,7 +3181,9 @@ exports.mergeBrowserCapabilities = mergeBrowserCapabilities;
|
|
|
2899
3181
|
exports.nextDocumentEpoch = nextDocumentEpoch;
|
|
2900
3182
|
exports.noBrowserCapabilities = noBrowserCapabilities;
|
|
2901
3183
|
exports.normalizeCdpShadowRootType = normalizeCdpShadowRootType;
|
|
3184
|
+
exports.normalizePostLoadTrackerState = normalizePostLoadTrackerState;
|
|
2902
3185
|
exports.parseCdpStringTable = parseCdpStringTable;
|
|
3186
|
+
exports.postLoadTrackerIsSettled = postLoadTrackerIsSettled;
|
|
2903
3187
|
exports.quadBounds = quadBounds;
|
|
2904
3188
|
exports.rareCdpIntegerValue = rareCdpIntegerValue;
|
|
2905
3189
|
exports.rareCdpStringValue = rareCdpStringValue;
|
|
@@ -2909,6 +3193,7 @@ exports.serializeDocumentEpoch = serializeDocumentEpoch;
|
|
|
2909
3193
|
exports.serializeRef = serializeRef;
|
|
2910
3194
|
exports.staleNodeRefError = staleNodeRefError;
|
|
2911
3195
|
exports.unsupportedCapabilityError = unsupportedCapabilityError;
|
|
3196
|
+
exports.waitForActionBoundary = waitForActionBoundary;
|
|
2912
3197
|
exports.waitForCdpVisualStability = waitForCdpVisualStability;
|
|
2913
3198
|
//# sourceMappingURL=index.cjs.map
|
|
2914
3199
|
//# sourceMappingURL=index.cjs.map
|