aboutsummaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
authortoasted-nutbread <toasted-nutbread@users.noreply.github.com>2020-09-19 19:04:28 -0400
committerGitHub <noreply@github.com>2020-09-19 19:04:28 -0400
commit51d4e5b0ff4c0054bf5012464414ec0657d09963 (patch)
tree9920d1a9c84bf968ca8105700450792d78ac0088 /test
parent4293f731537906785da3b1f20535ddd18a4edd21 (diff)
Dev/test script organization (#846)
* Move lint scripts * Move dictionary-validate.js * Move schema-validate.js * Move createTestDictionaryArchive, remove yomichan-test.js * Rename yomichan-util.js to util.js * Move test/yomichan-vm.js to dev/vm.js * Move getArgs into util.js (and fix name) * Create test-all.js * Update test-code script
Diffstat (limited to 'test')
-rw-r--r--test/dictionary-validate.js118
-rw-r--r--test/lint/global-declarations.js130
-rw-r--r--test/schema-validate.js57
-rw-r--r--test/test-all.js66
-rw-r--r--test/test-cache-map.js2
-rw-r--r--test/test-core.js2
-rw-r--r--test/test-database.js11
-rw-r--r--test/test-dictionary.js11
-rw-r--r--test/test-document-util.js2
-rw-r--r--test/test-dom-text-scanner.js2
-rw-r--r--test/test-japanese.js2
-rw-r--r--test/test-manifest.js2
-rw-r--r--test/test-object-property-accessor.js2
-rw-r--r--test/test-profile-conditions.js2
-rw-r--r--test/test-schema.js2
-rw-r--r--test/test-text-source-map.js2
-rw-r--r--test/yomichan-test.js49
-rw-r--r--test/yomichan-vm.js194
18 files changed, 93 insertions, 563 deletions
diff --git a/test/dictionary-validate.js b/test/dictionary-validate.js
deleted file mode 100644
index a669a542..00000000
--- a/test/dictionary-validate.js
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * Copyright (C) 2020 Yomichan Authors
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <https://www.gnu.org/licenses/>.
- */
-
-const fs = require('fs');
-const path = require('path');
-const {JSZip} = require('../dev/yomichan-util');
-const {VM} = require('./yomichan-vm');
-
-const vm = new VM();
-vm.execute([
- 'mixed/js/core.js',
- 'mixed/js/cache-map.js',
- 'bg/js/json-schema.js'
-]);
-const JsonSchemaValidator = vm.get('JsonSchemaValidator');
-
-
-function readSchema(relativeFileName) {
- const fileName = path.join(__dirname, relativeFileName);
- const source = fs.readFileSync(fileName, {encoding: 'utf8'});
- return JSON.parse(source);
-}
-
-
-async function validateDictionaryBanks(zip, fileNameFormat, schema) {
- let index = 1;
- while (true) {
- const fileName = fileNameFormat.replace(/\?/, index);
-
- const file = zip.files[fileName];
- if (!file) { break; }
-
- const data = JSON.parse(await file.async('string'));
- new JsonSchemaValidator().validate(data, schema);
-
- ++index;
- }
-}
-
-async function validateDictionary(archive, schemas) {
- const indexFile = archive.files['index.json'];
- if (!indexFile) {
- throw new Error('No dictionary index found in archive');
- }
-
- const index = JSON.parse(await indexFile.async('string'));
- const version = index.format || index.version;
-
- new JsonSchemaValidator().validate(index, schemas.index);
-
- await validateDictionaryBanks(archive, 'term_bank_?.json', version === 1 ? schemas.termBankV1 : schemas.termBankV3);
- await validateDictionaryBanks(archive, 'term_meta_bank_?.json', schemas.termMetaBankV3);
- await validateDictionaryBanks(archive, 'kanji_bank_?.json', version === 1 ? schemas.kanjiBankV1 : schemas.kanjiBankV3);
- await validateDictionaryBanks(archive, 'kanji_meta_bank_?.json', schemas.kanjiMetaBankV3);
- await validateDictionaryBanks(archive, 'tag_bank_?.json', schemas.tagBankV3);
-}
-
-function getSchemas() {
- return {
- index: readSchema('../ext/bg/data/dictionary-index-schema.json'),
- kanjiBankV1: readSchema('../ext/bg/data/dictionary-kanji-bank-v1-schema.json'),
- kanjiBankV3: readSchema('../ext/bg/data/dictionary-kanji-bank-v3-schema.json'),
- kanjiMetaBankV3: readSchema('../ext/bg/data/dictionary-kanji-meta-bank-v3-schema.json'),
- tagBankV3: readSchema('../ext/bg/data/dictionary-tag-bank-v3-schema.json'),
- termBankV1: readSchema('../ext/bg/data/dictionary-term-bank-v1-schema.json'),
- termBankV3: readSchema('../ext/bg/data/dictionary-term-bank-v3-schema.json'),
- termMetaBankV3: readSchema('../ext/bg/data/dictionary-term-meta-bank-v3-schema.json')
- };
-}
-
-
-async function main() {
- const dictionaryFileNames = process.argv.slice(2);
- if (dictionaryFileNames.length === 0) {
- console.log([
- 'Usage:',
- ' node dictionary-validate <dictionary-file-names>...'
- ].join('\n'));
- return;
- }
-
- const schemas = getSchemas();
-
- for (const dictionaryFileName of dictionaryFileNames) {
- try {
- console.log(`Validating ${dictionaryFileName}...`);
- const source = fs.readFileSync(dictionaryFileName);
- const archive = await JSZip.loadAsync(source);
- await validateDictionary(archive, schemas);
- console.log('No issues found');
- } catch (e) {
- console.warn(e);
- }
- }
-}
-
-
-if (require.main === module) { main(); }
-
-
-module.exports = {
- getSchemas,
- validateDictionary
-};
diff --git a/test/lint/global-declarations.js b/test/lint/global-declarations.js
deleted file mode 100644
index 355cb64a..00000000
--- a/test/lint/global-declarations.js
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
- * Copyright (C) 2020 Yomichan Authors
- * Author: Yomichan Authors
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <https://www.gnu.org/licenses/>.
- */
-
-const fs = require('fs');
-const path = require('path');
-const assert = require('assert');
-const {getAllFiles} = require('../../dev/yomichan-util');
-
-
-function countOccurences(string, pattern) {
- return (string.match(pattern) || []).length;
-}
-
-function getNewline(string) {
- const count1 = countOccurences(string, /(?:^|[^\r])\n/g);
- const count2 = countOccurences(string, /\r\n/g);
- const count3 = countOccurences(string, /\r(?:[^\n]|$)/g);
- if (count2 > count1) {
- return (count3 > count2) ? '\r' : '\r\n';
- } else {
- return (count3 > count1) ? '\r' : '\n';
- }
-}
-
-function getSubstringCount(string, substring) {
- let start = 0;
- let count = 0;
- while (true) {
- const pos = string.indexOf(substring, start);
- if (pos < 0) { break; }
- ++count;
- start = pos + substring.length;
- }
- return count;
-}
-
-
-function validateGlobals(fileName, fix) {
- const pattern = /\/\*\s*global\s+([\w\W]*?)\*\//g;
- const trimPattern = /^[\s,*]+|[\s,*]+$/g;
- const splitPattern = /[\s,*]+/;
- const source = fs.readFileSync(fileName, {encoding: 'utf8'});
- let match;
- let first = true;
- let endIndex = 0;
- let newSource = '';
- const allGlobals = [];
- const newline = getNewline(source);
- while ((match = pattern.exec(source)) !== null) {
- if (!first) {
- console.error(`Encountered more than one global declaration in ${fileName}`);
- return false;
- }
- first = false;
-
- const parts = match[1].replace(trimPattern, '').split(splitPattern);
- parts.sort();
-
- const actual = match[0];
- const expected = `/* global${parts.map((v) => `${newline} * ${v}`).join('')}${newline} */`;
-
- try {
- assert.strictEqual(actual, expected);
- } catch (e) {
- console.error(`Global declaration error encountered in ${fileName}:`);
- console.error(e.message);
- if (!fix) {
- return false;
- }
- }
-
- newSource += source.substring(0, match.index);
- newSource += expected;
- endIndex = match.index + match[0].length;
-
- allGlobals.push(...parts);
- }
-
- newSource += source.substring(endIndex);
-
- // This is an approximate check to see if a global variable is unused.
- // If the global appears in a comment, string, or similar, the check will pass.
- let errorCount = 0;
- for (const global of allGlobals) {
- if (getSubstringCount(newSource, global) <= 1) {
- console.error(`Global variable ${global} appears to be unused in ${fileName}`);
- ++errorCount;
- }
- }
-
- if (fix) {
- fs.writeFileSync(fileName, newSource, {encoding: 'utf8'});
- }
-
- return errorCount === 0;
-}
-
-
-function main() {
- const fix = (process.argv.length >= 2 && process.argv[2] === '--fix');
- const directory = path.resolve(__dirname, '..', '..', 'ext');
- const pattern = /\.js$/;
- const ignorePattern = /[\\/]ext[\\/]mixed[\\/]lib[\\/]/;
- const fileNames = getAllFiles(directory, null, (f) => pattern.test(f) && !ignorePattern.test(f));
- for (const fileName of fileNames) {
- if (!validateGlobals(fileName, fix)) {
- process.exit(-1);
- return;
- }
- }
- process.exit(0);
-}
-
-
-if (require.main === module) { main(); }
diff --git a/test/schema-validate.js b/test/schema-validate.js
deleted file mode 100644
index 7b7a21a6..00000000
--- a/test/schema-validate.js
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright (C) 2020 Yomichan Authors
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <https://www.gnu.org/licenses/>.
- */
-
-const fs = require('fs');
-const {VM} = require('./yomichan-vm');
-
-const vm = new VM();
-vm.execute([
- 'mixed/js/core.js',
- 'mixed/js/cache-map.js',
- 'bg/js/json-schema.js'
-]);
-const JsonSchemaValidator = vm.get('JsonSchemaValidator');
-
-
-function main() {
- const args = process.argv.slice(2);
- if (args.length < 2) {
- console.log([
- 'Usage:',
- ' node schema-validate <schema-file-name> <data-file-names>...'
- ].join('\n'));
- return;
- }
-
- const schemaSource = fs.readFileSync(args[0], {encoding: 'utf8'});
- const schema = JSON.parse(schemaSource);
-
- for (const dataFileName of args.slice(1)) {
- try {
- console.log(`Validating ${dataFileName}...`);
- const dataSource = fs.readFileSync(dataFileName, {encoding: 'utf8'});
- const data = JSON.parse(dataSource);
- new JsonSchemaValidator().validate(data, schema);
- console.log('No issues found');
- } catch (e) {
- console.warn(e);
- }
- }
-}
-
-
-if (require.main === module) { main(); }
diff --git a/test/test-all.js b/test/test-all.js
new file mode 100644
index 00000000..71261408
--- /dev/null
+++ b/test/test-all.js
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2020 Yomichan Authors
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+const fs = require('fs');
+const path = require('path');
+const {spawnSync} = require('child_process');
+const {getArgs} = require('../dev/util');
+
+
+function main() {
+ const args = getArgs(process.argv.slice(2), new Map([
+ ['skip', []],
+ [null, []]
+ ]));
+ const directories = args.get(null);
+ const skip = new Set([__filename, ...args.get('skip')].map((value) => path.resolve(value)));
+
+ const node = process.execPath;
+ const fileNamePattern = /\.js$/i;
+
+ let first = true;
+ for (const directory of directories) {
+ const fileNames = fs.readdirSync(directory);
+ for (const fileName of fileNames) {
+ if (!fileNamePattern.test(fileName)) { continue; }
+
+ const fullFileName = path.resolve(path.join(directory, fileName));
+ if (skip.has(fullFileName)) { continue; }
+
+ const stats = fs.lstatSync(fullFileName);
+ if (!stats.isFile()) { continue; }
+
+ process.stdout.write(`${first ? '' : '\n'}Running ${fileName}...\n`);
+ first = false;
+
+ const {error, status} = spawnSync(node, [fileName], {cwd: directory, stdio: 'inherit'});
+
+ if (status !== null && status !== 0) {
+ process.exit(status);
+ return;
+ }
+ if (error) {
+ throw error;
+ }
+ }
+ }
+
+ process.exit(0);
+}
+
+
+if (require.main === module) { main(); }
diff --git a/test/test-cache-map.js b/test/test-cache-map.js
index 00383e65..9307dd2c 100644
--- a/test/test-cache-map.js
+++ b/test/test-cache-map.js
@@ -16,7 +16,7 @@
*/
const assert = require('assert');
-const {VM} = require('./yomichan-vm');
+const {VM} = require('../dev/vm');
const vm = new VM({console});
vm.execute([
diff --git a/test/test-core.js b/test/test-core.js
index d4a880d1..b5c0683f 100644
--- a/test/test-core.js
+++ b/test/test-core.js
@@ -17,7 +17,7 @@
const assert = require('assert');
const crypto = require('crypto');
-const {VM} = require('./yomichan-vm');
+const {VM} = require('../dev/vm');
const vm = new VM({
crypto: {
diff --git a/test/test-database.js b/test/test-database.js
index df152e57..dce89559 100644
--- a/test/test-database.js
+++ b/test/test-database.js
@@ -19,9 +19,8 @@ const fs = require('fs');
const url = require('url');
const path = require('path');
const assert = require('assert');
-const {JSZip} = require('../dev/yomichan-util');
-const {createTestDictionaryArchive} = require('./yomichan-test');
-const {VM} = require('./yomichan-vm');
+const {JSZip, createDictionaryArchive} = require('../dev/util');
+const {VM} = require('../dev/vm');
require('fake-indexeddb/auto');
const chrome = {
@@ -125,6 +124,12 @@ const DictionaryImporter = vm.get('DictionaryImporter');
const DictionaryDatabase = vm.get('DictionaryDatabase');
+function createTestDictionaryArchive(dictionary, dictionaryName) {
+ const dictionaryDirectory = path.join(__dirname, 'data', 'dictionaries', dictionary);
+ return createDictionaryArchive(dictionaryDirectory, dictionaryName);
+}
+
+
function countTermsWithExpression(terms, expression) {
return terms.reduce((i, v) => (i + (v.expression === expression ? 1 : 0)), 0);
}
diff --git a/test/test-dictionary.js b/test/test-dictionary.js
index 2ca0c652..e7db75eb 100644
--- a/test/test-dictionary.js
+++ b/test/test-dictionary.js
@@ -15,8 +15,15 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
-const {createTestDictionaryArchive} = require('./yomichan-test');
-const dictionaryValidate = require('./dictionary-validate');
+const path = require('path');
+const {createDictionaryArchive} = require('../dev/util');
+const dictionaryValidate = require('../dev/dictionary-validate');
+
+
+function createTestDictionaryArchive(dictionary, dictionaryName) {
+ const dictionaryDirectory = path.join(__dirname, 'data', 'dictionaries', dictionary);
+ return createDictionaryArchive(dictionaryDirectory, dictionaryName);
+}
async function main() {
diff --git a/test/test-document-util.js b/test/test-document-util.js
index 4ff380ec..4489bdf1 100644
--- a/test/test-document-util.js
+++ b/test/test-document-util.js
@@ -19,7 +19,7 @@ const fs = require('fs');
const path = require('path');
const assert = require('assert');
const {JSDOM} = require('jsdom');
-const {VM} = require('./yomichan-vm');
+const {VM} = require('../dev/vm');
// DOMRect class definition
diff --git a/test/test-dom-text-scanner.js b/test/test-dom-text-scanner.js
index 7374ff87..b9ff6239 100644
--- a/test/test-dom-text-scanner.js
+++ b/test/test-dom-text-scanner.js
@@ -19,7 +19,7 @@ const fs = require('fs');
const path = require('path');
const assert = require('assert');
const {JSDOM} = require('jsdom');
-const {VM} = require('./yomichan-vm');
+const {VM} = require('../dev/vm');
function createJSDOM(fileName) {
diff --git a/test/test-japanese.js b/test/test-japanese.js
index 39004128..ad3084f1 100644
--- a/test/test-japanese.js
+++ b/test/test-japanese.js
@@ -16,7 +16,7 @@
*/
const assert = require('assert');
-const {VM} = require('./yomichan-vm');
+const {VM} = require('../dev/vm');
const vm = new VM();
vm.execute([
diff --git a/test/test-manifest.js b/test/test-manifest.js
index 07889105..230e6139 100644
--- a/test/test-manifest.js
+++ b/test/test-manifest.js
@@ -18,7 +18,7 @@
const fs = require('fs');
const path = require('path');
const assert = require('assert');
-const {getDefaultManifest, createManifestString} = require('../dev/yomichan-util');
+const {getDefaultManifest, createManifestString} = require('../dev/util');
function loadManifestString() {
diff --git a/test/test-object-property-accessor.js b/test/test-object-property-accessor.js
index 1e694946..42fa3d40 100644
--- a/test/test-object-property-accessor.js
+++ b/test/test-object-property-accessor.js
@@ -16,7 +16,7 @@
*/
const assert = require('assert');
-const {VM} = require('./yomichan-vm');
+const {VM} = require('../dev/vm');
const vm = new VM({});
vm.execute('mixed/js/object-property-accessor.js');
diff --git a/test/test-profile-conditions.js b/test/test-profile-conditions.js
index 23bbdacb..8ef24b5a 100644
--- a/test/test-profile-conditions.js
+++ b/test/test-profile-conditions.js
@@ -16,7 +16,7 @@
*/
const assert = require('assert');
-const {VM} = require('./yomichan-vm');
+const {VM} = require('../dev/vm');
const vm = new VM({});
diff --git a/test/test-schema.js b/test/test-schema.js
index a4a0de2e..a79650d6 100644
--- a/test/test-schema.js
+++ b/test/test-schema.js
@@ -16,7 +16,7 @@
*/
const assert = require('assert');
-const {VM} = require('./yomichan-vm');
+const {VM} = require('../dev/vm');
const vm = new VM();
vm.execute([
diff --git a/test/test-text-source-map.js b/test/test-text-source-map.js
index f092de2c..c9810d19 100644
--- a/test/test-text-source-map.js
+++ b/test/test-text-source-map.js
@@ -16,7 +16,7 @@
*/
const assert = require('assert');
-const {VM} = require('./yomichan-vm');
+const {VM} = require('../dev/vm');
const vm = new VM();
vm.execute(['bg/js/text-source-map.js']);
diff --git a/test/yomichan-test.js b/test/yomichan-test.js
deleted file mode 100644
index af1ea2e3..00000000
--- a/test/yomichan-test.js
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright (C) 2020 Yomichan Authors
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <https://www.gnu.org/licenses/>.
- */
-
-const fs = require('fs');
-const path = require('path');
-
-
-function createTestDictionaryArchive(dictionary, dictionaryName) {
- const dictionaryDirectory = path.join(__dirname, 'data', 'dictionaries', dictionary);
- const fileNames = fs.readdirSync(dictionaryDirectory);
-
- const {JSZip} = require('../dev/yomichan-util');
- const archive = new JSZip();
-
- for (const fileName of fileNames) {
- if (/\.json$/.test(fileName)) {
- const content = fs.readFileSync(path.join(dictionaryDirectory, fileName), {encoding: 'utf8'});
- const json = JSON.parse(content);
- if (fileName === 'index.json' && typeof dictionaryName === 'string') {
- json.title = dictionaryName;
- }
- archive.file(fileName, JSON.stringify(json, null, 0));
- } else {
- const content = fs.readFileSync(path.join(dictionaryDirectory, fileName), {encoding: null});
- archive.file(fileName, content);
- }
- }
-
- return archive;
-}
-
-
-module.exports = {
- createTestDictionaryArchive
-};
diff --git a/test/yomichan-vm.js b/test/yomichan-vm.js
deleted file mode 100644
index 79e92772..00000000
--- a/test/yomichan-vm.js
+++ /dev/null
@@ -1,194 +0,0 @@
-/*
- * Copyright (C) 2020 Yomichan Authors
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <https://www.gnu.org/licenses/>.
- */
-
-const fs = require('fs');
-const vm = require('vm');
-const path = require('path');
-const assert = require('assert');
-
-
-function getContextEnvironmentRecords(context, names) {
- // Enables export of values from the declarative environment record
- if (!Array.isArray(names) || names.length === 0) {
- return [];
- }
-
- let scriptSource = '(() => {\n "use strict";\n const results = [];';
- for (const name of names) {
- scriptSource += `\n try { results.push(${name}); } catch (e) { results.push(void 0); }`;
- }
- scriptSource += '\n return results;\n})();';
-
- const script = new vm.Script(scriptSource, {filename: 'getContextEnvironmentRecords'});
-
- const contextHasNames = Object.prototype.hasOwnProperty.call(context, 'names');
- const contextNames = context.names;
- context.names = names;
-
- const results = script.runInContext(context, {});
-
- if (contextHasNames) {
- context.names = contextNames;
- } else {
- delete context.names;
- }
-
- return Array.from(results);
-}
-
-function isDeepStrictEqual(val1, val2) {
- if (val1 === val2) { return true; }
-
- if (Array.isArray(val1)) {
- if (Array.isArray(val2)) {
- return isArrayDeepStrictEqual(val1, val2);
- }
- } else if (typeof val1 === 'object' && val1 !== null) {
- if (typeof val2 === 'object' && val2 !== null) {
- return isObjectDeepStrictEqual(val1, val2);
- }
- }
-
- return false;
-}
-
-function isArrayDeepStrictEqual(val1, val2) {
- const ii = val1.length;
- if (ii !== val2.length) { return false; }
-
- for (let i = 0; i < ii; ++i) {
- if (!isDeepStrictEqual(val1[i], val2[i])) {
- return false;
- }
- }
-
- return true;
-}
-
-function isObjectDeepStrictEqual(val1, val2) {
- const keys1 = Object.keys(val1);
- const keys2 = Object.keys(val2);
-
- if (keys1.length !== keys2.length) { return false; }
-
- const keySet = new Set(keys1);
- for (const key of keys2) {
- if (!keySet.delete(key)) { return false; }
- }
-
- for (const key of keys1) {
- if (!isDeepStrictEqual(val1[key], val2[key])) {
- return false;
- }
- }
-
- const tag1 = Object.prototype.toString.call(val1);
- const tag2 = Object.prototype.toString.call(val2);
- if (tag1 !== tag2) { return false; }
-
- return true;
-}
-
-function deepStrictEqual(actual, expected) {
- try {
- // This will fail on prototype === comparison on cross context objects
- assert.deepStrictEqual(actual, expected);
- } catch (e) {
- if (!isDeepStrictEqual(actual, expected)) {
- throw e;
- }
- }
-}
-
-
-function createURLClass() {
- const BaseURL = URL;
- return function URL(url) {
- const u = new BaseURL(url);
- this.hash = u.hash;
- this.host = u.host;
- this.hostname = u.hostname;
- this.href = u.href;
- this.origin = u.origin;
- this.password = u.password;
- this.pathname = u.pathname;
- this.port = u.port;
- this.protocol = u.protocol;
- this.search = u.search;
- this.searchParams = u.searchParams;
- this.username = u.username;
- };
-}
-
-
-class VM {
- constructor(context={}) {
- context.URL = createURLClass();
- this._context = vm.createContext(context);
- this._assert = {
- deepStrictEqual
- };
- }
-
- get context() {
- return this._context;
- }
-
- get assert() {
- return this._assert;
- }
-
- get(names) {
- if (typeof names === 'string') {
- return getContextEnvironmentRecords(this._context, [names])[0];
- } else if (Array.isArray(names)) {
- return getContextEnvironmentRecords(this._context, names);
- } else {
- throw new Error('Invalid argument');
- }
- }
-
- set(values) {
- if (typeof values === 'object' && values !== null) {
- Object.assign(this._context, values);
- } else {
- throw new Error('Invalid argument');
- }
- }
-
- execute(fileNames) {
- const single = !Array.isArray(fileNames);
- if (single) {
- fileNames = [fileNames];
- }
-
- const results = [];
- for (const fileName of fileNames) {
- const absoluteFileName = path.resolve(__dirname, '..', 'ext', fileName);
- const source = fs.readFileSync(absoluteFileName, {encoding: 'utf8'});
- const script = new vm.Script(source, {filename: absoluteFileName});
- results.push(script.runInContext(this._context, {}));
- }
-
- return single ? results[0] : results;
- }
-}
-
-
-module.exports = {
- VM
-};