Clone function (#624)

* Add clone function

* Replace utilIsolate with clone

* Replace JsonSchema.isolate with clone function

* Include core.js for tests which use json-schema.js

* Update visisted set
This commit is contained in:
toasted-nutbread 2020-06-28 12:38:34 -04:00 committed by GitHub
parent 5bf805755a
commit cdf191336a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 88 additions and 40 deletions

View File

@ -99,6 +99,7 @@
"getSetDifference": "readonly",
"escapeRegExp": "readonly",
"deferPromise": "readonly",
"clone": "readonly",
"EventDispatcher": "readonly",
"EventListenerCollection": "readonly",
"EXTENSION_IS_BROWSER_EDGE": "readonly"

View File

@ -38,7 +38,6 @@
* profileConditionsDescriptorPromise
* requestJson
* requestText
* utilIsolate
*/
class Backend {
@ -875,7 +874,7 @@ class Backend {
for (const target of targets) {
try {
const result = this._modifySetting(target);
results.push({result: utilIsolate(result)});
results.push({result: clone(result)});
} catch (e) {
results.push({error: errorToJson(e)});
}
@ -889,7 +888,7 @@ class Backend {
for (const target of targets) {
try {
const result = this._getSetting(target);
results.push({result: utilIsolate(result)});
results.push({result: clone(result)});
} catch (e) {
results.push({error: errorToJson(e)});
}

View File

@ -90,7 +90,7 @@ class JsonSchemaProxyHandler {
throw new Error(`Property ${property} not supported`);
}
value = JsonSchema.isolate(value);
value = JsonSchema.clone(value);
JsonSchemaProxyHandler.validate(value, propertySchema, new JsonSchemaTraversalInfo(value, propertySchema));
@ -515,7 +515,7 @@ class JsonSchemaProxyHandler {
const schemaDefault = schema.default;
if (typeof schemaDefault !== 'undefined') {
value = JsonSchema.isolate(schemaDefault);
value = JsonSchema.clone(schemaDefault);
type = JsonSchemaProxyHandler.getValueType(value);
assignDefault = !JsonSchemaProxyHandler.isValueTypeAny(value, type, schemaType);
}
@ -628,19 +628,7 @@ class JsonSchema {
return JsonSchemaProxyHandler.getValidValueOrDefault(schema, value);
}
static isolate(value) {
if (value === null) { return null; }
switch (typeof value) {
case 'boolean':
case 'number':
case 'string':
case 'bigint':
case 'symbol':
return value;
}
const stringValue = JSON.stringify(value);
return typeof stringValue === 'string' ? JSON.parse(stringValue) : null;
static clone(value) {
return clone(value);
}
}

View File

@ -15,26 +15,10 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
function utilIsolate(value) {
if (value === null) { return null; }
switch (typeof value) {
case 'boolean':
case 'number':
case 'string':
case 'bigint':
case 'symbol':
return value;
}
const stringValue = JSON.stringify(value);
return typeof stringValue === 'string' ? JSON.parse(stringValue) : null;
}
function utilFunctionIsolate(func) {
return function isolatedFunction(...args) {
try {
args = args.map((v) => utilIsolate(v));
args = args.map((v) => clone(v));
return func.call(this, ...args);
} catch (e) {
try {
@ -50,7 +34,7 @@ function utilFunctionIsolate(func) {
function utilBackgroundIsolate(data) {
const backgroundPage = chrome.extension.getBackgroundPage();
return backgroundPage.utilIsolate(data);
return backgroundPage.clone(data);
}
function utilBackgroundFunctionIsolate(func) {

View File

@ -157,6 +157,73 @@ function getSetDifference(set1, set2) {
);
}
const clone = (() => {
// eslint-disable-next-line no-shadow
function clone(value) {
if (value === null) { return null; }
switch (typeof value) {
case 'boolean':
case 'number':
case 'string':
case 'bigint':
case 'symbol':
case 'undefined':
return value;
default:
return cloneInternal(value, new Set());
}
}
function cloneInternal(value, visited) {
if (value === null) { return null; }
switch (typeof value) {
case 'boolean':
case 'number':
case 'string':
case 'bigint':
case 'symbol':
case 'undefined':
return value;
case 'function':
return cloneObject(value, visited);
case 'object':
return Array.isArray(value) ? cloneArray(value, visited) : cloneObject(value, visited);
}
}
function cloneArray(value, visited) {
if (visited.has(value)) { throw new Error('Circular'); }
try {
visited.add(value);
const result = [];
for (const item of value) {
result.push(cloneInternal(item, visited));
}
return result;
} finally {
visited.delete(value);
}
}
function cloneObject(value, visited) {
if (visited.has(value)) { throw new Error('Circular'); }
try {
visited.add(value);
const result = {};
for (const key in value) {
if (Object.prototype.hasOwnProperty.call(value, key)) {
result[key] = cloneInternal(value[key], visited);
}
}
return result;
} finally {
visited.delete(value);
}
}
return clone;
})();
/*
* Async utilities

View File

@ -21,7 +21,10 @@ const {JSZip} = require('./yomichan-test');
const {VM} = require('./yomichan-vm');
const vm = new VM();
vm.execute('bg/js/json-schema.js');
vm.execute([
'mixed/js/core.js',
'bg/js/json-schema.js'
]);
const JsonSchema = vm.get('JsonSchema');

View File

@ -19,7 +19,10 @@ const fs = require('fs');
const {VM} = require('./yomichan-vm');
const vm = new VM();
vm.execute('bg/js/json-schema.js');
vm.execute([
'mixed/js/core.js',
'bg/js/json-schema.js'
]);
const JsonSchema = vm.get('JsonSchema');

View File

@ -19,7 +19,10 @@ const assert = require('assert');
const {VM} = require('./yomichan-vm');
const vm = new VM();
vm.execute('bg/js/json-schema.js');
vm.execute([
'mixed/js/core.js',
'bg/js/json-schema.js'
]);
const JsonSchema = vm.get('JsonSchema');