diff --git a/node_modules/proxy-polyfill/src/proxy.js b/node_modules/proxy-polyfill/src/proxy.js index 01ced4b..ea7287a 100644 --- a/node_modules/proxy-polyfill/src/proxy.js +++ b/node_modules/proxy-polyfill/src/proxy.js @@ -104,7 +104,9 @@ module.exports = function proxyPolyfill() { handler = { 'get': null, 'set': null, 'apply': null, 'construct': null }; for (let k in unsafeHandler) { if (!(k in handler)) { - throw new TypeError(`Proxy polyfill does not support trap '${k}'`); + // MYHACK + // throw new TypeError(`Proxy polyfill does not support trap '${k}'`); + // console.error(`Proxy polyfill does not support trap '${k}'`); } handler[k] = unsafeHandler[k]; } @@ -114,6 +116,30 @@ module.exports = function proxyPolyfill() { handler.apply = unsafeHandler.apply.bind(unsafeHandler); } + // Create default getters/setters. Create different code paths as handler.get/handler.set can't + // change after creation. + const getter = handler.get ? function(prop) { + throwRevoked('get'); + return handler.get(this, prop, proxy); + } : function(prop) { + throwRevoked('get'); + return this[prop]; + }; + const setter = handler.set ? function(prop, value) { + throwRevoked('set'); + const status = handler.set(this, prop, value, proxy); + // TODO(samthor): If the calling code is in strict mode, throw TypeError. + // if (!status) { + // It's (sometimes) possible to work this out, if this code isn't strict- try to load the + // callee, and if it's available, that code is non-strict. However, this isn't exhaustive. + // } + } : function(prop, value) { + throwRevoked('set'); + this[prop] = value; + }; + + const propertyMap = {}; + // Define proxy as an object that extends target.[[Prototype]], // or a Function (if either it's callable, or apply is set). const proto = getProto(target); // can return null in old browsers @@ -144,47 +170,64 @@ module.exports = function proxyPolyfill() { return target.apply(this, args); }; isMethod = true; - } else if (target instanceof Array) { + } /* else if (target instanceof Array) { proxy = []; isArray = true; - } else { - proxy = (canCreateNullProtoObjects || proto !== null) ? objectCreate(proto) : {}; + } */ else { + if (proto) { + // set delegate proxy proto + proxy = new proto.constructor(); + const propertyNames = $Object.getOwnPropertyNames(proto); + propertyNames.forEach(function(prop) { + const real = $Object.getOwnPropertyDescriptor(proto, prop); + const desc = { + enumerable: Boolean(real.enumerable), + get: getter.bind(target, prop), + set: setter.bind(target, prop) + }; + try { + $Object.defineProperty(proxy, prop, desc); + } catch (e) { + // just set + proxy[prop] = target[prop]; + } + propertyMap[prop] = true; + }); + } else { + proxy = {}; + } } - // Create default getters/setters. Create different code paths as handler.get/handler.set can't - // change after creation. - const getter = handler.get ? function(prop) { - throwRevoked('get'); - return handler.get(this, prop, proxy); - } : function(prop) { - throwRevoked('get'); - return this[prop]; - }; - const setter = handler.set ? function(prop, value) { - throwRevoked('set'); - const status = handler.set(this, prop, value, proxy); - // TODO(samthor): If the calling code is in strict mode, throw TypeError. - // if (!status) { - // It's (sometimes) possible to work this out, if this code isn't strict- try to load the - // callee, and if it's available, that code is non-strict. However, this isn't exhaustive. - // } - } : function(prop, value) { - throwRevoked('set'); - this[prop] = value; - }; + const __getter__ = '___@getter___' + const __setter__ = '___@setter___' + $Object.defineProperty(proxy, __getter__, { + enumerable: false, + get() { + return getter + } + }) + propertyMap[__getter__] = true + $Object.defineProperty(proxy, __setter__, { + enumerable: false, + get() { + return setter + } + }) + propertyMap[__setter__] = true // Clone direct properties (i.e., not part of a prototype). const propertyNames = $Object.getOwnPropertyNames(target); - const propertyMap = {}; propertyNames.forEach(function(prop) { - if ((isMethod || isArray) && prop in proxy) { + if (propertyMap[prop] || ((isMethod || isArray) && prop in proxy)) { return; // ignore properties already here, e.g. 'bind', 'prototype' etc } const real = $Object.getOwnPropertyDescriptor(target, prop); const desc = { + // in array cases the prop should be deleteable + configurable: true, enumerable: Boolean(real.enumerable), get: getter.bind(target, prop), - set: setter.bind(target, prop), + set: setter.bind(target, prop) }; $Object.defineProperty(proxy, prop, desc); propertyMap[prop] = true; @@ -221,8 +264,9 @@ module.exports = function proxyPolyfill() { } // The Proxy polyfill cannot handle adding new properties. Seal the target and proxy. - $Object.seal(target); - $Object.seal(proxy); + // MYHACK + // $Object.seal(target); + // $Object.seal(proxy); return proxy; // nb. if isMethod is true, proxy != this };