diff options
| -rw-r--r-- | .eslintrc.json | 1 | ||||
| -rw-r--r-- | ext/bg/js/backend.js | 5 | ||||
| -rw-r--r-- | ext/bg/js/json-schema.js | 20 | ||||
| -rw-r--r-- | ext/bg/js/util.js | 20 | ||||
| -rw-r--r-- | ext/mixed/js/core.js | 67 | ||||
| -rw-r--r-- | test/dictionary-validate.js | 5 | ||||
| -rw-r--r-- | test/schema-validate.js | 5 | ||||
| -rw-r--r-- | test/test-schema.js | 5 | 
8 files changed, 88 insertions, 40 deletions
| diff --git a/.eslintrc.json b/.eslintrc.json index b8b7bee8..b7ed0164 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -99,6 +99,7 @@                  "getSetDifference": "readonly",                  "escapeRegExp": "readonly",                  "deferPromise": "readonly", +                "clone": "readonly",                  "EventDispatcher": "readonly",                  "EventListenerCollection": "readonly",                  "EXTENSION_IS_BROWSER_EDGE": "readonly" diff --git a/ext/bg/js/backend.js b/ext/bg/js/backend.js index 344706d1..59a3de45 100644 --- a/ext/bg/js/backend.js +++ b/ext/bg/js/backend.js @@ -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)});              } diff --git a/ext/bg/js/json-schema.js b/ext/bg/js/json-schema.js index f62402f9..2e009a7a 100644 --- a/ext/bg/js/json-schema.js +++ b/ext/bg/js/json-schema.js @@ -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);      }  } diff --git a/ext/bg/js/util.js b/ext/bg/js/util.js index edc19c6e..fa31b0d8 100644 --- a/ext/bg/js/util.js +++ b/ext/bg/js/util.js @@ -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) { diff --git a/ext/mixed/js/core.js b/ext/mixed/js/core.js index 21b7bf5e..9b3ea3e2 100644 --- a/ext/mixed/js/core.js +++ b/ext/mixed/js/core.js @@ -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 diff --git a/test/dictionary-validate.js b/test/dictionary-validate.js index f1730852..446de38d 100644 --- a/test/dictionary-validate.js +++ b/test/dictionary-validate.js @@ -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'); diff --git a/test/schema-validate.js b/test/schema-validate.js index 761f0a1c..4c01fa70 100644 --- a/test/schema-validate.js +++ b/test/schema-validate.js @@ -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'); diff --git a/test/test-schema.js b/test/test-schema.js index 7620ab16..f0a99c3b 100644 --- a/test/test-schema.js +++ b/test/test-schema.js @@ -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'); |