dcp-client 4.2.18 → 4.2.20
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/dcp-client-bundle.js +5 -5
- package/index.js +2 -0
- package/ns-map.js +1 -0
- package/package.json +2 -2
|
@@ -3041,7 +3041,7 @@ eval("/* provided dependency */ var Buffer = __webpack_require__(/*! ./node_modu
|
|
|
3041
3041
|
/***/ ((__unused_webpack_module, exports) => {
|
|
3042
3042
|
|
|
3043
3043
|
"use strict";
|
|
3044
|
-
eval("/**\n * @file kvin.js A general-purpose library for marshaling and serializing\n * ES objects. This library is a functional superset of JSON\n * and relies on JSON for speed, adding:\n * - Typed Arrays with efficient spare representation\n * - Sparse arrays\n * - Arrays with enumerable properties\n * - Object graphs with cycles\n * - Boxed primitives (excluding Symbol)\n * - Functions (including enumerable properties, global scope)\n * - Regular Expressions\n * - undefined\n * - simple objects made with constructors\n * - objects will re-constructed with no constructor arguments\n * during deserialization\n * - enumerable properties will be copied on after construction\n * - opt-in list of supported constructors (kvin.constructorAllowList)\n *\n * This library is safe to use on user-supplied data.\n *\n * The basic implementation strategy is to marshal to an intermediate\n * format, called a 'prepared object', that can be used to recreate\n * the original object, but can also be serialized with JSON. We\n * track a list objects we have seen and their initial appearance in\n * the object graph. We rely on the /de-facto/ enumeration order of\n * properties in vanilla objects that has been present in all popular\n * browsers since the dawn of time; namely, that enumeration order is\n * object insertion order. This could cause bugs with objects with\n * cycles in less-common interpreters, such as Rhino and (especially)\n * the NJS/NGS ES3 platform by Brian Basset.\n *\n * *note* - This module free of external dependencies, and can be loaded as either a Node module,\n * a BravoJS module, or as a script tag in the browser.\n *\n * *bugs* - There are known or suspected issues in the following areas:\n * - Arrays which contain the same object more than once\n * - Arrays which mix numeric and non-numeric properties, especially if they are objects\n * - Sparse Arrays\n *\n * @author Wes Garland, wes@kingsds.network\n * @date June 2018\n *\n */\n\n\n\n{/* This prologue allows a CJS2 module's exports to be loaded with eval(readFileSync(filename)) */\n var module;\n let moduleSystemType;\n let realModule = module;\n \n if (true)\n moduleSystemType = 'webpack';\n else {}\n\n module = Object.assign({}, realModule);\n\n if (moduleSystemType === 'nodejs' || moduleSystemType === 'webpack' || moduleSystemType === 'cjs1') {\n module.declare = function kvin$$cjs1$$moduleDeclare(deps, factory) {\n factory(null, exports, null);\n module = realModule;\n return exports;\n };\n } else if (moduleSystemType === 'cjs2') {\n module = realModule;\n } else if (moduleSystemType === 'none') {\n module.declare = function kvin$$cjs1$$moduleDeclare(deps, factory) {\n let exports = {};\n factory(null, exports, null);\n module = realModule;\n\n if (typeof window === 'object')\n window.KVIN = exports;\n if (typeof globalThis === 'object')\n globalThis.KVIN = exports;\n\n return exports;\n };\n }\n/* Now initialize the module by invoking module.declare per CommonJS Modules/2.0-draft8 */\n \n/* eslint-disable indent */ module.declare([], function (require, exports, module) {\n\n/** \n * @constructor to create an alternate KVIN context. This allows us to recogonize instance of\n * the standard classes from a different JS context or have different tuning parameters. \n * @param ctors list or object of standard constructors\n */\nfunction KVIN(ctors)\n{\n // We always need to initialize the standardObjects. It is used for comparisons for primitive types etc\n this.standardObjects = {};\n for (let ctor of KVIN.prototype.ctors) {\n this.standardObjects[ctor.name] = ctor;\n }\n\n this.ctors = [].concat(KVIN.prototype.ctors);\n \n if (!ctors)\n return;\n\n if (Array.isArray(ctors))\n {\n for (let ctor of ctors)\n {\n this[ctor.name] = ctor\n for (let i=0; i < this.ctors.length; i++)\n {\n if (this.ctors[i].name === ctor.name)\n this.ctors[i] = ctor;\n }\n }\n }\n else\n {\n for (let entry of Object.entries(ctors))\n {\n for (let i=0; i < this.ctors.length; i++)\n {\n let [ name, ctor ] = entry; \n if (this.ctors[i].name === name)\n this.ctors[i] = ctor;\n this.standardObjects[name] = ctor;\n }\n }\n }\n}\n/*\n * Set exports.makeFunctions = true to allow deserializer to make functions.\n * If the deserializer can make functions, it is equivalent to eval() from a\n * security POV. Otherwise, the deserializer will turn functions into boxed\n * strings containing the function's source code, having a name property that\n * matches the original function.\n */\nKVIN.prototype.makeFunctions = false\n\n/* More bytes in a TypedArray than typedArrayPackThreshold will trigger\n * the code to prepare these into strings rather than arrays.\n */\nKVIN.prototype.typedArrayPackThreshold = 8\n\n/* Arrays of primitives which are >= the threshold in length are scrutinized\n * for further optimization, e.g. by run-length encoding\n */\nKVIN.prototype.scanArrayThreshold = 8\n\n\n/** Maxmimum number of arguments we can pass to a function in this engine.\n * @todo this needs to be detected at startup based on environment\n */\nconst _vm_fun_maxargs = 100000\n\nconst littleEndian = (function () {\n let ui16 = new Uint16Array(1)\n let ui8\n\n ui16[0] = 0xffef\n ui8 = new Uint8Array(ui16.buffer, ui16.byteOffset, ui16.byteLength)\n\n if (ui8[0] === 0x0ff) {\n console.error('KVIN: Detected big-endian platform')\n return false\n }\n\n return true\n})()\n\n/** Pre-defined constructors, used to compact payload */\nKVIN.prototype.ctors = [\n Object,\n Int8Array,\n Uint8Array,\n Uint8ClampedArray,\n Int16Array,\n Uint16Array,\n Int32Array,\n Uint32Array,\n Float32Array,\n Float64Array,\n RegExp,\n Number,\n String,\n Boolean,\n Array,\n Function,\n Error,\n Promise,\n];\nif (typeof URL !== 'undefined'){\n KVIN.prototype.ctors.push(URL)\n}\n\nKVIN.prototype.userCtors = {}; /**< name: implementation for user-defined constructors that are not props of global */\n\n/** Take a 'prepared object' (which can be represented by JSON) and turn it\n * into an object which resembles the object it was created from.\n *\n * @param seen An array objects we have already seen in this\n * object graph; used to track cycles.\n * @param po A prepared object representing a value or a primitive\n * @param position A string respresenting our position within\n * the graph. Used only for error messages.\n * @returns the value encoded by po\n */\nKVIN.prototype.unprepare = function unprepare (seen, po, position) {\n switch (typeof po) {\n case 'boolean':\n case 'number':\n case 'string':\n return po;\n }\n if (po.hasOwnProperty('ctr')) {\n switch (typeof po.ctr) {\n case 'string':\n if (!po.ctr.match(/^[A-Za-z_0-9$][A-Za-z_0-9$]*$/)) {\n if (this.constructorAllowlist && this.constructorAllowlist.indexOf(po.ctr) === -1) {\n throw new Error('Allowlist does not include constructor ' + po.ctr)\n }\n throw new Error('Invalid constructor name: ' + po.ctr)\n }\n break\n case 'number':\n if (!(po.ctr >= 0 && po.ctr < this.ctors.length)) {\n throw new Error('Invalid constructor number: ' + po.ctr)\n }\n break\n default:\n throw new Error('Invalid constructor label type ' + typeof po.ctr)\n }\n }\n if (po.hasOwnProperty('raw')) {\n if (typeof po.raw === 'object' && po.raw !== null && !Array.isArray(po.raw))\n {\n if (!po.used)\n po.used = true;\n else\n return JSON.parse(JSON.stringify(po.raw));\n return Object.assign(new this.standardObjects.Object(), po.raw);\n }\n return po.raw;\n }\n if (po.hasOwnProperty('ptv')) {\n return po.ptv; /* deprecated: only created by v3-6 */\n }\n if (po.hasOwnProperty('number')) {\n return unprepare$number(po.number);\n }\n if (po.hasOwnProperty('bigint')) {\n return unprepare$bigint(po.bigint);\n }\n if (po.hasOwnProperty('fnName')) {\n return this.unprepare$function(seen, po, position)\n }\n if (po.hasOwnProperty('ab16') || po.hasOwnProperty('isl16')) {\n return this.unprepare$ArrayBuffer16(seen, po, position)\n }\n if (po.hasOwnProperty('ab8') || po.hasOwnProperty('isl8')) {\n return this.unprepare$ArrayBuffer8(seen, po, position)\n }\n if (po.hasOwnProperty('arr')) {\n return this.unprepare$Array(seen, po, position)\n }\n if (po.hasOwnProperty('ctr')) {\n return this.unprepare$object(seen, po, position)\n }\n if (po.hasOwnProperty('json')) {\n return JSON.parse(po.json)\n }\n if (po.hasOwnProperty('undefined')) {\n return undefined\n }\n\n if (Object.hasOwnProperty.call(po, 'resolve')) {\n // Unprepare a Promise by assuming po.resolve is a marshalled value.\n const promise = Promise.resolve(this.unmarshal(po.resolve));\n seen.push(promise);\n return promise;\n }\n\n if (po.hasOwnProperty('seen')) {\n if (!seen.hasOwnProperty(po.seen)) {\n throw new Error('Seen-list corruption detected at index ' + po.seen)\n }\n return seen[po.seen]\n }\n throw new TypeError('Invalid preparation formula at ' + position)\n}\n\nKVIN.prototype.unprepare$object = function unprepare$object (seen, po, position) {\n let o\n let constructor;\n\n if (typeof po.ctr === 'string' && !po.ctr.match(/^[1-9][0-9]*$/)) {\n if (this.userCtors.hasOwnProperty(po.ctr))\n constructor = this.userCtors[po.ctr];\n else \n constructor = eval(po.ctr) /* pre-validated! */ // eslint-disable-line\n } else {\n constructor = this.ctors[po.ctr]\n }\n\n if (po.hasOwnProperty('arg')) {\n o = new constructor(po.arg)\n } else {\n o = new constructor() // eslint-disable-line\n }\n\n if (po.ctr === 'Error')\n {\n delete o.stack;\n delete o.lineNumber;\n delete o.fileName;\n }\n \n seen.push(o)\n\n if (po.hasOwnProperty('ps')) {\n for (let prop in po.ps) {\n if (po.ps.hasOwnProperty(prop)) {\n o[prop] = this.unprepare(seen, po.ps[prop], position + '.' + prop)\n }\n }\n }\n\n return o\n}\n\nKVIN.prototype.unprepare$function = function unprepare$function (seen, po, position) {\n let obj, fn\n let fnName = po.fnName\n\n /* A function is basically a callable object */\n po.ctr = this.ctors.indexOf(Object)\n delete po.fnName\n obj = this.unprepare(seen, po, position)\n\n if (!this.makeFunctions) {\n obj.name = fnName\n return obj\n }\n\n fn = (new Function('return ' + po.arg))() // eslint-disable-line\n if (po.hasOwnProperty('ps')) {\n for (let prop in po.ps) {\n fn[prop] = obj[prop]\n }\n }\n\n return fn\n}\n\nfunction unprepare$bigint(arg) {\n return BigInt(arg);\n}\n\nfunction unprepare$number(arg) {\n return parseFloat(arg);\n}\n \n/**\n * arr:[] - Array of primitives of prepared objects\n * lst:N - repeat last element N times\n * ps:[] - property list\n */\nKVIN.prototype.unprepare$Array = function unprepare$Array (seen, po, position) {\n let a = []\n let last\n\n seen.push(a)\n\n for (let i = 0; i < po.arr.length; i++) {\n if (typeof po.arr[i] === 'object') {\n if (po.arr[i].lst) {\n for (let j = 0; j < po.arr[i].lst; j++) {\n a.push(this.unprepare(seen, last, position + '.' + (i + j)))\n }\n continue\n }\n a.push(this.unprepare(seen, po.arr[i], position + '.' + i))\n last = po.arr[i]\n } else {\n a.push(po.arr[i])\n last = prepare$primitive(a[a.length-1], 'unprepare$Array')\n }\n }\n\n if (po.hasOwnProperty('isl')) {\n for (let prop in po.isl) {\n let island = po.isl[prop]\n let els = Array.isArray(island.arr) ? island.arr : this.unprepare$Array(seen, island.arr, [ position, 'isl', prop ].join('.'))\n\n if (els.length - 3 <= _vm_fun_maxargs) {\n if (els.length && (a.length < island['@'] + els.length)) {\n a.length = island['@'] + els.length\n }\n a.splice.apply(a, [island['@'], els.length].concat(els))\n } else {\n for (let i=0; i < els.length; i++) {\n a[i + +island['@']] = els[i]\n }\n }\n }\n }\n\n if (po.hasOwnProperty('ps')) {\n for (let prop in po.ps) {\n if (typeof po.ps[prop] === 'object') {\n a[prop] = this.unprepare(seen, po.ps[prop], position + '.' + prop)\n } else {\n a[prop] = po.ps[prop]\n }\n }\n }\n\n if (po.len) {\n a.length = po.len\n }\n\n return a\n}\n\n/** The ab8 (array buffer 8 bit) encoding encodes TypedArrays and related types by\n * converting them to Latin-1 strings full of binary data in 8-bit words.\n *\n * The isl8 (islands) encoding is almost the same, except that it encodes only\n * sequences of mostly-non-zero sections of the string.\n */\nKVIN.prototype.unprepare$ArrayBuffer8 = function unprepare$ArrayBuffer8 (seen, po, position) {\n let i8\n let bytes\n let constructor;\n\n if (typeof po.ctr === 'string' && !po.ctr.match(/^[1-9][0-9]*$/)) {\n constructor = eval(po.ctr) /* pre-validated! */ // eslint-disable-line\n } else {\n constructor = this.ctors[po.ctr]\n }\n\n if (po.hasOwnProperty('ab8')) {\n bytes = po.ab8.length\n } else {\n bytes = po.len\n }\n i8 = new Int8Array(bytes)\n if (po.hasOwnProperty('ab8')) {\n for (let i = 0; i < po.ab8.length; i++) {\n i8[i] = po.ab8.charCodeAt(i)\n }\n } else {\n for (let j = 0; j < po.isl8.length; j++) {\n for (let i = 0; i < po.isl8[j][0].length; i++) {\n i8[po.isl8[j]['@'] + i] = po.isl8[j][0].charCodeAt(i)\n }\n }\n }\n let o = new constructor(i8.buffer, i8.byteOffset) // eslint-disable-line;\n seen.push(o)\n return o;\n}\n\n/** The ab16 (array buffer 16 bit) encoding encodes TypedArrays and related types by\n * converting them to strings full of binary data in 16-bit words. Buffers\n * with an odd number of bytes encode an extra byte 'eb' at the end by itself.\n *\n * The isl16 (islands) encoding is almost the same, except that it encodes only\n * sequences of mostly-non-zero sections of the string.\n */\n KVIN.prototype.unprepare$ArrayBuffer16 = function unprepare$ArrayBuffer16 (seen, po, position) {\n let i16, i8, words\n let bytes\n let constructor;\n\n if (typeof po.ctr === 'string' && !po.ctr.match(/^[1-9][0-9]*$/)) {\n constructor = eval(po.ctr) /* pre-validated! */ // eslint-disable-line\n } else {\n constructor = this.ctors[po.ctr]\n }\n\n if (po.hasOwnProperty('ab16')) {\n bytes = po.ab16.length * 2\n if (po.hasOwnProperty('eb')) {\n bytes++\n }\n } else {\n bytes = po.len\n }\n\n words = Math.floor(bytes / 2) + (bytes % 2)\n i16 = new Int16Array(words)\n if (po.hasOwnProperty('ab16')) {\n for (let i = 0; i < po.ab16.length; i++) {\n i16[i] = po.ab16.charCodeAt(i)\n }\n } else {\n for (let j = 0; j < po.isl16.length; j++) {\n for (let i = 0; i < po.isl16[j][0].length; i++) {\n i16[po.isl16[j]['@'] + i] = po.isl16[j][0].charCodeAt(i)\n }\n }\n }\n i8 = new Int8Array(i16.buffer, i16.byteOffset, bytes)\n if (po.hasOwnProperty('eb')) {\n i8[i8.byteLength - 1] = po.eb.charCodeAt(0)\n }\n\n if (!littleEndian) {\n for (let i = 0; i < i8.length; i += 2) {\n i8[(i * 2) + 0] = i8[(i * 2) + 0] ^ i8[(i * 2) + 1]\n i8[(i * 2) + 1] = i8[(i * 2) + 1] ^ i8[(i * 2) + 0]\n i8[(i * 2) + 0] = i8[(i * 2) + 0] ^ i8[(i * 2) + 1]\n }\n }\n let o = new constructor(i8.buffer, i8.byteOffset) // eslint-disable-line\n seen.push(o)\n return o\n}\n\n/* Primitives and primitive-like objects do not have any special\n * marshaling requirements -- specifically, we don't need to\n * iterate over their properties in order to serialize them; we\n * can let JSON.stringify() do any heavy lifting.\n */\nKVIN.prototype.isPrimitiveLike = function isPrimitiveLike (o, seen) {\n if (o === null || typeof o === 'string' || typeof o === 'boolean')\n return true;\n\n if (typeof o === 'number')\n return Number.isFinite(o);\n\n if (typeof o !== 'object')\n return false;\n \n if (o.constructor === this.standardObjects.Object && Object.keys(o).length === 0)\n return true;\n\n if (o.constructor === this.standardObjects.Array && o.length === 0 && Object.keys(o).length === 0)\n return true;\n\n if (o.constructor !== this.standardObjects.Object && o.constructor !== this.standardObjects.Array)\n return false;\n\n if (Array.isArray(o)) {\n if (Object.keys(o).length !== o.length) {\n return false /* sparse array or named props */\n }\n }\n\n seen = seen.concat(o);\n for (let prop in o) {\n if (!o.hasOwnProperty(prop))\n return false;\n if (seen.indexOf(o[prop]) !== -1)\n return false; \n if (!this.isPrimitiveLike(o[prop], seen))\n return false;\n }\n\n return true\n}\n\n/**\n * Serialize an instance of Error, preserving standard-ish non-enumerable properties \n */ \nfunction prepare$Error(o)\n{\n let ret = {\n ctr: 'Error',\n ps: {},\n arg: o.message\n };\n\n for (let prop of ['code', 'stack', 'lineNumber', 'fileName'])\n if (o.hasOwnProperty(prop))\n ret.ps[prop] = o[prop];\n for (let prop in o)\n if (o.hasOwnProperty(prop))\n ret.ps[prop] = o[prop];\n\n return ret;\n}\n \n/** Take an arbitrary object and turn it into a 'prepared object'.\n * A prepared object can always be represented with JSON.\n *\n * @param seen An array objects we have already seen in this\n * object graph; used to track cycles.\n * @param o The object that the prepared object reflects\n * @returns A prepared object\n */\nKVIN.prototype.prepare = function prepare (seen, o, where) {\n let i, ret\n let po = {}\n\n if (typeof o === 'number') {\n return prepare$number(o)\n }\n if (typeof o === 'bigint') {\n return prepare$bigint(o)\n }\n if (this.isPrimitiveLike(o, seen)) {\n if (!Array.isArray(o) || o.length < this.scanArrayThreshold)\n return prepare$primitive(o, where)\n }\n if (typeof o === 'undefined') {\n return prepare$undefined(o)\n }\n /* value types below here can be used as targets of cycles */\n if ((i = seen.indexOf(o)) === -1) {\n seen.push(o)\n } else {\n return { seen: i }\n }\n if (Array.isArray(o)) {\n return this.prepare$Array(seen, o, where)\n }\n if (ArrayBuffer.isView(o)) {\n return this.prepare$ArrayBuffer(o)\n }\n if (o.constructor === String || o.constructor === Number || o.constructor === Boolean) {\n return this.prepare$boxedPrimitive(o)\n }\n if (o.constructor === RegExp) {\n return this.prepare$RegExp(o)\n }\n\n if (o instanceof Promise || o instanceof this.standardObjects.Promise) {\n /**\n * Let the caller replace the `resolve` property with its marshalled\n * resolved value.\n */\n return { resolve: o };\n }\n\n if (o instanceof Error || o instanceof this.standardObjects.Error) {\n /* special-case Error to get non-enumerable properties */\n return prepare$Error(o);\n }\n\n if (typeof o.constructor === 'undefined') {\n console.warn('KVIN Warning: ' + where + ' is missing .constructor -- skipping')\n return prepare$undefined(o)\n }\n\n ret = { ctr: this.ctors.indexOf(o.constructor), ps: po }\n if (ret.ctr === -1) {\n /**\n * If the constructor is `Object` from another context, the indexOf check\n * would fail. So if the name of `o`'s constructor matches one of the valid\n * constructors, use the index from the mapped array to get the proper\n * constructor index.\n */\n const constructorNames = this.ctors.map((ctor) => ctor.name);\n const ctrIndex = constructorNames.indexOf(o.constructor.name);\n if (ctrIndex !== -1) {\n ret.ctr = ctrIndex;\n /**\n * Fix the `o`'s constructor to match its constructor in the current\n * context so that later equality/instanceof checks don't fail.\n */\n o.constructor = this.ctors[ctrIndex];\n } else {\n ret.ctr = o.constructor.name || this.ctors.indexOf(Object)\n }\n }\n\n if (typeof o === 'function') {\n ret.fnName = o.name\n }\n\n if (typeof o.toJSON === 'function') {\n ret.arg = o.toJSON()\n } else {\n if (o.constructor !== this.standardObjects.Object)\n ret.arg = o.toString()\n }\n\n if (typeof o.hasOwnProperty === 'undefined') {\n console.warn('KVIN Warning: ' + where + ' is missing .hasOwnProperty -- skipping')\n return prepare$undefined(o)\n }\n\n /* Iterate over the properties and prepare each in turn, recursing\n * with a depth-first traversal of the object graph. Iteration order\n * must match unprepare()!\n */\n for (let prop in o) {\n if (!o.hasOwnProperty(prop)) {\n continue\n }\n\n switch (typeof o[prop]) {\n case 'function':\n case 'object':\n if (o[prop] !== null) {\n if (typeof o[prop].constructor !== 'undefined'\n && o[prop].constructor !== this.standardObjects.Object && o[prop].constructor.constructor !== this.standardObjects.Object\n && o[prop].constructor !== this.standardObjects.Function && o[prop].constructor.constructor !== this.standardObjects.Function\n && o[prop].constructor !== this.standardObjects.Function && o[prop].constructor.constructor.name !== \"Function\" /* vm context issue /wg aug 2020 */\n ) {\n throw new Error(`Cannot serialize property ${where}.${prop} - multiple inheritance is not supported.`);\n }\n if ((i = seen.indexOf(o[prop])) === -1) {\n po[prop] = this.prepare(seen, o[prop], where + '.' + prop)\n } else {\n po[prop] = { seen: i }\n }\n break\n } /* else fallthrough */\n case 'number':\n po[prop] = prepare$number(o[prop]);\n break;\n case 'bigint':\n po[prop] = prepare$bigint(o[prop]);\n break;\n case 'boolean':\n case 'string':\n po[prop] = prepare$primitive(o[prop], where + '.' + prop)\n break\n case 'undefined':\n po[prop] = prepare$undefined(o[prop])\n break\n default:\n throw new TypeError('Cannot serialize property ' + prop + ' which is a ' + typeof o[prop])\n }\n }\n\n return ret\n}\n\n/** Prepare an Array. Sparse arrays and arrays with properties\n * are supported, and represented reasonably efficiently, as are\n * arrays of repeated values.\n *\n * @param seen The current seen list for this marshal - things pointers point to\n * @param o The array we are preparing\n * @param where Human description of where we are in the object, for debugging purposes\n */\n KVIN.prototype.prepare$Array = function prepare$Array (seen, o, where) {\n let pa = { arr: [] }\n let keys = Object.keys(o)\n let lastJson = NaN\n let json\n let lstTotal = 0\n\n for (let i = 0; i < o.length; i++) {\n if (!o.hasOwnProperty(i)) {\n break /* sparse array */\n }\n if (typeof o[i] !== 'object' && this.isPrimitiveLike(o[i], seen)) {\n pa.arr.push(o[i])\n } else {\n pa.arr.push(this.prepare(seen, o[i], where + '.' + i))\n }\n\n json = JSON.stringify(pa.arr[pa.arr.length - 1])\n if (json === lastJson) {\n if (pa.arr[pa.arr.length - 2].lst) {\n pa.arr[pa.arr.length - 2].lst++\n pa.arr.length--\n lstTotal++\n } else {\n pa.arr[pa.arr.length - 1] = {lst: 1}\n }\n } else {\n lastJson = json\n }\n }\n\n if (keys.length !== o.length) {\n /* sparse array or array with own properties - difference between sparse entry and value=undefined preserved */\n for (let j = 0; j < keys.length; j++) {\n let key = keys[j]\n let idx = +key\n if (idx < j && pa.arr.hasOwnProperty(idx)) { /* test order for speed */\n continue\n }\n if (typeof idx === 'number' && o.hasOwnProperty(idx + 1)) {\n let island = { '@':idx, arr:[] }\n /* island of data inside sparse array */\n if (!pa.isl) {\n pa.isl = []\n }\n for (let k = idx; o.hasOwnProperty(k); k++) {\n island.arr.push(o[k])\n }\n j += island.arr.length - 1\n if (island.arr.length >= this.scanArrayThreshold) {\n let tmp = this.prepare(seen, island.arr, where + '.' + 'isl@' + (j - island.arr.length))\n if (tmp.hasOwnProperty('arr')) {\n island.arr = tmp\n } else {\n pa.isl.push(island)\n }\n }\n pa.isl.push(island)\n continue\n }\n if (!pa.hasOwnProperty('ps')) {\n pa.ps = {}\n }\n if (typeof o[key] !== 'object' && this.isPrimitiveLike(o[key], seen)) {\n pa.ps[key] = o[key]\n } else {\n pa.ps[key] = this.prepare(seen, o[key], where + '.' + key)\n }\n }\n }\n\n if (pa.arr.length + lstTotal !== o.length) {\n pa.len = o.length\n }\n return pa\n}\n\n/** Detect JavaScript strings which contain ill-formed UTF-16 sequences */\nfunction notUnicode(s) {\n if (/[\\ud800-\\udbff][^\\udc00-\\udfff]/.test(s)) {\n return true /* high-surrogate without low-surrogate */\n }\n\n if (/[^\\ud800-\\udbff][\\udc00-\\udfff]/.test(s)) {\n return true /* low-surrogate without high-surrogate */\n }\n\n return false\n}\n/** Prepare an ArrayBuffer into UCS-2, returning null when we cannot guarantee\n * that the UCS-2 is also composed of valid UTF-16 code points\n *\n * @see unprepare$ArrayBuffer16\n */\nKVIN.prototype.prepare$ArrayBuffer16 = function prepare$ArrayBuffer16 (o) {\n let ret = { ctr: this.ctors.indexOf(o.constructor) }\n let nWords = Math.floor(o.byteLength / 2)\n let s = ''\n\n if (ret.ctr === -1)\n ret.ctr = o.constructor.name\n\n if (littleEndian) {\n let ui16 = new Uint16Array(o.buffer, o.byteOffset, nWords)\n for (let i = 0; i < nWords; i++) {\n s += String.fromCharCode(ui16[i])\n }\n } else {\n let ui8 = new Uint8Array(o.buffer, o.byteOffset, o.byteLength)\n for (let i = 0; i < nWords; i++) {\n s += String.fromCharCode((ui8[0 + (2 * i)] << 8) + (ui8[1 + (2 * i)]))\n }\n }\n\n let manyZeroes = '\\u0000\\u0000\\u0000\\u0000'\n if (s.indexOf(manyZeroes) === -1) {\n ret.ab16 = s\n } else {\n /* String looks zero-busy: represent via islands of mostly non-zero (sparse string). */\n // let re = /([^\\u0000]+/g\n let re = /([^\\u0000]+(.{0,3}([^\\u0000]|$))*)+/g\n let island\n\n ret.isl16 = []\n ret.len = o.byteLength\n while ((island = re.exec(s))) {\n ret.isl16.push({0: island[0].replace(/\\u0000*$/, ''), '@': island.index})\n }\n }\n if ((2 * nWords) !== o.byteLength) {\n let ui8 = new Uint8Array(o.buffer, o.byteOffset + o.byteLength - 1, 1)\n ret.eb = ui8[0]\n }\n\n if (ret.ab16 && notUnicode(ret.ab16)) {\n return null\n } else if (ret.isl16) {\n for (let i = 0; i < ret.isl16.length; i++) {\n if (notUnicode(ret.isl16[i])) {\n return null\n }\n }\n }\n return ret\n}\n\n/** Encode an ArrayBuffer (TypedArray) into a string composed solely of Latin-1 characters.\n * Strings with many zeroes will be represented as sparse-string objects.\n */\nKVIN.prototype.prepare$ArrayBuffer8 = function prepare$ArrayBuffer8 (o) {\n let ret = { ctr: this.ctors.indexOf(o.constructor) }\n\n if (ret.ctr === -1)\n ret.ctr = o.constructor.name\n\n const mss = _vm_fun_maxargs - 1\n let ui8 = new Uint8Array(o.buffer, o.byteOffset, o.byteLength)\n let segments = []\n let s\n\n for (let i=0; i < ui8.length / mss; i++) {\n segments.push(String.fromCharCode.apply(null, ui8.slice(i * mss, (i + 1) * mss)))\n }\n s = segments.join('')\n\n let manyZeroes = '\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000'\n if (s.indexOf(manyZeroes) === -1) {\n ret.ab8 = s\n } else {\n /* String looks zero-busy: represent via islands of mostly non-zero (sparse string). */\n // let re = /([^\\u0000]+/g\n let re = /([^\\u0000]+(.{0,3}([^\\u0000]|$))*)+/g\n let island\n\n ret.isl8 = []\n ret.len = o.byteLength\n while ((island = re.exec(s))) {\n ret.isl8.push({0: island[0].replace(/\\u0000*$/, ''), '@': island.index})\n }\n }\n\n return ret\n}\n\n/** Encode an ArrayBuffer (TypedArray) into a string, trying multiple methods to determine\n * optimimum size/performance. The this.tune variable affects the behaviour of this code this:\n *\n * \"speed\" - only do naive encoding: floats get represented as byte-per-digit strings\n * \"size\" - try the naive, ab8, and ab16 encodings; pick the smallest\n * neither - try the naive encoding if under typedArrayPackThreshold and use if smaller than\n * ab8; otherwise, use ab8\n */\nKVIN.prototype.prepare$ArrayBuffer = function prepare$ArrayBuffer (o) {\n let naive, naiveJSONLen;\n let ab8, ab8JSONLen;\n let ab16, ab16JSONLen;\n\n if (this.tune === \"speed\" || this.tune === \"size\" || (o.byteLength < this.typedArrayPackThreshold)) {\n naive = { ctr: this.ctors.indexOf(o.constructor), arg: Array.prototype.slice.call(o) }\n if (this.tune === \"speed\") {\n return naive\n }\n }\n\n naiveJSONLen = naive ? JSON.stringify(naive).length : Infinity\n\n ab8 = this.prepare$ArrayBuffer8(o)\n if (this.tune !== \"size\") {\n if (naive && naive.length < ab8.length) {\n return naive\n }\n return ab8\n }\n\n ab16 = this.prepare$ArrayBuffer16(o)\n ab8JSONLen = JSON.stringify(ab8).length;\n ab16JSONLen = ab16 ? JSON.stringify(ab16).length : Infinity\n\n if (ab16JSONLen < ab8JSONLen && ab16JSONLen < naiveJSONLen) {\n return ab16\n }\n if (naiveJSONLen < ab8JSONLen) {\n return naive\n }\n\n return ab8;\n}\n\nKVIN.prototype.prepare$RegExp = function prepare$RegExp (o) {\n return { ctr: this.ctors.indexOf(o.constructor), arg: o.toString().slice(1, -1) }\n}\n\nKVIN.prototype.prepare$boxedPrimitive = function prepare$boxedPrimitive (o) {\n return { ctr: this.ctors.indexOf(o.constructor), arg: o.toString() }\n}\n\nfunction prepare$bigint (n) {\n return { bigint: n.toString() }\n}\n\nfunction prepare$number (n) {\n if (!Number.isFinite(n))\n return { number: n + '' };\n\n if (1/n === -Infinity)\n return { json: \"-0\" };\n\n return n;\n}\n \n/* Store primitives and sort-of-primitives (like object literals) directly */\nfunction prepare$primitive (primitive, where) {\n switch (typeof po) {\n case 'boolean':\n case 'number': /* not all cases, see prepare$number */\n case 'string':\n return primitive;\n }\n return { raw: primitive };\n}\n\nfunction prepare$undefined (o) {\n return { undefined: true }\n}\n\n/** Prepare a value for serialization\n * @param what any (supported) js value\n * @returns an object which can be serialized with json\n */\nKVIN.prototype.marshal = function serialize$$marshal (what) {\n return {_serializeVerId: this.serializeVerId, what: this.prepare([], what, 'top')}\n}\n\n/**\n * Prepare a value that is a Promise or contains a Promise for serialization.\n *\n * Removes cycles in objects to enable stringification using `JSON.stringify`.\n *\n * @param {*} value A supported js value that can be marshalled\n * @returns {Promise<object>} An object which can be serialized with\n * `JSON.stringify`\n */\nKVIN.prototype.marshalAsync = async function serialize$$marshalAsync(value, isRecursing = false) {\n /**\n * First, have marshal memoize returned an object graph with any instances of\n * Promise found during the marshal operation with { resolve: X }, where X is\n * an instance of Promise.\n *\n * If we're recursing, we're traversing a marshaled object and shouldn't\n * redundantly marshal a nested part of it.\n */\n let marshalledObject;\n if (!isRecursing) {\n marshalledObject = this.marshal(value);\n } else {\n marshalledObject = value;\n }\n\n /**\n * Then, traverse the marshalled object, looking for these Promise memos\n * (resolve property). await the promise (X above) and replace it in the\n * marshaled object with the marshaled representation of the resolve value.\n */\n for (const key in marshalledObject) {\n if (!Object.hasOwnProperty.call(marshalledObject, key)) {\n continue;\n }\n\n switch (typeof marshalledObject[key]) {\n case 'object':\n if (marshalledObject[key] === null) {\n continue;\n }\n\n if (\n typeof marshalledObject[key].resolve !== 'undefined' &&\n marshalledObject[key].resolve instanceof Promise\n ) {\n marshalledObject[key].resolve = await this.marshalAsync(\n await marshalledObject[key].resolve,\n );\n }\n\n /**\n * Recursively traverse the marshalled object\n *\n * Operating on the marshalled object graph means we know for certain we\n * are working on a directed acyclic graph (DAG); prepares's \"seen\"\n * array argument expresses cycles separately.\n */\n marshalledObject[key] = await this.marshalAsync(\n marshalledObject[key],\n true,\n );\n break;\n default:\n break;\n }\n }\n\n return marshalledObject;\n}\n\n/** Turn a marshaled (prepared) value back into its original form\n * @param obj a prepared object - the output of this.marshal()\n * @returns object an object resembling the object originally passed to this.marshal()\n */\nKVIN.prototype.unmarshal = function serialize$$unmarshal (obj) {\n if (typeof obj !== 'object' || obj === null) {\n throw new Error(`Cannot unmarshal type ${typeof obj} or null.`)\n }\n if (!obj.hasOwnProperty('_serializeVerId')) {\n try {\n let str = JSON.stringify(obj)\n throw new Error('Invalid serialization format (' + str.slice(0, 20) + '\\u22ef' + str.slice(-20) + ')')\n } catch (e) {\n throw new Error('Invalid serialization format')\n }\n }\n switch (obj._serializeVerId) {\n case 'v4':\n case 'v5':\n case 'v6':\n case 'v7':\n break\n default:\n throw new Error(`Cannot unmarshal ${obj._serializeVerId} objects - please update Kvin`)\n }\n return this.unprepare([], obj.what, 'top')\n}\n\n/** Serialize a value.\n * @param what The value to serialize\n * @returns The JSON serialization of the prepared object representing what.\n */\nKVIN.prototype.serialize = function serialize (what) {\n return JSON.stringify(this.marshal(what))\n}\n\n/**\n * Serialize a value that is a Promise or contains Promises.\n *\n * @param {*} value The value to serialize\n * @returns {Promise<string>} A JSON serialization representing the value\n */\nKVIN.prototype.serializeAsync = async function serializeAsync(value) {\n return JSON.stringify(await this.marshalAsync(value))\n}\n\n/** Deserialize a value.\n * @param str The JSON serialization of the prepared object representing the value.\n * @returns The deserialized value\n */\nKVIN.prototype.deserialize = function deserialize (str) {\n if (typeof str !== 'string') {\n throw new Error(`Cannot deserialize type ${typeof str}`)\n }\n return this.unmarshal(JSON.parse(str))\n}\n\nKVIN.prototype.serializeVerId = 'v7'\n \n/* JSON-like interface */\nKVIN.prototype.parse = KVIN.prototype.deserialize; \nKVIN.prototype.stringify = KVIN.prototype.serialize;\nKVIN.prototype.stringifyAsync = KVIN.prototype.serializeAsync;\n\nexports.base_kvin = new KVIN();\n\nfor (let prop in exports.base_kvin)\n{\n if (typeof exports.base_kvin[prop] === 'function')\n exports[prop] = exports.base_kvin[prop].bind(exports);\n else {\n exports[prop] = exports.base_kvin[prop]\n }\n}\n\nexports.KVIN = KVIN;\n/* end of module */ })}\n\n\n//# sourceURL=webpack://dcp/./node_modules/kvin/kvin.js?");
|
|
3044
|
+
eval("/**\n * @file kvin.js A general-purpose library for marshaling and serializing\n * ES objects. This library is a functional superset of JSON\n * and relies on JSON for speed, adding:\n * - Typed Arrays with efficient spare representation\n * - Sparse arrays\n * - Arrays with enumerable properties\n * - Object graphs with cycles\n * - Boxed primitives (excluding Symbol)\n * - Functions (including enumerable properties, global scope)\n * - Regular Expressions\n * - undefined\n * - simple objects made with constructors\n * - objects will re-constructed with no constructor arguments\n * during deserialization\n * - enumerable properties will be copied on after construction\n * - opt-in list of supported constructors (kvin.constructorAllowList)\n *\n * This library is safe to use on user-supplied data.\n *\n * The basic implementation strategy is to marshal to an intermediate\n * format, called a 'prepared object', that can be used to recreate\n * the original object, but can also be serialized with JSON. We\n * track a list objects we have seen and their initial appearance in\n * the object graph. We rely on the /de-facto/ enumeration order of\n * properties in vanilla objects that has been present in all popular\n * browsers since the dawn of time; namely, that enumeration order is\n * object insertion order. This could cause bugs with objects with\n * cycles in less-common interpreters, such as Rhino and (especially)\n * the NJS/NGS ES3 platform by Brian Basset.\n *\n * *note* - This module free of external dependencies, and can be loaded as either a Node module,\n * a BravoJS module, or as a script tag in the browser.\n *\n * *bugs* - There are known or suspected issues in the following areas:\n * - Arrays which contain the same object more than once\n * - Arrays which mix numeric and non-numeric properties, especially if they are objects\n * - Sparse Arrays\n *\n * @author Wes Garland, wes@kingsds.network\n * @date June 2018\n *\n */\n\n\n\n{/* This prologue allows a CJS2 module's exports to be loaded with eval(readFileSync(filename)) */\n var module;\n let moduleSystemType;\n let realModule = module;\n \n if (true)\n moduleSystemType = 'webpack';\n else {}\n\n module = Object.assign({}, realModule);\n\n if (moduleSystemType === 'nodejs' || moduleSystemType === 'webpack' || moduleSystemType === 'cjs1') {\n module.declare = function kvin$$cjs1$$moduleDeclare(deps, factory) {\n factory(null, exports, null);\n module = realModule;\n return exports;\n };\n } else if (moduleSystemType === 'cjs2') {\n module = realModule;\n } else if (moduleSystemType === 'none') {\n module.declare = function kvin$$cjs1$$moduleDeclare(deps, factory) {\n let exports = {};\n factory(null, exports, null);\n module = realModule;\n\n if (typeof window === 'object')\n window.KVIN = exports;\n if (typeof globalThis === 'object')\n globalThis.KVIN = exports;\n\n return exports;\n };\n }\n/* Now initialize the module by invoking module.declare per CommonJS Modules/2.0-draft8 */\n \n/* eslint-disable indent */ module.declare([], function (require, exports, module) {\n\n/** \n * @constructor to create an alternate KVIN context. This allows us to recogonize instance of\n * the standard classes from a different JS context or have different tuning parameters. \n * @param ctors list or object of standard constructors\n */\nfunction KVIN(ctors)\n{\n // We always need to initialize the standardObjects. It is used for comparisons for primitive types etc\n this.standardObjects = {};\n for (let ctor of KVIN.prototype.ctors) {\n if (!ctor)\n continue;\n this.standardObjects[ctor.name] = ctor;\n }\n\n this.ctors = [].concat(KVIN.prototype.ctors);\n \n if (!ctors)\n return;\n\n if (Array.isArray(ctors))\n {\n for (let ctor of ctors)\n {\n if (!ctor)\n continue;\n this[ctor.name] = ctor\n for (let i=0; i < this.ctors.length; i++)\n {\n if (this.ctors[i].name === ctor.name)\n this.ctors[i] = ctor;\n }\n }\n }\n else\n {\n for (let entry of Object.entries(ctors))\n {\n for (let i=0; i < this.ctors.length; i++)\n {\n let [ name, ctor ] = entry; \n if (!ctor)\n continue;\n if (this.ctors[i].name === name)\n this.ctors[i] = ctor;\n this.standardObjects[name] = ctor;\n }\n }\n }\n}\n/*\n * Set exports.makeFunctions = true to allow deserializer to make functions.\n * If the deserializer can make functions, it is equivalent to eval() from a\n * security POV. Otherwise, the deserializer will turn functions into boxed\n * strings containing the function's source code, having a name property that\n * matches the original function.\n */\nKVIN.prototype.makeFunctions = false\n\n/* More bytes in a TypedArray than typedArrayPackThreshold will trigger\n * the code to prepare these into strings rather than arrays.\n */\nKVIN.prototype.typedArrayPackThreshold = 8\n\n/* Arrays of primitives which are >= the threshold in length are scrutinized\n * for further optimization, e.g. by run-length encoding\n */\nKVIN.prototype.scanArrayThreshold = 8\n\n\n/** Maxmimum number of arguments we can pass to a function in this engine.\n * @todo this needs to be detected at startup based on environment\n */\nconst _vm_fun_maxargs = 100000\n\nconst littleEndian = (function () {\n let ui16 = new Uint16Array(1)\n let ui8\n\n ui16[0] = 0xffef\n ui8 = new Uint8Array(ui16.buffer, ui16.byteOffset, ui16.byteLength)\n\n if (ui8[0] === 0x0ff) {\n console.error('KVIN: Detected big-endian platform')\n return false\n }\n\n return true\n})()\n\n/** Pre-defined constructors, used to compact payload */\nKVIN.prototype.ctors = [\n Object,\n Int8Array,\n Uint8Array,\n Uint8ClampedArray,\n Int16Array,\n Uint16Array,\n Int32Array,\n Uint32Array,\n Float32Array,\n Float64Array,\n RegExp,\n Number,\n String,\n Boolean,\n Array,\n Function,\n Error,\n Promise,\n typeof URL !== 'undefined' ? URL : undefined, /* not part of ES => feature-test */\n Date,\n];\n\nKVIN.prototype.userCtors = {}; /**< name: implementation for user-defined constructors that are not props of global */\n\n/** Take a 'prepared object' (which can be represented by JSON) and turn it\n * into an object which resembles the object it was created from.\n *\n * @param seen An array objects we have already seen in this\n * object graph; used to track cycles.\n * @param po A prepared object representing a value or a primitive\n * @param position A string respresenting our position within\n * the graph. Used only for error messages.\n * @returns the value encoded by po\n */\nKVIN.prototype.unprepare = function unprepare (seen, po, position) {\n switch (typeof po) {\n case 'boolean':\n case 'number':\n case 'string':\n return po;\n }\n if (po.hasOwnProperty('ctr')) {\n switch (typeof po.ctr) {\n case 'string':\n if (!po.ctr.match(/^[A-Za-z_0-9$][A-Za-z_0-9$]*$/)) {\n if (this.constructorAllowlist && this.constructorAllowlist.indexOf(po.ctr) === -1) {\n throw new Error('Allowlist does not include constructor ' + po.ctr)\n }\n throw new Error('Invalid constructor name: ' + po.ctr)\n }\n break\n case 'number':\n if (!(po.ctr >= 0 && po.ctr < this.ctors.length)) {\n throw new Error('Invalid constructor number: ' + po.ctr)\n }\n break\n default:\n throw new Error('Invalid constructor label type ' + typeof po.ctr)\n }\n }\n if (po.hasOwnProperty('raw')) {\n if (typeof po.raw === 'object' && po.raw !== null && !Array.isArray(po.raw))\n {\n if (!po.used)\n po.used = true;\n else\n return JSON.parse(JSON.stringify(po.raw));\n return Object.assign(new this.standardObjects.Object(), po.raw);\n }\n return po.raw;\n }\n if (po.hasOwnProperty('ptv')) {\n return po.ptv; /* deprecated: only created by v3-6 */\n }\n if (po.hasOwnProperty('number')) {\n return unprepare$number(po.number);\n }\n if (po.hasOwnProperty('bigint')) {\n return unprepare$bigint(po.bigint);\n }\n if (po.hasOwnProperty('fnName')) {\n return this.unprepare$function(seen, po, position)\n }\n if (po.hasOwnProperty('mapKeys') || po.hasOwnProperty('mapVals')) {\n return this.unprepare$Map(seen, po, position)\n }\n if (po.hasOwnProperty('ab16') || po.hasOwnProperty('isl16')) {\n return this.unprepare$ArrayBuffer16(seen, po, position)\n }\n if (po.hasOwnProperty('ab8') || po.hasOwnProperty('isl8')) {\n return this.unprepare$ArrayBuffer8(seen, po, position)\n }\n if (po.hasOwnProperty('arr')) {\n return this.unprepare$Array(seen, po, position)\n }\n if (po.hasOwnProperty('ctr')) {\n return this.unprepare$object(seen, po, position)\n }\n if (po.hasOwnProperty('json')) {\n return JSON.parse(po.json)\n }\n if (po.hasOwnProperty('undefined')) {\n return undefined\n }\n\n if (Object.hasOwnProperty.call(po, 'resolve')) {\n // Unprepare a Promise by assuming po.resolve is a marshalled value.\n const promise = Promise.resolve(this.unmarshal(po.resolve));\n seen.push(promise);\n return promise;\n }\n\n if (po.hasOwnProperty('seen')) {\n if (!seen.hasOwnProperty(po.seen)) {\n throw new Error('Seen-list corruption detected at index ' + po.seen)\n }\n return seen[po.seen]\n }\n throw new TypeError('Invalid preparation formula at ' + position)\n}\n\nKVIN.prototype.unprepare$object = function unprepare$object (seen, po, position) {\n let o\n let constructor;\n\n function construct(constructor, args) {\n function fun() {\n return constructor.apply(this, args);\n }\n fun.prototype = constructor.prototype;\n return new fun();\n }\n \n if (typeof po.ctr === 'string' && !po.ctr.match(/^[1-9][0-9]*$/)) {\n if (this.userCtors.hasOwnProperty(po.ctr))\n constructor = this.userCtors[po.ctr];\n else \n constructor = eval(po.ctr) /* pre-validated! */ // eslint-disable-line\n } else {\n constructor = this.ctors[po.ctr]\n }\n\n if (po.hasOwnProperty('args'))\n o = construct(constructor, po.args);\n else if (po.hasOwnProperty('arg'))\n o = new constructor(po.arg);\n else\n o = new constructor(); // eslint-disable-line\n\n if (po.ctr === 'Error')\n {\n delete o.stack;\n delete o.lineNumber;\n delete o.fileName;\n }\n \n seen.push(o)\n\n if (po.hasOwnProperty('ps')) {\n for (let prop in po.ps) {\n if (po.ps.hasOwnProperty(prop)) {\n o[prop] = this.unprepare(seen, po.ps[prop], position + '.' + prop)\n }\n }\n }\n\n return o\n}\n\nKVIN.prototype.unprepare$function = function unprepare$function (seen, po, position) {\n let obj, fn\n let fnName = po.fnName\n\n /* A function is basically a callable object */\n po.ctr = this.ctors.indexOf(Object)\n delete po.fnName\n obj = this.unprepare(seen, po, position)\n\n if (!this.makeFunctions) {\n obj.name = fnName\n return obj\n }\n\n fn = (new Function('return ' + po.arg))() // eslint-disable-line\n if (po.hasOwnProperty('ps')) {\n for (let prop in po.ps) {\n fn[prop] = obj[prop]\n }\n }\n\n return fn\n}\n\nKVIN.prototype.unprepare$Map = function unprepare$Map (seen, po, position) {\n \n let m = new Map();\n\n seen.push(m)\n\n let mapKeyArr = this.unprepare$Array(seen, po.mapKeys, position);\n let mapValArr = this.unprepare$Array(seen, po.mapVals, position);\n\n for (let i = 0; i < mapKeyArr.length; i++)\n {\n m.set(mapKeyArr[i], mapValArr[i]);\n }\n\n if (po.hasOwnProperty('ps')) {\n for (let prop in po.ps) {\n if (po.ps.hasOwnProperty(prop)) {\n m[prop] = this.unprepare(seen, po.ps[prop], position + '.' + prop)\n }\n }\n }\n\n return m;\n}\n\nfunction unprepare$bigint(arg) {\n return BigInt(arg);\n}\n\nfunction unprepare$number(arg) {\n return parseFloat(arg);\n}\n \n/**\n * arr:[] - Array of primitives of prepared objects\n * lst:N - repeat last element N times\n * ps:[] - property list\n */\nKVIN.prototype.unprepare$Array = function unprepare$Array (seen, po, position) {\n let a = []\n let last\n\n seen.push(a)\n\n for (let i = 0; i < po.arr.length; i++) {\n if (typeof po.arr[i] === 'object') {\n if (po.arr[i].lst) {\n for (let j = 0; j < po.arr[i].lst; j++) {\n a.push(this.unprepare(seen, last, position + '.' + (i + j)))\n }\n continue\n }\n a.push(this.unprepare(seen, po.arr[i], position + '.' + i))\n last = po.arr[i]\n } else {\n a.push(po.arr[i])\n last = prepare$primitive(a[a.length-1], 'unprepare$Array')\n }\n }\n\n if (po.hasOwnProperty('isl')) {\n for (let prop in po.isl) {\n let island = po.isl[prop]\n let els = Array.isArray(island.arr) ? island.arr : this.unprepare$Array(seen, island.arr, [ position, 'isl', prop ].join('.'))\n\n if (els.length - 3 <= _vm_fun_maxargs) {\n if (els.length && (a.length < island['@'] + els.length)) {\n a.length = island['@'] + els.length\n }\n a.splice.apply(a, [island['@'], els.length].concat(els))\n } else {\n for (let i=0; i < els.length; i++) {\n a[i + +island['@']] = els[i]\n }\n }\n }\n }\n\n if (po.hasOwnProperty('ps')) {\n for (let prop in po.ps) {\n if (typeof po.ps[prop] === 'object') {\n a[prop] = this.unprepare(seen, po.ps[prop], position + '.' + prop)\n } else {\n a[prop] = po.ps[prop]\n }\n }\n }\n\n if (po.len) {\n a.length = po.len\n }\n\n return a\n}\n\n/** The ab8 (array buffer 8 bit) encoding encodes TypedArrays and related types by\n * converting them to Latin-1 strings full of binary data in 8-bit words.\n *\n * The isl8 (islands) encoding is almost the same, except that it encodes only\n * sequences of mostly-non-zero sections of the string.\n */\nKVIN.prototype.unprepare$ArrayBuffer8 = function unprepare$ArrayBuffer8 (seen, po, position) {\n let i8\n let bytes\n let constructor;\n\n if (typeof po.ctr === 'string' && !po.ctr.match(/^[1-9][0-9]*$/)) {\n constructor = eval(po.ctr) /* pre-validated! */ // eslint-disable-line\n } else {\n constructor = this.ctors[po.ctr]\n }\n\n if (po.hasOwnProperty('ab8')) {\n bytes = po.ab8.length\n } else {\n bytes = po.len\n }\n i8 = new Int8Array(bytes)\n if (po.hasOwnProperty('ab8')) {\n for (let i = 0; i < po.ab8.length; i++) {\n i8[i] = po.ab8.charCodeAt(i)\n }\n } else {\n for (let j = 0; j < po.isl8.length; j++) {\n for (let i = 0; i < po.isl8[j][0].length; i++) {\n i8[po.isl8[j]['@'] + i] = po.isl8[j][0].charCodeAt(i)\n }\n }\n }\n let o = new constructor(i8.buffer, i8.byteOffset) // eslint-disable-line;\n seen.push(o)\n return o;\n}\n\n/** The ab16 (array buffer 16 bit) encoding encodes TypedArrays and related types by\n * converting them to strings full of binary data in 16-bit words. Buffers\n * with an odd number of bytes encode an extra byte 'eb' at the end by itself.\n *\n * The isl16 (islands) encoding is almost the same, except that it encodes only\n * sequences of mostly-non-zero sections of the string.\n */\n KVIN.prototype.unprepare$ArrayBuffer16 = function unprepare$ArrayBuffer16 (seen, po, position) {\n let i16, i8, words\n let bytes\n let constructor;\n\n if (typeof po.ctr === 'string' && !po.ctr.match(/^[1-9][0-9]*$/)) {\n constructor = eval(po.ctr) /* pre-validated! */ // eslint-disable-line\n } else {\n constructor = this.ctors[po.ctr]\n }\n\n if (po.hasOwnProperty('ab16')) {\n bytes = po.ab16.length * 2\n if (po.hasOwnProperty('eb')) {\n bytes++\n }\n } else {\n bytes = po.len\n }\n\n words = Math.floor(bytes / 2) + (bytes % 2)\n i16 = new Int16Array(words)\n if (po.hasOwnProperty('ab16')) {\n for (let i = 0; i < po.ab16.length; i++) {\n i16[i] = po.ab16.charCodeAt(i)\n }\n } else {\n for (let j = 0; j < po.isl16.length; j++) {\n for (let i = 0; i < po.isl16[j][0].length; i++) {\n i16[po.isl16[j]['@'] + i] = po.isl16[j][0].charCodeAt(i)\n }\n }\n }\n i8 = new Int8Array(i16.buffer, i16.byteOffset, bytes)\n if (po.hasOwnProperty('eb')) {\n i8[i8.byteLength - 1] = po.eb.charCodeAt(0)\n }\n\n if (!littleEndian) {\n for (let i = 0; i < i8.length; i += 2) {\n i8[(i * 2) + 0] = i8[(i * 2) + 0] ^ i8[(i * 2) + 1]\n i8[(i * 2) + 1] = i8[(i * 2) + 1] ^ i8[(i * 2) + 0]\n i8[(i * 2) + 0] = i8[(i * 2) + 0] ^ i8[(i * 2) + 1]\n }\n }\n let o = new constructor(i8.buffer, i8.byteOffset) // eslint-disable-line\n seen.push(o)\n return o\n}\n\n/* Primitives and primitive-like objects do not have any special\n * marshaling requirements -- specifically, we don't need to\n * iterate over their properties in order to serialize them; we\n * can let JSON.stringify() do any heavy lifting.\n */\nKVIN.prototype.isPrimitiveLike = function isPrimitiveLike (o, seen) {\n if (o === null || typeof o === 'string' || typeof o === 'boolean')\n return true;\n\n if (typeof o === 'number')\n return Number.isFinite(o);\n\n if (typeof o !== 'object')\n return false;\n \n if (o.constructor === this.standardObjects.Object && Object.keys(o).length === 0)\n return true;\n\n if (o.constructor === this.standardObjects.Array && o.length === 0 && Object.keys(o).length === 0)\n return true;\n\n if (o.constructor !== this.standardObjects.Object && o.constructor !== this.standardObjects.Array)\n return false;\n\n if (Array.isArray(o)) {\n if (Object.keys(o).length !== o.length) {\n return false /* sparse array or named props */\n }\n }\n\n seen = seen.concat(o);\n for (let prop in o) {\n if (!o.hasOwnProperty(prop))\n return false;\n if (seen.indexOf(o[prop]) !== -1)\n return false; \n if (!this.isPrimitiveLike(o[prop], seen))\n return false;\n }\n\n return true\n}\n\n/**\n * Serialize an instance of Error, preserving standard-ish non-enumerable properties \n */ \nfunction prepare$Error(o)\n{\n let ret = {\n ctr: 'Error',\n ps: {},\n arg: o.message\n };\n\n for (let prop of ['code', 'stack', 'lineNumber', 'fileName'])\n if (o.hasOwnProperty(prop))\n ret.ps[prop] = o[prop];\n for (let prop in o)\n if (o.hasOwnProperty(prop))\n ret.ps[prop] = o[prop];\n\n return ret;\n}\n \n/** Take an arbitrary object and turn it into a 'prepared object'.\n * A prepared object can always be represented with JSON.\n *\n * @param seen An array objects we have already seen in this\n * object graph; used to track cycles.\n * @param o The object that the prepared object reflects\n * @returns A prepared object\n */\nKVIN.prototype.prepare = function prepare (seen, o, where) {\n let i, ret\n let po = {}\n\n if (typeof o === 'number') {\n return prepare$number(o)\n }\n if (typeof o === 'bigint') {\n return prepare$bigint(o)\n }\n if (this.isPrimitiveLike(o, seen)) {\n if (!Array.isArray(o) || o.length < this.scanArrayThreshold)\n return prepare$primitive(o, where)\n }\n if (typeof o === 'undefined') {\n return prepare$undefined(o)\n }\n /* value types below here can be used as targets of cycles */\n if ((i = seen.indexOf(o)) === -1) {\n seen.push(o)\n } else {\n return { seen: i }\n }\n if (Array.isArray(o)) {\n return this.prepare$Array(seen, o, where)\n }\n if (ArrayBuffer.isView(o)) {\n return this.prepare$ArrayBuffer(o)\n }\n if (o.constructor === Map) {\n return this.prepare$Map(seen, o, where)\n }\n if (o.constructor === WeakMap) {\n return prepare$WeakMap(o)\n }\n if (o.constructor === String || o.constructor === Number || o.constructor === Boolean) {\n return this.prepare$boxedPrimitive(o)\n }\n if (o.constructor === RegExp) {\n return this.prepare$RegExp(o)\n }\n\n if (o instanceof Promise || o instanceof this.standardObjects.Promise) {\n /**\n * Let the caller replace the `resolve` property with its marshalled\n * resolved value.\n */\n return { resolve: o };\n }\n\n if (o instanceof Error || o instanceof this.standardObjects.Error) {\n /* special-case Error to get non-enumerable properties */\n return prepare$Error(o);\n }\n\n if (typeof o.constructor === 'undefined') {\n console.warn('KVIN Warning: ' + where + ' is missing .constructor -- skipping')\n return prepare$undefined(o)\n }\n\n ret = { ctr: this.ctors.indexOf(o.constructor), ps: po }\n if (ret.ctr === -1) {\n /**\n * If the constructor is `Object` from another context, the indexOf check\n * would fail. So if the name of `o`'s constructor matches one of the valid\n * constructors, use the index from the mapped array to get the proper\n * constructor index.\n */\n const constructorNames = this.ctors.map((ctor) => ctor.name);\n const ctrIndex = constructorNames.indexOf(o.constructor.name);\n if (ctrIndex !== -1) {\n ret.ctr = ctrIndex;\n /**\n * Fix the `o`'s constructor to match its constructor in the current\n * context so that later equality/instanceof checks don't fail.\n */\n o.constructor = this.ctors[ctrIndex];\n } else {\n ret.ctr = o.constructor.name || this.ctors.indexOf(Object)\n }\n }\n\n if (typeof o === 'function') {\n ret.fnName = o.name\n }\n\n if (typeof o.toKVIN === 'function')\n return Object.assign(ret, o.toKVIN(o, this));\n else if (typeof o.toJSON === 'function')\n ret.arg = o.toJSON();\n else if (o.toString !== this.standardObjects.Object.prototype.toString)\n ret.arg = o.toString();\n\n if (typeof o.hasOwnProperty === 'undefined') {\n return ret;\n }\n\n /* Iterate over the properties and prepare each in turn, recursing\n * with a depth-first traversal of the object graph. Iteration order\n * must match unprepare()!\n */\n for (let prop in o) {\n if (!o.hasOwnProperty(prop)) {\n continue\n }\n\n switch (typeof o[prop]) {\n case 'function':\n case 'object':\n if (o[prop] !== null) {\n if (typeof o[prop].constructor !== 'undefined'\n && o[prop].constructor !== this.standardObjects.Object && o[prop].constructor.constructor !== this.standardObjects.Object\n && o[prop].constructor !== this.standardObjects.Function && o[prop].constructor.constructor !== this.standardObjects.Function\n && o[prop].constructor !== this.standardObjects.Function && o[prop].constructor.constructor.name !== \"Function\" /* vm context issue /wg aug 2020 */\n ) {\n throw new Error(`Cannot serialize property ${where}.${prop} - multiple inheritance is not supported.`);\n }\n if ((i = seen.indexOf(o[prop])) === -1) {\n po[prop] = this.prepare(seen, o[prop], where + '.' + prop)\n } else {\n po[prop] = { seen: i }\n }\n break\n } /* else fallthrough */\n case 'number':\n po[prop] = prepare$number(o[prop]);\n break;\n case 'bigint':\n po[prop] = prepare$bigint(o[prop]);\n break;\n case 'boolean':\n case 'string':\n po[prop] = prepare$primitive(o[prop], where + '.' + prop)\n break\n case 'undefined':\n po[prop] = prepare$undefined(o[prop])\n break\n default:\n throw new TypeError('Cannot serialize property ' + prop + ' which is a ' + typeof o[prop])\n }\n }\n\n return ret\n}\n\n/** Prepare an Array. Sparse arrays and arrays with properties\n * are supported, and represented reasonably efficiently, as are\n * arrays of repeated values.\n *\n * @param seen The current seen list for this marshal - things pointers point to\n * @param o The array we are preparing\n * @param where Human description of where we are in the object, for debugging purposes\n */\n KVIN.prototype.prepare$Array = function prepare$Array (seen, o, where) {\n let pa = { arr: [] }\n let keys = Object.keys(o)\n let lastJson = NaN\n let json\n let lstTotal = 0\n\n for (let i = 0; i < o.length; i++) {\n if (!o.hasOwnProperty(i)) {\n break /* sparse array */\n }\n if (typeof o[i] !== 'object' && this.isPrimitiveLike(o[i], seen)) {\n pa.arr.push(o[i])\n } else {\n pa.arr.push(this.prepare(seen, o[i], where + '.' + i))\n }\n\n json = JSON.stringify(pa.arr[pa.arr.length - 1])\n if (json === lastJson) {\n if (pa.arr[pa.arr.length - 2].lst) {\n pa.arr[pa.arr.length - 2].lst++\n pa.arr.length--\n lstTotal++\n } else {\n pa.arr[pa.arr.length - 1] = {lst: 1}\n }\n } else {\n lastJson = json\n }\n }\n\n if (keys.length !== o.length) {\n /* sparse array or array with own properties - difference between sparse entry and value=undefined preserved */\n for (let j = 0; j < keys.length; j++) {\n let key = keys[j]\n let idx = +key\n if (idx < j && pa.arr.hasOwnProperty(idx)) { /* test order for speed */\n continue\n }\n if (typeof idx === 'number' && o.hasOwnProperty(idx + 1)) {\n let island = { '@':idx, arr:[] }\n /* island of data inside sparse array */\n if (!pa.isl) {\n pa.isl = []\n }\n for (let k = idx; o.hasOwnProperty(k); k++) {\n island.arr.push(o[k])\n }\n j += island.arr.length - 1\n if (island.arr.length >= this.scanArrayThreshold) {\n let tmp = this.prepare(seen, island.arr, where + '.' + 'isl@' + (j - island.arr.length))\n if (tmp.hasOwnProperty('arr')) {\n island.arr = tmp\n } else {\n pa.isl.push(island)\n }\n }\n pa.isl.push(island)\n continue\n }\n if (!pa.hasOwnProperty('ps')) {\n pa.ps = {}\n }\n if (typeof o[key] !== 'object' && this.isPrimitiveLike(o[key], seen)) {\n pa.ps[key] = o[key]\n } else {\n pa.ps[key] = this.prepare(seen, o[key], where + '.' + key)\n }\n }\n }\n\n if (pa.arr.length + lstTotal !== o.length) {\n pa.len = o.length\n }\n return pa\n}\n\n/** Prepare a Map. This can be robustly handled with the existing array preparation, as\n * long as we differentiate it from normal arrays and treat keys and values separately.\n *\n * @param seen The current seen list for this marshal - things pointers point to\n * @param o The Map we are preparing\n * @param where Human description of where we are in the object, for debugging purposes\n */\n KVIN.prototype.prepare$Map = function prepare$Map (seen, o, where) {\n\n let pm = { mapKeys: [], mapVals: [] }\n\n let mapKeyArr = Array.from(o.keys());\n pm.mapKeys = this.prepare$Array(seen, mapKeyArr, where);\n\n let mapValArr = Array.from(o.values());\n pm.mapVals = this.prepare$Array(seen, mapValArr, where);\n\n let keys = Object.keys(o)\n if (keys.length !== o.length) {\n for (let j = 0; j < keys.length; j++) {\n let key = keys[j]\n if (!pm.hasOwnProperty('ps')) {\n pm.ps = {}\n }\n if (typeof o[key] !== 'object' && this.isPrimitiveLike(o[key])) {\n pm.ps[key] = o[key]\n } else {\n pm.ps[key] = this.prepare(seen, o[key], where + '.' + key)\n }\n }\n }\n\n return pm;\n}\n\n/** Prepare a WeakMap. The closest to correct behaviour for a WeakMap serialized over\n * a network is for the resulting WeakMap to be empty, since the WeakMap keys are\n * by design never directly referenced or retained, and cannot be iterated on.\n * This is why we pass an empty array to the constructor.\n *\n * @param o The WeakMap we are preparing\n */\n KVIN.prototype.prepare$WeakMap = function prepare$WeakMap (o) {\n return { ctr: ctors.indexOf(o.constructor), arg: [] }\n}\n\n/** Detect JavaScript strings which contain ill-formed UTF-16 sequences */\nfunction notUnicode(s) {\n if (/[\\ud800-\\udbff][^\\udc00-\\udfff]/.test(s)) {\n return true /* high-surrogate without low-surrogate */\n }\n\n if (/[^\\ud800-\\udbff][\\udc00-\\udfff]/.test(s)) {\n return true /* low-surrogate without high-surrogate */\n }\n\n return false\n}\n/** Prepare an ArrayBuffer into UCS-2, returning null when we cannot guarantee\n * that the UCS-2 is also composed of valid UTF-16 code points\n *\n * @see unprepare$ArrayBuffer16\n */\nKVIN.prototype.prepare$ArrayBuffer16 = function prepare$ArrayBuffer16 (o) {\n let ret = { ctr: this.ctors.indexOf(o.constructor) }\n let nWords = Math.floor(o.byteLength / 2)\n let s = ''\n\n if (ret.ctr === -1)\n ret.ctr = o.constructor.name\n\n if (littleEndian) {\n let ui16 = new Uint16Array(o.buffer, o.byteOffset, nWords)\n for (let i = 0; i < nWords; i++) {\n s += String.fromCharCode(ui16[i])\n }\n } else {\n let ui8 = new Uint8Array(o.buffer, o.byteOffset, o.byteLength)\n for (let i = 0; i < nWords; i++) {\n s += String.fromCharCode((ui8[0 + (2 * i)] << 8) + (ui8[1 + (2 * i)]))\n }\n }\n\n let manyZeroes = '\\u0000\\u0000\\u0000\\u0000'\n if (s.indexOf(manyZeroes) === -1) {\n ret.ab16 = s\n } else {\n /* String looks zero-busy: represent via islands of mostly non-zero (sparse string). */\n // let re = /([^\\u0000]+/g\n let re = /([^\\u0000]+(.{0,3}([^\\u0000]|$))*)+/g\n let island\n\n ret.isl16 = []\n ret.len = o.byteLength\n while ((island = re.exec(s))) {\n ret.isl16.push({0: island[0].replace(/\\u0000*$/, ''), '@': island.index})\n }\n }\n if ((2 * nWords) !== o.byteLength) {\n let ui8 = new Uint8Array(o.buffer, o.byteOffset + o.byteLength - 1, 1)\n ret.eb = ui8[0]\n }\n\n if (ret.ab16 && notUnicode(ret.ab16)) {\n return null\n } else if (ret.isl16) {\n for (let i = 0; i < ret.isl16.length; i++) {\n if (notUnicode(ret.isl16[i])) {\n return null\n }\n }\n }\n return ret\n}\n\n/** Encode an ArrayBuffer (TypedArray) into a string composed solely of Latin-1 characters.\n * Strings with many zeroes will be represented as sparse-string objects.\n */\nKVIN.prototype.prepare$ArrayBuffer8 = function prepare$ArrayBuffer8 (o) {\n let ret = { ctr: this.ctors.indexOf(o.constructor) }\n\n if (ret.ctr === -1)\n ret.ctr = o.constructor.name\n\n const mss = _vm_fun_maxargs - 1\n let ui8 = new Uint8Array(o.buffer, o.byteOffset, o.byteLength)\n let segments = []\n let s\n\n for (let i=0; i < ui8.length / mss; i++) {\n segments.push(String.fromCharCode.apply(null, ui8.slice(i * mss, (i + 1) * mss)))\n }\n s = segments.join('')\n\n let manyZeroes = '\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000'\n if (s.indexOf(manyZeroes) === -1) {\n ret.ab8 = s\n } else {\n /* String looks zero-busy: represent via islands of mostly non-zero (sparse string). */\n // let re = /([^\\u0000]+/g\n let re = /([^\\u0000]+(.{0,3}([^\\u0000]|$))*)+/g\n let island\n\n ret.isl8 = []\n ret.len = o.byteLength\n while ((island = re.exec(s))) {\n ret.isl8.push({0: island[0].replace(/\\u0000*$/, ''), '@': island.index})\n }\n }\n\n return ret\n}\n\n/** Encode an ArrayBuffer (TypedArray) into a string, trying multiple methods to determine\n * optimimum size/performance. The this.tune variable affects the behaviour of this code this:\n *\n * \"speed\" - only do naive encoding: floats get represented as byte-per-digit strings\n * \"size\" - try the naive, ab8, and ab16 encodings; pick the smallest\n * neither - try the naive encoding if under typedArrayPackThreshold and use if smaller than\n * ab8; otherwise, use ab8\n */\nKVIN.prototype.prepare$ArrayBuffer = function prepare$ArrayBuffer (o) {\n let naive, naiveJSONLen;\n let ab8, ab8JSONLen;\n let ab16, ab16JSONLen;\n\n if (this.tune === \"speed\" || this.tune === \"size\" || (o.byteLength < this.typedArrayPackThreshold)) {\n naive = { ctr: this.ctors.indexOf(o.constructor), arg: Array.prototype.slice.call(o) }\n if (this.tune === \"speed\") {\n return naive\n }\n }\n\n naiveJSONLen = naive ? JSON.stringify(naive).length : Infinity\n\n ab8 = this.prepare$ArrayBuffer8(o)\n if (this.tune !== \"size\") {\n if (naive && naive.length < ab8.length) {\n return naive\n }\n return ab8\n }\n\n ab16 = this.prepare$ArrayBuffer16(o)\n ab8JSONLen = JSON.stringify(ab8).length;\n ab16JSONLen = ab16 ? JSON.stringify(ab16).length : Infinity\n\n if (ab16JSONLen < ab8JSONLen && ab16JSONLen < naiveJSONLen) {\n return ab16\n }\n if (naiveJSONLen < ab8JSONLen) {\n return naive\n }\n\n return ab8;\n}\n\nKVIN.prototype.prepare$RegExp = function prepare$RegExp (o) {\n return { ctr: this.ctors.indexOf(o.constructor), arg: o.toString().slice(1, -1) }\n}\n\nKVIN.prototype.prepare$boxedPrimitive = function prepare$boxedPrimitive (o) {\n return { ctr: this.ctors.indexOf(o.constructor), arg: o.toString() }\n}\n\nfunction prepare$bigint (n) {\n return { bigint: n.toString() }\n}\n\nfunction prepare$number (n) {\n if (!Number.isFinite(n))\n return { number: n + '' };\n\n if (1/n === -Infinity)\n return { json: \"-0\" };\n\n return n;\n}\n \n/* Store primitives and sort-of-primitives (like object literals) directly */\nfunction prepare$primitive (primitive, where) {\n switch (typeof po) {\n case 'boolean':\n case 'number': /* not all cases, see prepare$number */\n case 'string':\n return primitive;\n }\n return { raw: primitive };\n}\n\nfunction prepare$undefined (o) {\n return { undefined: true }\n}\n\n/** Prepare a value for serialization\n * @param what any (supported) js value\n * @returns an object which can be serialized with json\n */\nKVIN.prototype.marshal = function serialize$$marshal (what) {\n return {_serializeVerId: this.serializeVerId, what: this.prepare([], what, 'top')}\n}\n\n/**\n * Prepare a value that is a Promise or contains a Promise for serialization.\n *\n * Removes cycles in objects to enable stringification using `JSON.stringify`.\n *\n * @param {*} value A supported js value that can be marshalled\n * @returns {Promise<object>} An object which can be serialized with\n * `JSON.stringify`\n */\nKVIN.prototype.marshalAsync = async function serialize$$marshalAsync(value, isRecursing = false) {\n /**\n * First, have marshal memoize returned an object graph with any instances of\n * Promise found during the marshal operation with { resolve: X }, where X is\n * an instance of Promise.\n *\n * If we're recursing, we're traversing a marshaled object and shouldn't\n * redundantly marshal a nested part of it.\n */\n let marshalledObject;\n if (!isRecursing) {\n marshalledObject = this.marshal(value);\n } else {\n marshalledObject = value;\n }\n\n /**\n * Then, traverse the marshalled object, looking for these Promise memos\n * (resolve property). await the promise (X above) and replace it in the\n * marshaled object with the marshaled representation of the resolve value.\n */\n for (const key in marshalledObject) {\n if (!Object.hasOwnProperty.call(marshalledObject, key)) {\n continue;\n }\n\n switch (typeof marshalledObject[key]) {\n case 'object':\n if (marshalledObject[key] === null) {\n continue;\n }\n\n if (\n typeof marshalledObject[key].resolve !== 'undefined' &&\n marshalledObject[key].resolve instanceof Promise\n ) {\n marshalledObject[key].resolve = await this.marshalAsync(\n await marshalledObject[key].resolve,\n );\n }\n\n /**\n * Recursively traverse the marshalled object\n *\n * Operating on the marshalled object graph means we know for certain we\n * are working on a directed acyclic graph (DAG); prepares's \"seen\"\n * array argument expresses cycles separately.\n */\n marshalledObject[key] = await this.marshalAsync(\n marshalledObject[key],\n true,\n );\n break;\n default:\n break;\n }\n }\n\n return marshalledObject;\n}\n\n/** Turn a marshaled (prepared) value back into its original form\n * @param obj a prepared object - the output of this.marshal()\n * @returns object an object resembling the object originally passed to this.marshal()\n */\nKVIN.prototype.unmarshal = function serialize$$unmarshal (obj) {\n if (typeof obj !== 'object' || obj === null) {\n throw new Error(`Cannot unmarshal type ${typeof obj} or null.`)\n }\n if (!obj.hasOwnProperty('_serializeVerId')) {\n try {\n let str = JSON.stringify(obj)\n throw new Error('Invalid serialization format (' + str.slice(0, 20) + '\\u22ef' + str.slice(-20) + ')')\n } catch (e) {\n throw new Error('Invalid serialization format')\n }\n }\n switch (obj._serializeVerId) {\n case 'v4':\n case 'v5':\n case 'v6':\n case 'v7':\n case 'v8':\n break\n default:\n throw new Error(`Cannot unmarshal ${obj._serializeVerId} objects - please update Kvin`)\n }\n return this.unprepare([], obj.what, 'top')\n}\n\n/** Serialize a value.\n * @param what The value to serialize\n * @returns The JSON serialization of the prepared object representing what.\n */\nKVIN.prototype.serialize = function serialize (what) {\n return JSON.stringify(this.marshal(what))\n}\n\n/**\n * Serialize a value that is a Promise or contains Promises.\n *\n * @param {*} value The value to serialize\n * @returns {Promise<string>} A JSON serialization representing the value\n */\nKVIN.prototype.serializeAsync = async function serializeAsync(value) {\n return JSON.stringify(await this.marshalAsync(value))\n}\n\n/** Deserialize a value.\n * @param str The JSON serialization of the prepared object representing the value.\n * @returns The deserialized value\n */\nKVIN.prototype.deserialize = function deserialize (str) {\n if (typeof str !== 'string') {\n throw new Error(`Cannot deserialize type ${typeof str}`)\n }\n return this.unmarshal(JSON.parse(str))\n}\n\nKVIN.prototype.serializeVerId = 'v8'\n \n/* JSON-like interface */\nKVIN.prototype.parse = KVIN.prototype.deserialize; \nKVIN.prototype.stringify = KVIN.prototype.serialize;\nKVIN.prototype.stringifyAsync = KVIN.prototype.serializeAsync;\n\nexports.base_kvin = new KVIN();\n\nfor (let prop in exports.base_kvin)\n{\n if (typeof exports.base_kvin[prop] === 'function')\n exports[prop] = exports.base_kvin[prop].bind(exports);\n else {\n exports[prop] = exports.base_kvin[prop]\n }\n}\n\nexports.KVIN = KVIN;\n/* end of module */ })}\n\n\n//# sourceURL=webpack://dcp/./node_modules/kvin/kvin.js?");
|
|
3045
3045
|
|
|
3046
3046
|
/***/ }),
|
|
3047
3047
|
|
|
@@ -3794,7 +3794,7 @@ eval("// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission
|
|
|
3794
3794
|
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
|
3795
3795
|
|
|
3796
3796
|
"use strict";
|
|
3797
|
-
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (/* binding */ Modal)\n/* harmony export */ });\n/**\n * A Small Modal Class\n * @module Modal\n */\n/* globals Event dcpConfig */\nclass Modal {\n constructor (title, message, callback = false, exitHandler = false, {\n continueLabel = 'Continue',\n cancelLabel = 'Cancel',\n cancelVisible = true\n } = {}) {\n const modal = document.createElement('div')\n modal.className = 'dcp-modal-container-old day'\n modal.innerHTML = `\n <dialog class=\"dcp-modal-content\">\n <div class=\"dcp-modal-header\">\n <h2>${title}<button type=\"button\" class=\"close\">×</button></h2>\n ${message ? '<p>' + message + '</p>' : ''}\n </div>\n <div class=\"dcp-modal-loading hidden\">\n <div class='loading'></div>\n </div>\n <form onsubmit='return false' method=\"dialog\">\n <div class=\"dcp-modal-body\"></div>\n <div class=\"dcp-modal-footer ${cancelVisible ? '' : 'centered'}\">\n <button type=\"submit\" class=\"continue green-modal-button\">${continueLabel}</button>\n <button type=\"button\" class=\"cancel green-modal-button\">${cancelLabel}</button>\n </div>\n </form>\n </dialog>`\n\n // To give a reference to do developer who wants to override the form submit.\n // May occur if they want to validate the information in the backend\n // without closing the modal prematurely.\n this.form = modal.querySelector('.dcp-modal-content form')\n this.continueButton = modal.querySelector('.dcp-modal-footer button.continue')\n this.cancelButton = modal.querySelector('.dcp-modal-footer button.cancel')\n this.closeButton = modal.querySelector('.dcp-modal-header .close')\n if (!cancelVisible) {\n this.cancelButton.style.display = 'none'\n }\n\n // To remove the event listener, the reference to the original function\n // added is required.\n this.formSubmitHandler = this.continue.bind(this)\n\n modal.addEventListener('keydown', function (event) {\n event.stopPropagation()\n // 27 is the keycode for the escape key.\n if (event.keyCode === 27) this.close()\n }.bind(this))\n\n this.container = modal\n this.callback = callback\n this.exitHandler = exitHandler\n document.body.appendChild(modal)\n }\n\n changeFormSubmitHandler (newFormSubmitHandler) {\n this.formSubmitHandler = newFormSubmitHandler\n }\n\n /**\n * Validates the form values in the modal and calls the modal's callback\n */\n async continue (event) {\n // To further prevent form submission from trying to redirect from the\n // current page.\n if (event instanceof Event) {\n event.preventDefault()\n }\n let fieldsAreValid = true\n let formElements = this.container.querySelectorAll('.dcp-modal-body select, .dcp-modal-body input, .dcp-modal-body textarea')\n\n const formValues = []\n if (typeof formElements.length === 'undefined') formElements = [formElements]\n // Separate into two loops to enable input validation requiring formValues\n // that come after it. e.g. Two password fields matching.\n for (let i = 0; i < formElements.length; i++) {\n switch (formElements[i].type) {\n case 'file':\n formValues.push(formElements[i])\n break\n case 'checkbox':\n formValues.push(formElements[i].checked)\n break\n default:\n formValues.push(formElements[i].value)\n break\n }\n }\n for (let i = 0; i < formElements.length; i++) {\n if (formElements[i].validation) {\n // Optional fields are allowed to be empty but still can't be wrong if not empty.\n if (!(formElements[i].value === '' && !formElements[i].required)) {\n if (typeof formElements[i].validation === 'function') {\n if (!formElements[i].validation(formValues)) {\n fieldsAreValid = false\n formElements[i].classList.add('is-invalid')\n }\n } else if (!formElements[i].validation.test(formElements[i].value)) {\n fieldsAreValid = false\n formElements[i].classList.add('is-invalid')\n }\n }\n }\n }\n\n if (!fieldsAreValid) return\n\n this.loading()\n if (typeof this.callback === 'function') {\n try {\n return this.callback(formValues)\n } catch (error) {\n console.error('Unexpected error in modal.continue:', error);\n return this.close(false)\n }\n }\n this.close(true)\n }\n\n loading () {\n this.container.querySelector('.dcp-modal-loading').classList.remove('hidden')\n this.container.querySelector('.dcp-modal-body').classList.add('hidden')\n this.container.querySelector('.dcp-modal-footer').classList.add('hidden')\n }\n\n open () {\n this.form.addEventListener('submit', async (event) => {\n const success = await this.formSubmitHandler(event)\n if (success === false) {\n return\n }\n this.close(true)\n })\n // When the user clicks on <span> (x), close the modal\n this.closeButton.addEventListener('click', this.close.bind(this))\n this.cancelButton.addEventListener('click', this.close.bind(this))\n\n // Prevent lingering outlines after clicking some form elements.\n this.container.querySelectorAll('.dcp-modal-body button, .dcp-modal-body input[type=\"checkbox\"]').forEach(element => {\n element.addEventListener('click', () => {\n element.blur()\n })\n })\n\n // Show the modal.\n this.container.style.display = 'block'\n\n const formElements = this.container.querySelectorAll('.dcp-modal-body select, .dcp-modal-body input')\n if (formElements.length) {\n formElements[0].focus()\n if (formElements[0].type === 'text') {\n formElements[0].select()\n }\n for (const el of formElements) {\n if (el.realType) {\n el.type = el.realType\n }\n }\n } else {\n // With no form elements to allow for form submission on enter, focus the\n // continue button.\n this.container.querySelector('.dcp-modal-footer button.continue').focus()\n }\n } // TODO: This should return a promise with the action resolving it\n\n /**\n * Shows the modal and returns a promise of the result of the modal (e.g. was\n * it closed, did its action succeed?)\n */\n showModal () {\n return new Promise((resolve, reject) => {\n this.form.addEventListener('submit', handleContinue.bind(this))\n this.cancelButton.addEventListener('click', handleCancel.bind(this))\n this.closeButton.addEventListener('click', handleCancel.bind(this))\n\n // Prevent lingering outlines after clicking some form elements.\n this.container.querySelectorAll('.dcp-modal-body button, .dcp-modal-body input[type=\"checkbox\"]').forEach(element => {\n element.addEventListener('click', () => {\n element.blur()\n })\n })\n\n // Show the modal.\n this.container.style.display = 'block'\n\n const formElements = this.container.querySelectorAll('.dcp-modal-body select, .dcp-modal-body input')\n if (formElements.length) {\n formElements[0].focus()\n if (formElements[0].type === 'text') {\n formElements[0].select()\n }\n for (const el of formElements) {\n if (el.realType) {\n el.type = el.realType\n }\n }\n } else {\n // With no form elements to allow for form submission on enter, focus the\n // continue button.\n this.continueButton.focus()\n }\n\n async function handleContinue (event) {\n let result\n try {\n result = await this.formSubmitHandler(event)\n } catch (error) {\n reject(error)\n }\n this.close(true)\n resolve(result)\n }\n\n async function handleCancel () {\n let result\n try {\n result = await this.close()\n } catch (error) {\n reject(error)\n }\n resolve(result)\n }\n })\n }\n\n close (success = false) {\n this.container.style.display = 'none'\n if (this.container.parentNode) {\n this.container.parentNode.removeChild(this.container)\n }\n\n // @todo this needs to remove eventlisteners to prevent memory leaks\n\n if ((success !== true) && typeof this.exitHandler === 'function') {\n return this.exitHandler(this)\n }\n }\n\n /**\n * Adds different form elements to the modal depending on the case.\n *\n * @param {*} elements - The properties of the form elements to add.\n * @returns {HTMLElement} The input form elements.\n */\n addFormElement (...elements) {\n const body = this.container.querySelector('.dcp-modal-body')\n const inputElements = []\n let label\n for (let i = 0; i < elements.length; i++) {\n let row = document.createElement('div')\n row.className = 'row'\n\n let col, input\n switch (elements[i].type) {\n case 'button':\n col = document.createElement('div')\n col.className = 'col-md-12'\n\n input = document.createElement('button')\n input.innerHTML = elements[i].label\n input.type = 'button'\n input.classList.add('green-modal-button')\n if (!elements[i].onclick) {\n throw new Error('A button in the modal body should have an on click event handler.')\n }\n input.addEventListener('click', elements[i].onclick)\n\n col.appendChild(input)\n row.appendChild(col)\n break\n case 'textarea':\n col = document.createElement('div')\n col.className = 'col-md-12'\n\n input = document.createElement('textarea')\n input.className = 'text-input-field form-control'\n if (elements[i].placeholder) input.placeholder = elements[i].placeholder\n\n col.appendChild(input)\n row.appendChild(col)\n break\n case 'text':\n case 'email':\n case 'number':\n case 'password': {\n const inputCol = document.createElement('div')\n\n input = document.createElement('input')\n input.type = elements[i].type\n input.validation = elements[i].validation\n input.autocomplete = elements[i].autocomplete || (elements[i].type === 'password' ? 'off' : 'on')\n input.className = 'text-input-field form-control'\n\n // Adding bootstraps custom feedback styles.\n let invalidFeedback = null\n if (elements[i].invalidFeedback) {\n invalidFeedback = document.createElement('div')\n invalidFeedback.className = 'invalid-feedback'\n invalidFeedback.innerText = elements[i].invalidFeedback\n }\n\n if (elements[i].type === 'password') {\n elements[i].realType = 'password'\n }\n\n if (elements[i].label) {\n const labelCol = document.createElement('div')\n label = document.createElement('label')\n label.innerText = elements[i].label\n const inputId = 'dcp-modal-input-' + this.container.querySelectorAll('input[type=\"text\"], input[type=\"email\"], input[type=\"number\"], input[type=\"password\"]').length\n label.setAttribute('for', inputId)\n input.id = inputId\n labelCol.classList.add('col-md-6', 'label-column')\n labelCol.appendChild(label)\n row.appendChild(labelCol)\n inputCol.className = 'col-md-6'\n } else {\n inputCol.className = 'col-md-12'\n }\n\n inputCol.appendChild(input)\n if (invalidFeedback !== null) {\n inputCol.appendChild(invalidFeedback)\n }\n row.appendChild(inputCol)\n break\n }\n case 'select':\n col = document.createElement('div')\n col.className = 'col-md-4'\n\n label = document.createElement('span')\n label.innerText = elements[i].label\n\n col.appendChild(label)\n row.appendChild(col)\n\n col = document.createElement('div')\n col.className = 'col-md-8'\n\n input = document.createElement('select')\n\n col.appendChild(input)\n row.appendChild(col)\n break\n case 'checkbox': {\n row.classList.add('checkbox-row')\n const checkboxLabelCol = document.createElement('div')\n checkboxLabelCol.classList.add('label-column', 'checkbox-label-column')\n\n label = document.createElement('label')\n label.innerText = elements[i].label\n label.for = 'dcp-checkbox-input-' + this.container.querySelectorAll('input[type=\"checkbox\"]').length\n label.setAttribute('for', label.for)\n label.className = 'checkbox-label'\n\n checkboxLabelCol.appendChild(label)\n\n const checkboxCol = document.createElement('div')\n checkboxCol.classList.add('checkbox-column')\n\n input = document.createElement('input')\n input.type = 'checkbox'\n input.id = label.for\n if (elements[i].checked) {\n input.checked = true\n }\n\n checkboxCol.appendChild(input)\n\n if (elements[i].labelToTheRightOfCheckbox) {\n checkboxCol.classList.add('col-md-5')\n row.appendChild(checkboxCol)\n checkboxLabelCol.classList.add('col-md-7')\n row.appendChild(checkboxLabelCol)\n } else {\n checkboxLabelCol.classList.add('col-md-6')\n checkboxCol.classList.add('col-md-6')\n row.appendChild(checkboxLabelCol)\n row.appendChild(checkboxCol)\n }\n break\n }\n case 'file':\n [input, row] = this.addFileInput(elements[i], input, row)\n break\n case 'label':\n row.classList.add('label-row')\n label = document.createElement('label')\n label.innerText = elements[i].label\n row.appendChild(label)\n break\n }\n\n // Copy other possibly specified element properties:\n const inputPropertyNames = ['title', 'inputmode', 'value', 'minLength', 'maxLength', 'size', 'required', 'pattern', 'min', 'max', 'step', 'placeholder', 'accept', 'multiple', 'id', 'onkeypress', 'oninput', 'for', 'readonly', 'autocomplete']\n for (const propertyName of inputPropertyNames) {\n if (Object.prototype.hasOwnProperty.call(elements[i], propertyName)) {\n if (propertyName === 'for' && !label.hasAttribute(propertyName)) {\n label.setAttribute(propertyName, elements[i][propertyName])\n }\n if (propertyName.startsWith('on')) {\n input.addEventListener(propertyName.slice(2), elements[i][propertyName])\n } else {\n input.setAttribute(propertyName, elements[i][propertyName])\n }\n }\n }\n\n inputElements.push(input)\n body.appendChild(row)\n }\n\n if (inputElements.length === 1) return inputElements[0]\n else return inputElements\n }\n\n /**\n * Adds a drag and drop file form element to the modal.\n *\n * @param {*} fileInputProperties - An object specifying some of the\n * properties of the file input element.\n * @param {*} fileInput - Placeholders to help create the file\n * input.\n * @param {HTMLDivElement} row - Placeholders to help create the file\n * input.\n */\n addFileInput (fileInputProperties, fileInput, row) {\n // Adding the upload label.\n const uploadLabel = document.createElement('label')\n uploadLabel.innerText = fileInputProperties.label\n row.appendChild(uploadLabel)\n const body = this.container.querySelector('.dcp-modal-body')\n body.appendChild(row)\n const fileSelectionRow = document.createElement('div')\n fileSelectionRow.id = 'file-selection-row'\n\n // Adding the drag and drop file upload input.\n const dropContainer = document.createElement('div')\n dropContainer.id = 'drop-container'\n\n // Adding an image of a wallet\n const imageContainer = document.createElement('div')\n imageContainer.id = 'image-container'\n const walletImage = document.createElement('span')\n walletImage.classList.add('fas', 'fa-wallet')\n imageContainer.appendChild(walletImage)\n\n // Adding some text prompts\n const dropMessage = document.createElement('span')\n dropMessage.innerText = 'Drop a keystore file here'\n const orMessage = document.createElement('span')\n orMessage.innerText = 'or'\n\n // Adding the manual file input element (hiding the default one)\n const fileInputContainer = document.createElement('div')\n const fileInputLabel = document.createElement('label')\n // Linking the label to the file input so that clicking on the label\n // activates the file input.\n fileInputLabel.setAttribute('for', 'file-input')\n fileInputLabel.innerText = 'Browse'\n fileInput = document.createElement('input')\n fileInput.type = fileInputProperties.type\n fileInput.id = 'file-input'\n // To remove the lingering outline after selecting the file.\n fileInput.addEventListener('click', () => {\n fileInput.blur()\n })\n fileInputContainer.append(fileInput, fileInputLabel)\n\n // Creating the final row element to append to the modal body.\n dropContainer.append(imageContainer, dropMessage, orMessage, fileInputContainer)\n fileSelectionRow.appendChild(dropContainer)\n\n // Adding functionality to the drag and drop file input.\n dropContainer.addEventListener('drop', selectDroppedFile.bind(this))\n dropContainer.addEventListener('drop', unhighlightDropArea)\n // Prevent file from being opened by the browser.\n dropContainer.ondragover = highlightDropArea\n dropContainer.ondragenter = highlightDropArea\n dropContainer.ondragleave = unhighlightDropArea\n\n fileInput.addEventListener('change', handleFileChange)\n\n const fileNamePlaceholder = document.createElement('center')\n fileNamePlaceholder.id = 'file-name-placeholder'\n fileNamePlaceholder.className = 'row'\n fileNamePlaceholder.innerText = ''\n fileSelectionRow.appendChild(fileNamePlaceholder)\n fileNamePlaceholder.classList.add('hidden')\n\n // Check if the continue button is invalid on the keystore upload modal and\n // click it if it should no longer be invalid.\n this.continueButton.addEventListener('invalid', () => {\n const fileFormElements = this.container.querySelectorAll('.dcp-modal-body input[type=\"file\"], .dcp-modal-body input[type=\"text\"]')\n const filledInFileFormElements = Array.from(fileFormElements).filter(fileFormElement => fileFormElement.value !== '')\n if (fileFormElements.length !== 0 && filledInFileFormElements.length !== 0) {\n this.continueButton.setCustomValidity('')\n // Clicking instead of dispatching a submit event to ensure other form validation is used before submitting the form.\n this.continueButton.click()\n }\n })\n\n return [fileInput, fileSelectionRow]\n\n /**\n * Checks that the dropped items contain only a single keystore file.\n * If valid, sets the file input's value to the dropped file.\n * @param {DragEvent} event - Contains the files dropped.\n */\n function selectDroppedFile (event) {\n // Prevent file from being opened.\n event.preventDefault()\n\n // Check if only one file was dropped.\n const wasOneFileDropped = event.dataTransfer.items.length === 1 ||\n event.dataTransfer.files.length === 1\n updateFileSelectionStatus(wasOneFileDropped)\n if (!wasOneFileDropped) {\n fileInput.setCustomValidity('Only one file can be uploaded.')\n fileInput.reportValidity()\n return\n } else {\n fileInput.setCustomValidity('')\n }\n\n // Now to use the DataTransfer interface to access the file(s), setting\n // the value of the file input.\n const file = event.dataTransfer.files[0]\n\n if (checkFileExtension(file)) {\n fileInput.files = event.dataTransfer.files\n fileInput.dispatchEvent(new Event('change'))\n }\n }\n\n function handleFileChange () {\n if (checkFileExtension(this.files[0]) && this.files.length === 1) {\n fileNamePlaceholder.innerText = `Selected File: ${this.files[0].name}`\n updateFileSelectionStatus(true)\n // Invoke a callback if additional functionality is required.\n if (typeof fileInputProperties.callback === 'function') {\n fileInputProperties.callback(this.files[0])\n }\n }\n }\n\n /**\n * Checks if the file extension on the inputted file is correct.\n * @param {File} file - The file to check\n * @returns {boolean} True if the file extension is valid, false otherwise.\n */\n function checkFileExtension (file) {\n // If there's no restriction, return true.\n if (!fileInputProperties.extension) {\n return true\n }\n const fileExtension = file.name.split('.').pop()\n const isValidExtension = fileExtension === fileInputProperties.extension\n updateFileSelectionStatus(isValidExtension)\n if (!isValidExtension) {\n fileInput.setCustomValidity(`Only a .${fileInputProperties.extension} file can be uploaded.`)\n fileInput.reportValidity()\n fileNamePlaceholder.classList.add('hidden')\n } else {\n fileInput.setCustomValidity('')\n }\n return isValidExtension\n }\n\n /**\n * Updates the file input to reflect the validity of the current file\n * selection.\n * @param {boolean} isValidFileSelection - True if a single .keystore file\n * was selected. False otherwise.\n */\n function updateFileSelectionStatus (isValidFileSelection) {\n imageContainer.innerHTML = ''\n const statusImage = document.createElement('span')\n statusImage.classList.add('fas', isValidFileSelection ? 'fa-check' : 'fa-times')\n statusImage.style.color = isValidFileSelection ? 'green' : 'red'\n imageContainer.appendChild(statusImage)\n\n if (!isValidFileSelection) {\n fileInput.value = null\n fileNamePlaceholder.classList.add('hidden')\n } else {\n fileNamePlaceholder.classList.remove('hidden')\n }\n\n // If the modal contains a password field for a keystore file, change its\n // visibility.\n const walletPasswordInputContainer = document.querySelector('.dcp-modal-body input[type=\"password\"]').parentElement.parentElement\n if (walletPasswordInputContainer) {\n if (isValidFileSelection) {\n walletPasswordInputContainer.classList.remove('hidden')\n const walletPasswordInput = document.querySelector('.dcp-modal-body input[type=\"password\"]')\n walletPasswordInput.focus()\n } else {\n walletPasswordInputContainer.classList.add('hidden')\n }\n }\n }\n\n function highlightDropArea (event) {\n event.preventDefault()\n this.classList.add('highlight')\n }\n\n function unhighlightDropArea (event) {\n event.preventDefault()\n this.classList.remove('highlight')\n }\n }\n\n /**\n * Sets up a custom tooltip to pop up when the passwords do not match, but are\n * valid otherwise.\n */\n addFormValidationForPasswordConfirmation () {\n const [newPassword, confirmPassword] = document.querySelectorAll('.dcp-modal-body input[type=\"password\"]')\n if (!newPassword || !confirmPassword) {\n throw Error('New Password field and Confirm Password fields not present.')\n }\n\n newPassword.addEventListener('input', checkMatchingPasswords)\n confirmPassword.addEventListener('input', checkMatchingPasswords)\n\n function checkMatchingPasswords () {\n if (newPassword.value !== confirmPassword.value &&\n newPassword.validity.valid &&\n confirmPassword.validity.valid) {\n newPassword.setCustomValidity('Both passwords must match.')\n } else if (newPassword.value === confirmPassword.value ||\n newPassword.validity.tooShort ||\n newPassword.validity.patternMismatch ||\n newPassword.validity.valueMissing ||\n confirmPassword.validity.tooShort ||\n confirmPassword.validity.patternMismatch ||\n confirmPassword.validity.valueMissing) {\n // If the passwords fields match or have become invalidated some other\n // way again, reset the custom message.\n newPassword.setCustomValidity('')\n }\n }\n }\n\n updateInvalidEmailMessage() {\n const email = document.querySelector('.dcp-modal-body input[id=\"email\"')\n if (!email){\n throw Error(\"Email field not present\")\n }\n email.addEventListener('input', checkValidEmail);\n function checkValidEmail() {\n if (!email.validity.patternMismatch &&\n !email.validity.valueMissing) {\n email.setCustomValidity('')\n } else {\n email.setCustomValidity(\"Enter a valid email address.\")\n }\n\n }\n }\n\n /**\n * Adds message(s) to the modal's body.\n * @param {string} messages - The message(s) to add to the modal's body.\n * @returns Paragraph element(s) containing the message(s) added to the\n * modal's body.\n */\n addMessage (...messages) {\n const elements = []\n const body = this.container.querySelector('.dcp-modal-body')\n for (let i = 0; i < messages.length; i++) {\n const row = document.createElement('div')\n row.className = 'row'\n\n const paragraph = document.createElement('p')\n paragraph.innerHTML = messages[i]\n paragraph.classList.add('message')\n row.appendChild(paragraph)\n body.appendChild(row)\n\n elements.push(paragraph)\n }\n\n if (elements.length === 1) return elements[0]\n else return elements\n }\n\n addHorizontalRule () {\n const body = this.container.querySelector('.dcp-modal-body')\n body.appendChild(document.createElement('hr'))\n }\n\n // Does what it says. Still ill advised to use unless you have to.\n addCustomHTML (htmlStr, browseCallback) {\n const elements = []\n const body = this.container.querySelector('.dcp-modal-body')\n body.innerHTML += htmlStr\n body.querySelector('#browse-button').addEventListener('click', browseCallback.bind(this, this))\n\n if (elements.length === 1) return elements[0]\n else return elements\n }\n\n addButton (...buttons) {\n const elements = []\n const body = this.container.querySelector('.dcp-modal-body')\n for (let i = 0; i < buttons.length; i++) {\n const row = document.createElement('div')\n row.className = 'row'\n\n let col = document.createElement('div')\n col.className = 'col-md-4'\n\n const description = document.createElement('span')\n description.innerText = buttons[i].description\n\n col.appendChild(description)\n row.appendChild(col)\n\n col = document.createElement('div')\n col.className = 'col-md-8'\n\n const button = document.createElement('button')\n button.innerText = buttons[i].label\n button.addEventListener('click', buttons[i].callback.bind(this, this))\n\n elements.push(button)\n\n col.appendChild(button)\n row.appendChild(col)\n\n body.appendChild(row)\n }\n\n if (elements.length === 1) return elements[0]\n else return elements\n }\n}\n\n\n// Inject our special stylesheet from dcp-client only if we're on the portal webpage.\nif (typeof window !== 'undefined' && typeof document !== 'undefined' && dcpConfig.portal.location.hostname === window.location.hostname) {\n // <link rel='stylesheet' href='/css/dashboard.css'>\n const stylesheet = document.createElement('link')\n stylesheet.rel = 'stylesheet'\n // Needed for the duplicate check done later.\n stylesheet.id = 'dcp-modal-styles'\n\n const dcpClientBundle = document.getElementById('_dcp_client_bundle')\n let src\n if (dcpClientBundle) {\n src = dcpClientBundle.src.replace('dcp-client-bundle.js', 'dcp-modal-style.css')\n } else {\n src = dcpConfig.portal.location.href + 'dcp-client/dist/dcp-modal-style.css'\n }\n\n stylesheet.href = src\n // If the style was injected before, don't inject it again.\n // Could occur when loading a file that imports Modal.js and loading\n // comput.min.js in the same HTML file.\n if (document.getElementById(stylesheet.id) === null) {\n document.getElementsByTagName('head')[0].appendChild(stylesheet)\n }\n\n if (typeof {\"version\":\"bcdd0728ce28e9f58c7093651f0113bf0221c93a\",\"branch\":\"release\",\"dcpClient\":{\"version\":\"4.2.18\",\"from\":\"git+ssh://git@gitlab.com/Distributed-Compute-Protocol/dcp-client.git#prod-20221018\",\"resolved\":\"git+ssh://git@gitlab.com/Distributed-Compute-Protocol/dcp-client.git#c5ea513e7e6bc0294075a59ae63c78815c7a73ee\"},\"built\":\"Thu Oct 20 2022 16:34:01 GMT-0400 (Eastern Daylight Saving Time)\",\"config\":{\"generated\":\"Thu 20 Oct 2022 04:34:00 PM EDT by erose on lorge\",\"build\":\"debug\"},\"webpack\":\"5.74.0\",\"node\":\"v14.20.1\"} !== 'undefined' && typeof window.Modal === 'undefined') {\n window.Modal = Modal\n }\n}\n\n\n//# sourceURL=webpack://dcp/./portal/www/js/modal.js?");
|
|
3797
|
+
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (/* binding */ Modal)\n/* harmony export */ });\n/**\n * A Small Modal Class\n * @module Modal\n */\n/* globals Event dcpConfig */\nclass Modal {\n constructor (title, message, callback = false, exitHandler = false, {\n continueLabel = 'Continue',\n cancelLabel = 'Cancel',\n cancelVisible = true\n } = {}) {\n const modal = document.createElement('div')\n modal.className = 'dcp-modal-container-old day'\n modal.innerHTML = `\n <dialog class=\"dcp-modal-content\">\n <div class=\"dcp-modal-header\">\n <h2>${title}<button type=\"button\" class=\"close\">×</button></h2>\n ${message ? '<p>' + message + '</p>' : ''}\n </div>\n <div class=\"dcp-modal-loading hidden\">\n <div class='loading'></div>\n </div>\n <form onsubmit='return false' method=\"dialog\">\n <div class=\"dcp-modal-body\"></div>\n <div class=\"dcp-modal-footer ${cancelVisible ? '' : 'centered'}\">\n <button type=\"submit\" class=\"continue green-modal-button\">${continueLabel}</button>\n <button type=\"button\" class=\"cancel green-modal-button\">${cancelLabel}</button>\n </div>\n </form>\n </dialog>`\n\n // To give a reference to do developer who wants to override the form submit.\n // May occur if they want to validate the information in the backend\n // without closing the modal prematurely.\n this.form = modal.querySelector('.dcp-modal-content form')\n this.continueButton = modal.querySelector('.dcp-modal-footer button.continue')\n this.cancelButton = modal.querySelector('.dcp-modal-footer button.cancel')\n this.closeButton = modal.querySelector('.dcp-modal-header .close')\n if (!cancelVisible) {\n this.cancelButton.style.display = 'none'\n }\n\n // To remove the event listener, the reference to the original function\n // added is required.\n this.formSubmitHandler = this.continue.bind(this)\n\n modal.addEventListener('keydown', function (event) {\n event.stopPropagation()\n // 27 is the keycode for the escape key.\n if (event.keyCode === 27) this.close()\n }.bind(this))\n\n this.container = modal\n this.callback = callback\n this.exitHandler = exitHandler\n document.body.appendChild(modal)\n }\n\n changeFormSubmitHandler (newFormSubmitHandler) {\n this.formSubmitHandler = newFormSubmitHandler\n }\n\n /**\n * Validates the form values in the modal and calls the modal's callback\n */\n async continue (event) {\n // To further prevent form submission from trying to redirect from the\n // current page.\n if (event instanceof Event) {\n event.preventDefault()\n }\n let fieldsAreValid = true\n let formElements = this.container.querySelectorAll('.dcp-modal-body select, .dcp-modal-body input, .dcp-modal-body textarea')\n\n const formValues = []\n if (typeof formElements.length === 'undefined') formElements = [formElements]\n // Separate into two loops to enable input validation requiring formValues\n // that come after it. e.g. Two password fields matching.\n for (let i = 0; i < formElements.length; i++) {\n switch (formElements[i].type) {\n case 'file':\n formValues.push(formElements[i])\n break\n case 'checkbox':\n formValues.push(formElements[i].checked)\n break\n default:\n formValues.push(formElements[i].value)\n break\n }\n }\n for (let i = 0; i < formElements.length; i++) {\n if (formElements[i].validation) {\n // Optional fields are allowed to be empty but still can't be wrong if not empty.\n if (!(formElements[i].value === '' && !formElements[i].required)) {\n if (typeof formElements[i].validation === 'function') {\n if (!formElements[i].validation(formValues)) {\n fieldsAreValid = false\n formElements[i].classList.add('is-invalid')\n }\n } else if (!formElements[i].validation.test(formElements[i].value)) {\n fieldsAreValid = false\n formElements[i].classList.add('is-invalid')\n }\n }\n }\n }\n\n if (!fieldsAreValid) return\n\n this.loading()\n if (typeof this.callback === 'function') {\n try {\n return this.callback(formValues)\n } catch (error) {\n console.error('Unexpected error in modal.continue:', error);\n return this.close(false)\n }\n }\n this.close(true)\n }\n\n loading () {\n this.container.querySelector('.dcp-modal-loading').classList.remove('hidden')\n this.container.querySelector('.dcp-modal-body').classList.add('hidden')\n this.container.querySelector('.dcp-modal-footer').classList.add('hidden')\n }\n\n open () {\n this.form.addEventListener('submit', async (event) => {\n const success = await this.formSubmitHandler(event)\n if (success === false) {\n return\n }\n this.close(true)\n })\n // When the user clicks on <span> (x), close the modal\n this.closeButton.addEventListener('click', this.close.bind(this))\n this.cancelButton.addEventListener('click', this.close.bind(this))\n\n // Prevent lingering outlines after clicking some form elements.\n this.container.querySelectorAll('.dcp-modal-body button, .dcp-modal-body input[type=\"checkbox\"]').forEach(element => {\n element.addEventListener('click', () => {\n element.blur()\n })\n })\n\n // Show the modal.\n this.container.style.display = 'block'\n\n const formElements = this.container.querySelectorAll('.dcp-modal-body select, .dcp-modal-body input')\n if (formElements.length) {\n formElements[0].focus()\n if (formElements[0].type === 'text') {\n formElements[0].select()\n }\n for (const el of formElements) {\n if (el.realType) {\n el.type = el.realType\n }\n }\n } else {\n // With no form elements to allow for form submission on enter, focus the\n // continue button.\n this.container.querySelector('.dcp-modal-footer button.continue').focus()\n }\n } // TODO: This should return a promise with the action resolving it\n\n /**\n * Shows the modal and returns a promise of the result of the modal (e.g. was\n * it closed, did its action succeed?)\n */\n showModal () {\n return new Promise((resolve, reject) => {\n this.form.addEventListener('submit', handleContinue.bind(this))\n this.cancelButton.addEventListener('click', handleCancel.bind(this))\n this.closeButton.addEventListener('click', handleCancel.bind(this))\n\n // Prevent lingering outlines after clicking some form elements.\n this.container.querySelectorAll('.dcp-modal-body button, .dcp-modal-body input[type=\"checkbox\"]').forEach(element => {\n element.addEventListener('click', () => {\n element.blur()\n })\n })\n\n // Show the modal.\n this.container.style.display = 'block'\n\n const formElements = this.container.querySelectorAll('.dcp-modal-body select, .dcp-modal-body input')\n if (formElements.length) {\n formElements[0].focus()\n if (formElements[0].type === 'text') {\n formElements[0].select()\n }\n for (const el of formElements) {\n if (el.realType) {\n el.type = el.realType\n }\n }\n } else {\n // With no form elements to allow for form submission on enter, focus the\n // continue button.\n this.continueButton.focus()\n }\n\n async function handleContinue (event) {\n let result\n try {\n result = await this.formSubmitHandler(event)\n } catch (error) {\n reject(error)\n }\n this.close(true)\n resolve(result)\n }\n\n async function handleCancel () {\n let result\n try {\n result = await this.close()\n } catch (error) {\n reject(error)\n }\n resolve(result)\n }\n })\n }\n\n close (success = false) {\n this.container.style.display = 'none'\n if (this.container.parentNode) {\n this.container.parentNode.removeChild(this.container)\n }\n\n // @todo this needs to remove eventlisteners to prevent memory leaks\n\n if ((success !== true) && typeof this.exitHandler === 'function') {\n return this.exitHandler(this)\n }\n }\n\n /**\n * Adds different form elements to the modal depending on the case.\n *\n * @param {*} elements - The properties of the form elements to add.\n * @returns {HTMLElement} The input form elements.\n */\n addFormElement (...elements) {\n const body = this.container.querySelector('.dcp-modal-body')\n const inputElements = []\n let label\n for (let i = 0; i < elements.length; i++) {\n let row = document.createElement('div')\n row.className = 'row'\n\n let col, input\n switch (elements[i].type) {\n case 'button':\n col = document.createElement('div')\n col.className = 'col-md-12'\n\n input = document.createElement('button')\n input.innerHTML = elements[i].label\n input.type = 'button'\n input.classList.add('green-modal-button')\n if (!elements[i].onclick) {\n throw new Error('A button in the modal body should have an on click event handler.')\n }\n input.addEventListener('click', elements[i].onclick)\n\n col.appendChild(input)\n row.appendChild(col)\n break\n case 'textarea':\n col = document.createElement('div')\n col.className = 'col-md-12'\n\n input = document.createElement('textarea')\n input.className = 'text-input-field form-control'\n if (elements[i].placeholder) input.placeholder = elements[i].placeholder\n\n col.appendChild(input)\n row.appendChild(col)\n break\n case 'text':\n case 'email':\n case 'number':\n case 'password': {\n const inputCol = document.createElement('div')\n\n input = document.createElement('input')\n input.type = elements[i].type\n input.validation = elements[i].validation\n input.autocomplete = elements[i].autocomplete || (elements[i].type === 'password' ? 'off' : 'on')\n input.className = 'text-input-field form-control'\n\n // Adding bootstraps custom feedback styles.\n let invalidFeedback = null\n if (elements[i].invalidFeedback) {\n invalidFeedback = document.createElement('div')\n invalidFeedback.className = 'invalid-feedback'\n invalidFeedback.innerText = elements[i].invalidFeedback\n }\n\n if (elements[i].type === 'password') {\n elements[i].realType = 'password'\n }\n\n if (elements[i].label) {\n const labelCol = document.createElement('div')\n label = document.createElement('label')\n label.innerText = elements[i].label\n const inputId = 'dcp-modal-input-' + this.container.querySelectorAll('input[type=\"text\"], input[type=\"email\"], input[type=\"number\"], input[type=\"password\"]').length\n label.setAttribute('for', inputId)\n input.id = inputId\n labelCol.classList.add('col-md-6', 'label-column')\n labelCol.appendChild(label)\n row.appendChild(labelCol)\n inputCol.className = 'col-md-6'\n } else {\n inputCol.className = 'col-md-12'\n }\n\n inputCol.appendChild(input)\n if (invalidFeedback !== null) {\n inputCol.appendChild(invalidFeedback)\n }\n row.appendChild(inputCol)\n break\n }\n case 'select':\n col = document.createElement('div')\n col.className = 'col-md-4'\n\n label = document.createElement('span')\n label.innerText = elements[i].label\n\n col.appendChild(label)\n row.appendChild(col)\n\n col = document.createElement('div')\n col.className = 'col-md-8'\n\n input = document.createElement('select')\n\n col.appendChild(input)\n row.appendChild(col)\n break\n case 'checkbox': {\n row.classList.add('checkbox-row')\n const checkboxLabelCol = document.createElement('div')\n checkboxLabelCol.classList.add('label-column', 'checkbox-label-column')\n\n label = document.createElement('label')\n label.innerText = elements[i].label\n label.for = 'dcp-checkbox-input-' + this.container.querySelectorAll('input[type=\"checkbox\"]').length\n label.setAttribute('for', label.for)\n label.className = 'checkbox-label'\n\n checkboxLabelCol.appendChild(label)\n\n const checkboxCol = document.createElement('div')\n checkboxCol.classList.add('checkbox-column')\n\n input = document.createElement('input')\n input.type = 'checkbox'\n input.id = label.for\n if (elements[i].checked) {\n input.checked = true\n }\n\n checkboxCol.appendChild(input)\n\n if (elements[i].labelToTheRightOfCheckbox) {\n checkboxCol.classList.add('col-md-5')\n row.appendChild(checkboxCol)\n checkboxLabelCol.classList.add('col-md-7')\n row.appendChild(checkboxLabelCol)\n } else {\n checkboxLabelCol.classList.add('col-md-6')\n checkboxCol.classList.add('col-md-6')\n row.appendChild(checkboxLabelCol)\n row.appendChild(checkboxCol)\n }\n break\n }\n case 'file':\n [input, row] = this.addFileInput(elements[i], input, row)\n break\n case 'label':\n row.classList.add('label-row')\n label = document.createElement('label')\n label.innerText = elements[i].label\n row.appendChild(label)\n break\n }\n\n // Copy other possibly specified element properties:\n const inputPropertyNames = ['title', 'inputmode', 'value', 'minLength', 'maxLength', 'size', 'required', 'pattern', 'min', 'max', 'step', 'placeholder', 'accept', 'multiple', 'id', 'onkeypress', 'oninput', 'for', 'readonly', 'autocomplete']\n for (const propertyName of inputPropertyNames) {\n if (Object.prototype.hasOwnProperty.call(elements[i], propertyName)) {\n if (propertyName === 'for' && !label.hasAttribute(propertyName)) {\n label.setAttribute(propertyName, elements[i][propertyName])\n }\n if (propertyName.startsWith('on')) {\n input.addEventListener(propertyName.slice(2), elements[i][propertyName])\n } else {\n input.setAttribute(propertyName, elements[i][propertyName])\n }\n }\n }\n\n inputElements.push(input)\n body.appendChild(row)\n }\n\n if (inputElements.length === 1) return inputElements[0]\n else return inputElements\n }\n\n /**\n * Adds a drag and drop file form element to the modal.\n *\n * @param {*} fileInputProperties - An object specifying some of the\n * properties of the file input element.\n * @param {*} fileInput - Placeholders to help create the file\n * input.\n * @param {HTMLDivElement} row - Placeholders to help create the file\n * input.\n */\n addFileInput (fileInputProperties, fileInput, row) {\n // Adding the upload label.\n const uploadLabel = document.createElement('label')\n uploadLabel.innerText = fileInputProperties.label\n row.appendChild(uploadLabel)\n const body = this.container.querySelector('.dcp-modal-body')\n body.appendChild(row)\n const fileSelectionRow = document.createElement('div')\n fileSelectionRow.id = 'file-selection-row'\n\n // Adding the drag and drop file upload input.\n const dropContainer = document.createElement('div')\n dropContainer.id = 'drop-container'\n\n // Adding an image of a wallet\n const imageContainer = document.createElement('div')\n imageContainer.id = 'image-container'\n const walletImage = document.createElement('span')\n walletImage.classList.add('fas', 'fa-wallet')\n imageContainer.appendChild(walletImage)\n\n // Adding some text prompts\n const dropMessage = document.createElement('span')\n dropMessage.innerText = 'Drop a keystore file here'\n const orMessage = document.createElement('span')\n orMessage.innerText = 'or'\n\n // Adding the manual file input element (hiding the default one)\n const fileInputContainer = document.createElement('div')\n const fileInputLabel = document.createElement('label')\n // Linking the label to the file input so that clicking on the label\n // activates the file input.\n fileInputLabel.setAttribute('for', 'file-input')\n fileInputLabel.innerText = 'Browse'\n fileInput = document.createElement('input')\n fileInput.type = fileInputProperties.type\n fileInput.id = 'file-input'\n // To remove the lingering outline after selecting the file.\n fileInput.addEventListener('click', () => {\n fileInput.blur()\n })\n fileInputContainer.append(fileInput, fileInputLabel)\n\n // Creating the final row element to append to the modal body.\n dropContainer.append(imageContainer, dropMessage, orMessage, fileInputContainer)\n fileSelectionRow.appendChild(dropContainer)\n\n // Adding functionality to the drag and drop file input.\n dropContainer.addEventListener('drop', selectDroppedFile.bind(this))\n dropContainer.addEventListener('drop', unhighlightDropArea)\n // Prevent file from being opened by the browser.\n dropContainer.ondragover = highlightDropArea\n dropContainer.ondragenter = highlightDropArea\n dropContainer.ondragleave = unhighlightDropArea\n\n fileInput.addEventListener('change', handleFileChange)\n\n const fileNamePlaceholder = document.createElement('center')\n fileNamePlaceholder.id = 'file-name-placeholder'\n fileNamePlaceholder.className = 'row'\n fileNamePlaceholder.innerText = ''\n fileSelectionRow.appendChild(fileNamePlaceholder)\n fileNamePlaceholder.classList.add('hidden')\n\n // Check if the continue button is invalid on the keystore upload modal and\n // click it if it should no longer be invalid.\n this.continueButton.addEventListener('invalid', () => {\n const fileFormElements = this.container.querySelectorAll('.dcp-modal-body input[type=\"file\"], .dcp-modal-body input[type=\"text\"]')\n const filledInFileFormElements = Array.from(fileFormElements).filter(fileFormElement => fileFormElement.value !== '')\n if (fileFormElements.length !== 0 && filledInFileFormElements.length !== 0) {\n this.continueButton.setCustomValidity('')\n // Clicking instead of dispatching a submit event to ensure other form validation is used before submitting the form.\n this.continueButton.click()\n }\n })\n\n return [fileInput, fileSelectionRow]\n\n /**\n * Checks that the dropped items contain only a single keystore file.\n * If valid, sets the file input's value to the dropped file.\n * @param {DragEvent} event - Contains the files dropped.\n */\n function selectDroppedFile (event) {\n // Prevent file from being opened.\n event.preventDefault()\n\n // Check if only one file was dropped.\n const wasOneFileDropped = event.dataTransfer.items.length === 1 ||\n event.dataTransfer.files.length === 1\n updateFileSelectionStatus(wasOneFileDropped)\n if (!wasOneFileDropped) {\n fileInput.setCustomValidity('Only one file can be uploaded.')\n fileInput.reportValidity()\n return\n } else {\n fileInput.setCustomValidity('')\n }\n\n // Now to use the DataTransfer interface to access the file(s), setting\n // the value of the file input.\n const file = event.dataTransfer.files[0]\n\n if (checkFileExtension(file)) {\n fileInput.files = event.dataTransfer.files\n fileInput.dispatchEvent(new Event('change'))\n }\n }\n\n function handleFileChange () {\n if (checkFileExtension(this.files[0]) && this.files.length === 1) {\n fileNamePlaceholder.innerText = `Selected File: ${this.files[0].name}`\n updateFileSelectionStatus(true)\n // Invoke a callback if additional functionality is required.\n if (typeof fileInputProperties.callback === 'function') {\n fileInputProperties.callback(this.files[0])\n }\n }\n }\n\n /**\n * Checks if the file extension on the inputted file is correct.\n * @param {File} file - The file to check\n * @returns {boolean} True if the file extension is valid, false otherwise.\n */\n function checkFileExtension (file) {\n // If there's no restriction, return true.\n if (!fileInputProperties.extension) {\n return true\n }\n const fileExtension = file.name.split('.').pop()\n const isValidExtension = fileExtension === fileInputProperties.extension\n updateFileSelectionStatus(isValidExtension)\n if (!isValidExtension) {\n fileInput.setCustomValidity(`Only a .${fileInputProperties.extension} file can be uploaded.`)\n fileInput.reportValidity()\n fileNamePlaceholder.classList.add('hidden')\n } else {\n fileInput.setCustomValidity('')\n }\n return isValidExtension\n }\n\n /**\n * Updates the file input to reflect the validity of the current file\n * selection.\n * @param {boolean} isValidFileSelection - True if a single .keystore file\n * was selected. False otherwise.\n */\n function updateFileSelectionStatus (isValidFileSelection) {\n imageContainer.innerHTML = ''\n const statusImage = document.createElement('span')\n statusImage.classList.add('fas', isValidFileSelection ? 'fa-check' : 'fa-times')\n statusImage.style.color = isValidFileSelection ? 'green' : 'red'\n imageContainer.appendChild(statusImage)\n\n if (!isValidFileSelection) {\n fileInput.value = null\n fileNamePlaceholder.classList.add('hidden')\n } else {\n fileNamePlaceholder.classList.remove('hidden')\n }\n\n // If the modal contains a password field for a keystore file, change its\n // visibility.\n const walletPasswordInputContainer = document.querySelector('.dcp-modal-body input[type=\"password\"]').parentElement.parentElement\n if (walletPasswordInputContainer) {\n if (isValidFileSelection) {\n walletPasswordInputContainer.classList.remove('hidden')\n const walletPasswordInput = document.querySelector('.dcp-modal-body input[type=\"password\"]')\n walletPasswordInput.focus()\n } else {\n walletPasswordInputContainer.classList.add('hidden')\n }\n }\n }\n\n function highlightDropArea (event) {\n event.preventDefault()\n this.classList.add('highlight')\n }\n\n function unhighlightDropArea (event) {\n event.preventDefault()\n this.classList.remove('highlight')\n }\n }\n\n /**\n * Sets up a custom tooltip to pop up when the passwords do not match, but are\n * valid otherwise.\n */\n addFormValidationForPasswordConfirmation () {\n const [newPassword, confirmPassword] = document.querySelectorAll('.dcp-modal-body input[type=\"password\"]')\n if (!newPassword || !confirmPassword) {\n throw Error('New Password field and Confirm Password fields not present.')\n }\n\n newPassword.addEventListener('input', checkMatchingPasswords)\n confirmPassword.addEventListener('input', checkMatchingPasswords)\n\n function checkMatchingPasswords () {\n if (newPassword.value !== confirmPassword.value &&\n newPassword.validity.valid &&\n confirmPassword.validity.valid) {\n newPassword.setCustomValidity('Both passwords must match.')\n } else if (newPassword.value === confirmPassword.value ||\n newPassword.validity.tooShort ||\n newPassword.validity.patternMismatch ||\n newPassword.validity.valueMissing ||\n confirmPassword.validity.tooShort ||\n confirmPassword.validity.patternMismatch ||\n confirmPassword.validity.valueMissing) {\n // If the passwords fields match or have become invalidated some other\n // way again, reset the custom message.\n newPassword.setCustomValidity('')\n }\n }\n }\n\n updateInvalidEmailMessage() {\n const email = document.querySelector('.dcp-modal-body input[id=\"email\"')\n if (!email){\n throw Error(\"Email field not present\")\n }\n email.addEventListener('input', checkValidEmail);\n function checkValidEmail() {\n if (!email.validity.patternMismatch &&\n !email.validity.valueMissing) {\n email.setCustomValidity('')\n } else {\n email.setCustomValidity(\"Enter a valid email address.\")\n }\n\n }\n }\n\n /**\n * Adds message(s) to the modal's body.\n * @param {string} messages - The message(s) to add to the modal's body.\n * @returns Paragraph element(s) containing the message(s) added to the\n * modal's body.\n */\n addMessage (...messages) {\n const elements = []\n const body = this.container.querySelector('.dcp-modal-body')\n for (let i = 0; i < messages.length; i++) {\n const row = document.createElement('div')\n row.className = 'row'\n\n const paragraph = document.createElement('p')\n paragraph.innerHTML = messages[i]\n paragraph.classList.add('message')\n row.appendChild(paragraph)\n body.appendChild(row)\n\n elements.push(paragraph)\n }\n\n if (elements.length === 1) return elements[0]\n else return elements\n }\n\n addHorizontalRule () {\n const body = this.container.querySelector('.dcp-modal-body')\n body.appendChild(document.createElement('hr'))\n }\n\n // Does what it says. Still ill advised to use unless you have to.\n addCustomHTML (htmlStr, browseCallback) {\n const elements = []\n const body = this.container.querySelector('.dcp-modal-body')\n body.innerHTML += htmlStr\n body.querySelector('#browse-button').addEventListener('click', browseCallback.bind(this, this))\n\n if (elements.length === 1) return elements[0]\n else return elements\n }\n\n addButton (...buttons) {\n const elements = []\n const body = this.container.querySelector('.dcp-modal-body')\n for (let i = 0; i < buttons.length; i++) {\n const row = document.createElement('div')\n row.className = 'row'\n\n let col = document.createElement('div')\n col.className = 'col-md-4'\n\n const description = document.createElement('span')\n description.innerText = buttons[i].description\n\n col.appendChild(description)\n row.appendChild(col)\n\n col = document.createElement('div')\n col.className = 'col-md-8'\n\n const button = document.createElement('button')\n button.innerText = buttons[i].label\n button.addEventListener('click', buttons[i].callback.bind(this, this))\n\n elements.push(button)\n\n col.appendChild(button)\n row.appendChild(col)\n\n body.appendChild(row)\n }\n\n if (elements.length === 1) return elements[0]\n else return elements\n }\n}\n\n\n// Inject our special stylesheet from dcp-client only if we're on the portal webpage.\nif (typeof window !== 'undefined' && typeof document !== 'undefined' && dcpConfig.portal.location.hostname === window.location.hostname) {\n // <link rel='stylesheet' href='/css/dashboard.css'>\n const stylesheet = document.createElement('link')\n stylesheet.rel = 'stylesheet'\n // Needed for the duplicate check done later.\n stylesheet.id = 'dcp-modal-styles'\n\n const dcpClientBundle = document.getElementById('_dcp_client_bundle')\n let src\n if (dcpClientBundle) {\n src = dcpClientBundle.src.replace('dcp-client-bundle.js', 'dcp-modal-style.css')\n } else {\n src = dcpConfig.portal.location.href + 'dcp-client/dist/dcp-modal-style.css'\n }\n\n stylesheet.href = src\n // If the style was injected before, don't inject it again.\n // Could occur when loading a file that imports Modal.js and loading\n // comput.min.js in the same HTML file.\n if (document.getElementById(stylesheet.id) === null) {\n document.getElementsByTagName('head')[0].appendChild(stylesheet)\n }\n\n if (typeof {\"version\":\"764872ded972b9068efdd89d2b1144bf7cb48e7e\",\"branch\":\"release\",\"dcpClient\":{\"version\":\"4.2.18\",\"from\":\"git+ssh://git@gitlab.com/Distributed-Compute-Protocol/dcp-client.git#prod-20221018\",\"resolved\":\"git+ssh://git@gitlab.com/Distributed-Compute-Protocol/dcp-client.git#c5ea513e7e6bc0294075a59ae63c78815c7a73ee\"},\"built\":\"Fri Oct 21 2022 11:28:26 GMT-0400 (Eastern Daylight Saving Time)\",\"config\":{\"generated\":\"Fri 21 Oct 2022 11:28:24 AM EDT by erose on lorge\",\"build\":\"debug\"},\"webpack\":\"5.74.0\",\"node\":\"v14.20.1\"} !== 'undefined' && typeof window.Modal === 'undefined') {\n window.Modal = Modal\n }\n}\n\n\n//# sourceURL=webpack://dcp/./portal/www/js/modal.js?");
|
|
3798
3798
|
|
|
3799
3799
|
/***/ }),
|
|
3800
3800
|
|
|
@@ -4100,7 +4100,7 @@ eval("/**\n * @file password.js\n * Modal providing a way to
|
|
|
4100
4100
|
\**********************************************/
|
|
4101
4101
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
4102
4102
|
|
|
4103
|
-
eval("/**\n * @file client-modal/utils.js\n * @author KC Erb\n * @date Mar 2020\n * \n * All shared functions among the modals.\n */\nconst { fetchRelative } = __webpack_require__(/*! ./fetch-relative */ \"./src/dcp-client/client-modal/fetch-relative.js\");\nconst { DCPError } = __webpack_require__(/*! dcp/common/dcp-error */ \"./src/common/dcp-error.js\");\nconst DCP_ENV = __webpack_require__(/*! dcp/common/dcp-env */ \"./src/common/dcp-env.js\");\nexports.OnCloseErrorCode = 'DCP_CM:CANCELX';\n\nif (DCP_ENV.isBrowserPlatform) {\n // Provide as export for the convenience of `utils.MicroModal` instead of a separate require.\n exports.MicroModal = __webpack_require__(/*! micromodal */ \"./node_modules/micromodal/dist/micromodal.es.js\")[\"default\"];\n}\n\n/**\n * Return a unique string, formatted as a GET parameter, that changes often enough to\n * always force the browser to fetch the latest version of our resource.\n *\n * @note Currently always returns the Date-based poison due to webpack. \n */\nfunction cachePoison() {\n if (true)\n return '?ucp=
|
|
4103
|
+
eval("/**\n * @file client-modal/utils.js\n * @author KC Erb\n * @date Mar 2020\n * \n * All shared functions among the modals.\n */\nconst { fetchRelative } = __webpack_require__(/*! ./fetch-relative */ \"./src/dcp-client/client-modal/fetch-relative.js\");\nconst { DCPError } = __webpack_require__(/*! dcp/common/dcp-error */ \"./src/common/dcp-error.js\");\nconst DCP_ENV = __webpack_require__(/*! dcp/common/dcp-env */ \"./src/common/dcp-env.js\");\nexports.OnCloseErrorCode = 'DCP_CM:CANCELX';\n\nif (DCP_ENV.isBrowserPlatform) {\n // Provide as export for the convenience of `utils.MicroModal` instead of a separate require.\n exports.MicroModal = __webpack_require__(/*! micromodal */ \"./node_modules/micromodal/dist/micromodal.es.js\")[\"default\"];\n}\n\n/**\n * Return a unique string, formatted as a GET parameter, that changes often enough to\n * always force the browser to fetch the latest version of our resource.\n *\n * @note Currently always returns the Date-based poison due to webpack. \n */\nfunction cachePoison() {\n if (true)\n return '?ucp=764872ded972b9068efdd89d2b1144bf7cb48e7e'; /* installer token */\n return '?ucp=' + Date.now();\n}\n \n/* Detect load type - on webpack, load dynamic content relative to webpack bundle;\n * otherwise load relative to the current scheduler's configured portal.\n */\nexports.myScript = (typeof document !== 'undefined') && document.currentScript;\nexports.corsProxyHref = undefined;\nif (exports.myScript && exports.myScript === (__webpack_require__(/*! ./fetch-relative */ \"./src/dcp-client/client-modal/fetch-relative.js\").myScript)) {\n let url = new ((__webpack_require__(/*! dcp/common/dcp-url */ \"./src/common/dcp-url.js\").DcpURL))(exports.myScript.src);\n exports.corsProxyHref = url.resolve('../cors-proxy.html');\n}\n\n/**\n * Look for modal id and required ids on page based on config, if not found, provide from dcp-client.\n * The first id in the required array must be the id of the modal's form element.\n * @param {Object} modalConfig Modal configuration object\n * @param {string} modalConfig.id Id of parent modal element\n * @param {string[]} modalConfig.required Array of required ids in parent modal element\n * @param {string[]} [modalConfig.optional] Array of optional ids in parent modal element\n * @param {string} modalConfig.path Relative path to modal html in dcp-client\n * @returns {DOMElement[]} Array of modal elements on page [config.id, ...config.required]\n */\nexports.initModal = async function (modalConfig, onClose) {\n exports.corsProxyHref = exports.corsProxyHref || dcpConfig.portal.location.resolve('dcp-client/cors-proxy.html');\n\n // Call ensure modal on any eager-loaded modals.\n if (modalConfig.eagerLoad) {\n Promise.all(\n modalConfig.eagerLoad.map(config => ensureModal(config))\n )\n };\n\n const [elements, optionalElements] = await ensureModal(modalConfig);\n\n // Wire up form to prevent default, resolve on submission, reject+reset when closed (or call onClose when closed)\n const [modal, form] = elements;\n form.reset(); // ensure that form is fresh\n let formResolve, formReject;\n let formPromise = new Promise( function(res, rej) {\n formResolve = res;\n formReject = rej;\n });\n form.onsubmit = function (submitEvent) {\n submitEvent.preventDefault();\n modal.setAttribute(\"data-state\", \"submitted\");\n formResolve(submitEvent);\n }\n\n exports.MicroModal.show(modalConfig.id, { \n disableFocus: true, \n onClose: onClose || getDefaultOnClose(formReject)\n });\n return [elements, formPromise, optionalElements];\n};\n\n// Ensure all required modal elements are on page according to modalConfig\nasync function ensureModal(modalConfig) {\n let allRequiredIds = [modalConfig.id, ...modalConfig.required];\n let missing = allRequiredIds.filter( id => !document.getElementById(id) );\n if (missing.length > 0) {\n if (missing.length !== allRequiredIds.length)\n console.warn(`Some of the ids needed to replace the default DCP-modal were found, but not all. So the default DCP-Modal will be used. Missing ids are: [${missing}].`);\n let contents = await fetchRelative(exports.corsProxyHref, modalConfig.path + cachePoison());\n const container = document.createElement('div');\n container.innerHTML = contents;\n document.body.appendChild(container);\n }\n\n const elements = allRequiredIds.map(id => document.getElementById(id));\n const optionalElements = (modalConfig.optional || []).map(id => document.getElementById(id));\n return [elements, optionalElements];\n};\n\n// This onClose is called by MicroModal and thus has the modal passed to it.\nfunction getDefaultOnClose (formReject) {\n return (modal) => {\n modal.offsetLeft; // forces style recalc\n const origState = modal.dataset.state;\n // reset form including data-state\n modal.setAttribute(\"data-state\", \"new\");\n // reject if closed without submitting form.\n if (origState !== \"submitted\") {\n const err = new DCPError(\"Modal was closed but modal's form was not submitted.\", exports.OnCloseErrorCode);\n formReject(err);\n }\n }\n}\n\n\n//# sourceURL=webpack://dcp/./src/dcp-client/client-modal/utils.js?");
|
|
4104
4104
|
|
|
4105
4105
|
/***/ }),
|
|
4106
4106
|
|
|
@@ -4131,7 +4131,7 @@ eval("/**\n * @file Module that implements Compute API\n * @module dcp/comput
|
|
|
4131
4131
|
\*********************************/
|
|
4132
4132
|
/***/ ((module, exports, __webpack_require__) => {
|
|
4133
4133
|
|
|
4134
|
-
eval("/* module decorator */ module = __webpack_require__.nmd(module);\n/**\n * @file dcp-client-bundle-src.js\n * Top-level file which gets webpacked into the bundle consumed by dcp-client 2.5\n * @author Wes Garland, wes@kingsds.network\n * @date July 2019\n */\n\n{\n let thisScript = typeof document !== 'undefined' ? (typeof document.currentScript !== 'undefined' && document.currentScript) || document.getElementById('_dcp_client_bundle') : {}\n let realModuleDeclare\n\n if ( false || typeof module.declare === 'undefined') {\n realModuleDeclare = ( true) ? module.declare : 0\n if (false) {}\n module.declare = function moduleUnWrapper (deps, factory) {\n factory(null, module.exports, module)\n return module.exports\n }\n }\n\n let _debugging = () => false\n dcpConfig.future = (__webpack_require__(/*! ../common/config-future.js */ \"./src/common/config-future.js\").futureFactory)(_debugging, dcpConfig);\n\n /* These modules are official API and must be part of DCP Client */\n let officialApi = {\n 'protocol': __webpack_require__(/*! ../protocol-v4 */ \"./src/protocol-v4/index.js\"),\n 'compute': (__webpack_require__(/*! ./compute */ \"./src/dcp-client/compute.js\").compute),\n 'worker': __webpack_require__(/*! ./worker */ \"./src/dcp-client/worker/index.js\"),\n 'wallet': __webpack_require__(/*! ./wallet */ \"./src/dcp-client/wallet/index.js\"),\n };\n\n /* Allow client programs to use modules which happen to be in the bundle anyhow */\n let conveniencePeers = {\n 'ethereumjs-wallet': (__webpack_require__(/*! ./wallet/keystore */ \"./src/dcp-client/wallet/keystore.js\")._internalEth.wallet),\n 'ethereumjs-util': (__webpack_require__(/*! ./wallet/keystore */ \"./src/dcp-client/wallet/keystore.js\")._internalEth.util),\n 'socket.io-client': __webpack_require__(/*! socket.io-client */ \"./node_modules/socket.io-client/build/cjs/index.js\"),\n 'bignumber.js': __webpack_require__(/*! bignumber.js */ \"./node_modules/bignumber.js/bignumber.js\"),\n 'semver': __webpack_require__(/*! semver */ \"./node_modules/semver/semver.js\"),\n };\n\n /* Some of these modules are API-track. Some of them need to be published to be\n * available for top-level resolution by DCP internals. Those (mostly) should have\n * been written using relative module paths.....\n */\n let modules = Object.assign({\n 'dcp-build': {\"version\":\"
|
|
4134
|
+
eval("/* module decorator */ module = __webpack_require__.nmd(module);\n/**\n * @file dcp-client-bundle-src.js\n * Top-level file which gets webpacked into the bundle consumed by dcp-client 2.5\n * @author Wes Garland, wes@kingsds.network\n * @date July 2019\n */\n\n{\n let thisScript = typeof document !== 'undefined' ? (typeof document.currentScript !== 'undefined' && document.currentScript) || document.getElementById('_dcp_client_bundle') : {}\n let realModuleDeclare\n\n if ( false || typeof module.declare === 'undefined') {\n realModuleDeclare = ( true) ? module.declare : 0\n if (false) {}\n module.declare = function moduleUnWrapper (deps, factory) {\n factory(null, module.exports, module)\n return module.exports\n }\n }\n\n let _debugging = () => false\n dcpConfig.future = (__webpack_require__(/*! ../common/config-future.js */ \"./src/common/config-future.js\").futureFactory)(_debugging, dcpConfig);\n\n /* These modules are official API and must be part of DCP Client */\n let officialApi = {\n 'protocol': __webpack_require__(/*! ../protocol-v4 */ \"./src/protocol-v4/index.js\"),\n 'compute': (__webpack_require__(/*! ./compute */ \"./src/dcp-client/compute.js\").compute),\n 'worker': __webpack_require__(/*! ./worker */ \"./src/dcp-client/worker/index.js\"),\n 'wallet': __webpack_require__(/*! ./wallet */ \"./src/dcp-client/wallet/index.js\"),\n };\n\n /* Allow client programs to use modules which happen to be in the bundle anyhow */\n let conveniencePeers = {\n 'ethereumjs-wallet': (__webpack_require__(/*! ./wallet/keystore */ \"./src/dcp-client/wallet/keystore.js\")._internalEth.wallet),\n 'ethereumjs-util': (__webpack_require__(/*! ./wallet/keystore */ \"./src/dcp-client/wallet/keystore.js\")._internalEth.util),\n 'socket.io-client': __webpack_require__(/*! socket.io-client */ \"./node_modules/socket.io-client/build/cjs/index.js\"),\n 'bignumber.js': __webpack_require__(/*! bignumber.js */ \"./node_modules/bignumber.js/bignumber.js\"),\n 'semver': __webpack_require__(/*! semver */ \"./node_modules/semver/semver.js\"),\n };\n\n /* Some of these modules are API-track. Some of them need to be published to be\n * available for top-level resolution by DCP internals. Those (mostly) should have\n * been written using relative module paths.....\n */\n let modules = Object.assign({\n 'dcp-build': {\"version\":\"764872ded972b9068efdd89d2b1144bf7cb48e7e\",\"branch\":\"release\",\"dcpClient\":{\"version\":\"4.2.18\",\"from\":\"git+ssh://git@gitlab.com/Distributed-Compute-Protocol/dcp-client.git#prod-20221018\",\"resolved\":\"git+ssh://git@gitlab.com/Distributed-Compute-Protocol/dcp-client.git#c5ea513e7e6bc0294075a59ae63c78815c7a73ee\"},\"built\":\"Fri Oct 21 2022 11:28:26 GMT-0400 (Eastern Daylight Saving Time)\",\"config\":{\"generated\":\"Fri 21 Oct 2022 11:28:24 AM EDT by erose on lorge\",\"build\":\"debug\"},\"webpack\":\"5.74.0\",\"node\":\"v14.20.1\"},\n 'dcp-xhr': __webpack_require__(/*! ../common/dcp-xhr */ \"./src/common/dcp-xhr.js\"),\n 'dcp-env': __webpack_require__(/*! ../common/dcp-env */ \"./src/common/dcp-env.js\"),\n 'dcp-url': __webpack_require__(/*! ../common/dcp-url */ \"./src/common/dcp-url.js\"),\n 'cli': __webpack_require__(/*! ../common/cli */ \"./src/common/cli.js\"),\n 'dcp-timers': __webpack_require__(/*! ../common/dcp-timers */ \"./src/common/dcp-timers.js\"),\n 'dcp-dot-dir': __webpack_require__(/*! ../common/dcp-dot-dir */ \"./src/common/dcp-dot-dir.js\"),\n 'dcp-assert': __webpack_require__(/*! ../common/dcp-assert */ \"./src/common/dcp-assert.js\"),\n 'dcp-events': __webpack_require__(/*! ../common/dcp-events */ \"./src/common/dcp-events/index.js\"),\n 'utils': __webpack_require__(/*! ../utils */ \"./src/utils/index.js\"),\n 'debugging': __webpack_require__(/*! ../debugging */ \"./src/debugging.js\"),\n 'publish': __webpack_require__(/*! ../common/dcp-publish */ \"./src/common/dcp-publish.js\"),\n 'compute-groups': {\n ...__webpack_require__(/*! ./compute-groups */ \"./src/dcp-client/compute-groups/index.js\"),\n publicGroupOpaqueId: (__webpack_require__(/*! ../common/scheduler-constants */ \"./src/common/scheduler-constants.js\").computeGroups[\"public\"].opaqueId),\n },\n 'bank-util': __webpack_require__(/*! ./bank-util */ \"./src/dcp-client/bank-util.js\"),\n 'protocol-v4': __webpack_require__(/*! ../protocol-v4 */ \"./src/protocol-v4/index.js\"), /* deprecated */\n 'client-modal': __webpack_require__(/*! ./client-modal */ \"./src/dcp-client/client-modal/index.js\"),\n 'legacy-modal': (__webpack_require__(/*! ../../portal/www/js/modal */ \"./portal/www/js/modal.js\").Modal),\n 'eth': __webpack_require__(/*! ./wallet/eth */ \"./src/dcp-client/wallet/eth.js\"),\n 'serialize': __webpack_require__(/*! ../utils/serialize */ \"./src/utils/serialize.js\"),\n 'job': __webpack_require__(/*! ./job */ \"./src/dcp-client/job/index.js\"),\n 'range-object': __webpack_require__(/*! ./range-object */ \"./src/dcp-client/range-object.js\"),\n 'stats-ranges': __webpack_require__(/*! ./stats-ranges */ \"./src/dcp-client/stats-ranges.js\"),\n 'job-values': __webpack_require__(/*! ./job-values */ \"./src/dcp-client/job-values.js\"),\n 'signal-handler': __webpack_require__(/*! ../node-libs/signal-handler */ \"./src/node-libs/signal-handler.js\"),\n 'standard-objects': {}\n }, conveniencePeers, officialApi);\n\n /* Export the JS Standard Classes (etc) from the global object of the bundle evaluation context,\n * in case we have code somewhere that needs to use these for instanceof checks.\n */\n ;[ Object, Function, Boolean, Symbol,\n Error, EvalError, RangeError, ReferenceError, SyntaxError, TypeError, URIError,\n Number, Math, Date,\n String, RegExp,\n Array, Int8Array, Uint8Array, Uint8ClampedArray, Int16Array, Uint16Array, Int32Array, Uint32Array, Float32Array, Float64Array,\n Map, Set, WeakMap, WeakSet,\n ArrayBuffer, DataView, JSON,\n Promise, \n Reflect, Proxy, Intl, WebAssembly, __webpack_require__\n ].forEach(function (obj) {\n if (obj.name && (typeof obj === 'function' || typeof obj === 'object'))\n modules['standard-objects'][obj.name] = obj\n })\n\n if (typeof BigInt !== 'undefined')\n modules['standard-objects']['BigInt'] === BigInt;\n if (typeof BigInt64Array !== 'undefined')\n modules['standard-objects']['BigInt64Array'] === BigInt64Array;\n if (typeof BigInt64Array !== 'undefined')\n modules['standard-objects']['BigUint64Array'] === BigUint64Array;\n\n module.declare([], function(require, exports, module) {\n Object.assign(exports, modules)\n exports['dcp-config'] = dcpConfig\n })\n if (realModuleDeclare)\n module.declare = realModuleDeclare\n\n bundleExports = thisScript.exports = exports; /* must be last expression evaluated! */\n}\n\n\n//# sourceURL=webpack://dcp/./src/dcp-client/index.js?");
|
|
4135
4135
|
|
|
4136
4136
|
/***/ }),
|
|
4137
4137
|
|
|
@@ -4253,7 +4253,7 @@ eval("/* provided dependency */ var process = __webpack_require__(/*! ./node_mod
|
|
|
4253
4253
|
\*************************************************/
|
|
4254
4254
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
4255
4255
|
|
|
4256
|
-
eval("/**\n * @file /src/schedmsg/schedmsg-web.js\n * @author Ryan Rossiter, ryan@kingsds.network\n * @date March 2020\n *\n * This is the SchedMsg implementation for commands that are browser-specific\n * or have browser-specific behaviour.\n */\n\nconst { SchedMsg } = __webpack_require__(/*! ./schedmsg */ \"./src/dcp-client/schedmsg/schedmsg.js\");\n\nclass SchedMsgWeb extends SchedMsg {\n constructor(worker) {\n super(worker);\n this.modal = null;\n\n this.registerHandler('announce', this.onAnnouncement.bind(this));\n this.registerHandler('openPopup', this.onOpenPopup.bind(this));\n this.registerHandler('reload', this.onReload.bind(this));\n }\n\n onAnnouncement({ message }) {\n if (this.modal) {\n this.modal.close();\n }\n\n this.modal = window.userInterface.alert('Announcement', '' /* subtitle */, message,\n /* onClose */ () => this.modal = null);\n }\n\n onOpenPopup({ href }) {\n window.open(href);\n }\n\n onReload() {\n const hash = window.location.hash;\n\n let newUrl = window.location.href.replace(/#.*/, '');\n newUrl += (newUrl.indexOf('?') === -1 ? '?' : '&');\n newUrl += 'dcp=
|
|
4256
|
+
eval("/**\n * @file /src/schedmsg/schedmsg-web.js\n * @author Ryan Rossiter, ryan@kingsds.network\n * @date March 2020\n *\n * This is the SchedMsg implementation for commands that are browser-specific\n * or have browser-specific behaviour.\n */\n\nconst { SchedMsg } = __webpack_require__(/*! ./schedmsg */ \"./src/dcp-client/schedmsg/schedmsg.js\");\n\nclass SchedMsgWeb extends SchedMsg {\n constructor(worker) {\n super(worker);\n this.modal = null;\n\n this.registerHandler('announce', this.onAnnouncement.bind(this));\n this.registerHandler('openPopup', this.onOpenPopup.bind(this));\n this.registerHandler('reload', this.onReload.bind(this));\n }\n\n onAnnouncement({ message }) {\n if (this.modal) {\n this.modal.close();\n }\n\n this.modal = window.userInterface.alert('Announcement', '' /* subtitle */, message,\n /* onClose */ () => this.modal = null);\n }\n\n onOpenPopup({ href }) {\n window.open(href);\n }\n\n onReload() {\n const hash = window.location.hash;\n\n let newUrl = window.location.href.replace(/#.*/, '');\n newUrl += (newUrl.indexOf('?') === -1 ? '?' : '&');\n newUrl += 'dcp=764872ded972b9068efdd89d2b1144bf7cb48e7e,' + Date.now() + hash;\n\n window.location.replace(newUrl);\n }\n}\n\nObject.assign(module.exports, {\n SchedMsgWeb\n});\n\n\n//# sourceURL=webpack://dcp/./src/dcp-client/schedmsg/schedmsg-web.js?");
|
|
4257
4257
|
|
|
4258
4258
|
/***/ }),
|
|
4259
4259
|
|
package/index.js
CHANGED
package/ns-map.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dcp-client",
|
|
3
|
-
"version": "4.2.
|
|
3
|
+
"version": "4.2.20",
|
|
4
4
|
"description": "Core libraries for accessing DCP network",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"dcp"
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
"http-proxy-agent": "^4.0.1",
|
|
37
37
|
"https-agent": "^1.0.0",
|
|
38
38
|
"https-proxy-agent": "^5.0.0",
|
|
39
|
-
"kvin": "^1.2.
|
|
39
|
+
"kvin": "^1.2.12",
|
|
40
40
|
"nanoid": "^3.2.0",
|
|
41
41
|
"node-localstorage": "^2.1.5",
|
|
42
42
|
"physical-cpu-count": "^2.0.0",
|