All user data for FoundryVTT. Includes worlds, systems, modules, and any asset in the "foundryuserdata" directory. Does NOT include the FoundryVTT installation itself.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

1 lines
220 KiB

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