diff --git a/.eslintrc.json b/.eslintrc.json new file mode 100644 index 0000000000000000000000000000000000000000..401b533f5637909193eb0597f17859a28a33fe9b --- /dev/null +++ b/.eslintrc.json @@ -0,0 +1,28 @@ +{ + "env": { + "browser": true, + "node": true + }, + "extends": "eslint:recommended", + "parserOptions": { + "ecmaVersion": 3 + }, + "rules": { + "indent": [ + "error", + "tab" + ], + "linebreak-style": [ + "error", + "windows" + ], + "quotes": [ + "error", + "single" + ], + "semi": [ + "error", + "always" + ] + } +} \ No newline at end of file diff --git a/.npmignore b/.npmignore new file mode 100644 index 0000000000000000000000000000000000000000..b636ebeab921427b7b769fd815fdf7ce35b51eed --- /dev/null +++ b/.npmignore @@ -0,0 +1,2 @@ +# Test directory +test/ diff --git a/README.md b/README.md index 1aa453fdac07e975472418d79b60a01134be84e9..4f786d4074d37d5ce9012c888fc79d5e3a768fde 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -
[ 中文 ]
+English | 中文 # ES6 Proxy Polyfill This is a polyfill for the `Proxy` constructor based on **ES3** supports **IE8** , Node.js, etc. @@ -13,7 +13,7 @@ The `Proxy.revocable` method is also supported, but only for calls to the above #### Installation -1. Use NPM: `npm install es6-proxy-polyfill` +1. Use NPM: `npm install -S es6-proxy-polyfill` 2. Download directly: Development Version, Production Version diff --git a/README_zh.md b/README.zh-CN.md similarity index 91% rename from README_zh.md rename to README.zh-CN.md index 3217b8a1c8671088f9943dcdbd6185ff3d7ea609..89c0b29870036a25300d072478630bc994da76fa 100644 --- a/README_zh.md +++ b/README.zh-CN.md @@ -1,49 +1,49 @@ -
[ English ]
- -# ES6 Proxy Polyfill -这是一个基于 **ES3** 的`Proxy`构造器polyfill,支持 **IE8** 和 Node.js 等。 - -参照 ECMAScript 标准编写,无外部依赖。 - -由于ES3的限制,该polyfill只支持有限的'traps'代理: -* apply -* construct - -`Proxy.revocable`方法也被支持,但只限于调用上面的'traps'。 - -#### 安装 - -1. 使用NPM:`npm install es6-proxy-polyfill` -2. 直接下载:开发版本生产版本 - - -#### 用法 - -1. 浏览器: -``` - - -``` -2. Node.js: -``` -require('es6-proxy-polyfill'); - -var target = function(){/* code */}; -var handler = {/* code */}; -var proxy = new Proxy(target, handler); -``` - - -#### 注意 - -1. 在ES6中,对`Proxy`对象属性的访问将会被传递给目标对象。为了模拟这个特性,polyfill会尝试使用`Object.assign`方法从目标对象复制属性,因此最好先加载一个`Object.assign`的polyfill; -``` - - -``` -2. 代码已经在Node.js 0.10.48 和 IE8 测试过,而且它也应该能够运行在其他环境下; +English | 中文 + +# ES6 Proxy Polyfill +这是一个基于 **ES3** 的`Proxy`构造器polyfill,支持 **IE8** 和 Node.js 等。 + +参照 ECMAScript 标准编写,无外部依赖。 + +由于ES3的限制,该polyfill只支持有限的'traps'代理: +* apply +* construct + +`Proxy.revocable`方法也被支持,但只限于调用上面的'traps'。 + +#### 安装 + +1. 使用NPM:`npm install -S es6-proxy-polyfill` +2. 直接下载:开发版本生产版本 + + +#### 用法 + +1. 浏览器: +``` + + +``` +2. Node.js: +``` +require('es6-proxy-polyfill'); + +var target = function(){/* code */}; +var handler = {/* code */}; +var proxy = new Proxy(target, handler); +``` + + +#### 注意 + +1. 在ES6中,对`Proxy`对象属性的访问将会被传递给目标对象。为了模拟这个特性,polyfill会尝试使用`Object.assign`方法从目标对象复制属性,因此最好先加载一个`Object.assign`的polyfill; +``` + + +``` +2. 代码已经在Node.js 0.10.48 和 IE8 测试过,而且它也应该能够运行在其他环境下; 3. 当自身属性被访问时,被撤销的`Proxy`对象不会抛出错误。 \ No newline at end of file diff --git a/dist/es6-proxy-polyfill.js b/dist/es6-proxy-polyfill.js index 752b152c055212b8f9094e64f02350923141300b..b1058f4d3b0201a1bb726d1eadf979bced0761f0 100644 --- a/dist/es6-proxy-polyfill.js +++ b/dist/es6-proxy-polyfill.js @@ -1,6 +1,6 @@ /** * ES6 Proxy Polyfill - * @version 1.2.0 + * @version 1.2.1 * @author Ambit Tsai * @license Apache-2.0 * @see {@link https://github.com/ambit-tsai/es6-proxy-polyfill} diff --git a/dist/es6-proxy-polyfill.js.map b/dist/es6-proxy-polyfill.js.map deleted file mode 100644 index 4badeae21fb366301f0f153b7d577b86d01b0065..0000000000000000000000000000000000000000 --- a/dist/es6-proxy-polyfill.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"sources":["src/es6-proxy-polyfill.js"],"names":["global","Proxy","noop","assign","Object","getProto","getPrototypeOf","setProto","setPrototypeOf","InternalMember","prototype","$call","thisArg","argsList","target","this","handler","throwTypeError","apply","$construct","obj","construct","revocable","result","proxy","createProxy","message","TypeError","member","P","arguments","revoke","key","hasOwnProperty","window"],"mappings":";;;;;;;CAOE,SAASA,GACV,IAAGA,EAAOC,MAAV,CAEA,IAAIC,EAAO,aACVC,EAASC,OAAOD,QAAUD,EAC1BG,EAAWD,OAAOE,gBAAkBJ,EACpCK,EAAWH,OAAOI,gBAAkBN,EA0BrCO,EAAeC,UAAUC,MAAQ,SAASC,EAASC,GAClD,IAAIC,EAASC,KAAKD,OACjBE,EAAUD,KAAKC,QAIhB,OAHIA,GACHC,EAAe,0DAEI,MAAjBD,EAAQE,MACHJ,EAAOI,MAAMN,EAASC,GACI,mBAAlBG,EAAQE,MAChBF,EAAQE,MAAMJ,EAAQF,EAASC,QAEtCI,EAAe,kDAUjBR,EAAeC,UAAUS,WAAa,SAASP,EAASC,GACvD,IAECO,EAFGN,EAASC,KAAKD,OACjBE,EAAUD,KAAKC,QAKhB,GAHIA,GACHC,EAAe,+DAEQ,MAArBD,EAAQK,UAEV,OADAD,EAAMN,EAAOI,MAAMN,EAASC,cACNT,OAAQgB,EAAKR,EAC9B,GAAgC,mBAAtBI,EAAQK,UAAyB,CAEhD,IADAD,EAAMJ,EAAQK,UAAUP,EAAQD,cACdT,OACjB,OAAOgB,EAEPH,EAAe,6DAGhBA,EAAe,sDAoEjBhB,MAAMqB,UAAY,SAASR,EAAQE,GAClC,IAAIO,EAAS,GAEb,OADAA,EAAOC,MAAQC,EAAYX,EAAQE,EAASO,GACrCA,GAGRvB,EAAOC,MAAQA,MArIf,SAASgB,EAAeS,GACvB,MAAM,IAAIC,UAAUD,GASrB,SAASjB,EAAeK,EAAQE,GAC/BD,KAAKD,OAASA,EACdC,KAAKC,QAAUA,EA0DhB,SAASS,EAAYX,EAAQE,EAASO,GAEhB,mBAAXT,EACTG,EAAe,+CACJD,aAAmBZ,QAC9Ba,EAAe,iDAIhB,IAAIW,EAAS,IAAInB,EAAeK,EAAQE,GAGxC,SAASa,IACR,OAAOd,gBAAgBc,EACtBD,EAAOT,WAAWJ,KAAMe,WACxBF,EAAOjB,MAAMI,KAAMe,WAkBrB,OAfA3B,EAAO0B,EAAGf,GACVe,EAAEnB,UAAYI,EAAOJ,UACrBH,EAASsB,EAAGxB,EAASS,IAGrBS,IAAWA,EAAOQ,OAAS,WAG1B,IAAI,IAAIC,KAFRJ,EAAOd,OAAS,KAChBc,EAAOZ,QAAU,KACFa,EACdA,EAAEI,eAAeD,WAAeH,EAAEG,GAEnCH,EAAEnB,UAAY,GACdH,EAASsB,EAAG,MAGNA,EAUR,SAAS5B,MAAMa,EAAQE,GACtB,GAAGD,gBAAgBd,MAClB,OAAOwB,EAAYX,EAAQE,GAE3BC,EAAe,qCAjIjB,CAmJkB,iBAAXiB,OACNA,OAEgB,iBAATlC,OAAmBA,OAAQe"} \ No newline at end of file diff --git a/package.json b/package.json index e7a1a84b076757af75028d260d6266ef97febfa0..8381f71429c5fe346bb57a63a6e331465330ee71 100644 --- a/package.json +++ b/package.json @@ -1,17 +1,19 @@ { "name": "es6-proxy-polyfill", - "version": "1.2.0", + "version": "1.2.1", "description": "Proxy polyfill based on ES3 supports IE8, Node.js, etc.", "main": "src/es6-proxy-polyfill.js", "scripts": { - "build": "uglifyjs src/es6-proxy-polyfill.js -c -m reserved=[Proxy] --ie8 --comments --source-map -o dist/es6-proxy-polyfill.js" + "build": "uglifyjs src/es6-proxy-polyfill.js -c -m reserved=[Proxy] --ie8 --comments -o dist/es6-proxy-polyfill.js" }, "keywords": [ + "proxy", "es6-proxy", "proxy-polyfill", - "proxy", - "polyfill", - "ie8" + "ie8", + "Proxy", + "ES6-Proxy", + "IE8" ], "author": "ambit_tsai@qq.com", "license": "Apache-2.0", diff --git a/src/es6-proxy-polyfill.js b/src/es6-proxy-polyfill.js index b71ecdc56e8ba202ea40f1e85f5fb46701e2c974..59f109cd719db9a6b1bc192b54884488c9e4e46d 100644 --- a/src/es6-proxy-polyfill.js +++ b/src/es6-proxy-polyfill.js @@ -1,81 +1,82 @@ /** * ES6 Proxy Polyfill - * @version 1.2.0 + * @version 1.2.1 * @author Ambit Tsai * @license Apache-2.0 * @see {@link https://github.com/ambit-tsai/es6-proxy-polyfill} */ -;(function(global){ - if(global.Proxy) return; // return if Proxy already exist - - var noop = function(){}, + +(function (context) { + if (context.Proxy) return; // return if Proxy already exist + + var noop = function () {}, assign = Object.assign || noop, getProto = Object.getPrototypeOf || noop, setProto = Object.setPrototypeOf || noop; - + /** * Throw a type error * @param {String} message */ - function throwTypeError(message){ + function throwTypeError(message) { throw new TypeError(message); } - + /** - * The internal member constructor - * @constructor - * @param {Function} target - * @param {Object} handler - */ - function InternalMember(target, handler){ - this.target = target; // [[ProxyTarget]] - this.handler = handler; // [[ProxyHandler]] + * The internal member constructor + * @constructor + * @param {Function} target + * @param {Object} handler + */ + function InternalMember(target, handler) { + this.target = target; // [[ProxyTarget]] + this.handler = handler; // [[ProxyHandler]] } - + /** - * The [[Call]] internal method - * @param {Object} thisArg - * @param {Object} argsList - */ - InternalMember.prototype.$call = function(thisArg, argsList){ + * The [[Call]] internal method + * @param {Object} thisArg + * @param {Object} argsList + */ + InternalMember.prototype.$call = function (thisArg, argsList) { var target = this.target, handler = this.handler; - if(!handler){ - throwTypeError("Cannot perform 'call' on a proxy that has been revoked"); + if (!handler) { + throwTypeError('Cannot perform \'call\' on a proxy that has been revoked'); } - if(handler.apply == null){ + if (handler.apply == null) { return target.apply(thisArg, argsList); - }else if(typeof handler.apply === 'function'){ + } else if (typeof handler.apply === 'function') { return handler.apply(target, thisArg, argsList); - }else{ + } else { throwTypeError('Proxy handler\'s apply trap must be a function'); } }; - + /** - * The [[Construct]] internal method - * @param {Object} thisArg - * @param {Object} argsList - * @returns {Object} - */ - InternalMember.prototype.$construct = function(thisArg, argsList){ + * The [[Construct]] internal method + * @param {Object} thisArg + * @param {Object} argsList + * @returns {Object} + */ + InternalMember.prototype.$construct = function (thisArg, argsList) { var target = this.target, handler = this.handler, - obj; - if(!handler){ - throwTypeError("Cannot perform 'construct' on a proxy that has been revoked"); + result; + if (!handler) { + throwTypeError('Cannot perform \'construct\' on a proxy that has been revoked'); } - if(handler.construct == null){ - obj = target.apply(thisArg, argsList); - return obj instanceof Object? obj: thisArg; - }else if(typeof handler.construct === 'function'){ - obj = handler.construct(target, argsList); - if(obj instanceof Object){ - return obj; - }else{ + if (handler.construct == null) { + result = target.apply(thisArg, argsList); + return result instanceof Object ? result : thisArg; + } else if (typeof handler.construct === 'function') { + result = handler.construct(target, argsList); + if (result instanceof Object) { + return result; + } else { throwTypeError('Proxy handler\'s construct trap must return an object'); } - }else{ + } else { throwTypeError('Proxy handler\'s construct trap must be a function'); } }; @@ -84,45 +85,47 @@ * Create a Proxy object * @param {Function} target * @param {Object} handler - * @param {Object} result + * @param {Object} revokeResult * @returns {Function} */ - function createProxy(target, handler, result){ + function createProxy(target, handler, revokeResult) { // Check the type of arguments - if(typeof target !== 'function'){ + if (typeof target !== 'function') { throwTypeError('Proxy polyfill only support function target'); - }else if( !(handler instanceof Object) ){ + } else if (!(handler instanceof Object)) { throwTypeError('Cannot create proxy with a non-object handler'); } - - // The internal member + + // Create an internal member object var member = new InternalMember(target, handler); - - // The Proxy object - function P(){ - return this instanceof P? - member.$construct(this, arguments): + + // Create a proxy object - `P` + function P() { + return this instanceof P ? + member.$construct(this, arguments) : member.$call(this, arguments); } - - assign(P, target); // copy target's properties - P.prototype = target.prototype; // copy target's prototype - setProto(P, getProto(target)); // copy target's [[Prototype]] - - // The Proxy revocation function - result && (result.revoke = function(){ - member.target = null; - member.handler = null; - for(var key in P){ // delete proxy's properties - P.hasOwnProperty(key) && delete P[key]; - } - P.prototype = {}; // reset proxy's prototype - setProto(P, {}); // reset proxy's [[Prototype]] - }); + + assign(P, target); // copy target's properties + P.prototype = target.prototype; // copy target's prototype + setProto(P, getProto(target)); // copy target's [[Prototype]] + + if (revokeResult) { + // Set the revocation function + revokeResult.revoke = function () { + member.target = null; + member.handler = null; + for (var key in P) { // delete proxy's properties + P.hasOwnProperty(key) && delete P[key]; + } + P.prototype = {}; // reset proxy's prototype + setProto(P, {}); // reset proxy's [[Prototype]] + }; + } return P; } - + /** * The Proxy constructor * @constructor @@ -130,11 +133,11 @@ * @param {Object} handler * @returns {Function} */ - function Proxy(target, handler){ - if(this instanceof Proxy){ + function Proxy(target, handler) { + if (this instanceof Proxy) { return createProxy(target, handler); - }else{ - throwTypeError("Constructor Proxy requires 'new'"); + } else { + throwTypeError('Constructor Proxy requires \'new\''); } } @@ -144,16 +147,15 @@ * @param {Object} handler * @returns {{proxy, revoke}} */ - Proxy.revocable = function(target, handler){ + Proxy.revocable = function (target, handler) { var result = {}; result.proxy = createProxy(target, handler, result); return result; }; - - global.Proxy = Proxy; + + context.Proxy = Proxy; }( - typeof window === 'object'? - window: - // Using `this` for web workers & supports Browserify / Webpack. - typeof global==='object'? global: this + typeof window === 'object' ? + window : + typeof global === 'object' ? global : this // using `this` for web workers & supports Browserify / Webpack )); \ No newline at end of file