You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

409 lines
14 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

/**
* P0Autocomplete 实例拓扑 + place_changed 监听器指纹
* P2全局 fetch 劫持axel/location/place
* 纯字符串 initScript供 addInitScript 注入。
*/
export const P0_PLACE_DIAG_INIT = `(() => {
if (window.__rpaPlaceDiagP0) return;
window.__rpaPlaceDiagP0 = true;
window.__rpaPlaceDiag = window.__rpaPlaceDiag || {
instances: [],
listeners: [],
events: [],
fetchLog: [],
mark: "init",
nextInstanceId: 1,
nextListenerId: 1,
};
var diag = window.__rpaPlaceDiag;
function inputMeta(el) {
if (!el) return null;
var gmKeys = Object.keys(el).filter(function(k) { return k.indexOf("gm_") === 0; });
return {
tagName: el.tagName || "",
id: el.id || "",
className: (el.className || "").slice(0, 80),
placeholder: el.placeholder || "",
pacTarget: el.classList && el.classList.contains("pac-target-input"),
valuePreview: ((el.value || el.textContent || "") + "").replace(/\\s+/g, " ").trim().slice(0, 100),
gmKeyCount: gmKeys.length,
gmKeys: gmKeys.slice(0, 6),
};
}
function resolveInstanceFromInput(el) {
if (!el) return null;
for (var i = 0; i < Object.keys(el).length; i += 1) {
var key = Object.keys(el)[i];
if (key.indexOf("gm_") !== 0) continue;
var val = el[key];
if (val && typeof val.getPlace === "function") return val;
}
for (var j = 0; j < diag.instances.length; j += 1) {
if (diag.instances[j].inputEl === el) return diag.instances[j].instance;
}
return null;
}
function instanceIdFor(inst, inputEl) {
for (var i = 0; i < diag.instances.length; i += 1) {
if (diag.instances[i].instance === inst) return diag.instances[i].id;
}
var id = "ac-" + diag.nextInstanceId++;
diag.instances.push({
id: id,
instance: inst,
inputEl: inputEl || inst.__rpaInputEl || null,
input: inputMeta(inputEl || inst.__rpaInputEl || null),
createdAt: Date.now(),
listenerIds: [],
});
return id;
}
function fingerprintHandler(handler, source) {
var src = "";
try { src = Function.prototype.toString.call(handler); } catch (e) { src = String(handler); }
var compact = src.replace(/\\s+/g, " ").trim();
return {
source: source,
length: compact.length,
preview: compact.slice(0, 240),
hasFetch: /\\bfetch\\s*\\(/.test(compact),
hasAxelPlace: /axel\\/location\\/place/.test(compact),
hasGetPlace: /getPlace\\s*\\(/.test(compact),
hasXMLHttpRequest: /XMLHttpRequest|\\.open\\s*\\(/.test(compact),
};
}
function safeGetPlace(inst) {
if (!inst || typeof inst.getPlace !== "function") {
return { ok: false, reason: "no-getPlace" };
}
try {
var p = inst.getPlace();
if (!p) return { ok: true, empty: true };
var loc = p.geometry && p.geometry.location;
var lat = null;
var lng = null;
if (loc) {
lat = typeof loc.lat === "function" ? loc.lat() : loc.lat;
lng = typeof loc.lng === "function" ? loc.lng() : loc.lng;
}
return {
ok: true,
place_id: p.place_id || null,
formatted_address: (p.formatted_address || "").slice(0, 160),
name: (p.name || "").slice(0, 80),
hasGeometry: Boolean(loc),
lat: lat,
lng: lng,
};
} catch (e2) {
return { ok: false, reason: "getPlace-threw", error: String(e2) };
}
}
function wrapHandler(inst, handler, source, inputEl) {
var instId = instanceIdFor(inst, inputEl);
var fp = fingerprintHandler(handler, source);
var lid = "lh-" + diag.nextListenerId++;
diag.listeners.push({
id: lid,
instanceId: instId,
registeredAt: Date.now(),
fingerprint: fp,
});
for (var i = 0; i < diag.instances.length; i += 1) {
if (diag.instances[i].id === instId) {
diag.instances[i].listenerIds.push(lid);
break;
}
}
return function wrappedPlaceChangedHandler() {
diag.events.push({
type: "place_changed_handler",
mark: diag.mark,
at: Date.now(),
instanceId: instId,
listenerId: lid,
fingerprint: fp,
getPlaceBefore: safeGetPlace(inst),
});
return handler.apply(this, arguments);
};
}
function registerPlaceChanged(inst, handler, source, inputEl) {
if (!inst || typeof handler !== "function") return handler;
return wrapHandler(inst, handler, source, inputEl);
}
window.__rpaAutocompleteInstances = window.__rpaAutocompleteInstances || [];
window.__rpaPlaceChangedHandlers = window.__rpaPlaceChangedHandlers || [];
var waitForGoogle = function() {
if (typeof google === "undefined" || !google.maps || !google.maps.places || !google.maps.places.Autocomplete) {
setTimeout(waitForGoogle, 200);
return;
}
if (window.__rpaAutocompletePatched) return;
window.__rpaAutocompletePatched = true;
var AutocompleteCtor = google.maps.places.Autocomplete;
google.maps.places.Autocomplete = function() {
var args = arguments;
var instance = Reflect.construct(AutocompleteCtor, args);
var inputEl = args[0] || null;
instance.__rpaInputEl = inputEl;
window.__rpaAutocompleteInstances.push(instance);
instanceIdFor(instance, inputEl);
if (typeof instance.addListener === "function") {
var origInstAdd = instance.addListener.bind(instance);
instance.addListener = function(eventName, handler) {
var h = handler;
if (eventName === "place_changed" && typeof handler === "function") {
h = registerPlaceChanged(instance, handler, "instance.addListener", inputEl);
window.__rpaPlaceChangedHandlers.push({ instance: instance, handler: h, inputEl: inputEl });
}
return origInstAdd(eventName, h);
};
}
return instance;
};
google.maps.places.Autocomplete.prototype = AutocompleteCtor.prototype;
if (google.maps.event && typeof google.maps.event.addListener === "function") {
var origMapsAdd = google.maps.event.addListener;
google.maps.event.addListener = function(instance, eventName, handler) {
var h = handler;
if (
eventName === "place_changed" &&
instance &&
typeof instance.getPlace === "function" &&
typeof handler === "function"
) {
h = registerPlaceChanged(instance, handler, "maps.event.addListener", instance.__rpaInputEl || null);
window.__rpaPlaceChangedHandlers.push({
instance: instance,
handler: h,
inputEl: instance.__rpaInputEl || null,
});
}
return origMapsAdd(instance, eventName, h);
};
}
if (google.maps.event && typeof google.maps.event.trigger === "function") {
var origTrigger = google.maps.event.trigger;
google.maps.event.trigger = function(instance, eventName) {
var instId = instance && typeof instance.getPlace === "function"
? instanceIdFor(instance, instance.__rpaInputEl || null)
: null;
if (eventName === "place_changed") {
diag.events.push({
type: "maps_event_trigger",
mark: diag.mark,
at: Date.now(),
instanceId: instId,
getPlaceAtTrigger: instance ? safeGetPlace(instance) : null,
});
}
return origTrigger.apply(this, arguments);
};
}
diag.events.push({ type: "p0-ready", at: Date.now(), mark: diag.mark });
};
waitForGoogle();
})();`;
export const P2_FETCH_HIJACK_INIT = `(() => {
if (window.__rpaPlaceFetchP2) return;
window.__rpaPlaceFetchP2 = true;
window.__rpaPlaceDiag = window.__rpaPlaceDiag || { fetchLog: [], events: [], mark: "init" };
var diag = window.__rpaPlaceDiag;
diag.fetchLog = diag.fetchLog || [];
var origFetch = window.fetch;
if (typeof origFetch === "function") {
window.fetch = function() {
var url = "";
try {
var first = arguments[0];
url = typeof first === "string" ? first : (first && first.url) || "";
} catch (e) {}
if (url && url.indexOf("axel/location/place") >= 0) {
var stack = "";
try { stack = (new Error("place-fetch")).stack || ""; } catch (e2) {}
diag.fetchLog.push({
mark: diag.mark,
at: Date.now(),
url: url.slice(0, 240),
stackPreview: stack.split("\\n").slice(0, 8).join(" | "),
});
diag.events.push({ type: "fetch_place", mark: diag.mark, at: Date.now(), url: url.slice(0, 240) });
}
return origFetch.apply(this, arguments);
};
}
var XHR = window.XMLHttpRequest;
if (XHR && XHR.prototype && XHR.prototype.open) {
var origOpen = XHR.prototype.open;
XHR.prototype.open = function(method, url) {
this.__rpaUrl = url;
return origOpen.apply(this, arguments);
};
var origSend = XHR.prototype.send;
XHR.prototype.send = function() {
var url = this.__rpaUrl || "";
if (url && String(url).indexOf("axel/location/place") >= 0) {
diag.fetchLog.push({
mark: diag.mark,
at: Date.now(),
url: String(url).slice(0, 240),
transport: "xhr",
});
diag.events.push({ type: "xhr_place", mark: diag.mark, at: Date.now(), url: String(url).slice(0, 240) });
}
return origSend.apply(this, arguments);
};
}
})();`;
/** 设置诊断阶段标记并清空本阶段事件 */
export const PLACE_DIAG_SET_MARK = `(mark) => {
window.__rpaPlaceDiag = window.__rpaPlaceDiag || { events: [], mark: "init" };
window.__rpaPlaceDiag.mark = mark || "phase";
return { ok: true, mark: window.__rpaPlaceDiag.mark };
}`;
/** 采集实例拓扑 + 监听器指纹 + 事件 + fetch 日志(可序列化) */
export const PLACE_DIAG_COLLECT_SNAPSHOT = `() => {
try {
var diag = window.__rpaPlaceDiag;
if (!diag) return { ok: false, reason: "no-diag" };
function inputMeta(el) {
if (!el) return null;
var gmKeys = Object.keys(el).filter(function(k) { return k.indexOf("gm_") === 0; });
return {
tagName: el.tagName || "",
placeholder: el.placeholder || "",
pacTarget: el.classList && el.classList.contains("pac-target-input"),
valuePreview: ((el.value || "") + "").replace(/\\s+/g, " ").trim().slice(0, 100),
gmKeyCount: gmKeys.length,
};
}
function resolveFromInput(el) {
if (!el) return null;
for (var i = 0; i < Object.keys(el).length; i += 1) {
var key = Object.keys(el)[i];
if (key.indexOf("gm_") !== 0) continue;
var val = el[key];
if (val && typeof val.getPlace === "function") return val;
}
return null;
}
var widget = document.querySelector("#react-quoter-landing-plugin");
var inputProbes = [];
if (widget) {
var inputs = widget.querySelectorAll("input[type='text'], input:not([type])");
for (var i = 0; i < inputs.length; i += 1) {
var inp = inputs[i];
var inst = resolveFromInput(inp);
inputProbes.push({
index: i,
meta: inputMeta(inp),
hasGmInstance: Boolean(inst),
getPlace: inst && typeof inst.getPlace === "function"
? (function() {
try {
var p = inst.getPlace();
return {
place_id: p && p.place_id,
formatted_address: p && p.formatted_address,
hasGeometry: Boolean(p && p.geometry && p.geometry.location),
};
} catch (e) { return { error: String(e) }; }
})()
: null,
});
}
}
var instances = (diag.instances || []).map(function(row) {
var inst = row.instance;
var getPlace = null;
if (inst && typeof inst.getPlace === "function") {
try {
var p = inst.getPlace();
getPlace = {
place_id: p && p.place_id,
formatted_address: p && p.formatted_address,
hasGeometry: Boolean(p && p.geometry && p.geometry.location),
};
} catch (e2) {
getPlace = { error: String(e2) };
}
}
var listenerRows = (diag.listeners || []).filter(function(l) { return l.instanceId === row.id; });
return {
id: row.id,
input: row.input,
listenerCount: listenerRows.length,
listenerFingerprints: listenerRows.map(function(l) { return l.fingerprint; }),
getPlace: getPlace,
};
});
var anyListenerHasFetch = (diag.listeners || []).some(function(l) {
return l.fingerprint && l.fingerprint.hasFetch;
});
var anyListenerHasAxel = (diag.listeners || []).some(function(l) {
return l.fingerprint && l.fingerprint.hasAxelPlace;
});
var handlerEvents = (diag.events || []).filter(function(e) {
return e.type === "place_changed_handler" || e.type === "maps_event_trigger";
});
var fetchEvents = (diag.fetchLog || []).slice(-20);
return {
ok: true,
mark: diag.mark,
topology: {
instanceCount: instances.length,
instances: instances,
inputProbes: inputProbes,
monkeyPatchInstances: (window.__rpaAutocompleteInstances || []).length,
capturedHandlers: (window.__rpaPlaceChangedHandlers || []).length,
},
listeners: {
total: (diag.listeners || []).length,
anyHasFetch: anyListenerHasFetch,
anyHasAxelPlace: anyListenerHasAxel,
rows: (diag.listeners || []).map(function(l) {
return { id: l.id, instanceId: l.instanceId, fingerprint: l.fingerprint };
}),
},
events: (diag.events || []).slice(-40),
handlerEvents: handlerEvents,
fetchLog: fetchEvents,
activeElement: (function() {
var el = document.activeElement;
if (!el) return null;
return inputMeta(el);
})(),
};
} catch (err) {
return { ok: false, reason: "snapshot-error", error: String(err) };
}
}`;