|
{"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, prepend_stack=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);\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\t// We use prepend_stack as a workaround to mimic FVTT's Hooks.onError behaviour, see https://github.com/ruipin/fvtt-lib-wrapper/issues/76\n\t\terror.stack = error.stack.replace(orig_msg, `${prepend_stack}. ${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, prepend_stack=undefined) {\n\t// Detect packages and inject a list into the error object\n\tinject_packages_into_error(error, prepend_stack);\n}\n\n\n/*\n * Error Listeners\n */\nexport const onUnhandledError = function(error, prepend_stack=undefined) {\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, prepend_stack);\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\tconst msg = args?.[2]?.msg;\n\t\t\tonUnhandledError(err, msg);\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","PACKAGE_TITLE","HOOKS_SCOPE","PROPERTIES_CONFIGURABLE","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","res","value_int","parseInt","Number","isInteger","toString","a","b","value_cls_name","enum","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","init","force","enabled","fn_verbosity","obj","nm","verbosity_to_log_function","prefix","suffix","verbosity_to_log_prefix","log","args","generate_verbosity_aliases","defineProperty","configurable","generate_enabled_aliases","i18nLangs","langBaseUrl","url","endsWith","i18n","_fetch","lang","isArray","includes","URL","request","fetch","status","ok","json","warn$","href","jsons","langs","clientLanguage","debug$","serverLanguage","length","results","Promise","all","on_ready","localize","split","reduce","y","en_json","format","replace","_","Hooks","once","PACKAGE_TYPES","UNKNOWN_ID","PACKAGE_ID_REGEX","RegExp","STACK_TRACE_REGEX","IGNORE_PACKAGE_IDS","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","collect_all","include_fn","Set","add","is_valid_key_or_id","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","needle","get_involved_packages","p","join","has_property_string_writable","desc","inject_packages_into_error","prepend_stack","packages_str","libwrapper_skip_package_detection","can_inject_message","message","orig_msg","LibWrapperError","notification_verbosity","ui_msg","console_msg","super","captureStackTrace","LibWrapperInternalError","onUnhandled","construct_message","technical_msg","package_info","key_prefix","type_prefix","user_msg","info_msg","report_msg","tech_details","related_pkg_msg","package_id","LibWrapperPackageError","get_community_support_message","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","getSetting","getNotifyIssues","isGM","orig_game_user_isGM","role","game_user_isGM","VERBOSITY_NOTIFY_FN_MAP","LibWrapperNotifications","ui_notifications_enabled","NOTIFICATION_SET","_ui","msg","add_title","ui_notifications","ui","notifications","hash","i","charCodeAt","hash_string","permanent","ready","console_ui","conflict","other_info","potential","other","format_obj","main","LibWrapperStats","_collect_stats","action","orig_game_user_can","can","permissions","game_permissions_str","rolePerms","game_user_can","collect_stats","PACKAGES","CONFLICTS","register_package","register_conflict","wrapper","ignored","count","targets","target","target_data","conflicts","IgnoredConflictEntry","ignore_infos","ignore_errors","is_ignored","is_warning","names","LibWrapperConflicts","IGNORED","register_ignore","ignore_entries","clear_ignores","clear","_is_ignored_oneway","_is_ignored","notify","forEach","frozen_names","LibWrapperAlreadyOverriddenError","conflicting_info","pkg_i18n","pkg_i18n_capitalized","confl_i18n","confl_i18n_capitalized","conflict_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","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","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","showYesNoDialog","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","_updateObject","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","libWrapper$1","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","callAll","info$","unregister_all","ignore_conflicts","is_string","every","addEventListener","onError","err","init_hooksOnError_listener","orig","_call","patched","patched_fn","catch","init_pre_v9p2_listeners","GAME_INITIALIZE_ID","GAME_TOSTRING_ID","libWrapperInit","async","lw_info"],"mappings":"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"}
|