var PropertyModifier = (function () {
var origToString = Function.prototype.toString;
var registry = new WeakMap();
var parentToString = null;
try {
if (typeof window !== 'undefined' && window.parent && window.parent !== window) {
parentToString = window.parent.Function.prototype.toString;
}
} catch (e) {}
var patchedToString = ({
toString() {
var name = registry.get(this);
if (name !== undefined) return 'function ' + name + '() { [native code] }';
if (parentToString !== null) {
try { return parentToString.call(this); } catch (e) {}
}
return origToString.call(this);
},
}).toString;
registry.set(patchedToString, 'toString');
Object.defineProperty(Function.prototype, 'toString', {
value: patchedToString, writable: true, enumerable: false, configurable: true,
});
function nativeGetter(prop, impl) {
var holder = { get [prop]() { return impl.call(this); } };
var fn = Object.getOwnPropertyDescriptor(holder, prop).get;
registry.set(fn, 'get ' + prop);
return fn;
}
function nativeMethod(name, arity, impl) {
var holder = { [name](...args) { return impl.apply(this, args); } };
var fn = holder[name];
if (fn.length !== arity) Object.defineProperty(fn, 'length', { value: arity });
registry.set(fn, name);
return fn;
}
return {
nativeGetter: nativeGetter,
nativeMethod: nativeMethod,
markNative: function (fn, name) { registry.set(fn, name); return fn; },
spoofProperty: function (target, prop, value) {
var desc = Object.getOwnPropertyDescriptor(target, prop);
var origGet = desc && desc.get;
var getter = nativeGetter(prop, function () {
if (origGet) origGet.call(this);
return value;
});
Object.defineProperty(target, prop, {
get: getter,
set: desc ? desc.set : undefined,
enumerable: desc ? desc.enumerable : true,
configurable: true,
});
},
spoofAccessor: function (target, prop, transform) {
var desc = Object.getOwnPropertyDescriptor(target, prop);
if (!desc || !desc.get) return;
var origGet = desc.get;
var getter = nativeGetter(prop, function () {
return transform(origGet.call(this), this);
});
Object.defineProperty(target, prop, {
get: getter, set: desc.set, enumerable: desc.enumerable, configurable: true,
});
},
spoofMethod: function (target, name, wrap) {
var orig = target[name];
if (typeof orig !== 'function') return;
var fn = nativeMethod(name, orig.length, wrap(orig));
Object.defineProperty(target, name, {
value: fn, writable: true, enumerable: true, configurable: true,
});
},
deleteProperty: function (target, prop) {
try { delete target[prop]; } catch (e) {}
},
};
})();