diff options
author | toasted-nutbread <toasted-nutbread@users.noreply.github.com> | 2021-02-13 22:52:28 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-02-13 22:52:28 -0500 |
commit | 6a271e067fa917614f4c81f473533e24c6d04404 (patch) | |
tree | 0d81658b1c03aecfbba133425aefc0ea7612338c /ext/mixed/js/object-property-accessor.js | |
parent | deed5027cd18bcdb9cb9d13cb7831be0ec5384e8 (diff) |
Move mixed/js (#1383)
* Move mixed/js/core.js to js/core.js
* Move mixed/js/yomichan.js to js/yomichan.js
* Move mixed/js/timer.js to js/debug/timer.js
* Move mixed/js/hotkey-handler.js to js/input/hotkey-handler.js
* Move mixed/js/hotkey-help-controller.js to js/input/hotkey-help-controller.js
* Move mixed/js/hotkey-util.js to js/input/hotkey-util.js
* Move mixed/js/audio-system.js to js/input/audio-system.js
* Move mixed/js/media-loader.js to js/input/media-loader.js
* Move mixed/js/text-to-speech-audio.js to js/input/text-to-speech-audio.js
* Move mixed/js/comm.js to js/comm/cross-frame-api.js
* Move mixed/js/api.js to js/comm/api.js
* Move mixed/js/frame-client.js to js/comm/frame-client.js
* Move mixed/js/frame-endpoint.js to js/comm/frame-endpoint.js
* Move mixed/js/display.js to js/display/display.js
* Move mixed/js/display-audio.js to js/display/display-audio.js
* Move mixed/js/display-generator.js to js/display/display-generator.js
* Move mixed/js/display-history.js to js/display/display-history.js
* Move mixed/js/display-notification.js to js/display/display-notification.js
* Move mixed/js/display-profile-selection.js to js/display/display-profile-selection.js
* Move mixed/js/japanese.js to js/language/japanese-util.js
* Move mixed/js/dictionary-data-util.js to js/language/dictionary-data-util.js
* Move mixed/js/document-focus-controller.js to js/dom/document-focus-controller.js
* Move mixed/js/document-util.js to js/dom/document-util.js
* Move mixed/js/dom-data-binder.js to js/dom/dom-data-binder.js
* Move mixed/js/html-template-collection.js to js/dom/html-template-collection.js
* Move mixed/js/panel-element.js to js/dom/panel-element.js
* Move mixed/js/popup-menu.js to js/dom/popup-menu.js
* Move mixed/js/selector-observer.js to js/dom/selector-observer.js
* Move mixed/js/scroll.js to js/dom/window-scroll.js
* Move mixed/js/text-scanner.js to js/language/text-scanner.js
* Move mixed/js/cache-map.js to js/general/cache-map.js
* Move mixed/js/object-property-accessor.js to js/general/object-property-accessor.js
* Move mixed/js/task-accumulator.js to js/general/task-accumulator.js
* Move mixed/js/environment.js to js/background/environment.js
* Move mixed/js/dynamic-loader.js to js/scripting/dynamic-loader.js
* Move mixed/js/dynamic-loader-sentinel.js to js/scripting/dynamic-loader-sentinel.js
Diffstat (limited to 'ext/mixed/js/object-property-accessor.js')
-rw-r--r-- | ext/mixed/js/object-property-accessor.js | 342 |
1 files changed, 0 insertions, 342 deletions
diff --git a/ext/mixed/js/object-property-accessor.js b/ext/mixed/js/object-property-accessor.js deleted file mode 100644 index 95773029..00000000 --- a/ext/mixed/js/object-property-accessor.js +++ /dev/null @@ -1,342 +0,0 @@ -/* - * Copyright (C) 2016-2021 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/>. - */ - -/** - * Class used to get and mutate generic properties of an object by using path strings. - */ -class ObjectPropertyAccessor { - /** - * Create a new accessor for a specific object. - * @param target The object which the getter and mutation methods are applied to. - * @returns A new ObjectPropertyAccessor instance. - */ - constructor(target) { - this._target = target; - } - - /** - * Gets the value at the specified path. - * @param pathArray The path to the property on the target object. - * @param pathLength How many parts of the pathArray to use. - * This parameter is optional and defaults to the length of pathArray. - * @returns The value found at the path. - * @throws An error is thrown if pathArray is not valid for the target object. - */ - get(pathArray, pathLength) { - let target = this._target; - const ii = typeof pathLength === 'number' ? Math.min(pathArray.length, pathLength) : pathArray.length; - for (let i = 0; i < ii; ++i) { - const key = pathArray[i]; - if (!ObjectPropertyAccessor.hasProperty(target, key)) { - throw new Error(`Invalid path: ${ObjectPropertyAccessor.getPathString(pathArray.slice(0, i + 1))}`); - } - target = target[key]; - } - return target; - } - - /** - * Sets the value at the specified path. - * @param pathArray The path to the property on the target object. - * @param value The value to assign to the property. - * @throws An error is thrown if pathArray is not valid for the target object. - */ - set(pathArray, value) { - const ii = pathArray.length - 1; - if (ii < 0) { throw new Error('Invalid path'); } - - const target = this.get(pathArray, ii); - const key = pathArray[ii]; - if (!ObjectPropertyAccessor.isValidPropertyType(target, key)) { - throw new Error(`Invalid path: ${ObjectPropertyAccessor.getPathString(pathArray)}`); - } - - target[key] = value; - } - - /** - * Deletes the property of the target object at the specified path. - * @param pathArray The path to the property on the target object. - * @throws An error is thrown if pathArray is not valid for the target object. - */ - delete(pathArray) { - const ii = pathArray.length - 1; - if (ii < 0) { throw new Error('Invalid path'); } - - const target = this.get(pathArray, ii); - const key = pathArray[ii]; - if (!ObjectPropertyAccessor.isValidPropertyType(target, key)) { - throw new Error(`Invalid path: ${ObjectPropertyAccessor.getPathString(pathArray)}`); - } - - if (Array.isArray(target)) { - throw new Error('Invalid type'); - } - - delete target[key]; - } - - /** - * Swaps two properties of an object or array. - * @param pathArray1 The path to the first property on the target object. - * @param pathArray2 The path to the second property on the target object. - * @throws An error is thrown if pathArray1 or pathArray2 is not valid for the target object, - * or if the swap cannot be performed. - */ - swap(pathArray1, pathArray2) { - const ii1 = pathArray1.length - 1; - if (ii1 < 0) { throw new Error('Invalid path 1'); } - const target1 = this.get(pathArray1, ii1); - const key1 = pathArray1[ii1]; - if (!ObjectPropertyAccessor.isValidPropertyType(target1, key1)) { throw new Error(`Invalid path 1: ${ObjectPropertyAccessor.getPathString(pathArray1)}`); } - - const ii2 = pathArray2.length - 1; - if (ii2 < 0) { throw new Error('Invalid path 2'); } - const target2 = this.get(pathArray2, ii2); - const key2 = pathArray2[ii2]; - if (!ObjectPropertyAccessor.isValidPropertyType(target2, key2)) { throw new Error(`Invalid path 2: ${ObjectPropertyAccessor.getPathString(pathArray2)}`); } - - const value1 = target1[key1]; - const value2 = target2[key2]; - - target1[key1] = value2; - try { - target2[key2] = value1; - } catch (e) { - // Revert - try { - target1[key1] = value1; - } catch (e2) { - // NOP - } - throw e; - } - } - - /** - * Converts a path string to a path array. - * @param pathArray The path array to convert. - * @returns A string representation of pathArray. - */ - static getPathString(pathArray) { - const regexShort = /^[a-zA-Z_][a-zA-Z0-9_]*$/; - let pathString = ''; - let first = true; - for (let part of pathArray) { - switch (typeof part) { - case 'number': - if (Math.floor(part) !== part || part < 0) { - throw new Error('Invalid index'); - } - part = `[${part}]`; - break; - case 'string': - if (!regexShort.test(part)) { - const escapedPart = part.replace(/["\\]/g, '\\$&'); - part = `["${escapedPart}"]`; - } else { - if (!first) { - part = `.${part}`; - } - } - break; - default: - throw new Error(`Invalid type: ${typeof part}`); - } - pathString += part; - first = false; - } - return pathString; - } - - /** - * Converts a path array to a path string. For the most part, the format of this string - * matches Javascript's notation for property access. - * @param pathString The path string to convert. - * @returns An array representation of pathString. - */ - static getPathArray(pathString) { - const pathArray = []; - let state = 'empty'; - let quote = 0; - let value = ''; - let escaped = false; - for (const c of pathString) { - const v = c.codePointAt(0); - switch (state) { - case 'empty': // Empty - case 'id-start': // Expecting identifier start - if (v === 0x5b) { // '[' - if (state === 'id-start') { - throw new Error(`Unexpected character: ${c}`); - } - state = 'open-bracket'; - } else if ( - (v >= 0x41 && v <= 0x5a) || // ['A', 'Z'] - (v >= 0x61 && v <= 0x7a) || // ['a', 'z'] - v === 0x5f // '_' - ) { - state = 'id'; - value += c; - } else { - throw new Error(`Unexpected character: ${c}`); - } - break; - case 'id': // Identifier - if ( - (v >= 0x41 && v <= 0x5a) || // ['A', 'Z'] - (v >= 0x61 && v <= 0x7a) || // ['a', 'z'] - (v >= 0x30 && v <= 0x39) || // ['0', '9'] - v === 0x5f // '_' - ) { - value += c; - } else if (v === 0x5b) { // '[' - pathArray.push(value); - value = ''; - state = 'open-bracket'; - } else if (v === 0x2e) { // '.' - pathArray.push(value); - value = ''; - state = 'id-start'; - } else { - throw new Error(`Unexpected character: ${c}`); - } - break; - case 'open-bracket': // Open bracket - if (v === 0x22 || v === 0x27) { // '"' or '\'' - quote = v; - state = 'string'; - } else if (v >= 0x30 && v <= 0x39) { // ['0', '9'] - state = 'number'; - value += c; - } else { - throw new Error(`Unexpected character: ${c}`); - } - break; - case 'string': // Quoted string - if (escaped) { - value += c; - escaped = false; - } else if (v === 0x5c) { // '\\' - escaped = true; - } else if (v !== quote) { - value += c; - } else { - state = 'close-bracket'; - } - break; - case 'number': // Number - if (v >= 0x30 && v <= 0x39) { // ['0', '9'] - value += c; - } else if (v === 0x5d) { // ']' - pathArray.push(Number.parseInt(value, 10)); - value = ''; - state = 'next'; - } else { - throw new Error(`Unexpected character: ${c}`); - } - break; - case 'close-bracket': // Expecting closing bracket after quoted string - if (v === 0x5d) { // ']' - pathArray.push(value); - value = ''; - state = 'next'; - } else { - throw new Error(`Unexpected character: ${c}`); - } - break; - case 'next': // Expecting . or [ - if (v === 0x5b) { // '[' - state = 'open-bracket'; - } else if (v === 0x2e) { // '.' - state = 'id-start'; - } else { - throw new Error(`Unexpected character: ${c}`); - } - break; - } - } - switch (state) { - case 'empty': - case 'next': - break; - case 'id': - pathArray.push(value); - value = ''; - break; - default: - throw new Error('Path not terminated correctly'); - } - return pathArray; - } - - /** - * Checks whether an object or array has the specified property. - * @param object The object to test. - * @param property The property to check for existence. - * This value should be a string if the object is a non-array object. - * For arrays, it should be an integer. - * @returns true if the property exists, otherwise false. - */ - static hasProperty(object, property) { - switch (typeof property) { - case 'string': - return ( - typeof object === 'object' && - object !== null && - !Array.isArray(object) && - Object.prototype.hasOwnProperty.call(object, property) - ); - case 'number': - return ( - Array.isArray(object) && - property >= 0 && - property < object.length && - property === Math.floor(property) - ); - default: - return false; - } - } - - /** - * Checks whether a property is valid for the given object - * @param object The object to test. - * @param property The property to check for existence. - * @returns true if the property is correct for the given object type, otherwise false. - * For arrays, this means that the property should be a positive integer. - * For non-array objects, the property should be a string. - */ - static isValidPropertyType(object, property) { - switch (typeof property) { - case 'string': - return ( - typeof object === 'object' && - object !== null && - !Array.isArray(object) - ); - case 'number': - return ( - Array.isArray(object) && - property >= 0 && - property === Math.floor(property) - ); - default: - return false; - } - } -} |