From 99a1c8a443f916cc87bd48e93ee9004b579f65b5 Mon Sep 17 00:00:00 2001 From: jfactory-es Date: Sun, 3 Nov 2024 23:18:25 +0000 Subject: [PATCH] chore(build): add build id --- dist/cjs-devel/index.cjs | 2 +- dist/cjs-devel/jFactory-env.cjs | 2 +- dist/cjs/index.cjs | 2 +- dist/cjs/jFactory-env.cjs | 2 +- dist/es-devel/index.mjs | 2 +- dist/es-devel/jFactory-env.mjs | 2 +- dist/es/index.mjs | 2 +- dist/es/jFactory-env.mjs | 2 +- dist/index-loader.cjs | 2 +- dist/index-loader.mjs | 2 +- dist/umd/jFactory-devel.umd.js | 4 ++-- dist/umd/jFactory-devel.umd.js.map | 2 +- dist/umd/jFactory.umd.js | 4 ++-- dist/umd/jFactory.umd.js.map | 2 +- scripts/build/rollup.config.cjs | 4 ++-- src/tpl/banner.txt | 2 +- 16 files changed, 19 insertions(+), 19 deletions(-) diff --git a/dist/cjs-devel/index.cjs b/dist/cjs-devel/index.cjs index c282fb8..2028156 100644 --- a/dist/cjs-devel/index.cjs +++ b/dist/cjs-devel/index.cjs @@ -1,5 +1,5 @@ /*! - * jFactory-devel v1.8.0-alpha.2 2024-11-03 + * jFactory-devel v1.8.0-alpha.2+build.1730675680538 * https://github.com/jfactory-es/jfactory * (c) 2019-2024 Stephane Plazis * License: https://raw.githubusercontent.com/jfactory-es/jfactory/master/LICENSE.md diff --git a/dist/cjs-devel/jFactory-env.cjs b/dist/cjs-devel/jFactory-env.cjs index 15c2384..35b4f5a 100644 --- a/dist/cjs-devel/jFactory-env.cjs +++ b/dist/cjs-devel/jFactory-env.cjs @@ -17,7 +17,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); */ const JFACTORY_NAME = "jFactory-devel"; -const JFACTORY_VER = "1.8.0-alpha.2"; +const JFACTORY_VER = "1.8.0-alpha.2+build.1730675680538"; const JFACTORY_DEV = true; // Developer Mode const JFACTORY_MOD = "cjs" ?? "raw"; diff --git a/dist/cjs/index.cjs b/dist/cjs/index.cjs index 2450186..ad4664f 100644 --- a/dist/cjs/index.cjs +++ b/dist/cjs/index.cjs @@ -1,5 +1,5 @@ /*! - * jFactory v1.8.0-alpha.2 2024-11-03 + * jFactory v1.8.0-alpha.2+build.1730675680538 * https://github.com/jfactory-es/jfactory * (c) 2019-2024 Stephane Plazis * License: https://raw.githubusercontent.com/jfactory-es/jfactory/master/LICENSE.md diff --git a/dist/cjs/jFactory-env.cjs b/dist/cjs/jFactory-env.cjs index 7db6e6c..742fba0 100644 --- a/dist/cjs/jFactory-env.cjs +++ b/dist/cjs/jFactory-env.cjs @@ -17,7 +17,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); */ const JFACTORY_NAME = "jFactory"; -const JFACTORY_VER = "1.8.0-alpha.2"; +const JFACTORY_VER = "1.8.0+build.1730675680538"; const JFACTORY_DEV = false; // Developer Mode const JFACTORY_MOD = "cjs" ?? "raw"; diff --git a/dist/es-devel/index.mjs b/dist/es-devel/index.mjs index 0e26e81..71b0669 100644 --- a/dist/es-devel/index.mjs +++ b/dist/es-devel/index.mjs @@ -1,5 +1,5 @@ /*! - * jFactory-devel v1.8.0-alpha.2 2024-11-03 + * jFactory-devel v1.8.0-alpha.2+build.1730675680538 * https://github.com/jfactory-es/jfactory * (c) 2019-2024 Stephane Plazis * License: https://raw.githubusercontent.com/jfactory-es/jfactory/master/LICENSE.md diff --git a/dist/es-devel/jFactory-env.mjs b/dist/es-devel/jFactory-env.mjs index 4595317..9b7b040 100644 --- a/dist/es-devel/jFactory-env.mjs +++ b/dist/es-devel/jFactory-env.mjs @@ -13,7 +13,7 @@ */ const JFACTORY_NAME = "jFactory-devel"; -const JFACTORY_VER = "1.8.0-alpha.2"; +const JFACTORY_VER = "1.8.0-alpha.2+build.1730675680538"; const JFACTORY_DEV = true; // Developer Mode const JFACTORY_MOD = "es" ?? "raw"; diff --git a/dist/es/index.mjs b/dist/es/index.mjs index 37b131e..97cf7b0 100644 --- a/dist/es/index.mjs +++ b/dist/es/index.mjs @@ -1,5 +1,5 @@ /*! - * jFactory v1.8.0-alpha.2 2024-11-03 + * jFactory v1.8.0-alpha.2+build.1730675680538 * https://github.com/jfactory-es/jfactory * (c) 2019-2024 Stephane Plazis * License: https://raw.githubusercontent.com/jfactory-es/jfactory/master/LICENSE.md diff --git a/dist/es/jFactory-env.mjs b/dist/es/jFactory-env.mjs index 082646b..b46c40c 100644 --- a/dist/es/jFactory-env.mjs +++ b/dist/es/jFactory-env.mjs @@ -13,7 +13,7 @@ */ const JFACTORY_NAME = "jFactory"; -const JFACTORY_VER = "1.8.0-alpha.2"; +const JFACTORY_VER = "1.8.0-alpha.2+build.1730675680538"; const JFACTORY_DEV = false; // Developer Mode const JFACTORY_MOD = "es" ?? "raw"; diff --git a/dist/index-loader.cjs b/dist/index-loader.cjs index b52bbfa..70889d5 100644 --- a/dist/index-loader.cjs +++ b/dist/index-loader.cjs @@ -1,5 +1,5 @@ /*! - * jFactory v1.8.0-alpha.2 2024-11-03 + * jFactory v1.8.0-alpha.2+build.1730675680538 * https://github.com/jfactory-es/jfactory * (c) 2019-2024 Stephane Plazis * License: https://raw.githubusercontent.com/jfactory-es/jfactory/master/LICENSE.md diff --git a/dist/index-loader.mjs b/dist/index-loader.mjs index f229df6..2b52a75 100644 --- a/dist/index-loader.mjs +++ b/dist/index-loader.mjs @@ -1,5 +1,5 @@ /*! - * jFactory v1.8.0-alpha.2 2024-11-03 + * jFactory v1.8.0-alpha.2+build.1730675680538 * https://github.com/jfactory-es/jfactory * (c) 2019-2024 Stephane Plazis * License: https://raw.githubusercontent.com/jfactory-es/jfactory/master/LICENSE.md diff --git a/dist/umd/jFactory-devel.umd.js b/dist/umd/jFactory-devel.umd.js index edc2a51..dfb1b06 100644 --- a/dist/umd/jFactory-devel.umd.js +++ b/dist/umd/jFactory-devel.umd.js @@ -1,5 +1,5 @@ /*! - * jFactory-devel v1.8.0-alpha.2 2024-11-03 + * jFactory-devel v1.8.0-alpha.2+build.1730675680538 * https://github.com/jfactory-es/jfactory * (c) 2019-2024 Stephane Plazis * License: https://raw.githubusercontent.com/jfactory-es/jfactory/master/LICENSE.md @@ -25,7 +25,7 @@ */ const JFACTORY_NAME = "jFactory-devel"; - const JFACTORY_VER = "1.8.0-alpha.2"; + const JFACTORY_VER = "1.8.0-alpha.2+build.1730675680538"; const JFACTORY_DEV = true; // Developer Mode const JFACTORY_MOD = "umd" ?? "raw"; diff --git a/dist/umd/jFactory-devel.umd.js.map b/dist/umd/jFactory-devel.umd.js.map index 5c1279e..138ad93 100644 --- a/dist/umd/jFactory-devel.umd.js.map +++ b/dist/umd/jFactory-devel.umd.js.map @@ -1 +1 @@ -{"version":3,"file":"jFactory-devel.umd.js","sources":["../../src/jFactory-env.mjs","../../src/jFactory-helpers.mjs","../../src/jFactory-config.mjs","../../src/jFactory-compat.mjs","../../src/jFactory-bootstrap.mjs","../../src/lib/JFactoryTrace.mjs","../../src/lib/JFactoryError.mjs","../../src/lib/JFactoryExpect.mjs","../../src/lib/JFactoryObject.mjs","../../src/lib/JFactoryAbout.mjs","../../src/lib/JFactoryTraits.mjs","../../src/lib/JFactoryFunction.mjs","../../src/jFactory-traits.mjs","../../src/jFactory.mjs","../../src/lib/JFactoryLogger.mjs","../../src/lib/JFactoryPromise.mjs","../../src/lib/JFactoryEvents.mjs","../../src/lib/JFactoryTime.mjs","../../src/TraitsCore.mjs","../../src/lib/JFactoryFetch.mjs","../../src/TraitsComponents.mjs","../../src/lib/JFactoryComponents.mjs","../../src/index.mjs"],"sourcesContent":["/**\n * -----------------------------------------------------------------------------------------------------------------\n * jFactory Env\n * -----------------------------------------------------------------------------------------------------------------\n * Contextualize jFactory for bundle, raw source or partial export usage\n * -----------------------------------------------------------------------------------------------------------------\n * JFACTORY_ENV_* are optional globals that allow contextualization at startup.\n * Bundler can replace some 'env(\"JFACTORY_ENV_*\")' with hard-coded primitives to improve tree shaking\n * See https://github.com/jfactory-es/jfactory/blob/master/docs/ref-overriding.md\n * -----------------------------------------------------------------------------------------------------------------\n * Status: Beta\n * -----------------------------------------------------------------------------------------------------------------\n */\n\nexport const JFACTORY_NAME = env(\"JFACTORY_ENV_NAME\") ?? \"jFactory\";\nexport const JFACTORY_VER = env(\"JFACTORY_ENV_VER\") ?? \"(custom build)\";\nexport const JFACTORY_DEV = env(\"JFACTORY_ENV_DEV\") ?? false; // Developer Mode\nexport const JFACTORY_MOD = env(\"JFACTORY_ENV_MOD\") ?? \"raw\";\n\nexport const JFACTORY_CLI = /*#__PURE__*/ env(\"JFACTORY_ENV_CLI\") ?? /*#__PURE__*/ isNode();\nexport const JFACTORY_REPL = /*#__PURE__*/ env(\"JFACTORY_ENV_REPL\") ?? /*#__PURE__*/ isPlayground();\nexport const JFACTORY_LOG = /*#__PURE__*/ env(\"JFACTORY_ENV_LOG\") ?? JFACTORY_DEV;\nexport const JFACTORY_TRACE = /*#__PURE__*/ env(\"JFACTORY_ENV_TRACE\") ?? JFACTORY_DEV;\nexport const JFACTORY_BOOT = /*#__PURE__*/ env(\"JFACTORY_ENV_BOOT\") ?? true; // Boot jFactory at load\n\nfunction env(key) {\n return globalThis[key]\n}\n\nfunction isNode() {\n return (\n typeof process === \"object\" &&\n typeof process.versions === \"object\" &&\n process.versions.node\n )\n}\n\nfunction isPlayground() {\n const hosts = [\n \"cdpn.io\",\n \"fiddle.jshell.net\",\n \"null.jsbin.com\",\n \"jsitor.com\",\n \"jseditor.io\",\n \"liveweave.com\",\n \"run.plnkr.co\",\n \"playcode.io\"\n ];\n try {\n return hosts.indexOf(new URL(document.location.href).hostname) !== -1\n } catch {}\n}","/**\n * -----------------------------------------------------------------------------------------------------------------\n * jFactory Helpers\n * -----------------------------------------------------------------------------------------------------------------\n * Centralize helpers and externals in one module\n * -----------------------------------------------------------------------------------------------------------------\n * Status: Beta\n * -----------------------------------------------------------------------------------------------------------------\n */\n\n// --------------\n// jQuery\n// --------------\n\nexport { default as jQuery } from \"jquery\";\n\n// --------------\n// Lodash\n// --------------\n\n// Individual importation improves the tree shaking\n// This is supposed to be equivalent to babel-plugin-lodash\n\n// CAUTION\n// Please ensure that the bundler configuration is updated accordingly\n// to prevent unexpected build errors, see \"external\" in /scripts/build/rollup.config.cjs\n// export { default as helper_camelCase } from \"lodash/camelCase.js\";\n// export { default as helper_get } from \"lodash/get.js\";\n// export { default as helper_lowerFirst } from \"lodash/lowerFirst.js\";\nexport { default as helper_template } from \"lodash/template.js\";\nexport { default as helper_isString } from \"lodash/isString.js\";\nexport { default as helper_isNumber } from \"lodash/isNumber.js\";\nexport { default as helper_isPlainObject } from \"lodash/isPlainObject.js\";\nexport { default as helper_defaultsDeep } from \"lodash/defaultsDeep.js\";\n\nexport const helper_lowerFirst = str => str ? str[0].toLowerCase() + str.slice(1) : \"\";\n\nexport function helper_get(object, path) {\n return path.split(\".\").reduce((acc, key) => acc?.[key], object);\n}\n\nexport function helper_camelCase(str) {\n return str\n .toLowerCase() // Met tout en minuscules\n .replace(/[^a-zA-Z0-9]+(.)/g,\n (match, chr) => chr.toUpperCase());\n}\n\n// import i_helper_camelCase from \"lodash/camelCase.js\";\n// import i_helper_get from \"lodash/get.js\";\n// import i_helper_lowerFirst from \"lodash/lowerFirst.js\";\n// import i_helper_template from \"lodash/template.js\";\n// import i_helper_isString from \"lodash/isString.js\";\n// import i_helper_isNumber from \"lodash/isNumber.js\";\n// import i_helper_isPlainObject from \"lodash/isPlainObject.js\";\n// import i_helper_defaultsDeep from \"lodash/defaultsDeep.js\";\n//\n// const helper_camelCase = i_helper_camelCase\n// const helper_get = i_helper_get\n// const helper_lowerFirst = i_helper_lowerFirst\n// const helper_template = i_helper_template\n// const helper_isString = i_helper_isString\n// const helper_isNumber = i_helper_isNumber\n// const helper_isPlainObject = i_helper_isPlainObject\n// const helper_defaultsDeep = i_helper_defaultsDeep\n//\n// export {\n// helper_camelCase,\n// helper_get,\n// helper_lowerFirst,\n// helper_template,\n// helper_isString,\n// helper_isNumber,\n// helper_isPlainObject,\n// helper_defaultsDeep\n// }\n\n// --------------\n// Helpers\n// --------------\n\nexport const NOOP = () => {};\nexport const helper_setFunctionName = (name, f) => Object.defineProperty(f, \"name\", { value: name });\nconst helper_url_base = typeof window !== \"undefined\" && window.location ? window.location.href : \"http://localhost\";\nexport const helper_url_abs = url => new URL(url, helper_url_base).href\n\nexport const helper_isNative = function(f) {\n return typeof f === \"function\" && Function.prototype.toString.call(f).indexOf(\"[native code]\") !== -1\n}\n\nexport function helper_useragent(id) {\n return globalThis.navigator &&\n globalThis.navigator.userAgent &&\n globalThis.navigator.userAgent.indexOf(id + \"/\") > 0\n}\n\nexport const helper_deferred = () => new Deferred;\nclass Deferred {\n constructor() {\n this._done = [];\n this._fail = [];\n }\n execute(list) {\n for (let h of list){\n h()\n }\n this.fulfilled = true\n }\n resolve() {\n this.execute(this._done);\n }\n reject() {\n this.execute(this._fail);\n }\n done(callback) {\n if (this.fulfilled) {\n callback()\n } else {\n this._done.push(callback);\n }\n }\n fail(callback) {\n if (this.fulfilled) {\n callback()\n } else {\n this._fail.push(callback);\n }\n }\n}","/**\n * -----------------------------------------------------------------------------------------------------------------\n * jFactory Config\n * -----------------------------------------------------------------------------------------------------------------\n * Status: Beta\n * -----------------------------------------------------------------------------------------------------------------\n */\nimport { JFACTORY_DEV } from \"./jFactory-env.mjs\";\n\nconst JFACTORY_CFG = {};\nexport function jFactoryCfg(key, config) {\n if (config !== undefined) {\n if (JFACTORY_DEV) {\n if (typeof config != \"object\" || config === null) {\n throw \"argument config given to jFactoryCfg(key, config) must be an object\"\n }\n }\n JFACTORY_CFG[key] = config\n }\n return JFACTORY_CFG[key] ??= {}\n}","/**\n * -----------------------------------------------------------------------------------------------------------------\n * jFactory Compat\n * -----------------------------------------------------------------------------------------------------------------\n * Status: Beta\n * -----------------------------------------------------------------------------------------------------------------\n */\n\nexport const JFACTORY_COMPAT_fetch = {\n name: \"fetch\",\n test: () => fetch,\n info: \"https://developer.mozilla.org/docs/Web/API/Fetch_API/Using_Fetch\"\n}\nexport const JFACTORY_COMPAT_Request = {\n name: \"Request\",\n test: () => Request,\n info: \"https://developer.mozilla.org/docs/Web/API/Request\"\n}\nexport const JFACTORY_COMPAT_AbortController = {\n name: \"AbortController/AbortSignal\",\n test: () => new AbortController().signal,\n info: \"https://developer.mozilla.org/docs/Web/API/AbortController, \" +\n \"https://developer.mozilla.org/docs/Web/API/AbortSignal\"\n}\nexport const JFACTORY_COMPAT_MutationObserver = {\n name: \"MutationObserver\",\n test: () => MutationObserver,\n info: \"https://developer.mozilla.org/docs/Web/API/MutationObserver\"\n}\n\n// -----------------------------------------------------------------------------------------------------------------\n// -----------------------------------------------------------------------------------------------------------------\n\nlet deferred = {};\n\nexport function jFactoryCompat_require(...args) {\n for (let compat of args) {\n deferred[compat.name] = compat\n }\n}\n\nexport function jFactoryCompat_run(entries = deferred) {\n for (let entry of Object.values(entries)) {\n let pass;\n try {pass = Boolean(entry.test())} catch (ignore) {}\n if (!pass) {\n let msg = `jFactory may require the support of \"${entry.name}\", ${entry.info}`;\n entry.message && (msg += \"\\n\" + entry.message);\n if (entry.strict) {\n throw new Error(msg)\n } else {\n console.warn(msg)\n }\n }\n }\n}","/**\n * -----------------------------------------------------------------------------------------------------------------\n * jFactory Bootstrap\n * -----------------------------------------------------------------------------------------------------------------\n * Status: Beta\n * -----------------------------------------------------------------------------------------------------------------\n */\nimport {\n JFACTORY_BOOT,\n JFACTORY_DEV,\n JFACTORY_LOG,\n JFACTORY_NAME,\n JFACTORY_VER,\n JFACTORY_MOD\n} from \"./jFactory-env.mjs\";\nimport { jFactoryCompat_run } from \"./jFactory-compat.mjs\";\n\nlet isLoaded = false;\nlet seq = [];\n\nexport function jFactoryBootstrap() {\n if (!isLoaded) {\n if (!JFACTORY_BOOT) {\n // auto bootstrap is disabled by env\n return\n }\n if (JFACTORY_DEV && JFACTORY_LOG !== 0) { // 0 => skip boot logs\n console.log(`${JFACTORY_NAME} ${JFACTORY_VER} running in development mode. ` +\n \"This incurs a performance overhead.\");\n JFACTORY_MOD !== \"es\" && console.log(\"jFactoryBootstrap Warning:\" +\n \" Consider using the ES module (jfactory/es or jfactory/es-devel) for tree-shaking.\");\n !JFACTORY_LOG && console.log(\"jFactoryBootstrap Warning: Logs disabled by JFACTORY_LOG.\");\n jFactoryCompat_run()\n }\n init();\n isLoaded = true\n }\n}\n\nfunction init() {\n if (seq) {\n for (let handler of seq) {\n handler()\n }\n seq = null;\n }\n}\n\nexport function jFactoryBootstrap_onBoot(handler) {\n if (isLoaded) {\n throw new Error(\"trying to set handler for jFactoryBootstrap() but already called:\\n\"\n + handler.toString())\n }\n seq.push(handler)\n}\n\nexport function jFactoryBootstrap_expected() {\n if (!isLoaded) {\n throw new Error(\"jFactoryBootstrap() must be called before using jFactory\")\n }\n}","/**\n * -----------------------------------------------------------------------------------------------------------------\n * JFactoryTrace\n * -----------------------------------------------------------------------------------------------------------------\n * Status: Beta, HasSideEffects\n * -----------------------------------------------------------------------------------------------------------------\n * - #limitation# Error.stack is not standardized\n * - #limitation# Error.stack is not source-mapped\n * - #limitation# bug https://bugzilla.mozilla.org/show_bug.cgi?id=1584244\n * - #limitation# StackTrace.js resolves sourcemaps. Unfortunately, it doesn't work with \"webpack:\" protocol\n * see https://github.com/stacktracejs/stacktrace.js/issues/209\n * -----------------------------------------------------------------------------------------------------------------\n * https://github.com/mozilla/source-map/\n * https://www.stacktracejs.com/\n * https://github.com/novocaine/sourcemapped-stacktrace\n * -----------------------------------------------------------------------------------------------------------------\n */\nimport { JFACTORY_DEV } from \"../jFactory-env.mjs\";\nimport { JFACTORY_TRACE } from \"../jFactory-env.mjs\";\nimport { NOOP, helper_useragent } from \"../jFactory-helpers.mjs\";\nimport { jFactoryCfg } from \"../jFactory-config.mjs\";\nimport { jFactoryBootstrap_onBoot } from \"../jFactory-bootstrap.mjs\";\n\nexport class JFactoryTrace {\n\n constructor(omitAboveFunctionName = \"JFactoryTrace\", omitSelf = true, stackTraceLimit = Infinity) {\n let _stackTraceLimit;\n if (stackTraceLimit) {\n _stackTraceLimit = Error.stackTraceLimit;\n Error.stackTraceLimit = stackTraceLimit\n }\n\n this.source = new Error();\n this.omitAboveFunctionName = omitAboveFunctionName;\n this.omitSelf = omitSelf;\n\n if (stackTraceLimit) {\n Error.stackTraceLimit = _stackTraceLimit\n }\n\n this.init()\n }\n\n init() {\n this.printable = this.source;\n this.asyncPrintable = Promise.resolve(this.printable)\n }\n\n static createErrorFromStack(stack) {\n let e = new Error();\n e.name = \"JFactoryTrace\";\n e.stack = stack;\n return e\n }\n}\n\nexport class JFactoryTrace_LIB_STACKTRACE extends JFactoryTrace {\n\n init() {\n let h = traceFrames => {\n this.printable = this.constructor.createErrorFromStack(\n this.createStackFromTraceFrames(\n this.filterTraceFrames(traceFrames)\n )\n )\n }\n\n h(StackTrace.getSync(this.source, CONFIG.libOptions));\n if (CONFIG.useSourcemap) {\n this.asyncPrintable = StackTrace.fromError(this.source, CONFIG.libOptions).then(h)\n } else {\n this.asyncPrintable = Promise.resolve(this.printable)\n }\n }\n\n filterTraceFrames(traceFrames) {\n if (this.omitAboveFunctionName) {\n let slice = traceFrames.findIndex(\n value => value.functionName && value.functionName.endsWith(this.omitAboveFunctionName)\n );\n if (slice > 0) {\n if (this.omitSelf) {\n slice++\n }\n traceFrames = traceFrames.slice(slice);\n }\n }\n return traceFrames\n }\n\n createStackFromTraceFrames(traceFrames) {\n for (let formatter of Object.values(jFactoryTrace.formatters)) {\n if (formatter.test()) {\n return formatter.format(traceFrames)\n }\n }\n return this.source.stack\n }\n}\n\n// -----------------------------------------------------------------------------------------------------------------\n// jFactoryTrace\n// -----------------------------------------------------------------------------------------------------------------\n// Status: Beta\n// -----------------------------------------------------------------------------------------------------------------\n\nlet tracer;\nif (JFACTORY_DEV && JFACTORY_TRACE) {\n\n tracer = {\n\n captureTraceSource(omitAboveFunctionName, omitSelf, stackTraceLimit) {\n return new(CONFIG.tracer || JFactoryTrace)(omitAboveFunctionName, omitSelf, stackTraceLimit)\n },\n\n attachTrace(\n targetObject, traceSource /* or omitAboveFunctionName */,\n traceLogKey = CONFIG.keys[0], traceSourceKey = CONFIG.keys[1],\n label = CONFIG.label\n ) {\n if (typeof traceSource !== \"object\") {\n traceSource = this.captureTraceSource(traceSource || \"attachTrace\", !traceSource);\n }\n\n let log = () => console.log(traceSource.printable) || label || \"The stack has been printed in the console\";\n\n Object.defineProperty(targetObject, traceLogKey, {\n // hide the function body to improve readability in devtool\n get: () => log()\n });\n\n Object.defineProperty(targetObject, traceSourceKey, {\n value: traceSource\n });\n },\n\n formatters: {\n\n webkit: {\n test() {\n return helper_useragent(\"Chrome\")\n },\n format(traceFrames) {\n // Chrome syntax\n // String must start with \"Error\" and parenthesis are important\n // => The console will convert the uri using sourcemaps\n return \"Error (generated by JFactoryTrace)\\n\" +\n traceFrames.map(sf => {\n let s = \"\\tat \";\n let uri = sf.fileName + \":\" + sf.lineNumber + \":\" + sf.columnNumber;\n if (sf.functionName) {\n s += sf.functionName + \" (\" + uri + \")\"\n } else {\n s += uri // no parenthesis\n }\n return s\n }).join(\"\\n\");\n }\n },\n\n firefox: {\n test() {\n return helper_useragent(\"Gecko\")\n },\n format(traceFrames) {\n // Firefox syntax\n return traceFrames.map(sf =>\n (sf.functionName ?? \"\")\n + \"@\" + sf.fileName + \":\" + sf.lineNumber + \":\" + sf.columnNumber\n ).join(\"\\n\");\n }\n }\n }\n }\n\n} else {\n\n tracer = {\n captureTraceSource: NOOP,\n attachTrace: NOOP\n };\n\n}\n\nexport const jFactoryTrace = tracer;\n\n// -----------------------------------------------------------------------------------------------------------------\n// Config JFactoryTrace\n// -----------------------------------------------------------------------------------------------------------------\n\nconst CONFIG = /*#__PURE__*/jFactoryCfg(\"JFactoryTrace\");\n\nif (JFACTORY_DEV && JFACTORY_TRACE) {\n CONFIG.keys = [\"$dev_traceLog\", \"$dev_traceSource\"];\n if (typeof StackTrace === \"object\") {\n CONFIG.tracer = JFactoryTrace_LIB_STACKTRACE;\n CONFIG.useSourcemap = false;\n }\n jFactoryBootstrap_onBoot(function() {\n if (CONFIG.tracer === JFactoryTrace_LIB_STACKTRACE) {\n console.log(\"JFactoryTrace: Stacktrace.js support enabled; performances will be affected\")\n }\n })\n}","/**\n * -----------------------------------------------------------------------------------------------------------------\n * JFactoryError\n * -----------------------------------------------------------------------------------------------------------------\n * Status: Beta\n * -----------------------------------------------------------------------------------------------------------------\n */\nimport { helper_get, helper_isNative, helper_lowerFirst, helper_template } from \"../jFactory-helpers.mjs\";\nimport { jFactoryCfg } from \"../jFactory-config.mjs\";\nimport { jFactoryTrace } from \"./JFactoryTrace.mjs\";\n\nexport class JFactoryError extends Error {\n constructor(message = \"unspecified error\", data = null) {\n data = Object.assign(Object.create(null), data);\n message = JFactoryError.toPrintable(message, data);\n super(message);\n this.$data = Object.assign(Object.create(null), data);\n }\n\n toString() {\n return this.message\n }\n\n * [Symbol.iterator]() {\n yield this.message;\n yield this.$data;\n }\n\n static getId(object) {\n return object[CONFIG.keys.find(key => {\n let val = helper_get(object, key);\n return val || val === 0\n })]\n }\n\n static toPrintableData(data) {\n const templateData = {};\n let nv;\n for (let [key, val] of Object.entries(data)) {\n switch (typeof val) {\n case \"function\":\n val = val.name + \"()\";\n break;\n case \"object\":\n if (val === null) {\n val = \"null\";\n break\n }\n if (val instanceof Error) {\n val = val.toString();\n break\n }\n if ((nv = JFactoryError.getId(val)) !== undefined) {\n val = '\"' + nv + '\"'\n } else {\n if (!helper_isNative(val.toString)) {\n val = val.toString()\n } else {\n try {\n nv = JSON.stringify(val);\n val = nv.length > CONFIG.jsonMax\n ? nv.substring(0, CONFIG.jsonMax) + \"[...]\" : nv;\n } catch (e) {\n val = \"[object \" + val.constructor.name + \"]\"\n }\n }\n }\n break;\n case \"string\":\n val = '\"' + val + '\"';\n break;\n default:\n val = String(val)\n }\n templateData[key] = val\n }\n return templateData\n }\n\n static toPrintable(template, data) {\n const templateMessage = [];\n for (let part of template.split(\";\")) {\n let placeholder;\n let re = CONFIG.regPlaceholder\n re.lastIndex = 0;\n if ((placeholder = re.exec(part))) {\n do {\n if (placeholder[1] && placeholder[1] in data) {\n templateMessage.push(part.trim());\n break\n }\n } while ((placeholder = re.exec(part)) !== null)\n } else {\n templateMessage.push(part.trim());\n }\n }\n return helper_lowerFirst(helper_template(templateMessage.join(\"; \"))(JFactoryError.toPrintableData(data)));\n }\n\n static factory(type, template) {\n let ret = {\n [type]: class extends JFactoryError {\n constructor(data, traceSource) {\n super(template, data);\n jFactoryTrace.attachTrace(this.$data, traceSource);\n }\n }\n }[type];\n\n // Chrome automatically resolves sourcemap when logging errors\n // but only if the error name starts with \"Error\"\n ret.prototype.name = \"Error JFACTORY_ERR_\" + type;\n return ret\n }\n}\n\n// -----------------------------------------------------------------------------------------------------------------\n// JFACTORY_ERR_*\n// -----------------------------------------------------------------------------------------------------------------\n\nconst E = JFactoryError.factory;\n/* eslint-disable @stylistic/js/max-len */\nexport const JFACTORY_ERR_INVALID_VALUE = /*#__PURE__*/E(\"INVALID_VALUE\", \"invalid value for ${target}; Reason: ${reason}; Given: ${given}\");\nexport const JFACTORY_ERR_INVALID_CALL = /*#__PURE__*/E(\"INVALID_CALL\", \"invalid call ${target}; Reason: ${reason}; Owner: ${owner}\");\nexport const JFACTORY_ERR_PROMISE_EXPIRED = /*#__PURE__*/E(\"PROMISE_EXPIRED\", \"expired promise ${target}; Reason: ${reason}\");\nexport const JFACTORY_ERR_REQUEST_ERROR = /*#__PURE__*/E(\"REQUEST_ERROR\", \"error requesting ${target}; Reason: ${reason}; Owner: ${owner}\");\nexport const JFACTORY_ERR_KEY_DUPLICATED = /*#__PURE__*/E(\"KEY_DUPLICATED\", \"duplicated key for ${target}; Given: ${given}\");\nexport const JFACTORY_ERR_KEY_MISSING = /*#__PURE__*/E(\"KEY_MISSING\", \"missing key for ${target}; Given: ${given}\");\n/* eslint-enable @stylistic/js/max-len */\n\n// -----------------------------------------------------------------------------------------------------------------\n// Config JFactoryError\n// -----------------------------------------------------------------------------------------------------------------\n\nconst CONFIG = /*#__PURE__*/jFactoryCfg(\"JFactoryError\", {\n regPlaceholder: /\\${([^}]+)}/g,\n jsonMax: 40,\n keys: [\"$.about.name\", \"$dev_name\", \"$name\", \"name\", \"id\"]\n})","/**\n * -----------------------------------------------------------------------------------------------------------------\n * JFactoryExpect\n * -----------------------------------------------------------------------------------------------------------------\n * A small input/output validation tool\n * -----------------------------------------------------------------------------------------------------------------\n * Status: Beta, HasSideEffects\n * -----------------------------------------------------------------------------------------------------------------\n */\nimport { JFACTORY_DEV } from \"../jFactory-env.mjs\";\nimport { JFACTORY_ERR_INVALID_VALUE } from \"./JFactoryError.mjs\";\nimport { helper_isNumber, helper_isPlainObject, helper_isString } from \"../jFactory-helpers.mjs\";\nimport { jFactoryBootstrap_onBoot } from \"../jFactory-bootstrap.mjs\";\nimport { jFactoryBootstrap_expected } from \"../jFactory-bootstrap.mjs\";\n\n/**\n * @return {*|JFactoryExpect}\n */\nexport function JFactoryExpect(label, value) {\n JFACTORY_DEV && jFactoryBootstrap_expected();\n if (new.target) {\n this.label = label;\n this.value = value;\n } else {\n return new JFactoryExpect(label, value)\n }\n}\n\nconst error = function jFactoryThrow(label, value, message) {\n throw new JFACTORY_ERR_INVALID_VALUE({\n target: label,\n reason: message,\n given: value\n })\n};\n\nconst staticMethods = {\n /**\n * @method notUndefined\n * @memberOf JFactoryExpect#\n * @return JFactoryExpect\n */\n /**\n * @method notUndefined\n * @memberOf JFactoryExpect\n */\n notUndefined(label, value) {\n if (value === undefined) {\n error(label, value, \"cannot be undefined\")\n }\n return true\n },\n\n /**\n * @method notEmptyString\n * @memberOf JFactoryExpect#\n * @return JFactoryExpect\n */\n /**\n * @method notEmptyString\n * @memberOf JFactoryExpect\n */\n notEmptyString(label, value) {\n if (value === \"\") {\n error(label, value, \"cannot be empty string\")\n }\n return true\n },\n\n /**\n * @method notFalsy\n * @memberOf JFactoryExpect#\n * @return JFactoryExpect\n */\n /**\n * @method notFalsy\n * @memberOf JFactoryExpect\n */\n notFalsy(label, value) {\n if (!value) {\n error(label, value, 'cannot be a falsy value (undefined, null, NaN, 0, \"\")')\n }\n return true\n },\n\n /**\n * @method validSpaces\n * @memberOf JFactoryExpect#\n * @return JFactoryExpect\n */\n /**\n * @method validSpaces\n * @memberOf JFactoryExpect\n */\n validSpaces(label, value) {\n if (!value.replace || value.replace(/\\s+/g, \" \").trim() !== value) {\n error(label, value, \"invalid space delimiters\")\n }\n return true\n },\n\n /**\n * @method matchReg\n * @memberOf JFactoryExpect#\n * @param {RegExp} reg\n * @return JFactoryExpect\n */\n /**\n * @method matchReg\n * @memberOf JFactoryExpect\n */\n matchReg(label, value, reg) {\n if (!reg.test(value)) {\n error(label, value, 'string \"' + value + '\" must match ' + reg)\n }\n return true\n },\n\n /**\n * @method type\n * @memberOf JFactoryExpect#\n * @param {...*} expected\n * @return JFactoryExpect\n */\n /**\n * @method type\n * @memberOf JFactoryExpect\n */\n type(label, value, ...expected) {\n let name, ok = false;\n for (let constructor of expected) {\n if (constructor === null) {\n name = \"Null\"\n } else if (\"name\" in constructor) {\n name = constructor.name\n }\n let test = staticMethods[\"type\" + name];\n if (test) {\n try {ok = test(label, value/*, e*/)} catch (e) {}\n } else {\n ok = value instanceof constructor\n }\n if (ok) break\n }\n if (!ok) {\n error(label, value, \"must be an instance of [\" + expected.map(e => e.name).join(\", \") + \"]\")\n }\n return true\n },\n\n /**\n * @method typeNull\n * @memberOf JFactoryExpect#\n * @return JFactoryExpect\n */\n /**\n * @method typeNull\n * @memberOf JFactoryExpect\n */\n typeNull(label, value) {\n if (value !== null) {\n error(label, value, \"must be null\")\n }\n return true\n },\n\n /**\n * @method typeBoolean\n * @memberOf JFactoryExpect#\n * @return JFactoryExpect\n */\n /**\n * @method typeBoolean\n * @memberOf JFactoryExpect\n */\n typeBoolean(label, value) {\n if (value !== true && value !== false) {\n error(label, value, \"must be a boolean\")\n }\n return true\n },\n\n /**\n * @method typeString\n * @memberOf JFactoryExpect#\n * @return JFactoryExpect\n */\n /**\n * @method typeString\n * @memberOf JFactoryExpect\n */\n typeString(label, value) {\n if (!helper_isString(value)) {\n error(label, value, \"must be a string\")\n }\n return true\n },\n\n /**\n * @method typeNumber\n * @memberOf JFactoryExpect#\n * @return JFactoryExpect\n */\n /**\n * @method typeNumber\n * @memberOf JFactoryExpect\n */\n typeNumber(label, value) {\n if (!helper_isNumber(value)) {\n error(label, value, \"must be a number\")\n }\n return true\n },\n\n /**\n * @method typeFunction\n * @memberOf JFactoryExpect#\n * @return JFactoryExpect\n */\n /**\n * @method typeFunction\n * @memberOf JFactoryExpect\n */\n typeFunction(label, value) {\n if (!(typeof value === \"function\")) {\n error(label, value, \"must be a function\")\n }\n return true\n },\n\n /**\n * @method typePlainObject\n * @memberOf JFactoryExpect#\n * @return JFactoryExpect\n */\n /**\n * @method typePlainObject\n * @memberOf JFactoryExpect\n */\n typePlainObject(label, value) {\n if (!helper_isPlainObject(value)) {\n error(label, value, \"must be a plain object\")\n }\n return true\n },\n\n /**\n * @method equal\n * @memberOf JFactoryExpect#\n * @param {*} expected\n * @return JFactoryExpect\n */\n /**\n * @method equal\n * @memberOf JFactoryExpect\n */\n equal(label, value, ...expected) {\n let ok = false;\n for (let e of expected) {\n if ((ok = value === e)) break\n }\n if (!ok) {\n error(label, value, \"must be one of [\" + expected + \"]\")\n }\n return true;\n },\n\n /**\n * @method equalIn\n * @memberOf JFactoryExpect#\n * @param {Array|Object} expected\n * @return JFactoryExpect\n */\n /**\n * @method equalIn\n * @memberOf JFactoryExpect\n */\n equalIn(label, value, expected) {\n if (!Array.isArray(expected)) {\n expected = Object.values(expected)\n }\n if (!expected.includes(value)) {\n error(label, value, \"must be one from [\" + expected.join(\", \") + \"]\")\n }\n return true\n },\n\n /**\n * @method properties\n * @memberOf JFactoryExpect#\n * @param {Array} expected\n * @return JFactoryExpect\n */\n /**\n * @method properties\n * @memberOf JFactoryExpect\n */\n properties(label, value, expected) {\n for (let name of Object.getOwnPropertyNames(value)) {\n JFactoryExpect(label + ', property name \"' + name + '\"', name).equalIn(expected)\n }\n return true\n },\n\n /**\n * @method writable\n * @memberOf JFactoryExpect#\n * @param {String} key\n * @return JFactoryExpect\n */\n /**\n * @method writable\n * @memberOf JFactoryExpect\n */\n writable(label, value, key) {\n if (!Object.getOwnPropertyDescriptor(value, key).writable) {\n error(label, value, \"must be writable\")\n }\n return true\n },\n\n /**\n * @method notWritable\n * @memberOf JFactoryExpect#\n * @param {String} key\n * @return JFactoryExpect\n */\n /**\n * @method notWritable\n * @memberOf JFactoryExpect\n */\n notWritable(label, value, key) {\n if (Object.getOwnPropertyDescriptor(value, key).writable) {\n error(label, value, \"must not be writable\")\n }\n return true\n },\n\n /**\n * @method enumerable\n * @memberOf JFactoryExpect#\n * @param {String} key\n * @return JFactoryExpect\n */\n /**\n * @method enumerable\n * @memberOf JFactoryExpect\n */\n enumerable(label, value, key) {\n if (!Object.prototype.propertyIsEnumerable.call(value, key)) {\n error(label, value, \"must be enumerable\")\n }\n return true\n },\n\n /**\n * @method notEnumerable\n * @memberOf JFactoryExpect#\n * @param {String} key\n * @return JFactoryExpect\n */\n /**\n * @method notEnumerable\n * @memberOf JFactoryExpect\n */\n notEnumerable(label, value, key) {\n if (Object.prototype.propertyIsEnumerable.call(value, key)) {\n error(label, value, \"must not be enumerable\")\n }\n return true\n },\n\n /**\n * @method configurable\n * @memberOf JFactoryExpect#\n * @param {String} key\n * @return JFactoryExpect\n */\n /**\n * @method configurable\n * @memberOf JFactoryExpect\n */\n configurable(label, value, key) {\n if (!Object.getOwnPropertyDescriptor(value, key).configurable) {\n error(label, value, \"must be configurable\")\n }\n return true\n },\n\n /**\n * @method notConfigurable\n * @memberOf JFactoryExpect#\n * @param {String} key\n * @return JFactoryExpect\n */\n /**\n * @method notConfigurable\n * @memberOf JFactoryExpect\n */\n notConfigurable(label, value, key) {\n if (Object.getOwnPropertyDescriptor(value, key).configurable) {\n error(label, value, \"must not be configurable\")\n }\n return true\n },\n\n /**\n * @method reservedProperty\n * @memberOf JFactoryExpect#\n * @param {String} key\n * @return JFactoryExpect\n */\n /**\n * @method reservedProperty\n * @memberOf JFactoryExpect\n */\n reservedProperty(label, value, key) {\n if (key in value) {\n error(label, value, \"is a reserved property\")\n }\n return true\n }\n};\n\njFactoryBootstrap_onBoot(function() {\n Object.assign(JFactoryExpect, staticMethods);\n // Generate members from static methods\n for (const name of Object.getOwnPropertyNames(staticMethods)) {\n JFactoryExpect.prototype[name] =\n function callStatic(...args) {\n JFactoryExpect[name](this.label, this.value, ...args);\n return this\n }\n }\n});","/**\n * -----------------------------------------------------------------------------------------------------------------\n * JFactoryObject\n * -----------------------------------------------------------------------------------------------------------------\n * Status: Beta, HasSideEffects\n * -----------------------------------------------------------------------------------------------------------------\n */\nimport { jFactoryBootstrap_onBoot } from \"../jFactory-bootstrap.mjs\";\n\nexport class JFactoryObject {\n\n static createDescriptors(descriptorPrototype = JFactoryObject.DESCRIPTORS_PROTOTYPE) {\n let create = JFactoryObject.create(descriptorPrototype, true, true);\n let o = Object.create(null);\n\n o.NONE = create();\n\n o.WRITABLE = create({ writable: true });\n o.ENUMERABLE = create({ enumerable: true });\n o.CONFIGURABLE = create({ configurable: true });\n\n o.CONFIGURABLE_WRITABLE =\n o.WRITABLE_CONFIGURABLE = create({ writable: true, configurable: true });\n\n o.CONFIGURABLE_ENUMERABLE =\n o.ENUMERABLE_CONFIGURABLE = create({ enumerable: true, configurable: true });\n\n o.ENUMERABLE_WRITABLE =\n o.WRITABLE_ENUMERABLE = create({ writable: true, enumerable: true });\n\n o.WRITABLE_ENUMERABLE_CONFIGURABLE =\n o.WRITABLE_CONFIGURABLE_ENUMERABLE =\n o.ENUMERABLE_CONFIGURABLE_WRITABLE =\n o.ENUMERABLE_WRITABLE_CONFIGURABLE =\n o.CONFIGURABLE_WRITABLE_ENUMERABLE =\n o.CONFIGURABLE_ENUMERABLE_WRITABLE = create({ writable: true, enumerable: true, configurable: true });\n\n // Shortcuts\n o.READONLY = create({ writable: false, enumerable: false, configurable: false });\n\n return o\n }\n\n /**\n * @example\n * assign(obj, 'myProperty', 123, {writable:false})\n * assign(obj, {a:1, b:2}', {writable:false})\n *\n * deprecated\n * assign(obj, 'myProperty', {value:\"ok\", writable:false}) => not strict\n * assign(obj, 'myProperty', 123) => use native instead\n * assign(obj, {a:1, b:2}) => use native instead\n */\n static assign(target, property, value, descriptor) {\n let descriptors = {};\n\n switch (typeof property) {\n\n case \"string\":\n case \"symbol\":\n\n // ------------------------------------------------\n // assign(obj, 'myProperty', 123, {writable:false})\n // ------------------------------------------------\n\n if (!descriptor) {\n throw new Error(\"missing descriptor argument; use Object.assign instead\")\n }\n\n descriptor = Object.create(descriptor); // avoid descriptor corruption\n descriptor.value = value;\n\n Object.defineProperty(target, property, descriptor);\n\n break;\n\n case \"object\":\n\n // ------------------------------------------------\n // assign(obj, {a:1, b:2}', {writable:false})\n // ------------------------------------------------\n\n [value, descriptor] = [property, value];\n\n if (!descriptor) {\n throw new Error(\"missing descriptor argument; use Object.assign instead\")\n }\n\n for (let name of Object.getOwnPropertyNames(value)) {\n descriptors[name] = Object.create(descriptor); // avoid descriptor corruption\n descriptors[name].value = value[name]\n }\n for (let name of Object.getOwnPropertySymbols(value)) {\n descriptors[name] = Object.create(descriptor); // avoid descriptor corruption\n descriptors[name].value = value[name]\n }\n\n Object.defineProperties(target, descriptors);\n\n break;\n\n default:\n throw new Error(\"invalid property argument\")\n }\n\n return target\n }\n\n static create(prototype, flat = false, disinherit = false) {\n return function create(properties) {\n if (flat) {\n return Object.assign(disinherit ? Object.create(null) : {}, prototype, properties)\n } else {\n return Object.assign(Object.create(\n disinherit ? Object.assign(Object.create(null), prototype) : prototype\n ), properties)\n }\n }\n }\n\n static disinherit(object) {\n return Object.assign(Object.create(null), object);\n }\n}\n\nJFactoryObject.DESCRIPTORS_PROTOTYPE = { writable: false, enumerable: false, configurable: false };\n\njFactoryBootstrap_onBoot(function() {\n JFactoryObject.descriptors = JFactoryObject.createDescriptors()\n});","/**\n * -----------------------------------------------------------------------------------------------------------------\n * JFactoryAbout\n * -----------------------------------------------------------------------------------------------------------------\n * Status: Beta\n * -----------------------------------------------------------------------------------------------------------------\n */\nimport { JFACTORY_DEV } from \"../jFactory-env.mjs\";\nimport { helper_camelCase } from \"../jFactory-helpers.mjs\";\nimport { JFactoryExpect } from \"./JFactoryExpect.mjs\";\nimport { JFactoryObject } from \"./JFactoryObject.mjs\";\n\nconst moduleGenId = () => ++moduleGenId.uid; moduleGenId.uid = 0;\n\nexport class JFactoryAbout {\n constructor(owner, about = {}) {\n if (JFACTORY_DEV) {\n JFactoryExpect(\"JFactoryAbout(owner)\", owner).type(Object);\n JFactoryExpect(\"JFactoryAbout(about)\", about)\n .typePlainObject()\n .reservedProperty(\"uid\")\n .reservedProperty(\"fingerprint\");\n if (\"name\" in about) {\n JFactoryExpect(\"JFactoryAbout(about.name)\", about.name)\n .typeString()\n .notEmptyString()\n }\n }\n\n let name;\n let fingerprint;\n let uid = moduleGenId();\n\n if (about.name) {\n name = about.name;\n delete about.name;\n fingerprint = \"jFactory\" + \"_\" + helper_camelCase(name.toLowerCase()) + \"_\" + uid\n } else {\n delete about.name;\n name = `[${owner.constructor.name}#${uid}]`;\n fingerprint = \"jFactory\" + \"_\" + owner.constructor.name + \"_\" + uid;\n }\n\n JFactoryObject.assign(this, /** @lends JFactoryAbout# */ {\n uid,\n name,\n fingerprint\n }, JFactoryObject.descriptors.ENUMERABLE);\n\n Object.assign(this, about);\n\n // ---\n\n if (JFACTORY_DEV) {\n JFactoryExpect(\"JFactoryAbout.name\", this.name)\n .matchReg(/^[\\w[\\]#]+$/);\n JFactoryExpect(\"JFactoryAbout.fingerprint\", this.fingerprint)\n .matchReg(/^[\\w]+$/);\n }\n }\n}","/**\n * -----------------------------------------------------------------------------------------------------------------\n * JFactoryTraits\n * -----------------------------------------------------------------------------------------------------------------\n * Status: Beta\n * -----------------------------------------------------------------------------------------------------------------\n */\nimport { JFACTORY_DEV, JFACTORY_LOG } from \"../jFactory-env.mjs\";\nimport { JFactoryExpect } from \"./JFactoryExpect.mjs\";\n\nexport class JFactoryTraits {\n /**\n * @param {JFactoryCoreObject|Object} callerInstance\n * @param {Class|Function} callerConstructor\n * @param options\n */\n constructor(callerInstance, callerConstructor, options = {}) {\n /**\n * @type {JFactoryCoreObject}\n */\n this.callerInstance = callerInstance;\n\n /**\n * @type {Class|Function}\n */\n this.callerConstructor = callerConstructor;\n\n /**\n * @type {Object}\n */\n this.options = options;\n }\n\n use(trait, ...traitArgs) {\n if (JFACTORY_DEV) {\n JFactoryExpect(\"JFactoryTraits(trait)\", trait).typeFunction();\n }\n\n // callerConstructor is not always the callerInstance.constructor:\n // The Trait can be injected in an inherited constructor from super() at call time\n let { callerInstance, callerConstructor } = this;\n\n // Detect improper duplication (can be a trait already called by a super class)\n let cache = JFactoryTraits.CACHE.get(callerInstance);\n\n if (cache) {\n if (cache.has(trait)) {\n if (JFACTORY_LOG) {\n console.warn(`${trait.name} already called on`, callerInstance);\n }\n return this;\n } else {\n cache.add(trait)\n }\n } else {\n JFactoryTraits.CACHE.set(callerInstance, new WeakSet([trait]))\n }\n\n !callerConstructor.JFactoryTrait && (callerConstructor.JFactoryTrait = new WeakSet);\n\n if (!callerConstructor.JFactoryTrait.has(trait)) {\n callerConstructor.JFactoryTrait.add(trait);\n this.export(trait.prototype, callerConstructor.prototype);\n this.export(trait, callerConstructor, true);\n }\n\n // In a Trait.constructor(callerInstance, ...args) : this != callerInstance\n // In a Trait.trait_constructor(...args) : this == callerInstance (traits is injected and available)\n\n // Traits are injections. They are not dynamic inheritance.\n // So the Trait.constructor() doesn't share the \"this\" keyword with its caller.\n\n // #limitation# No way to bind an ES6 class constructor to an object\n // => Implementer can define a \"trait_constructor()\" that is automatically bound to \"callerInstance\"\n // and called after the native trait constructor().\n\n let traitInstance = new trait(callerInstance, ...traitArgs);\n if (traitInstance.trait_constructor) {\n traitInstance.trait_constructor.apply(callerInstance, traitArgs)\n }\n return this\n }\n\n export(source, target, isStatic) {\n let sourceDescriptor = Object.getOwnPropertyDescriptors(source);\n\n for (let propertyName of Object.keys(sourceDescriptor)) {\n let prefix = JFactoryTraits.getPrefix(propertyName);\n\n if (JFactoryTraits.getTarget(propertyName, target, prefix)) {\n let propertyDescriptor = sourceDescriptor[propertyName];\n let parsed = (this.options.parser || JFactoryTraits.defaultParser)(\n propertyName, propertyDescriptor, source, target, isStatic\n );\n if (parsed) {\n ({ propertyName, propertyDescriptor } = parsed);\n Object.defineProperty(target, propertyName, propertyDescriptor);\n }\n }\n }\n }\n\n static defaultParser(propertyName, propertyDescriptor, source, target, isStatic) {\n let value = propertyDescriptor.value;\n\n if (isStatic) {return null} // don't export static members\n\n if (propertyName in target) { // skip existing properties\n if (JFACTORY_LOG) {\n console.warn(\n `${target.constructor.name}> skipping export of existing property \"${propertyName}\"`,\n value);\n }\n return null\n }\n\n if (typeof value === \"object\") { // prevent shared object exportation\n if (JFACTORY_LOG) {\n console.warn(\n `${target.constructor.name}> skipping export of shared object \"${propertyName}\"`,\n value);\n }\n return null;\n }\n\n return { propertyName, propertyDescriptor }\n }\n\n static getPrefix(key) {\n let split = key.split(\"_\");\n return split.length > 1 ? split[0] : null;\n }\n\n static getTarget(key, target, prefix) {\n if (\n JFactoryTraits.EXCLUDES.includes(key) ||\n prefix === \"trait\"\n ) {\n return null\n }\n\n return target\n }\n}\n\nJFactoryTraits.CACHE = new WeakMap;\nJFactoryTraits.EXCLUDES = [\"constructor\", \"prototype\", \"length\", \"size\"];","/**\n * -----------------------------------------------------------------------------------------------------------------\n * JFactoryFunction\n * -----------------------------------------------------------------------------------------------------------------\n * Status: Beta\n * -----------------------------------------------------------------------------------------------------------------\n */\nimport { JFACTORY_DEV, JFACTORY_LOG } from \"../jFactory-env.mjs\";\nimport { JFACTORY_ERR_INVALID_CALL } from \"./JFactoryError.mjs\";\nimport { JFactoryExpect } from \"./JFactoryExpect.mjs\";\nimport { helper_setFunctionName } from \"../jFactory-helpers.mjs\";\n\n// -----------------------------------------------------------------------------------------------------------------\n// JFactoryFunctionComposer\n// -----------------------------------------------------------------------------------------------------------------\n\nexport class JFactoryFunctionComposer {\n\n constructor() {\n this.handlers = Object.create(null);\n }\n\n * [Symbol.iterator](handlerGroups = []) {\n\n if (!handlerGroups.length) {\n handlerGroups = Object.keys(this.handlers)\n }\n if (!handlerGroups.length) {\n handlerGroups = [\"default\"]\n }\n\n for (let handlerGroup of handlerGroups) {\n if (handlerGroup in this.handlers) {\n yield* this.handlers[handlerGroup]\n }\n }\n }\n\n /** @return {JFactoryFunctionComposer} */\n first(handlerGroup, handler) {\n if (arguments.length === 1) {\n [handlerGroup, handler] = [\"default\", handlerGroup]\n }\n (this.handlers[handlerGroup] || (this.handlers[handlerGroup] = [])).unshift(handler);\n return this\n }\n\n /** @return {JFactoryFunctionComposer} */\n last(handlerGroup, handler) {\n if (arguments.length === 1) {\n [handlerGroup, handler] = [\"default\", handlerGroup]\n }\n (this.handlers[handlerGroup] || (this.handlers[handlerGroup] = [])).push(handler);\n return this\n }\n\n /** @return {(function(): *) & {composer: JFactoryFunctionComposer}} */\n compose(...handlerGroups) {\n let composer = this;\n let composite = function() {\n // !!!!--!!!!--!!!!--!!!!--!!!!--!!!!--!!!!--!!!! //\n // //\n // wrapped function //\n // //\n // You should Blackbox JFactoryFunction.mjs //\n // to simplify debugging //\n // //\n // !!!!--!!!!--!!!!--!!!!--!!!!--!!!!--!!!!--!!!! //\n let context = {\n canceled: false,\n parameters: Array.from(arguments),\n result: undefined\n };\n let iterator = composer[Symbol.iterator](handlerGroups);\n let iteration = iterator.next();\n return JFactoryFunctionComposer.composite_iterator(\n this /* preserve call scope */, context, iteration, iterator)\n };\n composite.composer = composer;\n return composite;\n }\n\n // SPEC: Composite functions returns promise *only* if at least\n // one handler returns a promise (async function or promise return)\n // So we cannot just iterate using an \"await for of\"\n static composite_iterator(scope, context, iteration, handlers) {\n let handler,\n result;\n\n while (!context.canceled && !iteration.done) {\n handler = iteration.value;\n if (scope) {\n result = handler.call(scope, context, ...context.parameters)\n } else {\n result = handler(context, ...context.parameters)\n }\n iteration = handlers.next(); // prepares next iteration to know if \"done\"\n if (result instanceof Promise) {\n if (iteration.done\n // case of last handler returning a promise\n // #limitation# now way to detect if the promise is the returned value or an \"await\"\n // (we don't want to change the value of context.result during a pending handler)\n // => native Promise are always chained\n && result.constructor !== Promise) {\n context.result = result // we can safely set the new result\n } else {\n return result.then(helper_setFunctionName(\n [handler.name, \"[compositeAsyncHandler]\"].filter(Boolean).join(\" \"),\n function(value) {\n context.result = value;\n return JFactoryFunctionComposer.composite_iterator(scope, context, iteration, handlers)\n })\n )\n }\n } else {\n context.result = result\n }\n }\n return context.result\n }\n}\n\n// -----------------------------------------------------------------------------------------------------------------\n// JFactoryFunctionExpirable - Expirable Function Pattern\n// -----------------------------------------------------------------------------------------------------------------\n\nexport function jFactoryFunctionExpirable(originalHandler) {\n return new JFactoryFunctionExpirable(originalHandler).compose()\n}\n\nexport class JFactoryFunctionExpirable {\n\n constructor(originalHandler) {\n this.originalHandler = originalHandler;\n this.expiredCalls = 0;\n this.composer = new JFactoryFunctionComposer;\n\n let isExpired = this.composer.compose(\"conditions\");\n let expirable = this;\n let expired;\n\n // cannot use a real accessor here (conditions can be scoped, so isExpired too)\n this.isExpired = scope => expired || isExpired.call(scope) || false;\n this.setExpired = value => expired = value ?\n value instanceof Error ? value : new JFACTORY_ERR_INVALID_CALL({\n target: this.originalHandler,\n reason: \"manually expired\"\n }) : Boolean(this.expiredCalls = 0);\n\n this.addExpireCondition = function(condition) {\n this.composer.last(\"conditions\", function(context) {\n let done = function(result) {\n if (JFACTORY_DEV) {\n JFactoryExpect(\"JFactoryFunctionExpirable.addExpireCondition(), result\", result)\n .type(Boolean, Error)\n }\n return expirable.setExpired(result ?\n (context.canceled = true) &&\n (result instanceof Error ?\n result :\n new JFACTORY_ERR_INVALID_CALL({\n target: expirable.originalHandler,\n reason: \"conditionally expired\",\n condition\n })\n ) : false\n )\n };\n let result = condition.apply(this, context.parameters);\n return result instanceof Promise ? result.then(done) : done(result);\n })\n };\n }\n\n compose() {\n let expirable = this;\n let composite = function() {\n let isExpired = expirable.isExpired(this);\n let call = expirable.constructor.call.bind(undefined, expirable, this, arguments);\n return isExpired instanceof Promise ? isExpired.then(call) : call(isExpired);\n };\n return Object.assign(composite, {\n expirable: this,\n isExpired: f => this.isExpired(f),\n setExpired: f => this.setExpired(f),\n addExpireCondition: f => {this.addExpireCondition(f); return composite}\n });\n }\n\n static call(expirable, scope, args, isExpired) {\n return isExpired ? expirable.onExpired(isExpired) : expirable.onNotExpired(scope, args);\n }\n\n onExpired(expired) {\n if (this.expiredCalls < JFactoryFunctionExpirable.MaxWarningExpiration) {\n this.expiredCalls++;\n if (JFACTORY_LOG) {\n console.warn(...new JFACTORY_ERR_INVALID_CALL({\n ...expired.$data,\n reason: expired.$data.reason\n + \"; expiredCalls=\"\n + this.expiredCalls\n + (this.expiredCalls === JFactoryFunctionExpirable.MaxWarningExpiration\n ? \"; Max Warning Exceeded\" : \"\")\n }));\n }\n }\n return expired\n }\n\n onNotExpired(scope, args) {\n return this.originalHandler.apply(scope, args)\n }\n}\n\nJFactoryFunctionExpirable.MaxWarningExpiration = 10;\n\n// -----------------------------------------------------------------------------------------------------------------\n// JFactoryFunctionConditional - Conditional Function Pattern\n// -----------------------------------------------------------------------------------------------------------------\n\nexport function jFactoryFunctionConditional(originalHandler) {\n return new JFactoryFunctionConditional(originalHandler).compose()\n}\n\nexport class JFactoryFunctionConditional {\n\n constructor(originalHandler) {\n this.originalHandler = originalHandler;\n this.composer = new JFactoryFunctionComposer;\n this.composer.first(\"original\", helper_setFunctionName(\n [originalHandler.name, \"[condition]\"].filter(Boolean).join(\" \"),\n function(context) {\n return originalHandler.apply(this, context.parameters);\n })\n );\n }\n\n compose() {\n let composite = this.composer.compose(\"conditions\", \"original\");\n return Object.assign(composite, {\n conditional: this,\n addCondition: f => {this.addCondition(f); return composite}\n });\n }\n\n addCondition(condition) {\n this.composer.last(\"conditions\", function(context) {\n let handle = function(result) {\n if (JFACTORY_DEV) {\n JFactoryExpect(\"JFactoryFunctionConditional.addCondition(), result\", result)\n .typeBoolean();\n }\n !result && (context.canceled = true);\n };\n let result = condition.apply(this, context.parameters);\n return result instanceof Promise ? result.then(handle) : handle(result);\n })\n }\n}\n\n// -----------------------------------------------------------------------------------------------------------------\n// JFactoryFunctionWrappable - Wrappable Function Pattern\n// -----------------------------------------------------------------------------------------------------------------\n\nexport function jFactoryFunctionWrappable(originalHandler) {\n return new JFactoryFunctionWrappable(originalHandler).compose()\n}\n\nexport class JFactoryFunctionWrappable {\n\n constructor(originalHandler) {\n this.originalHandler = originalHandler;\n this.composer = new JFactoryFunctionComposer;\n this.composer.first(\"original\", helper_setFunctionName(\n [originalHandler.name, \"[wrapped]\"].filter(Boolean).join(\" \"),\n function(context) {\n return originalHandler.apply(this, context.parameters);\n })\n );\n }\n\n compose() {\n let composite = this.composer.compose(\"before\", \"original\", \"after\");\n return Object.assign(composite, {\n wrappable: this,\n beforeAll: f => {this.beforeAll(f); return composite},\n justBefore: f => {this.justBefore(f); return composite},\n justAfter: f => {this.justAfter(f); return composite},\n afterAll: f => {this.afterAll(f); return composite}\n });\n }\n\n beforeAll(handler) {\n this.composer.first(\"before\", handler);\n }\n\n justBefore(handler) {\n this.composer.last(\"before\", handler);\n }\n\n justAfter(handler) {\n this.composer.first(\"after\", handler);\n }\n\n afterAll(handler) {\n this.composer.last(\"after\", handler);\n }\n}","/**\n * -----------------------------------------------------------------------------------------------------------------\n * jFactory Traits\n * -----------------------------------------------------------------------------------------------------------------\n * Status: Beta\n * -----------------------------------------------------------------------------------------------------------------\n */\nimport { JFACTORY_ERR_INVALID_CALL } from \"./lib/JFactoryError.mjs\";\nimport { JFactoryTraits } from \"./lib/JFactoryTraits.mjs\";\nimport { jFactoryFunctionWrappable } from \"./lib/JFactoryFunction.mjs\";\n\nexport function jFactoryTraits(callerInstance, callerConstructor) {\n return new JFactoryTraits(callerInstance, callerConstructor, {\n\n parser(propertyName, propertyDescriptor/*, source, target, isStatic */) {\n let parsed = JFactoryTraits.defaultParser(...arguments);\n\n if (parsed) {\n ({ propertyName, propertyDescriptor } = parsed);\n\n let value = propertyDescriptor.value;\n if (typeof value === \"function\") {\n switch (value.name) {\n case \"$install\":\n case \"$uninstall\":\n case \"$enable\":\n case \"$disable\":\n case \"$state\":\n break;\n default:\n propertyDescriptor.value = jFactoryFunctionWrappable(value)\n .beforeAll(function() {\n if (!this.$.states.enabled && this.$.service.phase === \"PHASE_NONE\") {\n let e = new JFACTORY_ERR_INVALID_CALL({\n owner: this,\n target: value,\n reason: \"component disabled\"\n });\n this.$logErr(...e);\n throw e\n }\n })\n }\n }\n\n return { propertyName, propertyDescriptor }\n }\n }\n })\n}","/**\n * -----------------------------------------------------------------------------------------------------------------\n * jFactory\n * -----------------------------------------------------------------------------------------------------------------\n * Status: Beta\n * -----------------------------------------------------------------------------------------------------------------\n */\nimport { jFactoryCfg } from \"./jFactory-config.mjs\";\n\nexport const jFactory = function(name, properties) {\n return Object.assign(new (jFactoryCfg('jFactory').baseComponent)(name), properties);\n};","/**\n * -----------------------------------------------------------------------------------------------------------------\n * JFactoryLogger\n * -----------------------------------------------------------------------------------------------------------------\n * A contextual logger that prepends a label and allows runtime filtering while preserving the caller line number\n * -----------------------------------------------------------------------------------------------------------------\n * logger.createSubLogger(label) create a sub-logger of logger; \"logger\" can be a sub-logger.\n * logger.disable() disable console for itself and sub-loggers\n * logger.disallow('log') disallow logger.log() only\n * logger.disallow('log', subLogger.label) disallow sub-logger.log() only. This is callable from any logger/sub-logger\n * -----------------------------------------------------------------------------------------------------------------\n * Status : Beta\n * -----------------------------------------------------------------------------------------------------------------\n */\nimport { JFACTORY_DEV, JFACTORY_CLI, JFACTORY_REPL } from \"../jFactory-env.mjs\";\nimport { jFactoryCfg } from \"../jFactory-config.mjs\";\nimport { JFactoryExpect } from \"./JFactoryExpect.mjs\";\nimport { helper_defaultsDeep, helper_isNative, NOOP } from \"../jFactory-helpers.mjs\";\n\nconst SYMBOL_ENABLED = Symbol();\n\nexport class JFactoryLogger {\n\n constructor(options) {\n if (JFACTORY_DEV && options) {\n JFactoryExpect(\"JFactoryLogger(options)\", options)\n .properties(Object.getOwnPropertyNames(JFactoryLogger.DEFAULT_CONFIG))\n }\n helper_defaultsDeep(this, options, CONFIG);\n this.installAccessor(\"log\");\n this.installAccessor(\"warn\");\n this.installAccessor(\"error\")\n }\n\n get enabled() {\n return this[SYMBOL_ENABLED] && (this.parentLogger ? this.parentLogger.enabled : true)\n }\n\n set enabled(v) {\n v ? this.enable() : this.disable()\n }\n\n enable() {\n if (this[SYMBOL_ENABLED] !== true) {\n this[SYMBOL_ENABLED] = true;\n }\n }\n\n disable() {\n if (this[SYMBOL_ENABLED] !== false) {\n this[SYMBOL_ENABLED] = false;\n }\n }\n\n disallow(nativeName, label = this.label) {\n if (!this.filters[label]) {this.filters[label] = {}}\n this.filters[label][nativeName] = true\n }\n\n allow(nativeName, label = this.label) {\n if (this.filters[label]) {\n delete this.filters[label][nativeName]\n }\n }\n\n installAccessor(nativeName, targetName = nativeName, target = this) {\n if (JFACTORY_DEV) {\n JFactoryExpect(\"JFactoryLogger(nativeName)\", nativeName).equalIn([\"log\", \"warn\", \"error\"]);\n }\n Object.defineProperties(target, {\n [targetName]: {\n get: this.accessor.bind(this, nativeName/*, target*/),\n configurable: true\n }\n })\n }\n\n accessor(nativeName/*, target*/) {\n if (!this[SYMBOL_ENABLED]) {\n return NOOP;\n }\n return this.condition(nativeName) && this.formatter[nativeName](this) || NOOP\n }\n\n createSubLogger(label) {\n /** @type JFactoryLogger */\n let sub = new JFactoryLogger({\n enabled: this.enabled,\n label: this.label + \".\" + label,\n styles_css: this.styles_css,\n styles_cli: this.styles_cli,\n console: this.console,\n formatter: this.formatter\n });\n sub.parentLogger = this;\n sub.condition.addCondition(() => this.enabled);\n sub.filters = this.filters; // shared to allow/disallow from anywhere\n return sub\n }\n}\n\n// #limitation# To preserve the line number, we can only use native functions, like bind\n// #limitation# Because we use bind(), only the style of the first element can be defined efficiently\n\nJFactoryLogger.FORMATTER_NATIVE = {\n log: logger => logger.console.log.bind(logger.console, logger.label + \">\"),\n warn: logger => logger.console.warn.bind(logger.console, logger.label + \">\"),\n error: logger => logger.console.error.bind(logger.console, logger.label + \">\")\n};\n\nJFactoryLogger.FORMATTER_CLI = {\n log: logger => logger.console.log.bind(logger.console, logger.styles_cli.label, logger.label + \">\"),\n warn: logger => logger.console.warn.bind(logger.console, logger.styles_cli.label, logger.label + \">\"),\n error: logger => logger.console.error.bind(logger.console, logger.styles_cli.label, logger.label + \">\")\n};\n\nJFactoryLogger.FORMATTER_BROWSER = {\n log: logger => logger.console.log.bind(logger.console, \"%c\" + logger.label + \">\", logger.styles_css.label),\n warn: logger => logger.console.warn.bind(logger.console, \"%c\" + logger.label + \">\", logger.styles_css.label),\n error: logger => logger.console.error.bind(logger.console, \"%c\" + logger.label + \">\", logger.styles_css.label)\n};\n\n/** @return {boolean} */\nJFactoryLogger.DEFAULT_CONDITION = function(nativeName) {\n if (JFACTORY_DEV) {\n JFactoryExpect(\"JFactoryLogger.condition(nativeName)\", nativeName).equalIn([\"log\", \"warn\", \"error\"]);\n JFactoryExpect(\"JFactoryLogger.enabled\", this.enabled).equal(true);\n }\n return !(this.filters[this.label] && this.filters[this.label][nativeName])\n};\n\nJFactoryLogger.DEFAULT_CONFIG = /** @lends JFactoryLogger# */ {\n label: \"\",\n enabled: true,\n parentLogger: null,\n condition: JFactoryLogger.DEFAULT_CONDITION,\n formatter:\n !helper_isNative(console.log) || JFACTORY_REPL ? JFactoryLogger.FORMATTER_NATIVE :\n JFACTORY_CLI ? JFactoryLogger.FORMATTER_CLI :\n JFactoryLogger.FORMATTER_BROWSER\n ,\n console,\n filters: {\n },\n styles_cli: {\n label: \"\\x1b[1;30m%s\\x1b[0m\"\n },\n styles_css: {\n label: \"color: gray\"\n }\n};\n\n// -----------------------------------------------------------------------------------------------------------------\n// Config JFactoryLogger\n// -----------------------------------------------------------------------------------------------------------------\n\nconst CONFIG = /*#__PURE__*/jFactoryCfg(\"JFactoryLogger\", JFactoryLogger.DEFAULT_CONFIG);","/**\n * -----------------------------------------------------------------------------------------------------------------\n * JFactoryPromise\n * -----------------------------------------------------------------------------------------------------------------\n * Status: Beta\n * -----------------------------------------------------------------------------------------------------------------\n */\nimport { JFACTORY_DEV } from \"../jFactory-env.mjs\";\nimport { JFACTORY_ERR_INVALID_CALL, JFACTORY_ERR_PROMISE_EXPIRED } from \"./JFactoryError.mjs\";\nimport { JFactoryExpect } from \"./JFactoryExpect.mjs\";\nimport { jFactoryTrace } from \"./JFactoryTrace.mjs\";\nimport { helper_isNative } from \"../jFactory-helpers.mjs\";\nimport { helper_deferred } from \"../jFactory-helpers.mjs\";\nimport { jFactoryBootstrap_expected } from \"../jFactory-bootstrap.mjs\";\nimport { jFactoryCfg } from \"../jFactory-config.mjs\";\n\n// #limitation# async functions always use the native Promise constructor even if native Promise class is overridden\n// #limitation# async functions always returns a native Promise even if returning an extended Promise\n// #limitation# async functions always returns a pending Promise even if returning a resolved Promise\n\nconst moduleGenId = () => ++moduleGenId.uid; moduleGenId.uid = 0;\n\n// -----------------------------------------------------------------------------------------------------------------\n// JFactoryPromise\n// -----------------------------------------------------------------------------------------------------------------\n\nexport class JFactoryPromise extends Promise {\n\n constructor({ name, config, traceSource }, executor) {\n JFACTORY_DEV && jFactoryBootstrap_expected();\n\n if (arguments.length === 1) {\n [name, config, executor] = [null, null, arguments[0]]\n }\n\n const chainId = moduleGenId();\n config = { ...CONFIG, ...config };\n name = name || \"unnamed\";\n\n if (JFACTORY_DEV) {\n JFactoryExpect(\"name\", name)\n .type(String, Number)\n .matchReg(/^[^. ]+$/);\n JFactoryExpect(\"config\", config).typePlainObject();\n JFactoryExpect(\"executor\", executor).typeFunction();\n }\n\n let resolve;\n let reject;\n\n super((_resolve, _reject) => {\n resolve = _resolve;\n reject = _reject;\n });\n\n const chain = new JFactoryPromiseChain(this, chainId, name, config);\n\n Object.defineProperties(this, {\n $chain: {\n enumerable: true,\n writable: true,\n value: chain\n },\n $type: {\n writable: true,\n value: \"promise\"\n },\n $value: {\n writable: true,\n value: undefined\n },\n $isSettled: {\n writable: true,\n value: false\n },\n $isRejected: {\n writable: true,\n value: null\n },\n $isFulfilled: {\n writable: true,\n value: null\n },\n $isExpired: {\n writable: true,\n value: false\n },\n $isAborted: {\n writable: true,\n value: false\n }\n });\n\n if (JFACTORY_DEV) {\n Object.defineProperties(this, {\n $dev_name: {\n configurable: true,\n value: name + \"[\" + chainId + \":0]\"\n },\n $dev_path: {\n writable: true,\n value: new JFactoryPromisePath(this)\n },\n $dev_position: {\n writable: true,\n value: 0\n }\n });\n if (!helper_isNative(executor)) {\n Object.defineProperties(this, {\n $dev_source: {\n value: executor\n }\n });\n }\n jFactoryTrace.attachTrace(this, traceSource);\n }\n\n const tryAutoComplete = () => {\n if (!this.$chain.isPending) {\n try {\n this.$chainComplete(\"auto-completed\");\n } catch (e) {\n // Case of error in \"complete\" callback\n // We catch the exception because the promise is already fulfilled\n // Furthermore this issue must be handled by the chain, not the current promise\n console.error(e) // print the error otherwise nothing happens\n }\n }\n };\n\n const onResolve = value => {\n // console.trace(\"onResolve\", this.$dev_name);\n if (!this.$isSettled) {\n // 2.3.1. If promise and x refer to the same object, reject promise with a TypeError as the reason.\n if (value === this) {\n onReject(new TypeError(\"Chaining cycle detected for promise \" + this.$dev_name));\n return;\n }\n\n let then;\n if (value !== null && (typeof value == \"object\" || typeof value == \"function\")) {\n // 2.3.3.2. If retrieving the property x.then results in a thrown exception e,\n // reject promise with e as the reason.\n try {\n then = value.then;\n } catch (e) {\n onReject(e);\n return;\n }\n }\n\n if (typeof then == \"function\") {\n let called = false;\n let resolvePromise = function(y) {\n // 2.3.3.3.1. If/when resolvePromise is called with a value y, run [[Resolve]](promise, y).\n if (!called) {\n called = true;\n onResolve(y);\n }\n };\n let rejectPromise = function(r) {\n // 2.3.3.3.2. If/when rejectPromise is called with a reason r, reject promise with r.\n if (!called) {\n called = true;\n onReject(r);\n }\n };\n\n try {\n // 2.3.3.3: If `then` is a function, call it as x.then(resolvePromise, rejectPromise)\n then.call(value, resolvePromise, rejectPromise);\n } catch (e) { // 2.3.3.3.4. If calling then throws an exception e,\n // 2.3.3.3.4.1. If resolvePromise or rejectPromise have been called, ignore it.\n if (!called) {\n // 2.3.3.3.4.2. Otherwise, reject promise with e as the reason.\n onReject(e);\n }\n }\n }\n else {\n this.$isRejected = false;\n this.$isFulfilled = true;\n if (this.$isExpired) {\n value = this.$chain.errorExpired;\n }\n resolve(value);\n onSettle(value)\n }\n }\n };\n\n const onReject = reason => {\n // console.log(\"onReject\", this.$dev_name);\n if (!this.$isSettled) {\n this.$isRejected = true;\n this.$isFulfilled = false;\n reject(reason);\n onSettle(reason)\n }\n };\n\n const onSettle = value => {\n this.$value = value;\n this.$isSettled = true;\n this.$chain.chainMap.set(this, true);\n\n if (this.$chain.chainConfig.chainAutoComplete) {\n if (this.$chain.chainMap.size === 1 && !this.$isExpired) {\n // ensures that tryAutoComplete() will be called asynchronously (then() callback is asynchronous)\n // case of promise.resolve(primitive), prevents following then() from being immediately locked\n this.then(tryAutoComplete)\n } else {\n tryAutoComplete()\n }\n }\n };\n\n let _chainAutoComplete = config.chainAutoComplete;\n Object.defineProperty(config, \"chainAutoComplete\", {\n get: () => _chainAutoComplete,\n set: value => {\n if (_chainAutoComplete !== value) {\n _chainAutoComplete = value;\n if (value) {\n tryAutoComplete()\n }\n }\n }\n });\n\n chain.chainMap.set(this, false);\n\n Object.defineProperties(this, {\n __resolve__: {\n value: onResolve\n },\n __reject__: {\n value: onReject\n }\n });\n\n try {\n executor(onResolve, onReject);\n } catch (e) {\n // console.error(\"exception in executor\", this.$dev_name);\n onReject(e)\n }\n }\n\n then(onFulfilled, onRejected, forceType) {\n let wrappedFulfilled;\n let wrappedRejected;\n let newPromise;\n\n // Caution: \"await\" detection is not reliable.\n // Passing native functions for both onFulfilled and onRejected will\n // result to \"await\" type and may cause side effects\n let type = forceType || (\n helper_isNative(onFulfilled) && !onFulfilled.name.startsWith(\"bound \") &&\n helper_isNative(onRejected) && !onRejected.name.startsWith(\"bound \")\n ? \"await\" : onFulfilled === undefined ? \"catch\" : \"then\"\n );\n\n if (onFulfilled && typeof onFulfilled === \"function\") {\n wrappedFulfilled = function(r) {\n // \"await\" must always run the native handler\n if (type === \"await\") {\n // SPEC: \"await\" throws the errorExpired if $isAborted is true.\n // Allows async function to try catch the awaited aborted promise\n // or, if not caught, breaks and ignore the rest of the async function.\n if (newPromise.$isAborted) {\n return onRejected(newPromise.$chain.errorExpired)\n } else {\n return onFulfilled(r)\n }\n }\n // otherwise don't call the handler if expired\n if (!newPromise.$isExpired) {\n if (newPromise.$isSettled) {\n // eslint-disable-next-line no-debugger\n debugger\n }\n return onFulfilled(r)\n }\n }\n }\n if (onRejected && typeof onRejected === \"function\") {\n wrappedRejected = function(r) {\n if (newPromise.$isSettled) {\n // eslint-disable-next-line no-debugger\n debugger\n }\n return onRejected(r)\n }\n }\n\n newPromise = Object.assign(super.then(wrappedFulfilled, wrappedRejected), this);\n moduleGenId.uid--; // reverse because not a new chain\n newPromise.$type = type;\n\n Object.defineProperties(newPromise, {\n __onFulfilled__: { value: onFulfilled },\n __onRejected__: { value: onRejected }\n });\n\n if (JFACTORY_DEV) {\n newPromise.$dev_position = this.$chain.chainMap.size;\n let fNames = \"\";\n if (onFulfilled && onFulfilled.name) {\n fNames += onFulfilled.name\n }\n if (onRejected && onRejected.name) {\n fNames += \",\" + onRejected.name\n }\n Object.defineProperties(newPromise, {\n $dev_name: {\n value:\n this.$chain.chainName\n + \"[\"\n + this.$chain.chainId\n + \":\"\n + this.$dev_position\n + \"]\"\n + \".\"\n + newPromise.$type\n + (fNames ? \"(\" + fNames + \")\" : \"\")\n + \"[\"\n + newPromise.$chain.chainId\n + \":\"\n + newPromise.$dev_position\n + \"]\"\n },\n $dev_path: { value: new JFactoryPromisePath(this.$dev_path, newPromise) }\n });\n }\n\n newPromise.$chain.chainMap.set(newPromise, false);\n\n if (this.$isExpired) {\n // case: p0.then(); chainAbort(); p1.then()\n // => the new promise must be expired\n // if parent promise is just expired, abort silently\n // if parent promise is aborted, abort explicitly\n\n // JFactoryPromise.setExpired(newPromise, true, !this.$isAborted, this.$chain.errorExpired);\n JFactoryPromise.setExpired(newPromise, this.$isAborted, true);\n }\n\n return newPromise\n }\n\n static resolve(optionalArgs, value) {\n // resolve()\n // resolve(optionalArgs, value)\n // resolve(value)\n\n if (arguments.length === 1) {\n [optionalArgs, value] = [{}, optionalArgs]\n }\n if (!optionalArgs) {\n optionalArgs = {}\n }\n if (value instanceof this && arguments.length === 1) {\n // Returns the promise as is (native spec)\n // but only if no optionalArgs\n return value\n } else {\n return new this(optionalArgs, function(resolve) {\n resolve(value)\n });\n }\n }\n\n static reject(optionalArgs, reason) {\n // reject()\n // reject(optionalArgs, reason)\n // reject(reason)\n\n if (arguments.length === 1) {\n [optionalArgs, reason] = [{}, optionalArgs]\n }\n if (!optionalArgs) {\n optionalArgs = {}\n }\n return new this(optionalArgs, function(resolve, reject) {\n reject(reason)\n });\n }\n\n // $toPromise(rejectIfExpired = true) {\n // return new Promise((resolve, reject) => {\n // let promise = this.then(resolve, e => {\n // debugger\n // reject(e)\n // });\n // if (rejectIfExpired) {\n // promise.$thenIfExpired(reject)\n // }\n // })\n // }\n\n // $toNewChain(abortIfExpired = true) {\n // let newChain;\n // return newChain = new JFactoryPromise((resolve, reject) => {\n // let promise = this.then(resolve, e => {\n // debugger\n // reject(e)\n // });\n // if (abortIfExpired) {\n // promise.$thenIfExpired(function(e){\n // newChain.$chainAbort(e)\n // })\n // }\n // });\n // }\n\n // A \"then\" where the handler is called only if the chain is expired\n // it's not a catch (a catchExpired concept should cancel the expiration)\n $thenIfExpired(onExpired) {\n return this.then(r => this.$chain.chainRoot.$isExpired ? onExpired(r) : r,\n undefined, \"$thenIfExpired\"\n )\n }\n\n // Completes an expires the whole chain before its normal end\n // Sets the $isAborted to true on aborted promises\n $chainAbort(reason = \"$chainAbort()\") {\n this.$chain.complete(reason, true);\n return this\n }\n\n // Manually completes and expires the whole chain\n // Only required if awaiting \"myPromise.$chain\"\n // when the autocomplete watcher is not used\n $chainComplete(reason = \"$chainComplete()\") {\n if (this.$chain.isPending) {\n throw new JFACTORY_ERR_INVALID_CALL({\n target: this,\n reason: \"Trying to complete a pending chain. Use $chainAbort() if you want to stop it.\"\n });\n }\n this.$chain.complete(reason, false);\n return this\n }\n\n $chainAutoComplete() {\n this.$chain.chainConfig.chainAutoComplete = true;\n return this\n }\n\n static setExpired(promise, abort, silent /*, reason*/) {\n promise.$isExpired = true;\n if (!promise.$isSettled) {\n if (promise.$type === \"$thenIfExpired\") {\n promise.__onFulfilled__(promise.$chain.chainRoot.$chain.errorExpired)\n }\n else if (abort) {\n promise.$isAborted = true;\n } else {\n if (!silent) {\n throw new JFACTORY_ERR_INVALID_CALL({\n target: promise,\n reason: \"promise must be aborted or settled before setting it to expired.\"\n })\n }\n }\n promise.__resolve__(/*reason*/);\n }\n }\n}\n\n// -----------------------------------------------------------------------------------------------------------------\n// JFactoryPromiseChain\n// -----------------------------------------------------------------------------------------------------------------\n\nexport class JFactoryPromiseChain {\n\n constructor(chainRoot, chainId, chainName, chainConfig) {\n Object.defineProperties(this, {\n chainConfig: { value: chainConfig },\n chainRoot: { value: chainRoot },\n chainId: { value: chainId },\n chainName: { value: chainName },\n chainMap: { value: new Map },\n isCompleted: { value: false, configurable: true },\n data: { value: {} },\n __deferred__: { value: helper_deferred() }\n })\n }\n\n get isPending() {\n return Array.from(this.chainMap.values()).includes(false)\n }\n\n then(onResolve) { // => \"await chain\"\n this.__deferred__.done(onResolve);\n return this\n }\n\n complete(reason = \"chain.complete()\", abort) {\n let chainRoot = this.chainRoot;\n if (!chainRoot.$isExpired) {\n /*let errorExpired = */chainRoot.$chain.errorExpired = new JFACTORY_ERR_PROMISE_EXPIRED({\n target: chainRoot,\n reason\n });\n\n let map = this.chainMap;\n for (let item of map.keys()) {\n JFactoryPromise.setExpired(item, abort/*, false, errorExpired*/);\n }\n\n Object.defineProperty(this, \"isCompleted\", { value: true });\n this.__deferred__.resolve();\n }\n return this\n }\n}\n\n// -----------------------------------------------------------------------------------------------------------------\n// JFactoryPromisePath\n// -----------------------------------------------------------------------------------------------------------------\n\nexport class JFactoryPromisePath extends Array {\n\n constructor() {\n super();\n for (let i of arguments) {\n if (Array.isArray(i)) {\n this.push(...i)\n } else {\n this.push(i)\n }\n }\n }\n\n get printable() {\n return this.map((v, i) => i === 0 ? v.$dev_name : v.$dev_name.split(\".\")[1]).join(\".\")\n }\n\n toString() {return this.printable}\n}\n\n/**\n * -----------------------------------------------------------------------------------------------------------------\n * JFactoryPromiseSync\n * -----------------------------------------------------------------------------------------------------------------\n * Promise that tries to resolve synchronously\n * allowing synchronous states and result\n * -----------------------------------------------------------------------------------------------------------------\n */\n\nexport class JFactoryPromiseSync extends Promise {\n\n constructor(executor) {\n\n let states = {\n $isSettled: false, // true = not pending\n $isRejected: null, // true = not pending + rejected\n $value: undefined\n };\n\n super((resolve, reject) => {\n\n let called = false;\n\n let onResolve = r => {\n if (r instanceof Promise) {\n JFactoryPromiseSync.resolve(r)\n .then(onResolve, onReject)\n } else {\n if (!called) {\n called = true;\n states.$isSettled = true;\n states.$isRejected = false;\n states.$value = r;\n resolve(r)\n }\n }\n };\n\n let onReject = r => {\n // don't resolve pending promise\n // to keep native specification\n if (!called) {\n called = true;\n states.$isSettled = true;\n states.$isRejected = true;\n states.$value = r;\n reject(r)\n }\n };\n\n try {\n executor(onResolve, onReject)\n } catch (e) {\n onReject(e)\n }\n });\n\n Object.assign(this, states);\n states = this\n }\n\n then(onFulfilled, onRejected) {\n\n if (this.$isSettled) {\n let value = this.$value;\n\n try {\n if (this.$isRejected) {\n // cancel any uncaught rejected result from this promise\n // before returning the new one\n super.then(undefined, () => null);\n\n if (onRejected && typeof onRejected === \"function\") {\n value = onRejected(value)\n } else {\n return JFactoryPromiseSync.reject(value)\n }\n } else {\n if (onFulfilled && typeof onFulfilled === \"function\") {\n value = onFulfilled(value)\n }\n }\n } catch (e) {\n return JFactoryPromiseSync.reject(e)\n }\n\n return JFactoryPromiseSync.resolve(value)\n\n } else {\n return super.then(onFulfilled, onRejected)\n }\n }\n\n static resolve(value) {\n if (value instanceof JFactoryPromiseSync) {\n return value\n } else {\n if (value instanceof Promise) {\n return new JFactoryPromiseSync(value.then.bind(value))\n } else {\n return new JFactoryPromiseSync(r => r(value))\n }\n }\n }\n}\n\n// -----------------------------------------------------------------------------------------------------------------\n// Config JFactoryPromise\n// -----------------------------------------------------------------------------------------------------------------\n\nconst CONFIG = /*#__PURE__*/jFactoryCfg(\"JFactoryPromise\", {\n chainAutoComplete: false\n});","/**\n * -----------------------------------------------------------------------------------------------------------------\n * JFactoryEvents\n * -----------------------------------------------------------------------------------------------------------------\n * https://learn.jquery.com/events/event-extensions/\n * -----------------------------------------------------------------------------------------------------------------\n * Status: Beta\n * -----------------------------------------------------------------------------------------------------------------\n */\nimport { JFACTORY_DEV } from \"../jFactory-env.mjs\";\nimport { JFACTORY_ERR_INVALID_VALUE } from \"./JFactoryError.mjs\";\nimport { JFactoryExpect } from \"./JFactoryExpect.mjs\";\nimport { JFactoryPromiseSync } from \"./JFactoryPromise.mjs\";\nimport { JFactoryFunctionComposer } from \"./JFactoryFunction.mjs\";\nimport { jQuery, helper_isPlainObject } from \"../jFactory-helpers.mjs\";\n\nexport class JFactoryEvents {\n // -------------------------------------------------------------------------------------------------------------\n // jQuery doesn't handle async trigger so jFactory provides the following :\n //\n // - triggerParallel(): the trigger function returns a Promise.all(pendingArray)\n // where pendingArray is filled by any async running handler.\n // Not recommended because it's the best way to produce unpredictable async side effects\n //\n // - triggerSeries(): handlers are run in a synchronous order, with \"await\"\n // This avoids unpredictable async race condition\n //\n // Both returns a JFactoryPromiseSync that contains the jFactory_fulfilled flag\n // This flag is immediately (not async) set to true if no async handler is still pending\n //\n // => handlers are wrapped. OriginalHandlers and wrappedHandlers relations are stored in a WeakMap\n // -------------------------------------------------------------------------------------------------------------\n\n constructor() {\n Object.defineProperties(this, /** @lends JFactoryEvents# */ {\n registry: { value: jQuery(Object.create(null)) },\n handlers: { value: new WeakMap },\n onListenerUpdate: { value: null, writable: true },\n onObserverUpdate: { value: null, writable: true }\n });\n }\n\n on({ events, handler, target, selector }) {\n if (JFACTORY_DEV) {\n JFactoryEvents.validateSelector(events);\n JFactoryExpect(\"JFactoryEvents.on({handler})\", handler).typeFunction();\n target && JFactoryExpect(\"JFactoryEvents.on({target})\", target).type(String, jQuery, HTMLElement);\n selector && JFactoryExpect(\"JFactoryEvents.on({selector})\", target).typeString();\n }\n\n let wrappedHandler = this.handlers.get(handler);\n if (target) {\n // don't need to wrap DOM handlers\n if (!wrappedHandler) {\n this.handlers.set(handler, true);\n }\n if (selector) {\n jQuery(target).on(events, selector, handler);\n } else {\n jQuery(target).on(events, handler);\n }\n if (this.onListenerUpdate) {\n this.onListenerUpdate(arguments)\n }\n } else {\n if (!wrappedHandler) {\n this.handlers.set(handler, wrappedHandler = function(e, { data, stack }) {\n stack.push(() => handler(e, data))\n });\n wrappedHandler.originalHandler = handler;\n }\n this.registry.on(events, wrappedHandler);\n if (this.onObserverUpdate) {\n this.onObserverUpdate(arguments)\n }\n }\n }\n\n off({ events, handler, target, selector }) {\n if (JFACTORY_DEV) {\n if (events !== undefined) { // off() is valid\n JFactoryEvents.validateSelector(events);\n handler && JFactoryExpect(\"JFactoryEvents.off({handler})\", handler).typeFunction();\n target && JFactoryExpect(\"JFactoryEvents.off({target})\", target).type(String, jQuery, HTMLElement);\n selector && JFactoryExpect(\"JFactoryEvents.off({selector})\", target).typeString();\n }\n }\n\n if (target) {\n if (selector) {\n jQuery(target).off(events, selector, handler)\n } else {\n jQuery(target).off(events, handler)\n }\n } else {\n jQuery(\"*\").off(events, handler);\n\n if (handler) {\n handler = this.handlers.get(handler);\n if (!handler) {\n throw new JFACTORY_ERR_INVALID_VALUE({\n target: \"handler\",\n reason: \"not registered\",\n given: handler\n })\n }\n }\n this.registry.off(events, handler);\n }\n if (this.onObserverUpdate) {\n this.onObserverUpdate(arguments)\n }\n if (this.onListenerUpdate) {\n this.onListenerUpdate(arguments)\n }\n }\n\n /**\n * Run in parallel. Don't \"await\" for async handlers\n * Obviously produces unpredictable race conditions\n */\n triggerParallel({ events, data, target }) {\n if (JFACTORY_DEV) {\n JFactoryEvents.validateSelector(events);\n target\n && JFactoryExpect(\"JFactoryEvents.triggerParallel({target})\", target).type(String, jQuery, HTMLElement)\n }\n\n const stack = [];\n const pending = [];\n events = events.split(\" \");\n\n if (target) {\n for (let event of events) {\n jQuery(target).trigger(event, { data, stack });\n }\n } else {\n for (let event of events) {\n this.registry.triggerHandler(event, { data, stack })\n }\n }\n\n for (let handler of stack) {\n let result = handler();\n if (result instanceof Promise\n && !result.$isSettled // don't need to await\n ) {\n pending.push(result)\n }\n }\n\n if (pending.length) {\n return Promise.all(pending)\n } else {\n return JFactoryPromiseSync.resolve()\n }\n }\n\n /**\n * Run in declaration order synchronously. Will \"await\" for async handlers\n * Prevents unpredictable race conditions\n */\n triggerSeries({ events, data, target }) {\n if (JFACTORY_DEV) {\n JFactoryEvents.validateSelector(events);\n target && JFactoryExpect(\"JFactoryEvents.triggerSeries({target})\", target).type(String, jQuery, HTMLElement)\n }\n\n return new JFactoryPromiseSync(async resolve => {\n const stack = [];\n events = events.split(\" \");\n\n if (target) {\n for (let event of events) {\n jQuery(target).trigger(event, { data, stack });\n }\n } else {\n for (let event of events) {\n this.registry.triggerHandler(event, { data, stack })\n }\n }\n\n for (let handler of stack) {\n let result = handler();\n if (result instanceof Promise\n && !result.$isSettled // don't need to await\n ) {\n await result\n }\n }\n resolve()\n })\n }\n}\n\n// -----------------------------------------------------------------------------------------------------------------\n// JFactoryEventsManager\n// -----------------------------------------------------------------------------------------------------------------\n\nexport class JFactoryEventsManager extends JFactoryEvents {\n constructor(parent) {\n super();\n Object.defineProperties(this, {\n parent: { value: parent },\n affiliateRules: { value: new JFactoryFunctionComposer().compose() }\n });\n this.affiliateAddRule(JFactoryEventsManager.rule_namespace)\n }\n\n affiliate(events = \"\", namespaces = \"\", options) {\n let parser = new JFactoryEventSelectorParser(events);\n for (let parsedEvent of parser.events) {\n this.affiliateRules(parsedEvent, namespaces, options)\n }\n return parser.toString();\n }\n\n affiliateAddRule(handler) {\n this.affiliateRules.composer.last(handler)\n }\n\n static rule_namespace(context, parsedEvent, namespaces) {\n namespaces = namespaces.split(\".\");\n for (let namespace of namespaces) {\n namespace && parsedEvent.addNamespace(namespace);\n }\n }\n\n on(events, target, selector, handler, options) {\n // Observers:\n // events, handler\n // events, handler, options\n\n // DOM Events:\n // events, target, handler\n // events, target, handler, options\n // events, target, selector, handler,\n // events, target, selector, handler, options\n\n switch (arguments.length) {\n case 2:\n // events, handler\n [handler, target] = [target/*, undefined*/];\n break;\n case 3:\n if (typeof arguments[2] === \"function\") {\n // events, target, handler\n [handler, selector] = [selector/*, undefined*/];\n } else {\n // events, handler, options\n [handler, options, target, selector] = [target, selector/*, undefined, undefined*/];\n }\n break;\n case 4:\n if (typeof arguments[3] === \"object\") {\n // events, target, handler, options\n [options, handler, selector] = [handler, selector/*, undefined*/];\n }\n break;\n }\n\n events = this.affiliate(events, this.parent.$.about.fingerprint, options);\n\n target === undefined ?\n super.on({ events, handler }) :\n super.on({ events, target, selector, handler/*, options*/ })\n }\n\n off(events, target, selector, handler, options) {\n // Both:\n // events (can be namespaces)\n // events, options\n // options (can be removal)\n\n // Observer:\n // events, handler\n // events, handler, options\n\n // DOM Events:\n // events, target, handler\n // events, target, handler, options\n // events, target, selector\n // events, target, selector, handler,\n // events, target, selector, handler, options\n\n const argL = arguments.length;\n switch (argL) {\n case 1:\n if (typeof arguments[0] === \"object\") {\n // options\n [options, events] = [events/*, undefined*/];\n }\n // else events (can namespaces)\n break;\n case 2:\n if (typeof arguments[1] === \"function\") {\n // events, handler\n [handler, target] = [target/*, undefined*/];\n } else if (helper_isPlainObject(arguments[1])) {\n // events, options\n [options, target] = [target/*, undefined*/]\n }\n // else events, target\n break;\n case 3:\n if (typeof arguments[2] === \"function\") {\n // events, target, handler\n [handler, selector] = [selector/*, undefined*/];\n } else if (typeof arguments[1] === \"function\") {\n // events, handler, options\n [handler, options, target, selector] = [target, selector/*, undefined, undefined*/];\n } else {\n // events, target, selector\n }\n break;\n case 4:\n if (typeof arguments[3] === \"object\") {\n // events, target, handler, options\n [options, handler, selector] = [handler, selector/*, undefined*/];\n }\n break;\n }\n\n events = this.affiliate(events, this.parent.$.about.fingerprint, options);\n\n if (argL < 2) {\n super.off({ events });\n } else {\n target ?\n super.off({ events, target, selector, handler/*, options*/ }) :\n super.off({ events, handler })\n }\n }\n\n trigger(events, target, data) {\n // events\n // events, target\n // events, data\n // events, target, data\n\n switch (arguments.length) {\n case 2:\n if (typeof target === \"object\" && !target.jquery) {\n // events, data\n [data, target] = [target]\n }\n // events, target\n break\n }\n\n return target ?\n super.triggerSeries({ events, target, data }) :\n super.triggerSeries({ events, data })\n }\n\n triggerParallel(events, target, data) {\n // events\n // events, target\n // events, data\n // events, target, data\n\n switch (arguments.length) {\n case 2:\n if (typeof target === \"object\" && !target.jquery) {\n // events, data\n [data, target] = [target]\n }\n // events, target\n break\n }\n\n return target ?\n super.triggerParallel({ events, target, data }) :\n super.triggerParallel({ events, data })\n }\n\n // #unoptimized draft#\n // It's not easy to keep this list up to date because:\n // - listeners can be removed by external dom mutations\n // - listeners can be delegated\n // - off() method can remove listeners globally\n getDomListeners(namespace) {\n let result = new Map();\n for (let elm of jQuery(\"*\")) {\n let data = jQuery._data(elm, \"events\");\n if (data) {// data = {click: [{}], ... }\n for (let entries of Object.values(data)) {// entries = [{type:...}]\n for (let entry of entries) {// entry = {type, namespace, handler, ...}\n let parser = new JFactoryEventSelector(entry.namespace);\n let types;\n if (parser.hasNamespace(namespace)) {\n if (!(types = result.get(elm))) {\n result.set(elm, types = {})\n }\n let type = types[entry.type] || (types[entry.type] = []);\n type.push({\n // ...entry,\n selector: entry.selector || null,\n handler: entry.handler,\n namespace: entry.namespace\n });\n }\n }\n }\n }\n }\n return result\n }\n\n // #unoptimized draft#\n getObservers() {\n let result = new Map();\n let events = this.registry._events;\n\n if (!events) {\n let registry = Object.values(this.registry)[0];\n let expando = Object.getOwnPropertyNames(registry).find(k => k.indexOf(\"jQuery\") === 0);\n if (registry && expando) {\n events = this.registry._events = registry[expando].events;\n }\n }\n\n if (events) {\n for (let [key, val] of Object.entries(events)) {\n let event = result.get(key);\n if (!event) {\n event = [];\n result.set(key, event);\n }\n for (let eventTypeEntry of val) {\n event.push({\n handler: eventTypeEntry.handler.originalHandler,\n namespace: eventTypeEntry.namespace\n })\n }\n }\n }\n\n return result\n }\n}\n\n// -----------------------------------------------------------------------------------------------------------------\n// JFactoryEventSelectorParser\n// -----------------------------------------------------------------------------------------------------------------\n\nexport class JFactoryEventSelectorParser {\n constructor(selectors) {\n if (JFACTORY_DEV) {\n JFactoryEvents.validateSelector(selectors);\n }\n /**\n * @type Array\n */\n this.events = selectors.split(\" \").map(selector => new JFactoryEventSelector(selector))\n }\n\n toString() {\n let s = [];\n for (let event of this.events) {\n s.push(event.toString())\n }\n return s.join(\" \")\n }\n}\n\nexport class JFactoryEventSelector {\n constructor(selector) {\n let [event, ...namespace] = selector.split(\".\");\n this.event = event;\n this.namespace = new Set(namespace)\n }\n\n /** @return {Boolean|String} */\n hasNamespace(namespaces) {\n if (!Array.isArray(namespaces)) {\n namespaces = [namespaces]\n }\n for (let namespace of namespaces) {\n if (JFACTORY_DEV) {\n if (!/^[\\w:]+$/.test(namespace)) {\n throw new JFACTORY_ERR_INVALID_VALUE({\n target: \"namespace\",\n reason: \"must be alphanumeric, underscore and colon characters\",\n given: namespace\n })\n }\n }\n if (namespace && this.namespace.has(namespace)) {\n return namespace\n }\n }\n return false\n }\n\n addNamespace(namespace) {\n if (JFACTORY_DEV) {\n if (!/^[\\w:]+$/.test(namespace)) {\n throw new JFACTORY_ERR_INVALID_VALUE({\n target: \"namespace\",\n reason: \"must be alphanumeric, underscore and colon characters\",\n given: namespace\n })\n }\n }\n this.namespace.add(namespace)\n }\n\n deleteNamespace(namespace) {\n if (JFACTORY_DEV) {\n if (!/^[\\w:]+$/.test(namespace)) {\n throw new JFACTORY_ERR_INVALID_VALUE({\n target: \"namespace\",\n reason: \"must be alphanumeric, underscore and colon characters\",\n given: namespace\n })\n }\n }\n this.namespace.delete(namespace)\n }\n\n toString() {\n return this.namespace.size ? this.event + \".\" + Array.from(this.namespace.values()).join(\".\") : this.event;\n }\n}\n\n// -----------------------------------------------------------------------------------------------------------------\n// JFactoryEvents validation\n// -----------------------------------------------------------------------------------------------------------------\n\nif (JFACTORY_DEV) {\n JFactoryEvents.validateSelector = function(selector) {\n if (JFACTORY_DEV) {\n JFactoryExpect(\"JFactoryEvents.validateSelector(selector)\", selector)\n .notUndefined()\n .validSpaces();\n }\n\n for (let [event, ns] of selector.split(\" \")\n .map(v => v.split(\".\"))\n .map(v => [v.shift(), v.join(\".\")])) {\n event && JFactoryEvents.validateEvent(event);\n ns && JFactoryEvents.validateNamespace(ns);\n }\n return true\n };\n\n JFactoryEvents.validateEvent = function(event) {\n if (JFACTORY_DEV) {\n JFactoryExpect(\"JFactoryEvents.validateEvent(event)\", event)\n .notUndefined()\n .notEmptyString()\n .validSpaces();\n }\n\n if (!/^[\\w:]+$/.test(event)) {\n throw new JFACTORY_ERR_INVALID_VALUE({\n target: \"JFactoryEvents.validateEvent(event)\",\n reason: \"must be alphanumeric, underscore and colon characters\",\n given: event\n })\n }\n\n return true\n };\n\n JFactoryEvents.validateNamespace = function(namespace) { // ex: ns.ns2.ns3\n if (JFACTORY_DEV) {\n JFactoryExpect(\"JFactoryEvents.validateNamespace(namespace)\", namespace)\n .notUndefined()\n .notEmptyString()\n .validSpaces();\n }\n\n if (!/^[\\w:.]+$/.test(namespace)) {\n throw new JFACTORY_ERR_INVALID_VALUE({\n target: \"JFactoryEvents.validateNamespace(namespace)\",\n reason: \"must be alphanumeric, underscore, dot and colon characters\",\n given: namespace\n })\n }\n\n return true\n };\n}","/**\n * -----------------------------------------------------------------------------------------------------------------\n * JFactoryTime\n * -----------------------------------------------------------------------------------------------------------------\n * Status: Beta\n * -----------------------------------------------------------------------------------------------------------------\n */\nexport class JFactoryTime extends Date {\n toString() {\n return this.toLocaleTimeString() + \", \" + this.getUTCMilliseconds() + \"ms (\" + this.valueOf() + \")\"\n }\n $toDurationString() {\n let hours = this.getUTCHours();\n let minutes = this.getUTCMinutes();\n let seconds = this.getUTCSeconds();\n let milliseconds = this.getUTCMilliseconds();\n\n let a = [];\n if (hours) {\n a.push(hours + \"h\")\n }\n if (minutes) {\n a.push(minutes + \"min\")\n }\n if (seconds) {\n a.push(seconds + \"s\")\n }\n a.push(milliseconds + \"ms\");\n if (a.length === 1) {\n return a[0];\n } else {\n return a.join(\",\") + \" (\" + this.valueOf() + \")\";\n }\n }\n}\n\nexport class JFactoryTimeTrace extends Date {\n constructor() {\n super();\n this.elapsed = null;\n Object.defineProperties(this, {\n t1: { value: null, writable: true },\n t0: { value: new JFactoryTime() }\n })\n }\n end() {\n this.t1 = new JFactoryTime();\n this.elapsed = new JFactoryTime(this.t1 - this.t0).$toDurationString()\n }\n toString() {\n return this.elapsed\n }\n}","/**\n * -----------------------------------------------------------------------------------------------------------------\n * -----------------------------------------------------------------------------------------------------------------\n * TraitCore\n * -----------------------------------------------------------------------------------------------------------------\n * -----------------------------------------------------------------------------------------------------------------\n * Status: Beta\n * -----------------------------------------------------------------------------------------------------------------\n */\nimport { JFACTORY_DEV, JFACTORY_LOG } from \"./jFactory-env.mjs\";\nimport {\n JFACTORY_ERR_KEY_DUPLICATED, JFACTORY_ERR_KEY_MISSING,\n JFACTORY_ERR_PROMISE_EXPIRED, JFactoryError\n} from \"./lib/JFactoryError.mjs\";\nimport { jFactory } from \"./jFactory.mjs\";\nimport { JFactoryExpect } from \"./lib/JFactoryExpect.mjs\";\nimport { JFactoryAbout } from \"./lib/JFactoryAbout.mjs\";\nimport { JFactoryLogger } from \"./lib/JFactoryLogger.mjs\";\nimport { JFactoryPromise, JFactoryPromiseSync } from \"./lib/JFactoryPromise.mjs\";\nimport { JFactoryEventsManager } from \"./lib/JFactoryEvents.mjs\";\nimport { JFactoryObject } from \"./lib/JFactoryObject.mjs\";\nimport { JFactoryTimeTrace } from \"./lib/JFactoryTime.mjs\";\n\n/**\n * -----------------------------------------------------------------------------------------------------------------\n * Trait Core\n * -----------------------------------------------------------------------------------------------------------------\n */\n\nexport class TraitCore {\n trait_constructor() {\n const owner = this;\n\n class SubMap extends Map {\n constructor(...args) {\n super(...args);\n Object.defineProperty(this, \"id_autoinc\", { value: 0, writable: true });\n }\n $registerSync(key, value) {\n let sub = Object.defineProperties({}, {\n $value: { value },\n $phaseRemove: { value: TraitService.getContextualRemovePhase(owner) }\n });\n this.set(key, sub);\n return sub\n }\n $registerAsync(key, taskName, promise) {\n let task = owner.$task(taskName, promise.$chain);\n\n // End of promise chain must complete the task\n promise.$chain.then(() => { // synchronous then\n task.$chainAutoComplete()\n });\n\n // Aborted task must abort the promise if still running\n task.$chain.then(() => {// synchronous then\n if (!promise.$chain.isCompleted) {\n promise.$chainAbort(\"aborted by task\")\n }\n });\n\n Object.defineProperty(promise, \"$phaseRemove\", { value: task.$phaseRemove });\n this.set(key, promise);\n return task\n }\n\n $id_resolve(str) {\n if (str.indexOf(\"?\") >= 0) {\n let id = ++this.id_autoinc;\n str = str.replace(/\\?/g, id)\n }\n return str\n }\n }\n\n const proto = Object.assign(Object.create(null), {\n [TraitCore.SYMBOL_PRIVATE]: Object.create(null),\n assign: function(property, value, descriptor) {JFactoryObject.assign(this, property, value, descriptor)},\n createSubMap: () => new SubMap()\n });\n\n Object.defineProperty(this, \"$\", { value: Object.create(proto) });\n\n // pre-define most important properties\n // to order them first in devtool (reduced form only)\n this.$.assign({\n tasks: null,\n requests: null\n }, JFactoryObject.descriptors.ENUMERABLE_WRITABLE);\n }\n}\n\nTraitCore.SYMBOL_PRIVATE = Symbol(\"_\");\n\n/**\n * -----------------------------------------------------------------------------------------------------------------\n * Trait About\n * -----------------------------------------------------------------------------------------------------------------\n */\n\nexport class TraitAbout {\n\n trait_constructor(about) {\n JFactoryObject.assign(this.$, \"about\",\n new JFactoryAbout(this, about), JFactoryObject.descriptors.READONLY)\n }\n}\n\n/**\n * -----------------------------------------------------------------------------------------------------------------\n * Trait Log\n * -----------------------------------------------------------------------------------------------------------------\n */\n\nexport class TraitLog {\n\n trait_constructor() {\n let config = Object.assign({\n label: this.$.about.name\n }, JFACTORY_LOG || {\n enabled: false\n });\n\n let logger = new JFactoryLogger(config);\n\n Object.defineProperty(this.$, \"logger\", { value: logger });\n\n logger.installAccessor(\"log\", \"$log\", this);\n logger.installAccessor(\"warn\", \"$logWarn\", this);\n logger.installAccessor(\"error\", \"$logErr\", this);\n }\n}\n\n/**\n * -----------------------------------------------------------------------------------------------------------------\n * Trait Tasks\n * -----------------------------------------------------------------------------------------------------------------\n */\n\nexport class TraitTask {\n\n trait_constructor() {\n this.$.assign(\"tasks\", this.$.createSubMap(), JFactoryObject.descriptors.ENUMERABLE);\n }\n\n $task(id, executorOrValue) {\n id = this.$.tasks.$id_resolve(id);\n\n if (JFACTORY_DEV) {\n JFactoryExpect(\"$task(id)\", id).typeString();\n JFactoryExpect(\"$task(executorOrValue)\", executorOrValue).notUndefined();\n if (this.$.tasks.has(id)) {\n throw new JFACTORY_ERR_KEY_DUPLICATED({ target: \"$task(id)\", given: id })\n }\n }\n\n let task;\n\n if (typeof executorOrValue === \"function\") {\n task = new JFactoryPromise({ name: id, owner: this }, executorOrValue)\n } else {\n task = JFactoryPromise.resolve({ name: id, owner: this }, executorOrValue);\n }\n\n task.$phaseRemove = TraitService.getContextualRemovePhase(this);\n\n let metrics;\n if (JFACTORY_DEV) {\n metrics = new JFactoryTimeTrace();\n task.$taskMetrics = { $dev_timing: metrics };\n }\n\n task.$chain.then(() => {\n if (JFACTORY_DEV) {\n metrics.end();\n }\n if (this.$.tasks.get(id)) {\n this.$taskRemove(id);\n }\n });\n\n this.$.tasks.set(id, task);\n return task\n }\n\n $taskRemove(id, reason) {\n if (JFACTORY_DEV) {\n JFactoryExpect(\"$taskRemove(id)\", id).typeString();\n reason && JFactoryExpect(\"$taskRemove(reason)\", reason).typeString();\n if (!this.$.tasks.has(id)) {\n throw new JFACTORY_ERR_KEY_MISSING({\n target: \"$taskRemove(id)\",\n given: id\n })\n }\n // eslint-disable-next-line no-debugger\n if (this.$.tasks.get(id)._called) {debugger}\n this.$.tasks.get(id)._called = true\n }\n\n let entry = this.$.tasks.get(id);\n // deleting before chainAbort() to prevent remove() recall\n this.$.tasks.delete(id);\n entry.$chainAbort(reason || \"$taskRemove()\");\n }\n\n $taskRemoveAll(removePhase) {\n if (JFACTORY_DEV) {\n JFactoryExpect(\"$taskRemoveAll(removePhase)\", removePhase)\n .equalIn(TraitService.PHASES)\n }\n let tasks = this.$.tasks;\n if (tasks.size) {\n for (const [key, task] of tasks) {\n if (task.$phaseRemove === removePhase) {\n this.$taskRemove(key, \"$taskRemoveAll(\" + removePhase + \")\")\n }\n }\n }\n }\n\n $taskPromiseAll(autoComplete = false) {\n let pending = [];\n if (this.$.tasks.size) {\n for (let task of this.$.tasks.values()) {\n if (autoComplete) {\n // resolves the chain as soon as no more pending promise in the chain\n task.$chain.chainConfig.chainAutoComplete = true;\n }\n // still pending ?\n if (task.$chain.isPending) {\n pending.push(task.$chain)\n }\n }\n }\n if (pending.length) {\n return JFactoryPromise.all(pending);\n } else {\n return JFactoryPromiseSync.resolve()\n }\n }\n}\n\n/**\n * -----------------------------------------------------------------------------------------------------------------\n * Trait Events\n * -----------------------------------------------------------------------------------------------------------------\n */\n\nexport class TraitEvents {\n\n trait_constructor() {\n assignPrivate(this, \"events\", {\n custom: new JFactoryEventsManager(this),\n kernel: new JFactoryEventsManager(this)\n }, JFactoryObject.descriptors.NONE);\n\n let eventManager = this.$[TraitCore.SYMBOL_PRIVATE].events.custom;\n\n // if (JFACTORY_DEV) { // very slow; requires optimization\n // // registry are auto updated in dev mode (unoptimized implementation)\n //\n // let listenerUpdate = () => {\n // this.$.listeners = eventManager.getDomListeners(this.$.about.fingerprint);\n // };\n // let observerUpdate = () => {\n // this.$.observers = eventManager.getObservers();\n // };\n //\n // eventManager.onListenerUpdate = listenerUpdate;\n // eventManager.onObserverUpdate = observerUpdate;\n //\n // let observer = new MutationObserver(listenerUpdate);\n // observer.observe(document.documentElement, {childList: true, subtree: true});\n //\n // listenerUpdate();\n // observerUpdate();\n // } else\n {\n Object.defineProperties(this.$, {\n listeners: {\n get: eventManager.getDomListeners.bind(eventManager, this.$.about.fingerprint),\n enumerable: true\n },\n observers: {\n get: eventManager.getObservers.bind(eventManager),\n enumerable: true\n }\n })\n }\n }\n\n $on(/* events, target, selector, handler, options */) {\n this.$[TraitCore.SYMBOL_PRIVATE].events.custom.on(...arguments)\n }\n\n $off(/* events, target, selector, handler, options */) {\n this.$[TraitCore.SYMBOL_PRIVATE].events.custom.off(...arguments)\n }\n\n $trigger(/* events, target, data */) {\n return this.$[TraitCore.SYMBOL_PRIVATE].events.custom.trigger(...arguments)\n }\n\n $triggerParallel(/* events, target, data */) {\n return this.$[TraitCore.SYMBOL_PRIVATE].events.custom.triggerParallel(...arguments)\n }\n\n $notify(events, data) {\n return this.$trigger(events, data)\n .then(() => this.$[TraitCore.SYMBOL_PRIVATE].events.kernel.trigger(events, data))\n }\n}\n\n/**\n * -----------------------------------------------------------------------------------------------------------------\n * Trait State\n * -----------------------------------------------------------------------------------------------------------------\n */\n\nexport class TraitState {\n\n trait_constructor() {\n const states = Object.create(null);\n const stateRoutes = Object.create(null);\n const kernel = this.$[TraitCore.SYMBOL_PRIVATE].events.kernel;\n\n assignPrivate(this, { states, stateRoutes }, JFactoryObject.descriptors.READONLY);\n\n JFactoryObject.assign(this.$, \"states\", new Proxy(states, {\n set: (target, key, val) => this.$state(key, val),\n get: (target, key) => states[key]\n }), JFactoryObject.descriptors.READONLY);\n\n kernel.on(\"beforeStateChange\", (e, data) => {\n let h;\n if (stateRoutes[data.key] && stateRoutes[data.key].before\n && (h = stateRoutes[data.key].before(data.val))) {\n return this.$notify(h);\n }\n });\n\n kernel.on(\"afterStateChange\", (e, data) => {\n let h;\n if (stateRoutes[data.key] && stateRoutes[data.key].after\n && (h = stateRoutes[data.key].after(data.val))) {\n return this.$notify(h);\n }\n });\n }\n\n $state(key, val, notify = true) {\n if (JFACTORY_DEV) {\n JFactoryExpect(\"$state(key)\", key).typeString();\n JFactoryExpect(\"$state(notify)\", notify).typeBoolean();\n }\n\n return new JFactoryPromiseSync(async resolve => {\n\n let states = this.$[TraitCore.SYMBOL_PRIVATE].states;\n let previousVal = states[key];\n let pending;\n\n if (!(key in states) || previousVal !== val) {\n\n pending = notify && this.$notify(\"beforeStateChange\", { key, val, previousVal });\n if (JFACTORY_DEV) {\n pending && JFactoryExpect(\"beforeStateChange result\", pending).type(JFactoryPromiseSync);\n }\n\n if (pending && !pending.$isSettled) {\n states[key] = pending;\n await pending;\n }\n\n if (val === undefined) {\n delete states[key]\n } else {\n states[key] = val;\n }\n\n pending = notify && this.$notify(\"afterStateChange\", { key, val, previousVal });\n if (JFACTORY_DEV) {\n pending && JFactoryExpect(\"afterStateChange result\", pending).type(JFactoryPromiseSync);\n }\n }\n\n if (pending) {\n pending.then(resolve);\n } else {\n resolve()\n }\n });\n }\n}\n\n/**\n * -----------------------------------------------------------------------------------------------------------------\n * Trait Service\n * -----------------------------------------------------------------------------------------------------------------\n */\n\nexport class TraitService {\n\n trait_constructor() {\n /**\n * @name this.$.service\n * @type {object}\n */\n JFactoryObject.assign(this.$, \"service\", Object.create(null), JFactoryObject.descriptors.READONLY);\n this.$.service.phase = TraitService.PHASE.NONE;\n this.$.service.phaseQueue = JFactoryPromise.resolve({ name: \"phaseQueue\" }, null);\n this.$.service.phaseTask = null;\n this.$.service.phaseMap = {\n install: new Set(),\n enable: new Set(),\n disable: new Set(),\n uninstall: new Set()\n };\n\n // Set initial states but don't trigger events\n this.$state(\"installed\", false, false);\n this.$state(\"enabled\", false, false);\n\n // Define the events to notify before/after a state change\n // stateName : {before : eventName, after : eventName}\n\n // SPEC\n // stat is changed before calling handlers even if pending\n\n assignPrivateMember(this, \"stateRoutes\", {\n installed: { after: val => val ? \"install\" : \"uninstall\" },\n enabled: { after: val => val ? \"enable\" : \"disable\" }\n }, JFactoryObject.descriptors.NONE);\n\n let custom = this.$[TraitCore.SYMBOL_PRIVATE].events.custom;\n let kernel = this.$[TraitCore.SYMBOL_PRIVATE].events.kernel;\n\n // Attach a remove phase namespaces on events\n custom.affiliateAddRule((context, parsedEvent, namespaces, options) =>\n TraitService.setEventNamespaceRemovePhase(this, parsedEvent, options)\n );\n\n // Attach module event handlers\n\n /** @name JFactoryCoreObject#onInstall */\n /** @name JFactoryCoreObject#onEnable */\n /** @name JFactoryCoreObject#onDisable */\n /** @name JFactoryCoreObject#onUninstall */\n\n let phaseResolve = handler => {\n if (this.$.tasks.size) {\n this.$taskRemoveAll(this.$.service.phase)\n }\n let promise = JFactoryPromiseSync.resolve();\n if (handler) {\n promise = promise\n .then(() => handler.call(this))\n .then(() => this.$taskPromiseAll(true))\n }\n return promise\n .catch(e => {\n if (!(/*this.$.service.isPhaseKilling &&*/ e instanceof JFACTORY_ERR_PROMISE_EXPIRED)) {\n this.$logErr(\"unhandled promise rejection in \" + this.$.service.phase + \";\",\n ...e instanceof JFactoryError ? e : [e])\n }\n });\n };\n\n kernel.on(\"install\", () => phaseResolve(this.onInstall));\n kernel.on(\"enable\", () => phaseResolve(this.onEnable));\n kernel.on(\"disable\", () => phaseResolve(this.onDisable));\n kernel.on(\"uninstall\", () => phaseResolve(this.onUninstall));\n\n kernel.on(\"disable\", () => this.$off({ removal: TraitService.PHASE.DISABLE }));\n kernel.on(\"uninstall\", () => this.$off({ removal: TraitService.PHASE.UNINSTALL }));\n }\n\n $install(enable) {\n let resolve;\n const p = new JFactoryPromise(\n { name: \"install\", config: { chainAutoComplete: true } },\n _resolve => resolve = _resolve)\n .then(() => {\n if (!this.$.states.installed) {\n this.$.service.phase = TraitService.PHASE.INSTALL;\n return this.$state(\"installed\", true)\n }\n });\n\n this.$.service.phaseMap.install.add(p);\n p.$chain.then(() => {\n this.$.service.phaseTask = null;\n this.$.service.phaseMap.install.delete(p);\n this.$.service.phase = TraitService.PHASE.NONE\n });\n\n this.$.service.phaseQueue = this.$.service.phaseQueue.then(() => {\n this.$.service.phaseTask = p;\n resolve();\n return p.$chain\n });\n\n // register the enable\n if (enable) {return this.$enable()}\n return p\n }\n\n $enable() {\n let resolve;\n const p = new JFactoryPromise(\n { name: \"enable\", config: { chainAutoComplete: true } },\n _resolve => resolve = _resolve)\n .then(() => {\n if (this.$.states.installed && !this.$.states.enabled) {\n this.$.service.phase = TraitService.PHASE.ENABLE;\n return this.$state(\"enabled\", true)\n }\n });\n\n this.$.service.phaseMap.enable.add(p);\n p.$chain.then(() => {\n this.$.service.phaseTask = null;\n this.$.service.phaseMap.enable.delete(p);\n this.$.service.phase = TraitService.PHASE.NONE\n });\n\n this.$.service.phaseQueue = this.$.service.phaseQueue.then(() => {\n this.$.service.phaseTask = p;\n resolve();\n return p.$chain\n });\n return p\n }\n\n $disable() {\n let resolve;\n const p = new JFactoryPromise(\n { name: \"disable\", config: { chainAutoComplete: true } },\n _resolve => resolve = _resolve)\n .then(() => {\n if (this.$.states.enabled) {\n this.$.service.phase = TraitService.PHASE.DISABLE;\n return this.$state(\"enabled\", false)\n }\n });\n\n this.$.service.phaseMap.disable.add(p);\n p.$chain.then(() => {\n this.$.service.phaseTask = null;\n this.$.service.phaseMap.disable.delete(p);\n this.$.service.phase = TraitService.PHASE.NONE\n });\n\n // expires all stacked enable\n for (let [key, val] of this.$.service.phaseMap.enable.entries()) {\n if (val === this.$.service.phaseTask) {\n TraitService.phaseKill(this);\n }\n val.$chainAbort();\n this.$.service.phaseMap.enable.delete(key)\n }\n\n this.$.service.phaseQueue = this.$.service.phaseQueue.then(() => {\n this.$.service.phaseTask = p;\n resolve();\n return p.$chain\n });\n return p\n }\n\n $uninstall() {\n let resolve;\n const p = new JFactoryPromise(\n { name: \"uninstall\", config: { chainAutoComplete: true } },\n _resolve => resolve = _resolve)\n .then(() => {\n if (this.$.states.installed) {\n this.$.service.phase = TraitService.PHASE.UNINSTALL;\n return this.$state(\"installed\", false)\n }\n });\n\n this.$.service.phaseMap.uninstall.add(p);\n p.$chain.then(() => {\n this.$.service.phaseTask = null;\n this.$.service.phaseMap.uninstall.delete(p);\n this.$.service.phase = TraitService.PHASE.NONE\n });\n\n // expires all stacked install\n for (let [key, val] of this.$.service.phaseMap.install.entries()) {\n if (val === this.$.service.phaseTask) {\n TraitService.phaseKill(this);\n }\n val.$chainAbort();\n this.$.service.phaseMap.install.delete(key)\n }\n\n // queue disable before uninstall\n this.$disable();\n\n this.$.service.phaseQueue = this.$.service.phaseQueue.then(() => {\n this.$.service.phaseTask = p;\n resolve();\n return p.$chain\n });\n return p\n }\n\n static phaseKill(component) {\n // component.$.service.isPhaseKilling = true;\n if (component.$.tasks.size) {\n component.$taskRemoveAll(TraitService.getContextualRemovePhase(component));\n }\n component.$.service.phase = TraitService.PHASE.NONE;\n }\n\n static getContextualRemovePhase(jFactoryCoreObject) {\n return TraitService.PHASE_REVERT[jFactoryCoreObject.$.service.phase]\n }\n\n static setEventNamespaceRemovePhase(jFactoryCoreObject, parsedEvent, options) {\n let curRemovePhase = parsedEvent.hasNamespace(TraitService.PHASES);\n let newRemovePhase = options && options.removal;\n\n if (!newRemovePhase) {\n newRemovePhase = TraitService.getContextualRemovePhase(jFactoryCoreObject);\n }\n\n // special case : on(\"uninstall\") with removal = DISABLE (the default value)\n // => disable() is always called before uninstall() causing the event to be removed too early\n if (parsedEvent.event === \"uninstall\" && newRemovePhase === TraitService.PHASE.DISABLE) {\n newRemovePhase = TraitService.PHASE.UNINSTALL\n }\n\n if (curRemovePhase !== newRemovePhase) {\n parsedEvent.deleteNamespace(curRemovePhase);\n parsedEvent.addNamespace(newRemovePhase);\n }\n\n parsedEvent.addNamespace(newRemovePhase);\n }\n}\n\nTraitService.PHASE = {\n NONE: \"PHASE_NONE\",\n INSTALL: \"PHASE_INSTALL\",\n ENABLE: \"PHASE_ENABLE\",\n DISABLE: \"PHASE_DISABLE\",\n UNINSTALL: \"PHASE_UNINSTALL\"\n};\n\nTraitService.PHASE_REVERT = {\n [TraitService.PHASE.INSTALL]: TraitService.PHASE.UNINSTALL,\n [TraitService.PHASE.UNINSTALL]: TraitService.PHASE.INSTALL,\n [TraitService.PHASE.DISABLE]: TraitService.PHASE.ENABLE,\n [TraitService.PHASE.ENABLE]: TraitService.PHASE.DISABLE,\n [TraitService.PHASE.NONE]: TraitService.PHASE.DISABLE\n};\n\nTraitService.PHASES = Object.values(TraitService.PHASE);\n\n// -----------------------------------------------------------------------------------------------------------------\n\nexport function assignPrivate(scope, property, value, descriptor) {\n JFactoryObject.assign(scope.$[TraitCore.SYMBOL_PRIVATE], property, value, descriptor)\n}\n\nexport function assignPrivateMember(scope, property, value, descriptor) {\n JFactoryObject.assign(scope.$[TraitCore.SYMBOL_PRIVATE][property], value, descriptor)\n}\n\njFactory.PHASE = JFactoryObject.disinherit(TraitService.PHASE);","/**\n * -----------------------------------------------------------------------------------------------------------------\n * JFactoryFetch\n * -----------------------------------------------------------------------------------------------------------------\n * Status: Beta\n * -----------------------------------------------------------------------------------------------------------------\n */\nimport { JFACTORY_ERR_REQUEST_ERROR } from \"./JFactoryError.mjs\";\nimport { JFactoryPromise } from \"./JFactoryPromise.mjs\";\nimport {\n JFACTORY_COMPAT_AbortController,\n JFACTORY_COMPAT_fetch,\n JFACTORY_COMPAT_Request,\n jFactoryCompat_require\n} from \"../jFactory-compat.mjs\";\n\nexport class JFactoryFetch extends JFactoryPromise {\n\n constructor(optionalArgs, url, fetchOptions = {}) {\n if (typeof optionalArgs === \"function\") {\n super(optionalArgs);\n } else {\n if (typeof optionalArgs === \"string\") {\n [optionalArgs, url, fetchOptions] = [{}, arguments[0], arguments[1]]\n }\n\n let fetchRequest = new Request(url, fetchOptions);\n\n super(optionalArgs, (resolve, reject) => {\n let promise = fetch(fetchRequest)\n .then(response => {\n this.$chain.fetchResponse = response;\n if (!response.ok) {\n throw Error(response.status + \":\" + response.statusText);\n }\n return response\n });\n\n if (fetchOptions.$typeText) {\n promise = promise\n .then(response => response.text())\n .then(r => this.$chain.responseText = r);\n }\n else if (fetchOptions.$typeJSON) {\n promise = promise\n .then(response => response.json())\n .then(r => this.$chain.responseJSON = r);\n }\n\n promise = promise.catch(reason => {\n throw new JFACTORY_ERR_REQUEST_ERROR({\n reason: reason.message || reason,\n target: this.$chain.fetchResponse && this.$chain.fetchResponse.url || url,\n owner: this,\n fetchOptions,\n fetchRequest,\n fetchResponse: this.$chain.fetchResponse || null\n }, optionalArgs.traceSource)\n });\n\n promise.then(resolve, reject)\n });\n\n this.$chain.fetchOptions = fetchOptions;\n this.$chain.fetchRequest = fetchRequest;\n\n let abortCtrl = fetchOptions.abortController || new AbortController();\n fetchOptions.signal = abortCtrl.signal;\n this.$chain.fetchAbortController = abortCtrl;\n }\n }\n\n $chainAbort(reason = \"request aborted\") {\n super.$chainAbort(reason);\n this.$chain.fetchAbortController.abort();\n return this\n }\n}\n\njFactoryCompat_require(\n JFACTORY_COMPAT_fetch,\n JFACTORY_COMPAT_Request,\n JFACTORY_COMPAT_AbortController\n);","/**\n * -----------------------------------------------------------------------------------------------------------------\n * -----------------------------------------------------------------------------------------------------------------\n * TraitComponents\n * -----------------------------------------------------------------------------------------------------------------\n * -----------------------------------------------------------------------------------------------------------------\n * Status: Beta\n * -----------------------------------------------------------------------------------------------------------------\n */\nimport { jFactory } from \"./jFactory.mjs\";\nimport { JFACTORY_DEV } from \"./jFactory-env.mjs\";\nimport { JFACTORY_COMPAT_MutationObserver, jFactoryCompat_require } from \"./jFactory-compat.mjs\";\nimport { JFACTORY_ERR_INVALID_VALUE, JFACTORY_ERR_KEY_DUPLICATED, JFACTORY_ERR_KEY_MISSING } from \"./lib/JFactoryError.mjs\";\nimport { JFactoryExpect } from \"./lib/JFactoryExpect.mjs\";\nimport { TraitCore, TraitService } from \"./TraitsCore.mjs\";\nimport { JFactoryFetch } from \"./lib/JFactoryFetch.mjs\";\nimport { JFactoryPromise } from \"./lib/JFactoryPromise.mjs\";\nimport { JFactoryObject } from \"./lib/JFactoryObject.mjs\";\nimport { jFactoryTrace } from \"./lib/JFactoryTrace.mjs\";\nimport { helper_isPlainObject, helper_url_abs, jQuery } from \"./jFactory-helpers.mjs\";\n\n/**\n * -----------------------------------------------------------------------------------------------------------------\n * Trait Fetch\n * -----------------------------------------------------------------------------------------------------------------\n */\n\nexport class TraitFetch {\n trait_constructor() {\n const kernel = this.$[TraitCore.SYMBOL_PRIVATE].events.kernel;\n kernel.on(\"disable\", () => this.$fetchRemoveAll(TraitService.PHASE.DISABLE));\n kernel.on(\"uninstall\", () => this.$fetchRemoveAll(TraitService.PHASE.UNINSTALL));\n this.$.assign(\"requests\", this.$.createSubMap(), JFactoryObject.descriptors.ENUMERABLE);\n }\n\n $fetch(id, url, fetchOptions = {}) {\n id = this.$.requests.$id_resolve(id);\n\n if (JFACTORY_DEV) {\n JFactoryExpect(\"$fetch(id)\", id).typeString();\n JFactoryExpect(\"$fetch(url)\", url).typeString();\n JFactoryExpect(\"$fetch(fetchOptions)\", fetchOptions).typePlainObject();\n if (this.$.requests.has(id)) {\n throw new JFACTORY_ERR_KEY_DUPLICATED({ target: \"$fetch(id)\", given: id })\n }\n }\n\n let promise = new JFactoryFetch({\n name: id,\n traceSource: jFactoryTrace.captureTraceSource(\"$fetch\"),\n config: {\n chainAutoComplete: true\n }\n }, url, fetchOptions);\n\n this.$.requests.$registerAsync(id, '$fetch(\"' + id + '\")', promise);\n\n promise.$chain.then(() => {\n if (this.$.requests.has(id)) {\n this.$fetchRemove(id)\n }\n });\n\n return promise;\n }\n\n $fetchText(id, url, fetchOptions = {}) {\n return this.$fetch(id, url, { ...fetchOptions, $typeText: true });\n }\n\n $fetchJSON(id, url, fetchOptions = {}) {\n return this.$fetch(id, url, { ...fetchOptions, $typeJSON: true });\n }\n\n $fetchRemove(id, reason) {\n if (JFACTORY_DEV) {\n JFactoryExpect(\"$fetchRemove(id)\", id).typeString();\n reason && JFactoryExpect(\"$fetchRemove(reason)\", reason).typeString();\n if (!this.$.requests.has(id)) {\n throw new JFACTORY_ERR_KEY_MISSING({\n target: \"$fetchRemove(id)\",\n given: id\n })\n }\n // eslint-disable-next-line no-debugger,brace-style\n if (this.$.requests.get(id)._debug_remove_called) {debugger}\n this.$.requests.get(id)._debug_remove_called = true\n }\n\n let entry = this.$.requests.get(id);\n this.$.requests.delete(id);\n entry.$chainAbort(reason || \"$fetchRemove()\");\n }\n\n $fetchRemoveAll(removePhase) {\n if (JFACTORY_DEV) {\n JFactoryExpect(\"removePhase\", removePhase)\n .equalIn(TraitService.PHASES)\n }\n let subs = this.$.requests;\n if (subs.size) {\n for (const [key, sub] of subs) {\n if (sub.$phaseRemove === removePhase) {\n this.$fetchRemove(key, \"$fetchRemoveAll(\" + removePhase + \")\")\n }\n }\n }\n }\n}\n\n/**\n * -----------------------------------------------------------------------------------------------------------------\n * Trait Timeout\n * -----------------------------------------------------------------------------------------------------------------\n */\n\nexport class TraitTimeout {\n trait_constructor() {\n const kernel = this.$[TraitCore.SYMBOL_PRIVATE].events.kernel;\n kernel.on(\"disable\", () => this.$timeoutRemoveAll(TraitService.PHASE.DISABLE));\n kernel.on(\"uninstall\", () => this.$timeoutRemoveAll(TraitService.PHASE.UNINSTALL));\n this.$.assign(\"timeouts\", this.$.createSubMap(), JFactoryObject.descriptors.ENUMERABLE);\n }\n\n $timeout(id, delay, handler = null, ...args) {\n // id\n // id, delay\n // id, delay, handler, ...args\n\n id = this.$.timeouts.$id_resolve(id);\n\n if (JFACTORY_DEV) {\n JFactoryExpect(\"id\", id).typeString();\n JFactoryExpect(\"delay\", delay).typeNumber();\n JFactoryExpect(\"handler\", handler).type(Function, null);\n if (this.$.timeouts.has(id)) {\n throw new JFACTORY_ERR_KEY_DUPLICATED({ target: \"$timeout(id)\", given: id })\n }\n }\n\n let timer;\n let promise = new JFactoryPromise(\n {\n name: id,\n traceSource: jFactoryTrace.captureTraceSource(\"$timeout\"),\n config: {\n chainAutoComplete: true\n }\n },\n resolve => {\n timer = setTimeout(() => {\n if (!promise.$isExpired) {\n resolve(handler ? handler(...args) : undefined);\n }\n }, delay)\n }\n );\n\n promise.$chain.data.timer = timer;\n this.$.timeouts.$registerAsync(id, '$timeout(\"' + id + '\")', promise);\n\n promise.$chain.then(() => {\n if (this.$.timeouts.has(id)) {\n this.$timeoutRemove(id);\n }\n });\n\n return promise;\n }\n\n $timeoutRemove(id, reason) {\n if (JFACTORY_DEV) {\n JFactoryExpect(\"$timeoutRemove(id)\", id).typeString();\n reason && JFactoryExpect(\"$timeoutRemove(reason)\", reason).typeString();\n if (!this.$.timeouts.has(id)) {\n throw new JFACTORY_ERR_KEY_MISSING({\n target: \"$timeoutRemove(id)\",\n given: id\n })\n }\n // eslint-disable-next-line no-debugger,brace-style\n if (this.$.timeouts.get(id)._debug_remove_called) {debugger}\n this.$.timeouts.get(id)._debug_remove_called = true;\n }\n\n let entry = this.$.timeouts.get(id);\n clearTimeout(entry.$chain.data.timer);\n // deleting before chainAbort() to prevent remove() recall\n this.$.timeouts.delete(id);\n entry.$chainAbort(reason || \"$timeoutRemove()\");\n }\n\n $timeoutRemoveAll(removePhase) {\n if (JFACTORY_DEV) {\n JFactoryExpect(\"removePhase\", removePhase)\n .equalIn(TraitService.PHASES);\n }\n let subs = this.$.timeouts;\n if (subs.size) {\n for (const [key, sub] of subs) {\n if (sub.$phaseRemove === removePhase) {\n this.$timeoutRemove(key, \"$timeoutRemoveAll()\")\n }\n }\n }\n }\n}\n\n/**\n * -----------------------------------------------------------------------------------------------------------------\n * Trait Interval\n * -----------------------------------------------------------------------------------------------------------------\n */\n\nexport class TraitInterval {\n trait_constructor() {\n const kernel = this.$[TraitCore.SYMBOL_PRIVATE].events.kernel;\n kernel.on(\"disable\", () => this.$intervalRemoveAll(TraitService.PHASE.DISABLE));\n kernel.on(\"uninstall\", () => this.$intervalRemoveAll(TraitService.PHASE.UNINSTALL));\n this.$.assign(\"timeints\", this.$.createSubMap(), JFactoryObject.descriptors.ENUMERABLE);\n }\n\n $interval(id, delay, handler, ...args) {\n id = this.$.timeints.$id_resolve(id);\n if (JFACTORY_DEV) {\n JFactoryExpect(\"id\", id).typeString();\n JFactoryExpect(\"handler\", handler).typeFunction();\n JFactoryExpect(\"delay\", delay).typeNumber();\n if (this.$.timeints.has(id)) {\n throw new JFACTORY_ERR_KEY_DUPLICATED({ target: \"$interval(id)\", given: id })\n }\n }\n let timer = setInterval(handler, delay, ...args);\n this.$.timeints.$registerSync(id, timer)\n }\n\n $intervalRemove(id) {\n if (JFACTORY_DEV) {\n JFactoryExpect(\"$intervalRemove(id)\", id).typeString();\n if (!this.$.timeints.has(id)) {\n throw new JFACTORY_ERR_KEY_MISSING({\n target: \"$intervalRemove(id)\",\n given: id\n })\n }\n // eslint-disable-next-line no-debugger,brace-style\n if (this.$.timeints.get(id)._debug_remove_called) {debugger}\n this.$.timeints.get(id)._debug_remove_called = true\n }\n clearInterval(this.$.timeints.get(id).$value);\n this.$.timeints.delete(id)\n }\n\n $intervalRemoveAll(removePhase) {\n if (JFACTORY_DEV) {\n JFactoryExpect(\"removePhase\", removePhase)\n .equalIn(TraitService.PHASES)\n }\n let subs = this.$.timeints;\n if (subs.size) {\n for (const [key, sub] of subs) {\n if (sub.$phaseRemove === removePhase) {\n this.$intervalRemove(key)\n }\n }\n }\n }\n}\n\n/**\n * -----------------------------------------------------------------------------------------------------------------\n * Trait Mutations\n * -----------------------------------------------------------------------------------------------------------------\n */\n\nif (JFACTORY_DEV) {\n jFactoryCompat_require(JFACTORY_COMPAT_MutationObserver);\n}\n\nexport class TraitMutation {\n trait_constructor() {\n const kernel = this.$[TraitCore.SYMBOL_PRIVATE].events.kernel;\n kernel.on(\"disable\", () => this.$mutationRemoveAll(TraitService.PHASE.DISABLE));\n kernel.on(\"uninstall\", () => this.$mutationRemoveAll(TraitService.PHASE.UNINSTALL));\n this.$.assign(\"mutations\", this.$.createSubMap(), JFactoryObject.descriptors.ENUMERABLE);\n }\n\n $mutation(id, parent, config, handler) {\n id = this.$.mutations.$id_resolve(id);\n if (JFACTORY_DEV) {\n JFactoryExpect(\"id\", id).typeString();\n JFactoryExpect(\"parent\", parent).type(HTMLElement, Document);\n JFactoryExpect(\"config\", config).typePlainObject();\n JFactoryExpect(\"handler\", handler).typeFunction();\n if (this.$.mutations.has(id)) {\n throw new JFACTORY_ERR_KEY_DUPLICATED({ target: \"$mutation(id)\", given: id })\n }\n }\n let observer = new MutationObserver(handler);\n observer.observe(parent, config);\n this.$.mutations.$registerSync(id, observer);\n }\n\n $mutationRemove(id, reason) {\n if (JFACTORY_DEV) {\n JFactoryExpect(\"$mutationRemove(id)\", id).typeString();\n reason && JFactoryExpect(\"$mutationRemove(reason)\", reason).typeString();\n if (!this.$.mutations.has(id)) {\n throw new JFACTORY_ERR_KEY_MISSING({\n target: \"$mutationRemove(id)\",\n given: id\n })\n }\n // eslint-disable-next-line no-debugger,brace-style\n if (this.$.mutations.get(id)._debug_remove_called) {debugger}\n this.$.mutations.get(id)._debug_remove_called = true\n }\n this.$.mutations.get(id).$value.disconnect();\n this.$.mutations.delete(id)\n }\n\n $mutationRemoveAll(removePhase) {\n if (JFACTORY_DEV) {\n JFactoryExpect(\"removePhase\", removePhase)\n .equalIn(TraitService.PHASES)\n }\n let subs = this.$.mutations;\n if (subs.size) {\n for (const [key, sub] of subs) {\n if (sub.$phaseRemove === removePhase) {\n this.$mutationRemove(key)\n }\n }\n }\n }\n}\n\n/**\n * -----------------------------------------------------------------------------------------------------------------\n * Trait DOM\n * -----------------------------------------------------------------------------------------------------------------\n */\n\nexport class TraitDOM {\n trait_constructor() {\n const kernel = this.$[TraitCore.SYMBOL_PRIVATE].events.kernel;\n kernel.on(\"disable\", () => this.$domRemoveAll(TraitService.PHASE.DISABLE));\n kernel.on(\"uninstall\", () => this.$domRemoveAll(TraitService.PHASE.UNINSTALL));\n this.$.assign(\"dom\", this.$.createSubMap(), JFactoryObject.descriptors.ENUMERABLE);\n }\n\n $dom(id, jQueryArgument, appendTo) {\n id = this.$.dom.$id_resolve(id);\n\n if (JFACTORY_DEV) {\n JFactoryExpect(\"id\", id).typeString();\n JFactoryExpect(\"jQueryArgument\", jQueryArgument).type(String, jQuery, HTMLElement);\n appendTo && JFactoryExpect(\"appendTo\", appendTo).type(String, jQuery, HTMLElement);\n }\n\n let domId;\n if (id[0] === \"#\") {\n id = id.substring(1);\n domId = true\n }\n\n if (JFACTORY_DEV && this.$.dom.has(id)) {\n throw new JFACTORY_ERR_KEY_DUPLICATED({ target: \"$dom(id)\", given: id })\n }\n\n let dom = jQuery(jQueryArgument);\n\n if (dom[0].tagName === \"TEMPLATE\") {\n dom = jQuery(jQuery(dom[0]).html());\n }\n\n if (domId) {\n if (JFACTORY_DEV) {\n if (dom[0].nodeType !== Node.ELEMENT_NODE) {\n throw new JFACTORY_ERR_INVALID_VALUE({\n target: \"$dom(#id)\",\n given: dom,\n reason: \"cannot set the dom id: the first element of the selection isn't an ELEMENT_NODE\"\n })\n }\n }\n dom[0].id = id\n }\n\n if (appendTo) {\n dom.appendTo(appendTo)\n }\n\n return this.$.dom.$registerSync(id, dom).$value;\n }\n\n $domFetch(id, url, fetchOptions, appendTo) {\n if (fetchOptions && !helper_isPlainObject(fetchOptions)) {\n [fetchOptions, appendTo] = [{}, fetchOptions]\n }\n\n id = this.$.dom.$id_resolve(id);\n\n if (JFACTORY_DEV) {\n JFactoryExpect(\"id\", id).typeString();\n JFactoryExpect(\"url\", url).typeString();\n appendTo && JFactoryExpect(\"appendTo\", appendTo).type(String, Object);\n fetchOptions && JFactoryExpect(\"fetchOptions\", fetchOptions).type(Object);\n }\n\n let domId;\n if (id[0] === \"#\") {\n id = id.substring(1);\n domId = true\n }\n\n if (JFACTORY_DEV && this.$.dom.has(id)) {\n throw new JFACTORY_ERR_KEY_DUPLICATED({ target: \"$domFetch(id)\", given: id })\n }\n\n let promise = this.$fetchText('$domFetch(\"' + id + '\")', url, fetchOptions)\n .then(r => {\n let dom = jQuery(r);\n if (domId) {\n dom[0].id = id\n }\n if (appendTo) {\n dom.appendTo(appendTo)\n }\n return dom\n });\n\n this.$.dom.$registerAsync(id, '$domFetch(\"' + id + '\")', promise);\n return promise\n }\n\n $domRemove(id, reason) {\n if (JFACTORY_DEV) {\n JFactoryExpect(\"$domRemove(id)\", id).typeString();\n reason && JFactoryExpect(\"$domRemove(reason)\", reason).typeString();\n if (!this.$.dom.has(id)) {\n throw new JFACTORY_ERR_KEY_MISSING({\n target: \"$domRemove(id)\",\n given: id\n })\n }\n // eslint-disable-next-line no-debugger,brace-style\n if (this.$.dom.get(id)._debug_remove_called) {debugger}\n this.$.dom.get(id)._debug_remove_called = true\n }\n\n let entry = this.$.dom.get(id);\n let value = entry.$value;\n if (value instanceof jQuery) {\n value.remove()\n }\n if (entry instanceof JFactoryFetch) {\n entry.$chainAbort(reason || \"$domRemove()\");\n }\n this.$.dom.delete(id)\n }\n\n $domRemoveAll(removePhase) {\n if (JFACTORY_DEV) {\n JFactoryExpect(\"removePhase\", removePhase)\n .equalIn(TraitService.PHASES)\n }\n let subs = this.$.dom;\n if (subs.size) {\n for (const [key, sub] of subs) {\n if (sub.$phaseRemove === removePhase) {\n this.$domRemove(key)\n }\n }\n }\n }\n}\n\n/**\n * -----------------------------------------------------------------------------------------------------------------\n * Trait CSS\n * -----------------------------------------------------------------------------------------------------------------\n */\n\nexport class TraitCSS {\n trait_constructor() {\n const kernel = this.$[TraitCore.SYMBOL_PRIVATE].events.kernel;\n kernel.on(\"disable\", () => this.$cssRemoveAll(TraitService.PHASE.DISABLE));\n kernel.on(\"uninstall\", () => this.$cssRemoveAll(TraitService.PHASE.UNINSTALL));\n this.$.assign(\"css\", this.$.createSubMap(), JFactoryObject.descriptors.ENUMERABLE);\n }\n\n $css(id, styleBody) {\n id = this.$.css.$id_resolve(id);\n\n if (JFACTORY_DEV) {\n JFactoryExpect(\"id\", id).typeString();\n JFactoryExpect(\"css\", styleBody).typeString();\n }\n\n let cssId;\n if (id[0] === \"#\") {\n id = id.substring(1);\n cssId = true\n }\n\n if (JFACTORY_DEV && this.$.css.has(id)) {\n throw new JFACTORY_ERR_KEY_DUPLICATED({ target: \"$css(id)\", given: id })\n }\n\n return this.$.css.$registerSync(id,\n jQuery(\"