Upgrade QUnit from 2.4.0 to 2.6.0
Source https://code.jquery.com/qunit/qunit-2.6.0.js https://code.jquery.com/qunit/qunit-2.6.0.css Changelog https://github.com/qunitjs/qunit/blob/2.6.0/History.md Highlights: * 2.4.1: Fixed various bugs in HTML interface. * 2.5.0: Added assert.rejects. * 2.5.1: Fixed HTML reporter to reset attributes on qunit-fixture. * 2.6.0: Changed behaviour to fail if no test suites exist. Change-Id: I24120a74094db358f02f9fc1935920c43a0a7ced
This commit is contained in:
parent
0e746c7ef3
commit
065b21b4bd
3 changed files with 291 additions and 75 deletions
|
|
@ -22,7 +22,7 @@ production.
|
|||
* …
|
||||
|
||||
==== Upgraded external libraries ====
|
||||
* …
|
||||
* Updated QUnit from 2.4.0 to 2.6.0.
|
||||
|
||||
==== New external libraries ====
|
||||
* …
|
||||
|
|
|
|||
|
|
@ -1,12 +1,12 @@
|
|||
/*!
|
||||
* QUnit 2.4.0
|
||||
* QUnit 2.6.0
|
||||
* https://qunitjs.com/
|
||||
*
|
||||
* Copyright jQuery Foundation and other contributors
|
||||
* Released under the MIT license
|
||||
* https://jquery.org/license
|
||||
*
|
||||
* Date: 2017-07-08T15:20Z
|
||||
* Date: 2018-03-27T02:18Z
|
||||
*/
|
||||
|
||||
/** Font Family and Sizes */
|
||||
|
|
|
|||
|
|
@ -1,17 +1,17 @@
|
|||
/*!
|
||||
* QUnit 2.4.0
|
||||
* QUnit 2.6.0
|
||||
* https://qunitjs.com/
|
||||
*
|
||||
* Copyright jQuery Foundation and other contributors
|
||||
* Released under the MIT license
|
||||
* https://jquery.org/license
|
||||
*
|
||||
* Date: 2017-07-08T15:20Z
|
||||
* Date: 2018-03-27T02:18Z
|
||||
*/
|
||||
(function (global$1) {
|
||||
'use strict';
|
||||
|
||||
global$1 = global$1 && 'default' in global$1 ? global$1['default'] : global$1;
|
||||
global$1 = global$1 && global$1.hasOwnProperty('default') ? global$1['default'] : global$1;
|
||||
|
||||
var window = global$1.window;
|
||||
var self$1 = global$1.self;
|
||||
|
|
@ -1097,58 +1097,89 @@
|
|||
var priorityCount = 0;
|
||||
var unitSampler = void 0;
|
||||
|
||||
// This is a queue of functions that are tasks within a single test.
|
||||
// After tests are dequeued from config.queue they are expanded into
|
||||
// a set of tasks in this queue.
|
||||
var taskQueue = [];
|
||||
|
||||
/**
|
||||
* Advances the ProcessingQueue to the next item if it is ready.
|
||||
* @param {Boolean} last
|
||||
* Advances the taskQueue to the next task. If the taskQueue is empty,
|
||||
* process the testQueue
|
||||
*/
|
||||
function advance() {
|
||||
advanceTaskQueue();
|
||||
|
||||
if (!taskQueue.length) {
|
||||
advanceTestQueue();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Advances the taskQueue to the next task if it is ready and not empty.
|
||||
*/
|
||||
function advanceTaskQueue() {
|
||||
var start = now();
|
||||
config.depth = (config.depth || 0) + 1;
|
||||
|
||||
while (config.queue.length && !config.blocking) {
|
||||
while (taskQueue.length && !config.blocking) {
|
||||
var elapsedTime = now() - start;
|
||||
|
||||
if (!defined.setTimeout || config.updateRate <= 0 || elapsedTime < config.updateRate) {
|
||||
if (priorityCount > 0) {
|
||||
priorityCount--;
|
||||
}
|
||||
|
||||
config.queue.shift()();
|
||||
var task = taskQueue.shift();
|
||||
task();
|
||||
} else {
|
||||
setTimeout(advance, 13);
|
||||
setTimeout(advance);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
config.depth--;
|
||||
|
||||
if (!config.blocking && !config.queue.length && config.depth === 0) {
|
||||
done();
|
||||
}
|
||||
}
|
||||
|
||||
function addToQueueImmediate(callback) {
|
||||
if (objectType(callback) === "array") {
|
||||
while (callback.length) {
|
||||
addToQueueImmediate(callback.pop());
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
config.queue.unshift(callback);
|
||||
priorityCount++;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a function to the ProcessingQueue for execution.
|
||||
* @param {Function|Array} callback
|
||||
* @param {Boolean} priority
|
||||
* Advance the testQueue to the next test to process. Call done() if testQueue completes.
|
||||
*/
|
||||
function advanceTestQueue() {
|
||||
if (!config.blocking && !config.queue.length && config.depth === 0) {
|
||||
done();
|
||||
return;
|
||||
}
|
||||
|
||||
var testTasks = config.queue.shift();
|
||||
addToTaskQueue(testTasks());
|
||||
|
||||
if (priorityCount > 0) {
|
||||
priorityCount--;
|
||||
}
|
||||
|
||||
advance();
|
||||
}
|
||||
|
||||
/**
|
||||
* Enqueue the tasks for a test into the task queue.
|
||||
* @param {Array} tasksArray
|
||||
*/
|
||||
function addToTaskQueue(tasksArray) {
|
||||
taskQueue.push.apply(taskQueue, toConsumableArray(tasksArray));
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the number of tasks remaining in the task queue to be processed.
|
||||
* @return {Number}
|
||||
*/
|
||||
function taskQueueLength() {
|
||||
return taskQueue.length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a test to the TestQueue for execution.
|
||||
* @param {Function} testTasksFunc
|
||||
* @param {Boolean} prioritize
|
||||
* @param {String} seed
|
||||
*/
|
||||
function addToQueue(callback, prioritize, seed) {
|
||||
function addToTestQueue(testTasksFunc, prioritize, seed) {
|
||||
if (prioritize) {
|
||||
config.queue.splice(priorityCount++, 0, callback);
|
||||
config.queue.splice(priorityCount++, 0, testTasksFunc);
|
||||
} else if (seed) {
|
||||
if (!unitSampler) {
|
||||
unitSampler = unitSamplerGenerator(seed);
|
||||
|
|
@ -1156,9 +1187,9 @@
|
|||
|
||||
// Insert into a random position after all prioritized items
|
||||
var index = Math.floor(unitSampler() * (config.queue.length - priorityCount + 1));
|
||||
config.queue.splice(priorityCount + index, 0, callback);
|
||||
config.queue.splice(priorityCount + index, 0, testTasksFunc);
|
||||
} else {
|
||||
config.queue.push(callback);
|
||||
config.queue.push(testTasksFunc);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1196,6 +1227,27 @@
|
|||
var runtime = now() - config.started;
|
||||
var passed = config.stats.all - config.stats.bad;
|
||||
|
||||
if (config.stats.all === 0) {
|
||||
|
||||
if (config.filter && config.filter.length) {
|
||||
throw new Error("No tests matched the filter \"" + config.filter + "\".");
|
||||
}
|
||||
|
||||
if (config.module && config.module.length) {
|
||||
throw new Error("No tests matched the module \"" + config.module + "\".");
|
||||
}
|
||||
|
||||
if (config.moduleId && config.moduleId.length) {
|
||||
throw new Error("No tests matched the moduleId \"" + config.moduleId + "\".");
|
||||
}
|
||||
|
||||
if (config.testId && config.testId.length) {
|
||||
throw new Error("No tests matched the testId \"" + config.testId + "\".");
|
||||
}
|
||||
|
||||
throw new Error("No tests were run.");
|
||||
}
|
||||
|
||||
emit("runEnd", globalSuite.end(true));
|
||||
runLoggingCallbacks("done", {
|
||||
passed: passed,
|
||||
|
|
@ -1218,9 +1270,9 @@
|
|||
|
||||
var ProcessingQueue = {
|
||||
finished: false,
|
||||
add: addToQueue,
|
||||
addImmediate: addToQueueImmediate,
|
||||
advance: advance
|
||||
add: addToTestQueue,
|
||||
advance: advance,
|
||||
taskCount: taskQueueLength
|
||||
};
|
||||
|
||||
var TestReport = function () {
|
||||
|
|
@ -1388,6 +1440,13 @@
|
|||
this.async = false;
|
||||
this.expected = 0;
|
||||
} else {
|
||||
if (typeof this.callback !== "function") {
|
||||
var method = this.todo ? "todo" : "test";
|
||||
|
||||
// eslint-disable-next-line max-len
|
||||
throw new TypeError("You must provide a function as a test callback to QUnit." + method + "(\"" + settings.testName + "\")");
|
||||
}
|
||||
|
||||
this.assert = new Assert(this);
|
||||
}
|
||||
}
|
||||
|
|
@ -1500,7 +1559,9 @@
|
|||
_this.preserveEnvironment = true;
|
||||
}
|
||||
|
||||
if (hookName === "after" && hookOwner.unskippedTestsRun !== numberOfUnskippedTests(hookOwner) - 1 && config.queue.length > 2) {
|
||||
// The 'after' hook should only execute when there are not tests left and
|
||||
// when the 'after' and 'finish' tasks are the only tasks left to process
|
||||
if (hookName === "after" && hookOwner.unskippedTestsRun !== numberOfUnskippedTests(hookOwner) - 1 && (config.queue.length > 0 || ProcessingQueue.taskCount() > 2)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -1547,6 +1608,12 @@
|
|||
|
||||
finish: function finish() {
|
||||
config.current = this;
|
||||
|
||||
if (this.steps.length) {
|
||||
var stepsList = this.steps.join(", ");
|
||||
this.pushFailure("Expected assert.verifySteps() to be called before end of test " + ("after using assert.step(). Unverified steps: " + stepsList), this.stack);
|
||||
}
|
||||
|
||||
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) {
|
||||
|
|
@ -1653,15 +1720,13 @@
|
|||
}
|
||||
|
||||
function runTest() {
|
||||
|
||||
// Each of these can by async
|
||||
ProcessingQueue.addImmediate([function () {
|
||||
return [function () {
|
||||
test.before();
|
||||
}, test.hooks("before"), function () {
|
||||
}].concat(toConsumableArray(test.hooks("before")), [function () {
|
||||
test.preserveTestEnvironment();
|
||||
}, test.hooks("beforeEach"), function () {
|
||||
}], toConsumableArray(test.hooks("beforeEach")), [function () {
|
||||
test.run();
|
||||
}, test.hooks("afterEach").reverse(), test.hooks("after").reverse(), function () {
|
||||
}], toConsumableArray(test.hooks("afterEach").reverse()), toConsumableArray(test.hooks("after").reverse()), [function () {
|
||||
test.after();
|
||||
}, function () {
|
||||
test.finish();
|
||||
|
|
@ -1686,7 +1751,7 @@
|
|||
|
||||
pushResult: function pushResult(resultInfo) {
|
||||
if (this !== config.current) {
|
||||
throw new Error("Assertion occured after test had finished.");
|
||||
throw new Error("Assertion occurred after test had finished.");
|
||||
}
|
||||
|
||||
// Destructure of resultInfo = { result, actual, expected, message, negative }
|
||||
|
|
@ -1697,13 +1762,16 @@
|
|||
result: resultInfo.result,
|
||||
message: resultInfo.message,
|
||||
actual: resultInfo.actual,
|
||||
expected: resultInfo.expected,
|
||||
testId: this.testId,
|
||||
negative: resultInfo.negative || false,
|
||||
runtime: now() - this.started,
|
||||
todo: !!this.todo
|
||||
};
|
||||
|
||||
if (hasOwn.call(resultInfo, "expected")) {
|
||||
details.expected = resultInfo.expected;
|
||||
}
|
||||
|
||||
if (!resultInfo.result) {
|
||||
source = resultInfo.source || sourceFromStacktrace();
|
||||
|
||||
|
|
@ -1729,7 +1797,6 @@
|
|||
result: false,
|
||||
message: message || "error",
|
||||
actual: actual || null,
|
||||
expected: null,
|
||||
source: source
|
||||
});
|
||||
},
|
||||
|
|
@ -1765,18 +1832,24 @@
|
|||
then = promise.then;
|
||||
if (objectType(then) === "function") {
|
||||
resume = internalStop(test);
|
||||
then.call(promise, function () {
|
||||
resume();
|
||||
}, function (error) {
|
||||
message = "Promise rejected " + (!phase ? "during" : phase.replace(/Each$/, "")) + " \"" + test.testName + "\": " + (error && error.message || error);
|
||||
test.pushFailure(message, extractStacktrace(error, 0));
|
||||
if (config.notrycatch) {
|
||||
then.call(promise, function () {
|
||||
resume();
|
||||
});
|
||||
} else {
|
||||
then.call(promise, function () {
|
||||
resume();
|
||||
}, function (error) {
|
||||
message = "Promise rejected " + (!phase ? "during" : phase.replace(/Each$/, "")) + " \"" + test.testName + "\": " + (error && error.message || error);
|
||||
test.pushFailure(message, extractStacktrace(error, 0));
|
||||
|
||||
// Else next test will carry the responsibility
|
||||
saveGlobal();
|
||||
// Else next test will carry the responsibility
|
||||
saveGlobal();
|
||||
|
||||
// Unblock
|
||||
resume();
|
||||
});
|
||||
// Unblock
|
||||
internalRecover(test);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
@ -2040,7 +2113,7 @@
|
|||
}
|
||||
|
||||
begin();
|
||||
}, 13);
|
||||
});
|
||||
} else {
|
||||
begin();
|
||||
}
|
||||
|
|
@ -2125,13 +2198,21 @@
|
|||
}, {
|
||||
key: "step",
|
||||
value: function step(message) {
|
||||
var assertionMessage = message;
|
||||
var result = !!message;
|
||||
|
||||
this.test.steps.push(message);
|
||||
|
||||
if (objectType(message) === "undefined" || message === "") {
|
||||
assertionMessage = "You must provide a message to assert.step";
|
||||
} else if (objectType(message) !== "string") {
|
||||
assertionMessage = "You must provide a string value to assert.step";
|
||||
result = false;
|
||||
}
|
||||
|
||||
return this.pushResult({
|
||||
result: result,
|
||||
message: message || "You must provide a message to assert.step"
|
||||
message: assertionMessage
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -2140,7 +2221,11 @@
|
|||
}, {
|
||||
key: "verifySteps",
|
||||
value: function verifySteps(steps, message) {
|
||||
this.deepEqual(this.test.steps, steps, message);
|
||||
|
||||
// Since the steps array is just string values, we can clone with slice
|
||||
var actualStepsClone = this.test.steps.slice();
|
||||
this.deepEqual(actualStepsClone, steps, message);
|
||||
this.test.steps.length = 0;
|
||||
}
|
||||
|
||||
// Specify the number of expected assertions to guarantee that failed test
|
||||
|
|
@ -2418,6 +2503,98 @@
|
|||
message: message
|
||||
});
|
||||
}
|
||||
}, {
|
||||
key: "rejects",
|
||||
value: function rejects(promise, expected, message) {
|
||||
var result = false;
|
||||
|
||||
var currentTest = this instanceof Assert && this.test || config.current;
|
||||
|
||||
// 'expected' is optional unless doing string comparison
|
||||
if (objectType(expected) === "string") {
|
||||
if (message === undefined) {
|
||||
message = expected;
|
||||
expected = undefined;
|
||||
} else {
|
||||
message = "assert.rejects does not accept a string value for the expected " + "argument.\nUse a non-string object value (e.g. validator function) instead " + "if necessary.";
|
||||
|
||||
currentTest.assert.pushResult({
|
||||
result: false,
|
||||
message: message
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
var then = promise && promise.then;
|
||||
if (objectType(then) !== "function") {
|
||||
var _message = "The value provided to `assert.rejects` in " + "\"" + currentTest.testName + "\" was not a promise.";
|
||||
|
||||
currentTest.assert.pushResult({
|
||||
result: false,
|
||||
message: _message,
|
||||
actual: promise
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
var done = this.async();
|
||||
|
||||
return then.call(promise, function handleFulfillment() {
|
||||
var message = "The promise returned by the `assert.rejects` callback in " + "\"" + currentTest.testName + "\" did not reject.";
|
||||
|
||||
currentTest.assert.pushResult({
|
||||
result: false,
|
||||
message: message,
|
||||
actual: promise
|
||||
});
|
||||
|
||||
done();
|
||||
}, function handleRejection(actual) {
|
||||
var expectedType = objectType(expected);
|
||||
|
||||
// We don't want to validate
|
||||
if (expected === undefined) {
|
||||
result = true;
|
||||
expected = actual;
|
||||
|
||||
// Expected is a regexp
|
||||
} else if (expectedType === "regexp") {
|
||||
result = expected.test(errorString(actual));
|
||||
|
||||
// Expected is a constructor, maybe an Error constructor
|
||||
} else if (expectedType === "function" && actual instanceof expected) {
|
||||
result = true;
|
||||
|
||||
// Expected is an Error object
|
||||
} else if (expectedType === "object") {
|
||||
result = 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") {
|
||||
result = expected.call({}, actual) === true;
|
||||
expected = null;
|
||||
|
||||
// Expected is some other invalid type
|
||||
} else {
|
||||
result = false;
|
||||
message = "invalid expected value provided to `assert.rejects` " + "callback in \"" + currentTest.testName + "\": " + expectedType + ".";
|
||||
}
|
||||
}
|
||||
|
||||
currentTest.assert.pushResult({
|
||||
result: result,
|
||||
actual: actual,
|
||||
expected: expected,
|
||||
message: message
|
||||
});
|
||||
|
||||
done();
|
||||
});
|
||||
}
|
||||
}]);
|
||||
return Assert;
|
||||
}();
|
||||
|
|
@ -2633,6 +2810,25 @@
|
|||
return false;
|
||||
}
|
||||
|
||||
// Handle an unhandled rejection
|
||||
function onUnhandledRejection(reason) {
|
||||
var resultInfo = {
|
||||
result: false,
|
||||
message: reason.message || "error",
|
||||
actual: reason,
|
||||
source: reason.stack || sourceFromStacktrace(3)
|
||||
};
|
||||
|
||||
var currentTest = config.current;
|
||||
if (currentTest) {
|
||||
currentTest.assert.pushResult(resultInfo);
|
||||
} else {
|
||||
test("global failure", extend(function (assert) {
|
||||
assert.pushResult(resultInfo);
|
||||
}, { validTest: true }));
|
||||
}
|
||||
}
|
||||
|
||||
var focused = false;
|
||||
var QUnit = {};
|
||||
var globalSuite = new SuiteReport();
|
||||
|
|
@ -2650,7 +2846,7 @@
|
|||
QUnit.isLocal = !(defined.document && window.location.protocol !== "file:");
|
||||
|
||||
// Expose the current QUnit version
|
||||
QUnit.version = "2.4.0";
|
||||
QUnit.version = "2.6.0";
|
||||
|
||||
function createModule(name, testEnvironment, modifiers) {
|
||||
var parentModule = moduleStack.length ? moduleStack.slice(-1)[0] : null;
|
||||
|
|
@ -2868,7 +3064,9 @@
|
|||
return sourceFromStacktrace(offset);
|
||||
},
|
||||
|
||||
onError: onError
|
||||
onError: onError,
|
||||
|
||||
onUnhandledRejection: onUnhandledRejection
|
||||
});
|
||||
|
||||
QUnit.pushFailure = pushFailure;
|
||||
|
|
@ -2886,7 +3084,7 @@
|
|||
if (defined.setTimeout) {
|
||||
setTimeout(function () {
|
||||
begin();
|
||||
}, 13);
|
||||
});
|
||||
} else {
|
||||
begin();
|
||||
}
|
||||
|
|
@ -2955,7 +3153,7 @@
|
|||
|
||||
var fixture = document.getElementById("qunit-fixture");
|
||||
if (fixture) {
|
||||
config.fixture = fixture.innerHTML;
|
||||
config.fixture = fixture.cloneNode(true);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2968,8 +3166,17 @@
|
|||
}
|
||||
|
||||
var fixture = document.getElementById("qunit-fixture");
|
||||
if (fixture) {
|
||||
fixture.innerHTML = config.fixture;
|
||||
var resetFixtureType = _typeof(config.fixture);
|
||||
if (resetFixtureType === "string") {
|
||||
|
||||
// support user defined values for `config.fixture`
|
||||
var newFixture = document.createElement("div");
|
||||
newFixture.setAttribute("id", "qunit-fixture");
|
||||
newFixture.innerHTML = config.fixture;
|
||||
fixture.parentNode.replaceChild(newFixture, fixture);
|
||||
} else {
|
||||
var clonedFixture = config.fixture.cloneNode(true);
|
||||
fixture.parentNode.replaceChild(clonedFixture, fixture);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -3284,7 +3491,8 @@
|
|||
// Skip inherited or undefined properties
|
||||
if (hasOwn.call(params, key) && params[key] !== undefined) {
|
||||
|
||||
// Output a parameter for each value of this key (but usually just one)
|
||||
// Output a parameter for each value of this key
|
||||
// (but usually just one)
|
||||
arrValue = [].concat(params[key]);
|
||||
for (i = 0; i < arrValue.length; i++) {
|
||||
querystring += encodeURIComponent(key);
|
||||
|
|
@ -3705,7 +3913,8 @@
|
|||
if (config.altertitle && document$$1.title) {
|
||||
|
||||
// Show ✖ for good, ✔ for bad suite result in title
|
||||
// use escape sequences in case file gets loaded with non-utf-8-charset
|
||||
// use escape sequences in case file gets loaded with non-utf-8
|
||||
// charset
|
||||
document$$1.title = [stats.failedTests ? "\u2716" : "\u2714", document$$1.title.replace(/^[\u2714\u2716] /i, "")].join(" ");
|
||||
}
|
||||
|
||||
|
|
@ -3743,7 +3952,7 @@
|
|||
if (running) {
|
||||
bad = QUnit.config.reorder && details.previousFailure;
|
||||
|
||||
running.innerHTML = (bad ? "Rerunning previously failed test: <br />" : "Running: <br />") + getNameHtml(details.name, details.module);
|
||||
running.innerHTML = [bad ? "Rerunning previously failed test: <br />" : "Running: <br />", getNameHtml(details.name, details.module)].join("");
|
||||
}
|
||||
});
|
||||
|
||||
|
|
@ -3974,6 +4183,11 @@
|
|||
|
||||
return ret;
|
||||
};
|
||||
|
||||
// Listen for unhandled rejections, and call QUnit.onUnhandledRejection
|
||||
window.addEventListener("unhandledrejection", function (event) {
|
||||
QUnit.onUnhandledRejection(event.reason);
|
||||
});
|
||||
})();
|
||||
|
||||
/*
|
||||
|
|
@ -4874,7 +5088,9 @@
|
|||
line = text.substring(lineStart, lineEnd + 1);
|
||||
lineStart = lineEnd + 1;
|
||||
|
||||
if (lineHash.hasOwnProperty ? lineHash.hasOwnProperty(line) : lineHash[line] !== undefined) {
|
||||
var lineHashExists = lineHash.hasOwnProperty ? lineHash.hasOwnProperty(line) : lineHash[line] !== undefined;
|
||||
|
||||
if (lineHashExists) {
|
||||
chars += String.fromCharCode(lineHash[line]);
|
||||
} else {
|
||||
chars += String.fromCharCode(lineArrayLength);
|
||||
|
|
|
|||
Loading…
Reference in a new issue