| Index: lib/content/snippets.js |
| =================================================================== |
| --- a/lib/content/snippets.js |
| +++ b/lib/content/snippets.js |
| @@ -695,22 +695,46 @@ |
| // 2176782336 - 60466176 = 2116316160. This ensure to always have 6 |
| // chars even if Math.random() returns its minimum value 0.0 |
| // |
| return Math.floor(Math.random() * 2116316160 + 60466176).toString(36); |
| } |
| function wrapPropertyAccess(object, property, descriptor) |
| { |
| - let currentDescriptor = Object.getOwnPropertyDescriptor(object, property); |
| + let dotIndex = property.indexOf("."); |
| + if (dotIndex == -1) |
| + { |
| + // simple property case. |
| + let currentDescriptor = Object.getOwnPropertyDescriptor(object, property); |
| + if (currentDescriptor && !currentDescriptor.configurable) |
| + return; |
| + |
| + Object.defineProperty(object, property, descriptor); |
| + return; |
| + } |
| + |
| + let name = property.slice(0, dotIndex); |
| + property = property.slice(dotIndex + 1); |
| + let value = object[name]; |
| + if (value && typeof value == "object") |
| + wrapPropertyAccess(value, property, descriptor); |
| + |
| + let currentDescriptor = Object.getOwnPropertyDescriptor(object, name); |
| if (currentDescriptor && !currentDescriptor.configurable) |
| - return false; |
| + return; |
| - Object.defineProperty(object, property, descriptor); |
| - return true; |
| + let setter = newValue => |
| + { |
| + value = newValue; |
| + if (newValue && typeof newValue == "object") |
| + wrapPropertyAccess(newValue, property, descriptor); |
| + }; |
| + |
| + Object.defineProperty(object, name, {get: () => value, set: setter}); |
| } |
| /** |
| * Overrides the <code>onerror</code> handler to discard tagged error messages |
| * from our property wrapping. |
| * |
| * @param {string} magic The magic string that tags the error message. |
| */ |
| @@ -744,18 +768,18 @@ |
| let rid = randomId(); |
| function abort() |
| { |
| throw new ReferenceError(rid); |
| } |
| - if (wrapPropertyAccess(window, property, {get: abort, set() {}})) |
| - overrideOnError(rid); |
| + wrapPropertyAccess(window, property, {get: abort, set() {}}); |
| + overrideOnError(rid); |
| } |
| exports["abort-on-property-read"] = makeInjector(abortOnPropertyRead, |
| wrapPropertyAccess, |
| overrideOnError, |
| randomId); |
| /** |
| @@ -776,18 +800,18 @@ |
| let rid = randomId(); |
| function abort() |
| { |
| throw new ReferenceError(rid); |
| } |
| - if (wrapPropertyAccess(window, property, {set: abort})) |
| - overrideOnError(rid); |
| + wrapPropertyAccess(window, property, {set: abort}); |
| + overrideOnError(rid); |
| } |
| exports["abort-on-property-write"] = makeInjector(abortOnPropertyWrite, |
| wrapPropertyAccess, |
| overrideOnError, |
| randomId); |
| /** |
| @@ -839,18 +863,18 @@ |
| }, |
| set(value) |
| { |
| abort(); |
| currentValue = value; |
| } |
| }; |
| - if (wrapPropertyAccess(object, name, descriptor)) |
| - overrideOnError(rid); |
| + wrapPropertyAccess(object, name, descriptor); |
| + overrideOnError(rid); |
| } |
| exports["abort-current-inline-script"] = |
| makeInjector(abortCurrentInlineScript, wrapPropertyAccess, toRegExp, |
| overrideOnError, regexEscape, randomId); |
| /** |
| * Strips a query string parameter from <code>fetch()</code> calls. |