"use strict";var _typeof=typeof Symbol==="function"&&typeof Symbol.iterator==="symbol"?function(obj){return typeof obj;}:function(obj){return obj&&typeof Symbol==="function"&&obj.constructor===Symbol&&obj!==Symbol.prototype?"symbol":typeof obj;};/*!
 * QUnit 1.20.0
 * http://qunitjs.com/
 *
 * Copyright jQuery Foundation and other contributors
 * Released under the MIT license
 * http://jquery.org/license
 *
 * Date: 2015-10-27T17:53Z
 */(function(global){var QUnit={};var Date=global.Date;var now=Date.now||function(){return new Date().getTime();};var setTimeout=global.setTimeout;var clearTimeout=global.clearTimeout;// Store a local window from the global to allow direct references.
var window=global.window;var defined={document:window&&window.document!==undefined,setTimeout:setTimeout!==undefined,sessionStorage:function(){var x="qunit-test-string";try{sessionStorage.setItem(x,x);sessionStorage.removeItem(x);return true;}catch(e){return false;}}()};var fileName=(sourceFromStacktrace(0)||"").replace(/(:\d+)+\)?/,"").replace(/.+\//,"");var globalStartCalled=false;var runStarted=false;var toString=Object.prototype.toString,hasOwn=Object.prototype.hasOwnProperty;// returns a new Array with the elements that are in a but not in b
function diff(a,b){var i,j,result=a.slice();for(i=0;i<result.length;i++){for(j=0;j<b.length;j++){if(result[i]===b[j]){result.splice(i,1);i--;break;}}}return result;}// 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;}/**
 * Makes a clone of an object using only Array or Object as base,
 * and copies over the own enumerable properties.
 *
 * @param {Object} obj
 * @return {Object} New object with only the own properties (recursively).
 */function objectValues(obj){var key,val,vals=QUnit.is("array",obj)?[]:{};for(key in obj){if(hasOwn.call(obj,key)){val=obj[key];vals[key]=val===Object(val)?objectValues(val):val;}}return vals;}function extend(a,b,undefOnly){for(var prop in b){if(hasOwn.call(b,prop)){// Avoid "Member not found" error in IE8 caused by messing with window.constructor
// This block runs on every environment, so `global` is being used instead of `window`
// to avoid errors on node.
if(prop!=="constructor"||a!==global){if(b[prop]===undefined){delete a[prop];}else if(!(undefOnly&&typeof a[prop]!=="undefined")){a[prop]=b[prop];}}}}return a;}function objectType(obj){if(typeof obj==="undefined"){return"undefined";}// Consider: typeof null === object
if(obj===null){return"null";}var match=toString.call(obj).match(/^\[object\s(.*)\]$/),type=match&&match[1];switch(type){case"Number":if(isNaN(obj)){return"nan";}return"number";case"String":case"Boolean":case"Array":case"Set":case"Map":case"Date":case"RegExp":case"Function":case"Symbol":return type.toLowerCase();}if((typeof obj==="undefined"?"undefined":_typeof(obj))==="object"){return"object";}}// Safe object type checking
function is(type,obj){return QUnit.objectType(obj)===type;}var getUrlParams=function getUrlParams(){var i,current;var urlParams={};var location=window.location;var params=location.search.slice(1).split("&");var length=params.length;if(params[0]){for(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;if(urlParams[current[0]]){urlParams[current[0]]=[].concat(urlParams[current[0]],current[1]);}else{urlParams[current[0]]=current[1];}}}return urlParams;};// Doesn't support IE6 to IE9, it will return undefined on these browsers
// See also https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error/Stack
function extractStacktrace(e,offset){offset=offset===undefined?4:offset;var stack,include,i;if(e.stack){stack=e.stack.split("\n");if(/^error$/i.test(stack[0])){stack.shift();}if(fileName){include=[];for(i=offset;i<stack.length;i++){if(stack[i].indexOf(fileName)!==-1){break;}include.push(stack[i]);}if(include.length){return include.join("\n");}}return stack[offset];// Support: Safari <=6 only
}else if(e.sourceURL){// exclude useless self-reference for generated Error objects
if(/qunit.js$/.test(e.sourceURL)){return;}// for actual exceptions, this is useful
return e.sourceURL+":"+e.line;}}function sourceFromStacktrace(offset){var error=new Error();// Support: Safari <=7 only, IE <=10 - 11 only
// Not all browsers generate the `stack` property for `new Error()`, see also #636
if(!error.stack){try{throw error;}catch(err){error=err;}}return extractStacktrace(error,offset);}/**
 * Config object: Maintain internal state
 * Later exposed as QUnit.config
 * `config` initialized at top of scope
 */var config={// The queue of tests to run
queue:[],// block until document ready
blocking:true,// 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,// HTML Reporter: collapse every test except the first failing test
// If false, all failing tests will be expanded
collapse:true,// by default, scroll to top of the page when suite is done
scrolltop:true,// depth up-to which object will be dumped
maxDepth:5,// when enabled, all tests must call expect()
requireExpects:false,// add checkboxes that are persisted in the query-string
// when enabled, the id is set to `true` as a `QUnit.config` property
urlConfig:[{id:"hidepassed",label:"Hide passed tests",tooltip:"Only show tests and assertions that fail. Stored as query-strings."},{id:"noglobals",label:"Check for Globals",tooltip:"Enabling this will test if any test introduces new properties on the "+"global object (`window` in Browsers). Stored as query-strings."},{id:"notrycatch",label:"No try-catch",tooltip:"Enabling this will run tests outside of a try-catch block. Makes debugging "+"exceptions in IE reasonable. Stored as query-strings."}],// Set of all modules.
modules:[],// Stack of nested modules
moduleStack:[],// The first unnamed module
currentModule:{name:"",tests:[]},callbacks:{}};var urlParams=defined.document?getUrlParams():{};// Push a loose unnamed module to the modules collection
config.modules.push(config.currentModule);if(urlParams.filter===true){delete urlParams.filter;}// String search anywhere in moduleName+testName
config.filter=urlParams.filter;config.testId=[];if(urlParams.testId){// Ensure that urlParams.testId is an array
urlParams.testId=decodeURIComponent(urlParams.testId).split(",");for(var i=0;i<urlParams.testId.length;i++){config.testId.push(urlParams.testId[i]);}}var loggingCallbacks={};// Register logging callbacks
function registerLoggingCallbacks(obj){var i,l,key,callbackNames=["begin","done","log","testStart","testDone","moduleStart","moduleDone"];function registerLoggingCallback(key){var loggingCallback=function loggingCallback(callback){if(objectType(callback)!=="function"){throw new Error("QUnit logging methods require a callback function as their first parameters.");}config.callbacks[key].push(callback);};// DEPRECATED: This will be removed on QUnit 2.0.0+
// Stores the registered functions allowing restoring
// at verifyLoggingCallbacks() if modified
loggingCallbacks[key]=loggingCallback;return loggingCallback;}for(i=0,l=callbackNames.length;i<l;i++){key=callbackNames[i];// Initialize key collection of logging callback
if(objectType(config.callbacks[key])==="undefined"){config.callbacks[key]=[];}obj[key]=registerLoggingCallback(key);}}function runLoggingCallbacks(key,args){var i,l,callbacks;callbacks=config.callbacks[key];for(i=0,l=callbacks.length;i<l;i++){callbacks[i](args);}}// DEPRECATED: This will be removed on 2.0.0+
// This function verifies if the loggingCallbacks were modified by the user
// If so, it will restore it, assign the given callback and print a console warning
function verifyLoggingCallbacks(){var loggingCallback,userCallback;for(loggingCallback in loggingCallbacks){if(QUnit[loggingCallback]!==loggingCallbacks[loggingCallback]){userCallback=QUnit[loggingCallback];// Restore the callback function
QUnit[loggingCallback]=loggingCallbacks[loggingCallback];// Assign the deprecated given callback
QUnit[loggingCallback](userCallback);if(global.console&&global.console.warn){global.console.warn("QUnit."+loggingCallback+" was replaced with a new value.\n"+"Please, check out the documentation on how to apply logging callbacks.\n"+"Reference: http://api.qunitjs.com/category/callbacks/");}}}}(function(){if(!defined.document){return;}// `onErrorFnPrev` initialized at top of scope
// Preserve other handlers
var onErrorFnPrev=window.onerror;// Cover uncaught exceptions
// Returning true will suppress the default browser handler,
// returning false will let it run.
window.onerror=function(error,filePath,linerNr){var ret=false;if(onErrorFnPrev){ret=onErrorFnPrev(error,filePath,linerNr);}// Treat return value as window.onerror itself does,
// Only do our handling if not suppressed.
if(ret!==true){if(QUnit.config.current){if(QUnit.config.current.ignoreGlobalErrors){return true;}QUnit.pushFailure(error,filePath+":"+linerNr);}else{QUnit.test("global failure",extend(function(){QUnit.pushFailure(error,filePath+":"+linerNr);},{validTest:true}));}return false;}return ret;};})();QUnit.urlParams=urlParams;// Figure out if we're running the tests from a server or not
QUnit.isLocal=!(defined.document&&window.location.protocol!=="file:");// Expose the current QUnit version
QUnit.version="1.20.0";extend(QUnit,{// call on start of module test to prepend name to all tests
module:function module(name,testEnvironment,executeNow){var module,moduleFns;var currentModule=config.currentModule;if(arguments.length===2){if(testEnvironment instanceof Function){executeNow=testEnvironment;testEnvironment=undefined;}}// DEPRECATED: handles setup/teardown functions,
// beforeEach and afterEach should be used instead
if(testEnvironment&&testEnvironment.setup){testEnvironment.beforeEach=testEnvironment.setup;delete testEnvironment.setup;}if(testEnvironment&&testEnvironment.teardown){testEnvironment.afterEach=testEnvironment.teardown;delete testEnvironment.teardown;}module=createModule();moduleFns={beforeEach:setHook(module,"beforeEach"),afterEach:setHook(module,"afterEach")};if(executeNow instanceof Function){config.moduleStack.push(module);setCurrentModule(module);executeNow.call(module.testEnvironment,moduleFns);config.moduleStack.pop();module=module.parentModule||currentModule;}setCurrentModule(module);function createModule(){var parentModule=config.moduleStack.length?config.moduleStack.slice(-1)[0]:null;var moduleName=parentModule!==null?[parentModule.name,name].join(" > "):name;var module={name:moduleName,parentModule:parentModule,tests:[]};var env={};if(parentModule){extend(env,parentModule.testEnvironment);delete env.beforeEach;delete env.afterEach;}extend(env,testEnvironment);module.testEnvironment=env;config.modules.push(module);return module;}function setCurrentModule(module){config.currentModule=module;}},// DEPRECATED: QUnit.asyncTest() will be removed in QUnit 2.0.
asyncTest:asyncTest,test:test,skip:skip,only:only,// DEPRECATED: The functionality of QUnit.start() will be altered in QUnit 2.0.
// In QUnit 2.0, invoking it will ONLY affect the `QUnit.config.autostart` blocking behavior.
start:function start(count){var globalStartAlreadyCalled=globalStartCalled;if(!config.current){globalStartCalled=true;if(runStarted){throw new Error("Called start() outside of a test context while already started");}else if(globalStartAlreadyCalled||count>1){throw new Error("Called start() outside of a test context too many times");}else if(config.autostart){throw new Error("Called start() outside of a test context when "+"QUnit.config.autostart was true");}else if(!config.pageLoaded){// The page isn't completely loaded yet, so bail out and let `QUnit.load` handle it
config.autostart=true;return;}}else{// If a test is running, adjust its semaphore
config.current.semaphore-=count||1;// If semaphore is non-numeric, throw error
if(isNaN(config.current.semaphore)){config.current.semaphore=0;QUnit.pushFailure("Called start() with a non-numeric decrement.",sourceFromStacktrace(2));return;}// Don't start until equal number of stop-calls
if(config.current.semaphore>0){return;}// throw an Error if start is called more often than stop
if(config.current.semaphore<0){config.current.semaphore=0;QUnit.pushFailure("Called start() while already started (test's semaphore was 0 already)",sourceFromStacktrace(2));return;}}resumeProcessing();},// DEPRECATED: QUnit.stop() will be removed in QUnit 2.0.
stop:function stop(count){// If there isn't a test running, don't allow QUnit.stop() to be called
if(!config.current){throw new Error("Called stop() outside of a test context");}// If a test is running, adjust its semaphore
config.current.semaphore+=count||1;pauseProcessing();},config:config,is:is,objectType:objectType,extend:extend,load:function load(){config.pageLoaded=true;// Initialize the configuration options
extend(config,{stats:{all:0,bad:0},moduleStats:{all:0,bad:0},started:0,updateRate:1000,autostart:true,filter:""},true);config.blocking=false;if(config.autostart){resumeProcessing();}},stack:function stack(offset){offset=(offset||0)+2;return sourceFromStacktrace(offset);}});registerLoggingCallbacks(QUnit);function begin(){var i,l,modulesLog=[];// If the test run hasn't officially begun yet
if(!config.started){// Record the time of the test run's beginning
config.started=now();verifyLoggingCallbacks();// Delete the loose unnamed module if unused.
if(config.modules[0].name===""&&config.modules[0].tests.length===0){config.modules.shift();}// Avoid unnecessary information by not logging modules' test environments
for(i=0,l=config.modules.length;i<l;i++){modulesLog.push({name:config.modules[i].name,tests:config.modules[i].tests});}// The test run is officially beginning now
runLoggingCallbacks("begin",{totalTests:Test.count,modules:modulesLog});}config.blocking=false;process(true);}function process(last){function next(){process(last);}var start=now();config.depth=(config.depth||0)+1;while(config.queue.length&&!config.blocking){if(!defined.setTimeout||config.updateRate<=0||now()-start<config.updateRate){if(config.current){// Reset async tracking for each phase of the Test lifecycle
config.current.usedAsync=false;}config.queue.shift()();}else{setTimeout(next,13);break;}}config.depth--;if(last&&!config.blocking&&!config.queue.length&&config.depth===0){done();}}function pauseProcessing(){config.blocking=true;if(config.testTimeout&&defined.setTimeout){clearTimeout(config.timeout);config.timeout=setTimeout(function(){if(config.current){config.current.semaphore=0;QUnit.pushFailure("Test timed out",sourceFromStacktrace(2));}else{throw new Error("Test timed out");}resumeProcessing();},config.testTimeout);}}function resumeProcessing(){runStarted=true;// A slight delay to allow this iteration of the event loop to finish (more assertions, etc.)
if(defined.setTimeout){setTimeout(function(){if(config.current&&config.current.semaphore>0){return;}if(config.timeout){clearTimeout(config.timeout);}begin();},13);}else{begin();}}function done(){var runtime,passed;config.autorun=true;// Log the last module results
if(config.previousModule){runLoggingCallbacks("moduleDone",{name:config.previousModule.name,tests:config.previousModule.tests,failed:config.moduleStats.bad,passed:config.moduleStats.all-config.moduleStats.bad,total:config.moduleStats.all,runtime:now()-config.moduleStats.started});}delete config.previousModule;runtime=now()-config.started;passed=config.stats.all-config.stats.bad;runLoggingCallbacks("done",{failed:config.stats.bad,passed:passed,total:config.stats.all,runtime:runtime});}function setHook(module,hookName){if(module.testEnvironment===undefined){module.testEnvironment={};}return function(callback){module.testEnvironment[hookName]=callback;};}var focused=false;function Test(settings){var i,l;++Test.count;extend(this,settings);this.assertions=[];this.semaphore=0;this.usedAsync=false;this.module=config.currentModule;this.stack=sourceFromStacktrace(3);// Register unique strings
for(i=0,l=this.module.tests;i<l.length;i++){if(this.module.tests[i].name===this.testName){this.testName+=" ";}}this.testId=generateHash(this.module.name,this.testName);this.module.tests.push({name:this.testName,testId:this.testId});if(settings.skip){// Skipped tests will fully ignore any sent callback
this.callback=function(){};this.async=false;this.expected=0;}else{this.assert=new Assert(this);}}Test.count=0;Test.prototype={before:function before(){if(// Emit moduleStart when we're switching from one module to another
this.module!==config.previousModule||// They could be equal (both undefined) but if the previousModule property doesn't
// yet exist it means this is the first test in a suite that isn't wrapped in a
// module, in which case we'll just emit a moduleStart event for 'undefined'.
// Without this, reporters can get testStart before moduleStart  which is a problem.
!hasOwn.call(config,"previousModule")){if(hasOwn.call(config,"previousModule")){runLoggingCallbacks("moduleDone",{name:config.previousModule.name,tests:config.previousModule.tests,failed:config.moduleStats.bad,passed:config.moduleStats.all-config.moduleStats.bad,total:config.moduleStats.all,runtime:now()-config.moduleStats.started});}config.previousModule=this.module;config.moduleStats={all:0,bad:0,started:now()};runLoggingCallbacks("moduleStart",{name:this.module.name,tests:this.module.tests});}config.current=this;if(this.module.testEnvironment){delete this.module.testEnvironment.beforeEach;delete this.module.testEnvironment.afterEach;}this.testEnvironment=extend({},this.module.testEnvironment);this.started=now();runLoggingCallbacks("testStart",{name:this.testName,module:this.module.name,testId:this.testId});if(!config.pollution){saveGlobal();}},run:function run(){var promise;config.current=this;if(this.async){QUnit.stop();}this.callbackStarted=now();if(config.notrycatch){runTest(this);return;}try{runTest(this);}catch(e){this.pushFailure("Died on test #"+(this.assertions.length+1)+" "+this.stack+": "+(e.message||e),extractStacktrace(e,0));// else next test will carry the responsibility
saveGlobal();// Restart the tests if they're blocking
if(config.blocking){QUnit.start();}}function runTest(test){promise=test.callback.call(test.testEnvironment,test.assert);test.resolvePromise(promise);}},after:function after(){checkPollution();},queueHook:function queueHook(hook,hookName){var promise,test=this;return function runHook(){config.current=test;if(config.notrycatch){callHook();return;}try{callHook();}catch(error){test.pushFailure(hookName+" failed on "+test.testName+": "+(error.message||error),extractStacktrace(error,0));}function callHook(){promise=hook.call(test.testEnvironment,test.assert);test.resolvePromise(promise,hookName);}};},// Currently only used for module level hooks, can be used to add global level ones
hooks:function hooks(handler){var hooks=[];function processHooks(test,module){if(module.parentModule){processHooks(test,module.parentModule);}if(module.testEnvironment&&QUnit.objectType(module.testEnvironment[handler])==="function"){hooks.push(test.queueHook(module.testEnvironment[handler],handler));}}// Hooks are ignored on skipped tests
if(!this.skip){processHooks(this,this.module);}return hooks;},finish:function finish(){config.current=this;if(config.requireExpects&&this.expected===null){this.pushFailure("Expected number of assertions to be defined, but expect() was "+"not called.",this.stack);}else if(this.expected!==null&&this.expected!==this.assertions.length){this.pushFailure("Expected "+this.expected+" assertions, but "+this.assertions.length+" were run",this.stack);}else if(this.expected===null&&!this.assertions.length){this.pushFailure("Expected at least one assertion, but none were run - call "+"expect(0) to accept zero assertions.",this.stack);}var i,bad=0;this.runtime=now()-this.started;config.stats.all+=this.assertions.length;config.moduleStats.all+=this.assertions.length;for(i=0;i<this.assertions.length;i++){if(!this.assertions[i].result){bad++;config.stats.bad++;config.moduleStats.bad++;}}runLoggingCallbacks("testDone",{name:this.testName,module:this.module.name,skipped:!!this.skip,failed:bad,passed:this.assertions.length-bad,total:this.assertions.length,runtime:this.runtime,// HTML Reporter use
assertions:this.assertions,testId:this.testId,// Source of Test
source:this.stack,// DEPRECATED: this property will be removed in 2.0.0, use runtime instead
duration:this.runtime});// QUnit.reset() is deprecated and will be replaced for a new
// fixture reset function on QUnit 2.0/2.1.
// It's still called here for backwards compatibility handling
QUnit.reset();config.current=undefined;},queue:function queue(){var priority,test=this;if(!this.valid()){return;}function run(){// each of these can by async
synchronize([function(){test.before();},test.hooks("beforeEach"),function(){test.run();},test.hooks("afterEach").reverse(),function(){test.after();},function(){test.finish();}]);}// Prioritize previously failed tests, detected from sessionStorage
priority=QUnit.config.reorder&&defined.sessionStorage&&+sessionStorage.getItem("qunit-test-"+this.module.name+"-"+this.testName);return synchronize(run,priority);},push:function push(result,actual,expected,message,negative){var source,details={module:this.module.name,name:this.testName,result:result,message:message,actual:actual,expected:expected,testId:this.testId,negative:negative||false,runtime:now()-this.started};if(!result){source=sourceFromStacktrace();if(source){details.source=source;}}runLoggingCallbacks("log",details);this.assertions.push({result:!!result,message:message});},pushFailure:function pushFailure(message,source,actual){if(!(this instanceof Test)){throw new Error("pushFailure() assertion outside test context, was "+sourceFromStacktrace(2));}var details={module:this.module.name,name:this.testName,result:false,message:message||"error",actual:actual||null,testId:this.testId,runtime:now()-this.started};if(source){details.source=source;}runLoggingCallbacks("log",details);this.assertions.push({result:false,message:message});},resolvePromise:function resolvePromise(promise,phase){var then,message,test=this;if(promise!=null){then=promise.then;if(QUnit.objectType(then)==="function"){QUnit.stop();then.call(promise,function(){QUnit.start();},function(error){message="Promise rejected "+(!phase?"during":phase.replace(/Each$/,""))+" "+test.testName+": "+(error.message||error);test.pushFailure(message,extractStacktrace(error,0));// else next test will carry the responsibility
saveGlobal();// Unblock
QUnit.start();});}}},valid:function valid(){var include,filter=config.filter&&config.filter.toLowerCase(),module=QUnit.urlParams.module&&QUnit.urlParams.module.toLowerCase(),fullName=(this.module.name+": "+this.testName).toLowerCase();function testInModuleChain(testModule){var testModuleName=testModule.name?testModule.name.toLowerCase():null;if(testModuleName===module){return true;}else if(testModule.parentModule){return testInModuleChain(testModule.parentModule);}else{return false;}}// Internally-generated tests are always valid
if(this.callback&&this.callback.validTest){return true;}if(config.testId.length>0&&inArray(this.testId,config.testId)<0){return false;}if(module&&!testInModuleChain(this.module)){return false;}if(!filter){return true;}include=filter.charAt(0)!=="!";if(!include){filter=filter.slice(1);}// If the filter matches, we need to honour include
if(fullName.indexOf(filter)!==-1){return include;}// Otherwise, do the opposite
return!include;}};// Resets the test setup. Useful for tests that modify the DOM.
/*
DEPRECATED: Use multiple tests instead of resetting inside a test.
Use testStart or testDone for custom cleanup.
This method will throw an error in 2.0, and will be removed in 2.1
*/QUnit.reset=function(){// Return on non-browser environments
// This is necessary to not break on node tests
if(!defined.document){return;}var fixture=defined.document&&document.getElementById&&document.getElementById("qunit-fixture");if(fixture){fixture.innerHTML=config.fixture;}};QUnit.pushFailure=function(){if(!QUnit.config.current){throw new Error("pushFailure() assertion outside test context, in "+sourceFromStacktrace(2));}// Gets current test obj
var currentTest=QUnit.config.current;return currentTest.pushFailure.apply(currentTest,arguments);};// Based on Java's String.hashCode, a simple but not
// rigorously collision resistant hashing function
function generateHash(module,testName){var hex,i=0,hash=0,str=module+"\x1C"+testName,len=str.length;for(;i<len;i++){hash=(hash<<5)-hash+str.charCodeAt(i);hash|=0;}// Convert the possibly negative integer hash code into an 8 character hex string, which isn't
// strictly necessary but increases user understanding that the id is a SHA-like hash
hex=(0x100000000+hash).toString(16);if(hex.length<8){hex="0000000"+hex;}return hex.slice(-8);}function synchronize(callback,priority){var last=!priority;if(QUnit.objectType(callback)==="array"){while(callback.length){synchronize(callback.shift());}return;}if(priority){priorityFill(callback);}else{config.queue.push(callback);}if(config.autorun&&!config.blocking){process(last);}}// Place previously failed tests on a queue priority line, respecting the order they get assigned.
function priorityFill(callback){var queue,prioritizedQueue;queue=config.queue.slice(priorityFill.pos);prioritizedQueue=config.queue.slice(0,-config.queue.length+priorityFill.pos);queue.unshift(callback);queue.unshift.apply(queue,prioritizedQueue);config.queue=queue;priorityFill.pos+=1;}priorityFill.pos=0;function saveGlobal(){config.pollution=[];if(config.noglobals){for(var key in global){if(hasOwn.call(global,key)){// in Opera sometimes DOM element ids show up here, ignore them
if(/^qunit-test-output/.test(key)){continue;}config.pollution.push(key);}}}}function checkPollution(){var newGlobals,deletedGlobals,old=config.pollution;saveGlobal();newGlobals=diff(config.pollution,old);if(newGlobals.length>0){QUnit.pushFailure("Introduced global variable(s): "+newGlobals.join(", "));}deletedGlobals=diff(old,config.pollution);if(deletedGlobals.length>0){QUnit.pushFailure("Deleted global variable(s): "+deletedGlobals.join(", "));}}// Will be exposed as QUnit.asyncTest
function asyncTest(testName,expected,callback){if(arguments.length===2){callback=expected;expected=null;}QUnit.test(testName,expected,callback,true);}// Will be exposed as QUnit.test
function test(testName,expected,callback,async){if(focused){return;}var newTest;if(arguments.length===2){callback=expected;expected=null;}newTest=new Test({testName:testName,expected:expected,async:async,callback:callback});newTest.queue();}// Will be exposed as QUnit.skip
function skip(testName){if(focused){return;}var test=new Test({testName:testName,skip:true});test.queue();}// Will be exposed as QUnit.only
function only(testName,expected,callback,async){var newTest;if(focused){return;}QUnit.config.queue.length=0;focused=true;if(arguments.length===2){callback=expected;expected=null;}newTest=new Test({testName:testName,expected:expected,async:async,callback:callback});newTest.queue();}function Assert(testContext){this.test=testContext;}// Assert helpers
QUnit.assert=Assert.prototype={// Specify the number of expected assertions to guarantee that failed test
// (no assertions are run at all) don't slip through.
expect:function expect(asserts){if(arguments.length===1){this.test.expected=asserts;}else{return this.test.expected;}},// Increment this Test's semaphore counter, then return a function that
// decrements that counter a maximum of once.
async:function async(count){var test=this.test,popped=false,acceptCallCount=count;if(typeof acceptCallCount==="undefined"){acceptCallCount=1;}test.semaphore+=1;test.usedAsync=true;pauseProcessing();return function done(){if(popped){test.pushFailure("Too many calls to the `assert.async` callback",sourceFromStacktrace(2));return;}acceptCallCount-=1;if(acceptCallCount>0){return;}test.semaphore-=1;popped=true;resumeProcessing();};},// Exports test.push() to the user API
push:function push()/* result, actual, expected, message, negative */{var assert=this,currentTest=assert instanceof Assert&&assert.test||QUnit.config.current;// Backwards compatibility fix.
// Allows the direct use of global exported assertions and QUnit.assert.*
// Although, it's use is not recommended as it can leak assertions
// to other tests from async tests, because we only get a reference to the current test,
// not exactly the test where assertion were intended to be called.
if(!currentTest){throw new Error("assertion outside test context, in "+sourceFromStacktrace(2));}if(currentTest.usedAsync===true&&currentTest.semaphore===0){currentTest.pushFailure("Assertion after the final `assert.async` was resolved",sourceFromStacktrace(2));// Allow this assertion to continue running anyway...
}if(!(assert instanceof Assert)){assert=currentTest.assert;}return assert.test.push.apply(assert.test,arguments);},ok:function ok(result,message){message=message||(result?"okay":"failed, expected argument to be truthy, was: "+QUnit.dump.parse(result));this.push(!!result,result,true,message);},notOk:function notOk(result,message){message=message||(!result?"okay":"failed, expected argument to be falsy, was: "+QUnit.dump.parse(result));this.push(!result,result,false,message,true);},equal:function equal(actual,expected,message){/*jshint eqeqeq:false */this.push(expected==actual,actual,expected,message);},notEqual:function notEqual(actual,expected,message){/*jshint eqeqeq:false */this.push(expected!=actual,actual,expected,message,true);},propEqual:function propEqual(actual,expected,message){actual=objectValues(actual);expected=objectValues(expected);this.push(QUnit.equiv(actual,expected),actual,expected,message);},notPropEqual:function notPropEqual(actual,expected,message){actual=objectValues(actual);expected=objectValues(expected);this.push(!QUnit.equiv(actual,expected),actual,expected,message,true);},deepEqual:function deepEqual(actual,expected,message){this.push(QUnit.equiv(actual,expected),actual,expected,message);},notDeepEqual:function notDeepEqual(actual,expected,message){this.push(!QUnit.equiv(actual,expected),actual,expected,message,true);},strictEqual:function strictEqual(actual,expected,message){this.push(expected===actual,actual,expected,message);},notStrictEqual:function notStrictEqual(actual,expected,message){this.push(expected!==actual,actual,expected,message,true);},"throws":function throws(block,expected,message){var actual,expectedType,expectedOutput=expected,ok=false,currentTest=this instanceof Assert&&this.test||QUnit.config.current;// 'expected' is optional unless doing string comparison
if(message==null&&typeof expected==="string"){message=expected;expected=null;}currentTest.ignoreGlobalErrors=true;try{block.call(currentTest.testEnvironment);}catch(e){actual=e;}currentTest.ignoreGlobalErrors=false;if(actual){expectedType=QUnit.objectType(expected);// we don't want to validate thrown error
if(!expected){ok=true;expectedOutput=null;// expected is a regexp
}else if(expectedType==="regexp"){ok=expected.test(errorString(actual));// expected is a string
}else if(expectedType==="string"){ok=expected===errorString(actual);// expected is a constructor, maybe an Error constructor
}else if(expectedType==="function"&&actual instanceof expected){ok=true;// expected is an Error object
}else if(expectedType==="object"){ok=actual instanceof expected.constructor&&actual.name===expected.name&&actual.message===expected.message;// expected is a validation function which returns true if validation passed
}else if(expectedType==="function"&&expected.call({},actual)===true){expectedOutput=null;ok=true;}}currentTest.assert.push(ok,actual,expectedOutput,message);}};// Provide an alternative to assert.throws(), for environments that consider throws a reserved word
// Known to us are: Closure Compiler, Narwhal
(function(){/*jshint sub:true */Assert.prototype.raises=Assert.prototype["throws"];})();function errorString(error){var name,message,resultErrorString=error.toString();if(resultErrorString.substring(0,7)==="[object"){name=error.name?error.name.toString():"Error";message=error.message?error.message.toString():"";if(name&&message){return name+": "+message;}else if(name){return name;}else if(message){return message;}else{return"Error";}}else{return resultErrorString;}}// Test for equality any JavaScript type.
// Author: Philippe Rathé <prathe@gmail.com>
QUnit.equiv=function(){// Stack to decide between skip/abort functions
var callers=[];// Stack to avoiding loops from circular referencing
var parents=[];var parentsB=[];function useStrictEquality(b,a){/*jshint eqeqeq:false */if(b instanceof a.constructor||a instanceof b.constructor){// To catch short annotation VS 'new' annotation of a declaration. e.g.:
// `var i = 1;`
// `var j = new Number(1);`
return a==b;}else{return a===b;}}function compareConstructors(a,b){var getProto=Object.getPrototypeOf||function(obj){/*jshint proto: true */return obj.__proto__;};var protoA=getProto(a);var protoB=getProto(b);// Comparing constructors is more strict than using `instanceof`
if(a.constructor===b.constructor){return true;}// Ref #851
// If the obj prototype descends from a null constructor, treat it
// as a null prototype.
if(protoA&&protoA.constructor===null){protoA=null;}if(protoB&&protoB.constructor===null){protoB=null;}// Allow objects with no prototype to be equivalent to
// objects with Object as their constructor.
if(protoA===null&&protoB===Object.prototype||protoB===null&&protoA===Object.prototype){return true;}return false;}var callbacks={"string":useStrictEquality,"boolean":useStrictEquality,"number":useStrictEquality,"null":useStrictEquality,"undefined":useStrictEquality,"symbol":useStrictEquality,"nan":function nan(b){return isNaN(b);},"date":function date(b,a){return QUnit.objectType(b)==="date"&&a.valueOf()===b.valueOf();},"regexp":function regexp(b,a){return QUnit.objectType(b)==="regexp"&&// The regex itself
a.source===b.source&&// And its modifiers
a.global===b.global&&// (gmi) ...
a.ignoreCase===b.ignoreCase&&a.multiline===b.multiline&&a.sticky===b.sticky;},// - skip when the property is a method of an instance (OOP)
// - abort otherwise,
// initial === would have catch identical references anyway
"function":function _function(){var caller=callers[callers.length-1];return caller!==Object&&typeof caller!=="undefined";},"array":function array(b,a){var i,j,len,loop,aCircular,bCircular;// b could be an object literal here
if(QUnit.objectType(b)!=="array"){return false;}len=a.length;if(len!==b.length){// safe and faster
return false;}// Track reference to avoid circular references
parents.push(a);parentsB.push(b);for(i=0;i<len;i++){loop=false;for(j=0;j<parents.length;j++){aCircular=parents[j]===a[i];bCircular=parentsB[j]===b[i];if(aCircular||bCircular){if(a[i]===b[i]||aCircular&&bCircular){loop=true;}else{parents.pop();parentsB.pop();return false;}}}if(!loop&&!innerEquiv(a[i],b[i])){parents.pop();parentsB.pop();return false;}}parents.pop();parentsB.pop();return true;},"set":function set(b,a){var aArray,bArray;// `b` could be any object here
if(QUnit.objectType(b)!=="set"){return false;}aArray=[];a.forEach(function(v){aArray.push(v);});bArray=[];b.forEach(function(v){bArray.push(v);});return innerEquiv(bArray,aArray);},"map":function map(b,a){var aArray,bArray;// `b` could be any object here
if(QUnit.objectType(b)!=="map"){return false;}aArray=[];a.forEach(function(v,k){aArray.push([k,v]);});bArray=[];b.forEach(function(v,k){bArray.push([k,v]);});return innerEquiv(bArray,aArray);},"object":function object(b,a){var i,j,loop,aCircular,bCircular;// Default to true
var eq=true;var aProperties=[];var bProperties=[];if(compareConstructors(a,b)===false){return false;}// Stack constructor before traversing properties
callers.push(a.constructor);// Track reference to avoid circular references
parents.push(a);parentsB.push(b);// Be strict: don't ensure hasOwnProperty and go deep
for(i in a){loop=false;for(j=0;j<parents.length;j++){aCircular=parents[j]===a[i];bCircular=parentsB[j]===b[i];if(aCircular||bCircular){if(a[i]===b[i]||aCircular&&bCircular){loop=true;}else{eq=false;break;}}}aProperties.push(i);if(!loop&&!innerEquiv(a[i],b[i])){eq=false;break;}}parents.pop();parentsB.pop();// Unstack, we are done
callers.pop();for(i in b){// Collect b's properties
bProperties.push(i);}// Ensures identical properties name
return eq&&innerEquiv(aProperties.sort(),bProperties.sort());}};function typeEquiv(a,b){var prop=QUnit.objectType(a);return callbacks[prop](b,a);}// The real equiv function
function innerEquiv(){var args=[].slice.apply(arguments);if(args.length<2){// End transition
return true;}return function(a,b){if(a===b){// Catch the most you can
return true;}else if(a===null||b===null||typeof a==="undefined"||typeof b==="undefined"||QUnit.objectType(a)!==QUnit.objectType(b)){// Don't lose time with error prone cases
return false;}else{return typeEquiv(a,b);}// Apply transition with (1..n) arguments
}(args[0],args[1])&&innerEquiv.apply(this,args.splice(1,args.length-1));}return innerEquiv;}();// Based on jsDump by Ariel Flesler
// http://flesler.blogspot.com/2008/05/jsdump-pretty-dump-of-any-javascript.html
QUnit.dump=function(){function quote(str){return"\""+str.toString().replace(/\\/g,"\\\\").replace(/"/g,"\\\"")+"\"";}function literal(o){return o+"";}function join(pre,arr,post){var s=dump.separator(),base=dump.indent(),inner=dump.indent(1);if(arr.join){arr=arr.join(","+s+inner);}if(!arr){return pre+post;}return[pre,inner+arr,base+post].join(s);}function array(arr,stack){var i=arr.length,ret=new Array(i);if(dump.maxDepth&&dump.depth>dump.maxDepth){return"[object Array]";}this.up();while(i--){ret[i]=this.parse(arr[i],undefined,stack);}this.down();return join("[",ret,"]");}var reName=/^function (\w+)/,dump={// objType is used mostly internally, you can fix a (custom) type in advance
parse:function parse(obj,objType,stack){stack=stack||[];var res,parser,parserType,inStack=inArray(obj,stack);if(inStack!==-1){return"recursion("+(inStack-stack.length)+")";}objType=objType||this.typeOf(obj);parser=this.parsers[objType];parserType=typeof parser==="undefined"?"undefined":_typeof(parser);if(parserType==="function"){stack.push(obj);res=parser.call(this,obj,stack);stack.pop();return res;}return parserType==="string"?parser:this.parsers.fatal_error;},typeOf:function typeOf(obj){var type;if(obj===null){type="null";}else if(typeof obj==="undefined"){type="undefined";}else if(QUnit.is("regexp",obj)){type="regexp";}else if(QUnit.is("date",obj)){type="date";}else if(QUnit.is("function",obj)){type="function";}else if(obj.setInterval!==undefined&&obj.document!==undefined&&obj.nodeType===undefined){type="window";}else if(obj.nodeType===9){type="document";}else if(obj.nodeType){type="node";}else if(// native arrays
toString.call(obj)==="[object Array]"||// NodeList objects
typeof obj.length==="number"&&obj.item!==undefined&&(obj.length?obj.item(0)===obj[0]:obj.item(0)===null&&obj[0]===undefined)){type="array";}else if(obj.constructor===Error.prototype.constructor){type="error";}else{type=typeof obj==="undefined"?"undefined":_typeof(obj);}return type;},separator:function separator(){return this.multiline?this.HTML?"<br />":"\n":this.HTML?"&#160;":" ";},// extra can be a number, shortcut for increasing-calling-decreasing
indent:function indent(extra){if(!this.multiline){return"";}var chr=this.indentChar;if(this.HTML){chr=chr.replace(/\t/g,"   ").replace(/ /g,"&#160;");}return new Array(this.depth+(extra||0)).join(chr);},up:function up(a){this.depth+=a||1;},down:function down(a){this.depth-=a||1;},setParser:function setParser(name,parser){this.parsers[name]=parser;},// The next 3 are exposed so you can use them
quote:quote,literal:literal,join:join,//
depth:1,maxDepth:QUnit.config.maxDepth,// This is the list of parsers, to modify them, use dump.setParser
parsers:{window:"[Window]",document:"[Document]",fatal_error:function fatal_error(error){return"Error(\""+error.message+"\")";},unknown:"[Unknown]","null":"null","undefined":"undefined","function":function _function(fn){var ret="function",// functions never have name in IE
name="name"in fn?fn.name:(reName.exec(fn)||[])[1];if(name){ret+=" "+name;}ret+="( ";ret=[ret,dump.parse(fn,"functionArgs"),"){"].join("");return join(ret,dump.parse(fn,"functionCode"),"}");},array:array,nodelist:array,"arguments":array,object:function object(map,stack){var keys,key,val,i,nonEnumerableProperties,ret=[];if(dump.maxDepth&&dump.depth>dump.maxDepth){return"[object Object]";}dump.up();keys=[];for(key in map){keys.push(key);}// Some properties are not always enumerable on Error objects.
nonEnumerableProperties=["message","name"];for(i in nonEnumerableProperties){key=nonEnumerableProperties[i];if(key in map&&inArray(key,keys)<0){keys.push(key);}}keys.sort();for(i=0;i<keys.length;i++){key=keys[i];val=map[key];ret.push(dump.parse(key,"key")+": "+dump.parse(val,undefined,stack));}dump.down();return join("{",ret,"}");},node:function node(_node){var len,i,val,open=dump.HTML?"&lt;":"<",close=dump.HTML?"&gt;":">",tag=_node.nodeName.toLowerCase(),ret=open+tag,attrs=_node.attributes;if(attrs){for(i=0,len=attrs.length;i<len;i++){val=attrs[i].nodeValue;// IE6 includes all attributes in .attributes, even ones not explicitly
// set. Those have values like undefined, null, 0, false, "" or
// "inherit".
if(val&&val!=="inherit"){ret+=" "+attrs[i].nodeName+"="+dump.parse(val,"attribute");}}}ret+=close;// Show content of TextNode or CDATASection
if(_node.nodeType===3||_node.nodeType===4){ret+=_node.nodeValue;}return ret+open+"/"+tag+close;},// function calls it internally, it's the arguments part of the function
functionArgs:function functionArgs(fn){var args,l=fn.length;if(!l){return"";}args=new Array(l);while(l--){// 97 is 'a'
args[l]=String.fromCharCode(97+l);}return" "+args.join(", ")+" ";},// object calls it internally, the key part of an item in a map
key:quote,// function calls it internally, it's the content of the function
functionCode:"[code]",// node calls it internally, it's an html attribute value
attribute:quote,string:quote,date:quote,regexp:literal,number:literal,"boolean":literal},// if true, entities are escaped ( <, >, \t, space and \n )
HTML:false,// indentation unit
indentChar:"  ",// if true, items in a collection, are separated by a \n, else just a space.
multiline:true};return dump;}();// back compat
QUnit.jsDump=QUnit.dump;// For browser, export only select globals
if(defined.document){// Deprecated
// Extend assert methods to QUnit and Global scope through Backwards compatibility
(function(){var i,assertions=Assert.prototype;function applyCurrent(current){return function(){var assert=new Assert(QUnit.config.current);current.apply(assert,arguments);};}for(i in assertions){QUnit[i]=applyCurrent(assertions[i]);}})();(function(){var i,l,keys=["test","module","expect","asyncTest","start","stop","ok","notOk","equal","notEqual","propEqual","notPropEqual","deepEqual","notDeepEqual","strictEqual","notStrictEqual","throws","raises"];for(i=0,l=keys.length;i<l;i++){window[keys[i]]=QUnit[keys[i]];}})();window.QUnit=QUnit;}// For nodejs
if(typeof module!=="undefined"&&module&&module.exports){module.exports=QUnit;// For consistency with CommonJS environments' exports
module.exports.QUnit=QUnit;}// For CommonJS with exports, but without module.exports, like Rhino
if(typeof exports!=="undefined"&&exports){exports.QUnit=QUnit;}if(typeof define==="function"&&define.amd){define(function(){return QUnit;});QUnit.config.autostart=false;}/*
 * This file is a modified version of google-diff-match-patch's JavaScript implementation
 * (https://code.google.com/p/google-diff-match-patch/source/browse/trunk/javascript/diff_match_patch_uncompressed.js),
 * modifications are licensed as more fully set forth in LICENSE.txt.
 *
 * The original source of google-diff-match-patch is attributable and licensed as follows:
 *
 * Copyright 2006 Google Inc.
 * http://code.google.com/p/google-diff-match-patch/
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * More Info:
 *  https://code.google.com/p/google-diff-match-patch/
 *
 * Usage: QUnit.diff(expected, actual)
 *
 */QUnit.diff=function(){function DiffMatchPatch(){}//  DIFF FUNCTIONS
/**
	 * The data structure representing a diff is an array of tuples:
	 * [[DIFF_DELETE, 'Hello'], [DIFF_INSERT, 'Goodbye'], [DIFF_EQUAL, ' world.']]
	 * which means: delete 'Hello', add 'Goodbye' and keep ' world.'
	 */var DIFF_DELETE=-1,DIFF_INSERT=1,DIFF_EQUAL=0;/**
	 * Find the differences between two texts.  Simplifies the problem by stripping
	 * any common prefix or suffix off the texts before diffing.
	 * @param {string} text1 Old string to be diffed.
	 * @param {string} text2 New string to be diffed.
	 * @param {boolean=} optChecklines Optional speedup flag. If present and false,
	 *     then don't run a line-level diff first to identify the changed areas.
	 *     Defaults to true, which does a faster, slightly less optimal diff.
	 * @return {!Array.<!DiffMatchPatch.Diff>} Array of diff tuples.
	 */DiffMatchPatch.prototype.DiffMain=function(text1,text2,optChecklines){var deadline,checklines,commonlength,commonprefix,commonsuffix,diffs;// The diff must be complete in up to 1 second.
deadline=new Date().getTime()+1000;// Check for null inputs.
if(text1===null||text2===null){throw new Error("Null input. (DiffMain)");}// Check for equality (speedup).
if(text1===text2){if(text1){return[[DIFF_EQUAL,text1]];}return[];}if(typeof optChecklines==="undefined"){optChecklines=true;}checklines=optChecklines;// Trim off common prefix (speedup).
commonlength=this.diffCommonPrefix(text1,text2);commonprefix=text1.substring(0,commonlength);text1=text1.substring(commonlength);text2=text2.substring(commonlength);// Trim off common suffix (speedup).
commonlength=this.diffCommonSuffix(text1,text2);commonsuffix=text1.substring(text1.length-commonlength);text1=text1.substring(0,text1.length-commonlength);text2=text2.substring(0,text2.length-commonlength);// Compute the diff on the middle block.
diffs=this.diffCompute(text1,text2,checklines,deadline);// Restore the prefix and suffix.
if(commonprefix){diffs.unshift([DIFF_EQUAL,commonprefix]);}if(commonsuffix){diffs.push([DIFF_EQUAL,commonsuffix]);}this.diffCleanupMerge(diffs);return diffs;};/**
	 * Reduce the number of edits by eliminating operationally trivial equalities.
	 * @param {!Array.<!DiffMatchPatch.Diff>} diffs Array of diff tuples.
	 */DiffMatchPatch.prototype.diffCleanupEfficiency=function(diffs){var changes,equalities,equalitiesLength,lastequality,pointer,preIns,preDel,postIns,postDel;changes=false;equalities=[];// Stack of indices where equalities are found.
equalitiesLength=0;// Keeping our own length var is faster in JS.
/** @type {?string} */lastequality=null;// Always equal to diffs[equalities[equalitiesLength - 1]][1]
pointer=0;// Index of current position.
// Is there an insertion operation before the last equality.
preIns=false;// Is there a deletion operation before the last equality.
preDel=false;// Is there an insertion operation after the last equality.
postIns=false;// Is there a deletion operation after the last equality.
postDel=false;while(pointer<diffs.length){// Equality found.
if(diffs[pointer][0]===DIFF_EQUAL){if(diffs[pointer][1].length<4&&(postIns||postDel)){// Candidate found.
equalities[equalitiesLength++]=pointer;preIns=postIns;preDel=postDel;lastequality=diffs[pointer][1];}else{// Not a candidate, and can never become one.
equalitiesLength=0;lastequality=null;}postIns=postDel=false;// An insertion or deletion.
}else{if(diffs[pointer][0]===DIFF_DELETE){postDel=true;}else{postIns=true;}/*
				 * Five types to be split:
				 * <ins>A</ins><del>B</del>XY<ins>C</ins><del>D</del>
				 * <ins>A</ins>X<ins>C</ins><del>D</del>
				 * <ins>A</ins><del>B</del>X<ins>C</ins>
				 * <ins>A</del>X<ins>C</ins><del>D</del>
				 * <ins>A</ins><del>B</del>X<del>C</del>
				 */if(lastequality&&(preIns&&preDel&&postIns&&postDel||lastequality.length<2&&preIns+preDel+postIns+postDel===3)){// Duplicate record.
diffs.splice(equalities[equalitiesLength-1],0,[DIFF_DELETE,lastequality]);// Change second copy to insert.
diffs[equalities[equalitiesLength-1]+1][0]=DIFF_INSERT;equalitiesLength--;// Throw away the equality we just deleted;
lastequality=null;if(preIns&&preDel){// No changes made which could affect previous entry, keep going.
postIns=postDel=true;equalitiesLength=0;}else{equalitiesLength--;// Throw away the previous equality.
pointer=equalitiesLength>0?equalities[equalitiesLength-1]:-1;postIns=postDel=false;}changes=true;}}pointer++;}if(changes){this.diffCleanupMerge(diffs);}};/**
	 * Convert a diff array into a pretty HTML report.
	 * @param {!Array.<!DiffMatchPatch.Diff>} diffs Array of diff tuples.
	 * @param {integer} string to be beautified.
	 * @return {string} HTML representation.
	 */DiffMatchPatch.prototype.diffPrettyHtml=function(diffs){var op,data,x,html=[];for(x=0;x<diffs.length;x++){op=diffs[x][0];// Operation (insert, delete, equal)
data=diffs[x][1];// Text of change.
switch(op){case DIFF_INSERT:html[x]="<ins>"+data+"</ins>";break;case DIFF_DELETE:html[x]="<del>"+data+"</del>";break;case DIFF_EQUAL:html[x]="<span>"+data+"</span>";break;}}return html.join("");};/**
	 * Determine the common prefix of two strings.
	 * @param {string} text1 First string.
	 * @param {string} text2 Second string.
	 * @return {number} The number of characters common to the start of each
	 *     string.
	 */DiffMatchPatch.prototype.diffCommonPrefix=function(text1,text2){var pointermid,pointermax,pointermin,pointerstart;// Quick check for common null cases.
if(!text1||!text2||text1.charAt(0)!==text2.charAt(0)){return 0;}// Binary search.
// Performance analysis: http://neil.fraser.name/news/2007/10/09/
pointermin=0;pointermax=Math.min(text1.length,text2.length);pointermid=pointermax;pointerstart=0;while(pointermin<pointermid){if(text1.substring(pointerstart,pointermid)===text2.substring(pointerstart,pointermid)){pointermin=pointermid;pointerstart=pointermin;}else{pointermax=pointermid;}pointermid=Math.floor((pointermax-pointermin)/2+pointermin);}return pointermid;};/**
	 * Determine the common suffix of two strings.
	 * @param {string} text1 First string.
	 * @param {string} text2 Second string.
	 * @return {number} The number of characters common to the end of each string.
	 */DiffMatchPatch.prototype.diffCommonSuffix=function(text1,text2){var pointermid,pointermax,pointermin,pointerend;// Quick check for common null cases.
if(!text1||!text2||text1.charAt(text1.length-1)!==text2.charAt(text2.length-1)){return 0;}// Binary search.
// Performance analysis: http://neil.fraser.name/news/2007/10/09/
pointermin=0;pointermax=Math.min(text1.length,text2.length);pointermid=pointermax;pointerend=0;while(pointermin<pointermid){if(text1.substring(text1.length-pointermid,text1.length-pointerend)===text2.substring(text2.length-pointermid,text2.length-pointerend)){pointermin=pointermid;pointerend=pointermin;}else{pointermax=pointermid;}pointermid=Math.floor((pointermax-pointermin)/2+pointermin);}return pointermid;};/**
	 * Find the differences between two texts.  Assumes that the texts do not
	 * have any common prefix or suffix.
	 * @param {string} text1 Old string to be diffed.
	 * @param {string} text2 New string to be diffed.
	 * @param {boolean} checklines Speedup flag.  If false, then don't run a
	 *     line-level diff first to identify the changed areas.
	 *     If true, then run a faster, slightly less optimal diff.
	 * @param {number} deadline Time when the diff should be complete by.
	 * @return {!Array.<!DiffMatchPatch.Diff>} Array of diff tuples.
	 * @private
	 */DiffMatchPatch.prototype.diffCompute=function(text1,text2,checklines,deadline){var diffs,longtext,shorttext,i,hm,text1A,text2A,text1B,text2B,midCommon,diffsA,diffsB;if(!text1){// Just add some text (speedup).
return[[DIFF_INSERT,text2]];}if(!text2){// Just delete some text (speedup).
return[[DIFF_DELETE,text1]];}longtext=text1.length>text2.length?text1:text2;shorttext=text1.length>text2.length?text2:text1;i=longtext.indexOf(shorttext);if(i!==-1){// Shorter text is inside the longer text (speedup).
diffs=[[DIFF_INSERT,longtext.substring(0,i)],[DIFF_EQUAL,shorttext],[DIFF_INSERT,longtext.substring(i+shorttext.length)]];// Swap insertions for deletions if diff is reversed.
if(text1.length>text2.length){diffs[0][0]=diffs[2][0]=DIFF_DELETE;}return diffs;}if(shorttext.length===1){// Single character string.
// After the previous speedup, the character can't be an equality.
return[[DIFF_DELETE,text1],[DIFF_INSERT,text2]];}// Check to see if the problem can be split in two.
hm=this.diffHalfMatch(text1,text2);if(hm){// A half-match was found, sort out the return data.
text1A=hm[0];text1B=hm[1];text2A=hm[2];text2B=hm[3];midCommon=hm[4];// Send both pairs off for separate processing.
diffsA=this.DiffMain(text1A,text2A,checklines,deadline);diffsB=this.DiffMain(text1B,text2B,checklines,deadline);// Merge the results.
return diffsA.concat([[DIFF_EQUAL,midCommon]],diffsB);}if(checklines&&text1.length>100&&text2.length>100){return this.diffLineMode(text1,text2,deadline);}return this.diffBisect(text1,text2,deadline);};/**
	 * Do the two texts share a substring which is at least half the length of the
	 * longer text?
	 * This speedup can produce non-minimal diffs.
	 * @param {string} text1 First string.
	 * @param {string} text2 Second string.
	 * @return {Array.<string>} Five element Array, containing the prefix of
	 *     text1, the suffix of text1, the prefix of text2, the suffix of
	 *     text2 and the common middle.  Or null if there was no match.
	 * @private
	 */DiffMatchPatch.prototype.diffHalfMatch=function(text1,text2){var longtext,shorttext,dmp,text1A,text2B,text2A,text1B,midCommon,hm1,hm2,hm;longtext=text1.length>text2.length?text1:text2;shorttext=text1.length>text2.length?text2:text1;if(longtext.length<4||shorttext.length*2<longtext.length){return null;// Pointless.
}dmp=this;// 'this' becomes 'window' in a closure.
/**
		 * Does a substring of shorttext exist within longtext such that the substring
		 * is at least half the length of longtext?
		 * Closure, but does not reference any external variables.
		 * @param {string} longtext Longer string.
		 * @param {string} shorttext Shorter string.
		 * @param {number} i Start index of quarter length substring within longtext.
		 * @return {Array.<string>} Five element Array, containing the prefix of
		 *     longtext, the suffix of longtext, the prefix of shorttext, the suffix
		 *     of shorttext and the common middle.  Or null if there was no match.
		 * @private
		 */function diffHalfMatchI(longtext,shorttext,i){var seed,j,bestCommon,prefixLength,suffixLength,bestLongtextA,bestLongtextB,bestShorttextA,bestShorttextB;// Start with a 1/4 length substring at position i as a seed.
seed=longtext.substring(i,i+Math.floor(longtext.length/4));j=-1;bestCommon="";while((j=shorttext.indexOf(seed,j+1))!==-1){prefixLength=dmp.diffCommonPrefix(longtext.substring(i),shorttext.substring(j));suffixLength=dmp.diffCommonSuffix(longtext.substring(0,i),shorttext.substring(0,j));if(bestCommon.length<suffixLength+prefixLength){bestCommon=shorttext.substring(j-suffixLength,j)+shorttext.substring(j,j+prefixLength);bestLongtextA=longtext.substring(0,i-suffixLength);bestLongtextB=longtext.substring(i+prefixLength);bestShorttextA=shorttext.substring(0,j-suffixLength);bestShorttextB=shorttext.substring(j+prefixLength);}}if(bestCommon.length*2>=longtext.length){return[bestLongtextA,bestLongtextB,bestShorttextA,bestShorttextB,bestCommon];}else{return null;}}// First check if the second quarter is the seed for a half-match.
hm1=diffHalfMatchI(longtext,shorttext,Math.ceil(longtext.length/4));// Check again based on the third quarter.
hm2=diffHalfMatchI(longtext,shorttext,Math.ceil(longtext.length/2));if(!hm1&&!hm2){return null;}else if(!hm2){hm=hm1;}else if(!hm1){hm=hm2;}else{// Both matched.  Select the longest.
hm=hm1[4].length>hm2[4].length?hm1:hm2;}// A half-match was found, sort out the return data.
text1A,text1B,text2A,text2B;if(text1.length>text2.length){text1A=hm[0];text1B=hm[1];text2A=hm[2];text2B=hm[3];}else{text2A=hm[0];text2B=hm[1];text1A=hm[2];text1B=hm[3];}midCommon=hm[4];return[text1A,text1B,text2A,text2B,midCommon];};/**
	 * Do a quick line-level diff on both strings, then rediff the parts for
	 * greater accuracy.
	 * This speedup can produce non-minimal diffs.
	 * @param {string} text1 Old string to be diffed.
	 * @param {string} text2 New string to be diffed.
	 * @param {number} deadline Time when the diff should be complete by.
	 * @return {!Array.<!DiffMatchPatch.Diff>} Array of diff tuples.
	 * @private
	 */DiffMatchPatch.prototype.diffLineMode=function(text1,text2,deadline){var a,diffs,linearray,pointer,countInsert,countDelete,textInsert,textDelete,j;// Scan the text on a line-by-line basis first.
a=this.diffLinesToChars(text1,text2);text1=a.chars1;text2=a.chars2;linearray=a.lineArray;diffs=this.DiffMain(text1,text2,false,deadline);// Convert the diff back to original text.
this.diffCharsToLines(diffs,linearray);// Eliminate freak matches (e.g. blank lines)
this.diffCleanupSemantic(diffs);// Rediff any replacement blocks, this time character-by-character.
// Add a dummy entry at the end.
diffs.push([DIFF_EQUAL,""]);pointer=0;countDelete=0;countInsert=0;textDelete="";textInsert="";while(pointer<diffs.length){switch(diffs[pointer][0]){case DIFF_INSERT:countInsert++;textInsert+=diffs[pointer][1];break;case DIFF_DELETE:countDelete++;textDelete+=diffs[pointer][1];break;case DIFF_EQUAL:// Upon reaching an equality, check for prior redundancies.
if(countDelete>=1&&countInsert>=1){// Delete the offending records and add the merged ones.
diffs.splice(pointer-countDelete-countInsert,countDelete+countInsert);pointer=pointer-countDelete-countInsert;a=this.DiffMain(textDelete,textInsert,false,deadline);for(j=a.length-1;j>=0;j--){diffs.splice(pointer,0,a[j]);}pointer=pointer+a.length;}countInsert=0;countDelete=0;textDelete="";textInsert="";break;}pointer++;}diffs.pop();// Remove the dummy entry at the end.
return diffs;};/**
	 * Find the 'middle snake' of a diff, split the problem in two
	 * and return the recursively constructed diff.
	 * See Myers 1986 paper: An O(ND) Difference Algorithm and Its Variations.
	 * @param {string} text1 Old string to be diffed.
	 * @param {string} text2 New string to be diffed.
	 * @param {number} deadline Time at which to bail if not yet complete.
	 * @return {!Array.<!DiffMatchPatch.Diff>} Array of diff tuples.
	 * @private
	 */DiffMatchPatch.prototype.diffBisect=function(text1,text2,deadline){var text1Length,text2Length,maxD,vOffset,vLength,v1,v2,x,delta,front,k1start,k1end,k2start,k2end,k2Offset,k1Offset,x1,x2,y1,y2,d,k1,k2;// Cache the text lengths to prevent multiple calls.
text1Length=text1.length;text2Length=text2.length;maxD=Math.ceil((text1Length+text2Length)/2);vOffset=maxD;vLength=2*maxD;v1=new Array(vLength);v2=new Array(vLength);// Setting all elements to -1 is faster in Chrome & Firefox than mixing
// integers and undefined.
for(x=0;x<vLength;x++){v1[x]=-1;v2[x]=-1;}v1[vOffset+1]=0;v2[vOffset+1]=0;delta=text1Length-text2Length;// If the total number of characters is odd, then the front path will collide
// with the reverse path.
front=delta%2!==0;// Offsets for start and end of k loop.
// Prevents mapping of space beyond the grid.
k1start=0;k1end=0;k2start=0;k2end=0;for(d=0;d<maxD;d++){// Bail out if deadline is reached.
if(new Date().getTime()>deadline){break;}// Walk the front path one step.
for(k1=-d+k1start;k1<=d-k1end;k1+=2){k1Offset=vOffset+k1;if(k1===-d||k1!==d&&v1[k1Offset-1]<v1[k1Offset+1]){x1=v1[k1Offset+1];}else{x1=v1[k1Offset-1]+1;}y1=x1-k1;while(x1<text1Length&&y1<text2Length&&text1.charAt(x1)===text2.charAt(y1)){x1++;y1++;}v1[k1Offset]=x1;if(x1>text1Length){// Ran off the right of the graph.
k1end+=2;}else if(y1>text2Length){// Ran off the bottom of the graph.
k1start+=2;}else if(front){k2Offset=vOffset+delta-k1;if(k2Offset>=0&&k2Offset<vLength&&v2[k2Offset]!==-1){// Mirror x2 onto top-left coordinate system.
x2=text1Length-v2[k2Offset];if(x1>=x2){// Overlap detected.
return this.diffBisectSplit(text1,text2,x1,y1,deadline);}}}}// Walk the reverse path one step.
for(k2=-d+k2start;k2<=d-k2end;k2+=2){k2Offset=vOffset+k2;if(k2===-d||k2!==d&&v2[k2Offset-1]<v2[k2Offset+1]){x2=v2[k2Offset+1];}else{x2=v2[k2Offset-1]+1;}y2=x2-k2;while(x2<text1Length&&y2<text2Length&&text1.charAt(text1Length-x2-1)===text2.charAt(text2Length-y2-1)){x2++;y2++;}v2[k2Offset]=x2;if(x2>text1Length){// Ran off the left of the graph.
k2end+=2;}else if(y2>text2Length){// Ran off the top of the graph.
k2start+=2;}else if(!front){k1Offset=vOffset+delta-k2;if(k1Offset>=0&&k1Offset<vLength&&v1[k1Offset]!==-1){x1=v1[k1Offset];y1=vOffset+x1-k1Offset;// Mirror x2 onto top-left coordinate system.
x2=text1Length-x2;if(x1>=x2){// Overlap detected.
return this.diffBisectSplit(text1,text2,x1,y1,deadline);}}}}}// Diff took too long and hit the deadline or
// number of diffs equals number of characters, no commonality at all.
return[[DIFF_DELETE,text1],[DIFF_INSERT,text2]];};/**
	 * Given the location of the 'middle snake', split the diff in two parts
	 * and recurse.
	 * @param {string} text1 Old string to be diffed.
	 * @param {string} text2 New string to be diffed.
	 * @param {number} x Index of split point in text1.
	 * @param {number} y Index of split point in text2.
	 * @param {number} deadline Time at which to bail if not yet complete.
	 * @return {!Array.<!DiffMatchPatch.Diff>} Array of diff tuples.
	 * @private
	 */DiffMatchPatch.prototype.diffBisectSplit=function(text1,text2,x,y,deadline){var text1a,text1b,text2a,text2b,diffs,diffsb;text1a=text1.substring(0,x);text2a=text2.substring(0,y);text1b=text1.substring(x);text2b=text2.substring(y);// Compute both diffs serially.
diffs=this.DiffMain(text1a,text2a,false,deadline);diffsb=this.DiffMain(text1b,text2b,false,deadline);return diffs.concat(diffsb);};/**
	 * Reduce the number of edits by eliminating semantically trivial equalities.
	 * @param {!Array.<!DiffMatchPatch.Diff>} diffs Array of diff tuples.
	 */DiffMatchPatch.prototype.diffCleanupSemantic=function(diffs){var changes,equalities,equalitiesLength,lastequality,pointer,lengthInsertions2,lengthDeletions2,lengthInsertions1,lengthDeletions1,deletion,insertion,overlapLength1,overlapLength2;changes=false;equalities=[];// Stack of indices where equalities are found.
equalitiesLength=0;// Keeping our own length var is faster in JS.
/** @type {?string} */lastequality=null;// Always equal to diffs[equalities[equalitiesLength - 1]][1]
pointer=0;// Index of current position.
// Number of characters that changed prior to the equality.
lengthInsertions1=0;lengthDeletions1=0;// Number of characters that changed after the equality.
lengthInsertions2=0;lengthDeletions2=0;while(pointer<diffs.length){if(diffs[pointer][0]===DIFF_EQUAL){// Equality found.
equalities[equalitiesLength++]=pointer;lengthInsertions1=lengthInsertions2;lengthDeletions1=lengthDeletions2;lengthInsertions2=0;lengthDeletions2=0;lastequality=diffs[pointer][1];}else{// An insertion or deletion.
if(diffs[pointer][0]===DIFF_INSERT){lengthInsertions2+=diffs[pointer][1].length;}else{lengthDeletions2+=diffs[pointer][1].length;}// Eliminate an equality that is smaller or equal to the edits on both
// sides of it.
if(lastequality&&lastequality.length<=Math.max(lengthInsertions1,lengthDeletions1)&&lastequality.length<=Math.max(lengthInsertions2,lengthDeletions2)){// Duplicate record.
diffs.splice(equalities[equalitiesLength-1],0,[DIFF_DELETE,lastequality]);// Change second copy to insert.
diffs[equalities[equalitiesLength-1]+1][0]=DIFF_INSERT;// Throw away the equality we just deleted.
equalitiesLength--;// Throw away the previous equality (it needs to be reevaluated).
equalitiesLength--;pointer=equalitiesLength>0?equalities[equalitiesLength-1]:-1;// Reset the counters.
lengthInsertions1=0;lengthDeletions1=0;lengthInsertions2=0;lengthDeletions2=0;lastequality=null;changes=true;}}pointer++;}// Normalize the diff.
if(changes){this.diffCleanupMerge(diffs);}// Find any overlaps between deletions and insertions.
// e.g: <del>abcxxx</del><ins>xxxdef</ins>
//   -> <del>abc</del>xxx<ins>def</ins>
// e.g: <del>xxxabc</del><ins>defxxx</ins>
//   -> <ins>def</ins>xxx<del>abc</del>
// Only extract an overlap if it is as big as the edit ahead or behind it.
pointer=1;while(pointer<diffs.length){if(diffs[pointer-1][0]===DIFF_DELETE&&diffs[pointer][0]===DIFF_INSERT){deletion=diffs[pointer-1][1];insertion=diffs[pointer][1];overlapLength1=this.diffCommonOverlap(deletion,insertion);overlapLength2=this.diffCommonOverlap(insertion,deletion);if(overlapLength1>=overlapLength2){if(overlapLength1>=deletion.length/2||overlapLength1>=insertion.length/2){// Overlap found.  Insert an equality and trim the surrounding edits.
diffs.splice(pointer,0,[DIFF_EQUAL,insertion.substring(0,overlapLength1)]);diffs[pointer-1][1]=deletion.substring(0,deletion.length-overlapLength1);diffs[pointer+1][1]=insertion.substring(overlapLength1);pointer++;}}else{if(overlapLength2>=deletion.length/2||overlapLength2>=insertion.length/2){// Reverse overlap found.
// Insert an equality and swap and trim the surrounding edits.
diffs.splice(pointer,0,[DIFF_EQUAL,deletion.substring(0,overlapLength2)]);diffs[pointer-1][0]=DIFF_INSERT;diffs[pointer-1][1]=insertion.substring(0,insertion.length-overlapLength2);diffs[pointer+1][0]=DIFF_DELETE;diffs[pointer+1][1]=deletion.substring(overlapLength2);pointer++;}}pointer++;}pointer++;}};/**
	 * Determine if the suffix of one string is the prefix of another.
	 * @param {string} text1 First string.
	 * @param {string} text2 Second string.
	 * @return {number} The number of characters common to the end of the first
	 *     string and the start of the second string.
	 * @private
	 */DiffMatchPatch.prototype.diffCommonOverlap=function(text1,text2){var text1Length,text2Length,textLength,best,length,pattern,found;// Cache the text lengths to prevent multiple calls.
text1Length=text1.length;text2Length=text2.length;// Eliminate the null case.
if(text1Length===0||text2Length===0){return 0;}// Truncate the longer string.
if(text1Length>text2Length){text1=text1.substring(text1Length-text2Length);}else if(text1Length<text2Length){text2=text2.substring(0,text1Length);}textLength=Math.min(text1Length,text2Length);// Quick check for the worst case.
if(text1===text2){return textLength;}// Start by looking for a single character match
// and increase length until no match is found.
// Performance analysis: http://neil.fraser.name/news/2010/11/04/
best=0;length=1;while(true){pattern=text1.substring(textLength-length);found=text2.indexOf(pattern);if(found===-1){return best;}length+=found;if(found===0||text1.substring(textLength-length)===text2.substring(0,length)){best=length;length++;}}};/**
	 * Split two texts into an array of strings.  Reduce the texts to a string of
	 * hashes where each Unicode character represents one line.
	 * @param {string} text1 First string.
	 * @param {string} text2 Second string.
	 * @return {{chars1: string, chars2: string, lineArray: !Array.<string>}}
	 *     An object containing the encoded text1, the encoded text2 and
	 *     the array of unique strings.
	 *     The zeroth element of the array of unique strings is intentionally blank.
	 * @private
	 */DiffMatchPatch.prototype.diffLinesToChars=function(text1,text2){var lineArray,lineHash,chars1,chars2;lineArray=[];// e.g. lineArray[4] === 'Hello\n'
lineHash={};// e.g. lineHash['Hello\n'] === 4
// '\x00' is a valid character, but various debuggers don't like it.
// So we'll insert a junk entry to avoid generating a null character.
lineArray[0]="";/**
		 * Split a text into an array of strings.  Reduce the texts to a string of
		 * hashes where each Unicode character represents one line.
		 * Modifies linearray and linehash through being a closure.
		 * @param {string} text String to encode.
		 * @return {string} Encoded string.
		 * @private
		 */function diffLinesToCharsMunge(text){var chars,lineStart,lineEnd,lineArrayLength,line;chars="";// Walk the text, pulling out a substring for each line.
// text.split('\n') would would temporarily double our memory footprint.
// Modifying text would create many large strings to garbage collect.
lineStart=0;lineEnd=-1;// Keeping our own length variable is faster than looking it up.
lineArrayLength=lineArray.length;while(lineEnd<text.length-1){lineEnd=text.indexOf("\n",lineStart);if(lineEnd===-1){lineEnd=text.length-1;}line=text.substring(lineStart,lineEnd+1);lineStart=lineEnd+1;if(lineHash.hasOwnProperty?lineHash.hasOwnProperty(line):lineHash[line]!==undefined){chars+=String.fromCharCode(lineHash[line]);}else{chars+=String.fromCharCode(lineArrayLength);lineHash[line]=lineArrayLength;lineArray[lineArrayLength++]=line;}}return chars;}chars1=diffLinesToCharsMunge(text1);chars2=diffLinesToCharsMunge(text2);return{chars1:chars1,chars2:chars2,lineArray:lineArray};};/**
	 * Rehydrate the text in a diff from a string of line hashes to real lines of
	 * text.
	 * @param {!Array.<!DiffMatchPatch.Diff>} diffs Array of diff tuples.
	 * @param {!Array.<string>} lineArray Array of unique strings.
	 * @private
	 */DiffMatchPatch.prototype.diffCharsToLines=function(diffs,lineArray){var x,chars,text,y;for(x=0;x<diffs.length;x++){chars=diffs[x][1];text=[];for(y=0;y<chars.length;y++){text[y]=lineArray[chars.charCodeAt(y)];}diffs[x][1]=text.join("");}};/**
	 * Reorder and merge like edit sections.  Merge equalities.
	 * Any edit section can move as long as it doesn't cross an equality.
	 * @param {!Array.<!DiffMatchPatch.Diff>} diffs Array of diff tuples.
	 */DiffMatchPatch.prototype.diffCleanupMerge=function(diffs){var pointer,countDelete,countInsert,textInsert,textDelete,commonlength,changes,diffPointer,position;diffs.push([DIFF_EQUAL,""]);// Add a dummy entry at the end.
pointer=0;countDelete=0;countInsert=0;textDelete="";textInsert="";commonlength;while(pointer<diffs.length){switch(diffs[pointer][0]){case DIFF_INSERT:countInsert++;textInsert+=diffs[pointer][1];pointer++;break;case DIFF_DELETE:countDelete++;textDelete+=diffs[pointer][1];pointer++;break;case DIFF_EQUAL:// Upon reaching an equality, check for prior redundancies.
if(countDelete+countInsert>1){if(countDelete!==0&&countInsert!==0){// Factor out any common prefixies.
commonlength=this.diffCommonPrefix(textInsert,textDelete);if(commonlength!==0){if(pointer-countDelete-countInsert>0&&diffs[pointer-countDelete-countInsert-1][0]===DIFF_EQUAL){diffs[pointer-countDelete-countInsert-1][1]+=textInsert.substring(0,commonlength);}else{diffs.splice(0,0,[DIFF_EQUAL,textInsert.substring(0,commonlength)]);pointer++;}textInsert=textInsert.substring(commonlength);textDelete=textDelete.substring(commonlength);}// Factor out any common suffixies.
commonlength=this.diffCommonSuffix(textInsert,textDelete);if(commonlength!==0){diffs[pointer][1]=textInsert.substring(textInsert.length-commonlength)+diffs[pointer][1];textInsert=textInsert.substring(0,textInsert.length-commonlength);textDelete=textDelete.substring(0,textDelete.length-commonlength);}}// Delete the offending records and add the merged ones.
if(countDelete===0){diffs.splice(pointer-countInsert,countDelete+countInsert,[DIFF_INSERT,textInsert]);}else if(countInsert===0){diffs.splice(pointer-countDelete,countDelete+countInsert,[DIFF_DELETE,textDelete]);}else{diffs.splice(pointer-countDelete-countInsert,countDelete+countInsert,[DIFF_DELETE,textDelete],[DIFF_INSERT,textInsert]);}pointer=pointer-countDelete-countInsert+(countDelete?1:0)+(countInsert?1:0)+1;}else if(pointer!==0&&diffs[pointer-1][0]===DIFF_EQUAL){// Merge this equality with the previous one.
diffs[pointer-1][1]+=diffs[pointer][1];diffs.splice(pointer,1);}else{pointer++;}countInsert=0;countDelete=0;textDelete="";textInsert="";break;}}if(diffs[diffs.length-1][1]===""){diffs.pop();// Remove the dummy entry at the end.
}// Second pass: look for single edits surrounded on both sides by equalities
// which can be shifted sideways to eliminate an equality.
// e.g: A<ins>BA</ins>C -> <ins>AB</ins>AC
changes=false;pointer=1;// Intentionally ignore the first and last element (don't need checking).
while(pointer<diffs.length-1){if(diffs[pointer-1][0]===DIFF_EQUAL&&diffs[pointer+1][0]===DIFF_EQUAL){diffPointer=diffs[pointer][1];position=diffPointer.substring(diffPointer.length-diffs[pointer-1][1].length);// This is a single edit surrounded by equalities.
if(position===diffs[pointer-1][1]){// Shift the edit over the previous equality.
diffs[pointer][1]=diffs[pointer-1][1]+diffs[pointer][1].substring(0,diffs[pointer][1].length-diffs[pointer-1][1].length);diffs[pointer+1][1]=diffs[pointer-1][1]+diffs[pointer+1][1];diffs.splice(pointer-1,1);changes=true;}else if(diffPointer.substring(0,diffs[pointer+1][1].length)===diffs[pointer+1][1]){// Shift the edit over the next equality.
diffs[pointer-1][1]+=diffs[pointer+1][1];diffs[pointer][1]=diffs[pointer][1].substring(diffs[pointer+1][1].length)+diffs[pointer+1][1];diffs.splice(pointer+1,1);changes=true;}}pointer++;}// If shifts were made, the diff needs reordering and another shift sweep.
if(changes){this.diffCleanupMerge(diffs);}};return function(o,n){var diff,output,text;diff=new DiffMatchPatch();output=diff.DiffMain(o,n);diff.diffCleanupEfficiency(output);text=diff.diffPrettyHtml(output);return text;};}();// Get a reference to the global object, like window in browsers
})(function(){return this;}());(function(){// Don't load the HTML Reporter on non-Browser environments
if(typeof window==="undefined"||!window.document){return;}// Deprecated QUnit.init - Ref #530
// Re-initialize the configuration options
QUnit.init=function(){var tests,banner,result,qunit,config=QUnit.config;config.stats={all:0,bad:0};config.moduleStats={all:0,bad:0};config.started=0;config.updateRate=1000;config.blocking=false;config.autostart=true;config.autorun=false;config.filter="";config.queue=[];// Return on non-browser environments
// This is necessary to not break on node tests
if(typeof window==="undefined"){return;}qunit=id("qunit");if(qunit){qunit.innerHTML="<h1 id='qunit-header'>"+escapeText(document.title)+"</h1>"+"<h2 id='qunit-banner'></h2>"+"<div id='qunit-testrunner-toolbar'></div>"+"<h2 id='qunit-userAgent'></h2>"+"<ol id='qunit-tests'></ol>";}tests=id("qunit-tests");banner=id("qunit-banner");result=id("qunit-testresult");if(tests){tests.innerHTML="";}if(banner){banner.className="";}if(result){result.parentNode.removeChild(result);}if(tests){result=document.createElement("p");result.id="qunit-testresult";result.className="result";tests.parentNode.insertBefore(result,tests);result.innerHTML="Running...<br />&#160;";}};var config=QUnit.config,collapseNext=false,hasOwn=Object.prototype.hasOwnProperty,defined={document:window.document!==undefined,sessionStorage:function(){var x="qunit-test-string";try{sessionStorage.setItem(x,x);sessionStorage.removeItem(x);return true;}catch(e){return false;}}()},modulesList=[];/**
* Escape text for attribute or text content.
*/function escapeText(s){if(!s){return"";}s=s+"";// Both single quotes and double quotes (for attributes)
return s.replace(/['"<>&]/g,function(s){switch(s){case"'":return"&#039;";case"\"":return"&quot;";case"<":return"&lt;";case">":return"&gt;";case"&":return"&amp;";}});}/**
 * @param {HTMLElement} elem
 * @param {string} type
 * @param {Function} fn
 */function addEvent(elem,type,fn){if(elem.addEventListener){// Standards-based browsers
elem.addEventListener(type,fn,false);}else if(elem.attachEvent){// support: IE <9
elem.attachEvent("on"+type,function(){var event=window.event;if(!event.target){event.target=event.srcElement||document;}fn.call(elem,event);});}}/**
 * @param {Array|NodeList} elems
 * @param {string} type
 * @param {Function} fn
 */function addEvents(elems,type,fn){var i=elems.length;while(i--){addEvent(elems[i],type,fn);}}function hasClass(elem,name){return(" "+elem.className+" ").indexOf(" "+name+" ")>=0;}function addClass(elem,name){if(!hasClass(elem,name)){elem.className+=(elem.className?" ":"")+name;}}function toggleClass(elem,name){if(hasClass(elem,name)){removeClass(elem,name);}else{addClass(elem,name);}}function removeClass(elem,name){var set=" "+elem.className+" ";// Class name may appear multiple times
while(set.indexOf(" "+name+" ")>=0){set=set.replace(" "+name+" "," ");}// trim for prettiness
elem.className=typeof set.trim==="function"?set.trim():set.replace(/^\s+|\s+$/g,"");}function id(name){return defined.document&&document.getElementById&&document.getElementById(name);}function getUrlConfigHtml(){var i,j,val,escaped,escapedTooltip,selection=false,len=config.urlConfig.length,urlConfigHtml="";for(i=0;i<len;i++){val=config.urlConfig[i];if(typeof val==="string"){val={id:val,label:val};}escaped=escapeText(val.id);escapedTooltip=escapeText(val.tooltip);if(config[val.id]===undefined){config[val.id]=QUnit.urlParams[val.id];}if(!val.value||typeof val.value==="string"){urlConfigHtml+="<input id='qunit-urlconfig-"+escaped+"' name='"+escaped+"' type='checkbox'"+(val.value?" value='"+escapeText(val.value)+"'":"")+(config[val.id]?" checked='checked'":"")+" title='"+escapedTooltip+"' /><label for='qunit-urlconfig-"+escaped+"' title='"+escapedTooltip+"'>"+val.label+"</label>";}else{urlConfigHtml+="<label for='qunit-urlconfig-"+escaped+"' title='"+escapedTooltip+"'>"+val.label+": </label><select id='qunit-urlconfig-"+escaped+"' name='"+escaped+"' title='"+escapedTooltip+"'><option></option>";if(QUnit.is("array",val.value)){for(j=0;j<val.value.length;j++){escaped=escapeText(val.value[j]);urlConfigHtml+="<option value='"+escaped+"'"+(config[val.id]===val.value[j]?(selection=true)&&" selected='selected'":"")+">"+escaped+"</option>";}}else{for(j in val.value){if(hasOwn.call(val.value,j)){urlConfigHtml+="<option value='"+escapeText(j)+"'"+(config[val.id]===j?(selection=true)&&" selected='selected'":"")+">"+escapeText(val.value[j])+"</option>";}}}if(config[val.id]&&!selection){escaped=escapeText(config[val.id]);urlConfigHtml+="<option value='"+escaped+"' selected='selected' disabled='disabled'>"+escaped+"</option>";}urlConfigHtml+="</select>";}}return urlConfigHtml;}// Handle "click" events on toolbar checkboxes and "change" for select menus.
// Updates the URL with the new state of `config.urlConfig` values.
function toolbarChanged(){var updatedUrl,value,field=this,params={};// Detect if field is a select menu or a checkbox
if("selectedIndex"in field){value=field.options[field.selectedIndex].value||undefined;}else{value=field.checked?field.defaultValue||true:undefined;}params[field.name]=value;updatedUrl=setUrl(params);if("hidepassed"===field.name&&"replaceState"in window.history){config[field.name]=value||false;if(value){addClass(id("qunit-tests"),"hidepass");}else{removeClass(id("qunit-tests"),"hidepass");}// It is not necessary to refresh the whole page
window.history.replaceState(null,"",updatedUrl);}else{window.location=updatedUrl;}}function setUrl(params){var key,querystring="?";params=QUnit.extend(QUnit.extend({},QUnit.urlParams),params);for(key in params){if(hasOwn.call(params,key)){if(params[key]===undefined){continue;}querystring+=encodeURIComponent(key);if(params[key]!==true){querystring+="="+encodeURIComponent(params[key]);}querystring+="&";}}return location.protocol+"//"+location.host+location.pathname+querystring.slice(0,-1);}function applyUrlParams(){var selectedModule,modulesList=id("qunit-modulefilter"),filter=id("qunit-filter-input").value;selectedModule=modulesList?decodeURIComponent(modulesList.options[modulesList.selectedIndex].value):undefined;window.location=setUrl({module:selectedModule===""?undefined:selectedModule,filter:filter===""?undefined:filter,// Remove testId filter
testId:undefined});}function toolbarUrlConfigContainer(){var urlConfigContainer=document.createElement("span");urlConfigContainer.innerHTML=getUrlConfigHtml();addClass(urlConfigContainer,"qunit-url-config");// For oldIE support:
// * Add handlers to the individual elements instead of the container
// * Use "click" instead of "change" for checkboxes
addEvents(urlConfigContainer.getElementsByTagName("input"),"click",toolbarChanged);addEvents(urlConfigContainer.getElementsByTagName("select"),"change",toolbarChanged);return urlConfigContainer;}function toolbarLooseFilter(){var filter=document.createElement("form"),label=document.createElement("label"),input=document.createElement("input"),button=document.createElement("button");addClass(filter,"qunit-filter");label.innerHTML="Filter: ";input.type="text";input.value=config.filter||"";input.name="filter";input.id="qunit-filter-input";button.innerHTML="Go";label.appendChild(input);filter.appendChild(label);filter.appendChild(button);addEvent(filter,"submit",function(ev){applyUrlParams();if(ev&&ev.preventDefault){ev.preventDefault();}return false;});return filter;}function toolbarModuleFilterHtml(){var i,moduleFilterHtml="";if(!modulesList.length){return false;}modulesList.sort(function(a,b){return a.localeCompare(b);});moduleFilterHtml+="<label for='qunit-modulefilter'>Module: </label>"+"<select id='qunit-modulefilter' name='modulefilter'><option value='' "+(QUnit.urlParams.module===undefined?"selected='selected'":"")+">< All Modules ></option>";for(i=0;i<modulesList.length;i++){moduleFilterHtml+="<option value='"+escapeText(encodeURIComponent(modulesList[i]))+"' "+(QUnit.urlParams.module===modulesList[i]?"selected='selected'":"")+">"+escapeText(modulesList[i])+"</option>";}moduleFilterHtml+="</select>";return moduleFilterHtml;}function toolbarModuleFilter(){var toolbar=id("qunit-testrunner-toolbar"),moduleFilter=document.createElement("span"),moduleFilterHtml=toolbarModuleFilterHtml();if(!toolbar||!moduleFilterHtml){return false;}moduleFilter.setAttribute("id","qunit-modulefilter-container");moduleFilter.innerHTML=moduleFilterHtml;addEvent(moduleFilter.lastChild,"change",applyUrlParams);toolbar.appendChild(moduleFilter);}function appendToolbar(){var toolbar=id("qunit-testrunner-toolbar");if(toolbar){toolbar.appendChild(toolbarUrlConfigContainer());toolbar.appendChild(toolbarLooseFilter());}}function appendHeader(){var header=id("qunit-header");if(header){header.innerHTML="<a href='"+setUrl({filter:undefined,module:undefined,testId:undefined})+"'>"+header.innerHTML+"</a> ";}}function appendBanner(){var banner=id("qunit-banner");if(banner){banner.className="";}}function appendTestResults(){var tests=id("qunit-tests"),result=id("qunit-testresult");if(result){result.parentNode.removeChild(result);}if(tests){tests.innerHTML="";result=document.createElement("p");result.id="qunit-testresult";result.className="result";tests.parentNode.insertBefore(result,tests);result.innerHTML="Running...<br />&#160;";}}function storeFixture(){var fixture=id("qunit-fixture");if(fixture){config.fixture=fixture.innerHTML;}}function appendFilteredTest(){var testId=QUnit.config.testId;if(!testId||testId.length<=0){return"";}return"<div id='qunit-filteredTest'>Rerunning selected tests: "+testId.join(", ")+" <a id='qunit-clearFilter' href='"+setUrl({filter:undefined,module:undefined,testId:undefined})+"'>"+"Run all tests"+"</a></div>";}function appendUserAgent(){var userAgent=id("qunit-userAgent");if(userAgent){userAgent.innerHTML="";userAgent.appendChild(document.createTextNode("QUnit "+QUnit.version+"; "+navigator.userAgent));}}function appendTestsList(modules){var i,l,x,z,test,moduleObj;for(i=0,l=modules.length;i<l;i++){moduleObj=modules[i];if(moduleObj.name){modulesList.push(moduleObj.name);}for(x=0,z=moduleObj.tests.length;x<z;x++){test=moduleObj.tests[x];appendTest(test.name,test.testId,moduleObj.name);}}}function appendTest(name,testId,moduleName){var title,rerunTrigger,testBlock,assertList,tests=id("qunit-tests");if(!tests){return;}title=document.createElement("strong");title.innerHTML=getNameHtml(name,moduleName);rerunTrigger=document.createElement("a");rerunTrigger.innerHTML="Rerun";rerunTrigger.href=setUrl({testId:testId});testBlock=document.createElement("li");testBlock.appendChild(title);testBlock.appendChild(rerunTrigger);testBlock.id="qunit-test-output-"+testId;assertList=document.createElement("ol");assertList.className="qunit-assert-list";testBlock.appendChild(assertList);tests.appendChild(testBlock);}// HTML Reporter initialization and load
QUnit.begin(function(details){var qunit=id("qunit");// Fixture is the only one necessary to run without the #qunit element
storeFixture();if(qunit){qunit.innerHTML="<h1 id='qunit-header'>"+escapeText(document.title)+"</h1>"+"<h2 id='qunit-banner'></h2>"+"<div id='qunit-testrunner-toolbar'></div>"+appendFilteredTest()+"<h2 id='qunit-userAgent'></h2>"+"<ol id='qunit-tests'></ol>";}appendHeader();appendBanner();appendTestResults();appendUserAgent();appendToolbar();appendTestsList(details.modules);toolbarModuleFilter();if(qunit&&config.hidepassed){addClass(qunit.lastChild,"hidepass");}});QUnit.done(function(details){var i,key,banner=id("qunit-banner"),tests=id("qunit-tests"),html=["Tests completed in ",details.runtime," milliseconds.<br />","<span class='passed'>",details.passed,"</span> assertions of <span class='total'>",details.total,"</span> passed, <span class='failed'>",details.failed,"</span> failed."].join("");if(banner){banner.className=details.failed?"qunit-fail":"qunit-pass";}if(tests){id("qunit-testresult").innerHTML=html;}if(config.altertitle&&defined.document&&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=[details.failed?"\u2716":"\u2714",document.title.replace(/^[\u2714\u2716] /i,"")].join(" ");}// clear own sessionStorage items if all tests passed
if(config.reorder&&defined.sessionStorage&&details.failed===0){for(i=0;i<sessionStorage.length;i++){key=sessionStorage.key(i++);if(key.indexOf("qunit-test-")===0){sessionStorage.removeItem(key);}}}// scroll back to top to show results
if(config.scrolltop&&window.scrollTo){window.scrollTo(0,0);}});function getNameHtml(name,module){var nameHtml="";if(module){nameHtml="<span class='module-name'>"+escapeText(module)+"</span>: ";}nameHtml+="<span class='test-name'>"+escapeText(name)+"</span>";return nameHtml;}QUnit.testStart(function(details){var running,testBlock,bad;testBlock=id("qunit-test-output-"+details.testId);if(testBlock){testBlock.className="running";}else{// Report later registered tests
appendTest(details.name,details.testId,details.module);}running=id("qunit-testresult");if(running){bad=QUnit.config.reorder&&defined.sessionStorage&&+sessionStorage.getItem("qunit-test-"+details.module+"-"+details.name);running.innerHTML=(bad?"Rerunning previously failed test: <br />":"Running: <br />")+getNameHtml(details.name,details.module);}});function stripHtml(string){// strip tags, html entity and whitespaces
return string.replace(/<\/?[^>]+(>|$)/g,"").replace(/\&quot;/g,"").replace(/\s+/g,"");}QUnit.log(function(details){var assertList,assertLi,message,expected,actual,diff,showDiff=false,testItem=id("qunit-test-output-"+details.testId);if(!testItem){return;}message=escapeText(details.message)||(details.result?"okay":"failed");message="<span class='test-message'>"+message+"</span>";message+="<span class='runtime'>@ "+details.runtime+" ms</span>";// pushFailure doesn't provide details.expected
// when it calls, it's implicit to also not show expected and diff stuff
// Also, we need to check details.expected existence, as it can exist and be undefined
if(!details.result&&hasOwn.call(details,"expected")){if(details.negative){expected=escapeText("NOT "+QUnit.dump.parse(details.expected));}else{expected=escapeText(QUnit.dump.parse(details.expected));}actual=escapeText(QUnit.dump.parse(details.actual));message+="<table><tr class='test-expected'><th>Expected: </th><td><pre>"+expected+"</pre></td></tr>";if(actual!==expected){message+="<tr class='test-actual'><th>Result: </th><td><pre>"+actual+"</pre></td></tr>";// Don't show diff if actual or expected are booleans
if(!/^(true|false)$/.test(actual)&&!/^(true|false)$/.test(expected)){diff=QUnit.diff(expected,actual);showDiff=stripHtml(diff).length!==stripHtml(expected).length+stripHtml(actual).length;}// Don't show diff if expected and actual are totally different
if(showDiff){message+="<tr class='test-diff'><th>Diff: </th><td><pre>"+diff+"</pre></td></tr>";}}else if(expected.indexOf("[object Array]")!==-1||expected.indexOf("[object Object]")!==-1){message+="<tr class='test-message'><th>Message: </th><td>"+"Diff suppressed as the depth of object is more than current max depth ("+QUnit.config.maxDepth+").<p>Hint: Use <code>QUnit.dump.maxDepth</code> to "+" run with a higher max depth or <a href='"+setUrl({maxDepth:-1})+"'>"+"Rerun</a> without max depth.</p></td></tr>";}if(details.source){message+="<tr class='test-source'><th>Source: </th><td><pre>"+escapeText(details.source)+"</pre></td></tr>";}message+="</table>";// this occours when pushFailure is set and we have an extracted stack trace
}else if(!details.result&&details.source){message+="<table>"+"<tr class='test-source'><th>Source: </th><td><pre>"+escapeText(details.source)+"</pre></td></tr>"+"</table>";}assertList=testItem.getElementsByTagName("ol")[0];assertLi=document.createElement("li");assertLi.className=details.result?"pass":"fail";assertLi.innerHTML=message;assertList.appendChild(assertLi);});QUnit.testDone(function(details){var testTitle,time,testItem,assertList,good,bad,testCounts,skipped,sourceName,tests=id("qunit-tests");if(!tests){return;}testItem=id("qunit-test-output-"+details.testId);assertList=testItem.getElementsByTagName("ol")[0];good=details.passed;bad=details.failed;// store result when possible
if(config.reorder&&defined.sessionStorage){if(bad){sessionStorage.setItem("qunit-test-"+details.module+"-"+details.name,bad);}else{sessionStorage.removeItem("qunit-test-"+details.module+"-"+details.name);}}if(bad===0){// Collapse the passing tests
addClass(assertList,"qunit-collapsed");}else if(bad&&config.collapse&&!collapseNext){// Skip collapsing the first failing test
collapseNext=true;}else{// Collapse remaining tests
addClass(assertList,"qunit-collapsed");}// testItem.firstChild is the test name
testTitle=testItem.firstChild;testCounts=bad?"<b class='failed'>"+bad+"</b>, "+"<b class='passed'>"+good+"</b>, ":"";testTitle.innerHTML+=" <b class='counts'>("+testCounts+details.assertions.length+")</b>";if(details.skipped){testItem.className="skipped";skipped=document.createElement("em");skipped.className="qunit-skipped-label";skipped.innerHTML="skipped";testItem.insertBefore(skipped,testTitle);}else{addEvent(testTitle,"click",function(){toggleClass(assertList,"qunit-collapsed");});testItem.className=bad?"fail":"pass";time=document.createElement("span");time.className="runtime";time.innerHTML=details.runtime+" ms";testItem.insertBefore(time,assertList);}// Show the source of the test when showing assertions
if(details.source){sourceName=document.createElement("p");sourceName.innerHTML="<strong>Source: </strong>"+details.source;addClass(sourceName,"qunit-source");if(bad===0){addClass(sourceName,"qunit-collapsed");}addEvent(testTitle,"click",function(){toggleClass(sourceName,"qunit-collapsed");});testItem.appendChild(sourceName);}});if(defined.document){// Avoid readyState issue with phantomjs
// Ref: #818
var notPhantom=function(p){return!(p&&p.version&&p.version.major>0);}(window.phantom);if(notPhantom&&document.readyState==="complete"){QUnit.load();}else{addEvent(window,"load",QUnit.load);}}else{config.pageLoaded=true;config.autorun=true;}})();