|
{"version":3,"file":"lib-wrapper.js","sources":["src/errors/libWrapper-errors.js","src/libWrapper-consts.js","src/shared/libWrapper-enums.js","src/shared/libWrapper-polyfill.js","src/shared/libWrapper-log.js","src/shared/libWrapper-i18n.js","src/shared/libWrapper-package_info.js","src/utils/libWrapper-misc.js","src/errors/libWrapper-error-utils.js","src/errors/libWrapper-base_errors.js","src/utils/libWrapper-settings.js","src/ui/libWrapper-notifications.js","src/ui/libWrapper-stats.js","src/ui/libWrapper-conflicts.js","src/errors/libWrapper-api_errors.js","src/errors/listeners.js","src/shared/libWrapper-version.js","src/lib/libWrapper-enums.js","src/lib/libWrapper-storage.js","src/lib/libWrapper-wrapper.js","src/ui/libWrapper-settings.js","src/lib/libWrapper-api.js"],"sourcesContent":["// SPDX-License-Identifier: LGPL-3.0-or-later\n// Copyright © 2021 fvtt-lib-wrapper Rui Pinheiro\n\n'use strict';\n\n// Object that contains the error classes that libWrapper should use.\n// This is used to avoid cyclic dependencies, and is what should be imported by files outside the 'errors' folder.\nexport const ERRORS = {\n base : Error,\n internal : Error,\n package : Error,\n already_overridden: Error,\n invalid_chain : Error\n};\nObject.seal(ERRORS);","// SPDX-License-Identifier: LGPL-3.0-or-later\n// Copyright © 2021 fvtt-lib-wrapper Rui Pinheiro\n\n'use strict';\n\n\n//*********************\n// Package information\nexport const PACKAGE_ID = 'lib-wrapper';\nexport const PACKAGE_TITLE = 'libWrapper';\nexport const HOOKS_SCOPE = 'libWrapper';\n\n\n//*********************\n// Miscellaneous definitions\n\n// This allows rollup to strip out all unit-test code from the release artifact\n/*#if _ROLLUP\n\texport const IS_UNITTEST = false;\n//#else */\n\texport const IS_UNITTEST = (typeof Game === 'undefined');\n//#endif\n\nexport const PROPERTIES_CONFIGURABLE = IS_UNITTEST ? true : false;","// SPDX-License-Identifier: LGPL-3.0-or-later\n// Copyright © 2021 fvtt-shared-library Rui Pinheiro\n\n'use strict';\n\n\nimport {PACKAGE_TITLE} from '../consts.js';\n\n\n// Enumeration Value factory\nexport const EnumValue = function(enum_cls, name, value, sort=true) {\n\t// Sanity check for a frozen object\n\tif(Object.isFrozen(enum_cls))\n\t\tthrow new Error(`${PACKAGE_TITLE}: Enum '${enum_cls.name}' is frozen.`);\n\n\t// Validate name\n\tif(name !== name.toUpperCase())\n\t\tthrow new Error(`${PACKAGE_TITLE}: Enum keys must be all uppercase.`);\n\n\t// We use an eval here to coerce the browser to display more readable console output\n\tconst value_cls = Function(\"x\", `return class ${name} extends x {}`)(enum_cls.value_cls);\n\tconst value_obj = new value_cls();\n\n\tif(value_obj.name != name)\n\t\tthrow new Error(`${PACKAGE_TITLE}: Incorrect value_obj name ${value_obj.name}. Expected ${name}.`);\n\n\t// If we were provided a value, add it\n\tif(value !== undefined)\n\t\tvalue_obj.value = value;\n\n\t// We always freeze the temporary value class we just created\n\tObject.freeze(value_obj);\n\tObject.freeze(value_obj.prototype);\n\tObject.freeze(value_obj.constructor);\n\tObject.freeze(value_obj.constructor.prototype);\n\n\t// Store instance into enum\n\tif(name in enum_cls)\n\t\tthrow new Error(`${PACKAGE_TITLE}: Name '${name}' is already present in ${enum_cls.name}.`);\n\tenum_cls[name] = value_obj;\n\n\t// Store value->object mapping too, if a value was provided\n\tif(value !== undefined) {\n\t\tif(enum_cls.reverse.has(value))\n\t\t\tthrow new Error(`${PACKAGE_TITLE}: Value '${value}' is already present in ${enum_cls.name}.`);\n\t\tenum_cls.reverse.set(value, value_obj);\n\t}\n\n\t// Store key into list of keys - no need to check for duplicates\n\tenum_cls.list.push(value_obj);\n\tif(sort)\n\t\tenum_cls.sort_list_by_value();\n\n\t// Done\n\treturn value_obj;\n}\n\n\n\n// Enumeration factory\nexport const Enum = function(name, collection, freeze=true) {\n\tlet value_cls;\n\n\t// Validate name\n\tif(typeof name !== \"string\")\n\t\tthrow new Error(`${PACKAGE_TITLE}: Enum name must be a string`);\n\n\t// Validate collection\n\tif(typeof collection !== \"object\")\n\t\tthrow new Error(`${PACKAGE_TITLE}: Enum collection must be a dictionary or an array`);\n\n\tconst has_value = !(collection instanceof Array);\n\n\t// Enum class\n\tconst enum_name = `${name}Enum`;\n\tconst enum_cls = {\n\t\t[enum_name]: class {\n\t\t\tconstructor(value, dflt=undefined) {\n\t\t\t\treturn this.constructor.get(value, dflt);\n\t\t\t}\n\n\t\t\tstatic get(value, dflt=undefined) {\n\t\t\t\t// If passing an enum value object directly, just return it\n\t\t\t\tif(value instanceof value_cls)\n\t\t\t\t\treturn value;\n\n\t\t\t\t// If passing a key, return the corresponding object\n\t\t\t\tif(typeof value === \"string\") {\n\t\t\t\t\tconst res = this[value.toUpperCase()];\n\t\t\t\t\tif(res)\n\t\t\t\t\t\treturn res;\n\t\t\t\t}\n\n\t\t\t\t// If we got something else, this might be the actual enum \"value\" field\n\t\t\t\t{\n\t\t\t\t\t// Check the reverse map\n\t\t\t\t\tlet reverse = this.reverse.get(value);\n\n\t\t\t\t\t// Also try casting to int, since values are often numbers\n\t\t\t\t\tif(reverse === undefined && typeof value === 'string') {\n\t\t\t\t\t\tconst value_int = parseInt(value);\n\t\t\t\t\t\tif(Number.isInteger(value_int))\n\t\t\t\t\t\t\treverse = this.reverse.get(value_int);\n\t\t\t\t\t}\n\n\t\t\t\t\t// Return the enum value if we found it\n\t\t\t\t\tif(reverse !== undefined)\n\t\t\t\t\t\treturn reverse;\n\t\t\t\t}\n\n\t\t\t\t// Fail or return default value\n\t\t\t\tif(dflt === undefined)\n\t\t\t\t\tthrow new Error(`${PACKAGE_TITLE}: '${value}' is not a valid key or value for the enum ${name}.`);\n\n\t\t\t\treturn dflt;\n\t\t\t}\n\n\t\t\tstatic has(value) {\n\t\t\t\treturn (value instanceof value_cls);\n\t\t\t}\n\n\t\t\tstatic toString() {\n\t\t\t\treturn this.name;\n\t\t\t}\n\n\t\t\tstatic get value_cls() {\n\t\t\t\treturn value_cls;\n\t\t\t}\n\n\t\t\tstatic sort_list_by_value() {\n\t\t\t\treturn this.list.sort(function(a,b){\n\t\t\t\t\treturn (a.value ?? 0) - (b.value ?? 0);\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}[enum_name];\n\n\t// Value Class\n\t// Note: We need to use an eval here in order to coerce the browser to have the correct class name... Other tricks don't work.\n\tconst value_cls_name = `${name}Value`;\n\tvalue_cls = {\n\t\t[value_cls_name]: class {\n\t\t\tstatic toString() {\n\t\t\t\treturn value_cls_name;\n\t\t\t}\n\n\t\t\tget name() {\n\t\t\t\treturn this.constructor.name;\n\t\t\t}\n\n\t\t\tget enum() {\n\t\t\t\treturn enum_cls;\n\t\t\t}\n\n\t\t\ttoString() {\n\t\t\t\treturn this.name;\n\t\t\t}\n\n\t\t\tget lower() {\n\t\t\t\treturn this.name.toLowerCase();\n\t\t\t}\n\t\t}\n\t}[value_cls_name];\n\n\t// We always freeze the value class\n\tObject.freeze(value_cls);\n\tObject.freeze(value_cls.prototype);\n\n\t// Extra Enum Class members\n\tenum_cls.list = [];\n\n\tif(has_value)\n\t\tenum_cls.reverse = new Map();\n\n\t// Construct enum values\n\tif(collection instanceof Array) {\n\t\tfor(const key of collection) {\n\t\t\tEnumValue(enum_cls, key, undefined, /*sort=*/false);\n\t\t}\n\t}\n\telse {\n\t\tfor(const key in collection) {\n\t\t\tEnumValue(enum_cls, key, collection[key], /*sort=*/false);\n\t\t}\n\t}\n\n\tenum_cls.sort_list_by_value();\n\n\t// Freeze everything\n\tif(freeze) {\n\t\tObject.freeze(enum_cls);\n\t\tObject.freeze(enum_cls.prototype);\n\t\tObject.freeze(enum_cls.list);\n\n\t\tif(has_value)\n\t\t\tObject.freeze(enum_cls.reverse);\n\t}\n\n\t// Done\n\treturn enum_cls;\n}","// SPDX-License-Identifier: LGPL-3.0-or-later\n// Copyright © 2021 fvtt-shared-library Rui Pinheiro\n\n'use strict';\n\nimport { ERRORS } from '../errors/errors.js';\n\n\n// game.user.data polyfill, so it can be used before 'ready'\nexport const game_user_data = function(return_null=false) {\n\t// Try game.user.data first\n\tconst orig_game_user_data = globalThis.game?.user?.data;\n\tif(orig_game_user_data)\n\t\treturn orig_game_user_data;\n\n\t// Grab the user ID\n\tconst userid = globalThis.game?.userId ?? globalThis.game?.data?.userId;\n\tif(!userid) {\n\t\tif(return_null)\n\t\t\treturn null;\n\t\tthrow new ERRORS.internal(\"Unable to obtain the current user ID\");\n\t}\n\n\t// Find user in game.data.users\n\tconst user_data = globalThis.game?.data?.users?.find((x) => { return x._id == userid });\n\tif(!user_data) {\n\t\tif(return_null)\n\t\t\treturn null;\n\t\tthrow new ERRORS.internal(\"Unable to obtain the current user data object\");\n\t}\n\n\t// Done\n\treturn user_data;\n}\n\n// game.user.can polyfill, so it can be used before 'ready'\nexport const game_user_can = function(action, return_null=false) {\n\t// Try game.user.can first\n\tconst orig_game_user_can = globalThis.game?.user?.can;\n\tif(orig_game_user_can)\n\t\treturn orig_game_user_can.call(game.user, action);\n\n\t// Obtain game.user.data\n\tconst user_data = game_user_data(return_null);\n\tif(!user_data)\n\t\treturn null;\n\n\t// Check if user is GM\n\tif(user_data.role === 4)\n\t\treturn true;\n\n\t// Check if the action is in the per-user permissions\n\tif(action in user_data.permissions) return user_data.permissions[action];\n\n\t// Otherwise, check the role's permissions\n\tconst game_permissions_str = globalThis.game?.data?.settings?.find((x) => { return x.key === 'core.permissions'});\n\tif(game_permissions_str?.value) {\n\t\tconst game_permissions = JSON.parse(game_permissions_str.value);\n\n\t\tconst rolePerms = game_permissions[action];\n\t\tif(rolePerms && rolePerms.includes(user_data.role))\n\t\t\treturn true;\n\t}\n\n\treturn false;\n}\n\n// game.user.isGM polyfill, so it can be used before 'ready'\nexport const game_user_isGM = function(return_null=false) {\n\t// Try game.user.isGM first\n\tconst orig_game_user_isGM = globalThis.game?.user?.isGM;\n\tif(orig_game_user_isGM !== undefined)\n\t\treturn orig_game_user_isGM;\n\n\t// Obtain game.user.data\n\tconst user_data = game_user_data(return_null);\n\tif(!user_data)\n\t\treturn null;\n\n\t// Done\n\treturn user_data.role === 4;\n}\n\n// Polyfill to get the Foundry version\nexport const game_release_display = function(return_null=true) {\n\tconst display =\n\t\tglobalThis.game?.release?.display ??\n\t\tglobalThis.game?.version ??\n\t\tglobalThis.game?.data?.version ??\n\t\tnull\n\t;\n\n\tif(!return_null && display === null)\n\t\tthrow new ERRORS.internal(\"Unable to obtain the Foundry display version\");\n\n\treturn display;\n}\n\nexport const game_version = function(return_null=true) {\n\tconst version =\n\t\tglobalThis.game?.version ??\n\t\tglobalThis.game?.release?.version ??\n\t\tglobalThis.game?.data?.version ??\n\t\tnull\n\t;\n\n\tif(!return_null && version === null)\n\t\tthrow new ERRORS.internal(\"Unable to obtain the Foundry version\");\n\n\treturn version;\n}\n\n\n// Polyfill to get module settings (allows accessing settings before 'init' if they are client-scoped)\nexport const game_settings_get = function(namespace, key, always_fallback=false, return_null=true) {\n\t// Try game.settings.get first\n\ttry {\n\t\tconst orig_game_settings_get = globalThis.game?.settings?.get;\n\t\tif(orig_game_settings_get)\n\t\t\treturn orig_game_settings_get.call(game.settings, namespace, key);\n\t}\n\tcatch(e) {\n\t\tif(!always_fallback)\n\t\t\tthrow e;\n\t}\n\n\t// Access localStorage to get the client-scoped version of the setting\n\tconst storage_key = `${namespace}.${key}`;\n\n\ttry {\n\t\tconst data = globalThis.localStorage?.[storage_key];\n\t\tif(data === undefined || data === null) {\n\t\t\tif(return_null)\n\t\t\t\treturn null;\n\t\t\tthrow new ERRORS.internal(`Unable to obtain the setting '${storage_key}'`);\n\t\t}\n\n\t\t// Parse the localStorage data the same way as Core does\n\t\tconst json_data = JSON.parse(data)\n\t\tif(json_data === undefined || json_data === null) {\n\t\t\tif(return_null)\n\t\t\t\treturn null;\n\t\t\tthrow new ERRORS.internal(`Unable to obtain the setting '${storage_key}'`);\n\t\t}\n\n\t\t// Done\n\t\treturn json_data;\n\t}\n\tcatch(e) {\n\t\tif(return_null)\n\t\t\treturn null;\n\t\tthrow new ERRORS.internal(`Unable to obtain the setting '${storage_key}' due to exception in polyfill:`, e);\n\t}\n}","// SPDX-License-Identifier: LGPL-3.0-or-later\n// Copyright © 2021 fvtt-shared-library Rui Pinheiro\n\n'use strict';\n\nimport { PACKAGE_ID, PACKAGE_TITLE } from \"../consts.js\";\nimport { Enum } from './enums.js';\nimport { game_settings_get } from \"./polyfill.js\";\nimport { ERRORS } from '../errors/errors.js';\n\n\n//*********************\n// Constants\nexport const VERBOSITY = Enum('PackageType', {\n\t\"ZERO\" : 0,\n\t\"TRACE\" : 100,\n\t\"DEBUG\" : 200,\n\t\"INFO\" : 300,\n\t\"WARNING\" : 400,\n\t\"ERROR\" : 500,\n\t\"CRITICAL\": Number.MAX_SAFE_INTEGER - 1,\n\t\"ALWAYS\" : Number.MAX_SAFE_INTEGER\n});\n\nconst VERBOSITY_ALIASES_MAP = {\n\t\"NEVER\": VERBOSITY.ZERO,\n\t\"ALL\" : VERBOSITY.ZERO,\n\t\"WARN\" : VERBOSITY.WARNING\n}\n\nconst VERBOSITY_CONSOLEFN_MAP = {\n\t[VERBOSITY.ZERO .value]: [console, 'debug'],\n\t[VERBOSITY.TRACE .value]: [console, 'debug'],\n\t[VERBOSITY.DEBUG .value]: [console, 'debug'],\n\t[VERBOSITY.INFO .value]: [console, 'info' ],\n\t[VERBOSITY.WARNING .value]: [console, 'warn' ],\n\t[VERBOSITY.ERROR .value]: [console, 'error'],\n\t[VERBOSITY.CRITICAL.value]: [console, 'error'],\n\t[VERBOSITY.ALWAYS .value]: [console, 'info' ]\n};\n\nconst LOG_ALIASES_VERBOSITY_MAP = {\n\tnever : VERBOSITY.ZERO,\n\ttrace : VERBOSITY.TRACE,\n\tdebug : VERBOSITY.DEBUG,\n\tinfo : VERBOSITY.INFO,\n\twarning : VERBOSITY.WARNING,\n\twarn : VERBOSITY.WARNING,\n\terror : VERBOSITY.ERROR,\n\tcritical: VERBOSITY.CRITICAL,\n\talways : VERBOSITY.ALWAYS\n};\n\n\nconst LOG_PREFIX = `${PACKAGE_TITLE}:`;\nconst LOG_PREFIX_VERBOSITY_MAP = {\n\t[VERBOSITY.ZERO .value]: `[0] ${LOG_PREFIX}`,\n\t[VERBOSITY.TRACE .value]: `[T] ${LOG_PREFIX}`,\n\t[VERBOSITY.DEBUG .value]: `[D] ${LOG_PREFIX}`,\n\t[VERBOSITY.INFO .value]: `[I] ${LOG_PREFIX}`,\n\t[VERBOSITY.WARNING .value]: `[W] ${LOG_PREFIX}`,\n\t[VERBOSITY.ERROR .value]: `[E] ${LOG_PREFIX}`,\n\t[VERBOSITY.CRITICAL.value]: `[!] ${LOG_PREFIX}`,\n\t[VERBOSITY.ALWAYS .value]: LOG_PREFIX\n};\n\n\n//*********************\n// Variables\n\n// Current verbosity. Setting it to 'null' or 'undefined' results in the default verbosity value being used.\nlet CURRENT_VERBOSITY = null;\n\n\n//*********************\n// Utility functions\nexport const verbosity_to_value = function(verbosity) {\n\t// If no verbosity is provided, we default to a value of 0 (i.e. VERBOSITY.NEVER)\n\tif(verbosity === null || verbosity === undefined)\n\t\treturn 0;\n\n\t// Otherwise, return value or verbosity\n\treturn verbosity.value ?? verbosity;\n}\n\nexport const verbosity_to_mapped_value = function(verbosity, map, dflt) {\n\tconst value = verbosity_to_value(verbosity);\n\n\t// If the value is in the map, just use it\n\t{\n\t\tconst result = map[value];\n\t\tif(result)\n\t\t\treturn result;\n\t}\n\n\t// Use the nearest verbosity\n\tfor(const v of VERBOSITY.list) {\n\t\tif(value > v.value)\n\t\t\tcontinue;\n\n\t\treturn map[v.value];\n\t}\n\n\t// Default\n\treturn dflt;\n}\n\nfunction verbosity_to_log_function(verbosity) {\n\treturn verbosity_to_mapped_value(verbosity, VERBOSITY_CONSOLEFN_MAP, [console, 'log']);\n}\n\nfunction verbosity_to_log_prefix(verbosity, suffix) {\n\treturn verbosity_to_mapped_value(verbosity, LOG_PREFIX_VERBOSITY_MAP, LOG_PREFIX);\n}\n\nfunction generate_verbosity_aliases() {\n\tfor(const verbosity of VERBOSITY.list) {\n\t\tLog[verbosity.name] = verbosity;\n\t}\n\n\tfor(const alias in VERBOSITY_ALIASES_MAP) {\n\t\tLog[alias] = VERBOSITY_ALIASES_MAP[alias];\n\t}\n}\n\nfunction generate_enabled_aliases() {\n\tfor(const alias in LOG_ALIASES_VERBOSITY_MAP) {\n\t\tconst verbosity = LOG_ALIASES_VERBOSITY_MAP[alias];\n\n\t\tObject.defineProperty(Log, `has_${alias}`, {\n\t\t\tget: Log.enabled.bind(Log, verbosity),\n\t\t\tconfigurable: false\n\t\t});\n\t}\n}\n\nfunction generate_log_aliases() {\n\t// Generic log aliases\n\tfor(const alias in LOG_ALIASES_VERBOSITY_MAP) {\n\t\tconst verbosity = LOG_ALIASES_VERBOSITY_MAP[alias];\n\n\t\tconst fn = Log.fn(verbosity);\n\n\t\t// Default logging function, logs or does nothing depending on enabled verbosity\n\t\tLog[alias ] = fn ?? (()=>{});\n\n\t\t// $-suffixed logging functions allow using optional chaining '?.' to easily skip evaluating\n\t\t// the function arguments (e.g. skip building the log message)\n\t\t// if the function would otherwise do nothing because of verbosity\n\t\tLog[`${alias}$`] = fn;\n\t}\n\n\t// Stack trace helper\n\tLog.stack = (console.trace && Log.has_trace) ? console.trace.bind(console) : (()=>{});\n}\n\n\n\n//*********************\n// Logging helper class\nexport class Log {\n\t/*\n\t * Attributes\n\t */\n\tstatic get verbosity() {\n\t\t// Note: This default value is only used until LibWrapperSettings.init\n\t\treturn CURRENT_VERBOSITY ?? VERBOSITY.WARNING;\n\t}\n\n\tstatic set verbosity(in_value) {\n\t\t// Convert to VERBOSITY type if it exists\n\t\tconst value = VERBOSITY.get(in_value, /*default=*/ parseInt(in_value));\n\n\t\t// Sanity check types\n\t\tif(!VERBOSITY.has(value) && !Number.isInteger(value))\n\t\t\tthrow new ERRORS.internal(`Parameter 'value' must be a 'VERBOSITY' enum value or an integer, but got '${in_value}'.`);\n\n\t\t// Store verbosity\n\t\tCURRENT_VERBOSITY = value;\n\n\t\t// We generate the logging methods statically any time the verbosity changes in order to:\n\t\t// 1. Log with the highest performance possible (no need to dynamically check verbosity)\n\t\t// 2. Not affect the log file/line from the caller that is shown in the JS console\n\t\tgenerate_log_aliases();\n\t}\n\n\tstatic get verbosity_value() {\n\t\treturn verbosity_to_value(this.verbosity);\n\t}\n\n\tstatic get verbosities() {\n\t\treturn VERBOSITY;\n\t}\n\n\n\t/*\n\t * Utility Methods\n\t */\n\tstatic init(force=false) {\n\t\t// We do nothing if the verbosity is already set, unless forced\n\t\tif(!force && CURRENT_VERBOSITY !== undefined && CURRENT_VERBOSITY !== null)\n\t\t\treturn;\n\n\t\t// Grab verbosity from settings\n\t\tconst value = game_settings_get(PACKAGE_ID, 'log-verbosity', /*always_fallback=*/ true, /*return_null=*/ true);\n\n\t\t// We do nothing if the setting is null/undefined\n\t\tif(value === undefined || value === null)\n\t\t\treturn;\n\n\t\t// Use try-catch in case something goes wrong, as this method runs in critical code paths...\n\t\ttry {\n\t\t\tthis.verbosity = value;\n\t\t}\n\t\tcatch(e) {\n\t\t\tconsole.error(`${PACKAGE_TITLE}: Unable to set logging verbosity.\\n`, e);\n\t\t}\n\t}\n\n\tstatic enabled(verbosity=null) {\n\t\tconst desired_value = verbosity_to_value(verbosity);\n\t\tconst current_value = this.verbosity_value;\n\n\t\treturn (desired_value >= current_value);\n\t}\n\n\n\t/*\n\t * Logging\n\t */\n\n\t/* Returns a function to log at a given verbosity, or 'null' if the given verbosity is not enabled.\n\t * You should use the optional chaining operator '?.' when calling the result.\n\t * Can specify a different verbosity to use when calculating the underlying logging function, as well as a custom prefix\n\t *\n\t * Usage Examples:\n\t *\n\t * - 'DEBUG' message:\n\t * Log.fn(Log.DEBUG)?.(\"Some message\");\n\t *\n\t * - 'ALWAYS' message using the underlying logging function for 'INFO' messages:\n\t * Log.fn(Log.ALWAYS, Log.INFO)?.(\"Another message\");\n\t */\n\tstatic fn(verbosity, fn_verbosity=verbosity) {\n\t\tif(!this.enabled(verbosity))\n\t\t\treturn null;\n\n\t\tconst [obj, nm] = verbosity_to_log_function(fn_verbosity);\n\t\tconst prefix = verbosity_to_log_prefix(verbosity);\n\t\treturn obj[nm].bind(obj, prefix);\n\t}\n\n\t/*\n\t * Dynamic logging function. Verbosity check happens at call-time.\n\t */\n\tstatic log(verbosity, ...args) {\n\t\treturn this.fn(verbosity)?.(...args);\n\t}\n}\n\n// Generate static aliases\ngenerate_verbosity_aliases();\ngenerate_enabled_aliases();\ngenerate_log_aliases();\n\n// Initialise\nLog.init(/*force=*/ true);\n\n// Seal Log class\nObject.seal(Log);","// SPDX-License-Identifier: LGPL-3.0-or-later\n// Copyright © 2021 fvtt-shared-library Rui Pinheiro\n\n'use strict';\n\nimport { IS_UNITTEST, PACKAGE_ID } from \"../consts.js\";\nimport { game_settings_get } from \"./polyfill.js\";\nimport { Log } from \"./log.js\";\n\n\n// We want to load the EN language by default, in order to use it for polyfill while i18n hasn't loaded yet\n// The import/fetch below will allow Rollup, with rollup-plugin-json and rollup-plugin-jscc, to directly include the JSON contents into the build artifact\n// but also still allow libWrapper to work fine without the rollup step.\n\n/*#if _ROLLUP\n\timport en_json from '../../lang/en.json';\n\tconst i18nLangs = $_I18N_LANGS;\n\tconst langBaseUrl = (!import.meta?.url?.endsWith(`dist/${PACKAGE_ID}.js`)) ? './lang' : '../lang';\n//#else */\n\tconst langBaseUrl = '../../lang';\n\tlet en_json;\n\tif(IS_UNITTEST) {\n\t\t// Use readFileSync, supported by node\n\t\tconst fs = await import('fs');\n\t\tconst en_file = fs.readFileSync('lang/en.json'); // readFileSync does not use a relative path\n\t\ten_json = JSON.parse(en_file);\n\t}\n\telse {\n\t\t// Use fetch - supported by browsers\n\t\tconst request = await fetch(new URL(`${langBaseUrl}/en.json`, import.meta.url));\n\t\ten_json = await request.json();\n\t}\n//#endif\n\n\n// Polyfill game.i18n until libWrapper initialises\nexport class i18n {\n\t/*\n\t * Initialisation\n\t */\n\tstatic async _fetch(lang) {\n\t\t/*#if _ROLLUP\n\t\t\t// Avoid unnecessary requests if we know they're just going to 404\n\t\t\tif(Array.isArray(i18nLangs) && !i18nLangs.includes(lang))\n\t\t\t\treturn null;\n\t\t//#endif */\n\n\t\t// Fetch language JSONs, if any\n\t\ttry {\n\t\t\tconst url = new URL(`${langBaseUrl}/${lang}.json`, import.meta.url);\n\n\t\t\tconst request = await fetch(url);\n\t\t\tif(request.status !== 200 || !request.ok)\n\t\t\t\treturn null;\n\n\t\t\treturn request.json();\n\t\t}\n\t\tcatch(e) {\n\t\t\tLog.warn$?.(`Failed to load or parse ${url.href}.`, e);\n\t\t\treturn null;\n\t\t}\n\t}\n\n\tstatic async init() {\n\t\t// Default members\n\t\tthis.jsons = [];\n\n\t\t// Load languages\n\t\tconst langs = [];\n\n\t\ttry {\n\t\t\t// client-scoped setting, but we do this before game.settings has initialised so have to grab it manually\n\t\t\tconst clientLanguage = game_settings_get('core', 'language', /*always_fallback=*/ true, /*return_null=*/ false);\n\t\t\tif(clientLanguage && clientLanguage !== 'en')\n\t\t\t\tlangs.push(clientLanguage);\n\t\t}\n\t\tcatch(e) {\n\t\t\tLog.debug$?.(`Could not find or parse client language settings.`);\n\t\t}\n\n\t\tconst serverLanguage = game?.i18n?.lang;\n\t\tif(serverLanguage && serverLanguage !== 'en')\n\t\t\tlangs.push(serverLanguage);\n\n\t\t// Fetch language JSONs\n\t\tif(langs.length > 0) {\n\t\t\t// Await all fetches\n\t\t\tconst results = await Promise.all(langs.map((x)=>this._fetch(x)));\n\n\t\t\t// Store the valid results in this.jsons\n\t\t\tfor(const json of results) {\n\t\t\t\tif(json)\n\t\t\t\t\tthis.jsons.push(json);\n\t\t\t}\n\t\t}\n\t}\n\n\tstatic on_ready() {\n\t\t// Allow garbage collection of JSONs\n\t\tdelete this.jsons;\n\n\t\t//#if !_ROLLUP\n\t\t\ten_json = undefined;\n\t\t//#endif\n\t}\n\n\n\t/*\n\t * Polyfill\n\t */\n\tstatic localize(key) {\n\t\t// Try real i18n library\n\t\tif(game?.i18n) {\n\t\t\tconst res = game.i18n.localize(key);\n\t\t\tif(res !== key)\n\t\t\t\treturn res;\n\t\t}\n\n\t\t// Fallback to polyfill\n\t\ttry {\n\t\t\tconst split = key.split('.');\n\n\t\t\t// Try main language first\n\t\t\tif(this.jsons) {\n\t\t\t\tfor(const json of this.jsons) {\n\t\t\t\t\tconst res = split.reduce((x,y) => x?.[y], json);\n\t\t\t\t\tif(res)\n\t\t\t\t\t\treturn res;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Default to just returning the key\n\t\t\treturn split.reduce((x,y) => x?.[y], en_json) ?? key;\n\t\t}\n\t\tcatch(e) {\n\t\t\tLog.error(e);\n\t\t\treturn key;\n\t\t}\n\t}\n\n\tstatic format(key, args) {\n\t\t// Try real i18n library\n\t\tif(game?.i18n) {\n\t\t\tconst res = game.i18n.format(key, args);\n\t\t\tif(res !== key)\n\t\t\t\treturn res;\n\t\t}\n\n\t\t// Fallback to polyfill\n\t\tconst localize = this.localize(key);\n\t\tif(localize === key)\n\t\t\treturn localize;\n\n\t\ttry {\n\t\t\treturn localize.replace(/\\{(.*?)\\}/g, (_,y) => args?.[y]);\n\t\t}\n\t\tcatch(e) {\n\t\t\tLog.error(e);\n\t\t\treturn key;\n\t\t}\n\t}\n}\n\n// Set up a hook to cleanup once we are no longer a polyfill\nif(!IS_UNITTEST)\n\tHooks.once('ready', i18n.on_ready.bind(i18n));","// SPDX-License-Identifier: LGPL-3.0-or-later\n// Copyright © 2021 fvtt-shared-library Rui Pinheiro\n\n'use strict';\n\nimport {PACKAGE_ID, PACKAGE_TITLE} from '../consts.js';\nimport {Enum} from './enums.js';\nimport {i18n} from './i18n.js';\nimport {Log} from './log.js';\nimport {game_version} from './polyfill.js';\n\n\n//*********************\n// ID types\nexport const PACKAGE_TYPES = Enum('PackageType', [\n\t\"UNKNOWN\",\n\t\"MODULE\",\n\t\"SYSTEM\",\n\t\"WORLD\"\n]);\n\n\n//*********************\n// Constants\nconst KEY_SEPARATOR = ':';\nconst UNKNOWN_ID = '\\u00ABunknown\\u00BB';\nconst PACKAGE_ID_REGEX = new RegExp(\"^[a-z0-9_-]+$\", \"i\");\nconst STACK_TRACE_REGEX = /^.*?\\/(worlds|systems|modules)\\/(.+?)(?=\\/).*?$/igm;\n\n// A package ID string, or an array of package ID strings, that should be ignored when automatically detecting the package ID based on a stack trace.\n// Not set as a constant, so that a default value can be set by the user\nexport let IGNORE_PACKAGE_IDS = PACKAGE_ID;\n\n\n//*********************\n// Utility methods\n\n/**\n * @returns {boolean} Returns 'false' if aborted early (because of 'matchFn' returning 'false'), 'true' if executed to completion.\n */\nconst foreach_package_in_stack_trace = function(matchFn, stack_trace, ignore_ids) {\n\t// If supplied, stack_trace must be a string\n\tif(stack_trace !== undefined) {\n\t\tif(typeof stack_trace !== 'string')\n\t\t\tthrow new Error(`${PACKAGE_TITLE}: Parameter 'stack_trace' must be a string, got ${typeof stack_trace}.`);\n\t}\n\t// Collect stack trace if none passed\n\telse {\n\t\tconst old_stack_limit = Error.stackTraceLimit;\n\n\t\ttry {\n\t\t\tError.stackTraceLimit = Infinity;\n\t\t\tstack_trace = Error().stack;\n\t\t}\n\t\tfinally {\n\t\t\tError.stackTraceLimit = old_stack_limit;\n\t\t}\n\n\t\t// Simply exit if not a string\n\t\tif(typeof stack_trace !== 'string')\n\t\t\treturn true;\n\t}\n\n\t// If the stack trace is empty, just exit\n\tif(!stack_trace)\n\t\treturn true;\n\n\t// Apply regex onto stack trace\n\tconst matches = stack_trace.matchAll(STACK_TRACE_REGEX);\n\tif(!matches)\n\t\treturn true;\n\n\t// Find matches\n\tfor(const match of matches) {\n\t\tconst type = match[1];\n\t\tconst name = match[2];\n\n\t\tif(!type || !name)\n\t\t\tcontinue;\n\n\t\t// Check for match\n\t\tlet match_id, match_type;\n\n\t\tif(type === 'worlds') {\n\t\t\tconst game_world_id = globalThis.game?.data?.world?.id;\n\t\t\tif(game_world_id && name != game_world_id)\n\t\t\t\tcontinue;\n\n\t\t\tmatch_id = name;\n\t\t\tmatch_type = PACKAGE_TYPES.WORLD;\n\t\t}\n\t\telse if(type === 'systems') {\n\t\t\tconst game_system_id = globalThis.game?.data?.system?.id;\n\t\t\tif(game_system_id && name != game_system_id)\n\t\t\t\tcontinue;\n\n\t\t\tmatch_id = name;\n\t\t\tmatch_type = PACKAGE_TYPES.SYSTEM;\n\t\t}\n\t\telse if(type === 'modules') {\n\t\t\tif(globalThis.game?.modules && !globalThis.game.modules.has(name))\n\t\t\t\tcontinue;\n\n\t\t\tif(ignore_ids && (name === ignore_ids || ignore_ids?.includes?.(name)))\n\t\t\t\tcontinue;\n\n\t\t\tmatch_id = name;\n\t\t\tmatch_type = PACKAGE_TYPES.MODULE;\n\t\t}\n\t\telse {\n\t\t\tthrow new Error(`${PACKAGE_TITLE}: Invalid script type: ${type}`);\n\t\t}\n\n\t\t// On match, call matchFn, and return if it returns 'false'\n\t\tconst matchRes = matchFn(match_id, match_type, match[0]);\n\t\tif(matchRes === false)\n\t\t\treturn false;\n\t}\n\n\t// Done\n\treturn true;\n}\n\n\n//*********************\n// Package info class\n// Stores package information. Able to auto-detect the package ID that is calling libWrapper.\nexport class PackageInfo {\n\t/*\n\t * Static methods\n\t */\n\tstatic get UNKNOWN() {\n\t\treturn new PackageInfo(UNKNOWN_ID, PACKAGE_TYPES.UNKNOWN);\n\t};\n\n\tstatic collect_all(stack_trace=undefined, include_fn=undefined, ignore_ids=undefined) {\n\t\t// Collect a set of all packages in the stack trace\n\t\tconst set = new Set();\n\n\t\tforeach_package_in_stack_trace((id, type, match) => {\n\t\t\tconst key = `${type.lower}${KEY_SEPARATOR}${id}`; // see 'get key' below\n\n\t\t\tif(set.has(key))\n\t\t\t\treturn true;\n\n\t\t\tif(include_fn !== undefined && !include_fn(id, type, match))\n\t\t\t\t\treturn true;\n\n\t\t\tset.add(key);\n\t\t\treturn true;\n\t\t}, stack_trace, ignore_ids);\n\n\t\t// Convert the set into an array of PackageInfo objects\n\t\tconst modules = [];\n\n\t\tfor(const key of set)\n\t\t\tmodules.push(new PackageInfo(key));\n\n\t\t// Done\n\t\treturn modules;\n\t}\n\n\tstatic is_valid_key_or_id(key_or_id) {\n\t\treturn this.is_valid_key(key_or_id) || this.is_valid_id(key_or_id);\n\t}\n\n\tstatic is_valid_key(key) {\n\t\tif(!key || typeof key !== 'string')\n\t\t\treturn false;\n\n\t\tconst [id, type] = this.parse_key(key);\n\t\tif(!id || !type)\n\t\t\treturn false;\n\n\t\tif(!this.is_valid_id(id))\n\t\t\treturn false;\n\n\t\treturn true;\n\t}\n\n\tstatic is_valid_id(id) {\n\t\tif(!id || typeof id !== 'string')\n\t\t\treturn false;\n\n\t\tif(!PACKAGE_ID_REGEX.test(id))\n\t\t\treturn false;\n\n\t\treturn true;\n\t}\n\n\tstatic parse_key(key) {\n\t\tconst split = key.split(KEY_SEPARATOR);\n\t\tif(split.length !== 2)\n\t\t\treturn [null, null];\n\n\t\tconst id = split[1];\n\t\tconst type = PACKAGE_TYPES.get(split[0]);\n\n\t\treturn [id, type];\n\t}\n\n\n\n\t/*\n\t * Constructor\n\t */\n\tconstructor(id=null, type=null) {\n\t\tthis.set(id, type);\n\t}\n\n\n\t/*\n\t * Member methods\n\t */\n\tset(id=null, type=null, freeze=true) {\n\t\t// Auto-detect the ID\n\t\tif(!id)\n\t\t\treturn this.detect_id();\n\n\t\t// Sanity check the ID\n\t\tif(typeof id !== 'string')\n\t\t\tthrow new Error(`${PACKAGE_TITLE}: PackageInfo IDs must be strings`);\n\n\t\t// Handle unknown package\n\t\tif(id === UNKNOWN_ID) {\n\t\t\tthis.set_unknown();\n\t\t\treturn;\n\t\t}\n\n\t\t// If we need to auto-detect the type, and find a key separator, we should parse the ID as a key instead\n\t\tif(type === null) {\n\t\t\tif(this.from_key(id, /*fail=*/false))\n\t\t\t\treturn; // from_key returning 'true' means that it succeeded and has called set(id, type) successfuly\n\t\t}\n\n\t\t// Validate ID (if we got this far, 'id' must be an ID, and not a key)\n\t\tif(!this.constructor.is_valid_id(id))\n\t\t\tthrow new Error(`${PACKAGE_TITLE}: Invalid package ID '${id}'`);\n\n\t\t// Validate type\n\t\tif(type !== null && !PACKAGE_TYPES.has(type))\n\t\t\tthrow new Error(`${PACKAGE_TITLE}: Package type for '${id}' must belong to the PACKAGE_TYPES enum, but got '${type}'.`);\n\n\t\t// Store in instance\n\t\tthis.id = id;\n\t\tthis.type = type;\n\n\t\t// Detect type automatically, if necessary\n\t\tif(!type)\n\t\t\tthis.detect_type();\n\n\t\t// Freeze if requested\n\t\tif(freeze)\n\t\t\tObject.freeze(this);\n\t}\n\n\tset_unknown() {\n\t\tthis.id = UNKNOWN_ID;\n\t\tthis.type = PACKAGE_TYPES.UNKNOWN;\n\t}\n\n\tequals(obj) {\n\t\treturn obj && (obj.constructor === this.constructor) && (obj.id === this.id) && (obj.type === this.type);\n\t}\n\n\tdetect_id(stack_trace=undefined) {\n\t\tthis.set_unknown();\n\n\t\tforeach_package_in_stack_trace((id, type) => {\n\t\t\tthis.set(id, type);\n\t\t\treturn false; // stop on first match\n\t\t}, stack_trace, IGNORE_PACKAGE_IDS);\n\t}\n\n\tdetect_type() {\n\t\t// We need to support this even when 'game.modules' hasn't been initialised yet\n\t\tif(!globalThis.game?.modules) {\n\t\t\tif(this.id === PACKAGE_ID)\n\t\t\t\tthis.type = PACKAGE_TYPES.MODULE;\n\t\t\telse\n\t\t\t\tthis.type = PACKAGE_TYPES.UNKNOWN;\n\n\t\t\treturn;\n\t\t}\n\n\t\tif(globalThis.game.modules?.get(this.id)?.active)\n\t\t\tthis.type = PACKAGE_TYPES.MODULE;\n\t\telse if(this.id === globalThis.game.data?.system?.id)\n\t\t\tthis.type = PACKAGE_TYPES.SYSTEM;\n\t\telse if(this.id === globalThis.game.data?.world?.id)\n\t\t\tthis.type = PACKAGE_TYPES.WORLD;\n\t\telse\n\t\t\tthis.type = PACKAGE_TYPES.UNKNOWN;\n\t}\n\n\n\t// Conversion to/from key\n\tfrom_key(key, fail=true) {\n\t\tconst [id, type] = this.constructor.parse_key(key);\n\n\t\tif(!id || !type) {\n\t\t\tif(fail)\n\t\t\t\tthrow new Error(`${PACKAGE_TITLE}: Invalid key '${key}'`);\n\t\t\treturn false;\n\t\t}\n\n\t\tthis.set(id, type);\n\t\treturn true;\n\t}\n\n\n\t// Cast to string\n\ttoString() {\n\t\treturn this.key;\n\t}\n\n\n\t/*\n\t * Attributes\n\t */\n\tget known() {\n\t\treturn this.type != PACKAGE_TYPES.UNKNOWN;\n\t}\n\n\tget exists() {\n\t\tswitch(this.type) {\n\t\t\tcase PACKAGE_TYPES.MODULE:\n\t\t\t\treturn globalThis.game?.modules?.get(this.id)?.active;\n\t\t\tcase PACKAGE_TYPES.SYSTEM:\n\t\t\t\treturn globalThis.game?.data?.system?.id === this.id;\n\t\t\tcase PACKAGE_TYPES.WORLD:\n\t\t\t\treturn globalThis.game?.data?.world?.id === this.id;\n\t\t\tdefault:\n\t\t\t\treturn false;\n\t\t}\n\t}\n\n\tget data() {\n\t\tif(!this.exists)\n\t\t\treturn null;\n\n\t\tconst fvtt_gen = globalThis.game?.release?.generation;\n\t\tconst v10_or_newer = (fvtt_gen && fvtt_gen >= 10);\n\n\t\tswitch(this.type) {\n\t\t\tcase PACKAGE_TYPES.MODULE:\n\t\t\t\treturn v10_or_newer ? globalThis.game?.modules?.get(this.id) : globalThis.game?.modules?.get(this.id)?.data;\n\t\t\tcase PACKAGE_TYPES.SYSTEM:\n\t\t\t\treturn v10_or_newer ? globalThis.game?.data?.system : globalThis.game?.data?.system?.data;\n\t\t\tcase PACKAGE_TYPES.WORLD:\n\t\t\t\treturn globalThis.game?.data?.world;\n\t\t\tdefault:\n\t\t\t\treturn null;\n\t\t}\n\t}\n\n\tstatic get unknown_title() {\n\t\treturn i18n.localize(`${PACKAGE_ID}.packages.unknown-title`)\n\t}\n\n\tget title() {\n\t\tif(!this.exists)\n\t\t\treturn this.constructor.unknown_title;\n\n\t\tswitch(this.type) {\n\t\t\tcase PACKAGE_TYPES.MODULE:\n\t\t\tcase PACKAGE_TYPES.SYSTEM:\n\t\t\tcase PACKAGE_TYPES.WORLD :\n\t\t\t\treturn this.data.title;\n\t\t\tdefault:\n\t\t\t\treturn this.constructor.unknown_title;\n\t\t}\n\t}\n\n\tget key() {\n\t\treturn `${this.type.lower}${KEY_SEPARATOR}${this.id}`;\n\t}\n\n\tget type_i18n() {\n\t\treturn i18n.localize(`${PACKAGE_ID}.packages.types.${this.type.lower}`);\n\t}\n\n\tget type_plus_id() {\n\t\treturn `${this.type.lower} ${this.id}`;\n\t}\n\n\tget type_plus_id_capitalized() {\n\t\tlet str = this.type_plus_id;\n\t\treturn str.charAt(0).toUpperCase() + str.slice(1);\n\t}\n\n\tget type_plus_id_i18n() {\n\t\treturn i18n.format(`${PACKAGE_ID}.packages.type-plus-id`, {type: this.type_i18n, id: this.id});\n\t}\n\n\tget type_plus_title() {\n\t\treturn `${this.type.lower} ${this.title}`;\n\t}\n\n\tget type_plus_title_i18n() {\n\t\treturn i18n.format(`${PACKAGE_ID}.packages.type-plus-title`, {type: this.type_i18n, title: this.title});\n\t}\n\n\tget logId() {\n\t\treturn (this.type == PACKAGE_TYPES.MODULE) ? this.id : this.key;\n\t}\n\n\tget settingsName() {\n\t\tswitch(this.type) {\n\t\t\tcase PACKAGE_TYPES.MODULE:\n\t\t\t\treturn this.id;\n\t\t\tcase PACKAGE_TYPES.SYSTEM:\n\t\t\t\treturn `${this.id} [System]`;\n\t\t\tcase PACKAGE_TYPES.WORLD:\n\t\t\t\treturn `${this.id} [World]`;\n\t\t\tdefault:\n\t\t\t\treturn this.id;\n\t\t}\n\t}\n\n\tget url() {\n\t\treturn this.data?.url;\n\t}\n\n\tget bugs() {\n\t\treturn this.data?.bugs;\n\t}\n\n\tget version() {\n\t\treturn this.data?.version;\n\t}\n\n\tget core_version_range() {\n\t\tconst data = this.data;\n\t\tif(!data)\n\t\t\treturn null;\n\n\t\t// FVTT v10 and newer\n\t\tif(data.compatibility)\n\t\t\treturn [data.compatibility.minimum, data.compatibility.verified, data.compatibility.maximum];\n\n\t\t// FVTT v9 and older\n\t\treturn [data.minimumCoreVersion, data.compatibleCoreVersion, null];\n\t}\n\n\tget compatible_with_core() {\n\t\tconst versions = this.core_version_range;\n\t\tconst fvtt_version = game_version(/*return_null=*/ true);\n\t\tconst fvtt_major = fvtt_version?.split('.')[0];\n\n\t\tif(!versions || !fvtt_version || !fvtt_major)\n\t\t\treturn true; // assume it is compatible if we aren't sure\n\n\t\t// Check if the core version is between the minimum and maximum version\n\t\tconst [min, verif, max] = versions;\n\n\t\t// Minimum version\n\t\tif(min) {\n\t\t\tconst fvtt_min = min.includes('.') ? fvtt_version : fvtt_major;\n\t\t\tif(min !== fvtt_min && !isNewerVersion(fvtt_min, min))\n\t\t\t\treturn false;\n\t\t}\n\n\t\t// Verified version\n\t\tif(verif) {\n\t\t\tconst fvtt_verif = verif.includes('.') ? fvtt_version : fvtt_major;\n\t\t\tif(isNewerVersion(fvtt_verif, verif))\n\t\t\t\treturn false;\n\t\t}\n\n\t\t// Maximum version\n\t\tif(max) {\n\t\t\tconst fvtt_max = max.includes('.') ? fvtt_version : fvtt_major;\n\t\t\tif(fvtt_max == max || isNewerVersion(fvtt_max, max))\n\t\t\t\treturn false;\n\t\t}\n\n\t\t// Done\n\t\treturn true;\n\t}\n}\nObject.freeze(PackageInfo);","// SPDX-License-Identifier: LGPL-3.0-or-later\n// Copyright © 2021 fvtt-lib-wrapper Rui Pinheiro\n\n'use strict';\n\nimport { IS_UNITTEST } from '../consts.js';\nimport { ERRORS } from '../errors/errors.js';\n\n\n// HACK: The browser doesn't expose all global variables (e.g. 'Game') inside globalThis, but it does to an eval\n// We declare this helper here so that the eval does not have access to the anonymous function scope\nexport const global_eval = eval;\n\nexport function get_global_variable(varname) {\n\ttry {\n\t\treturn globalThis[varname] ?? global_eval(varname);\n\t}\n\tcatch (e) {\n\t\treturn undefined;\n\t}\n}\n\n\n// Change the name of a function object\n// Note: This is extremely hacky, and only works in some browsers, and only sometimes (usually when a function is anonymous)\nexport function set_function_name(fn, name) {\n\ttry {\n\t\t// Only supported by Firefox: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/displayName\n\t\tfn.displayName = name;\n\n\t\t// Hack: Try and over-ride the 'name' property\n\t\tObject.defineProperty(fn, 'name', {\n\t\t\tvalue: name,\n\t\t\twritable: false,\n\t\t\tenumerable: false,\n\t\t\tconfigurable: true\n\t\t});\n\t}\n\tcatch (e) {\n\t\t// disregard unless this is a unit test - probably unsupported by browser\n\t\tif(IS_UNITTEST)\n\t\t\tthrow e;\n\t}\n}\n\n// Decorate name\nexport function decorate_name(name, suffix='') {\n\tif(suffix !== '')\n\t\treturn `🎁${name}#${suffix}`;\n\telse\n\t\treturn `🎁${name}`;\n}\n\n// Decorate the name of all functions of a given class\n// Note: This is extremely hacky, and only works in some browsers, and only sometimes (usually when a function is anonymous)\nexport function decorate_class_function_names(klass) {\n\tconst props = Object.getOwnPropertyNames(klass);\n\tprops.push(...Object.getOwnPropertySymbols(klass))\n\n\tfor(const prop of props) {\n\t\tconst descriptor = Object.getOwnPropertyDescriptor(klass, prop);\n\n\t\tif(typeof descriptor.value === 'function')\n\t\t\tset_function_name(descriptor.value, decorate_name(prop));\n\t\tif(typeof descriptor.get === 'function')\n\t\t\tset_function_name(descriptor.get, decorate_name(prop, 'getter'));\n\t\tif(typeof descriptor.set === 'function')\n\t\t\tset_function_name(descriptor.set, decorate_name(prop, 'setter'));\n\t}\n\n\tif(klass.prototype)\n\t\tdecorate_class_function_names(klass.prototype);\n}\n\n\n// Get an unsecure hash of a string, mimics Java's String.hashCode\nexport const hash_string = function(str) {\n\tif(typeof str !== 'string')\n\t\tthrow ERRORS.internal(\"Parameter 'str' must be a string.\");\n\n\tconst length = str.length;\n\n let hash = 0;\n for (let i = 0; i < length; i++) {\n const char = str.charCodeAt(i);\n hash = ((hash << 5) - hash) + char;\n hash = hash & hash; // Convert to 32bit integer\n }\n\n return hash;\n}","// SPDX-License-Identifier: LGPL-3.0-or-later\n// Copyright © 2021 fvtt-lib-wrapper Rui Pinheiro\n\n'use strict';\n\nimport { PACKAGE_ID } from '../consts.js';\nimport { PackageInfo, PACKAGE_TYPES } from '../shared/package_info.js';\nimport { decorate_name } from '../utils/misc.js';\nimport { Log } from '../shared/log.js';\n\n\n/*\n * Utility methods for exceptions\n */\nexport function is_error_object(obj) {\n\t// We ignore anything that is not an object\n\tif(obj === null || obj === undefined || typeof obj !== 'object')\n\t\treturn false;\n\n\t// We figure out if this cause has a message and a stack frame - i.e. duck typing of an error object\n\tif(!('message' in obj) || !('stack' in obj))\n\t\treturn false;\n\n\t// This is (probably) an error\n\treturn true;\n}\n\n\nconst LIBWRAPPER_IGNORE_MATCHES = [\n\t'/listeners.js', // ignore anything in the listeners.js file\n\tdecorate_name('call_wrapped'), // shows up every time libWrapper is in the callstack\n\tdecorate_name('Application.prototype._render'), // has a libWrapper patch for unhandled error detection\n];\nfunction get_involved_packages(stack, ignore_ids=undefined) {\n\treturn PackageInfo.collect_all(stack, /* include_fn= */ (id, type, match) => {\n\t\t// Include any module that isn't libWrapper\n\t\tif(id !== PACKAGE_ID || type !== PACKAGE_TYPES.MODULE)\n\t\t\treturn true;\n\n\t\t// We don't include some libWrapper matches - specifically those that are in every single exception, or caused by a different module\n\t\tfor(const needle of LIBWRAPPER_IGNORE_MATCHES) {\n\t\t\tif(match.includes(needle))\n\t\t\t\treturn false;\n\t\t}\n\n\t\t// Otherwise it is included\n\t\treturn true;\n\t}, ignore_ids);\n}\n\n\nfunction get_involved_packages_message(stack, ignore_ids=undefined) {\n\tconst packages = get_involved_packages(stack, ignore_ids);\n\tconst length = packages.length;\n\n\t// Zero packages\n\tif(length <= 0)\n\t\treturn \"[No packages detected]\";\n\n\t// 1 package\n\tif(length == 1)\n\t\treturn `[Detected 1 package: ${packages[0].logId}]`;\n\n\t// 2+ packages\n\treturn`[Detected ${length} packages: ${packages.map((p)=>p.logId).join(', ')}]`;\n}\n\n\nfunction has_property_string_writable(obj, prop) {\n\tif(!(prop in obj))\n\t\treturn false\n\n\t// Get the property's descriptor if available\n\tconst desc = Object.getOwnPropertyDescriptor(obj, prop);\n\tif(desc) {\n\t\t// Check if the descriptor is not a getter/setter\n\t\tif(!('value' in desc))\n\t\t\treturn false;\n\n\t\t// Check if the value is a string\n\t\tif(typeof desc.value !== 'string')\n\t\t\treturn false;\n\n\t\t// Check if it is writable\n\t\tif(!desc.writable)\n\t\t\treturn false;\n\t}\n\t// We assume that if the property descriptor doesn't exist, then it is writable by default\n\t// But we still need to validate that it is a string\n\telse {\n\t\tconst value = obj[prop];\n\n\t\tif(typeof value !== 'string')\n\t\t\treturn false;\n\t}\n\n\t// Done\n\treturn true;\n}\n\n\nfunction can_inject_message(error) {\n\t// Can't modify a frozen object\n\tif(Object.isFrozen(error))\n\t\treturn false;\n\n\t// We need both 'message' and 'stack' to be writable strings\n\tif(!has_property_string_writable(error, 'message') || !has_property_string_writable(error, 'stack'))\n\t\treturn false;\n\n\t// Done\n\treturn true;\n}\n\n\nexport function inject_packages_into_error(error, ignore_ids=undefined) {\n\tlet packages_str;\n\n\ttry {\n\t\t// Sanity check\n\t\tif(!is_error_object(error))\n\t\t\treturn;\n\n\t\t// Skip package detection is already marked\n\t\tif(error.libwrapper_skip_package_detection)\n\t\t\treturn;\n\n\t\t// Test whether error object allows injection\n\t\tif(!can_inject_message(error))\n\t\t\treturn;\n\n\t\t// Generate involved packages string\n\t\tpackages_str = get_involved_packages_message(error.stack, ignore_ids);\n\n\t\t// Not necessary to inject a second time, if already present\n\t\tif(error.message.endsWith(packages_str)) {\n\t\t\terror.libwrapper_skip_package_detection = true;\n\t\t\treturn;\n\t\t}\n\t}\n\tcatch (e) {\n\t\tLog.error('Exception thrown while attempting to inject package information into an error.', e);\n\t}\n\n\t// Separate try-catch, we don't need to be noisy if the error occurs due to assigning to 'error' members.\n\ttry {\n\t\t// Append to error message\n\t\tconst orig_msg = error.message;\n\t\terror.message += `\\n${packages_str}`;\n\n\t\t// If the stack contains the error message, replace that as well\n\t\terror.stack = error.stack.replace(orig_msg, error.message);\n\n\t\t// Done - signal this error doesn't need package detection any more\n\t\terror.libwrapper_skip_package_detection = true;\n\t}\n\tcatch (e) {\n\t\tLog.debug$?.('Exception thrown while modifying error object.', e);\n\t}\n}","// SPDX-License-Identifier: LGPL-3.0-or-later\n// Copyright © 2021 fvtt-lib-wrapper Rui Pinheiro\n\n'use strict';\n\nimport { PACKAGE_ID, PACKAGE_TITLE } from '../consts.js';\nimport { ERRORS } from './errors.js';\nimport { PackageInfo } from '../shared/package_info.js';\nimport { inject_packages_into_error } from './error-utils.js';\nimport { i18n } from '../shared/i18n.js';\nimport { game_release_display } from '../shared/polyfill.js';\nimport { Log } from '../shared/log.js';\n\n\n// Custom libWrapper Error\nexport class LibWrapperError extends Error {\n\tget notification_verbosity() { return Log.ERROR };\n\n\tconstructor(ui_msg, console_msg, ...args) {\n\t\t// Create actual error object\n\t\tsuper(console_msg, ...args);\n\n\t\t// Maintains proper stack trace for where our error was thrown (only available on V8)\n\t\tif (Error.captureStackTrace)\n\t\t\tError.captureStackTrace(this, this.constructor);\n\t\tthis.name = this.constructor.name;\n\n\t\t// Store arguments\n\t\tthis.ui_msg = ui_msg;\n\t\tthis.console_msg = console_msg;\n\n\t\t// Detect packages, inject them into error message\n\t\t// Note: We hide 'lib-wrapper' from the list of detected packages, except when this was a libWrapper-internal error\n\t\tinject_packages_into_error(this, this instanceof LibWrapperInternalError ? null : PACKAGE_ID);\n\t}\n\n\t/**\n\t * Called if this error is unhandled\n\t */\n\tonUnhandled() {\n\t}\n}\nObject.freeze(LibWrapperError);\nERRORS.base = LibWrapperError;\n\n\n\n// Internal error\nexport class LibWrapperInternalError extends LibWrapperError {\n\tstatic construct_message(technical_msg, package_info) {\n\t\tconst key_prefix = 'lib-wrapper.error';\n\t\tconst type_prefix = `${key_prefix}.internal`;\n\n\t\t// User message\n\t\tconst user_msg = (!package_info.known ?\n\t\t\ti18n.localize(`${type_prefix}.message`) :\n\t\t\ti18n.format(`${type.prefix}.message-with-package`, {type: package_info.type_i18n, title: package_info.title})\n\t\t);\n\n\t\t// Console message\n\t\tconst info_msg = i18n.format(`${type_prefix}.info`, {url: 'https://github.com/ruipin/fvtt-lib-wrapper'});\n\t\tconst report_msg = i18n.format(`${type_prefix}.report`, {url: 'https://github.com/ruipin/fvtt-lib-wrapper/issues'});\n\t\tconst tech_details = i18n.localize(`${key_prefix}.tech-details`);\n\n\t\tconst related_pkg_msg = (!package_info.known ? '' : `Related Package ID= ${package_info.logId}\\n`);\n\n\t\t// Done\n\t\treturn [\n\t\t\t`${PACKAGE_TITLE}: ${user_msg}`,\n\t\t\t`${user_msg}\\n\\n${info_msg}\\n${report_msg}\\n\\n${tech_details}\\nInternal libWrapper error.\\n${related_pkg_msg}Error= ${technical_msg}\\n`\n\t\t];\n\t}\n\n\tconstructor(technical_msg, ...args) {\n\t\tconst package_info = new PackageInfo();\n\t\tconst [ui_msg, console_msg] = LibWrapperInternalError.construct_message(technical_msg, package_info);\n\n\t\tsuper(\n\t\t\tui_msg,\n\t\t\tconsole_msg,\n\t\t\t...args\n\t\t);\n\n\t\t// Custom debugging information\n\t\tthis.package_info = package_info;\n\t}\n\n\t/**\n\t * Returns the package ID\n\t */\n\tget package_id() { return this.package_info?.id; }\n}\nObject.freeze(LibWrapperInternalError);\nERRORS.internal = LibWrapperInternalError;\n\n\n\n// Error caused by a package\nexport class LibWrapperPackageError extends LibWrapperError {\n\tstatic get_community_support_message() {\n\t\tconst support_list = [];\n\n\t\tconst key = `${PACKAGE_ID}.support-channels`;\n\t\tconst list = i18n.localize(key);\n\t\tif(Array.isArray(list)) {\n\t\t\tfor(const entry of list) {\n\t\t\t\tif(!('title' in entry) || !('url' in entry))\n\t\t\t\t\tcontinue;\n\n\t\t\t\tsupport_list.push(`- ${entry.title}: ${entry.url}`);\n\t\t\t}\n\t\t}\n\n\t\treturn support_list.length > 0 ? support_list.join('\\n') : null;\n\t}\n\n\tstatic construct_message(technical_msg, package_info) {\n\t\tconst key_prefix = 'lib-wrapper.error';\n\t\tconst type_prefix = `${key_prefix}.external`;\n\n\t\tconst pkg_title = package_info.title;\n\t\tconst pkg_type_i18n = package_info.type_i18n;\n\n\t\t// UI Message\n\t\tlet ui_msg = i18n.format(`${type_prefix}.notification`, {title: pkg_title, type: pkg_type_i18n});\n\t\tlet console_ui_msg = i18n.format(`${type_prefix}.message`, {title: pkg_title, type: pkg_type_i18n});\n\n\t\tif(!package_info.compatible_with_core) {\n\t\t\tconst display_version = game_release_display(/*return_null=*/true);\n\t\t\tif(display_version) {\n\t\t\t\tconst notupd_msg = ` ${i18n.format(`${type_prefix}.likely-not-updated`, {type: pkg_type_i18n, version: display_version})}`;\n\n\t\t\t\tui_msg += notupd_msg;\n\t\t\t\tconsole_ui_msg += notupd_msg;\n\t\t\t}\n\t\t}\n\n\t\t// Console Message\n\t\tlet console_msg = `${console_ui_msg}\\n\\n${i18n.localize(`${key_prefix}.not-lw`)}\\n\\n`;\n\n\t\tconst info_url = package_info.url;\n\t\tconst has_info = (typeof info_url === 'string');\n\t\tif(has_info) {\n\t\t\tconsole_msg += i18n.format(`${type_prefix}.info`, {type: pkg_type_i18n, url: info_url});\n\t\t}\n\n\t\tconst report_url = package_info.bugs;\n\t\tif(typeof report_url === 'string') {\n\t\t\tif(has_info) console_msg += '\\n';\n\t\t\tconsole_msg += i18n.format(`${type_prefix}.report`, {url: report_url});\n\t\t}\n\t\telse {\n\t\t\tconst community_support_msg = this.get_community_support_message();\n\t\t\tif(community_support_msg) {\n\t\t\t\tif(has_info) console_msg += '\\n\\n';\n\t\t\t\tconsole_msg += i18n.localize(`${key_prefix}.community-support`);\n\t\t\t\tconsole_msg += '\\n';\n\t\t\t\tconsole_msg += community_support_msg;\n\t\t\t}\n\t\t}\n\t\tconsole_msg += \"\\n\\n\";\n\n\t\tconsole_msg += i18n.localize(`${key_prefix}.tech-details`);\n\t\tconsole_msg += `\\nDetected by libWrapper.\\nPackage ID= ${package_info.logId}\\nError= ${technical_msg}\\n`\n\n\n\t\t// Done\n\t\treturn [\n\t\t\tui_msg,\n\t\t\tconsole_msg\n\t\t];\n\t}\n\n\tconstructor(technical_msg, package_info, ...args) {\n\t\tif(!package_info)\n\t\t\tpackage_info = new PackageInfo();\n\t\telse if(package_info?.constructor !== PackageInfo)\n\t\t\tpackage_info = new PackageInfo(package_info);\n\n\t\tconst [ui_msg, console_msg] = LibWrapperPackageError.construct_message(technical_msg, package_info);\n\n\t\tsuper(\n\t\t\tui_msg,\n\t\t\tconsole_msg,\n\t\t\t...args\n\t\t);\n\n\t\t// Custom debugging information\n\t\tthis.package_info = package_info;\n\t}\n\n\t/**\n\t * Returns the package ID\n\t */\n\tget package_id() { return this.package_info?.id; }\n}\nObject.freeze(LibWrapperPackageError);\nERRORS.package = LibWrapperPackageError;","// SPDX-License-Identifier: LGPL-3.0-or-later\n// Copyright © 2021 fvtt-lib-wrapper Rui Pinheiro\n\n'use strict';\n\nimport { PACKAGE_ID } from '../consts.js';\nimport { game_user_isGM } from '../shared/polyfill.js'\n\n\n// Query settings\nexport function getSetting(key, dflt=undefined) {\n\ttry {\n\t\treturn game?.settings?.get(PACKAGE_ID, key);\n\t}\n\tcatch(e) {\n\t\tif(dflt !== undefined)\n\t\t\treturn dflt;\n\t\tthrow e;\n\t}\n}\n\nexport function getNotifyIssues() {\n\tconst isGM = game_user_isGM(/*return_null*/ true);\n\n\tif(isGM === null)\n\t\treturn true;\n\n\treturn getSetting(isGM ? 'notify-issues-gm' : 'notify-issues-player', true);\n}\n\nexport function getHighPerformanceMode() {\n\treturn getSetting('high-performance-mode', false);\n}","// SPDX-License-Identifier: LGPL-3.0-or-later\n// Copyright © 2021 fvtt-lib-wrapper Rui Pinheiro\n\n'use strict';\n\nimport { PACKAGE_TITLE } from '../consts.js';\nimport { decorate_class_function_names, hash_string } from '../utils/misc.js';\nimport { i18n } from '../shared/i18n.js';\nimport { getNotifyIssues } from '../utils/settings.js';\nimport { Log, verbosity_to_mapped_value } from '../shared/log.js';\n\n\n//*********************\n// Constants\nconst VERBOSITY_NOTIFY_FN_MAP = {\n\t[Log.INFO .value]: 'info' ,\n\t[Log.WARNING .value]: 'warn' ,\n\t[Log.ERROR .value]: 'error'\n};\n\n\n//*********************\n// User notifications helper class\nexport class LibWrapperNotifications {\n\t/*\n\t * Attributes\n\t */\n\tstatic get ui_notifications_enabled() {\n\t\t// Make sure we don't accidentally throw a second time, while handling what might be another exception\n\t\ttry {\n\t\t\tif(!getNotifyIssues())\n\t\t\t\treturn false;\n\t\t}\n\t\tcatch(e) {\n\t\t\t// We swallow the new error, and assume we want to display errors\n\t\t\tLog.error(\"Could not decide whether to show notifications or not. Defaulting to 'yes'.\\n\", e);\n\t\t\treturn true;\n\t\t}\n\n\t\treturn true;\n\t}\n\n\n\t/*\n\t * Methods\n\t */\n\tstatic init() {\n\t\tthis.NOTIFICATION_SET = new Set();\n\n\t\t// Seal to prevent accidental modification\n\t\tObject.seal(this);\n\t}\n\n\t// UI Notification\n\tstatic _ui(msg, verbosity=Log.ERROR, add_title=true) {\n\t\tif(!this.ui_notifications_enabled)\n\t\t\treturn;\n\n\t\t// Ensure that ui.notifications exists as if an error occurs too early it might not be defined yet\n\t\tconst ui_notifications = globalThis?.ui?.notifications;\n\t\tif(!ui_notifications)\n\t\t\treturn;\n\n\t\t// Calculate hash of message\n\t\tconst hash = hash_string(msg);\n\n\t\t// Check if we've already notified the user of this\n\t\tif(this.NOTIFICATION_SET.has(hash))\n\t\t\treturn;\n\n\t\t// Notify\n\t\tthis.NOTIFICATION_SET.add(hash);\n\t\tconst fn = verbosity_to_mapped_value(verbosity, VERBOSITY_NOTIFY_FN_MAP, 'error');\n\t\tui_notifications[fn].call(ui_notifications, add_title ? `${PACKAGE_TITLE}: ${msg}` : msg, {permanent: fn == 'error'});\n\t}\n\n\tstatic ui(...args) {\n\t\t// Wait until 'ready' in case we want to trigger a notification early during load\n\t\tif(!globalThis.game?.ready)\n\t\t\tHooks.once('ready', this._ui.bind(this, ...args));\n\t\telse\n\t\t\tthis._ui(...args);\n\t}\n\n\n\t// Console + UI notifications\n\tstatic console_ui(ui_msg, console_msg, verbosity=Log.ERROR, ...args) {\n\t\tconst log = Log.fn(verbosity);\n\t\tif(log) {\n\t\t\tlog(`${ui_msg}\\n${console_msg}`, ...args);\n\t\t\tui_msg += ` ${i18n.localize('lib-wrapper.error.see-js-console')}`;\n\t\t}\n\n\t\tthis.ui(ui_msg, verbosity);\n\t}\n\n\n\t// Conflict report\n\tstatic conflict(package_info, other_info, potential, console_msg) {\n\t\tlet other;\n\t\tif(Array.isArray(other_info)) {\n\t\t\tother = (other_info.length > 1) ?\n\t\t\t\t`[${other_info.map((x) => x.type_plus_title_i18n).join(', ')}]` :\n\t\t\t\tother_info[0].type_plus_title_i18n\n\t\t\t;\n\t\t}\n\t\telse {\n\t\t\tother = other_info.type_plus_title_i18n;\n\t\t}\n\n\t\tconst format_obj = {\n\t\t\tmain: package_info.type_plus_title_i18n,\n\t\t\tother: other\n\t\t};\n\n\t\tthis.console_ui(\n\t\t\tpotential ? i18n.format('lib-wrapper.error.conflict.potential', format_obj) :\n\t\t\t i18n.format('lib-wrapper.error.conflict.confirmed', format_obj) ,\n\t\t\tconsole_msg,\n\t\t\tpotential ? Log.WARNING : Log.ERROR\n\t\t);\n\t}\n}\ndecorate_class_function_names(LibWrapperNotifications);","// SPDX-License-Identifier: LGPL-3.0-or-later\n// Copyright © 2021 fvtt-lib-wrapper Rui Pinheiro\n\n'use strict';\n\nimport {PACKAGE_ID, IS_UNITTEST} from '../consts.js';\nimport {LibWrapperNotifications} from './notifications.js';\nimport {game_user_can} from '../shared/polyfill.js'\nimport {Log} from '../shared/log.js';\n\nexport class LibWrapperStats {\n\tstatic _collect_stats() {\n\t\t// We do this in a try-catch in case future Foundry versions break this code, it won't completely break libWrapper\n\t\ttry {\n\t\t\treturn game_user_can('SETTINGS_MODIFY');\n\t\t}\n\t\tcatch(e) {\n\t\t\tif(IS_UNITTEST)\n\t\t\t\tthrow e;\n\n\t\t\tLibWrapperNotifications.console_ui(\n\t\t\t\t\"A non-critical error occurred while initializing libWrapper.\",\n\t\t\t\t\"Could not read user permissions during initialization.\\n\",\n\t\t\t\tLog.WARNING,\n\t\t\t\te\n\t\t\t);\n\n\t\t\t// Default to 'true' on error\n\t\t\treturn true;\n\t\t}\n\t}\n\n\tstatic init() {\n\t\tthis.collect_stats = this._collect_stats();\n\n\t\t// If we got this far, we're going to be collecting statistics, so initialize the containers\n\t\tif(!this.collect_stats)\n\t\t\treturn;\n\n\t\tthis.PACKAGES = new Set();\n\t\tthis.CONFLICTS = new Map();\n\n\t\t// Seal to prevent accidental modification\n\t\tObject.seal(this);\n\t}\n\n\tstatic register_package(package_info) {\n\t\tif(!this.collect_stats)\n\t\t\treturn;\n\n\t\tif(package_info.id == PACKAGE_ID)\n\t\t\treturn;\n\n\t\tthis.PACKAGES.add(package_info.key);\n\t}\n\n\tstatic register_conflict(package_info, other_info, wrapper, ignored) {\n\t\tif(!this.collect_stats)\n\t\t\treturn;\n\n\t\t// Grab conflict data from storage, or create it if this is a new conflict\n\t\tconst key = `${package_info.key}/${other_info.key}`;\n\n\t\tlet data = this.CONFLICTS.get(key);\n\t\tif(!data) {\n\t\t\tdata = {\n\t\t\t\tcount: 0,\n\t\t\t\tignored: 0,\n\t\t\t\tpackage_info: package_info,\n\t\t\t\tother_info: other_info,\n\t\t\t\ttargets: new Map()\n\t\t\t};\n\t\t\tthis.CONFLICTS.set(key, data);\n\t\t}\n\n\t\tconst target = wrapper.name;\n\t\tlet target_data = data.targets.get(target);\n\t\tif(!target_data) {\n\t\t\ttarget_data = {\n\t\t\t\tcount: 0,\n\t\t\t\tignored: 0\n\t\t\t}\n\t\t\tdata.targets.set(target, target_data);\n\t\t}\n\n\t\t// Increment the conflict counter\n\t\tif(!ignored) {\n\t\t\tdata.count++;\n\t\t\ttarget_data.count++;\n\t\t}\n\t\telse {\n\t\t\tdata.ignored++;\n\t\t\ttarget_data.ignored++;\n\t\t}\n\t}\n\n\tstatic get conflicts() {\n\t\treturn this.CONFLICTS;\n\t}\n\n\tstatic get packages() {\n\t\treturn this.PACKAGES;\n\t}\n}","// SPDX-License-Identifier: LGPL-3.0-or-later\n// Copyright © 2021 fvtt-lib-wrapper Rui Pinheiro\n\n'use strict';\n\nimport {HOOKS_SCOPE} from '../consts.js';\nimport {ERRORS} from '../errors/errors.js';\nimport {LibWrapperStats} from './stats.js';\nimport {PackageInfo} from '../shared/package_info.js';\nimport { Log } from '../shared/log.js';\n\n\nclass IgnoredConflictEntry {\n\tconstructor(ignore_infos, targets, ignore_errors) {\n\t\t// Packages to ignore\n\t\tthis.ignore_infos = new Set(ignore_infos.map((x) => x.key));\n\n\t\t// Targets to ignore\n\t\tthis.targets = new Set(targets);\n\n\t\t// Whether this ignore also should match errors, and not just warnings\n\t\tthis.ignore_errors = ignore_errors;\n\n\t\t// Done\n\t\tObject.seal(this);\n\t}\n\n\tis_ignored(package_info, wrapper, is_warning) {\n\t\t// Skip if this is an error and we aren't set to ignore errors\n\t\tif(!is_warning && !this.ignore_errors)\n\t\t\treturn false;\n\n\t\t// Search for a matching package\n\t\tconst found_package = this.ignore_infos.has(package_info.key);\n\t\tif(!found_package)\n\t\t\treturn false;\n\n\t\t// Find matching target\n\t\tconst found_target = wrapper.names.find((name) => this.targets.has(name));\n\t\treturn (found_target !== undefined);\n\t}\n}\n\nexport class LibWrapperConflicts {\n\tstatic init() {\n\t\tthis.IGNORED = new Map();\n\n\t\t// Seal to prevent accidental modification\n\t\tObject.seal(this);\n\t}\n\n\tstatic register_ignore(package_info, ignore_infos, targets, is_warning) {\n\t\t// Create IgnoredConflictEntry\n\t\tconst entry = new IgnoredConflictEntry(ignore_infos, targets, is_warning);\n\n\t\t// Get the existing list of ignore entries for this package, or create a new one and add it to the map\n\t\tconst key = package_info.key;\n\t\tlet ignore_entries = this.IGNORED.get(key);\n\t\tif(!ignore_entries) {\n\t\t\tignore_entries = [];\n\t\t\tthis.IGNORED.set(key, ignore_entries);\n\t\t}\n\n\t\t// Add new entry to list\n\t\tignore_entries.push(entry);\n\t}\n\n\tstatic clear_ignores() {\n\t\tthis.IGNORED.clear();\n\t}\n\n\tstatic _is_ignored_oneway(package_info, other_info, wrapper, is_warning) {\n\t\t// Get the existing list of ignore entries for this package\n\t\tconst key = package_info.key;\n\t\tconst ignore_entries = this.IGNORED.get(key);\n\t\tif(!ignore_entries)\n\t\t\treturn false;\n\n\t\t// Check if any of the entries causes this conflict to be ignored\n\t\tfor(const entry of ignore_entries) {\n\t\t\tif(entry.is_ignored(other_info, wrapper, is_warning))\n\t\t\t\treturn true;\n\t\t}\n\n\t\t// Otherwise, it's not ignored\n\t\treturn false;\n\t}\n\n\tstatic _is_ignored(package_info, other_info, wrapper, is_warning) {\n\t\treturn this._is_ignored_oneway(package_info, other_info, wrapper, is_warning) ||\n\t\t this._is_ignored_oneway(other_info, package_info, wrapper, is_warning);\n\t}\n\n\tstatic register_conflict(package_info, other_info, wrapper, target, is_warning) {\n\t\t// Ignore an empty conflict\n\t\tif(!other_info)\n\t\t\treturn false;\n\n\t\t// Convert from array if necessary\n\t\tif(Array.isArray(other_info)) {\n\t\t\tlet notify = false;\n\t\t\tother_info.forEach((other) => {\n\t\t\t\tnotify |= this.register_conflict(package_info, other, wrapper, target, is_warning);\n\t\t\t});\n\t\t\treturn notify;\n\t\t}\n\n\t\t// Sanity checks #2\n\t\tif(package_info.constructor !== PackageInfo)\n\t\t\tthrow new ERRORS.internal(`LibWrapperConflicts.register_conflict: 'package_info' must be a PackageInfo object, but got '${package_info}'.`);\n\n\t\tif(other_info.constructor !== PackageInfo)\n\t\t\tthrow new ERRORS.internal(`LibWrapperConflicts.register_conflict: 'other_info' must be a PackageInfo object, but got '${other_info}'.`);\n\n\t\t// Note: Not checked because of cyclic dependency\n\t\t//if(wrapper.constructor != Wrapper)\n\t\t//\tthrow new ERRORS.internal(`LibWrapperConflicts.register_conflict: 'wrapper' must be a Wrapper object, but got '${wrapper}'.`);\n\n\t\tif(target != null && typeof target !== 'string')\n\t\t\tthrow new ERRORS.internal(`LibWrapperConflicts.register_conflict: 'target' must be a string, or null, but got '${target}'.`);\n\n\t\tif(typeof is_warning !== 'boolean')\n\t\t\tthrow new ERRORS.internal(`LibWrapperConflicts.register_conflict: 'is_warning' must be a boolean, but got '${is_warning}'.`);\n\n\n\t\t// We first check if this conflict is ignored\n\t\tlet ignored = false;\n\n\t\tif(!ignored && this._is_ignored(package_info, other_info, wrapper, is_warning)) {\n\t\t\tignored = true;\n\t\t\tLog.debug$?.(`Conflict between ${package_info.type_plus_id} and ${other_info.type_plus_id} over '${wrapper.name}' ignored through 'ignore_conflicts' API.`);\n\t\t}\n\n\t\t// We then notify everyone that a conflict was just detected. This hook being handled will prevent us from registering the package conflict\n\t\tif(!ignored && Hooks.call(`${HOOKS_SCOPE}.ConflictDetected`, package_info.id, other_info.id, target, wrapper.frozen_names) === false) {\n\t\t\tignored = true;\n\t\t\tLog.debug$?.(`Conflict between ${package_info.type_plus_id} and ${other_info.type_plus_id} over '${wrapper.name}' ignored, as 'libWrapper.ConflictDetected' hook returned false.`);\n\t\t}\n\n\t\t// We now register the conflict with LibWrapperStats\n\t\tLibWrapperStats.register_conflict(package_info, other_info, wrapper, ignored);\n\n\t\t// Done\n\t\treturn !ignored;\n\t}\n}","// SPDX-License-Identifier: LGPL-3.0-or-later\n// Copyright © 2021 fvtt-lib-wrapper Rui Pinheiro\n\n'use strict';\n\nimport { LibWrapperError, LibWrapperPackageError } from './base_errors.js';\nimport { ERRORS } from './errors.js';\nimport { PackageInfo } from '../shared/package_info.js';\nimport { LibWrapperConflicts } from '../ui/conflicts.js';\nimport { i18n } from '../shared/i18n.js';\nimport { PACKAGE_TITLE } from '../consts.js';\n\n\n// Already Overridden Error\nexport class LibWrapperAlreadyOverriddenError extends LibWrapperError {\n\tstatic construct_message(package_info, conflicting_info, technical_msg) {\n\t\tconst key_prefix = 'lib-wrapper.error';\n\t\tconst type_prefix = `${key_prefix}.conflict`;\n\n\t\tconst pkg_i18n = package_info.type_plus_title_i18n;\n\t\tconst pkg_i18n_capitalized = pkg_i18n.charAt(0).toUpperCase() + pkg_i18n.slice(1);\n\t\tconst confl_i18n = conflicting_info.type_plus_title_i18n;\n\t\tconst confl_i18n_capitalized = confl_i18n.charAt(0).toUpperCase() + confl_i18n.slice(1);\n\n\t\tconst conflict_msg = i18n.format(`${type_prefix}.confirmed`, {main: pkg_i18n, other: confl_i18n});\n\n\t\t// UI Message\n\t\tlet ui_msg = `${PACKAGE_TITLE}: ${conflict_msg}`;\n\n\n\t\t// Console Message\n\t\tlet console_msg = `${conflict_msg}\\n\\n${i18n.localize(`${key_prefix}.not-lw`)}\\n\\n`;\n\n\t\t// Info links\n\t\tlet info_msg = '';\n\n\t\tconst info1_url = package_info.url;\n\t\tif(typeof info1_url === 'string')\n\t\t\tinfo_msg += `\\n- ${pkg_i18n_capitalized}: ${info1_url}`;\n\n\t\tconst info2_url = conflicting_info.url;\n\t\tif(typeof info2_url === 'string')\n\t\t\tinfo_msg += `\\n- ${confl_i18n_capitalized}: ${info2_url}`;\n\n\t\tif(info_msg)\n\t\t\tconsole_msg += `${i18n.localize(`${type_prefix}.info`)}${info_msg}\\n\\n`;\n\n\t\t// Report links\n\t\tlet bugs_msg = '';\n\n\t\tconst bugs1_url = package_info.bugs;\n\t\tif(typeof bugs1_url === 'string')\n\t\t\tbugs_msg += `\\n- ${pkg_i18n_capitalized}: ${bugs1_url}`;\n\n\t\tconst bugs2_url = conflicting_info.bugs;\n\t\tif(typeof bugs2_url === 'string')\n\t\t\tbugs_msg += `\\n- ${confl_i18n_capitalized}: ${bugs2_url}`;\n\n\t\tif(bugs_msg)\n\t\t\tconsole_msg += `${i18n.localize(`${type_prefix}.report`)}${bugs_msg}\\n\\n`;\n\n\t\t// Support links\n\t\tconst community_support_msg = LibWrapperPackageError.get_community_support_message();\n\t\tif(community_support_msg) {\n\t\t\tconsole_msg += i18n.localize(`${key_prefix}.community-support`);\n\t\t\tconsole_msg += '\\n';\n\t\t\tconsole_msg += community_support_msg;\n\t\t\tconsole_msg += \"\\n\\n\";\n\t\t}\n\n\t\t// Tech details\n\t\tconsole_msg += i18n.localize(`${key_prefix}.tech-details`);\n\t\tconsole_msg += `\\nDetected by libWrapper.\\nPackage IDs= ${package_info.logId}, ${conflicting_info.logId}\\nError= ${technical_msg}\\n`\n\n\n\t\t// Done\n\t\treturn [\n\t\t\tui_msg,\n\t\t\tconsole_msg\n\t\t];\n\t}\n\n\tconstructor(package_info, conflicting_info, wrapper, target, ...args) {\n\t\tif(package_info?.constructor !== PackageInfo)\n\t\t\tpackage_info = new PackageInfo(package_info);\n\n\t\tif(conflicting_info?.constructor !== PackageInfo)\n\t\t\tconflicting_info = new PackageInfo(conflicting_info);\n\n\t\tconst [ui_msg, console_msg] = LibWrapperAlreadyOverriddenError.construct_message(package_info, conflicting_info,\n\t\t\t`Failed to wrap '${target}' for ${package_info.type_plus_id} with type OVERRIDE. An OVERRIDE wrapper for the same method has already been registered by ${conflicting_info.type_plus_id}.`\n\t\t);\n\n\t\tsuper(\n\t\t\tui_msg,\n\t\t\tconsole_msg,\n\t\t\t...args\n\t\t);\n\n\t\t// Custom debugging information\n\t\tthis.package_info = package_info;\n\t\tthis.conflicting_info = conflicting_info;\n\t\tthis.target = target;\n\t\tthis._wrapper = wrapper;\n\t}\n\n\t/**\n\t * Returns the package ID\n\t */\n\tget package_id() { return this.package_info?.id; }\n\n\t/**\n\t * Deprecated since v1.6.0.0\n\t * Returns the package ID\n\t */\n\tget module() { return this.package_id; }\n\n\t/**\n\t * Returns the conflicting package ID\n\t */\n\tget conflicting_id() { return this.conflicting_info?.id; }\n\n\t/**\n\t * Deprecated since v1.6.0.0\n\t * Returns the conflicting package ID\n\t */\n\tget conflicting_module() { return this.conflicting_id; }\n\n\t/**\n\t * Called if this error is unhandled\n\t */\n\tonUnhandled() {\n\t\tsuper.onUnhandled();\n\n\t\tLibWrapperConflicts.register_conflict(this.package_info, this.conflicting_info, this._wrapper, this.target, false);\n\t}\n}\nObject.freeze(LibWrapperAlreadyOverriddenError);\nERRORS.already_overridden = LibWrapperAlreadyOverriddenError;\n\n\n\n// Invalid Wrapper Chain Error\nexport class LibWrapperInvalidWrapperChainError extends LibWrapperPackageError {\n\tconstructor(wrapper, package_info, technical_msg, ...args) {\n\t\tif(package_info?.constructor !== PackageInfo)\n\t\t\tpackage_info = new PackageInfo(package_info);\n\n\t\tsuper(\n\t\t\ttechnical_msg,\n\t\t\tpackage_info,\n\t\t\t...args\n\t\t);\n\n\t\t// Custom debugging information\n\t\tthis._wrapper = wrapper;\n\t}\n}\nObject.freeze(LibWrapperInvalidWrapperChainError);\nERRORS.invalid_chain = LibWrapperInvalidWrapperChainError;","// SPDX-License-Identifier: LGPL-3.0-or-later\n// Copyright © 2021 fvtt-lib-wrapper Rui Pinheiro\n\n'use strict';\n\nimport { IS_UNITTEST } from '../consts.js';\nimport { global_eval } from '../utils/misc.js';\nimport { LibWrapperError } from './base_errors.js';\nimport { is_error_object, inject_packages_into_error } from './error-utils.js';\nimport { LibWrapperNotifications } from '../ui/notifications.js';\nimport { i18n } from '../shared/i18n.js';\nimport { Log } from '../shared/log.js';\n\n\n/*\n * Make sure browser is allowed to collect full stack traces, for easier debugging of issues\n */\nError.stackTraceLimit = Infinity;\n\n\n/*\n * Utility Methods\n */\nfunction on_libwrapper_error(error) {\n\t// Notify user of the issue\n\tif(error.ui_msg && error.notification_verbosity)\n\t\tLibWrapperNotifications.ui(`${error.ui_msg} ${i18n.localize('lib-wrapper.error.see-js-console')}`, error.notification_verbosity, false);\n\n\t// Trigger 'onUnhandled'\n\tif(error.onUnhandled)\n\t\terror.onUnhandled.apply(error);\n}\n\nfunction on_any_error(error) {\n\t// Detect packages and inject a list into the error object\n\tinject_packages_into_error(error);\n}\n\n\n/*\n * Error Listeners\n */\nexport const onUnhandledError = function(error) {\n\ttry {\n\t\t// Sanity check\n\t\tif(!is_error_object(error))\n\t\t\treturn;\n\n\t\t// If we have an instance of LibWrapperError, we trigger the libWrapper-specific behaviour\n\t\tif(error instanceof LibWrapperError)\n\t\t\ton_libwrapper_error(error);\n\n\t\t// Trigger the error handling code for all errors\n\t\ton_any_error(error);\n\t}\n\tcatch (e) {\n\t\tLog.error('Exception thrown while processing an unhandled error.', e);\n\t}\n}\n\nconst onUnhandledErrorEvent = function(event) {\n\ttry {\n\t\t// The cause of the event is what we're interested in\n\t\tconst cause = event.reason ?? event.error ?? event;\n\n\t\t// We've got our error object, call onUnhandledError\n\t\treturn onUnhandledError(cause);\n\t}\n\tcatch (e) {\n\t\tLog.error('Exception thrown while processing an unhandled error event.', e);\n\t}\n}\n\n\n/*\n * Set up error listeners\n */\nfunction init_pre_v9p2_listeners() {\n\t// Wrap Hooks._call to intercept unhandled exceptions during hooks\n\t// We don't use libWrapper itself here as we can guarantee we come first (well, before any libWrapper wrapper) and we want to avoid polluting the callstack of every single hook.\n\t// Otherwise users might think libWrapper is causing failures, when they're actually the fault of another package.\n\t// We try to patch the existing method. If anything fails, we just alert the user and skip this section.\n\ttry {\n\t\t// Patch original method\n\t\tconst orig = '() => function ' + Hooks._call.toString();\n\t\tconst patched = orig.replace(/catch[\\s\\n]*\\((.*)\\)[\\s\\n]*{/img, '$& globalThis.libWrapper.onUnhandledError($1);');\n\t\tif(orig === patched)\n\t\t\tthrow new Error(`Could not patch 'Hooks._call' method:\\n${orig}`);\n\t\tLog.debug$?.(`Patched Hooks._call: ${patched}`);\n\n\t\tconst patched_fn = global_eval(patched)?.();\n\t\tif(typeof patched_fn !== 'function')\n\t\t\tthrow new Error(`Evaluation of patched 'Hooks._call' method did not return a function:\\nPatched Method: ${patched}\\nReturned: ${patched_fn}`);\n\n\t\tHooks._call = patched_fn;\n\t}\n\tcatch(e) {\n\t\t// Handle a possible error gracefully\n\t\tLibWrapperNotifications.console_ui(\n\t\t\t\"A non-critical error occurred while initializing libWrapper.\",\n\t\t\t\"Could not setup 'Hooks._call' wrapper.\\n\",\n\t\t\tLog.WARNING,\n\t\t\te\n\t\t);\n\t}\n\n\t// Wrap Application.prototype._render to intercept unhandled exceptions when rendering Applications\n\ttry {\n\t\tlibWrapper.register('lib-wrapper', 'Application.prototype._render', function(wrapped, ...args) {\n\t\t\treturn wrapped(...args).catch(err => {\n\t\t\t\tonUnhandledError(err);\n\t\t\t\tthrow err;\n\t\t\t});\n\t\t}, 'WRAPPER', {perf_mode: 'FAST'});\n\t}\n\tcatch(e) {\n\t\t// Handle a possible error gracefully\n\t\tLibWrapperNotifications.console_ui(\n\t\t\t\"A non-critical error occurred while initializing libWrapper.\",\n\t\t\t\"Could not setup 'Application.prototype._render' wrapper.\\n\",\n\t\t\tLog.WARNING,\n\t\t\te\n\t\t);\n\t}\n}\n\nfunction init_hooksOnError_listener() {\n\t// Wrap Hooks._onError to intercept unhandled exceptions\n\t// We could use the 'error' hook instead, but then we wouldn't be able to see an exception before it gets logged to the console\n\ttry {\n\t\tlibWrapper.register('lib-wrapper', 'Hooks.onError', function(wrapped, ...args) {\n\t\t\t// Handle error ourselves first\n\t\t\tconst err = args[1];\n\t\t\tonUnhandledError(err);\n\n\t\t\t// Let Foundry do its thing after\n\t\t\treturn wrapped(...args);\n\t\t}, 'WRAPPER', {perf_mode: 'FAST'});\n\t}\n\tcatch(e) {\n\t\t// Handle a possible error gracefully\n\t\tLibWrapperNotifications.console_ui(\n\t\t\t\"A non-critical error occurred while initializing libWrapper.\",\n\t\t\t\"Could not setup 'Hooks.onError' wrapper.\\n\",\n\t\t\tLog.WARNING,\n\t\t\te\n\t\t);\n\t}\n}\n\n// Called during libWrapper initialisation\nexport const init_error_listeners = function() {\n\t// Do nothing inside unit tests\n\tif(IS_UNITTEST)\n\t\treturn;\n\n\t// Javascript native unhandled exception listeners\n\tglobalThis.addEventListener('error', onUnhandledErrorEvent);\n\tglobalThis.addEventListener('unhandledrejection', onUnhandledErrorEvent);\n\n\t// v9p2 or newer triggers 'Hooks.onError' any time there is an unhandled error\n\tif(Hooks.onError) {\n\t\tinit_hooksOnError_listener();\n\t}\n\t// v9p1 or older needs individual patching\n\telse {\n\t\tinit_pre_v9p2_listeners();\n\t}\n}","// SPDX-License-Identifier: LGPL-3.0-or-later\n// Copyright © 2021 fvtt-shared-library Rui Pinheiro\n\n'use strict';\n\nimport {PACKAGE_TITLE, PACKAGE_ID} from '../consts.js';\n\n\n//*********************\n// Versioning\n\n// This allows rollup to optimise the version-related code\n/*#if _ROLLUP\n\n\texport const VERSION = $_PACKAGE_VERSION;\n\n//#else */\n\n\t// Utility method to simplify throwing exceptions when parsing the manifest version\n\tconst throw_error = (msg) => { throw new Error(`${PACKAGE_TITLE}: ${msg}.\\nFoundry might not have initialized properly, please try refreshing.`) };\n\n\t// This method will be used by Rollup to feed the JSCC pre-processor\n\texport const _parse_manifest_version = function(version, git_hash) {\n\t\t// Default to a sane value\n\t\tconst known = (typeof version === 'string');\n\t\tif(!known)\n\t\t\tversion = '1.99.99.99';\n\n\t\t// Parse version string\n\t\tconst match = version.match(/^([0-9]+)\\.([0-9]+)\\.([0-9]+).([0-9]+)(.*)$/i);\n\t\tif(!match)\n\t\t\tthrow_error(`Unable to parse version string '${version_str}'`);\n\n\t\tconst result = {\n\t\t\tknown : known,\n\t\t\tfull : version,\n\t\t\tmajor : parseInt(match[1]),\n\t\t\tminor : parseInt(match[2]),\n\t\t\tpatch : parseInt(match[3]),\n\t\t\tsuffix : parseInt(match[4]),\n\t\t\tmeta : match[5],\n\t\t};\n\n\t\t// Process git hash\n\t\tresult.git = git_hash ?? 'unknown';\n\t\tresult.git_short = (result.git.length >= 40) ? result.git.slice(0,7) : result.git;\n\t\tresult.full_git = `${result.full} (${result.git_short})`\n\n\t\t// Done\n\t\treturn result;\n\t}\n\n\t// This method is fallback, and only used when running libWrapper directly from the source code without going through the Rollup build step first\n\t// e.g. during unit tests\n\texport const parse_manifest_version = function() {\n\t\tif(VERSION.known)\n\t\t\treturn;\n\n\t\ttry {\n\t\t\t// Get package manifest\n\t\t\tif(!game.modules)\n\t\t\t\tthrow_error(\"Could not find 'game.modules'\");\n\n\t\t\tif(!game.modules.size)\n\t\t\t\tthrow_error(\"Map 'game.modules' is empty\");\n\n\t\t\tconst mdl = game.modules.get(PACKAGE_ID);\n\t\t\tif(!mdl)\n\t\t\t\tthrow_error(`Could not find 'game.modules.get(\"${PACKAGE_ID}\")'`);\n\n\t\t\t// Grab git version (no need to validate)\n\t\t\tconst git_hash = mdl.flags?.git_version ?? mdl.data?.flags?.git_version;\n\n\t\t\t// Grab version string\n\t\t\tconst version_str = mdl.version ?? mdl.data?.version;\n\t\t\tif(!version_str)\n\t\t\t\tthrow_error(\"Unable to find version string inside package manifest\");\n\n\t\t\t// Done\n\t\t\tVERSION = _parse_manifest_version(version_str, git_hash);\n\t\t}\n\t\tcatch(e) {\n\t\t\tconsole.error(e);\n\t\t\tHooks?.once('ready', () => globalThis?.ui?.notifications?.error?.(e));\n\t\t}\n\t}\n\n\texport let VERSION = _parse_manifest_version(null, null);\n\n//#endif\n\n\n//*********************\n// Test for a minimum version\nexport const version_at_least = function(major, minor=0, patch=0, suffix=0) {\n\tif(VERSION.major == major) {\n\t\tif(VERSION.minor == minor) {\n\t\t\tif(VERSION.patch == patch) {\n\t\t\t\treturn VERSION.suffix == suffix;\n\t\t\t}\n\n\t\t\treturn VERSION.patch >= patch;\n\t\t}\n\n\t\treturn VERSION.minor > minor;\n\t}\n\treturn VERSION.major > major;\n}","// SPDX-License-Identifier: LGPL-3.0-or-later\n// Copyright © 2021 fvtt-event-viewer Rui Pinheiro\n\n'use strict';\n\n\nimport {Enum} from '../shared/enums.js';\n\n\n//*********************\n// WRAPPER TYPES\nexport const WRAPPER_TYPES = Enum('WrapperType', {\n\t'WRAPPER' : 1,\n\t'MIXED' : 2,\n\t'OVERRIDE': 3\n});\n\n\n//*********************\n// PERFORMANCE MODES\nexport const PERF_MODES = Enum('PerformanceMode', {\n\t'NORMAL': 1,\n\t'AUTO' : 2,\n\t'FAST' : 3\n});","// SPDX-License-Identifier: LGPL-3.0-or-later\n// Copyright © 2021 fvtt-lib-wrapper Rui Pinheiro\n\n'use strict';\n\nimport {ERRORS} from '../errors/errors.js';\n\n\n// Class meant to store active wrappers\nclass WrapperStorage {\n\t// Construction\n\tconstructor() {\n\t\tthis.clear();\n\t}\n\n\n\t// IDs\n\tindex_for_id(id) {\n\t\treturn Math.floor(id / 2);\n\t}\n\n\tindex_for_wrapper(wrapper) {\n\t\treturn this.index_for_id(wrapper.getter_id);\n\t}\n\n\tget_next_id_pair() {\n\t\treturn [this.next_id++, this.next_id++];\n\t}\n\n\n\t// Data Storage\n\t_delete(idx) {\n\t\tthis.data.delete(idx);\n\t}\n\n\t_set(idx, wrapper) {\n\t\tif(wrapper === null || wrapper === undefined)\n\t\t\treturn this._delete(idx);\n\n\t\tconst ref = new WeakRef(wrapper);\n\t\tthis.data.set(idx, ref);\n\t}\n\n\t_deref(idx, ref) {\n\t\tconst obj = ref?.deref();\n\n\t\t// If the weak reference dereferences to null, we can garbage-collect it from the Map\n\t\tif(!obj)\n\t\t\tthis._delete(idx);\n\n\t\treturn obj;\n\t}\n\n\t_get(idx) {\n\t\tconst ref = this.data.get(idx);\n\t\treturn this._deref(idx, ref);\n\t}\n\n\n\t// Utility\n\texists(wrapper, idx=undefined) {\n\t\tif(idx === undefined)\n\t\t\tidx = this.index_for_wrapper(wrapper);\n\n\t\tconst existing = this._get(idx);\n\n\t\t// If the index already exists, it must be the same object\n\t\tif(existing) {\n\t\t\tif(existing !== wrapper)\n\t\t\t\tthrow new ERRORS.internal(`Sanity check failed: The WrapperStorage index ${idx} does not contain the wrapper object '${wrapper.name}'.`);\n\n\t\t\treturn true;\n\t\t}\n\n\t\t// Otherwise, it does not exist\n\t\treturn false;\n\t}\n\n\n\t// Insertion and Deletion\n\tadd(wrapper) {\n\t\tconst idx = this.index_for_wrapper(wrapper);\n\n\t\t// Add to storage if it does not exist yet\n\t\tif(!this.exists(wrapper, idx))\n\t\t\tthis._set(idx, wrapper);\n\t}\n\n\tremove(wrapper) {\n\t\tconst idx = this.index_for_wrapper(wrapper);\n\n\t\tif(this.exists(wrapper, idx))\n\t\t\tthis._delete(idx);\n\t}\n\n\tclear() {\n\t\tthis.data = new Map();\n\t\tthis.next_id = 0;\n\t}\n\n\n\t// Iteration\n\t*wrappers() {\n\t\tfor(const [idx, ref] of this.data.entries()) {\n\t\t\tconst wrapper = this._deref(idx, ref);\n\t\t\tif(!wrapper)\n\t\t\t\tcontinue;\n\n\t\t\tyield wrapper;\n\t\t}\n\t}\n\n\tforEach(callbackFn) {\n\t\tfor(const wrapper of this.wrappers())\n\t\t\tcallbackFn(wrapper);\n\t}\n\n\tfind(callbackFn) {\n\t\tfor(const wrapper of this.wrappers()) {\n\t\t\tif(callbackFn(wrapper))\n\t\t\t\treturn wrapper;\n\t\t}\n\n\t\treturn undefined;\n\t}\n\n\n\t// Wrapper ID\n\tfind_by_id(id) {\n\t\tconst idx = this.index_for_id(id);\n\t\treturn this._get(idx);\n\t}\n}\n\n\n// Export singleton object containing the shared list of active wrappers\nexport const WRAPPERS = new WrapperStorage();","// SPDX-License-Identifier: LGPL-3.0-or-later\n// Copyright © 2021 fvtt-lib-wrapper Rui Pinheiro\n\n'use strict';\n\nimport {PROPERTIES_CONFIGURABLE, PACKAGE_TITLE} from '../consts.js';\nimport {WRAPPER_TYPES, PERF_MODES} from './enums.js';\nimport {WRAPPERS} from './storage.js';\nimport {decorate_name, set_function_name, decorate_class_function_names} from '../utils/misc.js';\nimport {getHighPerformanceMode} from '../utils/settings.js';\nimport {PackageInfo} from '../shared/package_info.js';\nimport {Log} from '../shared/log.js';\n\nimport {ERRORS} from '../errors/errors.js';\n\nimport {LibWrapperNotifications} from '../ui/notifications.js';\nimport {LibWrapperStats} from '../ui/stats.js';\nimport {LibWrapperConflicts} from '../ui/conflicts.js';\nimport {onUnhandledError} from '../errors/listeners.js';\n\n\n// Wrapper class - this class is responsible for the actual wrapping\nexport class Wrapper {\n\t// IDs\n\tget_id(is_setter=false) {\n\t\treturn is_setter ? this.setter_id : this.getter_id;\n\t}\n\n\n\n\t// Names\n\tget name() {\n\t\treturn this.names[0];\n\t}\n\n\tget frozen_names() {\n\t\tObject.freeze(this.names);\n\t\treturn this.names;\n\t}\n\n\tget_name(is_setter=false) {\n\t\treturn is_setter ? `${this.name}#set` : this.name;\n\t}\n\n\tget_names(is_setter=false) {\n\t\tif(!is_setter)\n\t\t\treturn this.frozen_names;\n\n\t\treturn this.names.map((name) => `${name}#set`);\n\t}\n\n\t_add_name(name) {\n\t\tif(!this.names.includes(name)) {\n\t\t\t// Note: 'this._names' might be frozen, assuming the 'this.frozen_names' getter has ever been used, in which case we need to clone it.\n\t\t\tif(Object.isFrozen(this.names))\n\t\t\t\tthis.names = this.names.slice();\n\n\t\t\tthis.names.push(name);\n\t\t}\n\t}\n\n\n\n\t// Callstack\n\t_callstack_name(nm, arg1=this.name) {\n\t\treturn decorate_name(arg1, nm);\n\t}\n\n\n\n\t// Constructor\n\tconstructor (obj, fn_name, name=undefined, package_info=undefined) {\n\t\t// Basic instance variables\n\t\tthis.fn_name = fn_name;\n\t\tthis.object = obj;\n\n\t\t// Validate whether we can wrap this object\n\t\tlet descriptor = Object.getOwnPropertyDescriptor(obj, fn_name);\n\n\t\tif(descriptor) {\n\t\t\tif(descriptor.get?._lib_wrapper) {\n\t\t\t\tconst wrapper = descriptor.get?._lib_wrapper;\n\n\t\t\t\tif(!(wrapper instanceof this.constructor))\n\t\t\t\t\tthrow new ERRORS.internal(`'${name}' cannot be wrapped, the descriptor already has a wrapper, but of an unexpected class ('${wrapper.constructor.name}' vs '${this.constructor.name}').`);\n\n\t\t\t\twrapper._add_name(name);\n\n\t\t\t\treturn wrapper;\n\t\t\t}\n\n\t\t\tif(descriptor.configurable === false) {\n\t\t\t\tthrow new ERRORS.package(`'${name}' cannot be wrapped, the corresponding descriptor has 'configurable=false'.`, package_info);\n\t\t\t}\n\t\t\telse {\n\t\t\t\tif(descriptor.get) {\n\t\t\t\t\tthis.is_property = true;\n\t\t\t\t\tthis._wrapped_getter = descriptor.get;\n\t\t\t\t\tthis._wrapped_setter = descriptor.set;\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tthis.is_property = false;\n\t\t\t\t\tthis._wrapped = descriptor.value;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\telse {\n\t\t\tdescriptor = this._get_inherited_descriptor();\n\n\t\t\tif(!descriptor)\n\t\t\t\tthrow new ERRORS.package(`Can't wrap '${name}', target does not exist or could not be found.`, package_info);\n\n\t\t\tconst wrapper = descriptor.get?._lib_wrapper;\n\n\t\t\tif(wrapper) {\n\t\t\t\tthis.is_property = wrapper.is_property;\n\t\t\t}\n\t\t\telse {\n\t\t\t\tif(descriptor.get ?? descriptor.set)\n\t\t\t\t\tthis.is_property = true;\n\t\t\t\telse\n\t\t\t\t\tthis.is_property = false;\n\t\t\t}\n\t\t}\n\n\t\t// Setup instance variables\n\t\t[this.getter_id, this.setter_id] = WRAPPERS.get_next_id_pair();\n\n\t\tthis.names = [];\n\n\t\tthis.getter_data = [];\n\t\tif(this.is_property)\n\t\t\tthis.setter_data = [];\n\n\t\tthis.active = false;\n\n\t\tthis._outstanding_wrappers = 0;\n\n\t\tif(!this.is_property) {\n\t\t\tthis._current_handler_id = 0;\n\t\t\tthis._pending_wrapped_calls = [];\n\t\t\tthis._pending_wrapped_calls_cnt = 0;\n\t\t}\n\n\t\tthis.use_static_dispatch = false;\n\n\t\t// Add name\n\t\tif(!name)\n\t\t\tname = fn_name;\n\t\tthis._add_name(name);\n\n\t\t// Do actual wrapping\n\t\tthis._wrap();\n\t}\n\n\n\n\t// Handler\n\t_get_handler() {\n\t\t// Properties cannot use handlers\n\t\tif(this.is_property)\n\t\t\tthrow new ERRORS.internal(`Unreachable: _get_handler with is_property=false`);\n\n\t\t// Return the cached handler, if it is still valid\n\t\tconst handler_id = this._current_handler_id;\n\t\tif(handler_id === this._cached_handler_id)\n\t\t\treturn this._cached_handler;\n\n\t\t// Create a handler function\n\t\tconst _this = this;\n\t\tconst handler_nm = this._callstack_name(handler_id);\n\t\tconst wrapped = this._wrapped ?? null; // we explicitly convert undefined to null here, to force a inheritance chain search when calling get_wrapped\n\n\t\t// We use a trick here to be able to convince the browser to name the method the way we want it\n\t\tconst obj = {\n\t\t\t[handler_nm]: function(...args) {\n\t\t\t\tconst is_static_dispatch = _this.use_static_dispatch;\n\n\t\t\t\t// Check if we should skip wrappers\n\t\t\t\tif(_this.should_skip_wrappers(this, handler_id, is_static_dispatch)) {\n\t\t\t\t\treturn _this.get_wrapped(this, false, wrapped).apply(this, args);\n\t\t\t\t}\n\t\t\t\t// Otherwise, trigger the wrapper dispatch chain\n\t\t\t\telse {\n\t\t\t\t\t// Trigger the desired dispatch chain - dynamic or static\n\t\t\t\t\tif(is_static_dispatch)\n\t\t\t\t\t\treturn _this.get_static_dispatch_chain(this).apply(this, args);\n\t\t\t\t\telse\n\t\t\t\t\t\treturn _this.call_wrapper(null, this, ...args);\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t\tconst handler = obj[handler_nm];\n\n\t\thandler.toString = function () {\n\t\t\treturn \"/* WARNING: libWrapper wrappers present! */\\n\" + _this.get_wrapped(this).toString();\n\t\t}\n\n\t\t// Cache handler\n\t\tthis._cached_handler = handler;\n\t\tthis._cached_handler_id = handler_id;\n\n\t\t// Done\n\t\treturn handler;\n\t}\n\n\tshould_skip_wrappers(obj, handler_id, is_static_dispatch) {\n\t\t// We don't need to skip wrappers if the handler is still valid\n\t\tif(handler_id == this._current_handler_id)\n\t\t\treturn false;\n\n\t\t// Sanity check\n\t\tif(handler_id > this._current_handler_id)\n\t\t\tthrow new ERRORS.internal(`Unreachable: handler_id=${handler_id} > this._current_handler_id=${this._current_handler_id}`);\n\n\t\t// Find pending calls that match this object - if any is found, skip wrappers\n\t\tif(!this.is_property) {\n\t\t\t// Check if there's any pending wrapped calls\n\t\t\tif(this._pending_wrapped_calls_cnt <= 0)\n\t\t\t\treturn false;\n\n\t\t\t// Check if our object exists in the pending wrapped calls\n\t\t\tif(!is_static_dispatch) {\n\t\t\t\tconst pend_i = this._pending_wrapped_calls.indexOf(obj);\n\t\t\t\tif(pend_i < 0)\n\t\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\n\t\treturn true;\n\t}\n\n\tskip_existing_handlers() {\n\t\tthis._current_handler_id++;\n\t}\n\n\n\n\t// Static Dispatch Chain\n\t_get_static_dispatch_chain_cache(obj) {\n\t\treturn this._static_dispatch_weakmap?.get(obj) ?? this._static_dispatch_strongmap?.get(obj);\n\t}\n\n\t_set_static_dispatch_chain_cache(obj, dispatch_chain) {\n\t\ttry {\n\t\t\tif(!this._static_dispatch_weakmap)\n\t\t\t\tthis._static_dispatch_weakmap = new WeakMap();\n\t\t\tthis._static_dispatch_weakmap.set(obj, dispatch_chain);\n\t\t}\n\t\tcatch {\n\t\t\tif(!this._static_dispatch_strongmap)\n\t\t\t\tthis._static_dispatch_strongmap = new Map();\n\t\t\tthis._static_dispatch_strongmap.set(obj, dispatch_chain);\n\t\t}\n\t}\n\n\tclear_static_dispatch_chain_cache() {\n\t\tthis._static_dispatch_weakmap?.clear ? this._static_dispatch_weakmap.clear() : delete this._static_dispatch_weakmap;\n\t\tthis._static_dispatch_strongmap?.clear();\n\t}\n\n\tget_static_dispatch_chain(obj) {\n\t\t// Properties cannot use handlers\n\t\tif(this.is_property)\n\t\t\tthrow new ERRORS.internal(`Unreachable: get_static_dispatch_chain with is_property=false`);\n\n\t\t// Obtain dispatch chain\n\t\tlet dispatch_chain = this._get_static_dispatch_chain_cache(obj);\n\n\t\t// Use the cached dispatch chain, if still valid\n\t\tif(!dispatch_chain) {\n\t\t\tdispatch_chain = this.call_wrapped.bind(this, /*state=*/ null, obj);\n\n\t\t\t// Walk wrappers in reverse order\n\t\t\tconst fn_data = this.get_fn_data(false);\n\t\t\tfor(let i = fn_data.length-1; i >= 0; i--) {\n\t\t\t\tconst data = fn_data[i];\n\t\t\t\tconst fn = data.fn;\n\n\t\t\t\t// OVERRIDE type will usually not continue the chain\n\t\t\t\tif(!data.chain)\n\t\t\t\t\tdispatch_chain = fn.bind(obj, ...(data.bind ?? []));\n\t\t\t\t// Else, bind the wrapper\n\t\t\t\telse\n\t\t\t\t\tdispatch_chain = fn.bind(obj, dispatch_chain, ...(data.bind ?? []));\n\t\t\t}\n\n\t\t\t// Cache static dispatch chain\n\t\t\tthis._set_static_dispatch_chain_cache(obj, dispatch_chain);\n\t\t}\n\n\t\t// Done\n\t\treturn dispatch_chain;\n\t}\n\n\t_calc_use_static_dispatch() {\n\t\t// Properties cannot use static dispatch\n\t\tif(this.is_property)\n\t\t\treturn false;\n\n\t\t// Do all the wrappers in fn_data specify the same, explicit, performance mode wish?\n\t\tlet perf_mode = PERF_MODES.AUTO;\n\t\tconst fn_data = this.get_fn_data(false);\n\n\t\tfor(const data of fn_data) {\n\t\t\tif(!data.perf_mode)\n\t\t\t\tcontinue;\n\n\t\t\tif(perf_mode === PERF_MODES.AUTO) {\n\t\t\t\tperf_mode = data.perf_mode;\n\t\t\t}\n\t\t\telse if(perf_mode !== data.perf_mode) {\n\t\t\t\tperf_mode = PERF_MODES.AUTO;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\t// Automatic performance mode\n\t\tif(perf_mode === PERF_MODES.AUTO) {\n\t\t\t// Default to fast mode if user explicitly enabled it\n\t\t\tif(getHighPerformanceMode())\n\t\t\t\tperf_mode = PERF_MODES.FAST;\n\n\t\t\t// Otherwise, default to normal mode\n\t\t\telse\n\t\t\t\tperf_mode = PERF_MODES.NORMAL;\n\t\t}\n\n\t\t// Enable static dispatch only in fast mode\n\t\treturn perf_mode === PERF_MODES.FAST;\n\t}\n\n\tupdate_use_static_dispatch() {\n\t\tthis.use_static_dispatch = this._calc_use_static_dispatch();\n\t}\n\n\n\n\t// Wrap/unwrap logic\n\t_wrap() {\n\t\tif(this.active)\n\t\t\treturn;\n\n\t\t// Create setter / getter functions\n\t\t// Note: We use a trick here to be able to convince the browser to name the method the way we want it\n\t\tconst getter_nm = this._callstack_name('getter');\n\t\tconst setter_nm = this._callstack_name('setter');\n\n\t\tconst _this = this;\n\t\tlet obj;\n\n\t\tif(!this.is_property) {\n\t\t\tobj = {\n\t\t\t\t[getter_nm]: _this._get_handler.bind(_this),\n\n\t\t\t\t[setter_nm]: function(value) {\n\t\t\t\t\treturn _this.set_nonproperty(value, this);\n\t\t\t\t}\n\t\t\t};\n\t\t}\n\t\telse {\n\t\t\tobj = {\n\t\t\t\t[getter_nm]: function(...args) {\n\t\t\t\t\treturn _this.call_wrapper(null, this, ...args);\n\t\t\t\t},\n\n\t\t\t\t[setter_nm]: function(...args) {\n\t\t\t\t\treturn _this.call_wrapper({setter: true}, this, ...args);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tconst getter = obj[getter_nm];\n\t\tconst setter = obj[setter_nm];\n\n\t\t// Store a reference to this in the getter so that we can support 'singleton'-like functionality\n\t\tgetter._lib_wrapper = this;\n\n\t\t// Define a property with a getter/setter\n\t\tObject.defineProperty(this.object, this.fn_name, {\n\t\t\tget: getter,\n\t\t\tset: setter,\n\t\t\tconfigurable: PROPERTIES_CONFIGURABLE\n\t\t});\n\n\t\tthis.active = true;\n\n\t\tLog.debug$?.(`Wrapped '${this.name}'.`);\n\t}\n\n\tunwrap() {\n\t\tif(!this.active)\n\t\t\treturn;\n\n\t\tif(!PROPERTIES_CONFIGURABLE)\n\t\t\tthrow new ERRORS.internal(`${PACKAGE_TITLE}: Cannot unwrap when PROPERTIES_CONFIGURABLE==false`);\n\n\n\t\t// Remove the property\n\t\tdelete this.object[this.fn_name];\n\n\t\tif(this.is_property) {\n\t\t\tObject.defineProperty(this.object, this.fn_name, {\n\t\t\t\tget: this._wrapped_getter,\n\t\t\t\tset: this._wrapped_setter,\n\t\t\t\tconfigurable: true\n\t\t\t});\n\t\t}\n\t\telse {\n\t\t\tthis.object[this.fn_name] = this._wrapped;\n\t\t}\n\n\n\t\t// Done\n\t\tthis.active = false;\n\n\t\tLog.debug$?.(`Unwrapped '${this.name}'.`);\n\t}\n\n\n\n\t// Utilities related to getting the wrapped value\n\t_get_inherited_descriptor() {\n\t\tlet iObj = Object.getPrototypeOf(this.object);\n\n\t\twhile(iObj) {\n\t\t\tconst descriptor = Object.getOwnPropertyDescriptor(iObj, this.fn_name);\n\t\t\tif(descriptor)\n\t\t\t\treturn descriptor;\n\n\t\t\tiObj = Object.getPrototypeOf(iObj);\n\t\t}\n\n\t\treturn null;\n\t}\n\n\tget_wrapped(obj, setter=false, wrapped=undefined) {\n\t\tlet result;\n\n\t\t// A non-undefined \"wrapped\" parameter is taken as-is\n\t\tif(wrapped !== undefined)\n\t\t\tresult = wrapped;\n\t\t// Otherwise we grab what is currently wrapped\n\t\telse if(this.is_property)\n\t\t\tresult = setter ? this._wrapped_setter : this._wrapped_getter;\n\t\telse\n\t\t\tresult = this._wrapped;\n\n\t\t// We convert 'null' to undefined. This means passing parameter 'wrapped==null' forces an inheritance chain search\n\t\tif(result === null)\n\t\t\tresult = undefined;\n\n\t\t// If this wrapper is 'empty', we need to search up the inheritance hierarchy for the return value\n\t\tif(result === undefined) {\n\t\t\tconst descriptor = this._get_inherited_descriptor();\n\n\t\t\tif(descriptor) {\n\t\t\t\tif(this.is_property) {\n\t\t\t\t\tif(!descriptor.get && !descriptor.set)\n\t\t\t\t\t\tthrow new ERRORS.internal(`This wrapper is set up to wrap a property, but the inherited descriptor is a method.`);\n\n\t\t\t\t\tif(setter)\n\t\t\t\t\t\tresult = descriptor.set;\n\t\t\t\t\telse\n\t\t\t\t\t\tresult = descriptor.get;\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tresult = descriptor.value ?? descriptor.get.apply(obj);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Done\n\t\tif(result === undefined)\n\t\t\tLog.warn$?.(`There is no wrapped method for '${this.name}', returning 'undefined'.`);\n\n\t\treturn result;\n\t}\n\n\n\n\t// Calling the wrapped method\n\tcall_wrapped(state, obj, ...args) {\n\t\t// Keep track of call state\n\t\tif(state)\n\t\t\tthis._call_wrapper_update_state(state);\n\n\t\t// Load necessary state\n\t\tconst is_setter = state?.setter ?? false;\n\t\tconst is_dynamic_dispatch = (!!state);\n\n\t\t// If necessary, set this wrapped call as pending\n\t\tlet pend = undefined;\n\t\tif(!this.is_property) {\n\t\t\tthis._pending_wrapped_calls_cnt++;\n\n\t\t\tif(is_dynamic_dispatch) {\n\t\t\t\tpend = obj;\n\t\t\t\tthis._pending_wrapped_calls.push(pend);\n\t\t\t}\n\t\t}\n\n\t\t// Try-catch block to handle normal exception flow\n\t\tlet result = undefined;\n\t\ttry {\n\t\t\tconst wrapped = this.get_wrapped(this.object, is_setter);\n\t\t\tresult = wrapped?.apply(obj, args);\n\t\t}\n\t\tcatch(e) {\n\t\t\tif(!this.is_property)\n\t\t\t\tthis._cleanup_call_wrapped(pend, is_dynamic_dispatch);\n\n\t\t\tthrow e;\n\t\t}\n\n\t\t// We only need to keep track of pending calls when we're not wrapping a property\n\t\tif(this.is_property)\n\t\t\treturn result;\n\n\t\t// If the result is a Promise, then we must wait until it fulfills before cleaning up.\n\t\t// Per the JS spec, the only way to detect a Promise (since Promises can be polyfilled, extended, wrapped, etc) is to look for the 'then' method.\n\t\t// Anything with a 'then' function is technically a Promise. This leaves a path for false-positives, but I don't see a way to avoid this.\n\t\tif(typeof result?.then === 'function') {\n\t\t\tresult = result.then(\n\t\t\t\t// onResolved\n\t\t\t\tv => {\n\t\t\t\t\tthis._cleanup_call_wrapped(pend, is_dynamic_dispatch);\n\t\t\t\t\treturn v;\n\t\t\t\t},\n\t\t\t\t// onRejected\n\t\t\t\te => {\n\t\t\t\t\tthis._cleanup_call_wrapped(pend, is_dynamic_dispatch);\n\t\t\t\t\tthrow e;\n\t\t\t\t}\n\t\t\t);\n\t\t}\n\t\t// Otherwise, we can immediately cleanup.\n\t\telse {\n\t\t\tthis._cleanup_call_wrapped(pend, is_dynamic_dispatch);\n\t\t}\n\n\t\t// Done\n\t\treturn result;\n\t}\n\n\t_cleanup_call_wrapped(pend, is_dynamic_dispatch) {\n\t\tif(this._pending_wrapped_calls_cnt <= 0)\n\t\t\tthrow new ERRORS.internal(`this._pending_wrapped_calls_cnt=${this._pending_wrapped_calls_cnt} should be unreachable at this point.`);\n\t\tthis._pending_wrapped_calls_cnt--;\n\n\t\tif(is_dynamic_dispatch) {\n\t\t\tconst pend_i = this._pending_wrapped_calls.indexOf(pend);\n\t\t\tif(pend_i < 0)\n\t\t\t\tthrow new ERRORS.internal(`Could not find 'pend' inside 'this._pending_wrapped_calls'.`);\n\n\t\t\tthis._pending_wrapped_calls.splice(pend_i, 1);\n\t\t}\n\t}\n\n\n\n\t// Main call wrapper logic\n\tcall_wrapper(state, obj, ...args) {\n\t\t// Keep track of call state\n\t\tif(state)\n\t\t\tthis._call_wrapper_update_state(state);\n\n\t\t// Set up basic information about this wrapper\n\t\tconst index = state?.index ?? 0;\n\t\tconst is_setter = state?.setter ?? false;\n\t\tconst fn_data = state?.fn_data ?? this.get_fn_data(is_setter);\n\n\t\t// Grab the next function data from the function data array\n\t\tconst data = fn_data[index];\n\n\t\t// If no methods exist, then finish the chain\n\t\tif(!data) {\n\t\t\tif(fn_data.length > 0)\n\t\t\t\tthrow new ERRORS.internal(`Must not have 'data===${data}' when 'fn_data.length==${fn_data.length}'.`);\n\n\t\t\t// There are no wrappers, return the wrapped value.\n\t\t\treturn this.call_wrapped(state, obj, ...args);\n\t\t}\n\n\t\t// Grab wrapper function from function data object\n\t\tconst fn = data.fn;\n\n\t\t// OVERRIDE type will usually not continue the chain\n\t\tif(!data.chain) {\n\t\t\t// Call next method in the chain\n\t\t\treturn fn.apply(obj, ...(data.bind ?? []), args);\n\t\t}\n\n\t\t// Get next index\n\t\tconst next_index = index + 1;\n\t\tconst is_last = (next_index >= fn_data.length);\n\n\t\t// Prepare the continuation of the chain\n\t\tconst next_state = {\n\t\t\tindex : next_index,\n\t\t\tcalled : false,\n\t\t\tvalid : true,\n\t\t\tsetter : is_setter,\n\t\t\tprev_data: data,\n\t\t\tfn_data : fn_data\n\t\t};\n\n\t\t// Create the next wrapper function\n\t\tconst next_fn = is_last ? this.call_wrapped.bind(this, next_state, obj) : this.call_wrapper.bind(this, next_state, obj);\n\t\tthis._outstanding_wrappers++;\n\n\t\t// Try-catch block to handle normal exception flow\n\t\tlet result = undefined;\n\t\ttry {\n\t\t\t// Call next method in the chain\n\t\t\tresult = fn.call(obj, next_fn, ...(data.bind ?? []), ...args);\n\t\t}\n\t\tcatch(e) {\n\t\t\treturn this._cleanup_call_wrapper_thrown(next_state, e);\n\t\t}\n\n\t\t// If the result is a Promise, then we must wait until it fulfills before cleaning up.\n\t\t// Per the JS spec, the only way to detect a Promise (since Promises can be polyfilled, extended, wrapped, etc) is to look for the 'then' method.\n\t\t// Anything with a 'then' function is technically a Promise. This leaves a path for false-positives, but I don't see a way to avoid this.\n\t\tif(typeof result?.then === 'function') {\n\t\t\tresult = result.then(\n\t\t\t\t// onResolved\n\t\t\t\tv => this._cleanup_call_wrapper(v, next_state, data, fn_data, next_fn, obj, args),\n\t\t\t\t// onRejected\n\t\t\t\te => this._cleanup_call_wrapper_thrown(next_state, e)\n\t\t\t);\n\t\t}\n\t\t// Otherwise, we can immediately cleanup.\n\t\telse {\n\t\t\tresult = this._cleanup_call_wrapper(result, next_state, data, fn_data, next_fn, obj, args);\n\t\t}\n\n\t\t// Done\n\t\treturn result;\n\t}\n\n\t_call_wrapper_update_state(state) {\n\t\t// Keep track of call state\n\t\tif(state.valid === false) {\n\t\t\tthrow new ERRORS.invalid_chain(\n\t\t\t\tthis,\n\t\t\t\tstate.prev_data?.package_info,\n\t\t\t\t`This wrapper function for '${this.name}' is no longer valid, and must not be called.`\n\t\t\t);\n\t\t}\n\n\t\t// Mark this state object as called\n\t\tstate.called = true;\n\t}\n\n\t_invalidate_state(state) {\n\t\tstate.valid = false;\n\n\t\tthis._outstanding_wrappers--;\n\t\tif(this._outstanding_wrappers < 0)\n\t\t\tthrow new ERRORS.internal(`Outstanding wrappers = ${this._outstanding_wrappers}, should never fall below 0.`);\n\t}\n\n\t_cleanup_call_wrapper_thrown(next_state, e) {\n\t\t// An exception/rejection causes invalidation of next_state\n\t\tthis._invalidate_state(next_state);\n\n\t\t// Re-throw\n\t\tthrow e;\n\t}\n\n\t_cleanup_call_wrapper(result, next_state, data, fn_data, next_fn, obj, args) {\n\t\t// Try-finally to ensure we invalidate the wrapper even if this logic fails\n\t\ttry {\n\t\t\t// Check that next_fn was called\n\t\t\tif(!next_state.called) {\n\t\t\t\t// We need to collect affected package information if we're collecting statistics, or we haven't warned the user of this conflict yet.\n\t\t\t\tlet collect_affected = (!data.warned_conflict || LibWrapperStats.collect_stats);\n\t\t\t\tlet affectedPackages = null;\n\t\t\t\tlet is_last_wrapper = false;\n\t\t\t\tlet notify_user = false;\n\n\t\t\t\tif(collect_affected) {\n\t\t\t\t\taffectedPackages = fn_data.slice(next_state.index).filter((x) => {\n\t\t\t\t\t\treturn !x.package_info.equals(data.package_info);\n\t\t\t\t\t}).map((x) => {\n\t\t\t\t\t\treturn x.package_info;\n\t\t\t\t\t});\n\n\t\t\t\t\tis_last_wrapper = (affectedPackages.length == 0);\n\n\t\t\t\t\tif(!is_last_wrapper)\n\t\t\t\t\t\tnotify_user = LibWrapperConflicts.register_conflict(data.package_info, affectedPackages, this, null, true);\n\t\t\t\t}\n\n\t\t\t\t// WRAPPER-type functions that do this are breaking an API requirement, as such we need to be loud about this.\n\t\t\t\t// As a \"punishment\" of sorts, we forcefully unregister them and ignore whatever they did.\n\t\t\t\tif(data.type === WRAPPER_TYPES.WRAPPER) {\n\t\t\t\t\t// We automatically trigger an unhandled error since we don't want to throw\n\t\t\t\t\tconst error = new ERRORS.package(\n\t\t\t\t\t\t`The wrapper for '${data.target}' registered by ${data.package_info.type_plus_id} with type WRAPPER did not chain the call to the next wrapper, which breaks a libWrapper API requirement. This wrapper will be unregistered.`,\n\t\t\t\t\t\tdata.package_info\n\t\t\t\t\t);\n\t\t\t\t\tonUnhandledError(error);\n\t\t\t\t\tLog.error$?.(error);\n\n\t\t\t\t\t// Unregister this module\n\t\t\t\t\tglobalThis.libWrapper.unregister(data.package_info.id, this.get_id(data.setter));\n\n\t\t\t\t\t// Manually chain to the next wrapper if there are more in the chain\n\t\t\t\t\tif(!is_last_wrapper)\n\t\t\t\t\t\tresult = next_fn.apply(obj, args);\n\t\t\t\t}\n\n\t\t\t\t// Other WRAPPER_TYPES get a generic 'conflict' message\n\t\t\t\telse if(notify_user && !data.warned_conflict) {\n\t\t\t\t\tLibWrapperNotifications.conflict(data.package_info, affectedPackages, true, `${data.package_info.type_plus_id_capitalized} did not chain the wrapper for '${data.target}'.`);\n\t\t\t\t\tdata.warned_conflict = true;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tfinally {\n\t\t\t// Invalidate state to avoid asynchronous calls\n\t\t\tthis._invalidate_state(next_state);\n\t\t}\n\n\t\t// Done\n\t\treturn result;\n\t}\n\n\n\n\t// Non-property setter\n\tset_nonproperty(value, obj=null) {\n\t\tif(this.is_property)\n\t\t\tthrow new ERRORS.internal('Must not call \\'set_nonproperty\\' for a property wrapper.');\n\n\t\tconst inherited = (obj !== this.object);\n\n\t\t// If assigning to an instance directly, assign directly to instance\n\t\tif(inherited) {\n\t\t\tObject.defineProperty(obj, this.fn_name, {\n\t\t\t\tvalue: value,\n\t\t\t\tconfigurable: true,\n\t\t\t\tenumerable: true,\n\t\t\t\twritable: true\n\t\t\t});\n\n\t\t\treturn;\n\t\t}\n\n\t\t// Wrap the new value\n\t\tthis._wrapped = value;\n\t\tthis.skip_existing_handlers();\n\n\t\t// Warn user and/or log conflict\n\t\tthis.warn_classic_wrapper();\n\t}\n\n\n\n\t// Conflict logging utilities\n\tget_affected_packages() {\n\t\tconst affectedPackages = this.getter_data.map((x) => {\n\t\t\treturn x.package_info;\n\t\t});\n\n\t\treturn affectedPackages;\n\t}\n\n\twarn_classic_wrapper() {\n\t\tconst package_info = new PackageInfo();\n\t\tconst affectedPackages = this.get_affected_packages();\n\n\t\tif(affectedPackages.length > 0) {\n\t\t\tconst notify_user = LibWrapperConflicts.register_conflict(package_info, affectedPackages, this, null, true);\n\n\t\t\tif(notify_user) {\n\t\t\t\tLibWrapperNotifications.conflict(package_info, affectedPackages, true, `Detected non-libWrapper wrapping of '${this.name}' by ${package_info.type_plus_id}. This will potentially lead to conflicts.`);\n\t\t\t\tLog.trace();\n\t\t\t}\n\t\t}\n\n\t\tif(!this.detected_classic_wrapper)\n\t\t\tthis.detected_classic_wrapper = []\n\t\tthis.detected_classic_wrapper.push(package_info.key);\n\t}\n\n\n\n\t// Wraper array methods\n\t// NOTE: These should only ever be called from libWrapper, they do not clean up after themselves\n\tget_fn_data(setter, to_modify=false) {\n\t\t// to_modify=true must be used any time the fn_data array will be modified.\n\t\t// If there are any outstanding wrapper calls, this will force the creation of a copy of the array, to avoid affecting said outstanding wrapper calls.\n\n\t\t// Sanity check\n\t\tif(setter && !this.is_property)\n\t\t\tthrow new ERRORS.internal(`'${this.name}' does not wrap a property, thus setter=true is illegal.`);\n\n\t\t// Get current fn_data\n\t\tconst prop_nm = setter ? 'setter_data' : 'getter_data';\n\t\tlet result = this[prop_nm];\n\n\t\t// If we are going to modify the return result...\n\t\tif(to_modify) {\n\t\t\t// Duplicate fn_data if we are modifying it and there are outstanding wrappers\n\t\t\tif(this._outstanding_wrappers > 0) {\n\t\t\t\tresult = this[prop_nm].slice(0);\n\t\t\t\tthis[prop_nm] = result;\n\t\t\t}\n\t\t}\n\n\t\t// Done\n\t\treturn result;\n\t}\n\n\t_post_update_fn_data() {\n\t\tthis.update_use_static_dispatch();\n\t\tthis.clear_static_dispatch_chain_cache();\n\t}\n\n\tsort() {\n\t\tfor(let setter of [false, true]) {\n\t\t\tif(setter && !this.is_property)\n\t\t\t\tcontinue;\n\n\t\t\tlet fn_data = this.get_fn_data(setter);\n\t\t\tfn_data.sort((a,b) => { return a.type.value - b.type.value || b.priority - a.priority });\n\t\t}\n\t}\n\n\tadd(data) {\n\t\t// Try to set a function name if there is none already\n\t\tconst fn = data.fn;\n\t\tif(!fn.name || fn.name === 'anonymous')\n\t\t\tset_function_name(fn, this._callstack_name(data.package_info.id ?? '<unknown>'));\n\n\t\t// Add to fn_data\n\t\tconst fn_data = this.get_fn_data(data.setter, true);\n\n\t\tfn_data.splice(0, 0, data);\n\t\tthis.sort(data.setter);\n\n\t\tthis._post_update_fn_data();\n\t}\n\n\tremove(data) {\n\t\tconst fn_data = this.get_fn_data(data.setter, true);\n\n\t\tconst index = fn_data.indexOf(data);\n\t\tfn_data.splice(index, 1);\n\n\t\tthis._post_update_fn_data();\n\t}\n\n\tclear() {\n\t\tthis.getter_data = [];\n\n\t\tif(this.is_property)\n\t\t\tthis.setter_data = [];\n\n\t\tthis._post_update_fn_data();\n\t}\n\n\tis_empty() {\n\t\treturn !this.getter_data.length && !this.setter_data?.length;\n\t}\n};\ndecorate_class_function_names(Wrapper);\n\n// Prevent modifications\nObject.freeze(Wrapper);","// SPDX-License-Identifier: LGPL-3.0-or-later\n// Copyright © 2021 fvtt-lib-wrapper Rui Pinheiro\n\n'use strict';\n\nimport { VERSION } from '../shared/version.js';\nimport { PACKAGE_ID, PACKAGE_TITLE } from '../consts.js';\nimport { LibWrapperStats } from './stats.js';\nimport { WRAPPERS } from '../lib/storage.js';\nimport { PackageInfo, PACKAGE_TYPES } from '../shared/package_info.js';\nimport { i18n } from '../shared/i18n.js';\nimport { Log } from '../shared/log.js';\n\n// Map of currently loaded priorities\nexport const PRIORITIES = new Map();\n\n\nfunction is_valid_priority_key_data(key, data) {\n\tif(!PackageInfo.is_valid_key_or_id(key))\n\t\treturn false;\n\n\tif(!data)\n\t\treturn false;\n\n\tif(typeof data.id !== 'string' || typeof data.title !== 'string' || typeof data.index !== 'number')\n\t\treturn false;\n\n\treturn true;\n}\n\nexport const load_priorities = function(value=null) {\n\t// Create existing priorities\n\tPRIORITIES.clear();\n\n\t// Parse config\n\tconst priority_cfg = value ?? game?.settings?.get(PACKAGE_ID, 'module-priorities');\n\tif(!priority_cfg)\n\t\treturn;\n\n\tfor(let type of ['prioritized', 'deprioritized']) {\n\t\tconst current = priority_cfg[type];\n\t\tif(!current)\n\t\t\tcontinue;\n\n\t\tconst base_priority = (type == 'prioritized') ? 10000 : -10000;\n\n\t\tlet new_current = null;\n\t\tObject.entries(current).forEach(entry => {\n\t\t\tlet [key, data] = entry;\n\n\t\t\t// Check key/data validity\n\t\t\tif(!is_valid_priority_key_data(key, data)) {\n\t\t\t\tLog.warn$?.(`Ignoring '${key}' entry while loading module priorities due to invalid format.`)\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Add to priorities dictionary\n\t\t\tif(PRIORITIES.has(key))\n\t\t\t\treturn;\n\n\t\t\tPRIORITIES.set(key, base_priority - data.index);\n\t\t});\n\t}\n}\n\n\n\n// Main settings class\nexport class LibWrapperSettings extends FormApplication {\n\tstatic init() {\n\t\tgame.settings.register(PACKAGE_ID, 'notify-issues-gm', {\n\t\t\tname: `${PACKAGE_ID}.settings.notify-issues-gm.name`,\n\t\t\thint: `${PACKAGE_ID}.settings.notify-issues-gm.hint`,\n\t\t\tdefault: true,\n\t\t\ttype: Boolean,\n\t\t\tscope: 'world',\n\t\t\tconfig: true,\n\t\t});\n\n\t\tgame.settings.register(PACKAGE_ID, 'notify-issues-player', {\n\t\t\tname: `${PACKAGE_ID}.settings.notify-issues-player.name`,\n\t\t\thint: `${PACKAGE_ID}.settings.notify-issues-player.hint`,\n\t\t\tdefault: false,\n\t\t\ttype: Boolean,\n\t\t\tscope: 'world',\n\t\t\tconfig: true,\n\t\t});\n\n\t\tgame.settings.register(PACKAGE_ID, 'high-performance-mode', {\n\t\t\tname: `${PACKAGE_ID}.settings.high-performance-mode.name`,\n\t\t\thint: `${PACKAGE_ID}.settings.high-performance-mode.hint`,\n\t\t\tdefault: false,\n\t\t\ttype: Boolean,\n\t\t\tscope: 'world',\n\t\t\tconfig: true,\n\t\t});\n\n\t\tgame.settings.register(PACKAGE_ID, 'log-verbosity', {\n\t\t\tname: `${PACKAGE_ID}.settings.log-verbosity.name`,\n\t\t\thint: `${PACKAGE_ID}.settings.log-verbosity.hint`,\n\t\t\tdefault: Log.WARNING.value,\n\t\t\ttype: Number,\n\t\t\tchoices: {\n\t\t\t\t// NOTE: Some choices removed as too much choice will just confuse users or make technical support more difficult.\n\t\t\t\t// For example, I don't want users to disable errors accidentally, and then ask for support without any error messages showing up on console.\n\n\t\t\t\t0 : i18n.localize(`${PACKAGE_ID}.settings.log-verbosity.choices.all`),\n\t\t\t\t//[Log.TRACE .value]: i18n.localize(`${PACKAGE_ID}.settings.log-verbosity.choices.trace`),\n\t\t\t\t[Log.DEBUG .value]: i18n.localize(`${PACKAGE_ID}.settings.log-verbosity.choices.debug`),\n\t\t\t\t[Log.INFO .value]: i18n.localize(`${PACKAGE_ID}.settings.log-verbosity.choices.info`),\n\t\t\t\t[Log.WARNING .value]: i18n.localize(`${PACKAGE_ID}.settings.log-verbosity.choices.warning`),\n\t\t\t\t//[Log.ERROR .value]: i18n.localize(`${PACKAGE_ID}.settings.log-verbosity.choices.error`),\n\t\t\t\t//[Log.CRITICAL.value]: i18n.localize(`${PACKAGE_ID}.settings.log-verbosity.choices.critical`),\n\t\t\t\t//[Log.ALWAYS .value]: i18n.localize(`${PACKAGE_ID}.settings.log-verbosity.choices.always`),\n\t\t\t},\n\t\t\tscope: 'client',\n\t\t\tconfig: true,\n\t\t\tonChange: _ => Log.init(/*force=*/ true)\n\t\t});\n\n\t\tgame.settings.registerMenu(PACKAGE_ID, 'menu', {\n\t\t\tname: '',\n\t\t\tlabel: `${PACKAGE_ID}.settings.menu.title`,\n\t\t\ticon: \"fas fa-cog\",\n\t\t\ttype: LibWrapperSettings,\n\t\t\trestricted: true\n\t\t});\n\n\t\tgame.settings.register(PACKAGE_ID, 'module-priorities', {\n\t\t\tname: '',\n\t\t\tdefault: {},\n\t\t\ttype: Object,\n\t\t\tscope: 'world',\n\t\t\tconfig: false,\n\t\t\tonChange: _ => load_priorities()\n\t\t});\n\n\t\t// Variables\n\t\tthis.show_ignored_conflicts = false;\n\n\t\t// When done, calculate the logging verbosity\n\t\tLog.init();\n\n\t\t// When done, load the priorities\n\t\tload_priorities();\n\n\t\t// Seal to prevent accidental modification\n\t\tObject.seal(this);\n\t}\n\n\n\t// Settings UI\n\tstatic get defaultOptions() {\n\t\treturn {\n\t\t\t...super.defaultOptions,\n\t\t\ttemplate: `modules/${PACKAGE_ID}/templates/settings.html`,\n\t\t\theight: 700,\n\t\t\ttitle: i18n.localize(`${PACKAGE_ID}.settings.menu.title`),\n\t\t\twidth: 600,\n\t\t\tclasses: [PACKAGE_ID, \"settings\"],\n\t\t\ttabs: [\n\t\t\t\t{\n\t\t\t\t\tnavSelector: '.tabs',\n\t\t\t\t\tcontentSelector: 'form',\n\t\t\t\t\tinitial: 'name'\n\t\t\t\t}\n\t\t\t],\n\t\t\tsubmitOnClose: false,\n\t\t\tcloseOnSubmit: false\n\t\t}\n\t}\n\n\tconstructor(object = {}, options) {\n\t\tsuper(object, options);\n\t}\n\n\tstatic showYesNoDialog(msg, yes_callback) {\n\t\tnew Dialog({\n\t\t\tcontent: msg,\n\t\t\tbuttons: {\n\t\t\t\tyes: {\n\t\t\t\t\ticon: '<i class=\"fas fa-check\"></i>',\n\t\t\t\t\tlabel: i18n.localize(`${PACKAGE_ID}.settings.yes`),\n\t\t\t\t\tcallback: yes_callback\n\t\t\t\t},\n\t\t\t\tno: {\n\t\t\t\t\ticon: '<i class=\"fas fa-times\"></i>',\n\t\t\t\t\tlabel: i18n.localize(`${PACKAGE_ID}.settings.no`)\n\t\t\t\t}\n\t\t\t}\n\t\t}).render(true);\n\t}\n\n\tgetActiveWrappers() {\n\t\tlet data = [];\n\n\t\tWRAPPERS.forEach((wrapper) => {\n\t\t\tfor(let is_setter of [false, true]) {\n\t\t\t\tif(is_setter && !wrapper.is_property)\n\t\t\t\t\tcontinue;\n\n\t\t\t\t// Obtain list of packages\n\t\t\t\tconst packages = [];\n\n\t\t\t\twrapper.get_fn_data(is_setter).forEach((fn_data) => {\n\t\t\t\t\tif(fn_data.package_info.id == PACKAGE_ID)\n\t\t\t\t\t\treturn;\n\n\t\t\t\t\tconst d = {\n\t\t\t\t\t\tname : fn_data.package_info.settingsName,\n\t\t\t\t\t\ttype : fn_data.type.name,\n\t\t\t\t\t\tperf_mode: fn_data.perf_mode.name\n\t\t\t\t\t};\n\n\t\t\t\t\tif(d.perf_mode == 'AUTO')\n\t\t\t\t\t\td.perf_mode = null;\n\t\t\t\t\telse\n\t\t\t\t\t\td.perf_mode = `, ${d.perf_mode}`;\n\n\t\t\t\t\tpackages.push(d);\n\t\t\t\t});\n\n\t\t\t\tif(wrapper.detected_classic_wrapper) {\n\t\t\t\t\twrapper.detected_classic_wrapper.forEach((key) => {\n\t\t\t\t\t\tpackages.push({\n\t\t\t\t\t\t\tname : new PackageInfo(key).settingsName,\n\t\t\t\t\t\t\ttype : 'MANUAL',\n\t\t\t\t\t\t\tperf_mode: null\n\t\t\t\t\t\t});\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\t// We only need to show this to the user if there is at least one active package\n\t\t\t\tif(packages.length <= 0)\n\t\t\t\t\tcontinue;\n\n\t\t\t\t// Obtain remaining information\n\t\t\t\tconst id = wrapper.get_id(is_setter);\n\t\t\t\tconst names = wrapper.get_names(is_setter);\n\n\t\t\t\tdata.push({\n\t\t\t\t\tid : id,\n\t\t\t\t\tname : names[0],\n\t\t\t\t\tnames : names.slice(1),\n\t\t\t\t\tpackages: packages\n\t\t\t\t});\n\t\t\t}\n\t\t});\n\n\t\tdata.sort((a,b) => b.packages.length - a.packages.length);\n\n\t\treturn data;\n\t}\n\n\tgetConflicts() {\n\t\tif(!LibWrapperStats.collect_stats)\n\t\t\treturn null;\n\n\t\tlet data = [];\n\n\t\tLibWrapperStats.conflicts.forEach((conflict) => {\n\t\t\tlet total = conflict.count;\n\t\t\tif(this.show_ignored_conflicts)\n\t\t\t\ttotal += conflict.ignored;\n\n\t\t\tif(total == 0)\n\t\t\t\treturn;\n\n\t\t\tconst targets = [];\n\n\t\t\tdata.push({\n\t\t\t\tcount: conflict.count,\n\t\t\t\tignored: this.show_ignored_conflicts ? conflict.ignored : 0,\n\t\t\t\ttotal: total,\n\t\t\t\tpackage_id: conflict.package_info.settingsName,\n\t\t\t\tother_id: conflict.other_info.settingsName,\n\t\t\t\ttargets: targets\n\t\t\t});\n\n\t\t\tconflict.targets.forEach((obj, target) => {\n\t\t\t\tlet obj_total = obj.count;\n\t\t\t\tif(this.show_ignored_conflicts)\n\t\t\t\t\tobj_total += obj.ignored;\n\n\t\t\t\tif(obj_total > 0)\n\t\t\t\t\ttargets.push({\n\t\t\t\t\t\ttarget: target,\n\t\t\t\t\t\tcount: obj.count,\n\t\t\t\t\t\ttotal: obj_total,\n\t\t\t\t\t\tignored: this.show_ignored_conflicts ? obj.ignored : 0\n\t\t\t\t\t});\n\t\t\t});\n\n\t\t\ttargets.sort((a,b) => a.total - b.total);\n\t\t});\n\n\t\tdata.sort((a,b) => a.total - b.total);\n\n\t\treturn data;\n\t}\n\n\tgetPackages() {\n\t\tlet ret = {\n\t\t\tprioritized: [],\n\t\t\tnormal: [],\n\t\t\tdeprioritized: []\n\t\t};\n\n\t\tconst priorities = game.settings.get(PACKAGE_ID, 'module-priorities');\n\t\tconst cfg_prioritized = priorities.prioritized ?? {};\n\t\tconst cfg_deprioritized = priorities.deprioritized ?? {};\n\n\t\tconst inactive = i18n.localize(`${PACKAGE_ID}.settings.menu.priorities.package-inactive`);\n\n\t\t// Normal packages\n\t\tif(LibWrapperStats.collect_stats) {\n\t\t\tLibWrapperStats.packages.forEach((key) => {\n\t\t\t\tconst info = new PackageInfo(key);\n\n\t\t\t\tif(info.key in cfg_prioritized || info.key in cfg_deprioritized)\n\t\t\t\t\treturn;\n\n\t\t\t\tret.normal.push(info);\n\t\t\t});\n\t\t\tret.normal.sort((a,b) => a.id.localeCompare(b.id));\n\t\t}\n\n\t\t// Prioritized packages\n\t\tObject.entries(cfg_prioritized).forEach((entry) => {\n\t\t\tlet [key, data] = entry;\n\n\t\t\t// Check key/data validity\n\t\t\tif(!is_valid_priority_key_data(key, data)) {\n\t\t\t\tLog.warn$?.(`Ignoring '${key}' entry while loading module priorities due to invalid format.`)\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Push data\n\t\t\tret.prioritized.push({\n\t\t\t\tkey : key,\n\t\t\t\tid : data.id,\n\t\t\t\ttitle: data.title ?? `${data.title} <${inactive}>`,\n\t\t\t\tindex: data.index\n\t\t\t});\n\t\t});\n\t\tret.prioritized.sort((a,b) => { return a.index - b.index });\n\n\t\t// Deprioritized packages\n\t\tObject.entries(cfg_deprioritized).forEach((entry) => {\n\t\t\tlet [key, data] = entry;\n\n\t\t\t// In case something went wrong and we have a duplicate package\n\t\t\tif(key in cfg_prioritized)\n\t\t\t\treturn;\n\n\t\t\t// Check key/data validity\n\t\t\tif(!is_valid_priority_key_data(key, data)) {\n\t\t\t\tLog.warn$?.(`Ignoring '${key}' entry while loading module priorities due to invalid format.`)\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Push data\n\t\t\tret.deprioritized.push({\n\t\t\t\tkey : key,\n\t\t\t\tid : data.id,\n\t\t\t\ttitle: data.title ?? `${data.title} <${inactive}>`,\n\t\t\t\tindex: data.index\n\t\t\t});\n\t\t});\n\t\tret.deprioritized.sort((a,b) => { return a.index - b.index });\n\n\t\t// Done\n\t\treturn ret;\n\t}\n\n\tgetData() {\n\t\t// Prepare the list of help links\n\t\tconst support_list = [];\n\t\t{\n\t\t\tconst key = `${PACKAGE_ID}.support-channels`;\n\t\t\tconst list = i18n.localize(key);\n\t\t\tif(Array.isArray(list)) {\n\t\t\t\tfor(const entry of list) {\n\t\t\t\t\tif(!('title' in entry) || !('url' in entry))\n\t\t\t\t\t\tcontinue;\n\n\t\t\t\t\tsupport_list.push(entry);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Create data object\n\t\tlet data = {\n\t\t\tabout: {\n\t\t\t\tname: PACKAGE_TITLE,\n\t\t\t\tversion: VERSION.full_git,\n\t\t\t\tcollect_stats: LibWrapperStats.collect_stats,\n\t\t\t\ttranslation_credits: i18n.localize(`${PACKAGE_ID}.settings.menu.about.credits-translation`),\n\t\t\t\tsupport: support_list\n\t\t\t},\n\n\t\t\twrappers: this.getActiveWrappers(),\n\t\t\tconflicts: this.getConflicts(),\n\t\t\tpackages: this.getPackages(),\n\t\t\tshow_ignored_conflicts: this.show_ignored_conflicts\n\t\t};\n\n\t\treturn data;\n\t}\n\n\tactivateListeners(html) {\n\t\tsuper.activateListeners(html);\n\n\t\tlet _this = this;\n\n\t\t// Tree view\n\t\thtml.find('.caret.has-nested').on('click', function(event) {\n\t\t\tconst $this = $(this);\n\n\t\t\t$this.parent().find('.nested').toggleClass('active');\n\t\t\t$this.toggleClass('caret-down');\n\t\t});\n\n\t\t// Reload button\n\t\thtml.find('button.reload').on('click', function(event) {\n\t\t\t_this.render(true);\n\t\t});\n\n\t\t// Show ignored conflicts checkbox\n\t\thtml.find('.lw-show-ignored-conflicts').on('change', function(event) {\n\t\t\tconst $this = $(this);\n\t\t\tconst checkbox = $this.find('input[type=checkbox]');\n\t\t\tconst checked = checkbox.prop('checked');\n\n\t\t\t_this.show_ignored_conflicts = checked;\n\t\t\t_this.render(true);\n\t\t});\n\n\t\t// Easily focus the priority groups\n\t\thtml.find('.package-priority-group').on('click', function(event) {\n\t\t\tconst $this = $(this);\n\n\t\t\tconst select = $this.find('select');\n\n\t\t\tif(!select.is(':focus'))\n\t\t\t\tselect.focus();\n\t\t});\n\n\t\t// Change priority buttons\n\t\thtml.find('button.change-priority').on('click', function(event) {\n\t\t\tconst $this = $(this);\n\n\t\t\tconst which = $this.data('which');\n\t\t\tconst direction = $this.data('direction');\n\t\t\tconst up = (direction === 'up');\n\n\t\t\tconst list = html.find(`.${which}`);\n\t\t\tconst selected = list.find('option:selected');\n\n\t\t\tconst insertPos = up ? selected.prev() : selected.next();\n\n\t\t\tif(!insertPos.length)\n\t\t\t\treturn;\n\n\t\t\tif(up)\n\t\t\t\tinsertPos.before(selected);\n\t\t\telse\n\t\t\t\tinsertPos.after(selected);\n\t\t});\n\n\t\t// Change category buttons\n\t\thtml.find('button.change-category').on('click', function(event) {\n\t\t\tconst $this = $(this);\n\n\t\t\tconst _from = $this.data('from');\n\t\t\tconst _to = $this.data('to');\n\n\t\t\tconst from = html.find(`.${_from}`);\n\t\t\tconst to = html.find(`.${_to}`);\n\n\t\t\tconst element = from.find('option:selected');\n\n\t\t\t// Search for the element to focus next\n\t\t\tlet next_focus = element.next();\n\t\t\tif(next_focus.length == 0)\n\t\t\t\tnext_focus = element.prev();\n\n\t\t\t// Move to the destination list\n\t\t\tto.append(element);\n\n\t\t\t// If the destination was the 'normal', we need to sort it alphabetically\n\t\t\tif(_to == 'packages-normal') {\n\t\t\t\tconst options = to.find('option');\n\t\t\t\toptions.sort((a,b) => { return $(a).val() > $(b).val() ? 1 : -1 });\n\t\t\t\tto.empty().append(options);\n\t\t\t}\n\n\t\t\t// Focus the previous list again\n\t\t\tif(next_focus.length)\n\t\t\t\tfrom.val(next_focus.val());\n\n\t\t\tfrom.focus();\n\t\t});\n\n\t\t// Submit 'Priorities'\n\t\thtml.find('.submit').on('click', function(event) {\n\t\t\t// Collect prioritization order into hidden fields that will be submitted\n\t\t\tfor(let type of ['packages-prioritized', 'packages-deprioritized']) {\n\t\t\t\tconst select = html.find(`.${type}`);\n\n\t\t\t\tconst options = select.find('option');\n\n\t\t\t\tlet arr = [];\n\t\t\t\toptions.each((i, option) => {\n\t\t\t\t\tarr.push($(option).val());\n\t\t\t\t});\n\n\t\t\t\t$('<input>').attr('type', 'hidden').attr('name', `${type}-hidden`).attr('value', arr.join(',')).appendTo(html);\n\t\t\t}\n\n\t\t\thtml.submit();\n\t\t});\n\n\t\t// Reset button\n\t\thtml.find('.reset').on('click', function(event) {\n\t\t\t$('input[type=hidden]').remove();\n\n\t\t\tLibWrapperSettings.showYesNoDialog(`<p>${i18n.localize(`${PACKAGE_ID}.settings.menu.warning-reset-priorities`)}</p>`, () => {\n\t\t\t\tfor(let type of ['packages-prioritized', 'packages-deprioritized']) {\n\t\t\t\t\t$('<input>').attr('type', 'hidden').attr('name', `${type}-hidden`).attr('value', '').appendTo(html);\n\t\t\t\t}\n\n\t\t\t\thtml.submit();\n\t\t\t});\n\t\t});\n\t}\n\n\tasync _updateObject(ev, formData) {\n\t\t// Parse priorities\n\t\tconst priorities = game.settings.get(PACKAGE_ID, 'module-priorities');\n\n\t\tfor(let type of ['prioritized', 'deprioritized']) {\n\t\t\tconst fld = `packages-${type}-hidden`;\n\n\t\t\tif(!(fld in formData))\n\t\t\t\tcontinue;\n\n\t\t\tconst value = formData[fld];\n\t\t\tconst split = (value === '') ? [] : value.split(',');\n\n\t\t\tlet old_prio = priorities[type] ?? {};\n\t\t\tlet new_prio = {};\n\t\t\tlet counter = 0;\n\n\t\t\tsplit.forEach((key) => {\n\t\t\t\tif(!key)\n\t\t\t\t\treturn;\n\n\t\t\t\tconst old_data = old_prio[key];\n\t\t\t\tconst new_data = new PackageInfo(key);\n\n\t\t\t\tnew_prio[key] = {\n\t\t\t\t\tid : new_data.id,\n\t\t\t\t\ttitle: new_data.exists ? new_data.title : old_data.title,\n\t\t\t\t\tindex: counter++\n\t\t\t\t};\n\t\t\t});\n\n\t\t\tpriorities[type] = new_prio;\n\t\t}\n\n\t\t// Sanity check for duplicates\n\t\tObject.keys(priorities.deprioritized).forEach((key) => {\n\t\t\tif(key in priorities.prioritized)\n\t\t\t\tdelete priorities.deprioritized[key];\n\t\t});\n\n\t\t// Save\n\t\tawait game.settings.set(PACKAGE_ID, 'module-priorities', priorities);\n\n\t\t// Re-render\n\t\tthis.render(true);\n\n\t\t// Ask user to refresh page\n\t\tLibWrapperSettings.showYesNoDialog(`<p>${i18n.localize(`${PACKAGE_ID}.settings.menu.warning-save`)}</p>`, () => location.reload());\n\t}\n}","// SPDX-License-Identifier: LGPL-3.0-or-later\n// Copyright © 2021 fvtt-lib-wrapper Rui Pinheiro\n\n'use strict';\n\nimport {\n//#if !_ROLLUP\n\tparse_manifest_version,\n//#endif\n\tVERSION, version_at_least\n} from '../shared/version.js';\n\nimport {\n\tPACKAGE_ID, HOOKS_SCOPE, IS_UNITTEST, PROPERTIES_CONFIGURABLE,\n} from '../consts.js';\n\nimport { WRAPPER_TYPES, PERF_MODES } from './enums.js';\nimport { Wrapper } from './wrapper.js';\nimport { WRAPPERS } from './storage.js';\nimport { get_global_variable, decorate_name, decorate_class_function_names } from '../utils/misc.js';\nimport { PackageInfo, PACKAGE_TYPES } from '../shared/package_info.js';\n\nimport { init_error_listeners, onUnhandledError } from '../errors/listeners.js';\nimport { ERRORS } from '../errors/errors.js';\n\nimport { LibWrapperNotifications } from '../ui/notifications.js'\nimport { LibWrapperStats } from '../ui/stats.js';\nimport { LibWrapperConflicts } from '../ui/conflicts.js';\nimport { LibWrapperSettings, PRIORITIES } from '../ui/settings.js';\nimport { i18n } from '../shared/i18n.js';\nimport { Log } from '../shared/log.js';\n\n\n\n// Internal variables\nlet libwrapper_ready = false;\nlet allow_libwrapper_registrations = true;\n\n\n// Regexes used in _get_target_object\nconst TGT_SPLIT_RE = new RegExp([\n\t'(', // {\n\t\t'[^.[]+', // Match anything not containing a . or [\n\t'|', // |\n\t\t'\\\\[', // Match anything starting with [\n\t\t'(', // {\n\t\t\t\"'\", // Followed by a '\n\t\t\t'(', // {\n\t\t\t\t'[^\\'\\\\\\\\]', // That does not contain ' or \\\n\t\t\t'|', // |\n\t\t\t\t'\\\\\\\\.', // Ignore any character that is escaped by \\\n\t\t\t')+?', // } (Non-greedy)\n\t\t\t\"'\", // Ending in a '\n\t\t'|', // |\n\t\t\t'\"', // Followed by a \"\n\t\t\t'(', // {\n\t\t\t\t'[^\"\\\\\\\\]', // That does not contain \" or \\\n\t\t\t'|', // |\n\t\t\t\t'\\\\\\\\.', // Ignore any character that is escaped by \\\n\t\t\t')+?', // } (Non-greedy)\n\t\t\t'\"', // Ending in a \"\n\t\t')', // }\n\t\t'\\\\]', // And ending with ]\n\t')' // }\n].join(''), 'g');\n\nconst TGT_CLEANUP_RE = new RegExp([\n\t'(', // {\n\t\t'^\\\\[\\'', // Anything starting with ['\n\t'|', // |\n\t\t'\\'\\\\]$', // Anything ending with ']\n\t'|', // |\n\t\t'^\\\\[\"', // Anything starting with [\"\n\t'|', // |\n\t\t'\"\\\\]$', // Anything ending with \"]\n\t')' // }\n].join(''), 'g');\n\n\n// Internal Methods\nexport function _create_wrapper_from_object(obj, fn_name, name=undefined, package_info=undefined) {\n\tconst wrapper = new Wrapper(obj, fn_name, name, package_info);\n\tWRAPPERS.add(wrapper);\n\treturn wrapper;\n}\n\nfunction _split_target_and_setter(target) {\n\tlet is_setter = target.endsWith('#set');\n\tlet _target = !is_setter ? target : target.slice(0, -4);\n\n\treturn [_target, is_setter];\n}\n\nfunction _valid_root_scope_string(str) {\n\treturn /^[a-zA-Z_$][0-9a-zA-Z_$]*$/.test(str);\n}\n\nfunction _valid_target_string(str) {\n\treturn /^[a-zA-Z_$][0-9a-zA-Z_$]*?([.[]|$)/.test(str);\n}\n\nfunction _get_target_object(_target, package_info=undefined) {\n\t// Parse the target\n\tconst target = _split_target_and_setter(_target)[0];\n\tif(!_valid_target_string(target))\n\t\tthrow new ERRORS.package(`Invalid target '${target}'.`, package_info);\n\n\t// Split the target\n\tconst split = target.match(TGT_SPLIT_RE).map((x)=>x.replace(/\\\\(.)/g, '$1').replace(TGT_CLEANUP_RE,''));\n\n\t// Get root object\n\tconst root_nm = split.splice(0,1)[0]; // equivalent to 'split.pop_front()' which JS doesn't have\n\tif(!_valid_root_scope_string(root_nm))\n\t\tthrow new ERRORS.package(`Invalid target '${target}': Invalid root scope '${root_nm}'.`, package_info);\n\tif(root_nm == 'libWrapper')\n\t\tthrow new ERRORS.package(`Not allowed to wrap libWrapper internals.`, package_info);\n\n\t// Figure out the object and function name we want to wrap\n\tlet obj, fn_name;\n\tif(split.length == 0) {\n\t\t// In order to wrap something in global scope, it must be accessible from 'globalThis'\n\t\tif(!(root_nm in globalThis))\n\t\t\tthrow new ERRORS.package(`Could not find target '${target}': Could not find scope 'globalThis.${root_nm}'.`, package_info);\n\n\t\tfn_name = root_nm;\n\t\tobj = globalThis;\n\t}\n\telse {\n\t\t// Get function name\n\t\tfn_name = split.pop();\n\n\t\t// Get root variable\n\t\tconst root = get_global_variable(root_nm);\n\t\tif(!root)\n\t\t\tthrow new ERRORS.package(`Could not find target '${target}': Could not find root scope '${root_nm}'.`, package_info);\n\n\t\t// Get target object\n\t\tobj = root;\n\t\tfor(const scope of split) {\n\t\t\tobj = obj[scope];\n\t\t\tif(!obj)\n\t\t\t\tthrow new ERRORS.package(`Could not find target '${target}': Could not find scope '${scope}'.`, package_info);\n\t\t}\n\t}\n\n\t// Done\n\treturn [obj, fn_name, target];\n}\n\nfunction _create_wrapper(target, package_info=undefined) {\n\t// Get target information\n\tconst tgt_info = _get_target_object(target, package_info);\n\n\t// Create wrapper\n\treturn _create_wrapper_from_object(...tgt_info, package_info);\n}\n\nfunction _get_target_from_info(obj, fn_name) {\n\tconst descriptor = Object.getOwnPropertyDescriptor(obj, fn_name);\n\treturn descriptor?.get?._lib_wrapper ?? null;\n}\n\nexport function _find_wrapper_by_name(_name, package_info=undefined) {\n\t// Get target information\n\tconst tgt_info = _get_target_object(_name, package_info);\n\n\t// Return target wrapper\n\treturn _get_target_from_info(...tgt_info);\n}\n\nfunction _find_wrapper_by_id(id) {\n\tconst wrapper = WRAPPERS.find_by_id(id);\n\treturn [wrapper, (id === wrapper?.setter_id)];\n}\n\nfunction _find_package_data_in_wrapper(package_info, wrapper, is_setter) {\n\treturn wrapper.get_fn_data(is_setter).find((x) => x.package_info?.equals(package_info));\n}\n\nfunction _find_package_data_with_target(package_info, target) {\n\tlet wrapper = null;\n\tlet is_setter;\n\n\tif(typeof target === 'number') {\n\t\t[wrapper, is_setter] = _find_wrapper_by_id(target);\n\t}\n\telse {\n\t\tconst target_and_setter = _split_target_and_setter(target);\n\n\t\twrapper = _find_wrapper_by_name(target_and_setter[0]);\n\t\tis_setter = target_and_setter[1];\n\t}\n\n\t// Return null if not found, or if we wanted a setter but there is none\n\tif(!wrapper)\n\t\treturn null;\n\tif(is_setter && !wrapper.is_property)\n\t\treturn null;\n\n\t// Otherwise return the data relevant to the requested package\n\treturn _find_package_data_in_wrapper(package_info, wrapper, is_setter);\n}\n\nfunction _get_default_priority(package_info, target) {\n\tif(package_info.id === PACKAGE_ID)\n\t\treturn Number.MAX_VALUE;\n\n\tconst priority_cfg = PRIORITIES.get(package_info.key);\n\tif(priority_cfg !== undefined)\n\t\treturn priority_cfg;\n\n\treturn 0;\n}\n\nfunction _unwrap_if_possible(wrapper) {\n\tif(wrapper.is_empty() && PROPERTIES_CONFIGURABLE) {\n\t\twrapper.unwrap();\n\t\tWRAPPERS.remove(wrapper);\n\t}\n}\n\nexport function _clear(target) {\n\tconst wrapper = _find_wrapper_by_name(target);\n\n\tif(wrapper) {\n\t\twrapper.clear();\n\t\t_unwrap_if_possible(wrapper);\n\n\t\tLog.info$?.(`Cleared all wrapper functions for '${target}'.`);\n\t}\n}\n\nfunction _unregister(package_info, target, fail) {\n\t// Find wrapper\n\tconst data = _find_package_data_with_target(package_info, target);\n\tif(!data) {\n\t\tif(fail)\n\t\t\tthrow new ERRORS.package(`Cannot unregister '${target}' by ${package_info.type_plus_id} as no such wrapper has been registered`, package_info);\n\t\treturn;\n\t}\n\n\tconst wrapper = data.wrapper;\n\n\t// Remove from fn_data\n\twrapper.remove(data);\n\t_unwrap_if_possible(wrapper);\n\n\t// Done\n\treturn data;\n}\n\nexport function _unwrap_all() {\n\tWRAPPERS.forEach((wrapper) => {\n\t\twrapper.clear();\n\t\t_unwrap_if_possible(wrapper);\n\t});\n\n\tWRAPPERS.clear();\n}\n\nfunction _get_package_info(package_id) {\n\t// Auto-detect package info, initially\n\tlet package_info = new PackageInfo();\n\n\t// Sanity check user provided ID\n\tif(!PackageInfo.is_valid_key_or_id(package_id))\n\t\tthrow new ERRORS.package('Parameter \\'package_id\\' is invalid.', package_info);\n\n\t// Parse user provided ID into a PackageInfo object\n\tconst user_package_info = new PackageInfo(package_id);\n\n\t// If we were able to auto-detect the package, validate user provided info against automatically detected info\n\tif(package_info.exists) {\n\t\tif(!package_info.equals(user_package_info))\n\t\t\tthrow new ERRORS.package(`${package_info.type_plus_id_capitalized} is not allowed to call libWrapper with package_id='${package_id}'.`, package_info);\n\t}\n\t// Otherwise, just assume what the user provided is correct\n\telse {\n\t\tpackage_info = user_package_info;\n\t}\n\n\t// Sanity Check: Must not allow registering wrappers as lib-wrapper\n\tif(package_id == PACKAGE_ID) {\n\t\tif(!allow_libwrapper_registrations)\n\t\t\tthrow new ERRORS.package(`Not allowed to call libWrapper with package_id='${package_id}'.`, package_info);\n\t}\n\t// Sanity Check: Package must exist (single exception is lib-wrapper, since we register wrappers before 'init')\n\telse {\n\t\tif(!package_info.exists && globalThis.game?.modules?.size)\n\t\t\tthrow new ERRORS.package(`Package '${package_id}' is not a valid package.`, package_info);\n\t}\n\n\t// Done\n\treturn package_info;\n}\n\nlet FORCE_FAST_MODE = false;\nfunction _force_fast_mode(new_fast_mode) {\n\tFORCE_FAST_MODE = new_fast_mode;\n}\n\n\n\n// Publicly exposed class\nexport class libWrapper {\n\t// Properties\n\t/**\n\t * Get libWrapper version\n\t * @returns {string} libWrapper version in string form, i.e. \"<MAJOR>.<MINOR>.<PATCH>.<SUFFIX><META>\"\n\t */\n\tstatic get version() { return VERSION.full; }\n\n\t/**\n\t * Get libWrapper version\n\t * @returns {[number,number,number,number,string]} libWrapper version in array form, i.e. [<MAJOR>, <MINOR>, <PATCH>, <SUFFIX>, <META>]\n\t */\n\tstatic get versions() { return [VERSION.major, VERSION.minor, VERSION.patch, VERSION.suffix, VERSION.meta]; }\n\n\t/**\n\t * Get the Git version identifier.\n\t * @returns {string} Git version identifier, usually 'HEAD' or the commit hash.\n\t */\n\tstatic get git_version() { return VERSION.git };\n\n\n\t/**\n\t * @returns {boolean} The real libWrapper module will always return false. Fallback implementations (e.g. poly-fill / shim) should return true.\n\t */\n\tstatic get is_fallback() { return false; }\n\n\n\t// Errors\n\tstatic get LibWrapperError() { return ERRORS.base; };\n\tstatic get Error() { return ERRORS.base; }\n\n\tstatic get LibWrapperInternalError() { return ERRORS.internal; };\n\tstatic get InternalError() { return ERRORS.internal; };\n\n\tstatic get LibWrapperPackageError() { return ERRORS.package; };\n\tstatic get PackageError() { return ERRORS.package; };\n\n\tstatic get LibWrapperAlreadyOverriddenError() { return ERRORS.already_overridden; };\n\tstatic get AlreadyOverriddenError() { return ERRORS.already_overridden; };\n\n\tstatic get LibWrapperInvalidWrapperChainError() { return ERRORS.invalid_chain; };\n\tstatic get InvalidWrapperChainError() { return ERRORS.invalid_chain; };\n\n\t/* Undocumented on purpose, do not use */\n\tstatic get onUnhandledError() { return onUnhandledError; };\n\n\n\t// Enums - First introduced in v1.9.0.0\n\tstatic get WRAPPER() { return WRAPPER_TYPES.WRAPPER };\n\tstatic get MIXED() { return WRAPPER_TYPES.MIXED };\n\tstatic get OVERRIDE() { return WRAPPER_TYPES.OVERRIDE };\n\n\tstatic get PERF_NORMAL() { return PERF_MODES.NORMAL };\n\tstatic get PERF_AUTO() { return PERF_MODES.AUTO };\n\tstatic get PERF_FAST() { return PERF_MODES.FAST };\n\n\n\t// Methods\n\t/**\n\t * Test for a minimum libWrapper version.\n\t * First introduced in v1.4.0.0.\n\t *\n\t * @param {number} major Minimum major version\n\t * @param {number} minor [Optional] Minimum minor version. Default is 0.\n\t * @param {number} patch [Optional] Minimum patch version. Default is 0.\n\t * @param {number} suffix [Optional] Minimum suffix version. Default is 0.\n\t * @returns {boolean} Returns true if the libWrapper version is at least the queried version, otherwise false.\n\t */\n\tstatic get version_at_least() { return version_at_least };\n\n\t/**\n\t * Register a new wrapper.\n\t * Important: If called before the 'init' hook, this method will fail.\n\t *\n\t * In addition to wrapping class methods, there is also support for wrapping methods on specific object instances, as well as class methods inherited from parent classes.\n\t * However, it is recommended to wrap methods directly in the class that defines them whenever possible, as inheritance/instance wrapping is less thoroughly tested and will incur a performance penalty.\n\t *\n\t * Triggers FVTT hook 'libWrapper.Register' when successful.\n\t *\n\t * Returns a unique numeric target identifier, which can be used as a replacement for 'target' in future calls to 'libWrapper.register' and 'libWrapper.unregister'.\n\t *\n\t * @param {string} package_id The package identifier, i.e. the 'id' field in your module/system/world's manifest.\n\t *\n\t * @param {number|string} target The target identifier, specifying which wrapper should be registered.\n\t *\n\t * This can be either:\n\t * 1. A unique target identifier obtained from a previous 'libWrapper.register' call.\n\t * 2. A string containing the path to the function you wish to add the wrapper to, starting at global scope, for example 'SightLayer.prototype.updateToken'.\n\t *\n\t * Support for the unique target identifiers (option #1) was added in v1.11.0.0, with previous versions only supporting option #2.\n\t *\n\t * Since v1.8.0.0, the string path (option #2) can contain string array indexing.\n\t * For example, 'CONFIG.Actor.sheetClasses.character[\"dnd5e.ActorSheet5eCharacter\"].cls.prototype._onLongRest' is a valid path.\n\t * It is important to note that indexing in libWrapper does not work exactly like in JavaScript:\n\t * - The index must be a single string, quoted using the ' or \" characters. It does not support e.g. numbers or objects.\n\t * - A backslash \\ can be used to escape another character so that it loses its special meaning, e.g. quotes i.e. ' and \" as well as the character \\ itself.\n\t *\n\t * By default, libWrapper searches for normal methods or property getters only. To wrap a property's setter, append '#set' to the name, for example 'SightLayer.prototype.blurDistance#set'.\n\t *\n\t * @param {function} fn Wrapper function. The first argument will be the next function in the chain, except for 'OVERRIDE' wrappers.\n\t * The remaining arguments will correspond to the parameters passed to the wrapped method.\n\t *\n\t * @param {string} type [Optional] The type of the wrapper. Default is 'MIXED'.\n\t *\n\t * The possible types are:\n\t *\n\t * 'WRAPPER' / libWrapper.WRAPPER:\n\t * Use if your wrapper will *always* continue the chain.\n\t * This type has priority over every other type. It should be used whenever possible as it massively reduces the likelihood of conflicts.\n\t * Note that the library will auto-detect if you use this type but do not call the original function, and automatically unregister your wrapper.\n\t *\n\t * 'MIXED' / libWrapper.MIXED:\n\t * Default type. Your wrapper will be allowed to decide whether it continue the chain or not.\n\t * These will always come after 'WRAPPER'-type wrappers. Order is not guaranteed, but conflicts will be auto-detected.\n\t *\n\t * 'OVERRIDE' / libWrapper.OVERRIDE:\n\t * Use if your wrapper will *never* continue the chain. This type has the lowest priority, and will always be called last.\n\t * If another package already has an 'OVERRIDE' wrapper registered to the same method, using this type will throw a <libWrapper.ERRORS.package> exception.\n\t * Catching this exception should allow you to fail gracefully, and for example warn the user of the conflict.\n\t * Note that if the GM has explicitly given your package priority over the existing one, no exception will be thrown and your wrapper will take over.\n\t *\n\t * @param {Object} options [Optional] Additional options to libWrapper.\n\t *\n\t * @param {boolean} options.chain [Optional] If 'true', the first parameter to 'fn' will be a function object that can be called to continue the chain.\n\t * This parameter must be 'true' when registering non-OVERRIDE wrappers.\n\t * Default is 'false' if type=='OVERRIDE', otherwise 'true'.\n\t * First introduced in v1.3.6.0.\n\t *\n\t * @param {string} options.perf_mode [Optional] Selects the preferred performance mode for this wrapper. Default is 'AUTO'.\n\t * It will be used if all other wrappers registered on the same target also prefer the same mode, otherwise the default will be used instead.\n\t * This option should only be specified with good reason. In most cases, using 'AUTO' in order to allow the GM to choose is the best option.\n\t * First introduced in v1.5.0.0.\n\t *\n\t * The possible modes are:\n\t *\n\t * 'NORMAL' / libWrapper.PERF_NORMAL:\n\t * Enables all conflict detection capabilities provided by libWrapper. Slower than 'FAST'.\n\t * Useful if wrapping a method commonly modified by other packages, to ensure most issues are detected.\n\t * In most other cases, this mode is not recommended and 'AUTO' should be used instead.\n\t *\n\t * 'FAST' / libWrapper.PERF_FAST:\n\t * Disables some conflict detection capabilities provided by libWrapper, in exchange for performance. Faster than 'NORMAL'.\n\t * Will guarantee wrapper call order and per-package prioritization, but fewer conflicts will be detectable.\n\t * This performance mode will result in comparable performance to traditional non-libWrapper wrapping methods.\n\t * Useful if wrapping a method called repeatedly in a tight loop, for example 'WallsLayer.testWall'.\n\t * In most other cases, this mode is not recommended and 'AUTO' should be used instead.\n\t *\n\t * 'AUTO' / libWrapper.PERF_AUTO:\n\t * Default performance mode. If unsure, choose this mode.\n\t * Will allow the GM to choose which performance mode to use.\n\t * Equivalent to 'FAST' when the libWrapper 'High-Performance Mode' setting is enabled by the GM, otherwise 'NORMAL'.\n\t *\n\t * @param {any[]} options.bind [Optional] An array of parameters that should be passed to 'fn'.\n\t *\n\t * This allows avoiding an extra function call, for instance:\n\t * libWrapper.register(PACKAGE_ID, \"foo\", function(wrapped, ...args) { return someFunction.call(this, wrapped, \"foo\", \"bar\", ...args) });\n\t * becomes\n\t * libWrapper.register(PACKAGE_ID, \"foo\", someFunction, \"WRAPPER\", {bind: [\"foo\", \"bar\"]});\n\t *\n\t * First introduced in v1.12.0.0.\n\t *\n\t * @returns {number} Unique numeric 'target' identifier which can be used in future 'libWrapper.register' and 'libWrapper.unregister' calls.\n\t * Added in v1.11.0.0.\n\t */\n\tstatic register(package_id, target, fn, type='MIXED', options={}) {\n\t\t// Get package information\n\t\tconst package_info = _get_package_info(package_id);\n\n\t\t// Validate we're allowed to register wrappers at this moment\n\t\tif(package_id != PACKAGE_ID && !libwrapper_ready)\n\t\t\tthrow new ERRORS.package('Not allowed to register wrappers before the \\'libWrapper.Ready\\' hook fires', package_info);\n\n\t\t// Validate other arguments\n\t\tif(typeof target !== 'string' && typeof target !== 'number')\n\t\t\tthrow new ERRORS.package('Parameter \\'target\\' must be a number or a string.', package_info);\n\n\t\tif(!fn || !(fn instanceof Function))\n\t\t\tthrow new ERRORS.package('Parameter \\'fn\\' must be a function.', package_info);\n\n\t\ttype = WRAPPER_TYPES.get(type, null);\n\t\tif(type === null)\n\t\t\tthrow new ERRORS.package(`Parameter 'type' must be one of [${WRAPPER_TYPES.list.join(', ')}].`, package_info);\n\n\t\tconst chain = options?.chain ?? (type.value < WRAPPER_TYPES.OVERRIDE.value);\n\t\tif(typeof chain !== 'boolean')\n\t\t\tthrow new ERRORS.package(`Parameter 'options.chain' must be a boolean.`, package_info);\n\t\tif(!chain && type.value < WRAPPER_TYPES.OVERRIDE.value)\n\t\t\tthrow new ERRORS.package(`Parameter 'options.chain' must be 'true' for non-OVERRIDE wrappers.`, package_info);\n\n\t\tif(IS_UNITTEST && FORCE_FAST_MODE)\n\t\t\toptions.perf_mode = 'FAST';\n\t\tconst perf_mode = PERF_MODES.get(options?.perf_mode ?? 'AUTO', null);\n\t\tif(perf_mode === null)\n\t\t\tthrow new ERRORS.package(`Parameter 'options.perf_mode' must be one of [${PERF_MODE.list.join(', ')}].`, package_info);\n\n\t\tconst bind = options?.bind ?? null;\n\t\tif(bind !== null && !Array.isArray(bind))\n\t\t\tthrow new ERRORS.package(`Parameter 'options.bind' must be an array.`, package_info);\n\n\n\t\t// Process 'target' parameter\n\t\tlet wrapper = undefined;\n\t\tlet is_setter;\n\n\t\t// In the case it is a number, then this means the wrapper must already exist, we simply need to find it\n\t\tif(typeof target === 'number') {\n\t\t\t[wrapper, is_setter] = _find_wrapper_by_id(target);\n\n\t\t\tif(!wrapper)\n\t\t\t\tthrow new ERRORS.package(`Could not find target '${target}': Invalid or unknown unique identifier.`, package_info);\n\t\t}\n\t\t// Otherwise, we need to create a wrapper from a target string (or obtain it if it already exists)\n\t\telse {\n\t\t\t// Split '#set' from the target\n\t\t\tconst target_and_setter = _split_target_and_setter(target);\n\t\t\tconst target_without_set = target_and_setter[0];\n\n\t\t\tis_setter = target_and_setter[1];\n\n\t\t\t// Create wrapper\n\t\t\twrapper = _create_wrapper(target, package_info);\n\n\t\t\t// Sanity check\n\t\t\tif(!wrapper)\n\t\t\t\tthrow new ERRORS.internal(`Sanity check failed: 'wrapper' must not be falsy after _create_wrapper call`);\n\n\t\t\t// Only allow '#set' when the wrapper is wrapping a property\n\t\t\tif(is_setter && !wrapper.is_property)\n\t\t\t\tthrow new ERRORS.package(`Cannot register a wrapper for '${target}' by ${package_info.type_plus_id}' because '${target_without_set}' is not a property, and therefore has no setter.`, package_info);\n\t\t}\n\n\t\t// Get wrapper ID and name for log messages\n\t\tconst wrapper_id = wrapper.get_id(is_setter);\n\t\tconst wrapper_name = wrapper.get_name(is_setter);\n\n\t\t// Check if this wrapper is already registered\n\t\tif(_find_package_data_in_wrapper(package_info, wrapper, is_setter))\n\t\t\tthrow new ERRORS.package(`A wrapper for '${wrapper_name}' (ID=${wrapper_id}) has already been registered by ${package_info.type_plus_id}.`, package_info);\n\n\t\t// Get priority\n\t\tconst priority = _get_default_priority(package_info, target);\n\n\t\t// Register this package as having wrapped something\n\t\t// We do this before checking for duplicate OVERRIDEs to ensure users can change this package's priorities regardless\n\t\tif(package_info.id != PACKAGE_ID)\n\t\t\tLibWrapperStats.register_package(package_info);\n\n\t\t// Only allow one 'OVERRIDE' type\n\t\tif(type.value >= WRAPPER_TYPES.OVERRIDE.value) {\n\t\t\tconst existing = wrapper.get_fn_data(is_setter).find((x) => { return x.type === WRAPPER_TYPES.OVERRIDE });\n\n\t\t\tif(existing) {\n\t\t\t\tif(priority <= existing.priority) {\n\t\t\t\t\tthrow new ERRORS.already_overridden(package_info, existing.package_info, wrapper, target);\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\t// We trigger a hook first\n\t\t\t\t\tif(Hooks.call(`${HOOKS_SCOPE}.OverrideLost`, existing.package_info.id, package_info.id, wrapper.name, wrapper.frozen_names) !== false) {\n\t\t\t\t\t\tconst notify_user = LibWrapperConflicts.register_conflict(package_info, existing.package_info, wrapper, null, false);\n\n\t\t\t\t\t\tif(notify_user) {\n\t\t\t\t\t\t\tLibWrapperNotifications.conflict(existing.package_info, package_info, false,\n\t\t\t\t\t\t\t\t`${package_info.type_plus_id_capitalized} has higher priority, and is replacing the 'OVERRIDE' registered by ${package_info.type_plus_id} for '${wrapper_name}'.`\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Wrap\n\t\tlet data = {\n\t\t\tpackage_info : package_info,\n\t\t\ttarget : target,\n\t\t\tsetter : is_setter,\n\t\t\tfn : fn,\n\t\t\ttype : type,\n\t\t\twrapper : wrapper,\n\t\t\tpriority : priority,\n\t\t\tchain : chain,\n\t\t\tperf_mode : perf_mode,\n\t\t\tbind : bind\n\t\t};\n\n\t\twrapper.add(data);\n\n\t\t// Done\n\t\tif(package_info.id != PACKAGE_ID)\n\t\t\tHooks.callAll(`${HOOKS_SCOPE}.Register`, package_info.id, (typeof target === 'number') ? wrapper_name : target, type, options, wrapper_id);\n\n\t\tLog.info$?.(`Registered a wrapper for '${wrapper_name}' (ID=${wrapper_id}) by ${package_info.type_plus_id} with type ${type}.`);\n\n\t\treturn wrapper_id;\n\t}\n\n\t/**\n\t * Unregister an existing wrapper.\n\t *\n\t * Triggers FVTT hook 'libWrapper.Unregister' when successful.\n\t *\n\t * @param {string} package_id The package identifier, i.e. the 'id' field in your module/system/world's manifest.\n\t *\n\t * @param {number|string} target The target identifier, specifying which wrapper should be unregistered.\n\t *\n\t * This can be either:\n\t * 1. A unique target identifier obtained from a previous 'libWrapper.register' call. This is the recommended option.\n\t * 2. A string containing the path to the function you wish to remove the wrapper from, starting at global scope, with the same syntax as the 'target' parameter to 'libWrapper.register'.\n\t *\n\t * Support for the unique target identifiers (option #1) was added in v1.11.0.0, with previous versions only supporting option #2.\n\t * It is recommended to use option #1 if possible, in order to guard against the case where the class or object at the given path is no longer the same as when `libWrapper.register' was called.\n\t *\n\t * @param {function} fail [Optional] If true, this method will throw an exception if it fails to find the method to unwrap. Default is 'true'.\n\t */\n\tstatic unregister(package_id, target, fail=true) {\n\t\t// Get package information\n\t\tconst package_info = _get_package_info(package_id);\n\n\t\t// Validate we're allowed to unregister wrappers at this moment\n\t\tif(package_id != PACKAGE_ID && !libwrapper_ready)\n\t\t\tthrow new ERRORS.package('Not allowed to unregister wrappers before the \\'libWrapper.Ready\\' hook fires', package_info);\n\n\t\t// Validate arguments\n\t\tif(typeof target !== 'string' && typeof target !== 'number')\n\t\t\tthrow new ERRORS.package('Parameter \\'target\\' must be a number or a string.', package_info);\n\n\t\t// Unregister wrapper\n\t\tconst data = _unregister(package_info, target, fail);\n\t\tif(!data)\n\t\t\treturn;\n\n\t\t// Done\n\t\tconst wrapper_id = data.wrapper.get_id(data.setter);\n\t\tconst wrapper_name = data.wrapper.get_name(data.setter);\n\n\t\tif(package_info.id != PACKAGE_ID)\n\t\t\tHooks.callAll(`${HOOKS_SCOPE}.Unregister`, package_info.id, (typeof target === 'number') ? wrapper_name : target, wrapper_id);\n\n\t\tLog.info$?.(`Unregistered the wrapper for '${wrapper_name}' (ID=${wrapper_id}) by ${package_info.type_plus_id}.`);\n\t}\n\n\t/**\n\t * Unregister all wrappers created by a given package.\n\t *\n\t * Triggers FVTT hook 'libWrapper.UnregisterAll' when successful.\n\t *\n\t * @param {string} package_id The package identifier, i.e. the 'id' field in your module/system/world's manifest.\n\t */\n\tstatic unregister_all(package_id) {\n\t\t// Get package information\n\t\tconst package_info = _get_package_info(package_id);\n\n\t\t// Validate we're allowed to unregister wrappers at this moment\n\t\tif(package_id != PACKAGE_ID && !libwrapper_ready)\n\t\t\tthrow new ERRORS.package('Not allowed to unregister wrappers before the \\'libWrapper.Ready\\' hook fires', package_info);\n\n\t\t// Clear package wrappers\n\t\tWRAPPERS.forEach((wrapper) => {\n\t\t\tthis.unregister(package_info.id, wrapper.getter_id, false);\n\n\t\t\tif(wrapper.is_property)\n\t\t\t\tthis.unregister(package_info.id, wrapper.setter_id, false);\n\t\t});\n\n\t\tif(package_info.id != PACKAGE_ID)\n\t\t\tHooks.callAll(`${HOOKS_SCOPE}.UnregisterAll`, package_info.id);\n\n\t\tLog.info$?.(`Unregistered all wrapper functions by ${package_info.type_plus_id}.`);\n\t}\n\n\t/**\n\t * Ignore conflicts matching specific filters when detected, instead of warning the user.\n\t *\n\t * This can be used when there are conflict warnings that are known not to cause any issues, but are unable to be resolved.\n\t * Conflicts will be ignored if they involve both 'package_id' and one of 'ignore_ids', and relate to one of 'targets'.\n\t *\n\t * Note that the user can still see which detected conflicts were ignored, by toggling \"Show ignored conflicts\" in the \"Conflicts\" tab in the libWrapper settings.\n\t *\n\t * First introduced in v1.7.0.0.\n\t *\n\t * @param {string} package_id The package identifier, i.e. the 'id' field in your module/system/world's manifest. This will be the package that owns this ignore entry.\n\t *\n\t * @param {(string|string[])} ignore_ids Other package ID(s) with which conflicts should be ignored.\n\t *\n\t * @param {(string|string[])} targets Target(s) for which conflicts should be ignored, corresponding to the 'target' parameter to 'libWrapper.register'.\n\t * This method does not accept the unique target identifiers returned by 'libWrapper.register'.\n\t *\n\t * @param {Object} options [Optional] Additional options to libWrapper.\n\t *\n\t * @param {boolean} options.ignore_errors [Optional] If 'true', will also ignore confirmed conflicts (i.e. errors), rather than only potential conflicts (i.e. warnings).\n\t * Be careful when setting this to 'true', as confirmed conflicts are almost certainly something the user should be made aware of.\n\t * Defaults to 'false'.\n\t */\n\tstatic ignore_conflicts(package_id, ignore_ids, targets, options={}) {\n\t\t// Get package information\n\t\tconst package_info = _get_package_info(package_id);\n\n\t\t// Validate we are allowed to call this method right now\n\t\tif(!libwrapper_ready)\n\t\t\tthrow new ERRORS.package('Not allowed to ignore conflicts before the \\'libWrapper.Ready\\' hook fires', package_info);\n\n\t\t// Convert parameters to arrays\n\t\tif(!Array.isArray(ignore_ids))\n\t\t\tignore_ids = [ignore_ids];\n\t\tif(!Array.isArray(targets))\n\t\t\ttargets = [targets];\n\n\t\t// Validate parameters #2\n\t\tconst is_string = (x) => (typeof x === 'string');\n\n\t\tif(!ignore_ids.every(is_string))\n\t\t\tthrow new ERRORS.package(`Parameter 'ignore_ids' must be a string, or an array of strings.`, package_info);\n\n\t\tif(!targets.every(is_string))\n\t\t\tthrow new ERRORS.package(`Parameter 'targets' must be a string, or an array of strings.`, package_info);\n\t\tif(!targets.every((x) => _valid_target_string(x)))\n\t\t\tthrow new ERRORS.package(`Parameter 'targets' must only contain valid targets.`, package_info);\n\n\t\tconst ignore_errors = options.ignore_errors ?? false;\n\t\tif(typeof ignore_errors !== 'boolean')\n\t\t\tthrow new ERRORS.package(`Parameter 'options.ignore_errors' must be a boolean.`, package_info);\n\n\n\t\t// Convert 'other_ids' to PackageInfo objects and filter out any that do not exist\n\t\tconst ignore_infos = ignore_ids.map((x) => new PackageInfo(x)).filter((x) => x.exists);\n\n\t\t// Ignore API call if no packages to be ignored\n\t\tif(ignore_infos.length == 0) {\n\t\t\tLog.debug$?.(`Ignoring 'ignore_conflict' call for ${package_info.type_plus_id} since none of the package IDs provided exist or are active.`)\n\t\t\treturn;\n\t\t}\n\n\t\t// Register ignores\n\t\tLibWrapperConflicts.register_ignore(package_info, ignore_infos, targets, ignore_errors);\n\n\t\tif(package_info.id != PACKAGE_ID)\n\t\t\tLog.info$?.(`Ignoring conflicts involving ${package_info.type_plus_id} and [${ignore_infos.map((x) => x.type_plus_id).join(', ')}] for targets [${targets.join(', ')}].`);\n\t}\n};\ndecorate_class_function_names(libWrapper);\nif(IS_UNITTEST) {\n\t// Some methods should be exposed during unit tests\n\tlibWrapper._UT_unwrap_all = _unwrap_all;\n\tlibWrapper._UT_create_wrapper_from_object = _create_wrapper_from_object\n\tlibWrapper._UT_clear = _clear;\n\tlibWrapper._UT_force_fast_mode = _force_fast_mode;\n\tlibWrapper._UT_get_force_fast_mode = (() => FORCE_FAST_MODE);\n\tlibWrapper._UT_clear_ignores = (() => LibWrapperConflicts.clear_ignores());\n\tlibWrapper._UT_TGT_SPLIT_REGEX = TGT_SPLIT_RE;\n\tlibWrapper._UT_TGT_CLEANUP_REGEX = TGT_CLEANUP_RE;\n\tlibWrapper._UT_setReady = ((rdy) => libwrapper_ready = rdy);\n}\nObject.freeze(libWrapper);\n\n\n\n// Define as property so that it can't be deleted\ndelete globalThis.libWrapper;\nObject.defineProperty(globalThis, 'libWrapper', {\n\tget: () => libWrapper,\n\tset: (value) => { throw new ERRORS.package(\"Not allowed to re-assign the global instance of libWrapper\") },\n\tconfigurable: false\n});\n\n\n\n// Setup unhandled error listeners\ninit_error_listeners();\n\n// Initialize libWrapper right before the 'init' hook. Unit tests just initialize immediately\n{\n\tlet GAME_INITIALIZE_ID;\n\tlet GAME_TOSTRING_ID;\n\n\tconst libWrapperInit = decorate_name('libWrapperInit');\n\tconst obj = {\n\t\t[libWrapperInit]: async function(wrapped, ...args) {\n\t\t\t// Unregister our pre-initialisation patches as they are no longer necessary\n\t\t\tif(!IS_UNITTEST) {\n\t\t\t\tconst lw_info = new PackageInfo('lib-wrapper', PACKAGE_TYPES.MODULE);\n\t\t\t\t_unregister(lw_info, GAME_TOSTRING_ID , /*fail=*/ true);\n\t\t\t\t_unregister(lw_info, GAME_INITIALIZE_ID, /*fail=*/ true);\n\t\t\t}\n\n\t\t\t// Initialization steps\n\t\t\tlibwrapper_ready = true;\n\n\t\t\t//#if !_ROLLUP\n\t\t\t\tparse_manifest_version();\n\t\t\t//#endif\n\n\t\t\tawait i18n.init();\n\t\t\tLibWrapperSettings.init();\n\t\t\tLibWrapperStats.init();\n\t\t\tLibWrapperConflicts.init();\n\t\t\tLibWrapperNotifications.init();\n\n\t\t\t// Notify everyone the library has loaded and is ready to start registering wrappers\n\t\t\tLog.fn(Log.ALWAYS, /*fn_verbosity=*/ Log.INFO)(`Version ${VERSION.full_git} ready.`);\n\t\t\tHooks.callAll(`${HOOKS_SCOPE}.Ready`, libWrapper);\n\n\t\t\treturn wrapped(...args);\n\t\t}\n\t};\n\n\tif(!IS_UNITTEST) {\n\t\tGAME_INITIALIZE_ID = libWrapper.register('lib-wrapper', 'Game.prototype.initialize', obj[libWrapperInit], libWrapper.WRAPPER, {perf_mode: libWrapper.PERF_FAST});\n\n\t\t// We need to prevent people patching 'Game' and breaking libWrapper.\n\t\t// Unfortunately we cannot re-define 'Game' as a non-settable property, but we can prevent people from using 'Game.toString'.\n\t\tGAME_TOSTRING_ID = libWrapper.register('lib-wrapper', 'Game.toString', function() {\n\t\t\tthrow new ERRORS.package(\"Using 'Game.toString()' before libWrapper initialises is not allowed for compatibility reasons.\");\n\t\t}, libWrapper.WRAPPER, {perf_mode: libWrapper.PERF_FAST});\n\n\t\t// Add a sanity check hook, just in case someone breaks our initialisation procedure\n\t\tHooks.once('init', ()=>{\n\t\t\tif(!libwrapper_ready)\n\t\t\t\tthrow new ERRORS.internal(\"Could not successfuly initialise libWrapper, likely due to a compatibility issue with another module.\");\n\t\t});\n\t}\n\telse\n\t\tobj[libWrapperInit](()=>{});\n}\n\n// Lock down registrations using package ID 'lib-wrapper'\nallow_libwrapper_registrations = false;"],"names":["ERRORS","base","Error","internal","package","already_overridden","invalid_chain","Object","seal","PACKAGE_ID","EnumValue","enum_cls","name","value","sort","isFrozen","toUpperCase","value_obj","Function","value_cls","undefined","freeze","prototype","constructor","reverse","has","set","list","push","sort_list_by_value","Enum","collection","has_value","Array","enum_name","dflt","this","get","static","res","value_int","parseInt","Number","isInteger","a","b","value_cls_name","enum","toString","lower","toLowerCase","Map","key","game_user_data","return_null","orig_game_user_data","globalThis","game","user","data","userid","userId","user_data","users","find","x","_id","game_settings_get","namespace","always_fallback","orig_game_settings_get","settings","call","e","storage_key","localStorage","json_data","JSON","parse","VERBOSITY","ZERO","TRACE","DEBUG","INFO","WARNING","ERROR","CRITICAL","MAX_SAFE_INTEGER","ALWAYS","VERBOSITY_ALIASES_MAP","NEVER","ALL","WARN","VERBOSITY_CONSOLEFN_MAP","console","LOG_ALIASES_VERBOSITY_MAP","never","trace","debug","info","warning","warn","error","critical","always","LOG_PREFIX","LOG_PREFIX_VERBOSITY_MAP","CURRENT_VERBOSITY","verbosity_to_value","verbosity","verbosity_to_mapped_value","map","result","v","generate_log_aliases","alias","fn","Log","stack","has_trace","bind","in_value","verbosity_value","verbosities","force","fn_verbosity","enabled","obj","nm","verbosity_to_log_function","prefix","suffix","verbosity_to_log_prefix","args","generate_verbosity_aliases","defineProperty","configurable","generate_enabled_aliases","init","i18nLangs","langBaseUrl","import","meta","url","endsWith","i18n","lang","isArray","includes","URL","request","fetch","status","ok","json","warn$","href","jsons","langs","clientLanguage","debug$","serverLanguage","length","results","Promise","all","_fetch","localize","split","reduce","y","en_json","format","replace","_","Hooks","once","on_ready","PACKAGE_TYPES","PACKAGE_ID_REGEX","RegExp","STACK_TRACE_REGEX","foreach_package_in_stack_trace","matchFn","stack_trace","ignore_ids","old_stack_limit","stackTraceLimit","Infinity","matches","matchAll","match","type","match_id","match_type","game_world_id","world","id","WORLD","game_system_id","system","SYSTEM","modules","MODULE","PackageInfo","UNKNOWN","include_fn","Set","add","key_or_id","is_valid_key","is_valid_id","parse_key","test","detect_id","from_key","detect_type","set_unknown","equals","active","fail","known","exists","fvtt_gen","release","generation","v10_or_newer","unknown_title","title","type_i18n","type_plus_id","type_plus_id_capitalized","str","charAt","slice","type_plus_id_i18n","type_plus_title","type_plus_title_i18n","logId","settingsName","bugs","version","core_version_range","compatibility","minimum","verified","maximum","minimumCoreVersion","compatibleCoreVersion","compatible_with_core","versions","fvtt_version","game_version","fvtt_major","min","verif","max","fvtt_min","isNewerVersion","fvtt_verif","fvtt_max","global_eval","eval","set_function_name","displayName","writable","enumerable","decorate_name","decorate_class_function_names","klass","props","getOwnPropertyNames","getOwnPropertySymbols","prop","descriptor","getOwnPropertyDescriptor","is_error_object","LIBWRAPPER_IGNORE_MATCHES","get_involved_packages_message","packages","collect_all","needle","get_involved_packages","p","join","has_property_string_writable","desc","inject_packages_into_error","packages_str","libwrapper_skip_package_detection","can_inject_message","message","orig_msg","LibWrapperError","notification_verbosity","ui_msg","console_msg","super","captureStackTrace","LibWrapperInternalError","onUnhandled","technical_msg","package_info","key_prefix","type_prefix","user_msg","construct_message","package_id","LibWrapperPackageError","support_list","entry","pkg_title","pkg_type_i18n","console_ui_msg","display_version","display","game_release_display","notupd_msg","info_url","has_info","report_url","community_support_msg","get_community_support_message","getSetting","getNotifyIssues","isGM","orig_game_user_isGM","role","game_user_isGM","VERBOSITY_NOTIFY_FN_MAP","LibWrapperNotifications","ui_notifications_enabled","NOTIFICATION_SET","msg","add_title","ui_notifications","ui","notifications","hash","i","charCodeAt","hash_string","permanent","ready","_ui","log","other_info","potential","other","format_obj","main","console_ui","LibWrapperStats","action","orig_game_user_can","can","permissions","game_permissions_str","rolePerms","game_user_can","collect_stats","_collect_stats","PACKAGES","CONFLICTS","wrapper","ignored","count","targets","target","target_data","conflicts","IgnoredConflictEntry","ignore_infos","ignore_errors","is_ignored","is_warning","names","LibWrapperConflicts","IGNORED","ignore_entries","clear","_is_ignored_oneway","notify","forEach","register_conflict","_is_ignored","frozen_names","LibWrapperAlreadyOverriddenError","conflicting_info","pkg_i18n","pkg_i18n_capitalized","confl_i18n","confl_i18n_capitalized","conflict_msg","info_msg","info1_url","info2_url","bugs_msg","bugs1_url","bugs2_url","_wrapper","module","conflicting_id","conflicting_module","LibWrapperInvalidWrapperChainError","onUnhandledError","apply","on_libwrapper_error","on_any_error","onUnhandledErrorEvent","event","cause","reason","VERSION","version_at_least","major","minor","patch","WRAPPER_TYPES","WRAPPER","MIXED","OVERRIDE","PERF_MODES","NORMAL","AUTO","FAST","WRAPPERS","WrapperStorage","index_for_id","Math","floor","index_for_wrapper","getter_id","get_next_id_pair","next_id","_delete","idx","delete","_set","ref","WeakRef","_deref","deref","_get","existing","remove","wrappers","entries","callbackFn","find_by_id","Wrapper","get_id","is_setter","setter_id","get_name","get_names","_add_name","_callstack_name","arg1","fn_name","object","_lib_wrapper","is_property","_wrapped_getter","_wrapped_setter","_wrapped","_get_inherited_descriptor","getter_data","setter_data","_outstanding_wrappers","_current_handler_id","_pending_wrapped_calls","_pending_wrapped_calls_cnt","use_static_dispatch","_wrap","_get_handler","handler_id","_cached_handler_id","_cached_handler","_this","handler_nm","wrapped","handler","is_static_dispatch","should_skip_wrappers","get_wrapped","get_static_dispatch_chain","call_wrapper","indexOf","skip_existing_handlers","_get_static_dispatch_chain_cache","_static_dispatch_weakmap","_static_dispatch_strongmap","_set_static_dispatch_chain_cache","dispatch_chain","WeakMap","clear_static_dispatch_chain_cache","call_wrapped","fn_data","get_fn_data","chain","_calc_use_static_dispatch","perf_mode","update_use_static_dispatch","getter_nm","setter_nm","setter","set_nonproperty","getter","unwrap","iObj","getPrototypeOf","state","_call_wrapper_update_state","is_dynamic_dispatch","pend","_cleanup_call_wrapped","then","pend_i","splice","index","next_index","is_last","next_state","called","valid","prev_data","next_fn","_cleanup_call_wrapper_thrown","_cleanup_call_wrapper","_invalidate_state","collect_affected","warned_conflict","affectedPackages","is_last_wrapper","notify_user","filter","error$","libWrapper","unregister","conflict","warn_classic_wrapper","get_affected_packages","detected_classic_wrapper","to_modify","prop_nm","_post_update_fn_data","priority","is_empty","PRIORITIES","is_valid_priority_key_data","is_valid_key_or_id","load_priorities","priority_cfg","current","base_priority","LibWrapperSettings","FormApplication","register","hint","default","Boolean","scope","config","choices","onChange","registerMenu","label","icon","restricted","show_ignored_conflicts","defaultOptions","template","height","width","classes","tabs","navSelector","contentSelector","initial","submitOnClose","closeOnSubmit","options","yes_callback","Dialog","content","buttons","yes","callback","no","render","getActiveWrappers","d","getConflicts","total","other_id","obj_total","getPackages","ret","prioritized","normal","deprioritized","priorities","cfg_prioritized","cfg_deprioritized","inactive","localeCompare","getData","about","translation_credits","support","activateListeners","html","on","$this","$","parent","toggleClass","checked","select","is","focus","which","up","selected","insertPos","prev","next","before","after","_from","_to","from","to","element","next_focus","append","val","empty","arr","each","option","attr","appendTo","submit","showYesNoDialog","async","ev","formData","fld","old_prio","new_prio","counter","old_data","new_data","keys","location","reload","libwrapper_ready","allow_libwrapper_registrations","TGT_SPLIT_RE","TGT_CLEANUP_RE","_split_target_and_setter","_valid_target_string","_get_target_object","_target","root_nm","pop","root","varname","get_global_variable","_create_wrapper","_create_wrapper_from_object","_find_wrapper_by_name","_name","_get_target_from_info","_find_wrapper_by_id","_find_package_data_in_wrapper","_unregister","target_and_setter","_find_package_data_with_target","_unwrap_if_possible","_get_package_info","user_package_info","size","git_version","is_fallback","InternalError","PackageError","AlreadyOverriddenError","InvalidWrapperChainError","PERF_NORMAL","PERF_AUTO","PERF_FAST","PERF_MODE","target_without_set","wrapper_id","wrapper_name","MAX_VALUE","_get_default_priority","register_package","callAll","info$","is_string","every","register_ignore","addEventListener","onError","err","init_hooksOnError_listener","orig","_call","patched","patched_fn","catch","init_pre_v9p2_listeners","GAME_INITIALIZE_ID","GAME_TOSTRING_ID","libWrapperInit","lw_info"],"mappings":"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"}
|