Socket
Socket
Sign inDemoInstall

jsface

Package Overview
Dependencies
0
Maintainers
1
Versions
8
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 2.3.0 to 2.4.9

gulpfile.js

15

bower.json
{
"name": "jsface"
"name": "jsface",
"version": "2.4.9",
"main": "jsface.js",
"ignore": [
".gitignore",
".travis.yml",
"CHANGELOG.txt",
"package.json",
"README.md",
"Gruntfile.js",
"dist",
"samples",
"test"
]
}

@@ -0,1 +1,30 @@

v2.4.9 Jul 23, 2015
----------------------------------------------------------------
* Support getter/setter on mixins
v2.4.6 Jun 24, 2015
----------------------------------------------------------------
* Implement $const plugin (thanks to Federico Budassi)
v2.4.5 May 26, 2015
----------------------------------------------------------------
* Rename $static to $statics ($statics will be removed in 2.5.0)
v2.4.2 May 22, 2015
----------------------------------------------------------------
* Fix undefined issue caused by getter/setter impl
v2.4.1 Apr 25, 2015
----------------------------------------------------------------
* Merge Milos Zikic's getter/setter support
v2.4.0 Mar 07, 2015
----------------------------------------------------------------
* Remove static properties from instance (#25). Class level only
* Integrate jsface.$ready plugin into core
* Remove jsface.stringOrNil, sorry if it breaks ;-)
* Fix (#26) - Thanks Freddy Snijder!
* Fix (#12)
* More unit tests
v2.3.0 Dec 02, 2014

@@ -74,2 +103,2 @@ ----------------------------------------------------------------

* Initial release. A complete new look from version 1.2a which
was developed for browsers.
was developed for browsers.

165

dist/jsface.js

@@ -5,6 +5,6 @@ /*

*
* Copyright (c) 2009-2013 Tan Nhu
* Copyright (c) Tan Nhu
* Licensed under MIT license (https://github.com/tnhu/jsface/blob/master/LICENSE.txt)
*/
(function(context, OBJECT, NUMBER, LENGTH, toString, undefined, oldClass, jsface) {
(function(context, OBJECT, NUMBER, LENGTH, toString, readyFns, readyCount, undefined, oldClass, jsface) {
/**

@@ -32,9 +32,2 @@ * Return a map itself or null. A map is a set of { key: value }

/**
* Return a string itself or null
* @param obj object to be checked
* @return obj itself as a string or null
*/
function stringOrNil(obj) { return (toString.apply(obj) === "[object String]" && obj) || null; }
/**
* Return a class itself or null

@@ -58,3 +51,2 @@ * @param obj object to be checked

object[key] = value;
if (iClass) { oPrototype[key] = value; } // class? copy to prototype as well
}

@@ -80,3 +72,3 @@ }

// copy static properties and prototype.* to object
if (mapOrNil(subject)) {
if (mapOrNil(subject) || iClass) {
for (key in subject) {

@@ -100,2 +92,22 @@ copier(key, subject[key], ignoredKeys, object, iClass, oPrototype);

/**
* To make object fully immutable, freeze each object inside it.
* @param object to deep freeze
*/
function deepFreeze(object) {
var prop, propKey;
Object.freeze(object); // first freeze the object
for (propKey in object) {
prop = object[propKey];
if (!object.hasOwnProperty(propKey) || !(typeof prop === 'object') || Object.isFrozen(prop)) {
// If the object is on the prototype, not an object, or is already frozen,
// skip it. Note that this might leave an unfrozen reference somewhere in the
// object if there is an already frozen object containing an unfrozen object.
continue;
}
deepFreeze(prop); // recursively call deepFreeze
}
}
/**
* Create a class.

@@ -108,8 +120,10 @@ * @param parent parent class(es)

if ( !api) {
parent = (api = parent, 0); // !api means there's no parent
parent = (api = parent, 0); // !api means there's no parent
}
// TODO remove $statics, use $static instead
var clazz, constructor, singleton, statics, key, bindTo, len, i = 0, p,
ignoredKeys = { constructor: 1, $singleton: 1, $statics: 1, prototype: 1, $super: 1, $superp: 1, main: 1, toString: 0 },
plugins = Class.plugins;
ignoredKeys = { constructor: 1, $singleton: 1, $static:1, $statics: 1, prototype: 1, $super: 1, $superp: 1, main: 1, toString: 0 },
plugins = Class.plugins,
rootParent, parentClass, Stub;

@@ -119,3 +133,3 @@ api = (typeof api === "function" ? api() : api) || {}; // execute api if it's a function

singleton = api.$singleton;
statics = api.$statics;
statics = api.$statics || api.$static;

@@ -126,11 +140,24 @@ // add plugins' keys into ignoredKeys

// construct constructor
clazz = singleton ? {} : (constructor ? constructor : function(){});
clazz = singleton ? function(){} : (constructor ? constructor : function(){});
// make sure parent is always an array
parent = !parent || arrayOrNil(parent) ? parent : [ parent ];
parent = !parent || parent instanceof Array ? parent : [ parent ];
len = parent && parent.length;
rootParent = parent[0];
if ( !singleton && len) {
clazz.prototype = classOrNil(parent[0]) ? new parent[0] : parent[0];
clazz.prototype.constructor = clazz;
parentClass = rootParent.prototype && rootParent === rootParent.prototype.constructor && rootParent;
if ( !parentClass) {
clazz.prototype = rootParent;
} else {
// Constributed by Freddy Snijder (https://github.com/tnhu/jsface/issues/26)
Stub = function(){};
Stub.prototype = parentClass.prototype;
Stub.prototype.constructor = Stub;
clazz.prototype = new Stub();
clazz.prototype.constructor = clazz; // restoring proper constructor for child class
parentClass.prototype.constructor = parentClass; // restoring proper constructor for parent class
}
}

@@ -141,12 +168,19 @@

// do inherit
// do inherit static properties and extentions (parents other than the first one)
while (i < len) {
p = parent[i++];
// copy static properties
for (key in p) {
if ( !ignoredKeys[key]) {
bindTo[key] = p[key];
if ( !singleton) { clazz[key] = p[key]; }
clazz[key] = p[key];
}
}
for (key in p.prototype) { if ( !ignoredKeys[key]) { bindTo[key] = p.prototype[key]; } }
if ( !singleton && i !== 0) {
for (key in p.prototype) {
if ( !ignoredKeys[key]) {
bindTo[key] = p.prototype[key];
}
}
}
}

@@ -157,18 +191,26 @@

if ( !ignoredKeys[key]) {
bindTo[key] = api[key];
var prop = api[key];
if (prop && (prop.get || prop.set)) { // check if it is a property descriptor
prop.enumerable = true;
Object.defineProperty(bindTo, key, prop);
} else {
bindTo[key] = prop;
}
}
}
// copy static properties from statics to both clazz and bindTo
for (key in statics) { clazz[key] = bindTo[key] = statics[key]; }
// if class is not a singleton, add $super and $superp
if ( !singleton) {
p = parent && parent[0] || parent;
clazz.$super = p;
clazz.$superp = p && p.prototype ? p.prototype : p;
// copy static properties from statics to clazz
for (key in statics) {
clazz[key] = statics[key];
}
for (key in plugins) { plugins[key](clazz, parent, api); } // pass control to plugins
if (functionOrNil(api.main)) { api.main.call(clazz, clazz); } // execute main()
// add $super and $superp to refer to parent class and parent.prototype (if applied)
p = parent && rootParent || parent;
clazz.$super = p;
clazz.$superp = p && p.prototype || p;
for (key in plugins) { plugins[key](clazz, parent, api); } // pass control to plugins
if (typeof api.main === "function") { api.main.call(clazz, clazz); } // execute main()
return clazz;

@@ -178,4 +220,54 @@ }

/* Class plugins repository */
Class.plugins = {};
Class.plugins = {
$ready: function invoke(clazz, parent, api, loop) {
var r = api.$ready,
len = parent ? parent.length : 0,
count = len,
_super = len && parent[0].$super,
pa, i, entry;
// find and invoke $ready from parent(s)
while (len--) {
for (i = 0; i < readyCount; i++) {
entry = readyFns[i];
pa = parent[len];
if (pa === entry[0]) {
entry[1].call(pa, clazz, parent, api);
count--;
}
if ( !count) { break; }
}
}
// call $ready from grandparent(s), if any
if (_super) {
invoke(clazz, [ _super ], api, true);
}
// in an environment where there are a lot of class creating/removing (rarely)
// this implementation might cause a leak (saving pointers to clazz and $ready)
if ( !loop && functionOrNil(r)) {
r.call(clazz, clazz, parent, api); // invoke ready from current class
readyFns.push([ clazz, r ]);
readyCount++;
}
},
$const: function (clazz, parent, api) {
var key,
consts = api.$const;
// copy immutable properties from consts to clazz and freeze them recursively
for (key in consts) {
Object.defineProperty(clazz, key, { enumerable: true, value: consts[key] }); // enumerable for proper inheritance
if ((typeof clazz[key] === 'object') && !Object.isFrozen(clazz[key])) {
deepFreeze(clazz[key]); // if property is an unfrozen object, freeze it recursively
}
}
}
};
/* Initialization */

@@ -188,3 +280,2 @@ jsface = {

functionOrNil: functionOrNil,
stringOrNil : stringOrNil,
classOrNil : classOrNil

@@ -201,2 +292,2 @@ };

}
})(this, "object", "number", "length", Object.prototype.toString);
})(this, "object", "number", "length", Object.prototype.toString, [], 0);

@@ -1,5 +0,1 @@

/*
* JSFace Object Oriented Programming Library.
* Copyright (c) 2009-2013 Tan Nhu, http://lnkd.in/tnhu
*/
!function(a,b,c,d,e,f,g,h){function i(a){return a&&typeof a===b&&!(typeof a.length===c&&!a.propertyIsEnumerable(d))&&a||null}function j(a){return a&&typeof a===b&&typeof a.length===c&&!a.propertyIsEnumerable(d)&&a||null}function k(a){return a&&"function"==typeof a&&a||null}function l(a){return"[object String]"===e.apply(a)&&a||null}function m(a){return k(a)&&a.prototype&&a===a.prototype.constructor&&a||null}function n(a,b,c,d,e,f){c&&c.hasOwnProperty(a)||(d[a]=b,e&&(f[a]=b))}function o(a,b,c){if(j(b))for(var d=b.length;--d>=0;)o(a,b[d],c);else{c=c||{constructor:1,$super:1,prototype:1,$superp:1};var e,f,g=m(a),h=m(b),k=a.prototype;if(i(b))for(e in b)n(e,b[e],c,a,g,k);if(h){f=b.prototype;for(e in f)n(e,f[e],c,a,g,k)}g&&h&&o(k,b.prototype,c)}}function p(a,b){b||(b=a,a=0);var c,d,e,f,g,h,i,l,n=0,o={constructor:1,$singleton:1,$statics:1,prototype:1,$super:1,$superp:1,main:1,toString:0},q=p.plugins;b=("function"==typeof b?b():b)||{},d=b.hasOwnProperty("constructor")?b.constructor:0,e=b.$singleton,f=b.$statics;for(g in q)o[g]=1;for(c=e?{}:d?d:function(){},a=!a||j(a)?a:[a],i=a&&a.length,!e&&i&&(c.prototype=m(a[0])?new a[0]:a[0],c.prototype.constructor=c),h=e?c:c.prototype;i>n;){l=a[n++];for(g in l)o[g]||(h[g]=l[g],e||(c[g]=l[g]));for(g in l.prototype)o[g]||(h[g]=l.prototype[g])}for(g in b)o[g]||(h[g]=b[g]);for(g in f)c[g]=h[g]=f[g];e||(l=a&&a[0]||a,c.$super=l,c.$superp=l&&l.prototype?l.prototype:l);for(g in q)q[g](c,a,b);return k(b.main)&&b.main.call(c,c),c}p.plugins={},h={Class:p,extend:o,mapOrNil:i,arrayOrNil:j,functionOrNil:k,stringOrNil:l,classOrNil:m},"undefined"!=typeof module&&module.exports?module.exports=h:(g=a.Class,a.Class=p,a.jsface=h,h.noConflict=function(){a.Class=g})}(this,"object","number","length",Object.prototype.toString);
!function(t,o,r,e,n,p,c,i,u,f){function s(t){return t&&typeof t===o&&!(typeof t.length===r&&!t.propertyIsEnumerable(e))&&t||null}function l(t){return t&&typeof t===o&&typeof t.length===r&&!t.propertyIsEnumerable(e)&&t||null}function y(t){return t&&"function"==typeof t&&t||null}function a(t){return y(t)&&t.prototype&&t===t.prototype.constructor&&t||null}function $(t,o,r,e,n,p){r&&r.hasOwnProperty(t)||(e[t]=o)}function b(t,o,r){if(l(o))for(var e=o.length;--e>=0;)b(t,o[e],r);else{r=r||{constructor:1,$super:1,prototype:1,$superp:1};var n,p,c=a(t),i=a(o),u=t.prototype;if(s(o)||c)for(n in o)$(n,o[n],r,t,c,u);if(i){p=o.prototype;for(n in p)$(n,p[n],r,t,c,u)}c&&i&&b(u,o.prototype,r)}}function g(t){var o,r;Object.freeze(t);for(r in t)o=t[r],t.hasOwnProperty(r)&&"object"==typeof o&&!Object.isFrozen(o)&&g(o)}function O(t,o){o||(o=t,t=0);var r,e,n,p,c,i,u,f,s,l,y,a=0,$={constructor:1,$singleton:1,$static:1,$statics:1,prototype:1,$super:1,$superp:1,main:1,toString:0},b=O.plugins;o=("function"==typeof o?o():o)||{},e=o.hasOwnProperty("constructor")?o.constructor:0,n=o.$singleton,p=o.$statics||o.$static;for(c in b)$[c]=1;for(r=n?function(){}:e?e:function(){},t=!t||t instanceof Array?t:[t],u=t&&t.length,s=t[0],!n&&u&&(l=s.prototype&&s===s.prototype.constructor&&s,l?(y=function(){},y.prototype=l.prototype,y.prototype.constructor=y,r.prototype=new y,r.prototype.constructor=r,l.prototype.constructor=l):r.prototype=s),i=n?r:r.prototype;u>a;){f=t[a++];for(c in f)$[c]||(r[c]=f[c]);if(!n&&0!==a)for(c in f.prototype)$[c]||(i[c]=f.prototype[c])}for(c in o)if(!$[c]){var g=o[c];g&&(g.get||g.set)?(g.enumerable=!0,Object.defineProperty(i,c,g)):i[c]=g}for(c in p)r[c]=p[c];f=t&&s||t,r.$super=f,r.$superp=f&&f.prototype||f;for(c in b)b[c](r,t,o);return"function"==typeof o.main&&o.main.call(r,r),r}O.plugins={$ready:function m(t,o,r,e){for(var n,i,u,f=r.$ready,s=o?o.length:0,l=s,a=s&&o[0].$super;s--;)for(i=0;c>i&&(u=p[i],n=o[s],n===u[0]&&(u[1].call(n,t,o,r),l--),l);i++);a&&m(t,[a],r,!0),!e&&y(f)&&(f.call(t,t,o,r),p.push([t,f]),c++)},$const:function(t,o,r){var e,n=r.$const;for(e in n)Object.defineProperty(t,e,{enumerable:!0,value:n[e]}),"object"!=typeof t[e]||Object.isFrozen(t[e])||g(t[e])}},f={Class:O,extend:b,mapOrNil:s,arrayOrNil:l,functionOrNil:y,classOrNil:a},"undefined"!=typeof module&&module.exports?module.exports=f:(u=t.Class,t.Class=O,t.jsface=f,f.noConflict=function(){t.Class=u})}(this,"object","number","length",Object.prototype.toString,[],0);

@@ -5,3 +5,3 @@ /*

*
* Copyright (c) 2009-2012 Tan Nhu
* Copyright (c) Tan Nhu
* Licensed under MIT license (https://github.com/tnhu/jsface/blob/master/LICENSE.txt).

@@ -21,4 +21,2 @@ */

ADVISOR = "___advisors___",
INVALID = "Invalid ",
NON_FUNC = "Non-function property named ",
noop = function(){};

@@ -135,11 +133,13 @@

iConstructor = (key === "constructor");
iStatic = iClass && bindTo[key] === clazz[key];
fn = restore(iConstructor && iClass && clazz || bindTo[key], advisor);
iStatic = iClass && clazz[key];
constructor = constructor || (iConstructor && fn);
if (fn && !iConstructor) {
bindTo[key] = fn;
if (iStatic) {
clazz[key] = fn;
if (key === "constructor" && iClass) {
constructor = restore(iClass, advisor);;
} else {
if (clazz[key]) {
clazz[key] = restore(clazz[key], advisor);
}
if (bindTo[key]) {
bindTo[key] = restore(bindTo[key], advisor);
}
}

@@ -153,12 +153,7 @@ }

for (var name in bindTo) {
var fn = bindTo[name],
iStatic = iClass && bindTo[name] === clazz[name];
bindTo[name] = restore(fn) || bindTo[name];
// restore static method
if (iStatic) {
clazz[name] = bindTo[name];
}
bindTo[name] = restore(bindTo[name]) || bindTo[name];
}
for (var name in clazz) {
clazz[name] = restore(clazz[name]) || clazz[name];
}
} else { // type 2: "remove", advisor

@@ -171,3 +166,3 @@ doRestore(advisor, advisor);

} else {
throw INVALID + "params";
throw "Invalid params";
}

@@ -181,3 +176,3 @@ return constructor || clazz;

jsface.pointcut = function pointcut(clazz, opts) {
var iClass = functionOrNil(clazz),
var iClass = classOrNil(clazz) || functionOrNil(clazz),
iInstance = mapOrNil(clazz),

@@ -189,3 +184,3 @@ iRemove = (/^remove ?/.exec(opts) !== null),

if ( !(iClass || iInstance) || !(mapOrNil(opts) || iRemove)) {
throw INVALID + "params";
throw "Invalid params";
}

@@ -204,10 +199,10 @@ bindTo = iClass ? clazz.prototype : clazz;

after = mapOrNil(pointcuts) && !pointcuts.after ? noop : pointcuts.after,
isStatic;
isStatic, found = false;
// check if before & after are valid
if ( !functionOrNil(before)) {
throw INVALID + method + ":before";
throw "Invalid " + method + ":before";
}
if ( !functionOrNil(after)) {
throw INVALID + method + ":after";
throw "Invalid " + method + ":after";
}

@@ -219,3 +214,3 @@

} else {
throw NON_FUNC + method;
throw "Non-function property named " + method + " on instance";
}

@@ -226,9 +221,15 @@ } else {

} else {
if (functionOrNil(bindTo[method])) {
isStatic = iClass && bindTo[method] === clazz[method];
if (functionOrNil(clazz[method])) { // static method
clazz[method] = wrap(clazz[method], before, after, opts);
found = true;
}
if (functionOrNil(bindTo[method])) { // normal (non-static) method
bindTo[method] = wrap(bindTo[method], before, after, opts);
if (isStatic) { clazz[method] = bindTo[method]; }
} else {
throw NON_FUNC + method;
found = true;
}
if ( !found) {
throw "Non-function property named " + method + " on class";
}
}

@@ -235,0 +236,0 @@ }

@@ -1,5 +0,1 @@

/*
* JSFace Object Oriented Programming Library.
* Copyright (c) 2009-2013 Tan Nhu, http://lnkd.in/tnhu
*/
!function(a){function b(a,b,c,d){function e(){for(var a,b,c=e[k],d=c.length,f=e[l],g=f.length,h=e[m];d--;)if(b=c[d].apply(this,arguments),i(b)&&b.$skip===!0)return b.$data;for(a=h.apply(this,arguments);g--;)if(b=f[g].apply(this,arguments),i(b)&&b.$skip===!0)return a;return a}return a[j]===a?(a[k].push(b),a[l].push(c),a[n].push(d),a):(h(e,a,0,!0),f(a)&&(e.prototype=a.prototype),e[k]=[b],e[l]=[c],e[m]=a,e[n]=[d],e[j]=e,e.$super=a.$super,e.$superp=a.$superp,e)}function c(a,b){var d,e,f;if(a&&a===a[j])if(b){for(e=f=a[n].length;e--&&a[n][e]!==b;);if(e>=0){if(1===f)return c(a);a[n].splice(e,1),a[k].splice(e,1),a[l].splice(e,1)}}else d=a[m],delete a[m],delete a[n],delete a[k],delete a[l],delete a[j];return d}function d(a,b,d,e,f,g){function h(b,d){var f,h,j,k,l;for(f in b)h=f/1==f?b[f]:f,j="constructor"===h,k=e&&g[h]===a[h],l=c(j&&e&&a||g[h],d),i=i||j&&l,l&&!j&&(g[h]=l,k&&(a[h]=l))}var i,k,l,n;if("remove"===b)if(d)h(d,d);else{i=e&&a===a[j]&&a[m];for(var p in g){var n=g[p],q=e&&g[p]===a[p];g[p]=c(n)||g[p],q&&(a[p]=g[p])}}else{if(null===(k=/^remove /.exec(b)))throw o+"params";l=b.replace(k,"").split(" "),h(l)}return i||a}var e=a.jsface||require("./jsface"),f=(e.Class,e.classOrNil),g=e.functionOrNil,h=e.extend,i=e.mapOrNil,j="___wrapper___",k="___before_fns___",l="___after_fns___",m="___origin_fn___",n="___advisors___",o="Invalid ",p="Non-function property named ",q=function(){};e.pointcut=function(a,c){var e,f,h,j=g(a),k=i(a),l=null!==/^remove ?/.exec(c),m=l&&arguments[2];if(!j&&!k||!i(c)&&!l)throw o+"params";if(e=j?a.prototype:a,l)return d(a,c,m,j,k,e);for(f in c){h=c[f],h=g(h)?{before:h}:h;var n,r=i(h)&&!h.before?q:h.before,s=i(h)&&!h.after?q:h.after;if(!g(r))throw o+f+":before";if(!g(s))throw o+f+":after";if(k){if(!g(e[f]))throw p+f;e[f]=b(e[f],r,s,c)}else if("constructor"===f)a=b(a,r,s,c);else{if(!g(e[f]))throw p+f;n=j&&e[f]===a[f],e[f]=b(e[f],r,s,c),n&&(a[f]=e[f])}}return a},"undefined"!=typeof module&&module.exports&&(module.exports=e.pointcut)}(this);
!function(e){function r(e,r,t,n){function o(){for(var e,r,t=o[p],n=t.length,i=o[l],f=i.length,s=o[_];n--;)if(r=t[n].apply(this,arguments),u(r)&&r.$skip===!0)return r.$data;for(e=s.apply(this,arguments);f--;)if(r=i[f].apply(this,arguments),u(r)&&r.$skip===!0)return e;return e}return e[a]===e?(e[p].push(r),e[l].push(t),e[c].push(n),e):(s(o,e,0,!0),i(e)&&(o.prototype=e.prototype),o[p]=[r],o[l]=[t],o[_]=e,o[c]=[n],o[a]=o,o.$super=e.$super,o.$superp=e.$superp,o)}function t(e,r){var n,o,i;if(e&&e===e[a])if(r){for(o=i=e[c].length;o--&&e[c][o]!==r;);if(o>=0){if(1===i)return t(e);e[c].splice(o,1),e[p].splice(o,1),e[l].splice(o,1)}}else n=e[_],delete e[_],delete e[c],delete e[p],delete e[l],delete e[a];return n}function n(e,r,n,o,i,f){function s(r,n){var i,s,a,p;for(i in r)s=i/1==i?r[i]:i,a="constructor"===s,p=o&&e[s],"constructor"===s&&o?u=t(o,n):(e[s]&&(e[s]=t(e[s],n)),f[s]&&(f[s]=t(f[s],n)))}var u,p,l;if("remove"===r)if(n)s(n,n);else{u=o&&e===e[a]&&e[_];for(var c in f)f[c]=t(f[c])||f[c];for(var c in e)e[c]=t(e[c])||e[c]}else{if(null===(p=/^remove /.exec(r)))throw"Invalid params";l=r.replace(p,"").split(" "),s(l)}return u||e}var o=e.jsface||require("./jsface"),i=(o.Class,o.classOrNil),f=o.functionOrNil,s=o.extend,u=o.mapOrNil,a="___wrapper___",p="___before_fns___",l="___after_fns___",_="___origin_fn___",c="___advisors___",d=function(){};o.pointcut=function(e,t){var o,s,a,p=i(e)||f(e),l=u(e),_=null!==/^remove ?/.exec(t),c=_&&arguments[2];if(!p&&!l||!u(t)&&!_)throw"Invalid params";if(o=p?e.prototype:e,_)return n(e,t,c,p,l,o);for(s in t){a=t[s],a=f(a)?{before:a}:a;var v=u(a)&&!a.before?d:a.before,h=u(a)&&!a.after?d:a.after,m=!1;if(!f(v))throw"Invalid "+s+":before";if(!f(h))throw"Invalid "+s+":after";if(l){if(!f(o[s]))throw"Non-function property named "+s+" on instance";o[s]=r(o[s],v,h,t)}else if("constructor"===s)e=r(e,v,h,t);else if(f(e[s])&&(e[s]=r(e[s],v,h,t),m=!0),f(o[s])&&(o[s]=r(o[s],v,h,t),m=!0),!m)throw"Non-function property named "+s+" on class"}return e},"undefined"!=typeof module&&module.exports&&(module.exports=o.pointcut)}(this);

@@ -5,6 +5,6 @@ /*

*
* Copyright (c) 2009-2013 Tan Nhu
* Copyright (c) Tan Nhu
* Licensed under MIT license (https://github.com/tnhu/jsface/blob/master/LICENSE.txt)
*/
(function(context, OBJECT, NUMBER, LENGTH, toString, undefined, oldClass, jsface) {
(function(context, OBJECT, NUMBER, LENGTH, toString, readyFns, readyCount, undefined, oldClass, jsface) {
/**

@@ -32,9 +32,2 @@ * Return a map itself or null. A map is a set of { key: value }

/**
* Return a string itself or null
* @param obj object to be checked
* @return obj itself as a string or null
*/
function stringOrNil(obj) { return (toString.apply(obj) === "[object String]" && obj) || null; }
/**
* Return a class itself or null

@@ -58,3 +51,2 @@ * @param obj object to be checked

object[key] = value;
if (iClass) { oPrototype[key] = value; } // class? copy to prototype as well
}

@@ -80,3 +72,3 @@ }

// copy static properties and prototype.* to object
if (mapOrNil(subject)) {
if (mapOrNil(subject) || iClass) {
for (key in subject) {

@@ -100,2 +92,22 @@ copier(key, subject[key], ignoredKeys, object, iClass, oPrototype);

/**
* To make object fully immutable, freeze each object inside it.
* @param object to deep freeze
*/
function deepFreeze(object) {
var prop, propKey;
Object.freeze(object); // first freeze the object
for (propKey in object) {
prop = object[propKey];
if (!object.hasOwnProperty(propKey) || !(typeof prop === 'object') || Object.isFrozen(prop)) {
// If the object is on the prototype, not an object, or is already frozen,
// skip it. Note that this might leave an unfrozen reference somewhere in the
// object if there is an already frozen object containing an unfrozen object.
continue;
}
deepFreeze(prop); // recursively call deepFreeze
}
}
/**
* Create a class.

@@ -108,8 +120,10 @@ * @param parent parent class(es)

if ( !api) {
parent = (api = parent, 0); // !api means there's no parent
parent = (api = parent, 0); // !api means there's no parent
}
// TODO remove $statics, use $static instead
var clazz, constructor, singleton, statics, key, bindTo, len, i = 0, p,
ignoredKeys = { constructor: 1, $singleton: 1, $statics: 1, prototype: 1, $super: 1, $superp: 1, main: 1, toString: 0 },
plugins = Class.plugins;
ignoredKeys = { constructor: 1, $singleton: 1, $static:1, $statics: 1, prototype: 1, $super: 1, $superp: 1, main: 1, toString: 0 },
plugins = Class.plugins,
rootParent, parentClass, Stub;

@@ -119,3 +133,3 @@ api = (typeof api === "function" ? api() : api) || {}; // execute api if it's a function

singleton = api.$singleton;
statics = api.$statics;
statics = api.$statics || api.$static;

@@ -126,11 +140,24 @@ // add plugins' keys into ignoredKeys

// construct constructor
clazz = singleton ? {} : (constructor ? constructor : function(){});
clazz = singleton ? function(){} : (constructor ? constructor : function(){});
// make sure parent is always an array
parent = !parent || arrayOrNil(parent) ? parent : [ parent ];
parent = !parent || parent instanceof Array ? parent : [ parent ];
len = parent && parent.length;
rootParent = parent[0];
if ( !singleton && len) {
clazz.prototype = classOrNil(parent[0]) ? new parent[0] : parent[0];
clazz.prototype.constructor = clazz;
parentClass = rootParent.prototype && rootParent === rootParent.prototype.constructor && rootParent;
if ( !parentClass) {
clazz.prototype = rootParent;
} else {
// Constributed by Freddy Snijder (https://github.com/tnhu/jsface/issues/26)
Stub = function(){};
Stub.prototype = parentClass.prototype;
Stub.prototype.constructor = Stub;
clazz.prototype = new Stub();
clazz.prototype.constructor = clazz; // restoring proper constructor for child class
parentClass.prototype.constructor = parentClass; // restoring proper constructor for parent class
}
}

@@ -141,12 +168,19 @@

// do inherit
// do inherit static properties and extentions (parents other than the first one)
while (i < len) {
p = parent[i++];
// copy static properties
for (key in p) {
if ( !ignoredKeys[key]) {
bindTo[key] = p[key];
if ( !singleton) { clazz[key] = p[key]; }
clazz[key] = p[key];
}
}
for (key in p.prototype) { if ( !ignoredKeys[key]) { bindTo[key] = p.prototype[key]; } }
if ( !singleton && i !== 0) {
for (key in p.prototype) {
if ( !ignoredKeys[key]) {
bindTo[key] = p.prototype[key];
}
}
}
}

@@ -157,18 +191,26 @@

if ( !ignoredKeys[key]) {
bindTo[key] = api[key];
var prop = api[key];
if (prop && (prop.get || prop.set)) { // check if it is a property descriptor
prop.enumerable = true;
Object.defineProperty(bindTo, key, prop);
} else {
bindTo[key] = prop;
}
}
}
// copy static properties from statics to both clazz and bindTo
for (key in statics) { clazz[key] = bindTo[key] = statics[key]; }
// if class is not a singleton, add $super and $superp
if ( !singleton) {
p = parent && parent[0] || parent;
clazz.$super = p;
clazz.$superp = p && p.prototype ? p.prototype : p;
// copy static properties from statics to clazz
for (key in statics) {
clazz[key] = statics[key];
}
for (key in plugins) { plugins[key](clazz, parent, api); } // pass control to plugins
if (functionOrNil(api.main)) { api.main.call(clazz, clazz); } // execute main()
// add $super and $superp to refer to parent class and parent.prototype (if applied)
p = parent && rootParent || parent;
clazz.$super = p;
clazz.$superp = p && p.prototype || p;
for (key in plugins) { plugins[key](clazz, parent, api); } // pass control to plugins
if (typeof api.main === "function") { api.main.call(clazz, clazz); } // execute main()
return clazz;

@@ -178,4 +220,54 @@ }

/* Class plugins repository */
Class.plugins = {};
Class.plugins = {
$ready: function invoke(clazz, parent, api, loop) {
var r = api.$ready,
len = parent ? parent.length : 0,
count = len,
_super = len && parent[0].$super,
pa, i, entry;
// find and invoke $ready from parent(s)
while (len--) {
for (i = 0; i < readyCount; i++) {
entry = readyFns[i];
pa = parent[len];
if (pa === entry[0]) {
entry[1].call(pa, clazz, parent, api);
count--;
}
if ( !count) { break; }
}
}
// call $ready from grandparent(s), if any
if (_super) {
invoke(clazz, [ _super ], api, true);
}
// in an environment where there are a lot of class creating/removing (rarely)
// this implementation might cause a leak (saving pointers to clazz and $ready)
if ( !loop && functionOrNil(r)) {
r.call(clazz, clazz, parent, api); // invoke ready from current class
readyFns.push([ clazz, r ]);
readyCount++;
}
},
$const: function (clazz, parent, api) {
var key,
consts = api.$const;
// copy immutable properties from consts to clazz and freeze them recursively
for (key in consts) {
Object.defineProperty(clazz, key, { enumerable: true, value: consts[key] }); // enumerable for proper inheritance
if ((typeof clazz[key] === 'object') && !Object.isFrozen(clazz[key])) {
deepFreeze(clazz[key]); // if property is an unfrozen object, freeze it recursively
}
}
}
};
/* Initialization */

@@ -188,3 +280,2 @@ jsface = {

functionOrNil: functionOrNil,
stringOrNil : stringOrNil,
classOrNil : classOrNil

@@ -201,2 +292,2 @@ };

}
})(this, "object", "number", "length", Object.prototype.toString);
})(this, "object", "number", "length", Object.prototype.toString, [], 0);

@@ -5,3 +5,3 @@ /*

*
* Copyright (c) 2009-2012 Tan Nhu
* Copyright (c) Tan Nhu
* Licensed under MIT license (https://github.com/tnhu/jsface/blob/master/LICENSE.txt).

@@ -21,4 +21,2 @@ */

ADVISOR = "___advisors___",
INVALID = "Invalid ",
NON_FUNC = "Non-function property named ",
noop = function(){};

@@ -135,11 +133,13 @@

iConstructor = (key === "constructor");
iStatic = iClass && bindTo[key] === clazz[key];
fn = restore(iConstructor && iClass && clazz || bindTo[key], advisor);
iStatic = iClass && clazz[key];
constructor = constructor || (iConstructor && fn);
if (fn && !iConstructor) {
bindTo[key] = fn;
if (iStatic) {
clazz[key] = fn;
if (key === "constructor" && iClass) {
constructor = restore(iClass, advisor);;
} else {
if (clazz[key]) {
clazz[key] = restore(clazz[key], advisor);
}
if (bindTo[key]) {
bindTo[key] = restore(bindTo[key], advisor);
}
}

@@ -153,12 +153,7 @@ }

for (var name in bindTo) {
var fn = bindTo[name],
iStatic = iClass && bindTo[name] === clazz[name];
bindTo[name] = restore(fn) || bindTo[name];
// restore static method
if (iStatic) {
clazz[name] = bindTo[name];
}
bindTo[name] = restore(bindTo[name]) || bindTo[name];
}
for (var name in clazz) {
clazz[name] = restore(clazz[name]) || clazz[name];
}
} else { // type 2: "remove", advisor

@@ -171,3 +166,3 @@ doRestore(advisor, advisor);

} else {
throw INVALID + "params";
throw "Invalid params";
}

@@ -181,3 +176,3 @@ return constructor || clazz;

jsface.pointcut = function pointcut(clazz, opts) {
var iClass = functionOrNil(clazz),
var iClass = classOrNil(clazz) || functionOrNil(clazz),
iInstance = mapOrNil(clazz),

@@ -189,3 +184,3 @@ iRemove = (/^remove ?/.exec(opts) !== null),

if ( !(iClass || iInstance) || !(mapOrNil(opts) || iRemove)) {
throw INVALID + "params";
throw "Invalid params";
}

@@ -204,10 +199,10 @@ bindTo = iClass ? clazz.prototype : clazz;

after = mapOrNil(pointcuts) && !pointcuts.after ? noop : pointcuts.after,
isStatic;
isStatic, found = false;
// check if before & after are valid
if ( !functionOrNil(before)) {
throw INVALID + method + ":before";
throw "Invalid " + method + ":before";
}
if ( !functionOrNil(after)) {
throw INVALID + method + ":after";
throw "Invalid " + method + ":after";
}

@@ -219,3 +214,3 @@

} else {
throw NON_FUNC + method;
throw "Non-function property named " + method + " on instance";
}

@@ -226,9 +221,15 @@ } else {

} else {
if (functionOrNil(bindTo[method])) {
isStatic = iClass && bindTo[method] === clazz[method];
if (functionOrNil(clazz[method])) { // static method
clazz[method] = wrap(clazz[method], before, after, opts);
found = true;
}
if (functionOrNil(bindTo[method])) { // normal (non-static) method
bindTo[method] = wrap(bindTo[method], before, after, opts);
if (isStatic) { clazz[method] = bindTo[method]; }
} else {
throw NON_FUNC + method;
found = true;
}
if ( !found) {
throw "Non-function property named " + method + " on class";
}
}

@@ -235,0 +236,0 @@ }

@@ -6,3 +6,3 @@ {

"author": "Tan Nhu <tnhu AT me . com>",
"version": "2.3.0",
"version": "2.4.9",
"keywords": [

@@ -33,10 +33,8 @@ "jsface",

"devDependencies": {
"grunt": "~0.4.1",
"grunt-contrib-qunit": ">=0.2.1",
"grunt-contrib-watch": ">=0.3.1",
"grunt-contrib-uglify": ">=0.2.0",
"grunt-contrib-copy": ">=0.4.0",
"grunt-contrib-clean": "~0.5.0",
"grunt-contrib-concat": "~0.3.0"
"del": "^1.2.0",
"gulp": "^3.9.0",
"gulp-rename": "^1.2.2",
"gulp-uglify": "^1.2.0",
"run-sequence": "^1.1.2"
}
}
}
![Benchmark result](https://lh5.googleusercontent.com/-2dQo8ttjn48/T2KVyppgd2I/AAAAAAAADQw/GvEpE5MIYUo/s956/Screen%2520Shot%25202012-03-15%2520at%25206.21.04%2520PM.png "Benchmark")
[![Build Status](https://secure.travis-ci.org/tannhu/jsface.png?branch=master)](http://travis-ci.org/tannhu/jsface)
[![Build Status](https://secure.travis-ci.org/tannhu/jsface.svg?branch=master)](http://travis-ci.org/tannhu/jsface)
## Features

@@ -10,3 +11,3 @@

* Support CommonJS.
* Support main, singleton, mixin, private properties, Aspect Oriented Programming.
* Support getter/setter, constant, main, singleton, mixin, private properties, Aspect Oriented Programming.
* Plugins mechanism to extend itself.

@@ -18,12 +19,30 @@

Browser:
### Browser
#### bower
``` sh
bower install jsface
```
``` html
<script src="jsface.js" type="text/javascript"></script>
<script src="bower_components/jsface/jsface.js"></script>
```
JSFace introduces two global variables: jsface and Class. Other APIs are under jsface namespace.
#### dnsjs
In NodeJS environment, first install JSFace via npm:
``` javascript
<script src="https://cdn.jsdelivr.net/jsface/2.4.8/jsface.min.js"></script>
```
#### Manually
``` html
<script src="jsface.js"></script>
```
### NodeJS environment
First install JSFace via npm:
``` sh

@@ -41,3 +60,3 @@ npm install jsface

## API
## Usage

@@ -53,2 +72,12 @@ ### Define a class

// Getter/Setter
address: {
get: function() {
return this._address;
},
set: function(value) {
this._address = value;
}
},
toString: function() {

@@ -69,7 +98,7 @@ return this.name + "/" + this.age;

this.id = id;
Student.$super.call(this, name, age); // Invoke parent's constructor
Student.$super.call(this, name, age); // Call parent's constructor
},
toString: function() {
return this.id + "/" + Student.$superp.toString.call(this); // Invoke parent's toString method
return this.id + "/" + Student.$superp.toString.call(this); // Call parent's toString method
}

@@ -120,7 +149,5 @@ });

JSFace supports Java-style static properties. Meaning they are accessible on both class and instance levels.
``` javascript
var Person = Class({
$statics: {
$static: {
MIN_AGE: 1,

@@ -140,10 +167,29 @@ MAX_AGE: 150,

var person = new Person("Rika", 20);
Person.MIN_AGE === person.MIN_AGE; // true
Person.MAX_AGE === person.MAX_AGE; // true
Person.MIN_AGE === 1; // true
Person.MAX_AGE === 150; // true
Person.isValidAge(0); // false
person.isValidAge(person.age); // true
```
### Constants
Constants work the same as static properties. The only different is they are immutable.
``` javascript
var Person = Class({
$const: {
MIN_AGE: 1,
MAX_AGE: 150
},
constructor: function(name, age) {
this.name = name;
this.age = age;
}
});
Person.MIN_AGE = -1;
Person.MIN_AGE === 1; // true, MIN_AGE is immutable
```
### Private properties

@@ -272,3 +318,3 @@

``` html
<script src="jsface.pointcut.js" type="text/javascript"></script>
<script src="jsface.pointcut.js"></script>
```

@@ -356,19 +402,4 @@

$ready plugin is designed to help parent classes to intercept their subclasses' creation. If a class uses $ready,
it notifies itself.
$ready plugin is designed to help a parent class to intercept their subclasses' creation.
#### Setup
Browser:
``` html
<script src="jsface.ready.js" type="text/javascript"></script>
```
NodeJS:
``` javascript
var ready = require("jsface.ready");
```
#### Sample

@@ -379,3 +410,3 @@

$ready: function(clazz, parent, api) {
var type = (this !== clazz) && api.type;
var type = (this !== clazz) && api.type; // (this !== clazz) means this comes from a sub-class

@@ -408,3 +439,3 @@ switch (type) {

Copyright (c) 2009-2013 Tan Nhu
Copyright (c) Tan Nhu

@@ -427,2 +458,2 @@ Permission is hereby granted, free of charge, to any person obtaining a copy

OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
THE SOFTWARE.

@@ -16,6 +16,14 @@ var Events = Class({

var Foo = Class({
$statics: {
$static: {
VERSION: "1.3"
},
$const: {
CONSTANT: "frozen value",
Namespace: {
FIRST_OPTION: "first option",
SECOND_OPTION: "second option"
}
},
constructor: function(name) {

@@ -22,0 +30,0 @@ this.name = name;

@@ -145,3 +145,3 @@ var context = this,

equal(classOrNil(Bar), Bar, "jsface.classOrNil works incorrectly on a simple class");
equal(classOrNil(Util), null, "jsface.classOrNil works incorrectly a singleton class (singleton is a map, not a class)");
equal(classOrNil(Util), Util, "jsface.classOrNil works incorrectly a singleton class (singleton is a map, not a class)");
});

@@ -295,2 +295,110 @@

test("Constants", function() {
var Bar = Class({
constructor: function(name) {
this.name = name;
},
$const: {
CONSTANT: 1,
OBJECT: {
C1: "c1",
C2: "c2",
C3: {
C31: "c31"
}
}
}
});
var bar = new Bar("Constants");
equal(Bar.CONSTANT, 1, "Error getting constant");
equal(Bar.OBJECT.C1, "c1", "Error getting object constant");
equal(bar.CONSTANT, undefined, "Constant should not be on instance level");
equal(bar.OBJECT, undefined, "Object constant should not be on instance level");
Bar.CONSTANT = 2;
equal(Bar.CONSTANT, 1, "Error, constant value was changed");
Bar.OBJECT.C3.C31 = "foo";
equal(Bar.OBJECT.C3.C31, "c31", "Error, object constant value was changed");
});
test("Constants - inheritance", function() {
var Foo = Class({
fooField: 100,
constructor: function(name) {
this.name = name;
},
fooMethod: function() {
return "fooMethod";
},
$const: {
FOO_CONST: "fooConst",
OVERRIDDEN_CONST: "originalValue",
OBJECT_CONST: {
FIRST: "first",
SECOND: "second",
THIRD: {
THIRD_FIRST: "thirdFirst",
THIRD_SECOND: "thirdSecond"
}
}
}
});
var Bar = Class(Foo, {
barField: 200,
constructor: function(name) {
this.name = name;
},
barMethod: function() {
return "barMethod";
},
$const: {
BAR_CONST: "barConst",
OVERRIDDEN_CONST: "overriddenValue"
}
});
equal(Foo.FOO_CONST, "fooConst", "Constant is not created properly");
equal(Bar.FOO_CONST, "fooConst", "Constant is not inherited properly");
equal(Bar.BAR_CONST, "barConst", "Constant is not created properly");
equal(Foo.OVERRIDDEN_CONST, "originalValue", "Constant is not created properly");
equal(Bar.OVERRIDDEN_CONST, "overriddenValue", "Constant is not overridden properly");
equal(Bar.OBJECT_CONST.FIRST, "first", "Constant is not inherited properly");
equal(Bar.OBJECT_CONST.THIRD.THIRD_SECOND, "thirdSecond", "Constant is not inherited properly");
Bar.OBJECT_CONST.THIRD.THIRD_SECOND = "bar";
equal(Bar.OBJECT_CONST.THIRD.THIRD_SECOND, "thirdSecond", "Error, object constant value was changed");
var foo = new Foo("Tom");
var bar = new Bar("John Rambo");
equal(foo.name, "Tom", "Invalid class creation");
equal(foo.fooField, 100, "Invalid class creation");
equal(foo.fooMethod(), "fooMethod", "Invalid class creation");
equal(foo.FOO_CONST, undefined, "Constant should not be on instance");
equal(bar.name, "John Rambo", "Invalid class creation");
equal(bar.fooField, 100, "Invalid class creation");
equal(bar.barField, 200, "Invalid class creation");
equal(bar.fooMethod(), "fooMethod", "Invalid class creation");
equal(bar.barMethod(), "barMethod", "Invalid class creation");
equal(bar.FOO_CONST, undefined, "Constant should not be on instance");
equal(bar.BAR_CONST, undefined, "Constant should not be on instance");
equal(bar.OVERRIDDEN_CONST, undefined, "Constant should not be on instance");
equal(bar.OBJECT_CONST, undefined, "Constant should not be on instance");
});
test("Static methods", function() {

@@ -302,3 +410,3 @@ var Bar = Class({

$statics: {
$static: {
sayBye: function() {

@@ -313,6 +421,192 @@ return "Bye!";

equal(Bar.sayBye(), "Bye!", "Error invoking static method");
equal(bar.sayBye(), "Bye!", "Error invoking static method from class instance");
equal(bar.sayBye, Bar.sayBye, "Static method must be the same on both class and class instance");
equal(bar.sayBye, undefined, "Static method should not be on instance level");
});
test("Static methods should be inherited accordingly", function() {
var Foo = Class({
fooField: 100,
constructor: function(name) {
this.name = name;
},
fooMethod: function() {
return "fooMethod";
},
$static: {
fooStaticMethod: function() {
return "fooStaticMethod";
}
}
});
var Bar = Class(Foo, {
barField: 200,
constructor: function(name) {
this.name = name;
},
barMethod: function() {
return "barMethod";
},
$static: {
barStaticMethod: function() {
return "barStaticMethod";
}
}
});
equal(Foo.fooStaticMethod(), "fooStaticMethod", "Static method is not created properly");
equal(Bar.fooStaticMethod(), "fooStaticMethod", "Static method is not inherited properly");
equal(Bar.barStaticMethod(), "barStaticMethod", "Static method is not created properly");
var foo = new Foo("Tom");
bar = new Bar("John Rambo");
equal(foo.name, "Tom", "Invalid class creation");
equal(foo.fooField, 100, "Invalid class creation");
equal(foo.fooMethod(), "fooMethod", "Invalid class creation");
equal(foo.fooStaticMethod, undefined, "Static method should not be on instance");
equal(bar.name, "John Rambo", "Invalid class creation");
equal(bar.fooField, 100, "Invalid class creation");
equal(bar.barField, 200, "Invalid class creation");
equal(bar.fooMethod(), "fooMethod", "Invalid class creation");
equal(bar.barMethod(), "barMethod", "Invalid class creation");
equal(bar.fooStaticMethod, undefined, "Static method should not be on instance");
equal(bar.barStaticMethod, undefined, "Static method should not be on instance");
});
test("Properties - getters and setters", function() {
var Person = Class({
constructor : function(name) {
this._name = name;
},
name : {
get : function() {
return this._name;
},
set : function(value) {
this._name = value;
}
}
});
var person = new Person("Milos");
equal(person.name, "Milos", "Invalid property getter");
person.name = "Boki";
equal(person.name, "Boki", "Invalid property setter");
});
test("Properties - skip getters and setters", function() {
var Person = Class({
name: undefined,
setName: function(name) {
this.name = name;
}
});
var person = new Person();
equal(person.name, undefined, "Invalid property getter");
person.setName("Boki");
equal(person.name, "Boki", "Invalid property setter");
});
test("Properties - getters and setters - inheritance", function() {
var Person = Class({
constructor: function(name) {
this._name = name;
},
name: {
get: function() {
return this._name;
},
set: function(value) {
this._name = value;
}
}
});
var Student = Class(Person, {
constructor: function(name, age) {
Student.$super.call(this, name);
this._age = age;
},
age: {
get: function() {
return this._age;
},
set: function(value) {
this._age = value;
}
}
});
var student = new Student("Mia", 18);
equal(student.name, "Mia", "Bad property inheritance");
student.name = "Persa";
equal(student.name, "Persa", "Bad property inheritance");
equal(student.age, 18, "Invalid property getter");
});
test("Properties - getters and setters - inheritance and mixins", function() {
var Person = Class({
constructor: function(name) {
this._name = name;
},
name: {
get: function() {
return this._name;
},
set: function(value) {
this._name = value;
}
}
});
var Options = Class({
option: {
get: function() {
return this._option;
},
set: function(value) {
this._option = value;
}
}
});
var Student = Class([Person, Options], {
constructor: function(name, age) {
Student.$super.call(this, name);
this._age = age;
},
age: {
get: function() {
return this._age;
},
set: function(value) {
this._age = value;
}
}
});
var student = new Student("Mia", 18);
student.option = 'some option';
equal(student.option, 'some option', 'Getter/setter does not work properly with mixin');
});
test("Singleton class", function() {

@@ -327,3 +621,3 @@ var Foo = Class({

equal(mapOrNil(Foo), Foo, "Singleton class must be a map object");
equal(classOrNil(Foo), Foo, "Singleton class must be a a class");
equal(Foo.sayHi(), "Hello World", "Error invoking method on singleton class");

@@ -349,3 +643,3 @@ });

equal(mapOrNil(Bar), Bar, "Singleton class must be a map object");
equal(classOrNil(Bar), Bar, "Singleton class must be a a class");
equal(Bar.sayHi(), "Hello World", "Error invoking method on singleton class");

@@ -373,10 +667,65 @@ equal(Bar.sayBye(), "Bye!", "Error invoking method on singleton class");

equal(classOrNil(Bar), Bar, "Class definition must be a class");
equal(bar.sayHi, Bar.sayHi, "Static method must be the same on both class and class instance");
equal(bar.sayHi, Foo.sayHi, "Static method must be the same on both class and class instance");
equal(bar.sayHi, undefined, "Static method from parent class should not be available on child instance");
equal(Foo.sayHi(), "Hello World", "Error invoking method on singleton class");
equal(Bar.sayHi(), "Hello World", "Static method should be available on child class");
equal(Foo.sayHi, Bar.sayHi, "Static method must be the same on both class");
equal(Bar.sayHi(), "Hello World", "Error invoking method on singleton class");
equal(bar.sayHi(), "Hello World", "Error invoking method on singleton class");
equal(bar.sayBye(), "Bye!", "Error invoking method on class");
});
test("Override singleton method", function() {
var Foo = Class({
$singleton: true,
hi: function() {
return "hi";
},
bye: function() {
return "bye";
}
});
var Bar = Class(Foo, {
$singleton: true,
// override hi
hi: function() {
return "override-hi";
}
});
equal(Foo.hi(), "hi", "Error invoking method on singleton class");
equal(Foo.bye(), "bye", "Static method should be available on child class");
equal(Bar.hi(), "override-hi", "Error invoking method on singleton class");
equal(Foo.bye(), "bye", "Static method should be available on child class");
});
test("Override singleton method and call parent method", function() {
var Foo = Class({
$singleton: true,
hi: function() {
return "hi";
},
bye: function() {
return "bye";
}
});
var Bar = Class(Foo, {
$singleton: true,
// override hi
hi: function() {
return "override-" + Bar.$super.hi.call(this);
}
});
equal(Foo.hi(), "hi", "Error invoking method on singleton class");
equal(Foo.bye(), "bye", "Static method should be available on child class");
equal(Bar.hi(), "override-hi", "Error invoking method on singleton class");
equal(Foo.bye(), "bye", "Static method should be available on child class");
});
test("Mixin: class extends class", function() {

@@ -593,5 +942,8 @@ var Foo = Class({

equal(bar.welcome(), "Welcome John Rambo", "Invalid extend() behavior, property must be overriden properly");
equal(bar.sayHi(), "Hello World John Rambo", "Invalid extend() behavior");
ok(functionOrNil(Bar.welcome), "Static method is not copied when extending");
ok(functionOrNil(Bar.sayHi), "Static method is not copied when extending");
equal(bar.welcome(), "invalid", "Invalid extend() behavior, property must be overriden properly");
equal(bar.sayBye(), "Bye!", "Invalid extend() behavior");
equal(bar.sayHi, undefined, "Invalid extend() behavior");
});

@@ -613,3 +965,3 @@

var Bar = Class({
$statics: {
$static: {
sample: 1,

@@ -680,6 +1032,6 @@ fn: function() { return 2; }

var Events = Class({
bind: function(event, fn) {
_bind: function(event, fn) {
return true;
},
unbind: function(event, fn) {
_unbind: function(event, fn) {
return false;

@@ -702,6 +1054,6 @@ }

equal(foo.opts, "nothing", "Invalid extend() behavior, constructor must be bound correctly");
equal(Foo.bind(), true, "Invalid extend() behavior");
equal( !Foo.unbind(), true, "Invalid extend() behavior");
equal(foo.bind(), true, "Invalid extend() behavior");
equal( !foo.unbind(), true, "Invalid extend() behavior");
equal(Foo._bind(), true, "Invalid extend() behavior");
equal( !Foo._unbind(), true, "Invalid extend() behavior");
equal(foo._bind, undefined, "Static method can't be copied to instance");
equal(foo._unbind, undefined, "Static method can't be copied to instance");
});

@@ -711,3 +1063,3 @@

extend(String, {
trim: function() {
myTrim: function() {
return this.replace(/^\s+|\s+$/g, "");

@@ -717,19 +1069,17 @@ }

equal(" Hello World ".trim(), "Hello World", "Invalid extend() binding String.prototype");
ok(String.myTrim, "Extend does not work properly");
equal(String.prototype.myTrim, undefined, "Extend does not work properly");
equal(String.myTrim.apply(" Hello World "), "Hello World", "Invalid extend() binding String.prototype");
extend(Array, {
sum: function() {
var s = 0, len = this.length;
while (len--) {
s += this[len];
}
return s;
delete String.myTrim;
extend(String.prototype, {
myTrim: function() {
return this.replace(/^\s+|\s+$/g, "");
}
});
var a = [ 1, 2, 3, 4, 5 ];
ok(a.sum, "Invalid extend() binding native object");
ok(Array.sum, "Invalid extend() binding native object");
ok(Array.prototype.sum, "Invalid extend() binding native object");
equal(a.sum(), 15, "Invalid extend() binding native object");
ok(String.prototype.myTrim, "Extend does not work properly");
equal(String.myTrim, undefined, "Extend does not work properly");
equal(" Hello World ".myTrim(), "Hello World", "Invalid extend() binding String.prototype");
});

@@ -784,4 +1134,25 @@

// --------- PLUGINS --------- //
test("Test instanceof", function() {
var Person = Class({
constructor: function(name) {
this.name = name;
}
});
var Student = Class(Person, {
constructor: function(id, name) {
this.id = id;
Person.call(this, name);
}
});
var p = new Person("Tom"),
s = new Student(1, "Mary");
ok(p instanceof Person, "class fails to test instanceof");
ok(s instanceof Person, "class fails to test instanceof");
ok(s instanceof Student, "class fails to test instanceof");
});
test("Develop a Class plugin", function() {

@@ -805,1 +1176,66 @@ var Logger = Class({

});
test("$ready plugin: class notifies itself", function() {
var notified = false;
var Foo = Class({
$ready: function(clazz, parent, api) {
notified = true;
equal(this, clazz, "clazz must be equal to this");
ok(functionOrNil(api.$ready), "$ready works incorrectly");
ok(functionOrNil(api.echo), "$ready works incorrectly");
ok(functionOrNil(clazz.prototype.echo), "$ready works incorrectly");
ok( !parent, "$ready works incorrectly");
},
echo: function(o) {
return o;
}
});
ok(notified, "$ready must be executed");
});
test("$ready plugin: class is notified when its subclasses are ready", function() {
var notified = false;
var Foo = Class({
$ready: function(clazz, parent, api) {
notified = true;
if (this !== clazz) {
ok(api.echo2, "$ready works incorrectly");
ok( !api.$ready, "$ready works incorrectly");
ok(functionOrNil(clazz.prototype.echo2), "$ready works incorrectly");
}
},
echo: function(o) {
return o;
}
});
ok(notified, "$ready must be executed when class is created");
var Bar = Class(Foo, {
echo2: function(o) {
return o;
}
});
});
test("$ready plugin: class is notified when its subclasses are ready (multiple levels)", function() {
var count = 0;
var Foo = Class({
$ready: function(clazz, parent, api) {
if (this !== clazz) {
count++;
}
}
});
var Bar1 = Class(Foo, {});
var Bar2 = Class(Bar1, {});
var Bar3 = Class(Bar2, {});
ok(count === 3, "$ready must be executed in multiple level inheritance");
});

@@ -37,3 +37,2 @@ var context = this;

ok(exports.functionOrNil, "functionOrNil must be available in exports");
ok(exports.stringOrNil, "stringOrNil must be available in exports");
ok(exports.classOrNil, "classOrNil must be available in exports");

@@ -40,0 +39,0 @@ delete context.module;

@@ -340,6 +340,8 @@ var context = this,

test("Pointcuts over static methods", function() {
var num = 0;
var Counter = Class({
constructor: function(num) {
this.num = num;
constructor: function(_num) {
num = _num;
},
$statics: {

@@ -349,3 +351,3 @@ counter: 0,

inc: function(n) {
this.num += n;
num += n;
}

@@ -358,7 +360,7 @@ }

before: function(n) {
this.num += n;
num += n;
Counter.counter += 1;
},
after: function(n) {
this.num += n;
num += n;
Counter.counter += 1;

@@ -370,6 +372,6 @@ }

var p = new Counter(100);
p.inc(1);
Counter.inc(0);
equal(p.num, 103, "Pointcut over static methods works incorrectly");
equal(Counter.counter, 4, "Pointcut over static methods works incorrectly");
Counter.inc(1);
equal(num, 103, "Pointcut over static methods works incorrectly");
equal(p.counter, undefined, "Pointcut over static methods works incorrectly");
});

@@ -558,3 +560,2 @@

equal(impl.$statics.foo, Person.prototype.foo, "Removing pointcut over prototype method unsuccessfully");
equal(impl.$statics.foo, Person.foo, "Removing pointcut over static method unsuccessfully");

@@ -582,4 +583,3 @@ });

equal(impl.$statics.foo, Person.prototype.foo, "Removing pointcut over prototype method unsuccessfully");
equal(impl.$statics.foo, Person.foo, "Removing pointcut over static method unsuccessfully");
});

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc