Comparing version 0.1.1 to 0.1.2
/*! (C) WebReflection *//** @preserve https://github.com/WebReflection/redefine */ | ||
var _=this._=function(e,m,d){function n(a,r,c,d){if(!(c instanceof v))if(c instanceof w){var e=c._,h=f.call(c,p)?!!c[p]:!0,m=f.call(c,q)&&c[q],n=f.call(c,k)&&c[k],s;c[t]=function(){b[j]=e.call(s=this);b[p]=h;b[q]=m;b[k]=n;x(s,r,b);y(b);return s[r]}}else c=(u[j]=c,u);l(d||g.defaults||{},b);l(c,b);if(f.call(c,t)||f.call(c,z))delete b[k],delete b[j];x(a,r,b);y(b);delete u[j]}function v(a){l(a,this)}function w(a){this._="function"==typeof a?a:l(a,this)||a[j]}function g(a,b,c,d){if("string"==typeof b)n(a, | ||
b,c,d);else for(var e in b)f.call(b,e)&&n(a,e,b[e],c);return a}var p="configurable",q="enumerable",t="get",z="set",j="value",k="writable",x=e.defineProperty||d.defineProperty,f=e.hasOwnProperty||d.hasOwnProperty,A=e.create||e.inherit||d.create;d=[p,q,t,z,j,k];var y=m("o","delete o."+d.join(";delete o.")),b=A(null),u={},h,l;for(h=0;h<d.length;h++)d[h]=["if(h.call(a,'","'))b.","=a.",";"].join(d[h]);l=m("h","return function(a,b){"+d.join("")+"}")(f);g.as=function(a){return new v(a)};g.from=function(a, | ||
b,c){a=A("function"==typeof a?a.prototype:a);return b?g(a,b,c):a};g.later=function(a){return new w(a)};g.defaults={};e.redefine=g;return e}(_||this,Function,Object); | ||
var _=this._=function(f,m,d){function n(a,r,c,d){if(!(c instanceof v))if(c instanceof w){var f=c._,h=g.call(c,p)?!!c[p]:!0,m=g.call(c,q)&&c[q],n=g.call(c,k)&&c[k],s;c[t]=function(){b[j]=f.call(s=this);b[p]=h;b[q]=m;b[k]=n;x(s,r,b);y(b);return s[r]}}else c=(u[j]=c,u);l(d||e.defaults||{},b);l(c,b);if(g.call(c,t)||g.call(c,z))delete b[k],delete b[j];x(a,r,b);y(b);delete u[j]}function v(a){l(a,this)}function w(a){this._="function"==typeof a?a:l(a,this)||a[j]}function e(a,b,c,d){if("string"==typeof b)n(a, | ||
b,c,d);else for(var e in b)g.call(b,e)&&n(a,e,b[e],c);return a}var p="configurable",q="enumerable",t="get",z="set",j="value",k="writable",x=f.defineProperty||d.defineProperty,g=f.hasOwnProperty||d.hasOwnProperty,A=f.create||f.inherit||d.create;d=[p,q,t,z,j,k];var y=m("o","delete o."+d.join(";delete o.")),b=A(null),u={},h,l;for(h=0;h<d.length;h++)d[h]=["if(h.call(a,'","'))b.","=a.",";"].join(d[h]);l=m("h","return function(a,b){"+d.join("")+"}")(g);e.as=function(a){return new v(a)};e.from=function(a, | ||
b,c){a=A("function"==typeof a?a.prototype:a);return b?e(a,b,c):a};e.later=function(a){return new w(a)};e.defaults={};"undefined"!==typeof module&&module.exports&&((module.exports=e).redefine=e);f.redefine=e;return f}(_||this,Function,Object); |
89
HOWTO.md
@@ -100,3 +100,3 @@ redefine VS ES5 | ||
#### Real World Example: An Emitter Class | ||
This a simplified `Emitter` class with completely memory safe logic. | ||
This a simplified `Emitter` class with a logic optimized to save some memory and GC cycle. | ||
@@ -152,4 +152,7 @@ // generic basic Emitter constructor | ||
Long story short: we can create 100 instances of `Emitter` and the amount of objects will be exactly `100 + 2` included the `Emitter` function and its prototype. Only when used, the `_handlers` object is created once and set as property to avoid calling the getter per each access. When listeners are removed, both Array used as type list and `_handlers` are removed, if empty. In order to obtain the same behavior in ES5: | ||
Long story short: we can create 100 instances of `Emitter` and the amount of extra objects will be exactly `100` instead of `200` considering a handler created during initialization. | ||
With this pattern, only when the `_handlers` object is needed is created once per instance and set as property to avoid calling the getter per each access. | ||
When listeners are removed, both Array used as type list and `_handlers` are removed, if empty. In order to obtain the same behavior in ES5: | ||
// ES5 | ||
@@ -209,13 +212,95 @@ Object.defineProperties( | ||
#### Real World Example: A Safer Definition | ||
While `Object.defineProperties(object, descriptorsList)` second argument loops only through `hasOwnProperty(key)`, once it comes to property definition, and the same is for `Object.defineProperty(obj, key, descriptor)`, the object used to described the property looks up for inherited properties too and consider them. | ||
Even if defaults are `{writable: false, enumerable: false, configurable: false}`, it's easy to make every property `enumerable` and `configurable` simply doing this: | ||
Object.prototype.configurable = true; | ||
Object.prototype.enumerable = true; | ||
After above malicious piece of code, if you think a constant variable defined like this cannot be changed you are wrong: | ||
Object.defineProperty(window, "myLibrary", {value:myLibrary}); | ||
It is necessary indeed to ensure that defaults are written as well, making defaults meaningless because of inheritance, but even worse, if a malicious code will write `Object.prototype.writable = true` and there are getters or setters involved, these will all throw an exception because `writable` does not accept getters or setters. | ||
##### How To Prevent Problems in ES5 | ||
In ES5 every descriptor should inherit from `null` otherwise no descriptor will be immune from possible attacks. | ||
Here an example of few problems we might want to avoid: | ||
// set up the nasty environment | ||
Object.prototype.configurable = | ||
Object.prototype.enumerable = | ||
Object.prototype.writable = true; | ||
// verify that there are actually problems | ||
try { | ||
Object.defineProperty(this, "problem", {get: function () { | ||
return "we gonna have bad time"; | ||
}}); | ||
} catch(o_O) { | ||
console.log("ouch!"); | ||
Object.defineProperty(this, "problem", {value:true}); | ||
console.log(this.propertyIsEnumerable("problem")); // true | ||
this.problem = {}; // no problems | ||
delete this.problem; // true again | ||
} | ||
Accordingly, every single descriptor should be created via `Object.crete(null)` so our code should look like | ||
function descriptor(object) { | ||
// now don't take this wrong | ||
// but this function is almost | ||
// as big as the whole redefine.js library | ||
// I would not go through this pattern | ||
for (var | ||
nullDescriptor = Object.create(null), | ||
properties = [ | ||
"configurable", | ||
"enumerable", | ||
"writable", | ||
"get", | ||
"set", | ||
"value" | ||
], | ||
i = properties.length; i--; | ||
object.hasOwnProperty(properties[i]) && ( | ||
nullDescriptor[properties[i]] = object[properties[i]] | ||
) | ||
); | ||
return nullDescriptor; | ||
} | ||
Object.defineProperty(this, "problem", descriptor({ | ||
value: "now we talk" | ||
})); | ||
this.propertyIsEnumerable("problem"); // false | ||
this.problem = {}; // nope | ||
delete this.problem; // false | ||
this.problem; // "now we talk" | ||
Got it? Now ... | ||
##### How To Prevent Problems in redefine.js | ||
redefine(this, "problem", "solved"); | ||
this.propertyIsEnumerable("problem"); // false | ||
this.problem = {}; // nope | ||
delete this.problem; // false | ||
this.problem; // "solved" | ||
If you are wondering about **performance** there are many things to consider behind `redefine.js` and one of these is that performance are really good for what it offers. | ||
While is usually slightly slower on desktop, `redefine.js` is [almost as fast in older Android 2.3 devices](http://jsperf.com/redefine-js) where performance matters the most. | ||
`redefine.js` is indeed suitable for mobile phones, even if quite old! | ||
{ | ||
"name": "redefine", | ||
"version": "0.1.1", | ||
"version": "0.1.2", | ||
"description": "A lightweight utility for an easier ES5 aware object properties definition introducing new, performance oriented, patterns.", | ||
@@ -5,0 +5,0 @@ "homepage": "https://github.com/WebReflection/redefine", |
@@ -173,2 +173,7 @@ var _ = this._ = function(_, Function, Object) { | ||
// var redefine = require("redefine"); | ||
if ("undefined" !== typeof module && module.exports) { | ||
(module.exports = redefine).redefine = redefine; | ||
} | ||
// there you are ... | ||
@@ -175,0 +180,0 @@ _.redefine = redefine; |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
50302
508