@@ -19218,6 +19218,45 @@ function proxyApplyFn(
1921819218 }
1921919219 context[prop] = new Proxy(fn, proxyDetails);
1922019220}
19221+ function parsePropertiesToMatchFn(propsToMatch, implicit = '') {
19222+ const safe = safeSelf();
19223+ const needles = new Map();
19224+ if ( propsToMatch === undefined || propsToMatch === '' ) { return needles; }
19225+ const options = { canNegate: true };
19226+ for ( const needle of safe.String_split.call(propsToMatch, /\s+/) ) {
19227+ let [ prop, pattern ] = safe.String_split.call(needle, ':');
19228+ if ( prop === '' ) { continue; }
19229+ if ( pattern !== undefined && /[^$\w -]/.test(prop) ) {
19230+ prop = `${prop}:${pattern}`;
19231+ pattern = undefined;
19232+ }
19233+ if ( pattern !== undefined ) {
19234+ needles.set(prop, safe.initPattern(pattern, options));
19235+ } else if ( implicit !== '' ) {
19236+ needles.set(implicit, safe.initPattern(prop, options));
19237+ }
19238+ }
19239+ return needles;
19240+ }
19241+ function matchObjectPropertiesFn(propNeedles, ...objs) {
19242+ const safe = safeSelf();
19243+ const matched = [];
19244+ for ( const obj of objs ) {
19245+ if ( obj instanceof Object === false ) { continue; }
19246+ for ( const [ prop, details ] of propNeedles ) {
19247+ let value = obj[prop];
19248+ if ( value === undefined ) { continue; }
19249+ if ( typeof value !== 'string' ) {
19250+ try { value = safe.JSON_stringify(value); }
19251+ catch { }
19252+ if ( typeof value !== 'string' ) { continue; }
19253+ }
19254+ if ( safe.testPattern(details, value) === false ) { return; }
19255+ matched.push(`${prop}: ${value}`);
19256+ }
19257+ }
19258+ return matched;
19259+ }
1922119260function safeSelf() {
1922219261 if ( scriptletGlobals.safeSelf ) {
1922319262 return scriptletGlobals.safeSelf;
@@ -19480,20 +19519,7 @@ function preventFetchFn(
1948019519 responseType
1948119520 );
1948219521 const extraArgs = safe.getExtraArgs(Array.from(arguments), 4);
19483- const needles = [];
19484- for ( const condition of safe.String_split.call(propsToMatch, /\s+/) ) {
19485- if ( condition === '' ) { continue; }
19486- const pos = condition.indexOf(':');
19487- let key, value;
19488- if ( pos !== -1 ) {
19489- key = condition.slice(0, pos);
19490- value = condition.slice(pos + 1);
19491- } else {
19492- key = 'url';
19493- value = condition;
19494- }
19495- needles.push({ key, pattern: safe.initPattern(value, { canNegate: true }) });
19496- }
19522+ const propNeedles = parsePropertiesToMatchFn(propsToMatch, 'url');
1949719523 const validResponseProps = {
1949819524 ok: [ false, true ],
1949919525 statusText: [ '', 'Not Found' ],
@@ -19523,41 +19549,38 @@ function preventFetchFn(
1952319549 }
1952419550 proxyApplyFn('fetch', function fetch(context) {
1952519551 const { callArgs } = context;
19526- const details = callArgs[0] instanceof self.Request
19527- ? callArgs[0]
19528- : Object.assign({ url: callArgs[0] }, callArgs[1]);
19529- let proceed = true;
19530- try {
19531- const props = new Map();
19532- for ( const prop in details ) {
19533- let v = details[prop];
19534- if ( typeof v !== 'string' ) {
19535- try { v = safe.JSON_stringify(v); }
19536- catch { }
19537- }
19538- if ( typeof v !== 'string' ) { continue; }
19539- props.set(prop, v);
19540- }
19541- if ( safe.logLevel > 1 || propsToMatch === '' && responseBody === '' ) {
19542- const out = Array.from(props).map(a => `${a[0]}:${a[1]}`);
19543- safe.uboLog(logPrefix, `Called: ${out.join('\n')}`);
19544- }
19545- if ( propsToMatch === '' && responseBody === '' ) {
19546- return context.reflect();
19547- }
19548- proceed = needles.length === 0;
19549- for ( const { key, pattern } of needles ) {
19550- if (
19551- pattern.expect && props.has(key) === false ||
19552- safe.testPattern(pattern, props.get(key)) === false
19553- ) {
19554- proceed = true;
19555- break;
19552+ const details = (( ) => {
19553+ const fetchProps = (src, out) => {
19554+ if ( typeof src !== 'object' || src === null ) { return; }
19555+ const props = [
19556+ 'body', 'cache', 'credentials', 'duplex', 'headers',
19557+ 'integrity', 'keepalive', 'method', 'mode', 'priority',
19558+ 'redirect', 'referrer', 'referrerPolicy', 'signal',
19559+ ];
19560+ for ( const prop of props ) {
19561+ if ( src[prop] === undefined ) { continue; }
19562+ out[prop] = src[prop];
1955619563 }
19564+ };
19565+ const out = {};
19566+ if ( callArgs[0] instanceof self.Request ) {
19567+ out.url = `${callArgs[0].url}`;
19568+ fetchProps(callArgs[0], out);
19569+ } else {
19570+ out.url = `${callArgs[0]}`;
1955719571 }
19558- } catch {
19572+ fetchProps(callArgs[1], out);
19573+ return out;
19574+ })();
19575+ if ( safe.logLevel > 1 || propsToMatch === '' && responseBody === '' ) {
19576+ const out = Array.from(details).map(a => `${a[0]}:${a[1]}`);
19577+ safe.uboLog(logPrefix, `Called: ${out.join('\n')}`);
19578+ }
19579+ if ( propsToMatch === '' && responseBody === '' ) {
19580+ return context.reflect();
1955919581 }
19560- if ( proceed ) {
19582+ const matched = matchObjectPropertiesFn(propNeedles, details);
19583+ if ( matched === undefined ) {
1956119584 return context.reflect();
1956219585 }
1956319586 return Promise.resolve(generateContentFn(trusted, responseBody)).then(text => {
@@ -19678,6 +19701,45 @@ function proxyApplyFn(
1967819701 }
1967919702 context[prop] = new Proxy(fn, proxyDetails);
1968019703}
19704+ function parsePropertiesToMatchFn(propsToMatch, implicit = '') {
19705+ const safe = safeSelf();
19706+ const needles = new Map();
19707+ if ( propsToMatch === undefined || propsToMatch === '' ) { return needles; }
19708+ const options = { canNegate: true };
19709+ for ( const needle of safe.String_split.call(propsToMatch, /\s+/) ) {
19710+ let [ prop, pattern ] = safe.String_split.call(needle, ':');
19711+ if ( prop === '' ) { continue; }
19712+ if ( pattern !== undefined && /[^$\w -]/.test(prop) ) {
19713+ prop = `${prop}:${pattern}`;
19714+ pattern = undefined;
19715+ }
19716+ if ( pattern !== undefined ) {
19717+ needles.set(prop, safe.initPattern(pattern, options));
19718+ } else if ( implicit !== '' ) {
19719+ needles.set(implicit, safe.initPattern(prop, options));
19720+ }
19721+ }
19722+ return needles;
19723+ }
19724+ function matchObjectPropertiesFn(propNeedles, ...objs) {
19725+ const safe = safeSelf();
19726+ const matched = [];
19727+ for ( const obj of objs ) {
19728+ if ( obj instanceof Object === false ) { continue; }
19729+ for ( const [ prop, details ] of propNeedles ) {
19730+ let value = obj[prop];
19731+ if ( value === undefined ) { continue; }
19732+ if ( typeof value !== 'string' ) {
19733+ try { value = safe.JSON_stringify(value); }
19734+ catch { }
19735+ if ( typeof value !== 'string' ) { continue; }
19736+ }
19737+ if ( safe.testPattern(details, value) === false ) { return; }
19738+ matched.push(`${prop}: ${value}`);
19739+ }
19740+ }
19741+ return matched;
19742+ }
1968119743function safeSelf() {
1968219744 if ( scriptletGlobals.safeSelf ) {
1968319745 return scriptletGlobals.safeSelf;
@@ -19940,20 +20002,7 @@ function preventFetchFn(
1994020002 responseType
1994120003 );
1994220004 const extraArgs = safe.getExtraArgs(Array.from(arguments), 4);
19943- const needles = [];
19944- for ( const condition of safe.String_split.call(propsToMatch, /\s+/) ) {
19945- if ( condition === '' ) { continue; }
19946- const pos = condition.indexOf(':');
19947- let key, value;
19948- if ( pos !== -1 ) {
19949- key = condition.slice(0, pos);
19950- value = condition.slice(pos + 1);
19951- } else {
19952- key = 'url';
19953- value = condition;
19954- }
19955- needles.push({ key, pattern: safe.initPattern(value, { canNegate: true }) });
19956- }
20005+ const propNeedles = parsePropertiesToMatchFn(propsToMatch, 'url');
1995720006 const validResponseProps = {
1995820007 ok: [ false, true ],
1995920008 statusText: [ '', 'Not Found' ],
@@ -19983,41 +20032,38 @@ function preventFetchFn(
1998320032 }
1998420033 proxyApplyFn('fetch', function fetch(context) {
1998520034 const { callArgs } = context;
19986- const details = callArgs[0] instanceof self.Request
19987- ? callArgs[0]
19988- : Object.assign({ url: callArgs[0] }, callArgs[1]);
19989- let proceed = true;
19990- try {
19991- const props = new Map();
19992- for ( const prop in details ) {
19993- let v = details[prop];
19994- if ( typeof v !== 'string' ) {
19995- try { v = safe.JSON_stringify(v); }
19996- catch { }
19997- }
19998- if ( typeof v !== 'string' ) { continue; }
19999- props.set(prop, v);
20000- }
20001- if ( safe.logLevel > 1 || propsToMatch === '' && responseBody === '' ) {
20002- const out = Array.from(props).map(a => `${a[0]}:${a[1]}`);
20003- safe.uboLog(logPrefix, `Called: ${out.join('\n')}`);
20004- }
20005- if ( propsToMatch === '' && responseBody === '' ) {
20006- return context.reflect();
20007- }
20008- proceed = needles.length === 0;
20009- for ( const { key, pattern } of needles ) {
20010- if (
20011- pattern.expect && props.has(key) === false ||
20012- safe.testPattern(pattern, props.get(key)) === false
20013- ) {
20014- proceed = true;
20015- break;
20035+ const details = (( ) => {
20036+ const fetchProps = (src, out) => {
20037+ if ( typeof src !== 'object' || src === null ) { return; }
20038+ const props = [
20039+ 'body', 'cache', 'credentials', 'duplex', 'headers',
20040+ 'integrity', 'keepalive', 'method', 'mode', 'priority',
20041+ 'redirect', 'referrer', 'referrerPolicy', 'signal',
20042+ ];
20043+ for ( const prop of props ) {
20044+ if ( src[prop] === undefined ) { continue; }
20045+ out[prop] = src[prop];
2001620046 }
20047+ };
20048+ const out = {};
20049+ if ( callArgs[0] instanceof self.Request ) {
20050+ out.url = `${callArgs[0].url}`;
20051+ fetchProps(callArgs[0], out);
20052+ } else {
20053+ out.url = `${callArgs[0]}`;
2001720054 }
20018- } catch {
20055+ fetchProps(callArgs[1], out);
20056+ return out;
20057+ })();
20058+ if ( safe.logLevel > 1 || propsToMatch === '' && responseBody === '' ) {
20059+ const out = Array.from(details).map(a => `${a[0]}:${a[1]}`);
20060+ safe.uboLog(logPrefix, `Called: ${out.join('\n')}`);
20061+ }
20062+ if ( propsToMatch === '' && responseBody === '' ) {
20063+ return context.reflect();
2001920064 }
20020- if ( proceed ) {
20065+ const matched = matchObjectPropertiesFn(propNeedles, details);
20066+ if ( matched === undefined ) {
2002120067 return context.reflect();
2002220068 }
2002320069 return Promise.resolve(generateContentFn(trusted, responseBody)).then(text => {
@@ -22587,6 +22633,7 @@ function trustedReplaceArgument(
2258722633 const parsed = parseReplaceFn(argraw.slice(5));
2258822634 if ( parsed === undefined ) { return; }
2258922635 replacer = arg => `${arg}`.replace(replacer.re, replacer.replacement);
22636+ Object.assign(replacer, parsed);
2259022637 } else if ( argraw.startsWith('add:') ) {
2259122638 const delta = parseFloat(argraw.slice(4));
2259222639 if ( isNaN(delta) ) { return; }
0 commit comments