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.0.0 to 2.0.1

17

CHANGELOG.txt

@@ -0,9 +1,16 @@

Version 2.0.1 Jan 16, 2011
----------------------------------------------------------------
* Fix unit tests on IE (extra commas, iframe injection)
* Fix jsface.isArray works incorrectly over String (IE6, IE5.5)
* Fix extend(instance, Class)
Version 2.0.0 Dec 10, 2011
----------------------------------------------------------------
* Get rid of $meta (cleaner class structure).
* Introduce $super, extend (mixin, trait).
* Overloading support as a standalone plugin (TBD).
* AOP support as a standalone plugin (TBD).
* Get rid of $meta (cleaner class structure)
* Introduce $super, extend (mixin, trait)
* Overloading support as a standalone plugin (TBD)
* AOP support as a standalone plugin (TBD)
* Anonymous class (without name) (i.e: var Animal = Class({});)
* constructor instead of java style ClassName
* noConflict() mode
* support private method (class body is a function)

@@ -15,3 +22,3 @@ * Single constructor inheritance, multiple trails (Scala style)

* Remove unneccessary code
* Optimization
* Size optimization
* More unit tests

@@ -18,0 +25,0 @@

/*
* JsFace Object Oriented Programming Library v2.0.0
* JSFace Object Oriented Programming Library
* https://github.com/tannhu/jsface
*
* Copyright (c) 2011 Tan Nhu
* Copyright (c) 2009-2012 Tan Nhu
* Licensed under MIT license (https://github.com/tannhu/jsface/blob/master/MIT-LICENSE.txt).
*
* Date: Saturday, March 07 2009
* Version: 2.0.1
*/

@@ -19,37 +20,2 @@ (function(context, undefined) {

/**
* Loop over a collection (a string, an array, an object (a map with pairs of {key:value})), or a function (over all
* static properties).
* Over a String or Array, fn is executed as: fn(value, index, collection) Otherwise: fn(key, value, collection).
* Return Infinity on fn will stop the iteration. each returns an array of results returned by fn.
*/
function each(collection, fn) {
var iArray, iMap, iFunction, item, i, r, len, result = [];
if ( !collection || !fn) { return; }
iArray = isArray(collection) || isString(collection);
iMap = isMap(collection);
iFunction = isFunction(collection);
// convert to array if collection is not a collection itself
if ( !iArray && !iMap && !iFunction) {
collection = [ collection ];
iArray = 1;
}
if (iArray) {
for (i = 0, len = collection.length; i < len; i++) {
if ((r = fn(collection[i], i, collection)) === Infinity) { break; }
result.push(r);
}
} else {
for (item in collection) {
if ((r = fn(item, collection[item], collection)) === Infinity) { break; }
result.push(r);
}
}
return result;
}
/**
* Check an object is a map or not. A map is something like { key1: value1, key2: value2 }.

@@ -90,2 +56,39 @@ */

/**
* Loop over a collection (a string, an array, an object (a map with pairs of {key:value})), or a function (over all
* static properties).
* Over a String or Array, fn is executed as: fn(value, index, collection) Otherwise: fn(key, value, collection).
* Return Infinity on fn will stop the iteration. each returns an array of results returned by fn.
*/
function each(collection, fn) {
var iArray, iMap, iString, iFunction, item, i, r, v, len, result = [];
if ( !collection || !fn) { return; }
iString = isString(collection);
iArray = isArray(collection) || iString;
iMap = isMap(collection);
iFunction = isFunction(collection);
// convert to array if collection is not a collection itself
if ( !iArray && !iMap && !iFunction) {
collection = [ collection ];
iArray = 1;
}
if (iArray) {
for (i = 0, len = collection.length; i < len; i++) {
v = iString ? collection.charAt(i) : collection[i];
if ((r = fn(v, i, collection)) === Infinity) { break; }
result.push(r);
}
} else {
for (item in collection) {
if ((r = fn(item, collection[item], collection)) === Infinity) { break; }
result.push(r);
}
}
return result;
}
/**
* Make $super method.

@@ -143,12 +146,13 @@ */

// first: static properties
if (isSubClass || isMap(subject)) { // only if meaningful
each(subject, function(key, value) {
if ( !ignoredKeys || !ignoredKeys.hasOwnProperty(key)) { // no copy ignored keys
object[key] = value; // do copy
if (iClass) { oPrototype[key] = value; } // class? copy to prototype as well
}
});
function copier(key, value) {
if ( !ignoredKeys || !ignoredKeys.hasOwnProperty(key)) { // no copy ignored keys
object[key] = value; // do copy
if (iClass) { oPrototype[key] = value; } // class? copy to prototype as well
}
}
// copy static properties and prototype.* to object
if (isMap(subject)) { each(subject, copier); }
if (isSubClass) { each(subject.prototype, copier); }
// second: prototype properties

@@ -155,0 +159,0 @@ if (iClass && isSubClass) { extend(oPrototype, subject.prototype, ignoredKeys); }

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

(function(n){function h(a,b){var c,f,d,g,e=[];if(a&&b){c=o(a)||r(a);f=p(a);d=i(a);!c&&!f&&!d&&(a=[a],c=1);if(c)for(g=0,f=a.length;g<f&&!(Infinity===(c=b(a[g],g,a)));g++)e.push(c);else for(g in a){if(Infinity===(c=b(g,a[g],a)))break;e.push(c)}return e}}function p(a){return a&&typeof a===s&&!(typeof a.length===t&&!a.propertyIsEnumerable(u))}function o(a){return a&&typeof a===s&&typeof a.length===t&&!a.propertyIsEnumerable(u)}function i(a){return a&&"function"===typeof a}function r(a){return"[object String]"===
Object.prototype.toString.apply(a)}function m(a){return i(a)&&a===a.prototype.constructor}function x(a,b){a.prototype.$super=function(){var c=arguments.callee.caller,f=this.$super,d,g,e,k;if(c===a.prototype.constructor){if(e=b?b[0]:0,m(e))this.$super=e.prototype.$super}else if(b){h(a.prototype,function(a,b){if(b===c)return g=a,Infinity});for(d=b.length;d--&&!e;){k=b[d];if(m(k))k=k.prototype;e=k[g]||0}if(i(e))this.$super=k.$super}if(i(e))return d=e.apply(this,arguments),this.$super=f,d}}function l(a,
b,c){if(o(b))return h(b,function(b){l(a,b,c)});var c=c||{constructor:1,$super:1,prototype:1},f=m(a),d=m(b),g=a.prototype;(d||p(b))&&h(b,function(b,d){if(!c||!c.hasOwnProperty(b))a[b]=d,f&&(g[b]=d)});f&&d&&l(g,b.prototype,c)}function j(a,b){b||(a=(b=a,0));var b=b||{},c,f,d,g,e={constructor:1,$singleton:1,$statics:1,prototype:1},a=a&&!o(a)?[a]:a,b=i(b)?b():b;if(!p(b))throw y;f=b.hasOwnProperty("constructor")?b.constructor:0;d=b.$singleton;g=b.$statics;h(j.plugins,function(a){e[a]=1});c=d?{}:f?j.overload?
j.overload("constructor",f):f:function(){};h(a,function(a){l(c,a,e,!0)});l(d?c:c.prototype,b,e);l(c,g,e,!0);d||x(c,a);h(j.plugins,function(d,e){e(c,a,b)});return c}var s="object",t="number",u="length",y="Invalid params",v=[],w,q;j.plugins={$ready:function(a,b,c){var f=c.$ready,d=0,g=b?b.length:0;h(v,function(e){return h(b,function(f){f===e[0]&&e[1].call(f,a,c,b);if(d++>=g)return Infinity})});i(f)&&(f.call(a,a,c,b),v.push([a,f]))}};q={Class:j,extend:l,each:h,isMap:p,isArray:o,isFunction:i,isString:r,
isClass:m};"undefined"!==typeof module&&module.exports?module.exports=q:(w=n.Class,n.Class=j,n.jsface=q,q.noConflict=function(){n.Class=w})})(this);
(function(n){function o(a){return a&&typeof a===r&&!(typeof a.length===s&&!a.propertyIsEnumerable(t))}function p(a){return a&&typeof a===r&&typeof a.length===s&&!a.propertyIsEnumerable(t)}function j(a){return a&&"function"===typeof a}function u(a){return"[object String]"===Object.prototype.toString.apply(a)}function m(a){return j(a)&&a===a.prototype.constructor}function h(a,b){var c,e,f,g,d,i=[];if(a&&b){f=u(a);c=p(a)||f;e=o(a);g=j(a);!c&&!e&&!g&&(a=[a],c=1);if(c)for(d=0,e=a.length;d<e;d++){c=f?a.charAt(d):
a[d];if(Infinity===(c=b(c,d,a)))break;i.push(c)}else for(d in a){if(Infinity===(c=b(d,a[d],a)))break;i.push(c)}return i}}function x(a,b){a.prototype.$super=function(){var c=arguments.callee.caller,e=this.$super,f,g,d,i;if(c===a.prototype.constructor){if(d=b?b[0]:0,m(d))this.$super=d.prototype.$super}else if(b){h(a.prototype,function(a,b){if(b===c)return g=a,Infinity});for(f=b.length;f--&&!d;){i=b[f];if(m(i))i=i.prototype;d=i[g]||0}if(j(d))this.$super=i.$super}if(j(d))return f=d.apply(this,arguments),
this.$super=e,f}}function l(a,b,c){function e(b,e){if(!c||!c.hasOwnProperty(b))a[b]=e,f&&(d[b]=e)}if(p(b))return h(b,function(b){l(a,b,c)});var c=c||{constructor:1,$super:1,prototype:1},f=m(a),g=m(b),d=a.prototype;o(b)&&h(b,e);g&&h(b.prototype,e);f&&g&&l(d,b.prototype,c)}function k(a,b){b||(a=(b=a,0));var b=b||{},c,e,f,g,d={constructor:1,$singleton:1,$statics:1,prototype:1},a=a&&!p(a)?[a]:a,b=j(b)?b():b;if(!o(b))throw y;e=b.hasOwnProperty("constructor")?b.constructor:0;f=b.$singleton;g=b.$statics;
h(k.plugins,function(a){d[a]=1});c=f?{}:e?k.overload?k.overload("constructor",e):e:function(){};h(a,function(a){l(c,a,d,!0)});l(f?c:c.prototype,b,d);l(c,g,d,!0);f||x(c,a);h(k.plugins,function(d,e){e(c,a,b)});return c}var r="object",s="number",t="length",y="Invalid params",v=[],w,q;k.plugins={$ready:function(a,b,c){var e=c.$ready,f=0,g=b?b.length:0;h(v,function(d){return h(b,function(e){e===d[0]&&d[1].call(e,a,c,b);if(f++>=g)return Infinity})});j(e)&&(e.call(a,a,c,b),v.push([a,e]))}};q={Class:k,extend:l,
each:h,isMap:o,isArray:p,isFunction:j,isString:u,isClass:m};"undefined"!==typeof module&&module.exports?module.exports=q:(w=n.Class,n.Class=k,n.jsface=q,q.noConflict=function(){n.Class=w})})(this);

@@ -0,1 +1,11 @@

/*
* JsFace Object Oriented Programming Library
* https://github.com/tannhu/jsface
*
* Copyright (c) 2009-2012 Tan Nhu
* Licensed under MIT license (https://github.com/tannhu/jsface/blob/master/MIT-LICENSE.txt).
*
* Date: Saturday, March 07 2009
* Version: 2.0.1
*/
!function(){

@@ -2,0 +12,0 @@ /**

@@ -1,2 +0,2 @@

Copyright (c) 2010 Tan Nhu
Copyright (c) 2009-2012 Tan Nhu

@@ -3,0 +3,0 @@ Permission is hereby granted, free of charge, to any person obtaining a copy

@@ -6,4 +6,4 @@ {

"author" : "Tan Nhu <tnhu AT me . com>",
"version" : "2.0.0",
"keywords" : [ "jsface", "JsFace", "OOP", "JavaScript OOP", "JavaScript Object Oriented Programming" ],
"version" : "2.0.1",
"keywords" : [ "jsface", "JSFace", "OOP", "JavaScript OOP", "JavaScript Object Oriented Programming" ],
"homepage" : "https://github.com/tannhu/jsface",

@@ -10,0 +10,0 @@ "licenses" : [{

@@ -8,3 +8,3 @@ JSFace is a library designed to facilitate object-oriented programming in JavaScript.

* Support CommonJS.
* Support singleton, trait, private properties.
* Support singleton, mixin, private properties.
* Plugins mechanism to extend itself.

@@ -117,3 +117,3 @@

var Person = Class(function() {
var MIN_AGE = 0, // private variables
var MIN_AGE = 1, // private variables
MAX_AGE = 150;

@@ -169,3 +169,3 @@

var Student = Class([ Person, Options, Events ], {
constructor: function(id, name, age) {
constructor: function(id, name, age) {}
});

@@ -204,3 +204,3 @@

``` javascript
extend(Array.prototype, {
extend(String.prototype, {
trim: function() {

@@ -213,2 +213,24 @@ return this.replace(/^\s+|\s+$/g, "");

```
## No conflict
In browser environment, you might be using another library which also introduces the global namespace Class. JSFace can return the original Class back to the library claims it with a call to jsface.noConflict().
``` javascript
jsface.noConflict();
// Code that uses other library's Class can follow here
```
Actually, Class is an alias of jsface.Class:
``` javascript
jsface.noConflict();
// Code that uses other library's Class can follow here
// Define classes by using jsface.Class directly
var Person = jsface.Class({
});
```
# Bug tracker

@@ -215,0 +237,0 @@

@@ -1,9 +0,9 @@

/*
* QUnit - A JavaScript Unit Testing Framework
/**
* QUnit v1.3.0pre - A JavaScript Unit Testing Framework
*
* http://docs.jquery.com/QUnit
*
* Copyright (c) 2009 John Resig, Jörn Zaefferer
* Copyright (c) 2011 John Resig, Jörn Zaefferer
* Dual licensed under the MIT (MIT-LICENSE.txt)
* and GPL (GPL-LICENSE.txt) licenses.
* or GPL (GPL-LICENSE.txt) licenses.
*/

@@ -13,214 +13,290 @@

var QUnit = {
var defined = {
setTimeout: typeof window.setTimeout !== "undefined",
sessionStorage: (function() {
try {
return !!sessionStorage.getItem;
} catch(e) {
return false;
}
})()
};
// call on start of module test to prepend name to all tests
module: function(name, testEnvironment) {
config.currentModule = name;
var testId = 0,
toString = Object.prototype.toString,
hasOwn = Object.prototype.hasOwnProperty;
synchronize(function() {
var Test = function(name, testName, expected, testEnvironmentArg, async, callback) {
this.name = name;
this.testName = testName;
this.expected = expected;
this.testEnvironmentArg = testEnvironmentArg;
this.async = async;
this.callback = callback;
this.assertions = [];
};
Test.prototype = {
init: function() {
var tests = id("qunit-tests");
if (tests) {
var b = document.createElement("strong");
b.innerHTML = "Running " + this.name;
var li = document.createElement("li");
li.appendChild( b );
li.className = "running";
li.id = this.id = "test-output" + testId++;
tests.appendChild( li );
}
},
setup: function() {
if (this.module != config.previousModule) {
if ( config.previousModule ) {
QUnit.moduleDone( config.currentModule, config.moduleStats.bad, config.moduleStats.all );
runLoggingCallbacks('moduleDone', QUnit, {
name: config.previousModule,
failed: config.moduleStats.bad,
passed: config.moduleStats.all - config.moduleStats.bad,
total: config.moduleStats.all
} );
}
config.previousModule = config.currentModule;
config.currentModule = name;
config.moduleTestEnvironment = testEnvironment;
config.previousModule = this.module;
config.moduleStats = { all: 0, bad: 0 };
runLoggingCallbacks( 'moduleStart', QUnit, {
name: this.module
} );
}
QUnit.moduleStart( name, testEnvironment );
config.current = this;
this.testEnvironment = extend({
setup: function() {},
teardown: function() {}
}, this.moduleTestEnvironment);
if (this.testEnvironmentArg) {
extend(this.testEnvironment, this.testEnvironmentArg);
}
runLoggingCallbacks( 'testStart', QUnit, {
name: this.testName,
module: this.module
});
},
// allow utility functions to access the current test environment
// TODO why??
QUnit.current_testEnvironment = this.testEnvironment;
asyncTest: function(testName, expected, callback) {
if ( arguments.length === 2 ) {
callback = expected;
expected = 0;
try {
if ( !config.pollution ) {
saveGlobal();
}
this.testEnvironment.setup.call(this.testEnvironment);
} catch(e) {
QUnit.ok( false, "Setup failed on " + this.testName + ": " + e.message );
}
QUnit.test(testName, expected, callback, true);
},
run: function() {
config.current = this;
if ( this.async ) {
QUnit.stop();
}
test: function(testName, expected, callback, async) {
var name = '<span class="test-name">' + testName + '</span>', testEnvironment, testEnvironmentArg;
if ( config.notrycatch ) {
this.callback.call(this.testEnvironment);
return;
}
try {
this.callback.call(this.testEnvironment);
} catch(e) {
fail("Test " + this.testName + " died, exception and test follows", e, this.callback);
QUnit.ok( false, "Died on test #" + (this.assertions.length + 1) + ": " + e.message + " - " + QUnit.jsDump.parse(e) );
// else next test will carry the responsibility
saveGlobal();
if ( arguments.length === 2 ) {
callback = expected;
expected = null;
// Restart the tests if they're blocking
if ( config.blocking ) {
QUnit.start();
}
}
// is 2nd argument a testEnvironment?
if ( expected && typeof expected === 'object') {
testEnvironmentArg = expected;
expected = null;
},
teardown: function() {
config.current = this;
try {
this.testEnvironment.teardown.call(this.testEnvironment);
checkPollution();
} catch(e) {
QUnit.ok( false, "Teardown failed on " + this.testName + ": " + e.message );
}
if ( config.currentModule ) {
name = '<span class="module-name">' + config.currentModule + "</span>: " + name;
},
finish: function() {
config.current = this;
if ( this.expected != null && this.expected != this.assertions.length ) {
QUnit.ok( false, "Expected " + this.expected + " assertions, but " + this.assertions.length + " were run" );
}
if ( !validTest(config.currentModule + ": " + testName) ) {
return;
}
var good = 0, bad = 0,
tests = id("qunit-tests");
synchronize(function() {
config.stats.all += this.assertions.length;
config.moduleStats.all += this.assertions.length;
testEnvironment = extend({
setup: function() {},
teardown: function() {}
}, config.moduleTestEnvironment);
if (testEnvironmentArg) {
extend(testEnvironment,testEnvironmentArg);
}
if ( tests ) {
var ol = document.createElement("ol");
QUnit.testStart( testName, testEnvironment );
for ( var i = 0; i < this.assertions.length; i++ ) {
var assertion = this.assertions[i];
// allow utility functions to access the current test environment
QUnit.current_testEnvironment = testEnvironment;
var li = document.createElement("li");
li.className = assertion.result ? "pass" : "fail";
li.innerHTML = assertion.message || (assertion.result ? "okay" : "failed");
ol.appendChild( li );
config.assertions = [];
config.expected = expected;
var tests = id("qunit-tests");
if (tests) {
var b = document.createElement("strong");
b.innerHTML = "Running " + name;
var li = document.createElement("li");
li.appendChild( b );
li.id = "current-test-output";
tests.appendChild( li );
if ( assertion.result ) {
good++;
} else {
bad++;
config.stats.bad++;
config.moduleStats.bad++;
}
}
try {
if ( !config.pollution ) {
saveGlobal();
// store result when possible
if ( QUnit.config.reorder && defined.sessionStorage ) {
if (bad) {
sessionStorage.setItem("qunit-" + this.module + "-" + this.testName, bad);
} else {
sessionStorage.removeItem("qunit-" + this.module + "-" + this.testName);
}
testEnvironment.setup.call(testEnvironment);
} catch(e) {
QUnit.ok( false, "Setup failed on " + name + ": " + e.message );
}
});
synchronize(function() {
if ( async ) {
QUnit.stop();
if (bad == 0) {
ol.style.display = "none";
}
try {
callback.call(testEnvironment);
} catch(e) {
fail("Test " + name + " died, exception and test follows", e, callback);
QUnit.ok( false, "Died on test #" + (config.assertions.length + 1) + ": " + e.message + " - " + QUnit.jsDump.parse(e) );
// else next test will carry the responsibility
saveGlobal();
var b = document.createElement("strong");
b.innerHTML = this.name + " <b class='counts'>(<b class='failed'>" + bad + "</b>, <b class='passed'>" + good + "</b>, " + this.assertions.length + ")</b>";
// Restart the tests if they're blocking
if ( config.blocking ) {
start();
var a = document.createElement("a");
a.innerHTML = "Rerun";
a.href = QUnit.url({ filter: getText([b]).replace(/\([^)]+\)$/, "").replace(/(^\s*|\s*$)/g, "") });
addEvent(b, "click", function() {
var next = b.nextSibling.nextSibling,
display = next.style.display;
next.style.display = display === "none" ? "block" : "none";
});
addEvent(b, "dblclick", function(e) {
var target = e && e.target ? e.target : window.event.srcElement;
if ( target.nodeName.toLowerCase() == "span" || target.nodeName.toLowerCase() == "b" ) {
target = target.parentNode;
}
}
});
if ( window.location && target.nodeName.toLowerCase() === "strong" ) {
window.location = QUnit.url({ filter: getText([target]).replace(/\([^)]+\)$/, "").replace(/(^\s*|\s*$)/g, "") });
}
});
synchronize(function() {
try {
checkPollution();
testEnvironment.teardown.call(testEnvironment);
} catch(e) {
QUnit.ok( false, "Teardown failed on " + name + ": " + e.message );
}
});
var li = id(this.id);
li.className = bad ? "fail" : "pass";
li.removeChild( li.firstChild );
li.appendChild( b );
li.appendChild( a );
li.appendChild( ol );
synchronize(function() {
if ( config.expected && config.expected != config.assertions.length ) {
QUnit.ok( false, "Expected " + config.expected + " assertions, but " + config.assertions.length + " were run" );
} else {
for ( var i = 0; i < this.assertions.length; i++ ) {
if ( !this.assertions[i].result ) {
bad++;
config.stats.bad++;
config.moduleStats.bad++;
}
}
}
var good = 0, bad = 0,
tests = id("qunit-tests");
try {
QUnit.reset();
} catch(e) {
fail("reset() failed, following Test " + this.testName + ", exception and reset fn follows", e, QUnit.reset);
}
config.stats.all += config.assertions.length;
config.moduleStats.all += config.assertions.length;
runLoggingCallbacks( 'testDone', QUnit, {
name: this.testName,
module: this.module,
failed: bad,
passed: this.assertions.length - bad,
total: this.assertions.length
} );
},
if ( tests ) {
var ol = document.createElement("ol");
queue: function() {
var test = this;
synchronize(function() {
test.init();
});
function run() {
// each of these can by async
synchronize(function() {
test.setup();
});
synchronize(function() {
test.run();
});
synchronize(function() {
test.teardown();
});
synchronize(function() {
test.finish();
});
}
// defer when previous test run passed, if storage is available
var bad = QUnit.config.reorder && defined.sessionStorage && +sessionStorage.getItem("qunit-" + this.module + "-" + this.testName);
if (bad) {
run();
} else {
synchronize(run, true);
};
}
for ( var i = 0; i < config.assertions.length; i++ ) {
var assertion = config.assertions[i];
};
var li = document.createElement("li");
li.className = assertion.result ? "pass" : "fail";
li.innerHTML = assertion.message || (assertion.result ? "okay" : "failed");
ol.appendChild( li );
var QUnit = {
if ( assertion.result ) {
good++;
} else {
bad++;
config.stats.bad++;
config.moduleStats.bad++;
}
}
if (bad == 0) {
ol.style.display = "none";
}
// call on start of module test to prepend name to all tests
module: function(name, testEnvironment) {
config.currentModule = name;
config.currentModuleTestEnviroment = testEnvironment;
},
var b = document.createElement("strong");
b.innerHTML = name + " <b class='counts'>(<b class='failed'>" + bad + "</b>, <b class='passed'>" + good + "</b>, " + config.assertions.length + ")</b>";
asyncTest: function(testName, expected, callback) {
if ( arguments.length === 2 ) {
callback = expected;
expected = null;
}
addEvent(b, "click", function() {
var next = b.nextSibling, display = next.style.display;
next.style.display = display === "none" ? "block" : "none";
});
QUnit.test(testName, expected, callback, true);
},
addEvent(b, "dblclick", function(e) {
var target = e && e.target ? e.target : window.event.srcElement;
if ( target.nodeName.toLowerCase() == "span" || target.nodeName.toLowerCase() == "b" ) {
target = target.parentNode;
}
if ( window.location && target.nodeName.toLowerCase() === "strong" ) {
window.location.search = "?" + encodeURIComponent(getText([target]).replace(/\(.+\)$/, "").replace(/(^\s*|\s*$)/g, ""));
}
});
test: function(testName, expected, callback, async) {
var name = '<span class="test-name">' + escapeInnerText(testName) + '</span>', testEnvironmentArg;
var li = id("current-test-output");
li.id = "";
li.className = bad ? "fail" : "pass";
li.style.display = resultDisplayStyle(!bad);
li.removeChild( li.firstChild );
li.appendChild( b );
li.appendChild( ol );
if ( arguments.length === 2 ) {
callback = expected;
expected = null;
}
// is 2nd argument a testEnvironment?
if ( expected && typeof expected === 'object') {
testEnvironmentArg = expected;
expected = null;
}
if ( bad ) {
var toolbar = id("qunit-testrunner-toolbar");
if ( toolbar ) {
toolbar.style.display = "block";
id("qunit-filter-pass").disabled = null;
id("qunit-filter-missing").disabled = null;
}
}
if ( config.currentModule ) {
name = '<span class="module-name">' + config.currentModule + "</span>: " + name;
}
} else {
for ( var i = 0; i < config.assertions.length; i++ ) {
if ( !config.assertions[i].result ) {
bad++;
config.stats.bad++;
config.moduleStats.bad++;
}
}
}
if ( !validTest(config.currentModule + ": " + testName) ) {
return;
}
try {
QUnit.reset();
} catch(e) {
fail("reset() failed, following Test " + name + ", exception and reset fn follows", e, QUnit.reset);
}
QUnit.testDone( testName, bad, config.assertions.length );
if ( !window.setTimeout && !config.queue.length ) {
done();
}
});
synchronize( done );
var test = new Test(name, testName, expected, testEnvironmentArg, async, callback);
test.module = config.currentModule;
test.moduleTestEnvironment = config.currentModuleTestEnviroment;
test.queue();
},

@@ -232,3 +308,3 @@

expect: function(asserts) {
config.expected = asserts;
config.current.expected = asserts;
},

@@ -246,5 +322,5 @@

};
msg = escapeHtml(msg);
QUnit.log(a, msg, details);
config.assertions.push({
msg = escapeInnerText(msg);
runLoggingCallbacks( 'log', QUnit, details );
config.current.assertions.push({
result: a,

@@ -291,16 +367,51 @@ message: msg

raises: function(fn, message) {
raises: function(block, expected, message) {
var actual, ok = false;
if (typeof expected === 'string') {
message = expected;
expected = null;
}
try {
fn();
ok( false, message );
block();
} catch (e) {
actual = e;
}
catch (e) {
ok( true, message );
if (actual) {
// we don't want to validate thrown error
if (!expected) {
ok = true;
// expected is a regexp
} else if (QUnit.objectType(expected) === "regexp") {
ok = expected.test(actual);
// expected is a constructor
} else if (actual instanceof expected) {
ok = true;
// expected is a validation function which returns true is validation passed
} else if (expected.call({}, actual) === true) {
ok = true;
}
}
QUnit.ok(ok, message);
},
start: function() {
start: function(count) {
config.semaphore -= count || 1;
if (config.semaphore > 0) {
// don't start until equal number of stop-calls
return;
}
if (config.semaphore < 0) {
// ignore if start is called more often then stop
config.semaphore = 0;
}
// A slight delay, to avoid any current callbacks
if ( window.setTimeout ) {
if ( defined.setTimeout ) {
window.setTimeout(function() {
if (config.semaphore > 0) {
return;
}
if ( config.timeout ) {

@@ -311,23 +422,34 @@ clearTimeout(config.timeout);

config.blocking = false;
process();
process(true);
}, 13);
} else {
config.blocking = false;
process();
process(true);
}
},
stop: function(timeout) {
stop: function(count) {
config.semaphore += count || 1;
config.blocking = true;
if ( timeout && window.setTimeout ) {
if ( config.testTimeout && defined.setTimeout ) {
clearTimeout(config.timeout);
config.timeout = window.setTimeout(function() {
QUnit.ok( false, "Test timed out" );
config.semaphore = 1;
QUnit.start();
}, timeout);
}, config.testTimeout);
}
}
};
//We want access to the constructor's prototype
(function() {
function F(){};
F.prototype = QUnit;
QUnit = new F();
//Make F QUnit's constructor so that we can add to the prototype later
QUnit.constructor = F;
})();
// Backwards compatibility, deprecated

@@ -343,3 +465,25 @@ QUnit.equals = QUnit.equal;

// block until document ready
blocking: true
blocking: true,
// when enabled, show only failing tests
// gets persisted through sessionStorage and can be changed in UI via checkbox
hidepassed: false,
// by default, run previously failed tests first
// very useful in combination with "Hide passed tests" checked
reorder: true,
// by default, modify document.title when suite is done
altertitle: true,
urlConfig: ['noglobals', 'notrycatch'],
//logging callback queues
begin: [],
done: [],
log: [],
testStart: [],
testDone: [],
moduleStart: [],
moduleDone: []
};

@@ -350,18 +494,19 @@

var location = window.location || { search: "", protocol: "file:" },
GETParams = location.search.slice(1).split('&');
params = location.search.slice( 1 ).split( "&" ),
length = params.length,
urlParams = {},
current;
for ( var i = 0; i < GETParams.length; i++ ) {
GETParams[i] = decodeURIComponent( GETParams[i] );
if ( GETParams[i] === "noglobals" ) {
GETParams.splice( i, 1 );
i--;
config.noglobals = true;
} else if ( GETParams[i].search('=') > -1 ) {
GETParams.splice( i, 1 );
i--;
if ( params[ 0 ] ) {
for ( var i = 0; i < length; i++ ) {
current = params[ i ].split( "=" );
current[ 0 ] = decodeURIComponent( current[ 0 ] );
// allow just a key to turn on a flag, e.g., test.html?noglobals
current[ 1 ] = current[ 1 ] ? decodeURIComponent( current[ 1 ] ) : true;
urlParams[ current[ 0 ] ] = current[ 1 ];
}
}
// restrict modules/tests by get parameters
config.filters = GETParams;
QUnit.urlParams = urlParams;
config.filter = urlParams.filter;

@@ -396,10 +541,10 @@ // Figure out if we're running the tests from a server or not

autorun: false,
assertions: [],
filters: [],
queue: []
filter: "",
queue: [],
semaphore: 0
});
var tests = id("qunit-tests"),
banner = id("qunit-banner"),
result = id("qunit-testresult");
var tests = id( "qunit-tests" ),
banner = id( "qunit-banner" ),
result = id( "qunit-testresult" );

@@ -417,2 +562,10 @@ if ( tests ) {

}
if ( tests ) {
result = document.createElement( "p" );
result.id = "qunit-testresult";
result.className = "result";
tests.parentNode.insertBefore( result, tests );
result.innerHTML = 'Running...<br/>&nbsp;';
}
},

@@ -427,5 +580,5 @@

if ( window.jQuery ) {
jQuery( "#main, #qunit-fixture" ).html( config.fixture );
jQuery( "#qunit-fixture" ).html( config.fixture );
} else {
var main = id( 'main' ) || id( 'qunit-fixture' );
var main = id( 'qunit-fixture' );
if ( main ) {

@@ -472,4 +625,3 @@ main.innerHTML = config.fixture;

var type = Object.prototype.toString.call( obj )
.match(/^\[object\s(.*)\]$/)[1] || '';
var type = toString.call( obj ).match(/^\[object\s(.*)\]$/)[1] || '';

@@ -505,14 +657,23 @@ switch (type) {

message = escapeHtml(message) || (result ? "okay" : "failed");
message = escapeInnerText(message) || (result ? "okay" : "failed");
message = '<span class="test-message">' + message + "</span>";
expected = escapeHtml(QUnit.jsDump.parse(expected));
actual = escapeHtml(QUnit.jsDump.parse(actual));
var output = message + ', expected: <span class="test-expected">' + expected + '</span>';
expected = escapeInnerText(QUnit.jsDump.parse(expected));
actual = escapeInnerText(QUnit.jsDump.parse(actual));
var output = message + '<table><tr class="test-expected"><th>Expected: </th><td><pre>' + expected + '</pre></td></tr>';
if (actual != expected) {
output += ' result: <span class="test-actual">' + actual + '</span>, diff: ' + QUnit.diff(expected, actual);
output += '<tr class="test-actual"><th>Result: </th><td><pre>' + actual + '</pre></td></tr>';
output += '<tr class="test-diff"><th>Diff: </th><td><pre>' + QUnit.diff(expected, actual) +'</pre></td></tr>';
}
if (!result) {
var source = sourceFromStacktrace();
if (source) {
details.source = source;
output += '<tr class="test-source"><th>Source: </th><td><pre>' + escapeInnerText(source) + '</pre></td></tr>';
}
}
output += "</table>";
QUnit.log(result, message, details);
runLoggingCallbacks( 'log', QUnit, details );
config.assertions.push({
config.current.assertions.push({
result: !!result,

@@ -523,12 +684,42 @@ message: output

// Logging callbacks
begin: function() {},
done: function(failures, total) {},
log: function(result, message) {},
testStart: function(name, testEnvironment) {},
testDone: function(name, failures, total) {},
moduleStart: function(name, testEnvironment) {},
moduleDone: function(name, failures, total) {}
url: function( params ) {
params = extend( extend( {}, QUnit.urlParams ), params );
var querystring = "?",
key;
for ( key in params ) {
if ( !hasOwn.call( params, key ) ) {
continue;
}
querystring += encodeURIComponent( key ) + "=" +
encodeURIComponent( params[ key ] ) + "&";
}
return window.location.pathname + querystring.slice( 0, -1 );
},
extend: extend,
id: id,
addEvent: addEvent
});
//QUnit.constructor is set to the empty F() above so that we can add to it's prototype later
//Doing this allows us to tell if the following methods have been overwritten on the actual
//QUnit object, which is a deprecated way of using the callbacks.
extend(QUnit.constructor.prototype, {
// Logging callbacks; all receive a single argument with the listed properties
// run test/logs.html for any related changes
begin: registerLoggingCallback('begin'),
// done: { failed, passed, total, runtime }
done: registerLoggingCallback('done'),
// log: { result, actual, expected, message }
log: registerLoggingCallback('log'),
// testStart: { name }
testStart: registerLoggingCallback('testStart'),
// testDone: { name, failed, passed, total }
testDone: registerLoggingCallback('testDone'),
// moduleStart: { name }
moduleStart: registerLoggingCallback('moduleStart'),
// moduleDone: { name, failed, passed, total }
moduleDone: registerLoggingCallback('moduleDone')
});
if ( typeof document === "undefined" || document.readyState === "complete" ) {

@@ -538,4 +729,4 @@ config.autorun = true;

addEvent(window, "load", function() {
QUnit.begin();
QUnit.load = function() {
runLoggingCallbacks( 'begin', QUnit, {} );

@@ -549,2 +740,8 @@ // Initialize the config, saving the execution queue

var urlConfigHtml = '', len = config.urlConfig.length;
for ( var i = 0, val; i < len, val = config.urlConfig[i]; i++ ) {
config[val] = QUnit.urlParams[val];
urlConfigHtml += '<label><input name="' + val + '" type="checkbox"' + ( config[val] ? ' checked="checked"' : '' ) + '>' + val + '</label>';
}
var userAgent = id("qunit-userAgent");

@@ -556,12 +753,8 @@ if ( userAgent ) {

if ( banner ) {
var paramsIndex = location.href.lastIndexOf(location.search);
if ( paramsIndex > -1 ) {
var mainPageLocation = location.href.slice(0, paramsIndex);
if ( mainPageLocation == location.href ) {
banner.innerHTML = '<a href=""> ' + banner.innerHTML + '</a> ';
} else {
var testName = decodeURIComponent(location.search.slice(1));
banner.innerHTML = '<a href="' + mainPageLocation + '">' + banner.innerHTML + '</a> &#8250; <a href="">' + testName + '</a>';
}
}
banner.innerHTML = '<a href="' + QUnit.url({ filter: undefined }) + '"> ' + banner.innerHTML + '</a> ' + urlConfigHtml;
addEvent( banner, "change", function( event ) {
var params = {};
params[ event.target.name ] = event.target.checked ? true : undefined;
window.location = QUnit.url( params );
});
}

@@ -571,16 +764,26 @@

if ( toolbar ) {
toolbar.style.display = "none";
var filter = document.createElement("input");
filter.type = "checkbox";
filter.id = "qunit-filter-pass";
filter.disabled = true;
addEvent( filter, "click", function() {
var li = document.getElementsByTagName("li");
for ( var i = 0; i < li.length; i++ ) {
if ( li[i].className.indexOf("pass") > -1 ) {
li[i].style.display = filter.checked ? "none" : "";
var ol = document.getElementById("qunit-tests");
if ( filter.checked ) {
ol.className = ol.className + " hidepass";
} else {
var tmp = " " + ol.className.replace( /[\n\t\r]/g, " " ) + " ";
ol.className = tmp.replace(/ hidepass /, " ");
}
if ( defined.sessionStorage ) {
if (filter.checked) {
sessionStorage.setItem("qunit-filter-passed-tests", "true");
} else {
sessionStorage.removeItem("qunit-filter-passed-tests");
}
}
});
if ( config.hidepassed || defined.sessionStorage && sessionStorage.getItem("qunit-filter-passed-tests") ) {
filter.checked = true;
var ol = document.getElementById("qunit-tests");
ol.className = ol.className + " hidepass";
}
toolbar.appendChild( filter );

@@ -592,24 +795,5 @@

toolbar.appendChild( label );
var missing = document.createElement("input");
missing.type = "checkbox";
missing.id = "qunit-filter-missing";
missing.disabled = true;
addEvent( missing, "click", function() {
var li = document.getElementsByTagName("li");
for ( var i = 0; i < li.length; i++ ) {
if ( li[i].className.indexOf("fail") > -1 && li[i].innerHTML.indexOf('missing test - untested code is broken code') > - 1 ) {
li[i].parentNode.parentNode.style.display = missing.checked ? "none" : "block";
}
}
});
toolbar.appendChild( missing );
label = document.createElement("label");
label.setAttribute("for", "qunit-filter-missing");
label.innerHTML = "Hide missing tests (untested code is broken code)";
toolbar.appendChild( label );
}
var main = id('main') || id('qunit-fixture');
var main = id('qunit-fixture');
if ( main ) {

@@ -622,22 +806,18 @@ config.fixture = main.innerHTML;

}
});
};
function done() {
if ( config.doneTimer && window.clearTimeout ) {
window.clearTimeout( config.doneTimer );
config.doneTimer = null;
}
addEvent(window, "load", QUnit.load);
if ( config.queue.length ) {
config.doneTimer = window.setTimeout(function(){
if ( !config.queue.length ) {
done();
} else {
synchronize( done );
}
}, 13);
return;
// addEvent(window, "error") gives us a useless event object
window.onerror = function( message, file, line ) {
if ( QUnit.config.current ) {
ok( false, message + ", " + file + ":" + line );
} else {
test( "global failure", function() {
ok( false, message + ", " + file + ":" + line );
});
}
};
function done() {
config.autorun = true;

@@ -647,3 +827,8 @@

if ( config.currentModule ) {
QUnit.moduleDone( config.currentModule, config.moduleStats.bad, config.moduleStats.all );
runLoggingCallbacks( 'moduleDone', QUnit, {
name: config.currentModule,
failed: config.moduleStats.bad,
passed: config.moduleStats.all - config.moduleStats.bad,
total: config.moduleStats.all
} );
}

@@ -653,5 +838,16 @@

tests = id("qunit-tests"),
html = ['Tests completed in ',
+new Date - config.started, ' milliseconds.<br/>',
'<span class="passed">', config.stats.all - config.stats.bad, '</span> tests of <span class="total">', config.stats.all, '</span> passed, <span class="failed">', config.stats.bad,'</span> failed.'].join('');
runtime = +new Date - config.started,
passed = config.stats.all - config.stats.bad,
html = [
'Tests completed in ',
runtime,
' milliseconds.<br/>',
'<span class="passed">',
passed,
'</span> tests of <span class="total">',
config.stats.all,
'</span> passed, <span class="failed">',
config.stats.bad,
'</span> failed.'
].join('');

@@ -663,40 +859,41 @@ if ( banner ) {

if ( tests ) {
var result = id("qunit-testresult");
id( "qunit-testresult" ).innerHTML = html;
}
if ( !result ) {
result = document.createElement("p");
result.id = "qunit-testresult";
result.className = "result";
tests.parentNode.insertBefore( result, tests.nextSibling );
}
result.innerHTML = html;
if ( config.altertitle && typeof document !== "undefined" && document.title ) {
// show ✖ for good, ✔ for bad suite result in title
// use escape sequences in case file gets loaded with non-utf-8-charset
document.title = [
(config.stats.bad ? "\u2716" : "\u2714"),
document.title.replace(/^[\u2714\u2716] /i, "")
].join(" ");
}
QUnit.done( config.stats.bad, config.stats.all );
runLoggingCallbacks( 'done', QUnit, {
failed: config.stats.bad,
passed: passed,
total: config.stats.all,
runtime: runtime
} );
}
function validTest( name ) {
var i = config.filters.length,
var filter = config.filter,
run = false;
if ( !i ) {
if ( !filter ) {
return true;
}
while ( i-- ) {
var filter = config.filters[i],
not = filter.charAt(0) == '!';
var not = filter.charAt( 0 ) === "!";
if ( not ) {
filter = filter.slice( 1 );
}
if ( not ) {
filter = filter.slice(1);
}
if ( name.indexOf( filter ) !== -1 ) {
return !not;
}
if ( name.indexOf(filter) !== -1 ) {
return !not;
}
if ( not ) {
run = true;
}
if ( not ) {
run = true;
}

@@ -707,7 +904,23 @@

function resultDisplayStyle(passed) {
return passed && id("qunit-filter-pass") && id("qunit-filter-pass").checked ? 'none' : '';
// so far supports only Firefox, Chrome and Opera (buggy)
// could be extended in the future to use something like https://github.com/csnover/TraceKit
function sourceFromStacktrace() {
try {
throw new Error();
} catch ( e ) {
if (e.stacktrace) {
// Opera
return e.stacktrace.split("\n")[6];
} else if (e.stack) {
// Firefox, Chrome
return e.stack.split("\n")[4];
} else if (e.sourceURL) {
// Safari, PhantomJS
// TODO sourceURL points at the 'throw new Error' line above, useless
//return e.sourceURL + ":" + e.line;
}
}
}
function escapeHtml(s) {
function escapeInnerText(s) {
if (!s) {

@@ -717,7 +930,5 @@ return "";

s = s + "";
return s.replace(/[\&"<>\\]/g, function(s) {
return s.replace(/[\&<>]/g, function(s) {
switch(s) {
case "&": return "&amp;";
case "\\": return "\\\\";
case '"': return '\"';
case "<": return "&lt;";

@@ -730,22 +941,28 @@ case ">": return "&gt;";

function synchronize( callback ) {
function synchronize( callback, last ) {
config.queue.push( callback );
if ( config.autorun && !config.blocking ) {
process();
process(last);
}
}
function process() {
var start = (new Date()).getTime();
function process( last ) {
var start = new Date().getTime();
config.depth = config.depth ? config.depth + 1 : 1;
while ( config.queue.length && !config.blocking ) {
if ( config.updateRate <= 0 || (((new Date()).getTime() - start) < config.updateRate) ) {
if ( !defined.setTimeout || config.updateRate <= 0 || ( ( new Date().getTime() - start ) < config.updateRate ) ) {
config.queue.shift()();
} else {
setTimeout( process, 13 );
window.setTimeout( function(){
process( last );
}, 13 );
break;
}
}
config.depth--;
if ( last && !config.blocking && !config.queue.length && config.depth === 0 ) {
done();
}
}

@@ -758,2 +975,5 @@

for ( var key in window ) {
if ( !hasOwn.call( window, key ) ) {
continue;
}
config.pollution.push( key );

@@ -768,12 +988,10 @@ }

var newGlobals = diff( old, config.pollution );
var newGlobals = diff( config.pollution, old );
if ( newGlobals.length > 0 ) {
ok( false, "Introduced global variable(s): " + newGlobals.join(", ") );
config.expected++;
}
var deletedGlobals = diff( config.pollution, old );
var deletedGlobals = diff( old, config.pollution );
if ( deletedGlobals.length > 0 ) {
ok( false, "Deleted global variable(s): " + deletedGlobals.join(", ") );
config.expected++;
}

@@ -801,2 +1019,3 @@ }

console.error(exception);
console.error(exception.stack);
console.warn(callback.toString());

@@ -811,3 +1030,9 @@

for ( var prop in b ) {
a[prop] = b[prop];
if ( b[prop] === undefined ) {
delete a[prop];
// Avoid "Member not found" error in IE8 caused by setting window.constructor
} else if ( prop !== "constructor" || a !== window ) {
a[prop] = b[prop];
}
}

@@ -833,172 +1058,212 @@

function registerLoggingCallback(key){
return function(callback){
config[key].push( callback );
};
}
// Supports deprecated method of completely overwriting logging callbacks
function runLoggingCallbacks(key, scope, args) {
//debugger;
var callbacks;
if ( QUnit.hasOwnProperty(key) ) {
QUnit[key].call(scope, args);
} else {
callbacks = config[key];
for( var i = 0; i < callbacks.length; i++ ) {
callbacks[i].call( scope, args );
}
}
}
// Test for equality any JavaScript type.
// Discussions and reference: http://philrathe.com/articles/equiv
// Test suites: http://philrathe.com/tests/equiv
// Author: Philippe Rathé <prathe@gmail.com>
QUnit.equiv = function () {
var innerEquiv; // the real equiv function
var callers = []; // stack to decide between skip/abort functions
var parents = []; // stack to avoiding loops from circular referencing
var innerEquiv; // the real equiv function
var callers = []; // stack to decide between skip/abort functions
var parents = []; // stack to avoiding loops from circular referencing
// Call the o related callback with the given arguments.
function bindCallbacks(o, callbacks, args) {
var prop = QUnit.objectType(o);
if (prop) {
if (QUnit.objectType(callbacks[prop]) === "function") {
return callbacks[prop].apply(callbacks, args);
} else {
return callbacks[prop]; // or undefined
}
}
}
// Call the o related callback with the given arguments.
function bindCallbacks(o, callbacks, args) {
var prop = QUnit.objectType(o);
if (prop) {
if (QUnit.objectType(callbacks[prop]) === "function") {
return callbacks[prop].apply(callbacks, args);
} else {
return callbacks[prop]; // or undefined
}
}
}
var callbacks = function () {
var getProto = Object.getPrototypeOf || function (obj) {
return obj.__proto__;
};
// for string, boolean, number and null
function useStrictEquality(b, a) {
if (b instanceof a.constructor || a instanceof b.constructor) {
// to catch short annotaion VS 'new' annotation of a declaration
// e.g. var i = 1;
// var j = new Number(1);
return a == b;
} else {
return a === b;
}
}
var callbacks = function () {
return {
"string": useStrictEquality,
"boolean": useStrictEquality,
"number": useStrictEquality,
"null": useStrictEquality,
"undefined": useStrictEquality,
// for string, boolean, number and null
function useStrictEquality(b, a) {
if (b instanceof a.constructor || a instanceof b.constructor) {
// to catch short annotaion VS 'new' annotation of a
// declaration
// e.g. var i = 1;
// var j = new Number(1);
return a == b;
} else {
return a === b;
}
}
"nan": function (b) {
return isNaN(b);
},
return {
"string" : useStrictEquality,
"boolean" : useStrictEquality,
"number" : useStrictEquality,
"null" : useStrictEquality,
"undefined" : useStrictEquality,
"date": function (b, a) {
return QUnit.objectType(b) === "date" && a.valueOf() === b.valueOf();
},
"nan" : function(b) {
return isNaN(b);
},
"regexp": function (b, a) {
return QUnit.objectType(b) === "regexp" &&
a.source === b.source && // the regex itself
a.global === b.global && // and its modifers (gmi) ...
a.ignoreCase === b.ignoreCase &&
a.multiline === b.multiline;
},
"date" : function(b, a) {
return QUnit.objectType(b) === "date"
&& a.valueOf() === b.valueOf();
},
// - skip when the property is a method of an instance (OOP)
// - abort otherwise,
// initial === would have catch identical references anyway
"function": function () {
var caller = callers[callers.length - 1];
return caller !== Object &&
typeof caller !== "undefined";
},
"regexp" : function(b, a) {
return QUnit.objectType(b) === "regexp"
&& a.source === b.source && // the regex itself
a.global === b.global && // and its modifers
// (gmi) ...
a.ignoreCase === b.ignoreCase
&& a.multiline === b.multiline;
},
"array": function (b, a) {
var i, j, loop;
var len;
// - skip when the property is a method of an instance (OOP)
// - abort otherwise,
// initial === would have catch identical references anyway
"function" : function() {
var caller = callers[callers.length - 1];
return caller !== Object && typeof caller !== "undefined";
},
// b could be an object literal here
if ( ! (QUnit.objectType(b) === "array")) {
return false;
}
"array" : function(b, a) {
var i, j, loop;
var len;
len = a.length;
if (len !== b.length) { // safe and faster
return false;
}
// b could be an object literal here
if (!(QUnit.objectType(b) === "array")) {
return false;
}
//track reference to avoid circular references
parents.push(a);
for (i = 0; i < len; i++) {
loop = false;
for(j=0;j<parents.length;j++){
if(parents[j] === a[i]){
loop = true;//dont rewalk array
}
}
if (!loop && ! innerEquiv(a[i], b[i])) {
parents.pop();
return false;
}
}
parents.pop();
return true;
},
len = a.length;
if (len !== b.length) { // safe and faster
return false;
}
"object": function (b, a) {
var i, j, loop;
var eq = true; // unless we can proove it
var aProperties = [], bProperties = []; // collection of strings
// track reference to avoid circular references
parents.push(a);
for (i = 0; i < len; i++) {
loop = false;
for (j = 0; j < parents.length; j++) {
if (parents[j] === a[i]) {
loop = true;// dont rewalk array
}
}
if (!loop && !innerEquiv(a[i], b[i])) {
parents.pop();
return false;
}
}
parents.pop();
return true;
},
// comparing constructors is more strict than using instanceof
if ( a.constructor !== b.constructor) {
return false;
}
"object" : function(b, a) {
var i, j, loop;
var eq = true; // unless we can proove it
var aProperties = [], bProperties = []; // collection of
// strings
// stack constructor before traversing properties
callers.push(a.constructor);
//track reference to avoid circular references
parents.push(a);
// comparing constructors is more strict than using
// instanceof
if (a.constructor !== b.constructor) {
// Allow objects with no prototype to be equivalent to
// objects with Object as their constructor.
if (!((getProto(a) === null && getProto(b) === Object.prototype) ||
(getProto(b) === null && getProto(a) === Object.prototype)))
{
return false;
}
}
for (i in a) { // be strict: don't ensures hasOwnProperty and go deep
loop = false;
for(j=0;j<parents.length;j++){
if(parents[j] === a[i])
loop = true; //don't go down the same path twice
}
aProperties.push(i); // collect a's properties
// stack constructor before traversing properties
callers.push(a.constructor);
// track reference to avoid circular references
parents.push(a);
if (!loop && ! innerEquiv(a[i], b[i])) {
eq = false;
break;
}
}
for (i in a) { // be strict: don't ensures hasOwnProperty
// and go deep
loop = false;
for (j = 0; j < parents.length; j++) {
if (parents[j] === a[i])
loop = true; // don't go down the same path
// twice
}
aProperties.push(i); // collect a's properties
callers.pop(); // unstack, we are done
parents.pop();
if (!loop && !innerEquiv(a[i], b[i])) {
eq = false;
break;
}
}
for (i in b) {
bProperties.push(i); // collect b's properties
}
callers.pop(); // unstack, we are done
parents.pop();
// Ensures identical properties name
return eq && innerEquiv(aProperties.sort(), bProperties.sort());
}
};
}();
for (i in b) {
bProperties.push(i); // collect b's properties
}
innerEquiv = function () { // can take multiple arguments
var args = Array.prototype.slice.apply(arguments);
if (args.length < 2) {
return true; // end transition
}
// Ensures identical properties name
return eq
&& innerEquiv(aProperties.sort(), bProperties
.sort());
}
};
}();
return (function (a, b) {
if (a === b) {
return true; // catch the most you can
} else if (a === null || b === null || typeof a === "undefined" || typeof b === "undefined" || QUnit.objectType(a) !== QUnit.objectType(b)) {
return false; // don't lose time with error prone cases
} else {
return bindCallbacks(a, callbacks, [b, a]);
}
innerEquiv = function() { // can take multiple arguments
var args = Array.prototype.slice.apply(arguments);
if (args.length < 2) {
return true; // end transition
}
// apply transition with (1..n) arguments
})(args[0], args[1]) && arguments.callee.apply(this, args.splice(1, args.length -1));
};
return (function(a, b) {
if (a === b) {
return true; // catch the most you can
} else if (a === null || b === null || typeof a === "undefined"
|| typeof b === "undefined"
|| QUnit.objectType(a) !== QUnit.objectType(b)) {
return false; // don't lose time with error prone cases
} else {
return bindCallbacks(a, callbacks, [ b, a ]);
}
return innerEquiv;
// apply transition with (1..n) arguments
})(args[0], args[1])
&& arguments.callee.apply(this, args.splice(1,
args.length - 1));
};
return innerEquiv;
}();
/**
* jsDump
* Copyright (c) 2008 Ariel Flesler - aflesler(at)gmail(dot)com | http://flesler.blogspot.com
* Licensed under BSD (http://www.opensource.org/licenses/bsd-license.php)
* Date: 5/15/2008
* jsDump Copyright (c) 2008 Ariel Flesler - aflesler(at)gmail(dot)com |
* http://flesler.blogspot.com Licensed under BSD
* (http://www.opensource.org/licenses/bsd-license.php) Date: 5/15/2008
*
* @projectDescription Advanced and extensible data dumping for Javascript.

@@ -1026,7 +1291,7 @@ * @version 1.0.0

};
function array( arr ) {
var i = arr.length, ret = Array(i);
function array( arr, stack ) {
var i = arr.length, ret = Array(i);
this.up();
while ( i-- )
ret[i] = this.parse( arr[i] );
ret[i] = this.parse( arr[i] , undefined , stack);
this.down();

@@ -1039,9 +1304,19 @@ return join( '[', ret, ']' );

var jsDump = {
parse:function( obj, type ) { //type is used mostly internally, you can fix a (custom)type in advance
var parser = this.parsers[ type || this.typeOf(obj) ];
parse:function( obj, type, stack ) { //type is used mostly internally, you can fix a (custom)type in advance
stack = stack || [ ];
var parser = this.parsers[ type || this.typeOf(obj) ];
type = typeof parser;
return type == 'function' ? parser.call( this, obj ) :
type == 'string' ? parser :
this.parsers.error;
var inStack = inArray(obj, stack);
if (inStack != -1) {
return 'recursion('+(inStack - stack.length)+')';
}
//else
if (type == 'function') {
stack.push(obj);
var res = parser.call( this, obj, stack );
stack.pop();
return res;
}
// else
return (type == 'string') ? parser : this.parsers.error;
},

@@ -1060,3 +1335,3 @@ typeOf:function( obj ) {

type = "function";
} else if (obj.setInterval && obj.document && !obj.nodeType) {
} else if (typeof obj.setInterval !== undefined && typeof obj.document !== "undefined" && typeof obj.nodeType === "undefined") {
type = "window";

@@ -1067,3 +1342,8 @@ } else if (obj.nodeType === 9) {

type = "node";
} else if (typeof obj === "object" && typeof obj.length === "number" && obj.length >= 0) {
} else if (
// native arrays
toString.call( obj ) === "[object Array]" ||
// NodeList objects
( typeof obj.length === "number" && typeof obj.item !== "undefined" && ( obj.length ? obj.item(0) === obj[0] : ( obj.item( 0 ) === null && typeof obj[0] === "undefined" ) ) )
) {
type = "array";

@@ -1108,3 +1388,3 @@ } else {

'null':'null',
undefined:'undefined',
'undefined':'undefined',
'function':function( fn ) {

@@ -1117,4 +1397,4 @@ var ret = 'function',

ret = [ ret, this.parse( fn, 'functionArgs' ), '){'].join('');
return join( ret, this.parse(fn,'functionCode'), '}' );
ret = [ ret, QUnit.jsDump.parse( fn, 'functionArgs' ), '){'].join('');
return join( ret, QUnit.jsDump.parse(fn,'functionCode'), '}' );
},

@@ -1124,13 +1404,15 @@ array: array,

arguments: array,
object:function( map ) {
object:function( map, stack ) {
var ret = [ ];
this.up();
for ( var key in map )
ret.push( this.parse(key,'key') + ': ' + this.parse(map[key]) );
this.down();
QUnit.jsDump.up();
for ( var key in map ) {
var val = map[key];
ret.push( QUnit.jsDump.parse(key,'key') + ': ' + QUnit.jsDump.parse(val, undefined, stack));
}
QUnit.jsDump.down();
return join( '{', ret, '}' );
},
node:function( node ) {
var open = this.HTML ? '&lt;' : '<',
close = this.HTML ? '&gt;' : '>';
var open = QUnit.jsDump.HTML ? '&lt;' : '<',
close = QUnit.jsDump.HTML ? '&gt;' : '>';

@@ -1140,6 +1422,6 @@ var tag = node.nodeName.toLowerCase(),

for ( var a in this.DOMAttrs ) {
var val = node[this.DOMAttrs[a]];
for ( var a in QUnit.jsDump.DOMAttrs ) {
var val = node[QUnit.jsDump.DOMAttrs[a]];
if ( val )
ret += ' ' + a + '=' + this.parse( val, 'attribute' );
ret += ' ' + a + '=' + QUnit.jsDump.parse( val, 'attribute' );
}

@@ -1172,4 +1454,4 @@ return ret + close + open + '/' + tag + close;

HTML:false,//if true, entities are escaped ( <, >, \t, space and \n )
indentChar:' ',//indentation unit
multiline:false //if true, items in a collection, are separated by a \n, else just a space.
indentChar:' ',//indentation unit
multiline:true //if true, items in a collection, are separated by a \n, else just a space.
};

@@ -1200,2 +1482,17 @@

//from jquery.js
function inArray( elem, array ) {
if ( array.indexOf ) {
return array.indexOf( elem );
}
for ( var i = 0, length = array.length; i < length; i++ ) {
if ( array[ i ] === elem ) {
return i;
}
}
return -1;
}
/*

@@ -1216,5 +1513,5 @@ * Javascript Diff Algorithm

QUnit.diff = (function() {
function diff(o, n){
var ns = new Object();
var os = new Object();
function diff(o, n) {
var ns = {};
var os = {};

@@ -1224,3 +1521,3 @@ for (var i = 0; i < n.length; i++) {

ns[n[i]] = {
rows: new Array(),
rows: [],
o: null

@@ -1234,3 +1531,3 @@ };

os[o[i]] = {
rows: new Array(),
rows: [],
n: null

@@ -1242,2 +1539,5 @@ };

for (var i in ns) {
if ( !hasOwn.call( ns, i ) ) {
continue;
}
if (ns[i].rows.length == 1 && typeof(os[i]) != "undefined" && os[i].rows.length == 1) {

@@ -1289,3 +1589,3 @@ n[ns[i].rows[0]] = {

return function(o, n){
return function(o, n) {
o = o.replace(/\s+$/, '');

@@ -1292,0 +1592,0 @@ n = n.replace(/\s+$/, '');

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

each("123456", function(e, index, st) {
ok(st[index] === e, "invalid each loop behavior over a string");
ok(st.charAt(index) === e, "invalid each loop behavior over a string");
});

@@ -82,12 +82,20 @@ });

ok( !isMap([ 1, 2, 3 ]), "jsface.isMap works incorrectly");
ok( !isMap(1), "jsface.isMap works incorrectly");
ok( !isMap(1234), "jsface.isMap works incorrectly");
});
test("Check type with jsface.isMap on iframe", function() {
var iframe, IObject;
var frame, iframe, IObject;
iframe = document.createElement("iframe");
document.body.appendChild(iframe);
IObject = window.frames[window.frames.length - 1].Object;
frame = window.frames[window.frames.length - 1];
// getObject returns JavaScript Object in iframe context
frame.getObject = function() {
return Object;
};
IObject = frame.getObject();
var map = new IObject();

@@ -115,8 +123,14 @@ map.one = 1;

test("Check type with jsface.isArray on iframe", function() {
var iframe, IArray, array;
var frame, iframe, IArray, array;
iframe = document.createElement("iframe");
document.body.appendChild(iframe);
IArray = window.frames[window.frames.length - 1].Array;
frame = window.frames[window.frames.length - 1];
frame.getArray = function() {
return Array;
};
IArray = frame.getArray();
array = new IArray(1, 2, 3);

@@ -141,8 +155,14 @@

test("Check type with jsface.isFunction on iframe", function() {
var iframe, IFunction, fn;
var frame, iframe, IFunction, fn;
iframe = document.createElement("iframe");
document.body.appendChild(iframe);
IFunction = window.frames[window.frames.length - 1].Function;
frame = window.frames[window.frames.length - 1];
frame.getFunction = function() {
return Function;
};
IFunction = frame.getFunction();
fn = new IFunction();

@@ -183,3 +203,28 @@ ok(isFunction(fn), "jsface.isFunction works incorrectly");

// Helper to inject a script and execute a callback when it's fully loaded
// Note: Old versions of Opera don't work well with this method (11.60 works perfectly).
function getScript(url, callback) {
var head = document.getElementsByTagName("head")[0],
script = document.createElement("script"),
done = false;
script.src = url;
script.type = "text/javascript";
script.onload = script.onreadystatechange = function() {
if ( !done && ( !this.readyState || this.readyState == "loaded" || this.readyState == "complete")) {
done = true;
callback();
script.onload = script.onreadystatechange = null;
head.removeChild(script);
}
}
head.appendChild(script);
}
asyncTest("CommonJS support", function() {
var head = document.getElementsByTagName("head")[0];
// this unit test is run on browsers for sure

@@ -193,8 +238,3 @@ ok(jsface, "jsface must be available globally");

// reload jsface.js
var script = document.createElement("script");
script.src = "../jsface.js";
script.type = "text/javascript";
script.onload = function() {
getScript("../jsface.js", function() {
var exports = context.module.exports;

@@ -211,28 +251,20 @@ start();

script.onload = null;
delete context.module;
}
document.body.appendChild(script);
context.module = undefined;
});
});
asyncTest("noConflict support", function() {
var clazz = context.Class;
var head = document.getElementsByTagName("head")[0],
clazz = context.Class;
context.Class = function() { return 1; };
// reload jsface.js
var script = document.createElement("script");
script.src = "../jsface.js";
script.type = "text/javascript";
script.onload = function() {
getScript("../jsface.js", function() {
jsface.noConflict();
ok(Class() === 1, "noConflict works incorrectly");
start();
script.onload = null;
context.Class = clazz;
}
ok(Class() === 1, "noConflict works incorrectly");
document.body.appendChild(script);
context.Class = jsface.Class;
});
});

@@ -513,2 +545,143 @@

test("Mixin: instance extends class", function() {
var Foo = Class({
constructor: function(name) {
this.name = name;
},
welcome: function() {
return "Welcome " + this.name;
},
sayHi: function() {
return "Hello World " + this.name;
}
});
var Bar = Class({
constructor: function(name) {
this.name = name;
},
welcome: function() {
return "invalid";
},
sayBye: function() {
return "Bye!";
}
});
var bar = new Bar("John Rambo");
extend(bar, Foo);
ok(bar.name === "John Rambo", "Invalid extend() behavior, constructor must be bound correctly");
ok(bar.welcome() === "Welcome John Rambo", "Invalid extend() behavior, property must be overriden properly");
ok(bar.sayHi() === "Hello World John Rambo", "Invalid extend() behavior");
ok(bar.sayBye() === "Bye!", "Invalid extend() behavior");
});
test("Mixin: instance extends multiple classes", function() {
var Foo = Class({
constructor: function(name) {
this.name = name;
},
welcome: function() {
return "Welcome " + this.name;
},
sayHi: function() {
return "Hello World " + this.name;
}
});
var Properties = Class({
setProperty: function(key, value) {
this[key] = value;
},
getProperty: function(key) {
return this[key];
}
});
var Bar = Class({
constructor: function(name) {
this.name = name;
},
welcome: function() {
return "invalid";
},
sayBye: function() {
return "Bye!";
}
});
var bar = new Bar("John Rambo");
extend(bar, [ Foo, Properties ]);
bar.setProperty("fooKey", "fooValue");
ok(bar.name === "John Rambo", "Invalid extend() behavior, constructor must be bound correctly");
ok(bar.welcome() === "Welcome John Rambo", "Invalid extend() behavior, property must be overriden properly");
ok(bar.sayHi() === "Hello World John Rambo", "Invalid extend() behavior");
ok(bar.sayBye() === "Bye!", "Invalid extend() behavior");
ok(bar.getProperty("fooKey") === "fooValue", "Invalid extend() behavior");
});
test("Mixin: instance extends class and instance", function() {
var Foo = Class({
constructor: function(name) {
this.name = name;
},
welcome: function() {
return "Welcome " + this.name;
},
sayHi: function() {
return "Hello World " + this.name;
}
});
var Properties = Class({
setProperty: function(key, value) {
this[key] = value;
},
getProperty: function(key) {
return this[key];
}
});
var Bar = Class({
constructor: function(name) {
this.name = name;
},
welcome: function() {
return "invalid";
},
sayBye: function() {
return "Bye!";
}
});
var bar = new Bar("John Rambo");
extend(bar, [ Foo, new Properties() ]);
bar.setProperty("fooKey", "fooValue");
ok(bar.name === "John Rambo", "Invalid extend() behavior, constructor must be bound correctly");
ok(bar.welcome() === "Welcome John Rambo", "Invalid extend() behavior, property must be overriden properly");
ok(bar.sayHi() === "Hello World John Rambo", "Invalid extend() behavior");
ok(bar.sayBye() === "Bye!", "Invalid extend() behavior");
ok(bar.getProperty("fooKey") === "fooValue", "Invalid extend() behavior");
});
test("Mixin: class extends singleton", function() {

@@ -568,2 +741,3 @@ var Foo = Class({

},
constructor: function(name) {

@@ -607,3 +781,3 @@ this.name = name;

this.name = name;
},
}
});

@@ -642,3 +816,3 @@

this.name = name;
},
}
});

@@ -660,2 +834,10 @@

test("Mixin: extending native objects", function() {
extend(String, {
trim: function() {
return this.replace(/^\s+|\s+$/g, "");
}
});
ok(" Hello World ".trim() === "Hello World", "Invalid extend() binding String.prototype");
extend(Array, {

@@ -767,3 +949,1 @@ sum: function() {

});

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