mirror of https://github.com/gorhill/uBlock.git
Support multiple trappers to same property in set-constant
Related issues: - https://github.com/uBlockOrigin/uBlock-issues/issues/156 - https://github.com/uBlockOrigin/uBlock-issues/issues/1162 Take into account that a trapped property may have been already trapped, and if so honour previous trapper getter/setter.
This commit is contained in:
parent
9880b9c18f
commit
c33de41660
|
@ -588,8 +588,9 @@
|
||||||
/// set-constant.js
|
/// set-constant.js
|
||||||
/// alias set.js
|
/// alias set.js
|
||||||
(function() {
|
(function() {
|
||||||
const thisScript = document.currentScript;
|
const chain = '{{1}}';
|
||||||
let cValue = '{{2}}';
|
let cValue = '{{2}}';
|
||||||
|
const thisScript = document.currentScript;
|
||||||
if ( cValue === 'undefined' ) {
|
if ( cValue === 'undefined' ) {
|
||||||
cValue = undefined;
|
cValue = undefined;
|
||||||
} else if ( cValue === 'false' ) {
|
} else if ( cValue === 'false' ) {
|
||||||
|
@ -622,53 +623,83 @@
|
||||||
(typeof v !== typeof cValue);
|
(typeof v !== typeof cValue);
|
||||||
return aborted;
|
return aborted;
|
||||||
};
|
};
|
||||||
const makeProxy = function(owner, chain) {
|
// https://github.com/uBlockOrigin/uBlock-issues/issues/156
|
||||||
|
// Support multiple trappers for the same property.
|
||||||
|
const trapProp = function(owner, prop, handler) {
|
||||||
|
if ( handler.init(owner[prop]) === false ) { return; }
|
||||||
|
const odesc = Object.getOwnPropertyDescriptor(owner, prop);
|
||||||
|
let prevGetter, prevSetter;
|
||||||
|
if ( odesc instanceof Object ) {
|
||||||
|
if ( odesc.get instanceof Function ) {
|
||||||
|
prevGetter = odesc.get;
|
||||||
|
}
|
||||||
|
if ( odesc.set instanceof Function ) {
|
||||||
|
prevSetter = odesc.set;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Object.defineProperty(owner, prop, {
|
||||||
|
configurable: true,
|
||||||
|
get() {
|
||||||
|
if ( prevGetter !== undefined ) {
|
||||||
|
prevGetter();
|
||||||
|
}
|
||||||
|
return handler.getter();
|
||||||
|
},
|
||||||
|
set(a) {
|
||||||
|
if ( prevSetter !== undefined ) {
|
||||||
|
prevSetter(a);
|
||||||
|
}
|
||||||
|
handler.setter(a);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
const trapChain = function(owner, chain) {
|
||||||
const pos = chain.indexOf('.');
|
const pos = chain.indexOf('.');
|
||||||
if ( pos === -1 ) {
|
if ( pos === -1 ) {
|
||||||
const original = owner[chain];
|
trapProp(owner, chain, {
|
||||||
if ( mustAbort(original) ) { return; }
|
v: undefined,
|
||||||
const desc = Object.getOwnPropertyDescriptor(owner, chain);
|
init: function(v) {
|
||||||
if ( desc === undefined || desc.get === undefined ) {
|
if ( mustAbort(v) ) { return false; }
|
||||||
Object.defineProperty(owner, chain, {
|
this.v = v;
|
||||||
get: function() {
|
return true;
|
||||||
return document.currentScript === thisScript
|
},
|
||||||
? original
|
getter: function() {
|
||||||
: cValue;
|
return document.currentScript === thisScript
|
||||||
},
|
? this.v
|
||||||
set: function(a) {
|
: cValue;
|
||||||
if ( mustAbort(a) ) {
|
},
|
||||||
cValue = a;
|
setter: function(a) {
|
||||||
}
|
if ( mustAbort(a) === false ) { return; }
|
||||||
}
|
cValue = a;
|
||||||
});
|
}
|
||||||
}
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const prop = chain.slice(0, pos);
|
const prop = chain.slice(0, pos);
|
||||||
let v = owner[prop];
|
const v = owner[prop];
|
||||||
chain = chain.slice(pos + 1);
|
chain = chain.slice(pos + 1);
|
||||||
if (
|
if ( v instanceof Object || typeof v === 'object' && v !== null ) {
|
||||||
(v instanceof Object) ||
|
trapChain(v, chain);
|
||||||
(typeof v === 'object' && v !== null)
|
|
||||||
) {
|
|
||||||
makeProxy(v, chain);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const desc = Object.getOwnPropertyDescriptor(owner, prop);
|
trapProp(owner, prop, {
|
||||||
if ( desc && desc.set !== undefined ) { return; }
|
v: undefined,
|
||||||
Object.defineProperty(owner, prop, {
|
init: function(v) {
|
||||||
get: function() {
|
this.v = v;
|
||||||
return v;
|
return true;
|
||||||
},
|
},
|
||||||
set: function(a) {
|
getter: function() {
|
||||||
v = a;
|
return this.v;
|
||||||
|
},
|
||||||
|
setter: function(a) {
|
||||||
|
this.v = a;
|
||||||
if ( a instanceof Object ) {
|
if ( a instanceof Object ) {
|
||||||
makeProxy(a, chain);
|
trapChain(a, chain);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
makeProxy(window, '{{1}}');
|
trapChain(window, chain);
|
||||||
})();
|
})();
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue