From 5facca6aa5e38cb11b7a4ecb997aac6a3c948e3f Mon Sep 17 00:00:00 2001 From: Masquerade Circus Date: Thu, 3 Feb 2022 06:54:59 -0600 Subject: [PATCH 01/19] Rewrited [WIP] --- .vscode/settings.json | 2 +- bench/.buffalo-test.json | 424 +++++-- bench/equalize_arrays.test.js | 4 +- ...cript.test.js => hyperscript-test-.js.bak} | 2 +- bench/hyperscript_bench.js | 39 + bench/iterations.test.js | 428 ++++++- ...ate.test.js => mount_n_update.test.js.bak} | 2 +- bench/mount_n_update_bench.js | 665 +++++++++++ dist/@types/lib/index.d.ts | 111 +- dist/@types/lib/index_.d.ts | 106 ++ dist/valyrian.min.js | 14 +- dist/valyrian.min.js.map | 2 +- lib/index.ts | 1013 +++++++++-------- lib/index_.ts | 564 +++++++++ package.json | 5 +- plugins/hooks.js | 8 +- plugins/node.js | 39 +- plugins/request.js | 228 ++-- plugins/router.js | 422 ++++--- plugins/signals.js | 229 ++-- plugins/store.js | 120 +- plugins/sw.js | 42 +- plugins/v-model.js | 24 +- register.js | 50 +- source.js | 4 +- test/directives_test.js | 164 ++- test/hooks_test.js | 3 +- test/hyperscript_test.js | 34 +- test/keyed_test.js | 21 +- test/lifecycle_test.js | 37 +- test/mount_n_update_test.js | 132 +-- test/node_test.js | 55 +- test/request_test.js | 65 +- test/router_test.js | 120 +- test/signals_test.js | 48 +- test/store_test.js | 14 +- yarn.lock | 5 + 37 files changed, 3568 insertions(+), 1677 deletions(-) rename bench/{hyperscript.test.js => hyperscript-test-.js.bak} (96%) create mode 100644 bench/hyperscript_bench.js rename bench/{mount_n_update.test.js => mount_n_update.test.js.bak} (99%) create mode 100644 bench/mount_n_update_bench.js create mode 100644 dist/@types/lib/index_.d.ts create mode 100644 lib/index_.ts diff --git a/.vscode/settings.json b/.vscode/settings.json index 7147c5c..6131d6a 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,5 +1,5 @@ { "deepcode.uploadApproved": true, - "cSpell.words": ["eqeqeq", "onbeforeupdate", "oncreate", "onremove"], + "cSpell.words": ["eqeqeq", "onbeforeupdate", "oncleanup", "oncreate", "onremove"], "prettier.trailingComma": "none" } diff --git a/bench/.buffalo-test.json b/bench/.buffalo-test.json index 490390e..5d479ff 100644 --- a/bench/.buffalo-test.json +++ b/bench/.buffalo-test.json @@ -1,44 +1,44 @@ [ { - "tag": "8f1ae1ed31d6fade49775f76180d4f480838e513", - "timestamp": "2021-12-17T00:06:41.419Z", + "tag": "ff7d5d73af49d9be6dab1d8cc4e40441c255cbba", + "timestamp": "2022-02-03T12:53:38.877Z", "suites": { "Matching keyed list": { "Removed at the end": { - "hz": 16671904.491364745, - "meanTime": 0.000059981149755143596, - "medianTime": 0.000056996941566467285, - "standardDeviation": 0.00021825156804251554, - "maxTime": 0.33727000281214714, - "minTime": 0.000048998743295669556 + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 } }, "Matching keyed list -> stress": { "Removed at the end": { - "hz": 15985997.638615083, - "meanTime": 0.00006255474463379397, - "medianTime": 0.000059001147747039795, - "standardDeviation": 0.0001994548743399828, - "maxTime": 0.17909200116991997, - "minTime": 0.00004999712109565735 + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 } }, "hyperscript": { "Valyrian 5.0.8": { - "hz": 13456357.953304552, - "meanTime": 0.00007431431323914986, - "medianTime": 0.00006800144910812378, - "standardDeviation": 0.000290168848348955, - "maxTime": 0.2560419999063015, - "minTime": 0.00005999952554702759 + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 }, "Valyrian next": { - "hz": 16580133.323220424, - "meanTime": 0.00006031314589005766, - "medianTime": 0.00005700066685676575, - "standardDeviation": 0.0002683531202565282, - "maxTime": 0.3098529987037182, - "minTime": 0.00005000084638595581 + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 } }, "Set.has vs [].indexOf": { @@ -137,148 +137,328 @@ "minTime": 0 } }, + "string comparison vs instance comparison vs property comparison": { + "string comparison": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "instance comparison": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "property comparison": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "property string comparison": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "typeof comparison": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "Object with property equals true vs set vs map vs string array": { + "Object with property equals true": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "key in object": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "set": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "map": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "string array": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "For loop if/continue vs if/else": { + "for loop if/continue": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "for loop if/else": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "map array of strings vs reduce with object keys equals index": { + "map array of strings": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "reduce with object keys equals index": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "array by for": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "object by for": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "object map by for": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "Symbol access vs direct access": { + "Direct access access": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "Symbol access access": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, "Mount and update: Mount multiple types": { "Valyrian 5.0.8": { - "hz": 3035.107184017302, - "meanTime": 0.3294776557697672, - "medianTime": 0.3060449995100498, - "standardDeviation": 0.11670815968939321, - "maxTime": 3.5715750008821487, - "minTime": 0.28655700013041496 + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 }, "Valyrian next": { - "hz": 1995.8871120056313, - "meanTime": 0.5010303408368211, - "medianTime": 0.490922998636961, - "standardDeviation": 0.11500613641370512, - "maxTime": 3.1317549981176853, - "minTime": 0.41110100224614143 + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 } }, "Mount and update: Mount single text": { "Valyrian 5.0.8": { - "hz": 574020.7897105797, - "meanTime": 0.001742097181713921, - "medianTime": 0.0015110000967979431, - "standardDeviation": 0.00871027385649084, - "maxTime": 1.0047080032527447, - "minTime": 0.00136600062251091 + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "Valyrian next": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "Mount and update: Mount single text in div": { + "Valyrian 5.0.8": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 }, "Valyrian next": { - "hz": 670298.460656875, - "meanTime": 0.0014918727383321543, - "medianTime": 0.0012869983911514282, - "standardDeviation": 0.008272256863081372, - "maxTime": 1.5173600018024445, - "minTime": 0.001189999282360077 + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 } }, "Mount and update: Update multiple types": { "Valyrian 5.0.8": { - "hz": 189.34742908870902, - "meanTime": 5.2812969513914085, - "medianTime": 5.137601997703314, - "standardDeviation": 0.5869414447582827, - "maxTime": 10.952287998050451, - "minTime": 4.94692900031805 + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 }, "Valyrian next": { - "hz": 1015.6718063437537, - "meanTime": 0.9845700094795684, - "medianTime": 0.958076000213623, - "standardDeviation": 0.16159128266950185, - "maxTime": 3.7391529977321625, - "minTime": 0.8335059992969036 + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 } }, "Mount and update: Update single text": { "Valyrian 5.0.8": { - "hz": 270212.40386823955, - "meanTime": 0.003700792360692731, - "medianTime": 0.0033080019056797028, - "standardDeviation": 0.012645737126902255, - "maxTime": 2.229399997740984, - "minTime": 0.003110002726316452 + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 }, "Valyrian next": { - "hz": 303415.56365041697, - "meanTime": 0.0032958098390501785, - "medianTime": 0.0028010010719299316, - "standardDeviation": 0.015595430114341434, - "maxTime": 1.4865939989686012, - "minTime": 0.0026200003921985626 + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 } }, "Mount and update: Render list": { "vOld": { - "hz": 30695.202025360184, - "meanTime": 0.03257838144130168, - "medianTime": 0.02901199832558632, - "standardDeviation": 0.043461287312234656, - "maxTime": 2.0518620014190674, - "minTime": 0.02764499932527542 + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 }, "VNext": { - "hz": 34264.97096268492, - "meanTime": 0.02918432357899895, - "medianTime": 0.02490699663758278, - "standardDeviation": 0.044102742115498944, - "maxTime": 3.1514320001006126, - "minTime": 0.02388399839401245 + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 } }, "Mount and update: Render keyed list": { "vOld": { - "hz": 10720.337430113585, - "meanTime": 0.09328064592360548, - "medianTime": 0.08023500069975853, - "standardDeviation": 0.0861680625592031, - "maxTime": 3.6683319993317127, - "minTime": 0.0776359997689724 + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 }, "VNext": { - "hz": 11728.004767713635, - "meanTime": 0.08526599535096789, - "medianTime": 0.07374100014567375, - "standardDeviation": 0.07861224431554834, - "maxTime": 3.2908590026199818, - "minTime": 0.07119200006127357 + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 } }, "Mount and update: Render keyed list -> stress": { "vOld": { - "hz": 5617.286997486036, - "meanTime": 0.17802188146120015, - "medianTime": 0.15422199666500092, - "standardDeviation": 0.12149204821686695, - "maxTime": 3.3464059978723526, - "minTime": 0.14767500013113022 + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 }, "VNext": { - "hz": 5506.425278112736, - "meanTime": 0.18160602378004817, - "medianTime": 0.1479550004005432, - "standardDeviation": 0.17073753397126684, - "maxTime": 6.763663999736309, - "minTime": 0.13728399947285652 + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 } }, "Mount and update: Render keyed list -> swap keys on large set": { "vOld": { - "hz": 924.5032237385955, - "meanTime": 1.081661993514856, - "medianTime": 0.9031809978187084, - "standardDeviation": 0.4723178336406087, - "maxTime": 6.736775998026133, - "minTime": 0.7774330005049706 + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 }, "VNext": { - "hz": 1035.442356229234, - "meanTime": 0.9657708070217406, - "medianTime": 0.8098049983382225, - "standardDeviation": 0.40682233960256786, - "maxTime": 3.912805996835232, - "minTime": 0.7240439988672733 + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 } } } diff --git a/bench/equalize_arrays.test.js b/bench/equalize_arrays.test.js index 17dca48..a8827bf 100644 --- a/bench/equalize_arrays.test.js +++ b/bench/equalize_arrays.test.js @@ -157,7 +157,7 @@ function matchKeyedList(oldKeyedList: Set, newKeyedList: Set): Movement[] { return movements; } -compare("Matching keyed list", () => { +compare.skip("Matching keyed list", () => { let set = [1, 2, 3, 4, 5]; let tests = [ { name: "Removed at the end", set: [1, 2, 3, 4], movements: 1 }, // Removed at the end @@ -209,7 +209,7 @@ compare("Matching keyed list", () => { }); }); -compare("Matching keyed list -> stress", () => { +compare.skip("Matching keyed list -> stress", () => { let set = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; let tests = [ { name: "Removed at the end", set: [1, 2, 3, 4, 5, 6, 7, 8, 9], movements: 1 }, // Removed at the end diff --git a/bench/hyperscript.test.js b/bench/hyperscript-test-.js.bak similarity index 96% rename from bench/hyperscript.test.js rename to bench/hyperscript-test-.js.bak index 09061c0..71c7a48 100644 --- a/bench/hyperscript.test.js +++ b/bench/hyperscript-test-.js.bak @@ -4,7 +4,7 @@ import "../lib/index.ts"; import expect from "expect"; import fs from "fs"; -import nodePlugin from "../plugins/node"; +import nodePlugin from "../plugins/node.mjs"; import vOld from "./index-old"; let VNext = v; diff --git a/bench/hyperscript_bench.js b/bench/hyperscript_bench.js new file mode 100644 index 0000000..20c5a78 --- /dev/null +++ b/bench/hyperscript_bench.js @@ -0,0 +1,39 @@ +const { before, benchmark, compare } = require("buffalo-test"); + +const { v: VNext } = require("../lib/index.ts"); +const expect = require("expect"); +const fs = require("fs"); +const nodePlugin = require("../plugins/node"); +const vOld = require("./index-old"); + +compare("hyperscript", () => { + let date = new Date(); + before(async () => { + nodePlugin.inline.extensions("ts"); + // await nodePlugin.inline.ts("./lib/index.ts", { compact: true }); + await nodePlugin.inline.js("./bench/index-old.js", { compact: true }); + // console.log(nodePlugin.inline.ts()[0].raw.length); + console.log(nodePlugin.inline.js()[0].raw.length); + + let compiled = fs.readFileSync("./dist/valyrian.min.js", "utf8"); + console.log(compiled.length); + + expect(vOld("div", null, [null, "Hello", , 1, date, { hello: "world" }, ["Hello"]])).toEqual({ + name: "div", + props: {}, + children: [[null, "Hello", undefined, 1, date, { hello: "world" }, ["Hello"]]] + }); + expect(VNext("div", null, [null, "Hello", , 1, date, { hello: "world" }, ["Hello"]])).toEqual({ + tag: "div", + props: {}, + children: [[null, "Hello", undefined, 1, date, { hello: "world" }, ["Hello"]]] + }); + }); + + benchmark("Valyrian 5.0.8", () => { + vOld("div", null, [null, "Hello", , 1, date, { hello: "world" }, ["Hello"]]); + }); + benchmark("Valyrian next", () => { + VNext("div", null, [null, "Hello", , 1, date, { hello: "world" }, ["Hello"]]); + }); +}); diff --git a/bench/iterations.test.js b/bench/iterations.test.js index 0e541d2..67f6f9d 100644 --- a/bench/iterations.test.js +++ b/bench/iterations.test.js @@ -1,5 +1,5 @@ /* eslint-disable eqeqeq */ -let { compare, benchmark, before } = require("buffalo-test"); +let { compare, benchmark, before, beforeEach } = require("buffalo-test"); import expect from "expect"; @@ -125,3 +125,429 @@ compare.skip("Array.isArray vs typeof object & Array.isArray", () => { typeof e === "object" && Array.isArray(e); }); }); + +compare.skip("string comparison vs instance comparison vs property comparison", () => { + class A { + name = "a"; + } + class B { + b = "b"; + } + let classA = new A(); + let classB = new B(); + + benchmark("string comparison", () => { + classA.name === "a"; + classB.name === "b"; + }); + + benchmark("instance comparison", () => { + classA instanceof A; + classB instanceof B; + }); + + benchmark("property comparison", () => { + "name" in classA; + "name" in classB; + }); + + benchmark("property string comparison", () => { + !classA.name; + !classB.name; + }); + + benchmark("typeof comparison", () => { + typeof classA.name === "string"; + typeof classB.name === "string"; + }); +}); + +compare.skip("Object with property equals true vs set vs map vs string array", () => { + let obj = { + alpha: true, + beta: true, + gamma: true, + delta: true, + epsilon: true, + zeta: true + }; + + let set = new Set(); + let map = new Map(); + let arr = []; + + for (let key in obj) { + set.add(key); + map.set(key, true); + arr.push(key); + } + + beforeEach(() => { + expect(obj.alpha).toEqual(true); + expect(obj.capa).toBeUndefined(); + expect(set.has("alpha")).toEqual(true); + expect(set.has("capa")).toEqual(false); + expect(map.has("alpha")).toEqual(true); + expect(map.has("capa")).toEqual(false); + expect(arr.indexOf("alpha") !== -1).toEqual(true); + expect(arr.indexOf("capa") !== -1).toEqual(false); + }); + + benchmark("Object with property equals true", () => { + obj.alpha === true; + obj.beta === true; + obj.gamma === true; + obj.delta === true; + obj.epsilon === true; + obj.zeta === true; + + obj.capa === true; + obj.capa === true; + obj.capa === true; + obj.capa === true; + obj.capa === true; + obj.capa === true; + }); + + benchmark("key in object", () => { + "alpha" in obj === true; + "beta" in obj === true; + "gamma" in obj === true; + "delta" in obj === true; + "epsilon" in obj === true; + "zeta" in obj === true; + + "capa" in obj === true; + "capa" in obj === true; + "capa" in obj === true; + "capa" in obj === true; + "capa" in obj === true; + "capa" in obj === true; + }); + + benchmark("set", () => { + set.has("alpha") === true; + set.has("beta") === true; + set.has("gamma") === true; + set.has("delta") === true; + set.has("epsilon") === true; + set.has("zeta") === true; + + set.has("capa") === true; + set.has("capa") === true; + set.has("capa") === true; + set.has("capa") === true; + set.has("capa") === true; + set.has("capa") === true; + }); + + benchmark("map", () => { + map.has("alpha") === true; + map.has("beta") === true; + map.has("gamma") === true; + map.has("delta") === true; + map.has("epsilon") === true; + map.has("zeta") === true; + + map.has("capa") === true; + map.has("capa") === true; + map.has("capa") === true; + map.has("capa") === true; + map.has("capa") === true; + map.has("capa") === true; + }); + + benchmark("string array", () => { + arr.indexOf("alpha") !== -1; + arr.indexOf("beta") !== -1; + arr.indexOf("gamma") !== -1; + arr.indexOf("delta") !== -1; + arr.indexOf("epsilon") !== -1; + arr.indexOf("zeta") !== -1; + + arr.indexOf("capa") !== -1; + arr.indexOf("capa") !== -1; + arr.indexOf("capa") !== -1; + arr.indexOf("capa") !== -1; + arr.indexOf("capa") !== -1; + arr.indexOf("capa") !== -1; + }); +}); + +compare.skip("For loop if/continue vs if/else", () => { + let arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; + + beforeEach(() => { + expect(arr.length).toEqual(10); + }); + + benchmark("for loop if/continue", () => { + let sum = 0; + for (let i = 0; i < arr.length; i++) { + if (arr[i] % 2 === 0) { + sum -= arr[i]; + continue; + } + sum += arr[i]; + } + }); + + benchmark("for loop if/else", () => { + let sum = 0; + for (let i = 0; i < arr.length; i++) { + if (arr[i] % 2 === 0) { + sum -= arr[i]; + } else { + sum += arr[i]; + } + } + }); +}); + +compare.skip("map array of strings vs reduce with object keys equals index", () => { + let objects = [{ key: "a" }, { key: "b" }, { key: "c" }, { key: "d" }, { key: "e" }, { key: "f" }, { key: "g" }, { key: "h" }, { key: "i" }, { key: "j" }]; + + beforeEach(() => { + let arrayByMap = objects.map((obj) => obj.key); + expect(arrayByMap[0]).toEqual("a"); + + let objectByReduce = objects.reduce((acc, obj, i) => { + acc[obj.key] = i; + return acc; + }, {}); + expect(objectByReduce.a).toEqual(0); + + let arrayByFor = []; + for (let i = 0; i < objects.length; i++) { + arrayByFor.push(objects[i].key); + } + expect(arrayByFor[0]).toEqual("a"); + + let objectByFor = {}; + for (let i = 0; i < objects.length; i++) { + objectByFor[objects[i].key] = i; + } + expect(objectByFor.a).toEqual(0); + + let objectMapByFor = new Map(); + for (let i = 0; i < objects.length; i++) { + objectMapByFor.set(objects[i].key, i); + } + expect(objectMapByFor.get("a")).toEqual(0); + }); + + benchmark("map array of strings", () => { + let arrayByMap = objects.map((obj) => obj.key); + arrayByMap.indexOf("a") !== -1; + arrayByMap.indexOf("b") !== -1; + arrayByMap.indexOf("c") !== -1; + arrayByMap.indexOf("d") !== -1; + arrayByMap.indexOf("e") !== -1; + arrayByMap.indexOf("f") !== -1; + arrayByMap.indexOf("g") !== -1; + arrayByMap.indexOf("h") !== -1; + arrayByMap.indexOf("i") !== -1; + arrayByMap.indexOf("j") !== -1; + + arrayByMap.indexOf("k") !== -1; + arrayByMap.indexOf("l") !== -1; + arrayByMap.indexOf("m") !== -1; + arrayByMap.indexOf("n") !== -1; + arrayByMap.indexOf("o") !== -1; + arrayByMap.indexOf("p") !== -1; + arrayByMap.indexOf("q") !== -1; + arrayByMap.indexOf("r") !== -1; + arrayByMap.indexOf("s") !== -1; + arrayByMap.indexOf("t") !== -1; + }); + + benchmark("reduce with object keys equals index", () => { + let objectByReduce = objects.reduce((acc, obj, i) => { + acc[obj.key] = i; + return acc; + }, {}); + objectByReduce.a === 0; + objectByReduce.b === 1; + objectByReduce.c === 2; + objectByReduce.d === 3; + objectByReduce.e === 4; + objectByReduce.f === 5; + objectByReduce.g === 6; + objectByReduce.h === 7; + objectByReduce.i === 8; + objectByReduce.j === 9; + + objectByReduce.k === 10; + objectByReduce.l === 11; + objectByReduce.m === 12; + objectByReduce.n === 13; + objectByReduce.o === 14; + objectByReduce.p === 15; + objectByReduce.q === 16; + objectByReduce.r === 17; + objectByReduce.s === 18; + objectByReduce.t === 19; + }); + + benchmark("array by for", () => { + let arrayByFor = []; + for (let i = 0; i < objects.length; i++) { + arrayByFor.push(objects[i].key); + } + arrayByFor.indexOf("a") !== -1; + arrayByFor.indexOf("b") !== -1; + arrayByFor.indexOf("c") !== -1; + arrayByFor.indexOf("d") !== -1; + arrayByFor.indexOf("e") !== -1; + arrayByFor.indexOf("f") !== -1; + arrayByFor.indexOf("g") !== -1; + arrayByFor.indexOf("h") !== -1; + arrayByFor.indexOf("i") !== -1; + arrayByFor.indexOf("j") !== -1; + + arrayByFor.indexOf("k") !== -1; + arrayByFor.indexOf("l") !== -1; + arrayByFor.indexOf("m") !== -1; + arrayByFor.indexOf("n") !== -1; + arrayByFor.indexOf("o") !== -1; + arrayByFor.indexOf("p") !== -1; + arrayByFor.indexOf("q") !== -1; + arrayByFor.indexOf("r") !== -1; + arrayByFor.indexOf("s") !== -1; + arrayByFor.indexOf("t") !== -1; + }); + + benchmark("object by for", () => { + let objectByFor = {}; + for (let i = 0; i < objects.length; i++) { + objectByFor[objects[i].key] = i; + } + objectByFor.a === 0; + objectByFor.b === 1; + objectByFor.c === 2; + objectByFor.d === 3; + objectByFor.e === 4; + objectByFor.f === 5; + objectByFor.g === 6; + objectByFor.h === 7; + objectByFor.i === 8; + objectByFor.j === 9; + + objectByFor.k === 10; + objectByFor.l === 11; + objectByFor.m === 12; + objectByFor.n === 13; + objectByFor.o === 14; + objectByFor.p === 15; + objectByFor.q === 16; + objectByFor.r === 17; + objectByFor.s === 18; + objectByFor.t === 19; + }); + + benchmark("object map by for", () => { + let objectMapByFor = new Map(); + for (let i = 0; i < objects.length; i++) { + objectMapByFor.set(objects[i].key, i); + } + objectMapByFor.get("a") === 0; + objectMapByFor.get("b") === 1; + objectMapByFor.get("c") === 2; + objectMapByFor.get("d") === 3; + objectMapByFor.get("e") === 4; + objectMapByFor.get("f") === 5; + objectMapByFor.get("g") === 6; + objectMapByFor.get("h") === 7; + objectMapByFor.get("i") === 8; + objectMapByFor.get("j") === 9; + + objectMapByFor.get("k") === 10; + objectMapByFor.get("l") === 11; + objectMapByFor.get("m") === 12; + objectMapByFor.get("n") === 13; + objectMapByFor.get("o") === 14; + objectMapByFor.get("p") === 15; + objectMapByFor.get("q") === 16; + objectMapByFor.get("r") === 17; + objectMapByFor.get("s") === 18; + objectMapByFor.get("t") === 19; + }); +}); + +compare.skip("Symbol access vs direct access", () => { + beforeEach(() => { + function Component1() {} + function Component2() {} + + Component1.__valyrian__ = { + render: () => {} + }; + + let ValyrianSymbol = Symbol("Valyrian"); + Component2[ValyrianSymbol] = { + render: () => {} + }; + + expect(Component1.__valyrian__).toBeDefined(); + expect(Component2[ValyrianSymbol]).toBeDefined(); + + Reflect.deleteProperty(Component1, "__valyrian__"); + Reflect.deleteProperty(Component2, ValyrianSymbol); + + expect(Component1.__valyrian__).toBeUndefined(); + expect(Component2[ValyrianSymbol]).toBeUndefined(); + }); + + benchmark("Direct access access", () => { + function Component1() {} + + for (let i = 1000; i--; ) { + Component1.__valyrian__ = { + render: () => {} + }; + } + + for (let i = 1000; i--; ) { + "__valyrian__" in Component1; + } + + for (let i = 1000; i--; ) { + Component1.__valyrian__; + } + + for (let i = 1000; i--; ) { + Component1.__valyrian__.render; + } + + for (let i = 1000; i--; ) { + Reflect.deleteProperty(Component1, "__valyrian__"); + } + }); + + benchmark("Symbol access access", () => { + function Component2() {} + let symbol = Symbol("Valyrian"); + + for (let i = 1000; i--; ) { + Component2[symbol] = { + render: () => {} + }; + } + + for (let i = 1000; i--; ) { + symbol in Component2; + } + + for (let i = 1000; i--; ) { + Component2[symbol]; + } + + for (let i = 1000; i--; ) { + Component2[symbol].render; + } + + for (let i = 1000; i--; ) { + Reflect.deleteProperty(Component2, symbol); + } + }); +}); diff --git a/bench/mount_n_update.test.js b/bench/mount_n_update.test.js.bak similarity index 99% rename from bench/mount_n_update.test.js rename to bench/mount_n_update.test.js.bak index d135762..bc8d034 100644 --- a/bench/mount_n_update.test.js +++ b/bench/mount_n_update.test.js.bak @@ -3,7 +3,7 @@ let { compare, benchmark, before } = require("buffalo-test"); import "../lib/index.ts"; import expect from "expect"; -import nodePlugin from "../plugins/node"; +import nodePlugin from "../plugins/node.mjs"; import vOld from "./index-old"; let VNext = v; diff --git a/bench/mount_n_update_bench.js b/bench/mount_n_update_bench.js new file mode 100644 index 0000000..003e860 --- /dev/null +++ b/bench/mount_n_update_bench.js @@ -0,0 +1,665 @@ +let { compare, benchmark, before } = require("buffalo-test"); + +const { mount, update, v } = require("../lib/index.ts"); + +const expect = require("expect"); +require("../plugins/node"); +const vOld = require("./index-old"); + +let VNext = v; + +let data = { + before: [], + before2: [], + update1: [], + update2: [] +}; + +function createNode({ className, i }, v) { + return v( + "div", + { + class: className, + data: i, + onbeforeupdate(n, o) { + return n.props.data !== o.props.data || n.props.class !== o.props.class; + }, + id: className + i, + style: "font-size:" + i + "px", + autocomplete: "off", + focus: false, + onclick() { + // console.log("clicked", this); + } + }, + "Hello" + ); +} + +for (let i = 1000; i--; ) { + data.before.push(createNode({ className: "ok", i }, vOld)); + data.before2.push(createNode({ className: "ok", i }, VNext)); + if (i % 3) { + data.before.push(createNode({ className: "ok", i: i + 3 }, vOld)); + data.before2.push(createNode({ className: "ok", i: i + 3 }, VNext)); + } else { + data.before.push(createNode({ className: "not-ok", i }, vOld)); + data.before2.push(createNode({ className: "not-ok", i }, VNext)); + } + data.update1.push(createNode({ className: "ok", i: 1000 - i }, vOld)); + data.update2.push(createNode({ className: "ok", i: 1000 - i }, VNext)); +} + +compare("Mount and update: Mount multiple types", () => { + let date = new Date(); + let useData = false; + let Component = () => vOld("div", null, [null, "Hello", , 1, date, { hello: "world" }, ["Hello"]], useData ? data.before : null); + let Component2 = () => VNext("div", null, [null, "Hello", , 1, date, { hello: "world" }, ["Hello"]], useData ? data.before2 : null); + + before(() => { + expect(vOld.mount("body", Component)).toEqual(`
Hello1${date}[object Object]Hello
`); + expect(mount("body", Component2)).toEqual(`
Hello1${date}[object Object]Hello
`); + useData = true; + }); + + benchmark("Valyrian 5.0.8", () => { + vOld.unMount(); + vOld.mount("body", Component); + }); + + benchmark("Valyrian next", () => { + mount("body", Component2); + }); +}); + +compare("Mount and update: Mount single text", () => { + let Component = () => "hello world"; + let Component2 = () => "hello world"; + + before(() => { + expect(vOld.mount("body", Component)).toEqual(`hello world`); + expect(mount("body", Component2)).toEqual(`hello world`); + }); + + benchmark("Valyrian 5.0.8", () => { + vOld.unMount(); + vOld.mount("body", Component); + }); + + benchmark("Valyrian next", () => { + mount("body", Component2); + }); +}); + +compare("Mount and update: Mount single text in div", () => { + let Component = () => vOld("div", null, ["hello world"]); + let Component2 = () => VNext("div", null, ["hello world"]); + + before(() => { + expect(vOld.mount("body", Component)).toEqual(`
hello world
`); + expect(mount("body", Component2)).toEqual(`
hello world
`); + }); + + benchmark("Valyrian 5.0.8", () => { + vOld.unMount(); + vOld.mount("body", Component); + }); + + benchmark("Valyrian next", () => { + mount("body", Component2); + }); +}); + +compare("Mount and update: Update multiple types", () => { + let date = new Date(); + let useData = false; + let updateData = false; + let Component = () => + vOld("div", null, [null, "Hello", , 1, date, { hello: "world" }, ["Hello"]], useData ? (updateData ? data.update1 : data.before) : null); + let Component2 = () => + VNext("div", null, [null, "Hello", , 1, date, { hello: "world" }, ["Hello"]], useData ? (updateData ? data.update2 : data.before2) : null); + + before(async () => { + let oldDate = date; + expect(vOld.mount("body", Component)).toEqual(`
Hello1${oldDate}[object Object]Hello
`); + await new Promise((resolve) => setTimeout(resolve, 1000)); + date = new Date(); + expect(vOld.update()).toEqual(`
Hello1${date}[object Object]Hello
`); + + date = oldDate; + let before = mount("body", Component2); + expect(before).toEqual(`
Hello1${oldDate}[object Object]Hello
`); + await new Promise((resolve) => setTimeout(resolve, 1000)); + date = new Date(); + let after = update(Component2); + expect(after).toEqual(`
Hello1${date}[object Object]Hello
`); + + useData = true; + vOld.unMount(); + vOld.mount("body", Component); + mount("body", Component2); + }); + + benchmark("Valyrian 5.0.8", () => { + updateData = true; + vOld.update(); + updateData = false; + vOld.update(); + updateData = true; + vOld.update(); + updateData = false; + }); + + benchmark("Valyrian next", () => { + updateData = true; + update(Component2); + updateData = false; + update(Component2); + updateData = true; + update(Component2); + updateData = false; + }); +}); + +compare("Mount and update: Update single text", () => { + let updateData = false; + let Component = () => vOld("div", null, [updateData ? "hello moon" : "hello world"]); + let Component2 = () => VNext("div", null, [updateData ? "hello moon" : "hello world"]); + + before(() => { + expect(vOld.mount("body", Component)).toEqual(`
hello world
`); + expect(mount("body", Component2)).toEqual(`
hello world
`); + updateData = true; + expect(vOld.update()).toEqual(`
hello moon
`); + expect(update(Component2)).toEqual(`
hello moon
`); + updateData = false; + vOld.unMount(); + vOld.mount("body", Component); + mount("body", Component2); + }); + + benchmark("Valyrian 5.0.8", () => { + updateData = true; + vOld.update(); + updateData = false; + vOld.update(); + updateData = true; + vOld.update(); + }); + + benchmark("Valyrian next", () => { + updateData = true; + update(Component2); + updateData = false; + update(Component2); + updateData = true; + update(Component2); + }); +}); + +compare("Mount and update: Render list", () => { + let set = [1, 2, 3, 4, 5]; + let tests = [ + { name: "Removed at the end", set: [1, 2, 3, 4] }, // Removed at the end + { name: "Removed at the start", set: [2, 3, 4, 5] }, // Remmoved at the start + { name: "Removed at the center", set: [1, 3, 5] }, // Removed at the center + { name: "Added at the end", set: [1, 2, 3, 4, 5, 6] }, // Added at the end + { name: "Added at the start", set: [6, 1, 2, 3, 4, 5] }, // Added at the start + { name: "Added at the center", set: [1, 2, 6, 3, 4, 5] }, // Added at the center + { name: "Reversed", set: [5, 4, 3, 2, 1] }, // Reversed + { name: "Switch positions", set: [5, 2, 3, 4, 1] }, // Switch positions, + { name: "Mixed positions", set: [1, 3, 2, 6, 5, 4] }, + { name: "Replaced with undefined", set: [1, 3, 2, , 5, 4] }, + { + name: "Added, remove and replaced with undefined", + set: [6, 7, 8, 9, , 10] + }, + { name: "Removed all at the end", set: [1] } // Removed at the end + ]; + + function getString(set) { + let str = ""; + return str; + } + let beforeString = getString(set); + + tests.forEach((test) => { + before(() => { + let keys = [...set]; + let component = () => + vOld( + "ul", + null, + keys.map((key) => { + if (key) { + return vOld("li", null, key); + } + }) + ); + + vOld.unMount(); + let before = vOld.mount("body", component); + keys = [...test.set]; + let after = vOld.update(); + + let afterString = getString(test.set); + + expect(before).toEqual(beforeString); + expect(after).toEqual(afterString); + }); + + before(() => { + let keys = [...set]; + let component = () => + VNext( + "ul", + null, + keys.map((key) => { + if (key) { + return VNext("li", null, key); + } + }) + ); + + let before = mount("body", component); + keys = [...test.set]; + let after = update(component); + + let afterString = getString(test.set); + + expect(before).toEqual(beforeString); + expect(after).toEqual(afterString); + }); + }); + + benchmark(`vOld`, () => { + let keys = [...set]; + let component = () => + vOld( + "ul", + null, + keys.map((key) => { + if (key) { + return vOld("li", null, key); + } + }) + ); + + vOld.unMount(); + vOld.mount("body", component); + for (let test of tests) { + keys = [...test.set]; + vOld.update(); + } + }); + + benchmark(`VNext`, () => { + let keys = [...set]; + let component = () => + VNext( + "ul", + null, + keys.map((key) => { + if (key) { + return VNext("li", null, key); + } + }) + ); + + mount("body", component); + for (let test of tests) { + keys = [...test.set]; + update(component); + } + }); +}); + +compare("Mount and update: Render keyed list", () => { + let set = [1, 2, 3, 4, 5]; + let tests = [ + { name: "Removed at the end", set: [1, 2, 3, 4] }, // Removed at the end + { name: "Removed at the start", set: [2, 3, 4, 5] }, // Remmoved at the start + { name: "Removed at the center", set: [1, 3, 5] }, // Removed at the center + { name: "Added at the end", set: [1, 2, 3, 4, 5, 6] }, // Added at the end + { name: "Added at the start", set: [6, 1, 2, 3, 4, 5] }, // Added at the start + { name: "Added at the center", set: [1, 2, 6, 3, 4, 5] }, // Added at the center + { name: "Reversed", set: [5, 4, 3, 2, 1] }, // Reversed + { name: "Switch positions", set: [5, 2, 3, 4, 1] }, // Switch positions, + { name: "Mixed positions", set: [1, 3, 2, 6, 5, 4] }, + { name: "Replaced with undefined", set: [1, 3, 2, , 5, 4] }, + { + name: "Added, remove and replaced with undefined", + set: [6, 7, 8, 9, , 10] + }, + { name: "Removed all at the end", set: [1] } // Removed at the end + ]; + + function getString(set) { + let str = `"; + return str; + } + let beforeString = getString(set); + + tests.forEach((test) => { + before(() => { + let keys = [...set]; + let component = () => + vOld( + "ul", + null, + keys.map((key) => { + if (key) { + return vOld("li", { key }, key); + } + }) + ); + + let before = vOld.mount("body", component); + keys = [...test.set]; + let after = vOld.update(); + + let afterString = getString(test.set); + + expect(before).toEqual(beforeString); + expect(after).toEqual(afterString); + }); + + before(() => { + let keys = [...set]; + let component = () => + VNext( + "ul", + null, + keys.map((key) => { + if (key) { + return VNext("li", { key }, key); + } + }) + ); + + console.log(test.name); + let before = mount("body", component); + keys = [...test.set]; + let after = update(component); + + let afterString = getString(test.set); + + expect(before).toEqual(beforeString); + expect(after).toEqual(afterString); + }); + }); + + benchmark(`vOld`, () => { + let keys = [...set]; + let component = () => + vOld( + "ul", + null, + keys.map((key) => { + if (key) { + return vOld("li", { key }, key); + } + }) + ); + + for (let test of tests) { + vOld.unMount(); + vOld.mount("body", component); + keys = [...test.set]; + vOld.update(); + } + }); + + benchmark(`VNext`, () => { + let keys = [...set]; + let component = () => + VNext( + "ul", + null, + keys.map((key) => { + if (key) { + return VNext("li", { key }, key); + } + }) + ); + + for (let test of tests) { + mount("body", component); + keys = [...test.set]; + update(component); + } + }); +}); + +compare("Mount and update: Render keyed list -> stress", () => { + let set = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; + + let tests = [ + { name: "Removed at the end", set: [1, 2, 3, 4, 5, 6, 7, 8, 9], movements: 1 }, // Removed at the end + { name: "Removed at the start", set: [2, 3, 4, 5, 6, 7, 8, 9, 10], movements: 1 }, // Remmoved at the start + { name: "Removed at the center", set: [1, 2, 3, 5, 6, 8, 9, 10], movements: 2 }, // Removed at the center + { name: "Added at the end", set: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11], movements: 1 }, // Added at the end + { name: "Added at the start", set: [11, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10], movements: 1 }, // Added at the start + { name: "Added at the center", set: [1, 2, 3, 4, 5, 11, 6, 7, 8, 9, 10], movements: 1 }, // Added at the center + { name: "Reversed", set: [10, 9, 8, 7, 6, 5, 4, 3, 2, 1], movements: 9 }, // Reversed + { name: "Switch positions", set: [10, 2, 3, 4, 5, 6, 7, 8, 9, 1], movements: 2 }, // Switch positions, + { name: "Switch different positions", set: [10, 6, 3, 4, 2, 5, 7, 8, 9, 1], movements: 4 }, // Switch positions, + { name: "Mixed positions", set: [1, 3, 2, 6, 5, 4, 7, 8, 9, 10], movements: 3 }, + { name: "Replaced with undefined", set: [1, 3, 2, , 5, 4, 6, 7, 8, 9, 10], movements: 2 }, + { + name: "Added, remove and replaced with undefined", + set: [11, 12, 13, 14, 15, 16, 17, , 18, 19, 20], + movements: 10 + }, + { name: "Removed all at the end", set: [1], movements: 9 }, // Removed at the end + { name: "Switch positions in large list", set: [10, 2, 3, 4, 5, 6, 7, 8, 9, 1], movements: 2 } // Switch positions + ]; + + function getString(set) { + let str = `"; + return str; + } + let beforeString = getString(set); + + tests.forEach((test) => { + before(() => { + let keys = [...set]; + let component = () => + vOld( + "ul", + null, + keys.map((key) => { + if (key) { + return vOld("li", { key }, key); + } + }) + ); + + let before = vOld.mount("body", component); + keys = [...test.set]; + let after = vOld.update(); + + let afterString = getString(test.set); + + expect(before).toEqual(beforeString); + expect(after).toEqual(afterString); + }); + + before(() => { + let keys = [...set]; + let component = () => + VNext( + "ul", + null, + keys.map((key) => { + if (key) { + return VNext("li", { key }, key); + } + }) + ); + + console.log(test.name); + let before = mount("body", component); + keys = [...test.set]; + let after = update(component); + + let afterString = getString(test.set); + + expect(before).toEqual(beforeString); + expect(after).toEqual(afterString); + }); + }); + + benchmark(`vOld`, () => { + let keys = [...set]; + let component = () => + vOld( + "ul", + null, + keys.map((key) => { + if (key) { + return vOld("li", { key }, key); + } + }) + ); + + for (let test of tests) { + vOld.unMount(); + vOld.mount("body", component); + keys = [...test.set]; + vOld.update(); + } + }); + + benchmark(`VNext`, () => { + let keys = [...set]; + let component = () => + VNext( + "ul", + null, + keys.map((key) => { + if (key) { + return VNext("li", { key }, key); + } + }) + ); + + for (let test of tests) { + mount("body", component); + keys = [...test.set]; + update(component); + } + }); +}); + +compare("Mount and update: Render keyed list -> swap keys on large set", () => { + let set = [...Array(1000).keys()]; + let updatedLargeSet = [...set]; + updatedLargeSet[1] = 998; + updatedLargeSet[998] = 1; + + function getString(set) { + let str = `"; + return str; + } + let beforeString = getString(set); + + before(() => { + let keys = [...set]; + let component = () => + vOld( + "ul", + null, + keys.map((key) => { + if (key !== undefined) { + return vOld("li", { key }, key); + } + }) + ); + + let before = vOld.mount("body", component); + keys = [...updatedLargeSet]; + let after = vOld.update(); + + let afterString = getString(updatedLargeSet); + + expect(before).toEqual(beforeString); + expect(after).toEqual(afterString); + }); + + before(() => { + let keys = [...set]; + let component = () => + VNext( + "ul", + null, + keys.map((key) => { + if (key !== undefined) { + return VNext("li", { key }, key); + } + }) + ); + + let before = mount("body", component); + keys = [...updatedLargeSet]; + let after = update(component); + + let afterString = getString(updatedLargeSet); + + expect(before).toEqual(beforeString); + expect(after).toEqual(afterString); + }); + + benchmark(`vOld`, () => { + let keys = [...set]; + let component = () => + vOld( + "ul", + null, + keys.map((key) => { + if (key !== undefined) { + return vOld("li", { key }, key); + } + }) + ); + + vOld.unMount(); + vOld.mount("body", component); + keys = [...updatedLargeSet]; + vOld.update(); + }); + + benchmark(`VNext`, () => { + let keys = [...set]; + let component = () => + VNext( + "ul", + null, + keys.map((key) => { + if (key !== undefined) { + return VNext("li", { key }, key); + } + }) + ); + + mount("body", component); + keys = [...updatedLargeSet]; + update(component); + }); +}); diff --git a/dist/@types/lib/index.d.ts b/dist/@types/lib/index.d.ts index a0f4dbe..aa7226b 100644 --- a/dist/@types/lib/index.d.ts +++ b/dist/@types/lib/index.d.ts @@ -1,106 +1,7 @@ -declare type VnodeOrUnknown = VnodeComponent | Vnode | TextVnode | any; -declare type DomAttribute = { - nodeName: string; - nodeValue: string; -}; -declare type DomElement = (HTMLElement | SVGElement) & Record; -declare type Props = { - key?: string | number; - data?: string; - oncreate?: { - (vnode: Vnode): never; - }; - onupdate?: { - (vnode: Vnode, oldVnode: Vnode | TextVnode): never; - }; - onremove?: { - (oldVnode: Vnode): never; - }; - onbeforeupdate?: { - (vnode: Vnode, oldVnode: Vnode | TextVnode): undefined | boolean; - }; -} & Record; -declare type Component = (props?: Record | null, children?: VnodeOrUnknown) => VnodeOrUnknown | VnodeOrUnknown[]; -declare type ValyrianComponent = Component | (Record & { - view: Component; -}); -declare type Current = { - parentVnode?: Vnode; - oldParentVnode?: Vnode; - component?: VnodeComponent; -}; -interface Plugin { - (v: Valyrian, options?: Record): never; +declare class Vnode { + tag: string; + props: {}; + children: []; + constructor(tag: string, props: {}, children: []); } -interface Directive { - (value: any, vnode: Vnode, oldVnode?: Vnode | TextVnode): void | boolean; -} -interface ValyrianEventHandler { - (a: Event, dom: DomElement): void; -} -interface Vnode { - name: string; - props: Props; - children: VnodeOrUnknown[]; - dom?: DomElement; - onCleanup?: FunctionConstructor[]; - isSVG?: boolean; - processed?: boolean; -} -declare class Vnode implements Vnode { - name: string; - props: Props; - children: VnodeOrUnknown[]; - dom?: DomElement; - onCleanup?: FunctionConstructor[]; - isSVG?: boolean; - processed?: boolean; - constructor(name: string, props: Props, children: VnodeOrUnknown); -} -interface TextVnode { - dom?: Text; - nodeValue: string; -} -declare class TextVnode implements TextVnode { - dom?: Text; - nodeValue: string; - constructor(nodeValue: string); -} -interface VnodeComponent { - component: ValyrianComponent; - props: Props; - children: VnodeOrUnknown[]; -} -declare class VnodeComponent implements VnodeComponent { - component: ValyrianComponent; - props: Props; - children: VnodeOrUnknown[]; - constructor(component: ValyrianComponent, props: Props, children: VnodeOrUnknown[]); -} -interface Valyrian { - (tagOrComponent: string | ValyrianComponent, props?: Props | null, children?: VnodeOrUnknown): Vnode | VnodeComponent; - fragment: (props: Props, children: VnodeOrUnknown[]) => VnodeOrUnknown[]; - isMounted: boolean; - isNode: boolean; - reservedWords: string[]; - current: Current; - trust: (htmlString: string) => Vnode[]; - usePlugin: (plugin: Plugin, options: Record) => void; - onCleanup: (callback: typeof Function) => void; - updateProperty: (name: string, newVnode: Vnode & { - dom: DomElement; - }, oldNode: Vnode & { - dom: DomElement; - }) => void; - update: (props?: Props | null, ...children: VnodeOrUnknown) => string | void; - mount: (container: string | DomElement, component: ValyrianComponent, props?: Props | null, ...children: VnodeOrUnknown[]) => string | void; - unMount: () => string | boolean | void; - directive: (directive: string, handler: Directive) => void; - newInstance: () => Valyrian; - [x: string]: any; -} -declare let isNode: boolean; -declare function createElement(tagName: string, isSVG?: boolean): DomElement; -declare function domToVnode(dom: DomElement): Vnode; -declare const trust: (htmlString: string) => Vnode[]; -declare function valyrian(): Valyrian; +export { Vnode }; diff --git a/dist/@types/lib/index_.d.ts b/dist/@types/lib/index_.d.ts new file mode 100644 index 0000000..a0f4dbe --- /dev/null +++ b/dist/@types/lib/index_.d.ts @@ -0,0 +1,106 @@ +declare type VnodeOrUnknown = VnodeComponent | Vnode | TextVnode | any; +declare type DomAttribute = { + nodeName: string; + nodeValue: string; +}; +declare type DomElement = (HTMLElement | SVGElement) & Record; +declare type Props = { + key?: string | number; + data?: string; + oncreate?: { + (vnode: Vnode): never; + }; + onupdate?: { + (vnode: Vnode, oldVnode: Vnode | TextVnode): never; + }; + onremove?: { + (oldVnode: Vnode): never; + }; + onbeforeupdate?: { + (vnode: Vnode, oldVnode: Vnode | TextVnode): undefined | boolean; + }; +} & Record; +declare type Component = (props?: Record | null, children?: VnodeOrUnknown) => VnodeOrUnknown | VnodeOrUnknown[]; +declare type ValyrianComponent = Component | (Record & { + view: Component; +}); +declare type Current = { + parentVnode?: Vnode; + oldParentVnode?: Vnode; + component?: VnodeComponent; +}; +interface Plugin { + (v: Valyrian, options?: Record): never; +} +interface Directive { + (value: any, vnode: Vnode, oldVnode?: Vnode | TextVnode): void | boolean; +} +interface ValyrianEventHandler { + (a: Event, dom: DomElement): void; +} +interface Vnode { + name: string; + props: Props; + children: VnodeOrUnknown[]; + dom?: DomElement; + onCleanup?: FunctionConstructor[]; + isSVG?: boolean; + processed?: boolean; +} +declare class Vnode implements Vnode { + name: string; + props: Props; + children: VnodeOrUnknown[]; + dom?: DomElement; + onCleanup?: FunctionConstructor[]; + isSVG?: boolean; + processed?: boolean; + constructor(name: string, props: Props, children: VnodeOrUnknown); +} +interface TextVnode { + dom?: Text; + nodeValue: string; +} +declare class TextVnode implements TextVnode { + dom?: Text; + nodeValue: string; + constructor(nodeValue: string); +} +interface VnodeComponent { + component: ValyrianComponent; + props: Props; + children: VnodeOrUnknown[]; +} +declare class VnodeComponent implements VnodeComponent { + component: ValyrianComponent; + props: Props; + children: VnodeOrUnknown[]; + constructor(component: ValyrianComponent, props: Props, children: VnodeOrUnknown[]); +} +interface Valyrian { + (tagOrComponent: string | ValyrianComponent, props?: Props | null, children?: VnodeOrUnknown): Vnode | VnodeComponent; + fragment: (props: Props, children: VnodeOrUnknown[]) => VnodeOrUnknown[]; + isMounted: boolean; + isNode: boolean; + reservedWords: string[]; + current: Current; + trust: (htmlString: string) => Vnode[]; + usePlugin: (plugin: Plugin, options: Record) => void; + onCleanup: (callback: typeof Function) => void; + updateProperty: (name: string, newVnode: Vnode & { + dom: DomElement; + }, oldNode: Vnode & { + dom: DomElement; + }) => void; + update: (props?: Props | null, ...children: VnodeOrUnknown) => string | void; + mount: (container: string | DomElement, component: ValyrianComponent, props?: Props | null, ...children: VnodeOrUnknown[]) => string | void; + unMount: () => string | boolean | void; + directive: (directive: string, handler: Directive) => void; + newInstance: () => Valyrian; + [x: string]: any; +} +declare let isNode: boolean; +declare function createElement(tagName: string, isSVG?: boolean): DomElement; +declare function domToVnode(dom: DomElement): Vnode; +declare const trust: (htmlString: string) => Vnode[]; +declare function valyrian(): Valyrian; diff --git a/dist/valyrian.min.js b/dist/valyrian.min.js index 5e65e94..ac8221d 100644 --- a/dist/valyrian.min.js +++ b/dist/valyrian.min.js @@ -1 +1,13 @@ -(()=>{var e=class{name;props;children;dom;onCleanup;isSVG;processed;constructor(e,o,n){this.props=o,this.children=n,this.name=e}},o=class{dom;nodeValue;constructor(e){this.nodeValue=e}},n=class{component;props;children;constructor(e,o,n){this.props=o,this.children=n,this.component=e}},t="undefined"==typeof window||"undefined"!=typeof global;function d(e,o=!1){return o?document.createElementNS("http://www.w3.org/2000/svg",e):document.createElement(e)}function r(n){let t={};[].forEach.call(n.attributes,e=>t[e.nodeName]=e.nodeValue);let d=new e(n.nodeName.toLowerCase(),t,[]);d.dom=n;for(let e=0,t=n.childNodes.length;e{let o=d("div");return o.innerHTML=e.trim(),[].map.call(o.childNodes,e=>r(e))};(t?global:window).v=function p(){let l=(o,t,...d)=>"string"==typeof o?new e(o,t||{},d):new n(o,t||{},d);l.fragment=(e,o)=>o,l.isMounted=!1,l.isNode=t;let s=["key","data","v-once","oncreate","onupdate","onremove","onbeforeupdate"];l.reservedWords=s,l.trust=i;let c={parentVnode:void 0,oldParentVnode:void 0,component:void 0};l.current=c;let a=new Map;l.usePlugin=(e,o={})=>!a.has(e)&&a.set(e,!0)&&e(l,o);let m=[];l.onCleanup=e=>{let o=l.current.parentVnode;o.onCleanup||(o.onCleanup=[]),o.onCleanup.push(e),-1===m.indexOf(o)&&m.push(o)};let u=null,f=()=>"",h=f,v=[];function V(e){let o=e.target,n=`v-on${e.type}`;for(;o;){if(o[n])return o[n](e,o),void(e.defaultPrevented||l.update());o=o.parentNode}}function g(e,o,n){if(-1!==s.indexOf(e)){if(e in M)return M[e](o.props[e],o,n)}else"function"==typeof o.props[e]?(-1===v.indexOf(e)&&(u.addEventListener(e.slice(2),V),v.push(e)),o.dom[`v-${e}`]=o.props[e]):e in o.dom&&!o.isSVG?o.dom[e]!=o.props[e]&&(o.dom[e]=o.props[e]):(void 0===n||o.props[e]!==n.props[e])&&(!1===o.props[e]?o.dom.removeAttribute(e):o.dom.setAttribute(e,o.props[e]))}function y(e,o){for(let n in e.props)if(!1===g(n,e,o))return}function N(e,o){for(let n in o.props)!(n in e.props)&&"function"!=typeof o.props[n]&&-1===s.indexOf(n)&&(n in e.dom?e.dom[n]=null:e.dom.removeAttribute(n))}l.updateProperty=g;let w=o=>{for(let n=0,t=o.children.length;n0&&p[d-1].nodeValue?(p[d-1].nodeValue+=r,p.splice(d--,1)):r instanceof o||(p[d]=new o(String(r)))}let a=p.length;if(0===a){if(s>0){for(let o=s;o--;)i[o]instanceof e&&w(i[o]);t.dom.textContent=""}}else if(s&&p[0]instanceof e&&"key"in p[0].props){let o;if(i[0]instanceof e&&"key"in i[0].props)o=i.map(e=>e.props.key);else{for(let o=s;o--;)i[o]instanceof e&&w(i[o]);t.dom.textContent="",o=[]}let n=p.map(e=>e.props.key),r=Math.max(a,o.length);for(let s=0;s=a;--o)i[o]instanceof e&&w(i[o]),i[o].dom.parentNode&&t.dom.removeChild(i[o].dom)}t.children=p}let x=null,S=null;l.unMount=()=>{h=f;let e=l.update();return l.isMounted=!1,u=null,e},l.update=(o,...n)=>{if(x&&((()=>{for(let e=m.length;e--;)for(let o of m[e].onCleanup)o();m=[]})(),S=x,x=new e(x.name,x.props,[l(h,o,...n)]),x.dom=S.dom,x.isSVG=S.isSVG,C(x,S),l.isMounted=!0,l.isNode))return x.dom.innerHTML},l.mount=(e,o,n,...i)=>(l.isMounted&&l.unMount(),u=t?"string"==typeof e?d(e,"svg"===e):e:"string"==typeof e?document.querySelectorAll(e)[0]:e,null!==u&&(x=r(u),x.isSVG="svg"===x.name,S=x,h=o),l.update(n,...i));let M={};l.directive=(e,o)=>{let n=`v-${e}`;-1===s.indexOf(n)&&(s.push(n),M[n]=o)};let b=o=>(n,t,d)=>{if(o?n:!n){let o=document.createTextNode("");return d&&d.dom&&d.dom.parentNode&&(d instanceof e&&w(d),d.dom.parentNode.replaceChild(o,d.dom)),t.name="#text",t.children=[],t.props={},t.dom=o,!1}};return l.directive("if",b(!1)),l.directive("unless",b(!0)),l.directive("for",(e,o)=>{o.children=e.map(o.children[0])}),l.directive("show",(e,o)=>{o.dom.style.display=e?"":"none"}),l.directive("class",(e,o)=>{for(let n in e)o.dom.classList.toggle(n,e[n])}),l.directive("html",(e,o)=>{o.children=[i(e)]}),l.newInstance=p,l}()})(); \ No newline at end of file +(() => { + // lib/index.ts + var Vnode = class { + tag; + props; + children; + constructor(tag, props, children) { + this.props = props; + this.children = children; + this.tag = tag; + } + }; +})(); diff --git a/dist/valyrian.min.js.map b/dist/valyrian.min.js.map index f9679e9..fced6db 100644 --- a/dist/valyrian.min.js.map +++ b/dist/valyrian.min.js.map @@ -1 +1 @@ -//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL2xpYi9pbmRleC50cyJdLCJuYW1lcyI6WyJwIiwibmFtZSIsInByb3BzIiwiY2hpbGRyZW4iLCJkb20iLCJvbkNsZWFudXAiLCJpc1NWRyIsInByb2Nlc3NlZCIsImNvbnN0cnVjdG9yIiwiYSIsInUiLCJjIiwidGhpcyIsIngiLCJub2RlVmFsdWUiLCJNIiwiY29tcG9uZW50IiwiUyIsIndpbmRvdyIsImdsb2JhbCIsImIiLCJkIiwiZG9jdW1lbnQiLCJjcmVhdGVFbGVtZW50TlMiLCJjcmVhdGVFbGVtZW50IiwiVSIsImZvckVhY2giLCJjYWxsIiwiYXR0cmlidXRlcyIsIm5vZGVOYW1lIiwidG9Mb3dlckNhc2UiLCJ5IiwiY2hpbGROb2RlcyIsImxlbmd0aCIsIm5vZGVUeXBlIiwicHVzaCIsIk4iLCJGIiwiaW5uZXJIVE1MIiwidHJpbSIsIm1hcCIsInYiLCJIIiwiZSIsIm8iLCJ0IiwiZnJhZ21lbnQiLCJpc01vdW50ZWQiLCJpc05vZGUiLCJyZXNlcnZlZFdvcmRzIiwidHJ1c3QiLCJwYXJlbnRWbm9kZSIsIm9sZFBhcmVudFZub2RlIiwiY3VycmVudCIsIk1hcCIsInVzZVBsdWdpbiIsImhhcyIsInNldCIsImluZGV4T2YiLCJnIiwidyIsIlQiLCJMIiwiVyIsInRhcmdldCIsInR5cGUiLCJkZWZhdWx0UHJldmVudGVkIiwidXBkYXRlIiwicGFyZW50Tm9kZSIsIkciLCJPIiwiYWRkRXZlbnRMaXN0ZW5lciIsInNsaWNlIiwicmVtb3ZlQXR0cmlidXRlIiwic2V0QXR0cmlidXRlIiwiRSIsIlAiLCJ1cGRhdGVQcm9wZXJ0eSIsIlYiLCJvbnJlbW92ZSIsIkQiLCJsIiwiQyIsInIiLCJuIiwic3BsaWNlIiwiQXJyYXkiLCJpc0FycmF5IiwidmlldyIsIlN0cmluZyIsInRleHRDb250ZW50IiwiaSIsImtleSIsIm0iLCJNYXRoIiwibWF4IiwicyIsImgiLCJBIiwib25iZWZvcmV1cGRhdGUiLCJvbnVwZGF0ZSIsIm9uY3JlYXRlIiwiYXBwZW5kQ2hpbGQiLCJyZXBsYWNlQ2hpbGQiLCJyZW1vdmVDaGlsZCIsImNyZWF0ZVRleHROb2RlIiwiZiIsImsiLCJ1bk1vdW50IiwibW91bnQiLCJxdWVyeVNlbGVjdG9yQWxsIiwiZGlyZWN0aXZlIiwiUiIsInN0eWxlIiwiZGlzcGxheSIsImNsYXNzTGlzdCIsInRvZ2dsZSIsIm5ld0luc3RhbmNlIl0sIm1hcHBpbmdzIjoiTUFvREEsSUFBQUEsRUFBQSxNQUNFQyxLQUNBQyxNQUNBQyxTQUNBQyxJQUNBQyxVQUNBQyxNQUNBQyxVQUVBQyxZQUFZQyxFQUFjQyxFQUFjQyxHQUN0Q0MsS0FBS1YsTUFBUVEsRUFDYkUsS0FBS1QsU0FBV1EsRUFDaEJDLEtBQUtYLEtBQU9RLElBU2hCSSxFQUFBLE1BQ0VULElBQ0FVLFVBRUFOLFlBQVlDLEdBQ1ZHLEtBQUtFLFVBQVlMLElBVXJCTSxFQUFBLE1BQ0VDLFVBQ0FkLE1BQ0FDLFNBRUFLLFlBQVlDLEVBQThCQyxFQUFjQyxHQUN0REMsS0FBS1YsTUFBUVEsRUFDYkUsS0FBS1QsU0FBV1EsRUFDaEJDLEtBQUtJLFVBQVlQLElBdUJqQlEsRUFBMkIsb0JBQVhDLFFBQTRDLG9CQUFYQyxPQUdyRCxTQUFBQyxFQUF1QkMsRUFBaUJaLEdBQWlCLEdBQ3ZELE9BQU9BLEVBQVFhLFNBQVNDLGdCQUFnQiw2QkFBOEJGLEdBQVdDLFNBQVNFLGNBQWNILEdBSTFHLFNBQUFJLEVBQW9CSixHQUNsQixJQUFJWixFQUFlLEdBQ25CLEdBQUdpQixRQUFRQyxLQUFLTixFQUFJTyxXQUFhakIsR0FBZ0JGLEVBQU1FLEVBQUtrQixVQUFZbEIsRUFBS0csV0FFN0UsSUFBSUosRUFBZSxJQUFJVixFQUFNcUIsRUFBSVEsU0FBU0MsY0FBZXJCLEVBQU8sSUFDaEVDLEVBQU1OLElBQU1pQixFQUVaLElBQUEsSUFBU1YsRUFBSSxFQUFHb0IsRUFBSVYsRUFBSVcsV0FBV0MsT0FBUXRCLEVBQUlvQixFQUFHcEIsSUFDaEQsR0FBbUMsSUFBL0JVLEVBQUlXLFdBQVdyQixHQUFHdUIsU0FDcEJ4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QVNtRixlQUFlLElBQ3JDLE9BQUl4QixHQUFXQSxFQUFRN0UsS0FBTzZFLEVBQVE3RSxJQUFJZ0UsYUFDeENhLGFBQW1CakYsR0FBUzhFLEVBQVdHLEdBQ3ZDQSxFQUFRN0UsSUFBSWdFLFdBQVdtQyxhQUFhOUQsRUFBUXdDLEVBQVE3RSxNQUV0RHlDLEVBQU01QyxLQUFPLFFBQ2I0QyxFQUFNMUMsU0FBVyxHQUNqQjBDLEVBQU0zQyxNQUFRLEdBQ2QyQyxFQUFNekMsSUFBTXFDLEdBQ0wsSUFJWCxPQUFBcEIsRUFBRTBGLFVBQVUsS0FBTUMsR0FBYyxJQUNoQzNGLEVBQUUwRixVQUFVLFNBQVVDLEdBQWMsSUFDcEMzRixFQUFFMEYsVUFBVSxNQUFPLENBQUNwRSxFQUFnQkMsS0FDbENBLEVBQU16QyxTQUFXd0MsRUFBSUgsSUFBSUksRUFBTXpDLFNBQVMsTUFFMUNrQixFQUFFMEYsVUFBVSxPQUFRLENBQUNwRSxFQUFlQyxLQUNqQ0EsRUFBTXhDLElBQXVDNkcsTUFBTUMsUUFBVXZFLEVBQU8sR0FBSyxTQUU1RXRCLEVBQUUwRixVQUFVLFFBQVMsQ0FBQ3BFLEVBQW1DQyxLQUN2RCxJQUFBLElBQVNDLEtBQVFGLEVBQ2RDLEVBQU14QyxJQUFtQitHLFVBQVVDLE9BQU92RSxFQUFNRixFQUFRRSxNQUc3RHhCLEVBQUUwRixVQUFVLE9BQVEsQ0FBQ3BFLEVBQWNDLEtBQ2pDQSxFQUFNekMsU0FBVyxDQUFDa0MsRUFBTU0sTUFHMUJ0QixFQUFFZ0csWUFBYzNFLEVBRVRyQixFQUdzRHFCIiwic291cmNlc0NvbnRlbnQiOlsiLyogZXNsaW50LWRpc2FibGUgY29tcGxleGl0eSAqL1xuLyogZXNsaW50LWRpc2FibGUgc29uYXJqcy9jb2duaXRpdmUtY29tcGxleGl0eSAqL1xuLyogZXNsaW50LWRpc2FibGUgbm8tdXNlLWJlZm9yZS1kZWZpbmUgKi9cbi8qIGVzbGludC1kaXNhYmxlIG5vLXVudXNlZC12YXJzICovXG5cbnR5cGUgVm5vZGVPclVua25vd24gPSBWbm9kZUNvbXBvbmVudCB8IFZub2RlIHwgVGV4dFZub2RlIHwgYW55O1xuXG50eXBlIERvbUF0dHJpYnV0ZSA9IHsgbm9kZU5hbWU6IHN0cmluZzsgbm9kZVZhbHVlOiBzdHJpbmcgfTtcblxudHlwZSBEb21FbGVtZW50ID0gKEhUTUxFbGVtZW50IHwgU1ZHRWxlbWVudCkgJiBSZWNvcmQ8c3RyaW5nLCBhbnk+O1xuXG50eXBlIFByb3BzID0ge1xuICBrZXk/OiBzdHJpbmcgfCBudW1iZXI7XG4gIGRhdGE/OiBzdHJpbmc7XG4gIG9uY3JlYXRlPzogeyAodm5vZGU6IFZub2RlKTogbmV2ZXIgfTtcbiAgb251cGRhdGU/OiB7ICh2bm9kZTogVm5vZGUsIG9sZFZub2RlOiBWbm9kZSB8IFRleHRWbm9kZSk6IG5ldmVyIH07XG4gIG9ucmVtb3ZlPzogeyAob2xkVm5vZGU6IFZub2RlKTogbmV2ZXIgfTtcbiAgb25iZWZvcmV1cGRhdGU/OiB7ICh2bm9kZTogVm5vZGUsIG9sZFZub2RlOiBWbm9kZSB8IFRleHRWbm9kZSk6IHVuZGVmaW5lZCB8IGJvb2xlYW4gfTtcbn0gJiBSZWNvcmQ8c3RyaW5nLCBhbnk+O1xuXG50eXBlIENvbXBvbmVudCA9IChwcm9wcz86IFJlY29yZDxzdHJpbmcsIGFueT4gfCBudWxsLCBjaGlsZHJlbj86IFZub2RlT3JVbmtub3duKSA9PiBWbm9kZU9yVW5rbm93biB8IFZub2RlT3JVbmtub3duW107XG5cbnR5cGUgVmFseXJpYW5Db21wb25lbnQgPVxuICB8IENvbXBvbmVudFxuICB8IChSZWNvcmQ8c3RyaW5nLCBhbnk+ICYge1xuICAgICAgdmlldzogQ29tcG9uZW50O1xuICAgIH0pO1xuXG50eXBlIEN1cnJlbnQgPSB7IHBhcmVudFZub2RlPzogVm5vZGU7IG9sZFBhcmVudFZub2RlPzogVm5vZGU7IGNvbXBvbmVudD86IFZub2RlQ29tcG9uZW50IH07XG5cbmludGVyZmFjZSBQbHVnaW4ge1xuICAodjogVmFseXJpYW4sIG9wdGlvbnM/OiBSZWNvcmQ8c3RyaW5nLCBhbnk+KTogbmV2ZXI7XG59XG5cbmludGVyZmFjZSBEaXJlY3RpdmUge1xuICAodmFsdWU6IGFueSwgdm5vZGU6IFZub2RlLCBvbGRWbm9kZT86IFZub2RlIHwgVGV4dFZub2RlKTogdm9pZCB8IGJvb2xlYW47XG59XG5cbmludGVyZmFjZSBWYWx5cmlhbkV2ZW50SGFuZGxlciB7XG4gIChhOiBFdmVudCwgZG9tOiBEb21FbGVtZW50KTogdm9pZDtcbn1cblxuaW50ZXJmYWNlIFZub2RlIHtcbiAgbmFtZTogc3RyaW5nO1xuICBwcm9wczogUHJvcHM7XG4gIGNoaWxkcmVuOiBWbm9kZU9yVW5rbm93bltdO1xuICBkb20/OiBEb21FbGVtZW50O1xuICBvbkNsZWFudXA/OiBGdW5jdGlvbkNvbnN0cnVjdG9yW107XG4gIGlzU1ZHPzogYm9vbGVhbjtcbiAgcHJvY2Vzc2VkPzogYm9vbGVhbjtcbn1cblxuY2xhc3MgVm5vZGUgaW1wbGVtZW50cyBWbm9kZSB7XG4gIG5hbWU6IHN0cmluZztcbiAgcHJvcHM6IFByb3BzO1xuICBjaGlsZHJlbjogVm5vZGVPclVua25vd25bXTtcbiAgZG9tPzogRG9tRWxlbWVudDtcbiAgb25DbGVhbnVwPzogRnVuY3Rpb25Db25zdHJ1Y3RvcltdO1xuICBpc1NWRz86IGJvb2xlYW47XG4gIHByb2Nlc3NlZD86IGJvb2xlYW47XG5cbiAgY29uc3RydWN0b3IobmFtZTogc3RyaW5nLCBwcm9wczogUHJvcHMsIGNoaWxkcmVuOiBWbm9kZU9yVW5rbm93bikge1xuICAgIHRoaXMucHJvcHMgPSBwcm9wcztcbiAgICB0aGlzLmNoaWxkcmVuID0gY2hpbGRyZW47XG4gICAgdGhpcy5uYW1lID0gbmFtZTtcbiAgfVxufVxuXG5pbnRlcmZhY2UgVGV4dFZub2RlIHtcbiAgZG9tPzogVGV4dDtcbiAgbm9kZVZhbHVlOiBzdHJpbmc7XG59XG5cbmNsYXNzIFRleHRWbm9kZSBpbXBsZW1lbnRzIFRleHRWbm9kZSB7XG4gIGRvbT86IFRleHQ7XG4gIG5vZGVWYWx1ZTogc3RyaW5nO1xuXG4gIGNvbnN0cnVjdG9yKG5vZGVWYWx1ZTogc3RyaW5nKSB7XG4gICAgdGhpcy5ub2RlVmFsdWUgPSBub2RlVmFsdWU7XG4gIH1cbn1cblxuaW50ZXJmYWNlIFZub2RlQ29tcG9uZW50IHtcbiAgY29tcG9uZW50OiBWYWx5cmlhbkNvbXBvbmVudDtcbiAgcHJvcHM6IFByb3BzO1xuICBjaGlsZHJlbjogVm5vZGVPclVua25vd25bXTtcbn1cblxuY2xhc3MgVm5vZGVDb21wb25lbnQgaW1wbGVtZW50cyBWbm9kZUNvbXBvbmVudCB7XG4gIGNvbXBvbmVudDogVmFseXJpYW5Db21wb25lbnQ7XG4gIHByb3BzOiBQcm9wcztcbiAgY2hpbGRyZW46IFZub2RlT3JVbmtub3duW107XG5cbiAgY29uc3RydWN0b3IoY29tcG9uZW50OiBWYWx5cmlhbkNvbXBvbmVudCwgcHJvcHM6IFByb3BzLCBjaGlsZHJlbjogVm5vZGVPclVua25vd25bXSkge1xuICAgIHRoaXMucHJvcHMgPSBwcm9wcztcbiAgICB0aGlzLmNoaWxkcmVuID0gY2hpbGRyZW47XG4gICAgdGhpcy5jb21wb25lbnQgPSBjb21wb25lbnQ7XG4gIH1cbn1cblxuaW50ZXJmYWNlIFZhbHlyaWFuIHtcbiAgKHRhZ09yQ29tcG9uZW50OiBzdHJpbmcgfCBWYWx5cmlhbkNvbXBvbmVudCwgcHJvcHM/OiBQcm9wcyB8IG51bGwsIGNoaWxkcmVuPzogVm5vZGVPclVua25vd24pOiBWbm9kZSB8IFZub2RlQ29tcG9uZW50O1xuICBmcmFnbWVudDogKHByb3BzOiBQcm9wcywgY2hpbGRyZW46IFZub2RlT3JVbmtub3duW10pID0+IFZub2RlT3JVbmtub3duW107XG4gIGlzTW91bnRlZDogYm9vbGVhbjtcbiAgaXNOb2RlOiBib29sZWFuO1xuICByZXNlcnZlZFdvcmRzOiBzdHJpbmdbXTtcbiAgY3VycmVudDogQ3VycmVudDtcbiAgdHJ1c3Q6IChodG1sU3RyaW5nOiBzdHJpbmcpID0+IFZub2RlW107XG4gIHVzZVBsdWdpbjogKHBsdWdpbjogUGx1Z2luLCBvcHRpb25zOiBSZWNvcmQ8c3RyaW5nLCBhbnk+KSA9PiB2b2lkO1xuICBvbkNsZWFudXA6IChjYWxsYmFjazogdHlwZW9mIEZ1bmN0aW9uKSA9PiB2b2lkO1xuICB1cGRhdGVQcm9wZXJ0eTogKG5hbWU6IHN0cmluZywgbmV3Vm5vZGU6IFZub2RlICYgeyBkb206IERvbUVsZW1lbnQgfSwgb2xkTm9kZTogVm5vZGUgJiB7IGRvbTogRG9tRWxlbWVudCB9KSA9PiB2b2lkO1xuICB1cGRhdGU6IChwcm9wcz86IFByb3BzIHwgbnVsbCwgLi4uY2hpbGRyZW46IFZub2RlT3JVbmtub3duKSA9PiBzdHJpbmcgfCB2b2lkO1xuICBtb3VudDogKGNvbnRhaW5lcjogc3RyaW5nIHwgRG9tRWxlbWVudCwgY29tcG9uZW50OiBWYWx5cmlhbkNvbXBvbmVudCwgcHJvcHM/OiBQcm9wcyB8IG51bGwsIC4uLmNoaWxkcmVuOiBWbm9kZU9yVW5rbm93bltdKSA9PiBzdHJpbmcgfCB2b2lkO1xuICB1bk1vdW50OiAoKSA9PiBzdHJpbmcgfCBib29sZWFuIHwgdm9pZDtcbiAgZGlyZWN0aXZlOiAoZGlyZWN0aXZlOiBzdHJpbmcsIGhhbmRsZXI6IERpcmVjdGl2ZSkgPT4gdm9pZDtcbiAgbmV3SW5zdGFuY2U6ICgpID0+IFZhbHlyaWFuO1xuICBbeDogc3RyaW5nXTogYW55O1xufVxuXG5sZXQgaXNOb2RlID0gdHlwZW9mIHdpbmRvdyA9PT0gXCJ1bmRlZmluZWRcIiB8fCB0eXBlb2YgZ2xvYmFsICE9PSBcInVuZGVmaW5lZFwiO1xuXG4vLyBDcmVhdGUgTm9kZSBlbGVtZW50XG5mdW5jdGlvbiBjcmVhdGVFbGVtZW50KHRhZ05hbWU6IHN0cmluZywgaXNTVkc6IGJvb2xlYW4gPSBmYWxzZSk6IERvbUVsZW1lbnQge1xuICByZXR1cm4gaXNTVkcgPyBkb2N1bWVudC5jcmVhdGVFbGVtZW50TlMoXCJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2Z1wiLCB0YWdOYW1lKSA6IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQodGFnTmFtZSk7XG59XG5cbi8vIFRyYW5zZm9ybXMgYSBET00gbm9kZSB0byBhIFZOb2RlXG5mdW5jdGlvbiBkb21Ub1Zub2RlKGRvbTogRG9tRWxlbWVudCk6IFZub2RlIHtcbiAgbGV0IHByb3BzOiBQcm9wcyA9IHt9O1xuICBbXS5mb3JFYWNoLmNhbGwoZG9tLmF0dHJpYnV0ZXMsIChwcm9wOiBBdHRyKSA9PiAocHJvcHNbcHJvcC5ub2RlTmFtZV0gPSBwcm9wLm5vZGVWYWx1ZSkpO1xuXG4gIGxldCB2bm9kZTogVm5vZGUgPSBuZXcgVm5vZGUoZG9tLm5vZGVOYW1lLnRvTG93ZXJDYXNlKCksIHByb3BzLCBbXSk7XG4gIHZub2RlLmRvbSA9IGRvbTtcblxuICBmb3IgKGxldCBpID0gMCwgbCA9IGRvbS5jaGlsZE5vZGVzLmxlbmd0aDsgaSA8IGw7IGkrKykge1xuICAgIGlmIChkb20uY2hpbGROb2Rlc1tpXS5ub2RlVHlwZSA9PT0gMSkge1xuICAgICAgdm5vZGUuY2hpbGRyZW4ucHVzaChkb21Ub1Zub2RlKGRvbS5jaGlsZE5vZGVzW2ldIGFzIERvbUVsZW1lbnQpKTtcbiAgICB9IGVsc2UgaWYgKGRvbS5jaGlsZE5vZGVzW2ldLm5vZGVUeXBlID09PSAzKSB7XG4gICAgICBsZXQgdGV4dFZub2RlID0gbmV3IFRleHRWbm9kZShkb20uY2hpbGROb2Rlc1tpXS5ub2RlVmFsdWUgfHwgXCJcIik7XG4gICAgICB0ZXh0Vm5vZGUuZG9tID0gZG9tLmNoaWxkTm9kZXNbaV0gYXMgdW5rbm93biBhcyBUZXh0O1xuICAgICAgdm5vZGUuY2hpbGRyZW4ucHVzaCh0ZXh0Vm5vZGUpO1xuICAgIH1cbiAgfVxuICByZXR1cm4gdm5vZGU7XG59XG5cbmNvbnN0IHRydXN0ID0gKGh0bWxTdHJpbmc6IHN0cmluZykgPT4ge1xuICBsZXQgZGl2ID0gY3JlYXRlRWxlbWVudChcImRpdlwiKTtcbiAgZGl2LmlubmVySFRNTCA9IGh0bWxTdHJpbmcudHJpbSgpO1xuXG4gIHJldHVybiBbXS5tYXAuY2FsbChkaXYuY2hpbGROb2RlcywgKGl0ZW0pID0+IGRvbVRvVm5vZGUoaXRlbSkpIGFzIFZub2RlW107XG59O1xuXG4vLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbWF4LWxpbmVzLXBlci1mdW5jdGlvblxuZnVuY3Rpb24gdmFseXJpYW4oKTogVmFseXJpYW4ge1xuICBjb25zdCB2OiBWYWx5cmlhbiA9ICh0YWdPckNvbXBvbmVudCwgcHJvcHMsIC4uLmNoaWxkcmVuKSA9PiB7XG4gICAgaWYgKHR5cGVvZiB0YWdPckNvbXBvbmVudCA9PT0gXCJzdHJpbmdcIikge1xuICAgICAgcmV0dXJuIG5ldyBWbm9kZSh0YWdPckNvbXBvbmVudCwgcHJvcHMgfHwge30sIGNoaWxkcmVuKTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIG5ldyBWbm9kZUNvbXBvbmVudCh0YWdPckNvbXBvbmVudCwgcHJvcHMgfHwge30sIGNoaWxkcmVuKTtcbiAgICB9XG4gIH07XG5cbiAgdi5mcmFnbWVudCA9IChwcm9wczogUHJvcHMsIHZub2RlczogVm5vZGVPclVua25vd25bXSkgPT4ge1xuICAgIHJldHVybiB2bm9kZXM7XG4gIH07XG5cbiAgdi5pc01vdW50ZWQgPSBmYWxzZTtcbiAgdi5pc05vZGUgPSBpc05vZGU7XG4gIGNvbnN0IHJlc2VydmVkV29yZHMgPSBbXCJrZXlcIiwgXCJkYXRhXCIsIFwidi1vbmNlXCIsIFwib25jcmVhdGVcIiwgXCJvbnVwZGF0ZVwiLCBcIm9ucmVtb3ZlXCIsIFwib25iZWZvcmV1cGRhdGVcIl07XG4gIHYucmVzZXJ2ZWRXb3JkcyA9IHJlc2VydmVkV29yZHM7XG4gIHYudHJ1c3QgPSB0cnVzdDtcblxuICBjb25zdCBjdXJyZW50OiBDdXJyZW50ID0ge1xuICAgIHBhcmVudFZub2RlOiB1bmRlZmluZWQsXG4gICAgb2xkUGFyZW50Vm5vZGU6IHVuZGVmaW5lZCxcbiAgICBjb21wb25lbnQ6IHVuZGVmaW5lZFxuICB9O1xuICB2LmN1cnJlbnQgPSBjdXJyZW50O1xuXG4gIGNvbnN0IHBsdWdpbnMgPSBuZXcgTWFwKCk7XG5cbiAgdi51c2VQbHVnaW4gPSAocGx1Z2luOiBQbHVnaW4sIG9wdGlvbnM6IFJlY29yZDxzdHJpbmcsIGFueT4gPSB7fSkgPT4gIXBsdWdpbnMuaGFzKHBsdWdpbikgJiYgcGx1Z2lucy5zZXQocGx1Z2luLCB0cnVlKSAmJiBwbHVnaW4odiBhcyBWYWx5cmlhbiwgb3B0aW9ucyk7XG5cbiAgbGV0IHZub2Rlc1RvQ2xlYW51cDogVm5vZGVbXSA9IFtdO1xuXG4gIHYub25DbGVhbnVwID0gKGNhbGxiYWNrOiBGdW5jdGlvbkNvbnN0cnVjdG9yKSA9PiB7XG4gICAgbGV0IHBhcmVudFZub2RlID0gdi5jdXJyZW50LnBhcmVudFZub2RlIGFzIFZub2RlO1xuICAgIGlmICghcGFyZW50Vm5vZGUub25DbGVhbnVwKSB7XG4gICAgICBwYXJlbnRWbm9kZS5vbkNsZWFudXAgPSBbXSBhcyBGdW5jdGlvbkNvbnN0cnVjdG9yW107XG4gICAgfVxuXG4gICAgcGFyZW50Vm5vZGUub25DbGVhbnVwLnB1c2goY2FsbGJhY2spO1xuXG4gICAgaWYgKHZub2Rlc1RvQ2xlYW51cC5pbmRleE9mKHBhcmVudFZub2RlKSA9PT0gLTEpIHtcbiAgICAgIHZub2Rlc1RvQ2xlYW51cC5wdXNoKHBhcmVudFZub2RlKTtcbiAgICB9XG4gIH07XG5cbiAgbGV0IGNsZWFudXBWbm9kZXMgPSAoKSA9PiB7XG4gICAgZm9yIChsZXQgbCA9IHZub2Rlc1RvQ2xlYW51cC5sZW5ndGg7IGwtLTsgKSB7XG4gICAgICBmb3IgKGxldCBjYWxsYmFjayBvZiB2bm9kZXNUb0NsZWFudXBbbF0ub25DbGVhbnVwIGFzIEZ1bmN0aW9uQ29uc3RydWN0b3JbXSkge1xuICAgICAgICBjYWxsYmFjaygpO1xuICAgICAgfVxuICAgIH1cbiAgICB2bm9kZXNUb0NsZWFudXAgPSBbXTtcbiAgfTtcblxuICBsZXQgbWFpbkNvbnRhaW5lcjogRG9tRWxlbWVudCB8IG51bGwgPSBudWxsO1xuICBsZXQgZW1wdHlDb21wb25lbnQ6IFZhbHlyaWFuQ29tcG9uZW50ID0gKCkgPT4gXCJcIjtcbiAgbGV0IG1vdW50ZWRDb21wb25lbnQ6IFZhbHlyaWFuQ29tcG9uZW50ID0gZW1wdHlDb21wb25lbnQ7XG5cbiAgY29uc3QgYXR0YWNoZWRMaXN0ZW5lcnM6IHN0cmluZ1tdID0gW107XG4gIGZ1bmN0aW9uIGV2ZW50TGlzdGVuZXIoZTogRXZlbnQpIHtcbiAgICBsZXQgZG9tID0gZS50YXJnZXQgYXMgRG9tRWxlbWVudDtcbiAgICBsZXQgbmFtZSA9IGB2LW9uJHtlLnR5cGV9YDtcbiAgICB3aGlsZSAoZG9tKSB7XG4gICAgICBpZiAoZG9tW25hbWVdKSB7XG4gICAgICAgIChkb21bbmFtZV0gYXMgVmFseXJpYW5FdmVudEhhbmRsZXIpKGUsIGRvbSk7XG4gICAgICAgIGlmICghZS5kZWZhdWx0UHJldmVudGVkKSB7XG4gICAgICAgICAgdi51cGRhdGUoKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgICBkb20gPSBkb20ucGFyZW50Tm9kZSBhcyBEb21FbGVtZW50O1xuICAgIH1cbiAgfVxuXG4gIGZ1bmN0aW9uIHVwZGF0ZVByb3BlcnR5KHByb3A6IHN0cmluZywgbmV3Vm5vZGU6IFZub2RlICYgeyBkb206IERvbUVsZW1lbnQgfSwgb2xkVm5vZGU/OiBWbm9kZSk6IHZvaWQgfCBib29sZWFuIHtcbiAgICBpZiAocmVzZXJ2ZWRXb3Jkcy5pbmRleE9mKHByb3ApICE9PSAtMSkge1xuICAgICAgaWYgKHByb3AgaW4gZGlyZWN0aXZlcykge1xuICAgICAgICByZXR1cm4gZGlyZWN0aXZlc1twcm9wXShuZXdWbm9kZS5wcm9wc1twcm9wXSwgbmV3Vm5vZGUsIG9sZFZub2RlKTtcbiAgICAgIH1cbiAgICB9IGVsc2UgaWYgKHR5cGVvZiBuZXdWbm9kZS5wcm9wc1twcm9wXSA9PT0gXCJmdW5jdGlvblwiKSB7XG4gICAgICBpZiAoYXR0YWNoZWRMaXN0ZW5lcnMuaW5kZXhPZihwcm9wKSA9PT0gLTEpIHtcbiAgICAgICAgKG1haW5Db250YWluZXIgYXMgRG9tRWxlbWVudCkuYWRkRXZlbnRMaXN0ZW5lcihwcm9wLnNsaWNlKDIpLCBldmVudExpc3RlbmVyKTtcbiAgICAgICAgYXR0YWNoZWRMaXN0ZW5lcnMucHVzaChwcm9wKTtcbiAgICAgIH1cbiAgICAgIG5ld1Zub2RlLmRvbVtgdi0ke3Byb3B9YF0gPSBuZXdWbm9kZS5wcm9wc1twcm9wXTtcbiAgICB9IGVsc2UgaWYgKHByb3AgaW4gbmV3Vm5vZGUuZG9tICYmICFuZXdWbm9kZS5pc1NWRykge1xuICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGVxZXFlcVxuICAgICAgaWYgKG5ld1Zub2RlLmRvbVtwcm9wXSAhPSBuZXdWbm9kZS5wcm9wc1twcm9wXSkge1xuICAgICAgICBuZXdWbm9kZS5kb21bcHJvcF0gPSBuZXdWbm9kZS5wcm9wc1twcm9wXTtcbiAgICAgIH1cbiAgICB9IGVsc2UgaWYgKG9sZFZub2RlID09PSB1bmRlZmluZWQgfHwgbmV3Vm5vZGUucHJvcHNbcHJvcF0gIT09IG9sZFZub2RlLnByb3BzW3Byb3BdKSB7XG4gICAgICBpZiAobmV3Vm5vZGUucHJvcHNbcHJvcF0gPT09IGZhbHNlKSB7XG4gICAgICAgIG5ld1Zub2RlLmRvbS5yZW1vdmVBdHRyaWJ1dGUocHJvcCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBuZXdWbm9kZS5kb20uc2V0QXR0cmlidXRlKHByb3AsIG5ld1Zub2RlLnByb3BzW3Byb3BdKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cbiAgdi51cGRhdGVQcm9wZXJ0eSA9IHVwZGF0ZVByb3BlcnR5O1xuXG4gIC8vIFVwZGF0ZSBhIFZub2RlLmRvbSBIVE1MRWxlbWVudCB3aXRoIG5ldyBWbm9kZSBwcm9wcyB0aGF0IGFyZSBkaWZmZXJlbnQgZnJvbSBvbGQgVm5vZGUgcHJvcHNcbiAgZnVuY3Rpb24gdXBkYXRlUHJvcGVydGllcyhuZXdWbm9kZTogVm5vZGUgJiB7IGRvbTogRG9tRWxlbWVudCB9LCBvbGRWbm9kZT86IFZub2RlKTogdm9pZCB7XG4gICAgZm9yIChsZXQgcHJvcCBpbiBuZXdWbm9kZS5wcm9wcykge1xuICAgICAgaWYgKHVwZGF0ZVByb3BlcnR5KHByb3AsIG5ld1Zub2RlLCBvbGRWbm9kZSkgPT09IGZhbHNlKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBmdW5jdGlvbiByZW1vdmVQcm9wZXJ0aWVzKG5ld1Zub2RlOiBWbm9kZSAmIHsgZG9tOiBEb21FbGVtZW50IH0sIG9sZFZub2RlOiBWbm9kZSkge1xuICAgIGZvciAobGV0IG5hbWUgaW4gb2xkVm5vZGUucHJvcHMpIHtcbiAgICAgIGlmIChuYW1lIGluIG5ld1Zub2RlLnByb3BzID09PSBmYWxzZSAmJiB0eXBlb2Ygb2xkVm5vZGUucHJvcHNbbmFtZV0gIT09IFwiZnVuY3Rpb25cIiAmJiByZXNlcnZlZFdvcmRzLmluZGV4T2YobmFtZSkgPT09IC0xKSB7XG4gICAgICAgIGlmIChuYW1lIGluIG5ld1Zub2RlLmRvbSkge1xuICAgICAgICAgIG5ld1Zub2RlLmRvbVtuYW1lXSA9IG51bGw7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgbmV3Vm5vZGUuZG9tLnJlbW92ZUF0dHJpYnV0ZShuYW1lKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIGNvbnN0IGNhbGxSZW1vdmUgPSAodm5vZGU6IFZub2RlKSA9PiB7XG4gICAgZm9yIChsZXQgaSA9IDAsIGwgPSB2bm9kZS5jaGlsZHJlbi5sZW5ndGg7IGkgPCBsOyBpKyspIHtcbiAgICAgIHZub2RlLmNoaWxkcmVuW2ldIGluc3RhbmNlb2YgVm5vZGUgJiYgY2FsbFJlbW92ZSh2bm9kZS5jaGlsZHJlbltpXSk7XG4gICAgfVxuXG4gICAgdm5vZGUucHJvcHMub25yZW1vdmUgJiYgdm5vZGUucHJvcHMub25yZW1vdmUodm5vZGUpO1xuICB9O1xuICAvLyBQYXRjaCBhIERPTSBub2RlIHdpdGggYSBuZXcgVk5vZGUgdHJlZVxuICBmdW5jdGlvbiBwYXRjaChuZXdQYXJlbnRWbm9kZTogVm5vZGUgJiB7IGRvbTogRG9tRWxlbWVudCB9LCBvbGRQYXJlbnRWbm9kZT86IFZub2RlICYgeyBkb206IERvbUVsZW1lbnQgfSk6IHZvaWQge1xuICAgIGxldCBvbGRUcmVlID0gb2xkUGFyZW50Vm5vZGU/LmNoaWxkcmVuIHx8IFtdO1xuICAgIGxldCBuZXdUcmVlID0gbmV3UGFyZW50Vm5vZGUuY2hpbGRyZW47XG4gICAgbGV0IG9sZFRyZWVMZW5ndGggPSBvbGRUcmVlLmxlbmd0aDtcblxuICAgIGN1cnJlbnQucGFyZW50Vm5vZGUgPSBuZXdQYXJlbnRWbm9kZTtcbiAgICBjdXJyZW50Lm9sZFBhcmVudFZub2RlID0gb2xkUGFyZW50Vm5vZGU7XG5cbiAgICAvLyBGbGF0IG5ld1RyZWVcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IG5ld1RyZWUubGVuZ3RoOyBpKyspIHtcbiAgICAgIGxldCBjaGlsZFZub2RlID0gbmV3VHJlZVtpXTtcblxuICAgICAgaWYgKGNoaWxkVm5vZGUgaW5zdGFuY2VvZiBWbm9kZSkge1xuICAgICAgICBjaGlsZFZub2RlLmlzU1ZHID0gbmV3UGFyZW50Vm5vZGUuaXNTVkcgfHwgY2hpbGRWbm9kZS5uYW1lID09PSBcInN2Z1wiO1xuICAgICAgfSBlbHNlIGlmIChjaGlsZFZub2RlID09PSBudWxsIHx8IGNoaWxkVm5vZGUgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICBuZXdUcmVlLnNwbGljZShpLS0sIDEpO1xuICAgICAgfSBlbHNlIGlmIChBcnJheS5pc0FycmF5KGNoaWxkVm5vZGUpKSB7XG4gICAgICAgIG5ld1RyZWUuc3BsaWNlKGktLSwgMSwgLi4uY2hpbGRWbm9kZSk7XG4gICAgICB9IGVsc2UgaWYgKGNoaWxkVm5vZGUgaW5zdGFuY2VvZiBWbm9kZUNvbXBvbmVudCkge1xuICAgICAgICB2LmN1cnJlbnQuY29tcG9uZW50ID0gY2hpbGRWbm9kZTtcbiAgICAgICAgbmV3VHJlZS5zcGxpY2UoXG4gICAgICAgICAgaS0tLFxuICAgICAgICAgIDEsXG4gICAgICAgICAgLi4uW1xuICAgICAgICAgICAgXCJ2aWV3XCIgaW4gY2hpbGRWbm9kZS5jb21wb25lbnRcbiAgICAgICAgICAgICAgPyBjaGlsZFZub2RlLmNvbXBvbmVudC52aWV3LmNhbGwoY2hpbGRWbm9kZS5jb21wb25lbnQsIGNoaWxkVm5vZGUucHJvcHMsIGNoaWxkVm5vZGUuY2hpbGRyZW4pXG4gICAgICAgICAgICAgIDogKGNoaWxkVm5vZGUuY29tcG9uZW50IGFzIENvbXBvbmVudCkuY2FsbChjaGlsZFZub2RlLmNvbXBvbmVudCwgY2hpbGRWbm9kZS5wcm9wcywgY2hpbGRWbm9kZS5jaGlsZHJlbilcbiAgICAgICAgICBdXG4gICAgICAgICk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBpZiAoaSA+IDAgJiYgbmV3VHJlZVtpIC0gMV0ubm9kZVZhbHVlKSB7XG4gICAgICAgICAgbmV3VHJlZVtpIC0gMV0ubm9kZVZhbHVlICs9IGNoaWxkVm5vZGU7XG4gICAgICAgICAgbmV3VHJlZS5zcGxpY2UoaS0tLCAxKTtcbiAgICAgICAgfSBlbHNlIGlmIChjaGlsZFZub2RlIGluc3RhbmNlb2YgVGV4dFZub2RlID09PSBmYWxzZSkge1xuICAgICAgICAgIG5ld1RyZWVbaV0gPSBuZXcgVGV4dFZub2RlKFN0cmluZyhjaGlsZFZub2RlKSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICBsZXQgbmV3VHJlZUxlbmd0aCA9IG5ld1RyZWUubGVuZ3RoO1xuXG4gICAgLy8gaWYgbmV3VHJlZSBpcyBlbXB0eSwgcmVtb3ZlIGl0XG4gICAgaWYgKG5ld1RyZWVMZW5ndGggPT09IDApIHtcbiAgICAgIGlmIChvbGRUcmVlTGVuZ3RoID4gMCkge1xuICAgICAgICBmb3IgKGxldCBpID0gb2xkVHJlZUxlbmd0aDsgaS0tOyApIHtcbiAgICAgICAgICBvbGRUcmVlW2ldIGluc3RhbmNlb2YgVm5vZGUgJiYgY2FsbFJlbW92ZShvbGRUcmVlW2ldKTtcbiAgICAgICAgfVxuICAgICAgICAvLyBGYXN0IG5vZGUgcmVtb3ZlIGJ5IHNldHRpbmcgdGV4dENvbnRlbnRcbiAgICAgICAgbmV3UGFyZW50Vm5vZGUuZG9tLnRleHRDb250ZW50ID0gXCJcIjtcbiAgICAgIH1cbiAgICAgIC8vIElmIHRoZSB0cmVlIGlzIGtleWVkIGxpc3QgYW5kIGlzIG5vdCBmaXJzdCByZW5kZXJcbiAgICB9IGVsc2UgaWYgKG9sZFRyZWVMZW5ndGggJiYgbmV3VHJlZVswXSBpbnN0YW5jZW9mIFZub2RlICYmIFwia2V5XCIgaW4gbmV3VHJlZVswXS5wcm9wcykge1xuICAgICAgLy8gMS4gTXV0YXRlIHRoZSBvbGQga2V5IGxpc3QgdG8gbWF0Y2ggdGhlIG5ldyBrZXkgbGlzdFxuICAgICAgbGV0IG9sZEtleWVkTGlzdDtcblxuICAgICAgLy8gaWYgdGhlIG9sZFRyZWUgZG9lcyBub3QgaGF2ZSBhIGtleWVkIGxpc3QgZmFzdCByZW1vdmUgYWxsIG5vZGVzXG4gICAgICBpZiAob2xkVHJlZVswXSBpbnN0YW5jZW9mIFZub2RlID09PSBmYWxzZSB8fCBcImtleVwiIGluIG9sZFRyZWVbMF0ucHJvcHMgPT09IGZhbHNlKSB7XG4gICAgICAgIGZvciAobGV0IGkgPSBvbGRUcmVlTGVuZ3RoOyBpLS07ICkge1xuICAgICAgICAgIG9sZFRyZWVbaV0gaW5zdGFuY2VvZiBWbm9kZSAmJiBjYWxsUmVtb3ZlKG9sZFRyZWVbaV0pO1xuICAgICAgICB9XG4gICAgICAgIC8vIEZhc3Qgbm9kZSByZW1vdmUgYnkgc2V0dGluZyB0ZXh0Q29udGVudFxuICAgICAgICBuZXdQYXJlbnRWbm9kZS5kb20udGV4dENvbnRlbnQgPSBcIlwiO1xuICAgICAgICBvbGRLZXllZExpc3QgPSBbXTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIG9sZEtleWVkTGlzdCA9IG9sZFRyZWUubWFwKCh2bm9kZSkgPT4gdm5vZGUucHJvcHMua2V5KTtcbiAgICAgIH1cblxuICAgICAgLy8gMi4gT2J0YWluIHRoZSBtYXggbGVuZ3RoIG9mIGJvdGggbGlzdHNcbiAgICAgIGxldCBuZXdLZXllZExpc3QgPSBuZXdUcmVlLm1hcCgodm5vZGUpID0+IHZub2RlLnByb3BzLmtleSk7XG4gICAgICBjb25zdCBtYXhMaXN0TGVuZ3RoID0gTWF0aC5tYXgobmV3VHJlZUxlbmd0aCwgb2xkS2V5ZWRMaXN0Lmxlbmd0aCk7XG5cbiAgICAgIC8vIDMuIEN5Y2xlIG92ZXIgYWxsIHRoZSBlbGVtZW50cyBvZiB0aGUgbGlzdCB1bnRpbCB0aGUgbWF4IGxlbmd0aFxuICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBtYXhMaXN0TGVuZ3RoOyBpKyspIHtcbiAgICAgICAgaWYgKGkgPCBuZXdUcmVlTGVuZ3RoKSB7XG4gICAgICAgICAgbGV0IGNoaWxkVm5vZGUgPSBuZXdUcmVlW2ldO1xuICAgICAgICAgIGxldCBvbGRDaGlsZFZub2RlID0gb2xkS2V5ZWRMaXN0W2ldID09PSBuZXdLZXllZExpc3RbaV0gPyBvbGRUcmVlW2ldIDogb2xkVHJlZVtvbGRLZXllZExpc3QuaW5kZXhPZihjaGlsZFZub2RlLnByb3BzLmtleSldO1xuICAgICAgICAgIGxldCBzaG91bGRQYXRjaCA9IHRydWU7XG5cbiAgICAgICAgICBpZiAob2xkQ2hpbGRWbm9kZSkge1xuICAgICAgICAgICAgY2hpbGRWbm9kZS5kb20gPSBvbGRDaGlsZFZub2RlLmRvbTtcbiAgICAgICAgICAgIG9sZENoaWxkVm5vZGUucHJvY2Vzc2VkID0gdHJ1ZTtcbiAgICAgICAgICAgIGlmIChcInYtb25jZVwiIGluIGNoaWxkVm5vZGUucHJvcHMgfHwgKGNoaWxkVm5vZGUucHJvcHMub25iZWZvcmV1cGRhdGUgJiYgY2hpbGRWbm9kZS5wcm9wcy5vbmJlZm9yZXVwZGF0ZShjaGlsZFZub2RlLCBvbGRDaGlsZFZub2RlKSA9PT0gZmFsc2UpKSB7XG4gICAgICAgICAgICAgIC8vIHNraXAgdGhpcyBwYXRjaFxuICAgICAgICAgICAgICBjaGlsZFZub2RlLmNoaWxkcmVuID0gb2xkQ2hpbGRWbm9kZS5jaGlsZHJlbjtcbiAgICAgICAgICAgICAgc2hvdWxkUGF0Y2ggPSBmYWxzZTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIHJlbW92ZVByb3BlcnRpZXMoY2hpbGRWbm9kZSBhcyBWbm9kZSAmIHsgZG9tOiBEb21FbGVtZW50IH0sIG9sZENoaWxkVm5vZGUpO1xuICAgICAgICAgICAgICB1cGRhdGVQcm9wZXJ0aWVzKGNoaWxkVm5vZGUgYXMgVm5vZGUgJiB7IGRvbTogRG9tRWxlbWVudCB9LCBvbGRDaGlsZFZub2RlKTtcbiAgICAgICAgICAgICAgaWYgKHYuaXNNb3VudGVkKSB7XG4gICAgICAgICAgICAgICAgY2hpbGRWbm9kZS5wcm9wcy5vbnVwZGF0ZSAmJiBjaGlsZFZub2RlLnByb3BzLm9udXBkYXRlKGNoaWxkVm5vZGUsIG9sZENoaWxkVm5vZGUpO1xuICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGNoaWxkVm5vZGUucHJvcHMub25jcmVhdGUgJiYgY2hpbGRWbm9kZS5wcm9wcy5vbmNyZWF0ZShjaGlsZFZub2RlKTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjaGlsZFZub2RlLmRvbSA9IGNyZWF0ZUVsZW1lbnQoY2hpbGRWbm9kZS5uYW1lLCBjaGlsZFZub2RlLmlzU1ZHKTtcbiAgICAgICAgICAgIHVwZGF0ZVByb3BlcnRpZXMoY2hpbGRWbm9kZSBhcyBWbm9kZSAmIHsgZG9tOiBEb21FbGVtZW50IH0pO1xuICAgICAgICAgICAgY2hpbGRWbm9kZS5wcm9wcy5vbmNyZWF0ZSAmJiBjaGlsZFZub2RlLnByb3BzLm9uY3JlYXRlKGNoaWxkVm5vZGUpO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGlmIChuZXdQYXJlbnRWbm9kZS5kb20uY2hpbGROb2Rlc1tpXSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICBuZXdQYXJlbnRWbm9kZS5kb20uYXBwZW5kQ2hpbGQoY2hpbGRWbm9kZS5kb20pO1xuICAgICAgICAgIH0gZWxzZSBpZiAobmV3UGFyZW50Vm5vZGUuZG9tLmNoaWxkTm9kZXNbaV0gIT09IGNoaWxkVm5vZGUuZG9tKSB7XG4gICAgICAgICAgICBvbGRUcmVlW2ldIGluc3RhbmNlb2YgVm5vZGUgJiYgIW9sZFRyZWVbaV0ucHJvY2Vzc2VkICYmIG5ld0tleWVkTGlzdC5pbmRleE9mKG9sZFRyZWVbaV0ucHJvcHMua2V5KSA9PT0gLTEgJiYgY2FsbFJlbW92ZShvbGRUcmVlW2ldKTtcbiAgICAgICAgICAgIG5ld1BhcmVudFZub2RlLmRvbS5yZXBsYWNlQ2hpbGQoY2hpbGRWbm9kZS5kb20sIG5ld1BhcmVudFZub2RlLmRvbS5jaGlsZE5vZGVzW2ldKTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBzaG91bGRQYXRjaCAmJiBwYXRjaChjaGlsZFZub2RlIGFzIFZub2RlICYgeyBkb206IERvbUVsZW1lbnQgfSwgb2xkQ2hpbGRWbm9kZSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgaWYgKCFvbGRUcmVlW2ldLnByb2Nlc3NlZCkge1xuICAgICAgICAgICAgb2xkVHJlZVtpXSBpbnN0YW5jZW9mIFZub2RlICYmIGNhbGxSZW1vdmUob2xkVHJlZVtpXSk7XG4gICAgICAgICAgICBvbGRUcmVlW2ldLmRvbS5wYXJlbnROb2RlICYmIG5ld1BhcmVudFZub2RlLmRvbS5yZW1vdmVDaGlsZChvbGRUcmVlW2ldLmRvbSk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbmV3VHJlZUxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGxldCBjaGlsZFZub2RlID0gbmV3VHJlZVtpXTtcbiAgICAgICAgbGV0IG9sZENoaWxkVm5vZGUgPSBvbGRUcmVlW2ldO1xuXG4gICAgICAgIC8vIGlmIG9sZENoaWxkVm5vZGUgaXMgdW5kZWZpbmVkLCBpdCdzIGEgbmV3IG5vZGUsIGFwcGVuZCBpdFxuICAgICAgICBpZiAob2xkQ2hpbGRWbm9kZSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgaWYgKGNoaWxkVm5vZGUgaW5zdGFuY2VvZiBWbm9kZSkge1xuICAgICAgICAgICAgY2hpbGRWbm9kZS5kb20gPSBjcmVhdGVFbGVtZW50KGNoaWxkVm5vZGUubmFtZSwgY2hpbGRWbm9kZS5pc1NWRyk7XG4gICAgICAgICAgICB1cGRhdGVQcm9wZXJ0aWVzKGNoaWxkVm5vZGUgYXMgVm5vZGUgJiB7IGRvbTogRG9tRWxlbWVudCB9KTtcbiAgICAgICAgICAgIGNoaWxkVm5vZGUucHJvcHMub25jcmVhdGUgJiYgY2hpbGRWbm9kZS5wcm9wcy5vbmNyZWF0ZShjaGlsZFZub2RlKTtcbiAgICAgICAgICAgIHBhdGNoKGNoaWxkVm5vZGUgYXMgVm5vZGUgJiB7IGRvbTogRG9tRWxlbWVudCB9KTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgY2hpbGRWbm9kZS5kb20gPSBkb2N1bWVudC5jcmVhdGVUZXh0Tm9kZShjaGlsZFZub2RlLm5vZGVWYWx1ZSk7XG4gICAgICAgICAgfVxuICAgICAgICAgIG5ld1BhcmVudFZub2RlLmRvbS5hcHBlbmRDaGlsZChjaGlsZFZub2RlLmRvbSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgLy8gaWYgY2hpbGRWbm9kZSBpcyBWbm9kZSwgcmVwbGFjZSBpdCB3aXRoIGl0cyBET00gbm9kZVxuICAgICAgICAgIGlmIChjaGlsZFZub2RlIGluc3RhbmNlb2YgVm5vZGUpIHtcbiAgICAgICAgICAgIGlmIChjaGlsZFZub2RlLm5hbWUgPT09IG9sZENoaWxkVm5vZGUubmFtZSkge1xuICAgICAgICAgICAgICBjaGlsZFZub2RlLmRvbSA9IG9sZENoaWxkVm5vZGUuZG9tO1xuXG4gICAgICAgICAgICAgIGlmIChcInYtb25jZVwiIGluIGNoaWxkVm5vZGUucHJvcHMgfHwgKGNoaWxkVm5vZGUucHJvcHMub25iZWZvcmV1cGRhdGUgJiYgY2hpbGRWbm9kZS5wcm9wcy5vbmJlZm9yZXVwZGF0ZShjaGlsZFZub2RlLCBvbGRDaGlsZFZub2RlKSA9PT0gZmFsc2UpKSB7XG4gICAgICAgICAgICAgICAgLy8gc2tpcCB0aGlzIHBhdGNoXG4gICAgICAgICAgICAgICAgY2hpbGRWbm9kZS5jaGlsZHJlbiA9IG9sZENoaWxkVm5vZGUuY2hpbGRyZW47XG4gICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICByZW1vdmVQcm9wZXJ0aWVzKGNoaWxkVm5vZGUgYXMgVm5vZGUgJiB7IGRvbTogRG9tRWxlbWVudCB9LCBvbGRDaGlsZFZub2RlKTtcbiAgICAgICAgICAgICAgdXBkYXRlUHJvcGVydGllcyhjaGlsZFZub2RlIGFzIFZub2RlICYgeyBkb206IERvbUVsZW1lbnQgfSwgb2xkQ2hpbGRWbm9kZSk7XG4gICAgICAgICAgICAgIGlmICh2LmlzTW91bnRlZCkge1xuICAgICAgICAgICAgICAgIGNoaWxkVm5vZGUucHJvcHMub251cGRhdGUgJiYgY2hpbGRWbm9kZS5wcm9wcy5vbnVwZGF0ZShjaGlsZFZub2RlLCBvbGRDaGlsZFZub2RlKTtcbiAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBjaGlsZFZub2RlLnByb3BzLm9uY3JlYXRlICYmIGNoaWxkVm5vZGUucHJvcHMub25jcmVhdGUoY2hpbGRWbm9kZSk7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgcGF0Y2goY2hpbGRWbm9kZSBhcyBWbm9kZSAmIHsgZG9tOiBEb21FbGVtZW50IH0sIG9sZENoaWxkVm5vZGUpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgY2hpbGRWbm9kZS5kb20gPSBjcmVhdGVFbGVtZW50KGNoaWxkVm5vZGUubmFtZSwgY2hpbGRWbm9kZS5pc1NWRyk7XG4gICAgICAgICAgICAgIHVwZGF0ZVByb3BlcnRpZXMoY2hpbGRWbm9kZSBhcyBWbm9kZSAmIHsgZG9tOiBEb21FbGVtZW50IH0pO1xuICAgICAgICAgICAgICBjaGlsZFZub2RlLnByb3BzLm9uY3JlYXRlICYmIGNoaWxkVm5vZGUucHJvcHMub25jcmVhdGUoY2hpbGRWbm9kZSk7XG4gICAgICAgICAgICAgIG9sZENoaWxkVm5vZGUgaW5zdGFuY2VvZiBWbm9kZSAmJiBjYWxsUmVtb3ZlKG9sZENoaWxkVm5vZGUpO1xuICAgICAgICAgICAgICBuZXdQYXJlbnRWbm9kZS5kb20ucmVwbGFjZUNoaWxkKGNoaWxkVm5vZGUuZG9tLCBvbGRDaGlsZFZub2RlLmRvbSk7XG4gICAgICAgICAgICAgIHBhdGNoKGNoaWxkVm5vZGUgYXMgVm5vZGUgJiB7IGRvbTogRG9tRWxlbWVudCB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgaWYgKG9sZENoaWxkVm5vZGUgaW5zdGFuY2VvZiBWbm9kZSkge1xuICAgICAgICAgICAgICBjaGlsZFZub2RlLmRvbSA9IGRvY3VtZW50LmNyZWF0ZVRleHROb2RlKGNoaWxkVm5vZGUubm9kZVZhbHVlKTtcbiAgICAgICAgICAgICAgY2FsbFJlbW92ZShvbGRDaGlsZFZub2RlKTtcbiAgICAgICAgICAgICAgbmV3UGFyZW50Vm5vZGUuZG9tLnJlcGxhY2VDaGlsZChjaGlsZFZub2RlLmRvbSwgb2xkQ2hpbGRWbm9kZS5kb20gYXMgRG9tRWxlbWVudCk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICBjaGlsZFZub2RlLmRvbSA9IG9sZENoaWxkVm5vZGUuZG9tO1xuICAgICAgICAgICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgZXFlcWVxXG4gICAgICAgICAgICAgIGlmIChjaGlsZFZub2RlLm5vZGVWYWx1ZSAhPSBjaGlsZFZub2RlLmRvbS5ub2RlVmFsdWUpIHtcbiAgICAgICAgICAgICAgICBjaGlsZFZub2RlLmRvbS5ub2RlVmFsdWUgPSBjaGlsZFZub2RlLm5vZGVWYWx1ZTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICAvLyBGb3IgcmVtYWluaW5nIG9sZCBjaGlsZHJlbjogcmVtb3ZlIGZyb20gRE9NLCBnYXJiYWdlIGNvbGxlY3RcbiAgICAgIGZvciAobGV0IGkgPSBvbGRUcmVlTGVuZ3RoIC0gMTsgaSA+PSBuZXdUcmVlTGVuZ3RoOyAtLWkpIHtcbiAgICAgICAgb2xkVHJlZVtpXSBpbnN0YW5jZW9mIFZub2RlICYmIGNhbGxSZW1vdmUob2xkVHJlZVtpXSk7XG4gICAgICAgIG9sZFRyZWVbaV0uZG9tLnBhcmVudE5vZGUgJiYgbmV3UGFyZW50Vm5vZGUuZG9tLnJlbW92ZUNoaWxkKG9sZFRyZWVbaV0uZG9tKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBuZXdQYXJlbnRWbm9kZS5jaGlsZHJlbiA9IG5ld1RyZWU7XG4gIH1cblxuICBsZXQgbWFpblZub2RlOiBWbm9kZSB8IG51bGwgPSBudWxsO1xuICBsZXQgb2xkTWFpblZub2RlOiBWbm9kZSB8IG51bGwgPSBudWxsO1xuXG4gIHYudW5Nb3VudCA9ICgpID0+IHtcbiAgICBtb3VudGVkQ29tcG9uZW50ID0gZW1wdHlDb21wb25lbnQ7XG4gICAgbGV0IHJlc3VsdCA9IHYudXBkYXRlKCk7XG4gICAgdi5pc01vdW50ZWQgPSBmYWxzZTtcbiAgICBtYWluQ29udGFpbmVyID0gbnVsbDtcbiAgICByZXR1cm4gcmVzdWx0O1xuICB9O1xuXG4gIHYudXBkYXRlID0gKHByb3BzLCAuLi5jaGlsZHJlbikgPT4ge1xuICAgIGlmIChtYWluVm5vZGUpIHtcbiAgICAgIGNsZWFudXBWbm9kZXMoKTtcbiAgICAgIG9sZE1haW5Wbm9kZSA9IG1haW5Wbm9kZTtcbiAgICAgIG1haW5Wbm9kZSA9IG5ldyBWbm9kZShtYWluVm5vZGUubmFtZSwgbWFpblZub2RlLnByb3BzLCBbdihtb3VudGVkQ29tcG9uZW50LCBwcm9wcywgLi4uY2hpbGRyZW4pXSk7XG4gICAgICBtYWluVm5vZGUuZG9tID0gb2xkTWFpblZub2RlLmRvbTtcbiAgICAgIG1haW5Wbm9kZS5pc1NWRyA9IG9sZE1haW5Wbm9kZS5pc1NWRztcbiAgICAgIHBhdGNoKG1haW5Wbm9kZSBhcyBWbm9kZSAmIHsgZG9tOiBOb2RlIH0sIG9sZE1haW5Wbm9kZSBhcyBWbm9kZSAmIHsgZG9tOiBOb2RlIH0pO1xuICAgICAgdi5pc01vdW50ZWQgPSB0cnVlO1xuICAgICAgaWYgKHYuaXNOb2RlKSB7XG4gICAgICAgIHJldHVybiAobWFpblZub2RlLmRvbSBhcyBIVE1MRWxlbWVudCkuaW5uZXJIVE1MO1xuICAgICAgfVxuICAgIH1cbiAgfTtcblxuICB2Lm1vdW50ID0gKGNvbnRhaW5lciwgY29tcG9uZW50LCBwcm9wcywgLi4uY2hpbGRyZW4pID0+IHtcbiAgICBpZiAodi5pc01vdW50ZWQpIHtcbiAgICAgIHYudW5Nb3VudCgpO1xuICAgIH1cblxuICAgIGlmIChpc05vZGUpIHtcbiAgICAgIG1haW5Db250YWluZXIgPSB0eXBlb2YgY29udGFpbmVyID09PSBcInN0cmluZ1wiID8gY3JlYXRlRWxlbWVudChjb250YWluZXIsIGNvbnRhaW5lciA9PT0gXCJzdmdcIikgOiBjb250YWluZXI7XG4gICAgfSBlbHNlIHtcbiAgICAgIG1haW5Db250YWluZXIgPSB0eXBlb2YgY29udGFpbmVyID09PSBcInN0cmluZ1wiID8gKGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3JBbGwoY29udGFpbmVyKVswXSBhcyBEb21FbGVtZW50KSA6IGNvbnRhaW5lcjtcbiAgICB9XG5cbiAgICBpZiAobWFpbkNvbnRhaW5lciAhPT0gbnVsbCkge1xuICAgICAgbWFpblZub2RlID0gZG9tVG9Wbm9kZShtYWluQ29udGFpbmVyKTtcbiAgICAgIG1haW5Wbm9kZS5pc1NWRyA9IG1haW5Wbm9kZS5uYW1lID09PSBcInN2Z1wiO1xuICAgICAgb2xkTWFpblZub2RlID0gbWFpblZub2RlO1xuICAgICAgbW91bnRlZENvbXBvbmVudCA9IGNvbXBvbmVudDtcbiAgICB9XG5cbiAgICByZXR1cm4gdi51cGRhdGUocHJvcHMsIC4uLmNoaWxkcmVuKTtcbiAgfTtcblxuICBsZXQgZGlyZWN0aXZlczogUmVjb3JkPHN0cmluZywgRGlyZWN0aXZlPiA9IHt9O1xuXG4gIHYuZGlyZWN0aXZlID0gKG5hbWU6IHN0cmluZywgZGlyZWN0aXZlOiBEaXJlY3RpdmUpID0+IHtcbiAgICBsZXQgZnVsbE5hbWUgPSBgdi0ke25hbWV9YDtcbiAgICBpZiAocmVzZXJ2ZWRXb3Jkcy5pbmRleE9mKGZ1bGxOYW1lKSA9PT0gLTEpIHtcbiAgICAgIHJlc2VydmVkV29yZHMucHVzaChmdWxsTmFtZSk7XG4gICAgICBkaXJlY3RpdmVzW2Z1bGxOYW1lXSA9IGRpcmVjdGl2ZTtcbiAgICB9XG4gIH07XG5cbiAgbGV0IGhpZGVEaXJlY3RpdmUgPSAodGVzdDogYm9vbGVhbikgPT4gKGJvb2w6IGJvb2xlYW4sIHZub2RlOiBWbm9kZSwgb2xkbm9kZT86IFZub2RlIHwgVGV4dFZub2RlKSA9PiB7XG4gICAgbGV0IHZhbHVlID0gdGVzdCA/IGJvb2wgOiAhYm9vbDtcbiAgICBpZiAodmFsdWUpIHtcbiAgICAgIGxldCBuZXdkb20gPSBkb2N1bWVudC5jcmVhdGVUZXh0Tm9kZShcIlwiKTtcbiAgICAgIGlmIChvbGRub2RlICYmIG9sZG5vZGUuZG9tICYmIG9sZG5vZGUuZG9tLnBhcmVudE5vZGUpIHtcbiAgICAgICAgb2xkbm9kZSBpbnN0YW5jZW9mIFZub2RlICYmIGNhbGxSZW1vdmUob2xkbm9kZSk7XG4gICAgICAgIG9sZG5vZGUuZG9tLnBhcmVudE5vZGUucmVwbGFjZUNoaWxkKG5ld2RvbSwgb2xkbm9kZS5kb20pO1xuICAgICAgfVxuICAgICAgdm5vZGUubmFtZSA9IFwiI3RleHRcIjtcbiAgICAgIHZub2RlLmNoaWxkcmVuID0gW107XG4gICAgICB2bm9kZS5wcm9wcyA9IHt9O1xuICAgICAgdm5vZGUuZG9tID0gbmV3ZG9tIGFzIHVua25vd24gYXMgRG9tRWxlbWVudDtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gIH07XG5cbiAgdi5kaXJlY3RpdmUoXCJpZlwiLCBoaWRlRGlyZWN0aXZlKGZhbHNlKSk7XG4gIHYuZGlyZWN0aXZlKFwidW5sZXNzXCIsIGhpZGVEaXJlY3RpdmUodHJ1ZSkpO1xuICB2LmRpcmVjdGl2ZShcImZvclwiLCAoc2V0OiB1bmtub3duW10sIHZub2RlOiBWbm9kZSkgPT4ge1xuICAgIHZub2RlLmNoaWxkcmVuID0gc2V0Lm1hcCh2bm9kZS5jaGlsZHJlblswXSBhcyAodmFsdWU6IHVua25vd24pID0+IEZ1bmN0aW9uKTtcbiAgfSk7XG4gIHYuZGlyZWN0aXZlKFwic2hvd1wiLCAoYm9vbDogYm9vbGVhbiwgdm5vZGU6IFZub2RlKSA9PiB7XG4gICAgKHZub2RlLmRvbSBhcyB7IHN0eWxlOiB7IGRpc3BsYXk6IHN0cmluZyB9IH0pLnN0eWxlLmRpc3BsYXkgPSBib29sID8gXCJcIiA6IFwibm9uZVwiO1xuICB9KTtcbiAgdi5kaXJlY3RpdmUoXCJjbGFzc1wiLCAoY2xhc3NlczogeyBbeDogc3RyaW5nXTogYm9vbGVhbiB9LCB2bm9kZTogVm5vZGUpID0+IHtcbiAgICBmb3IgKGxldCBuYW1lIGluIGNsYXNzZXMpIHtcbiAgICAgICh2bm9kZS5kb20gYXMgRG9tRWxlbWVudCkuY2xhc3NMaXN0LnRvZ2dsZShuYW1lLCBjbGFzc2VzW25hbWVdKTtcbiAgICB9XG4gIH0pO1xuICB2LmRpcmVjdGl2ZShcImh0bWxcIiwgKGh0bWw6IHN0cmluZywgdm5vZGU6IFZub2RlKSA9PiB7XG4gICAgdm5vZGUuY2hpbGRyZW4gPSBbdHJ1c3QoaHRtbCldO1xuICB9KTtcblxuICB2Lm5ld0luc3RhbmNlID0gdmFseXJpYW47XG5cbiAgcmV0dXJuIHY7XG59XG5cbigoaXNOb2RlID8gZ2xvYmFsIDogd2luZG93KSBhcyB1bmtub3duIGFzIHsgdjogVmFseXJpYW4gfSkudiA9IHZhbHlyaWFuKCk7XG4iXX0= \ No newline at end of file +//# sourceMappingURL=data:application/json;charset=utf-8;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vbGliL2luZGV4LnRzIl0sCiAgInNvdXJjZXNDb250ZW50IjogWyIvLyBXZSB3aWxsIG1ha2UgYSB2ZG9tIGxpYnJhcnkgdGhhdCB3aWxsIGJlIHVzZWQgdG8gY3JlYXRlIHZpcnR1YWwgZG9tIGVsZW1lbnRzIGFuZCByZW5kZXIgdGhlbSB0byB0aGUgc2NyZWVuLlxuLy8gV2UgbXVzdCB0cnkgdG8gaGF2ZSB0aGUgbGVzcyBhbW91bnQgb2YgYXNzaWdubWVudHMgYW5kIGlmIHN0YXRlbWVudHNcblxuY2xhc3MgVm5vZGUge1xuICB0YWc6IHN0cmluZztcbiAgcHJvcHM6IHt9O1xuICBjaGlsZHJlbjogW107XG4gIGNvbnN0cnVjdG9yKHRhZzogc3RyaW5nLCBwcm9wczoge30sIGNoaWxkcmVuOiBbXSkge1xuICAgIHRoaXMucHJvcHMgPSBwcm9wcztcbiAgICB0aGlzLmNoaWxkcmVuID0gY2hpbGRyZW47XG4gICAgdGhpcy50YWcgPSB0YWc7XG4gIH1cbn1cblxuZXhwb3J0IHsgVm5vZGUgfTtcbiJdLAogICJtYXBwaW5ncyI6ICI7O0FBR0Esb0JBQVk7QUFBQSxJQUNWO0FBQUEsSUFDQTtBQUFBLElBQ0E7QUFBQSxJQUNBLFlBQVksS0FBYSxPQUFXLFVBQWM7QUFDaEQsV0FBSyxRQUFRO0FBQ2IsV0FBSyxXQUFXO0FBQ2hCLFdBQUssTUFBTTtBQUFBO0FBQUE7IiwKICAibmFtZXMiOiBbXQp9Cg== \ No newline at end of file diff --git a/lib/index.ts b/lib/index.ts index 7e5a1b9..a515d18 100644 --- a/lib/index.ts +++ b/lib/index.ts @@ -1,564 +1,667 @@ -/* eslint-disable complexity */ -/* eslint-disable sonarjs/cognitive-complexity */ -/* eslint-disable no-use-before-define */ -/* eslint-disable no-unused-vars */ +// We will make a vdom library that will be used to create virtual dom elements and render them to the screen. +// We must try to have the less amount of assignments and if statements -type VnodeOrUnknown = VnodeComponent | Vnode | TextVnode | any; - -type DomAttribute = { nodeName: string; nodeValue: string }; - -type DomElement = (HTMLElement | SVGElement) & Record; +interface DomElement extends Element { + [key: string]: any; +} -type Props = { +interface Props { key?: string | number; data?: string; oncreate?: { (vnode: Vnode): never }; - onupdate?: { (vnode: Vnode, oldVnode: Vnode | TextVnode): never }; + onupdate?: { (vnode: Vnode, oldVnode: Vnode): never }; onremove?: { (oldVnode: Vnode): never }; - onbeforeupdate?: { (vnode: Vnode, oldVnode: Vnode | TextVnode): undefined | boolean }; -} & Record; - -type Component = (props?: Record | null, children?: VnodeOrUnknown) => VnodeOrUnknown | VnodeOrUnknown[]; - -type ValyrianComponent = - | Component - | (Record & { - view: Component; - }); - -type Current = { parentVnode?: Vnode; oldParentVnode?: Vnode; component?: VnodeComponent }; - -interface Plugin { - (v: Valyrian, options?: Record): never; -} - -interface Directive { - (value: any, vnode: Vnode, oldVnode?: Vnode | TextVnode): void | boolean; + shouldupdate?: { (vnode: Vnode, oldVnode: Vnode): undefined | boolean }; + "v-cleanup"?: Function; + [key: string | number | symbol]: any; } -interface ValyrianEventHandler { - (a: Event, dom: DomElement): void; -} +interface Children extends Array {} interface Vnode { - name: string; + new (tag: string, props: Props, children: Vnode[]): Vnode; + tag: string; props: Props; - children: VnodeOrUnknown[]; + children: Children; dom?: DomElement; - onCleanup?: FunctionConstructor[]; isSVG?: boolean; processed?: boolean; + component?: Component | POJOComponent; + nodeValue?: string; + [key: symbol]: any; } -class Vnode implements Vnode { - name: string; - props: Props; - children: VnodeOrUnknown[]; - dom?: DomElement; - onCleanup?: FunctionConstructor[]; - isSVG?: boolean; - processed?: boolean; +const Vnode = function Vnode(this: Vnode, tag: string, props: Props, children: Children) { + this.props = props; + this.children = children; + this.tag = tag; +} as unknown as Vnode; - constructor(name: string, props: Props, children: VnodeOrUnknown) { - this.props = props; - this.children = children; - this.name = name; - } +interface Component { + (props?: Record | null, children?: Children): Vnode | Children; + [key: string | number | symbol]: any; } -interface TextVnode { - dom?: Text; - nodeValue: string; +interface POJOComponent { + view: Component; + [key: string | number | symbol]: any; } -class TextVnode implements TextVnode { - dom?: Text; - nodeValue: string; +type ValyrianComponent = Component | POJOComponent; - constructor(nodeValue: string) { - this.nodeValue = nodeValue; - } +interface VnodeComponent extends Vnode { + tag: "__component__"; + component: ValyrianComponent; } -interface VnodeComponent { - component: ValyrianComponent; - props: Props; - children: VnodeOrUnknown[]; +interface VnodeWithDom extends Vnode { + dom: DomElement; } -class VnodeComponent implements VnodeComponent { - component: ValyrianComponent; - props: Props; - children: VnodeOrUnknown[]; +interface Directive { + (value: any, vnode: Vnode, oldVnode?: Vnode): void; +} - constructor(component: ValyrianComponent, props: Props, children: VnodeOrUnknown[]) { - this.props = props; - this.children = children; - this.component = component; - } +interface Plugin { + (v: v, options?: Record): never; } -interface Valyrian { - (tagOrComponent: string | ValyrianComponent, props?: Props | null, children?: VnodeOrUnknown): Vnode | VnodeComponent; - fragment: (props: Props, children: VnodeOrUnknown[]) => VnodeOrUnknown[]; +interface ValyrianApp { isMounted: boolean; - isNode: boolean; - reservedWords: string[]; - current: Current; - trust: (htmlString: string) => Vnode[]; - usePlugin: (plugin: Plugin, options: Record) => void; - onCleanup: (callback: typeof Function) => void; - updateProperty: (name: string, newVnode: Vnode & { dom: DomElement }, oldNode: Vnode & { dom: DomElement }) => void; - update: (props?: Props | null, ...children: VnodeOrUnknown) => string | void; - mount: (container: string | DomElement, component: ValyrianComponent, props?: Props | null, ...children: VnodeOrUnknown[]) => string | void; - unMount: () => string | boolean | void; - directive: (directive: string, handler: Directive) => void; - newInstance: () => Valyrian; - [x: string]: any; -} + eventListenerNames: Record; + cleanup: Function[]; -let isNode = typeof window === "undefined" || typeof global !== "undefined"; + eventListener?: EventListener; + mainVnode?: VnodeWithDom; + component?: VnodeComponent; + container?: DomElement; -// Create Node element -function createElement(tagName: string, isSVG: boolean = false): DomElement { - return isSVG ? document.createElementNS("http://www.w3.org/2000/svg", tagName) : document.createElement(tagName); + [key: string | number | symbol]: any; } -// Transforms a DOM node to a VNode -function domToVnode(dom: DomElement): Vnode { - let props: Props = {}; - [].forEach.call(dom.attributes, (prop: Attr) => (props[prop.nodeName] = prop.nodeValue)); - - let vnode: Vnode = new Vnode(dom.nodeName.toLowerCase(), props, []); - vnode.dom = dom; +interface MountedValyrianApp extends ValyrianApp { + eventListener: EventListener; + mainVnode: VnodeWithDom; + container: DomElement; + component: VnodeComponent; +} +const ValyrianSymbol = Symbol("Valyrian"); - for (let i = 0, l = dom.childNodes.length; i < l; i++) { - if (dom.childNodes[i].nodeType === 1) { - vnode.children.push(domToVnode(dom.childNodes[i] as DomElement)); - } else if (dom.childNodes[i].nodeType === 3) { - let textVnode = new TextVnode(dom.childNodes[i].nodeValue || ""); - textVnode.dom = dom.childNodes[i] as unknown as Text; - vnode.children.push(textVnode); +function hideDirective(test: boolean): Directive { + return (bool: boolean, vnode: Vnode, oldVnode?: Vnode) => { + let value = test ? bool : !bool; + if (value) { + let newdom = document.createTextNode(""); + if (oldVnode && oldVnode.dom && oldVnode.dom.parentNode) { + oldVnode.tag !== "#text" && onremove(oldVnode); + oldVnode.dom.parentNode.replaceChild(newdom, oldVnode.dom); + } + vnode.tag = "#text"; + vnode.children = []; + vnode.props = {}; + vnode.dom = newdom as unknown as DomElement; } - } - return vnode; + }; } -const trust = (htmlString: string) => { - let div = createElement("div"); +export const trust = (htmlString: string) => { + let div = createDomElement("div"); div.innerHTML = htmlString.trim(); return [].map.call(div.childNodes, (item) => domToVnode(item)) as Vnode[]; }; -// eslint-disable-next-line max-lines-per-function -function valyrian(): Valyrian { - const v: Valyrian = (tagOrComponent, props, ...children) => { - if (typeof tagOrComponent === "string") { - return new Vnode(tagOrComponent, props || {}, children); - } else { - return new VnodeComponent(tagOrComponent, props || {}, children); - } - }; +interface Current { + app?: ValyrianApp; + component?: ValyrianComponent; + vnode?: VnodeWithDom; + oldVnode?: VnodeWithDom; +} - v.fragment = (props: Props, vnodes: VnodeOrUnknown[]) => { - return vnodes; - }; +interface v { + (tagOrComponent: string | ValyrianComponent, props: Props, ...children: Children): Vnode | VnodeComponent; + fragment: (props: Props, ...children: Children) => Children; + current: Current; +} - v.isMounted = false; - v.isNode = isNode; - const reservedWords = ["key", "data", "v-once", "oncreate", "onupdate", "onremove", "onbeforeupdate"]; - v.reservedWords = reservedWords; - v.trust = trust; +export function v(tagOrComponent: string | ValyrianComponent, props: Props, ...children: Children): Vnode | VnodeComponent { + if (typeof tagOrComponent === "string") { + return new Vnode(tagOrComponent, props || {}, children); + } - const current: Current = { - parentVnode: undefined, - oldParentVnode: undefined, - component: undefined - }; - v.current = current; + const vnode = new Vnode("__component__", props || {}, children); + vnode.component = tagOrComponent; + return vnode as VnodeComponent; +} - const plugins = new Map(); +v.fragment = (props: Props, ...children: Children): Children => { + return children; +}; - v.usePlugin = (plugin: Plugin, options: Record = {}) => !plugins.has(plugin) && plugins.set(plugin, true) && plugin(v as Valyrian, options); +v.current = {} as Current; - let vnodesToCleanup: Vnode[] = []; +interface Directives { + [key: string]: Directive; +} - v.onCleanup = (callback: FunctionConstructor) => { - let parentVnode = v.current.parentVnode as Vnode; - if (!parentVnode.onCleanup) { - parentVnode.onCleanup = [] as FunctionConstructor[]; +const directives: Directives = { + "v-if": hideDirective(false), + "v-unless": hideDirective(true), + "v-for": (set: unknown[], vnode: Vnode) => { + vnode.children = set.map(vnode.children[0] as (value: unknown) => Function); + }, + "v-show": (bool: boolean, vnode: Vnode) => { + (vnode.dom as unknown as { style: { display: string } }).style.display = bool ? "" : "none"; + }, + "v-class": (classes: { [x: string]: boolean }, vnode: Vnode) => { + for (let name in classes) { + (vnode.dom as DomElement).classList.toggle(name, classes[name]); + } + }, + "v-html": (html: string, vnode: Vnode) => { + vnode.children = [trust(html)]; + }, + "v-cleanup"(cleanupFunction: Function) { + if (typeof cleanupFunction === "function") { + (this as unknown as ValyrianApp).cleanup.push(cleanupFunction); } + } +}; - parentVnode.onCleanup.push(callback); +interface ReservedProps { + [key: string]: true; +} - if (vnodesToCleanup.indexOf(parentVnode) === -1) { - vnodesToCleanup.push(parentVnode); - } - }; +const reservedProps: ReservedProps = { + key: true, + state: true, + oncreate: true, + onupdate: true, + onremove: true, + shouldupdate: true, + "v-cleanup": true, + "v-once": true, + + // Built in directives + "v-if": true, + "v-unless": true, + "v-for": true, + "v-show": true, + "v-class": true, + "v-html": true +}; - let cleanupVnodes = () => { - for (let l = vnodesToCleanup.length; l--; ) { - for (let callback of vnodesToCleanup[l].onCleanup as FunctionConstructor[]) { - callback(); - } - } - vnodesToCleanup = []; - }; +const plugins = new Set(); + +export const isNodeJs = Boolean(typeof process !== "undefined" && process.versions && process.versions.node); + +function createDomElement(tag: string, isSVG: boolean = false) { + return isSVG ? document.createElementNS("http://www.w3.org/2000/svg", tag) : document.createElement(tag); +} + +function domToVnode(dom: DomElement): VnodeWithDom { + let vnode = v( + dom.tagName.toLowerCase(), + {}, + ...Array.from(dom.childNodes) + .filter((child) => (child as DomElement).nodeType === 1 || (child as DomElement).nodeType === 3) + .map((child) => { + if ((child as DomElement).nodeType === 1) { + return domToVnode(child as DomElement); + } + + let text = new Vnode("#text", {}, []); + text.nodeValue = String((child as DomElement).nodeValue); + text.dom = child as DomElement; + return text; + }) + ); + [].forEach.call(dom.attributes, (prop: Attr) => (vnode.props[prop.nodeName] = prop.nodeValue)); + vnode.dom = dom; + return vnode as VnodeWithDom; +} + +export function isComponent(component?: unknown | ValyrianComponent): component is ValyrianComponent { + return typeof component === "function" || (typeof component === "object" && component !== null && "view" in component); +} + +export function isVnodeComponent(vnode?: unknown): vnode is VnodeComponent { + return vnode instanceof Vnode && vnode.tag === "__component__"; +} + +export function isVnode(component?: unknown): component is Vnode { + return component instanceof Vnode; +} + +/* + * Mounts a component to the DOM + mount('#app', () =>
Hello world
); // App is a Functional Component + mount('#app', { view: () =>
Hello world
}); // App is a POJO component with a view method + mount('#app', classInstance); // App is a class instance with a view method + mount('#app',
Hello world
); // App is a Vnode component (Vnode with tag __component__) +*/ + +export function mount(container: DomElement | string, component: ValyrianComponent | Vnode) { + let appContainer = null; + + if (isNodeJs) { + appContainer = typeof container === "string" ? createDomElement(container === "svg" ? "svg" : "div", container === "svg") : container; + } else { + appContainer = typeof container === "string" ? document.querySelectorAll(container)[0] : container; + } + + if (!appContainer) { + throw new Error("Container not found"); + } + + // If component is a POJO component or a Functional component or a Vnode + + let vnodeComponent: VnodeComponent | Vnode; + + if (isVnodeComponent(component)) { + vnodeComponent = component; + } else if (isComponent(component)) { + vnodeComponent = v(component, {}); + } else { + throw new Error("Component must be a Valyrian Component or a Vnode component"); + } - let mainContainer: DomElement | null = null; - let emptyComponent: ValyrianComponent = () => ""; - let mountedComponent: ValyrianComponent = emptyComponent; - - const attachedListeners: string[] = []; - function eventListener(e: Event) { - let dom = e.target as DomElement; - let name = `v-on${e.type}`; - while (dom) { - if (dom[name]) { - (dom[name] as ValyrianEventHandler)(e, dom); - if (!e.defaultPrevented) { - v.update(); + if (component[ValyrianSymbol]) { + unmount(component); + } else { + component[ValyrianSymbol] = { + isMounted: false, + eventListenerNames: {}, + isNodeJs, + cleanup: [] + }; + function eventListener(e: Event) { + let dom = e.target as DomElement & Record; + let name = `v-on${e.type}`; + while (dom) { + if (dom[name]) { + dom[name](e, dom); + if (!e.defaultPrevented) { + update(component); + } + return; } - return; + dom = dom.parentNode as DomElement; } - dom = dom.parentNode as DomElement; + } + component[ValyrianSymbol].eventListener = eventListener; + for (let plugin of plugins) { + plugin(v, component); } } - function updateProperty(prop: string, newVnode: Vnode & { dom: DomElement }, oldVnode?: Vnode): void | boolean { - if (reservedWords.indexOf(prop) !== -1) { - if (prop in directives) { - return directives[prop](newVnode.props[prop], newVnode, oldVnode); - } - } else if (typeof newVnode.props[prop] === "function") { - if (attachedListeners.indexOf(prop) === -1) { - (mainContainer as DomElement).addEventListener(prop.slice(2), eventListener); - attachedListeners.push(prop); - } - newVnode.dom[`v-${prop}`] = newVnode.props[prop]; - } else if (prop in newVnode.dom && !newVnode.isSVG) { - // eslint-disable-next-line eqeqeq - if (newVnode.dom[prop] != newVnode.props[prop]) { - newVnode.dom[prop] = newVnode.props[prop]; - } - } else if (oldVnode === undefined || newVnode.props[prop] !== oldVnode.props[prop]) { - if (newVnode.props[prop] === false) { - newVnode.dom.removeAttribute(prop); - } else { - newVnode.dom.setAttribute(prop, newVnode.props[prop]); - } + component[ValyrianSymbol].component = vnodeComponent; + component[ValyrianSymbol].container = appContainer; + component[ValyrianSymbol].mainVnode = domToVnode(appContainer); + + // update + return update(component); +} + +function cleanupVnodes(valyrianApp: ValyrianApp) { + for (let i = 0; i < valyrianApp.cleanup.length; i++) { + valyrianApp.cleanup[i](); + } + valyrianApp.cleanup = []; +} + +export function update(component?: ValyrianComponent | Vnode) { + if (component && component[ValyrianSymbol]) { + let valyrianApp = component[ValyrianSymbol]; + v.current.app = valyrianApp; + cleanupVnodes(valyrianApp); + let oldVnode: VnodeWithDom | null = valyrianApp.mainVnode as VnodeWithDom; + valyrianApp.mainVnode = new Vnode(valyrianApp.mainVnode.tag, valyrianApp.mainVnode.props, [valyrianApp.component]) as VnodeWithDom; + valyrianApp.mainVnode.dom = oldVnode.dom; + valyrianApp.mainVnode.isSVG = oldVnode.isSVG; + patch(valyrianApp.mainVnode, oldVnode, valyrianApp); + oldVnode = null; + valyrianApp.isMounted = true; + + if (isNodeJs) { + return valyrianApp.mainVnode.dom.innerHTML; } } - v.updateProperty = updateProperty; +} - // Update a Vnode.dom HTMLElement with new Vnode props that are different from old Vnode props - function updateProperties(newVnode: Vnode & { dom: DomElement }, oldVnode?: Vnode): void { - for (let prop in newVnode.props) { - if (updateProperty(prop, newVnode, oldVnode) === false) { - return; - } +export function unmount(component?: ValyrianComponent | Vnode) { + if (!component || !component[ValyrianSymbol]) { + return; + } + + let valyrianApp = component[ValyrianSymbol] as MountedValyrianApp; + + if (valyrianApp.isMounted) { + cleanupVnodes(valyrianApp); + let oldVnode: VnodeWithDom | null = valyrianApp.mainVnode as VnodeWithDom; + valyrianApp.mainVnode = new Vnode(valyrianApp.mainVnode.tag, valyrianApp.mainVnode.props, []) as VnodeWithDom; + valyrianApp.mainVnode.dom = oldVnode.dom; + valyrianApp.mainVnode.isSVG = oldVnode.isSVG; + patch(valyrianApp.mainVnode, oldVnode, valyrianApp); + oldVnode = null; + valyrianApp.isMounted = false; + } +} + +let emptyVnode = new Vnode("__empty__", {}, []); + +function onremove(vnode: Vnode) { + for (let i = 0; i < vnode.children.length; i++) { + vnode.children[i].tag !== "#text" && onremove(vnode.children[i]); + } + + vnode.props.onremove && vnode.props.onremove(vnode); +} + +function sharedUpdateProperty(prop: string, value: any, vnode: VnodeWithDom, oldVnode?: VnodeWithDom, valyrianApp?: MountedValyrianApp) { + // It is a reserved prop + if (reservedProps[prop]) { + // If it is a directive name call the directive + if (directives[prop]) { + directives[prop](vnode.props[prop], vnode, oldVnode); } + return; } - function removeProperties(newVnode: Vnode & { dom: DomElement }, oldVnode: Vnode) { - for (let name in oldVnode.props) { - if (name in newVnode.props === false && typeof oldVnode.props[name] !== "function" && reservedWords.indexOf(name) === -1) { - if (name in newVnode.dom) { - newVnode.dom[name] = null; - } else { - newVnode.dom.removeAttribute(name); - } - } + // It is not a reserved prop so we add it to the dom + if (typeof value === "function") { + if (valyrianApp && prop in valyrianApp.eventListenerNames === false) { + valyrianApp.eventListenerNames[prop] = true; + valyrianApp.container.addEventListener(prop.slice(2), valyrianApp.eventListener); } + vnode.dom[`v-${prop}`] = value; + return; } - const callRemove = (vnode: Vnode) => { - for (let i = 0, l = vnode.children.length; i < l; i++) { - vnode.children[i] instanceof Vnode && callRemove(vnode.children[i]); + if (prop in vnode.dom && vnode.isSVG === false) { + // eslint-disable-next-line eqeqeq + if (vnode.dom[prop] != value) { + vnode.dom[prop] = value; } + return; + } - vnode.props.onremove && vnode.props.onremove(vnode); - }; - // Patch a DOM node with a new VNode tree - function patch(newParentVnode: Vnode & { dom: DomElement }, oldParentVnode?: Vnode & { dom: DomElement }): void { - let oldTree = oldParentVnode?.children || []; - let newTree = newParentVnode.children; - let oldTreeLength = oldTree.length; - - current.parentVnode = newParentVnode; - current.oldParentVnode = oldParentVnode; - - // Flat newTree - for (let i = 0; i < newTree.length; i++) { - let childVnode = newTree[i]; - - if (childVnode instanceof Vnode) { - childVnode.isSVG = newParentVnode.isSVG || childVnode.name === "svg"; - } else if (childVnode === null || childVnode === undefined) { - newTree.splice(i--, 1); - } else if (Array.isArray(childVnode)) { - newTree.splice(i--, 1, ...childVnode); - } else if (childVnode instanceof VnodeComponent) { - v.current.component = childVnode; - newTree.splice( - i--, - 1, - ...[ - "view" in childVnode.component - ? childVnode.component.view.call(childVnode.component, childVnode.props, childVnode.children) - : (childVnode.component as Component).call(childVnode.component, childVnode.props, childVnode.children) - ] - ); - } else { - if (i > 0 && newTree[i - 1].nodeValue) { - newTree[i - 1].nodeValue += childVnode; - newTree.splice(i--, 1); - } else if (childVnode instanceof TextVnode === false) { - newTree[i] = new TextVnode(String(childVnode)); - } - } + // Use set attribute + if (!oldVnode || oldVnode.props[prop] !== value) { + if (value === false) { + vnode.dom.removeAttribute(prop); + } else { + vnode.dom.setAttribute(prop, value); } + } +} - let newTreeLength = newTree.length; +export function updateProperty(name: string, value: any, vnode: VnodeWithDom, oldVnode?: VnodeWithDom, valyrianApp?: MountedValyrianApp) { + if (name in vnode.props === false) { + vnode.props[name] = value; + } - // if newTree is empty, remove it - if (newTreeLength === 0) { - if (oldTreeLength > 0) { - for (let i = oldTreeLength; i--; ) { - oldTree[i] instanceof Vnode && callRemove(oldTree[i]); - } - // Fast node remove by setting textContent - newParentVnode.dom.textContent = ""; - } - // If the tree is keyed list and is not first render - } else if (oldTreeLength && newTree[0] instanceof Vnode && "key" in newTree[0].props) { - // 1. Mutate the old key list to match the new key list - let oldKeyedList; - - // if the oldTree does not have a keyed list fast remove all nodes - if (oldTree[0] instanceof Vnode === false || "key" in oldTree[0].props === false) { - for (let i = oldTreeLength; i--; ) { - oldTree[i] instanceof Vnode && callRemove(oldTree[i]); - } - // Fast node remove by setting textContent - newParentVnode.dom.textContent = ""; - oldKeyedList = []; - } else { - oldKeyedList = oldTree.map((vnode) => vnode.props.key); - } + sharedUpdateProperty(name, value, vnode, oldVnode, valyrianApp); +} - // 2. Obtain the max length of both lists - let newKeyedList = newTree.map((vnode) => vnode.props.key); - const maxListLength = Math.max(newTreeLength, oldKeyedList.length); - - // 3. Cycle over all the elements of the list until the max length - for (let i = 0; i < maxListLength; i++) { - if (i < newTreeLength) { - let childVnode = newTree[i]; - let oldChildVnode = oldKeyedList[i] === newKeyedList[i] ? oldTree[i] : oldTree[oldKeyedList.indexOf(childVnode.props.key)]; - let shouldPatch = true; - - if (oldChildVnode) { - childVnode.dom = oldChildVnode.dom; - oldChildVnode.processed = true; - if ("v-once" in childVnode.props || (childVnode.props.onbeforeupdate && childVnode.props.onbeforeupdate(childVnode, oldChildVnode) === false)) { - // skip this patch - childVnode.children = oldChildVnode.children; - shouldPatch = false; - } else { - removeProperties(childVnode as Vnode & { dom: DomElement }, oldChildVnode); - updateProperties(childVnode as Vnode & { dom: DomElement }, oldChildVnode); - if (v.isMounted) { - childVnode.props.onupdate && childVnode.props.onupdate(childVnode, oldChildVnode); - } else { - childVnode.props.oncreate && childVnode.props.oncreate(childVnode); - } - } - } else { - childVnode.dom = createElement(childVnode.name, childVnode.isSVG); - updateProperties(childVnode as Vnode & { dom: DomElement }); - childVnode.props.oncreate && childVnode.props.oncreate(childVnode); - } +function updateProperties(vnode: VnodeWithDom, oldVnode?: VnodeWithDom, valyrianApp?: MountedValyrianApp) { + for (let prop in vnode.props) { + // We asume that we clean the props in some directive + if (prop in vnode.props === false) { + return; + } - if (newParentVnode.dom.childNodes[i] === undefined) { - newParentVnode.dom.appendChild(childVnode.dom); - } else if (newParentVnode.dom.childNodes[i] !== childVnode.dom) { - oldTree[i] instanceof Vnode && !oldTree[i].processed && newKeyedList.indexOf(oldTree[i].props.key) === -1 && callRemove(oldTree[i]); - newParentVnode.dom.replaceChild(childVnode.dom, newParentVnode.dom.childNodes[i]); - } + sharedUpdateProperty(prop, vnode.props[prop], vnode, oldVnode, valyrianApp); + } - shouldPatch && patch(childVnode as Vnode & { dom: DomElement }, oldChildVnode); + if (oldVnode) { + for (let prop in oldVnode.props) { + if (prop in vnode.props === false && typeof oldVnode.props[prop] !== "function" && prop in reservedProps === false) { + if (prop in oldVnode.dom && vnode.isSVG === false) { + oldVnode.dom[prop] = null; } else { - if (!oldTree[i].processed) { - oldTree[i] instanceof Vnode && callRemove(oldTree[i]); - oldTree[i].dom.parentNode && newParentVnode.dom.removeChild(oldTree[i].dom); - } + oldVnode.dom.removeAttribute(prop); } } + } + } +} + +function flatTree(newVnode: Vnode): void { + let newTree = newVnode.children; + for (let i = 0; i < newTree.length; i++) { + let childVnode = newTree[i]; + if (childVnode instanceof Vnode) { + if (childVnode.tag !== "#text") { + if (childVnode.tag === "__component__") { + let component = childVnode.component as ValyrianComponent; + v.current.component = component; + let result = ("view" in component ? component.view : component).call(component, childVnode.props, ...childVnode.children); + + newTree.splice(i--, 1, result); + continue; + } + childVnode.isSVG = newVnode.isSVG || childVnode.tag === "svg"; + } + } else if (childVnode === null || childVnode === undefined) { + newTree.splice(i--, 1); + } else if (Array.isArray(childVnode)) { + newTree.splice(i--, 1, ...childVnode); } else { - for (let i = 0; i < newTreeLength; i++) { - let childVnode = newTree[i]; - let oldChildVnode = oldTree[i]; - - // if oldChildVnode is undefined, it's a new node, append it - if (oldChildVnode === undefined) { - if (childVnode instanceof Vnode) { - childVnode.dom = createElement(childVnode.name, childVnode.isSVG); - updateProperties(childVnode as Vnode & { dom: DomElement }); - childVnode.props.oncreate && childVnode.props.oncreate(childVnode); - patch(childVnode as Vnode & { dom: DomElement }); - } else { - childVnode.dom = document.createTextNode(childVnode.nodeValue); - } - newParentVnode.dom.appendChild(childVnode.dom); + if (i > 0 && newTree[i - 1].tag === "#text") { + newTree[i - 1].nodeValue += childVnode; + newTree.splice(i--, 1); + } else { + newTree[i] = new Vnode("#text", {}, []); + newTree[i].nodeValue = String(childVnode); + } + } + } +} + +function patchKeyedTree( + newVnode: VnodeWithDom, + newTree: (VnodeWithDom & { props: Props & { key: string } })[], + oldTree: (VnodeWithDom & { props: Props & { key: string } })[], + newTreeLength: number, + oldTreeLength: number, + valyrianApp?: MountedValyrianApp +) { + let oldKeyedList = oldTree.reduce((acc, vnode, i) => { + acc[vnode.props.key] = i; + return acc; + }, {} as { [key: string]: number }); + let newKeyedList = newTree.reduce((acc, vnode, i) => { + acc[vnode.props.key] = i; + return acc; + }, {} as { [key: string]: number }); + + for (let i = 0; i < newTreeLength; i++) { + let childVnode = newTree[i]; + let oldChildVnode = oldTree[oldKeyedList[childVnode.props.key]]; + let shouldPatch = true; + + if (oldChildVnode) { + childVnode.dom = oldChildVnode.dom; + if ("v-once" in childVnode.props || (childVnode.props.shouldupdate && childVnode.props.shouldupdate(childVnode, oldChildVnode) === false)) { + // skip this patch + childVnode.children = oldChildVnode.children; + shouldPatch = false; + } else { + updateProperties(childVnode, oldChildVnode, valyrianApp); + if (valyrianApp && valyrianApp.isMounted) { + childVnode.props.onupdate && childVnode.props.onupdate(childVnode, oldChildVnode); } else { - // if childVnode is Vnode, replace it with its DOM node - if (childVnode instanceof Vnode) { - if (childVnode.name === oldChildVnode.name) { - childVnode.dom = oldChildVnode.dom; - - if ("v-once" in childVnode.props || (childVnode.props.onbeforeupdate && childVnode.props.onbeforeupdate(childVnode, oldChildVnode) === false)) { - // skip this patch - childVnode.children = oldChildVnode.children; - continue; - } - - removeProperties(childVnode as Vnode & { dom: DomElement }, oldChildVnode); - updateProperties(childVnode as Vnode & { dom: DomElement }, oldChildVnode); - if (v.isMounted) { - childVnode.props.onupdate && childVnode.props.onupdate(childVnode, oldChildVnode); - } else { - childVnode.props.oncreate && childVnode.props.oncreate(childVnode); - } - patch(childVnode as Vnode & { dom: DomElement }, oldChildVnode); - } else { - childVnode.dom = createElement(childVnode.name, childVnode.isSVG); - updateProperties(childVnode as Vnode & { dom: DomElement }); - childVnode.props.oncreate && childVnode.props.oncreate(childVnode); - oldChildVnode instanceof Vnode && callRemove(oldChildVnode); - newParentVnode.dom.replaceChild(childVnode.dom, oldChildVnode.dom); - patch(childVnode as Vnode & { dom: DomElement }); - } - } else { - if (oldChildVnode instanceof Vnode) { - childVnode.dom = document.createTextNode(childVnode.nodeValue); - callRemove(oldChildVnode); - newParentVnode.dom.replaceChild(childVnode.dom, oldChildVnode.dom as DomElement); - } else { - childVnode.dom = oldChildVnode.dom; - // eslint-disable-next-line eqeqeq - if (childVnode.nodeValue != childVnode.dom.nodeValue) { - childVnode.dom.nodeValue = childVnode.nodeValue; - } - } - } + childVnode.props.oncreate && childVnode.props.oncreate(childVnode); } } + } else { + childVnode.dom = createDomElement(childVnode.tag, childVnode.isSVG); + updateProperties(childVnode, undefined, valyrianApp); + childVnode.props.oncreate && childVnode.props.oncreate(childVnode); + } - // For remaining old children: remove from DOM, garbage collect - for (let i = oldTreeLength - 1; i >= newTreeLength; --i) { - oldTree[i] instanceof Vnode && callRemove(oldTree[i]); - oldTree[i].dom.parentNode && newParentVnode.dom.removeChild(oldTree[i].dom); - } + if (newVnode.dom.childNodes[i] === undefined) { + newVnode.dom.appendChild(childVnode.dom); + } else if (newVnode.dom.childNodes[i] !== childVnode.dom) { + oldTree[i] && newKeyedList[oldTree[i].props.key] === undefined && onremove(oldTree[i]); + newVnode.dom.replaceChild(childVnode.dom, newVnode.dom.childNodes[i]); } - newParentVnode.children = newTree; + shouldPatch && patch(childVnode, oldChildVnode, valyrianApp); } - let mainVnode: Vnode | null = null; - let oldMainVnode: Vnode | null = null; + // For the rest of the children, we should remove them + for (let i = newTreeLength; i < oldTreeLength; i++) { + if (newKeyedList[oldTree[i].props.key] === undefined) { + let oldChildVnode = oldTree[i]; + onremove(oldChildVnode); + oldChildVnode.dom.parentNode && oldChildVnode.dom.parentNode.removeChild(oldChildVnode.dom); + } + } +} - v.unMount = () => { - mountedComponent = emptyComponent; - let result = v.update(); - v.isMounted = false; - mainContainer = null; - return result; - }; +// eslint-disable-next-line complexity +function patchNormalTree( + newVnode: VnodeWithDom, + newTree: (VnodeWithDom & { props: Props & { key: string } })[], + oldTree: (VnodeWithDom & { props: Props & { key: string } })[], + newTreeLength: number, + oldTreeLength: number, + valyrianApp?: MountedValyrianApp +) { + // If new tree and old tree have more than one child, we should update the dom + for (let i = 0; i < newTreeLength; i++) { + let oldChildVnode = oldTree[i]; + let newChildVnode = newTree[i]; + + // Old child does not exists + if (!oldChildVnode) { + // New child is a text node + if (newChildVnode.tag === "#text") { + newChildVnode.dom = document.createTextNode(newChildVnode.nodeValue as string) as unknown as DomElement; + newVnode.dom.appendChild(newChildVnode.dom); + continue; + } - v.update = (props, ...children) => { - if (mainVnode) { - cleanupVnodes(); - oldMainVnode = mainVnode; - mainVnode = new Vnode(mainVnode.name, mainVnode.props, [v(mountedComponent, props, ...children)]); - mainVnode.dom = oldMainVnode.dom; - mainVnode.isSVG = oldMainVnode.isSVG; - patch(mainVnode as Vnode & { dom: Node }, oldMainVnode as Vnode & { dom: Node }); - v.isMounted = true; - if (v.isNode) { - return (mainVnode.dom as HTMLElement).innerHTML; + // New child is a normal node + newChildVnode.dom = createDomElement(newChildVnode.tag, newChildVnode.isSVG); + updateProperties(newChildVnode, undefined, valyrianApp); + newVnode.dom.appendChild(newChildVnode.dom); + newChildVnode.props.oncreate && newChildVnode.props.oncreate(newChildVnode); + patch(newChildVnode, undefined, valyrianApp); + continue; + } + + // Old child exists + // New child is a text node + if (newChildVnode.tag === "#text") { + // Old child is a text node + if (oldChildVnode.tag === "#text") { + newChildVnode.dom = oldChildVnode.dom; + // eslint-disable-next-line eqeqeq + if (newChildVnode.dom.nodeValue != newChildVnode.nodeValue) { + newChildVnode.dom.nodeValue = newChildVnode.nodeValue as string; + } + continue; } + + // Old child is a normal node + newChildVnode.dom = document.createTextNode(newChildVnode.nodeValue as string) as unknown as DomElement; + onremove(oldChildVnode); + newVnode.dom.replaceChild(newChildVnode.dom, oldChildVnode.dom); + + continue; } - }; - v.mount = (container, component, props, ...children) => { - if (v.isMounted) { - v.unMount(); + // New child is a normal node + // Old child is the same type as new child + if (oldChildVnode.tag === newChildVnode.tag) { + newChildVnode.dom = oldChildVnode.dom; + // If we have a v-once directive or a shouldupdate method that returns false, we skip the update + if (newChildVnode.props["v-once"] || (newChildVnode.props.shouldupdate && newChildVnode.props.shouldupdate(newChildVnode, oldChildVnode) === false)) { + newChildVnode.children = oldChildVnode.children; + continue; + } + + // We update the dom element + updateProperties(newChildVnode, oldChildVnode, valyrianApp); + if (valyrianApp && valyrianApp.isMounted) { + newChildVnode.props.onupdate && newChildVnode.props.onupdate(newChildVnode, oldChildVnode); + } else { + newChildVnode.props.oncreate && newChildVnode.props.oncreate(newChildVnode); + } + patch(newChildVnode, oldChildVnode, valyrianApp); + + continue; } - if (isNode) { - mainContainer = typeof container === "string" ? createElement(container, container === "svg") : container; - } else { - mainContainer = typeof container === "string" ? (document.querySelectorAll(container)[0] as DomElement) : container; + // Old child is of a different type than new child + newChildVnode.dom = createDomElement(newChildVnode.tag, newChildVnode.isSVG); + updateProperties(newChildVnode, undefined, valyrianApp); + if (oldChildVnode.tag !== "#text") { + onremove(oldChildVnode); } + newChildVnode.props.oncreate && newChildVnode.props.oncreate(newChildVnode); + newVnode.dom.replaceChild(newChildVnode.dom, oldChildVnode.dom); + patch(newChildVnode, undefined, valyrianApp); + } - if (mainContainer !== null) { - mainVnode = domToVnode(mainContainer); - mainVnode.isSVG = mainVnode.name === "svg"; - oldMainVnode = mainVnode; - mountedComponent = component; + // For the rest of the children, we should remove them + for (let i = newTreeLength; i < oldTreeLength; i++) { + let oldChildVnode = oldTree[i]; + if (oldChildVnode.tag !== "#text") { + onremove(oldChildVnode); } + oldChildVnode.dom.parentNode && oldChildVnode.dom.parentNode.removeChild(oldChildVnode.dom); + } +} - return v.update(props, ...children); - }; +// eslint-disable-next-line complexity +function patch(newVnode: VnodeWithDom, oldVnode: VnodeWithDom = emptyVnode as VnodeWithDom, valyrianApp?: MountedValyrianApp) { + flatTree(newVnode); - let directives: Record = {}; + v.current.vnode = newVnode; + v.current.oldVnode = oldVnode; - v.directive = (name: string, directive: Directive) => { - let fullName = `v-${name}`; - if (reservedWords.indexOf(fullName) === -1) { - reservedWords.push(fullName); - directives[fullName] = directive; - } - }; + let newTree = newVnode.children; + let oldTree = oldVnode.children; + let oldTreeLength = oldTree.length; + let newTreeLength = newTree.length; - let hideDirective = (test: boolean) => (bool: boolean, vnode: Vnode, oldnode?: Vnode | TextVnode) => { - let value = test ? bool : !bool; - if (value) { - let newdom = document.createTextNode(""); - if (oldnode && oldnode.dom && oldnode.dom.parentNode) { - oldnode instanceof Vnode && callRemove(oldnode); - oldnode.dom.parentNode.replaceChild(newdom, oldnode.dom); - } - vnode.name = "#text"; - vnode.children = []; - vnode.props = {}; - vnode.dom = newdom as unknown as DomElement; - return false; + // If new tree is empty, remove all old nodes + if (newTreeLength === 0) { + for (let i = 0; i < oldTreeLength; i++) { + onremove(oldTree[i]); } - }; - v.directive("if", hideDirective(false)); - v.directive("unless", hideDirective(true)); - v.directive("for", (set: unknown[], vnode: Vnode) => { - vnode.children = set.map(vnode.children[0] as (value: unknown) => Function); - }); - v.directive("show", (bool: boolean, vnode: Vnode) => { - (vnode.dom as { style: { display: string } }).style.display = bool ? "" : "none"; - }); - v.directive("class", (classes: { [x: string]: boolean }, vnode: Vnode) => { - for (let name in classes) { - (vnode.dom as DomElement).classList.toggle(name, classes[name]); - } - }); - v.directive("html", (html: string, vnode: Vnode) => { - vnode.children = [trust(html)]; - }); + newVnode.dom.textContent = ""; + return; + } + + // If the tree is keyed list and is not first render and old tree is keyed list too + if (oldTreeLength && "key" in newTree[0].props && "key" in oldTree[0].props) { + patchKeyedTree(newVnode, newTree, oldTree, newTreeLength, oldTreeLength, valyrianApp); + return; + } - v.newInstance = valyrian; + patchNormalTree(newVnode, newTree, oldTree, newTreeLength, oldTreeLength, valyrianApp); +} + +export function directive(name: string, directive: Directive) { + let fullName = `v-${name}`; + if (reservedProps[fullName]) { + throw new Error(`Directive ${name} already exists`); + } - return v; + directives[fullName] = directive; + reservedProps[fullName] = true; +} + +export function plugin(plugin: Plugin) { + if (!plugins.has(plugin)) { + plugins.add(plugin); + } } -((isNode ? global : window) as unknown as { v: Valyrian }).v = valyrian(); +((isNodeJs ? global : window) as unknown as { v: v }).v = v; diff --git a/lib/index_.ts b/lib/index_.ts new file mode 100644 index 0000000..7e5a1b9 --- /dev/null +++ b/lib/index_.ts @@ -0,0 +1,564 @@ +/* eslint-disable complexity */ +/* eslint-disable sonarjs/cognitive-complexity */ +/* eslint-disable no-use-before-define */ +/* eslint-disable no-unused-vars */ + +type VnodeOrUnknown = VnodeComponent | Vnode | TextVnode | any; + +type DomAttribute = { nodeName: string; nodeValue: string }; + +type DomElement = (HTMLElement | SVGElement) & Record; + +type Props = { + key?: string | number; + data?: string; + oncreate?: { (vnode: Vnode): never }; + onupdate?: { (vnode: Vnode, oldVnode: Vnode | TextVnode): never }; + onremove?: { (oldVnode: Vnode): never }; + onbeforeupdate?: { (vnode: Vnode, oldVnode: Vnode | TextVnode): undefined | boolean }; +} & Record; + +type Component = (props?: Record | null, children?: VnodeOrUnknown) => VnodeOrUnknown | VnodeOrUnknown[]; + +type ValyrianComponent = + | Component + | (Record & { + view: Component; + }); + +type Current = { parentVnode?: Vnode; oldParentVnode?: Vnode; component?: VnodeComponent }; + +interface Plugin { + (v: Valyrian, options?: Record): never; +} + +interface Directive { + (value: any, vnode: Vnode, oldVnode?: Vnode | TextVnode): void | boolean; +} + +interface ValyrianEventHandler { + (a: Event, dom: DomElement): void; +} + +interface Vnode { + name: string; + props: Props; + children: VnodeOrUnknown[]; + dom?: DomElement; + onCleanup?: FunctionConstructor[]; + isSVG?: boolean; + processed?: boolean; +} + +class Vnode implements Vnode { + name: string; + props: Props; + children: VnodeOrUnknown[]; + dom?: DomElement; + onCleanup?: FunctionConstructor[]; + isSVG?: boolean; + processed?: boolean; + + constructor(name: string, props: Props, children: VnodeOrUnknown) { + this.props = props; + this.children = children; + this.name = name; + } +} + +interface TextVnode { + dom?: Text; + nodeValue: string; +} + +class TextVnode implements TextVnode { + dom?: Text; + nodeValue: string; + + constructor(nodeValue: string) { + this.nodeValue = nodeValue; + } +} + +interface VnodeComponent { + component: ValyrianComponent; + props: Props; + children: VnodeOrUnknown[]; +} + +class VnodeComponent implements VnodeComponent { + component: ValyrianComponent; + props: Props; + children: VnodeOrUnknown[]; + + constructor(component: ValyrianComponent, props: Props, children: VnodeOrUnknown[]) { + this.props = props; + this.children = children; + this.component = component; + } +} + +interface Valyrian { + (tagOrComponent: string | ValyrianComponent, props?: Props | null, children?: VnodeOrUnknown): Vnode | VnodeComponent; + fragment: (props: Props, children: VnodeOrUnknown[]) => VnodeOrUnknown[]; + isMounted: boolean; + isNode: boolean; + reservedWords: string[]; + current: Current; + trust: (htmlString: string) => Vnode[]; + usePlugin: (plugin: Plugin, options: Record) => void; + onCleanup: (callback: typeof Function) => void; + updateProperty: (name: string, newVnode: Vnode & { dom: DomElement }, oldNode: Vnode & { dom: DomElement }) => void; + update: (props?: Props | null, ...children: VnodeOrUnknown) => string | void; + mount: (container: string | DomElement, component: ValyrianComponent, props?: Props | null, ...children: VnodeOrUnknown[]) => string | void; + unMount: () => string | boolean | void; + directive: (directive: string, handler: Directive) => void; + newInstance: () => Valyrian; + [x: string]: any; +} + +let isNode = typeof window === "undefined" || typeof global !== "undefined"; + +// Create Node element +function createElement(tagName: string, isSVG: boolean = false): DomElement { + return isSVG ? document.createElementNS("http://www.w3.org/2000/svg", tagName) : document.createElement(tagName); +} + +// Transforms a DOM node to a VNode +function domToVnode(dom: DomElement): Vnode { + let props: Props = {}; + [].forEach.call(dom.attributes, (prop: Attr) => (props[prop.nodeName] = prop.nodeValue)); + + let vnode: Vnode = new Vnode(dom.nodeName.toLowerCase(), props, []); + vnode.dom = dom; + + for (let i = 0, l = dom.childNodes.length; i < l; i++) { + if (dom.childNodes[i].nodeType === 1) { + vnode.children.push(domToVnode(dom.childNodes[i] as DomElement)); + } else if (dom.childNodes[i].nodeType === 3) { + let textVnode = new TextVnode(dom.childNodes[i].nodeValue || ""); + textVnode.dom = dom.childNodes[i] as unknown as Text; + vnode.children.push(textVnode); + } + } + return vnode; +} + +const trust = (htmlString: string) => { + let div = createElement("div"); + div.innerHTML = htmlString.trim(); + + return [].map.call(div.childNodes, (item) => domToVnode(item)) as Vnode[]; +}; + +// eslint-disable-next-line max-lines-per-function +function valyrian(): Valyrian { + const v: Valyrian = (tagOrComponent, props, ...children) => { + if (typeof tagOrComponent === "string") { + return new Vnode(tagOrComponent, props || {}, children); + } else { + return new VnodeComponent(tagOrComponent, props || {}, children); + } + }; + + v.fragment = (props: Props, vnodes: VnodeOrUnknown[]) => { + return vnodes; + }; + + v.isMounted = false; + v.isNode = isNode; + const reservedWords = ["key", "data", "v-once", "oncreate", "onupdate", "onremove", "onbeforeupdate"]; + v.reservedWords = reservedWords; + v.trust = trust; + + const current: Current = { + parentVnode: undefined, + oldParentVnode: undefined, + component: undefined + }; + v.current = current; + + const plugins = new Map(); + + v.usePlugin = (plugin: Plugin, options: Record = {}) => !plugins.has(plugin) && plugins.set(plugin, true) && plugin(v as Valyrian, options); + + let vnodesToCleanup: Vnode[] = []; + + v.onCleanup = (callback: FunctionConstructor) => { + let parentVnode = v.current.parentVnode as Vnode; + if (!parentVnode.onCleanup) { + parentVnode.onCleanup = [] as FunctionConstructor[]; + } + + parentVnode.onCleanup.push(callback); + + if (vnodesToCleanup.indexOf(parentVnode) === -1) { + vnodesToCleanup.push(parentVnode); + } + }; + + let cleanupVnodes = () => { + for (let l = vnodesToCleanup.length; l--; ) { + for (let callback of vnodesToCleanup[l].onCleanup as FunctionConstructor[]) { + callback(); + } + } + vnodesToCleanup = []; + }; + + let mainContainer: DomElement | null = null; + let emptyComponent: ValyrianComponent = () => ""; + let mountedComponent: ValyrianComponent = emptyComponent; + + const attachedListeners: string[] = []; + function eventListener(e: Event) { + let dom = e.target as DomElement; + let name = `v-on${e.type}`; + while (dom) { + if (dom[name]) { + (dom[name] as ValyrianEventHandler)(e, dom); + if (!e.defaultPrevented) { + v.update(); + } + return; + } + dom = dom.parentNode as DomElement; + } + } + + function updateProperty(prop: string, newVnode: Vnode & { dom: DomElement }, oldVnode?: Vnode): void | boolean { + if (reservedWords.indexOf(prop) !== -1) { + if (prop in directives) { + return directives[prop](newVnode.props[prop], newVnode, oldVnode); + } + } else if (typeof newVnode.props[prop] === "function") { + if (attachedListeners.indexOf(prop) === -1) { + (mainContainer as DomElement).addEventListener(prop.slice(2), eventListener); + attachedListeners.push(prop); + } + newVnode.dom[`v-${prop}`] = newVnode.props[prop]; + } else if (prop in newVnode.dom && !newVnode.isSVG) { + // eslint-disable-next-line eqeqeq + if (newVnode.dom[prop] != newVnode.props[prop]) { + newVnode.dom[prop] = newVnode.props[prop]; + } + } else if (oldVnode === undefined || newVnode.props[prop] !== oldVnode.props[prop]) { + if (newVnode.props[prop] === false) { + newVnode.dom.removeAttribute(prop); + } else { + newVnode.dom.setAttribute(prop, newVnode.props[prop]); + } + } + } + v.updateProperty = updateProperty; + + // Update a Vnode.dom HTMLElement with new Vnode props that are different from old Vnode props + function updateProperties(newVnode: Vnode & { dom: DomElement }, oldVnode?: Vnode): void { + for (let prop in newVnode.props) { + if (updateProperty(prop, newVnode, oldVnode) === false) { + return; + } + } + } + + function removeProperties(newVnode: Vnode & { dom: DomElement }, oldVnode: Vnode) { + for (let name in oldVnode.props) { + if (name in newVnode.props === false && typeof oldVnode.props[name] !== "function" && reservedWords.indexOf(name) === -1) { + if (name in newVnode.dom) { + newVnode.dom[name] = null; + } else { + newVnode.dom.removeAttribute(name); + } + } + } + } + + const callRemove = (vnode: Vnode) => { + for (let i = 0, l = vnode.children.length; i < l; i++) { + vnode.children[i] instanceof Vnode && callRemove(vnode.children[i]); + } + + vnode.props.onremove && vnode.props.onremove(vnode); + }; + // Patch a DOM node with a new VNode tree + function patch(newParentVnode: Vnode & { dom: DomElement }, oldParentVnode?: Vnode & { dom: DomElement }): void { + let oldTree = oldParentVnode?.children || []; + let newTree = newParentVnode.children; + let oldTreeLength = oldTree.length; + + current.parentVnode = newParentVnode; + current.oldParentVnode = oldParentVnode; + + // Flat newTree + for (let i = 0; i < newTree.length; i++) { + let childVnode = newTree[i]; + + if (childVnode instanceof Vnode) { + childVnode.isSVG = newParentVnode.isSVG || childVnode.name === "svg"; + } else if (childVnode === null || childVnode === undefined) { + newTree.splice(i--, 1); + } else if (Array.isArray(childVnode)) { + newTree.splice(i--, 1, ...childVnode); + } else if (childVnode instanceof VnodeComponent) { + v.current.component = childVnode; + newTree.splice( + i--, + 1, + ...[ + "view" in childVnode.component + ? childVnode.component.view.call(childVnode.component, childVnode.props, childVnode.children) + : (childVnode.component as Component).call(childVnode.component, childVnode.props, childVnode.children) + ] + ); + } else { + if (i > 0 && newTree[i - 1].nodeValue) { + newTree[i - 1].nodeValue += childVnode; + newTree.splice(i--, 1); + } else if (childVnode instanceof TextVnode === false) { + newTree[i] = new TextVnode(String(childVnode)); + } + } + } + + let newTreeLength = newTree.length; + + // if newTree is empty, remove it + if (newTreeLength === 0) { + if (oldTreeLength > 0) { + for (let i = oldTreeLength; i--; ) { + oldTree[i] instanceof Vnode && callRemove(oldTree[i]); + } + // Fast node remove by setting textContent + newParentVnode.dom.textContent = ""; + } + // If the tree is keyed list and is not first render + } else if (oldTreeLength && newTree[0] instanceof Vnode && "key" in newTree[0].props) { + // 1. Mutate the old key list to match the new key list + let oldKeyedList; + + // if the oldTree does not have a keyed list fast remove all nodes + if (oldTree[0] instanceof Vnode === false || "key" in oldTree[0].props === false) { + for (let i = oldTreeLength; i--; ) { + oldTree[i] instanceof Vnode && callRemove(oldTree[i]); + } + // Fast node remove by setting textContent + newParentVnode.dom.textContent = ""; + oldKeyedList = []; + } else { + oldKeyedList = oldTree.map((vnode) => vnode.props.key); + } + + // 2. Obtain the max length of both lists + let newKeyedList = newTree.map((vnode) => vnode.props.key); + const maxListLength = Math.max(newTreeLength, oldKeyedList.length); + + // 3. Cycle over all the elements of the list until the max length + for (let i = 0; i < maxListLength; i++) { + if (i < newTreeLength) { + let childVnode = newTree[i]; + let oldChildVnode = oldKeyedList[i] === newKeyedList[i] ? oldTree[i] : oldTree[oldKeyedList.indexOf(childVnode.props.key)]; + let shouldPatch = true; + + if (oldChildVnode) { + childVnode.dom = oldChildVnode.dom; + oldChildVnode.processed = true; + if ("v-once" in childVnode.props || (childVnode.props.onbeforeupdate && childVnode.props.onbeforeupdate(childVnode, oldChildVnode) === false)) { + // skip this patch + childVnode.children = oldChildVnode.children; + shouldPatch = false; + } else { + removeProperties(childVnode as Vnode & { dom: DomElement }, oldChildVnode); + updateProperties(childVnode as Vnode & { dom: DomElement }, oldChildVnode); + if (v.isMounted) { + childVnode.props.onupdate && childVnode.props.onupdate(childVnode, oldChildVnode); + } else { + childVnode.props.oncreate && childVnode.props.oncreate(childVnode); + } + } + } else { + childVnode.dom = createElement(childVnode.name, childVnode.isSVG); + updateProperties(childVnode as Vnode & { dom: DomElement }); + childVnode.props.oncreate && childVnode.props.oncreate(childVnode); + } + + if (newParentVnode.dom.childNodes[i] === undefined) { + newParentVnode.dom.appendChild(childVnode.dom); + } else if (newParentVnode.dom.childNodes[i] !== childVnode.dom) { + oldTree[i] instanceof Vnode && !oldTree[i].processed && newKeyedList.indexOf(oldTree[i].props.key) === -1 && callRemove(oldTree[i]); + newParentVnode.dom.replaceChild(childVnode.dom, newParentVnode.dom.childNodes[i]); + } + + shouldPatch && patch(childVnode as Vnode & { dom: DomElement }, oldChildVnode); + } else { + if (!oldTree[i].processed) { + oldTree[i] instanceof Vnode && callRemove(oldTree[i]); + oldTree[i].dom.parentNode && newParentVnode.dom.removeChild(oldTree[i].dom); + } + } + } + } else { + for (let i = 0; i < newTreeLength; i++) { + let childVnode = newTree[i]; + let oldChildVnode = oldTree[i]; + + // if oldChildVnode is undefined, it's a new node, append it + if (oldChildVnode === undefined) { + if (childVnode instanceof Vnode) { + childVnode.dom = createElement(childVnode.name, childVnode.isSVG); + updateProperties(childVnode as Vnode & { dom: DomElement }); + childVnode.props.oncreate && childVnode.props.oncreate(childVnode); + patch(childVnode as Vnode & { dom: DomElement }); + } else { + childVnode.dom = document.createTextNode(childVnode.nodeValue); + } + newParentVnode.dom.appendChild(childVnode.dom); + } else { + // if childVnode is Vnode, replace it with its DOM node + if (childVnode instanceof Vnode) { + if (childVnode.name === oldChildVnode.name) { + childVnode.dom = oldChildVnode.dom; + + if ("v-once" in childVnode.props || (childVnode.props.onbeforeupdate && childVnode.props.onbeforeupdate(childVnode, oldChildVnode) === false)) { + // skip this patch + childVnode.children = oldChildVnode.children; + continue; + } + + removeProperties(childVnode as Vnode & { dom: DomElement }, oldChildVnode); + updateProperties(childVnode as Vnode & { dom: DomElement }, oldChildVnode); + if (v.isMounted) { + childVnode.props.onupdate && childVnode.props.onupdate(childVnode, oldChildVnode); + } else { + childVnode.props.oncreate && childVnode.props.oncreate(childVnode); + } + patch(childVnode as Vnode & { dom: DomElement }, oldChildVnode); + } else { + childVnode.dom = createElement(childVnode.name, childVnode.isSVG); + updateProperties(childVnode as Vnode & { dom: DomElement }); + childVnode.props.oncreate && childVnode.props.oncreate(childVnode); + oldChildVnode instanceof Vnode && callRemove(oldChildVnode); + newParentVnode.dom.replaceChild(childVnode.dom, oldChildVnode.dom); + patch(childVnode as Vnode & { dom: DomElement }); + } + } else { + if (oldChildVnode instanceof Vnode) { + childVnode.dom = document.createTextNode(childVnode.nodeValue); + callRemove(oldChildVnode); + newParentVnode.dom.replaceChild(childVnode.dom, oldChildVnode.dom as DomElement); + } else { + childVnode.dom = oldChildVnode.dom; + // eslint-disable-next-line eqeqeq + if (childVnode.nodeValue != childVnode.dom.nodeValue) { + childVnode.dom.nodeValue = childVnode.nodeValue; + } + } + } + } + } + + // For remaining old children: remove from DOM, garbage collect + for (let i = oldTreeLength - 1; i >= newTreeLength; --i) { + oldTree[i] instanceof Vnode && callRemove(oldTree[i]); + oldTree[i].dom.parentNode && newParentVnode.dom.removeChild(oldTree[i].dom); + } + } + + newParentVnode.children = newTree; + } + + let mainVnode: Vnode | null = null; + let oldMainVnode: Vnode | null = null; + + v.unMount = () => { + mountedComponent = emptyComponent; + let result = v.update(); + v.isMounted = false; + mainContainer = null; + return result; + }; + + v.update = (props, ...children) => { + if (mainVnode) { + cleanupVnodes(); + oldMainVnode = mainVnode; + mainVnode = new Vnode(mainVnode.name, mainVnode.props, [v(mountedComponent, props, ...children)]); + mainVnode.dom = oldMainVnode.dom; + mainVnode.isSVG = oldMainVnode.isSVG; + patch(mainVnode as Vnode & { dom: Node }, oldMainVnode as Vnode & { dom: Node }); + v.isMounted = true; + if (v.isNode) { + return (mainVnode.dom as HTMLElement).innerHTML; + } + } + }; + + v.mount = (container, component, props, ...children) => { + if (v.isMounted) { + v.unMount(); + } + + if (isNode) { + mainContainer = typeof container === "string" ? createElement(container, container === "svg") : container; + } else { + mainContainer = typeof container === "string" ? (document.querySelectorAll(container)[0] as DomElement) : container; + } + + if (mainContainer !== null) { + mainVnode = domToVnode(mainContainer); + mainVnode.isSVG = mainVnode.name === "svg"; + oldMainVnode = mainVnode; + mountedComponent = component; + } + + return v.update(props, ...children); + }; + + let directives: Record = {}; + + v.directive = (name: string, directive: Directive) => { + let fullName = `v-${name}`; + if (reservedWords.indexOf(fullName) === -1) { + reservedWords.push(fullName); + directives[fullName] = directive; + } + }; + + let hideDirective = (test: boolean) => (bool: boolean, vnode: Vnode, oldnode?: Vnode | TextVnode) => { + let value = test ? bool : !bool; + if (value) { + let newdom = document.createTextNode(""); + if (oldnode && oldnode.dom && oldnode.dom.parentNode) { + oldnode instanceof Vnode && callRemove(oldnode); + oldnode.dom.parentNode.replaceChild(newdom, oldnode.dom); + } + vnode.name = "#text"; + vnode.children = []; + vnode.props = {}; + vnode.dom = newdom as unknown as DomElement; + return false; + } + }; + + v.directive("if", hideDirective(false)); + v.directive("unless", hideDirective(true)); + v.directive("for", (set: unknown[], vnode: Vnode) => { + vnode.children = set.map(vnode.children[0] as (value: unknown) => Function); + }); + v.directive("show", (bool: boolean, vnode: Vnode) => { + (vnode.dom as { style: { display: string } }).style.display = bool ? "" : "none"; + }); + v.directive("class", (classes: { [x: string]: boolean }, vnode: Vnode) => { + for (let name in classes) { + (vnode.dom as DomElement).classList.toggle(name, classes[name]); + } + }); + v.directive("html", (html: string, vnode: Vnode) => { + vnode.children = [trust(html)]; + }); + + v.newInstance = valyrian; + + return v; +} + +((isNode ? global : window) as unknown as { v: Valyrian }).v = valyrian(); diff --git a/package.json b/package.json index 10150d2..7044c88 100644 --- a/package.json +++ b/package.json @@ -39,7 +39,7 @@ }, "scripts": { "dev:source": "cross-env NODE_ENV=development nodemon -e js,ts,json,css -w ./test -w ./lib -w ./plugins source.js", - "dev:test": "cross-env NODE_ENV=development nodemon -e js,ts,json,css -w ./test -w ./lib -w ./plugins --exec 'mocha --bail --timeout 10000 --slow 0 --require ./register \"test/**/*_test.js\"'", + "dev:test": "cross-env NODE_ENV=development nodemon -e js,ts,json,css,tsx -w ./test -w ./lib -w ./plugins --exec 'mocha --bail --timeout 10000 --slow 0 --require ./register'", "dev:test:nyc": "cross-env NODE_ENV=development nodemon -w ./test -w ./lib -w ./plugins --exec 'nyc --reporter=text --reporter=lcov mocha --timeout 10000 --slow 0 --require ./register \"test/**/*_test.js\"'", "build": "yarn build:source && yarn remark", "build:source": "cross-env NODE_ENV=production node source.js", @@ -49,7 +49,7 @@ "commit": "git add . && git-cz", "release": "release-it --verbose", "release-test": "release-it --dry-run --verbose", - "bench": " nodemon -e js,ts,json,css -w ./bench -w ./lib -w ./plugins --exec 'buffalo-test --require ./register'" + "bench": "nodemon -e js,ts,json,css,tsx -w ./bench -w ./lib -w ./plugins --exec 'buffalo-test --require ./register'" }, "dependencies": { "clean-css": "^5.2.2", @@ -68,6 +68,7 @@ }, "devDependencies": { "@release-it/conventional-changelog": "^3.3.0", + "@types/mocha": "^9.0.0", "@types/node": "^17.0.0", "@typescript-eslint/eslint-plugin": "^5.7.0", "@typescript-eslint/parser": "^5.7.0", diff --git a/plugins/hooks.js b/plugins/hooks.js index d19dac1..ba68c2e 100644 --- a/plugins/hooks.js +++ b/plugins/hooks.js @@ -1,8 +1,8 @@ let plugin = function (v) { let UND; - v.createHook = function ({ name, init, update, response }) { - name = `use${name.charAt(0).toUpperCase()}${name.slice(1).toLowerCase()}`; + function createHook ({ name, init, update, response }) { + if (!v[name]) { v[name] = (...args) => { let { component, parentVnode, oldParentVnode } = v.current; @@ -43,7 +43,7 @@ let plugin = function (v) { } }; - v.createHook({ + createHook({ name: "state", init: (value) => { let state = value; @@ -76,7 +76,7 @@ let plugin = function (v) { v.onCleanup(hook.onCleanup); } } - v.createHook({ + createHook({ name: "effect", init: (effect, changes) => { let hook = { effect, prev: changes }; diff --git a/plugins/node.js b/plugins/node.js index fdbd06d..32aaf57 100644 --- a/plugins/node.js +++ b/plugins/node.js @@ -1,7 +1,7 @@ /* eslint-disable sonarjs/cognitive-complexity */ +import { mount } from "../lib"; let fs = require("fs"); let path = require("path"); -require("ts-node/register"); let fetch = require("node-fetch"); let FormData = require("form-data"); @@ -71,10 +71,12 @@ function fileMethodFactory() { jsxFragment: "v.fragment" }; + console.log("tsc", tscProgOptions); + tsc.build(tscProgOptions); } - let result = esbuild.buildSync({ + let esbuildOptions = { entryPoints: [file], bundle: true, sourcemap: "external", @@ -86,7 +88,11 @@ function fileMethodFactory() { jsxFragment: "v.fragment", loader: { ".js": "jsx", ".ts": "tsx", ".mjs": "jsx" }, ...(options.esbuild || {}) - }); + }; + + console.log(esbuildOptions); + + let result = esbuild.buildSync(esbuildOptions); if (options.compact) { let result2 = await terser.minify(result.outputFiles[1].text, { @@ -341,25 +347,16 @@ icons.options = { } }; -let plugin = function (v) { - v.inline = inline; - v.sw = sw; - v.icons = icons; - v.htmlToDom = treeAdapter.htmlToDom; - v.domToHtml = treeAdapter.domToHtml; - v.domToHyperscript = treeAdapter.domToHyperscript; - v.htmlToHyperscript = treeAdapter.htmlToHyperscript; - v.hyperscriptToHtml = (...args) => v.mount("div", () => args); +let plugin = { + inline, + sw, + icons, + htmlTDom: treeAdapter.htmlToDom, + domToHtml: treeAdapter.domToHtml, + domToHyperscript: treeAdapter.domToHyperscript, + htmlToHyperscript: treeAdapter.htmlToHyperscript, + hyperscriptToHtml: (...args) => mount("div", () => args) }; -plugin.inline = inline; -plugin.sw = sw; -plugin.icons = icons; -plugin.htmlToDom = treeAdapter.htmlToDom; -plugin.domToHtml = treeAdapter.domToHtml; -plugin.domToHyperscript = treeAdapter.domToHyperscript; -plugin.htmlToHyperscript = treeAdapter.htmlToHyperscript; -plugin.hyperscriptToHtml = (...args) => v.mount("div", () => args); - plugin.default = plugin; module.exports = plugin; diff --git a/plugins/request.js b/plugins/request.js index e0acdbf..5e51f38 100644 --- a/plugins/request.js +++ b/plugins/request.js @@ -1,3 +1,5 @@ +const { isNodeJs } = require("../lib"); + function serialize(obj, prefix) { return Object.keys(obj) .map((p) => { @@ -7,159 +9,153 @@ function serialize(obj, prefix) { .join("&"); } -let plugin = function(v) { - function parseUrl(url, options = {}) { - let u = /^https?/gi.test(url) ? url : options.urls.base + url; - - let parts = u.split("?"); - u = parts[0] - .trim() - .replace(/^\/\//, "/") - .replace(/\/$/, "") - .trim(); +function parseUrl(url, options = {}) { + let u = /^https?/gi.test(url) ? url : options.urls.base + url; - if (parts[1]) { - u += `?${parts[1]}`; - } + let parts = u.split("?"); + u = parts[0].trim().replace(/^\/\//, "/").replace(/\/$/, "").trim(); - if (v.isNode && typeof options.urls.node === "string") { - options.urls.node = options.urls.node; + if (parts[1]) { + u += `?${parts[1]}`; + } - if (typeof options.urls.api === "string") { - options.urls.api = options.urls.api.replace(/\/$/gi, "").trim(); - u = u.replace(options.urls.api, options.urls.node); - } + if (isNodeJs && typeof options.urls.node === "string") { + options.urls.node = options.urls.node; - if (!/^https?/gi.test(u)) { - u = options.urls.node + u; - } + if (typeof options.urls.api === "string") { + options.urls.api = options.urls.api.replace(/\/$/gi, "").trim(); + u = u.replace(options.urls.api, options.urls.node); } - return u; + if (!/^https?/gi.test(u)) { + u = options.urls.node + u; + } } - function Request(baseUrl = "", options = {}) { - let url = baseUrl.replace(/\/$/gi, "").trim(); - options.urls = options.urls || {}; - let opts = { - methods: ["get", "post", "put", "patch", "delete"], - ...options, - urls: { - node: options.urls.node || null, - api: options.urls.api || null, - base: options.urls.base ? options.urls.base + url : url - } + return u; +} + +function Request(baseUrl = "", options = {}) { + let url = baseUrl.replace(/\/$/gi, "").trim(); + options.urls = options.urls || {}; + let opts = { + methods: ["get", "post", "put", "patch", "delete"], + ...options, + urls: { + node: options.urls.node || null, + api: options.urls.api || null, + base: options.urls.base ? options.urls.base + url : url + } + }; + + async function request(method, url, data, options = {}) { + let innerOptions = { + method: method.toLowerCase(), + headers: {}, + resolveWithFullResponse: false, + ...opts, + ...options }; - async function request(method, url, data, options = {}) { - let innerOptions = { - method: method.toLowerCase(), - headers: {}, - resolveWithFullResponse: false, - ...opts, - ...options - }; - - if (!innerOptions.headers.Accept) { - innerOptions.headers.Accept = "application/json"; - } + if (!innerOptions.headers.Accept) { + innerOptions.headers.Accept = "application/json"; + } - let acceptType = innerOptions.headers.Accept; - let contentType = innerOptions.headers["Content-Type"] || innerOptions.headers["content-type"] || ""; + let acceptType = innerOptions.headers.Accept; + let contentType = innerOptions.headers["Content-Type"] || innerOptions.headers["content-type"] || ""; - if (innerOptions.methods.indexOf(method) === -1) { - throw new Error("Method not allowed"); - } + if (innerOptions.methods.indexOf(method) === -1) { + throw new Error("Method not allowed"); + } - if (data) { - if (innerOptions.method === "get" && typeof data === "object") { - url += `?${serialize(data)}`; - } + if (data) { + if (innerOptions.method === "get" && typeof data === "object") { + url += `?${serialize(data)}`; + } - if (innerOptions.method !== "get") { - if (/json/gi.test(contentType)) { - innerOptions.body = JSON.stringify(data); + if (innerOptions.method !== "get") { + if (/json/gi.test(contentType)) { + innerOptions.body = JSON.stringify(data); + } else { + let formData; + if (data instanceof FormData) { + formData = data; } else { - let formData; - if (data instanceof FormData) { - formData = data; - } else { - formData = new FormData(); - for (let i in data) { - formData.append(i, data[i]); - } + formData = new FormData(); + for (let i in data) { + formData.append(i, data[i]); } - innerOptions.body = formData; } + innerOptions.body = formData; } } + } - let response = await fetch(parseUrl(url, opts), innerOptions); - - if (!response.ok) { - let err = new Error(response.statusText); - err.response = response; - throw err; - } + let response = await fetch(parseUrl(url, opts), innerOptions); - if (innerOptions.resolveWithFullResponse) { - return response; - } + if (!response.ok) { + let err = new Error(response.statusText); + err.response = response; + throw err; + } - if (/text/gi.test(acceptType)) { - return response.text(); - } + if (innerOptions.resolveWithFullResponse) { + return response; + } - if (/json/gi.test(acceptType)) { - return response.json(); - } + if (/text/gi.test(acceptType)) { + return response.text(); + } - return response; + if (/json/gi.test(acceptType)) { + return response.json(); } - request.new = (baseUrl, options) => Request(baseUrl, { ...opts, ...options }); + return response; + } - request.options = (key, value) => { - let result = opts; + request.new = (baseUrl, options) => Request(baseUrl, { ...opts, ...options }); - if (typeof key === "undefined") { - return result; - } + request.options = (key, value) => { + let result = opts; - let parsed = key.split("."); - let next; + if (typeof key === "undefined") { + return result; + } - while (parsed.length) { - next = parsed.shift(); + let parsed = key.split("."); + let next; - let nextIsArray = next.indexOf("[") > -1; - if (nextIsArray) { - let idx = next.replace(/\D/gi, ""); - next = next.split("[")[0]; - parsed.unshift(idx); - } + while (parsed.length) { + next = parsed.shift(); - if (parsed.length > 0 && typeof result[next] !== "object") { - result[next] = nextIsArray ? [] : {}; - } + let nextIsArray = next.indexOf("[") > -1; + if (nextIsArray) { + let idx = next.replace(/\D/gi, ""); + next = next.split("[")[0]; + parsed.unshift(idx); + } - if (parsed.length === 0 && typeof value !== "undefined") { - result[next] = value; - } + if (parsed.length > 0 && typeof result[next] !== "object") { + result[next] = nextIsArray ? [] : {}; + } - result = result[next]; + if (parsed.length === 0 && typeof value !== "undefined") { + result[next] = value; } - return result; - }; + result = result[next]; + } - opts.methods.forEach((method) => (request[method] = (url, data, options) => request(method, url, data, options))); + return result; + }; - return request; - } + opts.methods.forEach((method) => (request[method] = (url, data, options) => request(method, url, data, options))); + + return request; +} - v.request = Request(); -}; +const request = Request(); -plugin.default = plugin; -module.exports = plugin; +request.default = request; +module.exports = request; diff --git a/plugins/router.js b/plugins/router.js index 094ff44..b656fbd 100644 --- a/plugins/router.js +++ b/plugins/router.js @@ -1,279 +1,237 @@ -let plugin = function(v) { - function flat(array) { - return Array.isArray(array) ? array.flat(Infinity) : [array]; - } +import { isComponent, isNodeJs, isVnode, isVnodeComponent, mount, updateProperty, v } from "../lib"; - let addPath = (router, method, path, middlewares, i) => { - if (middlewares.length === 0) { - return; - } +function flat(array) { + return Array.isArray(array) ? array.flat(Infinity) : [array]; +} - let realpath = path.replace(/(\S)(\/+)$/, "$1"); +let addPath = (router, method, path, middlewares, i) => { + if (middlewares.length === 0) { + return; + } - // Find the express like params - let params = realpath.match(/:(\w+)?/gi) || []; + let realpath = path.replace(/(\S)(\/+)$/, "$1"); - // Set the names of the params found - for (i in params) { - params[i] = params[i].slice(1); - } + // Find the express like params + let params = realpath.match(/:(\w+)?/gi) || []; - let regexpPath = "^" + realpath.replace(/:(\w+)/gi, "([^\\/\\s]+)") + "$"; + // Set the names of the params found + for (i in params) { + params[i] = params[i].slice(1); + } - router.paths.push({ - method, - path: realpath, - middlewares: flat(middlewares), - params, - regexp: new RegExp(regexpPath, "i") - }); - }; + let regexpPath = "^" + realpath.replace(/:(\w+)/gi, "([^\\/\\s]+)") + "$"; - function parseQuery(queryParts) { - let parts = queryParts ? queryParts.split("&", 20) : []; - let query = {}; - let i = 0; - let nameValue; + router.paths.push({ + method, + path: realpath, + middlewares: flat(middlewares), + params, + regexp: new RegExp(regexpPath, "i") + }); +}; - for (; i < parts.length; i++) { - nameValue = parts[i].split("=", 2); - query[nameValue[0]] = nameValue[1]; - } +function parseQuery(queryParts) { + let parts = queryParts ? queryParts.split("&", 20) : []; + let query = {}; + let i = 0; + let nameValue; - return query; + for (; i < parts.length; i++) { + nameValue = parts[i].split("=", 2); + query[nameValue[0]] = nameValue[1]; } - function searchMiddlewares(router, path) { - let i; - let k; - let item; - let match; - let key; - let middlewares = []; - let params = {}; - let matches = []; - router.params = {}; - router.path = ""; - router.matches = []; - - // Search for middlewares - for (i = 0; i < router.paths.length; i++) { - item = router.paths[i]; - - match = item.regexp.exec(path); - // If we found middlewares - if (Array.isArray(match)) { - middlewares.push.apply(middlewares, item.middlewares); - match.shift(); - - // Parse params - for (k = 0; k < item.params.length; k++) { - key = item.params[k]; - params[key] = match.shift(); - } - - while (match.length) { - matches.push(match.shift()); - } - - if (item.method === "get") { - router.path = item.path; - break; - } + return query; +} + +function searchMiddlewares(router, path) { + let i; + let k; + let item; + let match; + let key; + let middlewares = []; + let params = {}; + let matches = []; + router.params = {}; + router.path = ""; + router.matches = []; + + // Search for middlewares + for (i = 0; i < router.paths.length; i++) { + item = router.paths[i]; + + match = item.regexp.exec(path); + // If we found middlewares + if (Array.isArray(match)) { + middlewares.push.apply(middlewares, item.middlewares); + match.shift(); + + // Parse params + for (k = 0; k < item.params.length; k++) { + key = item.params[k]; + params[key] = match.shift(); } - } - - router.params = params; - router.matches = matches; - return middlewares; - } - - async function searchComponent(router, middlewares) { - let response; - let item = false; - let req = { - params: router.params, - query: router.query, - url: router.url, - path: router.path, - matches: router.matches - }; - let i = 0; - - for (; i < middlewares.length; i++) { - response = await middlewares[i](req, response); - - if (response !== undefined) { - if (!response.view && typeof response === "function") { - response.view = response; - } + while (match.length) { + matches.push(match.shift()); + } - if (response.view) { - item = response; - break; - } + if (item.method === "get") { + router.path = item.path; + break; } } - return item; } - v.Router = function() { - const router = { - paths: [], - get(path, ...args) { - addPath(router, "get", path, args); - return router; - }, - use(...args) { - let path = typeof args[0] === "string" ? args.shift() : "/"; - let i; - let k; - let subrouter; - let item; - let subpath; - - for (i = 0; i < args.length; i++) { - subrouter = args[i]; - if (typeof subrouter === "function") { - addPath(router, "use", `${path}.*`, [subrouter]); - } else if (subrouter.paths) { - for (k = 0; k < subrouter.paths.length; k++) { - item = subrouter.paths[k]; - subpath = `${path}${item.path}`.replace(/^\/\//, "/"); - addPath(router, item.method, subpath, item.middlewares); - } - } - } - - return router; - }, - async go(path) { - let parts = path.split("?", 2); - let urlParts = parts[0].replace(/(.+)\/$/, "$1"); - let queryParts = parts[1]; - router.url = path; - - router.query = parseQuery(queryParts); - - let middlewares = searchMiddlewares(router, urlParts); + router.params = params; + router.matches = matches; - let component = await searchComponent(router, middlewares); + return middlewares; +} - if (!component || !component.view) { - throw new Error(`The url ${path} requested wasn't found`); - } - - return component; - } - }; - return router; +async function searchComponent(router, middlewares) { + let response; + let req = { + params: router.params, + query: router.query, + url: router.url, + path: router.path, + matches: router.matches }; + let i = 0; - let mainRouter; - let RoutesContainer; - async function runRoute(parentComponent, url, args) { - let response = await mainRouter.go(url); + for (; i < middlewares.length; i++) { + response = await middlewares[i](req, response); - if (parentComponent) { - args.unshift(v(response, ...args)); - args.unshift({}); - response = parentComponent; + if (response !== undefined && (isComponent(response) || isVnodeComponent(response))) { + return response; } + } +} + +class Router { + paths = []; + container = null; + url = ""; + query = {}; + options = {}; + current = ""; + params = {}; + matches = []; + + get(path, ...args) { + addPath(this, "get", path, args); + return this; + } - args.unshift(response); - - v.routes.params = mainRouter.params; - v.routes.query = mainRouter.query; - v.routes.url = mainRouter.url; - v.routes.path = mainRouter.path; - v.routes.matches = mainRouter.matches; - - if (!v.isNode) { - window.history.pushState(null, null, url); + use(...args) { + let path = typeof args[0] === "string" ? args.shift() : "/"; + let i; + let k; + let subrouter; + let item; + let subpath; + + for (i = 0; i < args.length; i++) { + subrouter = args[i]; + if (typeof subrouter === "function") { + addPath(this, "use", `${path}.*`, [subrouter]); + } else if (subrouter.paths) { + for (k = 0; k < subrouter.paths.length; k++) { + item = subrouter.paths[k]; + subpath = `${path}${item.path}`.replace(/^\/\//, "/"); + addPath(this, item.method, subpath, item.middlewares); + } + } } - args.unshift(RoutesContainer); - return v.mount.apply(v, args); + return this; } - v.routes = function(elementContainer, router) { - if (elementContainer && router) { - mainRouter = router; - RoutesContainer = elementContainer; - // Activate the use of the router - if (!v.isNode) { - function onPopStateGoToRoute() { - v.routes.go(document.location.pathname); - } - window.addEventListener("popstate", onPopStateGoToRoute, false); - onPopStateGoToRoute(); + routes() { + let routes = []; + this.paths.forEach((path) => { + if (path.method === "get") { + routes.push(path.path); } + }); + return routes; + } + + async go(path, parentComponent) { + if (!path) { + throw new Error("router.url.required"); } - }; - v.routes.url = ""; - v.routes.params = {}; - v.routes.query = {}; - v.routes.path = ""; - v.routes.matches = []; + let parts = path.split("?", 2); + let urlParts = parts[0].replace(/(.+)\/$/, "$1"); + let queryParts = parts[1]; + this.url = path; + this.query = parseQuery(queryParts); - v.routes.go = function(...args) { - let parentComponent; - let url; + let middlewares = searchMiddlewares(this, urlParts); - if (args[0]) { - let arg = args[0]; - let viewMethod = "view" in Object(arg) ? arg.view : arg; + let component = await searchComponent(this, middlewares); - if (typeof viewMethod === "function") { - parentComponent = args.shift(); - } + if (!component) { + throw new Error(`The url ${path} requested wasn't found`); } - if (typeof args[0] === "string") { - url = args.shift(); + if (parentComponent) { + let childComponent = isVnodeComponent(component) ? component : v(component, {}); + if (isVnodeComponent(parentComponent)) { + parentComponent.children.push(childComponent); + } else { + parentComponent = v(parentComponent, {}, childComponent); + } + component = parentComponent; } - if (!url) { - throw new Error("v.router.url.required"); + if (!isNodeJs) { + window.history.pushState(null, null, url); } - return runRoute(parentComponent, url, args); - }; + return mount(this.container, component); + } - v.routes.get = function() { - let routes = []; - mainRouter.paths.forEach((path) => { - if (path.method === "get") { - routes.push(path.path); - } - }); - return routes; - }; + mount(elementContainer, options = {}) { + if (elementContainer) { + this.container = elementContainer; + this.options = { ...options }; + this.options.directives = { + ...(this.options.directives || {}), + route: (url, vnode, oldnode) => { + vnode.props.href = url; + vnode.props.onclick = (e) => { + if (typeof url === "string" && url.length > 0) { + if (url.charAt(0) !== "/") { + let current = this.current.split("?", 2).shift().split("/"); + current.pop(); + url = `${current.join("/")}/${url}`; + } + + this.go(url); + } + e.preventDefault(); + }; - v.directive("route", (url, vnode, oldnode) => { - vnode.props.href = url; - vnode.props.onclick = (e) => { - if (typeof url === "string" && url.length > 0) { - if (url.charAt(0) !== "/") { - let current = v.routes.current - .split("?", 2) - .shift() - .split("/"); - current.pop(); - url = `${current.join("/")}/${url}`; + updateProperty("href", vnode, oldnode); + updateProperty("onclick", vnode, oldnode); } + }; - v.routes.go(url); + // Activate the use of the router + if (!isNodeJs) { + function onPopStateGoToRoute() { + this.go(document.location.pathname); + } + window.addEventListener("popstate", onPopStateGoToRoute.bind(this), false); + onPopStateGoToRoute(); } - e.preventDefault(); - }; - - v.updateProperty("href", vnode, oldnode); - v.updateProperty("onclick", vnode, oldnode); - }); -}; + } + } +} -plugin.default = plugin; -module.exports = plugin; +Router.default = Router; +module.exports = Router; diff --git a/plugins/signals.js b/plugins/signals.js index 2dce708..0abcffc 100644 --- a/plugins/signals.js +++ b/plugins/signals.js @@ -1,147 +1,132 @@ -let plugin = function (v) { - let signals = new Map(); +let signals = new Map(); - function makeUnsubscribe(subscriptions, computed, handler, cleanup) { - if (typeof cleanup === "function") { - computed.cleanup = cleanup; - } - computed.unsubscribe = () => { - subscriptions.delete(handler); - computed.cleanup(); - }; +function makeUnsubscribe(subscriptions, computed, handler, cleanup) { + if (typeof cleanup === "function") { + computed.cleanup = cleanup; } + computed.unsubscribe = () => { + subscriptions.delete(handler); + computed.cleanup(); + }; +} - function createGetter(signal, subscriptions, getters, nameOrHandler, getter) { - if (typeof nameOrHandler === "function") { - if (subscriptions.has(nameOrHandler) === false) { - let computed = v.Signal(() => nameOrHandler(signal.value)); - let cleanup = computed(); // Execute to register itself - makeUnsubscribe(subscriptions, computed, nameOrHandler, cleanup); - subscriptions.set(nameOrHandler, computed); - } - - return subscriptions.get(nameOrHandler); +function createGetter(signal, subscriptions, getters, nameOrHandler, getter) { + if (typeof nameOrHandler === "function") { + if (subscriptions.has(nameOrHandler) === false) { + // eslint-disable-next-line no-use-before-define + let computed = Signal(() => nameOrHandler(signal.value)); + let cleanup = computed(); // Execute to register itself + makeUnsubscribe(subscriptions, computed, nameOrHandler, cleanup); + subscriptions.set(nameOrHandler, computed); } - if (nameOrHandler in getters) { - throw new Error("Named computed already exists."); - } + return subscriptions.get(nameOrHandler); + } - getters[nameOrHandler] = getter; + if (nameOrHandler in getters) { + throw new Error("Named computed already exists."); } - // eslint-disable-next-line sonarjs/cognitive-complexity - v.Signal = function (value, key) { - if (typeof key !== "undefined" && signals.has(key)) { - let signal = signals.get(key); - signal.cleanup(); - return signal; - } + getters[nameOrHandler] = getter; +} - let subscriptions = new Map(); - let getters = {}; +// eslint-disable-next-line sonarjs/cognitive-complexity +function Signal(value, key) { + if (typeof key !== "undefined" && signals.has(key)) { + let signal = signals.get(key); + signal.cleanup(); + return signal; + } + + let subscriptions = new Map(); + let getters = {}; - let forceUpdate = false; + let forceUpdate = false; - let signal = new Proxy( - function (valOrPath, handler) { - if (typeof valOrPath === "undefined") { - return signal.value; - } else if (typeof valOrPath === "function") { - return createGetter(signal, subscriptions, getters, valOrPath); - } else if ( - typeof valOrPath === "string" && - typeof handler !== "undefined" - ) { - let parsed = valOrPath.split("."); - let result = signal.value; - let next; - while (parsed.length) { - next = parsed.shift(); - if (parsed.length > 0) { - if (typeof result[next] !== "object") { - result[next] = {}; - } - result = result[next]; - } else { - result[next] = - typeof handler === "function" ? handler(result[next]) : handler; + let signal = new Proxy( + function (valOrPath, handler) { + if (typeof valOrPath === "undefined") { + return signal.value; + } else if (typeof valOrPath === "function") { + return createGetter(signal, subscriptions, getters, valOrPath); + } else if (typeof valOrPath === "string" && typeof handler !== "undefined") { + let parsed = valOrPath.split("."); + let result = signal.value; + let next; + while (parsed.length) { + next = parsed.shift(); + if (parsed.length > 0) { + if (typeof result[next] !== "object") { + result[next] = {}; } + result = result[next]; + } else { + result[next] = typeof handler === "function" ? handler(result[next]) : handler; } - forceUpdate = true; - signal.value = signal.value; - } else { - signal.value = valOrPath; } - }, - { - set(state, prop, val) { - if ( - prop === "value" || - prop === "unsubscribe" || - prop === "cleanup" - ) { - let old = state[prop]; - state[prop] = val; - if (prop === "value" && (forceUpdate || val !== old)) { - forceUpdate = false; - for (let [handler, computed] of subscriptions) { - computed.cleanup(); - let cleanup = handler(val); - makeUnsubscribe(subscriptions, computed, handler, cleanup); - } + forceUpdate = true; + signal.value = signal.value; + } else { + signal.value = valOrPath; + } + }, + { + set(state, prop, val) { + if (prop === "value" || prop === "unsubscribe" || prop === "cleanup") { + let old = state[prop]; + state[prop] = val; + if (prop === "value" && (forceUpdate || val !== old)) { + forceUpdate = false; + for (let [handler, computed] of subscriptions) { + computed.cleanup(); + let cleanup = handler(val); + makeUnsubscribe(subscriptions, computed, handler, cleanup); } - return true; - } - }, - get(state, prop) { - if (prop === "value") { - return typeof state.value === "function" - ? state.value() - : state.value; } + return true; + } + }, + get(state, prop) { + if (prop === "value") { + return typeof state.value === "function" ? state.value() : state.value; + } - if ( - prop === "cleanup" || - prop === "unsubscribe" || - prop === "getter" - ) { - return state[prop]; - } + if (prop === "cleanup" || prop === "unsubscribe" || prop === "getter") { + return state[prop]; + } - if (prop in getters) { - return getters[prop](state.value); - } + if (prop in getters) { + return getters[prop](state.value); } } - ); + } + ); - Object.defineProperties(signal, { - value: { value, writable: true, enumerable: true }, - cleanup: { - value() { - for (let [handler, computed] of subscriptions) { - computed.unsubscribe(); - } - }, - writable: true, - enumerable: true + Object.defineProperties(signal, { + value: { value, writable: true, enumerable: true }, + cleanup: { + value() { + for (let [handler, computed] of subscriptions) { + computed.unsubscribe(); + } }, - getter: { - value(name, handler) { - createGetter(signal, subscriptions, getters, name, handler); - }, - enumerable: true - } - }); - - if (typeof key !== "undefined") { - signals.set(key, signal); + writable: true, + enumerable: true + }, + getter: { + value(name, handler) { + createGetter(signal, subscriptions, getters, name, handler); + }, + enumerable: true } + }); - return signal; - }; -}; + if (typeof key !== "undefined") { + signals.set(key, signal); + } + + return signal; +} -plugin.default = plugin; -module.exports = plugin; +Signal.default = Signal; +module.exports = Signal; diff --git a/plugins/store.js b/plugins/store.js index d7fbb13..79fddef 100644 --- a/plugins/store.js +++ b/plugins/store.js @@ -1,78 +1,74 @@ -let plugin = function (v) { - function keyExists(objectname, object, key) { - if (key in object === false) { - throw new Error(`The ${objectname} "${key}" does not exists.`); - } +function keyExists(objectname, object, key) { + if (key in object === false) { + throw new Error(`The ${objectname} "${key}" does not exists.`); } +} - function deepFreeze(obj) { - if (typeof obj === "object" && obj !== null && !Object.isFrozen(obj)) { - if (Array.isArray(obj)) { - for (let i = 0, l = obj.length; i < l; i++) { - deepFreeze(obj[i]); - } - } else { - for (let prop in obj) { - deepFreeze(obj[prop]); - } +function deepFreeze(obj) { + if (typeof obj === "object" && obj !== null && !Object.isFrozen(obj)) { + if (Array.isArray(obj)) { + for (let i = 0, l = obj.length; i < l; i++) { + deepFreeze(obj[i]); + } + } else { + for (let prop in obj) { + deepFreeze(obj[prop]); } - Object.freeze(obj); } - - return obj; + Object.freeze(obj); } - v.Store = function ({ state = {}, getters = {}, actions = {}, mutations = {} } = {}) { - let frozen = true; + return obj; +} - function isUnfrozen() { - if (frozen) { - throw new Error("You need to commit a mutation to change the state"); - } +function Store({ state = {}, getters = {}, actions = {}, mutations = {} } = {}) { + let frozen = true; + + function isUnfrozen() { + if (frozen) { + throw new Error("You need to commit a mutation to change the state"); } + } - let localState = typeof state === "function" ? state() : state; + let localState = typeof state === "function" ? state() : state; - this.state = new Proxy(localState || {}, { - get: (state, prop) => deepFreeze(state[prop]), - set: (state, prop, value) => { - isUnfrozen(); - state[prop] = value; - return true; - }, - deleteProperty: (state, prop) => { - isUnfrozen(); - delete state[prop]; - return true; - } - }); + this.state = new Proxy(localState || {}, { + get: (state, prop) => deepFreeze(state[prop]), + set: (state, prop, value) => { + isUnfrozen(); + state[prop] = value; + return true; + }, + deleteProperty: (state, prop) => { + isUnfrozen(); + delete state[prop]; + return true; + } + }); - this.getters = new Proxy(getters, { - get: (getters, getter) => { - try { - return getters[getter](this.state, this.getters); - } catch (e) { - // Getters should fail silently - } + this.getters = new Proxy(getters, { + get: (getters, getter) => { + try { + return getters[getter](this.state, this.getters); + } catch (e) { + // Getters should fail silently } - }); - - this.commit = (mutation, ...args) => { - keyExists("mutation", mutations, mutation); - frozen = false; - mutations[mutation](this.state, ...args); - frozen = true; - v.isMounted && v.update(); - }; + } + }); - this.dispatch = (action, ...args) => { - keyExists("action", actions, action); - return Promise.resolve(actions[action](this, ...args)); - }; + this.commit = (mutation, ...args) => { + keyExists("mutation", mutations, mutation); + frozen = false; + mutations[mutation](this.state, ...args); + frozen = true; + v.isMounted && v.update(); }; - v.useStore = (store) => (v.$store = store instanceof v.Store ? store : new v.Store(store)); -}; + this.dispatch = (action, ...args) => { + keyExists("action", actions, action); + return Promise.resolve(actions[action](this, ...args)); + }; +} -plugin.default = plugin; -module.exports = plugin; +Store.default = Store; +module.exports = Store; diff --git a/plugins/sw.js b/plugins/sw.js index 6a3120b..7108b42 100644 --- a/plugins/sw.js +++ b/plugins/sw.js @@ -1,19 +1,31 @@ -let plugin = function (v) { - if (!v.isNode) { - v.sw = async function (file = v.sw.file, options = v.sw.options) { - await navigator.serviceWorker.register(file, options); +const { isNodeJs } = require("../lib"); - v.sw.ready = true; - v.sw.file = file; - v.sw.options = options; - return navigator.serviceWorker; - }; +class Sw { + file = "/sw.js"; + options = { scope: "/" }; + ready = false; + sw = null; - v.sw.ready = false; - v.sw.file = "/sw.js"; - v.sw.options = { scope: "/" }; + constructor(file, options) { + if (isNodeJs) { + throw new Error("Not supported in Node.js"); + } + + if (file) { + this.file = file; + } + if (options) { + this.options = options; + } + } + + async register() { + await navigator.serviceWorker.register(this.file, this.options); + this.ready = true; + this.sw = navigator.serviceWorker; + return this.sw; } -}; +} -plugin.default = plugin; -module.exports = plugin; +Sw.default = Sw; +module.exports = Sw; diff --git a/plugins/v-model.js b/plugins/v-model.js index da12623..a4725d8 100644 --- a/plugins/v-model.js +++ b/plugins/v-model.js @@ -1,5 +1,8 @@ -let plugin = function (v) { - v.directive("model", ([model, property, event], vnode, oldvnode) => { +const { directive, updateProperty } = require("../lib"); + +let plugin = function () { + // eslint-disable-next-line sonarjs/cognitive-complexity + directive("model", ([model, property, event], vnode, oldVnode) => { if (vnode.name === "input") { event = event || "oninput"; switch (vnode.props.type) { @@ -14,8 +17,7 @@ let plugin = function (v) { model[property].splice(idx, 1); } }; - vnode.props.checked = - model[property].indexOf(vnode.dom.value) !== -1; + vnode.props.checked = model[property].indexOf(vnode.dom.value) !== -1; } else if ("value" in vnode.props) { vnode.props[event] = () => { if (model[property] === vnode.props.value) { @@ -62,20 +64,14 @@ let plugin = function (v) { }; vnode.children.forEach((child) => { if (child.name === "option") { - let value = - "value" in child.props - ? child.props.value - : child.children.join("").trim(); + let value = "value" in child.props ? child.props.value : child.children.join("").trim(); child.props.selected = model[property].indexOf(value) !== -1; } }); } else { vnode.children.forEach((child) => { if (child.name === "option") { - let value = - "value" in child.props - ? child.props.value - : child.children.join("").trim(); + let value = "value" in child.props ? child.props.value : child.children.join("").trim(); child.props.selected = value === model[property]; } }); @@ -86,10 +82,8 @@ let plugin = function (v) { } if (!vnode.props[event]) { - vnode.props[event] = (e) => (model[property] = e.target.value); + updateProperty(event, (e) => (model[property] = e.target.value), vnode, oldVnode, valyrianApp); } - - v.updateProperty(event, vnode, oldvnode); }); }; diff --git a/register.js b/register.js index 0bbafd4..c92b2c0 100644 --- a/register.js +++ b/register.js @@ -9,7 +9,9 @@ addHook( let loader = "default"; if (["js", "jsx", "ts", "tsx", "css", "json", "txt"].includes(extension)) { - if (["js", "jsx", "mjs", "ts", "tsx"].includes(extension)) { + if (["js", "jsx", "mjs"].includes(extension)) { + loader = "tsx"; + } else if (["ts", "tsx"].includes(extension)) { loader = "tsx"; } else if (extension === "txt") { loader = "text"; @@ -21,49 +23,17 @@ addHook( } let options = { - tsconfigRaw: { - compilerOptions: { - target: "ESNEXT", - module: "ESNEXT", - strict: true, - allowSyntheticDefaultImports: true, - allowJs: true, - esModuleInterop: true, - resolveJsonModule: true - } - }, - loader, + sourcefile: fileName, + sourcemap: "inline", minify: false, - format: "cjs", target: "esnext", - logLevel: "warning", + loader: loader, jsxFactory: "v", - jsxFragment: "v.fragment" - }; - - // Check if tsconfig.json exists with fs module - if ((extension === "ts" || extension === "tsx") && fs.existsSync(process.cwd() + "/tsconfig.json")) { - let tsconfig = fs.readFileSync(process.cwd() + "/tsconfig.json", "utf8"); - - let tsconfigRaw = JSON.parse(tsconfig); - let compilerOptions = tsconfigRaw.compilerOptions || {}; - - options.tsconfigRaw = { ...options.tsconfigRaw, ...tsconfigRaw }; - options.tsconfigRaw.compilerOptions = { ...options.tsconfigRaw.compilerOptions, ...compilerOptions }; + jsxFragment: "v.fragment", - if (compilerOptions.target) { - options.target = compilerOptions.target.toLowerCase(); - } - - if (compilerOptions.module) { - let format = compilerOptions.module.toLowerCase(); - if (format === "commonjs") { - options.format = "cjs"; - } else if (format.startsWith("es")) { - options.format = "esm"; - } - } - } + logLevel: "warning", + format: "cjs" + }; let { code: transformed } = transformSync(code, options); if (/"use strict"\;/gi.test(code) === false) { diff --git a/source.js b/source.js index c3161d6..d8b95df 100644 --- a/source.js +++ b/source.js @@ -1,4 +1,4 @@ -require("./register"); +require("./register.js"); let { inline } = require("./plugins/node"); let { writeFileSync } = require("fs"); const GzipSize = import("gzip-size"); @@ -8,7 +8,7 @@ async function run() { const gzipSizeSync = (await GzipSize).gzipSizeSync; inline.extensions("ts"); await inline.ts("./lib/index.ts", { - compact: true, + compact: false, declarationDir: "dist/@types", tsc: { include: files diff --git a/test/directives_test.js b/test/directives_test.js index 9ae29e7..57b7804 100644 --- a/test/directives_test.js +++ b/test/directives_test.js @@ -2,27 +2,20 @@ const expect = require("expect"); const faker = require("faker"); const dayjs = require("dayjs"); -import "../lib"; +import { directive, mount, trust, update, updateProperty } from "../lib/index"; -const nodePlugin = require("../plugins/node"); -v.usePlugin(nodePlugin); +require("../plugins/node"); // eslint-disable-next-line max-lines-per-function describe("Directives", () => { describe("Directive creation", () => { - let result; - it("should be able create a directive", () => { + let result; let expected = "Hello world"; - v.directive("test", (value) => (result = `Hello ${value}`)); - v.mount("div", () =>
); - expect(result).toEqual(expected); - }); - it("should not be able overwrite a directive", () => { - let expected = "Hello world"; - v.directive("test", () => (result = "Something else")); - v.mount("div", () =>
); + directive("test", (value) => (result = `Hello ${value}`)); + + mount("div", () =>
); expect(result).toEqual(expected); }); @@ -30,16 +23,18 @@ describe("Directives", () => { let newVnode; let oldVnode; - v.directive("test2", (v, vnode, oldvnode) => { + let app = () =>
; + + directive("test2", (v, vnode, old) => { newVnode = vnode; - oldVnode = oldvnode; + oldVnode = old; }); - v.mount("div", () =>
); - v.update(); + mount("div", app); + update(app); expect(newVnode).toEqual({ - name: "div", + tag: "div", props: { "v-test2": true }, @@ -49,7 +44,7 @@ describe("Directives", () => { }); expect(oldVnode).toEqual({ - name: "div", + tag: "div", props: { "v-test2": true }, @@ -60,59 +55,65 @@ describe("Directives", () => { }); it("should be able to identify if this is first render or update", () => { - v.directive("create", (placeholder, vnode, oldvnode) => { - if (!oldvnode) { + let app = () =>
; + + directive("create", (v, vnode, oldVnode) => { + if (!oldVnode) { vnode.children = ["First render, vnode created"]; } else { vnode.children = ["Second render, vnode updated"]; } }); - let component = () =>
; - let result = v.mount("body", component); + let result = mount("body", app); + expect(result).toEqual("
First render, vnode created
"); - let result2 = v.update(); + let result2 = update(app); expect(result2).toEqual("
Second render, vnode updated
"); }); it("should be able to modify the children of a vnode", () => { let expected = "
Hello world
"; - v.directive("test3", (v, vnode) => (vnode.children = ["Hello world"])); - let result = v.mount("div", () => ( + + directive("test3", (v, vnode) => { + vnode.children = ["Hello world"]; + }); + + let app = () => (
Hello John Doe
- )); + ); + + let result = mount("div", app); expect(result).toEqual(expected); }); /** * Modify properties is not guaranteed because the properties are processed by place - * If the directive needs to do update previous properties you need to update the property using the v.updateProperty method + * If the directive needs to update previous properties you need to update the property using the v.updateProperty method */ it("Modify properties is not guaranteed", () => { let update = false; - v.directive("test4", (p, vnode, oldVnode) => { + let app = () =>
; + + directive("test4", (v, vnode, oldVnode) => { // Try to change u property vnode.props.u = "property changed"; if (update) { - if (oldVnode || v.addProperty === undefined) { - v.updateProperty("u", vnode, oldVnode); - } else { - v.addProperty("u", vnode); - } + updateProperty("u", "property changed", vnode, oldVnode); } // Try to change x property vnode.props.x = "property changed"; }); - let result = v.mount("div", () =>
); + + let result = mount("div", app); expect(result).toEqual('
'); - v.unMount(); update = true; - let result2 = v.mount("div", () =>
); + let result2 = mount("div", app); expect(result2).toEqual('
'); }); @@ -125,14 +126,14 @@ describe("Directives", () => { let formatDate = (value) => dayjs(value).format("MMMM D, YYYY"); - v.directive("date-inline", (date, vnode) => (vnode.children = [formatDate(date)])); - v.directive("date", (v, vnode) => (vnode.children = [formatDate(vnode.children[0])])); + directive("date-inline", (date, vnode) => (vnode.children = [formatDate(date)])); + directive("date", (_, vnode) => (vnode.children = [formatDate(vnode.children[0])])); let date = "08-16-2018"; - let result = v.mount("div", () =>
); + let result = mount("div", () =>
); expect(result).toEqual(expected); - result = v.mount("div", () =>
{date}
); + result = mount("div", () =>
{date}
); expect(result).toEqual(expected); }); @@ -142,7 +143,7 @@ describe("Directives", () => { * This is not added to the base library but it shows the capabilities of valyrian directives */ it("v-switch example", () => { - v.directive("switch", (value, vnode) => { + directive("switch", (value, vnode) => { for (let i = 0, l = vnode.children.length; i < l; i++) { let [test, handler] = vnode.children[i]; let result = false; @@ -172,25 +173,25 @@ describe("Directives", () => { // Direct equality expected = "
Hello John
"; name = "John"; - result = v.mount("div", component); + result = mount("div", component); expect(result).toEqual(expected); // Comparison method expected = "
Hello John Doe
"; name = "John Doe"; - result = v.mount("div", component); + result = mount("div", component); expect(result).toEqual(expected); // Result method expected = "
Hello Jane Doe
"; name = "Jane"; - result = v.mount("div", component); + result = mount("div", component); expect(result).toEqual(expected); // If no case return the value as children expected = "
Hello Anonymous
"; name = "Hello Anonymous"; - result = v.mount("div", component); + result = mount("div", component); expect(result).toEqual(expected); }); }); @@ -206,7 +207,7 @@ describe("Directives", () => { it("should create 10 list items", () => { let items = faker.lorem.words(10).split(" "); let expected = "
    " + items.reduce((str, word) => str + `
  • ${word}
  • `, "") + "
"; - let result = v.mount("body", () =>
    {(word) =>
  • {word}
  • }
); + let result = mount("body", () =>
    {(word) =>
  • {word}
  • }
); expect(result).toEqual(expected); }); @@ -215,7 +216,7 @@ describe("Directives", () => { let items = faker.lorem.words(10).split(" "); let i = 0; let expected = "
    " + items.reduce((str, word) => str + `
  • ${i++} - ${word}
  • `, "") + "
"; - let result = v.mount("body", () => ( + let result = mount("body", () => (
    {(word, i) => (
  • @@ -240,8 +241,7 @@ describe("Directives", () => { let expected = "
    Hello world
    "; values.forEach((value) => { - v.unMount(); - let result = v.mount("div", () => ( + let result = mount("div", () => (
    Hello world
    @@ -256,8 +256,7 @@ describe("Directives", () => { let expected = "
    "; values.forEach((value) => { - v.unMount(); - let result = v.mount("div", () => ( + let result = mount("div", () => (
    Hello world
    @@ -271,15 +270,16 @@ describe("Directives", () => { let expected1 = "
    Hello world
    "; let expected2 = "
    "; - let result1 = v.mount("div", () => ( + let app = () => (
    Hello world
    - )); + ); + let result1 = mount("div", app); expect(result1).toEqual(expected1); value = false; - let result2 = v.update(); + let result2 = update(app); expect(result2).toEqual(expected2); }); }); @@ -298,8 +298,7 @@ describe("Directives", () => { let expected = "
    Hello world
    "; values.forEach((value) => { - v.unMount(); - let result = v.mount("div", () => ( + let result = mount("div", () => (
    Hello world
    @@ -314,8 +313,7 @@ describe("Directives", () => { let expected = "
    "; values.forEach((value) => { - v.unMount(); - let result = v.mount("div", () => ( + let result = mount("div", () => (
    Hello world
    @@ -333,7 +331,7 @@ describe("Directives", () => { it("should show a vnode if true", () => { let value = true; let expected = "
    Hello world
    "; - let result = v.mount("div", () => ( + let result = mount("div", () => (
    Hello world
    @@ -345,7 +343,7 @@ describe("Directives", () => { it("should hide a vnode if false", () => { let value = false; let expected = '
    Hello world
    '; - let result = v.mount("div", () => ( + let result = mount("div", () => (
    Hello world
    @@ -364,11 +362,12 @@ describe("Directives", () => { world: true }; - let result = v.mount("body", () =>
    ); + let app = () =>
    ; + let result = mount("body", app); expect(result).toEqual('
    '); classes.world = false; - let result2 = v.update(); + let result2 = update(app); expect(result2).toEqual("
    "); }); @@ -376,32 +375,32 @@ describe("Directives", () => { let classes = { world: true }; - - let result = v.mount("body", () =>
    ); + let app = () =>
    ; + let result = mount("body", app); expect(result).toEqual('
    '); classes.world = false; - let result2 = v.update(); + let result2 = update(app); expect(result2).toEqual('
    '); }); }); /** * The directive v-once is used to render just once and skip all subsequent render updates - * Similar to write the lifecycle onbeforeupdate={() => false} + * Similar to write the lifecycle shouldupdate={() => false} */ describe("v-once", () => { it("should not update the dom after first render", () => { let Store = { hello: "world" }; - let Component = () =>
    Hello {Store.hello}
    ; + let app = () =>
    Hello {Store.hello}
    ; - let result = v.mount("body", Component); + let result = mount("body", app); expect(result).toEqual("
    Hello world
    "); // We update our store Store.hello = "John Doe"; - let result2 = v.update(); + let result2 = update(app); expect(result2).toEqual("
    Hello world
    "); }); }); @@ -414,17 +413,14 @@ describe("Directives", () => { describe("v-html", () => { it("should handle direct html render", () => { // Using trust example - let Component = () =>
    {v.trust("
    Hello world
    ")}
    ; - let result = v.mount("body", Component); + let Component = () =>
    {trust("
    Hello world
    ")}
    ; + let result = mount("body", Component); expect(result).toEqual("
    Hello world
    "); - // Unmount to clean the instance - v.unMount(); - // Using v-html directive let Component2 = () =>
    ; - let result2 = v.mount("body", Component2); + let result2 = mount("body", Component2); expect(result2).toEqual("
    Hello world
    "); }); @@ -436,31 +432,31 @@ describe("Directives", () => { it("should use v-if with v-for directives", () => { let arr = [1, 2, 3, 4]; let show = true; - let component = () => ( + let app = () => (
    {(i) => {i}}
    ); - let result = v.mount("body", component); + let result = mount("body", app); expect(result).toEqual("
    1234
    "); show = false; - let result2 = v.update(); + let result2 = update(app); expect(result2).toEqual(""); }); }); /** - * The data directive is used just to pass data without creating an attribute on the node. + * The state directive is used just to pass data without creating an attribute on the node. * And its main use is in the lifecycle methods to validate properties or changes */ - describe("reserved word data", () => { + describe("reserved word state", () => { it("should not render an attribute", () => { - let data = { hello: "world" }; - let Component = () =>
    oldVnode.props.data.hello !== newVnode.props.data.hello} />; + let state = { hello: "world" }; + let Component = () =>
    oldVnode.props.state.hello !== newVnode.props.state.hello} />; - let result = v.mount("body", Component); + let result = mount("body", Component); expect(result).toEqual("
    "); }); }); diff --git a/test/hooks_test.js b/test/hooks_test.js index 948244d..9020159 100644 --- a/test/hooks_test.js +++ b/test/hooks_test.js @@ -1,10 +1,9 @@ import "../lib"; +import "../plugins/node"; import expect from "expect"; import hooksPlugin from "../plugins/hooks"; -import nodePlugin from "../plugins/node"; -v.usePlugin(nodePlugin); v.usePlugin(hooksPlugin); describe("Hooks", () => { diff --git a/test/hyperscript_test.js b/test/hyperscript_test.js index 83cf629..8b0265e 100644 --- a/test/hyperscript_test.js +++ b/test/hyperscript_test.js @@ -1,14 +1,12 @@ -import "../lib"; +require("../plugins/node"); import expect from "expect"; -import nodePlugin from "../plugins/node"; - -v.usePlugin(nodePlugin); +import { trust } from "../lib"; describe("Hyperscript", () => { it("should create a div element", () => { expect(v("div")).toEqual({ - name: "div", + tag: "div", props: {}, children: [] }); @@ -16,7 +14,7 @@ describe("Hyperscript", () => { it("should create a div element with a text child", () => { expect(v("div", null, "Hello")).toEqual({ - name: "div", + tag: "div", props: {}, children: ["Hello"] }); @@ -24,11 +22,11 @@ describe("Hyperscript", () => { it("should create a div element with an element child", () => { expect(v("div", null, v("span"))).toEqual({ - name: "div", + tag: "div", props: {}, children: [ { - name: "span", + tag: "span", props: {}, children: [] } @@ -38,7 +36,7 @@ describe("Hyperscript", () => { it("should create a div element with comma separated children", () => { expect(v("div", null, "Hello ", "world")).toEqual({ - name: "div", + tag: "div", props: {}, children: ["Hello ", "world"] }); @@ -46,7 +44,7 @@ describe("Hyperscript", () => { it("should create a div element with array of children", () => { expect(v("div", null, ["Hello ", "world"])).toEqual({ - name: "div", + tag: "div", props: {}, children: [["Hello ", "world"]] }); @@ -54,12 +52,12 @@ describe("Hyperscript", () => { it("should create a div element with mixed array of children and comma separated children", () => { expect(v("div", null, ["Hello ", "world"], v("span", null, "Whats up"))).toEqual({ - name: "div", + tag: "div", props: {}, children: [ ["Hello ", "world"], { - name: "span", + tag: "span", props: {}, children: ["Whats up"] } @@ -69,7 +67,7 @@ describe("Hyperscript", () => { it("should create a div element with mixed nested arrays of children ", () => { expect(v("div", null, ["Hello ", "world", ["Only", ["for", "this", ["time"]]]])).toEqual({ - name: "div", + tag: "div", props: {}, children: [["Hello ", "world", ["Only", ["for", "this", ["time"]]]]] }); @@ -77,7 +75,7 @@ describe("Hyperscript", () => { it("should create a div element with props", () => { expect(v("div", { id: "unique", class: "unique" })).toEqual({ - name: "div", + tag: "div", props: { id: "unique", class: "unique" @@ -87,14 +85,14 @@ describe("Hyperscript", () => { }); it("should create a div element from string", () => { - expect(v.trust('
    Hola mundo
    ')).toEqual([ + expect(trust('
    Hola mundo
    ')).toEqual([ { - name: "div", + tag: "div", props: { id: "unique", class: "unique" }, - children: [{ nodeValue: "Hola mundo", dom: expect.anything() }], + children: [expect.objectContaining({ nodeValue: "Hola mundo", dom: expect.anything() })], dom: expect.anything() } ]); @@ -104,7 +102,7 @@ describe("Hyperscript", () => { let date = new Date(); expect(v("div", null, [null, "Hello", , 1, date, { hello: "world" }, ["Hello"]])).toEqual({ - name: "div", + tag: "div", props: {}, children: [[null, "Hello", undefined, 1, date, { hello: "world" }, ["Hello"]]] }); diff --git a/test/keyed_test.js b/test/keyed_test.js index 4eb5540..074d98f 100644 --- a/test/keyed_test.js +++ b/test/keyed_test.js @@ -1,9 +1,8 @@ -import "../lib"; +import { mount, update } from "../lib"; import expect from "expect"; -import nodePlugin from "../plugins/node"; -v.usePlugin(nodePlugin); +require("../plugins/node"); describe("Keyed lists", () => { let set = [1, 2, 3, 4, 5]; @@ -47,9 +46,9 @@ describe("Keyed lists", () => {
); - let before = v.mount("body", component); + let before = mount("body", component); keys = [...test.set]; - let after = v.update(); + let after = update(component); let afterString = getString(test.set); @@ -72,15 +71,15 @@ describe("Keyed lists", () => { ); - let before = v.mount("body", component); + let before = mount("body", component); useStrings = false; - let after = v.update(); + let after = update(component); let afterString = getString(keys); useStrings = true; - let afterUpdate = v.update(); + let afterUpdate = update(component); expect(before).toEqual("
    12345
"); expect(after).toEqual(afterString); @@ -100,15 +99,15 @@ describe("Keyed lists", () => { ); - let before = v.mount("body", component); + let before = mount("body", component); keys = [6, 7, 8, 9, , 10]; - let after = v.update(); + let after = update(component); let afterString = getString(keys); keys = [1, 2, 3, 4, 5]; - let afterUpdate = v.update(); + let afterUpdate = update(component); let afterUpdateString = getString(keys); diff --git a/test/lifecycle_test.js b/test/lifecycle_test.js index 44c434e..ee3a2fa 100644 --- a/test/lifecycle_test.js +++ b/test/lifecycle_test.js @@ -1,9 +1,8 @@ -import "../lib"; +import "../plugins/node"; -import expect from "expect"; -import nodePlugin from "../plugins/node"; +import { mount, update } from "../lib"; -v.usePlugin(nodePlugin); +import expect from "expect"; describe("Lifecycle", () => { it("Mount and update", () => { @@ -19,10 +18,10 @@ describe("Lifecycle", () => { calls.push("component oncreate"); }, - onbeforeupdate() { + shouldupdate() { // before dom element is updated // if you return false the update step is skipped - calls.push("component onbeforeupdate"); + calls.push("component shouldupdate"); }, onupdate() { @@ -98,24 +97,24 @@ describe("Lifecycle", () => { let expectedLifeCycleCalls = [ "component oncreate", "oncreate", - "component onbeforeupdate", + "component shouldupdate", "component onupdate", "onremove", "onspanremove", - "component onbeforeupdate", + "component shouldupdate", "component onupdate", "oncreate", - "component onbeforeupdate", + "component shouldupdate", "component onupdate", "onupdate", - "component onbeforeupdate", + "component shouldupdate", "component onupdate", "onupdate", "onspanremove", - "component onbeforeupdate", + "component shouldupdate", "component onupdate", "onupdate", - "component onbeforeupdate", + "component shouldupdate", "component onupdate", "onremove", "onspanremove", @@ -123,19 +122,19 @@ describe("Lifecycle", () => { "onspanremove" ]; - result.push(v.mount("body", Lifecycle)); + result.push(mount("body", Lifecycle)); s = 0; - result.push(v.update()); + result.push(update(Lifecycle)); s = 1; - result.push(v.update()); + result.push(update(Lifecycle)); s = 2; - result.push(v.update()); + result.push(update(Lifecycle)); s = 1; - result.push(v.update()); + result.push(update(Lifecycle)); s = 3; - result.push(v.update()); + result.push(update(Lifecycle)); s = 0; - result.push(v.update()); + result.push(update(Lifecycle)); expect(result).toEqual(expectedDom); expect(calls).toEqual(expectedLifeCycleCalls); diff --git a/test/mount_n_update_test.js b/test/mount_n_update_test.js index 6a484ac..efd4fb2 100644 --- a/test/mount_n_update_test.js +++ b/test/mount_n_update_test.js @@ -1,9 +1,8 @@ -import "../lib"; +import { Valyrian, mount, trust, update } from "../lib"; import expect from "expect"; -import nodePlugin from "../plugins/node"; -v.usePlugin(nodePlugin); +require("../plugins/node"); describe("Mount and update", () => { it("Mount and update with POJO component", () => { @@ -17,9 +16,9 @@ describe("Mount and update", () => { let result = {}; - result.before = v.mount("body", Component); + result.before = mount("body", Component); Component.world = "John Doe"; - result.after = v.update(); + result.after = update(Component); expect(result).toEqual({ before: '
Hello World
', @@ -36,9 +35,9 @@ describe("Mount and update", () => { let result = {}; - result.before = v.mount("body", Component); + result.before = mount("body", Component); Component.world = "John Doe"; - result.after = v.update(); + result.after = update(Component); expect(result).toEqual({ before: '
Hello World
', @@ -58,9 +57,9 @@ describe("Mount and update", () => { let result = {}; - result.before = v.mount("body", Component); + result.before = mount("body", Component); state.world = "John Doe"; - result.after = v.update(); + result.after = update(Component); expect(result).toEqual({ before: '
Hello World
', @@ -68,6 +67,26 @@ describe("Mount and update", () => { }); }); + it("Mount and update with Vnode Component", () => { + let Component = ({ hello }, ...children) => ( +
+ Hello World + Hello {hello} + {...children} +
+ ); + + expect( + mount( + "body", + + Hello John + Hello Jane + + ) + ).toEqual('
Hello WorldHello worldHello JohnHello Jane
'); + }); + it("Handle multiple update calls", () => { let Component = { world: "World", @@ -78,10 +97,10 @@ describe("Mount and update", () => { }; let result = {}; - result.before = v.mount("body", Component); + result.before = mount("body", Component); Component.world = "John Doe"; - result.after = v.update(); - result.afteragain = v.update(); + result.after = update(Component); + result.afteragain = update(Component); expect(result).toEqual({ before: '
Hello World
', @@ -91,7 +110,7 @@ describe("Mount and update", () => { }); it("Antipattern: Mount and update with functional stateless component", () => { - let Component = (props) =>
Hello {props.world}
; + let Component = ({ props }) =>
Hello {props.world}
; let props = { world: "World", id: "example" @@ -99,9 +118,11 @@ describe("Mount and update", () => { let result = {}; - result.before = v.mount("body", Component, props); + let app = ; + + result.before = mount("body", app); props.world = "John Doe"; - result.after = v.update(props); + result.after = update(app); expect(result).toEqual({ before: '
Hello World
', @@ -115,9 +136,9 @@ describe("Mount and update", () => { let result = {}; - result.before = v.mount("body", Component); + result.before = mount("body", Component); text = false; - result.after = v.update(); + result.after = update(Component); expect(result).toEqual({ before: "Hello world", @@ -131,9 +152,9 @@ describe("Mount and update", () => { let result = {}; - result.before = v.mount("body", Component); + result.before = mount("body", Component); text = true; - result.after = v.update(); + result.after = update(Component); expect(result).toEqual({ before: "
Hello world
", @@ -147,9 +168,9 @@ describe("Mount and update", () => { let result = {}; - result.before = v.mount("body", Component); + result.before = mount("body", Component); disabled = false; - result.after = v.update(); + result.after = update(Component); expect(result).toEqual({ before: '
Hello world
', @@ -163,9 +184,9 @@ describe("Mount and update", () => { let result = {}; - result.before = v.mount("body", Component); + result.before = mount("body", Component); disabled = true; - result.after = v.update(); + result.after = update(Component); expect(result).toEqual({ before: "
Hello world
", @@ -177,77 +198,46 @@ describe("Mount and update", () => { let date = new Date(); let Component = () => v("div", null, [null, "Hello", , 1, date, { hello: "world" }, ["Hello"]]); - expect(v.mount("body", Component)).toEqual(`
Hello1${date}[object Object]Hello
`); + expect(mount("body", Component)).toEqual(`
Hello1${date}[object Object]Hello
`); }); it("Should handle svgs", () => { let svg = // eslint-disable-next-line max-len ''; - let Component = () => v.trust(svg); + let Component = () => trust(svg); // eslint-disable-next-line max-len - expect(v.mount("body", Component)).toEqual(svg); + expect(mount("body", Component)).toEqual(svg); }); it("should fail silently if try to update before mount", () => { - v.unMount(); - v.update(); + let Component = () =>
Hello world
; + update(Component); }); it("should handle text vnode as new node", () => { - let vnode = v.trust("Some text"); + let vnode = trust("Some text"); let component = () => vnode; - let result = v.mount("body", component); + let result = mount("body", component); expect(result).toEqual("Some text"); vnode.children = ["Other text"]; - let result2 = v.update(); + let result2 = update(component); expect(result2).toEqual("Some text"); }); - it("should handle the passing of data with the data property", () => { - let data = { foo: "bar" }; - let onupdate = (newNode, oldNode) => expect(newNode.props.data).toEqual(oldNode.props.data); - let component = () =>
; + it("should handle the passing of state with the state property", () => { + let state = { foo: "bar" }; + let component = () =>
expect(newNode.props.state).toEqual(oldNode.props.state)} />; - let result = v.mount("body", component); + let result = mount("body", component); expect(result).toEqual("
"); - let result2 = v.update(); + let result2 = update(component); expect(result2).toEqual("
"); }); - it("should create another v instance using the v.newInstance method", () => { - // We create a new instance - let v2 = v.newInstance(); - - let count = 0; - let component = () => `Hello world ${count}`; - - // Get the first render - let result1 = v.mount("body", component); - let result2 = v2.mount("body", component); - - // Bot updates must be equal - expect(result1).toEqual("Hello world 0"); - expect(result2).toEqual("Hello world 0"); - - // We increment the counter and unMount the first instance - count++; - v.unMount(); - - // Get the second render - let result3 = v.update(); - let result4 = v2.update(); - - // For the first instance should be '' because component has been unMounted; - expect(result3).toEqual(""); - - // For the second instance should be 'Hello world 1' because it is still mounted - expect(result4).toEqual("Hello world 1"); - }); - it("should allow to use fragments", () => { let component = () => ( <> @@ -256,7 +246,7 @@ describe("Mount and update", () => { ); - let result = v.mount("body", component); + let result = mount("body", component); expect(result).toEqual("HelloWorld"); }); }); @@ -303,10 +293,10 @@ describe.skip("performance test", () => { ); - let before = v.mount("body", component); + let before = mount("body", component); keys = [...test.set]; v.unMount(); - let after = v.mount("body", component); + let after = mount("body", component); let afterString = getString(test.set); @@ -315,7 +305,7 @@ describe.skip("performance test", () => { for (let i = 100000; i--; ) { v.unMount(); - v.mount("body", component); + mount("body", component); } }); }); diff --git a/test/node_test.js b/test/node_test.js index 8e93610..2a4999e 100644 --- a/test/node_test.js +++ b/test/node_test.js @@ -1,17 +1,16 @@ import "../lib"; +import { htmlToHyperscript, hyperscriptToHtml, icons, inline, sw } from "../plugins/node"; + import expect from "expect"; import fs from "fs"; -import nodePlugin from "../plugins/node"; import packageJson from "../package.json"; -v.usePlugin(nodePlugin); - describe("Node test", () => { it("Get hyperscript string from html", () => { let html = 'Hello world'; - let dom = v.htmlToHyperscript(html); + let dom = htmlToHyperscript(html); expect(dom).toEqual(`[ v("body", {}, [ @@ -22,7 +21,7 @@ describe("Node test", () => { html = 'Hello world'; - dom = v.htmlToHyperscript(html); + dom = htmlToHyperscript(html); expect(dom).toEqual(`[ v("html", {}, [ @@ -37,7 +36,7 @@ describe("Node test", () => { html = 'Hello world'; - dom = v.htmlToHyperscript(html); + dom = htmlToHyperscript(html); expect(dom).toEqual(`[ "", @@ -53,7 +52,7 @@ describe("Node test", () => { html = 'Hello world'; - dom = v.htmlToHyperscript(html); + dom = htmlToHyperscript(html); expect(dom).toEqual(`[ v("head", {}, [ @@ -63,7 +62,7 @@ describe("Node test", () => { html = '
Hello world
'; - dom = v.htmlToHyperscript(html); + dom = htmlToHyperscript(html); expect(dom).toEqual(`[ v("div", {}, [ @@ -74,7 +73,7 @@ describe("Node test", () => { html = 'Hello world'; - dom = v.htmlToHyperscript(html); + dom = htmlToHyperscript(html); expect(dom).toEqual(`[ v("link", {"rel":"shortcult icon","href":"/icons/favicon.ico"}, []), @@ -82,9 +81,15 @@ describe("Node test", () => { ]`); }); + it("Get html from hyperscript", () => { + let Component = () =>
Hello world
; + + expect(hyperscriptToHtml()).toEqual("
Hello world
"); + }); + it("Should create a service worker file", async () => { let file = ".tmp/sw.js"; - await v.sw(file, { + await sw(file, { name: "Test", version: packageJson.version, urls: ["/", "/hello"] @@ -141,7 +146,7 @@ describe("Node test", () => { } }; - await v.icons("./assets/icon.png", favicons); + await icons("./assets/icon.png", favicons); expect(fs.existsSync(".tmp/favicon.ico")).toBeTruthy(); expect(fs.existsSync(".tmp/links.js")).toBeTruthy(); expect(fs.existsSync(".tmp/manifest.json")).toBeTruthy(); @@ -154,25 +159,25 @@ span{display:block;} span.hello{display: inline-block} `; - await v.inline.css({ raw: css }); - let cleanCss = await v.inline.uncss([html]); + await inline.css({ raw: css }); + let cleanCss = await inline.uncss([html]); expect(cleanCss).toEqual("span{display:block}"); }); it("should inline js", async () => { - v.inline.extensions("ts"); - // await v.inline.ts("./lib/index.ts.old", { outputOptions: { minify: true } }); - await v.inline.ts("./lib/index.ts", { outputOptions: { compact: true } }); - await v.inline.js("./bench/index-old.js", { outputOptions: { compact: true } }); - console.log(v.inline.ts()[0].raw.length); - // console.log(v.inline.ts()[1].raw.length); - console.log(v.inline.js()[0].raw.length); - - // console.log(v.inline.ts()[1].raw); - // fs.writeFileSync("./dist/valyrian.lite.js", v.inline.ts()[1].raw); - - // expect(v.inline.ts()[0].raw.length).toBeLessThan(5115); + inline.extensions("ts"); + // await inline.ts("./lib/index.ts.old", { outputOptions: { minify: true } }); + await inline.ts("./lib/index.ts", { compact: true }); + await inline.js("./bench/index-old.js", { compact: true }); + console.log(inline.ts()[0].raw.length); + // console.log(inline.ts()[1].raw.length); + console.log(inline.js()[0].raw.length); + + // console.log(inline.ts()[1].raw); + // fs.writeFileSync("./dist/valyrian.lite.js", inline.ts()[1].raw); + + // expect(inline.ts()[0].raw.length).toBeLessThan(5115); let compiled = fs.readFileSync("./dist/valyrian.min.js", "utf8"); console.log(compiled.length); diff --git a/test/request_test.js b/test/request_test.js index dc0ba5e..0caac27 100644 --- a/test/request_test.js +++ b/test/request_test.js @@ -1,12 +1,9 @@ import "../lib"; +import "../plugins/node"; import expect from "expect"; import fastify from "fastify"; -import nodePlugin from "../plugins/node"; -import requestPlugin from "../plugins/request"; - -v.usePlugin(nodePlugin); -v.usePlugin(requestPlugin); +import request from "../plugins/request"; let posts = []; for (let i = 10; i--; ) { @@ -56,7 +53,7 @@ let createServer = async () => { describe("Request", () => { it("should get", async () => { let server = await createServer(); - let res = await v.request.get(`${server.baseUrl}/posts/1`); + let res = await request.get(`${server.baseUrl}/posts/1`); expect(res).toEqual({ userId: 1, id: 1, @@ -72,7 +69,7 @@ describe("Request", () => { it("should post", async () => { let server = await createServer(); - let res = await v.request.post( + let res = await request.post( `${server.baseUrl}/posts`, { title: "foo", @@ -96,7 +93,7 @@ describe("Request", () => { it("should put", async () => { let server = await createServer(); - let res = await v.request.put( + let res = await request.put( `${server.baseUrl}/posts/1`, { id: 1, @@ -122,7 +119,7 @@ describe("Request", () => { it("should patch", async () => { let server = await createServer(); - let res = await v.request.patch( + let res = await request.patch( `${server.baseUrl}/posts/1`, { body: "bar" @@ -144,14 +141,14 @@ describe("Request", () => { it("should delete", async () => { let server = await createServer(); - let res = await v.request.delete(`${server.baseUrl}/posts/1`); + let res = await request.delete(`${server.baseUrl}/posts/1`); expect(res).toEqual({}); await server.close(); }); it("should serialize data", async () => { let server = await createServer(); - let res = await v.request.get(`${server.baseUrl}/posts/`, { + let res = await request.get(`${server.baseUrl}/posts/`, { userId: 1 }); expect(res).toEqual(expect.any(Array)); @@ -161,7 +158,7 @@ describe("Request", () => { it("should resolve with full response", async () => { let server = await createServer(); - let res = await v.request.get(`${server.baseUrl}/posts/1`, null, { resolveWithFullResponse: true }); + let res = await request.get(`${server.baseUrl}/posts/1`, null, { resolveWithFullResponse: true }); expect(res).toEqual( expect.objectContaining({ body: expect.any(Object), @@ -176,8 +173,8 @@ describe("Request", () => { it("should create a scoped request", async () => { let server = await createServer(); - let request = v.request.new(`${server.baseUrl}`); - let res = await request.get("/posts", { + let request2 = request.new(`${server.baseUrl}`); + let res = await request2.get("/posts", { userId: 1 }); expect(res).toEqual(expect.any(Array)); @@ -187,21 +184,21 @@ describe("Request", () => { it("should create a scoped request with allowed methods", async () => { let server = await createServer(); - let request = v.request.new(`${server.baseUrl}`, { methods: ["get"] }); - let res = await request.get("/posts", { + let request2 = request.new(`${server.baseUrl}`, { methods: ["get"] }); + let res = await request2.get("/posts", { userId: 1 }); expect(res).toEqual(expect.any(Array)); expect(res.length).toEqual(10); - expect(request.post).toBeUndefined(); + expect(request2.post).toBeUndefined(); await server.close(); }); it("should create a child scoped request", async () => { let server = await createServer(); - let request = v.request.new(`${server.baseUrl}/`); - let requestChild = request.new("/posts"); + let request2 = request.new(`${server.baseUrl}/`); + let requestChild = request2.new("/posts"); let res = await requestChild.get("/", { userId: 1 }); @@ -212,8 +209,8 @@ describe("Request", () => { it("should create a child scoped request with allowed methods", async () => { let server = await createServer(); - let request = v.request.new(`${server.baseUrl}/`, { methods: ["get"] }); - let requestChild = request.new("/posts"); + let request2 = request.new(`${server.baseUrl}/`, { methods: ["get"] }); + let requestChild = request2.new("/posts"); let res = await requestChild.get("/", { userId: 1 }); @@ -226,9 +223,9 @@ describe("Request", () => { it("should work with server side rendering of local requests", async () => { let server = await createServer(); - v.request.options("urls.node", `${server.baseUrl}`); + request.options("urls.node", `${server.baseUrl}`); - let res = await v.request.get("/hello", null, { headers: { Accept: "text/html" } }); + let res = await request.get("/hello", null, { headers: { Accept: "text/html" } }); expect(res).toEqual("Hello world"); @@ -237,10 +234,10 @@ describe("Request", () => { it("should work with server side rendering of api requests", async () => { let server = await createServer(); - v.request.options("urls.node", `${server.baseUrl}`); - v.request.options("urls.api", "http://example.com/api"); + request.options("urls.node", `${server.baseUrl}`); + request.options("urls.api", "http://example.com/api"); - let res = await v.request.get("http://example.com/api/hello", null, { headers: { Accept: "text/html" } }); + let res = await request.get("http://example.com/api/hello", null, { headers: { Accept: "text/html" } }); expect(res).toEqual("Hello world"); @@ -249,13 +246,13 @@ describe("Request", () => { it("should work with server side rendering of local requests with scoped request", async () => { let server = await createServer(); - let request = v.request.new("/", { + let request2 = request.new("/", { urls: { node: `${server.baseUrl}` } }); - let res = await request.get("/hello", null, { headers: { Accept: "text/html" } }); + let res = await request2.get("/hello", null, { headers: { Accept: "text/html" } }); expect(res).toEqual("Hello world"); @@ -264,14 +261,14 @@ describe("Request", () => { it("should work with server side rendering of api requests with scoped request", async () => { let server = await createServer(); - let request = v.request.new("/", { + let request2 = request.new("/", { urls: { node: `${server.baseUrl}`, api: "http://example.com/api" } }); - let res = await request.get("http://example.com/api/hello", null, { headers: { Accept: "text/html" } }); + let res = await request2.get("http://example.com/api/hello", null, { headers: { Accept: "text/html" } }); expect(res).toEqual("Hello world"); @@ -280,14 +277,14 @@ describe("Request", () => { it("should work with server side rendering of local requests with child scoped request", async () => { let server = await createServer(); - let request = v.request.new("/", { + let request2 = request.new("/", { urls: { node: `${server.baseUrl}` }, methods: ["get"] }); - let childRequest = request.new("/hello"); + let childRequest = request2.new("/hello"); let res = await childRequest.get("/", null, { headers: { Accept: "text/html" } }); @@ -300,7 +297,7 @@ describe("Request", () => { it("should work with server side rendering of api requests with child scoped request", async () => { let server = await createServer(); - let request = v.request.new("/", { + let request2 = request.new("/", { urls: { node: `${server.baseUrl}`, api: "http://example.com/api" @@ -308,7 +305,7 @@ describe("Request", () => { methods: ["get"] }); - let childRequest = request.new("http://example.com/api/hello"); + let childRequest = request2.new("http://example.com/api/hello"); let res = await childRequest.get("/", null, { headers: { Accept: "text/html" } }); diff --git a/test/router_test.js b/test/router_test.js index c1cf805..37e3ced 100644 --- a/test/router_test.js +++ b/test/router_test.js @@ -1,17 +1,15 @@ import "../lib"; +import "../plugins/node"; +import Router from "../plugins/router"; import expect from "expect"; -import nodePlugin from "../plugins/node"; -import router from "../plugins/router"; - -v.usePlugin(nodePlugin); -v.usePlugin(router); +import { update } from "../lib"; // eslint-disable-next-line max-lines-per-function describe("Router", () => { it("Dev test", async () => { let Component = () =>
Hello world
; - let router = v.Router(); + let router = new Router(); router .get( "/", @@ -30,7 +28,7 @@ describe("Router", () => { ) .get("/hello/:world", [() => console.log("Hello 7"), () => Component], () => console.log("Hello 7")); - let subrouter = v.Router(); + let subrouter = new Router(); subrouter .get( @@ -54,9 +52,9 @@ describe("Router", () => { router.use("/ok", subrouter); router.use(() => () => "Not found"); - v.routes("body", router); - expect(await v.routes.go("/ok/not/found/url?hello=world")).toEqual("Not ok"); - expect(await v.routes.go("/not/found/url?hello=world")).toEqual("Not found"); + router.mount("body"); + expect(await router.go("/ok/not/found/url?hello=world")).toEqual("Not ok"); + expect(await router.go("/not/found/url?hello=world")).toEqual("Not found"); }); it("Mount and update with POJO component", async () => { @@ -69,15 +67,15 @@ describe("Router", () => { }; let result = {}; - let router = v.Router(); + let router = new Router(); router.get("/", () => Component); - v.routes("body", router); + router.mount("body"); - result.before = await v.routes.go("/"); + result.before = await router.go("/"); Component.world = "John Doe"; - result.after = await v.routes.go("/"); + result.after = await router.go("/"); Component.world = "World"; - result.final = v.update(); + result.final = update(Component); expect(result).toEqual({ before: '
Hello World
', @@ -95,15 +93,15 @@ describe("Router", () => { Component.id = "example"; let result = {}; - let router = v.Router(); + let router = new Router(); router.get("/", () => Component); - v.routes("body", router); + router.mount("body"); - result.before = await v.routes.go("/"); + result.before = await router.go("/"); Component.world = "John Doe"; - result.after = await v.routes.go("/"); + result.after = await router.go("/"); Component.world = "World"; - result.final = v.update(); + result.final = update(Component); expect(result).toEqual({ before: '
Hello World
', @@ -123,15 +121,15 @@ describe("Router", () => { }; let result = {}; - let router = v.Router(); + let router = new Router(); router.get("/", () => Component); - v.routes("body", router); + router.mount("body"); - result.before = await v.routes.go("/"); + result.before = await router.go("/"); state.world = "John Doe"; - result.after = await v.routes.go("/"); + result.after = await router.go("/"); state.world = "World"; - result.final = v.update(); + result.final = update(Component); expect(result).toEqual({ before: '
Hello World
', @@ -148,15 +146,15 @@ describe("Router", () => { }; let result = {}; - let router = v.Router(); - router.get("/", () => Component); - v.routes("body", router); + let router = new Router(); + router.get("/", () => ); + router.mount("body"); - result.before = await v.routes.go("/", props); + result.before = await router.go("/"); props.world = "John Doe"; - result.after = await v.routes.go("/", props); + result.after = await router.go("/"); props.world = "World"; - result.final = v.update(props); + result.final = await router.go("/"); expect(result).toEqual({ before: '
Hello World
', @@ -169,15 +167,15 @@ describe("Router", () => { let Hello = () => "Hello world"; let NotFound = () =>
Ups, no route was found.
; - let router = v.Router(); + let router = new Router(); router.get("/", () => Hello); router.use(() => NotFound); - v.routes("body", router); + router.mount("body"); let result = {}; - result.found = await v.routes.go("/"); - result.notFound = await v.routes.go("/not_found"); + result.found = await router.go("/"); + result.notFound = await router.go("/not_found"); expect(result).toEqual({ found: "Hello world", @@ -198,7 +196,7 @@ describe("Router", () => { ); }; - let router = v.Router(); + let router = new Router(); router.get( "/hello", () => Object.assign(Hello, Store), @@ -206,11 +204,11 @@ describe("Router", () => { ); router.get("/hello/:world/whats/:up", [({ params }) => Object.assign(Hello, params), () => Hello]); - v.routes("body", router); + router.mount("body"); let result = {}; - result.before = await v.routes.go("/hello"); - result.after = await v.routes.go("/hello/Mike/whats/new"); + result.before = await router.go("/hello"); + result.after = await router.go("/hello/Mike/whats/new"); expect(result).toEqual({ before: "
Hello world, what's up
", @@ -222,7 +220,7 @@ describe("Router", () => { let Hello = () =>
Hello World
; let middlewares = []; - let router = v.Router(); + let router = new Router(); router.get( "/", () => middlewares.push("Middleware 1"), @@ -240,9 +238,9 @@ describe("Router", () => { // This is the final response () => Hello ); - v.routes("body", router); + router.mount("body"); - let result = await v.routes.go("/"); + let result = await router.go("/"); expect(result).toEqual("
Hello World
"); expect(middlewares).toEqual([ @@ -266,7 +264,7 @@ describe("Router", () => { ); }; - let subrouter = v.Router(); + let subrouter = new Router(); subrouter .get("/from/:country", ({ params }) => { Component.world = params.world; @@ -279,13 +277,13 @@ describe("Router", () => { return Component; }); - let router = v.Router(); + let router = new Router(); router.use("/hello/:world", subrouter); - v.routes("body", router); + router.mount("body"); let result = {}; - result.before = await v.routes.go("/hello/Mike"); - result.after = await v.routes.go("/hello/John/from/Mexico"); + result.before = await router.go("/hello/Mike"); + result.after = await router.go("/hello/John/from/Mexico"); expect(result).toEqual({ before: "
Hello Mike, from USA
", @@ -302,11 +300,11 @@ describe("Router", () => { ); - let router = v.Router(); + let router = new Router(); router.get("/", () => Component); - v.routes("body", router); + router.mount("body"); - let result = await v.routes.go(ParentComponent, "/"); + let result = await router.go("/", ParentComponent); expect(result).toEqual("
Hello World
"); }); @@ -314,30 +312,30 @@ describe("Router", () => { it("Test show error when calling with a non url", async () => { let Component = () =>
Hello World
; - let router = v.Router(); + let router = new Router(); router.get("/", () => Component); - v.routes("body", router); + router.mount("body"); let err; try { - await v.routes.go(null); + await router.go(null); } catch (error) { err = error.message; } - expect(err).toEqual("v.router.url.required"); + expect(err).toEqual("router.url.required"); }); it("Test show error when no component is returned", async () => { - let router = v.Router(); + let router = new Router(); router.get("/", () => { // Component is not returned }); - v.routes("body", router); + router.mount("body"); let err; try { - await v.routes.go("/"); + await router.go("/"); } catch (error) { err = error.message; } @@ -347,14 +345,14 @@ describe("Router", () => { it("Test get routes", () => { let Component = () => "Hello world"; - let subrouter = v.Router(); + let subrouter = new Router(); subrouter.get("/from/:country", () => Component).get("/", () => Component); - let router = v.Router(); + let router = new Router(); router.use("/hello/:world", subrouter).get("/", () => Component); - v.routes("body", router); + router.mount("body"); - expect(v.routes.get()).toEqual(["/hello/:world/from/:country", "/hello/:world", "/"]); + expect(router.routes()).toEqual(["/hello/:world/from/:country", "/hello/:world", "/"]); }); }); diff --git a/test/signals_test.js b/test/signals_test.js index 4cb164f..cc62588 100644 --- a/test/signals_test.js +++ b/test/signals_test.js @@ -1,16 +1,15 @@ import "../lib"; +import "../plugins/node"; -import expect from "expect"; -import nodePlugin from "../plugins/node"; -import signalsPlugin from "../plugins/signals"; +import { mount, update } from "../lib"; -v.usePlugin(nodePlugin); -v.usePlugin(signalsPlugin); +import Signal from "../plugins/signals"; +import expect from "expect"; describe("Signals", () => { it("should create a signal", async () => { // Create signal - let counter = v.Signal(0); + let counter = Signal(0); // Read value counter(); @@ -34,7 +33,7 @@ describe("Signals", () => { let computed = counter((val) => "hello " + val); // Unlinked Pure computed - let unlinked = v.Signal(() => "hello " + counter.value); + let unlinked = Signal(() => "hello " + counter.value); let interval = setInterval(() => (counter.value += 1), 1000); expect(counter.hello).toEqual("hello 0"); @@ -62,8 +61,8 @@ describe("Signals", () => { }); it("should test effect cleanup", async () => { - let delay = v.Signal(1000); - let count = v.Signal(0); + let delay = Signal(1000); + let count = Signal(0); let effectInterval = delay((delay) => { let interval = setInterval(() => { count.value = count.value + 1; @@ -87,7 +86,7 @@ describe("Signals", () => { }); it("should test deep state effect cleanup", async () => { - let state = v.Signal({ + let state = Signal({ count: 0, delay: 1000 }); @@ -115,25 +114,26 @@ describe("Signals", () => { describe("Hooks like pattern", () => { it("should create a simple counter", async () => { let Counter = (ms) => { - let count = v.Signal(0); + let count = Signal(0); let interval = setInterval(() => { count.value = count.value + 1; }, ms); return () =>
clearInterval(interval)}>{count.value}
; }; - let result = v.mount("div", Counter(1000)); + let Component = Counter(1000); + + let result = mount("div", Component); expect(result).toEqual("
0
"); await new Promise((resolve) => setTimeout(() => resolve(), 2050)); - result = v.update(); + result = update(Component); expect(result).toEqual("
2
"); - v.unMount(); }); it("should create a counter with delay change", async () => { let Counter = (ms) => { - let delay = v.Signal(ms); - let count = v.Signal(0); + let delay = Signal(ms); + let count = Signal(0); let interval = delay((delay) => { let interval = setInterval(() => { count.value = count.value + 1; @@ -143,17 +143,18 @@ describe("Hooks like pattern", () => { return () =>
{count.value}
; }; - let result = v.mount("div", Counter(1000)); + let Component = Counter(1000); + + let result = mount("div", Component); expect(result).toEqual("
0
"); await new Promise((resolve) => setTimeout(() => resolve(), 2050)); - result = v.update(); + result = update(Component); expect(result).toEqual("
2
"); - v.unMount(); }); it("should create a counter with deep state", async () => { let Counter = (ms) => { - let state = v.Signal({ + let state = Signal({ count: 0, delay: ms }); @@ -166,11 +167,12 @@ describe("Hooks like pattern", () => { return () =>
{state.value.count}
; }; - let result = v.mount("div", Counter(1000)); + let Component = Counter(1000); + + let result = mount("div", Component); expect(result).toEqual("
0
"); await new Promise((resolve) => setTimeout(() => resolve(), 2050)); - result = v.update(); + result = update(Component); expect(result).toEqual("
2
"); - v.unMount(); }); }); diff --git a/test/store_test.js b/test/store_test.js index 3f0036c..e32214b 100644 --- a/test/store_test.js +++ b/test/store_test.js @@ -1,10 +1,8 @@ import "../lib"; -import StorePlugin from "../plugins/store"; +import Store from "../plugins/store"; import expect from "expect"; -v.usePlugin(StorePlugin); - function getNewStore() { let mainModule = { state: { b: [1], a: 0, c: { a: 1 } }, @@ -45,18 +43,18 @@ function getNewStore() { } }; - return new v.Store(mainModule); + return new Store(mainModule); } // eslint-disable-next-line max-lines-per-function describe("Store slim", () => { it("Create empty state if state is not passed", () => { - let store = new v.Store(); + let store = new Store(); expect(store.state).toBeDefined(); }); it("Use deepFrozen to froze the state", () => { - let store = new v.Store({ + let store = new Store({ state: { a: { b: { @@ -149,8 +147,8 @@ describe("Store slim", () => { } }; - const store1 = new v.Store(myModule); - const store2 = new v.Store(myModule); + const store1 = new Store(myModule); + const store2 = new Store(myModule); store1.commit("increment", 5); store2.commit("increment", 3); diff --git a/yarn.lock b/yarn.lock index a2d1b60..fda2094 100644 --- a/yarn.lock +++ b/yarn.lock @@ -894,6 +894,11 @@ resolved "https://registry.yarnpkg.com/@types/minimist/-/minimist-1.2.2.tgz#ee771e2ba4b3dc5b372935d549fd9617bf345b8c" integrity sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ== +"@types/mocha@^9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-9.0.0.tgz#3205bcd15ada9bc681ac20bef64e9e6df88fd297" + integrity sha512-scN0hAWyLVAvLR9AyW7HoFF5sJZglyBsbPuHO4fv7JRvfmPBMfp1ozWqOf/e4wwPNxezBZXRfWzMb6iFLgEVRA== + "@types/ms@*": version "0.7.31" resolved "https://registry.yarnpkg.com/@types/ms/-/ms-0.7.31.tgz#31b7ca6407128a3d2bbc27fe2d21b345397f6197" From 58937038b4f3a55dd64f3907a71fe255a26ecfbf Mon Sep 17 00:00:00 2001 From: Masquerade Circus Date: Thu, 3 Feb 2022 16:56:57 -0600 Subject: [PATCH 02/19] refactor: refactor to functional style BREAKING CHANGE: Global variable 'v' will only have the 'fragment' method and the 'current' object. All other methods are functional style methods. --- .vscode/settings.json | 12 +- bench/.buffalo-test.json | 464 +++++++++++++++++++++++++++++++++++++++ lib/index.ts | 18 +- plugins/hooks.js | 148 +++++++------ plugins/router.js | 2 +- test/hooks_test.js | 87 ++++---- 6 files changed, 599 insertions(+), 132 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 6131d6a..53d62a1 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,5 +1,11 @@ { - "deepcode.uploadApproved": true, - "cSpell.words": ["eqeqeq", "onbeforeupdate", "oncleanup", "oncreate", "onremove"], - "prettier.trailingComma": "none" + "cSpell.words": [ + "eqeqeq", + "onbeforeupdate", + "oncleanup", + "oncreate", + "onremove" + ], + "prettier.trailingComma": "none", + "prettier.printWidth": 160 } diff --git a/bench/.buffalo-test.json b/bench/.buffalo-test.json index 5d479ff..9bf29f7 100644 --- a/bench/.buffalo-test.json +++ b/bench/.buffalo-test.json @@ -1,4 +1,468 @@ [ + { + "tag": "5facca6aa5e38cb11b7a4ecb997aac6a3c948e3f", + "timestamp": "2022-02-03T22:46:40.072Z", + "suites": { + "Matching keyed list": { + "Removed at the end": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "Matching keyed list -> stress": { + "Removed at the end": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "hyperscript": { + "Valyrian 5.0.8": { + "hz": 16100452.93072125, + "meanTime": 0.00006211005394089887, + "medianTime": 0.000054001808166503906, + "standardDeviation": 0.0003290395264510733, + "maxTime": 0.36281299591064453, + "minTime": 0.00004699826240539551 + }, + "Valyrian next": { + "hz": 16434040.374422874, + "meanTime": 0.00006084930894756413, + "medianTime": 0.00005799531936645508, + "standardDeviation": 0.0007403887907110484, + "maxTime": 1.4644039869308472, + "minTime": 0.00005099177360534668 + } + }, + "Set.has vs [].indexOf": { + "Set.has": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "[].indexOf": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "Object.keys for loop vs Object.keys for of vs for in": { + "Object.keys for loop": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "Object.keys for of": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "for in": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "typeof function vs startsWith vs charAt vs string[0]": { + "typeof function": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "startsWith": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "charAt": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "string[0]": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "Array.isArray vs typeof object & Array.isArray": { + "Array.isArray": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "typeof object & Array.isArray": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "string comparison vs instance comparison vs property comparison": { + "string comparison": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "instance comparison": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "property comparison": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "property string comparison": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "typeof comparison": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "Object with property equals true vs set vs map vs string array": { + "Object with property equals true": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "key in object": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "set": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "map": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "string array": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "For loop if/continue vs if/else": { + "for loop if/continue": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "for loop if/else": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "map array of strings vs reduce with object keys equals index": { + "map array of strings": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "reduce with object keys equals index": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "array by for": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "object by for": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "object map by for": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "Symbol access vs direct access": { + "Direct access access": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "Symbol access access": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "Mount and update: Mount multiple types": { + "Valyrian 5.0.8": { + "hz": 156.0278006338212, + "meanTime": 6.409114247190357, + "medianTime": 4.104526996612549, + "standardDeviation": 4.2786484870340455, + "maxTime": 53.350247994065285, + "minTime": 3.5081720054149628 + }, + "Valyrian next": { + "hz": 147.11522570193347, + "meanTime": 6.797392963431776, + "medianTime": 4.745192989706993, + "standardDeviation": 3.879799607541915, + "maxTime": 53.691965997219086, + "minTime": 3.907906010746956 + } + }, + "Mount and update: Mount single text": { + "Valyrian 5.0.8": { + "hz": 629735.5089158076, + "meanTime": 0.0015879682594390511, + "medianTime": 0.0008700042963027954, + "standardDeviation": 0.05346277392066757, + "maxTime": 34.57287201285362, + "minTime": 0.000760003924369812 + }, + "Valyrian next": { + "hz": 771166.8946694123, + "meanTime": 0.001296736162965975, + "medianTime": 0.0007610023021697998, + "standardDeviation": 0.03629392280893103, + "maxTime": 23.255456000566483, + "minTime": 0.0006549954414367676 + } + }, + "Mount and update: Mount single text in div": { + "Valyrian 5.0.8": { + "hz": 323322.5893980026, + "meanTime": 0.0030928862776396465, + "medianTime": 0.001547008752822876, + "standardDeviation": 0.07432984344850142, + "maxTime": 19.169443994760513, + "minTime": 0.0013629943132400513 + }, + "Valyrian next": { + "hz": 356537.84409168496, + "meanTime": 0.002804751351283895, + "medianTime": 0.0011690109968185425, + "standardDeviation": 0.0770758689708197, + "maxTime": 26.725001007318497, + "minTime": 0.0010079890489578247 + } + }, + "Mount and update: Update multiple types": { + "Valyrian 5.0.8": { + "hz": 112.61485916556728, + "meanTime": 8.879822852948667, + "medianTime": 7.630842998623848, + "standardDeviation": 2.391480595191235, + "maxTime": 29.19546900689602, + "minTime": 6.9201240092515945 + }, + "Valyrian next": { + "hz": 79.3053222825804, + "meanTime": 12.60949418296043, + "medianTime": 11.439594998955727, + "standardDeviation": 2.450007423832887, + "maxTime": 31.415478006005287, + "minTime": 10.35980600118637 + } + }, + "Mount and update: Update single text": { + "Valyrian 5.0.8": { + "hz": 512194.9539475156, + "meanTime": 0.0019523815927762333, + "medianTime": 0.0018129944801330566, + "standardDeviation": 0.005251666594137278, + "maxTime": 2.5011999905109406, + "minTime": 0.0016760081052780151 + }, + "Valyrian next": { + "hz": 580450.0814674293, + "meanTime": 0.0017228010330740439, + "medianTime": 0.0014830082654953003, + "standardDeviation": 0.009247424948510186, + "maxTime": 1.316769003868103, + "minTime": 0.0013870000839233398 + } + }, + "Mount and update: Render list": { + "vOld": { + "hz": 21950.17725957362, + "meanTime": 0.04555771865413287, + "medianTime": 0.03048001229763031, + "standardDeviation": 0.26360842201547274, + "maxTime": 53.0407840013504, + "minTime": 0.027091994881629944 + }, + "VNext": { + "hz": 22480.242850336203, + "meanTime": 0.04448350521200195, + "medianTime": 0.028238996863365173, + "standardDeviation": 0.22902272887302527, + "maxTime": 18.99347099661827, + "minTime": 0.02472400665283203 + } + }, + "Mount and update: Render keyed list": { + "vOld": { + "hz": 4456.298218469571, + "meanTime": 0.22440149895161873, + "medianTime": 0.10216599702835083, + "standardDeviation": 0.872715812627799, + "maxTime": 23.933639004826546, + "minTime": 0.08914101123809814 + }, + "VNext": { + "hz": 4544.2061568088975, + "meanTime": 0.22006043860964164, + "medianTime": 0.10275200009346008, + "standardDeviation": 0.8256088387603412, + "maxTime": 26.58849000930786, + "minTime": 0.0857279896736145 + } + }, + "Mount and update: Render keyed list -> stress": { + "vOld": { + "hz": 2439.913922907917, + "meanTime": 0.4098505240743038, + "medianTime": 0.19490599632263184, + "standardDeviation": 1.2082613219808935, + "maxTime": 38.02886499464512, + "minTime": 0.1708189994096756 + }, + "VNext": { + "hz": 2368.508472714364, + "meanTime": 0.4222066382789746, + "medianTime": 0.1962120085954666, + "standardDeviation": 1.2012990034146538, + "maxTime": 49.84053599834442, + "minTime": 0.16314101219177246 + } + }, + "Mount and update: Render keyed list -> swap keys on large set": { + "vOld": { + "hz": 417.95547443978296, + "meanTime": 2.392599358437343, + "medianTime": 1.0978680104017258, + "standardDeviation": 3.1758308351124, + "maxTime": 47.34352000057697, + "minTime": 0.9298380017280579 + }, + "VNext": { + "hz": 415.153888162244, + "meanTime": 2.408745355672053, + "medianTime": 1.1263680011034012, + "standardDeviation": 3.309912031074918, + "maxTime": 74.48139899969101, + "minTime": 0.9392520040273666 + } + } + } + }, { "tag": "ff7d5d73af49d9be6dab1d8cc4e40441c255cbba", "timestamp": "2022-02-03T12:53:38.877Z", diff --git a/lib/index.ts b/lib/index.ts index a515d18..28616d4 100644 --- a/lib/index.ts +++ b/lib/index.ts @@ -191,8 +191,6 @@ const reservedProps: ReservedProps = { "v-html": true }; -const plugins = new Set(); - export const isNodeJs = Boolean(typeof process !== "undefined" && process.versions && process.versions.node); function createDomElement(tag: string, isSVG: boolean = false) { @@ -290,9 +288,6 @@ export function mount(container: DomElement | string, component: ValyrianCompone } } component[ValyrianSymbol].eventListener = eventListener; - for (let plugin of plugins) { - plugin(v, component); - } } component[ValyrianSymbol].component = vnodeComponent; @@ -345,6 +340,9 @@ export function unmount(component?: ValyrianComponent | Vnode) { patch(valyrianApp.mainVnode, oldVnode, valyrianApp); oldVnode = null; valyrianApp.isMounted = false; + if (isNodeJs) { + return valyrianApp.mainVnode.dom.innerHTML; + } } } @@ -619,11 +617,11 @@ function patchNormalTree( // eslint-disable-next-line complexity function patch(newVnode: VnodeWithDom, oldVnode: VnodeWithDom = emptyVnode as VnodeWithDom, valyrianApp?: MountedValyrianApp) { - flatTree(newVnode); - v.current.vnode = newVnode; v.current.oldVnode = oldVnode; + flatTree(newVnode); + let newTree = newVnode.children; let oldTree = oldVnode.children; let oldTreeLength = oldTree.length; @@ -658,9 +656,9 @@ export function directive(name: string, directive: Directive) { reservedProps[fullName] = true; } -export function plugin(plugin: Plugin) { - if (!plugins.has(plugin)) { - plugins.add(plugin); +export function cleanup(callback: Function) { + if (v.current.app?.cleanup.indexOf(callback) === -1) { + v.current.app?.cleanup.push(callback); } } diff --git a/plugins/hooks.js b/plugins/hooks.js index ba68c2e..ccc0a3d 100644 --- a/plugins/hooks.js +++ b/plugins/hooks.js @@ -1,91 +1,99 @@ -let plugin = function (v) { - let UND; +const UND = undefined; - function createHook ({ name, init, update, response }) { +function createHook({ init, update, response, cleanup }) { + return (...args) => { + let { component, vnode, oldVnode, app } = v.current; - if (!v[name]) { - v[name] = (...args) => { - let { component, parentVnode, oldParentVnode } = v.current; + // Init the components array for the current vnode + if (vnode.components === UND) { + vnode.components = []; + } - if (parentVnode.components === UND) { - parentVnode.components = []; - } + // Add the component to the components array if it's not already there + if (vnode.components.indexOf(component) === -1) { + vnode.components.push(component); + } - if (parentVnode.components.indexOf(component) === -1) { - parentVnode.components.push(component); - } + // Init the component hooks array + if (component.hooks === UND) { + component.hooks = []; + } - let hook; - let oldComponentNode = oldParentVnode && oldParentVnode.components && oldParentVnode.components[parentVnode.components.length - 1]; - let oldMethod = oldComponentNode && ("view" in oldComponentNode.component ? oldComponentNode.component.view : oldComponentNode.component); - let currentMethod = "view" in component.component ? component.component.view : component.component; + let componentIndex = vnode.components.length - 1; + let oldComponent = ((oldVnode || {}).components || [])[componentIndex]; + let hook; + let hookIndex = component.hooks.length - 1; - if (component.hooks === UND) { - component.hooks = []; - } - let hookIndex = component.hooks.length; + if (oldComponent === component) { + component.hooks = oldComponent.hooks; + hook = oldComponent.hooks[hookIndex]; + if (update) { + update(hook, ...args); + } + } else { + hook = init(...args); + component.hooks.push(hook); + } - if (oldMethod === currentMethod && "hooks" in oldComponentNode && oldComponentNode.hooks[hookIndex] !== UND) { - component.hooks = oldComponentNode.hooks; - hook = oldComponentNode.hooks[hookIndex]; - if (update) { - update(hook, ...args); - } - } else { - hook = init(...args); - component.hooks.push(hook); - } + if (cleanup) { + app.cleanup.push(() => cleanup(hook)); + } - if (response) { - return response(hook); - } - }; + if (response) { + return response(hook); + } else { + return hook; } }; +} - createHook({ - name: "state", - init: (value) => { - let state = value; - let setState = (value) => (state = value); +const useState = createHook({ + init: (value) => { + let state = value; + let setState = (value) => (state = value); - let stateObj = Object.create(null); - stateObj.toJSON = stateObj.toString = stateObj.valueOf = () => (typeof state === "function" ? state() : state); + let stateObj = Object.create(null); + stateObj.toJSON = stateObj.toString = stateObj.valueOf = () => (typeof state === "function" ? state() : state); - return [stateObj, setState]; - }, - response: (hook) => hook - }); + return [stateObj, setState]; + } +}); + +// Effect hook +function callEffectHook(hook, changes) { + let { prev } = hook; - // Effect hook - function callHook(hook, changes) { - let { prev } = hook; - if (!changes) { - hook.onCleanup = hook.effect(); - } else if (changes.length > 0) { - for (let i = 0, l = changes.length; i < l; i++) { - if (changes[i] !== prev[i]) { - hook.prev = changes; - hook.onCleanup = hook.effect(); - break; - } + if (!changes) { + hook.onCleanup = hook.effect(); + } else if (changes.length > 0) { + for (let i = 0, l = changes.length; i < l; i++) { + if (changes[i] !== prev[i]) { + hook.prev = changes; + hook.onCleanup = hook.effect(); + break; } } - + } +} +const useEffect = createHook({ + init: (effect, changes) => { + let hook = { effect, prev: changes }; + callEffectHook(hook); + return hook; + }, + update: (hook, effect, changes) => callEffectHook(hook, changes), + cleanup: (hook) => { if (typeof hook.onCleanup === "function") { - v.onCleanup(hook.onCleanup); + hook.onCleanup(); } } - createHook({ - name: "effect", - init: (effect, changes) => { - let hook = { effect, prev: changes }; - callHook(hook); - return hook; - }, - update: (hook, effect, changes) => callHook(hook, changes) - }); +}); + +let exports = { + createHook, + useState, + useEffect }; -plugin.default = plugin; -module.exports = plugin; +exports.default = exports; +module.exports = exports; diff --git a/plugins/router.js b/plugins/router.js index b656fbd..dc6c8be 100644 --- a/plugins/router.js +++ b/plugins/router.js @@ -1,4 +1,4 @@ -import { isComponent, isNodeJs, isVnode, isVnodeComponent, mount, updateProperty, v } from "../lib"; +import { isComponent, isNodeJs, isVnodeComponent, mount, updateProperty, v } from "../lib"; function flat(array) { return Array.isArray(array) ? array.flat(Infinity) : [array]; diff --git a/test/hooks_test.js b/test/hooks_test.js index 9020159..94bc2db 100644 --- a/test/hooks_test.js +++ b/test/hooks_test.js @@ -1,45 +1,40 @@ import "../lib"; import "../plugins/node"; -import expect from "expect"; -import hooksPlugin from "../plugins/hooks"; +import { cleanup, mount, unmount, update } from "../lib"; +import { useEffect, useState } from "../plugins/hooks"; -v.usePlugin(hooksPlugin); +import expect from "expect"; describe("Hooks", () => { describe("State hook", () => { it("should handle a component state", async () => { - v.unMount(); - let Counter = () => { - let [count, setCount] = v.useState(0); + let [count, setCount] = useState(0); let interval = setInterval(() => setCount(count + 1), 1000); - v.onCleanup(() => clearInterval(interval)); + cleanup(() => clearInterval(interval)); return
{count}
; }; - let result = v.mount("div", Counter); + let result = mount("div", Counter); expect(result).toEqual("
0
"); await new Promise((resolve) => setTimeout(() => resolve(), 2050)); - result = v.update(); + result = update(Counter); expect(result).toEqual("
2
"); - result = v.unMount(); }); it("should handle subcomponents state and cleanup", async () => { - v.unMount(); - let Ok = () => { - let [ok, setOk] = v.useState("ok"); + let [ok, setOk] = useState("ok"); let interval = setInterval(() => setOk("not ok"), 1000); - v.onCleanup(() => clearInterval(interval)); + cleanup(() => clearInterval(interval)); return
{ok}
; }; let Counter = () => { - let [count, setCount] = v.useState(0); + let [count, setCount] = useState(0); let interval = setInterval(() => setCount(count + 1), 1000); - v.onCleanup(() => clearInterval(interval)); + cleanup(() => clearInterval(interval)); return (
{count} @@ -47,30 +42,26 @@ describe("Hooks", () => { ); }; - let result = v.mount("div", Counter); + let result = mount("div", Counter); expect(result).toEqual("
0
ok
"); await new Promise((resolve) => setTimeout(() => resolve(), 2050)); - result = v.update(); + result = update(Counter); expect(result).toEqual("
2
not ok
"); - result = v.unMount(); }); it("array getter-setter based state", async () => { - v.unMount(); - let Counter = () => { - let [count, setCount] = v.useState(0); + let [count, setCount] = useState(0); let interval = setInterval(() => setCount(count + 1), 1000); - v.onCleanup(() => clearInterval(interval)); + cleanup(() => clearInterval(interval)); return
{count}
; }; - let result = v.mount("div", Counter); + let result = mount("div", Counter); expect(result).toEqual("
0
"); await new Promise((resolve) => setTimeout(() => resolve(), 2050)); - result = v.update(); + result = update(Counter); expect(result).toEqual("
2
"); - result = v.unMount(); }); }); @@ -78,106 +69,106 @@ describe("Hooks", () => { it("should call the effect at first render", () => { let count = 0; let Component = function () { - v.useEffect(() => count++); + useEffect(() => count++); return
{count}
; }; - let response = v.mount("body", Component); + let response = mount("body", Component); expect(response).toEqual("
1
"); }); it("should call the effect at every update", () => { let count = 0; let Component = function () { - v.useEffect(() => count++); + useEffect(() => count++); return
{count}
; }; - let response = v.mount("body", Component); + let response = mount("body", Component); expect(response).toEqual("
1
"); - response = v.update(); + response = update(Component); expect(response).toEqual("
2
"); }); it("should handle cleanup", () => { let count = 0; let Component = function () { - v.useEffect(() => { + useEffect(() => { count++; return () => (count -= 2); }); return
{count}
; }; - let response = v.mount("body", Component); + let response = mount("body", Component); expect(response).toEqual("
1
"); - response = v.update(); + response = update(Component); expect(response).toEqual("
0
"); }); it("should not call the effect if the change array is passed and there are no changes", () => { let count = 0; let Component = function () { - v.useEffect(() => count++, [0]); + useEffect(() => count++, [0]); return
{count}
; }; - let response = v.mount("body", Component); + let response = mount("body", Component); expect(response).toEqual("
1
"); - response = v.update(); + response = update(Component); expect(response).toEqual("
1
"); }); it("should call the effect if the change array is passed and there are changes", () => { let count = 0; let Component = function () { - v.useEffect(() => count++, [count]); + useEffect(() => count++, [count]); return
{count}
; }; - let response = v.mount("body", Component); + let response = mount("body", Component); expect(response).toEqual("
1
"); - response = v.update(); + response = update(Component); expect(response).toEqual("
2
"); }); it("should call cleanup even if the changes array is passed and there are changes", () => { let count = 0; let Component = function () { - v.useEffect(() => { + useEffect(() => { count++; return () => count++; }, [count]); return
{count}
; }; - let response = v.mount("body", Component); + let response = mount("body", Component); expect(response).toEqual("
1
"); - response = v.update(); + response = update(Component); expect(response).toEqual("
3
"); - response = v.update(); + response = update(Component); expect(response).toEqual("
5
"); }); it("should handle cleanup on unMount", () => { let count = 0; let Component = function () { - v.useEffect(() => { + useEffect(() => { count++; return () => (count -= 2); }); return
{count}
; }; - let response = v.mount("body", Component); + let response = mount("body", Component); expect(response).toEqual("
1
"); expect(count).toEqual(1); - response = v.update(); + response = update(Component); expect(response).toEqual("
0
"); expect(count).toEqual(0); - response = v.unMount(); + response = unmount(Component); expect(response).toEqual(""); expect(count).toEqual(-2); }); From 7313c056499f7888695a0dd3eab842c06e8c4d63 Mon Sep 17 00:00:00 2001 From: Masquerade Circus Date: Sun, 6 Feb 2022 13:45:08 -0600 Subject: [PATCH 03/19] refactor: Multiple updates --- bench/.buffalo-test.json | 464 ++++++++++++++ bench/hyperscript_bench.js | 13 +- bench/mount_n_update_bench.js | 2 +- dist/@types/lib/index.d.ts | 7 - dist/@types/lib/index_.d.ts | 106 ---- dist/@types/plugins/hooks.d.ts | 5 - dist/@types/plugins/node.d.ts | 53 -- dist/@types/plugins/request.d.ts | 5 - dist/@types/plugins/router.d.ts | 5 - dist/@types/plugins/signals.d.ts | 5 - dist/@types/plugins/store.d.ts | 5 - dist/@types/plugins/sw.d.ts | 5 - dist/@types/plugins/v-model.d.ts | 5 - dist/@types/register.d.ts | 1 - dist/index.cjs | 550 +++++++++++++++++ dist/index.js | 525 ++++++++++++++++ dist/index.min.js | 1 + dist/index.min.js.map | 1 + dist/valyrian.min.js | 13 - dist/valyrian.min.js.map | 1 - lib/index.ts | 411 ++++++++----- lib/index_.ts | 564 ------------------ package.json | 2 +- plugins/hooks.js | 85 ++- plugins/node.js | 313 +++++----- plugins/request.js | 3 +- plugins/router.js | 46 +- plugins/signals.js | 1 + plugins/sw.js | 4 +- plugins/v-model.js | 91 --- register.js | 9 +- source.js | 222 ++++++- test/directives_test.js | 3 +- test/hooks_test.js | 2 +- test/keyed_test.js | 2 +- test/lifecycle_test.js | 2 +- test/mount_n_update_test.js | 2 +- test/node_test.js | 23 +- test/request_test.js | 2 +- test/router_test.js | 4 +- test/signals_test.js | 4 +- test/store_test.js | 2 +- tsconfig.json | 2 +- types/lib/index.d.ts | 103 ++++ types/plugins/hooks.d.ts | 1 + types/plugins/node.d.ts | 1 + .../@types => types}/plugins/node.sw.tpl.d.ts | 0 types/plugins/request.d.ts | 5 + types/plugins/router.d.ts | 19 + types/plugins/signals.d.ts | 5 + types/plugins/store.d.ts | 22 + types/plugins/sw.d.ts | 14 + .../plugins/utils/tree-adapter.d.ts | 0 53 files changed, 2388 insertions(+), 1353 deletions(-) delete mode 100644 dist/@types/lib/index.d.ts delete mode 100644 dist/@types/lib/index_.d.ts delete mode 100644 dist/@types/plugins/hooks.d.ts delete mode 100644 dist/@types/plugins/node.d.ts delete mode 100644 dist/@types/plugins/request.d.ts delete mode 100644 dist/@types/plugins/router.d.ts delete mode 100644 dist/@types/plugins/signals.d.ts delete mode 100644 dist/@types/plugins/store.d.ts delete mode 100644 dist/@types/plugins/sw.d.ts delete mode 100644 dist/@types/plugins/v-model.d.ts delete mode 100644 dist/@types/register.d.ts create mode 100644 dist/index.cjs create mode 100644 dist/index.js create mode 100644 dist/index.min.js create mode 100644 dist/index.min.js.map delete mode 100644 dist/valyrian.min.js delete mode 100644 dist/valyrian.min.js.map delete mode 100644 lib/index_.ts delete mode 100644 plugins/v-model.js create mode 100644 types/lib/index.d.ts create mode 100644 types/plugins/hooks.d.ts create mode 100644 types/plugins/node.d.ts rename {dist/@types => types}/plugins/node.sw.tpl.d.ts (100%) create mode 100644 types/plugins/request.d.ts create mode 100644 types/plugins/router.d.ts create mode 100644 types/plugins/signals.d.ts create mode 100644 types/plugins/store.d.ts create mode 100644 types/plugins/sw.d.ts rename {dist/@types => types}/plugins/utils/tree-adapter.d.ts (100%) diff --git a/bench/.buffalo-test.json b/bench/.buffalo-test.json index 9bf29f7..e2d3e7a 100644 --- a/bench/.buffalo-test.json +++ b/bench/.buffalo-test.json @@ -1,4 +1,468 @@ [ + { + "tag": "58937038b4f3a55dd64f3907a71fe255a26ecfbf", + "timestamp": "2022-02-06T19:33:58.396Z", + "suites": { + "Matching keyed list": { + "Removed at the end": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "Matching keyed list -> stress": { + "Removed at the end": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "hyperscript": { + "Valyrian 5.0.8": { + "hz": 17250671.37325977, + "meanTime": 0.00005796875833772463, + "medianTime": 0.00004997849464416504, + "standardDeviation": 0.00046038119909960594, + "maxTime": 0.6135759949684143, + "minTime": 0.000044971704483032227 + }, + "Valyrian next": { + "hz": 16592575.824529294, + "meanTime": 0.00006026791804812309, + "medianTime": 0.000056999968364834785, + "standardDeviation": 0.00028681042792214214, + "maxTime": 0.42846699990332127, + "minTime": 0.00005000014789402485 + } + }, + "Set.has vs [].indexOf": { + "Set.has": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "[].indexOf": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "Object.keys for loop vs Object.keys for of vs for in": { + "Object.keys for loop": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "Object.keys for of": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "for in": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "typeof function vs startsWith vs charAt vs string[0]": { + "typeof function": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "startsWith": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "charAt": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "string[0]": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "Array.isArray vs typeof object & Array.isArray": { + "Array.isArray": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "typeof object & Array.isArray": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "string comparison vs instance comparison vs property comparison": { + "string comparison": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "instance comparison": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "property comparison": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "property string comparison": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "typeof comparison": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "Object with property equals true vs set vs map vs string array": { + "Object with property equals true": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "key in object": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "set": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "map": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "string array": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "For loop if/continue vs if/else": { + "for loop if/continue": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "for loop if/else": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "map array of strings vs reduce with object keys equals index": { + "map array of strings": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "reduce with object keys equals index": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "array by for": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "object by for": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "object map by for": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "Symbol access vs direct access": { + "Direct access access": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "Symbol access access": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "Mount and update: Mount multiple types": { + "Valyrian 5.0.8": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "Valyrian next": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "Mount and update: Mount single text": { + "Valyrian 5.0.8": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "Valyrian next": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "Mount and update: Mount single text in div": { + "Valyrian 5.0.8": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "Valyrian next": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "Mount and update: Update multiple types": { + "Valyrian 5.0.8": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "Valyrian next": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "Mount and update: Update single text": { + "Valyrian 5.0.8": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "Valyrian next": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "Mount and update: Render list": { + "vOld": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "VNext": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "Mount and update: Render keyed list": { + "vOld": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "VNext": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "Mount and update: Render keyed list -> stress": { + "vOld": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "VNext": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "Mount and update: Render keyed list -> swap keys on large set": { + "vOld": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "VNext": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + } + } + }, { "tag": "5facca6aa5e38cb11b7a4ecb997aac6a3c948e3f", "timestamp": "2022-02-03T22:46:40.072Z", diff --git a/bench/hyperscript_bench.js b/bench/hyperscript_bench.js index 20c5a78..393520b 100644 --- a/bench/hyperscript_bench.js +++ b/bench/hyperscript_bench.js @@ -2,21 +2,16 @@ const { before, benchmark, compare } = require("buffalo-test"); const { v: VNext } = require("../lib/index.ts"); const expect = require("expect"); -const fs = require("fs"); const nodePlugin = require("../plugins/node"); const vOld = require("./index-old"); compare("hyperscript", () => { let date = new Date(); before(async () => { - nodePlugin.inline.extensions("ts"); - // await nodePlugin.inline.ts("./lib/index.ts", { compact: true }); - await nodePlugin.inline.js("./bench/index-old.js", { compact: true }); - // console.log(nodePlugin.inline.ts()[0].raw.length); - console.log(nodePlugin.inline.js()[0].raw.length); - - let compiled = fs.readFileSync("./dist/valyrian.min.js", "utf8"); - console.log(compiled.length); + let { raw: newTs } = await nodePlugin.inline("./lib/index.ts", { compact: true }); + let { raw: oldjs } = await nodePlugin.inline("./bench/index-old.js", { compact: true }); + console.log(oldjs.length); + console.log(newTs.length); expect(vOld("div", null, [null, "Hello", , 1, date, { hello: "world" }, ["Hello"]])).toEqual({ name: "div", diff --git a/bench/mount_n_update_bench.js b/bench/mount_n_update_bench.js index 003e860..3256c8a 100644 --- a/bench/mount_n_update_bench.js +++ b/bench/mount_n_update_bench.js @@ -1,6 +1,6 @@ let { compare, benchmark, before } = require("buffalo-test"); -const { mount, update, v } = require("../lib/index.ts"); +const { mount, update, v } = require("../lib/index"); const expect = require("expect"); require("../plugins/node"); diff --git a/dist/@types/lib/index.d.ts b/dist/@types/lib/index.d.ts deleted file mode 100644 index aa7226b..0000000 --- a/dist/@types/lib/index.d.ts +++ /dev/null @@ -1,7 +0,0 @@ -declare class Vnode { - tag: string; - props: {}; - children: []; - constructor(tag: string, props: {}, children: []); -} -export { Vnode }; diff --git a/dist/@types/lib/index_.d.ts b/dist/@types/lib/index_.d.ts deleted file mode 100644 index a0f4dbe..0000000 --- a/dist/@types/lib/index_.d.ts +++ /dev/null @@ -1,106 +0,0 @@ -declare type VnodeOrUnknown = VnodeComponent | Vnode | TextVnode | any; -declare type DomAttribute = { - nodeName: string; - nodeValue: string; -}; -declare type DomElement = (HTMLElement | SVGElement) & Record; -declare type Props = { - key?: string | number; - data?: string; - oncreate?: { - (vnode: Vnode): never; - }; - onupdate?: { - (vnode: Vnode, oldVnode: Vnode | TextVnode): never; - }; - onremove?: { - (oldVnode: Vnode): never; - }; - onbeforeupdate?: { - (vnode: Vnode, oldVnode: Vnode | TextVnode): undefined | boolean; - }; -} & Record; -declare type Component = (props?: Record | null, children?: VnodeOrUnknown) => VnodeOrUnknown | VnodeOrUnknown[]; -declare type ValyrianComponent = Component | (Record & { - view: Component; -}); -declare type Current = { - parentVnode?: Vnode; - oldParentVnode?: Vnode; - component?: VnodeComponent; -}; -interface Plugin { - (v: Valyrian, options?: Record): never; -} -interface Directive { - (value: any, vnode: Vnode, oldVnode?: Vnode | TextVnode): void | boolean; -} -interface ValyrianEventHandler { - (a: Event, dom: DomElement): void; -} -interface Vnode { - name: string; - props: Props; - children: VnodeOrUnknown[]; - dom?: DomElement; - onCleanup?: FunctionConstructor[]; - isSVG?: boolean; - processed?: boolean; -} -declare class Vnode implements Vnode { - name: string; - props: Props; - children: VnodeOrUnknown[]; - dom?: DomElement; - onCleanup?: FunctionConstructor[]; - isSVG?: boolean; - processed?: boolean; - constructor(name: string, props: Props, children: VnodeOrUnknown); -} -interface TextVnode { - dom?: Text; - nodeValue: string; -} -declare class TextVnode implements TextVnode { - dom?: Text; - nodeValue: string; - constructor(nodeValue: string); -} -interface VnodeComponent { - component: ValyrianComponent; - props: Props; - children: VnodeOrUnknown[]; -} -declare class VnodeComponent implements VnodeComponent { - component: ValyrianComponent; - props: Props; - children: VnodeOrUnknown[]; - constructor(component: ValyrianComponent, props: Props, children: VnodeOrUnknown[]); -} -interface Valyrian { - (tagOrComponent: string | ValyrianComponent, props?: Props | null, children?: VnodeOrUnknown): Vnode | VnodeComponent; - fragment: (props: Props, children: VnodeOrUnknown[]) => VnodeOrUnknown[]; - isMounted: boolean; - isNode: boolean; - reservedWords: string[]; - current: Current; - trust: (htmlString: string) => Vnode[]; - usePlugin: (plugin: Plugin, options: Record) => void; - onCleanup: (callback: typeof Function) => void; - updateProperty: (name: string, newVnode: Vnode & { - dom: DomElement; - }, oldNode: Vnode & { - dom: DomElement; - }) => void; - update: (props?: Props | null, ...children: VnodeOrUnknown) => string | void; - mount: (container: string | DomElement, component: ValyrianComponent, props?: Props | null, ...children: VnodeOrUnknown[]) => string | void; - unMount: () => string | boolean | void; - directive: (directive: string, handler: Directive) => void; - newInstance: () => Valyrian; - [x: string]: any; -} -declare let isNode: boolean; -declare function createElement(tagName: string, isSVG?: boolean): DomElement; -declare function domToVnode(dom: DomElement): Vnode; -declare const trust: (htmlString: string) => Vnode[]; -declare function valyrian(): Valyrian; diff --git a/dist/@types/plugins/hooks.d.ts b/dist/@types/plugins/hooks.d.ts deleted file mode 100644 index c7e6301..0000000 --- a/dist/@types/plugins/hooks.d.ts +++ /dev/null @@ -1,5 +0,0 @@ -export = plugin; -declare function plugin(v: any): void; -declare namespace plugin { - export { plugin as default }; -} diff --git a/dist/@types/plugins/node.d.ts b/dist/@types/plugins/node.d.ts deleted file mode 100644 index 81979ce..0000000 --- a/dist/@types/plugins/node.d.ts +++ /dev/null @@ -1,53 +0,0 @@ -export = plugin; -declare function plugin(v: any): void; -declare namespace plugin { - export { inline }; - export { sw }; - export { icons }; - export const htmlToDom: (html: any, options?: {}) => any; - export const domToHtml: (dom: any) => any; - export const domToHyperscript: (childNodes: any, depth?: number) => any; - export const htmlToHyperscript: (html: any) => string; - export function hyperscriptToHtml(...args: any[]): any; - export { plugin as default }; -} -declare function inline(...args: any[]): Promise; -declare namespace inline { - function extensions(...extensions: any[]): void; - function css(file: any, options?: {}): any[] | Promise; - function js(file: any, options?: {}): any[] | Promise; - function uncss(renderedHtml: any, options?: {}): string | Promise; -} -declare function sw(file: any, options?: {}): Promise; -declare function icons(source: any, configuration?: {}): Promise; -declare namespace icons { - namespace options { - export const iconsPath: null; - export const linksViewPath: null; - export const path: string; - export const appName: null; - export const appDescription: null; - export const developerName: null; - export const developerURL: null; - export const dir: string; - export const lang: string; - export const background: string; - export const theme_color: string; - export const display: string; - export const orientation: string; - export const start_url: string; - export const version: string; - export const logging: boolean; - export namespace icons_1 { - const android: boolean; - const appleIcon: boolean; - const appleStartup: boolean; - const coast: boolean; - const favicons: boolean; - const firefox: boolean; - const windows: boolean; - const yandex: boolean; - } - export { icons_1 as icons }; - } -} diff --git a/dist/@types/plugins/request.d.ts b/dist/@types/plugins/request.d.ts deleted file mode 100644 index c7e6301..0000000 --- a/dist/@types/plugins/request.d.ts +++ /dev/null @@ -1,5 +0,0 @@ -export = plugin; -declare function plugin(v: any): void; -declare namespace plugin { - export { plugin as default }; -} diff --git a/dist/@types/plugins/router.d.ts b/dist/@types/plugins/router.d.ts deleted file mode 100644 index c7e6301..0000000 --- a/dist/@types/plugins/router.d.ts +++ /dev/null @@ -1,5 +0,0 @@ -export = plugin; -declare function plugin(v: any): void; -declare namespace plugin { - export { plugin as default }; -} diff --git a/dist/@types/plugins/signals.d.ts b/dist/@types/plugins/signals.d.ts deleted file mode 100644 index c7e6301..0000000 --- a/dist/@types/plugins/signals.d.ts +++ /dev/null @@ -1,5 +0,0 @@ -export = plugin; -declare function plugin(v: any): void; -declare namespace plugin { - export { plugin as default }; -} diff --git a/dist/@types/plugins/store.d.ts b/dist/@types/plugins/store.d.ts deleted file mode 100644 index c7e6301..0000000 --- a/dist/@types/plugins/store.d.ts +++ /dev/null @@ -1,5 +0,0 @@ -export = plugin; -declare function plugin(v: any): void; -declare namespace plugin { - export { plugin as default }; -} diff --git a/dist/@types/plugins/sw.d.ts b/dist/@types/plugins/sw.d.ts deleted file mode 100644 index c7e6301..0000000 --- a/dist/@types/plugins/sw.d.ts +++ /dev/null @@ -1,5 +0,0 @@ -export = plugin; -declare function plugin(v: any): void; -declare namespace plugin { - export { plugin as default }; -} diff --git a/dist/@types/plugins/v-model.d.ts b/dist/@types/plugins/v-model.d.ts deleted file mode 100644 index c7e6301..0000000 --- a/dist/@types/plugins/v-model.d.ts +++ /dev/null @@ -1,5 +0,0 @@ -export = plugin; -declare function plugin(v: any): void; -declare namespace plugin { - export { plugin as default }; -} diff --git a/dist/@types/register.d.ts b/dist/@types/register.d.ts deleted file mode 100644 index cb0ff5c..0000000 --- a/dist/@types/register.d.ts +++ /dev/null @@ -1 +0,0 @@ -export {}; diff --git a/dist/index.cjs b/dist/index.cjs new file mode 100644 index 0000000..de973e9 --- /dev/null +++ b/dist/index.cjs @@ -0,0 +1,550 @@ +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __markAsModule = (target) => __defProp(target, "__esModule", { value: true }); +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __reExport = (target, module2, copyDefault, desc) => { + if (module2 && typeof module2 === "object" || typeof module2 === "function") { + for (let key of __getOwnPropNames(module2)) + if (!__hasOwnProp.call(target, key) && (copyDefault || key !== "default")) + __defProp(target, key, { get: () => module2[key], enumerable: !(desc = __getOwnPropDesc(module2, key)) || desc.enumerable }); + } + return target; +}; +var __toCommonJS = /* @__PURE__ */ ((cache) => { + return (module2, temp) => { + return cache && cache.get(module2) || (temp = __reExport(__markAsModule({}), module2, 1), cache && cache.set(module2, temp), temp); + }; +})(typeof WeakMap !== "undefined" ? /* @__PURE__ */ new WeakMap() : 0); + +// lib/index.ts +var lib_exports = {}; +__export(lib_exports, { + Vnode: () => Vnode, + cleanup: () => cleanup, + directive: () => directive, + isComponent: () => isComponent, + isNodeJs: () => isNodeJs, + isVnode: () => isVnode, + isVnodeComponent: () => isVnodeComponent, + mount: () => mount, + onremove: () => onremove, + trust: () => trust, + unmount: () => unmount, + update: () => update, + updateProperty: () => updateProperty, + valyrian: () => valyrian +}); +var Vnode = function Vnode2(tag, props, children) { + this.props = props; + this.children = children; + this.tag = tag; +}; +function isVnode(component) { + return component instanceof Vnode; +} +function isComponent(component) { + return typeof component === "function" || typeof component === "object" && component !== null && "view" in component; +} +function isVnodeComponent(vnode) { + return vnode instanceof Vnode && vnode.tag === "__component__"; +} +var isNodeJs = Boolean(typeof process !== "undefined" && process.versions && process.versions.node); +function createDomElement(tag, isSVG = false) { + return isSVG ? document.createElementNS("http://www.w3.org/2000/svg", tag) : document.createElement(tag); +} +function domToVnode(dom) { + let vnode = v(dom.tagName.toLowerCase(), {}, ...Array.from(dom.childNodes).filter((child) => child.nodeType === 1 || child.nodeType === 3).map((child) => { + if (child.nodeType === 1) { + return domToVnode(child); + } + let text = new Vnode("#text", {}, []); + text.nodeValue = String(child.nodeValue); + text.dom = child; + return text; + })); + [].forEach.call(dom.attributes, (prop) => vnode.props[prop.nodeName] = prop.nodeValue); + vnode.dom = dom; + return vnode; +} +var trust = (htmlString) => { + let div = createDomElement("div"); + div.innerHTML = htmlString.trim(); + return [].map.call(div.childNodes, (item) => domToVnode(item)); +}; +var ValyrianSymbol = Symbol("Valyrian"); +function cleanup(callback) { + if (v.current.app?.cleanup.indexOf(callback) === -1) { + v.current.app?.cleanup.push(callback); + } +} +function mount(container, component) { + let appContainer = null; + if (isNodeJs) { + appContainer = typeof container === "string" ? createDomElement(container === "svg" ? "svg" : "div", container === "svg") : container; + } else { + appContainer = typeof container === "string" ? document.querySelectorAll(container)[0] : container; + } + if (!appContainer) { + throw new Error("Container not found"); + } + let vnodeComponent; + if (isVnodeComponent(component)) { + vnodeComponent = component; + } else if (isComponent(component)) { + vnodeComponent = v(component, {}); + } else { + throw new Error("Component must be a Valyrian Component or a Vnode component"); + } + if (component[ValyrianSymbol]) { + unmount(component); + } else { + let eventListener = function(e) { + let dom = e.target; + let name = `v-on${e.type}`; + while (dom) { + if (dom[name]) { + dom[name](e, dom); + if (!e.defaultPrevented) { + update(component); + } + return; + } + dom = dom.parentNode; + } + }; + component[ValyrianSymbol] = { + isMounted: false, + eventListenerNames: {}, + isNodeJs, + cleanup: [] + }; + component[ValyrianSymbol].eventListener = eventListener; + } + component[ValyrianSymbol].component = vnodeComponent; + component[ValyrianSymbol].container = appContainer; + component[ValyrianSymbol].mainVnode = domToVnode(appContainer); + return update(component); +} +function cleanupVnodes(valyrianApp) { + for (let i = 0; i < valyrianApp.cleanup.length; i++) { + valyrianApp.cleanup[i](); + } + valyrianApp.cleanup = []; +} +function update(component) { + if (component && component[ValyrianSymbol]) { + let valyrianApp = component[ValyrianSymbol]; + v.current.app = valyrianApp; + cleanupVnodes(valyrianApp); + let oldVnode = valyrianApp.mainVnode; + valyrianApp.mainVnode = new Vnode(valyrianApp.mainVnode.tag, valyrianApp.mainVnode.props, [valyrianApp.component]); + valyrianApp.mainVnode.dom = oldVnode.dom; + valyrianApp.mainVnode.isSVG = oldVnode.isSVG; + patch(valyrianApp.mainVnode, oldVnode, valyrianApp); + oldVnode = null; + valyrianApp.isMounted = true; + if (isNodeJs) { + return valyrianApp.mainVnode.dom.innerHTML; + } + } +} +function unmount(component) { + if (!component || !component[ValyrianSymbol]) { + return; + } + let valyrianApp = component[ValyrianSymbol]; + if (valyrianApp.isMounted) { + cleanupVnodes(valyrianApp); + let oldVnode = valyrianApp.mainVnode; + valyrianApp.mainVnode = new Vnode(valyrianApp.mainVnode.tag, valyrianApp.mainVnode.props, []); + valyrianApp.mainVnode.dom = oldVnode.dom; + valyrianApp.mainVnode.isSVG = oldVnode.isSVG; + patch(valyrianApp.mainVnode, oldVnode, valyrianApp); + oldVnode = null; + valyrianApp.isMounted = false; + if (isNodeJs) { + return valyrianApp.mainVnode.dom.innerHTML; + } + } +} +var emptyVnode = new Vnode("__empty__", {}, []); +function onremove(vnode) { + for (let i = 0; i < vnode.children.length; i++) { + vnode.children[i].tag !== "#text" && onremove(vnode.children[i]); + } + vnode.props.onremove && vnode.props.onremove(vnode); +} +function sharedUpdateProperty(prop, value, vnode, oldVnode) { + if (v.reservedProps[prop]) { + if (v.directives[prop]) { + v.directives[prop](vnode.props[prop], vnode, oldVnode); + } + return; + } + if (typeof value === "function") { + let valyrianApp = v.current.app; + if (prop in valyrianApp.eventListenerNames === false) { + valyrianApp.eventListenerNames[prop] = true; + valyrianApp.container.addEventListener(prop.slice(2), valyrianApp.eventListener); + } + vnode.dom[`v-${prop}`] = value; + return; + } + if (prop in vnode.dom && vnode.isSVG === false) { + if (vnode.dom[prop] != value) { + vnode.dom[prop] = value; + } + return; + } + if (!oldVnode || oldVnode.props[prop] !== value) { + if (value === false) { + vnode.dom.removeAttribute(prop); + } else { + vnode.dom.setAttribute(prop, value); + } + } +} +function updateProperty(name, value, vnode, oldVnode) { + if (name in vnode.props === false) { + vnode.props[name] = value; + } + sharedUpdateProperty(name, value, vnode, oldVnode); +} +function updateProperties(vnode, oldVnode) { + for (let prop in vnode.props) { + if (prop in vnode.props === false) { + return; + } + sharedUpdateProperty(prop, vnode.props[prop], vnode, oldVnode); + } + if (oldVnode) { + for (let prop in oldVnode.props) { + if (prop in vnode.props === false && typeof oldVnode.props[prop] !== "function" && prop in v.reservedProps === false) { + if (prop in oldVnode.dom && vnode.isSVG === false) { + oldVnode.dom[prop] = null; + } else { + oldVnode.dom.removeAttribute(prop); + } + } + } + } +} +function flatTree(newVnode) { + let newTree = newVnode.children; + for (let i = 0; i < newTree.length; i++) { + let childVnode = newTree[i]; + if (childVnode instanceof Vnode) { + if (childVnode.tag !== "#text") { + if (childVnode.tag === "__component__") { + let component = childVnode.component; + v.current.component = component; + let result = ("view" in component ? component.view : component).call(component, childVnode.props, ...childVnode.children); + newTree.splice(i--, 1, result); + continue; + } + childVnode.isSVG = newVnode.isSVG || childVnode.tag === "svg"; + } + } else if (childVnode === null || childVnode === void 0) { + newTree.splice(i--, 1); + } else if (Array.isArray(childVnode)) { + newTree.splice(i--, 1, ...childVnode); + } else { + if (i > 0 && newTree[i - 1].tag === "#text") { + newTree[i - 1].nodeValue += childVnode; + newTree.splice(i--, 1); + } else { + newTree[i] = new Vnode("#text", {}, []); + newTree[i].nodeValue = String(childVnode); + } + } + } +} +function patchKeyedTree(newVnode, newTree, oldTree, newTreeLength, oldTreeLength, valyrianApp) { + let oldKeyedList = oldTree.reduce((acc, vnode, i) => { + acc[vnode.props.key] = i; + return acc; + }, {}); + let newKeyedList = newTree.reduce((acc, vnode, i) => { + acc[vnode.props.key] = i; + return acc; + }, {}); + for (let i = 0; i < newTreeLength; i++) { + let childVnode = newTree[i]; + let oldChildVnode = oldTree[oldKeyedList[childVnode.props.key]]; + let shouldPatch = true; + if (oldChildVnode) { + childVnode.dom = oldChildVnode.dom; + if ("v-once" in childVnode.props || childVnode.props.shouldupdate && childVnode.props.shouldupdate(childVnode, oldChildVnode) === false) { + childVnode.children = oldChildVnode.children; + shouldPatch = false; + } else { + updateProperties(childVnode, oldChildVnode); + if (valyrianApp.isMounted) { + childVnode.props.onupdate && childVnode.props.onupdate(childVnode, oldChildVnode); + } else { + childVnode.props.oncreate && childVnode.props.oncreate(childVnode); + } + } + } else { + childVnode.dom = createDomElement(childVnode.tag, childVnode.isSVG); + updateProperties(childVnode); + childVnode.props.oncreate && childVnode.props.oncreate(childVnode); + } + if (newVnode.dom.childNodes[i] === void 0) { + newVnode.dom.appendChild(childVnode.dom); + } else if (newVnode.dom.childNodes[i] !== childVnode.dom) { + oldTree[i] && newKeyedList[oldTree[i].props.key] === void 0 && onremove(oldTree[i]); + newVnode.dom.replaceChild(childVnode.dom, newVnode.dom.childNodes[i]); + } + shouldPatch && patch(childVnode, oldChildVnode, valyrianApp); + } + for (let i = newTreeLength; i < oldTreeLength; i++) { + if (newKeyedList[oldTree[i].props.key] === void 0) { + let oldChildVnode = oldTree[i]; + onremove(oldChildVnode); + oldChildVnode.dom.parentNode && oldChildVnode.dom.parentNode.removeChild(oldChildVnode.dom); + } + } +} +function patchNormalTree(newVnode, newTree, oldTree, newTreeLength, oldTreeLength, valyrianApp) { + for (let i = 0; i < newTreeLength; i++) { + let oldChildVnode = oldTree[i]; + let newChildVnode = newTree[i]; + if (!oldChildVnode) { + if (newChildVnode.tag === "#text") { + newChildVnode.dom = document.createTextNode(newChildVnode.nodeValue); + newVnode.dom.appendChild(newChildVnode.dom); + continue; + } + newChildVnode.dom = createDomElement(newChildVnode.tag, newChildVnode.isSVG); + updateProperties(newChildVnode); + newVnode.dom.appendChild(newChildVnode.dom); + newChildVnode.props.oncreate && newChildVnode.props.oncreate(newChildVnode); + patch(newChildVnode, void 0, valyrianApp); + continue; + } + if (newChildVnode.tag === "#text") { + if (oldChildVnode.tag === "#text") { + newChildVnode.dom = oldChildVnode.dom; + if (newChildVnode.dom.nodeValue != newChildVnode.nodeValue) { + newChildVnode.dom.nodeValue = newChildVnode.nodeValue; + } + continue; + } + newChildVnode.dom = document.createTextNode(newChildVnode.nodeValue); + onremove(oldChildVnode); + newVnode.dom.replaceChild(newChildVnode.dom, oldChildVnode.dom); + continue; + } + if (oldChildVnode.tag === newChildVnode.tag) { + newChildVnode.dom = oldChildVnode.dom; + if (newChildVnode.props["v-once"] || newChildVnode.props.shouldupdate && newChildVnode.props.shouldupdate(newChildVnode, oldChildVnode) === false) { + newChildVnode.children = oldChildVnode.children; + continue; + } + updateProperties(newChildVnode, oldChildVnode); + if (valyrianApp && valyrianApp.isMounted) { + newChildVnode.props.onupdate && newChildVnode.props.onupdate(newChildVnode, oldChildVnode); + } else { + newChildVnode.props.oncreate && newChildVnode.props.oncreate(newChildVnode); + } + patch(newChildVnode, oldChildVnode, valyrianApp); + continue; + } + newChildVnode.dom = createDomElement(newChildVnode.tag, newChildVnode.isSVG); + updateProperties(newChildVnode); + if (oldChildVnode.tag !== "#text") { + onremove(oldChildVnode); + } + newChildVnode.props.oncreate && newChildVnode.props.oncreate(newChildVnode); + newVnode.dom.replaceChild(newChildVnode.dom, oldChildVnode.dom); + patch(newChildVnode, void 0, valyrianApp); + } + for (let i = newTreeLength; i < oldTreeLength; i++) { + let oldChildVnode = oldTree[i]; + if (oldChildVnode.tag !== "#text") { + onremove(oldChildVnode); + } + oldChildVnode.dom.parentNode && oldChildVnode.dom.parentNode.removeChild(oldChildVnode.dom); + } +} +function patch(newVnode, oldVnode = emptyVnode, valyrianApp) { + v.current.vnode = newVnode; + v.current.oldVnode = oldVnode; + flatTree(newVnode); + let newTree = newVnode.children; + let oldTree = oldVnode.children; + let oldTreeLength = oldTree.length; + let newTreeLength = newTree.length; + if (newTreeLength === 0) { + for (let i = 0; i < oldTreeLength; i++) { + onremove(oldTree[i]); + } + newVnode.dom.textContent = ""; + return; + } + if (oldTreeLength && "key" in newTree[0].props && "key" in oldTree[0].props) { + patchKeyedTree(newVnode, newTree, oldTree, newTreeLength, oldTreeLength, valyrianApp); + return; + } + patchNormalTree(newVnode, newTree, oldTree, newTreeLength, oldTreeLength, valyrianApp); +} +function directive(name, directive2) { + let fullName = `v-${name}`; + v.directives[fullName] = directive2; + v.reservedProps[fullName] = true; +} +function hideDirective(test) { + return (bool, vnode, oldVnode) => { + let value = test ? bool : !bool; + if (value) { + let newdom = document.createTextNode(""); + if (oldVnode && oldVnode.dom && oldVnode.dom.parentNode) { + oldVnode.tag !== "#text" && onremove(oldVnode); + oldVnode.dom.parentNode.replaceChild(newdom, oldVnode.dom); + } + vnode.tag = "#text"; + vnode.children = []; + vnode.props = {}; + vnode.dom = newdom; + } + }; +} +var builtInDirectives = { + "v-if": hideDirective(false), + "v-unless": hideDirective(true), + "v-for": (set, vnode) => { + vnode.children = set.map(vnode.children[0]); + }, + "v-show": (bool, vnode) => { + vnode.dom.style.display = bool ? "" : "none"; + }, + "v-class": (classes, vnode) => { + for (let name in classes) { + vnode.dom.classList.toggle(name, classes[name]); + } + }, + "v-html": (html, vnode) => { + vnode.children = [trust(html)]; + }, + "v-model": ([model, property, event], vnode, oldVnode) => { + let value; + let handler; + if (vnode.name === "input") { + event = event || "oninput"; + switch (vnode.props.type) { + case "checkbox": { + if (Array.isArray(model[property])) { + handler = (e) => { + let val = e.target.value; + let idx = model[property].indexOf(val); + if (idx === -1) { + model[property].push(val); + } else { + model[property].splice(idx, 1); + } + }; + value = model[property].indexOf(vnode.dom.value) !== -1; + } else if ("value" in vnode.props) { + handler = () => { + if (model[property] === vnode.props.value) { + model[property] = null; + } else { + model[property] = vnode.props.value; + } + }; + value = model[property] === vnode.props.value; + } else { + handler = () => model[property] = !model[property]; + value = model[property]; + } + updateProperty("checked", value, vnode, oldVnode); + break; + } + case "radio": { + updateProperty("checked", model[property] === vnode.dom.value, vnode, oldVnode); + break; + } + default: { + updateProperty("value", model[property], vnode, oldVnode); + } + } + } else if (vnode.name === "select") { + event = event || "onclick"; + if (vnode.props.multiple) { + handler = (e) => { + let val = e.target.value; + if (e.ctrlKey) { + let idx = model[property].indexOf(val); + if (idx === -1) { + model[property].push(val); + } else { + model[property].splice(idx, 1); + } + } else { + model[property].splice(0, model[property].length); + model[property].push(val); + } + }; + vnode.children.forEach((child) => { + if (child.name === "option") { + let value2 = "value" in child.props ? child.props.value : child.children.join("").trim(); + child.props.selected = model[property].indexOf(value2) !== -1; + } + }); + } else { + vnode.children.forEach((child) => { + if (child.name === "option") { + let value2 = "value" in child.props ? child.props.value : child.children.join("").trim(); + child.props.selected = value2 === model[property]; + } + }); + } + } else if (vnode.name === "textarea") { + event = event || "oninput"; + vnode.children = [model[property]]; + } + if (!vnode.props[event]) { + if (!handler) { + handler = (e) => model[property] = e.target.value; + } + updateProperty(event, handler, vnode, oldVnode); + } + } +}; +var valyrian = function v2(tagOrComponent, props, ...children) { + if (typeof tagOrComponent === "string") { + return new Vnode(tagOrComponent, props || {}, children); + } + const vnode = new Vnode("__component__", props || {}, children); + vnode.component = tagOrComponent; + return vnode; +}; +valyrian.fragment = (props, ...children) => { + return children; +}; +valyrian.current = {}; +valyrian.directives = { ...builtInDirectives }; +valyrian.reservedProps = { + key: true, + state: true, + oncreate: true, + onupdate: true, + onremove: true, + shouldupdate: true, + "v-cleanup": true, + "v-once": true, + "v-if": true, + "v-unless": true, + "v-for": true, + "v-show": true, + "v-class": true, + "v-html": true +}; +(isNodeJs ? global : window).v = valyrian; +module.exports = __toCommonJS(lib_exports); diff --git a/dist/index.js b/dist/index.js new file mode 100644 index 0000000..da149b0 --- /dev/null +++ b/dist/index.js @@ -0,0 +1,525 @@ +// lib/index.ts +var Vnode = function Vnode2(tag, props, children) { + this.props = props; + this.children = children; + this.tag = tag; +}; +function isVnode(component) { + return component instanceof Vnode; +} +function isComponent(component) { + return typeof component === "function" || typeof component === "object" && component !== null && "view" in component; +} +function isVnodeComponent(vnode) { + return vnode instanceof Vnode && vnode.tag === "__component__"; +} +var isNodeJs = Boolean(typeof process !== "undefined" && process.versions && process.versions.node); +function createDomElement(tag, isSVG = false) { + return isSVG ? document.createElementNS("http://www.w3.org/2000/svg", tag) : document.createElement(tag); +} +function domToVnode(dom) { + let vnode = v(dom.tagName.toLowerCase(), {}, ...Array.from(dom.childNodes).filter((child) => child.nodeType === 1 || child.nodeType === 3).map((child) => { + if (child.nodeType === 1) { + return domToVnode(child); + } + let text = new Vnode("#text", {}, []); + text.nodeValue = String(child.nodeValue); + text.dom = child; + return text; + })); + [].forEach.call(dom.attributes, (prop) => vnode.props[prop.nodeName] = prop.nodeValue); + vnode.dom = dom; + return vnode; +} +var trust = (htmlString) => { + let div = createDomElement("div"); + div.innerHTML = htmlString.trim(); + return [].map.call(div.childNodes, (item) => domToVnode(item)); +}; +var ValyrianSymbol = Symbol("Valyrian"); +function cleanup(callback) { + if (v.current.app?.cleanup.indexOf(callback) === -1) { + v.current.app?.cleanup.push(callback); + } +} +function mount(container, component) { + let appContainer = null; + if (isNodeJs) { + appContainer = typeof container === "string" ? createDomElement(container === "svg" ? "svg" : "div", container === "svg") : container; + } else { + appContainer = typeof container === "string" ? document.querySelectorAll(container)[0] : container; + } + if (!appContainer) { + throw new Error("Container not found"); + } + let vnodeComponent; + if (isVnodeComponent(component)) { + vnodeComponent = component; + } else if (isComponent(component)) { + vnodeComponent = v(component, {}); + } else { + throw new Error("Component must be a Valyrian Component or a Vnode component"); + } + if (component[ValyrianSymbol]) { + unmount(component); + } else { + let eventListener = function(e) { + let dom = e.target; + let name = `v-on${e.type}`; + while (dom) { + if (dom[name]) { + dom[name](e, dom); + if (!e.defaultPrevented) { + update(component); + } + return; + } + dom = dom.parentNode; + } + }; + component[ValyrianSymbol] = { + isMounted: false, + eventListenerNames: {}, + isNodeJs, + cleanup: [] + }; + component[ValyrianSymbol].eventListener = eventListener; + } + component[ValyrianSymbol].component = vnodeComponent; + component[ValyrianSymbol].container = appContainer; + component[ValyrianSymbol].mainVnode = domToVnode(appContainer); + return update(component); +} +function cleanupVnodes(valyrianApp) { + for (let i = 0; i < valyrianApp.cleanup.length; i++) { + valyrianApp.cleanup[i](); + } + valyrianApp.cleanup = []; +} +function update(component) { + if (component && component[ValyrianSymbol]) { + let valyrianApp = component[ValyrianSymbol]; + v.current.app = valyrianApp; + cleanupVnodes(valyrianApp); + let oldVnode = valyrianApp.mainVnode; + valyrianApp.mainVnode = new Vnode(valyrianApp.mainVnode.tag, valyrianApp.mainVnode.props, [valyrianApp.component]); + valyrianApp.mainVnode.dom = oldVnode.dom; + valyrianApp.mainVnode.isSVG = oldVnode.isSVG; + patch(valyrianApp.mainVnode, oldVnode, valyrianApp); + oldVnode = null; + valyrianApp.isMounted = true; + if (isNodeJs) { + return valyrianApp.mainVnode.dom.innerHTML; + } + } +} +function unmount(component) { + if (!component || !component[ValyrianSymbol]) { + return; + } + let valyrianApp = component[ValyrianSymbol]; + if (valyrianApp.isMounted) { + cleanupVnodes(valyrianApp); + let oldVnode = valyrianApp.mainVnode; + valyrianApp.mainVnode = new Vnode(valyrianApp.mainVnode.tag, valyrianApp.mainVnode.props, []); + valyrianApp.mainVnode.dom = oldVnode.dom; + valyrianApp.mainVnode.isSVG = oldVnode.isSVG; + patch(valyrianApp.mainVnode, oldVnode, valyrianApp); + oldVnode = null; + valyrianApp.isMounted = false; + if (isNodeJs) { + return valyrianApp.mainVnode.dom.innerHTML; + } + } +} +var emptyVnode = new Vnode("__empty__", {}, []); +function onremove(vnode) { + for (let i = 0; i < vnode.children.length; i++) { + vnode.children[i].tag !== "#text" && onremove(vnode.children[i]); + } + vnode.props.onremove && vnode.props.onremove(vnode); +} +function sharedUpdateProperty(prop, value, vnode, oldVnode) { + if (v.reservedProps[prop]) { + if (v.directives[prop]) { + v.directives[prop](vnode.props[prop], vnode, oldVnode); + } + return; + } + if (typeof value === "function") { + let valyrianApp = v.current.app; + if (prop in valyrianApp.eventListenerNames === false) { + valyrianApp.eventListenerNames[prop] = true; + valyrianApp.container.addEventListener(prop.slice(2), valyrianApp.eventListener); + } + vnode.dom[`v-${prop}`] = value; + return; + } + if (prop in vnode.dom && vnode.isSVG === false) { + if (vnode.dom[prop] != value) { + vnode.dom[prop] = value; + } + return; + } + if (!oldVnode || oldVnode.props[prop] !== value) { + if (value === false) { + vnode.dom.removeAttribute(prop); + } else { + vnode.dom.setAttribute(prop, value); + } + } +} +function updateProperty(name, value, vnode, oldVnode) { + if (name in vnode.props === false) { + vnode.props[name] = value; + } + sharedUpdateProperty(name, value, vnode, oldVnode); +} +function updateProperties(vnode, oldVnode) { + for (let prop in vnode.props) { + if (prop in vnode.props === false) { + return; + } + sharedUpdateProperty(prop, vnode.props[prop], vnode, oldVnode); + } + if (oldVnode) { + for (let prop in oldVnode.props) { + if (prop in vnode.props === false && typeof oldVnode.props[prop] !== "function" && prop in v.reservedProps === false) { + if (prop in oldVnode.dom && vnode.isSVG === false) { + oldVnode.dom[prop] = null; + } else { + oldVnode.dom.removeAttribute(prop); + } + } + } + } +} +function flatTree(newVnode) { + let newTree = newVnode.children; + for (let i = 0; i < newTree.length; i++) { + let childVnode = newTree[i]; + if (childVnode instanceof Vnode) { + if (childVnode.tag !== "#text") { + if (childVnode.tag === "__component__") { + let component = childVnode.component; + v.current.component = component; + let result = ("view" in component ? component.view : component).call(component, childVnode.props, ...childVnode.children); + newTree.splice(i--, 1, result); + continue; + } + childVnode.isSVG = newVnode.isSVG || childVnode.tag === "svg"; + } + } else if (childVnode === null || childVnode === void 0) { + newTree.splice(i--, 1); + } else if (Array.isArray(childVnode)) { + newTree.splice(i--, 1, ...childVnode); + } else { + if (i > 0 && newTree[i - 1].tag === "#text") { + newTree[i - 1].nodeValue += childVnode; + newTree.splice(i--, 1); + } else { + newTree[i] = new Vnode("#text", {}, []); + newTree[i].nodeValue = String(childVnode); + } + } + } +} +function patchKeyedTree(newVnode, newTree, oldTree, newTreeLength, oldTreeLength, valyrianApp) { + let oldKeyedList = oldTree.reduce((acc, vnode, i) => { + acc[vnode.props.key] = i; + return acc; + }, {}); + let newKeyedList = newTree.reduce((acc, vnode, i) => { + acc[vnode.props.key] = i; + return acc; + }, {}); + for (let i = 0; i < newTreeLength; i++) { + let childVnode = newTree[i]; + let oldChildVnode = oldTree[oldKeyedList[childVnode.props.key]]; + let shouldPatch = true; + if (oldChildVnode) { + childVnode.dom = oldChildVnode.dom; + if ("v-once" in childVnode.props || childVnode.props.shouldupdate && childVnode.props.shouldupdate(childVnode, oldChildVnode) === false) { + childVnode.children = oldChildVnode.children; + shouldPatch = false; + } else { + updateProperties(childVnode, oldChildVnode); + if (valyrianApp.isMounted) { + childVnode.props.onupdate && childVnode.props.onupdate(childVnode, oldChildVnode); + } else { + childVnode.props.oncreate && childVnode.props.oncreate(childVnode); + } + } + } else { + childVnode.dom = createDomElement(childVnode.tag, childVnode.isSVG); + updateProperties(childVnode); + childVnode.props.oncreate && childVnode.props.oncreate(childVnode); + } + if (newVnode.dom.childNodes[i] === void 0) { + newVnode.dom.appendChild(childVnode.dom); + } else if (newVnode.dom.childNodes[i] !== childVnode.dom) { + oldTree[i] && newKeyedList[oldTree[i].props.key] === void 0 && onremove(oldTree[i]); + newVnode.dom.replaceChild(childVnode.dom, newVnode.dom.childNodes[i]); + } + shouldPatch && patch(childVnode, oldChildVnode, valyrianApp); + } + for (let i = newTreeLength; i < oldTreeLength; i++) { + if (newKeyedList[oldTree[i].props.key] === void 0) { + let oldChildVnode = oldTree[i]; + onremove(oldChildVnode); + oldChildVnode.dom.parentNode && oldChildVnode.dom.parentNode.removeChild(oldChildVnode.dom); + } + } +} +function patchNormalTree(newVnode, newTree, oldTree, newTreeLength, oldTreeLength, valyrianApp) { + for (let i = 0; i < newTreeLength; i++) { + let oldChildVnode = oldTree[i]; + let newChildVnode = newTree[i]; + if (!oldChildVnode) { + if (newChildVnode.tag === "#text") { + newChildVnode.dom = document.createTextNode(newChildVnode.nodeValue); + newVnode.dom.appendChild(newChildVnode.dom); + continue; + } + newChildVnode.dom = createDomElement(newChildVnode.tag, newChildVnode.isSVG); + updateProperties(newChildVnode); + newVnode.dom.appendChild(newChildVnode.dom); + newChildVnode.props.oncreate && newChildVnode.props.oncreate(newChildVnode); + patch(newChildVnode, void 0, valyrianApp); + continue; + } + if (newChildVnode.tag === "#text") { + if (oldChildVnode.tag === "#text") { + newChildVnode.dom = oldChildVnode.dom; + if (newChildVnode.dom.nodeValue != newChildVnode.nodeValue) { + newChildVnode.dom.nodeValue = newChildVnode.nodeValue; + } + continue; + } + newChildVnode.dom = document.createTextNode(newChildVnode.nodeValue); + onremove(oldChildVnode); + newVnode.dom.replaceChild(newChildVnode.dom, oldChildVnode.dom); + continue; + } + if (oldChildVnode.tag === newChildVnode.tag) { + newChildVnode.dom = oldChildVnode.dom; + if (newChildVnode.props["v-once"] || newChildVnode.props.shouldupdate && newChildVnode.props.shouldupdate(newChildVnode, oldChildVnode) === false) { + newChildVnode.children = oldChildVnode.children; + continue; + } + updateProperties(newChildVnode, oldChildVnode); + if (valyrianApp && valyrianApp.isMounted) { + newChildVnode.props.onupdate && newChildVnode.props.onupdate(newChildVnode, oldChildVnode); + } else { + newChildVnode.props.oncreate && newChildVnode.props.oncreate(newChildVnode); + } + patch(newChildVnode, oldChildVnode, valyrianApp); + continue; + } + newChildVnode.dom = createDomElement(newChildVnode.tag, newChildVnode.isSVG); + updateProperties(newChildVnode); + if (oldChildVnode.tag !== "#text") { + onremove(oldChildVnode); + } + newChildVnode.props.oncreate && newChildVnode.props.oncreate(newChildVnode); + newVnode.dom.replaceChild(newChildVnode.dom, oldChildVnode.dom); + patch(newChildVnode, void 0, valyrianApp); + } + for (let i = newTreeLength; i < oldTreeLength; i++) { + let oldChildVnode = oldTree[i]; + if (oldChildVnode.tag !== "#text") { + onremove(oldChildVnode); + } + oldChildVnode.dom.parentNode && oldChildVnode.dom.parentNode.removeChild(oldChildVnode.dom); + } +} +function patch(newVnode, oldVnode = emptyVnode, valyrianApp) { + v.current.vnode = newVnode; + v.current.oldVnode = oldVnode; + flatTree(newVnode); + let newTree = newVnode.children; + let oldTree = oldVnode.children; + let oldTreeLength = oldTree.length; + let newTreeLength = newTree.length; + if (newTreeLength === 0) { + for (let i = 0; i < oldTreeLength; i++) { + onremove(oldTree[i]); + } + newVnode.dom.textContent = ""; + return; + } + if (oldTreeLength && "key" in newTree[0].props && "key" in oldTree[0].props) { + patchKeyedTree(newVnode, newTree, oldTree, newTreeLength, oldTreeLength, valyrianApp); + return; + } + patchNormalTree(newVnode, newTree, oldTree, newTreeLength, oldTreeLength, valyrianApp); +} +function directive(name, directive2) { + let fullName = `v-${name}`; + v.directives[fullName] = directive2; + v.reservedProps[fullName] = true; +} +function hideDirective(test) { + return (bool, vnode, oldVnode) => { + let value = test ? bool : !bool; + if (value) { + let newdom = document.createTextNode(""); + if (oldVnode && oldVnode.dom && oldVnode.dom.parentNode) { + oldVnode.tag !== "#text" && onremove(oldVnode); + oldVnode.dom.parentNode.replaceChild(newdom, oldVnode.dom); + } + vnode.tag = "#text"; + vnode.children = []; + vnode.props = {}; + vnode.dom = newdom; + } + }; +} +var builtInDirectives = { + "v-if": hideDirective(false), + "v-unless": hideDirective(true), + "v-for": (set, vnode) => { + vnode.children = set.map(vnode.children[0]); + }, + "v-show": (bool, vnode) => { + vnode.dom.style.display = bool ? "" : "none"; + }, + "v-class": (classes, vnode) => { + for (let name in classes) { + vnode.dom.classList.toggle(name, classes[name]); + } + }, + "v-html": (html, vnode) => { + vnode.children = [trust(html)]; + }, + "v-model": ([model, property, event], vnode, oldVnode) => { + let value; + let handler; + if (vnode.name === "input") { + event = event || "oninput"; + switch (vnode.props.type) { + case "checkbox": { + if (Array.isArray(model[property])) { + handler = (e) => { + let val = e.target.value; + let idx = model[property].indexOf(val); + if (idx === -1) { + model[property].push(val); + } else { + model[property].splice(idx, 1); + } + }; + value = model[property].indexOf(vnode.dom.value) !== -1; + } else if ("value" in vnode.props) { + handler = () => { + if (model[property] === vnode.props.value) { + model[property] = null; + } else { + model[property] = vnode.props.value; + } + }; + value = model[property] === vnode.props.value; + } else { + handler = () => model[property] = !model[property]; + value = model[property]; + } + updateProperty("checked", value, vnode, oldVnode); + break; + } + case "radio": { + updateProperty("checked", model[property] === vnode.dom.value, vnode, oldVnode); + break; + } + default: { + updateProperty("value", model[property], vnode, oldVnode); + } + } + } else if (vnode.name === "select") { + event = event || "onclick"; + if (vnode.props.multiple) { + handler = (e) => { + let val = e.target.value; + if (e.ctrlKey) { + let idx = model[property].indexOf(val); + if (idx === -1) { + model[property].push(val); + } else { + model[property].splice(idx, 1); + } + } else { + model[property].splice(0, model[property].length); + model[property].push(val); + } + }; + vnode.children.forEach((child) => { + if (child.name === "option") { + let value2 = "value" in child.props ? child.props.value : child.children.join("").trim(); + child.props.selected = model[property].indexOf(value2) !== -1; + } + }); + } else { + vnode.children.forEach((child) => { + if (child.name === "option") { + let value2 = "value" in child.props ? child.props.value : child.children.join("").trim(); + child.props.selected = value2 === model[property]; + } + }); + } + } else if (vnode.name === "textarea") { + event = event || "oninput"; + vnode.children = [model[property]]; + } + if (!vnode.props[event]) { + if (!handler) { + handler = (e) => model[property] = e.target.value; + } + updateProperty(event, handler, vnode, oldVnode); + } + } +}; +var valyrian = function v2(tagOrComponent, props, ...children) { + if (typeof tagOrComponent === "string") { + return new Vnode(tagOrComponent, props || {}, children); + } + const vnode = new Vnode("__component__", props || {}, children); + vnode.component = tagOrComponent; + return vnode; +}; +valyrian.fragment = (props, ...children) => { + return children; +}; +valyrian.current = {}; +valyrian.directives = { ...builtInDirectives }; +valyrian.reservedProps = { + key: true, + state: true, + oncreate: true, + onupdate: true, + onremove: true, + shouldupdate: true, + "v-cleanup": true, + "v-once": true, + "v-if": true, + "v-unless": true, + "v-for": true, + "v-show": true, + "v-class": true, + "v-html": true +}; +(isNodeJs ? global : window).v = valyrian; +export { + Vnode, + cleanup, + directive, + isComponent, + isNodeJs, + isVnode, + isVnodeComponent, + mount, + onremove, + trust, + unmount, + update, + updateProperty, + valyrian +}; diff --git a/dist/index.min.js b/dist/index.min.js new file mode 100644 index 0000000..ee26583 --- /dev/null +++ b/dist/index.min.js @@ -0,0 +1 @@ +(()=>{var e=function(e,o,n){this.props=o,this.children=n,this.tag=e};function o(e){return"function"==typeof e||"object"==typeof e&&null!==e&&"view"in e}function n(o){return o instanceof e&&"__component__"===o.tag}var t=Boolean("undefined"!=typeof process&&process.versions&&process.versions.node);function r(e,o=!1){return o?document.createElementNS("http://www.w3.org/2000/svg",e):document.createElement(e)}function i(o){let n=v(o.tagName.toLowerCase(),{},...Array.from(o.childNodes).filter(e=>1===e.nodeType||3===e.nodeType).map(o=>{if(1===o.nodeType)return i(o);let n=new e("#text",{},[]);return n.nodeValue=String(o.nodeValue),n.dom=o,n}));return[].forEach.call(o.attributes,e=>n.props[e.nodeName]=e.nodeValue),n.dom=o,n}var d=e=>{let o=r("div");return o.innerHTML=e.trim(),[].map.call(o.childNodes,e=>i(e))},p=Symbol("Valyrian");function l(e){for(let o=0;o0&&"#text"===n[t-1].tag?(n[t-1].nodeValue+=r,n.splice(t--,1)):(n[t]=new e("#text",{},[]),n[t].nodeValue=String(r))}}(o);let i=o.children,d=n.children,p=d.length,l=i.length;if(0!==l)p&&"key"in i[0].props&&"key"in d[0].props?function(e,o,n,t,i,d){let p=n.reduce((e,o,n)=>(e[o.props.key]=n,e),{}),l=o.reduce((e,o,n)=>(e[o.props.key]=n,e),{});for(let i=0;i{if(e?o:!o){let e=document.createTextNode("");t&&t.dom&&t.dom.parentNode&&("#text"!==t.tag&&u(t),t.dom.parentNode.replaceChild(e,t.dom)),n.tag="#text",n.children=[],n.props={},n.dom=e}}}var y={"v-if":V(!1),"v-unless":V(!0),"v-for":(e,o)=>{o.children=e.map(o.children[0])},"v-show":(e,o)=>{o.dom.style.display=e?"":"none"},"v-class":(e,o)=>{for(let n in e)o.dom.classList.toggle(n,e[n])},"v-html":(e,o)=>{o.children=[d(e)]},"v-model":([e,o,n],t,r)=>{let i,d;if("input"===t.name)switch(n=n||"oninput",t.props.type){case"checkbox":Array.isArray(e[o])?(d=n=>{let t=n.target.value,r=e[o].indexOf(t);-1===r?e[o].push(t):e[o].splice(r,1)},i=-1!==e[o].indexOf(t.dom.value)):"value"in t.props?(d=()=>{e[o]===t.props.value?e[o]=null:e[o]=t.props.value},i=e[o]===t.props.value):(d=()=>e[o]=!e[o],i=e[o]),f("checked",i,t,r);break;case"radio":f("checked",e[o]===t.dom.value,t,r);break;default:f("value",e[o],t,r)}else"select"===t.name?(n=n||"onclick",t.props.multiple?(d=n=>{let t=n.target.value;if(n.ctrlKey){let n=e[o].indexOf(t);-1===n?e[o].push(t):e[o].splice(n,1)}else e[o].splice(0,e[o].length),e[o].push(t)},t.children.forEach(n=>{if("option"===n.name){let t="value"in n.props?n.props.value:n.children.join("").trim();n.props.selected=-1!==e[o].indexOf(t)}})):t.children.forEach(n=>{if("option"===n.name){let t="value"in n.props?n.props.value:n.children.join("").trim();n.props.selected=t===e[o]}})):"textarea"===t.name&&(n=n||"oninput",t.children=[e[o]]);t.props[n]||(d||(d=n=>e[o]=n.target.value),f(n,d,t,r))}},w=function(o,n,...t){if("string"==typeof o)return new e(o,n||{},t);const r=new e("__component__",n||{},t);return r.component=o,r};w.fragment=(e,...o)=>o,w.current={},w.directives={...y},w.reservedProps={key:!0,state:!0,oncreate:!0,onupdate:!0,onremove:!0,shouldupdate:!0,"v-cleanup":!0,"v-once":!0,"v-if":!0,"v-unless":!0,"v-for":!0,"v-show":!0,"v-class":!0,"v-html":!0},(t?global:window).v=w;var x={Vnode:e,cleanup:function(e){-1===v.current.app?.cleanup.indexOf(e)&&v.current.app?.cleanup.push(e)},directive:function(e,o){let n=`v-${e}`;v.directives[n]=o,v.reservedProps[n]=!0},isComponent:o,isNodeJs:t,isVnode:function(o){return o instanceof e},isVnodeComponent:n,mount:function(e,d){let l,c=null;if(c=t?"string"==typeof e?r("svg"===e?"svg":"div","svg"===e):e:"string"==typeof e?document.querySelectorAll(e)[0]:e,!c)throw new Error("Container not found");if(n(d))l=d;else{if(!o(d))throw new Error("Component must be a Valyrian Component or a Vnode component");l=v(d,{})}if(d[p])a(d);else{let e=function(e){let o=e.target,n=`v-on${e.type}`;for(;o;){if(o[n])return o[n](e,o),void(e.defaultPrevented||s(d));o=o.parentNode}};d[p]={isMounted:!1,eventListenerNames:{},isNodeJs:t,cleanup:[]},d[p].eventListener=e}return d[p].component=l,d[p].container=c,d[p].mainVnode=i(c),s(d)},onremove:u,trust:d,unmount:a,update:s,updateProperty:f,valyrian:w};"undefined"!=typeof module?module.exports=x:self.Valyrian=x})(); \ No newline at end of file diff --git a/dist/index.min.js.map b/dist/index.min.js.map new file mode 100644 index 0000000..fdec8d8 --- /dev/null +++ b/dist/index.min.js.map @@ -0,0 +1 @@ +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL2xpYi9pbmRleC50cyJdLCJuYW1lcyI6WyJWbm9kZSIsInRhZyIsInByb3BzIiwiY2hpbGRyZW4iLCJ0aGlzIiwiaXNDb21wb25lbnQiLCJjb21wb25lbnQiLCJpc1Zub2RlQ29tcG9uZW50Iiwidm5vZGUiLCJpc05vZGVKcyIsIkJvb2xlYW4iLCJwcm9jZXNzIiwidmVyc2lvbnMiLCJub2RlIiwiY3JlYXRlRG9tRWxlbWVudCIsImlzU1ZHIiwiZG9jdW1lbnQiLCJjcmVhdGVFbGVtZW50TlMiLCJjcmVhdGVFbGVtZW50IiwiZG9tVG9Wbm9kZSIsImRvbSIsInYiLCJ0YWdOYW1lIiwidG9Mb3dlckNhc2UiLCJBcnJheSIsImZyb20iLCJjaGlsZE5vZGVzIiwiZmlsdGVyIiwiY2hpbGQiLCJub2RlVHlwZSIsIm1hcCIsInRleHQiLCJub2RlVmFsdWUiLCJTdHJpbmciLCJmb3JFYWNoIiwiY2FsbCIsImF0dHJpYnV0ZXMiLCJwcm9wIiwibm9kZU5hbWUiLCJ0cnVzdCIsImh0bWxTdHJpbmciLCJkaXYiLCJpbm5lckhUTUwiLCJ0cmltIiwiaXRlbSIsIlZhbHlyaWFuU3ltYm9sIiwiU3ltYm9sIiwiY2xlYW51cFZub2RlcyIsInZhbHlyaWFuQXBwIiwiaSIsImNsZWFudXAiLCJsZW5ndGgiLCJ1cGRhdGUiLCJjdXJyZW50IiwiYXBwIiwib2xkVm5vZGUiLCJtYWluVm5vZGUiLCJwYXRjaCIsImlzTW91bnRlZCIsInVubW91bnQiLCJlbXB0eVZub2RlIiwib25yZW1vdmUiLCJzaGFyZWRVcGRhdGVQcm9wZXJ0eSIsInZhbHVlIiwicmVzZXJ2ZWRQcm9wcyIsImRpcmVjdGl2ZXMiLCJldmVudExpc3RlbmVyTmFtZXMiLCJjb250YWluZXIiLCJhZGRFdmVudExpc3RlbmVyIiwic2xpY2UiLCJldmVudExpc3RlbmVyIiwicmVtb3ZlQXR0cmlidXRlIiwic2V0QXR0cmlidXRlIiwidXBkYXRlUHJvcGVydHkiLCJuYW1lIiwidXBkYXRlUHJvcGVydGllcyIsIm5ld1Zub2RlIiwibmV3VHJlZSIsImNoaWxkVm5vZGUiLCJyZXN1bHQiLCJ2aWV3Iiwic3BsaWNlIiwiaXNBcnJheSIsImZsYXRUcmVlIiwib2xkVHJlZSIsIm9sZFRyZWVMZW5ndGgiLCJuZXdUcmVlTGVuZ3RoIiwib2xkS2V5ZWRMaXN0IiwicmVkdWNlIiwiYWNjIiwia2V5IiwibmV3S2V5ZWRMaXN0Iiwib2xkQ2hpbGRWbm9kZSIsInNob3VsZFBhdGNoIiwic2hvdWxkdXBkYXRlIiwib251cGRhdGUiLCJvbmNyZWF0ZSIsImFwcGVuZENoaWxkIiwicmVwbGFjZUNoaWxkIiwicGFyZW50Tm9kZSIsInJlbW92ZUNoaWxkIiwicGF0Y2hLZXllZFRyZWUiLCJuZXdDaGlsZFZub2RlIiwiY3JlYXRlVGV4dE5vZGUiLCJwYXRjaE5vcm1hbFRyZWUiLCJ0ZXh0Q29udGVudCIsImhpZGVEaXJlY3RpdmUiLCJ0ZXN0IiwiYm9vbCIsIm5ld2RvbSIsImJ1aWx0SW5EaXJlY3RpdmVzIiwic2V0Iiwic3R5bGUiLCJkaXNwbGF5IiwiY2xhc3NlcyIsImNsYXNzTGlzdCIsInRvZ2dsZSIsImh0bWwiLCJtb2RlbCIsInByb3BlcnR5IiwiZXZlbnQiLCJoYW5kbGVyIiwidHlwZSIsImUiLCJ2YWwiLCJ0YXJnZXQiLCJpZHgiLCJpbmRleE9mIiwicHVzaCIsIm11bHRpcGxlIiwiY3RybEtleSIsInZhbHVlMiIsImpvaW4iLCJzZWxlY3RlZCIsInZhbHlyaWFuIiwidGFnT3JDb21wb25lbnQiLCJmcmFnbWVudCIsInN0YXRlIiwiZ2xvYmFsIiwid2luZG93IiwiY2FsbGJhY2siLCJkaXJlY3RpdmUyIiwiZnVsbE5hbWUiLCJ2bm9kZUNvbXBvbmVudCIsImFwcENvbnRhaW5lciIsInF1ZXJ5U2VsZWN0b3JBbGwiLCJFcnJvciIsImRlZmF1bHRQcmV2ZW50ZWQiXSwibWFwcGluZ3MiOiJNQXNHTyxJQUFNQSxFQUFRLFNBQTZCQyxFQUFhQyxFQUFjQyxHQUMzRUMsS0FBS0YsTUFBUUEsRUFDYkUsS0FBS0QsU0FBV0EsRUFDaEJD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RUFBZ0M3RCxHQUNwRCxJQVlJeUksRUFaQUMsRUFBZSxLQVFuQixHQUxFQSxFQURFdkksRUFDa0MsaUJBQWQwRCxFQUF5QnJELEVBQStCLFFBQWRxRCxFQUFzQixNQUFRLE1BQXFCLFFBQWRBLEdBQXVCQSxFQUV4RixpQkFBZEEsRUFBeUJuRCxTQUFTaUksaUJBQWlCOUUsR0FBVyxHQUFLQSxHQUd0RjZFLEVBQ0gsTUFBTSxJQUFJRSxNQUFNLHVCQUtsQixHQUFJM0ksRUFBaUJELEdBQ25CeUksRUFBaUJ6SSxNQUFBLENBQUEsSUFDUkQsRUFBWUMsR0FHckIsTUFBTSxJQUFJNEksTUFBTSwrREFGaEJILEVBQWlCMUgsRUFBRWYsRUFBVyxJQUtoQyxHQUFJQSxFQUFVdUMsR0FDWmMsRUFBUXJELE9BQ0gsQ0FPTCxJQUFTZ0UsRUFBVCxTQUF1QnFELEdBQ3JCLElBQUl2RyxFQUFNdUcsRUFBRUUsT0FDUm5ELEVBQU8sT0FBT2lELEVBQUVELE9BQ3BCLEtBQU90RyxHQUFLLENBQ1YsR0FBSUEsRUFBSXNELEdBS04sT0FKQXRELEVBQUlzRCxHQUFNaUQsRUFBR3ZHLFFBQ1J1RyxFQUFFd0Isa0JBQ0wvRixFQUFPOUMsSUFJWGMsRUFBTUEsRUFBSStFLGFBakJkN0YsRUFBVXVDLEdBQWtCLENBQzFCYSxXQUFXLEVBQ1hRLG1CQUFvQixHQUNwQnpELFNBQUFBLEVBQ0F5QyxRQUFTLElBZ0JYNUMsRUFBVXVDLEdBQWdCeUIsY0FBZ0JBLEVBUTVDLE9BTEFoRSxFQUFVdUMsR0FBZ0J2QyxVQUFZeUksRUFDdEN6SSxFQUFVdUMsR0FBZ0JzQixVQUFZNkUsRUFDdEMxSSxFQUFVdUMsR0FBZ0JXLFVBQVlyQyxFQUFXNkgsR0FHMUM1RixFQUFPOUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKioqIEludGVyZmFjZXMgKioqL1xuXG5leHBvcnQgaW50ZXJmYWNlIERvbUVsZW1lbnQgZXh0ZW5kcyBFbGVtZW50IHtcbiAgW2tleTogc3RyaW5nXTogYW55O1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIFByb3BzIHtcbiAga2V5Pzogc3RyaW5nIHwgbnVtYmVyO1xuICBkYXRhPzogc3RyaW5nO1xuICBvbmNyZWF0ZT86IHsgKHZub2RlOiBJVm5vZGUpOiBuZXZlciB9O1xuICBvbnVwZGF0ZT86IHsgKHZub2RlOiBJVm5vZGUsIG9sZFZub2RlOiBJVm5vZGUpOiBuZXZlciB9O1xuICBvbnJlbW92ZT86IHsgKG9sZFZub2RlOiBJVm5vZGUpOiBuZXZlciB9O1xuICBzaG91bGR1cGRhdGU/OiB7ICh2bm9kZTogSVZub2RlLCBvbGRWbm9kZTogSVZub2RlKTogdW5kZWZpbmVkIHwgYm9vbGVhbiB9O1xuICBcInYtY2xlYW51cFwiPzogRnVuY3Rpb247XG4gIFtrZXk6IHN0cmluZyB8IG51bWJlciB8IHN5bWJvbF06IGFueTtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBDaGlsZHJlbiBleHRlbmRzIEFycmF5PElWbm9kZSB8IGFueT4ge31cblxuZXhwb3J0IGludGVyZmFjZSBJVm5vZGUge1xuICBuZXcgKHRhZzogc3RyaW5nLCBwcm9wczogUHJvcHMsIGNoaWxkcmVuOiBJVm5vZGVbXSk6IElWbm9kZTtcbiAgdGFnOiBzdHJpbmc7XG4gIHByb3BzOiBQcm9wcztcbiAgY2hpbGRyZW46IENoaWxkcmVuO1xuICBkb20/OiBEb21FbGVtZW50O1xuICBpc1NWRz86IGJvb2xlYW47XG4gIHByb2Nlc3NlZD86IGJvb2xlYW47XG4gIGNvbXBvbmVudD86IENvbXBvbmVudCB8IFBPSk9Db21wb25lbnQ7XG4gIG5vZGVWYWx1ZT86IHN0cmluZztcbiAgW2tleTogc3RyaW5nIHwgbnVtYmVyIHwgc3ltYm9sXTogYW55O1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIENvbXBvbmVudCB7XG4gIChwcm9wcz86IFJlY29yZDxzdHJpbmcsIGFueT4gfCBudWxsLCBjaGlsZHJlbj86IENoaWxkcmVuKTogSVZub2RlIHwgQ2hpbGRyZW47XG4gIFtrZXk6IHN0cmluZyB8IG51bWJlciB8IHN5bWJvbF06IGFueTtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBQT0pPQ29tcG9uZW50IHtcbiAgdmlldzogQ29tcG9uZW50O1xuICBba2V5OiBzdHJpbmcgfCBudW1iZXIgfCBzeW1ib2xdOiBhbnk7XG59XG5cbmV4cG9ydCB0eXBlIFZhbHlyaWFuQ29tcG9uZW50ID0gQ29tcG9uZW50IHwgUE9KT0NvbXBvbmVudDtcblxuZXhwb3J0IGludGVyZmFjZSBWbm9kZUNvbXBvbmVudCBleHRlbmRzIElWbm9kZSB7XG4gIHRhZzogXCJfX2NvbXBvbmVudF9fXCI7XG4gIGNvbXBvbmVudDogVmFseXJpYW5Db21wb25lbnQ7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgVm5vZGVXaXRoRG9tIGV4dGVuZHMgSVZub2RlIHtcbiAgZG9tOiBEb21FbGVtZW50O1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIERpcmVjdGl2ZSB7XG4gICh2YWx1ZTogYW55LCB2bm9kZTogVm5vZGVXaXRoRG9tLCBvbGRWbm9kZT86IFZub2RlV2l0aERvbSk6IHZvaWQ7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgVmFseXJpYW5BcHAge1xuICBpc01vdW50ZWQ6IGJvb2xlYW47XG4gIGV2ZW50TGlzdGVuZXJOYW1lczogUmVjb3JkPHN0cmluZywgdHJ1ZT47XG4gIGNsZWFudXA6IEZ1bmN0aW9uW107XG5cbiAgZXZlbnRMaXN0ZW5lcj86IEV2ZW50TGlzdGVuZXI7XG4gIG1haW5Wbm9kZT86IFZub2RlV2l0aERvbTtcbiAgY29tcG9uZW50PzogVm5vZGVDb21wb25lbnQ7XG4gIGNvbnRhaW5lcj86IERvbUVsZW1lbnQ7XG5cbiAgW2tleTogc3RyaW5nIHwgbnVtYmVyIHwgc3ltYm9sXTogYW55O1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIE1vdW50ZWRWYWx5cmlhbkFwcCBleHRlbmRzIFZhbHlyaWFuQXBwIHtcbiAgZXZlbnRMaXN0ZW5lcjogRXZlbnRMaXN0ZW5lcjtcbiAgbWFpblZub2RlOiBWbm9kZVdpdGhEb207XG4gIGNvbnRhaW5lcjogRG9tRWxlbWVudDtcbiAgY29tcG9uZW50OiBWbm9kZUNvbXBvbmVudDtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBDdXJyZW50IHtcbiAgYXBwPzogVmFseXJpYW5BcHA7XG4gIGNvbXBvbmVudD86IFZhbHlyaWFuQ29tcG9uZW50O1xuICB2bm9kZT86IFZub2RlV2l0aERvbTtcbiAgb2xkVm5vZGU/OiBWbm9kZVdpdGhEb207XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgRGlyZWN0aXZlcyB7XG4gIFtrZXk6IHN0cmluZ106IERpcmVjdGl2ZTtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBSZXNlcnZlZFByb3BzIHtcbiAgW2tleTogc3RyaW5nXTogdHJ1ZTtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBWYWx5cmlhbiB7XG4gICh0YWdPckNvbXBvbmVudDogc3RyaW5nIHwgVmFseXJpYW5Db21wb25lbnQsIHByb3BzOiBQcm9wcywgLi4uY2hpbGRyZW46IENoaWxkcmVuKTogSVZub2RlIHwgVm5vZGVDb21wb25lbnQ7XG4gIGZyYWdtZW50OiAocHJvcHM6IFByb3BzLCAuLi5jaGlsZHJlbjogQ2hpbGRyZW4pID0+IENoaWxkcmVuO1xuICBjdXJyZW50OiBDdXJyZW50O1xuICBkaXJlY3RpdmVzOiBEaXJlY3RpdmVzO1xuICByZXNlcnZlZFByb3BzOiBSZXNlcnZlZFByb3BzO1xufVxuXG4vKioqIFZub2RlICoqKi9cblxuZXhwb3J0IGNvbnN0IFZub2RlID0gZnVuY3Rpb24gVm5vZGUodGhpczogSVZub2RlLCB0YWc6IHN0cmluZywgcHJvcHM6IFByb3BzLCBjaGlsZHJlbjogQ2hpbGRyZW4pIHtcbiAgdGhpcy5wcm9wcyA9IHByb3BzO1xuICB0aGlzLmNoaWxkcmVuID0gY2hpbGRyZW47XG4gIHRoaXMudGFnID0gdGFnO1xufSBhcyB1bmtub3duIGFzIElWbm9kZTtcblxuZXhwb3J0IGZ1bmN0aW9uIGlzVm5vZGUoY29tcG9uZW50PzogdW5rbm93bik6IGNvbXBvbmVudCBpcyBJVm5vZGUge1xuICByZXR1cm4gY29tcG9uZW50IGluc3RhbmNlb2YgVm5vZGU7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBpc0NvbXBvbmVudChjb21wb25lbnQ/OiB1bmtub3duIHwgVmFseXJpYW5Db21wb25lbnQpOiBjb21wb25lbnQgaXMgVmFseXJpYW5Db21wb25lbnQge1xuICByZXR1cm4gdHlwZW9mIGNvbXBvbmVudCA9PT0gXCJmdW5jdGlvblwiIHx8ICh0eXBlb2YgY29tcG9uZW50ID09PSBcIm9iamVjdFwiICYmIGNvbXBvbmVudCAhPT0gbnVsbCAmJiBcInZpZXdcIiBpbiBjb21wb25lbnQpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gaXNWbm9kZUNvbXBvbmVudCh2bm9kZT86IHVua25vd24pOiB2bm9kZSBpcyBWbm9kZUNvbXBvbmVudCB7XG4gIHJldHVybiB2bm9kZSBpbnN0YW5jZW9mIFZub2RlICYmIHZub2RlLnRhZyA9PT0gXCJfX2NvbXBvbmVudF9fXCI7XG59XG5cbi8qKiogVXRpbCAqKiovXG5cbmV4cG9ydCBjb25zdCBpc05vZGVKcyA9IEJvb2xlYW4odHlwZW9mIHByb2Nlc3MgIT09IFwidW5kZWZpbmVkXCIgJiYgcHJvY2Vzcy52ZXJzaW9ucyAmJiBwcm9jZXNzLnZlcnNpb25zLm5vZGUpO1xuXG5mdW5jdGlvbiBjcmVhdGVEb21FbGVtZW50KHRhZzogc3RyaW5nLCBpc1NWRzogYm9vbGVhbiA9IGZhbHNlKSB7XG4gIHJldHVybiBpc1NWRyA/IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnROUyhcImh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnXCIsIHRhZykgOiBkb2N1bWVudC5jcmVhdGVFbGVtZW50KHRhZyk7XG59XG5cbmZ1bmN0aW9uIGRvbVRvVm5vZGUoZG9tOiBEb21FbGVtZW50KTogVm5vZGVXaXRoRG9tIHtcbiAgbGV0IHZub2RlID0gdihcbiAgICBkb20udGFnTmFtZS50b0xvd2VyQ2FzZSgpLFxuICAgIHt9LFxuICAgIC4uLkFycmF5LmZyb20oZG9tLmNoaWxkTm9kZXMpXG4gICAgICAuZmlsdGVyKChjaGlsZCkgPT4gKGNoaWxkIGFzIERvbUVsZW1lbnQpLm5vZGVUeXBlID09PSAxIHx8IChjaGlsZCBhcyBEb21FbGVtZW50KS5ub2RlVHlwZSA9PT0gMylcbiAgICAgIC5tYXAoKGNoaWxkKSA9PiB7XG4gICAgICAgIGlmICgoY2hpbGQgYXMgRG9tRWxlbWVudCkubm9kZVR5cGUgPT09IDEpIHtcbiAgICAgICAgICByZXR1cm4gZG9tVG9Wbm9kZShjaGlsZCBhcyBEb21FbGVtZW50KTtcbiAgICAgICAgfVxuXG4gICAgICAgIGxldCB0ZXh0ID0gbmV3IFZub2RlKFwiI3RleHRcIiwge30sIFtdKTtcbiAgICAgICAgdGV4dC5ub2RlVmFsdWUgPSBTdHJpbmcoKGNoaWxkIGFzIERvbUVsZW1lbnQpLm5vZGVWYWx1ZSk7XG4gICAgICAgIHRleHQuZG9tID0gY2hpbGQgYXMgRG9tRWxlbWVudDtcbiAgICAgICAgcmV0dXJuIHRleHQ7XG4gICAgICB9KVxuICApO1xuICBbXS5mb3JFYWNoLmNhbGwoZG9tLmF0dHJpYnV0ZXMsIChwcm9wOiBBdHRyKSA9PiAodm5vZGUucHJvcHNbcHJvcC5ub2RlTmFtZV0gPSBwcm9wLm5vZGVWYWx1ZSkpO1xuICB2bm9kZS5kb20gPSBkb207XG4gIHJldHVybiB2bm9kZSBhcyBWbm9kZVdpdGhEb207XG59XG5cbmV4cG9ydCBjb25zdCB0cnVzdCA9IChodG1sU3RyaW5nOiBzdHJpbmcpID0+IHtcbiAgbGV0IGRpdiA9IGNyZWF0ZURvbUVsZW1lbnQoXCJkaXZcIik7XG4gIGRpdi5pbm5lckhUTUwgPSBodG1sU3RyaW5nLnRyaW0oKTtcblxuICByZXR1cm4gW10ubWFwLmNhbGwoZGl2LmNoaWxkTm9kZXMsIChpdGVtKSA9PiBkb21Ub1Zub2RlKGl0ZW0pKSBhcyBJVm5vZGVbXTtcbn07XG5cbi8qKiogTW91bnQgKioqL1xuXG5jb25zdCBWYWx5cmlhblN5bWJvbCA9IFN5bWJvbChcIlZhbHlyaWFuXCIpO1xuXG5leHBvcnQgZnVuY3Rpb24gY2xlYW51cChjYWxsYmFjazogRnVuY3Rpb24pIHtcbiAgaWYgKHYuY3VycmVudC5hcHA/LmNsZWFudXAuaW5kZXhPZihjYWxsYmFjaykgPT09IC0xKSB7XG4gICAgdi5jdXJyZW50LmFwcD8uY2xlYW51cC5wdXNoKGNhbGxiYWNrKTtcbiAgfVxufVxuXG4vKlxuICAqIE1vdW50cyBhIGNvbXBvbmVudCB0byB0aGUgRE9NXG4gIG1vdW50KCcjYXBwJywgKCkgPT4gPGRpdj5IZWxsbyB3b3JsZDwvZGl2Pik7IC8vIEFwcCBpcyBhIEZ1bmN0aW9uYWwgQ29tcG9uZW50XG4gIG1vdW50KCcjYXBwJywgeyB2aWV3OiAoKSA9PiA8ZGl2PkhlbGxvIHdvcmxkPC9kaXY+IH0pOyAvLyBBcHAgaXMgYSBQT0pPIGNvbXBvbmVudCB3aXRoIGEgdmlldyBtZXRob2RcbiAgbW91bnQoJyNhcHAnLCBjbGFzc0luc3RhbmNlKTsgLy8gQXBwIGlzIGEgY2xhc3MgaW5zdGFuY2Ugd2l0aCBhIHZpZXcgbWV0aG9kXG4gIG1vdW50KCcjYXBwJywgPEFwcD48ZGl2PkhlbGxvIHdvcmxkPC9kaXY+PC9BcHA+KTsgLy8gQXBwIGlzIGEgVm5vZGUgY29tcG9uZW50IChWbm9kZSB3aXRoIHRhZyBfX2NvbXBvbmVudF9fKVxuKi9cblxuZXhwb3J0IGZ1bmN0aW9uIG1vdW50KGNvbnRhaW5lcjogRG9tRWxlbWVudCB8IHN0cmluZywgY29tcG9uZW50OiBWYWx5cmlhbkNvbXBvbmVudCB8IElWbm9kZSkge1xuICBsZXQgYXBwQ29udGFpbmVyID0gbnVsbDtcblxuICBpZiAoaXNOb2RlSnMpIHtcbiAgICBhcHBDb250YWluZXIgPSB0eXBlb2YgY29udGFpbmVyID09PSBcInN0cmluZ1wiID8gY3JlYXRlRG9tRWxlbWVudChjb250YWluZXIgPT09IFwic3ZnXCIgPyBcInN2Z1wiIDogXCJkaXZcIiwgY29udGFpbmVyID09PSBcInN2Z1wiKSA6IGNvbnRhaW5lcjtcbiAgfSBlbHNlIHtcbiAgICBhcHBDb250YWluZXIgPSB0eXBlb2YgY29udGFpbmVyID09PSBcInN0cmluZ1wiID8gZG9jdW1lbnQucXVlcnlTZWxlY3RvckFsbChjb250YWluZXIpWzBdIDogY29udGFpbmVyO1xuICB9XG5cbiAgaWYgKCFhcHBDb250YWluZXIpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoXCJDb250YWluZXIgbm90IGZvdW5kXCIpO1xuICB9XG5cbiAgbGV0IHZub2RlQ29tcG9uZW50OiBWbm9kZUNvbXBvbmVudCB8IElWbm9kZTtcblxuICBpZiAoaXNWbm9kZUNvbXBvbmVudChjb21wb25lbnQpKSB7XG4gICAgdm5vZGVDb21wb25lbnQgPSBjb21wb25lbnQ7XG4gIH0gZWxzZSBpZiAoaXNDb21wb25lbnQoY29tcG9uZW50KSkge1xuICAgIHZub2RlQ29tcG9uZW50ID0gdihjb21wb25lbnQsIHt9KTtcbiAgfSBlbHNlIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoXCJDb21wb25lbnQgbXVzdCBiZSBhIFZhbHlyaWFuIENvbXBvbmVudCBvciBhIFZub2RlIGNvbXBvbmVudFwiKTtcbiAgfVxuXG4gIGlmIChjb21wb25lbnRbVmFseXJpYW5TeW1ib2xdKSB7XG4gICAgdW5tb3VudChjb21wb25lbnQpO1xuICB9IGVsc2Uge1xuICAgIGNvbXBvbmVudFtWYWx5cmlhblN5bWJvbF0gPSB7XG4gICAgICBpc01vdW50ZWQ6IGZhbHNlLFxuICAgICAgZXZlbnRMaXN0ZW5lck5hbWVzOiB7fSxcbiAgICAgIGlzTm9kZUpzLFxuICAgICAgY2xlYW51cDogW11cbiAgICB9O1xuICAgIGZ1bmN0aW9uIGV2ZW50TGlzdGVuZXIoZTogRXZlbnQpIHtcbiAgICAgIGxldCBkb20gPSBlLnRhcmdldCBhcyBEb21FbGVtZW50ICYgUmVjb3JkPHN0cmluZywgYW55PjtcbiAgICAgIGxldCBuYW1lID0gYHYtb24ke2UudHlwZX1gO1xuICAgICAgd2hpbGUgKGRvbSkge1xuICAgICAgICBpZiAoZG9tW25hbWVdKSB7XG4gICAgICAgICAgZG9tW25hbWVdKGUsIGRvbSk7XG4gICAgICAgICAgaWYgKCFlLmRlZmF1bHRQcmV2ZW50ZWQpIHtcbiAgICAgICAgICAgIHVwZGF0ZShjb21wb25lbnQpO1xuICAgICAgICAgIH1cbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgZG9tID0gZG9tLnBhcmVudE5vZGUgYXMgRG9tRWxlbWVudDtcbiAgICAgIH1cbiAgICB9XG4gICAgY29tcG9uZW50W1ZhbHlyaWFuU3ltYm9sXS5ldmVudExpc3RlbmVyID0gZXZlbnRMaXN0ZW5lcjtcbiAgfVxuXG4gIGNvbXBvbmVudFtWYWx5cmlhblN5bWJvbF0uY29tcG9uZW50ID0gdm5vZGVDb21wb25lbnQ7XG4gIGNvbXBvbmVudFtWYWx5cmlhblN5bWJvbF0uY29udGFpbmVyID0gYXBwQ29udGFpbmVyO1xuICBjb21wb25lbnRbVmFseXJpYW5TeW1ib2xdLm1haW5Wbm9kZSA9IGRvbVRvVm5vZGUoYXBwQ29udGFpbmVyKTtcblxuICAvLyB1cGRhdGVcbiAgcmV0dXJuIHVwZGF0ZShjb21wb25lbnQpO1xufVxuXG5mdW5jdGlvbiBjbGVhbnVwVm5vZGVzKHZhbHlyaWFuQXBwOiBWYWx5cmlhbkFwcCkge1xuICBmb3IgKGxldCBpID0gMDsgaSA8IHZhbHlyaWFuQXBwLmNsZWFudXAubGVuZ3RoOyBpKyspIHtcbiAgICB2YWx5cmlhbkFwcC5jbGVhbnVwW2ldKCk7XG4gIH1cbiAgdmFseXJpYW5BcHAuY2xlYW51cCA9IFtdO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gdXBkYXRlKGNvbXBvbmVudD86IFZhbHlyaWFuQ29tcG9uZW50IHwgSVZub2RlKSB7XG4gIGlmIChjb21wb25lbnQgJiYgY29tcG9uZW50W1ZhbHlyaWFuU3ltYm9sXSkge1xuICAgIGxldCB2YWx5cmlhbkFwcCA9IGNvbXBvbmVudFtWYWx5cmlhblN5bWJvbF07XG4gICAgdi5jdXJyZW50LmFwcCA9IHZhbHlyaWFuQXBwO1xuICAgIGNsZWFudXBWbm9kZXModmFseXJpYW5BcHApO1xuICAgIGxldCBvbGRWbm9kZTogVm5vZGVXaXRoRG9tIHwgbnVsbCA9IHZhbHlyaWFuQXBwLm1haW5Wbm9kZSBhcyBWbm9kZVdpdGhEb207XG4gICAgdmFseXJpYW5BcHAubWFpblZub2RlID0gbmV3IFZub2RlKHZhbHlyaWFuQXBwLm1haW5Wbm9kZS50YWcsIHZhbHlyaWFuQXBwLm1haW5Wbm9kZS5wcm9wcywgW3ZhbHlyaWFuQXBwLmNvbXBvbmVudF0pIGFzIFZub2RlV2l0aERvbTtcbiAgICB2YWx5cmlhbkFwcC5tYWluVm5vZGUuZG9tID0gb2xkVm5vZGUuZG9tO1xuICAgIHZhbHlyaWFuQXBwLm1haW5Wbm9kZS5pc1NWRyA9IG9sZFZub2RlLmlzU1ZHO1xuICAgIHBhdGNoKHZhbHlyaWFuQXBwLm1haW5Wbm9kZSwgb2xkVm5vZGUsIHZhbHlyaWFuQXBwKTtcbiAgICBvbGRWbm9kZSA9IG51bGw7XG4gICAgdmFseXJpYW5BcHAuaXNNb3VudGVkID0gdHJ1ZTtcblxuICAgIGlmIChpc05vZGVKcykge1xuICAgICAgcmV0dXJuIHZhbHlyaWFuQXBwLm1haW5Wbm9kZS5kb20uaW5uZXJIVE1MO1xuICAgIH1cbiAgfVxufVxuXG5leHBvcnQgZnVuY3Rpb24gdW5tb3VudChjb21wb25lbnQ/OiBWYWx5cmlhbkNvbXBvbmVudCB8IElWbm9kZSkge1xuICBpZiAoIWNvbXBvbmVudCB8fCAhY29tcG9uZW50W1ZhbHlyaWFuU3ltYm9sXSkge1xuICAgIHJldHVybjtcbiAgfVxuXG4gIGxldCB2YWx5cmlhbkFwcCA9IGNvbXBvbmVudFtWYWx5cmlhblN5bWJvbF0gYXMgTW91bnRlZFZhbHlyaWFuQXBwO1xuXG4gIGlmICh2YWx5cmlhbkFwcC5pc01vdW50ZWQpIHtcbiAgICBjbGVhbnVwVm5vZGVzKHZhbHlyaWFuQXBwKTtcbiAgICBsZXQgb2xkVm5vZGU6IFZub2RlV2l0aERvbSB8IG51bGwgPSB2YWx5cmlhbkFwcC5tYWluVm5vZGUgYXMgVm5vZGVXaXRoRG9tO1xuICAgIHZhbHlyaWFuQXBwLm1haW5Wbm9kZSA9IG5ldyBWbm9kZSh2YWx5cmlhbkFwcC5tYWluVm5vZGUudGFnLCB2YWx5cmlhbkFwcC5tYWluVm5vZGUucHJvcHMsIFtdKSBhcyBWbm9kZVdpdGhEb207XG4gICAgdmFseXJpYW5BcHAubWFpblZub2RlLmRvbSA9IG9sZFZub2RlLmRvbTtcbiAgICB2YWx5cmlhbkFwcC5tYWluVm5vZGUuaXNTVkcgPSBvbGRWbm9kZS5pc1NWRztcbiAgICBwYXRjaCh2YWx5cmlhbkFwcC5tYWluVm5vZGUsIG9sZFZub2RlLCB2YWx5cmlhbkFwcCk7XG4gICAgb2xkVm5vZGUgPSBudWxsO1xuICAgIHZhbHlyaWFuQXBwLmlzTW91bnRlZCA9IGZhbHNlO1xuICAgIGlmIChpc05vZGVKcykge1xuICAgICAgcmV0dXJuIHZhbHlyaWFuQXBwLm1haW5Wbm9kZS5kb20uaW5uZXJIVE1MO1xuICAgIH1cbiAgfVxufVxuXG5sZXQgZW1wdHlWbm9kZSA9IG5ldyBWbm9kZShcIl9fZW1wdHlfX1wiLCB7fSwgW10pO1xuXG5leHBvcnQgZnVuY3Rpb24gb25yZW1vdmUodm5vZGU6IElWbm9kZSkge1xuICBmb3IgKGxldCBpID0gMDsgaSA8IHZub2RlLmNoaWxkcmVuLmxlbmd0aDsgaSsrKSB7XG4gICAgdm5vZGUuY2hpbGRyZW5baV0udGFnICE9PSBcIiN0ZXh0XCIgJiYgb25yZW1vdmUodm5vZGUuY2hpbGRyZW5baV0pO1xuICB9XG5cbiAgdm5vZGUucHJvcHMub25yZW1vdmUgJiYgdm5vZGUucHJvcHMub25yZW1vdmUodm5vZGUpO1xufVxuXG5mdW5jdGlvbiBzaGFyZWRVcGRhdGVQcm9wZXJ0eShwcm9wOiBzdHJpbmcsIHZhbHVlOiBhbnksIHZub2RlOiBWbm9kZVdpdGhEb20sIG9sZFZub2RlPzogVm5vZGVXaXRoRG9tKSB7XG4gIC8vIEl0IGlzIGEgcmVzZXJ2ZWQgcHJvcFxuICBpZiAodi5yZXNlcnZlZFByb3BzW3Byb3BdKSB7XG4gICAgLy8gSWYgaXQgaXMgYSBkaXJlY3RpdmUgbmFtZSBjYWxsIHRoZSBkaXJlY3RpdmVcbiAgICBpZiAodi5kaXJlY3RpdmVzW3Byb3BdKSB7XG4gICAgICB2LmRpcmVjdGl2ZXNbcHJvcF0odm5vZGUucHJvcHNbcHJvcF0sIHZub2RlLCBvbGRWbm9kZSk7XG4gICAgfVxuICAgIHJldHVybjtcbiAgfVxuXG4gIC8vIEl0IGlzIG5vdCBhIHJlc2VydmVkIHByb3Agc28gd2UgYWRkIGl0IHRvIHRoZSBkb21cbiAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gXCJmdW5jdGlvblwiKSB7XG4gICAgbGV0IHZhbHlyaWFuQXBwID0gdi5jdXJyZW50LmFwcCBhcyBNb3VudGVkVmFseXJpYW5BcHA7XG4gICAgaWYgKHByb3AgaW4gdmFseXJpYW5BcHAuZXZlbnRMaXN0ZW5lck5hbWVzID09PSBmYWxzZSkge1xuICAgICAgdmFseXJpYW5BcHAuZXZlbnRMaXN0ZW5lck5hbWVzW3Byb3BdID0gdHJ1ZTtcbiAgICAgIHZhbHlyaWFuQXBwLmNvbnRhaW5lci5hZGRFdmVudExpc3RlbmVyKHByb3Auc2xpY2UoMiksIHZhbHlyaWFuQXBwLmV2ZW50TGlzdGVuZXIpO1xuICAgIH1cbiAgICB2bm9kZS5kb21bYHYtJHtwcm9wfWBdID0gdmFsdWU7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgaWYgKHByb3AgaW4gdm5vZGUuZG9tICYmIHZub2RlLmlzU1ZHID09PSBmYWxzZSkge1xuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBlcWVxZXFcbiAgICBpZiAodm5vZGUuZG9tW3Byb3BdICE9IHZhbHVlKSB7XG4gICAgICB2bm9kZS5kb21bcHJvcF0gPSB2YWx1ZTtcbiAgICB9XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgLy8gVXNlIHNldCBhdHRyaWJ1dGVcbiAgaWYgKCFvbGRWbm9kZSB8fCBvbGRWbm9kZS5wcm9wc1twcm9wXSAhPT0gdmFsdWUpIHtcbiAgICBpZiAodmFsdWUgPT09IGZhbHNlKSB7XG4gICAgICB2bm9kZS5kb20ucmVtb3ZlQXR0cmlidXRlKHByb3ApO1xuICAgIH0gZWxzZSB7XG4gICAgICB2bm9kZS5kb20uc2V0QXR0cmlidXRlKHByb3AsIHZhbHVlKTtcbiAgICB9XG4gIH1cbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHVwZGF0ZVByb3BlcnR5KG5hbWU6IHN0cmluZywgdmFsdWU6IGFueSwgdm5vZGU6IFZub2RlV2l0aERvbSwgb2xkVm5vZGU/OiBWbm9kZVdpdGhEb20pIHtcbiAgaWYgKG5hbWUgaW4gdm5vZGUucHJvcHMgPT09IGZhbHNlKSB7XG4gICAgdm5vZGUucHJvcHNbbmFtZV0gPSB2YWx1ZTtcbiAgfVxuXG4gIHNoYXJlZFVwZGF0ZVByb3BlcnR5KG5hbWUsIHZhbHVlLCB2bm9kZSwgb2xkVm5vZGUpO1xufVxuXG5mdW5jdGlvbiB1cGRhdGVQcm9wZXJ0aWVzKHZub2RlOiBWbm9kZVdpdGhEb20sIG9sZFZub2RlPzogVm5vZGVXaXRoRG9tKSB7XG4gIGZvciAobGV0IHByb3AgaW4gdm5vZGUucHJvcHMpIHtcbiAgICAvLyBXZSBhc3VtZSB0aGF0IHdlIGNsZWFuIHRoZSBwcm9wcyBpbiBzb21lIGRpcmVjdGl2ZVxuICAgIGlmIChwcm9wIGluIHZub2RlLnByb3BzID09PSBmYWxzZSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHNoYXJlZFVwZGF0ZVByb3BlcnR5KHByb3AsIHZub2RlLnByb3BzW3Byb3BdLCB2bm9kZSwgb2xkVm5vZGUpO1xuICB9XG5cbiAgaWYgKG9sZFZub2RlKSB7XG4gICAgZm9yIChsZXQgcHJvcCBpbiBvbGRWbm9kZS5wcm9wcykge1xuICAgICAgaWYgKHByb3AgaW4gdm5vZGUucHJvcHMgPT09IGZhbHNlICYmIHR5cGVvZiBvbGRWbm9kZS5wcm9wc1twcm9wXSAhPT0gXCJmdW5jdGlvblwiICYmIHByb3AgaW4gdi5yZXNlcnZlZFByb3BzID09PSBmYWxzZSkge1xuICAgICAgICBpZiAocHJvcCBpbiBvbGRWbm9kZS5kb20gJiYgdm5vZGUuaXNTVkcgPT09IGZhbHNlKSB7XG4gICAgICAgICAgb2xkVm5vZGUuZG9tW3Byb3BdID0gbnVsbDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBvbGRWbm9kZS5kb20ucmVtb3ZlQXR0cmlidXRlKHByb3ApO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICB9XG59XG5cbmZ1bmN0aW9uIGZsYXRUcmVlKG5ld1Zub2RlOiBJVm5vZGUpOiB2b2lkIHtcbiAgbGV0IG5ld1RyZWUgPSBuZXdWbm9kZS5jaGlsZHJlbjtcbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBuZXdUcmVlLmxlbmd0aDsgaSsrKSB7XG4gICAgbGV0IGNoaWxkVm5vZGUgPSBuZXdUcmVlW2ldO1xuICAgIGlmIChjaGlsZFZub2RlIGluc3RhbmNlb2YgVm5vZGUpIHtcbiAgICAgIGlmIChjaGlsZFZub2RlLnRhZyAhPT0gXCIjdGV4dFwiKSB7XG4gICAgICAgIGlmIChjaGlsZFZub2RlLnRhZyA9PT0gXCJfX2NvbXBvbmVudF9fXCIpIHtcbiAgICAgICAgICBsZXQgY29tcG9uZW50ID0gY2hpbGRWbm9kZS5jb21wb25lbnQgYXMgVmFseXJpYW5Db21wb25lbnQ7XG4gICAgICAgICAgdi5jdXJyZW50LmNvbXBvbmVudCA9IGNvbXBvbmVudDtcbiAgICAgICAgICBsZXQgcmVzdWx0ID0gKFwidmlld1wiIGluIGNvbXBvbmVudCA/IGNvbXBvbmVudC52aWV3IDogY29tcG9uZW50KS5jYWxsKGNvbXBvbmVudCwgY2hpbGRWbm9kZS5wcm9wcywgLi4uY2hpbGRWbm9kZS5jaGlsZHJlbik7XG5cbiAgICAgICAgICBuZXdUcmVlLnNwbGljZShpLS0sIDEsIHJlc3VsdCk7XG4gICAgICAgICAgY29udGludWU7XG4gICAgICAgIH1cbiAgICAgICAgY2hpbGRWbm9kZS5pc1NWRyA9IG5ld1Zub2RlLmlzU1ZHIHx8IGNoaWxkVm5vZGUudGFnID09PSBcInN2Z1wiO1xuICAgICAgfVxuICAgIH0gZWxzZSBpZiAoY2hpbGRWbm9kZSA9PT0gbnVsbCB8fCBjaGlsZFZub2RlID09PSB1bmRlZmluZWQpIHtcbiAgICAgIG5ld1RyZWUuc3BsaWNlKGktLSwgMSk7XG4gICAgfSBlbHNlIGlmIChBcnJheS5pc0FycmF5KGNoaWxkVm5vZGUpKSB7XG4gICAgICBuZXdUcmVlLnNwbGljZShpLS0sIDEsIC4uLmNoaWxkVm5vZGUpO1xuICAgIH0gZWxzZSB7XG4gICAgICBpZiAoaSA+IDAgJiYgbmV3VHJlZVtpIC0gMV0udGFnID09PSBcIiN0ZXh0XCIpIHtcbiAgICAgICAgbmV3VHJlZVtpIC0gMV0ubm9kZVZhbHVlICs9IGNoaWxkVm5vZGU7XG4gICAgICAgIG5ld1RyZWUuc3BsaWNlKGktLSwgMSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBuZXdUcmVlW2ldID0gbmV3IFZub2RlKFwiI3RleHRcIiwge30sIFtdKTtcbiAgICAgICAgbmV3VHJlZVtpXS5ub2RlVmFsdWUgPSBTdHJpbmcoY2hpbGRWbm9kZSk7XG4gICAgICB9XG4gICAgfVxuICB9XG59XG5cbmZ1bmN0aW9uIHBhdGNoS2V5ZWRUcmVlKFxuICBuZXdWbm9kZTogVm5vZGVXaXRoRG9tLFxuICBuZXdUcmVlOiAoVm5vZGVXaXRoRG9tICYgeyBwcm9wczogUHJvcHMgJiB7IGtleTogc3RyaW5nIH0gfSlbXSxcbiAgb2xkVHJlZTogKFZub2RlV2l0aERvbSAmIHsgcHJvcHM6IFByb3BzICYgeyBrZXk6IHN0cmluZyB9IH0pW10sXG4gIG5ld1RyZWVMZW5ndGg6IG51bWJlcixcbiAgb2xkVHJlZUxlbmd0aDogbnVtYmVyLFxuICB2YWx5cmlhbkFwcDogTW91bnRlZFZhbHlyaWFuQXBwXG4pIHtcbiAgbGV0IG9sZEtleWVkTGlzdCA9IG9sZFRyZWUucmVkdWNlKChhY2MsIHZub2RlLCBpKSA9PiB7XG4gICAgYWNjW3Zub2RlLnByb3BzLmtleV0gPSBpO1xuICAgIHJldHVybiBhY2M7XG4gIH0sIHt9IGFzIHsgW2tleTogc3RyaW5nXTogbnVtYmVyIH0pO1xuICBsZXQgbmV3S2V5ZWRMaXN0ID0gbmV3VHJlZS5yZWR1Y2UoKGFjYywgdm5vZGUsIGkpID0+IHtcbiAgICBhY2Nbdm5vZGUucHJvcHMua2V5XSA9IGk7XG4gICAgcmV0dXJuIGFjYztcbiAgfSwge30gYXMgeyBba2V5OiBzdHJpbmddOiBudW1iZXIgfSk7XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBuZXdUcmVlTGVuZ3RoOyBpKyspIHtcbiAgICBsZXQgY2hpbGRWbm9kZSA9IG5ld1RyZWVbaV07XG4gICAgbGV0IG9sZENoaWxkVm5vZGUgPSBvbGRUcmVlW29sZEtleWVkTGlzdFtjaGlsZFZub2RlLnByb3BzLmtleV1dO1xuICAgIGxldCBzaG91bGRQYXRjaCA9IHRydWU7XG5cbiAgICBpZiAob2xkQ2hpbGRWbm9kZSkge1xuICAgICAgY2hpbGRWbm9kZS5kb20gPSBvbGRDaGlsZFZub2RlLmRvbTtcbiAgICAgIGlmIChcInYtb25jZVwiIGluIGNoaWxkVm5vZGUucHJvcHMgfHwgKGNoaWxkVm5vZGUucHJvcHMuc2hvdWxkdXBkYXRlICYmIGNoaWxkVm5vZGUucHJvcHMuc2hvdWxkdXBkYXRlKGNoaWxkVm5vZGUsIG9sZENoaWxkVm5vZGUpID09PSBmYWxzZSkpIHtcbiAgICAgICAgLy8gc2tpcCB0aGlzIHBhdGNoXG4gICAgICAgIGNoaWxkVm5vZGUuY2hpbGRyZW4gPSBvbGRDaGlsZFZub2RlLmNoaWxkcmVuO1xuICAgICAgICBzaG91bGRQYXRjaCA9IGZhbHNlO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdXBkYXRlUHJvcGVydGllcyhjaGlsZFZub2RlLCBvbGRDaGlsZFZub2RlKTtcbiAgICAgICAgaWYgKHZhbHlyaWFuQXBwLmlzTW91bnRlZCkge1xuICAgICAgICAgIGNoaWxkVm5vZGUucHJvcHMub251cGRhdGUgJiYgY2hpbGRWbm9kZS5wcm9wcy5vbnVwZGF0ZShjaGlsZFZub2RlLCBvbGRDaGlsZFZub2RlKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBjaGlsZFZub2RlLnByb3BzLm9uY3JlYXRlICYmIGNoaWxkVm5vZGUucHJvcHMub25jcmVhdGUoY2hpbGRWbm9kZSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgY2hpbGRWbm9kZS5kb20gPSBjcmVhdGVEb21FbGVtZW50KGNoaWxkVm5vZGUudGFnLCBjaGlsZFZub2RlLmlzU1ZHKTtcbiAgICAgIHVwZGF0ZVByb3BlcnRpZXMoY2hpbGRWbm9kZSk7XG4gICAgICBjaGlsZFZub2RlLnByb3BzLm9uY3JlYXRlICYmIGNoaWxkVm5vZGUucHJvcHMub25jcmVhdGUoY2hpbGRWbm9kZSk7XG4gICAgfVxuXG4gICAgaWYgKG5ld1Zub2RlLmRvbS5jaGlsZE5vZGVzW2ldID09PSB1bmRlZmluZWQpIHtcbiAgICAgIG5ld1Zub2RlLmRvbS5hcHBlbmRDaGlsZChjaGlsZFZub2RlLmRvbSk7XG4gICAgfSBlbHNlIGlmIChuZXdWbm9kZS5kb20uY2hpbGROb2Rlc1tpXSAhPT0gY2hpbGRWbm9kZS5kb20pIHtcbiAgICAgIG9sZFRyZWVbaV0gJiYgbmV3S2V5ZWRMaXN0W29sZFRyZWVbaV0ucHJvcHMua2V5XSA9PT0gdW5kZWZpbmVkICYmIG9ucmVtb3ZlKG9sZFRyZWVbaV0pO1xuICAgICAgbmV3Vm5vZGUuZG9tLnJlcGxhY2VDaGlsZChjaGlsZFZub2RlLmRvbSwgbmV3Vm5vZGUuZG9tLmNoaWxkTm9kZXNbaV0pO1xuICAgIH1cblxuICAgIHNob3VsZFBhdGNoICYmIHBhdGNoKGNoaWxkVm5vZGUsIG9sZENoaWxkVm5vZGUsIHZhbHlyaWFuQXBwKTtcbiAgfVxuXG4gIC8vIEZvciB0aGUgcmVzdCBvZiB0aGUgY2hpbGRyZW4sIHdlIHNob3VsZCByZW1vdmUgdGhlbVxuICBmb3IgKGxldCBpID0gbmV3VHJlZUxlbmd0aDsgaSA8IG9sZFRyZWVMZW5ndGg7IGkrKykge1xuICAgIGlmIChuZXdLZXllZExpc3Rbb2xkVHJlZVtpXS5wcm9wcy5rZXldID09PSB1bmRlZmluZWQpIHtcbiAgICAgIGxldCBvbGRDaGlsZFZub2RlID0gb2xkVHJlZVtpXTtcbiAgICAgIG9ucmVtb3ZlKG9sZENoaWxkVm5vZGUpO1xuICAgICAgb2xkQ2hpbGRWbm9kZS5kb20ucGFyZW50Tm9kZSAmJiBvbGRDaGlsZFZub2RlLmRvbS5wYXJlbnROb2RlLnJlbW92ZUNoaWxkKG9sZENoaWxkVm5vZGUuZG9tKTtcbiAgICB9XG4gIH1cbn1cblxuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGNvbXBsZXhpdHlcbmZ1bmN0aW9uIHBhdGNoTm9ybWFsVHJlZShcbiAgbmV3Vm5vZGU6IFZub2RlV2l0aERvbSxcbiAgbmV3VHJlZTogKFZub2RlV2l0aERvbSAmIHsgcHJvcHM6IFByb3BzICYgeyBrZXk6IHN0cmluZyB9IH0pW10sXG4gIG9sZFRyZWU6IChWbm9kZVdpdGhEb20gJiB7IHByb3BzOiBQcm9wcyAmIHsga2V5OiBzdHJpbmcgfSB9KVtdLFxuICBuZXdUcmVlTGVuZ3RoOiBudW1iZXIsXG4gIG9sZFRyZWVMZW5ndGg6IG51bWJlcixcbiAgdmFseXJpYW5BcHA6IE1vdW50ZWRWYWx5cmlhbkFwcFxuKSB7XG4gIC8vIElmIG5ldyB0cmVlIGFuZCBvbGQgdHJlZSBoYXZlIG1vcmUgdGhhbiBvbmUgY2hpbGQsIHdlIHNob3VsZCB1cGRhdGUgdGhlIGRvbVxuICBmb3IgKGxldCBpID0gMDsgaSA8IG5ld1RyZWVMZW5ndGg7IGkrKykge1xuICAgIGxldCBvbGRDaGlsZFZub2RlID0gb2xkVHJlZVtpXTtcbiAgICBsZXQgbmV3Q2hpbGRWbm9kZSA9IG5ld1RyZWVbaV07XG5cbiAgICAvLyBPbGQgY2hpbGQgZG9lcyBub3QgZXhpc3RzXG4gICAgaWYgKCFvbGRDaGlsZFZub2RlKSB7XG4gICAgICAvLyBOZXcgY2hpbGQgaXMgYSB0ZXh0IG5vZGVcbiAgICAgIGlmIChuZXdDaGlsZFZub2RlLnRhZyA9PT0gXCIjdGV4dFwiKSB7XG4gICAgICAgIG5ld0NoaWxkVm5vZGUuZG9tID0gZG9jdW1lbnQuY3JlYXRlVGV4dE5vZGUobmV3Q2hpbGRWbm9kZS5ub2RlVmFsdWUgYXMgc3RyaW5nKSBhcyB1bmtub3duIGFzIERvbUVsZW1lbnQ7XG4gICAgICAgIG5ld1Zub2RlLmRvbS5hcHBlbmRDaGlsZChuZXdDaGlsZFZub2RlLmRvbSk7XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuXG4gICAgICAvLyBOZXcgY2hpbGQgaXMgYSBub3JtYWwgbm9kZVxuICAgICAgbmV3Q2hpbGRWbm9kZS5kb20gPSBjcmVhdGVEb21FbGVtZW50KG5ld0NoaWxkVm5vZGUudGFnLCBuZXdDaGlsZFZub2RlLmlzU1ZHKTtcbiAgICAgIHVwZGF0ZVByb3BlcnRpZXMobmV3Q2hpbGRWbm9kZSk7XG4gICAgICBuZXdWbm9kZS5kb20uYXBwZW5kQ2hpbGQobmV3Q2hpbGRWbm9kZS5kb20pO1xuICAgICAgbmV3Q2hpbGRWbm9kZS5wcm9wcy5vbmNyZWF0ZSAmJiBuZXdDaGlsZFZub2RlLnByb3BzLm9uY3JlYXRlKG5ld0NoaWxkVm5vZGUpO1xuICAgICAgcGF0Y2gobmV3Q2hpbGRWbm9kZSwgdW5kZWZpbmVkLCB2YWx5cmlhbkFwcCk7XG4gICAgICBjb250aW51ZTtcbiAgICB9XG5cbiAgICAvLyBPbGQgY2hpbGQgZXhpc3RzXG4gICAgLy8gTmV3IGNoaWxkIGlzIGEgdGV4dCBub2RlXG4gICAgaWYgKG5ld0NoaWxkVm5vZGUudGFnID09PSBcIiN0ZXh0XCIpIHtcbiAgICAgIC8vIE9sZCBjaGlsZCBpcyBhIHRleHQgbm9kZVxuICAgICAgaWYgKG9sZENoaWxkVm5vZGUudGFnID09PSBcIiN0ZXh0XCIpIHtcbiAgICAgICAgbmV3Q2hpbGRWbm9kZS5kb20gPSBvbGRDaGlsZFZub2RlLmRvbTtcbiAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGVxZXFlcVxuICAgICAgICBpZiAobmV3Q2hpbGRWbm9kZS5kb20ubm9kZVZhbHVlICE9IG5ld0NoaWxkVm5vZGUubm9kZVZhbHVlKSB7XG4gICAgICAgICAgbmV3Q2hpbGRWbm9kZS5kb20ubm9kZVZhbHVlID0gbmV3Q2hpbGRWbm9kZS5ub2RlVmFsdWUgYXMgc3RyaW5nO1xuICAgICAgICB9XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuXG4gICAgICAvLyBPbGQgY2hpbGQgaXMgYSBub3JtYWwgbm9kZVxuICAgICAgbmV3Q2hpbGRWbm9kZS5kb20gPSBkb2N1bWVudC5jcmVhdGVUZXh0Tm9kZShuZXdDaGlsZFZub2RlLm5vZGVWYWx1ZSBhcyBzdHJpbmcpIGFzIHVua25vd24gYXMgRG9tRWxlbWVudDtcbiAgICAgIG9ucmVtb3ZlKG9sZENoaWxkVm5vZGUpO1xuICAgICAgbmV3Vm5vZGUuZG9tLnJlcGxhY2VDaGlsZChuZXdDaGlsZFZub2RlLmRvbSwgb2xkQ2hpbGRWbm9kZS5kb20pO1xuXG4gICAgICBjb250aW51ZTtcbiAgICB9XG5cbiAgICAvLyBOZXcgY2hpbGQgaXMgYSBub3JtYWwgbm9kZVxuICAgIC8vIE9sZCBjaGlsZCBpcyB0aGUgc2FtZSB0eXBlIGFzIG5ldyBjaGlsZFxuICAgIGlmIChvbGRDaGlsZFZub2RlLnRhZyA9PT0gbmV3Q2hpbGRWbm9kZS50YWcpIHtcbiAgICAgIG5ld0NoaWxkVm5vZGUuZG9tID0gb2xkQ2hpbGRWbm9kZS5kb207XG4gICAgICAvLyBJZiB3ZSBoYXZlIGEgdi1vbmNlIGRpcmVjdGl2ZSBvciBhIHNob3VsZHVwZGF0ZSBtZXRob2QgdGhhdCByZXR1cm5zIGZhbHNlLCB3ZSBza2lwIHRoZSB1cGRhdGVcbiAgICAgIGlmIChuZXdDaGlsZFZub2RlLnByb3BzW1widi1vbmNlXCJdIHx8IChuZXdDaGlsZFZub2RlLnByb3BzLnNob3VsZHVwZGF0ZSAmJiBuZXdDaGlsZFZub2RlLnByb3BzLnNob3VsZHVwZGF0ZShuZXdDaGlsZFZub2RlLCBvbGRDaGlsZFZub2RlKSA9PT0gZmFsc2UpKSB7XG4gICAgICAgIG5ld0NoaWxkVm5vZGUuY2hpbGRyZW4gPSBvbGRDaGlsZFZub2RlLmNoaWxkcmVuO1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cblxuICAgICAgLy8gV2UgdXBkYXRlIHRoZSBkb20gZWxlbWVudFxuICAgICAgdXBkYXRlUHJvcGVydGllcyhuZXdDaGlsZFZub2RlLCBvbGRDaGlsZFZub2RlKTtcbiAgICAgIGlmICh2YWx5cmlhbkFwcCAmJiB2YWx5cmlhbkFwcC5pc01vdW50ZWQpIHtcbiAgICAgICAgbmV3Q2hpbGRWbm9kZS5wcm9wcy5vbnVwZGF0ZSAmJiBuZXdDaGlsZFZub2RlLnByb3BzLm9udXBkYXRlKG5ld0NoaWxkVm5vZGUsIG9sZENoaWxkVm5vZGUpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgbmV3Q2hpbGRWbm9kZS5wcm9wcy5vbmNyZWF0ZSAmJiBuZXdDaGlsZFZub2RlLnByb3BzLm9uY3JlYXRlKG5ld0NoaWxkVm5vZGUpO1xuICAgICAgfVxuICAgICAgcGF0Y2gobmV3Q2hpbGRWbm9kZSwgb2xkQ2hpbGRWbm9kZSwgdmFseXJpYW5BcHApO1xuXG4gICAgICBjb250aW51ZTtcbiAgICB9XG5cbiAgICAvLyBPbGQgY2hpbGQgaXMgb2YgYSBkaWZmZXJlbnQgdHlwZSB0aGFuIG5ldyBjaGlsZFxuICAgIG5ld0NoaWxkVm5vZGUuZG9tID0gY3JlYXRlRG9tRWxlbWVudChuZXdDaGlsZFZub2RlLnRhZywgbmV3Q2hpbGRWbm9kZS5pc1NWRyk7XG4gICAgdXBkYXRlUHJvcGVydGllcyhuZXdDaGlsZFZub2RlKTtcbiAgICBpZiAob2xkQ2hpbGRWbm9kZS50YWcgIT09IFwiI3RleHRcIikge1xuICAgICAgb25yZW1vdmUob2xkQ2hpbGRWbm9kZSk7XG4gICAgfVxuICAgIG5ld0NoaWxkVm5vZGUucHJvcHMub25jcmVhdGUgJiYgbmV3Q2hpbGRWbm9kZS5wcm9wcy5vbmNyZWF0ZShuZXdDaGlsZFZub2RlKTtcbiAgICBuZXdWbm9kZS5kb20ucmVwbGFjZUNoaWxkKG5ld0NoaWxkVm5vZGUuZG9tLCBvbGRDaGlsZFZub2RlLmRvbSk7XG4gICAgcGF0Y2gobmV3Q2hpbGRWbm9kZSwgdW5kZWZpbmVkLCB2YWx5cmlhbkFwcCk7XG4gIH1cblxuICAvLyBGb3IgdGhlIHJlc3Qgb2YgdGhlIGNoaWxkcmVuLCB3ZSBzaG91bGQgcmVtb3ZlIHRoZW1cbiAgZm9yIChsZXQgaSA9IG5ld1RyZWVMZW5ndGg7IGkgPCBvbGRUcmVlTGVuZ3RoOyBpKyspIHtcbiAgICBsZXQgb2xkQ2hpbGRWbm9kZSA9IG9sZFRyZWVbaV07XG4gICAgaWYgKG9sZENoaWxkVm5vZGUudGFnICE9PSBcIiN0ZXh0XCIpIHtcbiAgICAgIG9ucmVtb3ZlKG9sZENoaWxkVm5vZGUpO1xuICAgIH1cbiAgICBvbGRDaGlsZFZub2RlLmRvbS5wYXJlbnROb2RlICYmIG9sZENoaWxkVm5vZGUuZG9tLnBhcmVudE5vZGUucmVtb3ZlQ2hpbGQob2xkQ2hpbGRWbm9kZS5kb20pO1xuICB9XG59XG5cbi8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBjb21wbGV4aXR5XG5mdW5jdGlvbiBwYXRjaChuZXdWbm9kZTogVm5vZGVXaXRoRG9tLCBvbGRWbm9kZTogVm5vZGVXaXRoRG9tID0gZW1wdHlWbm9kZSBhcyBWbm9kZVdpdGhEb20sIHZhbHlyaWFuQXBwOiBNb3VudGVkVmFseXJpYW5BcHApIHtcbiAgdi5jdXJyZW50LnZub2RlID0gbmV3Vm5vZGU7XG4gIHYuY3VycmVudC5vbGRWbm9kZSA9IG9sZFZub2RlO1xuXG4gIGZsYXRUcmVlKG5ld1Zub2RlKTtcblxuICBsZXQgbmV3VHJlZSA9IG5ld1Zub2RlLmNoaWxkcmVuO1xuICBsZXQgb2xkVHJlZSA9IG9sZFZub2RlLmNoaWxkcmVuO1xuICBsZXQgb2xkVHJlZUxlbmd0aCA9IG9sZFRyZWUubGVuZ3RoO1xuICBsZXQgbmV3VHJlZUxlbmd0aCA9IG5ld1RyZWUubGVuZ3RoO1xuXG4gIC8vIElmIG5ldyB0cmVlIGlzIGVtcHR5LCByZW1vdmUgYWxsIG9sZCBub2Rlc1xuICBpZiAobmV3VHJlZUxlbmd0aCA9PT0gMCkge1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgb2xkVHJlZUxlbmd0aDsgaSsrKSB7XG4gICAgICBvbnJlbW92ZShvbGRUcmVlW2ldKTtcbiAgICB9XG5cbiAgICBuZXdWbm9kZS5kb20udGV4dENvbnRlbnQgPSBcIlwiO1xuICAgIHJldHVybjtcbiAgfVxuXG4gIC8vIElmIHRoZSB0cmVlIGlzIGtleWVkIGxpc3QgYW5kIGlzIG5vdCBmaXJzdCByZW5kZXIgYW5kIG9sZCB0cmVlIGlzIGtleWVkIGxpc3QgdG9vXG4gIGlmIChvbGRUcmVlTGVuZ3RoICYmIFwia2V5XCIgaW4gbmV3VHJlZVswXS5wcm9wcyAmJiBcImtleVwiIGluIG9sZFRyZWVbMF0ucHJvcHMpIHtcbiAgICBwYXRjaEtleWVkVHJlZShuZXdWbm9kZSwgbmV3VHJlZSwgb2xkVHJlZSwgbmV3VHJlZUxlbmd0aCwgb2xkVHJlZUxlbmd0aCwgdmFseXJpYW5BcHApO1xuICAgIHJldHVybjtcbiAgfVxuXG4gIHBhdGNoTm9ybWFsVHJlZShuZXdWbm9kZSwgbmV3VHJlZSwgb2xkVHJlZSwgbmV3VHJlZUxlbmd0aCwgb2xkVHJlZUxlbmd0aCwgdmFseXJpYW5BcHApO1xufVxuXG4vKioqIERpcmVjdGl2ZXMgKioqL1xuXG5leHBvcnQgZnVuY3Rpb24gZGlyZWN0aXZlKG5hbWU6IHN0cmluZywgZGlyZWN0aXZlOiBEaXJlY3RpdmUpIHtcbiAgbGV0IGZ1bGxOYW1lID0gYHYtJHtuYW1lfWA7XG4gIHYuZGlyZWN0aXZlc1tmdWxsTmFtZV0gPSBkaXJlY3RpdmU7XG4gIHYucmVzZXJ2ZWRQcm9wc1tmdWxsTmFtZV0gPSB0cnVlO1xufVxuXG5mdW5jdGlvbiBoaWRlRGlyZWN0aXZlKHRlc3Q6IGJvb2xlYW4pOiBEaXJlY3RpdmUge1xuICByZXR1cm4gKGJvb2w6IGJvb2xlYW4sIHZub2RlOiBJVm5vZGUsIG9sZFZub2RlPzogSVZub2RlKSA9PiB7XG4gICAgbGV0IHZhbHVlID0gdGVzdCA/IGJvb2wgOiAhYm9vbDtcbiAgICBpZiAodmFsdWUpIHtcbiAgICAgIGxldCBuZXdkb20gPSBkb2N1bWVudC5jcmVhdGVUZXh0Tm9kZShcIlwiKTtcbiAgICAgIGlmIChvbGRWbm9kZSAmJiBvbGRWbm9kZS5kb20gJiYgb2xkVm5vZGUuZG9tLnBhcmVudE5vZGUpIHtcbiAgICAgICAgb2xkVm5vZGUudGFnICE9PSBcIiN0ZXh0XCIgJiYgb25yZW1vdmUob2xkVm5vZGUpO1xuICAgICAgICBvbGRWbm9kZS5kb20ucGFyZW50Tm9kZS5yZXBsYWNlQ2hpbGQobmV3ZG9tLCBvbGRWbm9kZS5kb20pO1xuICAgICAgfVxuICAgICAgdm5vZGUudGFnID0gXCIjdGV4dFwiO1xuICAgICAgdm5vZGUuY2hpbGRyZW4gPSBbXTtcbiAgICAgIHZub2RlLnByb3BzID0ge307XG4gICAgICB2bm9kZS5kb20gPSBuZXdkb20gYXMgdW5rbm93biBhcyBEb21FbGVtZW50O1xuICAgIH1cbiAgfTtcbn1cblxuY29uc3QgYnVpbHRJbkRpcmVjdGl2ZXMgPSB7XG4gIFwidi1pZlwiOiBoaWRlRGlyZWN0aXZlKGZhbHNlKSxcbiAgXCJ2LXVubGVzc1wiOiBoaWRlRGlyZWN0aXZlKHRydWUpLFxuICBcInYtZm9yXCI6IChzZXQ6IHVua25vd25bXSwgdm5vZGU6IFZub2RlV2l0aERvbSkgPT4ge1xuICAgIHZub2RlLmNoaWxkcmVuID0gc2V0Lm1hcCh2bm9kZS5jaGlsZHJlblswXSBhcyAodmFsdWU6IHVua25vd24pID0+IEZ1bmN0aW9uKTtcbiAgfSxcbiAgXCJ2LXNob3dcIjogKGJvb2w6IGJvb2xlYW4sIHZub2RlOiBWbm9kZVdpdGhEb20pID0+IHtcbiAgICAodm5vZGUuZG9tIGFzIHVua25vd24gYXMgeyBzdHlsZTogeyBkaXNwbGF5OiBzdHJpbmcgfSB9KS5zdHlsZS5kaXNwbGF5ID0gYm9vbCA/IFwiXCIgOiBcIm5vbmVcIjtcbiAgfSxcbiAgXCJ2LWNsYXNzXCI6IChjbGFzc2VzOiB7IFt4OiBzdHJpbmddOiBib29sZWFuIH0sIHZub2RlOiBWbm9kZVdpdGhEb20pID0+IHtcbiAgICBmb3IgKGxldCBuYW1lIGluIGNsYXNzZXMpIHtcbiAgICAgICh2bm9kZS5kb20gYXMgRG9tRWxlbWVudCkuY2xhc3NMaXN0LnRvZ2dsZShuYW1lLCBjbGFzc2VzW25hbWVdKTtcbiAgICB9XG4gIH0sXG4gIFwidi1odG1sXCI6IChodG1sOiBzdHJpbmcsIHZub2RlOiBWbm9kZVdpdGhEb20pID0+IHtcbiAgICB2bm9kZS5jaGlsZHJlbiA9IFt0cnVzdChodG1sKV07XG4gIH0sXG4gIFwidi1tb2RlbFwiOiAoW21vZGVsLCBwcm9wZXJ0eSwgZXZlbnRdOiBhbnlbXSwgdm5vZGU6IFZub2RlV2l0aERvbSwgb2xkVm5vZGU/OiBWbm9kZVdpdGhEb20pID0+IHtcbiAgICBsZXQgdmFsdWU7XG4gICAgbGV0IGhhbmRsZXI7XG4gICAgaWYgKHZub2RlLm5hbWUgPT09IFwiaW5wdXRcIikge1xuICAgICAgZXZlbnQgPSBldmVudCB8fCBcIm9uaW5wdXRcIjtcbiAgICAgIHN3aXRjaCAodm5vZGUucHJvcHMudHlwZSkge1xuICAgICAgICBjYXNlIFwiY2hlY2tib3hcIjoge1xuICAgICAgICAgIGlmIChBcnJheS5pc0FycmF5KG1vZGVsW3Byb3BlcnR5XSkpIHtcbiAgICAgICAgICAgIGhhbmRsZXIgPSAoZTogRXZlbnQpID0+IHtcbiAgICAgICAgICAgICAgbGV0IHZhbCA9IChlLnRhcmdldCBhcyBEb21FbGVtZW50ICYgUmVjb3JkPHN0cmluZywgYW55PikudmFsdWU7XG4gICAgICAgICAgICAgIGxldCBpZHggPSBtb2RlbFtwcm9wZXJ0eV0uaW5kZXhPZih2YWwpO1xuICAgICAgICAgICAgICBpZiAoaWR4ID09PSAtMSkge1xuICAgICAgICAgICAgICAgIG1vZGVsW3Byb3BlcnR5XS5wdXNoKHZhbCk7XG4gICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgbW9kZWxbcHJvcGVydHldLnNwbGljZShpZHgsIDEpO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgdmFsdWUgPSBtb2RlbFtwcm9wZXJ0eV0uaW5kZXhPZih2bm9kZS5kb20udmFsdWUpICE9PSAtMTtcbiAgICAgICAgICB9IGVsc2UgaWYgKFwidmFsdWVcIiBpbiB2bm9kZS5wcm9wcykge1xuICAgICAgICAgICAgaGFuZGxlciA9ICgpID0+IHtcbiAgICAgICAgICAgICAgaWYgKG1vZGVsW3Byb3BlcnR5XSA9PT0gdm5vZGUucHJvcHMudmFsdWUpIHtcbiAgICAgICAgICAgICAgICBtb2RlbFtwcm9wZXJ0eV0gPSBudWxsO1xuICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIG1vZGVsW3Byb3BlcnR5XSA9IHZub2RlLnByb3BzLnZhbHVlO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgdmFsdWUgPSBtb2RlbFtwcm9wZXJ0eV0gPT09IHZub2RlLnByb3BzLnZhbHVlO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBoYW5kbGVyID0gKCkgPT4gKG1vZGVsW3Byb3BlcnR5XSA9ICFtb2RlbFtwcm9wZXJ0eV0pO1xuICAgICAgICAgICAgdmFsdWUgPSBtb2RlbFtwcm9wZXJ0eV07XG4gICAgICAgICAgfVxuICAgICAgICAgIHVwZGF0ZVByb3BlcnR5KFwiY2hlY2tlZFwiLCB2YWx1ZSwgdm5vZGUsIG9sZFZub2RlKTtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgICAgICBjYXNlIFwicmFkaW9cIjoge1xuICAgICAgICAgIHVwZGF0ZVByb3BlcnR5KFwiY2hlY2tlZFwiLCBtb2RlbFtwcm9wZXJ0eV0gPT09IHZub2RlLmRvbS52YWx1ZSwgdm5vZGUsIG9sZFZub2RlKTtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgICAgICBkZWZhdWx0OiB7XG4gICAgICAgICAgdXBkYXRlUHJvcGVydHkoXCJ2YWx1ZVwiLCBtb2RlbFtwcm9wZXJ0eV0sIHZub2RlLCBvbGRWbm9kZSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9IGVsc2UgaWYgKHZub2RlLm5hbWUgPT09IFwic2VsZWN0XCIpIHtcbiAgICAgIGV2ZW50ID0gZXZlbnQgfHwgXCJvbmNsaWNrXCI7XG4gICAgICBpZiAodm5vZGUucHJvcHMubXVsdGlwbGUpIHtcbiAgICAgICAgaGFuZGxlciA9IChlOiBFdmVudCAmIFJlY29yZDxzdHJpbmcsIGFueT4pID0+IHtcbiAgICAgICAgICBsZXQgdmFsID0gKGUudGFyZ2V0IGFzIERvbUVsZW1lbnQgJiBSZWNvcmQ8c3RyaW5nLCBhbnk+KS52YWx1ZTtcbiAgICAgICAgICBpZiAoZS5jdHJsS2V5KSB7XG4gICAgICAgICAgICBsZXQgaWR4ID0gbW9kZWxbcHJvcGVydHldLmluZGV4T2YodmFsKTtcbiAgICAgICAgICAgIGlmIChpZHggPT09IC0xKSB7XG4gICAgICAgICAgICAgIG1vZGVsW3Byb3BlcnR5XS5wdXNoKHZhbCk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICBtb2RlbFtwcm9wZXJ0eV0uc3BsaWNlKGlkeCwgMSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIG1vZGVsW3Byb3BlcnR5XS5zcGxpY2UoMCwgbW9kZWxbcHJvcGVydHldLmxlbmd0aCk7XG4gICAgICAgICAgICBtb2RlbFtwcm9wZXJ0eV0ucHVzaCh2YWwpO1xuICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgdm5vZGUuY2hpbGRyZW4uZm9yRWFjaCgoY2hpbGQpID0+IHtcbiAgICAgICAgICBpZiAoY2hpbGQubmFtZSA9PT0gXCJvcHRpb25cIikge1xuICAgICAgICAgICAgbGV0IHZhbHVlID0gXCJ2YWx1ZVwiIGluIGNoaWxkLnByb3BzID8gY2hpbGQucHJvcHMudmFsdWUgOiBjaGlsZC5jaGlsZHJlbi5qb2luKFwiXCIpLnRyaW0oKTtcbiAgICAgICAgICAgIGNoaWxkLnByb3BzLnNlbGVjdGVkID0gbW9kZWxbcHJvcGVydHldLmluZGV4T2YodmFsdWUpICE9PSAtMTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdm5vZGUuY2hpbGRyZW4uZm9yRWFjaCgoY2hpbGQpID0+IHtcbiAgICAgICAgICBpZiAoY2hpbGQubmFtZSA9PT0gXCJvcHRpb25cIikge1xuICAgICAgICAgICAgbGV0IHZhbHVlID0gXCJ2YWx1ZVwiIGluIGNoaWxkLnByb3BzID8gY2hpbGQucHJvcHMudmFsdWUgOiBjaGlsZC5jaGlsZHJlbi5qb2luKFwiXCIpLnRyaW0oKTtcbiAgICAgICAgICAgIGNoaWxkLnByb3BzLnNlbGVjdGVkID0gdmFsdWUgPT09IG1vZGVsW3Byb3BlcnR5XTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgIH0gZWxzZSBpZiAodm5vZGUubmFtZSA9PT0gXCJ0ZXh0YXJlYVwiKSB7XG4gICAgICBldmVudCA9IGV2ZW50IHx8IFwib25pbnB1dFwiO1xuICAgICAgdm5vZGUuY2hpbGRyZW4gPSBbbW9kZWxbcHJvcGVydHldXTtcbiAgICB9XG5cbiAgICBpZiAoIXZub2RlLnByb3BzW2V2ZW50XSkge1xuICAgICAgaWYgKCFoYW5kbGVyKSB7XG4gICAgICAgIGhhbmRsZXIgPSAoZTogRXZlbnQpID0+IChtb2RlbFtwcm9wZXJ0eV0gPSAoZS50YXJnZXQgYXMgRG9tRWxlbWVudCAmIFJlY29yZDxzdHJpbmcsIGFueT4pLnZhbHVlKTtcbiAgICAgIH1cbiAgICAgIHVwZGF0ZVByb3BlcnR5KGV2ZW50LCBoYW5kbGVyLCB2bm9kZSwgb2xkVm5vZGUpO1xuICAgIH1cbiAgfVxufTtcblxuLyoqKiBIeXBlcnNjcmlwdCAqKiovXG5cbmV4cG9ydCBjb25zdCB2YWx5cmlhbjogVmFseXJpYW4gPSBmdW5jdGlvbiB2KHRhZ09yQ29tcG9uZW50OiBzdHJpbmcgfCBWYWx5cmlhbkNvbXBvbmVudCwgcHJvcHM6IFByb3BzLCAuLi5jaGlsZHJlbjogQ2hpbGRyZW4pOiBJVm5vZGUgfCBWbm9kZUNvbXBvbmVudCB7XG4gIGlmICh0eXBlb2YgdGFnT3JDb21wb25lbnQgPT09IFwic3RyaW5nXCIpIHtcbiAgICByZXR1cm4gbmV3IFZub2RlKHRhZ09yQ29tcG9uZW50LCBwcm9wcyB8fCB7fSwgY2hpbGRyZW4pO1xuICB9XG5cbiAgY29uc3Qgdm5vZGUgPSBuZXcgVm5vZGUoXCJfX2NvbXBvbmVudF9fXCIsIHByb3BzIHx8IHt9LCBjaGlsZHJlbik7XG4gIHZub2RlLmNvbXBvbmVudCA9IHRhZ09yQ29tcG9uZW50O1xuICByZXR1cm4gdm5vZGUgYXMgVm5vZGVDb21wb25lbnQ7XG59O1xuXG52YWx5cmlhbi5mcmFnbWVudCA9IChwcm9wczogUHJvcHMsIC4uLmNoaWxkcmVuOiBDaGlsZHJlbik6IENoaWxkcmVuID0+IHtcbiAgcmV0dXJuIGNoaWxkcmVuO1xufTtcblxudmFseXJpYW4uY3VycmVudCA9IHt9IGFzIEN1cnJlbnQ7XG5cbnZhbHlyaWFuLmRpcmVjdGl2ZXMgPSB7IC4uLmJ1aWx0SW5EaXJlY3RpdmVzIH07XG5cbnZhbHlyaWFuLnJlc2VydmVkUHJvcHMgPSB7XG4gIGtleTogdHJ1ZSxcbiAgc3RhdGU6IHRydWUsXG4gIG9uY3JlYXRlOiB0cnVlLFxuICBvbnVwZGF0ZTogdHJ1ZSxcbiAgb25yZW1vdmU6IHRydWUsXG4gIHNob3VsZHVwZGF0ZTogdHJ1ZSxcbiAgXCJ2LWNsZWFudXBcIjogdHJ1ZSxcbiAgXCJ2LW9uY2VcIjogdHJ1ZSxcblxuICAvLyBCdWlsdCBpbiBkaXJlY3RpdmVzXG4gIFwidi1pZlwiOiB0cnVlLFxuICBcInYtdW5sZXNzXCI6IHRydWUsXG4gIFwidi1mb3JcIjogdHJ1ZSxcbiAgXCJ2LXNob3dcIjogdHJ1ZSxcbiAgXCJ2LWNsYXNzXCI6IHRydWUsXG4gIFwidi1odG1sXCI6IHRydWVcbn07XG5cbigoaXNOb2RlSnMgPyBnbG9iYWwgOiB3aW5kb3cpIGFzIHVua25vd24gYXMgeyB2OiBWYWx5cmlhbiB9KS52ID0gdmFseXJpYW4gYXMgVmFseXJpYW47XG4iXX0= \ No newline at end of file diff --git a/dist/valyrian.min.js b/dist/valyrian.min.js deleted file mode 100644 index ac8221d..0000000 --- a/dist/valyrian.min.js +++ /dev/null @@ -1,13 +0,0 @@ -(() => { - // lib/index.ts - var Vnode = class { - tag; - props; - children; - constructor(tag, props, children) { - this.props = props; - this.children = children; - this.tag = tag; - } - }; -})(); diff --git a/dist/valyrian.min.js.map b/dist/valyrian.min.js.map deleted file mode 100644 index fced6db..0000000 --- a/dist/valyrian.min.js.map +++ /dev/null @@ -1 +0,0 @@ -//# sourceMappingURL=data:application/json;charset=utf-8;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vbGliL2luZGV4LnRzIl0sCiAgInNvdXJjZXNDb250ZW50IjogWyIvLyBXZSB3aWxsIG1ha2UgYSB2ZG9tIGxpYnJhcnkgdGhhdCB3aWxsIGJlIHVzZWQgdG8gY3JlYXRlIHZpcnR1YWwgZG9tIGVsZW1lbnRzIGFuZCByZW5kZXIgdGhlbSB0byB0aGUgc2NyZWVuLlxuLy8gV2UgbXVzdCB0cnkgdG8gaGF2ZSB0aGUgbGVzcyBhbW91bnQgb2YgYXNzaWdubWVudHMgYW5kIGlmIHN0YXRlbWVudHNcblxuY2xhc3MgVm5vZGUge1xuICB0YWc6IHN0cmluZztcbiAgcHJvcHM6IHt9O1xuICBjaGlsZHJlbjogW107XG4gIGNvbnN0cnVjdG9yKHRhZzogc3RyaW5nLCBwcm9wczoge30sIGNoaWxkcmVuOiBbXSkge1xuICAgIHRoaXMucHJvcHMgPSBwcm9wcztcbiAgICB0aGlzLmNoaWxkcmVuID0gY2hpbGRyZW47XG4gICAgdGhpcy50YWcgPSB0YWc7XG4gIH1cbn1cblxuZXhwb3J0IHsgVm5vZGUgfTtcbiJdLAogICJtYXBwaW5ncyI6ICI7O0FBR0Esb0JBQVk7QUFBQSxJQUNWO0FBQUEsSUFDQTtBQUFBLElBQ0E7QUFBQSxJQUNBLFlBQVksS0FBYSxPQUFXLFVBQWM7QUFDaEQsV0FBSyxRQUFRO0FBQ2IsV0FBSyxXQUFXO0FBQ2hCLFdBQUssTUFBTTtBQUFBO0FBQUE7IiwKICAibmFtZXMiOiBbXQp9Cg== \ No newline at end of file diff --git a/lib/index.ts b/lib/index.ts index 28616d4..5dff72d 100644 --- a/lib/index.ts +++ b/lib/index.ts @@ -1,25 +1,24 @@ -// We will make a vdom library that will be used to create virtual dom elements and render them to the screen. -// We must try to have the less amount of assignments and if statements +/*** Interfaces ***/ -interface DomElement extends Element { +export interface DomElement extends Element { [key: string]: any; } -interface Props { +export interface Props { key?: string | number; data?: string; - oncreate?: { (vnode: Vnode): never }; - onupdate?: { (vnode: Vnode, oldVnode: Vnode): never }; - onremove?: { (oldVnode: Vnode): never }; - shouldupdate?: { (vnode: Vnode, oldVnode: Vnode): undefined | boolean }; + oncreate?: { (vnode: IVnode): never }; + onupdate?: { (vnode: IVnode, oldVnode: IVnode): never }; + onremove?: { (oldVnode: IVnode): never }; + shouldupdate?: { (vnode: IVnode, oldVnode: IVnode): undefined | boolean }; "v-cleanup"?: Function; [key: string | number | symbol]: any; } -interface Children extends Array {} +export interface Children extends Array {} -interface Vnode { - new (tag: string, props: Props, children: Vnode[]): Vnode; +export interface IVnode { + new (tag: string, props: Props, children: IVnode[]): IVnode; tag: string; props: Props; children: Children; @@ -28,45 +27,35 @@ interface Vnode { processed?: boolean; component?: Component | POJOComponent; nodeValue?: string; - [key: symbol]: any; + [key: string | number | symbol]: any; } -const Vnode = function Vnode(this: Vnode, tag: string, props: Props, children: Children) { - this.props = props; - this.children = children; - this.tag = tag; -} as unknown as Vnode; - -interface Component { - (props?: Record | null, children?: Children): Vnode | Children; +export interface Component { + (props?: Record | null, children?: Children): IVnode | Children; [key: string | number | symbol]: any; } -interface POJOComponent { +export interface POJOComponent { view: Component; [key: string | number | symbol]: any; } -type ValyrianComponent = Component | POJOComponent; +export type ValyrianComponent = Component | POJOComponent; -interface VnodeComponent extends Vnode { +export interface VnodeComponent extends IVnode { tag: "__component__"; component: ValyrianComponent; } -interface VnodeWithDom extends Vnode { +export interface VnodeWithDom extends IVnode { dom: DomElement; } -interface Directive { - (value: any, vnode: Vnode, oldVnode?: Vnode): void; -} - -interface Plugin { - (v: v, options?: Record): never; +export interface Directive { + (value: any, vnode: VnodeWithDom, oldVnode?: VnodeWithDom): void; } -interface ValyrianApp { +export interface ValyrianApp { isMounted: boolean; eventListenerNames: Record; cleanup: Function[]; @@ -79,117 +68,57 @@ interface ValyrianApp { [key: string | number | symbol]: any; } -interface MountedValyrianApp extends ValyrianApp { +export interface MountedValyrianApp extends ValyrianApp { eventListener: EventListener; mainVnode: VnodeWithDom; container: DomElement; component: VnodeComponent; } -const ValyrianSymbol = Symbol("Valyrian"); - -function hideDirective(test: boolean): Directive { - return (bool: boolean, vnode: Vnode, oldVnode?: Vnode) => { - let value = test ? bool : !bool; - if (value) { - let newdom = document.createTextNode(""); - if (oldVnode && oldVnode.dom && oldVnode.dom.parentNode) { - oldVnode.tag !== "#text" && onremove(oldVnode); - oldVnode.dom.parentNode.replaceChild(newdom, oldVnode.dom); - } - vnode.tag = "#text"; - vnode.children = []; - vnode.props = {}; - vnode.dom = newdom as unknown as DomElement; - } - }; -} -export const trust = (htmlString: string) => { - let div = createDomElement("div"); - div.innerHTML = htmlString.trim(); - - return [].map.call(div.childNodes, (item) => domToVnode(item)) as Vnode[]; -}; - -interface Current { +export interface Current { app?: ValyrianApp; component?: ValyrianComponent; vnode?: VnodeWithDom; oldVnode?: VnodeWithDom; } -interface v { - (tagOrComponent: string | ValyrianComponent, props: Props, ...children: Children): Vnode | VnodeComponent; - fragment: (props: Props, ...children: Children) => Children; - current: Current; +export interface Directives { + [key: string]: Directive; } -export function v(tagOrComponent: string | ValyrianComponent, props: Props, ...children: Children): Vnode | VnodeComponent { - if (typeof tagOrComponent === "string") { - return new Vnode(tagOrComponent, props || {}, children); - } +export interface ReservedProps { + [key: string]: true; +} - const vnode = new Vnode("__component__", props || {}, children); - vnode.component = tagOrComponent; - return vnode as VnodeComponent; +export interface Valyrian { + (tagOrComponent: string | ValyrianComponent, props: Props, ...children: Children): IVnode | VnodeComponent; + fragment: (props: Props, ...children: Children) => Children; + current: Current; + directives: Directives; + reservedProps: ReservedProps; } -v.fragment = (props: Props, ...children: Children): Children => { - return children; -}; +/*** Vnode ***/ -v.current = {} as Current; +export const Vnode = function Vnode(this: IVnode, tag: string, props: Props, children: Children) { + this.props = props; + this.children = children; + this.tag = tag; +} as unknown as IVnode; -interface Directives { - [key: string]: Directive; +export function isVnode(component?: unknown): component is IVnode { + return component instanceof Vnode; } -const directives: Directives = { - "v-if": hideDirective(false), - "v-unless": hideDirective(true), - "v-for": (set: unknown[], vnode: Vnode) => { - vnode.children = set.map(vnode.children[0] as (value: unknown) => Function); - }, - "v-show": (bool: boolean, vnode: Vnode) => { - (vnode.dom as unknown as { style: { display: string } }).style.display = bool ? "" : "none"; - }, - "v-class": (classes: { [x: string]: boolean }, vnode: Vnode) => { - for (let name in classes) { - (vnode.dom as DomElement).classList.toggle(name, classes[name]); - } - }, - "v-html": (html: string, vnode: Vnode) => { - vnode.children = [trust(html)]; - }, - "v-cleanup"(cleanupFunction: Function) { - if (typeof cleanupFunction === "function") { - (this as unknown as ValyrianApp).cleanup.push(cleanupFunction); - } - } -}; - -interface ReservedProps { - [key: string]: true; +export function isComponent(component?: unknown | ValyrianComponent): component is ValyrianComponent { + return typeof component === "function" || (typeof component === "object" && component !== null && "view" in component); } -const reservedProps: ReservedProps = { - key: true, - state: true, - oncreate: true, - onupdate: true, - onremove: true, - shouldupdate: true, - "v-cleanup": true, - "v-once": true, +export function isVnodeComponent(vnode?: unknown): vnode is VnodeComponent { + return vnode instanceof Vnode && vnode.tag === "__component__"; +} - // Built in directives - "v-if": true, - "v-unless": true, - "v-for": true, - "v-show": true, - "v-class": true, - "v-html": true -}; +/*** Util ***/ export const isNodeJs = Boolean(typeof process !== "undefined" && process.versions && process.versions.node); @@ -219,16 +148,21 @@ function domToVnode(dom: DomElement): VnodeWithDom { return vnode as VnodeWithDom; } -export function isComponent(component?: unknown | ValyrianComponent): component is ValyrianComponent { - return typeof component === "function" || (typeof component === "object" && component !== null && "view" in component); -} +export const trust = (htmlString: string) => { + let div = createDomElement("div"); + div.innerHTML = htmlString.trim(); -export function isVnodeComponent(vnode?: unknown): vnode is VnodeComponent { - return vnode instanceof Vnode && vnode.tag === "__component__"; -} + return [].map.call(div.childNodes, (item) => domToVnode(item)) as IVnode[]; +}; -export function isVnode(component?: unknown): component is Vnode { - return component instanceof Vnode; +/*** Mount ***/ + +const ValyrianSymbol = Symbol("Valyrian"); + +export function cleanup(callback: Function) { + if (v.current.app?.cleanup.indexOf(callback) === -1) { + v.current.app?.cleanup.push(callback); + } } /* @@ -239,7 +173,7 @@ export function isVnode(component?: unknown): component is Vnode { mount('#app',
Hello world
); // App is a Vnode component (Vnode with tag __component__) */ -export function mount(container: DomElement | string, component: ValyrianComponent | Vnode) { +export function mount(container: DomElement | string, component: ValyrianComponent | IVnode) { let appContainer = null; if (isNodeJs) { @@ -252,9 +186,7 @@ export function mount(container: DomElement | string, component: ValyrianCompone throw new Error("Container not found"); } - // If component is a POJO component or a Functional component or a Vnode - - let vnodeComponent: VnodeComponent | Vnode; + let vnodeComponent: VnodeComponent | IVnode; if (isVnodeComponent(component)) { vnodeComponent = component; @@ -305,7 +237,7 @@ function cleanupVnodes(valyrianApp: ValyrianApp) { valyrianApp.cleanup = []; } -export function update(component?: ValyrianComponent | Vnode) { +export function update(component?: ValyrianComponent | IVnode) { if (component && component[ValyrianSymbol]) { let valyrianApp = component[ValyrianSymbol]; v.current.app = valyrianApp; @@ -324,7 +256,7 @@ export function update(component?: ValyrianComponent | Vnode) { } } -export function unmount(component?: ValyrianComponent | Vnode) { +export function unmount(component?: ValyrianComponent | IVnode) { if (!component || !component[ValyrianSymbol]) { return; } @@ -348,7 +280,7 @@ export function unmount(component?: ValyrianComponent | Vnode) { let emptyVnode = new Vnode("__empty__", {}, []); -function onremove(vnode: Vnode) { +export function onremove(vnode: IVnode) { for (let i = 0; i < vnode.children.length; i++) { vnode.children[i].tag !== "#text" && onremove(vnode.children[i]); } @@ -356,19 +288,20 @@ function onremove(vnode: Vnode) { vnode.props.onremove && vnode.props.onremove(vnode); } -function sharedUpdateProperty(prop: string, value: any, vnode: VnodeWithDom, oldVnode?: VnodeWithDom, valyrianApp?: MountedValyrianApp) { +function sharedUpdateProperty(prop: string, value: any, vnode: VnodeWithDom, oldVnode?: VnodeWithDom) { // It is a reserved prop - if (reservedProps[prop]) { + if (v.reservedProps[prop]) { // If it is a directive name call the directive - if (directives[prop]) { - directives[prop](vnode.props[prop], vnode, oldVnode); + if (v.directives[prop]) { + v.directives[prop](vnode.props[prop], vnode, oldVnode); } return; } // It is not a reserved prop so we add it to the dom if (typeof value === "function") { - if (valyrianApp && prop in valyrianApp.eventListenerNames === false) { + let valyrianApp = v.current.app as MountedValyrianApp; + if (prop in valyrianApp.eventListenerNames === false) { valyrianApp.eventListenerNames[prop] = true; valyrianApp.container.addEventListener(prop.slice(2), valyrianApp.eventListener); } @@ -394,27 +327,27 @@ function sharedUpdateProperty(prop: string, value: any, vnode: VnodeWithDom, old } } -export function updateProperty(name: string, value: any, vnode: VnodeWithDom, oldVnode?: VnodeWithDom, valyrianApp?: MountedValyrianApp) { +export function updateProperty(name: string, value: any, vnode: VnodeWithDom, oldVnode?: VnodeWithDom) { if (name in vnode.props === false) { vnode.props[name] = value; } - sharedUpdateProperty(name, value, vnode, oldVnode, valyrianApp); + sharedUpdateProperty(name, value, vnode, oldVnode); } -function updateProperties(vnode: VnodeWithDom, oldVnode?: VnodeWithDom, valyrianApp?: MountedValyrianApp) { +function updateProperties(vnode: VnodeWithDom, oldVnode?: VnodeWithDom) { for (let prop in vnode.props) { // We asume that we clean the props in some directive if (prop in vnode.props === false) { return; } - sharedUpdateProperty(prop, vnode.props[prop], vnode, oldVnode, valyrianApp); + sharedUpdateProperty(prop, vnode.props[prop], vnode, oldVnode); } if (oldVnode) { for (let prop in oldVnode.props) { - if (prop in vnode.props === false && typeof oldVnode.props[prop] !== "function" && prop in reservedProps === false) { + if (prop in vnode.props === false && typeof oldVnode.props[prop] !== "function" && prop in v.reservedProps === false) { if (prop in oldVnode.dom && vnode.isSVG === false) { oldVnode.dom[prop] = null; } else { @@ -425,7 +358,7 @@ function updateProperties(vnode: VnodeWithDom, oldVnode?: VnodeWithDom, valyrian } } -function flatTree(newVnode: Vnode): void { +function flatTree(newVnode: IVnode): void { let newTree = newVnode.children; for (let i = 0; i < newTree.length; i++) { let childVnode = newTree[i]; @@ -463,7 +396,7 @@ function patchKeyedTree( oldTree: (VnodeWithDom & { props: Props & { key: string } })[], newTreeLength: number, oldTreeLength: number, - valyrianApp?: MountedValyrianApp + valyrianApp: MountedValyrianApp ) { let oldKeyedList = oldTree.reduce((acc, vnode, i) => { acc[vnode.props.key] = i; @@ -486,8 +419,8 @@ function patchKeyedTree( childVnode.children = oldChildVnode.children; shouldPatch = false; } else { - updateProperties(childVnode, oldChildVnode, valyrianApp); - if (valyrianApp && valyrianApp.isMounted) { + updateProperties(childVnode, oldChildVnode); + if (valyrianApp.isMounted) { childVnode.props.onupdate && childVnode.props.onupdate(childVnode, oldChildVnode); } else { childVnode.props.oncreate && childVnode.props.oncreate(childVnode); @@ -495,7 +428,7 @@ function patchKeyedTree( } } else { childVnode.dom = createDomElement(childVnode.tag, childVnode.isSVG); - updateProperties(childVnode, undefined, valyrianApp); + updateProperties(childVnode); childVnode.props.oncreate && childVnode.props.oncreate(childVnode); } @@ -526,7 +459,7 @@ function patchNormalTree( oldTree: (VnodeWithDom & { props: Props & { key: string } })[], newTreeLength: number, oldTreeLength: number, - valyrianApp?: MountedValyrianApp + valyrianApp: MountedValyrianApp ) { // If new tree and old tree have more than one child, we should update the dom for (let i = 0; i < newTreeLength; i++) { @@ -544,7 +477,7 @@ function patchNormalTree( // New child is a normal node newChildVnode.dom = createDomElement(newChildVnode.tag, newChildVnode.isSVG); - updateProperties(newChildVnode, undefined, valyrianApp); + updateProperties(newChildVnode); newVnode.dom.appendChild(newChildVnode.dom); newChildVnode.props.oncreate && newChildVnode.props.oncreate(newChildVnode); patch(newChildVnode, undefined, valyrianApp); @@ -583,7 +516,7 @@ function patchNormalTree( } // We update the dom element - updateProperties(newChildVnode, oldChildVnode, valyrianApp); + updateProperties(newChildVnode, oldChildVnode); if (valyrianApp && valyrianApp.isMounted) { newChildVnode.props.onupdate && newChildVnode.props.onupdate(newChildVnode, oldChildVnode); } else { @@ -596,7 +529,7 @@ function patchNormalTree( // Old child is of a different type than new child newChildVnode.dom = createDomElement(newChildVnode.tag, newChildVnode.isSVG); - updateProperties(newChildVnode, undefined, valyrianApp); + updateProperties(newChildVnode); if (oldChildVnode.tag !== "#text") { onremove(oldChildVnode); } @@ -616,7 +549,7 @@ function patchNormalTree( } // eslint-disable-next-line complexity -function patch(newVnode: VnodeWithDom, oldVnode: VnodeWithDom = emptyVnode as VnodeWithDom, valyrianApp?: MountedValyrianApp) { +function patch(newVnode: VnodeWithDom, oldVnode: VnodeWithDom = emptyVnode as VnodeWithDom, valyrianApp: MountedValyrianApp) { v.current.vnode = newVnode; v.current.oldVnode = oldVnode; @@ -646,20 +579,172 @@ function patch(newVnode: VnodeWithDom, oldVnode: VnodeWithDom = emptyVnode as Vn patchNormalTree(newVnode, newTree, oldTree, newTreeLength, oldTreeLength, valyrianApp); } +/*** Directives ***/ + export function directive(name: string, directive: Directive) { let fullName = `v-${name}`; - if (reservedProps[fullName]) { - throw new Error(`Directive ${name} already exists`); - } + v.directives[fullName] = directive; + v.reservedProps[fullName] = true; +} - directives[fullName] = directive; - reservedProps[fullName] = true; +function hideDirective(test: boolean): Directive { + return (bool: boolean, vnode: IVnode, oldVnode?: IVnode) => { + let value = test ? bool : !bool; + if (value) { + let newdom = document.createTextNode(""); + if (oldVnode && oldVnode.dom && oldVnode.dom.parentNode) { + oldVnode.tag !== "#text" && onremove(oldVnode); + oldVnode.dom.parentNode.replaceChild(newdom, oldVnode.dom); + } + vnode.tag = "#text"; + vnode.children = []; + vnode.props = {}; + vnode.dom = newdom as unknown as DomElement; + } + }; } -export function cleanup(callback: Function) { - if (v.current.app?.cleanup.indexOf(callback) === -1) { - v.current.app?.cleanup.push(callback); +const builtInDirectives = { + "v-if": hideDirective(false), + "v-unless": hideDirective(true), + "v-for": (set: unknown[], vnode: VnodeWithDom) => { + vnode.children = set.map(vnode.children[0] as (value: unknown) => Function); + }, + "v-show": (bool: boolean, vnode: VnodeWithDom) => { + (vnode.dom as unknown as { style: { display: string } }).style.display = bool ? "" : "none"; + }, + "v-class": (classes: { [x: string]: boolean }, vnode: VnodeWithDom) => { + for (let name in classes) { + (vnode.dom as DomElement).classList.toggle(name, classes[name]); + } + }, + "v-html": (html: string, vnode: VnodeWithDom) => { + vnode.children = [trust(html)]; + }, + "v-model": ([model, property, event]: any[], vnode: VnodeWithDom, oldVnode?: VnodeWithDom) => { + let value; + let handler; + if (vnode.name === "input") { + event = event || "oninput"; + switch (vnode.props.type) { + case "checkbox": { + if (Array.isArray(model[property])) { + handler = (e: Event) => { + let val = (e.target as DomElement & Record).value; + let idx = model[property].indexOf(val); + if (idx === -1) { + model[property].push(val); + } else { + model[property].splice(idx, 1); + } + }; + value = model[property].indexOf(vnode.dom.value) !== -1; + } else if ("value" in vnode.props) { + handler = () => { + if (model[property] === vnode.props.value) { + model[property] = null; + } else { + model[property] = vnode.props.value; + } + }; + value = model[property] === vnode.props.value; + } else { + handler = () => (model[property] = !model[property]); + value = model[property]; + } + updateProperty("checked", value, vnode, oldVnode); + break; + } + case "radio": { + updateProperty("checked", model[property] === vnode.dom.value, vnode, oldVnode); + break; + } + default: { + updateProperty("value", model[property], vnode, oldVnode); + } + } + } else if (vnode.name === "select") { + event = event || "onclick"; + if (vnode.props.multiple) { + handler = (e: Event & Record) => { + let val = (e.target as DomElement & Record).value; + if (e.ctrlKey) { + let idx = model[property].indexOf(val); + if (idx === -1) { + model[property].push(val); + } else { + model[property].splice(idx, 1); + } + } else { + model[property].splice(0, model[property].length); + model[property].push(val); + } + }; + vnode.children.forEach((child) => { + if (child.name === "option") { + let value = "value" in child.props ? child.props.value : child.children.join("").trim(); + child.props.selected = model[property].indexOf(value) !== -1; + } + }); + } else { + vnode.children.forEach((child) => { + if (child.name === "option") { + let value = "value" in child.props ? child.props.value : child.children.join("").trim(); + child.props.selected = value === model[property]; + } + }); + } + } else if (vnode.name === "textarea") { + event = event || "oninput"; + vnode.children = [model[property]]; + } + + if (!vnode.props[event]) { + if (!handler) { + handler = (e: Event) => (model[property] = (e.target as DomElement & Record).value); + } + updateProperty(event, handler, vnode, oldVnode); + } } -} +}; + +/*** Hyperscript ***/ + +export const v: Valyrian = function v(tagOrComponent: string | ValyrianComponent, props: Props, ...children: Children): IVnode | VnodeComponent { + if (typeof tagOrComponent === "string") { + return new Vnode(tagOrComponent, props || {}, children); + } + + const vnode = new Vnode("__component__", props || {}, children); + vnode.component = tagOrComponent; + return vnode as VnodeComponent; +}; + +v.fragment = (props: Props, ...children: Children): Children => { + return children; +}; + +v.current = {} as Current; + +v.directives = { ...builtInDirectives }; + +v.reservedProps = { + key: true, + state: true, + oncreate: true, + onupdate: true, + onremove: true, + shouldupdate: true, + "v-cleanup": true, + "v-once": true, + + // Built in directives + "v-if": true, + "v-unless": true, + "v-for": true, + "v-show": true, + "v-class": true, + "v-html": true +}; -((isNodeJs ? global : window) as unknown as { v: v }).v = v; +((isNodeJs ? global : window) as unknown as { v: Valyrian }).v = v as Valyrian; diff --git a/lib/index_.ts b/lib/index_.ts deleted file mode 100644 index 7e5a1b9..0000000 --- a/lib/index_.ts +++ /dev/null @@ -1,564 +0,0 @@ -/* eslint-disable complexity */ -/* eslint-disable sonarjs/cognitive-complexity */ -/* eslint-disable no-use-before-define */ -/* eslint-disable no-unused-vars */ - -type VnodeOrUnknown = VnodeComponent | Vnode | TextVnode | any; - -type DomAttribute = { nodeName: string; nodeValue: string }; - -type DomElement = (HTMLElement | SVGElement) & Record; - -type Props = { - key?: string | number; - data?: string; - oncreate?: { (vnode: Vnode): never }; - onupdate?: { (vnode: Vnode, oldVnode: Vnode | TextVnode): never }; - onremove?: { (oldVnode: Vnode): never }; - onbeforeupdate?: { (vnode: Vnode, oldVnode: Vnode | TextVnode): undefined | boolean }; -} & Record; - -type Component = (props?: Record | null, children?: VnodeOrUnknown) => VnodeOrUnknown | VnodeOrUnknown[]; - -type ValyrianComponent = - | Component - | (Record & { - view: Component; - }); - -type Current = { parentVnode?: Vnode; oldParentVnode?: Vnode; component?: VnodeComponent }; - -interface Plugin { - (v: Valyrian, options?: Record): never; -} - -interface Directive { - (value: any, vnode: Vnode, oldVnode?: Vnode | TextVnode): void | boolean; -} - -interface ValyrianEventHandler { - (a: Event, dom: DomElement): void; -} - -interface Vnode { - name: string; - props: Props; - children: VnodeOrUnknown[]; - dom?: DomElement; - onCleanup?: FunctionConstructor[]; - isSVG?: boolean; - processed?: boolean; -} - -class Vnode implements Vnode { - name: string; - props: Props; - children: VnodeOrUnknown[]; - dom?: DomElement; - onCleanup?: FunctionConstructor[]; - isSVG?: boolean; - processed?: boolean; - - constructor(name: string, props: Props, children: VnodeOrUnknown) { - this.props = props; - this.children = children; - this.name = name; - } -} - -interface TextVnode { - dom?: Text; - nodeValue: string; -} - -class TextVnode implements TextVnode { - dom?: Text; - nodeValue: string; - - constructor(nodeValue: string) { - this.nodeValue = nodeValue; - } -} - -interface VnodeComponent { - component: ValyrianComponent; - props: Props; - children: VnodeOrUnknown[]; -} - -class VnodeComponent implements VnodeComponent { - component: ValyrianComponent; - props: Props; - children: VnodeOrUnknown[]; - - constructor(component: ValyrianComponent, props: Props, children: VnodeOrUnknown[]) { - this.props = props; - this.children = children; - this.component = component; - } -} - -interface Valyrian { - (tagOrComponent: string | ValyrianComponent, props?: Props | null, children?: VnodeOrUnknown): Vnode | VnodeComponent; - fragment: (props: Props, children: VnodeOrUnknown[]) => VnodeOrUnknown[]; - isMounted: boolean; - isNode: boolean; - reservedWords: string[]; - current: Current; - trust: (htmlString: string) => Vnode[]; - usePlugin: (plugin: Plugin, options: Record) => void; - onCleanup: (callback: typeof Function) => void; - updateProperty: (name: string, newVnode: Vnode & { dom: DomElement }, oldNode: Vnode & { dom: DomElement }) => void; - update: (props?: Props | null, ...children: VnodeOrUnknown) => string | void; - mount: (container: string | DomElement, component: ValyrianComponent, props?: Props | null, ...children: VnodeOrUnknown[]) => string | void; - unMount: () => string | boolean | void; - directive: (directive: string, handler: Directive) => void; - newInstance: () => Valyrian; - [x: string]: any; -} - -let isNode = typeof window === "undefined" || typeof global !== "undefined"; - -// Create Node element -function createElement(tagName: string, isSVG: boolean = false): DomElement { - return isSVG ? document.createElementNS("http://www.w3.org/2000/svg", tagName) : document.createElement(tagName); -} - -// Transforms a DOM node to a VNode -function domToVnode(dom: DomElement): Vnode { - let props: Props = {}; - [].forEach.call(dom.attributes, (prop: Attr) => (props[prop.nodeName] = prop.nodeValue)); - - let vnode: Vnode = new Vnode(dom.nodeName.toLowerCase(), props, []); - vnode.dom = dom; - - for (let i = 0, l = dom.childNodes.length; i < l; i++) { - if (dom.childNodes[i].nodeType === 1) { - vnode.children.push(domToVnode(dom.childNodes[i] as DomElement)); - } else if (dom.childNodes[i].nodeType === 3) { - let textVnode = new TextVnode(dom.childNodes[i].nodeValue || ""); - textVnode.dom = dom.childNodes[i] as unknown as Text; - vnode.children.push(textVnode); - } - } - return vnode; -} - -const trust = (htmlString: string) => { - let div = createElement("div"); - div.innerHTML = htmlString.trim(); - - return [].map.call(div.childNodes, (item) => domToVnode(item)) as Vnode[]; -}; - -// eslint-disable-next-line max-lines-per-function -function valyrian(): Valyrian { - const v: Valyrian = (tagOrComponent, props, ...children) => { - if (typeof tagOrComponent === "string") { - return new Vnode(tagOrComponent, props || {}, children); - } else { - return new VnodeComponent(tagOrComponent, props || {}, children); - } - }; - - v.fragment = (props: Props, vnodes: VnodeOrUnknown[]) => { - return vnodes; - }; - - v.isMounted = false; - v.isNode = isNode; - const reservedWords = ["key", "data", "v-once", "oncreate", "onupdate", "onremove", "onbeforeupdate"]; - v.reservedWords = reservedWords; - v.trust = trust; - - const current: Current = { - parentVnode: undefined, - oldParentVnode: undefined, - component: undefined - }; - v.current = current; - - const plugins = new Map(); - - v.usePlugin = (plugin: Plugin, options: Record = {}) => !plugins.has(plugin) && plugins.set(plugin, true) && plugin(v as Valyrian, options); - - let vnodesToCleanup: Vnode[] = []; - - v.onCleanup = (callback: FunctionConstructor) => { - let parentVnode = v.current.parentVnode as Vnode; - if (!parentVnode.onCleanup) { - parentVnode.onCleanup = [] as FunctionConstructor[]; - } - - parentVnode.onCleanup.push(callback); - - if (vnodesToCleanup.indexOf(parentVnode) === -1) { - vnodesToCleanup.push(parentVnode); - } - }; - - let cleanupVnodes = () => { - for (let l = vnodesToCleanup.length; l--; ) { - for (let callback of vnodesToCleanup[l].onCleanup as FunctionConstructor[]) { - callback(); - } - } - vnodesToCleanup = []; - }; - - let mainContainer: DomElement | null = null; - let emptyComponent: ValyrianComponent = () => ""; - let mountedComponent: ValyrianComponent = emptyComponent; - - const attachedListeners: string[] = []; - function eventListener(e: Event) { - let dom = e.target as DomElement; - let name = `v-on${e.type}`; - while (dom) { - if (dom[name]) { - (dom[name] as ValyrianEventHandler)(e, dom); - if (!e.defaultPrevented) { - v.update(); - } - return; - } - dom = dom.parentNode as DomElement; - } - } - - function updateProperty(prop: string, newVnode: Vnode & { dom: DomElement }, oldVnode?: Vnode): void | boolean { - if (reservedWords.indexOf(prop) !== -1) { - if (prop in directives) { - return directives[prop](newVnode.props[prop], newVnode, oldVnode); - } - } else if (typeof newVnode.props[prop] === "function") { - if (attachedListeners.indexOf(prop) === -1) { - (mainContainer as DomElement).addEventListener(prop.slice(2), eventListener); - attachedListeners.push(prop); - } - newVnode.dom[`v-${prop}`] = newVnode.props[prop]; - } else if (prop in newVnode.dom && !newVnode.isSVG) { - // eslint-disable-next-line eqeqeq - if (newVnode.dom[prop] != newVnode.props[prop]) { - newVnode.dom[prop] = newVnode.props[prop]; - } - } else if (oldVnode === undefined || newVnode.props[prop] !== oldVnode.props[prop]) { - if (newVnode.props[prop] === false) { - newVnode.dom.removeAttribute(prop); - } else { - newVnode.dom.setAttribute(prop, newVnode.props[prop]); - } - } - } - v.updateProperty = updateProperty; - - // Update a Vnode.dom HTMLElement with new Vnode props that are different from old Vnode props - function updateProperties(newVnode: Vnode & { dom: DomElement }, oldVnode?: Vnode): void { - for (let prop in newVnode.props) { - if (updateProperty(prop, newVnode, oldVnode) === false) { - return; - } - } - } - - function removeProperties(newVnode: Vnode & { dom: DomElement }, oldVnode: Vnode) { - for (let name in oldVnode.props) { - if (name in newVnode.props === false && typeof oldVnode.props[name] !== "function" && reservedWords.indexOf(name) === -1) { - if (name in newVnode.dom) { - newVnode.dom[name] = null; - } else { - newVnode.dom.removeAttribute(name); - } - } - } - } - - const callRemove = (vnode: Vnode) => { - for (let i = 0, l = vnode.children.length; i < l; i++) { - vnode.children[i] instanceof Vnode && callRemove(vnode.children[i]); - } - - vnode.props.onremove && vnode.props.onremove(vnode); - }; - // Patch a DOM node with a new VNode tree - function patch(newParentVnode: Vnode & { dom: DomElement }, oldParentVnode?: Vnode & { dom: DomElement }): void { - let oldTree = oldParentVnode?.children || []; - let newTree = newParentVnode.children; - let oldTreeLength = oldTree.length; - - current.parentVnode = newParentVnode; - current.oldParentVnode = oldParentVnode; - - // Flat newTree - for (let i = 0; i < newTree.length; i++) { - let childVnode = newTree[i]; - - if (childVnode instanceof Vnode) { - childVnode.isSVG = newParentVnode.isSVG || childVnode.name === "svg"; - } else if (childVnode === null || childVnode === undefined) { - newTree.splice(i--, 1); - } else if (Array.isArray(childVnode)) { - newTree.splice(i--, 1, ...childVnode); - } else if (childVnode instanceof VnodeComponent) { - v.current.component = childVnode; - newTree.splice( - i--, - 1, - ...[ - "view" in childVnode.component - ? childVnode.component.view.call(childVnode.component, childVnode.props, childVnode.children) - : (childVnode.component as Component).call(childVnode.component, childVnode.props, childVnode.children) - ] - ); - } else { - if (i > 0 && newTree[i - 1].nodeValue) { - newTree[i - 1].nodeValue += childVnode; - newTree.splice(i--, 1); - } else if (childVnode instanceof TextVnode === false) { - newTree[i] = new TextVnode(String(childVnode)); - } - } - } - - let newTreeLength = newTree.length; - - // if newTree is empty, remove it - if (newTreeLength === 0) { - if (oldTreeLength > 0) { - for (let i = oldTreeLength; i--; ) { - oldTree[i] instanceof Vnode && callRemove(oldTree[i]); - } - // Fast node remove by setting textContent - newParentVnode.dom.textContent = ""; - } - // If the tree is keyed list and is not first render - } else if (oldTreeLength && newTree[0] instanceof Vnode && "key" in newTree[0].props) { - // 1. Mutate the old key list to match the new key list - let oldKeyedList; - - // if the oldTree does not have a keyed list fast remove all nodes - if (oldTree[0] instanceof Vnode === false || "key" in oldTree[0].props === false) { - for (let i = oldTreeLength; i--; ) { - oldTree[i] instanceof Vnode && callRemove(oldTree[i]); - } - // Fast node remove by setting textContent - newParentVnode.dom.textContent = ""; - oldKeyedList = []; - } else { - oldKeyedList = oldTree.map((vnode) => vnode.props.key); - } - - // 2. Obtain the max length of both lists - let newKeyedList = newTree.map((vnode) => vnode.props.key); - const maxListLength = Math.max(newTreeLength, oldKeyedList.length); - - // 3. Cycle over all the elements of the list until the max length - for (let i = 0; i < maxListLength; i++) { - if (i < newTreeLength) { - let childVnode = newTree[i]; - let oldChildVnode = oldKeyedList[i] === newKeyedList[i] ? oldTree[i] : oldTree[oldKeyedList.indexOf(childVnode.props.key)]; - let shouldPatch = true; - - if (oldChildVnode) { - childVnode.dom = oldChildVnode.dom; - oldChildVnode.processed = true; - if ("v-once" in childVnode.props || (childVnode.props.onbeforeupdate && childVnode.props.onbeforeupdate(childVnode, oldChildVnode) === false)) { - // skip this patch - childVnode.children = oldChildVnode.children; - shouldPatch = false; - } else { - removeProperties(childVnode as Vnode & { dom: DomElement }, oldChildVnode); - updateProperties(childVnode as Vnode & { dom: DomElement }, oldChildVnode); - if (v.isMounted) { - childVnode.props.onupdate && childVnode.props.onupdate(childVnode, oldChildVnode); - } else { - childVnode.props.oncreate && childVnode.props.oncreate(childVnode); - } - } - } else { - childVnode.dom = createElement(childVnode.name, childVnode.isSVG); - updateProperties(childVnode as Vnode & { dom: DomElement }); - childVnode.props.oncreate && childVnode.props.oncreate(childVnode); - } - - if (newParentVnode.dom.childNodes[i] === undefined) { - newParentVnode.dom.appendChild(childVnode.dom); - } else if (newParentVnode.dom.childNodes[i] !== childVnode.dom) { - oldTree[i] instanceof Vnode && !oldTree[i].processed && newKeyedList.indexOf(oldTree[i].props.key) === -1 && callRemove(oldTree[i]); - newParentVnode.dom.replaceChild(childVnode.dom, newParentVnode.dom.childNodes[i]); - } - - shouldPatch && patch(childVnode as Vnode & { dom: DomElement }, oldChildVnode); - } else { - if (!oldTree[i].processed) { - oldTree[i] instanceof Vnode && callRemove(oldTree[i]); - oldTree[i].dom.parentNode && newParentVnode.dom.removeChild(oldTree[i].dom); - } - } - } - } else { - for (let i = 0; i < newTreeLength; i++) { - let childVnode = newTree[i]; - let oldChildVnode = oldTree[i]; - - // if oldChildVnode is undefined, it's a new node, append it - if (oldChildVnode === undefined) { - if (childVnode instanceof Vnode) { - childVnode.dom = createElement(childVnode.name, childVnode.isSVG); - updateProperties(childVnode as Vnode & { dom: DomElement }); - childVnode.props.oncreate && childVnode.props.oncreate(childVnode); - patch(childVnode as Vnode & { dom: DomElement }); - } else { - childVnode.dom = document.createTextNode(childVnode.nodeValue); - } - newParentVnode.dom.appendChild(childVnode.dom); - } else { - // if childVnode is Vnode, replace it with its DOM node - if (childVnode instanceof Vnode) { - if (childVnode.name === oldChildVnode.name) { - childVnode.dom = oldChildVnode.dom; - - if ("v-once" in childVnode.props || (childVnode.props.onbeforeupdate && childVnode.props.onbeforeupdate(childVnode, oldChildVnode) === false)) { - // skip this patch - childVnode.children = oldChildVnode.children; - continue; - } - - removeProperties(childVnode as Vnode & { dom: DomElement }, oldChildVnode); - updateProperties(childVnode as Vnode & { dom: DomElement }, oldChildVnode); - if (v.isMounted) { - childVnode.props.onupdate && childVnode.props.onupdate(childVnode, oldChildVnode); - } else { - childVnode.props.oncreate && childVnode.props.oncreate(childVnode); - } - patch(childVnode as Vnode & { dom: DomElement }, oldChildVnode); - } else { - childVnode.dom = createElement(childVnode.name, childVnode.isSVG); - updateProperties(childVnode as Vnode & { dom: DomElement }); - childVnode.props.oncreate && childVnode.props.oncreate(childVnode); - oldChildVnode instanceof Vnode && callRemove(oldChildVnode); - newParentVnode.dom.replaceChild(childVnode.dom, oldChildVnode.dom); - patch(childVnode as Vnode & { dom: DomElement }); - } - } else { - if (oldChildVnode instanceof Vnode) { - childVnode.dom = document.createTextNode(childVnode.nodeValue); - callRemove(oldChildVnode); - newParentVnode.dom.replaceChild(childVnode.dom, oldChildVnode.dom as DomElement); - } else { - childVnode.dom = oldChildVnode.dom; - // eslint-disable-next-line eqeqeq - if (childVnode.nodeValue != childVnode.dom.nodeValue) { - childVnode.dom.nodeValue = childVnode.nodeValue; - } - } - } - } - } - - // For remaining old children: remove from DOM, garbage collect - for (let i = oldTreeLength - 1; i >= newTreeLength; --i) { - oldTree[i] instanceof Vnode && callRemove(oldTree[i]); - oldTree[i].dom.parentNode && newParentVnode.dom.removeChild(oldTree[i].dom); - } - } - - newParentVnode.children = newTree; - } - - let mainVnode: Vnode | null = null; - let oldMainVnode: Vnode | null = null; - - v.unMount = () => { - mountedComponent = emptyComponent; - let result = v.update(); - v.isMounted = false; - mainContainer = null; - return result; - }; - - v.update = (props, ...children) => { - if (mainVnode) { - cleanupVnodes(); - oldMainVnode = mainVnode; - mainVnode = new Vnode(mainVnode.name, mainVnode.props, [v(mountedComponent, props, ...children)]); - mainVnode.dom = oldMainVnode.dom; - mainVnode.isSVG = oldMainVnode.isSVG; - patch(mainVnode as Vnode & { dom: Node }, oldMainVnode as Vnode & { dom: Node }); - v.isMounted = true; - if (v.isNode) { - return (mainVnode.dom as HTMLElement).innerHTML; - } - } - }; - - v.mount = (container, component, props, ...children) => { - if (v.isMounted) { - v.unMount(); - } - - if (isNode) { - mainContainer = typeof container === "string" ? createElement(container, container === "svg") : container; - } else { - mainContainer = typeof container === "string" ? (document.querySelectorAll(container)[0] as DomElement) : container; - } - - if (mainContainer !== null) { - mainVnode = domToVnode(mainContainer); - mainVnode.isSVG = mainVnode.name === "svg"; - oldMainVnode = mainVnode; - mountedComponent = component; - } - - return v.update(props, ...children); - }; - - let directives: Record = {}; - - v.directive = (name: string, directive: Directive) => { - let fullName = `v-${name}`; - if (reservedWords.indexOf(fullName) === -1) { - reservedWords.push(fullName); - directives[fullName] = directive; - } - }; - - let hideDirective = (test: boolean) => (bool: boolean, vnode: Vnode, oldnode?: Vnode | TextVnode) => { - let value = test ? bool : !bool; - if (value) { - let newdom = document.createTextNode(""); - if (oldnode && oldnode.dom && oldnode.dom.parentNode) { - oldnode instanceof Vnode && callRemove(oldnode); - oldnode.dom.parentNode.replaceChild(newdom, oldnode.dom); - } - vnode.name = "#text"; - vnode.children = []; - vnode.props = {}; - vnode.dom = newdom as unknown as DomElement; - return false; - } - }; - - v.directive("if", hideDirective(false)); - v.directive("unless", hideDirective(true)); - v.directive("for", (set: unknown[], vnode: Vnode) => { - vnode.children = set.map(vnode.children[0] as (value: unknown) => Function); - }); - v.directive("show", (bool: boolean, vnode: Vnode) => { - (vnode.dom as { style: { display: string } }).style.display = bool ? "" : "none"; - }); - v.directive("class", (classes: { [x: string]: boolean }, vnode: Vnode) => { - for (let name in classes) { - (vnode.dom as DomElement).classList.toggle(name, classes[name]); - } - }); - v.directive("html", (html: string, vnode: Vnode) => { - vnode.children = [trust(html)]; - }); - - v.newInstance = valyrian; - - return v; -} - -((isNode ? global : window) as unknown as { v: Valyrian }).v = valyrian(); diff --git a/package.json b/package.json index 7044c88..5d3066d 100644 --- a/package.json +++ b/package.json @@ -191,4 +191,4 @@ "resolutions": { "minimist": "^1.2.5" } -} +} \ No newline at end of file diff --git a/plugins/hooks.js b/plugins/hooks.js index ccc0a3d..00667c7 100644 --- a/plugins/hooks.js +++ b/plugins/hooks.js @@ -1,54 +1,54 @@ -const UND = undefined; - -function createHook({ init, update, response, cleanup }) { +function createHook({ create, update, response, cleanup }) { return (...args) => { let { component, vnode, oldVnode, app } = v.current; - // Init the components array for the current vnode - if (vnode.components === UND) { - vnode.components = []; - } + if (vnode && component && app) { + // Init the components array for the current vnode + if (vnode.components === undefined) { + vnode.components = []; + } - // Add the component to the components array if it's not already there - if (vnode.components.indexOf(component) === -1) { - vnode.components.push(component); - } + // Add the component to the components array if it's not already there + if (vnode.components.indexOf(component) === -1) { + vnode.components.push(component); + } - // Init the component hooks array - if (component.hooks === UND) { - component.hooks = []; - } + // Init the component hooks array + if (component.hooks === undefined) { + component.hooks = []; + } - let componentIndex = vnode.components.length - 1; - let oldComponent = ((oldVnode || {}).components || [])[componentIndex]; - let hook; - let hookIndex = component.hooks.length - 1; + let componentIndex = vnode.components.length - 1; + let oldComponent = oldVnode && oldVnode.components && oldVnode.components[componentIndex]; + let hook; + let hookIndex = component.hooks.length - 1; - if (oldComponent === component) { - component.hooks = oldComponent.hooks; - hook = oldComponent.hooks[hookIndex]; - if (update) { - update(hook, ...args); + if (oldComponent === component) { + component.hooks = oldComponent.hooks; + hook = oldComponent.hooks[hookIndex]; + if (update) { + update(hook, ...args); + } + } else { + hook = create(...args); + component.hooks.push(hook); } - } else { - hook = init(...args); - component.hooks.push(hook); - } - if (cleanup) { - app.cleanup.push(() => cleanup(hook)); - } + if (cleanup) { + app.cleanup.push(() => cleanup(hook)); + } - if (response) { - return response(hook); - } else { - return hook; + if (response) { + return response(hook); + } else { + return hook; + } } }; } const useState = createHook({ - init: (value) => { + create: (value) => { let state = value; let setState = (value) => (state = value); @@ -76,7 +76,7 @@ function callEffectHook(hook, changes) { } } const useEffect = createHook({ - init: (effect, changes) => { + create: (effect, changes) => { let hook = { effect, prev: changes }; callEffectHook(hook); return hook; @@ -89,11 +89,6 @@ const useEffect = createHook({ } }); -let exports = { - createHook, - useState, - useEffect -}; - -exports.default = exports; -module.exports = exports; +const plugin = { useState, useEffect, createHook }; +plugin.default = plugin; +module.exports = plugin; diff --git a/plugins/node.js b/plugins/node.js index 32aaf57..30726df 100644 --- a/plugins/node.js +++ b/plugins/node.js @@ -1,5 +1,5 @@ /* eslint-disable sonarjs/cognitive-complexity */ -import { mount } from "../lib"; +const { mount, unmount } = require("../lib"); let fs = require("fs"); let path = require("path"); @@ -26,182 +26,91 @@ let errorHandler = (resolve, reject) => (err) => { resolve(); }; -function fileMethodFactory() { - let prop = []; - return function (file, options = {}) { - if (!file) { - return prop; - } +async function inline(file, options = {}) { + if (typeof file === "string") { + let ext = file.split(".").pop(); + if (/(js|cjs|jsx|mjs|ts|tsx)/.test(ext)) { + if (/(ts|tsx)/.test(ext) && !options.noValidate) { + let declarationDir = options.declarationDir; + let emitDeclaration = !!declarationDir; + + let tscProgOptions = { + basePath: process.cwd(), // always required, used for relative paths + configFilePath: "tsconfig.json", // config to inherit from (optional) + files: [file], + include: ["**/*.ts", "**/*.js", "**/*.tsx", "**/*.jsx", "**/*.mjs"], + exclude: ["test*/**/*", "**/*.test.ts", "**/*.spec.ts", "dist/**"], + pretty: true, + copyOtherToOutDir: false, + clean: emitDeclaration ? [declarationDir] : [], + ...(options.tsc || {}), + compilerOptions: { + rootDir: "./", + outDir: "dist", + noEmitOnError: true, + noEmit: !emitDeclaration, + declaration: emitDeclaration, + declarationDir, + emitDeclarationOnly: emitDeclaration, + allowJs: true, + esModuleInterop: true, + inlineSourceMap: true, + resolveJsonModule: true, + removeComments: true, + ...(options.tsc || {}).compilerOptions + }, + jsxFactory: "v", + jsxFragment: "v.fragment" + }; - let asyncMethod = async () => { - let contents = ""; - if (typeof file === "string") { - let ext = file.split(".").pop(); - if (/(js|jsx|mjs|ts|tsx)/.test(ext)) { - if (/(ts|tsx)/.test(ext) && !options.noValidate) { - let declarationDir = options.declarationDir; - let emitDeclaration = !!declarationDir; - - let tscProgOptions = { - basePath: process.cwd(), // always required, used for relative paths - configFilePath: "tsconfig.json", // config to inherit from (optional) - files: [file], - include: ["**/*.ts", "**/*.js", "**/*.tsx", "**/*.jsx", "**/*.mjs"], - exclude: ["test*/**/*", "**/*.test.ts", "**/*.spec.ts", "dist/**"], - pretty: true, - copyOtherToOutDir: false, - clean: emitDeclaration ? [declarationDir] : [], - ...(options.tsc || {}), - compilerOptions: { - rootDir: "./", - outDir: "dist", - noEmitOnError: true, - noEmit: !emitDeclaration, - declaration: emitDeclaration, - declarationDir, - emitDeclarationOnly: emitDeclaration, - allowJs: true, - esModuleInterop: true, - inlineSourceMap: true, - resolveJsonModule: true, - removeComments: true, - ...(options.tsc || {}).compilerOptions - }, - jsxFactory: "v", - jsxFragment: "v.fragment" - }; - - console.log("tsc", tscProgOptions); - - tsc.build(tscProgOptions); - } + // eslint-disable-next-line no-console + console.log("tsc", tscProgOptions); - let esbuildOptions = { - entryPoints: [file], - bundle: true, - sourcemap: "external", - write: false, - minify: options.compact, - outdir: "out", - target: "esnext", - jsxFactory: "v", - jsxFragment: "v.fragment", - loader: { ".js": "jsx", ".ts": "tsx", ".mjs": "jsx" }, - ...(options.esbuild || {}) - }; - - console.log(esbuildOptions); - - let result = esbuild.buildSync(esbuildOptions); - - if (options.compact) { - let result2 = await terser.minify(result.outputFiles[1].text, { - sourceMap: { - content: result.outputFiles[0].text.toString() - }, - compress: { - booleans_as_integers: false - }, - output: { - wrap_func_args: false - }, - ecma: 2020, - ...(options.terser || {}) - }); - - let mapBase64 = Buffer.from(result2.map.toString()).toString("base64"); - let suffix = `//# sourceMappingURL=data:application/json;charset=utf-8;base64,${mapBase64}`; - contents = { raw: result2.code, map: suffix, file }; - } else { - let mapBase64 = Buffer.from(result.outputFiles[0].text.toString()).toString("base64"); - let suffix = `//# sourceMappingURL=data:application/json;charset=utf-8;base64,${mapBase64}`; - contents = { raw: result.outputFiles[1].text, map: suffix, file }; - } - } else if (/(css|scss|styl)/.test(ext)) { - let result = new CleanCSS({ - sourceMap: true, - level: { - 1: { - roundingPrecision: "all=3" - }, - 2: { - restructureRules: true // controls rule restructuring; defaults to false - } - } - }).minify([file]); - - contents = { raw: result.styles, map: null, file }; - } else { - contents = { raw: fs.readFileSync(file, "utf8"), map: null, file }; - } - } else if (typeof file === "object" && "raw" in file) { - contents = { map: null, ...file }; + tsc.build(tscProgOptions); } - prop.push(contents); - return prop; - }; - - return asyncMethod(); - }; -} - -async function inline(...args) { - for (let item of args) { - let ext = item.split(".").pop(); - if (!inline[ext]) { - inline[ext] = fileMethodFactory(); - } - await inline[ext](item); - } -} - -inline.extensions = (...extensions) => { - for (let ext of extensions) { - if (!inline[ext]) { - inline[ext] = fileMethodFactory(); - } - } -}; - -inline.css = fileMethodFactory(); -inline.js = fileMethodFactory(); - -inline.uncss = (function () { - let prop = ""; - return function (renderedHtml, options = {}) { - if (!renderedHtml) { - return prop; - } - - let asyncMethod = async () => { - let html = await Promise.all(renderedHtml); - - let contents = html.map((item) => { - return { - raw: item, - extension: "html" - }; - }); - - let purgecss = new PurgeCSS(); - let css = inline - .css() - .map((item) => item.raw) - .join(""); - - let output = await purgecss.purge({ - fontFace: true, - keyframes: true, - variables: true, - defaultExtractor: (content) => content.match(/[A-Za-z0-9-_/:@]*[A-Za-z0-9-_/:@/]+/g) || [], - ...options, - content: contents, - css: [{ raw: css }] - }); - - prop = new CleanCSS({ - sourceMap: false, + let esbuildOptions = { + entryPoints: [file], + bundle: true, + sourcemap: "external", + write: false, + minify: options.compact, + outdir: "out", + target: "esnext", + jsxFactory: "v", + jsxFragment: "v.fragment", + loader: { ".js": "jsx", ".ts": "tsx", ".mjs": "jsx" }, + ...(options.esbuild || {}) + }; + + let result = esbuild.buildSync(esbuildOptions); + + if (options.compact) { + let result2 = await terser.minify(result.outputFiles[1].text, { + sourceMap: { + content: result.outputFiles[0].text.toString() + }, + compress: { + booleans_as_integers: false + }, + output: { + wrap_func_args: false + }, + ecma: 2020, + ...(options.terser || {}) + }); + + let mapBase64 = Buffer.from(result2.map.toString()).toString("base64"); + let suffix = `//# sourceMappingURL=data:application/json;charset=utf-8;base64,${mapBase64}`; + return { raw: result2.code, map: suffix, file }; + } else { + let mapBase64 = Buffer.from(result.outputFiles[0].text.toString()).toString("base64"); + let suffix = `//# sourceMappingURL=data:application/json;charset=utf-8;base64,${mapBase64}`; + return { raw: result.outputFiles[1].text, map: suffix, file }; + } + } else if (/(css|scss|styl)/.test(ext)) { + let result = new CleanCSS({ + sourceMap: true, level: { 1: { roundingPrecision: "all=3" @@ -209,15 +118,54 @@ inline.uncss = (function () { 2: { restructureRules: true // controls rule restructuring; defaults to false } - } - }).minify(output[0].css).styles; + }, + ...(options.cleanCss || {}) + }).minify([file]); + + return { raw: result.styles, map: null, file }; + } else { + return { raw: fs.readFileSync(file, "utf8"), map: null, file }; + } + } else if (typeof file === "object" && "raw" in file) { + return { map: null, ...file }; + } +} - return prop; +inline.uncss = async function (renderedHtml, css, options = {}) { + let html = await Promise.all(renderedHtml); + + let contents = html.map((item) => { + return { + raw: item, + extension: "html" }; + }); - return asyncMethod(); - }; -})(); + let purgecss = new PurgeCSS(); + + let output = await purgecss.purge({ + fontFace: true, + keyframes: true, + variables: true, + defaultExtractor: (content) => content.match(/[A-Za-z0-9-_/:@]*[A-Za-z0-9-_/:@/]+/g) || [], + ...options, + content: contents, + css: [{ raw: css }] + }); + + return new CleanCSS({ + sourceMap: false, + level: { + 1: { + roundingPrecision: "all=3" + }, + 2: { + restructureRules: true // controls rule restructuring; defaults to false + } + }, + ...(options.cleanCss || {}) + }).minify(output[0].css).styles; +}; function sw(file, options = {}) { let swfiletemplate = path.resolve(__dirname, "./node.sw.tpl.js"); @@ -355,7 +303,12 @@ let plugin = { domToHtml: treeAdapter.domToHtml, domToHyperscript: treeAdapter.domToHyperscript, htmlToHyperscript: treeAdapter.htmlToHyperscript, - hyperscriptToHtml: (...args) => mount("div", () => args) + render: (...args) => { + let Component = () => args; + let result = mount("div", Component); + unmount(Component); + return result; + } }; plugin.default = plugin; diff --git a/plugins/request.js b/plugins/request.js index 5e51f38..0a7e87d 100644 --- a/plugins/request.js +++ b/plugins/request.js @@ -1,4 +1,4 @@ -const { isNodeJs } = require("../lib"); +const isNodeJs = Boolean(typeof process !== "undefined" && process.versions && process.versions.node); function serialize(obj, prefix) { return Object.keys(obj) @@ -35,6 +35,7 @@ function parseUrl(url, options = {}) { return u; } +// eslint-disable-next-line sonarjs/cognitive-complexity function Request(baseUrl = "", options = {}) { let url = baseUrl.replace(/\/$/gi, "").trim(); options.urls = options.urls || {}; diff --git a/plugins/router.js b/plugins/router.js index dc6c8be..dd99199 100644 --- a/plugins/router.js +++ b/plugins/router.js @@ -1,4 +1,4 @@ -import { isComponent, isNodeJs, isVnodeComponent, mount, updateProperty, v } from "../lib"; +const { mount, updateProperty, directive, isNodeJs, isComponent, isVnodeComponent } = require("../lib/index"); function flat(array) { return Array.isArray(array) ? array.flat(Infinity) : [array]; @@ -195,32 +195,9 @@ class Router { return mount(this.container, component); } - mount(elementContainer, options = {}) { + mount(elementContainer) { if (elementContainer) { this.container = elementContainer; - this.options = { ...options }; - this.options.directives = { - ...(this.options.directives || {}), - route: (url, vnode, oldnode) => { - vnode.props.href = url; - vnode.props.onclick = (e) => { - if (typeof url === "string" && url.length > 0) { - if (url.charAt(0) !== "/") { - let current = this.current.split("?", 2).shift().split("/"); - current.pop(); - url = `${current.join("/")}/${url}`; - } - - this.go(url); - } - e.preventDefault(); - }; - - updateProperty("href", vnode, oldnode); - updateProperty("onclick", vnode, oldnode); - } - }; - // Activate the use of the router if (!isNodeJs) { function onPopStateGoToRoute() { @@ -229,6 +206,25 @@ class Router { window.addEventListener("popstate", onPopStateGoToRoute.bind(this), false); onPopStateGoToRoute(); } + + directive("route", (url, vnode, oldnode) => { + vnode.props.href = url; + vnode.props.onclick = (e) => { + if (typeof url === "string" && url.length > 0) { + if (url.charAt(0) !== "/") { + let current = this.current.split("?", 2).shift().split("/"); + current.pop(); + url = `${current.join("/")}/${url}`; + } + + this.go(url); + } + e.preventDefault(); + }; + + updateProperty("href", vnode, oldnode); + updateProperty("onclick", vnode, oldnode); + }); } } } diff --git a/plugins/signals.js b/plugins/signals.js index 0abcffc..304ac01 100644 --- a/plugins/signals.js +++ b/plugins/signals.js @@ -106,6 +106,7 @@ function Signal(value, key) { value: { value, writable: true, enumerable: true }, cleanup: { value() { + // eslint-disable-next-line no-unused-vars for (let [handler, computed] of subscriptions) { computed.unsubscribe(); } diff --git a/plugins/sw.js b/plugins/sw.js index 7108b42..61b1150 100644 --- a/plugins/sw.js +++ b/plugins/sw.js @@ -1,5 +1,3 @@ -const { isNodeJs } = require("../lib"); - class Sw { file = "/sw.js"; options = { scope: "/" }; @@ -7,7 +5,7 @@ class Sw { sw = null; constructor(file, options) { - if (isNodeJs) { + if (Boolean(typeof process !== "undefined" && process.versions && process.versions.node)) { throw new Error("Not supported in Node.js"); } diff --git a/plugins/v-model.js b/plugins/v-model.js deleted file mode 100644 index a4725d8..0000000 --- a/plugins/v-model.js +++ /dev/null @@ -1,91 +0,0 @@ -const { directive, updateProperty } = require("../lib"); - -let plugin = function () { - // eslint-disable-next-line sonarjs/cognitive-complexity - directive("model", ([model, property, event], vnode, oldVnode) => { - if (vnode.name === "input") { - event = event || "oninput"; - switch (vnode.props.type) { - case "checkbox": { - if (Array.isArray(model[property])) { - vnode.props[event] = (e) => { - let val = e.target.value; - let idx = model[property].indexOf(val); - if (idx === -1) { - model[property].push(val); - } else { - model[property].splice(idx, 1); - } - }; - vnode.props.checked = model[property].indexOf(vnode.dom.value) !== -1; - } else if ("value" in vnode.props) { - vnode.props[event] = () => { - if (model[property] === vnode.props.value) { - model[property] = null; - } else { - model[property] = vnode.props.value; - } - }; - vnode.props.checked = model[property] === vnode.props.value; - } else { - vnode.props[event] = () => (model[property] = !model[property]); - vnode.props.checked = model[property]; - } - - v.updateProperty("checked", vnode, oldvnode); - break; - } - case "radio": { - vnode.props.checked = model[property] === vnode.dom.value; - v.updateProperty("checked", vnode, oldvnode); - break; - } - default: { - vnode.props.value = model[property]; - v.updateProperty("value", vnode, oldvnode); - } - } - } else if (vnode.name === "select") { - event = event || "onclick"; - if (vnode.props.multiple) { - vnode.props[event] = (e) => { - let val = e.target.value; - if (e.ctrlKey) { - let idx = model[property].indexOf(val); - if (idx === -1) { - model[property].push(val); - } else { - model[property].splice(idx, 1); - } - } else { - model[property].splice(0, model[property].length); - model[property].push(val); - } - }; - vnode.children.forEach((child) => { - if (child.name === "option") { - let value = "value" in child.props ? child.props.value : child.children.join("").trim(); - child.props.selected = model[property].indexOf(value) !== -1; - } - }); - } else { - vnode.children.forEach((child) => { - if (child.name === "option") { - let value = "value" in child.props ? child.props.value : child.children.join("").trim(); - child.props.selected = value === model[property]; - } - }); - } - } else if (vnode.name === "textarea") { - event = event || "oninput"; - vnode.children = [model[property]]; - } - - if (!vnode.props[event]) { - updateProperty(event, (e) => (model[property] = e.target.value), vnode, oldVnode, valyrianApp); - } - }); -}; - -plugin.default = plugin; -module.exports = plugin; diff --git a/register.js b/register.js index c92b2c0..f0466fb 100644 --- a/register.js +++ b/register.js @@ -1,6 +1,5 @@ const { addHook } = require("pirates"); const { transformSync } = require("esbuild"); -const fs = require("fs"); addHook( (code, filePath) => { @@ -8,10 +7,8 @@ addHook( let extension = fileName.split(".").pop(); let loader = "default"; - if (["js", "jsx", "ts", "tsx", "css", "json", "txt"].includes(extension)) { - if (["js", "jsx", "mjs"].includes(extension)) { - loader = "tsx"; - } else if (["ts", "tsx"].includes(extension)) { + if (["js", "cjs", "jsx", "ts", "tsx", "css", "json", "txt"].includes(extension)) { + if (["js", "cjs", "jsx", "mjs", "ts", "tsx"].includes(extension)) { loader = "tsx"; } else if (extension === "txt") { loader = "text"; @@ -23,7 +20,7 @@ addHook( } let options = { - sourcefile: fileName, + sourcefile: filePath, sourcemap: "inline", minify: false, target: "esnext", diff --git a/source.js b/source.js index d8b95df..2176da9 100644 --- a/source.js +++ b/source.js @@ -1,25 +1,205 @@ -require("./register.js"); -let { inline } = require("./plugins/node"); -let { writeFileSync } = require("fs"); -const GzipSize = import("gzip-size"); -let { files } = require("./package.json"); - -async function run() { - const gzipSizeSync = (await GzipSize).gzipSizeSync; - inline.extensions("ts"); - await inline.ts("./lib/index.ts", { - compact: false, - declarationDir: "dist/@types", - tsc: { - include: files - } +const esbuild = require("esbuild"); +const terser = require("terser"); +const tsc = require("tsc-prog"); +const fs = require("fs"); +const zlib = require("zlib"); + +function convertToUMD(text, globalName) { + // HACK: convert to UMD - only supports cjs and global var + const varName = "__EXPORTS__"; + let code = text; + code = code.replace(/export\s*\{([^{}]+)\}/, (_, inner) => { + const defaultExport = inner.match(/^(\w+) as default$/); + return defaultExport != null ? `var ${varName}=${defaultExport[1]}` : `var ${varName}={${inner.replace(/(\w+) as (\w+)/g, "$2:$1")}}`; }); - let contents = inline.ts()[0].raw; - writeFileSync("./dist/valyrian.min.js", contents); - writeFileSync("./dist/valyrian.min.js.map", inline.ts()[0].map); + code = `(()=>{${code};typeof module!=='undefined'?module.exports=${varName}:self.${globalName}=${varName}})()`; + return code; +} + +function getSourceMap(contents) { + let mapBase64 = Buffer.from(contents.toString()).toString("base64"); + return `//# sourceMappingURL=data:application/json;charset=utf-8;base64,${mapBase64}`; +} + +async function build({ globalName, entryPoint, outfileName, clean = false, minify = true, external = [], bundle = true }) { + try { + let header = `/************ ${entryPoint} ************/`; + console.log(""); + console.log(header); + + let tscProgOptions2 = { + basePath: process.cwd(), // always required, used for relative paths + configFilePath: "tsconfig.json", // config to inherit from (optional) + files: [entryPoint], + pretty: true, + copyOtherToOutDir: false, + clean: clean ? ["types", "dist"] : [], + compilerOptions: { + rootDir: "./", + declaration: true, + declarationDir: "./types", + emitDeclarationOnly: true + } + }; + + tsc.build(tscProgOptions2); + let cjs = esbuild.buildSync({ + entryPoints: [entryPoint], + bundle, + sourcemap: "external", + write: false, + minify: false, + outdir: "out", + target: "esnext", + loader: { ".js": "jsx", ".ts": "tsx", ".mjs": "jsx" }, + format: "cjs", + metafile: true, + external + }); + + let esm = esbuild.buildSync({ + entryPoints: [entryPoint], + bundle, + sourcemap: "external", + write: false, + minify: false, + outdir: "out", + target: "esnext", + loader: { ".js": "jsx", ".ts": "tsx", ".mjs": "jsx" }, + format: "esm", + metafile: true, + external + }); + + let esmContent = esm.outputFiles[1].text; + + // HACK: simulate __dirname and __filename for esm + if (esmContent.indexOf("__dirname") !== -1 || esmContent.indexOf("__filename") !== -1) { + esmContent = + `import { fileURLToPath } from 'url'; const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); ` + esmContent; + if (esmContent.indexOf("import path from") === -1) { + esmContent = `import path from 'path'; ` + esmContent; + } + } + + // ensure outdir exists or create it + let outdir = outfileName.split("/").slice(0, -1).join("/"); + if (!fs.existsSync(outdir)) { + fs.mkdirSync(outdir, { recursive: true }); + } + + fs.writeFileSync(`${outfileName}.js`, esmContent); + // fs.writeFileSync(`${outfileName}.mjs.map`, getSourceMap(esm.outputFiles[0].text)); + fs.writeFileSync(`${outfileName}.cjs`, cjs.outputFiles[1].text); + // fs.writeFileSync(`${outfileName}.js.map`, getSourceMap(cjs.outputFiles[0].text)); - console.log("Size:", contents.length); - console.log("Gzip:", gzipSizeSync(contents)); + let text = await esbuild.analyzeMetafile(esm.metafile, { verbose: true }); + console.log(text); + + let result2; + if (minify) { + let code = convertToUMD(esm.outputFiles[1].text, globalName); + result2 = await terser.minify(code, { + sourceMap: { + content: esm.outputFiles[0].text.toString() + }, + compress: { + booleans_as_integers: false + }, + output: { + wrap_func_args: false + }, + ecma: 2020 + }); + + fs.writeFileSync(`${outfileName}.min.js`, result2.code); + fs.writeFileSync(`${outfileName}.min.js.map`, getSourceMap(result2.map)); + } + + function formatBytesToKiloBytes(bytes) { + return (bytes / 1024).toFixed(2) + "kb"; + } + + console.log("Esm", formatBytesToKiloBytes(esm.outputFiles[1].text.length)); + if (minify) { + console.log("Minified:", formatBytesToKiloBytes(result2.code.length)); + // Get the size using gzip compression + const gzip = zlib.gzipSync(result2.code); + console.log("Gzip:", formatBytesToKiloBytes(gzip.length)); + // Get the size using brotli algorithm + const brotli = zlib.brotliCompressSync(result2.code); + console.log("Brotli:", formatBytesToKiloBytes(brotli.length)); + } + console.log(`/${Array(header.length).fill("*").join("")}/`); + } catch (e) { + console.error(e); + } } -run(); +(async () => { + await build({ + globalName: "Valyrian", + entryPoint: "./lib/index.ts", + outfileName: "./dist/index", + clean: true, + minify: true, + bundle: true + }); + + // await build({ + // globalName: "ValyrianHooks", + // entryPoint: "./plugins/hooks.ts", + // outfileName: "./dist/hooks", + // clean: false, + // minify: false + // }); + + // await build({ + // globalName: "ValyrianRequest", + // entryPoint: "./plugins/request.js", + // outfileName: "./dist/request", + // clean: false, + // minify: false + // }); + + // await build({ + // globalName: "ValyrianRouter", + // entryPoint: "./plugins/router.js", + // outfileName: "./dist/router", + // clean: false, + // minify: false + // }); + + // await build({ + // globalName: "ValyrianSignals", + // entryPoint: "./plugins/signals.js", + // outfileName: "./dist/signals", + // clean: false, + // minify: false + // }); + + // await build({ + // globalName: "ValyrianStore", + // entryPoint: "./plugins/store.js", + // outfileName: "./dist/store", + // clean: false, + // minify: false + // }); + + // await build({ + // globalName: "ValyrianSw", + // entryPoint: "./plugins/sw.js", + // outfileName: "./dist/sw", + // clean: false, + // minify: false + // }); + + // await build({ + // globalName: 'ValyrianSignals', + // entryPoint: './plugins/signals.js', + // outfileName: './dist/signals', + // clean: false, + // minify: false, + // external: ['child_process', 'fs', 'os', 'path'] + // }); +})(); diff --git a/test/directives_test.js b/test/directives_test.js index 57b7804..7942695 100644 --- a/test/directives_test.js +++ b/test/directives_test.js @@ -26,6 +26,7 @@ describe("Directives", () => { let app = () =>
; directive("test2", (v, vnode, old) => { + console.log("here"); newVnode = vnode; oldVnode = old; }); @@ -92,7 +93,7 @@ describe("Directives", () => { /** * Modify properties is not guaranteed because the properties are processed by place - * If the directive needs to update previous properties you need to update the property using the v.updateProperty method + * If the directive needs to update previous properties you need to update the property using the updateProperty method */ it("Modify properties is not guaranteed", () => { let update = false; diff --git a/test/hooks_test.js b/test/hooks_test.js index 94bc2db..4e43fd7 100644 --- a/test/hooks_test.js +++ b/test/hooks_test.js @@ -1,7 +1,7 @@ import "../lib"; import "../plugins/node"; -import { cleanup, mount, unmount, update } from "../lib"; +import { cleanup, mount, unmount, update } from "../lib/index"; import { useEffect, useState } from "../plugins/hooks"; import expect from "expect"; diff --git a/test/keyed_test.js b/test/keyed_test.js index 074d98f..6bef201 100644 --- a/test/keyed_test.js +++ b/test/keyed_test.js @@ -1,4 +1,4 @@ -import { mount, update } from "../lib"; +import { mount, update } from "../lib/index"; import expect from "expect"; diff --git a/test/lifecycle_test.js b/test/lifecycle_test.js index ee3a2fa..8a6d1ed 100644 --- a/test/lifecycle_test.js +++ b/test/lifecycle_test.js @@ -1,6 +1,6 @@ import "../plugins/node"; -import { mount, update } from "../lib"; +import { mount, update } from "../lib/index"; import expect from "expect"; diff --git a/test/mount_n_update_test.js b/test/mount_n_update_test.js index efd4fb2..4c2098d 100644 --- a/test/mount_n_update_test.js +++ b/test/mount_n_update_test.js @@ -1,4 +1,4 @@ -import { Valyrian, mount, trust, update } from "../lib"; +import { mount, trust, update } from "../lib/index"; import expect from "expect"; diff --git a/test/node_test.js b/test/node_test.js index 2a4999e..1f9ace8 100644 --- a/test/node_test.js +++ b/test/node_test.js @@ -1,6 +1,6 @@ -import "../lib"; +import "../lib/index"; -import { htmlToHyperscript, hyperscriptToHtml, icons, inline, sw } from "../plugins/node"; +import { htmlToHyperscript, icons, inline, render, sw } from "../plugins/node"; import expect from "expect"; import fs from "fs"; @@ -84,7 +84,7 @@ describe("Node test", () => { it("Get html from hyperscript", () => { let Component = () =>
Hello world
; - expect(hyperscriptToHtml()).toEqual("
Hello world
"); + expect(render()).toEqual("
Hello world
"); }); it("Should create a service worker file", async () => { @@ -158,28 +158,21 @@ describe("Node test", () => { span{display:block;} span.hello{display: inline-block} `; - - await inline.css({ raw: css }); - let cleanCss = await inline.uncss([html]); + let cleanCss = await inline.uncss([html], css); expect(cleanCss).toEqual("span{display:block}"); }); it("should inline js", async () => { - inline.extensions("ts"); - // await inline.ts("./lib/index.ts.old", { outputOptions: { minify: true } }); - await inline.ts("./lib/index.ts", { compact: true }); - await inline.js("./bench/index-old.js", { compact: true }); - console.log(inline.ts()[0].raw.length); + let { raw: indexTs } = await inline("./lib/index.ts", { compact: true }); + let { raw: indexOld } = await inline("./bench/index-old.js", { compact: true }); + console.log(indexTs.length); // console.log(inline.ts()[1].raw.length); - console.log(inline.js()[0].raw.length); + console.log(indexOld.length); // console.log(inline.ts()[1].raw); // fs.writeFileSync("./dist/valyrian.lite.js", inline.ts()[1].raw); // expect(inline.ts()[0].raw.length).toBeLessThan(5115); - - let compiled = fs.readFileSync("./dist/valyrian.min.js", "utf8"); - console.log(compiled.length); }); }); diff --git a/test/request_test.js b/test/request_test.js index 0caac27..1699e30 100644 --- a/test/request_test.js +++ b/test/request_test.js @@ -1,4 +1,4 @@ -import "../lib"; +import "../lib/index"; import "../plugins/node"; import expect from "expect"; diff --git a/test/router_test.js b/test/router_test.js index 37e3ced..c21e37a 100644 --- a/test/router_test.js +++ b/test/router_test.js @@ -1,9 +1,9 @@ -import "../lib"; +import "../lib/index"; import "../plugins/node"; import Router from "../plugins/router"; import expect from "expect"; -import { update } from "../lib"; +import { update } from "../lib/index"; // eslint-disable-next-line max-lines-per-function describe("Router", () => { diff --git a/test/signals_test.js b/test/signals_test.js index cc62588..e3e29df 100644 --- a/test/signals_test.js +++ b/test/signals_test.js @@ -1,7 +1,7 @@ -import "../lib"; +import "../lib/index"; import "../plugins/node"; -import { mount, update } from "../lib"; +import { mount, update } from "../lib/index"; import Signal from "../plugins/signals"; import expect from "expect"; diff --git a/test/store_test.js b/test/store_test.js index e32214b..b97041d 100644 --- a/test/store_test.js +++ b/test/store_test.js @@ -1,4 +1,4 @@ -import "../lib"; +import "../lib/index"; import Store from "../plugins/store"; import expect from "expect"; diff --git a/tsconfig.json b/tsconfig.json index 9518268..a393984 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -6,7 +6,7 @@ "moduleResolution": "node", "esModuleInterop": true, "inlineSourceMap": true, - "allowJs": false, + "allowJs": true, "resolveJsonModule": true, "removeComments": true }, diff --git a/types/lib/index.d.ts b/types/lib/index.d.ts new file mode 100644 index 0000000..136c280 --- /dev/null +++ b/types/lib/index.d.ts @@ -0,0 +1,103 @@ +export interface DomElement extends Element { + [key: string]: any; +} +export interface Props { + key?: string | number; + data?: string; + oncreate?: { + (vnode: IVnode): never; + }; + onupdate?: { + (vnode: IVnode, oldVnode: IVnode): never; + }; + onremove?: { + (oldVnode: IVnode): never; + }; + shouldupdate?: { + (vnode: IVnode, oldVnode: IVnode): undefined | boolean; + }; + "v-cleanup"?: Function; + [key: string | number | symbol]: any; +} +export interface Children extends Array { +} +export interface IVnode { + new (tag: string, props: Props, children: IVnode[]): IVnode; + tag: string; + props: Props; + children: Children; + dom?: DomElement; + isSVG?: boolean; + processed?: boolean; + component?: Component | POJOComponent; + nodeValue?: string; + [key: string | number | symbol]: any; +} +export interface Component { + (props?: Record | null, children?: Children): IVnode | Children; + [key: string | number | symbol]: any; +} +export interface POJOComponent { + view: Component; + [key: string | number | symbol]: any; +} +export declare type ValyrianComponent = Component | POJOComponent; +export interface VnodeComponent extends IVnode { + tag: "__component__"; + component: ValyrianComponent; +} +export interface VnodeWithDom extends IVnode { + dom: DomElement; +} +export interface Directive { + (value: any, vnode: VnodeWithDom, oldVnode?: VnodeWithDom): void; +} +export interface ValyrianApp { + isMounted: boolean; + eventListenerNames: Record; + cleanup: Function[]; + eventListener?: EventListener; + mainVnode?: VnodeWithDom; + component?: VnodeComponent; + container?: DomElement; + [key: string | number | symbol]: any; +} +export interface MountedValyrianApp extends ValyrianApp { + eventListener: EventListener; + mainVnode: VnodeWithDom; + container: DomElement; + component: VnodeComponent; +} +export interface Current { + app?: ValyrianApp; + component?: ValyrianComponent; + vnode?: VnodeWithDom; + oldVnode?: VnodeWithDom; +} +export interface Directives { + [key: string]: Directive; +} +export interface ReservedProps { + [key: string]: true; +} +export interface Valyrian { + (tagOrComponent: string | ValyrianComponent, props: Props, ...children: Children): IVnode | VnodeComponent; + fragment: (props: Props, ...children: Children) => Children; + current: Current; + directives: Directives; + reservedProps: ReservedProps; +} +export declare const Vnode: IVnode; +export declare function isVnode(component?: unknown): component is IVnode; +export declare function isComponent(component?: unknown | ValyrianComponent): component is ValyrianComponent; +export declare function isVnodeComponent(vnode?: unknown): vnode is VnodeComponent; +export declare const isNodeJs: boolean; +export declare const trust: (htmlString: string) => IVnode[]; +export declare function cleanup(callback: Function): void; +export declare function mount(container: DomElement | string, component: ValyrianComponent | IVnode): any; +export declare function update(component?: ValyrianComponent | IVnode): any; +export declare function unmount(component?: ValyrianComponent | IVnode): string | undefined; +export declare function onremove(vnode: IVnode): void; +export declare function updateProperty(name: string, value: any, vnode: VnodeWithDom, oldVnode?: VnodeWithDom): void; +export declare function directive(name: string, directive: Directive): void; +export declare const valyrian: Valyrian; diff --git a/types/plugins/hooks.d.ts b/types/plugins/hooks.d.ts new file mode 100644 index 0000000..0d82332 --- /dev/null +++ b/types/plugins/hooks.d.ts @@ -0,0 +1 @@ +export { plugin as default }; diff --git a/types/plugins/node.d.ts b/types/plugins/node.d.ts new file mode 100644 index 0000000..0d82332 --- /dev/null +++ b/types/plugins/node.d.ts @@ -0,0 +1 @@ +export { plugin as default }; diff --git a/dist/@types/plugins/node.sw.tpl.d.ts b/types/plugins/node.sw.tpl.d.ts similarity index 100% rename from dist/@types/plugins/node.sw.tpl.d.ts rename to types/plugins/node.sw.tpl.d.ts diff --git a/types/plugins/request.d.ts b/types/plugins/request.d.ts new file mode 100644 index 0000000..31c66b8 --- /dev/null +++ b/types/plugins/request.d.ts @@ -0,0 +1,5 @@ +export = request; +declare function request(method: any, url: any, data: any, options?: {}): Promise; +declare namespace request { + export { request as default }; +} diff --git a/types/plugins/router.d.ts b/types/plugins/router.d.ts new file mode 100644 index 0000000..c80cce6 --- /dev/null +++ b/types/plugins/router.d.ts @@ -0,0 +1,19 @@ +export = Router; +declare class Router { + paths: any[]; + container: null; + url: string; + query: {}; + options: {}; + current: string; + params: {}; + matches: any[]; + get(path: any, ...args: any[]): Router; + use(...args: any[]): Router; + routes(): any[]; + go(path: any, parentComponent: any): Promise; + mount(elementContainer: any): void; +} +declare namespace Router { + export { Router as default }; +} diff --git a/types/plugins/signals.d.ts b/types/plugins/signals.d.ts new file mode 100644 index 0000000..2fe971f --- /dev/null +++ b/types/plugins/signals.d.ts @@ -0,0 +1,5 @@ +export = Signal; +declare function Signal(value: any, key: any): any; +declare namespace Signal { + export { Signal as default }; +} diff --git a/types/plugins/store.d.ts b/types/plugins/store.d.ts new file mode 100644 index 0000000..a2278ac --- /dev/null +++ b/types/plugins/store.d.ts @@ -0,0 +1,22 @@ +export = Store; +declare function Store({ state, getters, actions, mutations }?: { + state?: {} | undefined; + getters?: {} | undefined; + actions?: {} | undefined; + mutations?: {} | undefined; +}): void; +declare class Store { + constructor({ state, getters, actions, mutations }?: { + state?: {} | undefined; + getters?: {} | undefined; + actions?: {} | undefined; + mutations?: {} | undefined; + }); + state: any; + getters: any; + commit: (mutation: any, ...args: any[]) => void; + dispatch: (action: any, ...args: any[]) => Promise; +} +declare namespace Store { + export { Store as default }; +} diff --git a/types/plugins/sw.d.ts b/types/plugins/sw.d.ts new file mode 100644 index 0000000..a7a00b3 --- /dev/null +++ b/types/plugins/sw.d.ts @@ -0,0 +1,14 @@ +export = Sw; +declare class Sw { + constructor(file: any, options: any); + file: string; + options: { + scope: string; + }; + ready: boolean; + sw: null; + register(): Promise; +} +declare namespace Sw { + export { Sw as default }; +} diff --git a/dist/@types/plugins/utils/tree-adapter.d.ts b/types/plugins/utils/tree-adapter.d.ts similarity index 100% rename from dist/@types/plugins/utils/tree-adapter.d.ts rename to types/plugins/utils/tree-adapter.d.ts From c88db2d4b293edc93ca503cefbcf51dfae85be8c Mon Sep 17 00:00:00 2001 From: Masquerade Circus Date: Mon, 7 Feb 2022 07:17:37 -0600 Subject: [PATCH 04/19] Updated hooks implementation --- bench/.buffalo-test.json | 947 ++++++++++++++++++++++++++++++++++ bench/mount_n_update_bench.js | 54 +- lib/index.ts | 187 +++---- lib/interfaces.ts | 101 ++++ plugins/hooks.js | 124 +++-- test/hooks_test.js | 96 +++- 6 files changed, 1332 insertions(+), 177 deletions(-) create mode 100644 lib/interfaces.ts diff --git a/bench/.buffalo-test.json b/bench/.buffalo-test.json index e2d3e7a..3306a8d 100644 --- a/bench/.buffalo-test.json +++ b/bench/.buffalo-test.json @@ -1,4 +1,951 @@ [ + { + "tag": "7313c056499f7888695a0dd3eab842c06e8c4d63", + "timestamp": "2022-02-07T13:17:05.607Z", + "suites": { + "Matching keyed list": { + "Removed at the end": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "Matching keyed list -> stress": { + "Removed at the end": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "hyperscript": { + "Valyrian 5.0.8": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "Valyrian next": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "Set.has vs [].indexOf": { + "Set.has": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "[].indexOf": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "Object.keys for loop vs Object.keys for of vs for in": { + "Object.keys for loop": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "Object.keys for of": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "for in": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "typeof function vs startsWith vs charAt vs string[0]": { + "typeof function": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "startsWith": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "charAt": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "string[0]": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "Array.isArray vs typeof object & Array.isArray": { + "Array.isArray": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "typeof object & Array.isArray": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "string comparison vs instance comparison vs property comparison": { + "string comparison": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "instance comparison": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "property comparison": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "property string comparison": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "typeof comparison": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "Object with property equals true vs set vs map vs string array": { + "Object with property equals true": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "key in object": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "set": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "map": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "string array": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "For loop if/continue vs if/else": { + "for loop if/continue": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "for loop if/else": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "map array of strings vs reduce with object keys equals index": { + "map array of strings": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "reduce with object keys equals index": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "array by for": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "object by for": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "object map by for": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "Symbol access vs direct access": { + "Direct access access": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "Symbol access access": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "Mount and update: Mount multiple types": { + "Valyrian 5.0.8": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "Valyrian next": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "Mount and update: Mount single text": { + "Valyrian 5.0.8": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "Valyrian next": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "Mount and update: Mount single text in div": { + "Valyrian 5.0.8": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "Valyrian next": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "Mount and update: Update multiple types": { + "Valyrian 5.0.8": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "Valyrian next": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "Mount and update: Update single text": { + "Valyrian 5.0.8": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "Valyrian next": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "Mount and update: Render list": { + "vOld": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "VNext": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "Mount and update: Render keyed list": { + "vOld": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "VNext": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "Mount and update: Render keyed list -> stress": { + "vOld": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "VNext": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "Mount and update: Render keyed list -> swap keys on large set": { + "vOld": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "VNext": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "Lifecycle vs hooks": { + "Hooks": { + "hz": 418809.4932388646, + "meanTime": 0.002387720469912219, + "medianTime": 0.0021540001034736633, + "standardDeviation": 0.006061677122078444, + "maxTime": 1.682847999036312, + "minTime": 0.0019429996609687805 + }, + "Lifecycle": { + "hz": 479963.0824312632, + "meanTime": 0.0020834935781612177, + "medianTime": 0.0018789991736412048, + "standardDeviation": 0.0070840770698405485, + "maxTime": 5.112537998706102, + "minTime": 0.0016540028154850006 + } + } + } + }, + { + "tag": null, + "timestamp": "2022-02-07T05:56:56.577Z", + "suites": { + "Matching keyed list": { + "Removed at the end": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "Matching keyed list -> stress": { + "Removed at the end": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "hyperscript": { + "Valyrian 5.0.8": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "Valyrian next": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "Set.has vs [].indexOf": { + "Set.has": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "[].indexOf": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "Object.keys for loop vs Object.keys for of vs for in": { + "Object.keys for loop": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "Object.keys for of": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "for in": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "typeof function vs startsWith vs charAt vs string[0]": { + "typeof function": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "startsWith": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "charAt": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "string[0]": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "Array.isArray vs typeof object & Array.isArray": { + "Array.isArray": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "typeof object & Array.isArray": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "string comparison vs instance comparison vs property comparison": { + "string comparison": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "instance comparison": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "property comparison": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "property string comparison": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "typeof comparison": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "Object with property equals true vs set vs map vs string array": { + "Object with property equals true": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "key in object": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "set": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "map": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "string array": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "For loop if/continue vs if/else": { + "for loop if/continue": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "for loop if/else": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "map array of strings vs reduce with object keys equals index": { + "map array of strings": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "reduce with object keys equals index": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "array by for": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "object by for": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "object map by for": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "Symbol access vs direct access": { + "Direct access access": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "Symbol access access": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "Mount and update: Mount multiple types": { + "Valyrian 5.0.8": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "Valyrian next": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "Mount and update: Mount single text": { + "Valyrian 5.0.8": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "Valyrian next": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "Mount and update: Mount single text in div": { + "Valyrian 5.0.8": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "Valyrian next": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "Mount and update: Update multiple types": { + "Valyrian 5.0.8": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "Valyrian next": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "Mount and update: Update single text": { + "Valyrian 5.0.8": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "Valyrian next": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "Mount and update: Render list": { + "vOld": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "VNext": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "Mount and update: Render keyed list": { + "vOld": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "VNext": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "Mount and update: Render keyed list -> stress": { + "vOld": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "VNext": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "Mount and update: Render keyed list -> swap keys on large set": { + "vOld": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "VNext": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "Lifecycle vs hooks": {} + } + }, { "tag": "58937038b4f3a55dd64f3907a71fe255a26ecfbf", "timestamp": "2022-02-06T19:33:58.396Z", diff --git a/bench/mount_n_update_bench.js b/bench/mount_n_update_bench.js index 3256c8a..bf0d5dd 100644 --- a/bench/mount_n_update_bench.js +++ b/bench/mount_n_update_bench.js @@ -1,10 +1,11 @@ let { compare, benchmark, before } = require("buffalo-test"); -const { mount, update, v } = require("../lib/index"); +const { mount, update, unmount, v } = require("../lib/index"); const expect = require("expect"); require("../plugins/node"); const vOld = require("./index-old"); +const { useEffect } = require("../plugins/hooks"); let VNext = v; @@ -663,3 +664,54 @@ compare("Mount and update: Render keyed list -> swap keys on large set", () => { update(component); }); }); + +compare("Lifecycle vs hooks", () => { + let lifecycleCount = 0; + let plusLifeCycle = () => (lifecycleCount += 1); + + let hooksCount = 0; + let plusHooks = () => (hooksCount += 1); + + let LifecycleComponent = () => { + return ( +
+ Hello world +
+ ); + }; + + let HooksComponent = () => { + // useEffect(plusHooks, []); // Only create replaced by the next line + useEffect(plusHooks); // Create & Update + useEffect(plusHooks, null); // Remove + return
Hello world
; + }; + + before(() => { + mount("body", LifecycleComponent); + expect(lifecycleCount).toEqual(1); + update(LifecycleComponent); + expect(lifecycleCount).toEqual(2); + unmount(LifecycleComponent); + expect(lifecycleCount).toEqual(3); + + mount("body", HooksComponent); + expect(hooksCount).toEqual(1); + update(HooksComponent); + expect(hooksCount).toEqual(2); + unmount(HooksComponent); + expect(hooksCount).toEqual(3); + }); + + benchmark(`Hooks`, () => { + mount("body", HooksComponent); + update(HooksComponent); + unmount(HooksComponent); + }); + + benchmark(`Lifecycle`, () => { + mount("body", LifecycleComponent); + update(LifecycleComponent); + unmount(LifecycleComponent); + }); +}); diff --git a/lib/index.ts b/lib/index.ts index 5dff72d..4ce4f88 100644 --- a/lib/index.ts +++ b/lib/index.ts @@ -1,105 +1,20 @@ -/*** Interfaces ***/ - -export interface DomElement extends Element { - [key: string]: any; -} - -export interface Props { - key?: string | number; - data?: string; - oncreate?: { (vnode: IVnode): never }; - onupdate?: { (vnode: IVnode, oldVnode: IVnode): never }; - onremove?: { (oldVnode: IVnode): never }; - shouldupdate?: { (vnode: IVnode, oldVnode: IVnode): undefined | boolean }; - "v-cleanup"?: Function; - [key: string | number | symbol]: any; -} - -export interface Children extends Array {} - -export interface IVnode { - new (tag: string, props: Props, children: IVnode[]): IVnode; - tag: string; - props: Props; - children: Children; - dom?: DomElement; - isSVG?: boolean; - processed?: boolean; - component?: Component | POJOComponent; - nodeValue?: string; - [key: string | number | symbol]: any; -} - -export interface Component { - (props?: Record | null, children?: Children): IVnode | Children; - [key: string | number | symbol]: any; -} - -export interface POJOComponent { - view: Component; - [key: string | number | symbol]: any; -} - -export type ValyrianComponent = Component | POJOComponent; - -export interface VnodeComponent extends IVnode { - tag: "__component__"; - component: ValyrianComponent; -} - -export interface VnodeWithDom extends IVnode { - dom: DomElement; -} - -export interface Directive { - (value: any, vnode: VnodeWithDom, oldVnode?: VnodeWithDom): void; -} - -export interface ValyrianApp { - isMounted: boolean; - eventListenerNames: Record; - cleanup: Function[]; - - eventListener?: EventListener; - mainVnode?: VnodeWithDom; - component?: VnodeComponent; - container?: DomElement; - - [key: string | number | symbol]: any; -} - -export interface MountedValyrianApp extends ValyrianApp { - eventListener: EventListener; - mainVnode: VnodeWithDom; - container: DomElement; - component: VnodeComponent; -} - -export interface Current { - app?: ValyrianApp; - component?: ValyrianComponent; - vnode?: VnodeWithDom; - oldVnode?: VnodeWithDom; -} - -export interface Directives { - [key: string]: Directive; -} - -export interface ReservedProps { - [key: string]: true; -} - -export interface Valyrian { - (tagOrComponent: string | ValyrianComponent, props: Props, ...children: Children): IVnode | VnodeComponent; - fragment: (props: Props, ...children: Children) => Children; - current: Current; - directives: Directives; - reservedProps: ReservedProps; -} - /*** Vnode ***/ +import { + Children, + Current, + Directive, + DomElement, + IVnode, + MountedValyrianApp, + Props, + Valyrian, + ValyrianApp, + ValyrianComponent, + VnodeComponent, + VnodeWithDom +} from "./interfaces"; + export const Vnode = function Vnode(this: IVnode, tag: string, props: Props, children: Children) { this.props = props; this.children = children; @@ -159,9 +74,27 @@ export const trust = (htmlString: string) => { const ValyrianSymbol = Symbol("Valyrian"); -export function cleanup(callback: Function) { - if (v.current.app?.cleanup.indexOf(callback) === -1) { - v.current.app?.cleanup.push(callback); +export function onCleanup(callback: Function) { + if (v.current.app?.onCleanup.indexOf(callback) === -1) { + v.current.app?.onCleanup.push(callback); + } +} + +export function onUnmount(callback: Function) { + if (v.current.app?.onUnmount.indexOf(callback) === -1) { + v.current.app?.onUnmount.push(callback); + } +} + +export function onMount(callback: Function) { + if (v.current.app?.onMount.indexOf(callback) === -1) { + v.current.app?.onMount.push(callback); + } +} + +export function onUpdate(callback: Function) { + if (v.current.app?.onUpdate.indexOf(callback) === -1) { + v.current.app?.onUpdate.push(callback); } } @@ -203,7 +136,10 @@ export function mount(container: DomElement | string, component: ValyrianCompone isMounted: false, eventListenerNames: {}, isNodeJs, - cleanup: [] + onCleanup: [], + onMount: [], + onUpdate: [], + onUnmount: [] }; function eventListener(e: Event) { let dom = e.target as DomElement & Record; @@ -230,25 +166,51 @@ export function mount(container: DomElement | string, component: ValyrianCompone return update(component); } -function cleanupVnodes(valyrianApp: ValyrianApp) { - for (let i = 0; i < valyrianApp.cleanup.length; i++) { - valyrianApp.cleanup[i](); +function callCleanup(valyrianApp: ValyrianApp) { + for (let i = 0; i < valyrianApp.onCleanup.length; i++) { + valyrianApp.onCleanup[i](); } - valyrianApp.cleanup = []; + valyrianApp.onCleanup = []; +} + +function callUnmount(valyrianApp: ValyrianApp) { + for (let i = 0; i < valyrianApp.onUnmount.length; i++) { + valyrianApp.onUnmount[i](); + } + valyrianApp.onUnmount = []; +} + +function callMount(valyrianApp: ValyrianApp) { + for (let i = 0; i < valyrianApp.onMount.length; i++) { + valyrianApp.onMount[i](); + } + valyrianApp.onMount = []; +} + +function callUpdate(valyrianApp: ValyrianApp) { + for (let i = 0; i < valyrianApp.onUpdate.length; i++) { + valyrianApp.onUpdate[i](); + } + valyrianApp.onUpdate = []; } export function update(component?: ValyrianComponent | IVnode) { if (component && component[ValyrianSymbol]) { let valyrianApp = component[ValyrianSymbol]; v.current.app = valyrianApp; - cleanupVnodes(valyrianApp); + callCleanup(valyrianApp); let oldVnode: VnodeWithDom | null = valyrianApp.mainVnode as VnodeWithDom; valyrianApp.mainVnode = new Vnode(valyrianApp.mainVnode.tag, valyrianApp.mainVnode.props, [valyrianApp.component]) as VnodeWithDom; valyrianApp.mainVnode.dom = oldVnode.dom; valyrianApp.mainVnode.isSVG = oldVnode.isSVG; patch(valyrianApp.mainVnode, oldVnode, valyrianApp); oldVnode = null; - valyrianApp.isMounted = true; + if (valyrianApp.isMounted === false) { + callMount(valyrianApp); + valyrianApp.isMounted = true; + } else { + callUpdate(valyrianApp); + } if (isNodeJs) { return valyrianApp.mainVnode.dom.innerHTML; @@ -264,7 +226,8 @@ export function unmount(component?: ValyrianComponent | IVnode) { let valyrianApp = component[ValyrianSymbol] as MountedValyrianApp; if (valyrianApp.isMounted) { - cleanupVnodes(valyrianApp); + callCleanup(valyrianApp); + callUnmount(valyrianApp); let oldVnode: VnodeWithDom | null = valyrianApp.mainVnode as VnodeWithDom; valyrianApp.mainVnode = new Vnode(valyrianApp.mainVnode.tag, valyrianApp.mainVnode.props, []) as VnodeWithDom; valyrianApp.mainVnode.dom = oldVnode.dom; @@ -280,7 +243,7 @@ export function unmount(component?: ValyrianComponent | IVnode) { let emptyVnode = new Vnode("__empty__", {}, []); -export function onremove(vnode: IVnode) { +function onremove(vnode: IVnode) { for (let i = 0; i < vnode.children.length; i++) { vnode.children[i].tag !== "#text" && onremove(vnode.children[i]); } diff --git a/lib/interfaces.ts b/lib/interfaces.ts new file mode 100644 index 0000000..0ed183f --- /dev/null +++ b/lib/interfaces.ts @@ -0,0 +1,101 @@ +/*** Interfaces ***/ + +export interface DomElement extends Element { + [key: string]: any; +} + +export interface Props { + key?: string | number; + data?: string; + oncreate?: { (vnode: IVnode): never }; + onupdate?: { (vnode: IVnode, oldVnode: IVnode): never }; + onremove?: { (oldVnode: IVnode): never }; + shouldupdate?: { (vnode: IVnode, oldVnode: IVnode): undefined | boolean }; + [key: string | number | symbol]: any; +} + +export interface Children extends Array {} + +export interface IVnode { + new (tag: string, props: Props, children: IVnode[]): IVnode; + tag: string; + props: Props; + children: Children; + dom?: DomElement; + isSVG?: boolean; + processed?: boolean; + component?: Component | POJOComponent; + nodeValue?: string; + [key: string | number | symbol]: any; +} + +export interface Component { + (props?: Record | null, children?: Children): IVnode | Children; + [key: string | number | symbol]: any; +} + +export interface POJOComponent { + view: Component; + [key: string | number | symbol]: any; +} + +export type ValyrianComponent = Component | POJOComponent; + +export interface VnodeComponent extends IVnode { + tag: "__component__"; + component: ValyrianComponent; +} + +export interface VnodeWithDom extends IVnode { + dom: DomElement; +} + +export interface Directive { + (value: any, vnode: VnodeWithDom, oldVnode?: VnodeWithDom): void; +} + +export interface ValyrianApp { + isMounted: boolean; + eventListenerNames: Record; + onCleanup: Function[]; + onUnmount: Function[]; + onMount: Function[]; + onUpdate: Function[]; + + eventListener?: EventListener; + mainVnode?: VnodeWithDom; + component?: VnodeComponent; + container?: DomElement; + + [key: string | number | symbol]: any; +} + +export interface MountedValyrianApp extends ValyrianApp { + eventListener: EventListener; + mainVnode: VnodeWithDom; + container: DomElement; + component: VnodeComponent; +} + +export interface Current { + app?: ValyrianApp; + component?: ValyrianComponent; + vnode?: VnodeWithDom; + oldVnode?: VnodeWithDom; +} + +export interface Directives { + [key: string]: Directive; +} + +export interface ReservedProps { + [key: string]: true; +} + +export interface Valyrian { + (tagOrComponent: string | ValyrianComponent, props: Props, ...children: Children): IVnode | VnodeComponent; + fragment: (props: Props, ...children: Children) => Children; + current: Current; + directives: Directives; + reservedProps: ReservedProps; +} diff --git a/plugins/hooks.js b/plugins/hooks.js index 00667c7..eaf0644 100644 --- a/plugins/hooks.js +++ b/plugins/hooks.js @@ -1,49 +1,45 @@ -function createHook({ create, update, response, cleanup }) { +function createHook({ create, update, remove }) { return (...args) => { let { component, vnode, oldVnode, app } = v.current; - if (vnode && component && app) { - // Init the components array for the current vnode - if (vnode.components === undefined) { - vnode.components = []; - } - - // Add the component to the components array if it's not already there - if (vnode.components.indexOf(component) === -1) { - vnode.components.push(component); - } + // Init the components array for the current vnode + if (vnode.components === undefined) { + vnode.components = []; + app.onUnmount.push(() => { + Reflect.deleteProperty(vnode, "components"); + }); + } - // Init the component hooks array - if (component.hooks === undefined) { - component.hooks = []; - } + // Add the component to the components array if it's not already there + if (vnode.components.indexOf(component) === -1) { + vnode.components.push(component); + } - let componentIndex = vnode.components.length - 1; - let oldComponent = oldVnode && oldVnode.components && oldVnode.components[componentIndex]; - let hook; - let hookIndex = component.hooks.length - 1; + // Init the component hooks array + if (component.hooks === undefined) { + component.hooks = []; + app.onUnmount.push(() => { + Reflect.deleteProperty(component, "hooks"); + }); + } + let hook; - if (oldComponent === component) { - component.hooks = oldComponent.hooks; - hook = oldComponent.hooks[hookIndex]; - if (update) { - update(hook, ...args); - } - } else { - hook = create(...args); - component.hooks.push(hook); - } + if (!oldVnode || !oldVnode.components || oldVnode.components[vnode.components.length - 1] !== component) { + hook = create(...args); + component.hooks.push(hook); - if (cleanup) { - app.cleanup.push(() => cleanup(hook)); + if (remove) { + // Add the hook to the onRemove array + app.onUnmount.push(() => remove(hook)); } - - if (response) { - return response(hook); - } else { - return hook; + } else { + hook = component.hooks[component.hooks.length - 1]; + if (update) { + update(hook, ...args); } } + + return hook; }; } @@ -60,32 +56,52 @@ const useState = createHook({ }); // Effect hook -function callEffectHook(hook, changes) { - let { prev } = hook; +const useEffect = createHook({ + create: (effect, changes) => { + let hook = { effect, prev: [] }; + // on unmount + if (changes === null) { + hook.onRemove = effect; + return hook; + } - if (!changes) { + // on create + hook.prev = changes; hook.onCleanup = hook.effect(); - } else if (changes.length > 0) { - for (let i = 0, l = changes.length; i < l; i++) { - if (changes[i] !== prev[i]) { - hook.prev = changes; - hook.onCleanup = hook.effect(); - break; + return hook; + }, + update: (hook, effect, changes) => { + // on update + if (typeof changes === "undefined") { + hook.prev = changes; + if (typeof hook.onCleanup === "function") { + hook.onCleanup(); + } + hook.onCleanup = hook.effect(); + return; + } + + // on update if there are changes + if (Array.isArray(changes)) { + for (let i = 0, l = changes.length; i < l; i++) { + if (changes[i] !== hook.prev[i]) { + hook.prev = changes; + if (typeof hook.onCleanup === "function") { + hook.onCleanup(); + } + hook.onCleanup = hook.effect(); + return; + } } } - } -} -const useEffect = createHook({ - create: (effect, changes) => { - let hook = { effect, prev: changes }; - callEffectHook(hook); - return hook; }, - update: (hook, effect, changes) => callEffectHook(hook, changes), - cleanup: (hook) => { + remove: (hook) => { if (typeof hook.onCleanup === "function") { hook.onCleanup(); } + if (typeof hook.onRemove === "function") { + hook.onRemove(); + } } }); diff --git a/test/hooks_test.js b/test/hooks_test.js index 4e43fd7..185edfd 100644 --- a/test/hooks_test.js +++ b/test/hooks_test.js @@ -1,7 +1,7 @@ import "../lib"; import "../plugins/node"; -import { cleanup, mount, unmount, update } from "../lib/index"; +import { mount, onCleanup, unmount, update } from "../lib/index"; import { useEffect, useState } from "../plugins/hooks"; import expect from "expect"; @@ -12,7 +12,7 @@ describe("Hooks", () => { let Counter = () => { let [count, setCount] = useState(0); let interval = setInterval(() => setCount(count + 1), 1000); - cleanup(() => clearInterval(interval)); + onCleanup(() => clearInterval(interval)); return
{count}
; }; @@ -23,18 +23,18 @@ describe("Hooks", () => { expect(result).toEqual("
2
"); }); - it("should handle subcomponents state and cleanup", async () => { + it("should handle subcomponents state and onCleanup", async () => { let Ok = () => { let [ok, setOk] = useState("ok"); let interval = setInterval(() => setOk("not ok"), 1000); - cleanup(() => clearInterval(interval)); + onCleanup(() => clearInterval(interval)); return
{ok}
; }; let Counter = () => { let [count, setCount] = useState(0); let interval = setInterval(() => setCount(count + 1), 1000); - cleanup(() => clearInterval(interval)); + onCleanup(() => clearInterval(interval)); return (
{count} @@ -53,7 +53,7 @@ describe("Hooks", () => { let Counter = () => { let [count, setCount] = useState(0); let interval = setInterval(() => setCount(count + 1), 1000); - cleanup(() => clearInterval(interval)); + onCleanup(() => clearInterval(interval)); return
{count}
; }; @@ -90,7 +90,7 @@ describe("Hooks", () => { expect(response).toEqual("
2
"); }); - it("should handle cleanup", () => { + it("should handle onCleanup", () => { let count = 0; let Component = function () { useEffect(() => { @@ -109,7 +109,20 @@ describe("Hooks", () => { it("should not call the effect if the change array is passed and there are no changes", () => { let count = 0; let Component = function () { - useEffect(() => count++, [0]); + useEffect(() => count++, [1]); + return
{count}
; + }; + + let response = mount("body", Component); + expect(response).toEqual("
1
"); + response = update(Component); + expect(response).toEqual("
1
"); + }); + + it("should not call the effect if the change array is passed and is an empty array", () => { + let count = 0; + let Component = function () { + useEffect(() => count++, []); return
{count}
; }; @@ -132,7 +145,7 @@ describe("Hooks", () => { expect(response).toEqual("
2
"); }); - it("should call cleanup even if the changes array is passed and there are changes", () => { + it("should call onCleanup even if the changes array is passed and there are changes", () => { let count = 0; let Component = function () { useEffect(() => { @@ -150,7 +163,7 @@ describe("Hooks", () => { expect(response).toEqual("
5
"); }); - it("should handle cleanup on unMount", () => { + it("should handle onCleanup on unMount", () => { let count = 0; let Component = function () { useEffect(() => { @@ -172,5 +185,68 @@ describe("Hooks", () => { expect(response).toEqual(""); expect(count).toEqual(-2); }); + + it("should call the effect only in the unmount", () => { + let count = 0; + let Component = function () { + useEffect(() => { + count++; + }, null); + return
{count}
; + }; + + let response = mount("body", Component); + expect(response).toEqual("
0
"); + expect(count).toEqual(0); + + response = update(Component); + expect(response).toEqual("
0
"); + expect(count).toEqual(0); + + response = unmount(Component); + expect(response).toEqual(""); + expect(count).toEqual(1); + }); + + describe("Compare lifecycle vs hooks", () => { + let lifecycleCount = 0; + let plusLifeCycle = () => (lifecycleCount += 1); + + let hooksCount = 0; + let plusHooks = () => (hooksCount += 1); + + let LifecycleComponent = () => { + return ( +
+ Hello world +
+ ); + }; + + let HooksComponent = () => { + // useEffect(plusHooks, []); // Only create replaced by the next line + useEffect(plusHooks); // Create & Update + useEffect(plusHooks, null); // Remove + return
Hello world
; + }; + + it("should call the lifecycle", () => { + mount("body", LifecycleComponent); + expect(lifecycleCount).toEqual(1); + update(LifecycleComponent); + expect(lifecycleCount).toEqual(2); + unmount(LifecycleComponent); + expect(lifecycleCount).toEqual(3); + }); + + it("should call the hooks", () => { + mount("body", HooksComponent); + expect(hooksCount).toEqual(1); + update(HooksComponent); + expect(hooksCount).toEqual(2); + unmount(HooksComponent); + expect(hooksCount).toEqual(3); + }); + }); }); }); From a9e32010fe793ade3b1e88d21007a0ffb74cdf19 Mon Sep 17 00:00:00 2001 From: Masquerade Circus Date: Mon, 7 Feb 2022 14:05:03 -0600 Subject: [PATCH 05/19] refactor: Improve performance --- bench/.buffalo-test.json | 482 ++++++++++++++++++++++++++++++++++ bench/mount_n_update_bench.js | 26 +- lib/index.ts | 11 +- lib/interfaces.ts | 1 + 4 files changed, 511 insertions(+), 9 deletions(-) diff --git a/bench/.buffalo-test.json b/bench/.buffalo-test.json index 3306a8d..0744af5 100644 --- a/bench/.buffalo-test.json +++ b/bench/.buffalo-test.json @@ -1,4 +1,486 @@ [ + { + "tag": "c88db2d4b293edc93ca503cefbcf51dfae85be8c", + "timestamp": "2022-02-07T19:50:55.473Z", + "suites": { + "Matching keyed list": { + "Removed at the end": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "Matching keyed list -> stress": { + "Removed at the end": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "hyperscript": { + "Valyrian 5.0.8": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "Valyrian next": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "Set.has vs [].indexOf": { + "Set.has": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "[].indexOf": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "Object.keys for loop vs Object.keys for of vs for in": { + "Object.keys for loop": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "Object.keys for of": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "for in": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "typeof function vs startsWith vs charAt vs string[0]": { + "typeof function": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "startsWith": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "charAt": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "string[0]": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "Array.isArray vs typeof object & Array.isArray": { + "Array.isArray": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "typeof object & Array.isArray": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "string comparison vs instance comparison vs property comparison": { + "string comparison": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "instance comparison": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "property comparison": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "property string comparison": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "typeof comparison": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "Object with property equals true vs set vs map vs string array": { + "Object with property equals true": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "key in object": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "set": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "map": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "string array": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "For loop if/continue vs if/else": { + "for loop if/continue": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "for loop if/else": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "map array of strings vs reduce with object keys equals index": { + "map array of strings": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "reduce with object keys equals index": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "array by for": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "object by for": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "object map by for": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "Symbol access vs direct access": { + "Direct access access": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "Symbol access access": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "Mount and update: Mount multiple types": { + "Valyrian 5.0.8": { + "hz": 254469.6773321339, + "meanTime": 0.003929741297603799, + "medianTime": 0.003415994346141815, + "standardDeviation": 0.023324382268781793, + "maxTime": 14.75857099890709, + "minTime": 0.0031109973788261414 + }, + "Valyrian next": { + "hz": 222.4276361113605, + "meanTime": 4.495844210201202, + "medianTime": 3.9645669981837273, + "standardDeviation": 1.000323138074584, + "maxTime": 17.066419005393982, + "minTime": 3.6880349963903427 + } + }, + "Mount and update: Mount single text": { + "Valyrian 5.0.8": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "Valyrian next": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "Mount and update: Mount single text in div": { + "Valyrian 5.0.8": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "Valyrian next": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "Mount and update: Update multiple types": { + "Valyrian 5.0.8": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "Valyrian next": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "Mount and update: Update single text": { + "Valyrian 5.0.8": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "Valyrian next": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "Mount and update: Render list": { + "vOld": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "VNext": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "Mount and update: Render keyed list": { + "vOld": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "VNext": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "Mount and update: Render keyed list -> stress": { + "vOld": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "VNext": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "Mount and update: Render keyed list -> swap keys on large set": { + "vOld": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "VNext": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "Lifecycle vs hooks": { + "Hooks": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "Lifecycle": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + } + } + }, { "tag": "7313c056499f7888695a0dd3eab842c06e8c4d63", "timestamp": "2022-02-07T13:17:05.607Z", diff --git a/bench/mount_n_update_bench.js b/bench/mount_n_update_bench.js index bf0d5dd..baca7a3 100644 --- a/bench/mount_n_update_bench.js +++ b/bench/mount_n_update_bench.js @@ -1,4 +1,4 @@ -let { compare, benchmark, before } = require("buffalo-test"); +let { compare, benchmark, before, afterCycle } = require("buffalo-test"); const { mount, update, unmount, v } = require("../lib/index"); @@ -60,11 +60,17 @@ compare("Mount and update: Mount multiple types", () => { before(() => { expect(vOld.mount("body", Component)).toEqual(`
Hello1${date}[object Object]Hello
`); expect(mount("body", Component2)).toEqual(`
Hello1${date}[object Object]Hello
`); + vOld.unMount(); + unmount(Component2); useData = true; }); - benchmark("Valyrian 5.0.8", () => { + afterCycle(() => { vOld.unMount(); + unmount(Component2); + }); + + benchmark("Valyrian 5.0.8", () => { vOld.mount("body", Component); }); @@ -79,11 +85,17 @@ compare("Mount and update: Mount single text", () => { before(() => { expect(vOld.mount("body", Component)).toEqual(`hello world`); + vOld.unMount(); expect(mount("body", Component2)).toEqual(`hello world`); + unmount(Component2); }); - benchmark("Valyrian 5.0.8", () => { + afterCycle(() => { vOld.unMount(); + unmount(Component2); + }); + + benchmark("Valyrian 5.0.8", () => { vOld.mount("body", Component); }); @@ -99,10 +111,16 @@ compare("Mount and update: Mount single text in div", () => { before(() => { expect(vOld.mount("body", Component)).toEqual(`
hello world
`); expect(mount("body", Component2)).toEqual(`
hello world
`); + vOld.unMount(); + unmount(Component2); }); - benchmark("Valyrian 5.0.8", () => { + afterCycle(() => { vOld.unMount(); + unmount(Component2); + }); + + benchmark("Valyrian 5.0.8", () => { vOld.mount("body", Component); }); diff --git a/lib/index.ts b/lib/index.ts index 4ce4f88..fa71a1b 100644 --- a/lib/index.ts +++ b/lib/index.ts @@ -198,7 +198,7 @@ export function update(component?: ValyrianComponent | IVnode) { if (component && component[ValyrianSymbol]) { let valyrianApp = component[ValyrianSymbol]; v.current.app = valyrianApp; - callCleanup(valyrianApp); + valyrianApp.onCleanup.length && callCleanup(valyrianApp); let oldVnode: VnodeWithDom | null = valyrianApp.mainVnode as VnodeWithDom; valyrianApp.mainVnode = new Vnode(valyrianApp.mainVnode.tag, valyrianApp.mainVnode.props, [valyrianApp.component]) as VnodeWithDom; valyrianApp.mainVnode.dom = oldVnode.dom; @@ -206,10 +206,10 @@ export function update(component?: ValyrianComponent | IVnode) { patch(valyrianApp.mainVnode, oldVnode, valyrianApp); oldVnode = null; if (valyrianApp.isMounted === false) { - callMount(valyrianApp); + valyrianApp.onMount.length && callMount(valyrianApp); valyrianApp.isMounted = true; } else { - callUpdate(valyrianApp); + valyrianApp.onUpdate.length && callUpdate(valyrianApp); } if (isNodeJs) { @@ -226,8 +226,8 @@ export function unmount(component?: ValyrianComponent | IVnode) { let valyrianApp = component[ValyrianSymbol] as MountedValyrianApp; if (valyrianApp.isMounted) { - callCleanup(valyrianApp); - callUnmount(valyrianApp); + valyrianApp.onCleanup.length && callCleanup(valyrianApp); + valyrianApp.onUnmount.length && callUnmount(valyrianApp); let oldVnode: VnodeWithDom | null = valyrianApp.mainVnode as VnodeWithDom; valyrianApp.mainVnode = new Vnode(valyrianApp.mainVnode.tag, valyrianApp.mainVnode.props, []) as VnodeWithDom; valyrianApp.mainVnode.dom = oldVnode.dom; @@ -235,6 +235,7 @@ export function unmount(component?: ValyrianComponent | IVnode) { patch(valyrianApp.mainVnode, oldVnode, valyrianApp); oldVnode = null; valyrianApp.isMounted = false; + if (isNodeJs) { return valyrianApp.mainVnode.dom.innerHTML; } diff --git a/lib/interfaces.ts b/lib/interfaces.ts index 0ed183f..5725d63 100644 --- a/lib/interfaces.ts +++ b/lib/interfaces.ts @@ -98,4 +98,5 @@ export interface Valyrian { current: Current; directives: Directives; reservedProps: ReservedProps; + [key: string | number | symbol]: any; } From 179509bcd7d250d165e31e0f4676155fd187101f Mon Sep 17 00:00:00 2001 From: Masquerade Circus Date: Sat, 12 Feb 2022 12:07:47 -0600 Subject: [PATCH 06/19] refactor: Compare to old version --- .gitignore | 5 +- bench/.bench-test.json | 286 --- bench/.buffalo-test.json | 2823 ------------------------- bench/hyperscript_bench.js | 6 +- bench/index-old.ts | 566 +++++ bench/mount_n_update_bench.js | 4 +- dist/@types/lib/index.d.ts | 17 + dist/@types/lib/interfaces.d.ts | 90 + dist/index.cjs | 101 +- dist/index.js | 101 +- dist/index.min.js | 2 +- dist/index.min.js.map | 2 +- lib/index.ts | 16 +- lib/interfaces.ts | 2 - package.json | 12 +- plugins/node.js | 2 +- plugins/router.js | 2 +- source.js | 4 +- test/directives_test.js | 6 +- tsconfig.json | 2 +- types/plugins/hooks.d.ts | 1 - types/plugins/node.d.ts | 1 - types/plugins/node.sw.tpl.d.ts | 11 - types/plugins/request.d.ts | 5 - types/plugins/router.d.ts | 19 - types/plugins/signals.d.ts | 5 - types/plugins/store.d.ts | 22 - types/plugins/sw.d.ts | 14 - types/plugins/utils/tree-adapter.d.ts | 1 - 29 files changed, 854 insertions(+), 3274 deletions(-) delete mode 100644 bench/.bench-test.json create mode 100644 bench/index-old.ts create mode 100644 dist/@types/lib/index.d.ts create mode 100644 dist/@types/lib/interfaces.d.ts delete mode 100644 types/plugins/hooks.d.ts delete mode 100644 types/plugins/node.d.ts delete mode 100644 types/plugins/node.sw.tpl.d.ts delete mode 100644 types/plugins/request.d.ts delete mode 100644 types/plugins/router.d.ts delete mode 100644 types/plugins/signals.d.ts delete mode 100644 types/plugins/store.d.ts delete mode 100644 types/plugins/sw.d.ts delete mode 100644 types/plugins/utils/tree-adapter.d.ts diff --git a/.gitignore b/.gitignore index 91a2f79..7c1bba6 100644 --- a/.gitignore +++ b/.gitignore @@ -62,4 +62,7 @@ typings/ !.tmp/favicon.ico .cache -.dccache \ No newline at end of file +.dccache + +.yalc +yalc.lock \ No newline at end of file diff --git a/bench/.bench-test.json b/bench/.bench-test.json deleted file mode 100644 index e896c13..0000000 --- a/bench/.bench-test.json +++ /dev/null @@ -1,286 +0,0 @@ -[ - { - "tag": "8f1ae1ed31d6fade49775f76180d4f480838e513", - "timestamp": "2021-08-10T18:14:29.637Z", - "suites": { - "Matching keyed list": { - "Removed at the end": { - "hz": 13843147.117343122, - "meanTime": 0.0000722379088745773, - "medianTime": 0.0000680088996887207, - "standardDeviation": 0.00042877065505546146, - "maxTime": 0.4502910077571869, - "minTime": 0.000059992074966430664 - } - }, - "Matching keyed list -> stress": { - "Removed at the end": { - "hz": 12422377.247000432, - "meanTime": 0.00008049988984527619, - "medianTime": 0.0000749826431274414, - "standardDeviation": 0.00027194826576966674, - "maxTime": 0.21449699997901917, - "minTime": 0.00006699562072753906 - } - }, - "hyperscript": { - "Valyrian 5.0.8": { - "hz": 11319013.434587948, - "meanTime": 0.00008834692226305354, - "medianTime": 0.00008299946784973145, - "standardDeviation": 0.0005409524513552643, - "maxTime": 0.40178897976875305, - "minTime": 0.00007399916648864746 - }, - "Valyrian next": { - "hz": 12375130.889701415, - "meanTime": 0.00008080722611444863, - "medianTime": 0.00007599592208862305, - "standardDeviation": 0.00037632133074474907, - "maxTime": 0.3384949862957001, - "minTime": 0.0000680088996887207 - } - }, - "Set.has vs [].indexOf": { - "Set.has": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "[].indexOf": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "Object.keys for loop vs Object.keys for of vs for in": { - "Object.keys for loop": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "Object.keys for of": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "for in": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "typeof function vs startsWith vs charAt vs string[0]": { - "typeof function": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "startsWith": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "charAt": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "string[0]": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "Array.isArray vs typeof object & Array.isArray": { - "Array.isArray": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "typeof object & Array.isArray": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "Mount and update: Mount multiple types": { - "Valyrian 5.0.8": { - "hz": 2902.424855082848, - "meanTime": 0.344539497120402, - "medianTime": 0.3158630132675171, - "standardDeviation": 0.12547047831784758, - "maxTime": 3.329019993543625, - "minTime": 0.29217401146888733 - }, - "Valyrian next": { - "hz": 1955.2347882027263, - "meanTime": 0.5114475284675204, - "medianTime": 0.5008789896965027, - "standardDeviation": 0.10858653402744443, - "maxTime": 3.539449006319046, - "minTime": 0.42389801144599915 - } - }, - "Mount and update: Mount single text": { - "Valyrian 5.0.8": { - "hz": 563163.7564910672, - "meanTime": 0.0017756824519936268, - "medianTime": 0.0015400052070617676, - "standardDeviation": 0.008721908634331324, - "maxTime": 1.7687189877033234, - "minTime": 0.0013429820537567139 - }, - "Valyrian next": { - "hz": 588864.345468643, - "meanTime": 0.0016981839836204685, - "medianTime": 0.0014680027961730957, - "standardDeviation": 0.007901310872149805, - "maxTime": 0.9200059771537781, - "minTime": 0.0013020038604736328 - } - }, - "Mount and update: Update multiple types": { - "Valyrian 5.0.8": { - "hz": 191.46922053851156, - "meanTime": 5.222771561859797, - "medianTime": 5.1248679757118225, - "standardDeviation": 0.5295244468492879, - "maxTime": 11.35259997844696, - "minTime": 4.994443982839584 - }, - "Valyrian next": { - "hz": 988.9617184290813, - "meanTime": 1.0111614851871642, - "medianTime": 0.9874210059642792, - "standardDeviation": 0.17563506977385074, - "maxTime": 4.4599060118198395, - "minTime": 0.8580270111560822 - } - }, - "Mount and update: Update single text": { - "Valyrian 5.0.8": { - "hz": 281041.30071332253, - "meanTime": 0.0035581958860205196, - "medianTime": 0.003233999013900757, - "standardDeviation": 0.008330635728654796, - "maxTime": 2.148925006389618, - "minTime": 0.0029729902744293213 - }, - "Valyrian next": { - "hz": 303605.0335040786, - "meanTime": 0.0032937530332037995, - "medianTime": 0.0029140114784240723, - "standardDeviation": 0.010686156739409163, - "maxTime": 0.9253660142421722, - "minTime": 0.0026279985904693604 - } - }, - "Mount and update: Render list": { - "vOld": { - "hz": 32234.74893486094, - "meanTime": 0.031022422480186565, - "medianTime": 0.02816900610923767, - "standardDeviation": 0.028445183605242633, - "maxTime": 2.241923987865448, - "minTime": 0.026877999305725098 - }, - "VNext": { - "hz": 36094.39940924254, - "meanTime": 0.027705129226888708, - "medianTime": 0.024733006954193115, - "standardDeviation": 0.03313229161212847, - "maxTime": 3.294002026319504, - "minTime": 0.023487001657485962 - } - }, - "Mount and update: Render keyed list": { - "vOld": { - "hz": 10818.729602584868, - "meanTime": 0.09243229443141593, - "medianTime": 0.08125397562980652, - "standardDeviation": 0.0758776377704544, - "maxTime": 4.654555976390839, - "minTime": 0.07728502154350281 - }, - "VNext": { - "hz": 10520.295372507426, - "meanTime": 0.09505436535682156, - "medianTime": 0.08138898015022278, - "standardDeviation": 0.08801408887318905, - "maxTime": 4.140509992837906, - "minTime": 0.07600200176239014 - } - }, - "Mount and update: Render keyed list -> stress": { - "vOld": { - "hz": 5912.339869909631, - "meanTime": 0.1691377732003226, - "medianTime": 0.1536639928817749, - "standardDeviation": 0.07667175327766867, - "maxTime": 1.6021479964256287, - "minTime": 0.14648601412773132 - }, - "VNext": { - "hz": 6223.138379681636, - "meanTime": 0.16069062569217016, - "medianTime": 0.14509502053260803, - "standardDeviation": 0.07779315135447662, - "maxTime": 1.1707000136375427, - "minTime": 0.1383270025253296 - } - }, - "Mount and update: Render keyed list -> swap keys on large set": { - "vOld": { - "hz": 956.5646051100083, - "meanTime": 1.0454076961011918, - "medianTime": 0.899418979883194, - "standardDeviation": 0.3488216147974813, - "maxTime": 4.253165006637573, - "minTime": 0.8360439836978912 - }, - "VNext": { - "hz": 1088.780339822946, - "meanTime": 0.9184589061946297, - "medianTime": 0.8092609941959381, - "standardDeviation": 0.276212975273171, - "maxTime": 2.6908140182495117, - "minTime": 0.7434589862823486 - } - } - } - } -] \ No newline at end of file diff --git a/bench/.buffalo-test.json b/bench/.buffalo-test.json index 0744af5..e69de29 100644 --- a/bench/.buffalo-test.json +++ b/bench/.buffalo-test.json @@ -1,2823 +0,0 @@ -[ - { - "tag": "c88db2d4b293edc93ca503cefbcf51dfae85be8c", - "timestamp": "2022-02-07T19:50:55.473Z", - "suites": { - "Matching keyed list": { - "Removed at the end": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "Matching keyed list -> stress": { - "Removed at the end": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "hyperscript": { - "Valyrian 5.0.8": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "Valyrian next": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "Set.has vs [].indexOf": { - "Set.has": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "[].indexOf": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "Object.keys for loop vs Object.keys for of vs for in": { - "Object.keys for loop": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "Object.keys for of": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "for in": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "typeof function vs startsWith vs charAt vs string[0]": { - "typeof function": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "startsWith": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "charAt": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "string[0]": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "Array.isArray vs typeof object & Array.isArray": { - "Array.isArray": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "typeof object & Array.isArray": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "string comparison vs instance comparison vs property comparison": { - "string comparison": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "instance comparison": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "property comparison": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "property string comparison": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "typeof comparison": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "Object with property equals true vs set vs map vs string array": { - "Object with property equals true": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "key in object": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "set": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "map": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "string array": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "For loop if/continue vs if/else": { - "for loop if/continue": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "for loop if/else": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "map array of strings vs reduce with object keys equals index": { - "map array of strings": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "reduce with object keys equals index": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "array by for": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "object by for": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "object map by for": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "Symbol access vs direct access": { - "Direct access access": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "Symbol access access": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "Mount and update: Mount multiple types": { - "Valyrian 5.0.8": { - "hz": 254469.6773321339, - "meanTime": 0.003929741297603799, - "medianTime": 0.003415994346141815, - "standardDeviation": 0.023324382268781793, - "maxTime": 14.75857099890709, - "minTime": 0.0031109973788261414 - }, - "Valyrian next": { - "hz": 222.4276361113605, - "meanTime": 4.495844210201202, - "medianTime": 3.9645669981837273, - "standardDeviation": 1.000323138074584, - "maxTime": 17.066419005393982, - "minTime": 3.6880349963903427 - } - }, - "Mount and update: Mount single text": { - "Valyrian 5.0.8": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "Valyrian next": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "Mount and update: Mount single text in div": { - "Valyrian 5.0.8": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "Valyrian next": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "Mount and update: Update multiple types": { - "Valyrian 5.0.8": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "Valyrian next": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "Mount and update: Update single text": { - "Valyrian 5.0.8": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "Valyrian next": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "Mount and update: Render list": { - "vOld": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "VNext": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "Mount and update: Render keyed list": { - "vOld": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "VNext": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "Mount and update: Render keyed list -> stress": { - "vOld": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "VNext": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "Mount and update: Render keyed list -> swap keys on large set": { - "vOld": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "VNext": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "Lifecycle vs hooks": { - "Hooks": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "Lifecycle": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - } - } - }, - { - "tag": "7313c056499f7888695a0dd3eab842c06e8c4d63", - "timestamp": "2022-02-07T13:17:05.607Z", - "suites": { - "Matching keyed list": { - "Removed at the end": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "Matching keyed list -> stress": { - "Removed at the end": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "hyperscript": { - "Valyrian 5.0.8": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "Valyrian next": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "Set.has vs [].indexOf": { - "Set.has": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "[].indexOf": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "Object.keys for loop vs Object.keys for of vs for in": { - "Object.keys for loop": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "Object.keys for of": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "for in": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "typeof function vs startsWith vs charAt vs string[0]": { - "typeof function": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "startsWith": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "charAt": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "string[0]": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "Array.isArray vs typeof object & Array.isArray": { - "Array.isArray": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "typeof object & Array.isArray": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "string comparison vs instance comparison vs property comparison": { - "string comparison": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "instance comparison": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "property comparison": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "property string comparison": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "typeof comparison": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "Object with property equals true vs set vs map vs string array": { - "Object with property equals true": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "key in object": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "set": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "map": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "string array": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "For loop if/continue vs if/else": { - "for loop if/continue": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "for loop if/else": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "map array of strings vs reduce with object keys equals index": { - "map array of strings": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "reduce with object keys equals index": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "array by for": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "object by for": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "object map by for": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "Symbol access vs direct access": { - "Direct access access": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "Symbol access access": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "Mount and update: Mount multiple types": { - "Valyrian 5.0.8": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "Valyrian next": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "Mount and update: Mount single text": { - "Valyrian 5.0.8": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "Valyrian next": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "Mount and update: Mount single text in div": { - "Valyrian 5.0.8": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "Valyrian next": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "Mount and update: Update multiple types": { - "Valyrian 5.0.8": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "Valyrian next": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "Mount and update: Update single text": { - "Valyrian 5.0.8": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "Valyrian next": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "Mount and update: Render list": { - "vOld": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "VNext": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "Mount and update: Render keyed list": { - "vOld": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "VNext": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "Mount and update: Render keyed list -> stress": { - "vOld": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "VNext": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "Mount and update: Render keyed list -> swap keys on large set": { - "vOld": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "VNext": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "Lifecycle vs hooks": { - "Hooks": { - "hz": 418809.4932388646, - "meanTime": 0.002387720469912219, - "medianTime": 0.0021540001034736633, - "standardDeviation": 0.006061677122078444, - "maxTime": 1.682847999036312, - "minTime": 0.0019429996609687805 - }, - "Lifecycle": { - "hz": 479963.0824312632, - "meanTime": 0.0020834935781612177, - "medianTime": 0.0018789991736412048, - "standardDeviation": 0.0070840770698405485, - "maxTime": 5.112537998706102, - "minTime": 0.0016540028154850006 - } - } - } - }, - { - "tag": null, - "timestamp": "2022-02-07T05:56:56.577Z", - "suites": { - "Matching keyed list": { - "Removed at the end": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "Matching keyed list -> stress": { - "Removed at the end": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "hyperscript": { - "Valyrian 5.0.8": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "Valyrian next": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "Set.has vs [].indexOf": { - "Set.has": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "[].indexOf": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "Object.keys for loop vs Object.keys for of vs for in": { - "Object.keys for loop": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "Object.keys for of": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "for in": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "typeof function vs startsWith vs charAt vs string[0]": { - "typeof function": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "startsWith": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "charAt": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "string[0]": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "Array.isArray vs typeof object & Array.isArray": { - "Array.isArray": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "typeof object & Array.isArray": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "string comparison vs instance comparison vs property comparison": { - "string comparison": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "instance comparison": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "property comparison": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "property string comparison": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "typeof comparison": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "Object with property equals true vs set vs map vs string array": { - "Object with property equals true": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "key in object": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "set": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "map": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "string array": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "For loop if/continue vs if/else": { - "for loop if/continue": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "for loop if/else": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "map array of strings vs reduce with object keys equals index": { - "map array of strings": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "reduce with object keys equals index": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "array by for": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "object by for": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "object map by for": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "Symbol access vs direct access": { - "Direct access access": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "Symbol access access": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "Mount and update: Mount multiple types": { - "Valyrian 5.0.8": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "Valyrian next": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "Mount and update: Mount single text": { - "Valyrian 5.0.8": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "Valyrian next": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "Mount and update: Mount single text in div": { - "Valyrian 5.0.8": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "Valyrian next": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "Mount and update: Update multiple types": { - "Valyrian 5.0.8": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "Valyrian next": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "Mount and update: Update single text": { - "Valyrian 5.0.8": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "Valyrian next": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "Mount and update: Render list": { - "vOld": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "VNext": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "Mount and update: Render keyed list": { - "vOld": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "VNext": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "Mount and update: Render keyed list -> stress": { - "vOld": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "VNext": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "Mount and update: Render keyed list -> swap keys on large set": { - "vOld": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "VNext": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "Lifecycle vs hooks": {} - } - }, - { - "tag": "58937038b4f3a55dd64f3907a71fe255a26ecfbf", - "timestamp": "2022-02-06T19:33:58.396Z", - "suites": { - "Matching keyed list": { - "Removed at the end": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "Matching keyed list -> stress": { - "Removed at the end": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "hyperscript": { - "Valyrian 5.0.8": { - "hz": 17250671.37325977, - "meanTime": 0.00005796875833772463, - "medianTime": 0.00004997849464416504, - "standardDeviation": 0.00046038119909960594, - "maxTime": 0.6135759949684143, - "minTime": 0.000044971704483032227 - }, - "Valyrian next": { - "hz": 16592575.824529294, - "meanTime": 0.00006026791804812309, - "medianTime": 0.000056999968364834785, - "standardDeviation": 0.00028681042792214214, - "maxTime": 0.42846699990332127, - "minTime": 0.00005000014789402485 - } - }, - "Set.has vs [].indexOf": { - "Set.has": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "[].indexOf": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "Object.keys for loop vs Object.keys for of vs for in": { - "Object.keys for loop": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "Object.keys for of": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "for in": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "typeof function vs startsWith vs charAt vs string[0]": { - "typeof function": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "startsWith": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "charAt": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "string[0]": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "Array.isArray vs typeof object & Array.isArray": { - "Array.isArray": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "typeof object & Array.isArray": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "string comparison vs instance comparison vs property comparison": { - "string comparison": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "instance comparison": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "property comparison": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "property string comparison": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "typeof comparison": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "Object with property equals true vs set vs map vs string array": { - "Object with property equals true": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "key in object": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "set": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "map": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "string array": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "For loop if/continue vs if/else": { - "for loop if/continue": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "for loop if/else": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "map array of strings vs reduce with object keys equals index": { - "map array of strings": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "reduce with object keys equals index": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "array by for": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "object by for": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "object map by for": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "Symbol access vs direct access": { - "Direct access access": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "Symbol access access": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "Mount and update: Mount multiple types": { - "Valyrian 5.0.8": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "Valyrian next": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "Mount and update: Mount single text": { - "Valyrian 5.0.8": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "Valyrian next": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "Mount and update: Mount single text in div": { - "Valyrian 5.0.8": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "Valyrian next": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "Mount and update: Update multiple types": { - "Valyrian 5.0.8": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "Valyrian next": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "Mount and update: Update single text": { - "Valyrian 5.0.8": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "Valyrian next": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "Mount and update: Render list": { - "vOld": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "VNext": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "Mount and update: Render keyed list": { - "vOld": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "VNext": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "Mount and update: Render keyed list -> stress": { - "vOld": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "VNext": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "Mount and update: Render keyed list -> swap keys on large set": { - "vOld": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "VNext": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - } - } - }, - { - "tag": "5facca6aa5e38cb11b7a4ecb997aac6a3c948e3f", - "timestamp": "2022-02-03T22:46:40.072Z", - "suites": { - "Matching keyed list": { - "Removed at the end": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "Matching keyed list -> stress": { - "Removed at the end": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "hyperscript": { - "Valyrian 5.0.8": { - "hz": 16100452.93072125, - "meanTime": 0.00006211005394089887, - "medianTime": 0.000054001808166503906, - "standardDeviation": 0.0003290395264510733, - "maxTime": 0.36281299591064453, - "minTime": 0.00004699826240539551 - }, - "Valyrian next": { - "hz": 16434040.374422874, - "meanTime": 0.00006084930894756413, - "medianTime": 0.00005799531936645508, - "standardDeviation": 0.0007403887907110484, - "maxTime": 1.4644039869308472, - "minTime": 0.00005099177360534668 - } - }, - "Set.has vs [].indexOf": { - "Set.has": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "[].indexOf": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "Object.keys for loop vs Object.keys for of vs for in": { - "Object.keys for loop": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "Object.keys for of": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "for in": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "typeof function vs startsWith vs charAt vs string[0]": { - "typeof function": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "startsWith": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "charAt": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "string[0]": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "Array.isArray vs typeof object & Array.isArray": { - "Array.isArray": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "typeof object & Array.isArray": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "string comparison vs instance comparison vs property comparison": { - "string comparison": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "instance comparison": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "property comparison": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "property string comparison": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "typeof comparison": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "Object with property equals true vs set vs map vs string array": { - "Object with property equals true": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "key in object": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "set": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "map": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "string array": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "For loop if/continue vs if/else": { - "for loop if/continue": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "for loop if/else": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "map array of strings vs reduce with object keys equals index": { - "map array of strings": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "reduce with object keys equals index": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "array by for": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "object by for": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "object map by for": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "Symbol access vs direct access": { - "Direct access access": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "Symbol access access": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "Mount and update: Mount multiple types": { - "Valyrian 5.0.8": { - "hz": 156.0278006338212, - "meanTime": 6.409114247190357, - "medianTime": 4.104526996612549, - "standardDeviation": 4.2786484870340455, - "maxTime": 53.350247994065285, - "minTime": 3.5081720054149628 - }, - "Valyrian next": { - "hz": 147.11522570193347, - "meanTime": 6.797392963431776, - "medianTime": 4.745192989706993, - "standardDeviation": 3.879799607541915, - "maxTime": 53.691965997219086, - "minTime": 3.907906010746956 - } - }, - "Mount and update: Mount single text": { - "Valyrian 5.0.8": { - "hz": 629735.5089158076, - "meanTime": 0.0015879682594390511, - "medianTime": 0.0008700042963027954, - "standardDeviation": 0.05346277392066757, - "maxTime": 34.57287201285362, - "minTime": 0.000760003924369812 - }, - "Valyrian next": { - "hz": 771166.8946694123, - "meanTime": 0.001296736162965975, - "medianTime": 0.0007610023021697998, - "standardDeviation": 0.03629392280893103, - "maxTime": 23.255456000566483, - "minTime": 0.0006549954414367676 - } - }, - "Mount and update: Mount single text in div": { - "Valyrian 5.0.8": { - "hz": 323322.5893980026, - "meanTime": 0.0030928862776396465, - "medianTime": 0.001547008752822876, - "standardDeviation": 0.07432984344850142, - "maxTime": 19.169443994760513, - "minTime": 0.0013629943132400513 - }, - "Valyrian next": { - "hz": 356537.84409168496, - "meanTime": 0.002804751351283895, - "medianTime": 0.0011690109968185425, - "standardDeviation": 0.0770758689708197, - "maxTime": 26.725001007318497, - "minTime": 0.0010079890489578247 - } - }, - "Mount and update: Update multiple types": { - "Valyrian 5.0.8": { - "hz": 112.61485916556728, - "meanTime": 8.879822852948667, - "medianTime": 7.630842998623848, - "standardDeviation": 2.391480595191235, - "maxTime": 29.19546900689602, - "minTime": 6.9201240092515945 - }, - "Valyrian next": { - "hz": 79.3053222825804, - "meanTime": 12.60949418296043, - "medianTime": 11.439594998955727, - "standardDeviation": 2.450007423832887, - "maxTime": 31.415478006005287, - "minTime": 10.35980600118637 - } - }, - "Mount and update: Update single text": { - "Valyrian 5.0.8": { - "hz": 512194.9539475156, - "meanTime": 0.0019523815927762333, - "medianTime": 0.0018129944801330566, - "standardDeviation": 0.005251666594137278, - "maxTime": 2.5011999905109406, - "minTime": 0.0016760081052780151 - }, - "Valyrian next": { - "hz": 580450.0814674293, - "meanTime": 0.0017228010330740439, - "medianTime": 0.0014830082654953003, - "standardDeviation": 0.009247424948510186, - "maxTime": 1.316769003868103, - "minTime": 0.0013870000839233398 - } - }, - "Mount and update: Render list": { - "vOld": { - "hz": 21950.17725957362, - "meanTime": 0.04555771865413287, - "medianTime": 0.03048001229763031, - "standardDeviation": 0.26360842201547274, - "maxTime": 53.0407840013504, - "minTime": 0.027091994881629944 - }, - "VNext": { - "hz": 22480.242850336203, - "meanTime": 0.04448350521200195, - "medianTime": 0.028238996863365173, - "standardDeviation": 0.22902272887302527, - "maxTime": 18.99347099661827, - "minTime": 0.02472400665283203 - } - }, - "Mount and update: Render keyed list": { - "vOld": { - "hz": 4456.298218469571, - "meanTime": 0.22440149895161873, - "medianTime": 0.10216599702835083, - "standardDeviation": 0.872715812627799, - "maxTime": 23.933639004826546, - "minTime": 0.08914101123809814 - }, - "VNext": { - "hz": 4544.2061568088975, - "meanTime": 0.22006043860964164, - "medianTime": 0.10275200009346008, - "standardDeviation": 0.8256088387603412, - "maxTime": 26.58849000930786, - "minTime": 0.0857279896736145 - } - }, - "Mount and update: Render keyed list -> stress": { - "vOld": { - "hz": 2439.913922907917, - "meanTime": 0.4098505240743038, - "medianTime": 0.19490599632263184, - "standardDeviation": 1.2082613219808935, - "maxTime": 38.02886499464512, - "minTime": 0.1708189994096756 - }, - "VNext": { - "hz": 2368.508472714364, - "meanTime": 0.4222066382789746, - "medianTime": 0.1962120085954666, - "standardDeviation": 1.2012990034146538, - "maxTime": 49.84053599834442, - "minTime": 0.16314101219177246 - } - }, - "Mount and update: Render keyed list -> swap keys on large set": { - "vOld": { - "hz": 417.95547443978296, - "meanTime": 2.392599358437343, - "medianTime": 1.0978680104017258, - "standardDeviation": 3.1758308351124, - "maxTime": 47.34352000057697, - "minTime": 0.9298380017280579 - }, - "VNext": { - "hz": 415.153888162244, - "meanTime": 2.408745355672053, - "medianTime": 1.1263680011034012, - "standardDeviation": 3.309912031074918, - "maxTime": 74.48139899969101, - "minTime": 0.9392520040273666 - } - } - } - }, - { - "tag": "ff7d5d73af49d9be6dab1d8cc4e40441c255cbba", - "timestamp": "2022-02-03T12:53:38.877Z", - "suites": { - "Matching keyed list": { - "Removed at the end": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "Matching keyed list -> stress": { - "Removed at the end": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "hyperscript": { - "Valyrian 5.0.8": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "Valyrian next": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "Set.has vs [].indexOf": { - "Set.has": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "[].indexOf": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "Object.keys for loop vs Object.keys for of vs for in": { - "Object.keys for loop": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "Object.keys for of": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "for in": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "typeof function vs startsWith vs charAt vs string[0]": { - "typeof function": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "startsWith": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "charAt": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "string[0]": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "Array.isArray vs typeof object & Array.isArray": { - "Array.isArray": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "typeof object & Array.isArray": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "string comparison vs instance comparison vs property comparison": { - "string comparison": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "instance comparison": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "property comparison": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "property string comparison": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "typeof comparison": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "Object with property equals true vs set vs map vs string array": { - "Object with property equals true": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "key in object": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "set": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "map": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "string array": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "For loop if/continue vs if/else": { - "for loop if/continue": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "for loop if/else": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "map array of strings vs reduce with object keys equals index": { - "map array of strings": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "reduce with object keys equals index": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "array by for": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "object by for": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "object map by for": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "Symbol access vs direct access": { - "Direct access access": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "Symbol access access": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "Mount and update: Mount multiple types": { - "Valyrian 5.0.8": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "Valyrian next": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "Mount and update: Mount single text": { - "Valyrian 5.0.8": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "Valyrian next": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "Mount and update: Mount single text in div": { - "Valyrian 5.0.8": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "Valyrian next": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "Mount and update: Update multiple types": { - "Valyrian 5.0.8": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "Valyrian next": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "Mount and update: Update single text": { - "Valyrian 5.0.8": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "Valyrian next": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "Mount and update: Render list": { - "vOld": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "VNext": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "Mount and update: Render keyed list": { - "vOld": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "VNext": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "Mount and update: Render keyed list -> stress": { - "vOld": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "VNext": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "Mount and update: Render keyed list -> swap keys on large set": { - "vOld": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "VNext": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - } - } - } -] \ No newline at end of file diff --git a/bench/hyperscript_bench.js b/bench/hyperscript_bench.js index 393520b..f892bd3 100644 --- a/bench/hyperscript_bench.js +++ b/bench/hyperscript_bench.js @@ -3,13 +3,13 @@ const { before, benchmark, compare } = require("buffalo-test"); const { v: VNext } = require("../lib/index.ts"); const expect = require("expect"); const nodePlugin = require("../plugins/node"); -const vOld = require("./index-old"); +const { v: vOld } = require("./index-old.ts"); compare("hyperscript", () => { let date = new Date(); before(async () => { - let { raw: newTs } = await nodePlugin.inline("./lib/index.ts", { compact: true }); - let { raw: oldjs } = await nodePlugin.inline("./bench/index-old.js", { compact: true }); + let { raw: newTs } = await nodePlugin.inline("./lib/index.ts", { compact: true, bundle: false }); + let { raw: oldjs } = await nodePlugin.inline("./bench/index-old.ts", { compact: true, bundle: false }); console.log(oldjs.length); console.log(newTs.length); diff --git a/bench/index-old.ts b/bench/index-old.ts new file mode 100644 index 0000000..72024f4 --- /dev/null +++ b/bench/index-old.ts @@ -0,0 +1,566 @@ +/* eslint-disable complexity */ +/* eslint-disable sonarjs/cognitive-complexity */ +/* eslint-disable no-use-before-define */ +/* eslint-disable no-unused-vars */ + +// version 5.0.17 + +type VnodeOrUnknown = VnodeComponent | Vnode | TextVnode | any; + +type DomAttribute = { nodeName: string; nodeValue: string }; + +type DomElement = (HTMLElement | SVGElement) & Record; + +type Props = { + key?: string | number; + data?: string; + oncreate?: { (vnode: Vnode): never }; + onupdate?: { (vnode: Vnode, oldVnode: Vnode | TextVnode): never }; + onremove?: { (oldVnode: Vnode): never }; + onbeforeupdate?: { (vnode: Vnode, oldVnode: Vnode | TextVnode): undefined | boolean }; +} & Record; + +type Component = (props?: Record | null, children?: VnodeOrUnknown) => VnodeOrUnknown | VnodeOrUnknown[]; + +type ValyrianComponent = + | Component + | (Record & { + view: Component; + }); + +type Current = { parentVnode?: Vnode; oldParentVnode?: Vnode; component?: VnodeComponent }; + +interface Plugin { + (v: Valyrian, options?: Record): never; +} + +interface Directive { + (value: any, vnode: Vnode, oldVnode?: Vnode | TextVnode): void | boolean; +} + +interface ValyrianEventHandler { + (a: Event, dom: DomElement): void; +} + +interface Vnode { + name: string; + props: Props; + children: VnodeOrUnknown[]; + dom?: DomElement; + onCleanup?: FunctionConstructor[]; + isSVG?: boolean; + processed?: boolean; +} + +class Vnode implements Vnode { + name: string; + props: Props; + children: VnodeOrUnknown[]; + dom?: DomElement; + onCleanup?: FunctionConstructor[]; + isSVG?: boolean; + processed?: boolean; + + constructor(name: string, props: Props, children: VnodeOrUnknown) { + this.props = props; + this.children = children; + this.name = name; + } +} + +interface TextVnode { + dom?: Text; + nodeValue: string; +} + +class TextVnode implements TextVnode { + dom?: Text; + nodeValue: string; + + constructor(nodeValue: string) { + this.nodeValue = nodeValue; + } +} + +interface VnodeComponent { + component: ValyrianComponent; + props: Props; + children: VnodeOrUnknown[]; +} + +class VnodeComponent implements VnodeComponent { + component: ValyrianComponent; + props: Props; + children: VnodeOrUnknown[]; + + constructor(component: ValyrianComponent, props: Props, children: VnodeOrUnknown[]) { + this.props = props; + this.children = children; + this.component = component; + } +} + +interface Valyrian { + (tagOrComponent: string | ValyrianComponent, props?: Props | null, children?: VnodeOrUnknown): Vnode | VnodeComponent; + fragment: (props: Props, children: VnodeOrUnknown[]) => VnodeOrUnknown[]; + isMounted: boolean; + isNode: boolean; + reservedWords: string[]; + current: Current; + trust: (htmlString: string) => Vnode[]; + usePlugin: (plugin: Plugin, options: Record) => void; + onCleanup: (callback: typeof Function) => void; + updateProperty: (name: string, newVnode: Vnode & { dom: DomElement }, oldNode: Vnode & { dom: DomElement }) => void; + update: (props?: Props | null, ...children: VnodeOrUnknown) => string | void; + mount: (container: string | DomElement, component: ValyrianComponent, props?: Props | null, ...children: VnodeOrUnknown[]) => string | void; + unMount: () => string | boolean | void; + directive: (directive: string, handler: Directive) => void; + newInstance: () => Valyrian; + [x: string]: any; +} + +let isNode = typeof window === "undefined" || typeof global !== "undefined"; + +// Create Node element +function createElement(tagName: string, isSVG: boolean = false): DomElement { + return isSVG ? document.createElementNS("http://www.w3.org/2000/svg", tagName) : document.createElement(tagName); +} + +// Transforms a DOM node to a VNode +function domToVnode(dom: DomElement): Vnode { + let props: Props = {}; + [].forEach.call(dom.attributes, (prop: Attr) => (props[prop.nodeName] = prop.nodeValue)); + + let vnode: Vnode = new Vnode(dom.nodeName.toLowerCase(), props, []); + vnode.dom = dom; + + for (let i = 0, l = dom.childNodes.length; i < l; i++) { + if (dom.childNodes[i].nodeType === 1) { + vnode.children.push(domToVnode(dom.childNodes[i] as DomElement)); + } else if (dom.childNodes[i].nodeType === 3) { + let textVnode = new TextVnode(dom.childNodes[i].nodeValue || ""); + textVnode.dom = dom.childNodes[i] as unknown as Text; + vnode.children.push(textVnode); + } + } + return vnode; +} + +const trust = (htmlString: string) => { + let div = createElement("div"); + div.innerHTML = htmlString.trim(); + + return [].map.call(div.childNodes, (item) => domToVnode(item)) as Vnode[]; +}; + +// eslint-disable-next-line max-lines-per-function +function valyrian(): Valyrian { + const v: Valyrian = (tagOrComponent, props, ...children) => { + if (typeof tagOrComponent === "string") { + return new Vnode(tagOrComponent, props || {}, children); + } else { + return new VnodeComponent(tagOrComponent, props || {}, children); + } + }; + + v.fragment = (props: Props, vnodes: VnodeOrUnknown[]) => { + return vnodes; + }; + + v.isMounted = false; + v.isNode = isNode; + const reservedWords = ["key", "data", "v-once", "oncreate", "onupdate", "onremove", "onbeforeupdate"]; + v.reservedWords = reservedWords; + v.trust = trust; + + const current: Current = { + parentVnode: undefined, + oldParentVnode: undefined, + component: undefined + }; + v.current = current; + + const plugins = new Map(); + + v.usePlugin = (plugin: Plugin, options: Record = {}) => !plugins.has(plugin) && plugins.set(plugin, true) && plugin(v as Valyrian, options); + + let vnodesToCleanup: Vnode[] = []; + + v.onCleanup = (callback: FunctionConstructor) => { + let parentVnode = v.current.parentVnode as Vnode; + if (!parentVnode.onCleanup) { + parentVnode.onCleanup = [] as FunctionConstructor[]; + } + + parentVnode.onCleanup.push(callback); + + if (vnodesToCleanup.indexOf(parentVnode) === -1) { + vnodesToCleanup.push(parentVnode); + } + }; + + let cleanupVnodes = () => { + for (let l = vnodesToCleanup.length; l--; ) { + for (let callback of vnodesToCleanup[l].onCleanup as FunctionConstructor[]) { + callback(); + } + } + vnodesToCleanup = []; + }; + + let mainContainer: DomElement | null = null; + let emptyComponent: ValyrianComponent = () => ""; + let mountedComponent: ValyrianComponent = emptyComponent; + + const attachedListeners: string[] = []; + function eventListener(e: Event) { + let dom = e.target as DomElement; + let name = `v-on${e.type}`; + while (dom) { + if (dom[name]) { + (dom[name] as ValyrianEventHandler)(e, dom); + if (!e.defaultPrevented) { + v.update(); + } + return; + } + dom = dom.parentNode as DomElement; + } + } + + function updateProperty(prop: string, newVnode: Vnode & { dom: DomElement }, oldVnode?: Vnode): void | boolean { + if (reservedWords.indexOf(prop) !== -1) { + if (prop in directives) { + return directives[prop](newVnode.props[prop], newVnode, oldVnode); + } + } else if (typeof newVnode.props[prop] === "function") { + if (attachedListeners.indexOf(prop) === -1) { + (mainContainer as DomElement).addEventListener(prop.slice(2), eventListener); + attachedListeners.push(prop); + } + newVnode.dom[`v-${prop}`] = newVnode.props[prop]; + } else if (prop in newVnode.dom && !newVnode.isSVG) { + // eslint-disable-next-line eqeqeq + if (newVnode.dom[prop] != newVnode.props[prop]) { + newVnode.dom[prop] = newVnode.props[prop]; + } + } else if (oldVnode === undefined || newVnode.props[prop] !== oldVnode.props[prop]) { + if (newVnode.props[prop] === false) { + newVnode.dom.removeAttribute(prop); + } else { + newVnode.dom.setAttribute(prop, newVnode.props[prop]); + } + } + } + v.updateProperty = updateProperty; + + // Update a Vnode.dom HTMLElement with new Vnode props that are different from old Vnode props + function updateProperties(newVnode: Vnode & { dom: DomElement }, oldVnode?: Vnode): void { + for (let prop in newVnode.props) { + if (updateProperty(prop, newVnode, oldVnode) === false) { + return; + } + } + } + + function removeProperties(newVnode: Vnode & { dom: DomElement }, oldVnode: Vnode) { + for (let name in oldVnode.props) { + if (name in newVnode.props === false && typeof oldVnode.props[name] !== "function" && reservedWords.indexOf(name) === -1) { + if (name in newVnode.dom) { + newVnode.dom[name] = null; + } else { + newVnode.dom.removeAttribute(name); + } + } + } + } + + const callRemove = (vnode: Vnode) => { + for (let i = 0, l = vnode.children.length; i < l; i++) { + vnode.children[i] instanceof Vnode && callRemove(vnode.children[i]); + } + + vnode.props.onremove && vnode.props.onremove(vnode); + }; + // Patch a DOM node with a new VNode tree + function patch(newParentVnode: Vnode & { dom: DomElement }, oldParentVnode?: Vnode & { dom: DomElement }): void { + let oldTree = oldParentVnode?.children || []; + let newTree = newParentVnode.children; + let oldTreeLength = oldTree.length; + + current.parentVnode = newParentVnode; + current.oldParentVnode = oldParentVnode; + + // Flat newTree + for (let i = 0; i < newTree.length; i++) { + let childVnode = newTree[i]; + + if (childVnode instanceof Vnode) { + childVnode.isSVG = newParentVnode.isSVG || childVnode.name === "svg"; + } else if (childVnode === null || childVnode === undefined) { + newTree.splice(i--, 1); + } else if (Array.isArray(childVnode)) { + newTree.splice(i--, 1, ...childVnode); + } else if (childVnode instanceof VnodeComponent) { + v.current.component = childVnode; + newTree.splice( + i--, + 1, + ...[ + "view" in childVnode.component + ? childVnode.component.view.call(childVnode.component, childVnode.props, childVnode.children) + : (childVnode.component as Component).call(childVnode.component, childVnode.props, childVnode.children) + ] + ); + } else { + if (i > 0 && newTree[i - 1].nodeValue) { + newTree[i - 1].nodeValue += childVnode; + newTree.splice(i--, 1); + } else if (childVnode instanceof TextVnode === false) { + newTree[i] = new TextVnode(String(childVnode)); + } + } + } + + let newTreeLength = newTree.length; + + // if newTree is empty, remove it + if (newTreeLength === 0) { + if (oldTreeLength > 0) { + for (let i = oldTreeLength; i--; ) { + oldTree[i] instanceof Vnode && callRemove(oldTree[i]); + } + // Fast node remove by setting textContent + newParentVnode.dom.textContent = ""; + } + // If the tree is keyed list and is not first render + } else if (oldTreeLength && newTree[0] instanceof Vnode && "key" in newTree[0].props) { + // 1. Mutate the old key list to match the new key list + let oldKeyedList; + + // if the oldTree does not have a keyed list fast remove all nodes + if (oldTree[0] instanceof Vnode === false || "key" in oldTree[0].props === false) { + for (let i = oldTreeLength; i--; ) { + oldTree[i] instanceof Vnode && callRemove(oldTree[i]); + } + // Fast node remove by setting textContent + newParentVnode.dom.textContent = ""; + oldKeyedList = []; + } else { + oldKeyedList = oldTree.map((vnode) => vnode.props.key); + } + + // 2. Obtain the max length of both lists + let newKeyedList = newTree.map((vnode) => vnode.props.key); + const maxListLength = Math.max(newTreeLength, oldKeyedList.length); + + // 3. Cycle over all the elements of the list until the max length + for (let i = 0; i < maxListLength; i++) { + if (i < newTreeLength) { + let childVnode = newTree[i]; + let oldChildVnode = oldKeyedList[i] === newKeyedList[i] ? oldTree[i] : oldTree[oldKeyedList.indexOf(childVnode.props.key)]; + let shouldPatch = true; + + if (oldChildVnode) { + childVnode.dom = oldChildVnode.dom; + oldChildVnode.processed = true; + if ("v-once" in childVnode.props || (childVnode.props.onbeforeupdate && childVnode.props.onbeforeupdate(childVnode, oldChildVnode) === false)) { + // skip this patch + childVnode.children = oldChildVnode.children; + shouldPatch = false; + } else { + removeProperties(childVnode as Vnode & { dom: DomElement }, oldChildVnode); + updateProperties(childVnode as Vnode & { dom: DomElement }, oldChildVnode); + if (v.isMounted) { + childVnode.props.onupdate && childVnode.props.onupdate(childVnode, oldChildVnode); + } else { + childVnode.props.oncreate && childVnode.props.oncreate(childVnode); + } + } + } else { + childVnode.dom = createElement(childVnode.name, childVnode.isSVG); + updateProperties(childVnode as Vnode & { dom: DomElement }); + childVnode.props.oncreate && childVnode.props.oncreate(childVnode); + } + + if (newParentVnode.dom.childNodes[i] === undefined) { + newParentVnode.dom.appendChild(childVnode.dom); + } else if (newParentVnode.dom.childNodes[i] !== childVnode.dom) { + oldTree[i] instanceof Vnode && !oldTree[i].processed && newKeyedList.indexOf(oldTree[i].props.key) === -1 && callRemove(oldTree[i]); + newParentVnode.dom.replaceChild(childVnode.dom, newParentVnode.dom.childNodes[i]); + } + + shouldPatch && patch(childVnode as Vnode & { dom: DomElement }, oldChildVnode); + } else { + if (!oldTree[i].processed) { + oldTree[i] instanceof Vnode && callRemove(oldTree[i]); + oldTree[i].dom.parentNode && newParentVnode.dom.removeChild(oldTree[i].dom); + } + } + } + } else { + for (let i = 0; i < newTreeLength; i++) { + let childVnode = newTree[i]; + let oldChildVnode = oldTree[i]; + + // if oldChildVnode is undefined, it's a new node, append it + if (oldChildVnode === undefined) { + if (childVnode instanceof Vnode) { + childVnode.dom = createElement(childVnode.name, childVnode.isSVG); + updateProperties(childVnode as Vnode & { dom: DomElement }); + childVnode.props.oncreate && childVnode.props.oncreate(childVnode); + patch(childVnode as Vnode & { dom: DomElement }); + } else { + childVnode.dom = document.createTextNode(childVnode.nodeValue); + } + newParentVnode.dom.appendChild(childVnode.dom); + } else { + // if childVnode is Vnode, replace it with its DOM node + if (childVnode instanceof Vnode) { + if (childVnode.name === oldChildVnode.name) { + childVnode.dom = oldChildVnode.dom; + + if ("v-once" in childVnode.props || (childVnode.props.onbeforeupdate && childVnode.props.onbeforeupdate(childVnode, oldChildVnode) === false)) { + // skip this patch + childVnode.children = oldChildVnode.children; + continue; + } + + removeProperties(childVnode as Vnode & { dom: DomElement }, oldChildVnode); + updateProperties(childVnode as Vnode & { dom: DomElement }, oldChildVnode); + if (v.isMounted) { + childVnode.props.onupdate && childVnode.props.onupdate(childVnode, oldChildVnode); + } else { + childVnode.props.oncreate && childVnode.props.oncreate(childVnode); + } + patch(childVnode as Vnode & { dom: DomElement }, oldChildVnode); + } else { + childVnode.dom = createElement(childVnode.name, childVnode.isSVG); + updateProperties(childVnode as Vnode & { dom: DomElement }); + childVnode.props.oncreate && childVnode.props.oncreate(childVnode); + oldChildVnode instanceof Vnode && callRemove(oldChildVnode); + newParentVnode.dom.replaceChild(childVnode.dom, oldChildVnode.dom); + patch(childVnode as Vnode & { dom: DomElement }); + } + } else { + if (oldChildVnode instanceof Vnode) { + childVnode.dom = document.createTextNode(childVnode.nodeValue); + callRemove(oldChildVnode); + newParentVnode.dom.replaceChild(childVnode.dom, oldChildVnode.dom as DomElement); + } else { + childVnode.dom = oldChildVnode.dom; + // eslint-disable-next-line eqeqeq + if (childVnode.nodeValue != childVnode.dom.nodeValue) { + childVnode.dom.nodeValue = childVnode.nodeValue; + } + } + } + } + } + + // For remaining old children: remove from DOM, garbage collect + for (let i = oldTreeLength - 1; i >= newTreeLength; --i) { + oldTree[i] instanceof Vnode && callRemove(oldTree[i]); + oldTree[i].dom.parentNode && newParentVnode.dom.removeChild(oldTree[i].dom); + } + } + + newParentVnode.children = newTree; + } + + let mainVnode: Vnode | null = null; + let oldMainVnode: Vnode | null = null; + + v.unMount = () => { + mountedComponent = emptyComponent; + let result = v.update(); + v.isMounted = false; + mainContainer = null; + return result; + }; + + v.update = (props, ...children) => { + if (mainVnode) { + cleanupVnodes(); + oldMainVnode = mainVnode; + mainVnode = new Vnode(mainVnode.name, mainVnode.props, [v(mountedComponent, props, ...children)]); + mainVnode.dom = oldMainVnode.dom; + mainVnode.isSVG = oldMainVnode.isSVG; + patch(mainVnode as Vnode & { dom: Node }, oldMainVnode as Vnode & { dom: Node }); + v.isMounted = true; + if (v.isNode) { + return (mainVnode.dom as HTMLElement).innerHTML; + } + } + }; + + v.mount = (container, component, props, ...children) => { + if (v.isMounted) { + v.unMount(); + } + + if (isNode) { + mainContainer = typeof container === "string" ? createElement(container, container === "svg") : container; + } else { + mainContainer = typeof container === "string" ? (document.querySelectorAll(container)[0] as DomElement) : container; + } + + if (mainContainer !== null) { + mainVnode = domToVnode(mainContainer); + mainVnode.isSVG = mainVnode.name === "svg"; + oldMainVnode = mainVnode; + mountedComponent = component; + } + + return v.update(props, ...children); + }; + + let directives: Record = {}; + + v.directive = (name: string, directive: Directive) => { + let fullName = `v-${name}`; + if (reservedWords.indexOf(fullName) === -1) { + reservedWords.push(fullName); + directives[fullName] = directive; + } + }; + + let hideDirective = (test: boolean) => (bool: boolean, vnode: Vnode, oldnode?: Vnode | TextVnode) => { + let value = test ? bool : !bool; + if (value) { + let newdom = document.createTextNode(""); + if (oldnode && oldnode.dom && oldnode.dom.parentNode) { + oldnode instanceof Vnode && callRemove(oldnode); + oldnode.dom.parentNode.replaceChild(newdom, oldnode.dom); + } + vnode.name = "#text"; + vnode.children = []; + vnode.props = {}; + vnode.dom = newdom as unknown as DomElement; + return false; + } + }; + + v.directive("if", hideDirective(false)); + v.directive("unless", hideDirective(true)); + v.directive("for", (set: unknown[], vnode: Vnode) => { + vnode.children = set.map(vnode.children[0] as (value: unknown) => Function); + }); + v.directive("show", (bool: boolean, vnode: Vnode) => { + (vnode.dom as { style: { display: string } }).style.display = bool ? "" : "none"; + }); + v.directive("class", (classes: { [x: string]: boolean }, vnode: Vnode) => { + for (let name in classes) { + (vnode.dom as DomElement).classList.toggle(name, classes[name]); + } + }); + v.directive("html", (html: string, vnode: Vnode) => { + vnode.children = [trust(html)]; + }); + + v.newInstance = valyrian; + + return v; +} + +export const v = valyrian(); diff --git a/bench/mount_n_update_bench.js b/bench/mount_n_update_bench.js index baca7a3..1711f34 100644 --- a/bench/mount_n_update_bench.js +++ b/bench/mount_n_update_bench.js @@ -4,9 +4,11 @@ const { mount, update, unmount, v } = require("../lib/index"); const expect = require("expect"); require("../plugins/node"); -const vOld = require("./index-old"); +const { v: vOld } = require("./index-old.ts"); const { useEffect } = require("../plugins/hooks"); +console.log(vOld); + let VNext = v; let data = { diff --git a/dist/@types/lib/index.d.ts b/dist/@types/lib/index.d.ts new file mode 100644 index 0000000..d007ac5 --- /dev/null +++ b/dist/@types/lib/index.d.ts @@ -0,0 +1,17 @@ +import { Directive, DomElement, IVnode, Valyrian, ValyrianComponent, VnodeComponent, VnodeWithDom } from "./interfaces"; +export declare const Vnode: IVnode; +export declare function isVnode(component?: unknown): component is IVnode; +export declare function isComponent(component?: unknown | ValyrianComponent): component is ValyrianComponent; +export declare function isVnodeComponent(vnode?: unknown): vnode is VnodeComponent; +export declare const isNodeJs: boolean; +export declare const trust: (htmlString: string) => IVnode[]; +export declare function onCleanup(callback: Function): void; +export declare function onUnmount(callback: Function): void; +export declare function onMount(callback: Function): void; +export declare function onUpdate(callback: Function): void; +export declare function mount(container: DomElement | string, component: ValyrianComponent | IVnode): any; +export declare function update(component?: ValyrianComponent | IVnode): any; +export declare function unmount(component?: ValyrianComponent | IVnode): string | undefined; +export declare function setProperty(name: string, value: any, vnode: VnodeWithDom, oldVnode?: VnodeWithDom): void; +export declare function directive(name: string, directive: Directive): void; +export declare const v: Valyrian; diff --git a/dist/@types/lib/interfaces.d.ts b/dist/@types/lib/interfaces.d.ts new file mode 100644 index 0000000..4a56018 --- /dev/null +++ b/dist/@types/lib/interfaces.d.ts @@ -0,0 +1,90 @@ +export interface DomElement extends Element { + [key: string]: any; +} +export interface Props { + key?: string | number; + data?: string; + oncreate?: { + (vnode: IVnode): never; + }; + onupdate?: { + (vnode: IVnode, oldVnode: IVnode): never; + }; + onremove?: { + (oldVnode: IVnode): never; + }; + shouldupdate?: { + (vnode: IVnode, oldVnode: IVnode): undefined | boolean; + }; + [key: string | number | symbol]: any; +} +export interface Children extends Array { +} +export interface IVnode { + new (tag: string, props: Props, children: IVnode[]): IVnode; + tag: string; + props: Props; + children: Children; + dom?: DomElement; + isSVG?: boolean; + processed?: boolean; + component?: Component | POJOComponent; + nodeValue?: string; + [key: string | number | symbol]: any; +} +export interface Component { + (props?: Record | null, children?: Children): IVnode | Children; + [key: string | number | symbol]: any; +} +export interface POJOComponent { + view: Component; + [key: string | number | symbol]: any; +} +export declare type ValyrianComponent = Component | POJOComponent; +export interface VnodeComponent extends IVnode { + tag: "__component__"; + component: ValyrianComponent; +} +export interface VnodeWithDom extends IVnode { + dom: DomElement; +} +export interface Directive { + (value: any, vnode: VnodeWithDom, oldVnode?: VnodeWithDom): void; +} +export interface ValyrianApp { + isMounted: boolean; + eventListenerNames: Record; + onCleanup: Function[]; + onUnmount: Function[]; + onMount: Function[]; + onUpdate: Function[]; + eventListener?: EventListener; + mainVnode?: VnodeWithDom; + container?: DomElement; + [key: string | number | symbol]: any; +} +export interface MountedValyrianApp extends ValyrianApp { + eventListener: EventListener; + mainVnode: VnodeWithDom; + container: DomElement; +} +export interface Current { + app?: ValyrianApp; + component?: ValyrianComponent; + vnode?: VnodeWithDom; + oldVnode?: VnodeWithDom; +} +export interface Directives { + [key: string]: Directive; +} +export interface ReservedProps { + [key: string]: true; +} +export interface Valyrian { + (tagOrComponent: string | ValyrianComponent, props: Props, ...children: Children): IVnode | VnodeComponent; + fragment: (props: Props, ...children: Children) => Children; + current: Current; + directives: Directives; + reservedProps: ReservedProps; + [key: string | number | symbol]: any; +} diff --git a/dist/index.cjs b/dist/index.cjs index de973e9..96e0f5f 100644 --- a/dist/index.cjs +++ b/dist/index.cjs @@ -25,19 +25,21 @@ var __toCommonJS = /* @__PURE__ */ ((cache) => { var lib_exports = {}; __export(lib_exports, { Vnode: () => Vnode, - cleanup: () => cleanup, directive: () => directive, isComponent: () => isComponent, isNodeJs: () => isNodeJs, isVnode: () => isVnode, isVnodeComponent: () => isVnodeComponent, mount: () => mount, - onremove: () => onremove, + onCleanup: () => onCleanup, + onMount: () => onMount, + onUnmount: () => onUnmount, + onUpdate: () => onUpdate, + setProperty: () => setProperty, trust: () => trust, unmount: () => unmount, update: () => update, - updateProperty: () => updateProperty, - valyrian: () => valyrian + v: () => v }); var Vnode = function Vnode2(tag, props, children) { this.props = props; @@ -77,9 +79,24 @@ var trust = (htmlString) => { return [].map.call(div.childNodes, (item) => domToVnode(item)); }; var ValyrianSymbol = Symbol("Valyrian"); -function cleanup(callback) { - if (v.current.app?.cleanup.indexOf(callback) === -1) { - v.current.app?.cleanup.push(callback); +function onCleanup(callback) { + if (v.current.app?.onCleanup.indexOf(callback) === -1) { + v.current.app?.onCleanup.push(callback); + } +} +function onUnmount(callback) { + if (v.current.app?.onUnmount.indexOf(callback) === -1) { + v.current.app?.onUnmount.push(callback); + } +} +function onMount(callback) { + if (v.current.app?.onMount.indexOf(callback) === -1) { + v.current.app?.onMount.push(callback); + } +} +function onUpdate(callback) { + if (v.current.app?.onUpdate.indexOf(callback) === -1) { + v.current.app?.onUpdate.push(callback); } } function mount(container, component) { @@ -120,34 +137,60 @@ function mount(container, component) { component[ValyrianSymbol] = { isMounted: false, eventListenerNames: {}, - isNodeJs, - cleanup: [] + onCleanup: [], + onMount: [], + onUpdate: [], + onUnmount: [] }; component[ValyrianSymbol].eventListener = eventListener; } component[ValyrianSymbol].component = vnodeComponent; component[ValyrianSymbol].container = appContainer; component[ValyrianSymbol].mainVnode = domToVnode(appContainer); + component[ValyrianSymbol].mainVnode.isSVG = component[ValyrianSymbol].tag === "svg"; return update(component); } -function cleanupVnodes(valyrianApp) { - for (let i = 0; i < valyrianApp.cleanup.length; i++) { - valyrianApp.cleanup[i](); +function callCleanup(valyrianApp) { + for (let i = 0; i < valyrianApp.onCleanup.length; i++) { + valyrianApp.onCleanup[i](); + } + valyrianApp.onCleanup = []; +} +function callUnmount(valyrianApp) { + for (let i = 0; i < valyrianApp.onUnmount.length; i++) { + valyrianApp.onUnmount[i](); + } + valyrianApp.onUnmount = []; +} +function callMount(valyrianApp) { + for (let i = 0; i < valyrianApp.onMount.length; i++) { + valyrianApp.onMount[i](); } - valyrianApp.cleanup = []; + valyrianApp.onMount = []; +} +function callUpdate(valyrianApp) { + for (let i = 0; i < valyrianApp.onUpdate.length; i++) { + valyrianApp.onUpdate[i](); + } + valyrianApp.onUpdate = []; } function update(component) { if (component && component[ValyrianSymbol]) { let valyrianApp = component[ValyrianSymbol]; v.current.app = valyrianApp; - cleanupVnodes(valyrianApp); + valyrianApp.onCleanup.length && callCleanup(valyrianApp); let oldVnode = valyrianApp.mainVnode; valyrianApp.mainVnode = new Vnode(valyrianApp.mainVnode.tag, valyrianApp.mainVnode.props, [valyrianApp.component]); valyrianApp.mainVnode.dom = oldVnode.dom; valyrianApp.mainVnode.isSVG = oldVnode.isSVG; patch(valyrianApp.mainVnode, oldVnode, valyrianApp); oldVnode = null; - valyrianApp.isMounted = true; + if (valyrianApp.isMounted === false) { + valyrianApp.onMount.length && callMount(valyrianApp); + valyrianApp.isMounted = true; + } else { + valyrianApp.onUpdate.length && callUpdate(valyrianApp); + } if (isNodeJs) { return valyrianApp.mainVnode.dom.innerHTML; } @@ -159,17 +202,19 @@ function unmount(component) { } let valyrianApp = component[ValyrianSymbol]; if (valyrianApp.isMounted) { - cleanupVnodes(valyrianApp); + valyrianApp.onCleanup.length && callCleanup(valyrianApp); + valyrianApp.onUnmount.length && callUnmount(valyrianApp); let oldVnode = valyrianApp.mainVnode; valyrianApp.mainVnode = new Vnode(valyrianApp.mainVnode.tag, valyrianApp.mainVnode.props, []); valyrianApp.mainVnode.dom = oldVnode.dom; valyrianApp.mainVnode.isSVG = oldVnode.isSVG; patch(valyrianApp.mainVnode, oldVnode, valyrianApp); oldVnode = null; - valyrianApp.isMounted = false; if (isNodeJs) { return valyrianApp.mainVnode.dom.innerHTML; } + valyrianApp = null; + Reflect.deleteProperty(component, ValyrianSymbol); } } var emptyVnode = new Vnode("__empty__", {}, []); @@ -209,7 +254,7 @@ function sharedUpdateProperty(prop, value, vnode, oldVnode) { } } } -function updateProperty(name, value, vnode, oldVnode) { +function setProperty(name, value, vnode, oldVnode) { if (name in vnode.props === false) { vnode.props[name] = value; } @@ -463,15 +508,15 @@ var builtInDirectives = { handler = () => model[property] = !model[property]; value = model[property]; } - updateProperty("checked", value, vnode, oldVnode); + setProperty("checked", value, vnode, oldVnode); break; } case "radio": { - updateProperty("checked", model[property] === vnode.dom.value, vnode, oldVnode); + setProperty("checked", model[property] === vnode.dom.value, vnode, oldVnode); break; } default: { - updateProperty("value", model[property], vnode, oldVnode); + setProperty("value", model[property], vnode, oldVnode); } } } else if (vnode.name === "select") { @@ -513,11 +558,11 @@ var builtInDirectives = { if (!handler) { handler = (e) => model[property] = e.target.value; } - updateProperty(event, handler, vnode, oldVnode); + setProperty(event, handler, vnode, oldVnode); } } }; -var valyrian = function v2(tagOrComponent, props, ...children) { +var v = function v2(tagOrComponent, props, ...children) { if (typeof tagOrComponent === "string") { return new Vnode(tagOrComponent, props || {}, children); } @@ -525,12 +570,12 @@ var valyrian = function v2(tagOrComponent, props, ...children) { vnode.component = tagOrComponent; return vnode; }; -valyrian.fragment = (props, ...children) => { +v.fragment = (props, ...children) => { return children; }; -valyrian.current = {}; -valyrian.directives = { ...builtInDirectives }; -valyrian.reservedProps = { +v.current = {}; +v.directives = { ...builtInDirectives }; +v.reservedProps = { key: true, state: true, oncreate: true, @@ -546,5 +591,5 @@ valyrian.reservedProps = { "v-class": true, "v-html": true }; -(isNodeJs ? global : window).v = valyrian; +(isNodeJs ? global : window).v = v; module.exports = __toCommonJS(lib_exports); diff --git a/dist/index.js b/dist/index.js index da149b0..6853b28 100644 --- a/dist/index.js +++ b/dist/index.js @@ -37,9 +37,24 @@ var trust = (htmlString) => { return [].map.call(div.childNodes, (item) => domToVnode(item)); }; var ValyrianSymbol = Symbol("Valyrian"); -function cleanup(callback) { - if (v.current.app?.cleanup.indexOf(callback) === -1) { - v.current.app?.cleanup.push(callback); +function onCleanup(callback) { + if (v.current.app?.onCleanup.indexOf(callback) === -1) { + v.current.app?.onCleanup.push(callback); + } +} +function onUnmount(callback) { + if (v.current.app?.onUnmount.indexOf(callback) === -1) { + v.current.app?.onUnmount.push(callback); + } +} +function onMount(callback) { + if (v.current.app?.onMount.indexOf(callback) === -1) { + v.current.app?.onMount.push(callback); + } +} +function onUpdate(callback) { + if (v.current.app?.onUpdate.indexOf(callback) === -1) { + v.current.app?.onUpdate.push(callback); } } function mount(container, component) { @@ -80,34 +95,60 @@ function mount(container, component) { component[ValyrianSymbol] = { isMounted: false, eventListenerNames: {}, - isNodeJs, - cleanup: [] + onCleanup: [], + onMount: [], + onUpdate: [], + onUnmount: [] }; component[ValyrianSymbol].eventListener = eventListener; } component[ValyrianSymbol].component = vnodeComponent; component[ValyrianSymbol].container = appContainer; component[ValyrianSymbol].mainVnode = domToVnode(appContainer); + component[ValyrianSymbol].mainVnode.isSVG = component[ValyrianSymbol].tag === "svg"; return update(component); } -function cleanupVnodes(valyrianApp) { - for (let i = 0; i < valyrianApp.cleanup.length; i++) { - valyrianApp.cleanup[i](); +function callCleanup(valyrianApp) { + for (let i = 0; i < valyrianApp.onCleanup.length; i++) { + valyrianApp.onCleanup[i](); + } + valyrianApp.onCleanup = []; +} +function callUnmount(valyrianApp) { + for (let i = 0; i < valyrianApp.onUnmount.length; i++) { + valyrianApp.onUnmount[i](); + } + valyrianApp.onUnmount = []; +} +function callMount(valyrianApp) { + for (let i = 0; i < valyrianApp.onMount.length; i++) { + valyrianApp.onMount[i](); } - valyrianApp.cleanup = []; + valyrianApp.onMount = []; +} +function callUpdate(valyrianApp) { + for (let i = 0; i < valyrianApp.onUpdate.length; i++) { + valyrianApp.onUpdate[i](); + } + valyrianApp.onUpdate = []; } function update(component) { if (component && component[ValyrianSymbol]) { let valyrianApp = component[ValyrianSymbol]; v.current.app = valyrianApp; - cleanupVnodes(valyrianApp); + valyrianApp.onCleanup.length && callCleanup(valyrianApp); let oldVnode = valyrianApp.mainVnode; valyrianApp.mainVnode = new Vnode(valyrianApp.mainVnode.tag, valyrianApp.mainVnode.props, [valyrianApp.component]); valyrianApp.mainVnode.dom = oldVnode.dom; valyrianApp.mainVnode.isSVG = oldVnode.isSVG; patch(valyrianApp.mainVnode, oldVnode, valyrianApp); oldVnode = null; - valyrianApp.isMounted = true; + if (valyrianApp.isMounted === false) { + valyrianApp.onMount.length && callMount(valyrianApp); + valyrianApp.isMounted = true; + } else { + valyrianApp.onUpdate.length && callUpdate(valyrianApp); + } if (isNodeJs) { return valyrianApp.mainVnode.dom.innerHTML; } @@ -119,17 +160,19 @@ function unmount(component) { } let valyrianApp = component[ValyrianSymbol]; if (valyrianApp.isMounted) { - cleanupVnodes(valyrianApp); + valyrianApp.onCleanup.length && callCleanup(valyrianApp); + valyrianApp.onUnmount.length && callUnmount(valyrianApp); let oldVnode = valyrianApp.mainVnode; valyrianApp.mainVnode = new Vnode(valyrianApp.mainVnode.tag, valyrianApp.mainVnode.props, []); valyrianApp.mainVnode.dom = oldVnode.dom; valyrianApp.mainVnode.isSVG = oldVnode.isSVG; patch(valyrianApp.mainVnode, oldVnode, valyrianApp); oldVnode = null; - valyrianApp.isMounted = false; if (isNodeJs) { return valyrianApp.mainVnode.dom.innerHTML; } + valyrianApp = null; + Reflect.deleteProperty(component, ValyrianSymbol); } } var emptyVnode = new Vnode("__empty__", {}, []); @@ -169,7 +212,7 @@ function sharedUpdateProperty(prop, value, vnode, oldVnode) { } } } -function updateProperty(name, value, vnode, oldVnode) { +function setProperty(name, value, vnode, oldVnode) { if (name in vnode.props === false) { vnode.props[name] = value; } @@ -423,15 +466,15 @@ var builtInDirectives = { handler = () => model[property] = !model[property]; value = model[property]; } - updateProperty("checked", value, vnode, oldVnode); + setProperty("checked", value, vnode, oldVnode); break; } case "radio": { - updateProperty("checked", model[property] === vnode.dom.value, vnode, oldVnode); + setProperty("checked", model[property] === vnode.dom.value, vnode, oldVnode); break; } default: { - updateProperty("value", model[property], vnode, oldVnode); + setProperty("value", model[property], vnode, oldVnode); } } } else if (vnode.name === "select") { @@ -473,11 +516,11 @@ var builtInDirectives = { if (!handler) { handler = (e) => model[property] = e.target.value; } - updateProperty(event, handler, vnode, oldVnode); + setProperty(event, handler, vnode, oldVnode); } } }; -var valyrian = function v2(tagOrComponent, props, ...children) { +var v = function v2(tagOrComponent, props, ...children) { if (typeof tagOrComponent === "string") { return new Vnode(tagOrComponent, props || {}, children); } @@ -485,12 +528,12 @@ var valyrian = function v2(tagOrComponent, props, ...children) { vnode.component = tagOrComponent; return vnode; }; -valyrian.fragment = (props, ...children) => { +v.fragment = (props, ...children) => { return children; }; -valyrian.current = {}; -valyrian.directives = { ...builtInDirectives }; -valyrian.reservedProps = { +v.current = {}; +v.directives = { ...builtInDirectives }; +v.reservedProps = { key: true, state: true, oncreate: true, @@ -506,20 +549,22 @@ valyrian.reservedProps = { "v-class": true, "v-html": true }; -(isNodeJs ? global : window).v = valyrian; +(isNodeJs ? global : window).v = v; export { Vnode, - cleanup, directive, isComponent, isNodeJs, isVnode, isVnodeComponent, mount, - onremove, + onCleanup, + onMount, + onUnmount, + onUpdate, + setProperty, trust, unmount, update, - updateProperty, - valyrian + v }; diff --git a/dist/index.min.js b/dist/index.min.js index ee26583..44fd03e 100644 --- a/dist/index.min.js +++ b/dist/index.min.js @@ -1 +1 @@ -(()=>{var e=function(e,o,n){this.props=o,this.children=n,this.tag=e};function o(e){return"function"==typeof e||"object"==typeof e&&null!==e&&"view"in e}function n(o){return o instanceof e&&"__component__"===o.tag}var t=Boolean("undefined"!=typeof process&&process.versions&&process.versions.node);function r(e,o=!1){return o?document.createElementNS("http://www.w3.org/2000/svg",e):document.createElement(e)}function i(o){let n=v(o.tagName.toLowerCase(),{},...Array.from(o.childNodes).filter(e=>1===e.nodeType||3===e.nodeType).map(o=>{if(1===o.nodeType)return i(o);let n=new e("#text",{},[]);return n.nodeValue=String(o.nodeValue),n.dom=o,n}));return[].forEach.call(o.attributes,e=>n.props[e.nodeName]=e.nodeValue),n.dom=o,n}var d=e=>{let o=r("div");return o.innerHTML=e.trim(),[].map.call(o.childNodes,e=>i(e))},p=Symbol("Valyrian");function l(e){for(let o=0;o0&&"#text"===n[t-1].tag?(n[t-1].nodeValue+=r,n.splice(t--,1)):(n[t]=new e("#text",{},[]),n[t].nodeValue=String(r))}}(o);let i=o.children,d=n.children,p=d.length,l=i.length;if(0!==l)p&&"key"in i[0].props&&"key"in d[0].props?function(e,o,n,t,i,d){let p=n.reduce((e,o,n)=>(e[o.props.key]=n,e),{}),l=o.reduce((e,o,n)=>(e[o.props.key]=n,e),{});for(let i=0;i{if(e?o:!o){let e=document.createTextNode("");t&&t.dom&&t.dom.parentNode&&("#text"!==t.tag&&u(t),t.dom.parentNode.replaceChild(e,t.dom)),n.tag="#text",n.children=[],n.props={},n.dom=e}}}var y={"v-if":V(!1),"v-unless":V(!0),"v-for":(e,o)=>{o.children=e.map(o.children[0])},"v-show":(e,o)=>{o.dom.style.display=e?"":"none"},"v-class":(e,o)=>{for(let n in e)o.dom.classList.toggle(n,e[n])},"v-html":(e,o)=>{o.children=[d(e)]},"v-model":([e,o,n],t,r)=>{let i,d;if("input"===t.name)switch(n=n||"oninput",t.props.type){case"checkbox":Array.isArray(e[o])?(d=n=>{let t=n.target.value,r=e[o].indexOf(t);-1===r?e[o].push(t):e[o].splice(r,1)},i=-1!==e[o].indexOf(t.dom.value)):"value"in t.props?(d=()=>{e[o]===t.props.value?e[o]=null:e[o]=t.props.value},i=e[o]===t.props.value):(d=()=>e[o]=!e[o],i=e[o]),f("checked",i,t,r);break;case"radio":f("checked",e[o]===t.dom.value,t,r);break;default:f("value",e[o],t,r)}else"select"===t.name?(n=n||"onclick",t.props.multiple?(d=n=>{let t=n.target.value;if(n.ctrlKey){let n=e[o].indexOf(t);-1===n?e[o].push(t):e[o].splice(n,1)}else e[o].splice(0,e[o].length),e[o].push(t)},t.children.forEach(n=>{if("option"===n.name){let t="value"in n.props?n.props.value:n.children.join("").trim();n.props.selected=-1!==e[o].indexOf(t)}})):t.children.forEach(n=>{if("option"===n.name){let t="value"in n.props?n.props.value:n.children.join("").trim();n.props.selected=t===e[o]}})):"textarea"===t.name&&(n=n||"oninput",t.children=[e[o]]);t.props[n]||(d||(d=n=>e[o]=n.target.value),f(n,d,t,r))}},w=function(o,n,...t){if("string"==typeof o)return new e(o,n||{},t);const r=new e("__component__",n||{},t);return r.component=o,r};w.fragment=(e,...o)=>o,w.current={},w.directives={...y},w.reservedProps={key:!0,state:!0,oncreate:!0,onupdate:!0,onremove:!0,shouldupdate:!0,"v-cleanup":!0,"v-once":!0,"v-if":!0,"v-unless":!0,"v-for":!0,"v-show":!0,"v-class":!0,"v-html":!0},(t?global:window).v=w;var x={Vnode:e,cleanup:function(e){-1===v.current.app?.cleanup.indexOf(e)&&v.current.app?.cleanup.push(e)},directive:function(e,o){let n=`v-${e}`;v.directives[n]=o,v.reservedProps[n]=!0},isComponent:o,isNodeJs:t,isVnode:function(o){return o instanceof e},isVnodeComponent:n,mount:function(e,d){let l,c=null;if(c=t?"string"==typeof e?r("svg"===e?"svg":"div","svg"===e):e:"string"==typeof e?document.querySelectorAll(e)[0]:e,!c)throw new Error("Container not found");if(n(d))l=d;else{if(!o(d))throw new Error("Component must be a Valyrian Component or a Vnode component");l=v(d,{})}if(d[p])a(d);else{let e=function(e){let o=e.target,n=`v-on${e.type}`;for(;o;){if(o[n])return o[n](e,o),void(e.defaultPrevented||s(d));o=o.parentNode}};d[p]={isMounted:!1,eventListenerNames:{},isNodeJs:t,cleanup:[]},d[p].eventListener=e}return d[p].component=l,d[p].container=c,d[p].mainVnode=i(c),s(d)},onremove:u,trust:d,unmount:a,update:s,updateProperty:f,valyrian:w};"undefined"!=typeof module?module.exports=x:self.Valyrian=x})(); \ No newline at end of file +(()=>{var e=function(e,n,o){this.props=n,this.children=o,this.tag=e};function n(e){return"function"==typeof e||"object"==typeof e&&null!==e&&"view"in e}function o(n){return n instanceof e&&"__component__"===n.tag}var t=Boolean("undefined"!=typeof process&&process.versions&&process.versions.node);function r(e,n=!1){return n?document.createElementNS("http://www.w3.org/2000/svg",e):document.createElement(e)}function i(n){let o=y(n.tagName.toLowerCase(),{},...Array.from(n.childNodes).filter(e=>1===e.nodeType||3===e.nodeType).map(n=>{if(1===n.nodeType)return i(n);let o=new e("#text",{},[]);return o.nodeValue=String(n.nodeValue),o.dom=n,o}));return[].forEach.call(n.attributes,e=>o.props[e.nodeName]=e.nodeValue),o.dom=n,o}var p=e=>{let n=r("div");return n.innerHTML=e.trim(),[].map.call(n.childNodes,e=>i(e))},d=Symbol("Valyrian");function l(e){for(let n=0;n0&&"#text"===o[t-1].tag?(o[t-1].nodeValue+=r,o.splice(t--,1)):(o[t]=new e("#text",{},[]),o[t].nodeValue=String(r))}}(n);let i=n.children,p=o.children,d=p.length,l=i.length;if(0!==l)d&&"key"in i[0].props&&"key"in p[0].props?function(e,n,o,t,i,p){let d=o.reduce((e,n,o)=>(e[n.props.key]=o,e),{}),l=n.reduce((e,n,o)=>(e[n.props.key]=o,e),{});for(let i=0;i{if(e?n:!n){let e=document.createTextNode("");t&&t.dom&&t.dom.parentNode&&("#text"!==t.tag&&c(t),t.dom.parentNode.replaceChild(e,t.dom)),o.tag="#text",o.children=[],o.props={},o.dom=e}}}var V={"v-if":g(!1),"v-unless":g(!0),"v-for":(e,n)=>{n.children=e.map(n.children[0])},"v-show":(e,n)=>{n.dom.style.display=e?"":"none"},"v-class":(e,n)=>{for(let o in e)n.dom.classList.toggle(o,e[o])},"v-html":(e,n)=>{n.children=[p(e)]},"v-model":([e,n,o],t,r)=>{let i,p;if("input"===t.name)switch(o=o||"oninput",t.props.type){case"checkbox":Array.isArray(e[n])?(p=o=>{let t=o.target.value,r=e[n].indexOf(t);-1===r?e[n].push(t):e[n].splice(r,1)},i=-1!==e[n].indexOf(t.dom.value)):"value"in t.props?(p=()=>{e[n]===t.props.value?e[n]=null:e[n]=t.props.value},i=e[n]===t.props.value):(p=()=>e[n]=!e[n],i=e[n]),f("checked",i,t,r);break;case"radio":f("checked",e[n]===t.dom.value,t,r);break;default:f("value",e[n],t,r)}else"select"===t.name?(o=o||"onclick",t.props.multiple?(p=o=>{let t=o.target.value;if(o.ctrlKey){let o=e[n].indexOf(t);-1===o?e[n].push(t):e[n].splice(o,1)}else e[n].splice(0,e[n].length),e[n].push(t)},t.children.forEach(o=>{if("option"===o.name){let t="value"in o.props?o.props.value:o.children.join("").trim();o.props.selected=-1!==e[n].indexOf(t)}})):t.children.forEach(o=>{if("option"===o.name){let t="value"in o.props?o.props.value:o.children.join("").trim();o.props.selected=t===e[n]}})):"textarea"===t.name&&(o=o||"oninput",t.children=[e[n]]);t.props[o]||(p||(p=o=>e[n]=o.target.value),f(o,p,t,r))}},y=function(n,o,...t){if("string"==typeof n)return new e(n,o||{},t);const r=new e("__component__",o||{},t);return r.component=n,r};y.fragment=(e,...n)=>n,y.current={},y.directives={...V},y.reservedProps={key:!0,state:!0,oncreate:!0,onupdate:!0,onremove:!0,shouldupdate:!0,"v-cleanup":!0,"v-once":!0,"v-if":!0,"v-unless":!0,"v-for":!0,"v-show":!0,"v-class":!0,"v-html":!0},(t?global:window).v=y;var x={Vnode:e,directive:function(e,n){let o=`v-${e}`;y.directives[o]=n,y.reservedProps[o]=!0},isComponent:n,isNodeJs:t,isVnode:function(n){return n instanceof e},isVnodeComponent:o,mount:function(e,p){let l,u=null;if(u=t?"string"==typeof e?r("svg"===e?"svg":"div","svg"===e):e:"string"==typeof e?document.querySelectorAll(e)[0]:e,!u)throw new Error("Container not found");if(o(p))l=p;else{if(!n(p))throw new Error("Component must be a Valyrian Component or a Vnode component");l=y(p,{})}if(p[d])s(p);else{let e=function(e){let n=e.target,o=`v-on${e.type}`;for(;n;){if(n[o])return n[o](e,n),void(e.defaultPrevented||a(p));n=n.parentNode}};p[d]={isMounted:!1,eventListenerNames:{},onCleanup:[],onMount:[],onUpdate:[],onUnmount:[]},p[d].eventListener=e}return p[d].component=l,p[d].container=u,p[d].mainVnode=i(u),p[d].mainVnode.isSVG="svg"===p[d].tag,a(p)},onCleanup:function(e){-1===y.current.app?.onCleanup.indexOf(e)&&y.current.app?.onCleanup.push(e)},onMount:function(e){-1===y.current.app?.onMount.indexOf(e)&&y.current.app?.onMount.push(e)},onUnmount:function(e){-1===y.current.app?.onUnmount.indexOf(e)&&y.current.app?.onUnmount.push(e)},onUpdate:function(e){-1===y.current.app?.onUpdate.indexOf(e)&&y.current.app?.onUpdate.push(e)},setProperty:f,trust:p,unmount:s,update:a,v:y};"undefined"!=typeof module?module.exports=x:self.Valyrian=x})(); \ No newline at end of file diff --git a/dist/index.min.js.map b/dist/index.min.js.map index fdec8d8..0c2b47d 100644 --- a/dist/index.min.js.map +++ b/dist/index.min.js.map @@ -1 +1 @@ -//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL2xpYi9pbmRleC50cyJdLCJuYW1lcyI6WyJWbm9kZSIsInRhZyIsInByb3BzIiwiY2hpbGRyZW4iLCJ0aGlzIiwiaXNDb21wb25lbnQiLCJjb21wb25lbnQiLCJpc1Zub2RlQ29tcG9uZW50Iiwidm5vZGUiLCJpc05vZGVKcyIsIkJvb2xlYW4iLCJwcm9jZXNzIiwidmVyc2lvbnMiLCJub2RlIiwiY3JlYXRlRG9tRWxlbWVudCIsImlzU1ZHIiwiZG9jdW1lbnQiLCJjcmVhdGVFbGVtZW50TlMiLCJjcmVhdGVFbGVtZW50IiwiZG9tVG9Wbm9kZSIsImRvbSIsInYiLCJ0YWdOYW1lIiwidG9Mb3dlckNhc2UiLCJBcnJheSIsImZyb20iLCJjaGlsZE5vZGVzIiwiZmlsdGVyIiwiY2hpbGQiLCJub2RlVHlwZSIsIm1hcCIsInRleHQiLCJub2RlVmFsdWUiLCJTdHJpbmciLCJmb3JFYWNoIiwiY2FsbCIsImF0dHJpYnV0ZXMiLCJwcm9wIiwibm9kZU5hbWUiLCJ0cnVzdCIsImh0bWxTdHJpbmciLCJkaXYiLCJpbm5lckhUTUwiLCJ0cmltIiwiaXRlbSIsIlZhbHlyaWFuU3ltYm9sIiwiU3ltYm9sIiwiY2xlYW51cFZub2RlcyIsInZhbHlyaWFuQXBwIiwiaSIsImNsZWFudXAiLCJsZW5ndGgiLCJ1cGRhdGUiLCJjdXJyZW50IiwiYXBwIiwib2xkVm5vZGUiLCJtYWluVm5vZGUiLCJwYXRjaCIsImlzTW91bnRlZCIsInVubW91bnQiLCJlbXB0eVZub2RlIiwib25yZW1vdmUiLCJzaGFyZWRVcGRhdGVQcm9wZXJ0eSIsInZhbHVlIiwicmVzZXJ2ZWRQcm9wcyIsImRpcmVjdGl2ZXMiLCJldmVudExpc3RlbmVyTmFtZXMiLCJjb250YWluZXIiLCJhZGRFdmVudExpc3RlbmVyIiwic2xpY2UiLCJldmVudExpc3RlbmVyIiwicmVtb3ZlQXR0cmlidXRlIiwic2V0QXR0cmlidXRlIiwidXBkYXRlUHJvcGVydHkiLCJuYW1lIiwidXBkYXRlUHJvcGVydGllcyIsIm5ld1Zub2RlIiwibmV3VHJlZSIsImNoaWxkVm5vZGUiLCJyZXN1bHQiLCJ2aWV3Iiwic3BsaWNlIiwiaXNBcnJheSIsImZsYXRUcmVlIiwib2xkVHJlZSIsIm9sZFRyZWVMZW5ndGgiLCJuZXdUcmVlTGVuZ3RoIiwib2xkS2V5ZWRMaXN0IiwicmVkdWNlIiwiYWNjIiwia2V5IiwibmV3S2V5ZWRMaXN0Iiwib2xkQ2hpbGRWbm9kZSIsInNob3VsZFBhdGNoIiwic2hvdWxkdXBkYXRlIiwib251cGRhdGUiLCJvbmNyZWF0ZSIsImFwcGVuZENoaWxkIiwicmVwbGFjZUNoaWxkIiwicGFyZW50Tm9kZSIsInJlbW92ZUNoaWxkIiwicGF0Y2hLZXllZFRyZWUiLCJuZXdDaGlsZFZub2RlIiwiY3JlYXRlVGV4dE5vZGUiLCJwYXRjaE5vcm1hbFRyZWUiLCJ0ZXh0Q29udGVudCIsImhpZGVEaXJlY3RpdmUiLCJ0ZXN0IiwiYm9vbCIsIm5ld2RvbSIsImJ1aWx0SW5EaXJlY3RpdmVzIiwic2V0Iiwic3R5bGUiLCJkaXNwbGF5IiwiY2xhc3NlcyIsImNsYXNzTGlzdCIsInRvZ2dsZSIsImh0bWwiLCJtb2RlbCIsInByb3BlcnR5IiwiZXZlbnQiLCJoYW5kbGVyIiwidHlwZSIsImUiLCJ2YWwiLCJ0YXJnZXQiLCJpZHgiLCJpbmRleE9mIiwicHVzaCIsIm11bHRpcGxlIiwiY3RybEtleSIsInZhbHVlMiIsImpvaW4iLCJzZWxlY3RlZCIsInZhbHlyaWFuIiwidGFnT3JDb21wb25lbnQiLCJmcmFnbWVudCIsInN0YXRlIiwiZ2xvYmFsIiwid2luZG93IiwiY2FsbGJhY2siLCJkaXJlY3RpdmUyIiwiZnVsbE5hbWUiLCJ2bm9kZUNvbXBvbmVudCIsImFwcENvbnRhaW5lciIsInF1ZXJ5U2VsZWN0b3JBbGwiLCJFcnJvciIsImRlZmF1bHRQcmV2ZW50ZWQiXSwibWFwcGluZ3MiOiJNQXNHTyxJQUFNQSxFQUFRLFNBQTZCQyxFQUFhQyxFQUFjQyxHQUMzRUMsS0FBS0YsTUFBUUEsRUFDYkUsS0FBS0QsU0FBV0EsRUFDaEJD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RUFBZ0M3RCxHQUNwRCxJQVlJeUksRUFaQUMsRUFBZSxLQVFuQixHQUxFQSxFQURFdkksRUFDa0MsaUJBQWQwRCxFQUF5QnJELEVBQStCLFFBQWRxRCxFQUFzQixNQUFRLE1BQXFCLFFBQWRBLEdBQXVCQSxFQUV4RixpQkFBZEEsRUFBeUJuRCxTQUFTaUksaUJBQWlCOUUsR0FBVyxHQUFLQSxHQUd0RjZFLEVBQ0gsTUFBTSxJQUFJRSxNQUFNLHVCQUtsQixHQUFJM0ksRUFBaUJELEdBQ25CeUksRUFBaUJ6SSxNQUFBLENBQUEsSUFDUkQsRUFBWUMsR0FHckIsTUFBTSxJQUFJNEksTUFBTSwrREFGaEJILEVBQWlCMUgsRUFBRWYsRUFBVyxJQUtoQyxHQUFJQSxFQUFVdUMsR0FDWmMsRUFBUXJELE9BQ0gsQ0FPTCxJQUFTZ0UsRUFBVCxTQUF1QnFELEdBQ3JCLElBQUl2RyxFQUFNdUcsRUFBRUUsT0FDUm5ELEVBQU8sT0FBT2lELEVBQUVELE9BQ3BCLEtBQU90RyxHQUFLLENBQ1YsR0FBSUEsRUFBSXNELEdBS04sT0FKQXRELEVBQUlzRCxHQUFNaUQsRUFBR3ZHLFFBQ1J1RyxFQUFFd0Isa0JBQ0wvRixFQUFPOUMsSUFJWGMsRUFBTUEsRUFBSStFLGFBakJkN0YsRUFBVXVDLEdBQWtCLENBQzFCYSxXQUFXLEVBQ1hRLG1CQUFvQixHQUNwQnpELFNBQUFBLEVBQ0F5QyxRQUFTLElBZ0JYNUMsRUFBVXVDLEdBQWdCeUIsY0FBZ0JBLEVBUTVDLE9BTEFoRSxFQUFVdUMsR0FBZ0J2QyxVQUFZeUksRUFDdEN6SSxFQUFVdUMsR0FBZ0JzQixVQUFZNkUsRUFDdEMxSSxFQUFVdUMsR0FBZ0JXLFVBQVlyQyxFQUFXNkgsR0FHMUM1RixFQUFPOUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKioqIEludGVyZmFjZXMgKioqL1xuXG5leHBvcnQgaW50ZXJmYWNlIERvbUVsZW1lbnQgZXh0ZW5kcyBFbGVtZW50IHtcbiAgW2tleTogc3RyaW5nXTogYW55O1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIFByb3BzIHtcbiAga2V5Pzogc3RyaW5nIHwgbnVtYmVyO1xuICBkYXRhPzogc3RyaW5nO1xuICBvbmNyZWF0ZT86IHsgKHZub2RlOiBJVm5vZGUpOiBuZXZlciB9O1xuICBvbnVwZGF0ZT86IHsgKHZub2RlOiBJVm5vZGUsIG9sZFZub2RlOiBJVm5vZGUpOiBuZXZlciB9O1xuICBvbnJlbW92ZT86IHsgKG9sZFZub2RlOiBJVm5vZGUpOiBuZXZlciB9O1xuICBzaG91bGR1cGRhdGU/OiB7ICh2bm9kZTogSVZub2RlLCBvbGRWbm9kZTogSVZub2RlKTogdW5kZWZpbmVkIHwgYm9vbGVhbiB9O1xuICBcInYtY2xlYW51cFwiPzogRnVuY3Rpb247XG4gIFtrZXk6IHN0cmluZyB8IG51bWJlciB8IHN5bWJvbF06IGFueTtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBDaGlsZHJlbiBleHRlbmRzIEFycmF5PElWbm9kZSB8IGFueT4ge31cblxuZXhwb3J0IGludGVyZmFjZSBJVm5vZGUge1xuICBuZXcgKHRhZzogc3RyaW5nLCBwcm9wczogUHJvcHMsIGNoaWxkcmVuOiBJVm5vZGVbXSk6IElWbm9kZTtcbiAgdGFnOiBzdHJpbmc7XG4gIHByb3BzOiBQcm9wcztcbiAgY2hpbGRyZW46IENoaWxkcmVuO1xuICBkb20/OiBEb21FbGVtZW50O1xuICBpc1NWRz86IGJvb2xlYW47XG4gIHByb2Nlc3NlZD86IGJvb2xlYW47XG4gIGNvbXBvbmVudD86IENvbXBvbmVudCB8IFBPSk9Db21wb25lbnQ7XG4gIG5vZGVWYWx1ZT86IHN0cmluZztcbiAgW2tleTogc3RyaW5nIHwgbnVtYmVyIHwgc3ltYm9sXTogYW55O1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIENvbXBvbmVudCB7XG4gIChwcm9wcz86IFJlY29yZDxzdHJpbmcsIGFueT4gfCBudWxsLCBjaGlsZHJlbj86IENoaWxkcmVuKTogSVZub2RlIHwgQ2hpbGRyZW47XG4gIFtrZXk6IHN0cmluZyB8IG51bWJlciB8IHN5bWJvbF06IGFueTtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBQT0pPQ29tcG9uZW50IHtcbiAgdmlldzogQ29tcG9uZW50O1xuICBba2V5OiBzdHJpbmcgfCBudW1iZXIgfCBzeW1ib2xdOiBhbnk7XG59XG5cbmV4cG9ydCB0eXBlIFZhbHlyaWFuQ29tcG9uZW50ID0gQ29tcG9uZW50IHwgUE9KT0NvbXBvbmVudDtcblxuZXhwb3J0IGludGVyZmFjZSBWbm9kZUNvbXBvbmVudCBleHRlbmRzIElWbm9kZSB7XG4gIHRhZzogXCJfX2NvbXBvbmVudF9fXCI7XG4gIGNvbXBvbmVudDogVmFseXJpYW5Db21wb25lbnQ7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgVm5vZGVXaXRoRG9tIGV4dGVuZHMgSVZub2RlIHtcbiAgZG9tOiBEb21FbGVtZW50O1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIERpcmVjdGl2ZSB7XG4gICh2YWx1ZTogYW55LCB2bm9kZTogVm5vZGVXaXRoRG9tLCBvbGRWbm9kZT86IFZub2RlV2l0aERvbSk6IHZvaWQ7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgVmFseXJpYW5BcHAge1xuICBpc01vdW50ZWQ6IGJvb2xlYW47XG4gIGV2ZW50TGlzdGVuZXJOYW1lczogUmVjb3JkPHN0cmluZywgdHJ1ZT47XG4gIGNsZWFudXA6IEZ1bmN0aW9uW107XG5cbiAgZXZlbnRMaXN0ZW5lcj86IEV2ZW50TGlzdGVuZXI7XG4gIG1haW5Wbm9kZT86IFZub2RlV2l0aERvbTtcbiAgY29tcG9uZW50PzogVm5vZGVDb21wb25lbnQ7XG4gIGNvbnRhaW5lcj86IERvbUVsZW1lbnQ7XG5cbiAgW2tleTogc3RyaW5nIHwgbnVtYmVyIHwgc3ltYm9sXTogYW55O1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIE1vdW50ZWRWYWx5cmlhbkFwcCBleHRlbmRzIFZhbHlyaWFuQXBwIHtcbiAgZXZlbnRMaXN0ZW5lcjogRXZlbnRMaXN0ZW5lcjtcbiAgbWFpblZub2RlOiBWbm9kZVdpdGhEb207XG4gIGNvbnRhaW5lcjogRG9tRWxlbWVudDtcbiAgY29tcG9uZW50OiBWbm9kZUNvbXBvbmVudDtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBDdXJyZW50IHtcbiAgYXBwPzogVmFseXJpYW5BcHA7XG4gIGNvbXBvbmVudD86IFZhbHlyaWFuQ29tcG9uZW50O1xuICB2bm9kZT86IFZub2RlV2l0aERvbTtcbiAgb2xkVm5vZGU/OiBWbm9kZVdpdGhEb207XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgRGlyZWN0aXZlcyB7XG4gIFtrZXk6IHN0cmluZ106IERpcmVjdGl2ZTtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBSZXNlcnZlZFByb3BzIHtcbiAgW2tleTogc3RyaW5nXTogdHJ1ZTtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBWYWx5cmlhbiB7XG4gICh0YWdPckNvbXBvbmVudDogc3RyaW5nIHwgVmFseXJpYW5Db21wb25lbnQsIHByb3BzOiBQcm9wcywgLi4uY2hpbGRyZW46IENoaWxkcmVuKTogSVZub2RlIHwgVm5vZGVDb21wb25lbnQ7XG4gIGZyYWdtZW50OiAocHJvcHM6IFByb3BzLCAuLi5jaGlsZHJlbjogQ2hpbGRyZW4pID0+IENoaWxkcmVuO1xuICBjdXJyZW50OiBDdXJyZW50O1xuICBkaXJlY3RpdmVzOiBEaXJlY3RpdmVzO1xuICByZXNlcnZlZFByb3BzOiBSZXNlcnZlZFByb3BzO1xufVxuXG4vKioqIFZub2RlICoqKi9cblxuZXhwb3J0IGNvbnN0IFZub2RlID0gZnVuY3Rpb24gVm5vZGUodGhpczogSVZub2RlLCB0YWc6IHN0cmluZywgcHJvcHM6IFByb3BzLCBjaGlsZHJlbjogQ2hpbGRyZW4pIHtcbiAgdGhpcy5wcm9wcyA9IHByb3BzO1xuICB0aGlzLmNoaWxkcmVuID0gY2hpbGRyZW47XG4gIHRoaXMudGFnID0gdGFnO1xufSBhcyB1bmtub3duIGFzIElWbm9kZTtcblxuZXhwb3J0IGZ1bmN0aW9uIGlzVm5vZGUoY29tcG9uZW50PzogdW5rbm93bik6IGNvbXBvbmVudCBpcyBJVm5vZGUge1xuICByZXR1cm4gY29tcG9uZW50IGluc3RhbmNlb2YgVm5vZGU7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBpc0NvbXBvbmVudChjb21wb25lbnQ/OiB1bmtub3duIHwgVmFseXJpYW5Db21wb25lbnQpOiBjb21wb25lbnQgaXMgVmFseXJpYW5Db21wb25lbnQge1xuICByZXR1cm4gdHlwZW9mIGNvbXBvbmVudCA9PT0gXCJmdW5jdGlvblwiIHx8ICh0eXBlb2YgY29tcG9uZW50ID09PSBcIm9iamVjdFwiICYmIGNvbXBvbmVudCAhPT0gbnVsbCAmJiBcInZpZXdcIiBpbiBjb21wb25lbnQpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gaXNWbm9kZUNvbXBvbmVudCh2bm9kZT86IHVua25vd24pOiB2bm9kZSBpcyBWbm9kZUNvbXBvbmVudCB7XG4gIHJldHVybiB2bm9kZSBpbnN0YW5jZW9mIFZub2RlICYmIHZub2RlLnRhZyA9PT0gXCJfX2NvbXBvbmVudF9fXCI7XG59XG5cbi8qKiogVXRpbCAqKiovXG5cbmV4cG9ydCBjb25zdCBpc05vZGVKcyA9IEJvb2xlYW4odHlwZW9mIHByb2Nlc3MgIT09IFwidW5kZWZpbmVkXCIgJiYgcHJvY2Vzcy52ZXJzaW9ucyAmJiBwcm9jZXNzLnZlcnNpb25zLm5vZGUpO1xuXG5mdW5jdGlvbiBjcmVhdGVEb21FbGVtZW50KHRhZzogc3RyaW5nLCBpc1NWRzogYm9vbGVhbiA9IGZhbHNlKSB7XG4gIHJldHVybiBpc1NWRyA/IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnROUyhcImh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnXCIsIHRhZykgOiBkb2N1bWVudC5jcmVhdGVFbGVtZW50KHRhZyk7XG59XG5cbmZ1bmN0aW9uIGRvbVRvVm5vZGUoZG9tOiBEb21FbGVtZW50KTogVm5vZGVXaXRoRG9tIHtcbiAgbGV0IHZub2RlID0gdihcbiAgICBkb20udGFnTmFtZS50b0xvd2VyQ2FzZSgpLFxuICAgIHt9LFxuICAgIC4uLkFycmF5LmZyb20oZG9tLmNoaWxkTm9kZXMpXG4gICAgICAuZmlsdGVyKChjaGlsZCkgPT4gKGNoaWxkIGFzIERvbUVsZW1lbnQpLm5vZGVUeXBlID09PSAxIHx8IChjaGlsZCBhcyBEb21FbGVtZW50KS5ub2RlVHlwZSA9PT0gMylcbiAgICAgIC5tYXAoKGNoaWxkKSA9PiB7XG4gICAgICAgIGlmICgoY2hpbGQgYXMgRG9tRWxlbWVudCkubm9kZVR5cGUgPT09IDEpIHtcbiAgICAgICAgICByZXR1cm4gZG9tVG9Wbm9kZShjaGlsZCBhcyBEb21FbGVtZW50KTtcbiAgICAgICAgfVxuXG4gICAgICAgIGxldCB0ZXh0ID0gbmV3IFZub2RlKFwiI3RleHRcIiwge30sIFtdKTtcbiAgICAgICAgdGV4dC5ub2RlVmFsdWUgPSBTdHJpbmcoKGNoaWxkIGFzIERvbUVsZW1lbnQpLm5vZGVWYWx1ZSk7XG4gICAgICAgIHRleHQuZG9tID0gY2hpbGQgYXMgRG9tRWxlbWVudDtcbiAgICAgICAgcmV0dXJuIHRleHQ7XG4gICAgICB9KVxuICApO1xuICBbXS5mb3JFYWNoLmNhbGwoZG9tLmF0dHJpYnV0ZXMsIChwcm9wOiBBdHRyKSA9PiAodm5vZGUucHJvcHNbcHJvcC5ub2RlTmFtZV0gPSBwcm9wLm5vZGVWYWx1ZSkpO1xuICB2bm9kZS5kb20gPSBkb207XG4gIHJldHVybiB2bm9kZSBhcyBWbm9kZVdpdGhEb207XG59XG5cbmV4cG9ydCBjb25zdCB0cnVzdCA9IChodG1sU3RyaW5nOiBzdHJpbmcpID0+IHtcbiAgbGV0IGRpdiA9IGNyZWF0ZURvbUVsZW1lbnQoXCJkaXZcIik7XG4gIGRpdi5pbm5lckhUTUwgPSBodG1sU3RyaW5nLnRyaW0oKTtcblxuICByZXR1cm4gW10ubWFwLmNhbGwoZGl2LmNoaWxkTm9kZXMsIChpdGVtKSA9PiBkb21Ub1Zub2RlKGl0ZW0pKSBhcyBJVm5vZGVbXTtcbn07XG5cbi8qKiogTW91bnQgKioqL1xuXG5jb25zdCBWYWx5cmlhblN5bWJvbCA9IFN5bWJvbChcIlZhbHlyaWFuXCIpO1xuXG5leHBvcnQgZnVuY3Rpb24gY2xlYW51cChjYWxsYmFjazogRnVuY3Rpb24pIHtcbiAgaWYgKHYuY3VycmVudC5hcHA/LmNsZWFudXAuaW5kZXhPZihjYWxsYmFjaykgPT09IC0xKSB7XG4gICAgdi5jdXJyZW50LmFwcD8uY2xlYW51cC5wdXNoKGNhbGxiYWNrKTtcbiAgfVxufVxuXG4vKlxuICAqIE1vdW50cyBhIGNvbXBvbmVudCB0byB0aGUgRE9NXG4gIG1vdW50KCcjYXBwJywgKCkgPT4gPGRpdj5IZWxsbyB3b3JsZDwvZGl2Pik7IC8vIEFwcCBpcyBhIEZ1bmN0aW9uYWwgQ29tcG9uZW50XG4gIG1vdW50KCcjYXBwJywgeyB2aWV3OiAoKSA9PiA8ZGl2PkhlbGxvIHdvcmxkPC9kaXY+IH0pOyAvLyBBcHAgaXMgYSBQT0pPIGNvbXBvbmVudCB3aXRoIGEgdmlldyBtZXRob2RcbiAgbW91bnQoJyNhcHAnLCBjbGFzc0luc3RhbmNlKTsgLy8gQXBwIGlzIGEgY2xhc3MgaW5zdGFuY2Ugd2l0aCBhIHZpZXcgbWV0aG9kXG4gIG1vdW50KCcjYXBwJywgPEFwcD48ZGl2PkhlbGxvIHdvcmxkPC9kaXY+PC9BcHA+KTsgLy8gQXBwIGlzIGEgVm5vZGUgY29tcG9uZW50IChWbm9kZSB3aXRoIHRhZyBfX2NvbXBvbmVudF9fKVxuKi9cblxuZXhwb3J0IGZ1bmN0aW9uIG1vdW50KGNvbnRhaW5lcjogRG9tRWxlbWVudCB8IHN0cmluZywgY29tcG9uZW50OiBWYWx5cmlhbkNvbXBvbmVudCB8IElWbm9kZSkge1xuICBsZXQgYXBwQ29udGFpbmVyID0gbnVsbDtcblxuICBpZiAoaXNOb2RlSnMpIHtcbiAgICBhcHBDb250YWluZXIgPSB0eXBlb2YgY29udGFpbmVyID09PSBcInN0cmluZ1wiID8gY3JlYXRlRG9tRWxlbWVudChjb250YWluZXIgPT09IFwic3ZnXCIgPyBcInN2Z1wiIDogXCJkaXZcIiwgY29udGFpbmVyID09PSBcInN2Z1wiKSA6IGNvbnRhaW5lcjtcbiAgfSBlbHNlIHtcbiAgICBhcHBDb250YWluZXIgPSB0eXBlb2YgY29udGFpbmVyID09PSBcInN0cmluZ1wiID8gZG9jdW1lbnQucXVlcnlTZWxlY3RvckFsbChjb250YWluZXIpWzBdIDogY29udGFpbmVyO1xuICB9XG5cbiAgaWYgKCFhcHBDb250YWluZXIpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoXCJDb250YWluZXIgbm90IGZvdW5kXCIpO1xuICB9XG5cbiAgbGV0IHZub2RlQ29tcG9uZW50OiBWbm9kZUNvbXBvbmVudCB8IElWbm9kZTtcblxuICBpZiAoaXNWbm9kZUNvbXBvbmVudChjb21wb25lbnQpKSB7XG4gICAgdm5vZGVDb21wb25lbnQgPSBjb21wb25lbnQ7XG4gIH0gZWxzZSBpZiAoaXNDb21wb25lbnQoY29tcG9uZW50KSkge1xuICAgIHZub2RlQ29tcG9uZW50ID0gdihjb21wb25lbnQsIHt9KTtcbiAgfSBlbHNlIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoXCJDb21wb25lbnQgbXVzdCBiZSBhIFZhbHlyaWFuIENvbXBvbmVudCBvciBhIFZub2RlIGNvbXBvbmVudFwiKTtcbiAgfVxuXG4gIGlmIChjb21wb25lbnRbVmFseXJpYW5TeW1ib2xdKSB7XG4gICAgdW5tb3VudChjb21wb25lbnQpO1xuICB9IGVsc2Uge1xuICAgIGNvbXBvbmVudFtWYWx5cmlhblN5bWJvbF0gPSB7XG4gICAgICBpc01vdW50ZWQ6IGZhbHNlLFxuICAgICAgZXZlbnRMaXN0ZW5lck5hbWVzOiB7fSxcbiAgICAgIGlzTm9kZUpzLFxuICAgICAgY2xlYW51cDogW11cbiAgICB9O1xuICAgIGZ1bmN0aW9uIGV2ZW50TGlzdGVuZXIoZTogRXZlbnQpIHtcbiAgICAgIGxldCBkb20gPSBlLnRhcmdldCBhcyBEb21FbGVtZW50ICYgUmVjb3JkPHN0cmluZywgYW55PjtcbiAgICAgIGxldCBuYW1lID0gYHYtb24ke2UudHlwZX1gO1xuICAgICAgd2hpbGUgKGRvbSkge1xuICAgICAgICBpZiAoZG9tW25hbWVdKSB7XG4gICAgICAgICAgZG9tW25hbWVdKGUsIGRvbSk7XG4gICAgICAgICAgaWYgKCFlLmRlZmF1bHRQcmV2ZW50ZWQpIHtcbiAgICAgICAgICAgIHVwZGF0ZShjb21wb25lbnQpO1xuICAgICAgICAgIH1cbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgZG9tID0gZG9tLnBhcmVudE5vZGUgYXMgRG9tRWxlbWVudDtcbiAgICAgIH1cbiAgICB9XG4gICAgY29tcG9uZW50W1ZhbHlyaWFuU3ltYm9sXS5ldmVudExpc3RlbmVyID0gZXZlbnRMaXN0ZW5lcjtcbiAgfVxuXG4gIGNvbXBvbmVudFtWYWx5cmlhblN5bWJvbF0uY29tcG9uZW50ID0gdm5vZGVDb21wb25lbnQ7XG4gIGNvbXBvbmVudFtWYWx5cmlhblN5bWJvbF0uY29udGFpbmVyID0gYXBwQ29udGFpbmVyO1xuICBjb21wb25lbnRbVmFseXJpYW5TeW1ib2xdLm1haW5Wbm9kZSA9IGRvbVRvVm5vZGUoYXBwQ29udGFpbmVyKTtcblxuICAvLyB1cGRhdGVcbiAgcmV0dXJuIHVwZGF0ZShjb21wb25lbnQpO1xufVxuXG5mdW5jdGlvbiBjbGVhbnVwVm5vZGVzKHZhbHlyaWFuQXBwOiBWYWx5cmlhbkFwcCkge1xuICBmb3IgKGxldCBpID0gMDsgaSA8IHZhbHlyaWFuQXBwLmNsZWFudXAubGVuZ3RoOyBpKyspIHtcbiAgICB2YWx5cmlhbkFwcC5jbGVhbnVwW2ldKCk7XG4gIH1cbiAgdmFseXJpYW5BcHAuY2xlYW51cCA9IFtdO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gdXBkYXRlKGNvbXBvbmVudD86IFZhbHlyaWFuQ29tcG9uZW50IHwgSVZub2RlKSB7XG4gIGlmIChjb21wb25lbnQgJiYgY29tcG9uZW50W1ZhbHlyaWFuU3ltYm9sXSkge1xuICAgIGxldCB2YWx5cmlhbkFwcCA9IGNvbXBvbmVudFtWYWx5cmlhblN5bWJvbF07XG4gICAgdi5jdXJyZW50LmFwcCA9IHZhbHlyaWFuQXBwO1xuICAgIGNsZWFudXBWbm9kZXModmFseXJpYW5BcHApO1xuICAgIGxldCBvbGRWbm9kZTogVm5vZGVXaXRoRG9tIHwgbnVsbCA9IHZhbHlyaWFuQXBwLm1haW5Wbm9kZSBhcyBWbm9kZVdpdGhEb207XG4gICAgdmFseXJpYW5BcHAubWFpblZub2RlID0gbmV3IFZub2RlKHZhbHlyaWFuQXBwLm1haW5Wbm9kZS50YWcsIHZhbHlyaWFuQXBwLm1haW5Wbm9kZS5wcm9wcywgW3ZhbHlyaWFuQXBwLmNvbXBvbmVudF0pIGFzIFZub2RlV2l0aERvbTtcbiAgICB2YWx5cmlhbkFwcC5tYWluVm5vZGUuZG9tID0gb2xkVm5vZGUuZG9tO1xuICAgIHZhbHlyaWFuQXBwLm1haW5Wbm9kZS5pc1NWRyA9IG9sZFZub2RlLmlzU1ZHO1xuICAgIHBhdGNoKHZhbHlyaWFuQXBwLm1haW5Wbm9kZSwgb2xkVm5vZGUsIHZhbHlyaWFuQXBwKTtcbiAgICBvbGRWbm9kZSA9IG51bGw7XG4gICAgdmFseXJpYW5BcHAuaXNNb3VudGVkID0gdHJ1ZTtcblxuICAgIGlmIChpc05vZGVKcykge1xuICAgICAgcmV0dXJuIHZhbHlyaWFuQXBwLm1haW5Wbm9kZS5kb20uaW5uZXJIVE1MO1xuICAgIH1cbiAgfVxufVxuXG5leHBvcnQgZnVuY3Rpb24gdW5tb3VudChjb21wb25lbnQ/OiBWYWx5cmlhbkNvbXBvbmVudCB8IElWbm9kZSkge1xuICBpZiAoIWNvbXBvbmVudCB8fCAhY29tcG9uZW50W1ZhbHlyaWFuU3ltYm9sXSkge1xuICAgIHJldHVybjtcbiAgfVxuXG4gIGxldCB2YWx5cmlhbkFwcCA9IGNvbXBvbmVudFtWYWx5cmlhblN5bWJvbF0gYXMgTW91bnRlZFZhbHlyaWFuQXBwO1xuXG4gIGlmICh2YWx5cmlhbkFwcC5pc01vdW50ZWQpIHtcbiAgICBjbGVhbnVwVm5vZGVzKHZhbHlyaWFuQXBwKTtcbiAgICBsZXQgb2xkVm5vZGU6IFZub2RlV2l0aERvbSB8IG51bGwgPSB2YWx5cmlhbkFwcC5tYWluVm5vZGUgYXMgVm5vZGVXaXRoRG9tO1xuICAgIHZhbHlyaWFuQXBwLm1haW5Wbm9kZSA9IG5ldyBWbm9kZSh2YWx5cmlhbkFwcC5tYWluVm5vZGUudGFnLCB2YWx5cmlhbkFwcC5tYWluVm5vZGUucHJvcHMsIFtdKSBhcyBWbm9kZVdpdGhEb207XG4gICAgdmFseXJpYW5BcHAubWFpblZub2RlLmRvbSA9IG9sZFZub2RlLmRvbTtcbiAgICB2YWx5cmlhbkFwcC5tYWluVm5vZGUuaXNTVkcgPSBvbGRWbm9kZS5pc1NWRztcbiAgICBwYXRjaCh2YWx5cmlhbkFwcC5tYWluVm5vZGUsIG9sZFZub2RlLCB2YWx5cmlhbkFwcCk7XG4gICAgb2xkVm5vZGUgPSBudWxsO1xuICAgIHZhbHlyaWFuQXBwLmlzTW91bnRlZCA9IGZhbHNlO1xuICAgIGlmIChpc05vZGVKcykge1xuICAgICAgcmV0dXJuIHZhbHlyaWFuQXBwLm1haW5Wbm9kZS5kb20uaW5uZXJIVE1MO1xuICAgIH1cbiAgfVxufVxuXG5sZXQgZW1wdHlWbm9kZSA9IG5ldyBWbm9kZShcIl9fZW1wdHlfX1wiLCB7fSwgW10pO1xuXG5leHBvcnQgZnVuY3Rpb24gb25yZW1vdmUodm5vZGU6IElWbm9kZSkge1xuICBmb3IgKGxldCBpID0gMDsgaSA8IHZub2RlLmNoaWxkcmVuLmxlbmd0aDsgaSsrKSB7XG4gICAgdm5vZGUuY2hpbGRyZW5baV0udGFnICE9PSBcIiN0ZXh0XCIgJiYgb25yZW1vdmUodm5vZGUuY2hpbGRyZW5baV0pO1xuICB9XG5cbiAgdm5vZGUucHJvcHMub25yZW1vdmUgJiYgdm5vZGUucHJvcHMub25yZW1vdmUodm5vZGUpO1xufVxuXG5mdW5jdGlvbiBzaGFyZWRVcGRhdGVQcm9wZXJ0eShwcm9wOiBzdHJpbmcsIHZhbHVlOiBhbnksIHZub2RlOiBWbm9kZVdpdGhEb20sIG9sZFZub2RlPzogVm5vZGVXaXRoRG9tKSB7XG4gIC8vIEl0IGlzIGEgcmVzZXJ2ZWQgcHJvcFxuICBpZiAodi5yZXNlcnZlZFByb3BzW3Byb3BdKSB7XG4gICAgLy8gSWYgaXQgaXMgYSBkaXJlY3RpdmUgbmFtZSBjYWxsIHRoZSBkaXJlY3RpdmVcbiAgICBpZiAodi5kaXJlY3RpdmVzW3Byb3BdKSB7XG4gICAgICB2LmRpcmVjdGl2ZXNbcHJvcF0odm5vZGUucHJvcHNbcHJvcF0sIHZub2RlLCBvbGRWbm9kZSk7XG4gICAgfVxuICAgIHJldHVybjtcbiAgfVxuXG4gIC8vIEl0IGlzIG5vdCBhIHJlc2VydmVkIHByb3Agc28gd2UgYWRkIGl0IHRvIHRoZSBkb21cbiAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gXCJmdW5jdGlvblwiKSB7XG4gICAgbGV0IHZhbHlyaWFuQXBwID0gdi5jdXJyZW50LmFwcCBhcyBNb3VudGVkVmFseXJpYW5BcHA7XG4gICAgaWYgKHByb3AgaW4gdmFseXJpYW5BcHAuZXZlbnRMaXN0ZW5lck5hbWVzID09PSBmYWxzZSkge1xuICAgICAgdmFseXJpYW5BcHAuZXZlbnRMaXN0ZW5lck5hbWVzW3Byb3BdID0gdHJ1ZTtcbiAgICAgIHZhbHlyaWFuQXBwLmNvbnRhaW5lci5hZGRFdmVudExpc3RlbmVyKHByb3Auc2xpY2UoMiksIHZhbHlyaWFuQXBwLmV2ZW50TGlzdGVuZXIpO1xuICAgIH1cbiAgICB2bm9kZS5kb21bYHYtJHtwcm9wfWBdID0gdmFsdWU7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgaWYgKHByb3AgaW4gdm5vZGUuZG9tICYmIHZub2RlLmlzU1ZHID09PSBmYWxzZSkge1xuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBlcWVxZXFcbiAgICBpZiAodm5vZGUuZG9tW3Byb3BdICE9IHZhbHVlKSB7XG4gICAgICB2bm9kZS5kb21bcHJvcF0gPSB2YWx1ZTtcbiAgICB9XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgLy8gVXNlIHNldCBhdHRyaWJ1dGVcbiAgaWYgKCFvbGRWbm9kZSB8fCBvbGRWbm9kZS5wcm9wc1twcm9wXSAhPT0gdmFsdWUpIHtcbiAgICBpZiAodmFsdWUgPT09IGZhbHNlKSB7XG4gICAgICB2bm9kZS5kb20ucmVtb3ZlQXR0cmlidXRlKHByb3ApO1xuICAgIH0gZWxzZSB7XG4gICAgICB2bm9kZS5kb20uc2V0QXR0cmlidXRlKHByb3AsIHZhbHVlKTtcbiAgICB9XG4gIH1cbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHVwZGF0ZVByb3BlcnR5KG5hbWU6IHN0cmluZywgdmFsdWU6IGFueSwgdm5vZGU6IFZub2RlV2l0aERvbSwgb2xkVm5vZGU/OiBWbm9kZVdpdGhEb20pIHtcbiAgaWYgKG5hbWUgaW4gdm5vZGUucHJvcHMgPT09IGZhbHNlKSB7XG4gICAgdm5vZGUucHJvcHNbbmFtZV0gPSB2YWx1ZTtcbiAgfVxuXG4gIHNoYXJlZFVwZGF0ZVByb3BlcnR5KG5hbWUsIHZhbHVlLCB2bm9kZSwgb2xkVm5vZGUpO1xufVxuXG5mdW5jdGlvbiB1cGRhdGVQcm9wZXJ0aWVzKHZub2RlOiBWbm9kZVdpdGhEb20sIG9sZFZub2RlPzogVm5vZGVXaXRoRG9tKSB7XG4gIGZvciAobGV0IHByb3AgaW4gdm5vZGUucHJvcHMpIHtcbiAgICAvLyBXZSBhc3VtZSB0aGF0IHdlIGNsZWFuIHRoZSBwcm9wcyBpbiBzb21lIGRpcmVjdGl2ZVxuICAgIGlmIChwcm9wIGluIHZub2RlLnByb3BzID09PSBmYWxzZSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHNoYXJlZFVwZGF0ZVByb3BlcnR5KHByb3AsIHZub2RlLnByb3BzW3Byb3BdLCB2bm9kZSwgb2xkVm5vZGUpO1xuICB9XG5cbiAgaWYgKG9sZFZub2RlKSB7XG4gICAgZm9yIChsZXQgcHJvcCBpbiBvbGRWbm9kZS5wcm9wcykge1xuICAgICAgaWYgKHByb3AgaW4gdm5vZGUucHJvcHMgPT09IGZhbHNlICYmIHR5cGVvZiBvbGRWbm9kZS5wcm9wc1twcm9wXSAhPT0gXCJmdW5jdGlvblwiICYmIHByb3AgaW4gdi5yZXNlcnZlZFByb3BzID09PSBmYWxzZSkge1xuICAgICAgICBpZiAocHJvcCBpbiBvbGRWbm9kZS5kb20gJiYgdm5vZGUuaXNTVkcgPT09IGZhbHNlKSB7XG4gICAgICAgICAgb2xkVm5vZGUuZG9tW3Byb3BdID0gbnVsbDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBvbGRWbm9kZS5kb20ucmVtb3ZlQXR0cmlidXRlKHByb3ApO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICB9XG59XG5cbmZ1bmN0aW9uIGZsYXRUcmVlKG5ld1Zub2RlOiBJVm5vZGUpOiB2b2lkIHtcbiAgbGV0IG5ld1RyZWUgPSBuZXdWbm9kZS5jaGlsZHJlbjtcbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBuZXdUcmVlLmxlbmd0aDsgaSsrKSB7XG4gICAgbGV0IGNoaWxkVm5vZGUgPSBuZXdUcmVlW2ldO1xuICAgIGlmIChjaGlsZFZub2RlIGluc3RhbmNlb2YgVm5vZGUpIHtcbiAgICAgIGlmIChjaGlsZFZub2RlLnRhZyAhPT0gXCIjdGV4dFwiKSB7XG4gICAgICAgIGlmIChjaGlsZFZub2RlLnRhZyA9PT0gXCJfX2NvbXBvbmVudF9fXCIpIHtcbiAgICAgICAgICBsZXQgY29tcG9uZW50ID0gY2hpbGRWbm9kZS5jb21wb25lbnQgYXMgVmFseXJpYW5Db21wb25lbnQ7XG4gICAgICAgICAgdi5jdXJyZW50LmNvbXBvbmVudCA9IGNvbXBvbmVudDtcbiAgICAgICAgICBsZXQgcmVzdWx0ID0gKFwidmlld1wiIGluIGNvbXBvbmVudCA/IGNvbXBvbmVudC52aWV3IDogY29tcG9uZW50KS5jYWxsKGNvbXBvbmVudCwgY2hpbGRWbm9kZS5wcm9wcywgLi4uY2hpbGRWbm9kZS5jaGlsZHJlbik7XG5cbiAgICAgICAgICBuZXdUcmVlLnNwbGljZShpLS0sIDEsIHJlc3VsdCk7XG4gICAgICAgICAgY29udGludWU7XG4gICAgICAgIH1cbiAgICAgICAgY2hpbGRWbm9kZS5pc1NWRyA9IG5ld1Zub2RlLmlzU1ZHIHx8IGNoaWxkVm5vZGUudGFnID09PSBcInN2Z1wiO1xuICAgICAgfVxuICAgIH0gZWxzZSBpZiAoY2hpbGRWbm9kZSA9PT0gbnVsbCB8fCBjaGlsZFZub2RlID09PSB1bmRlZmluZWQpIHtcbiAgICAgIG5ld1RyZWUuc3BsaWNlKGktLSwgMSk7XG4gICAgfSBlbHNlIGlmIChBcnJheS5pc0FycmF5KGNoaWxkVm5vZGUpKSB7XG4gICAgICBuZXdUcmVlLnNwbGljZShpLS0sIDEsIC4uLmNoaWxkVm5vZGUpO1xuICAgIH0gZWxzZSB7XG4gICAgICBpZiAoaSA+IDAgJiYgbmV3VHJlZVtpIC0gMV0udGFnID09PSBcIiN0ZXh0XCIpIHtcbiAgICAgICAgbmV3VHJlZVtpIC0gMV0ubm9kZVZhbHVlICs9IGNoaWxkVm5vZGU7XG4gICAgICAgIG5ld1RyZWUuc3BsaWNlKGktLSwgMSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBuZXdUcmVlW2ldID0gbmV3IFZub2RlKFwiI3RleHRcIiwge30sIFtdKTtcbiAgICAgICAgbmV3VHJlZVtpXS5ub2RlVmFsdWUgPSBTdHJpbmcoY2hpbGRWbm9kZSk7XG4gICAgICB9XG4gICAgfVxuICB9XG59XG5cbmZ1bmN0aW9uIHBhdGNoS2V5ZWRUcmVlKFxuICBuZXdWbm9kZTogVm5vZGVXaXRoRG9tLFxuICBuZXdUcmVlOiAoVm5vZGVXaXRoRG9tICYgeyBwcm9wczogUHJvcHMgJiB7IGtleTogc3RyaW5nIH0gfSlbXSxcbiAgb2xkVHJlZTogKFZub2RlV2l0aERvbSAmIHsgcHJvcHM6IFByb3BzICYgeyBrZXk6IHN0cmluZyB9IH0pW10sXG4gIG5ld1RyZWVMZW5ndGg6IG51bWJlcixcbiAgb2xkVHJlZUxlbmd0aDogbnVtYmVyLFxuICB2YWx5cmlhbkFwcDogTW91bnRlZFZhbHlyaWFuQXBwXG4pIHtcbiAgbGV0IG9sZEtleWVkTGlzdCA9IG9sZFRyZWUucmVkdWNlKChhY2MsIHZub2RlLCBpKSA9PiB7XG4gICAgYWNjW3Zub2RlLnByb3BzLmtleV0gPSBpO1xuICAgIHJldHVybiBhY2M7XG4gIH0sIHt9IGFzIHsgW2tleTogc3RyaW5nXTogbnVtYmVyIH0pO1xuICBsZXQgbmV3S2V5ZWRMaXN0ID0gbmV3VHJlZS5yZWR1Y2UoKGFjYywgdm5vZGUsIGkpID0+IHtcbiAgICBhY2Nbdm5vZGUucHJvcHMua2V5XSA9IGk7XG4gICAgcmV0dXJuIGFjYztcbiAgfSwge30gYXMgeyBba2V5OiBzdHJpbmddOiBudW1iZXIgfSk7XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBuZXdUcmVlTGVuZ3RoOyBpKyspIHtcbiAgICBsZXQgY2hpbGRWbm9kZSA9IG5ld1RyZWVbaV07XG4gICAgbGV0IG9sZENoaWxkVm5vZGUgPSBvbGRUcmVlW29sZEtleWVkTGlzdFtjaGlsZFZub2RlLnByb3BzLmtleV1dO1xuICAgIGxldCBzaG91bGRQYXRjaCA9IHRydWU7XG5cbiAgICBpZiAob2xkQ2hpbGRWbm9kZSkge1xuICAgICAgY2hpbGRWbm9kZS5kb20gPSBvbGRDaGlsZFZub2RlLmRvbTtcbiAgICAgIGlmIChcInYtb25jZVwiIGluIGNoaWxkVm5vZGUucHJvcHMgfHwgKGNoaWxkVm5vZGUucHJvcHMuc2hvdWxkdXBkYXRlICYmIGNoaWxkVm5vZGUucHJvcHMuc2hvdWxkdXBkYXRlKGNoaWxkVm5vZGUsIG9sZENoaWxkVm5vZGUpID09PSBmYWxzZSkpIHtcbiAgICAgICAgLy8gc2tpcCB0aGlzIHBhdGNoXG4gICAgICAgIGNoaWxkVm5vZGUuY2hpbGRyZW4gPSBvbGRDaGlsZFZub2RlLmNoaWxkcmVuO1xuICAgICAgICBzaG91bGRQYXRjaCA9IGZhbHNlO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdXBkYXRlUHJvcGVydGllcyhjaGlsZFZub2RlLCBvbGRDaGlsZFZub2RlKTtcbiAgICAgICAgaWYgKHZhbHlyaWFuQXBwLmlzTW91bnRlZCkge1xuICAgICAgICAgIGNoaWxkVm5vZGUucHJvcHMub251cGRhdGUgJiYgY2hpbGRWbm9kZS5wcm9wcy5vbnVwZGF0ZShjaGlsZFZub2RlLCBvbGRDaGlsZFZub2RlKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBjaGlsZFZub2RlLnByb3BzLm9uY3JlYXRlICYmIGNoaWxkVm5vZGUucHJvcHMub25jcmVhdGUoY2hpbGRWbm9kZSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgY2hpbGRWbm9kZS5kb20gPSBjcmVhdGVEb21FbGVtZW50KGNoaWxkVm5vZGUudGFnLCBjaGlsZFZub2RlLmlzU1ZHKTtcbiAgICAgIHVwZGF0ZVByb3BlcnRpZXMoY2hpbGRWbm9kZSk7XG4gICAgICBjaGlsZFZub2RlLnByb3BzLm9uY3JlYXRlICYmIGNoaWxkVm5vZGUucHJvcHMub25jcmVhdGUoY2hpbGRWbm9kZSk7XG4gICAgfVxuXG4gICAgaWYgKG5ld1Zub2RlLmRvbS5jaGlsZE5vZGVzW2ldID09PSB1bmRlZmluZWQpIHtcbiAgICAgIG5ld1Zub2RlLmRvbS5hcHBlbmRDaGlsZChjaGlsZFZub2RlLmRvbSk7XG4gICAgfSBlbHNlIGlmIChuZXdWbm9kZS5kb20uY2hpbGROb2Rlc1tpXSAhPT0gY2hpbGRWbm9kZS5kb20pIHtcbiAgICAgIG9sZFRyZWVbaV0gJiYgbmV3S2V5ZWRMaXN0W29sZFRyZWVbaV0ucHJvcHMua2V5XSA9PT0gdW5kZWZpbmVkICYmIG9ucmVtb3ZlKG9sZFRyZWVbaV0pO1xuICAgICAgbmV3Vm5vZGUuZG9tLnJlcGxhY2VDaGlsZChjaGlsZFZub2RlLmRvbSwgbmV3Vm5vZGUuZG9tLmNoaWxkTm9kZXNbaV0pO1xuICAgIH1cblxuICAgIHNob3VsZFBhdGNoICYmIHBhdGNoKGNoaWxkVm5vZGUsIG9sZENoaWxkVm5vZGUsIHZhbHlyaWFuQXBwKTtcbiAgfVxuXG4gIC8vIEZvciB0aGUgcmVzdCBvZiB0aGUgY2hpbGRyZW4sIHdlIHNob3VsZCByZW1vdmUgdGhlbVxuICBmb3IgKGxldCBpID0gbmV3VHJlZUxlbmd0aDsgaSA8IG9sZFRyZWVMZW5ndGg7IGkrKykge1xuICAgIGlmIChuZXdLZXllZExpc3Rbb2xkVHJlZVtpXS5wcm9wcy5rZXldID09PSB1bmRlZmluZWQpIHtcbiAgICAgIGxldCBvbGRDaGlsZFZub2RlID0gb2xkVHJlZVtpXTtcbiAgICAgIG9ucmVtb3ZlKG9sZENoaWxkVm5vZGUpO1xuICAgICAgb2xkQ2hpbGRWbm9kZS5kb20ucGFyZW50Tm9kZSAmJiBvbGRDaGlsZFZub2RlLmRvbS5wYXJlbnROb2RlLnJlbW92ZUNoaWxkKG9sZENoaWxkVm5vZGUuZG9tKTtcbiAgICB9XG4gIH1cbn1cblxuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGNvbXBsZXhpdHlcbmZ1bmN0aW9uIHBhdGNoTm9ybWFsVHJlZShcbiAgbmV3Vm5vZGU6IFZub2RlV2l0aERvbSxcbiAgbmV3VHJlZTogKFZub2RlV2l0aERvbSAmIHsgcHJvcHM6IFByb3BzICYgeyBrZXk6IHN0cmluZyB9IH0pW10sXG4gIG9sZFRyZWU6IChWbm9kZVdpdGhEb20gJiB7IHByb3BzOiBQcm9wcyAmIHsga2V5OiBzdHJpbmcgfSB9KVtdLFxuICBuZXdUcmVlTGVuZ3RoOiBudW1iZXIsXG4gIG9sZFRyZWVMZW5ndGg6IG51bWJlcixcbiAgdmFseXJpYW5BcHA6IE1vdW50ZWRWYWx5cmlhbkFwcFxuKSB7XG4gIC8vIElmIG5ldyB0cmVlIGFuZCBvbGQgdHJlZSBoYXZlIG1vcmUgdGhhbiBvbmUgY2hpbGQsIHdlIHNob3VsZCB1cGRhdGUgdGhlIGRvbVxuICBmb3IgKGxldCBpID0gMDsgaSA8IG5ld1RyZWVMZW5ndGg7IGkrKykge1xuICAgIGxldCBvbGRDaGlsZFZub2RlID0gb2xkVHJlZVtpXTtcbiAgICBsZXQgbmV3Q2hpbGRWbm9kZSA9IG5ld1RyZWVbaV07XG5cbiAgICAvLyBPbGQgY2hpbGQgZG9lcyBub3QgZXhpc3RzXG4gICAgaWYgKCFvbGRDaGlsZFZub2RlKSB7XG4gICAgICAvLyBOZXcgY2hpbGQgaXMgYSB0ZXh0IG5vZGVcbiAgICAgIGlmIChuZXdDaGlsZFZub2RlLnRhZyA9PT0gXCIjdGV4dFwiKSB7XG4gICAgICAgIG5ld0NoaWxkVm5vZGUuZG9tID0gZG9jdW1lbnQuY3JlYXRlVGV4dE5vZGUobmV3Q2hpbGRWbm9kZS5ub2RlVmFsdWUgYXMgc3RyaW5nKSBhcyB1bmtub3duIGFzIERvbUVsZW1lbnQ7XG4gICAgICAgIG5ld1Zub2RlLmRvbS5hcHBlbmRDaGlsZChuZXdDaGlsZFZub2RlLmRvbSk7XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuXG4gICAgICAvLyBOZXcgY2hpbGQgaXMgYSBub3JtYWwgbm9kZVxuICAgICAgbmV3Q2hpbGRWbm9kZS5kb20gPSBjcmVhdGVEb21FbGVtZW50KG5ld0NoaWxkVm5vZGUudGFnLCBuZXdDaGlsZFZub2RlLmlzU1ZHKTtcbiAgICAgIHVwZGF0ZVByb3BlcnRpZXMobmV3Q2hpbGRWbm9kZSk7XG4gICAgICBuZXdWbm9kZS5kb20uYXBwZW5kQ2hpbGQobmV3Q2hpbGRWbm9kZS5kb20pO1xuICAgICAgbmV3Q2hpbGRWbm9kZS5wcm9wcy5vbmNyZWF0ZSAmJiBuZXdDaGlsZFZub2RlLnByb3BzLm9uY3JlYXRlKG5ld0NoaWxkVm5vZGUpO1xuICAgICAgcGF0Y2gobmV3Q2hpbGRWbm9kZSwgdW5kZWZpbmVkLCB2YWx5cmlhbkFwcCk7XG4gICAgICBjb250aW51ZTtcbiAgICB9XG5cbiAgICAvLyBPbGQgY2hpbGQgZXhpc3RzXG4gICAgLy8gTmV3IGNoaWxkIGlzIGEgdGV4dCBub2RlXG4gICAgaWYgKG5ld0NoaWxkVm5vZGUudGFnID09PSBcIiN0ZXh0XCIpIHtcbiAgICAgIC8vIE9sZCBjaGlsZCBpcyBhIHRleHQgbm9kZVxuICAgICAgaWYgKG9sZENoaWxkVm5vZGUudGFnID09PSBcIiN0ZXh0XCIpIHtcbiAgICAgICAgbmV3Q2hpbGRWbm9kZS5kb20gPSBvbGRDaGlsZFZub2RlLmRvbTtcbiAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGVxZXFlcVxuICAgICAgICBpZiAobmV3Q2hpbGRWbm9kZS5kb20ubm9kZVZhbHVlICE9IG5ld0NoaWxkVm5vZGUubm9kZVZhbHVlKSB7XG4gICAgICAgICAgbmV3Q2hpbGRWbm9kZS5kb20ubm9kZVZhbHVlID0gbmV3Q2hpbGRWbm9kZS5ub2RlVmFsdWUgYXMgc3RyaW5nO1xuICAgICAgICB9XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuXG4gICAgICAvLyBPbGQgY2hpbGQgaXMgYSBub3JtYWwgbm9kZVxuICAgICAgbmV3Q2hpbGRWbm9kZS5kb20gPSBkb2N1bWVudC5jcmVhdGVUZXh0Tm9kZShuZXdDaGlsZFZub2RlLm5vZGVWYWx1ZSBhcyBzdHJpbmcpIGFzIHVua25vd24gYXMgRG9tRWxlbWVudDtcbiAgICAgIG9ucmVtb3ZlKG9sZENoaWxkVm5vZGUpO1xuICAgICAgbmV3Vm5vZGUuZG9tLnJlcGxhY2VDaGlsZChuZXdDaGlsZFZub2RlLmRvbSwgb2xkQ2hpbGRWbm9kZS5kb20pO1xuXG4gICAgICBjb250aW51ZTtcbiAgICB9XG5cbiAgICAvLyBOZXcgY2hpbGQgaXMgYSBub3JtYWwgbm9kZVxuICAgIC8vIE9sZCBjaGlsZCBpcyB0aGUgc2FtZSB0eXBlIGFzIG5ldyBjaGlsZFxuICAgIGlmIChvbGRDaGlsZFZub2RlLnRhZyA9PT0gbmV3Q2hpbGRWbm9kZS50YWcpIHtcbiAgICAgIG5ld0NoaWxkVm5vZGUuZG9tID0gb2xkQ2hpbGRWbm9kZS5kb207XG4gICAgICAvLyBJZiB3ZSBoYXZlIGEgdi1vbmNlIGRpcmVjdGl2ZSBvciBhIHNob3VsZHVwZGF0ZSBtZXRob2QgdGhhdCByZXR1cm5zIGZhbHNlLCB3ZSBza2lwIHRoZSB1cGRhdGVcbiAgICAgIGlmIChuZXdDaGlsZFZub2RlLnByb3BzW1widi1vbmNlXCJdIHx8IChuZXdDaGlsZFZub2RlLnByb3BzLnNob3VsZHVwZGF0ZSAmJiBuZXdDaGlsZFZub2RlLnByb3BzLnNob3VsZHVwZGF0ZShuZXdDaGlsZFZub2RlLCBvbGRDaGlsZFZub2RlKSA9PT0gZmFsc2UpKSB7XG4gICAgICAgIG5ld0NoaWxkVm5vZGUuY2hpbGRyZW4gPSBvbGRDaGlsZFZub2RlLmNoaWxkcmVuO1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cblxuICAgICAgLy8gV2UgdXBkYXRlIHRoZSBkb20gZWxlbWVudFxuICAgICAgdXBkYXRlUHJvcGVydGllcyhuZXdDaGlsZFZub2RlLCBvbGRDaGlsZFZub2RlKTtcbiAgICAgIGlmICh2YWx5cmlhbkFwcCAmJiB2YWx5cmlhbkFwcC5pc01vdW50ZWQpIHtcbiAgICAgICAgbmV3Q2hpbGRWbm9kZS5wcm9wcy5vbnVwZGF0ZSAmJiBuZXdDaGlsZFZub2RlLnByb3BzLm9udXBkYXRlKG5ld0NoaWxkVm5vZGUsIG9sZENoaWxkVm5vZGUpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgbmV3Q2hpbGRWbm9kZS5wcm9wcy5vbmNyZWF0ZSAmJiBuZXdDaGlsZFZub2RlLnByb3BzLm9uY3JlYXRlKG5ld0NoaWxkVm5vZGUpO1xuICAgICAgfVxuICAgICAgcGF0Y2gobmV3Q2hpbGRWbm9kZSwgb2xkQ2hpbGRWbm9kZSwgdmFseXJpYW5BcHApO1xuXG4gICAgICBjb250aW51ZTtcbiAgICB9XG5cbiAgICAvLyBPbGQgY2hpbGQgaXMgb2YgYSBkaWZmZXJlbnQgdHlwZSB0aGFuIG5ldyBjaGlsZFxuICAgIG5ld0NoaWxkVm5vZGUuZG9tID0gY3JlYXRlRG9tRWxlbWVudChuZXdDaGlsZFZub2RlLnRhZywgbmV3Q2hpbGRWbm9kZS5pc1NWRyk7XG4gICAgdXBkYXRlUHJvcGVydGllcyhuZXdDaGlsZFZub2RlKTtcbiAgICBpZiAob2xkQ2hpbGRWbm9kZS50YWcgIT09IFwiI3RleHRcIikge1xuICAgICAgb25yZW1vdmUob2xkQ2hpbGRWbm9kZSk7XG4gICAgfVxuICAgIG5ld0NoaWxkVm5vZGUucHJvcHMub25jcmVhdGUgJiYgbmV3Q2hpbGRWbm9kZS5wcm9wcy5vbmNyZWF0ZShuZXdDaGlsZFZub2RlKTtcbiAgICBuZXdWbm9kZS5kb20ucmVwbGFjZUNoaWxkKG5ld0NoaWxkVm5vZGUuZG9tLCBvbGRDaGlsZFZub2RlLmRvbSk7XG4gICAgcGF0Y2gobmV3Q2hpbGRWbm9kZSwgdW5kZWZpbmVkLCB2YWx5cmlhbkFwcCk7XG4gIH1cblxuICAvLyBGb3IgdGhlIHJlc3Qgb2YgdGhlIGNoaWxkcmVuLCB3ZSBzaG91bGQgcmVtb3ZlIHRoZW1cbiAgZm9yIChsZXQgaSA9IG5ld1RyZWVMZW5ndGg7IGkgPCBvbGRUcmVlTGVuZ3RoOyBpKyspIHtcbiAgICBsZXQgb2xkQ2hpbGRWbm9kZSA9IG9sZFRyZWVbaV07XG4gICAgaWYgKG9sZENoaWxkVm5vZGUudGFnICE9PSBcIiN0ZXh0XCIpIHtcbiAgICAgIG9ucmVtb3ZlKG9sZENoaWxkVm5vZGUpO1xuICAgIH1cbiAgICBvbGRDaGlsZFZub2RlLmRvbS5wYXJlbnROb2RlICYmIG9sZENoaWxkVm5vZGUuZG9tLnBhcmVudE5vZGUucmVtb3ZlQ2hpbGQob2xkQ2hpbGRWbm9kZS5kb20pO1xuICB9XG59XG5cbi8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBjb21wbGV4aXR5XG5mdW5jdGlvbiBwYXRjaChuZXdWbm9kZTogVm5vZGVXaXRoRG9tLCBvbGRWbm9kZTogVm5vZGVXaXRoRG9tID0gZW1wdHlWbm9kZSBhcyBWbm9kZVdpdGhEb20sIHZhbHlyaWFuQXBwOiBNb3VudGVkVmFseXJpYW5BcHApIHtcbiAgdi5jdXJyZW50LnZub2RlID0gbmV3Vm5vZGU7XG4gIHYuY3VycmVudC5vbGRWbm9kZSA9IG9sZFZub2RlO1xuXG4gIGZsYXRUcmVlKG5ld1Zub2RlKTtcblxuICBsZXQgbmV3VHJlZSA9IG5ld1Zub2RlLmNoaWxkcmVuO1xuICBsZXQgb2xkVHJlZSA9IG9sZFZub2RlLmNoaWxkcmVuO1xuICBsZXQgb2xkVHJlZUxlbmd0aCA9IG9sZFRyZWUubGVuZ3RoO1xuICBsZXQgbmV3VHJlZUxlbmd0aCA9IG5ld1RyZWUubGVuZ3RoO1xuXG4gIC8vIElmIG5ldyB0cmVlIGlzIGVtcHR5LCByZW1vdmUgYWxsIG9sZCBub2Rlc1xuICBpZiAobmV3VHJlZUxlbmd0aCA9PT0gMCkge1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgb2xkVHJlZUxlbmd0aDsgaSsrKSB7XG4gICAgICBvbnJlbW92ZShvbGRUcmVlW2ldKTtcbiAgICB9XG5cbiAgICBuZXdWbm9kZS5kb20udGV4dENvbnRlbnQgPSBcIlwiO1xuICAgIHJldHVybjtcbiAgfVxuXG4gIC8vIElmIHRoZSB0cmVlIGlzIGtleWVkIGxpc3QgYW5kIGlzIG5vdCBmaXJzdCByZW5kZXIgYW5kIG9sZCB0cmVlIGlzIGtleWVkIGxpc3QgdG9vXG4gIGlmIChvbGRUcmVlTGVuZ3RoICYmIFwia2V5XCIgaW4gbmV3VHJlZVswXS5wcm9wcyAmJiBcImtleVwiIGluIG9sZFRyZWVbMF0ucHJvcHMpIHtcbiAgICBwYXRjaEtleWVkVHJlZShuZXdWbm9kZSwgbmV3VHJlZSwgb2xkVHJlZSwgbmV3VHJlZUxlbmd0aCwgb2xkVHJlZUxlbmd0aCwgdmFseXJpYW5BcHApO1xuICAgIHJldHVybjtcbiAgfVxuXG4gIHBhdGNoTm9ybWFsVHJlZShuZXdWbm9kZSwgbmV3VHJlZSwgb2xkVHJlZSwgbmV3VHJlZUxlbmd0aCwgb2xkVHJlZUxlbmd0aCwgdmFseXJpYW5BcHApO1xufVxuXG4vKioqIERpcmVjdGl2ZXMgKioqL1xuXG5leHBvcnQgZnVuY3Rpb24gZGlyZWN0aXZlKG5hbWU6IHN0cmluZywgZGlyZWN0aXZlOiBEaXJlY3RpdmUpIHtcbiAgbGV0IGZ1bGxOYW1lID0gYHYtJHtuYW1lfWA7XG4gIHYuZGlyZWN0aXZlc1tmdWxsTmFtZV0gPSBkaXJlY3RpdmU7XG4gIHYucmVzZXJ2ZWRQcm9wc1tmdWxsTmFtZV0gPSB0cnVlO1xufVxuXG5mdW5jdGlvbiBoaWRlRGlyZWN0aXZlKHRlc3Q6IGJvb2xlYW4pOiBEaXJlY3RpdmUge1xuICByZXR1cm4gKGJvb2w6IGJvb2xlYW4sIHZub2RlOiBJVm5vZGUsIG9sZFZub2RlPzogSVZub2RlKSA9PiB7XG4gICAgbGV0IHZhbHVlID0gdGVzdCA/IGJvb2wgOiAhYm9vbDtcbiAgICBpZiAodmFsdWUpIHtcbiAgICAgIGxldCBuZXdkb20gPSBkb2N1bWVudC5jcmVhdGVUZXh0Tm9kZShcIlwiKTtcbiAgICAgIGlmIChvbGRWbm9kZSAmJiBvbGRWbm9kZS5kb20gJiYgb2xkVm5vZGUuZG9tLnBhcmVudE5vZGUpIHtcbiAgICAgICAgb2xkVm5vZGUudGFnICE9PSBcIiN0ZXh0XCIgJiYgb25yZW1vdmUob2xkVm5vZGUpO1xuICAgICAgICBvbGRWbm9kZS5kb20ucGFyZW50Tm9kZS5yZXBsYWNlQ2hpbGQobmV3ZG9tLCBvbGRWbm9kZS5kb20pO1xuICAgICAgfVxuICAgICAgdm5vZGUudGFnID0gXCIjdGV4dFwiO1xuICAgICAgdm5vZGUuY2hpbGRyZW4gPSBbXTtcbiAgICAgIHZub2RlLnByb3BzID0ge307XG4gICAgICB2bm9kZS5kb20gPSBuZXdkb20gYXMgdW5rbm93biBhcyBEb21FbGVtZW50O1xuICAgIH1cbiAgfTtcbn1cblxuY29uc3QgYnVpbHRJbkRpcmVjdGl2ZXMgPSB7XG4gIFwidi1pZlwiOiBoaWRlRGlyZWN0aXZlKGZhbHNlKSxcbiAgXCJ2LXVubGVzc1wiOiBoaWRlRGlyZWN0aXZlKHRydWUpLFxuICBcInYtZm9yXCI6IChzZXQ6IHVua25vd25bXSwgdm5vZGU6IFZub2RlV2l0aERvbSkgPT4ge1xuICAgIHZub2RlLmNoaWxkcmVuID0gc2V0Lm1hcCh2bm9kZS5jaGlsZHJlblswXSBhcyAodmFsdWU6IHVua25vd24pID0+IEZ1bmN0aW9uKTtcbiAgfSxcbiAgXCJ2LXNob3dcIjogKGJvb2w6IGJvb2xlYW4sIHZub2RlOiBWbm9kZVdpdGhEb20pID0+IHtcbiAgICAodm5vZGUuZG9tIGFzIHVua25vd24gYXMgeyBzdHlsZTogeyBkaXNwbGF5OiBzdHJpbmcgfSB9KS5zdHlsZS5kaXNwbGF5ID0gYm9vbCA/IFwiXCIgOiBcIm5vbmVcIjtcbiAgfSxcbiAgXCJ2LWNsYXNzXCI6IChjbGFzc2VzOiB7IFt4OiBzdHJpbmddOiBib29sZWFuIH0sIHZub2RlOiBWbm9kZVdpdGhEb20pID0+IHtcbiAgICBmb3IgKGxldCBuYW1lIGluIGNsYXNzZXMpIHtcbiAgICAgICh2bm9kZS5kb20gYXMgRG9tRWxlbWVudCkuY2xhc3NMaXN0LnRvZ2dsZShuYW1lLCBjbGFzc2VzW25hbWVdKTtcbiAgICB9XG4gIH0sXG4gIFwidi1odG1sXCI6IChodG1sOiBzdHJpbmcsIHZub2RlOiBWbm9kZVdpdGhEb20pID0+IHtcbiAgICB2bm9kZS5jaGlsZHJlbiA9IFt0cnVzdChodG1sKV07XG4gIH0sXG4gIFwidi1tb2RlbFwiOiAoW21vZGVsLCBwcm9wZXJ0eSwgZXZlbnRdOiBhbnlbXSwgdm5vZGU6IFZub2RlV2l0aERvbSwgb2xkVm5vZGU/OiBWbm9kZVdpdGhEb20pID0+IHtcbiAgICBsZXQgdmFsdWU7XG4gICAgbGV0IGhhbmRsZXI7XG4gICAgaWYgKHZub2RlLm5hbWUgPT09IFwiaW5wdXRcIikge1xuICAgICAgZXZlbnQgPSBldmVudCB8fCBcIm9uaW5wdXRcIjtcbiAgICAgIHN3aXRjaCAodm5vZGUucHJvcHMudHlwZSkge1xuICAgICAgICBjYXNlIFwiY2hlY2tib3hcIjoge1xuICAgICAgICAgIGlmIChBcnJheS5pc0FycmF5KG1vZGVsW3Byb3BlcnR5XSkpIHtcbiAgICAgICAgICAgIGhhbmRsZXIgPSAoZTogRXZlbnQpID0+IHtcbiAgICAgICAgICAgICAgbGV0IHZhbCA9IChlLnRhcmdldCBhcyBEb21FbGVtZW50ICYgUmVjb3JkPHN0cmluZywgYW55PikudmFsdWU7XG4gICAgICAgICAgICAgIGxldCBpZHggPSBtb2RlbFtwcm9wZXJ0eV0uaW5kZXhPZih2YWwpO1xuICAgICAgICAgICAgICBpZiAoaWR4ID09PSAtMSkge1xuICAgICAgICAgICAgICAgIG1vZGVsW3Byb3BlcnR5XS5wdXNoKHZhbCk7XG4gICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgbW9kZWxbcHJvcGVydHldLnNwbGljZShpZHgsIDEpO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgdmFsdWUgPSBtb2RlbFtwcm9wZXJ0eV0uaW5kZXhPZih2bm9kZS5kb20udmFsdWUpICE9PSAtMTtcbiAgICAgICAgICB9IGVsc2UgaWYgKFwidmFsdWVcIiBpbiB2bm9kZS5wcm9wcykge1xuICAgICAgICAgICAgaGFuZGxlciA9ICgpID0+IHtcbiAgICAgICAgICAgICAgaWYgKG1vZGVsW3Byb3BlcnR5XSA9PT0gdm5vZGUucHJvcHMudmFsdWUpIHtcbiAgICAgICAgICAgICAgICBtb2RlbFtwcm9wZXJ0eV0gPSBudWxsO1xuICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIG1vZGVsW3Byb3BlcnR5XSA9IHZub2RlLnByb3BzLnZhbHVlO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgdmFsdWUgPSBtb2RlbFtwcm9wZXJ0eV0gPT09IHZub2RlLnByb3BzLnZhbHVlO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBoYW5kbGVyID0gKCkgPT4gKG1vZGVsW3Byb3BlcnR5XSA9ICFtb2RlbFtwcm9wZXJ0eV0pO1xuICAgICAgICAgICAgdmFsdWUgPSBtb2RlbFtwcm9wZXJ0eV07XG4gICAgICAgICAgfVxuICAgICAgICAgIHVwZGF0ZVByb3BlcnR5KFwiY2hlY2tlZFwiLCB2YWx1ZSwgdm5vZGUsIG9sZFZub2RlKTtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgICAgICBjYXNlIFwicmFkaW9cIjoge1xuICAgICAgICAgIHVwZGF0ZVByb3BlcnR5KFwiY2hlY2tlZFwiLCBtb2RlbFtwcm9wZXJ0eV0gPT09IHZub2RlLmRvbS52YWx1ZSwgdm5vZGUsIG9sZFZub2RlKTtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgICAgICBkZWZhdWx0OiB7XG4gICAgICAgICAgdXBkYXRlUHJvcGVydHkoXCJ2YWx1ZVwiLCBtb2RlbFtwcm9wZXJ0eV0sIHZub2RlLCBvbGRWbm9kZSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9IGVsc2UgaWYgKHZub2RlLm5hbWUgPT09IFwic2VsZWN0XCIpIHtcbiAgICAgIGV2ZW50ID0gZXZlbnQgfHwgXCJvbmNsaWNrXCI7XG4gICAgICBpZiAodm5vZGUucHJvcHMubXVsdGlwbGUpIHtcbiAgICAgICAgaGFuZGxlciA9IChlOiBFdmVudCAmIFJlY29yZDxzdHJpbmcsIGFueT4pID0+IHtcbiAgICAgICAgICBsZXQgdmFsID0gKGUudGFyZ2V0IGFzIERvbUVsZW1lbnQgJiBSZWNvcmQ8c3RyaW5nLCBhbnk+KS52YWx1ZTtcbiAgICAgICAgICBpZiAoZS5jdHJsS2V5KSB7XG4gICAgICAgICAgICBsZXQgaWR4ID0gbW9kZWxbcHJvcGVydHldLmluZGV4T2YodmFsKTtcbiAgICAgICAgICAgIGlmIChpZHggPT09IC0xKSB7XG4gICAgICAgICAgICAgIG1vZGVsW3Byb3BlcnR5XS5wdXNoKHZhbCk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICBtb2RlbFtwcm9wZXJ0eV0uc3BsaWNlKGlkeCwgMSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIG1vZGVsW3Byb3BlcnR5XS5zcGxpY2UoMCwgbW9kZWxbcHJvcGVydHldLmxlbmd0aCk7XG4gICAgICAgICAgICBtb2RlbFtwcm9wZXJ0eV0ucHVzaCh2YWwpO1xuICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgdm5vZGUuY2hpbGRyZW4uZm9yRWFjaCgoY2hpbGQpID0+IHtcbiAgICAgICAgICBpZiAoY2hpbGQubmFtZSA9PT0gXCJvcHRpb25cIikge1xuICAgICAgICAgICAgbGV0IHZhbHVlID0gXCJ2YWx1ZVwiIGluIGNoaWxkLnByb3BzID8gY2hpbGQucHJvcHMudmFsdWUgOiBjaGlsZC5jaGlsZHJlbi5qb2luKFwiXCIpLnRyaW0oKTtcbiAgICAgICAgICAgIGNoaWxkLnByb3BzLnNlbGVjdGVkID0gbW9kZWxbcHJvcGVydHldLmluZGV4T2YodmFsdWUpICE9PSAtMTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdm5vZGUuY2hpbGRyZW4uZm9yRWFjaCgoY2hpbGQpID0+IHtcbiAgICAgICAgICBpZiAoY2hpbGQubmFtZSA9PT0gXCJvcHRpb25cIikge1xuICAgICAgICAgICAgbGV0IHZhbHVlID0gXCJ2YWx1ZVwiIGluIGNoaWxkLnByb3BzID8gY2hpbGQucHJvcHMudmFsdWUgOiBjaGlsZC5jaGlsZHJlbi5qb2luKFwiXCIpLnRyaW0oKTtcbiAgICAgICAgICAgIGNoaWxkLnByb3BzLnNlbGVjdGVkID0gdmFsdWUgPT09IG1vZGVsW3Byb3BlcnR5XTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgIH0gZWxzZSBpZiAodm5vZGUubmFtZSA9PT0gXCJ0ZXh0YXJlYVwiKSB7XG4gICAgICBldmVudCA9IGV2ZW50IHx8IFwib25pbnB1dFwiO1xuICAgICAgdm5vZGUuY2hpbGRyZW4gPSBbbW9kZWxbcHJvcGVydHldXTtcbiAgICB9XG5cbiAgICBpZiAoIXZub2RlLnByb3BzW2V2ZW50XSkge1xuICAgICAgaWYgKCFoYW5kbGVyKSB7XG4gICAgICAgIGhhbmRsZXIgPSAoZTogRXZlbnQpID0+IChtb2RlbFtwcm9wZXJ0eV0gPSAoZS50YXJnZXQgYXMgRG9tRWxlbWVudCAmIFJlY29yZDxzdHJpbmcsIGFueT4pLnZhbHVlKTtcbiAgICAgIH1cbiAgICAgIHVwZGF0ZVByb3BlcnR5KGV2ZW50LCBoYW5kbGVyLCB2bm9kZSwgb2xkVm5vZGUpO1xuICAgIH1cbiAgfVxufTtcblxuLyoqKiBIeXBlcnNjcmlwdCAqKiovXG5cbmV4cG9ydCBjb25zdCB2YWx5cmlhbjogVmFseXJpYW4gPSBmdW5jdGlvbiB2KHRhZ09yQ29tcG9uZW50OiBzdHJpbmcgfCBWYWx5cmlhbkNvbXBvbmVudCwgcHJvcHM6IFByb3BzLCAuLi5jaGlsZHJlbjogQ2hpbGRyZW4pOiBJVm5vZGUgfCBWbm9kZUNvbXBvbmVudCB7XG4gIGlmICh0eXBlb2YgdGFnT3JDb21wb25lbnQgPT09IFwic3RyaW5nXCIpIHtcbiAgICByZXR1cm4gbmV3IFZub2RlKHRhZ09yQ29tcG9uZW50LCBwcm9wcyB8fCB7fSwgY2hpbGRyZW4pO1xuICB9XG5cbiAgY29uc3Qgdm5vZGUgPSBuZXcgVm5vZGUoXCJfX2NvbXBvbmVudF9fXCIsIHByb3BzIHx8IHt9LCBjaGlsZHJlbik7XG4gIHZub2RlLmNvbXBvbmVudCA9IHRhZ09yQ29tcG9uZW50O1xuICByZXR1cm4gdm5vZGUgYXMgVm5vZGVDb21wb25lbnQ7XG59O1xuXG52YWx5cmlhbi5mcmFnbWVudCA9IChwcm9wczogUHJvcHMsIC4uLmNoaWxkcmVuOiBDaGlsZHJlbik6IENoaWxkcmVuID0+IHtcbiAgcmV0dXJuIGNoaWxkcmVuO1xufTtcblxudmFseXJpYW4uY3VycmVudCA9IHt9IGFzIEN1cnJlbnQ7XG5cbnZhbHlyaWFuLmRpcmVjdGl2ZXMgPSB7IC4uLmJ1aWx0SW5EaXJlY3RpdmVzIH07XG5cbnZhbHlyaWFuLnJlc2VydmVkUHJvcHMgPSB7XG4gIGtleTogdHJ1ZSxcbiAgc3RhdGU6IHRydWUsXG4gIG9uY3JlYXRlOiB0cnVlLFxuICBvbnVwZGF0ZTogdHJ1ZSxcbiAgb25yZW1vdmU6IHRydWUsXG4gIHNob3VsZHVwZGF0ZTogdHJ1ZSxcbiAgXCJ2LWNsZWFudXBcIjogdHJ1ZSxcbiAgXCJ2LW9uY2VcIjogdHJ1ZSxcblxuICAvLyBCdWlsdCBpbiBkaXJlY3RpdmVzXG4gIFwidi1pZlwiOiB0cnVlLFxuICBcInYtdW5sZXNzXCI6IHRydWUsXG4gIFwidi1mb3JcIjogdHJ1ZSxcbiAgXCJ2LXNob3dcIjogdHJ1ZSxcbiAgXCJ2LWNsYXNzXCI6IHRydWUsXG4gIFwidi1odG1sXCI6IHRydWVcbn07XG5cbigoaXNOb2RlSnMgPyBnbG9iYWwgOiB3aW5kb3cpIGFzIHVua25vd24gYXMgeyB2OiBWYWx5cmlhbiB9KS52ID0gdmFseXJpYW4gYXMgVmFseXJpYW47XG4iXX0= \ No newline at end of file +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL2xpYi9pbmRleC50cyJdLCJuYW1lcyI6WyJWbm9kZSIsInRhZyIsInByb3BzIiwiY2hpbGRyZW4iLCJ0aGlzIiwiaXNDb21wb25lbnQiLCJjb21wb25lbnQiLCJpc1Zub2RlQ29tcG9uZW50Iiwidm5vZGUiLCJpc05vZGVKcyIsIkJvb2xlYW4iLCJwcm9jZXNzIiwidmVyc2lvbnMiLCJub2RlIiwiY3JlYXRlRG9tRWxlbWVudCIsImlzU1ZHIiwiZG9jdW1lbnQiLCJjcmVhdGVFbGVtZW50TlMiLCJjcmVhdGVFbGVtZW50IiwiZG9tVG9Wbm9kZSIsImRvbSIsInYiLCJ0YWdOYW1lIiwidG9Mb3dlckNhc2UiLCJBcnJheSIsImZyb20iLCJjaGlsZE5vZGVzIiwiZmlsdGVyIiwiY2hpbGQiLCJub2RlVHlwZSIsIm1hcCIsInRleHQiLCJub2RlVmFsdWUiLCJTdHJpbmciLCJmb3JFYWNoIiwiY2FsbCIsImF0dHJpYnV0ZXMiLCJwcm9wIiwibm9kZU5hbWUiLCJ0cnVzdCIsImh0bWxTdHJpbmciLCJkaXYiLCJpbm5lckhUTUwiLCJ0cmltIiwiaXRlbSIsIlZhbHlyaWFuU3ltYm9sIiwiU3ltYm9sIiwiY2FsbENsZWFudXAiLCJ2YWx5cmlhbkFwcCIsImkiLCJvbkNsZWFudXAiLCJsZW5ndGgiLCJ1cGRhdGUiLCJjdXJyZW50IiwiYXBwIiwib2xkVm5vZGUiLCJtYWluVm5vZGUiLCJwYXRjaCIsImlzTW91bnRlZCIsIm9uTW91bnQiLCJjYWxsTW91bnQiLCJvblVwZGF0ZSIsImNhbGxVcGRhdGUiLCJ1bm1vdW50Iiwib25Vbm1vdW50IiwiY2FsbFVubW91bnQiLCJSZWZsZWN0IiwiZGVsZXRlUHJvcGVydHkiLCJlbXB0eVZub2RlIiwib25yZW1vdmUiLCJzaGFyZWRVcGRhdGVQcm9wZXJ0eSIsInZhbHVlIiwicmVzZXJ2ZWRQcm9wcyIsImRpcmVjdGl2ZXMiLCJldmVudExpc3RlbmVyTmFtZXMiLCJjb250YWluZXIiLCJhZGRFdmVudExpc3RlbmVyIiwic2xpY2UiLCJldmVudExpc3RlbmVyIiwicmVtb3ZlQXR0cmlidXRlIiwic2V0QXR0cmlidXRlIiwic2V0UHJvcGVydHkiLCJuYW1lIiwidXBkYXRlUHJvcGVydGllcyIsIm5ld1Zub2RlIiwibmV3VHJlZSIsImNoaWxkVm5vZGUiLCJyZXN1bHQiLCJ2aWV3Iiwic3BsaWNlIiwiaXNBcnJheSIsImZsYXRUcmVlIiwib2xkVHJlZSIsIm9sZFRyZWVMZW5ndGgiLCJuZXdUcmVlTGVuZ3RoIiwib2xkS2V5ZWRMaXN0IiwicmVkdWNlIiwiYWNjIiwia2V5IiwibmV3S2V5ZWRMaXN0Iiwib2xkQ2hpbGRWbm9kZSIsInNob3VsZFBhdGNoIiwic2hvdWxkdXBkYXRlIiwib251cGRhdGUiLCJvbmNyZWF0ZSIsImFwcGVuZENoaWxkIiwicmVwbGFjZUNoaWxkIiwicGFyZW50Tm9kZSIsInJlbW92ZUNoaWxkIiwicGF0Y2hLZXllZFRyZWUiLCJuZXdDaGlsZFZub2RlIiwiY3JlYXRlVGV4dE5vZGUiLCJwYXRjaE5vcm1hbFRyZWUiLCJ0ZXh0Q29udGVudCIsImhpZGVEaXJlY3RpdmUiLCJ0ZXN0IiwiYm9vbCIsIm5ld2RvbSIsImJ1aWx0SW5EaXJlY3RpdmVzIiwic2V0Iiwic3R5bGUiLCJkaXNwbGF5IiwiY2xhc3NlcyIsImNsYXNzTGlzdCIsInRvZ2dsZSIsImh0bWwiLCJtb2RlbCIsInByb3BlcnR5IiwiZXZlbnQiLCJoYW5kbGVyIiwidHlwZSIsImUiLCJ2YWwiLCJ0YXJnZXQiLCJpZHgiLCJpbmRleE9mIiwicHVzaCIsIm11bHRpcGxlIiwiY3RybEtleSIsInZhbHVlMiIsImpvaW4iLCJzZWxlY3RlZCIsInRhZ09yQ29tcG9uZW50IiwiZnJhZ21lbnQiLCJzdGF0ZSIsImdsb2JhbCIsIndpbmRvdyIsImRpcmVjdGl2ZTIiLCJmdWxsTmFtZSIsInZub2RlQ29tcG9uZW50IiwiYXBwQ29udGFpbmVyIiwicXVlcnlTZWxlY3RvckFsbCIsIkVycm9yIiwiZGVmYXVsdFByZXZlbnRlZCIsImNhbGxiYWNrIl0sIm1hcHBp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cEIsS0FBTzlHLEdBQUssQ0FDVixHQUFJQSxFQUFJOEQsR0FLTixPQUpBOUQsRUFBSThELEdBQU1pRCxFQUFHL0csUUFDUitHLEVBQUVzQixrQkFDTHJHLEVBQU85QyxJQUlYYyxFQUFNQSxFQUFJdUYsYUFuQmRyRyxFQUFVdUMsR0FBa0IsQ0FDMUJhLFdBQVcsRUFDWGdCLG1CQUFvQixHQUNwQnhCLFVBQVcsR0FDWFMsUUFBUyxHQUNURSxTQUFVLEdBQ1ZHLFVBQVcsSUFnQmIxRCxFQUFVdUMsR0FBZ0JpQyxjQUFnQkEsRUFTNUMsT0FOQXhFLEVBQVV1QyxHQUFnQnZDLFVBQVkrSSxFQUN0Qy9JLEVBQVV1QyxHQUFnQjhCLFVBQVkyRSxFQUN0Q2hKLEVBQVV1QyxHQUFnQlcsVUFBWXJDLEVBQVdtSSxHQUNqRGhKLEVBQVV1QyxHQUFnQlcsVUFBVXpDLE1BQTBDLFFBQWxDVCxFQUFVdUMsR0FBZ0I1QyxJQUcvRG1ELEVBQU85QyxjQXpGVCxTQUFtQm9KLElBQzJCLElBQS9DckksRUFBRWdDLFFBQVFDLEtBQUtKLFVBQVVxRixRQUFRbUIsSUFDbkNySSxFQUFFZ0MsUUFBUUMsS0FBS0osVUFBVXNGLEtBQUtrQixZQVUzQixTQUFpQkEsSUFDMkIsSUFBN0NySSxFQUFFZ0MsUUFBUUMsS0FBS0ssUUFBUTRFLFFBQVFtQixJQUNqQ3JJLEVBQUVnQyxRQUFRQyxLQUFLSyxRQUFRNkUsS0FBS2tCLGNBUnpCLFNBQW1CQSxJQUMyQixJQUEvQ3JJLEVBQUVnQyxRQUFRQyxLQUFLVSxVQUFVdUUsUUFBUW1CLElBQ25DckksRUFBRWdDLFFBQVFDLEtBQUtVLFVBQVV3RSxLQUFLa0IsYUFVM0IsU0FBa0JBLElBQzJCLElBQTlDckksRUFBRWdDLFFBQVFDLEtBQUtPLFNBQVMwRSxRQUFRbUIsSUFDbENySSxFQUFFZ0MsUUFBUUMsS0FBS08sU0FBUzJFLEtBQUtrQiIsInNvdXJjZXNDb250ZW50IjpbIi8qKiogVm5vZGUgKioqL1xuXG5pbXBvcnQge1xuICBDaGlsZHJlbixcbiAgQ3VycmVudCxcbiAgRGlyZWN0aXZlLFxuICBEb21FbGVtZW50LFxuICBJVm5vZGUsXG4gIE1vdW50ZWRWYWx5cmlhbkFwcCxcbiAgUHJvcHMsXG4gIFZhbHlyaWFuLFxuICBWYWx5cmlhbkFwcCxcbiAgVmFseXJpYW5Db21wb25lbnQsXG4gIFZub2RlQ29tcG9uZW50LFxuICBWbm9kZVdpdGhEb21cbn0gZnJvbSBcIi4vaW50ZXJmYWNlc1wiO1xuXG5leHBvcnQgY29uc3QgVm5vZGUgPSBmdW5jdGlvbiBWbm9kZSh0aGlzOiBJVm5vZGUsIHRhZzogc3RyaW5nLCBwcm9wczogUHJvcHMsIGNoaWxkcmVuOiBDaGlsZHJlbikge1xuICB0aGlzLnByb3BzID0gcHJvcHM7XG4gIHRoaXMuY2hpbGRyZW4gPSBjaGlsZHJlbjtcbiAgdGhpcy50YWcgPSB0YWc7XG59IGFzIHVua25vd24gYXMgSVZub2RlO1xuXG5leHBvcnQgZnVuY3Rpb24gaXNWbm9kZShjb21wb25lbnQ/OiB1bmtub3duKTogY29tcG9uZW50IGlzIElWbm9kZSB7XG4gIHJldHVybiBjb21wb25lbnQgaW5zdGFuY2VvZiBWbm9kZTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGlzQ29tcG9uZW50KGNvbXBvbmVudD86IHVua25vd24gfCBWYWx5cmlhbkNvbXBvbmVudCk6IGNvbXBvbmVudCBpcyBWYWx5cmlhbkNvbXBvbmVudCB7XG4gIHJldHVybiB0eXBlb2YgY29tcG9uZW50ID09PSBcImZ1bmN0aW9uXCIgfHwgKHR5cGVvZiBjb21wb25lbnQgPT09IFwib2JqZWN0XCIgJiYgY29tcG9uZW50ICE9PSBudWxsICYmIFwidmlld1wiIGluIGNvbXBvbmVudCk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBpc1Zub2RlQ29tcG9uZW50KHZub2RlPzogdW5rbm93bik6IHZub2RlIGlzIFZub2RlQ29tcG9uZW50IHtcbiAgcmV0dXJuIHZub2RlIGluc3RhbmNlb2YgVm5vZGUgJiYgdm5vZGUudGFnID09PSBcIl9fY29tcG9uZW50X19cIjtcbn1cblxuLyoqKiBVdGlsICoqKi9cblxuZXhwb3J0IGNvbnN0IGlzTm9kZUpzID0gQm9vbGVhbih0eXBlb2YgcHJvY2VzcyAhPT0gXCJ1bmRlZmluZWRcIiAmJiBwcm9jZXNzLnZlcnNpb25zICYmIHByb2Nlc3MudmVyc2lvbnMubm9kZSk7XG5cbmZ1bmN0aW9uIGNyZWF0ZURvbUVsZW1lbnQodGFnOiBzdHJpbmcsIGlzU1ZHOiBib29sZWFuID0gZmFsc2UpIHtcbiAgcmV0dXJuIGlzU1ZHID8gZG9jdW1lbnQuY3JlYXRlRWxlbWVudE5TKFwiaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmdcIiwgdGFnKSA6IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQodGFnKTtcbn1cblxuZnVuY3Rpb24gZG9tVG9Wbm9kZShkb206IERvbUVsZW1lbnQpOiBWbm9kZVdpdGhEb20ge1xuICBsZXQgdm5vZGUgPSB2KFxuICAgIGRvbS50YWdOYW1lLnRvTG93ZXJDYXNlKCksXG4gICAge30sXG4gICAgLi4uQXJyYXkuZnJvbShkb20uY2hpbGROb2RlcylcbiAgICAgIC5maWx0ZXIoKGNoaWxkKSA9PiAoY2hpbGQgYXMgRG9tRWxlbWVudCkubm9kZVR5cGUgPT09IDEgfHwgKGNoaWxkIGFzIERvbUVsZW1lbnQpLm5vZGVUeXBlID09PSAzKVxuICAgICAgLm1hcCgoY2hpbGQpID0+IHtcbiAgICAgICAgaWYgKChjaGlsZCBhcyBEb21FbGVtZW50KS5ub2RlVHlwZSA9PT0gMSkge1xuICAgICAgICAgIHJldHVybiBkb21Ub1Zub2RlKGNoaWxkIGFzIERvbUVsZW1lbnQpO1xuICAgICAgICB9XG5cbiAgICAgICAgbGV0IHRleHQgPSBuZXcgVm5vZGUoXCIjdGV4dFwiLCB7fSwgW10pO1xuICAgICAgICB0ZXh0Lm5vZGVWYWx1ZSA9IFN0cmluZygoY2hpbGQgYXMgRG9tRWxlbWVudCkubm9kZVZhbHVlKTtcbiAgICAgICAgdGV4dC5kb20gPSBjaGlsZCBhcyBEb21FbGVtZW50O1xuICAgICAgICByZXR1cm4gdGV4dDtcbiAgICAgIH0pXG4gICk7XG4gIFtdLmZvckVhY2guY2FsbChkb20uYXR0cmlidXRlcywgKHByb3A6IEF0dHIpID0+ICh2bm9kZS5wcm9wc1twcm9wLm5vZGVOYW1lXSA9IHByb3Aubm9kZVZhbHVlKSk7XG4gIHZub2RlLmRvbSA9IGRvbTtcbiAgcmV0dXJuIHZub2RlIGFzIFZub2RlV2l0aERvbTtcbn1cblxuZXhwb3J0IGNvbnN0IHRydXN0ID0gKGh0bWxTdHJpbmc6IHN0cmluZykgPT4ge1xuICBsZXQgZGl2ID0gY3JlYXRlRG9tRWxlbWVudChcImRpdlwiKTtcbiAgZGl2LmlubmVySFRNTCA9IGh0bWxTdHJpbmcudHJpbSgpO1xuXG4gIHJldHVybiBbXS5tYXAuY2FsbChkaXYuY2hpbGROb2RlcywgKGl0ZW0pID0+IGRvbVRvVm5vZGUoaXRlbSkpIGFzIElWbm9kZVtdO1xufTtcblxuLyoqKiBNb3VudCAqKiovXG5cbmNvbnN0IFZhbHlyaWFuU3ltYm9sID0gU3ltYm9sKFwiVmFseXJpYW5cIik7XG5cbmV4cG9ydCBmdW5jdGlvbiBvbkNsZWFudXAoY2FsbGJhY2s6IEZ1bmN0aW9uKSB7XG4gIGlmICh2LmN1cnJlbnQuYXBwPy5vbkNsZWFudXAuaW5kZXhPZihjYWxsYmFjaykgPT09IC0xKSB7XG4gICAgdi5jdXJyZW50LmFwcD8ub25DbGVhbnVwLnB1c2goY2FsbGJhY2spO1xuICB9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBvblVubW91bnQoY2FsbGJhY2s6IEZ1bmN0aW9uKSB7XG4gIGlmICh2LmN1cnJlbnQuYXBwPy5vblVubW91bnQuaW5kZXhPZihjYWxsYmFjaykgPT09IC0xKSB7XG4gICAgdi5jdXJyZW50LmFwcD8ub25Vbm1vdW50LnB1c2goY2FsbGJhY2spO1xuICB9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBvbk1vdW50KGNhbGxiYWNrOiBGdW5jdGlvbikge1xuICBpZiAodi5jdXJyZW50LmFwcD8ub25Nb3VudC5pbmRleE9mKGNhbGxiYWNrKSA9PT0gLTEpIHtcbiAgICB2LmN1cnJlbnQuYXBwPy5vbk1vdW50LnB1c2goY2FsbGJhY2spO1xuICB9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBvblVwZGF0ZShjYWxsYmFjazogRnVuY3Rpb24pIHtcbiAgaWYgKHYuY3VycmVudC5hcHA/Lm9uVXBkYXRlLmluZGV4T2YoY2FsbGJhY2spID09PSAtMSkge1xuICAgIHYuY3VycmVudC5hcHA/Lm9uVXBkYXRlLnB1c2goY2FsbGJhY2spO1xuICB9XG59XG5cbi8qXG4gICogTW91bnRzIGEgY29tcG9uZW50IHRvIHRoZSBET01cbiAgbW91bnQoJyNhcHAnLCAoKSA9PiA8ZGl2PkhlbGxvIHdvcmxkPC9kaXY+KTsgLy8gQXBwIGlzIGEgRnVuY3Rpb25hbCBDb21wb25lbnRcbiAgbW91bnQoJyNhcHAnLCB7IHZpZXc6ICgpID0+IDxkaXY+SGVsbG8gd29ybGQ8L2Rpdj4gfSk7IC8vIEFwcCBpcyBhIFBPSk8gY29tcG9uZW50IHdpdGggYSB2aWV3IG1ldGhvZFxuICBtb3VudCgnI2FwcCcsIGNsYXNzSW5zdGFuY2UpOyAvLyBBcHAgaXMgYSBjbGFzcyBpbnN0YW5jZSB3aXRoIGEgdmlldyBtZXRob2RcbiAgbW91bnQoJyNhcHAnLCA8QXBwPjxkaXY+SGVsbG8gd29ybGQ8L2Rpdj48L0FwcD4pOyAvLyBBcHAgaXMgYSBWbm9kZSBjb21wb25lbnQgKFZub2RlIHdpdGggdGFnIF9fY29tcG9uZW50X18pXG4qL1xuXG5leHBvcnQgZnVuY3Rpb24gbW91bnQoY29udGFpbmVyOiBEb21FbGVtZW50IHwgc3RyaW5nLCBjb21wb25lbnQ6IFZhbHlyaWFuQ29tcG9uZW50IHwgSVZub2RlKSB7XG4gIGxldCBhcHBDb250YWluZXIgPSBudWxsO1xuXG4gIGlmIChpc05vZGVKcykge1xuICAgIGFwcENvbnRhaW5lciA9IHR5cGVvZiBjb250YWluZXIgPT09IFwic3RyaW5nXCIgPyBjcmVhdGVEb21FbGVtZW50KGNvbnRhaW5lciA9PT0gXCJzdmdcIiA/IFwic3ZnXCIgOiBcImRpdlwiLCBjb250YWluZXIgPT09IFwic3ZnXCIpIDogY29udGFpbmVyO1xuICB9IGVsc2Uge1xuICAgIGFwcENvbnRhaW5lciA9IHR5cGVvZiBjb250YWluZXIgPT09IFwic3RyaW5nXCIgPyBkb2N1bWVudC5xdWVyeVNlbGVjdG9yQWxsKGNvbnRhaW5lcilbMF0gOiBjb250YWluZXI7XG4gIH1cblxuICBpZiAoIWFwcENvbnRhaW5lcikge1xuICAgIHRocm93IG5ldyBFcnJvcihcIkNvbnRhaW5lciBub3QgZm91bmRcIik7XG4gIH1cblxuICBsZXQgdm5vZGVDb21wb25lbnQ6IFZub2RlQ29tcG9uZW50IHwgSVZub2RlO1xuXG4gIGlmIChpc1Zub2RlQ29tcG9uZW50KGNvbXBvbmVudCkpIHtcbiAgICB2bm9kZUNvbXBvbmVudCA9IGNvbXBvbmVudDtcbiAgfSBlbHNlIGlmIChpc0NvbXBvbmVudChjb21wb25lbnQpKSB7XG4gICAgdm5vZGVDb21wb25lbnQgPSB2KGNvbXBvbmVudCwge30pO1xuICB9IGVsc2Uge1xuICAgIHRocm93IG5ldyBFcnJvcihcIkNvbXBvbmVudCBtdXN0IGJlIGEgVmFseXJpYW4gQ29tcG9uZW50IG9yIGEgVm5vZGUgY29tcG9uZW50XCIpO1xuICB9XG5cbiAgaWYgKGNvbXBvbmVudFtWYWx5cmlhblN5bWJvbF0pIHtcbiAgICB1bm1vdW50KGNvbXBvbmVudCk7XG4gIH0gZWxzZSB7XG4gICAgY29tcG9uZW50W1ZhbHlyaWFuU3ltYm9sXSA9IHtcbiAgICAgIGlzTW91bnRlZDogZmFsc2UsXG4gICAgICBldmVudExpc3RlbmVyTmFtZXM6IHt9LFxuICAgICAgb25DbGVhbnVwOiBbXSxcbiAgICAgIG9uTW91bnQ6IFtdLFxuICAgICAgb25VcGRhdGU6IFtdLFxuICAgICAgb25Vbm1vdW50OiBbXVxuICAgIH07XG4gICAgZnVuY3Rpb24gZXZlbnRMaXN0ZW5lcihlOiBFdmVudCkge1xuICAgICAgbGV0IGRvbSA9IGUudGFyZ2V0IGFzIERvbUVsZW1lbnQgJiBSZWNvcmQ8c3RyaW5nLCBhbnk+O1xuICAgICAgbGV0IG5hbWUgPSBgdi1vbiR7ZS50eXBlfWA7XG4gICAgICB3aGlsZSAoZG9tKSB7XG4gICAgICAgIGlmIChkb21bbmFtZV0pIHtcbiAgICAgICAgICBkb21bbmFtZV0oZSwgZG9tKTtcbiAgICAgICAgICBpZiAoIWUuZGVmYXVsdFByZXZlbnRlZCkge1xuICAgICAgICAgICAgdXBkYXRlKGNvbXBvbmVudCk7XG4gICAgICAgICAgfVxuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBkb20gPSBkb20ucGFyZW50Tm9kZSBhcyBEb21FbGVtZW50O1xuICAgICAgfVxuICAgIH1cbiAgICBjb21wb25lbnRbVmFseXJpYW5TeW1ib2xdLmV2ZW50TGlzdGVuZXIgPSBldmVudExpc3RlbmVyO1xuICB9XG5cbiAgY29tcG9uZW50W1ZhbHlyaWFuU3ltYm9sXS5jb21wb25lbnQgPSB2bm9kZUNvbXBvbmVudDtcbiAgY29tcG9uZW50W1ZhbHlyaWFuU3ltYm9sXS5jb250YWluZXIgPSBhcHBDb250YWluZXI7XG4gIGNvbXBvbmVudFtWYWx5cmlhblN5bWJvbF0ubWFpblZub2RlID0gZG9tVG9Wbm9kZShhcHBDb250YWluZXIpO1xuICBjb21wb25lbnRbVmFseXJpYW5TeW1ib2xdLm1haW5Wbm9kZS5pc1NWRyA9IGNvbXBvbmVudFtWYWx5cmlhblN5bWJvbF0udGFnID09PSBcInN2Z1wiO1xuXG4gIC8vIHVwZGF0ZVxuICByZXR1cm4gdXBkYXRlKGNvbXBvbmVudCk7XG59XG5cbmZ1bmN0aW9uIGNhbGxDbGVhbnVwKHZhbHlyaWFuQXBwOiBWYWx5cmlhbkFwcCkge1xuICBmb3IgKGxldCBpID0gMDsgaSA8IHZhbHlyaWFuQXBwLm9uQ2xlYW51cC5sZW5ndGg7IGkrKykge1xuICAgIHZhbHlyaWFuQXBwLm9uQ2xlYW51cFtpXSgpO1xuICB9XG4gIHZhbHlyaWFuQXBwLm9uQ2xlYW51cCA9IFtdO1xufVxuXG5mdW5jdGlvbiBjYWxsVW5tb3VudCh2YWx5cmlhbkFwcDogVmFseXJpYW5BcHApIHtcbiAgZm9yIChsZXQgaSA9IDA7IGkgPCB2YWx5cmlhbkFwcC5vblVubW91bnQubGVuZ3RoOyBpKyspIHtcbiAgICB2YWx5cmlhbkFwcC5vblVubW91bnRbaV0oKTtcbiAgfVxuICB2YWx5cmlhbkFwcC5vblVubW91bnQgPSBbXTtcbn1cblxuZnVuY3Rpb24gY2FsbE1vdW50KHZhbHlyaWFuQXBwOiBWYWx5cmlhbkFwcCkge1xuICBmb3IgKGxldCBpID0gMDsgaSA8IHZhbHlyaWFuQXBwLm9uTW91bnQubGVuZ3RoOyBpKyspIHtcbiAgICB2YWx5cmlhbkFwcC5vbk1vdW50W2ldKCk7XG4gIH1cbiAgdmFseXJpYW5BcHAub25Nb3VudCA9IFtdO1xufVxuXG5mdW5jdGlvbiBjYWxsVXBkYXRlKHZhbHlyaWFuQXBwOiBWYWx5cmlhbkFwcCkge1xuICBmb3IgKGxldCBpID0gMDsgaSA8IHZhbHlyaWFuQXBwLm9uVXBkYXRlLmxlbmd0aDsgaSsrKSB7XG4gICAgdmFseXJpYW5BcHAub25VcGRhdGVbaV0oKTtcbiAgfVxuICB2YWx5cmlhbkFwcC5vblVwZGF0ZSA9IFtdO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gdXBkYXRlKGNvbXBvbmVudD86IFZhbHlyaWFuQ29tcG9uZW50IHwgSVZub2RlKSB7XG4gIGlmIChjb21wb25lbnQgJiYgY29tcG9uZW50W1ZhbHlyaWFuU3ltYm9sXSkge1xuICAgIGxldCB2YWx5cmlhbkFwcCA9IGNvbXBvbmVudFtWYWx5cmlhblN5bWJvbF07XG4gICAgdi5jdXJyZW50LmFwcCA9IHZhbHlyaWFuQXBwO1xuICAgIHZhbHlyaWFuQXBwLm9uQ2xlYW51cC5sZW5ndGggJiYgY2FsbENsZWFudXAodmFseXJpYW5BcHApO1xuICAgIGxldCBvbGRWbm9kZTogVm5vZGVXaXRoRG9tIHwgbnVsbCA9IHZhbHlyaWFuQXBwLm1haW5Wbm9kZSBhcyBWbm9kZVdpdGhEb207XG4gICAgdmFseXJpYW5BcHAubWFpblZub2RlID0gbmV3IFZub2RlKHZhbHlyaWFuQXBwLm1haW5Wbm9kZS50YWcsIHZhbHlyaWFuQXBwLm1haW5Wbm9kZS5wcm9wcywgW3ZhbHlyaWFuQXBwLmNvbXBvbmVudF0pIGFzIFZub2RlV2l0aERvbTtcbiAgICB2YWx5cmlhbkFwcC5tYWluVm5vZGUuZG9tID0gb2xkVm5vZGUuZG9tO1xuICAgIHZhbHlyaWFuQXBwLm1haW5Wbm9kZS5pc1NWRyA9IG9sZFZub2RlLmlzU1ZHO1xuICAgIHBhdGNoKHZhbHlyaWFuQXBwLm1haW5Wbm9kZSwgb2xkVm5vZGUsIHZhbHlyaWFuQXBwKTtcbiAgICBvbGRWbm9kZSA9IG51bGw7XG4gICAgaWYgKHZhbHlyaWFuQXBwLmlzTW91bnRlZCA9PT0gZmFsc2UpIHtcbiAgICAgIHZhbHlyaWFuQXBwLm9uTW91bnQubGVuZ3RoICYmIGNhbGxNb3VudCh2YWx5cmlhbkFwcCk7XG4gICAgICB2YWx5cmlhbkFwcC5pc01vdW50ZWQgPSB0cnVlO1xuICAgIH0gZWxzZSB7XG4gICAgICB2YWx5cmlhbkFwcC5vblVwZGF0ZS5sZW5ndGggJiYgY2FsbFVwZGF0ZSh2YWx5cmlhbkFwcCk7XG4gICAgfVxuXG4gICAgaWYgKGlzTm9kZUpzKSB7XG4gICAgICByZXR1cm4gdmFseXJpYW5BcHAubWFpblZub2RlLmRvbS5pbm5lckhUTUw7XG4gICAgfVxuICB9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiB1bm1vdW50KGNvbXBvbmVudD86IFZhbHlyaWFuQ29tcG9uZW50IHwgSVZub2RlKSB7XG4gIGlmICghY29tcG9uZW50IHx8ICFjb21wb25lbnRbVmFseXJpYW5TeW1ib2xdKSB7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgbGV0IHZhbHlyaWFuQXBwID0gY29tcG9uZW50W1ZhbHlyaWFuU3ltYm9sXSBhcyBNb3VudGVkVmFseXJpYW5BcHA7XG5cbiAgaWYgKHZhbHlyaWFuQXBwLmlzTW91bnRlZCkge1xuICAgIHZhbHlyaWFuQXBwLm9uQ2xlYW51cC5sZW5ndGggJiYgY2FsbENsZWFudXAodmFseXJpYW5BcHApO1xuICAgIHZhbHlyaWFuQXBwLm9uVW5tb3VudC5sZW5ndGggJiYgY2FsbFVubW91bnQodmFseXJpYW5BcHApO1xuICAgIGxldCBvbGRWbm9kZTogVm5vZGVXaXRoRG9tIHwgbnVsbCA9IHZhbHlyaWFuQXBwLm1haW5Wbm9kZSBhcyBWbm9kZVdpdGhEb207XG4gICAgdmFseXJpYW5BcHAubWFpblZub2RlID0gbmV3IFZub2RlKHZhbHlyaWFuQXBwLm1haW5Wbm9kZS50YWcsIHZhbHlyaWFuQXBwLm1haW5Wbm9kZS5wcm9wcywgW10pIGFzIFZub2RlV2l0aERvbTtcbiAgICB2YWx5cmlhbkFwcC5tYWluVm5vZGUuZG9tID0gb2xkVm5vZGUuZG9tO1xuICAgIHZhbHlyaWFuQXBwLm1haW5Wbm9kZS5pc1NWRyA9IG9sZFZub2RlLmlzU1ZHO1xuICAgIHBhdGNoKHZhbHlyaWFuQXBwLm1haW5Wbm9kZSwgb2xkVm5vZGUsIHZhbHlyaWFuQXBwKTtcbiAgICBvbGRWbm9kZSA9IG51bGw7XG5cbiAgICBpZiAoaXNOb2RlSnMpIHtcbiAgICAgIHJldHVybiB2YWx5cmlhbkFwcC5tYWluVm5vZGUuZG9tLmlubmVySFRNTDtcbiAgICB9XG5cbiAgICAodmFseXJpYW5BcHAgYXMgYW55KSA9IG51bGw7XG4gICAgUmVmbGVjdC5kZWxldGVQcm9wZXJ0eShjb21wb25lbnQsIFZhbHlyaWFuU3ltYm9sKTtcbiAgfVxufVxuXG5sZXQgZW1wdHlWbm9kZSA9IG5ldyBWbm9kZShcIl9fZW1wdHlfX1wiLCB7fSwgW10pO1xuXG5mdW5jdGlvbiBvbnJlbW92ZSh2bm9kZTogSVZub2RlKSB7XG4gIGZvciAobGV0IGkgPSAwOyBpIDwgdm5vZGUuY2hpbGRyZW4ubGVuZ3RoOyBpKyspIHtcbiAgICB2bm9kZS5jaGlsZHJlbltpXS50YWcgIT09IFwiI3RleHRcIiAmJiBvbnJlbW92ZSh2bm9kZS5jaGlsZHJlbltpXSk7XG4gIH1cblxuICB2bm9kZS5wcm9wcy5vbnJlbW92ZSAmJiB2bm9kZS5wcm9wcy5vbnJlbW92ZSh2bm9kZSk7XG59XG5cbmZ1bmN0aW9uIHNoYXJlZFVwZGF0ZVByb3BlcnR5KHByb3A6IHN0cmluZywgdmFsdWU6IGFueSwgdm5vZGU6IFZub2RlV2l0aERvbSwgb2xkVm5vZGU/OiBWbm9kZVdpdGhEb20pIHtcbiAgLy8gSXQgaXMgYSByZXNlcnZlZCBwcm9wXG4gIGlmICh2LnJlc2VydmVkUHJvcHNbcHJvcF0pIHtcbiAgICAvLyBJZiBpdCBpcyBhIGRpcmVjdGl2ZSBuYW1lIGNhbGwgdGhlIGRpcmVjdGl2ZVxuICAgIGlmICh2LmRpcmVjdGl2ZXNbcHJvcF0pIHtcbiAgICAgIHYuZGlyZWN0aXZlc1twcm9wXSh2bm9kZS5wcm9wc1twcm9wXSwgdm5vZGUsIG9sZFZub2RlKTtcbiAgICB9XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgLy8gSXQgaXMgbm90IGEgcmVzZXJ2ZWQgcHJvcCBzbyB3ZSBhZGQgaXQgdG8gdGhlIGRvbVxuICBpZiAodHlwZW9mIHZhbHVlID09PSBcImZ1bmN0aW9uXCIpIHtcbiAgICBsZXQgdmFseXJpYW5BcHAgPSB2LmN1cnJlbnQuYXBwIGFzIE1vdW50ZWRWYWx5cmlhbkFwcDtcbiAgICBpZiAocHJvcCBpbiB2YWx5cmlhbkFwcC5ldmVudExpc3RlbmVyTmFtZXMgPT09IGZhbHNlKSB7XG4gICAgICB2YWx5cmlhbkFwcC5ldmVudExpc3RlbmVyTmFtZXNbcHJvcF0gPSB0cnVlO1xuICAgICAgdmFseXJpYW5BcHAuY29udGFpbmVyLmFkZEV2ZW50TGlzdGVuZXIocHJvcC5zbGljZSgyKSwgdmFseXJpYW5BcHAuZXZlbnRMaXN0ZW5lcik7XG4gICAgfVxuICAgIHZub2RlLmRvbVtgdi0ke3Byb3B9YF0gPSB2YWx1ZTtcbiAgICByZXR1cm47XG4gIH1cblxuICBpZiAocHJvcCBpbiB2bm9kZS5kb20gJiYgdm5vZGUuaXNTVkcgPT09IGZhbHNlKSB7XG4gICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGVxZXFlcVxuICAgIGlmICh2bm9kZS5kb21bcHJvcF0gIT0gdmFsdWUpIHtcbiAgICAgIHZub2RlLmRvbVtwcm9wXSA9IHZhbHVlO1xuICAgIH1cbiAgICByZXR1cm47XG4gIH1cblxuICAvLyBVc2Ugc2V0IGF0dHJpYnV0ZVxuICBpZiAoIW9sZFZub2RlIHx8IG9sZFZub2RlLnByb3BzW3Byb3BdICE9PSB2YWx1ZSkge1xuICAgIGlmICh2YWx1ZSA9PT0gZmFsc2UpIHtcbiAgICAgIHZub2RlLmRvbS5yZW1vdmVBdHRyaWJ1dGUocHJvcCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHZub2RlLmRvbS5zZXRBdHRyaWJ1dGUocHJvcCwgdmFsdWUpO1xuICAgIH1cbiAgfVxufVxuXG5leHBvcnQgZnVuY3Rpb24gc2V0UHJvcGVydHkobmFtZTogc3RyaW5nLCB2YWx1ZTogYW55LCB2bm9kZTogVm5vZGVXaXRoRG9tLCBvbGRWbm9kZT86IFZub2RlV2l0aERvbSkge1xuICBpZiAobmFtZSBpbiB2bm9kZS5wcm9wcyA9PT0gZmFsc2UpIHtcbiAgICB2bm9kZS5wcm9wc1tuYW1lXSA9IHZhbHVlO1xuICB9XG5cbiAgc2hhcmVkVXBkYXRlUHJvcGVydHkobmFtZSwgdmFsdWUsIHZub2RlLCBvbGRWbm9kZSk7XG59XG5cbmZ1bmN0aW9uIHVwZGF0ZVByb3BlcnRpZXModm5vZGU6IFZub2RlV2l0aERvbSwgb2xkVm5vZGU/OiBWbm9kZVdpdGhEb20pIHtcbiAgZm9yIChsZXQgcHJvcCBpbiB2bm9kZS5wcm9wcykge1xuICAgIC8vIFdlIGFzdW1lIHRoYXQgd2UgY2xlYW4gdGhlIHByb3BzIGluIHNvbWUgZGlyZWN0aXZlXG4gICAgaWYgKHByb3AgaW4gdm5vZGUucHJvcHMgPT09IGZhbHNlKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgc2hhcmVkVXBkYXRlUHJvcGVydHkocHJvcCwgdm5vZGUucHJvcHNbcHJvcF0sIHZub2RlLCBvbGRWbm9kZSk7XG4gIH1cblxuICBpZiAob2xkVm5vZGUpIHtcbiAgICBmb3IgKGxldCBwcm9wIGluIG9sZFZub2RlLnByb3BzKSB7XG4gICAgICBpZiAocHJvcCBpbiB2bm9kZS5wcm9wcyA9PT0gZmFsc2UgJiYgdHlwZW9mIG9sZFZub2RlLnByb3BzW3Byb3BdICE9PSBcImZ1bmN0aW9uXCIgJiYgcHJvcCBpbiB2LnJlc2VydmVkUHJvcHMgPT09IGZhbHNlKSB7XG4gICAgICAgIGlmIChwcm9wIGluIG9sZFZub2RlLmRvbSAmJiB2bm9kZS5pc1NWRyA9PT0gZmFsc2UpIHtcbiAgICAgICAgICBvbGRWbm9kZS5kb21bcHJvcF0gPSBudWxsO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIG9sZFZub2RlLmRvbS5yZW1vdmVBdHRyaWJ1dGUocHJvcCk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gIH1cbn1cblxuZnVuY3Rpb24gZmxhdFRyZWUobmV3Vm5vZGU6IElWbm9kZSk6IHZvaWQge1xuICBsZXQgbmV3VHJlZSA9IG5ld1Zub2RlLmNoaWxkcmVuO1xuICBmb3IgKGxldCBpID0gMDsgaSA8IG5ld1RyZWUubGVuZ3RoOyBpKyspIHtcbiAgICBsZXQgY2hpbGRWbm9kZSA9IG5ld1RyZWVbaV07XG4gICAgaWYgKGNoaWxkVm5vZGUgaW5zdGFuY2VvZiBWbm9kZSkge1xuICAgICAgaWYgKGNoaWxkVm5vZGUudGFnICE9PSBcIiN0ZXh0XCIpIHtcbiAgICAgICAgaWYgKGNoaWxkVm5vZGUudGFnID09PSBcIl9fY29tcG9uZW50X19cIikge1xuICAgICAgICAgIGxldCBjb21wb25lbnQgPSBjaGlsZFZub2RlLmNvbXBvbmVudCBhcyBWYWx5cmlhbkNvbXBvbmVudDtcbiAgICAgICAgICB2LmN1cnJlbnQuY29tcG9uZW50ID0gY29tcG9uZW50O1xuICAgICAgICAgIGxldCByZXN1bHQgPSAoXCJ2aWV3XCIgaW4gY29tcG9uZW50ID8gY29tcG9uZW50LnZpZXcgOiBjb21wb25lbnQpLmNhbGwoY29tcG9uZW50LCBjaGlsZFZub2RlLnByb3BzLCAuLi5jaGlsZFZub2RlLmNoaWxkcmVuKTtcblxuICAgICAgICAgIG5ld1RyZWUuc3BsaWNlKGktLSwgMSwgcmVzdWx0KTtcbiAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuICAgICAgICBjaGlsZFZub2RlLmlzU1ZHID0gbmV3Vm5vZGUuaXNTVkcgfHwgY2hpbGRWbm9kZS50YWcgPT09IFwic3ZnXCI7XG4gICAgICB9XG4gICAgfSBlbHNlIGlmIChjaGlsZFZub2RlID09PSBudWxsIHx8IGNoaWxkVm5vZGUgPT09IHVuZGVmaW5lZCkge1xuICAgICAgbmV3VHJlZS5zcGxpY2UoaS0tLCAxKTtcbiAgICB9IGVsc2UgaWYgKEFycmF5LmlzQXJyYXkoY2hpbGRWbm9kZSkpIHtcbiAgICAgIG5ld1RyZWUuc3BsaWNlKGktLSwgMSwgLi4uY2hpbGRWbm9kZSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGlmIChpID4gMCAmJiBuZXdUcmVlW2kgLSAxXS50YWcgPT09IFwiI3RleHRcIikge1xuICAgICAgICBuZXdUcmVlW2kgLSAxXS5ub2RlVmFsdWUgKz0gY2hpbGRWbm9kZTtcbiAgICAgICAgbmV3VHJlZS5zcGxpY2UoaS0tLCAxKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIG5ld1RyZWVbaV0gPSBuZXcgVm5vZGUoXCIjdGV4dFwiLCB7fSwgW10pO1xuICAgICAgICBuZXdUcmVlW2ldLm5vZGVWYWx1ZSA9IFN0cmluZyhjaGlsZFZub2RlKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cbn1cblxuZnVuY3Rpb24gcGF0Y2hLZXllZFRyZWUoXG4gIG5ld1Zub2RlOiBWbm9kZVdpdGhEb20sXG4gIG5ld1RyZWU6IChWbm9kZVdpdGhEb20gJiB7IHByb3BzOiBQcm9wcyAmIHsga2V5OiBzdHJpbmcgfSB9KVtdLFxuICBvbGRUcmVlOiAoVm5vZGVXaXRoRG9tICYgeyBwcm9wczogUHJvcHMgJiB7IGtleTogc3RyaW5nIH0gfSlbXSxcbiAgbmV3VHJlZUxlbmd0aDogbnVtYmVyLFxuICBvbGRUcmVlTGVuZ3RoOiBudW1iZXIsXG4gIHZhbHlyaWFuQXBwOiBNb3VudGVkVmFseXJpYW5BcHBcbikge1xuICBsZXQgb2xkS2V5ZWRMaXN0ID0gb2xkVHJlZS5yZWR1Y2UoKGFjYywgdm5vZGUsIGkpID0+IHtcbiAgICBhY2Nbdm5vZGUucHJvcHMua2V5XSA9IGk7XG4gICAgcmV0dXJuIGFjYztcbiAgfSwge30gYXMgeyBba2V5OiBzdHJpbmddOiBudW1iZXIgfSk7XG4gIGxldCBuZXdLZXllZExpc3QgPSBuZXdUcmVlLnJlZHVjZSgoYWNjLCB2bm9kZSwgaSkgPT4ge1xuICAgIGFjY1t2bm9kZS5wcm9wcy5rZXldID0gaTtcbiAgICByZXR1cm4gYWNjO1xuICB9LCB7fSBhcyB7IFtrZXk6IHN0cmluZ106IG51bWJlciB9KTtcblxuICBmb3IgKGxldCBpID0gMDsgaSA8IG5ld1RyZWVMZW5ndGg7IGkrKykge1xuICAgIGxldCBjaGlsZFZub2RlID0gbmV3VHJlZVtpXTtcbiAgICBsZXQgb2xkQ2hpbGRWbm9kZSA9IG9sZFRyZWVbb2xkS2V5ZWRMaXN0W2NoaWxkVm5vZGUucHJvcHMua2V5XV07XG4gICAgbGV0IHNob3VsZFBhdGNoID0gdHJ1ZTtcblxuICAgIGlmIChvbGRDaGlsZFZub2RlKSB7XG4gICAgICBjaGlsZFZub2RlLmRvbSA9IG9sZENoaWxkVm5vZGUuZG9tO1xuICAgICAgaWYgKFwidi1vbmNlXCIgaW4gY2hpbGRWbm9kZS5wcm9wcyB8fCAoY2hpbGRWbm9kZS5wcm9wcy5zaG91bGR1cGRhdGUgJiYgY2hpbGRWbm9kZS5wcm9wcy5zaG91bGR1cGRhdGUoY2hpbGRWbm9kZSwgb2xkQ2hpbGRWbm9kZSkgPT09IGZhbHNlKSkge1xuICAgICAgICAvLyBza2lwIHRoaXMgcGF0Y2hcbiAgICAgICAgY2hpbGRWbm9kZS5jaGlsZHJlbiA9IG9sZENoaWxkVm5vZGUuY2hpbGRyZW47XG4gICAgICAgIHNob3VsZFBhdGNoID0gZmFsc2U7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB1cGRhdGVQcm9wZXJ0aWVzKGNoaWxkVm5vZGUsIG9sZENoaWxkVm5vZGUpO1xuICAgICAgICBpZiAodmFseXJpYW5BcHAuaXNNb3VudGVkKSB7XG4gICAgICAgICAgY2hpbGRWbm9kZS5wcm9wcy5vbnVwZGF0ZSAmJiBjaGlsZFZub2RlLnByb3BzLm9udXBkYXRlKGNoaWxkVm5vZGUsIG9sZENoaWxkVm5vZGUpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGNoaWxkVm5vZGUucHJvcHMub25jcmVhdGUgJiYgY2hpbGRWbm9kZS5wcm9wcy5vbmNyZWF0ZShjaGlsZFZub2RlKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICBjaGlsZFZub2RlLmRvbSA9IGNyZWF0ZURvbUVsZW1lbnQoY2hpbGRWbm9kZS50YWcsIGNoaWxkVm5vZGUuaXNTVkcpO1xuICAgICAgdXBkYXRlUHJvcGVydGllcyhjaGlsZFZub2RlKTtcbiAgICAgIGNoaWxkVm5vZGUucHJvcHMub25jcmVhdGUgJiYgY2hpbGRWbm9kZS5wcm9wcy5vbmNyZWF0ZShjaGlsZFZub2RlKTtcbiAgICB9XG5cbiAgICBpZiAobmV3Vm5vZGUuZG9tLmNoaWxkTm9kZXNbaV0gPT09IHVuZGVmaW5lZCkge1xuICAgICAgbmV3Vm5vZGUuZG9tLmFwcGVuZENoaWxkKGNoaWxkVm5vZGUuZG9tKTtcbiAgICB9IGVsc2UgaWYgKG5ld1Zub2RlLmRvbS5jaGlsZE5vZGVzW2ldICE9PSBjaGlsZFZub2RlLmRvbSkge1xuICAgICAgb2xkVHJlZVtpXSAmJiBuZXdLZXllZExpc3Rbb2xkVHJlZVtpXS5wcm9wcy5rZXldID09PSB1bmRlZmluZWQgJiYgb25yZW1vdmUob2xkVHJlZVtpXSk7XG4gICAgICBuZXdWbm9kZS5kb20ucmVwbGFjZUNoaWxkKGNoaWxkVm5vZGUuZG9tLCBuZXdWbm9kZS5kb20uY2hpbGROb2Rlc1tpXSk7XG4gICAgfVxuXG4gICAgc2hvdWxkUGF0Y2ggJiYgcGF0Y2goY2hpbGRWbm9kZSwgb2xkQ2hpbGRWbm9kZSwgdmFseXJpYW5BcHApO1xuICB9XG5cbiAgLy8gRm9yIHRoZSByZXN0IG9mIHRoZSBjaGlsZHJlbiwgd2Ugc2hvdWxkIHJlbW92ZSB0aGVtXG4gIGZvciAobGV0IGkgPSBuZXdUcmVlTGVuZ3RoOyBpIDwgb2xkVHJlZUxlbmd0aDsgaSsrKSB7XG4gICAgaWYgKG5ld0tleWVkTGlzdFtvbGRUcmVlW2ldLnByb3BzLmtleV0gPT09IHVuZGVmaW5lZCkge1xuICAgICAgbGV0IG9sZENoaWxkVm5vZGUgPSBvbGRUcmVlW2ldO1xuICAgICAgb25yZW1vdmUob2xkQ2hpbGRWbm9kZSk7XG4gICAgICBvbGRDaGlsZFZub2RlLmRvbS5wYXJlbnROb2RlICYmIG9sZENoaWxkVm5vZGUuZG9tLnBhcmVudE5vZGUucmVtb3ZlQ2hpbGQob2xkQ2hpbGRWbm9kZS5kb20pO1xuICAgIH1cbiAgfVxufVxuXG4vLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgY29tcGxleGl0eVxuZnVuY3Rpb24gcGF0Y2hOb3JtYWxUcmVlKFxuICBuZXdWbm9kZTogVm5vZGVXaXRoRG9tLFxuICBuZXdUcmVlOiAoVm5vZGVXaXRoRG9tICYgeyBwcm9wczogUHJvcHMgJiB7IGtleTogc3RyaW5nIH0gfSlbXSxcbiAgb2xkVHJlZTogKFZub2RlV2l0aERvbSAmIHsgcHJvcHM6IFByb3BzICYgeyBrZXk6IHN0cmluZyB9IH0pW10sXG4gIG5ld1RyZWVMZW5ndGg6IG51bWJlcixcbiAgb2xkVHJlZUxlbmd0aDogbnVtYmVyLFxuICB2YWx5cmlhbkFwcDogTW91bnRlZFZhbHlyaWFuQXBwXG4pIHtcbiAgLy8gSWYgbmV3IHRyZWUgYW5kIG9sZCB0cmVlIGhhdmUgbW9yZSB0aGFuIG9uZSBjaGlsZCwgd2Ugc2hvdWxkIHVwZGF0ZSB0aGUgZG9tXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgbmV3VHJlZUxlbmd0aDsgaSsrKSB7XG4gICAgbGV0IG9sZENoaWxkVm5vZGUgPSBvbGRUcmVlW2ldO1xuICAgIGxldCBuZXdDaGlsZFZub2RlID0gbmV3VHJlZVtpXTtcblxuICAgIC8vIE9sZCBjaGlsZCBkb2VzIG5vdCBleGlzdHNcbiAgICBpZiAoIW9sZENoaWxkVm5vZGUpIHtcbiAgICAgIC8vIE5ldyBjaGlsZCBpcyBhIHRleHQgbm9kZVxuICAgICAgaWYgKG5ld0NoaWxkVm5vZGUudGFnID09PSBcIiN0ZXh0XCIpIHtcbiAgICAgICAgbmV3Q2hpbGRWbm9kZS5kb20gPSBkb2N1bWVudC5jcmVhdGVUZXh0Tm9kZShuZXdDaGlsZFZub2RlLm5vZGVWYWx1ZSBhcyBzdHJpbmcpIGFzIHVua25vd24gYXMgRG9tRWxlbWVudDtcbiAgICAgICAgbmV3Vm5vZGUuZG9tLmFwcGVuZENoaWxkKG5ld0NoaWxkVm5vZGUuZG9tKTtcbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG5cbiAgICAgIC8vIE5ldyBjaGlsZCBpcyBhIG5vcm1hbCBub2RlXG4gICAgICBuZXdDaGlsZFZub2RlLmRvbSA9IGNyZWF0ZURvbUVsZW1lbnQobmV3Q2hpbGRWbm9kZS50YWcsIG5ld0NoaWxkVm5vZGUuaXNTVkcpO1xuICAgICAgdXBkYXRlUHJvcGVydGllcyhuZXdDaGlsZFZub2RlKTtcbiAgICAgIG5ld1Zub2RlLmRvbS5hcHBlbmRDaGlsZChuZXdDaGlsZFZub2RlLmRvbSk7XG4gICAgICBuZXdDaGlsZFZub2RlLnByb3BzLm9uY3JlYXRlICYmIG5ld0NoaWxkVm5vZGUucHJvcHMub25jcmVhdGUobmV3Q2hpbGRWbm9kZSk7XG4gICAgICBwYXRjaChuZXdDaGlsZFZub2RlLCB1bmRlZmluZWQsIHZhbHlyaWFuQXBwKTtcbiAgICAgIGNvbnRpbnVlO1xuICAgIH1cblxuICAgIC8vIE9sZCBjaGlsZCBleGlzdHNcbiAgICAvLyBOZXcgY2hpbGQgaXMgYSB0ZXh0IG5vZGVcbiAgICBpZiAobmV3Q2hpbGRWbm9kZS50YWcgPT09IFwiI3RleHRcIikge1xuICAgICAgLy8gT2xkIGNoaWxkIGlzIGEgdGV4dCBub2RlXG4gICAgICBpZiAob2xkQ2hpbGRWbm9kZS50YWcgPT09IFwiI3RleHRcIikge1xuICAgICAgICBuZXdDaGlsZFZub2RlLmRvbSA9IG9sZENoaWxkVm5vZGUuZG9tO1xuICAgICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgZXFlcWVxXG4gICAgICAgIGlmIChuZXdDaGlsZFZub2RlLmRvbS5ub2RlVmFsdWUgIT0gbmV3Q2hpbGRWbm9kZS5ub2RlVmFsdWUpIHtcbiAgICAgICAgICBuZXdDaGlsZFZub2RlLmRvbS5ub2RlVmFsdWUgPSBuZXdDaGlsZFZub2RlLm5vZGVWYWx1ZSBhcyBzdHJpbmc7XG4gICAgICAgIH1cbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG5cbiAgICAgIC8vIE9sZCBjaGlsZCBpcyBhIG5vcm1hbCBub2RlXG4gICAgICBuZXdDaGlsZFZub2RlLmRvbSA9IGRvY3VtZW50LmNyZWF0ZVRleHROb2RlKG5ld0NoaWxkVm5vZGUubm9kZVZhbHVlIGFzIHN0cmluZykgYXMgdW5rbm93biBhcyBEb21FbGVtZW50O1xuICAgICAgb25yZW1vdmUob2xkQ2hpbGRWbm9kZSk7XG4gICAgICBuZXdWbm9kZS5kb20ucmVwbGFjZUNoaWxkKG5ld0NoaWxkVm5vZGUuZG9tLCBvbGRDaGlsZFZub2RlLmRvbSk7XG5cbiAgICAgIGNvbnRpbnVlO1xuICAgIH1cblxuICAgIC8vIE5ldyBjaGlsZCBpcyBhIG5vcm1hbCBub2RlXG4gICAgLy8gT2xkIGNoaWxkIGlzIHRoZSBzYW1lIHR5cGUgYXMgbmV3IGNoaWxkXG4gICAgaWYgKG9sZENoaWxkVm5vZGUudGFnID09PSBuZXdDaGlsZFZub2RlLnRhZykge1xuICAgICAgbmV3Q2hpbGRWbm9kZS5kb20gPSBvbGRDaGlsZFZub2RlLmRvbTtcbiAgICAgIC8vIElmIHdlIGhhdmUgYSB2LW9uY2UgZGlyZWN0aXZlIG9yIGEgc2hvdWxkdXBkYXRlIG1ldGhvZCB0aGF0IHJldHVybnMgZmFsc2UsIHdlIHNraXAgdGhlIHVwZGF0ZVxuICAgICAgaWYgKG5ld0NoaWxkVm5vZGUucHJvcHNbXCJ2LW9uY2VcIl0gfHwgKG5ld0NoaWxkVm5vZGUucHJvcHMuc2hvdWxkdXBkYXRlICYmIG5ld0NoaWxkVm5vZGUucHJvcHMuc2hvdWxkdXBkYXRlKG5ld0NoaWxkVm5vZGUsIG9sZENoaWxkVm5vZGUpID09PSBmYWxzZSkpIHtcbiAgICAgICAgbmV3Q2hpbGRWbm9kZS5jaGlsZHJlbiA9IG9sZENoaWxkVm5vZGUuY2hpbGRyZW47XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuXG4gICAgICAvLyBXZSB1cGRhdGUgdGhlIGRvbSBlbGVtZW50XG4gICAgICB1cGRhdGVQcm9wZXJ0aWVzKG5ld0NoaWxkVm5vZGUsIG9sZENoaWxkVm5vZGUpO1xuICAgICAgaWYgKHZhbHlyaWFuQXBwICYmIHZhbHlyaWFuQXBwLmlzTW91bnRlZCkge1xuICAgICAgICBuZXdDaGlsZFZub2RlLnByb3BzLm9udXBkYXRlICYmIG5ld0NoaWxkVm5vZGUucHJvcHMub251cGRhdGUobmV3Q2hpbGRWbm9kZSwgb2xkQ2hpbGRWbm9kZSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBuZXdDaGlsZFZub2RlLnByb3BzLm9uY3JlYXRlICYmIG5ld0NoaWxkVm5vZGUucHJvcHMub25jcmVhdGUobmV3Q2hpbGRWbm9kZSk7XG4gICAgICB9XG4gICAgICBwYXRjaChuZXdDaGlsZFZub2RlLCBvbGRDaGlsZFZub2RlLCB2YWx5cmlhbkFwcCk7XG5cbiAgICAgIGNvbnRpbnVlO1xuICAgIH1cblxuICAgIC8vIE9sZCBjaGlsZCBpcyBvZiBhIGRpZmZlcmVudCB0eXBlIHRoYW4gbmV3IGNoaWxkXG4gICAgbmV3Q2hpbGRWbm9kZS5kb20gPSBjcmVhdGVEb21FbGVtZW50KG5ld0NoaWxkVm5vZGUudGFnLCBuZXdDaGlsZFZub2RlLmlzU1ZHKTtcbiAgICB1cGRhdGVQcm9wZXJ0aWVzKG5ld0NoaWxkVm5vZGUpO1xuICAgIGlmIChvbGRDaGlsZFZub2RlLnRhZyAhPT0gXCIjdGV4dFwiKSB7XG4gICAgICBvbnJlbW92ZShvbGRDaGlsZFZub2RlKTtcbiAgICB9XG4gICAgbmV3Q2hpbGRWbm9kZS5wcm9wcy5vbmNyZWF0ZSAmJiBuZXdDaGlsZFZub2RlLnByb3BzLm9uY3JlYXRlKG5ld0NoaWxkVm5vZGUpO1xuICAgIG5ld1Zub2RlLmRvbS5yZXBsYWNlQ2hpbGQobmV3Q2hpbGRWbm9kZS5kb20sIG9sZENoaWxkVm5vZGUuZG9tKTtcbiAgICBwYXRjaChuZXdDaGlsZFZub2RlLCB1bmRlZmluZWQsIHZhbHlyaWFuQXBwKTtcbiAgfVxuXG4gIC8vIEZvciB0aGUgcmVzdCBvZiB0aGUgY2hpbGRyZW4sIHdlIHNob3VsZCByZW1vdmUgdGhlbVxuICBmb3IgKGxldCBpID0gbmV3VHJlZUxlbmd0aDsgaSA8IG9sZFRyZWVMZW5ndGg7IGkrKykge1xuICAgIGxldCBvbGRDaGlsZFZub2RlID0gb2xkVHJlZVtpXTtcbiAgICBpZiAob2xkQ2hpbGRWbm9kZS50YWcgIT09IFwiI3RleHRcIikge1xuICAgICAgb25yZW1vdmUob2xkQ2hpbGRWbm9kZSk7XG4gICAgfVxuICAgIG9sZENoaWxkVm5vZGUuZG9tLnBhcmVudE5vZGUgJiYgb2xkQ2hpbGRWbm9kZS5kb20ucGFyZW50Tm9kZS5yZW1vdmVDaGlsZChvbGRDaGlsZFZub2RlLmRvbSk7XG4gIH1cbn1cblxuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGNvbXBsZXhpdHlcbmZ1bmN0aW9uIHBhdGNoKG5ld1Zub2RlOiBWbm9kZVdpdGhEb20sIG9sZFZub2RlOiBWbm9kZVdpdGhEb20gPSBlbXB0eVZub2RlIGFzIFZub2RlV2l0aERvbSwgdmFseXJpYW5BcHA6IE1vdW50ZWRWYWx5cmlhbkFwcCkge1xuICB2LmN1cnJlbnQudm5vZGUgPSBuZXdWbm9kZTtcbiAgdi5jdXJyZW50Lm9sZFZub2RlID0gb2xkVm5vZGU7XG5cbiAgZmxhdFRyZWUobmV3Vm5vZGUpO1xuXG4gIGxldCBuZXdUcmVlID0gbmV3Vm5vZGUuY2hpbGRyZW47XG4gIGxldCBvbGRUcmVlID0gb2xkVm5vZGUuY2hpbGRyZW47XG4gIGxldCBvbGRUcmVlTGVuZ3RoID0gb2xkVHJlZS5sZW5ndGg7XG4gIGxldCBuZXdUcmVlTGVuZ3RoID0gbmV3VHJlZS5sZW5ndGg7XG5cbiAgLy8gSWYgbmV3IHRyZWUgaXMgZW1wdHksIHJlbW92ZSBhbGwgb2xkIG5vZGVzXG4gIGlmIChuZXdUcmVlTGVuZ3RoID09PSAwKSB7XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBvbGRUcmVlTGVuZ3RoOyBpKyspIHtcbiAgICAgIG9ucmVtb3ZlKG9sZFRyZWVbaV0pO1xuICAgIH1cblxuICAgIG5ld1Zub2RlLmRvbS50ZXh0Q29udGVudCA9IFwiXCI7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgLy8gSWYgdGhlIHRyZWUgaXMga2V5ZWQgbGlzdCBhbmQgaXMgbm90IGZpcnN0IHJlbmRlciBhbmQgb2xkIHRyZWUgaXMga2V5ZWQgbGlzdCB0b29cbiAgaWYgKG9sZFRyZWVMZW5ndGggJiYgXCJrZXlcIiBpbiBuZXdUcmVlWzBdLnByb3BzICYmIFwia2V5XCIgaW4gb2xkVHJlZVswXS5wcm9wcykge1xuICAgIHBhdGNoS2V5ZWRUcmVlKG5ld1Zub2RlLCBuZXdUcmVlLCBvbGRUcmVlLCBuZXdUcmVlTGVuZ3RoLCBvbGRUcmVlTGVuZ3RoLCB2YWx5cmlhbkFwcCk7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgcGF0Y2hOb3JtYWxUcmVlKG5ld1Zub2RlLCBuZXdUcmVlLCBvbGRUcmVlLCBuZXdUcmVlTGVuZ3RoLCBvbGRUcmVlTGVuZ3RoLCB2YWx5cmlhbkFwcCk7XG59XG5cbi8qKiogRGlyZWN0aXZlcyAqKiovXG5cbmV4cG9ydCBmdW5jdGlvbiBkaXJlY3RpdmUobmFtZTogc3RyaW5nLCBkaXJlY3RpdmU6IERpcmVjdGl2ZSkge1xuICBsZXQgZnVsbE5hbWUgPSBgdi0ke25hbWV9YDtcbiAgdi5kaXJlY3RpdmVzW2Z1bGxOYW1lXSA9IGRpcmVjdGl2ZTtcbiAgdi5yZXNlcnZlZFByb3BzW2Z1bGxOYW1lXSA9IHRydWU7XG59XG5cbmZ1bmN0aW9uIGhpZGVEaXJlY3RpdmUodGVzdDogYm9vbGVhbik6IERpcmVjdGl2ZSB7XG4gIHJldHVybiAoYm9vbDogYm9vbGVhbiwgdm5vZGU6IElWbm9kZSwgb2xkVm5vZGU/OiBJVm5vZGUpID0+IHtcbiAgICBsZXQgdmFsdWUgPSB0ZXN0ID8gYm9vbCA6ICFib29sO1xuICAgIGlmICh2YWx1ZSkge1xuICAgICAgbGV0IG5ld2RvbSA9IGRvY3VtZW50LmNyZWF0ZVRleHROb2RlKFwiXCIpO1xuICAgICAgaWYgKG9sZFZub2RlICYmIG9sZFZub2RlLmRvbSAmJiBvbGRWbm9kZS5kb20ucGFyZW50Tm9kZSkge1xuICAgICAgICBvbGRWbm9kZS50YWcgIT09IFwiI3RleHRcIiAmJiBvbnJlbW92ZShvbGRWbm9kZSk7XG4gICAgICAgIG9sZFZub2RlLmRvbS5wYXJlbnROb2RlLnJlcGxhY2VDaGlsZChuZXdkb20sIG9sZFZub2RlLmRvbSk7XG4gICAgICB9XG4gICAgICB2bm9kZS50YWcgPSBcIiN0ZXh0XCI7XG4gICAgICB2bm9kZS5jaGlsZHJlbiA9IFtdO1xuICAgICAgdm5vZGUucHJvcHMgPSB7fTtcbiAgICAgIHZub2RlLmRvbSA9IG5ld2RvbSBhcyB1bmtub3duIGFzIERvbUVsZW1lbnQ7XG4gICAgfVxuICB9O1xufVxuXG5jb25zdCBidWlsdEluRGlyZWN0aXZlcyA9IHtcbiAgXCJ2LWlmXCI6IGhpZGVEaXJlY3RpdmUoZmFsc2UpLFxuICBcInYtdW5sZXNzXCI6IGhpZGVEaXJlY3RpdmUodHJ1ZSksXG4gIFwidi1mb3JcIjogKHNldDogdW5rbm93bltdLCB2bm9kZTogVm5vZGVXaXRoRG9tKSA9PiB7XG4gICAgdm5vZGUuY2hpbGRyZW4gPSBzZXQubWFwKHZub2RlLmNoaWxkcmVuWzBdIGFzICh2YWx1ZTogdW5rbm93bikgPT4gRnVuY3Rpb24pO1xuICB9LFxuICBcInYtc2hvd1wiOiAoYm9vbDogYm9vbGVhbiwgdm5vZGU6IFZub2RlV2l0aERvbSkgPT4ge1xuICAgICh2bm9kZS5kb20gYXMgdW5rbm93biBhcyB7IHN0eWxlOiB7IGRpc3BsYXk6IHN0cmluZyB9IH0pLnN0eWxlLmRpc3BsYXkgPSBib29sID8gXCJcIiA6IFwibm9uZVwiO1xuICB9LFxuICBcInYtY2xhc3NcIjogKGNsYXNzZXM6IHsgW3g6IHN0cmluZ106IGJvb2xlYW4gfSwgdm5vZGU6IFZub2RlV2l0aERvbSkgPT4ge1xuICAgIGZvciAobGV0IG5hbWUgaW4gY2xhc3Nlcykge1xuICAgICAgKHZub2RlLmRvbSBhcyBEb21FbGVtZW50KS5jbGFzc0xpc3QudG9nZ2xlKG5hbWUsIGNsYXNzZXNbbmFtZV0pO1xuICAgIH1cbiAgfSxcbiAgXCJ2LWh0bWxcIjogKGh0bWw6IHN0cmluZywgdm5vZGU6IFZub2RlV2l0aERvbSkgPT4ge1xuICAgIHZub2RlLmNoaWxkcmVuID0gW3RydXN0KGh0bWwpXTtcbiAgfSxcbiAgXCJ2LW1vZGVsXCI6IChbbW9kZWwsIHByb3BlcnR5LCBldmVudF06IGFueVtdLCB2bm9kZTogVm5vZGVXaXRoRG9tLCBvbGRWbm9kZT86IFZub2RlV2l0aERvbSkgPT4ge1xuICAgIGxldCB2YWx1ZTtcbiAgICBsZXQgaGFuZGxlcjtcbiAgICBpZiAodm5vZGUubmFtZSA9PT0gXCJpbnB1dFwiKSB7XG4gICAgICBldmVudCA9IGV2ZW50IHx8IFwib25pbnB1dFwiO1xuICAgICAgc3dpdGNoICh2bm9kZS5wcm9wcy50eXBlKSB7XG4gICAgICAgIGNhc2UgXCJjaGVja2JveFwiOiB7XG4gICAgICAgICAgaWYgKEFycmF5LmlzQXJyYXkobW9kZWxbcHJvcGVydHldKSkge1xuICAgICAgICAgICAgaGFuZGxlciA9IChlOiBFdmVudCkgPT4ge1xuICAgICAgICAgICAgICBsZXQgdmFsID0gKGUudGFyZ2V0IGFzIERvbUVsZW1lbnQgJiBSZWNvcmQ8c3RyaW5nLCBhbnk+KS52YWx1ZTtcbiAgICAgICAgICAgICAgbGV0IGlkeCA9IG1vZGVsW3Byb3BlcnR5XS5pbmRleE9mKHZhbCk7XG4gICAgICAgICAgICAgIGlmIChpZHggPT09IC0xKSB7XG4gICAgICAgICAgICAgICAgbW9kZWxbcHJvcGVydHldLnB1c2godmFsKTtcbiAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBtb2RlbFtwcm9wZXJ0eV0uc3BsaWNlKGlkeCwgMSk7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICB2YWx1ZSA9IG1vZGVsW3Byb3BlcnR5XS5pbmRleE9mKHZub2RlLmRvbS52YWx1ZSkgIT09IC0xO1xuICAgICAgICAgIH0gZWxzZSBpZiAoXCJ2YWx1ZVwiIGluIHZub2RlLnByb3BzKSB7XG4gICAgICAgICAgICBoYW5kbGVyID0gKCkgPT4ge1xuICAgICAgICAgICAgICBpZiAobW9kZWxbcHJvcGVydHldID09PSB2bm9kZS5wcm9wcy52YWx1ZSkge1xuICAgICAgICAgICAgICAgIG1vZGVsW3Byb3BlcnR5XSA9IG51bGw7XG4gICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgbW9kZWxbcHJvcGVydHldID0gdm5vZGUucHJvcHMudmFsdWU7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICB2YWx1ZSA9IG1vZGVsW3Byb3BlcnR5XSA9PT0gdm5vZGUucHJvcHMudmFsdWU7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGhhbmRsZXIgPSAoKSA9PiAobW9kZWxbcHJvcGVydHldID0gIW1vZGVsW3Byb3BlcnR5XSk7XG4gICAgICAgICAgICB2YWx1ZSA9IG1vZGVsW3Byb3BlcnR5XTtcbiAgICAgICAgICB9XG4gICAgICAgICAgc2V0UHJvcGVydHkoXCJjaGVja2VkXCIsIHZhbHVlLCB2bm9kZSwgb2xkVm5vZGUpO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgICAgIGNhc2UgXCJyYWRpb1wiOiB7XG4gICAgICAgICAgc2V0UHJvcGVydHkoXCJjaGVja2VkXCIsIG1vZGVsW3Byb3BlcnR5XSA9PT0gdm5vZGUuZG9tLnZhbHVlLCB2bm9kZSwgb2xkVm5vZGUpO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgICAgIGRlZmF1bHQ6IHtcbiAgICAgICAgICBzZXRQcm9wZXJ0eShcInZhbHVlXCIsIG1vZGVsW3Byb3BlcnR5XSwgdm5vZGUsIG9sZFZub2RlKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0gZWxzZSBpZiAodm5vZGUubmFtZSA9PT0gXCJzZWxlY3RcIikge1xuICAgICAgZXZlbnQgPSBldmVudCB8fCBcIm9uY2xpY2tcIjtcbiAgICAgIGlmICh2bm9kZS5wcm9wcy5tdWx0aXBsZSkge1xuICAgICAgICBoYW5kbGVyID0gKGU6IEV2ZW50ICYgUmVjb3JkPHN0cmluZywgYW55PikgPT4ge1xuICAgICAgICAgIGxldCB2YWwgPSAoZS50YXJnZXQgYXMgRG9tRWxlbWVudCAmIFJlY29yZDxzdHJpbmcsIGFueT4pLnZhbHVlO1xuICAgICAgICAgIGlmIChlLmN0cmxLZXkpIHtcbiAgICAgICAgICAgIGxldCBpZHggPSBtb2RlbFtwcm9wZXJ0eV0uaW5kZXhPZih2YWwpO1xuICAgICAgICAgICAgaWYgKGlkeCA9PT0gLTEpIHtcbiAgICAgICAgICAgICAgbW9kZWxbcHJvcGVydHldLnB1c2godmFsKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIG1vZGVsW3Byb3BlcnR5XS5zcGxpY2UoaWR4LCAxKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgbW9kZWxbcHJvcGVydHldLnNwbGljZSgwLCBtb2RlbFtwcm9wZXJ0eV0ubGVuZ3RoKTtcbiAgICAgICAgICAgIG1vZGVsW3Byb3BlcnR5XS5wdXNoKHZhbCk7XG4gICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICB2bm9kZS5jaGlsZHJlbi5mb3JFYWNoKChjaGlsZCkgPT4ge1xuICAgICAgICAgIGlmIChjaGlsZC5uYW1lID09PSBcIm9wdGlvblwiKSB7XG4gICAgICAgICAgICBsZXQgdmFsdWUgPSBcInZhbHVlXCIgaW4gY2hpbGQucHJvcHMgPyBjaGlsZC5wcm9wcy52YWx1ZSA6IGNoaWxkLmNoaWxkcmVuLmpvaW4oXCJcIikudHJpbSgpO1xuICAgICAgICAgICAgY2hpbGQucHJvcHMuc2VsZWN0ZWQgPSBtb2RlbFtwcm9wZXJ0eV0uaW5kZXhPZih2YWx1ZSkgIT09IC0xO1xuICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB2bm9kZS5jaGlsZHJlbi5mb3JFYWNoKChjaGlsZCkgPT4ge1xuICAgICAgICAgIGlmIChjaGlsZC5uYW1lID09PSBcIm9wdGlvblwiKSB7XG4gICAgICAgICAgICBsZXQgdmFsdWUgPSBcInZhbHVlXCIgaW4gY2hpbGQucHJvcHMgPyBjaGlsZC5wcm9wcy52YWx1ZSA6IGNoaWxkLmNoaWxkcmVuLmpvaW4oXCJcIikudHJpbSgpO1xuICAgICAgICAgICAgY2hpbGQucHJvcHMuc2VsZWN0ZWQgPSB2YWx1ZSA9PT0gbW9kZWxbcHJvcGVydHldO1xuICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgfSBlbHNlIGlmICh2bm9kZS5uYW1lID09PSBcInRleHRhcmVhXCIpIHtcbiAgICAgIGV2ZW50ID0gZXZlbnQgfHwgXCJvbmlucHV0XCI7XG4gICAgICB2bm9kZS5jaGlsZHJlbiA9IFttb2RlbFtwcm9wZXJ0eV1dO1xuICAgIH1cblxuICAgIGlmICghdm5vZGUucHJvcHNbZXZlbnRdKSB7XG4gICAgICBpZiAoIWhhbmRsZXIpIHtcbiAgICAgICAgaGFuZGxlciA9IChlOiBFdmVudCkgPT4gKG1vZGVsW3Byb3BlcnR5XSA9IChlLnRhcmdldCBhcyBEb21FbGVtZW50ICYgUmVjb3JkPHN0cmluZywgYW55PikudmFsdWUpO1xuICAgICAgfVxuICAgICAgc2V0UHJvcGVydHkoZXZlbnQsIGhhbmRsZXIsIHZub2RlLCBvbGRWbm9kZSk7XG4gICAgfVxuICB9XG59O1xuXG4vKioqIEh5cGVyc2NyaXB0ICoqKi9cblxuZXhwb3J0IGNvbnN0IHY6IFZhbHlyaWFuID0gZnVuY3Rpb24gdih0YWdPckNvbXBvbmVudDogc3RyaW5nIHwgVmFseXJpYW5Db21wb25lbnQsIHByb3BzOiBQcm9wcywgLi4uY2hpbGRyZW46IENoaWxkcmVuKTogSVZub2RlIHwgVm5vZGVDb21wb25lbnQge1xuICBpZiAodHlwZW9mIHRhZ09yQ29tcG9uZW50ID09PSBcInN0cmluZ1wiKSB7XG4gICAgcmV0dXJuIG5ldyBWbm9kZSh0YWdPckNvbXBvbmVudCwgcHJvcHMgfHwge30sIGNoaWxkcmVuKTtcbiAgfVxuXG4gIGNvbnN0IHZub2RlID0gbmV3IFZub2RlKFwiX19jb21wb25lbnRfX1wiLCBwcm9wcyB8fCB7fSwgY2hpbGRyZW4pO1xuICB2bm9kZS5jb21wb25lbnQgPSB0YWdPckNvbXBvbmVudDtcbiAgcmV0dXJuIHZub2RlIGFzIFZub2RlQ29tcG9uZW50O1xufTtcblxudi5mcmFnbWVudCA9IChwcm9wczogUHJvcHMsIC4uLmNoaWxkcmVuOiBDaGlsZHJlbik6IENoaWxkcmVuID0+IHtcbiAgcmV0dXJuIGNoaWxkcmVuO1xufTtcblxudi5jdXJyZW50ID0ge30gYXMgQ3VycmVudDtcblxudi5kaXJlY3RpdmVzID0geyAuLi5idWlsdEluRGlyZWN0aXZlcyB9O1xuXG52LnJlc2VydmVkUHJvcHMgPSB7XG4gIGtleTogdHJ1ZSxcbiAgc3RhdGU6IHRydWUsXG4gIG9uY3JlYXRlOiB0cnVlLFxuICBvbnVwZGF0ZTogdHJ1ZSxcbiAgb25yZW1vdmU6IHRydWUsXG4gIHNob3VsZHVwZGF0ZTogdHJ1ZSxcbiAgXCJ2LWNsZWFudXBcIjogdHJ1ZSxcbiAgXCJ2LW9uY2VcIjogdHJ1ZSxcblxuICAvLyBCdWlsdCBpbiBkaXJlY3RpdmVzXG4gIFwidi1pZlwiOiB0cnVlLFxuICBcInYtdW5sZXNzXCI6IHRydWUsXG4gIFwidi1mb3JcIjogdHJ1ZSxcbiAgXCJ2LXNob3dcIjogdHJ1ZSxcbiAgXCJ2LWNsYXNzXCI6IHRydWUsXG4gIFwidi1odG1sXCI6IHRydWVcbn07XG5cbigoaXNOb2RlSnMgPyBnbG9iYWwgOiB3aW5kb3cpIGFzIHVua25vd24gYXMgeyB2OiBWYWx5cmlhbiB9KS52ID0gdiBhcyBWYWx5cmlhbjtcbiJdfQ== \ No newline at end of file diff --git a/lib/index.ts b/lib/index.ts index fa71a1b..ddc0234 100644 --- a/lib/index.ts +++ b/lib/index.ts @@ -135,7 +135,6 @@ export function mount(container: DomElement | string, component: ValyrianCompone component[ValyrianSymbol] = { isMounted: false, eventListenerNames: {}, - isNodeJs, onCleanup: [], onMount: [], onUpdate: [], @@ -161,6 +160,7 @@ export function mount(container: DomElement | string, component: ValyrianCompone component[ValyrianSymbol].component = vnodeComponent; component[ValyrianSymbol].container = appContainer; component[ValyrianSymbol].mainVnode = domToVnode(appContainer); + component[ValyrianSymbol].mainVnode.isSVG = component[ValyrianSymbol].tag === "svg"; // update return update(component); @@ -234,11 +234,13 @@ export function unmount(component?: ValyrianComponent | IVnode) { valyrianApp.mainVnode.isSVG = oldVnode.isSVG; patch(valyrianApp.mainVnode, oldVnode, valyrianApp); oldVnode = null; - valyrianApp.isMounted = false; if (isNodeJs) { return valyrianApp.mainVnode.dom.innerHTML; } + + (valyrianApp as any) = null; + Reflect.deleteProperty(component, ValyrianSymbol); } } @@ -291,7 +293,7 @@ function sharedUpdateProperty(prop: string, value: any, vnode: VnodeWithDom, old } } -export function updateProperty(name: string, value: any, vnode: VnodeWithDom, oldVnode?: VnodeWithDom) { +export function setProperty(name: string, value: any, vnode: VnodeWithDom, oldVnode?: VnodeWithDom) { if (name in vnode.props === false) { vnode.props[name] = value; } @@ -616,15 +618,15 @@ const builtInDirectives = { handler = () => (model[property] = !model[property]); value = model[property]; } - updateProperty("checked", value, vnode, oldVnode); + setProperty("checked", value, vnode, oldVnode); break; } case "radio": { - updateProperty("checked", model[property] === vnode.dom.value, vnode, oldVnode); + setProperty("checked", model[property] === vnode.dom.value, vnode, oldVnode); break; } default: { - updateProperty("value", model[property], vnode, oldVnode); + setProperty("value", model[property], vnode, oldVnode); } } } else if (vnode.name === "select") { @@ -667,7 +669,7 @@ const builtInDirectives = { if (!handler) { handler = (e: Event) => (model[property] = (e.target as DomElement & Record).value); } - updateProperty(event, handler, vnode, oldVnode); + setProperty(event, handler, vnode, oldVnode); } } }; diff --git a/lib/interfaces.ts b/lib/interfaces.ts index 5725d63..465e668 100644 --- a/lib/interfaces.ts +++ b/lib/interfaces.ts @@ -64,7 +64,6 @@ export interface ValyrianApp { eventListener?: EventListener; mainVnode?: VnodeWithDom; - component?: VnodeComponent; container?: DomElement; [key: string | number | symbol]: any; @@ -74,7 +73,6 @@ export interface MountedValyrianApp extends ValyrianApp { eventListener: EventListener; mainVnode: VnodeWithDom; container: DomElement; - component: VnodeComponent; } export interface Current { diff --git a/package.json b/package.json index 5d3066d..ed73c6b 100644 --- a/package.json +++ b/package.json @@ -3,11 +3,11 @@ "version": "5.0.17", "description": "Lightweight steel to forge PWAs. (Minimal Frontend Framework with server side rendering and other capabilities)", "source": "lib/index.ts", - "main": "dist/valyrian.min.js", - "module": "dist/valyrian.min.js", - "unpkg": "dist/valyrian.min.js", - "browser": "dist/valyrian.min.js", - "types": "dist/types/lib/index.d.ts", + "main": "dist/index.cjs", + "module": "dist/index.js", + "unpkg": "dist/index.cjs", + "browser": "dist/index.min.js", + "types": "dist/@types/lib/index.d.ts", "repository": "git@github.com:Masquerade-Circus/valyrian.js.git", "author": "Masquerade ", "license": "Apache-2.0", @@ -191,4 +191,4 @@ "resolutions": { "minimist": "^1.2.5" } -} \ No newline at end of file +} diff --git a/plugins/node.js b/plugins/node.js index 30726df..09e978a 100644 --- a/plugins/node.js +++ b/plugins/node.js @@ -71,7 +71,7 @@ async function inline(file, options = {}) { let esbuildOptions = { entryPoints: [file], - bundle: true, + bundle: "bundle" in options ? options.bundle : true, sourcemap: "external", write: false, minify: options.compact, diff --git a/plugins/router.js b/plugins/router.js index dd99199..bd35f18 100644 --- a/plugins/router.js +++ b/plugins/router.js @@ -1,4 +1,4 @@ -const { mount, updateProperty, directive, isNodeJs, isComponent, isVnodeComponent } = require("../lib/index"); +const { mount, updateProperty, directive, isNodeJs, isComponent, isVnodeComponent } = require("../lib"); function flat(array) { return Array.isArray(array) ? array.flat(Infinity) : [array]; diff --git a/source.js b/source.js index 2176da9..5028669 100644 --- a/source.js +++ b/source.js @@ -33,11 +33,11 @@ async function build({ globalName, entryPoint, outfileName, clean = false, minif files: [entryPoint], pretty: true, copyOtherToOutDir: false, - clean: clean ? ["types", "dist"] : [], + clean: clean ? ["dist"] : [], compilerOptions: { rootDir: "./", declaration: true, - declarationDir: "./types", + declarationDir: "./dist/@types", emitDeclarationOnly: true } }; diff --git a/test/directives_test.js b/test/directives_test.js index 7942695..8b6e772 100644 --- a/test/directives_test.js +++ b/test/directives_test.js @@ -2,7 +2,7 @@ const expect = require("expect"); const faker = require("faker"); const dayjs = require("dayjs"); -import { directive, mount, trust, update, updateProperty } from "../lib/index"; +import { directive, mount, setProperty, trust, update } from "../lib/index"; require("../plugins/node"); @@ -93,7 +93,7 @@ describe("Directives", () => { /** * Modify properties is not guaranteed because the properties are processed by place - * If the directive needs to update previous properties you need to update the property using the updateProperty method + * If the directive needs to update previous properties you need to update the property using the setProperty method */ it("Modify properties is not guaranteed", () => { let update = false; @@ -103,7 +103,7 @@ describe("Directives", () => { // Try to change u property vnode.props.u = "property changed"; if (update) { - updateProperty("u", "property changed", vnode, oldVnode); + setProperty("u", "property changed", vnode, oldVnode); } // Try to change x property diff --git a/tsconfig.json b/tsconfig.json index a393984..9518268 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -6,7 +6,7 @@ "moduleResolution": "node", "esModuleInterop": true, "inlineSourceMap": true, - "allowJs": true, + "allowJs": false, "resolveJsonModule": true, "removeComments": true }, diff --git a/types/plugins/hooks.d.ts b/types/plugins/hooks.d.ts deleted file mode 100644 index 0d82332..0000000 --- a/types/plugins/hooks.d.ts +++ /dev/null @@ -1 +0,0 @@ -export { plugin as default }; diff --git a/types/plugins/node.d.ts b/types/plugins/node.d.ts deleted file mode 100644 index 0d82332..0000000 --- a/types/plugins/node.d.ts +++ /dev/null @@ -1 +0,0 @@ -export { plugin as default }; diff --git a/types/plugins/node.sw.tpl.d.ts b/types/plugins/node.sw.tpl.d.ts deleted file mode 100644 index 922731c..0000000 --- a/types/plugins/node.sw.tpl.d.ts +++ /dev/null @@ -1,11 +0,0 @@ -declare function fetchRequest(event: any): Promise; -declare let Log: { - (...data: any[]): void; - (message?: any, ...optionalParams: any[]): void; -}; -declare namespace config { - const version: string; - const name: string; - const urls: string[]; -} -declare let cacheName: string; diff --git a/types/plugins/request.d.ts b/types/plugins/request.d.ts deleted file mode 100644 index 31c66b8..0000000 --- a/types/plugins/request.d.ts +++ /dev/null @@ -1,5 +0,0 @@ -export = request; -declare function request(method: any, url: any, data: any, options?: {}): Promise; -declare namespace request { - export { request as default }; -} diff --git a/types/plugins/router.d.ts b/types/plugins/router.d.ts deleted file mode 100644 index c80cce6..0000000 --- a/types/plugins/router.d.ts +++ /dev/null @@ -1,19 +0,0 @@ -export = Router; -declare class Router { - paths: any[]; - container: null; - url: string; - query: {}; - options: {}; - current: string; - params: {}; - matches: any[]; - get(path: any, ...args: any[]): Router; - use(...args: any[]): Router; - routes(): any[]; - go(path: any, parentComponent: any): Promise; - mount(elementContainer: any): void; -} -declare namespace Router { - export { Router as default }; -} diff --git a/types/plugins/signals.d.ts b/types/plugins/signals.d.ts deleted file mode 100644 index 2fe971f..0000000 --- a/types/plugins/signals.d.ts +++ /dev/null @@ -1,5 +0,0 @@ -export = Signal; -declare function Signal(value: any, key: any): any; -declare namespace Signal { - export { Signal as default }; -} diff --git a/types/plugins/store.d.ts b/types/plugins/store.d.ts deleted file mode 100644 index a2278ac..0000000 --- a/types/plugins/store.d.ts +++ /dev/null @@ -1,22 +0,0 @@ -export = Store; -declare function Store({ state, getters, actions, mutations }?: { - state?: {} | undefined; - getters?: {} | undefined; - actions?: {} | undefined; - mutations?: {} | undefined; -}): void; -declare class Store { - constructor({ state, getters, actions, mutations }?: { - state?: {} | undefined; - getters?: {} | undefined; - actions?: {} | undefined; - mutations?: {} | undefined; - }); - state: any; - getters: any; - commit: (mutation: any, ...args: any[]) => void; - dispatch: (action: any, ...args: any[]) => Promise; -} -declare namespace Store { - export { Store as default }; -} diff --git a/types/plugins/sw.d.ts b/types/plugins/sw.d.ts deleted file mode 100644 index a7a00b3..0000000 --- a/types/plugins/sw.d.ts +++ /dev/null @@ -1,14 +0,0 @@ -export = Sw; -declare class Sw { - constructor(file: any, options: any); - file: string; - options: { - scope: string; - }; - ready: boolean; - sw: null; - register(): Promise; -} -declare namespace Sw { - export { Sw as default }; -} diff --git a/types/plugins/utils/tree-adapter.d.ts b/types/plugins/utils/tree-adapter.d.ts deleted file mode 100644 index 810a447..0000000 --- a/types/plugins/utils/tree-adapter.d.ts +++ /dev/null @@ -1 +0,0 @@ -export { TreeAdapter as default }; From 342faa488ecfc4dbe4b76e77863c8f675e754329 Mon Sep 17 00:00:00 2001 From: Masquerade Circus Date: Wed, 16 Feb 2022 20:13:36 -0600 Subject: [PATCH 07/19] Update eslint and interfaces --- .eslintrc | 2 +- lib/interfaces.ts | 13 +++++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/.eslintrc b/.eslintrc index 2723f19..93f1df6 100644 --- a/.eslintrc +++ b/.eslintrc @@ -67,7 +67,7 @@ "es6": true }, "parserOptions": { - "ecmaVersion": 9, + "ecmaVersion": "latest", "sourceType": "module", "ecmaFeatures": { "jsx": true, diff --git a/lib/interfaces.ts b/lib/interfaces.ts index 465e668..597f5d9 100644 --- a/lib/interfaces.ts +++ b/lib/interfaces.ts @@ -98,3 +98,16 @@ export interface Valyrian { reservedProps: ReservedProps; [key: string | number | symbol]: any; } + +declare global { + namespace JSX { + type Element = IVnode; + interface IntrinsicElements { + [elemName: string]: any; + } + } +} + +interface HTMLAttributes { + [key: string]: any; +} From 1eab8cf11ad57827a7cb085f6860735268b1470a Mon Sep 17 00:00:00 2001 From: Masquerade Circus Date: Thu, 17 Feb 2022 05:30:57 -0600 Subject: [PATCH 08/19] Updated --- bench/.buffalo-test.json | 484 +++++++++ bench/mount_n_update_bench.js | 7 +- dist/@types/lib/index.d.ts | 15 +- dist/@types/lib/interfaces.d.ts | 26 + dist/index.cjs | 60 +- dist/index.js | 60 +- dist/index.min.js | 2 +- dist/index.min.js.map | 2 +- lib/index.ts | 78 +- lib/interfaces.ts | 25 + package.json | 38 +- plugins/hooks.js | 13 +- plugins/node.js | 39 +- plugins/router.js | 87 +- plugins/store.js | 19 +- test/directives_test.js | 101 +- test/hooks_test.js | 94 +- test/hyperscript_test.js | 4 +- test/keyed_test.js | 19 +- test/lifecycle_test.js | 17 +- test/mount_n_update_test.js | 69 +- test/node_test.js | 7 +- test/request_test.js | 2 +- test/router_test.js | 40 +- test/signals_test.js | 16 +- test/store_test.js | 4 +- yarn.lock | 1675 ++++++++++++++++--------------- 27 files changed, 1836 insertions(+), 1167 deletions(-) diff --git a/bench/.buffalo-test.json b/bench/.buffalo-test.json index e69de29..2941bf0 100644 --- a/bench/.buffalo-test.json +++ b/bench/.buffalo-test.json @@ -0,0 +1,484 @@ +[ + { + "tag": "342faa488ecfc4dbe4b76e77863c8f675e754329", + "timestamp": "2022-02-17T11:07:35.317Z", + "suites": { + "Matching keyed list": { + "Removed at the end": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "Matching keyed list -> stress": { + "Removed at the end": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "hyperscript": { + "Valyrian 5.0.8": { + "hz": 1085513.3179712752, + "meanTime": 0.000921223151705691, + "medianTime": 0.0008530020713806152, + "standardDeviation": 0.019500465849231124, + "maxTime": 30.582818999886513, + "minTime": 0.0007930099964141846 + }, + "Valyrian next": { + "hz": 15794164.980239976, + "meanTime": 0.00006331452161295621, + "medianTime": 0.00005599856376647949, + "standardDeviation": 0.00031702862230284404, + "maxTime": 0.29975299537181854, + "minTime": 0.000048995018005371094 + } + }, + "Set.has vs [].indexOf": { + "Set.has": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "[].indexOf": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "Object.keys for loop vs Object.keys for of vs for in": { + "Object.keys for loop": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "Object.keys for of": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "for in": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "typeof function vs startsWith vs charAt vs string[0]": { + "typeof function": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "startsWith": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "charAt": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "string[0]": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "Array.isArray vs typeof object & Array.isArray": { + "Array.isArray": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "typeof object & Array.isArray": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "string comparison vs instance comparison vs property comparison": { + "string comparison": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "instance comparison": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "property comparison": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "property string comparison": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "typeof comparison": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "Object with property equals true vs set vs map vs string array": { + "Object with property equals true": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "key in object": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "set": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "map": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "string array": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "For loop if/continue vs if/else": { + "for loop if/continue": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "for loop if/else": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "map array of strings vs reduce with object keys equals index": { + "map array of strings": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "reduce with object keys equals index": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "array by for": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "object by for": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "object map by for": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "Symbol access vs direct access": { + "Direct access access": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "Symbol access access": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "Mount and update: Mount multiple types": { + "Valyrian 5.0.8": { + "hz": 260.633209072662, + "meanTime": 3.83680960518431, + "medianTime": 3.3641090095043182, + "standardDeviation": 0.8308150696566404, + "maxTime": 15.718204006552696, + "minTime": 3.1520179957151413 + }, + "Valyrian next": { + "hz": 222.65166867343356, + "meanTime": 4.4913204826087085, + "medianTime": 3.889599993824959, + "standardDeviation": 1.058344812867983, + "maxTime": 16.027059003710747, + "minTime": 3.5659329891204834 + } + }, + "Mount and update: Mount single text": { + "Valyrian 5.0.8": { + "hz": 347427.4290566243, + "meanTime": 0.00287829893775318, + "medianTime": 0.002673998475074768, + "standardDeviation": 0.006783133364727264, + "maxTime": 1.7252160012722015, + "minTime": 0.0024939924478530884 + }, + "Valyrian next": { + "hz": 1223910.384040943, + "meanTime": 0.0008170532851419515, + "medianTime": 0.0007089972496032715, + "standardDeviation": 0.0044411061831852415, + "maxTime": 1.6371040046215057, + "minTime": 0.0005789995193481445 + } + }, + "Mount and update: Mount single text in div": { + "Valyrian 5.0.8": { + "hz": 244343.36900502432, + "meanTime": 0.0040926013424143195, + "medianTime": 0.003850996494293213, + "standardDeviation": 0.005545521371988312, + "maxTime": 0.6497730016708374, + "minTime": 0.003649994730949402 + }, + "Valyrian next": { + "hz": 688361.7972213569, + "meanTime": 0.001452724430723208, + "medianTime": 0.0012419968843460083, + "standardDeviation": 0.007049924359907374, + "maxTime": 0.8489640057086945, + "minTime": 0.0010669976472854614 + } + }, + "Mount and update: Update multiple types": { + "Valyrian 5.0.8": { + "hz": 147.96662836834977, + "meanTime": 6.758280640892815, + "medianTime": 6.411444008350372, + "standardDeviation": 0.9741160663847195, + "maxTime": 24.285806000232697, + "minTime": 6.045272007584572 + }, + "Valyrian next": { + "hz": 88.94506469757148, + "meanTime": 11.242894739580796, + "medianTime": 10.90294100344181, + "standardDeviation": 1.1068453900004576, + "maxTime": 26.234234005212784, + "minTime": 10.178460001945496 + } + }, + "Mount and update: Update single text": { + "Valyrian 5.0.8": { + "hz": 121862.49891824297, + "meanTime": 0.008205969915904119, + "medianTime": 0.007762998342514038, + "standardDeviation": 0.009811824354673024, + "maxTime": 2.545636996626854, + "minTime": 0.007499009370803833 + }, + "Valyrian next": { + "hz": 602961.8000913017, + "meanTime": 0.0016584798570134594, + "medianTime": 0.001458004117012024, + "standardDeviation": 0.006942679619133388, + "maxTime": 1.9876960068941116, + "minTime": 0.0013519972562789917 + } + }, + "Mount and update: Render list": { + "vOld": { + "hz": 8595.287795706112, + "meanTime": 0.1163428175726196, + "medianTime": 0.11025500297546387, + "standardDeviation": 0.03396247127309931, + "maxTime": 2.3573189973831177, + "minTime": 0.10783299803733826 + }, + "VNext": { + "hz": 32325.596447472642, + "meanTime": 0.030935237393838848, + "medianTime": 0.027564987540245056, + "standardDeviation": 0.03658583480612852, + "maxTime": 2.6248089969158173, + "minTime": 0.024625003337860107 + } + }, + "Mount and update: Render keyed list": { + "vOld": { + "hz": 3504.474806096515, + "meanTime": 0.28534946185384547, + "medianTime": 0.27035000920295715, + "standardDeviation": 0.0721601162287672, + "maxTime": 4.122464999556541, + "minTime": 0.2602820098400116 + }, + "VNext": { + "hz": 9998.200945039185, + "meanTime": 0.1000179937867893, + "medianTime": 0.08610399067401886, + "standardDeviation": 0.10939394451753234, + "maxTime": 19.21594300866127, + "minTime": 0.07930800318717957 + } + }, + "Mount and update: Render keyed list -> stress": { + "vOld": { + "hz": 1855.192833444841, + "meanTime": 0.5390275242402354, + "medianTime": 0.5236269980669022, + "standardDeviation": 0.08498791322802589, + "maxTime": 2.095083996653557, + "minTime": 0.4774570018053055 + }, + "VNext": { + "hz": 5438.111021666333, + "meanTime": 0.18388738222074444, + "medianTime": 0.16006000339984894, + "standardDeviation": 0.13763924133347213, + "maxTime": 10.381516993045807, + "minTime": 0.15018099546432495 + } + }, + "Mount and update: Render keyed list -> swap keys on large set": { + "vOld": { + "hz": 328.8444144098936, + "meanTime": 3.0409517576708276, + "medianTime": 2.869830995798111, + "standardDeviation": 0.650294589183712, + "maxTime": 17.199512004852295, + "minTime": 2.7187130004167557 + }, + "VNext": { + "hz": 856.8353339507644, + "meanTime": 1.16708539012872, + "medianTime": 0.9925249963998795, + "standardDeviation": 0.6296643229410056, + "maxTime": 17.963095992803574, + "minTime": 0.8711500018835068 + } + }, + "Lifecycle vs hooks": { + "Hooks": { + "hz": 370117.74095190957, + "meanTime": 0.002701842925519025, + "medianTime": 0.0024130046367645264, + "standardDeviation": 0.00803690626128436, + "maxTime": 4.156716004014015, + "minTime": 0.0020949989557266235 + }, + "Lifecycle": { + "hz": 392517.0967079169, + "meanTime": 0.0025476597284222967, + "medianTime": 0.002181008458137512, + "standardDeviation": 0.010177234514366527, + "maxTime": 1.0994060039520264, + "minTime": 0.001976996660232544 + } + } + } + } +] \ No newline at end of file diff --git a/bench/mount_n_update_bench.js b/bench/mount_n_update_bench.js index 1711f34..ea48204 100644 --- a/bench/mount_n_update_bench.js +++ b/bench/mount_n_update_bench.js @@ -1,11 +1,14 @@ let { compare, benchmark, before, afterCycle } = require("buffalo-test"); -const { mount, update, unmount, v } = require("../lib/index"); +const { mount, update, unmount, v, use } = require("../lib/index"); const expect = require("expect"); require("../plugins/node"); const { v: vOld } = require("./index-old.ts"); -const { useEffect } = require("../plugins/hooks"); +const plugin = require("../plugins/hooks"); + +use(plugin); +const useEffect = plugin.useEffect; console.log(vOld); diff --git a/dist/@types/lib/index.d.ts b/dist/@types/lib/index.d.ts index d007ac5..1a121c3 100644 --- a/dist/@types/lib/index.d.ts +++ b/dist/@types/lib/index.d.ts @@ -1,17 +1,18 @@ -import { Directive, DomElement, IVnode, Valyrian, ValyrianComponent, VnodeComponent, VnodeWithDom } from "./interfaces"; +import { Directive, DomElement, IVnode, Plugin, Valyrian, ValyrianComponent, VnodeComponent, VnodeWithDom } from "./interfaces"; export declare const Vnode: IVnode; -export declare function isVnode(component?: unknown): component is IVnode; +export declare function isVnode(object?: unknown | IVnode): object is IVnode; export declare function isComponent(component?: unknown | ValyrianComponent): component is ValyrianComponent; -export declare function isVnodeComponent(vnode?: unknown): vnode is VnodeComponent; +export declare function isVnodeComponent(vnode?: unknown | VnodeComponent): vnode is VnodeComponent; export declare const isNodeJs: boolean; export declare const trust: (htmlString: string) => IVnode[]; export declare function onCleanup(callback: Function): void; export declare function onUnmount(callback: Function): void; export declare function onMount(callback: Function): void; export declare function onUpdate(callback: Function): void; -export declare function mount(container: DomElement | string, component: ValyrianComponent | IVnode): any; -export declare function update(component?: ValyrianComponent | IVnode): any; -export declare function unmount(component?: ValyrianComponent | IVnode): string | undefined; -export declare function setProperty(name: string, value: any, vnode: VnodeWithDom, oldVnode?: VnodeWithDom): void; +export declare function mount(container: DomElement | string, component: ValyrianComponent | IVnode): void | string; +export declare function update(component?: ValyrianComponent | IVnode): void | string; +export declare function unmount(component?: ValyrianComponent | IVnode): void | string; +export declare function setAttribute(name: string, value: any, vnode: VnodeWithDom, oldVnode?: VnodeWithDom): void; export declare function directive(name: string, directive: Directive): void; +export declare function use(plugin: Plugin, options?: Record): void | any; export declare const v: Valyrian; diff --git a/dist/@types/lib/interfaces.d.ts b/dist/@types/lib/interfaces.d.ts index 4a56018..4c92e5d 100644 --- a/dist/@types/lib/interfaces.d.ts +++ b/dist/@types/lib/interfaces.d.ts @@ -80,11 +80,37 @@ export interface Directives { export interface ReservedProps { [key: string]: true; } +export interface Plugin { + (valyrian: Valyrian, options?: Record): void | any; +} export interface Valyrian { (tagOrComponent: string | ValyrianComponent, props: Props, ...children: Children): IVnode | VnodeComponent; fragment: (props: Props, ...children: Children) => Children; current: Current; directives: Directives; reservedProps: ReservedProps; + isVnode: (object?: unknown | IVnode) => object is IVnode; + isComponent: (component?: unknown | ValyrianComponent) => component is ValyrianComponent; + isVnodeComponent: (vnode?: unknown | VnodeComponent) => vnode is VnodeComponent; + isNodeJs: boolean; + trust: (htmlString: string) => IVnode[]; + onCleanup: (fn: Function) => void; + onUnmount: (fn: Function) => void; + onMount: (fn: Function) => void; + onUpdate: (fn: Function) => void; + mount: (container: DomElement | string, component: ValyrianComponent | IVnode) => void | string; + update: (component: ValyrianComponent | IVnode) => void | string; + unmount: (component: ValyrianComponent | IVnode) => void | string; + setAttribute: (name: string, value: any, vnode: VnodeWithDom, oldVnode?: VnodeWithDom) => void; + directive: (name: string, directive: Directive) => void; + use: (plugin: Plugin, options?: Record) => void | any; [key: string | number | symbol]: any; } +declare global { + namespace JSX { + type Element = IVnode; + interface IntrinsicElements { + [elemName: string]: any; + } + } +} diff --git a/dist/index.cjs b/dist/index.cjs index 96e0f5f..0ce4e6a 100644 --- a/dist/index.cjs +++ b/dist/index.cjs @@ -35,10 +35,11 @@ __export(lib_exports, { onMount: () => onMount, onUnmount: () => onUnmount, onUpdate: () => onUpdate, - setProperty: () => setProperty, + setAttribute: () => setAttribute, trust: () => trust, unmount: () => unmount, update: () => update, + use: () => use, v: () => v }); var Vnode = function Vnode2(tag, props, children) { @@ -46,8 +47,8 @@ var Vnode = function Vnode2(tag, props, children) { this.children = children; this.tag = tag; }; -function isVnode(component) { - return component instanceof Vnode; +function isVnode(object) { + return object instanceof Vnode; } function isComponent(component) { return typeof component === "function" || typeof component === "object" && component !== null && "view" in component; @@ -224,7 +225,7 @@ function onremove(vnode) { } vnode.props.onremove && vnode.props.onremove(vnode); } -function sharedUpdateProperty(prop, value, vnode, oldVnode) { +function sharedSetAttribute(prop, value, vnode, oldVnode) { if (v.reservedProps[prop]) { if (v.directives[prop]) { v.directives[prop](vnode.props[prop], vnode, oldVnode); @@ -254,18 +255,18 @@ function sharedUpdateProperty(prop, value, vnode, oldVnode) { } } } -function setProperty(name, value, vnode, oldVnode) { +function setAttribute(name, value, vnode, oldVnode) { if (name in vnode.props === false) { vnode.props[name] = value; } - sharedUpdateProperty(name, value, vnode, oldVnode); + sharedSetAttribute(name, value, vnode, oldVnode); } -function updateProperties(vnode, oldVnode) { +function updateAttributes(vnode, oldVnode) { for (let prop in vnode.props) { if (prop in vnode.props === false) { return; } - sharedUpdateProperty(prop, vnode.props[prop], vnode, oldVnode); + sharedSetAttribute(prop, vnode.props[prop], vnode, oldVnode); } if (oldVnode) { for (let prop in oldVnode.props) { @@ -328,7 +329,7 @@ function patchKeyedTree(newVnode, newTree, oldTree, newTreeLength, oldTreeLength childVnode.children = oldChildVnode.children; shouldPatch = false; } else { - updateProperties(childVnode, oldChildVnode); + updateAttributes(childVnode, oldChildVnode); if (valyrianApp.isMounted) { childVnode.props.onupdate && childVnode.props.onupdate(childVnode, oldChildVnode); } else { @@ -337,7 +338,7 @@ function patchKeyedTree(newVnode, newTree, oldTree, newTreeLength, oldTreeLength } } else { childVnode.dom = createDomElement(childVnode.tag, childVnode.isSVG); - updateProperties(childVnode); + updateAttributes(childVnode); childVnode.props.oncreate && childVnode.props.oncreate(childVnode); } if (newVnode.dom.childNodes[i] === void 0) { @@ -367,7 +368,7 @@ function patchNormalTree(newVnode, newTree, oldTree, newTreeLength, oldTreeLengt continue; } newChildVnode.dom = createDomElement(newChildVnode.tag, newChildVnode.isSVG); - updateProperties(newChildVnode); + updateAttributes(newChildVnode); newVnode.dom.appendChild(newChildVnode.dom); newChildVnode.props.oncreate && newChildVnode.props.oncreate(newChildVnode); patch(newChildVnode, void 0, valyrianApp); @@ -392,7 +393,7 @@ function patchNormalTree(newVnode, newTree, oldTree, newTreeLength, oldTreeLengt newChildVnode.children = oldChildVnode.children; continue; } - updateProperties(newChildVnode, oldChildVnode); + updateAttributes(newChildVnode, oldChildVnode); if (valyrianApp && valyrianApp.isMounted) { newChildVnode.props.onupdate && newChildVnode.props.onupdate(newChildVnode, oldChildVnode); } else { @@ -402,7 +403,7 @@ function patchNormalTree(newVnode, newTree, oldTree, newTreeLength, oldTreeLengt continue; } newChildVnode.dom = createDomElement(newChildVnode.tag, newChildVnode.isSVG); - updateProperties(newChildVnode); + updateAttributes(newChildVnode); if (oldChildVnode.tag !== "#text") { onremove(oldChildVnode); } @@ -508,15 +509,15 @@ var builtInDirectives = { handler = () => model[property] = !model[property]; value = model[property]; } - setProperty("checked", value, vnode, oldVnode); + setAttribute("checked", value, vnode, oldVnode); break; } case "radio": { - setProperty("checked", model[property] === vnode.dom.value, vnode, oldVnode); + setAttribute("checked", model[property] === vnode.dom.value, vnode, oldVnode); break; } default: { - setProperty("value", model[property], vnode, oldVnode); + setAttribute("value", model[property], vnode, oldVnode); } } } else if (vnode.name === "select") { @@ -558,10 +559,19 @@ var builtInDirectives = { if (!handler) { handler = (e) => model[property] = e.target.value; } - setProperty(event, handler, vnode, oldVnode); + setAttribute(event, handler, vnode, oldVnode); } } }; +var plugins = /* @__PURE__ */ new Map(); +function use(plugin, options) { + if (plugins.has(plugin)) { + return plugins.get(plugin); + } + let result = plugin(v, options); + plugins.set(plugin, result); + return result; +} var v = function v2(tagOrComponent, props, ...children) { if (typeof tagOrComponent === "string") { return new Vnode(tagOrComponent, props || {}, children); @@ -591,5 +601,19 @@ v.reservedProps = { "v-class": true, "v-html": true }; -(isNodeJs ? global : window).v = v; +v.isVnode = isVnode; +v.isComponent = isComponent; +v.isVnodeComponent = isVnodeComponent; +v.isNodeJs = isNodeJs; +v.trust = trust; +v.onCleanup = onCleanup; +v.onUnmount = onUnmount; +v.onMount = onMount; +v.onUpdate = onUpdate; +v.mount = mount; +v.unmount = unmount; +v.update = update; +v.setAttribute = setAttribute; +v.directive = directive; +v.use = use; module.exports = __toCommonJS(lib_exports); diff --git a/dist/index.js b/dist/index.js index 6853b28..f204653 100644 --- a/dist/index.js +++ b/dist/index.js @@ -4,8 +4,8 @@ var Vnode = function Vnode2(tag, props, children) { this.children = children; this.tag = tag; }; -function isVnode(component) { - return component instanceof Vnode; +function isVnode(object) { + return object instanceof Vnode; } function isComponent(component) { return typeof component === "function" || typeof component === "object" && component !== null && "view" in component; @@ -182,7 +182,7 @@ function onremove(vnode) { } vnode.props.onremove && vnode.props.onremove(vnode); } -function sharedUpdateProperty(prop, value, vnode, oldVnode) { +function sharedSetAttribute(prop, value, vnode, oldVnode) { if (v.reservedProps[prop]) { if (v.directives[prop]) { v.directives[prop](vnode.props[prop], vnode, oldVnode); @@ -212,18 +212,18 @@ function sharedUpdateProperty(prop, value, vnode, oldVnode) { } } } -function setProperty(name, value, vnode, oldVnode) { +function setAttribute(name, value, vnode, oldVnode) { if (name in vnode.props === false) { vnode.props[name] = value; } - sharedUpdateProperty(name, value, vnode, oldVnode); + sharedSetAttribute(name, value, vnode, oldVnode); } -function updateProperties(vnode, oldVnode) { +function updateAttributes(vnode, oldVnode) { for (let prop in vnode.props) { if (prop in vnode.props === false) { return; } - sharedUpdateProperty(prop, vnode.props[prop], vnode, oldVnode); + sharedSetAttribute(prop, vnode.props[prop], vnode, oldVnode); } if (oldVnode) { for (let prop in oldVnode.props) { @@ -286,7 +286,7 @@ function patchKeyedTree(newVnode, newTree, oldTree, newTreeLength, oldTreeLength childVnode.children = oldChildVnode.children; shouldPatch = false; } else { - updateProperties(childVnode, oldChildVnode); + updateAttributes(childVnode, oldChildVnode); if (valyrianApp.isMounted) { childVnode.props.onupdate && childVnode.props.onupdate(childVnode, oldChildVnode); } else { @@ -295,7 +295,7 @@ function patchKeyedTree(newVnode, newTree, oldTree, newTreeLength, oldTreeLength } } else { childVnode.dom = createDomElement(childVnode.tag, childVnode.isSVG); - updateProperties(childVnode); + updateAttributes(childVnode); childVnode.props.oncreate && childVnode.props.oncreate(childVnode); } if (newVnode.dom.childNodes[i] === void 0) { @@ -325,7 +325,7 @@ function patchNormalTree(newVnode, newTree, oldTree, newTreeLength, oldTreeLengt continue; } newChildVnode.dom = createDomElement(newChildVnode.tag, newChildVnode.isSVG); - updateProperties(newChildVnode); + updateAttributes(newChildVnode); newVnode.dom.appendChild(newChildVnode.dom); newChildVnode.props.oncreate && newChildVnode.props.oncreate(newChildVnode); patch(newChildVnode, void 0, valyrianApp); @@ -350,7 +350,7 @@ function patchNormalTree(newVnode, newTree, oldTree, newTreeLength, oldTreeLengt newChildVnode.children = oldChildVnode.children; continue; } - updateProperties(newChildVnode, oldChildVnode); + updateAttributes(newChildVnode, oldChildVnode); if (valyrianApp && valyrianApp.isMounted) { newChildVnode.props.onupdate && newChildVnode.props.onupdate(newChildVnode, oldChildVnode); } else { @@ -360,7 +360,7 @@ function patchNormalTree(newVnode, newTree, oldTree, newTreeLength, oldTreeLengt continue; } newChildVnode.dom = createDomElement(newChildVnode.tag, newChildVnode.isSVG); - updateProperties(newChildVnode); + updateAttributes(newChildVnode); if (oldChildVnode.tag !== "#text") { onremove(oldChildVnode); } @@ -466,15 +466,15 @@ var builtInDirectives = { handler = () => model[property] = !model[property]; value = model[property]; } - setProperty("checked", value, vnode, oldVnode); + setAttribute("checked", value, vnode, oldVnode); break; } case "radio": { - setProperty("checked", model[property] === vnode.dom.value, vnode, oldVnode); + setAttribute("checked", model[property] === vnode.dom.value, vnode, oldVnode); break; } default: { - setProperty("value", model[property], vnode, oldVnode); + setAttribute("value", model[property], vnode, oldVnode); } } } else if (vnode.name === "select") { @@ -516,10 +516,19 @@ var builtInDirectives = { if (!handler) { handler = (e) => model[property] = e.target.value; } - setProperty(event, handler, vnode, oldVnode); + setAttribute(event, handler, vnode, oldVnode); } } }; +var plugins = /* @__PURE__ */ new Map(); +function use(plugin, options) { + if (plugins.has(plugin)) { + return plugins.get(plugin); + } + let result = plugin(v, options); + plugins.set(plugin, result); + return result; +} var v = function v2(tagOrComponent, props, ...children) { if (typeof tagOrComponent === "string") { return new Vnode(tagOrComponent, props || {}, children); @@ -549,7 +558,21 @@ v.reservedProps = { "v-class": true, "v-html": true }; -(isNodeJs ? global : window).v = v; +v.isVnode = isVnode; +v.isComponent = isComponent; +v.isVnodeComponent = isVnodeComponent; +v.isNodeJs = isNodeJs; +v.trust = trust; +v.onCleanup = onCleanup; +v.onUnmount = onUnmount; +v.onMount = onMount; +v.onUpdate = onUpdate; +v.mount = mount; +v.unmount = unmount; +v.update = update; +v.setAttribute = setAttribute; +v.directive = directive; +v.use = use; export { Vnode, directive, @@ -562,9 +585,10 @@ export { onMount, onUnmount, onUpdate, - setProperty, + setAttribute, trust, unmount, update, + use, v }; diff --git a/dist/index.min.js b/dist/index.min.js index 44fd03e..91d167e 100644 --- a/dist/index.min.js +++ b/dist/index.min.js @@ -1 +1 @@ -(()=>{var e=function(e,n,o){this.props=n,this.children=o,this.tag=e};function n(e){return"function"==typeof e||"object"==typeof e&&null!==e&&"view"in e}function o(n){return n instanceof e&&"__component__"===n.tag}var t=Boolean("undefined"!=typeof process&&process.versions&&process.versions.node);function r(e,n=!1){return n?document.createElementNS("http://www.w3.org/2000/svg",e):document.createElement(e)}function i(n){let o=y(n.tagName.toLowerCase(),{},...Array.from(n.childNodes).filter(e=>1===e.nodeType||3===e.nodeType).map(n=>{if(1===n.nodeType)return i(n);let o=new e("#text",{},[]);return o.nodeValue=String(n.nodeValue),o.dom=n,o}));return[].forEach.call(n.attributes,e=>o.props[e.nodeName]=e.nodeValue),o.dom=n,o}var p=e=>{let n=r("div");return n.innerHTML=e.trim(),[].map.call(n.childNodes,e=>i(e))},d=Symbol("Valyrian");function l(e){for(let n=0;n0&&"#text"===o[t-1].tag?(o[t-1].nodeValue+=r,o.splice(t--,1)):(o[t]=new e("#text",{},[]),o[t].nodeValue=String(r))}}(n);let i=n.children,p=o.children,d=p.length,l=i.length;if(0!==l)d&&"key"in i[0].props&&"key"in p[0].props?function(e,n,o,t,i,p){let d=o.reduce((e,n,o)=>(e[n.props.key]=o,e),{}),l=n.reduce((e,n,o)=>(e[n.props.key]=o,e),{});for(let i=0;i{if(e?n:!n){let e=document.createTextNode("");t&&t.dom&&t.dom.parentNode&&("#text"!==t.tag&&c(t),t.dom.parentNode.replaceChild(e,t.dom)),o.tag="#text",o.children=[],o.props={},o.dom=e}}}var V={"v-if":g(!1),"v-unless":g(!0),"v-for":(e,n)=>{n.children=e.map(n.children[0])},"v-show":(e,n)=>{n.dom.style.display=e?"":"none"},"v-class":(e,n)=>{for(let o in e)n.dom.classList.toggle(o,e[o])},"v-html":(e,n)=>{n.children=[p(e)]},"v-model":([e,n,o],t,r)=>{let i,p;if("input"===t.name)switch(o=o||"oninput",t.props.type){case"checkbox":Array.isArray(e[n])?(p=o=>{let t=o.target.value,r=e[n].indexOf(t);-1===r?e[n].push(t):e[n].splice(r,1)},i=-1!==e[n].indexOf(t.dom.value)):"value"in t.props?(p=()=>{e[n]===t.props.value?e[n]=null:e[n]=t.props.value},i=e[n]===t.props.value):(p=()=>e[n]=!e[n],i=e[n]),f("checked",i,t,r);break;case"radio":f("checked",e[n]===t.dom.value,t,r);break;default:f("value",e[n],t,r)}else"select"===t.name?(o=o||"onclick",t.props.multiple?(p=o=>{let t=o.target.value;if(o.ctrlKey){let o=e[n].indexOf(t);-1===o?e[n].push(t):e[n].splice(o,1)}else e[n].splice(0,e[n].length),e[n].push(t)},t.children.forEach(o=>{if("option"===o.name){let t="value"in o.props?o.props.value:o.children.join("").trim();o.props.selected=-1!==e[n].indexOf(t)}})):t.children.forEach(o=>{if("option"===o.name){let t="value"in o.props?o.props.value:o.children.join("").trim();o.props.selected=t===e[n]}})):"textarea"===t.name&&(o=o||"oninput",t.children=[e[n]]);t.props[o]||(p||(p=o=>e[n]=o.target.value),f(o,p,t,r))}},y=function(n,o,...t){if("string"==typeof n)return new e(n,o||{},t);const r=new e("__component__",o||{},t);return r.component=n,r};y.fragment=(e,...n)=>n,y.current={},y.directives={...V},y.reservedProps={key:!0,state:!0,oncreate:!0,onupdate:!0,onremove:!0,shouldupdate:!0,"v-cleanup":!0,"v-once":!0,"v-if":!0,"v-unless":!0,"v-for":!0,"v-show":!0,"v-class":!0,"v-html":!0},(t?global:window).v=y;var x={Vnode:e,directive:function(e,n){let o=`v-${e}`;y.directives[o]=n,y.reservedProps[o]=!0},isComponent:n,isNodeJs:t,isVnode:function(n){return n instanceof e},isVnodeComponent:o,mount:function(e,p){let l,u=null;if(u=t?"string"==typeof e?r("svg"===e?"svg":"div","svg"===e):e:"string"==typeof e?document.querySelectorAll(e)[0]:e,!u)throw new Error("Container not found");if(o(p))l=p;else{if(!n(p))throw new Error("Component must be a Valyrian Component or a Vnode component");l=y(p,{})}if(p[d])s(p);else{let e=function(e){let n=e.target,o=`v-on${e.type}`;for(;n;){if(n[o])return n[o](e,n),void(e.defaultPrevented||a(p));n=n.parentNode}};p[d]={isMounted:!1,eventListenerNames:{},onCleanup:[],onMount:[],onUpdate:[],onUnmount:[]},p[d].eventListener=e}return p[d].component=l,p[d].container=u,p[d].mainVnode=i(u),p[d].mainVnode.isSVG="svg"===p[d].tag,a(p)},onCleanup:function(e){-1===y.current.app?.onCleanup.indexOf(e)&&y.current.app?.onCleanup.push(e)},onMount:function(e){-1===y.current.app?.onMount.indexOf(e)&&y.current.app?.onMount.push(e)},onUnmount:function(e){-1===y.current.app?.onUnmount.indexOf(e)&&y.current.app?.onUnmount.push(e)},onUpdate:function(e){-1===y.current.app?.onUpdate.indexOf(e)&&y.current.app?.onUpdate.push(e)},setProperty:f,trust:p,unmount:s,update:a,v:y};"undefined"!=typeof module?module.exports=x:self.Valyrian=x})(); \ No newline at end of file +(()=>{var e=function(e,n,o){this.props=n,this.children=o,this.tag=e};function n(n){return n instanceof e}function o(e){return"function"==typeof e||"object"==typeof e&&null!==e&&"view"in e}function t(n){return n instanceof e&&"__component__"===n.tag}var r=Boolean("undefined"!=typeof process&&process.versions&&process.versions.node);function i(e,n=!1){return n?document.createElementNS("http://www.w3.org/2000/svg",e):document.createElement(e)}function p(n){let o=k(n.tagName.toLowerCase(),{},...Array.from(n.childNodes).filter(e=>1===e.nodeType||3===e.nodeType).map(n=>{if(1===n.nodeType)return p(n);let o=new e("#text",{},[]);return o.nodeValue=String(n.nodeValue),o.dom=n,o}));return[].forEach.call(n.attributes,e=>o.props[e.nodeName]=e.nodeValue),o.dom=n,o}var d=e=>{let n=i("div");return n.innerHTML=e.trim(),[].map.call(n.childNodes,e=>p(e))},l=Symbol("Valyrian");function a(e){-1===k.current.app?.onCleanup.indexOf(e)&&k.current.app?.onCleanup.push(e)}function s(e){-1===k.current.app?.onUnmount.indexOf(e)&&k.current.app?.onUnmount.push(e)}function u(e){-1===k.current.app?.onMount.indexOf(e)&&k.current.app?.onMount.push(e)}function c(e){-1===k.current.app?.onUpdate.indexOf(e)&&k.current.app?.onUpdate.push(e)}function m(e,n){let d,a=null;if(a=r?"string"==typeof e?i("svg"===e?"svg":"div","svg"===e):e:"string"==typeof e?document.querySelectorAll(e)[0]:e,!a)throw new Error("Container not found");if(t(n))d=n;else{if(!o(n))throw new Error("Component must be a Valyrian Component or a Vnode component");d=k(n,{})}if(n[l])h(n);else{let e=function(e){let o=e.target,t=`v-on${e.type}`;for(;o;){if(o[t])return o[t](e,o),void(e.defaultPrevented||v(n));o=o.parentNode}};n[l]={isMounted:!1,eventListenerNames:{},onCleanup:[],onMount:[],onUpdate:[],onUnmount:[]},n[l].eventListener=e}return n[l].component=d,n[l].container=a,n[l].mainVnode=p(a),n[l].mainVnode.isSVG="svg"===n[l].tag,v(n)}function f(e){for(let n=0;n0&&"#text"===o[t-1].tag?(o[t-1].nodeValue+=r,o.splice(t--,1)):(o[t]=new e("#text",{},[]),o[t].nodeValue=String(r))}}(n);let r=n.children,p=o.children,d=p.length,l=r.length;if(0!==l)d&&"key"in r[0].props&&"key"in p[0].props?function(e,n,o,t,r,p){let d=o.reduce((e,n,o)=>(e[n.props.key]=o,e),{}),l=n.reduce((e,n,o)=>(e[n.props.key]=o,e),{});for(let r=0;r{if(e?n:!n){let e=document.createTextNode("");t&&t.dom&&t.dom.parentNode&&("#text"!==t.tag&&V(t),t.dom.parentNode.replaceChild(e,t.dom)),o.tag="#text",o.children=[],o.props={},o.dom=e}}}var U={"v-if":M(!1),"v-unless":M(!0),"v-for":(e,n)=>{n.children=e.map(n.children[0])},"v-show":(e,n)=>{n.dom.style.display=e?"":"none"},"v-class":(e,n)=>{for(let o in e)n.dom.classList.toggle(o,e[o])},"v-html":(e,n)=>{n.children=[d(e)]},"v-model":([e,n,o],t,r)=>{let i,p;if("input"===t.name)switch(o=o||"oninput",t.props.type){case"checkbox":Array.isArray(e[n])?(p=o=>{let t=o.target.value,r=e[n].indexOf(t);-1===r?e[n].push(t):e[n].splice(r,1)},i=-1!==e[n].indexOf(t.dom.value)):"value"in t.props?(p=()=>{e[n]===t.props.value?e[n]=null:e[n]=t.props.value},i=e[n]===t.props.value):(p=()=>e[n]=!e[n],i=e[n]),C("checked",i,t,r);break;case"radio":C("checked",e[n]===t.dom.value,t,r);break;default:C("value",e[n],t,r)}else"select"===t.name?(o=o||"onclick",t.props.multiple?(p=o=>{let t=o.target.value;if(o.ctrlKey){let o=e[n].indexOf(t);-1===o?e[n].push(t):e[n].splice(o,1)}else e[n].splice(0,e[n].length),e[n].push(t)},t.children.forEach(o=>{if("option"===o.name){let t="value"in o.props?o.props.value:o.children.join("").trim();o.props.selected=-1!==e[n].indexOf(t)}})):t.children.forEach(o=>{if("option"===o.name){let t="value"in o.props?o.props.value:o.children.join("").trim();o.props.selected=t===e[n]}})):"textarea"===t.name&&(o=o||"oninput",t.children=[e[n]]);t.props[o]||(p||(p=o=>e[n]=o.target.value),C(o,p,t,r))}},S=new Map;function _(e,n){if(S.has(e))return S.get(e);let o=e(k,n);return S.set(e,o),o}var k=function(n,o,...t){if("string"==typeof n)return new e(n,o||{},t);const r=new e("__component__",o||{},t);return r.component=n,r};k.fragment=(e,...n)=>n,k.current={},k.directives={...U},k.reservedProps={key:!0,state:!0,oncreate:!0,onupdate:!0,onremove:!0,shouldupdate:!0,"v-cleanup":!0,"v-once":!0,"v-if":!0,"v-unless":!0,"v-for":!0,"v-show":!0,"v-class":!0,"v-html":!0},k.isVnode=n,k.isComponent=o,k.isVnodeComponent=t,k.isNodeJs=r,k.trust=d,k.onCleanup=a,k.onUnmount=s,k.onMount=u,k.onUpdate=c,k.mount=m,k.unmount=h,k.update=v,k.setAttribute=C,k.directive=N,k.use=_;var b={Vnode:e,directive:N,isComponent:o,isNodeJs:r,isVnode:n,isVnodeComponent:t,mount:m,onCleanup:a,onMount:u,onUnmount:s,onUpdate:c,setAttribute:C,trust:d,unmount:h,update:v,use:_,v:k};"undefined"!=typeof module?module.exports=b:self.Valyrian=b})(); \ No newline at end of file diff --git a/dist/index.min.js.map b/dist/index.min.js.map index 0c2b47d..87ece03 100644 --- a/dist/index.min.js.map +++ b/dist/index.min.js.map @@ -1 +1 @@ -//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL2xpYi9pbmRleC50cyJdLCJuYW1lcyI6WyJWbm9kZSIsInRhZyIsInByb3BzIiwiY2hpbGRyZW4iLCJ0aGlzIiwiaXNDb21wb25lbnQiLCJjb21wb25lbnQiLCJpc1Zub2RlQ29tcG9uZW50Iiwidm5vZGUiLCJpc05vZGVKcyIsIkJvb2xlYW4iLCJwcm9jZXNzIiwidmVyc2lvbnMiLCJub2RlIiwiY3JlYXRlRG9tRWxlbWVudCIsImlzU1ZHIiwiZG9jdW1lbnQiLCJjcmVhdGVFbGVtZW50TlMiLCJjcmVhdGVFbGVtZW50IiwiZG9tVG9Wbm9kZSIsImRvbSIsInYiLCJ0YWdOYW1lIiwidG9Mb3dlckNhc2UiLCJBcnJheSIsImZyb20iLCJjaGlsZE5vZGVzIiwiZmlsdGVyIiwiY2hpbGQiLCJub2RlVHlwZSIsIm1hcCIsInRleHQiLCJub2RlVmFsdWUiLCJTdHJpbmciLCJmb3JFYWNoIiwiY2FsbCIsImF0dHJpYnV0ZXMiLCJwcm9wIiwibm9kZU5hbWUiLCJ0cnVzdCIsImh0bWxTdHJpbmciLCJkaXYiLCJpbm5lckhUTUwiLCJ0cmltIiwiaXRlbSIsIlZhbHlyaWFuU3ltYm9sIiwiU3ltYm9sIiwiY2FsbENsZWFudXAiLCJ2YWx5cmlhbkFwcCIsImkiLCJvbkNsZWFudXAiLCJsZW5ndGgiLCJ1cGRhdGUiLCJjdXJyZW50IiwiYXBwIiwib2xkVm5vZGUiLCJtYWluVm5vZGUiLCJwYXRjaCIsImlzTW91bnRlZCIsIm9uTW91bnQiLCJjYWxsTW91bnQiLCJvblVwZGF0ZSIsImNhbGxVcGRhdGUiLCJ1bm1vdW50Iiwib25Vbm1vdW50IiwiY2FsbFVubW91bnQiLCJSZWZsZWN0IiwiZGVsZXRlUHJvcGVydHkiLCJlbXB0eVZub2RlIiwib25yZW1vdmUiLCJzaGFyZWRVcGRhdGVQcm9wZXJ0eSIsInZhbHVlIiwicmVzZXJ2ZWRQcm9wcyIsImRpcmVjdGl2ZXMiLCJldmVudExpc3RlbmVyTmFtZXMiLCJjb250YWluZXIiLCJhZGRFdmVudExpc3RlbmVyIiwic2xpY2UiLCJldmVudExpc3RlbmVyIiwicmVtb3ZlQXR0cmlidXRlIiwic2V0QXR0cmlidXRlIiwic2V0UHJvcGVydHkiLCJuYW1lIiwidXBkYXRlUHJvcGVydGllcyIsIm5ld1Zub2RlIiwibmV3VHJlZSIsImNoaWxkVm5vZGUiLCJyZXN1bHQiLCJ2aWV3Iiwic3BsaWNlIiwiaXNBcnJheSIsImZsYXRUcmVlIiwib2xkVHJlZSIsIm9sZFRyZWVMZW5ndGgiLCJuZXdUcmVlTGVuZ3RoIiwib2xkS2V5ZWRMaXN0IiwicmVkdWNlIiwiYWNjIiwia2V5IiwibmV3S2V5ZWRMaXN0Iiwib2xkQ2hpbGRWbm9kZSIsInNob3VsZFBhdGNoIiwic2hvdWxkdXBkYXRlIiwib251cGRhdGUiLCJvbmNyZWF0ZSIsImFwcGVuZENoaWxkIiwicmVwbGFjZUNoaWxkIiwicGFyZW50Tm9kZSIsInJlbW92ZUNoaWxkIiwicGF0Y2hLZXllZFRyZWUiLCJuZXdDaGlsZFZub2RlIiwiY3JlYXRlVGV4dE5vZGUiLCJwYXRjaE5vcm1hbFRyZWUiLCJ0ZXh0Q29udGVudCIsImhpZGVEaXJlY3RpdmUiLCJ0ZXN0IiwiYm9vbCIsIm5ld2RvbSIsImJ1aWx0SW5EaXJlY3RpdmVzIiwic2V0Iiwic3R5bGUiLCJkaXNwbGF5IiwiY2xhc3NlcyIsImNsYXNzTGlzdCIsInRvZ2dsZSIsImh0bWwiLCJtb2RlbCIsInByb3BlcnR5IiwiZXZlbnQiLCJoYW5kbGVyIiwidHlwZSIsImUiLCJ2YWwiLCJ0YXJnZXQiLCJpZHgiLCJpbmRleE9mIiwicHVzaCIsIm11bHRpcGxlIiwiY3RybEtleSIsInZhbHVlMiIsImpvaW4iLCJzZWxlY3RlZCIsInRhZ09yQ29tcG9uZW50IiwiZnJhZ21lbnQiLCJzdGF0ZSIsImdsb2JhbCIsIndpbmRvdyIsImRpcmVjdGl2ZTIiLCJmdWxsTmFtZSIsInZub2RlQ29tcG9uZW50IiwiYXBwQ29udGFpbmVyIiwicXVlcnlTZWxlY3RvckFsbCIsIkVycm9yIiwiZGVmYXVsdFByZXZlbnRlZCIsImNhbGxiYWNrIl0sIm1hcHBp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cEIsS0FBTzlHLEdBQUssQ0FDVixHQUFJQSxFQUFJOEQsR0FLTixPQUpBOUQsRUFBSThELEdBQU1pRCxFQUFHL0csUUFDUitHLEVBQUVzQixrQkFDTHJHLEVBQU85QyxJQUlYYyxFQUFNQSxFQUFJdUYsYUFuQmRyRyxFQUFVdUMsR0FBa0IsQ0FDMUJhLFdBQVcsRUFDWGdCLG1CQUFvQixHQUNwQnhCLFVBQVcsR0FDWFMsUUFBUyxHQUNURSxTQUFVLEdBQ1ZHLFVBQVcsSUFnQmIxRCxFQUFVdUMsR0FBZ0JpQyxjQUFnQkEsRUFTNUMsT0FOQXhFLEVBQVV1QyxHQUFnQnZDLFVBQVkrSSxFQUN0Qy9JLEVBQVV1QyxHQUFnQjhCLFVBQVkyRSxFQUN0Q2hKLEVBQVV1QyxHQUFnQlcsVUFBWXJDLEVBQVdtSSxHQUNqRGhKLEVBQVV1QyxHQUFnQlcsVUFBVXpDLE1BQTBDLFFBQWxDVCxFQUFVdUMsR0FBZ0I1QyxJQUcvRG1ELEVBQU85QyxjQXpGVCxTQUFtQm9KLElBQzJCLElBQS9DckksRUFBRWdDLFFBQVFDLEtBQUtKLFVBQVVxRixRQUFRbUIsSUFDbkNySSxFQUFFZ0MsUUFBUUMsS0FBS0osVUFBVXNGLEtBQUtrQixZQVUzQixTQUFpQkEsSUFDMkIsSUFBN0NySSxFQUFFZ0MsUUFBUUMsS0FBS0ssUUFBUTRFLFFBQVFtQixJQUNqQ3JJLEVBQUVnQyxRQUFRQyxLQUFLSyxRQUFRNkUsS0FBS2tCLGNBUnpCLFNBQW1CQSxJQUMyQixJQUEvQ3JJLEVBQUVnQyxRQUFRQyxLQUFLVSxVQUFVdUUsUUFBUW1CLElBQ25DckksRUFBRWdDLFFBQVFDLEtBQUtVLFVBQVV3RSxLQUFLa0IsYUFVM0IsU0FBa0JBLElBQzJCLElBQTlDckksRUFBRWdDLFFBQVFDLEtBQUtPLFNBQVMwRSxRQUFRbUIsSUFDbENySSxFQUFFZ0MsUUFBUUMsS0FBS08sU0FBUzJFLEtBQUtrQiIsInNvdXJjZXNDb250ZW50IjpbIi8qKiogVm5vZGUgKioqL1xuXG5pbXBvcnQge1xuICBDaGlsZHJlbixcbiAgQ3VycmVudCxcbiAgRGlyZWN0aXZlLFxuICBEb21FbGVtZW50LFxuICBJVm5vZGUsXG4gIE1vdW50ZWRWYWx5cmlhbkFwcCxcbiAgUHJvcHMsXG4gIFZhbHlyaWFuLFxuICBWYWx5cmlhbkFwcCxcbiAgVmFseXJpYW5Db21wb25lbnQsXG4gIFZub2RlQ29tcG9uZW50LFxuICBWbm9kZVdpdGhEb21cbn0gZnJvbSBcIi4vaW50ZXJmYWNlc1wiO1xuXG5leHBvcnQgY29uc3QgVm5vZGUgPSBmdW5jdGlvbiBWbm9kZSh0aGlzOiBJVm5vZGUsIHRhZzogc3RyaW5nLCBwcm9wczogUHJvcHMsIGNoaWxkcmVuOiBDaGlsZHJlbikge1xuICB0aGlzLnByb3BzID0gcHJvcHM7XG4gIHRoaXMuY2hpbGRyZW4gPSBjaGlsZHJlbjtcbiAgdGhpcy50YWcgPSB0YWc7XG59IGFzIHVua25vd24gYXMgSVZub2RlO1xuXG5leHBvcnQgZnVuY3Rpb24gaXNWbm9kZShjb21wb25lbnQ/OiB1bmtub3duKTogY29tcG9uZW50IGlzIElWbm9kZSB7XG4gIHJldHVybiBjb21wb25lbnQgaW5zdGFuY2VvZiBWbm9kZTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGlzQ29tcG9uZW50KGNvbXBvbmVudD86IHVua25vd24gfCBWYWx5cmlhbkNvbXBvbmVudCk6IGNvbXBvbmVudCBpcyBWYWx5cmlhbkNvbXBvbmVudCB7XG4gIHJldHVybiB0eXBlb2YgY29tcG9uZW50ID09PSBcImZ1bmN0aW9uXCIgfHwgKHR5cGVvZiBjb21wb25lbnQgPT09IFwib2JqZWN0XCIgJiYgY29tcG9uZW50ICE9PSBudWxsICYmIFwidmlld1wiIGluIGNvbXBvbmVudCk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBpc1Zub2RlQ29tcG9uZW50KHZub2RlPzogdW5rbm93bik6IHZub2RlIGlzIFZub2RlQ29tcG9uZW50IHtcbiAgcmV0dXJuIHZub2RlIGluc3RhbmNlb2YgVm5vZGUgJiYgdm5vZGUudGFnID09PSBcIl9fY29tcG9uZW50X19cIjtcbn1cblxuLyoqKiBVdGlsICoqKi9cblxuZXhwb3J0IGNvbnN0IGlzTm9kZUpzID0gQm9vbGVhbih0eXBlb2YgcHJvY2VzcyAhPT0gXCJ1bmRlZmluZWRcIiAmJiBwcm9jZXNzLnZlcnNpb25zICYmIHByb2Nlc3MudmVyc2lvbnMubm9kZSk7XG5cbmZ1bmN0aW9uIGNyZWF0ZURvbUVsZW1lbnQodGFnOiBzdHJpbmcsIGlzU1ZHOiBib29sZWFuID0gZmFsc2UpIHtcbiAgcmV0dXJuIGlzU1ZHID8gZG9jdW1lbnQuY3JlYXRlRWxlbWVudE5TKFwiaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmdcIiwgdGFnKSA6IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQodGFnKTtcbn1cblxuZnVuY3Rpb24gZG9tVG9Wbm9kZShkb206IERvbUVsZW1lbnQpOiBWbm9kZVdpdGhEb20ge1xuICBsZXQgdm5vZGUgPSB2KFxuICAgIGRvbS50YWdOYW1lLnRvTG93ZXJDYXNlKCksXG4gICAge30sXG4gICAgLi4uQXJyYXkuZnJvbShkb20uY2hpbGROb2RlcylcbiAgICAgIC5maWx0ZXIoKGNoaWxkKSA9PiAoY2hpbGQgYXMgRG9tRWxlbWVudCkubm9kZVR5cGUgPT09IDEgfHwgKGNoaWxkIGFzIERvbUVsZW1lbnQpLm5vZGVUeXBlID09PSAzKVxuICAgICAgLm1hcCgoY2hpbGQpID0+IHtcbiAgICAgICAgaWYgKChjaGlsZCBhcyBEb21FbGVtZW50KS5ub2RlVHlwZSA9PT0gMSkge1xuICAgICAgICAgIHJldHVybiBkb21Ub1Zub2RlKGNoaWxkIGFzIERvbUVsZW1lbnQpO1xuICAgICAgICB9XG5cbiAgICAgICAgbGV0IHRleHQgPSBuZXcgVm5vZGUoXCIjdGV4dFwiLCB7fSwgW10pO1xuICAgICAgICB0ZXh0Lm5vZGVWYWx1ZSA9IFN0cmluZygoY2hpbGQgYXMgRG9tRWxlbWVudCkubm9kZVZhbHVlKTtcbiAgICAgICAgdGV4dC5kb20gPSBjaGlsZCBhcyBEb21FbGVtZW50O1xuICAgICAgICByZXR1cm4gdGV4dDtcbiAgICAgIH0pXG4gICk7XG4gIFtdLmZvckVhY2guY2FsbChkb20uYXR0cmlidXRlcywgKHByb3A6IEF0dHIpID0+ICh2bm9kZS5wcm9wc1twcm9wLm5vZGVOYW1lXSA9IHByb3Aubm9kZVZhbHVlKSk7XG4gIHZub2RlLmRvbSA9IGRvbTtcbiAgcmV0dXJuIHZub2RlIGFzIFZub2RlV2l0aERvbTtcbn1cblxuZXhwb3J0IGNvbnN0IHRydXN0ID0gKGh0bWxTdHJpbmc6IHN0cmluZykgPT4ge1xuICBsZXQgZGl2ID0gY3JlYXRlRG9tRWxlbWVudChcImRpdlwiKTtcbiAgZGl2LmlubmVySFRNTCA9IGh0bWxTdHJpbmcudHJpbSgpO1xuXG4gIHJldHVybiBbXS5tYXAuY2FsbChkaXYuY2hpbGROb2RlcywgKGl0ZW0pID0+IGRvbVRvVm5vZGUoaXRlbSkpIGFzIElWbm9kZVtdO1xufTtcblxuLyoqKiBNb3VudCAqKiovXG5cbmNvbnN0IFZhbHlyaWFuU3ltYm9sID0gU3ltYm9sKFwiVmFseXJpYW5cIik7XG5cbmV4cG9ydCBmdW5jdGlvbiBvbkNsZWFudXAoY2FsbGJhY2s6IEZ1bmN0aW9uKSB7XG4gIGlmICh2LmN1cnJlbnQuYXBwPy5vbkNsZWFudXAuaW5kZXhPZihjYWxsYmFjaykgPT09IC0xKSB7XG4gICAgdi5jdXJyZW50LmFwcD8ub25DbGVhbnVwLnB1c2goY2FsbGJhY2spO1xuICB9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBvblVubW91bnQoY2FsbGJhY2s6IEZ1bmN0aW9uKSB7XG4gIGlmICh2LmN1cnJlbnQuYXBwPy5vblVubW91bnQuaW5kZXhPZihjYWxsYmFjaykgPT09IC0xKSB7XG4gICAgdi5jdXJyZW50LmFwcD8ub25Vbm1vdW50LnB1c2goY2FsbGJhY2spO1xuICB9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBvbk1vdW50KGNhbGxiYWNrOiBGdW5jdGlvbikge1xuICBpZiAodi5jdXJyZW50LmFwcD8ub25Nb3VudC5pbmRleE9mKGNhbGxiYWNrKSA9PT0gLTEpIHtcbiAgICB2LmN1cnJlbnQuYXBwPy5vbk1vdW50LnB1c2goY2FsbGJhY2spO1xuICB9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBvblVwZGF0ZShjYWxsYmFjazogRnVuY3Rpb24pIHtcbiAgaWYgKHYuY3VycmVudC5hcHA/Lm9uVXBkYXRlLmluZGV4T2YoY2FsbGJhY2spID09PSAtMSkge1xuICAgIHYuY3VycmVudC5hcHA/Lm9uVXBkYXRlLnB1c2goY2FsbGJhY2spO1xuICB9XG59XG5cbi8qXG4gICogTW91bnRzIGEgY29tcG9uZW50IHRvIHRoZSBET01cbiAgbW91bnQoJyNhcHAnLCAoKSA9PiA8ZGl2PkhlbGxvIHdvcmxkPC9kaXY+KTsgLy8gQXBwIGlzIGEgRnVuY3Rpb25hbCBDb21wb25lbnRcbiAgbW91bnQoJyNhcHAnLCB7IHZpZXc6ICgpID0+IDxkaXY+SGVsbG8gd29ybGQ8L2Rpdj4gfSk7IC8vIEFwcCBpcyBhIFBPSk8gY29tcG9uZW50IHdpdGggYSB2aWV3IG1ldGhvZFxuICBtb3VudCgnI2FwcCcsIGNsYXNzSW5zdGFuY2UpOyAvLyBBcHAgaXMgYSBjbGFzcyBpbnN0YW5jZSB3aXRoIGEgdmlldyBtZXRob2RcbiAgbW91bnQoJyNhcHAnLCA8QXBwPjxkaXY+SGVsbG8gd29ybGQ8L2Rpdj48L0FwcD4pOyAvLyBBcHAgaXMgYSBWbm9kZSBjb21wb25lbnQgKFZub2RlIHdpdGggdGFnIF9fY29tcG9uZW50X18pXG4qL1xuXG5leHBvcnQgZnVuY3Rpb24gbW91bnQoY29udGFpbmVyOiBEb21FbGVtZW50IHwgc3RyaW5nLCBjb21wb25lbnQ6IFZhbHlyaWFuQ29tcG9uZW50IHwgSVZub2RlKSB7XG4gIGxldCBhcHBDb250YWluZXIgPSBudWxsO1xuXG4gIGlmIChpc05vZGVKcykge1xuICAgIGFwcENvbnRhaW5lciA9IHR5cGVvZiBjb250YWluZXIgPT09IFwic3RyaW5nXCIgPyBjcmVhdGVEb21FbGVtZW50KGNvbnRhaW5lciA9PT0gXCJzdmdcIiA/IFwic3ZnXCIgOiBcImRpdlwiLCBjb250YWluZXIgPT09IFwic3ZnXCIpIDogY29udGFpbmVyO1xuICB9IGVsc2Uge1xuICAgIGFwcENvbnRhaW5lciA9IHR5cGVvZiBjb250YWluZXIgPT09IFwic3RyaW5nXCIgPyBkb2N1bWVudC5xdWVyeVNlbGVjdG9yQWxsKGNvbnRhaW5lcilbMF0gOiBjb250YWluZXI7XG4gIH1cblxuICBpZiAoIWFwcENvbnRhaW5lcikge1xuICAgIHRocm93IG5ldyBFcnJvcihcIkNvbnRhaW5lciBub3QgZm91bmRcIik7XG4gIH1cblxuICBsZXQgdm5vZGVDb21wb25lbnQ6IFZub2RlQ29tcG9uZW50IHwgSVZub2RlO1xuXG4gIGlmIChpc1Zub2RlQ29tcG9uZW50KGNvbXBvbmVudCkpIHtcbiAgICB2bm9kZUNvbXBvbmVudCA9IGNvbXBvbmVudDtcbiAgfSBlbHNlIGlmIChpc0NvbXBvbmVudChjb21wb25lbnQpKSB7XG4gICAgdm5vZGVDb21wb25lbnQgPSB2KGNvbXBvbmVudCwge30pO1xuICB9IGVsc2Uge1xuICAgIHRocm93IG5ldyBFcnJvcihcIkNvbXBvbmVudCBtdXN0IGJlIGEgVmFseXJpYW4gQ29tcG9uZW50IG9yIGEgVm5vZGUgY29tcG9uZW50XCIpO1xuICB9XG5cbiAgaWYgKGNvbXBvbmVudFtWYWx5cmlhblN5bWJvbF0pIHtcbiAgICB1bm1vdW50KGNvbXBvbmVudCk7XG4gIH0gZWxzZSB7XG4gICAgY29tcG9uZW50W1ZhbHlyaWFuU3ltYm9sXSA9IHtcbiAgICAgIGlzTW91bnRlZDogZmFsc2UsXG4gICAgICBldmVudExpc3RlbmVyTmFtZXM6IHt9LFxuICAgICAgb25DbGVhbnVwOiBbXSxcbiAgICAgIG9uTW91bnQ6IFtdLFxuICAgICAgb25VcGRhdGU6IFtdLFxuICAgICAgb25Vbm1vdW50OiBbXVxuICAgIH07XG4gICAgZnVuY3Rpb24gZXZlbnRMaXN0ZW5lcihlOiBFdmVudCkge1xuICAgICAgbGV0IGRvbSA9IGUudGFyZ2V0IGFzIERvbUVsZW1lbnQgJiBSZWNvcmQ8c3RyaW5nLCBhbnk+O1xuICAgICAgbGV0IG5hbWUgPSBgdi1vbiR7ZS50eXBlfWA7XG4gICAgICB3aGlsZSAoZG9tKSB7XG4gICAgICAgIGlmIChkb21bbmFtZV0pIHtcbiAgICAgICAgICBkb21bbmFtZV0oZSwgZG9tKTtcbiAgICAgICAgICBpZiAoIWUuZGVmYXVsdFByZXZlbnRlZCkge1xuICAgICAgICAgICAgdXBkYXRlKGNvbXBvbmVudCk7XG4gICAgICAgICAgfVxuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBkb20gPSBkb20ucGFyZW50Tm9kZSBhcyBEb21FbGVtZW50O1xuICAgICAgfVxuICAgIH1cbiAgICBjb21wb25lbnRbVmFseXJpYW5TeW1ib2xdLmV2ZW50TGlzdGVuZXIgPSBldmVudExpc3RlbmVyO1xuICB9XG5cbiAgY29tcG9uZW50W1ZhbHlyaWFuU3ltYm9sXS5jb21wb25lbnQgPSB2bm9kZUNvbXBvbmVudDtcbiAgY29tcG9uZW50W1ZhbHlyaWFuU3ltYm9sXS5jb250YWluZXIgPSBhcHBDb250YWluZXI7XG4gIGNvbXBvbmVudFtWYWx5cmlhblN5bWJvbF0ubWFpblZub2RlID0gZG9tVG9Wbm9kZShhcHBDb250YWluZXIpO1xuICBjb21wb25lbnRbVmFseXJpYW5TeW1ib2xdLm1haW5Wbm9kZS5pc1NWRyA9IGNvbXBvbmVudFtWYWx5cmlhblN5bWJvbF0udGFnID09PSBcInN2Z1wiO1xuXG4gIC8vIHVwZGF0ZVxuICByZXR1cm4gdXBkYXRlKGNvbXBvbmVudCk7XG59XG5cbmZ1bmN0aW9uIGNhbGxDbGVhbnVwKHZhbHlyaWFuQXBwOiBWYWx5cmlhbkFwcCkge1xuICBmb3IgKGxldCBpID0gMDsgaSA8IHZhbHlyaWFuQXBwLm9uQ2xlYW51cC5sZW5ndGg7IGkrKykge1xuICAgIHZhbHlyaWFuQXBwLm9uQ2xlYW51cFtpXSgpO1xuICB9XG4gIHZhbHlyaWFuQXBwLm9uQ2xlYW51cCA9IFtdO1xufVxuXG5mdW5jdGlvbiBjYWxsVW5tb3VudCh2YWx5cmlhbkFwcDogVmFseXJpYW5BcHApIHtcbiAgZm9yIChsZXQgaSA9IDA7IGkgPCB2YWx5cmlhbkFwcC5vblVubW91bnQubGVuZ3RoOyBpKyspIHtcbiAgICB2YWx5cmlhbkFwcC5vblVubW91bnRbaV0oKTtcbiAgfVxuICB2YWx5cmlhbkFwcC5vblVubW91bnQgPSBbXTtcbn1cblxuZnVuY3Rpb24gY2FsbE1vdW50KHZhbHlyaWFuQXBwOiBWYWx5cmlhbkFwcCkge1xuICBmb3IgKGxldCBpID0gMDsgaSA8IHZhbHlyaWFuQXBwLm9uTW91bnQubGVuZ3RoOyBpKyspIHtcbiAgICB2YWx5cmlhbkFwcC5vbk1vdW50W2ldKCk7XG4gIH1cbiAgdmFseXJpYW5BcHAub25Nb3VudCA9IFtdO1xufVxuXG5mdW5jdGlvbiBjYWxsVXBkYXRlKHZhbHlyaWFuQXBwOiBWYWx5cmlhbkFwcCkge1xuICBmb3IgKGxldCBpID0gMDsgaSA8IHZhbHlyaWFuQXBwLm9uVXBkYXRlLmxlbmd0aDsgaSsrKSB7XG4gICAgdmFseXJpYW5BcHAub25VcGRhdGVbaV0oKTtcbiAgfVxuICB2YWx5cmlhbkFwcC5vblVwZGF0ZSA9IFtdO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gdXBkYXRlKGNvbXBvbmVudD86IFZhbHlyaWFuQ29tcG9uZW50IHwgSVZub2RlKSB7XG4gIGlmIChjb21wb25lbnQgJiYgY29tcG9uZW50W1ZhbHlyaWFuU3ltYm9sXSkge1xuICAgIGxldCB2YWx5cmlhbkFwcCA9IGNvbXBvbmVudFtWYWx5cmlhblN5bWJvbF07XG4gICAgdi5jdXJyZW50LmFwcCA9IHZhbHlyaWFuQXBwO1xuICAgIHZhbHlyaWFuQXBwLm9uQ2xlYW51cC5sZW5ndGggJiYgY2FsbENsZWFudXAodmFseXJpYW5BcHApO1xuICAgIGxldCBvbGRWbm9kZTogVm5vZGVXaXRoRG9tIHwgbnVsbCA9IHZhbHlyaWFuQXBwLm1haW5Wbm9kZSBhcyBWbm9kZVdpdGhEb207XG4gICAgdmFseXJpYW5BcHAubWFpblZub2RlID0gbmV3IFZub2RlKHZhbHlyaWFuQXBwLm1haW5Wbm9kZS50YWcsIHZhbHlyaWFuQXBwLm1haW5Wbm9kZS5wcm9wcywgW3ZhbHlyaWFuQXBwLmNvbXBvbmVudF0pIGFzIFZub2RlV2l0aERvbTtcbiAgICB2YWx5cmlhbkFwcC5tYWluVm5vZGUuZG9tID0gb2xkVm5vZGUuZG9tO1xuICAgIHZhbHlyaWFuQXBwLm1haW5Wbm9kZS5pc1NWRyA9IG9sZFZub2RlLmlzU1ZHO1xuICAgIHBhdGNoKHZhbHlyaWFuQXBwLm1haW5Wbm9kZSwgb2xkVm5vZGUsIHZhbHlyaWFuQXBwKTtcbiAgICBvbGRWbm9kZSA9IG51bGw7XG4gICAgaWYgKHZhbHlyaWFuQXBwLmlzTW91bnRlZCA9PT0gZmFsc2UpIHtcbiAgICAgIHZhbHlyaWFuQXBwLm9uTW91bnQubGVuZ3RoICYmIGNhbGxNb3VudCh2YWx5cmlhbkFwcCk7XG4gICAgICB2YWx5cmlhbkFwcC5pc01vdW50ZWQgPSB0cnVlO1xuICAgIH0gZWxzZSB7XG4gICAgICB2YWx5cmlhbkFwcC5vblVwZGF0ZS5sZW5ndGggJiYgY2FsbFVwZGF0ZSh2YWx5cmlhbkFwcCk7XG4gICAgfVxuXG4gICAgaWYgKGlzTm9kZUpzKSB7XG4gICAgICByZXR1cm4gdmFseXJpYW5BcHAubWFpblZub2RlLmRvbS5pbm5lckhUTUw7XG4gICAgfVxuICB9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiB1bm1vdW50KGNvbXBvbmVudD86IFZhbHlyaWFuQ29tcG9uZW50IHwgSVZub2RlKSB7XG4gIGlmICghY29tcG9uZW50IHx8ICFjb21wb25lbnRbVmFseXJpYW5TeW1ib2xdKSB7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgbGV0IHZhbHlyaWFuQXBwID0gY29tcG9uZW50W1ZhbHlyaWFuU3ltYm9sXSBhcyBNb3VudGVkVmFseXJpYW5BcHA7XG5cbiAgaWYgKHZhbHlyaWFuQXBwLmlzTW91bnRlZCkge1xuICAgIHZhbHlyaWFuQXBwLm9uQ2xlYW51cC5sZW5ndGggJiYgY2FsbENsZWFudXAodmFseXJpYW5BcHApO1xuICAgIHZhbHlyaWFuQXBwLm9uVW5tb3VudC5sZW5ndGggJiYgY2FsbFVubW91bnQodmFseXJpYW5BcHApO1xuICAgIGxldCBvbGRWbm9kZTogVm5vZGVXaXRoRG9tIHwgbnVsbCA9IHZhbHlyaWFuQXBwLm1haW5Wbm9kZSBhcyBWbm9kZVdpdGhEb207XG4gICAgdmFseXJpYW5BcHAubWFpblZub2RlID0gbmV3IFZub2RlKHZhbHlyaWFuQXBwLm1haW5Wbm9kZS50YWcsIHZhbHlyaWFuQXBwLm1haW5Wbm9kZS5wcm9wcywgW10pIGFzIFZub2RlV2l0aERvbTtcbiAgICB2YWx5cmlhbkFwcC5tYWluVm5vZGUuZG9tID0gb2xkVm5vZGUuZG9tO1xuICAgIHZhbHlyaWFuQXBwLm1haW5Wbm9kZS5pc1NWRyA9IG9sZFZub2RlLmlzU1ZHO1xuICAgIHBhdGNoKHZhbHlyaWFuQXBwLm1haW5Wbm9kZSwgb2xkVm5vZGUsIHZhbHlyaWFuQXBwKTtcbiAgICBvbGRWbm9kZSA9IG51bGw7XG5cbiAgICBpZiAoaXNOb2RlSnMpIHtcbiAgICAgIHJldHVybiB2YWx5cmlhbkFwcC5tYWluVm5vZGUuZG9tLmlubmVySFRNTDtcbiAgICB9XG5cbiAgICAodmFseXJpYW5BcHAgYXMgYW55KSA9IG51bGw7XG4gICAgUmVmbGVjdC5kZWxldGVQcm9wZXJ0eShjb21wb25lbnQsIFZhbHlyaWFuU3ltYm9sKTtcbiAgfVxufVxuXG5sZXQgZW1wdHlWbm9kZSA9IG5ldyBWbm9kZShcIl9fZW1wdHlfX1wiLCB7fSwgW10pO1xuXG5mdW5jdGlvbiBvbnJlbW92ZSh2bm9kZTogSVZub2RlKSB7XG4gIGZvciAobGV0IGkgPSAwOyBpIDwgdm5vZGUuY2hpbGRyZW4ubGVuZ3RoOyBpKyspIHtcbiAgICB2bm9kZS5jaGlsZHJlbltpXS50YWcgIT09IFwiI3RleHRcIiAmJiBvbnJlbW92ZSh2bm9kZS5jaGlsZHJlbltpXSk7XG4gIH1cblxuICB2bm9kZS5wcm9wcy5vbnJlbW92ZSAmJiB2bm9kZS5wcm9wcy5vbnJlbW92ZSh2bm9kZSk7XG59XG5cbmZ1bmN0aW9uIHNoYXJlZFVwZGF0ZVByb3BlcnR5KHByb3A6IHN0cmluZywgdmFsdWU6IGFueSwgdm5vZGU6IFZub2RlV2l0aERvbSwgb2xkVm5vZGU/OiBWbm9kZVdpdGhEb20pIHtcbiAgLy8gSXQgaXMgYSByZXNlcnZlZCBwcm9wXG4gIGlmICh2LnJlc2VydmVkUHJvcHNbcHJvcF0pIHtcbiAgICAvLyBJZiBpdCBpcyBhIGRpcmVjdGl2ZSBuYW1lIGNhbGwgdGhlIGRpcmVjdGl2ZVxuICAgIGlmICh2LmRpcmVjdGl2ZXNbcHJvcF0pIHtcbiAgICAgIHYuZGlyZWN0aXZlc1twcm9wXSh2bm9kZS5wcm9wc1twcm9wXSwgdm5vZGUsIG9sZFZub2RlKTtcbiAgICB9XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgLy8gSXQgaXMgbm90IGEgcmVzZXJ2ZWQgcHJvcCBzbyB3ZSBhZGQgaXQgdG8gdGhlIGRvbVxuICBpZiAodHlwZW9mIHZhbHVlID09PSBcImZ1bmN0aW9uXCIpIHtcbiAgICBsZXQgdmFseXJpYW5BcHAgPSB2LmN1cnJlbnQuYXBwIGFzIE1vdW50ZWRWYWx5cmlhbkFwcDtcbiAgICBpZiAocHJvcCBpbiB2YWx5cmlhbkFwcC5ldmVudExpc3RlbmVyTmFtZXMgPT09IGZhbHNlKSB7XG4gICAgICB2YWx5cmlhbkFwcC5ldmVudExpc3RlbmVyTmFtZXNbcHJvcF0gPSB0cnVlO1xuICAgICAgdmFseXJpYW5BcHAuY29udGFpbmVyLmFkZEV2ZW50TGlzdGVuZXIocHJvcC5zbGljZSgyKSwgdmFseXJpYW5BcHAuZXZlbnRMaXN0ZW5lcik7XG4gICAgfVxuICAgIHZub2RlLmRvbVtgdi0ke3Byb3B9YF0gPSB2YWx1ZTtcbiAgICByZXR1cm47XG4gIH1cblxuICBpZiAocHJvcCBpbiB2bm9kZS5kb20gJiYgdm5vZGUuaXNTVkcgPT09IGZhbHNlKSB7XG4gICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGVxZXFlcVxuICAgIGlmICh2bm9kZS5kb21bcHJvcF0gIT0gdmFsdWUpIHtcbiAgICAgIHZub2RlLmRvbVtwcm9wXSA9IHZhbHVlO1xuICAgIH1cbiAgICByZXR1cm47XG4gIH1cblxuICAvLyBVc2Ugc2V0IGF0dHJpYnV0ZVxuICBpZiAoIW9sZFZub2RlIHx8IG9sZFZub2RlLnByb3BzW3Byb3BdICE9PSB2YWx1ZSkge1xuICAgIGlmICh2YWx1ZSA9PT0gZmFsc2UpIHtcbiAgICAgIHZub2RlLmRvbS5yZW1vdmVBdHRyaWJ1dGUocHJvcCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHZub2RlLmRvbS5zZXRBdHRyaWJ1dGUocHJvcCwgdmFsdWUpO1xuICAgIH1cbiAgfVxufVxuXG5leHBvcnQgZnVuY3Rpb24gc2V0UHJvcGVydHkobmFtZTogc3RyaW5nLCB2YWx1ZTogYW55LCB2bm9kZTogVm5vZGVXaXRoRG9tLCBvbGRWbm9kZT86IFZub2RlV2l0aERvbSkge1xuICBpZiAobmFtZSBpbiB2bm9kZS5wcm9wcyA9PT0gZmFsc2UpIHtcbiAgICB2bm9kZS5wcm9wc1tuYW1lXSA9IHZhbHVlO1xuICB9XG5cbiAgc2hhcmVkVXBkYXRlUHJvcGVydHkobmFtZSwgdmFsdWUsIHZub2RlLCBvbGRWbm9kZSk7XG59XG5cbmZ1bmN0aW9uIHVwZGF0ZVByb3BlcnRpZXModm5vZGU6IFZub2RlV2l0aERvbSwgb2xkVm5vZGU/OiBWbm9kZVdpdGhEb20pIHtcbiAgZm9yIChsZXQgcHJvcCBpbiB2bm9kZS5wcm9wcykge1xuICAgIC8vIFdlIGFzdW1lIHRoYXQgd2UgY2xlYW4gdGhlIHByb3BzIGluIHNvbWUgZGlyZWN0aXZlXG4gICAgaWYgKHByb3AgaW4gdm5vZGUucHJvcHMgPT09IGZhbHNlKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgc2hhcmVkVXBkYXRlUHJvcGVydHkocHJvcCwgdm5vZGUucHJvcHNbcHJvcF0sIHZub2RlLCBvbGRWbm9kZSk7XG4gIH1cblxuICBpZiAob2xkVm5vZGUpIHtcbiAgICBmb3IgKGxldCBwcm9wIGluIG9sZFZub2RlLnByb3BzKSB7XG4gICAgICBpZiAocHJvcCBpbiB2bm9kZS5wcm9wcyA9PT0gZmFsc2UgJiYgdHlwZW9mIG9sZFZub2RlLnByb3BzW3Byb3BdICE9PSBcImZ1bmN0aW9uXCIgJiYgcHJvcCBpbiB2LnJlc2VydmVkUHJvcHMgPT09IGZhbHNlKSB7XG4gICAgICAgIGlmIChwcm9wIGluIG9sZFZub2RlLmRvbSAmJiB2bm9kZS5pc1NWRyA9PT0gZmFsc2UpIHtcbiAgICAgICAgICBvbGRWbm9kZS5kb21bcHJvcF0gPSBudWxsO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIG9sZFZub2RlLmRvbS5yZW1vdmVBdHRyaWJ1dGUocHJvcCk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gIH1cbn1cblxuZnVuY3Rpb24gZmxhdFRyZWUobmV3Vm5vZGU6IElWbm9kZSk6IHZvaWQge1xuICBsZXQgbmV3VHJlZSA9IG5ld1Zub2RlLmNoaWxkcmVuO1xuICBmb3IgKGxldCBpID0gMDsgaSA8IG5ld1RyZWUubGVuZ3RoOyBpKyspIHtcbiAgICBsZXQgY2hpbGRWbm9kZSA9IG5ld1RyZWVbaV07XG4gICAgaWYgKGNoaWxkVm5vZGUgaW5zdGFuY2VvZiBWbm9kZSkge1xuICAgICAgaWYgKGNoaWxkVm5vZGUudGFnICE9PSBcIiN0ZXh0XCIpIHtcbiAgICAgICAgaWYgKGNoaWxkVm5vZGUudGFnID09PSBcIl9fY29tcG9uZW50X19cIikge1xuICAgICAgICAgIGxldCBjb21wb25lbnQgPSBjaGlsZFZub2RlLmNvbXBvbmVudCBhcyBWYWx5cmlhbkNvbXBvbmVudDtcbiAgICAgICAgICB2LmN1cnJlbnQuY29tcG9uZW50ID0gY29tcG9uZW50O1xuICAgICAgICAgIGxldCByZXN1bHQgPSAoXCJ2aWV3XCIgaW4gY29tcG9uZW50ID8gY29tcG9uZW50LnZpZXcgOiBjb21wb25lbnQpLmNhbGwoY29tcG9uZW50LCBjaGlsZFZub2RlLnByb3BzLCAuLi5jaGlsZFZub2RlLmNoaWxkcmVuKTtcblxuICAgICAgICAgIG5ld1RyZWUuc3BsaWNlKGktLSwgMSwgcmVzdWx0KTtcbiAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuICAgICAgICBjaGlsZFZub2RlLmlzU1ZHID0gbmV3Vm5vZGUuaXNTVkcgfHwgY2hpbGRWbm9kZS50YWcgPT09IFwic3ZnXCI7XG4gICAgICB9XG4gICAgfSBlbHNlIGlmIChjaGlsZFZub2RlID09PSBudWxsIHx8IGNoaWxkVm5vZGUgPT09IHVuZGVmaW5lZCkge1xuICAgICAgbmV3VHJlZS5zcGxpY2UoaS0tLCAxKTtcbiAgICB9IGVsc2UgaWYgKEFycmF5LmlzQXJyYXkoY2hpbGRWbm9kZSkpIHtcbiAgICAgIG5ld1RyZWUuc3BsaWNlKGktLSwgMSwgLi4uY2hpbGRWbm9kZSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGlmIChpID4gMCAmJiBuZXdUcmVlW2kgLSAxXS50YWcgPT09IFwiI3RleHRcIikge1xuICAgICAgICBuZXdUcmVlW2kgLSAxXS5ub2RlVmFsdWUgKz0gY2hpbGRWbm9kZTtcbiAgICAgICAgbmV3VHJlZS5zcGxpY2UoaS0tLCAxKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIG5ld1RyZWVbaV0gPSBuZXcgVm5vZGUoXCIjdGV4dFwiLCB7fSwgW10pO1xuICAgICAgICBuZXdUcmVlW2ldLm5vZGVWYWx1ZSA9IFN0cmluZyhjaGlsZFZub2RlKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cbn1cblxuZnVuY3Rpb24gcGF0Y2hLZXllZFRyZWUoXG4gIG5ld1Zub2RlOiBWbm9kZVdpdGhEb20sXG4gIG5ld1RyZWU6IChWbm9kZVdpdGhEb20gJiB7IHByb3BzOiBQcm9wcyAmIHsga2V5OiBzdHJpbmcgfSB9KVtdLFxuICBvbGRUcmVlOiAoVm5vZGVXaXRoRG9tICYgeyBwcm9wczogUHJvcHMgJiB7IGtleTogc3RyaW5nIH0gfSlbXSxcbiAgbmV3VHJlZUxlbmd0aDogbnVtYmVyLFxuICBvbGRUcmVlTGVuZ3RoOiBudW1iZXIsXG4gIHZhbHlyaWFuQXBwOiBNb3VudGVkVmFseXJpYW5BcHBcbikge1xuICBsZXQgb2xkS2V5ZWRMaXN0ID0gb2xkVHJlZS5yZWR1Y2UoKGFjYywgdm5vZGUsIGkpID0+IHtcbiAgICBhY2Nbdm5vZGUucHJvcHMua2V5XSA9IGk7XG4gICAgcmV0dXJuIGFjYztcbiAgfSwge30gYXMgeyBba2V5OiBzdHJpbmddOiBudW1iZXIgfSk7XG4gIGxldCBuZXdLZXllZExpc3QgPSBuZXdUcmVlLnJlZHVjZSgoYWNjLCB2bm9kZSwgaSkgPT4ge1xuICAgIGFjY1t2bm9kZS5wcm9wcy5rZXldID0gaTtcbiAgICByZXR1cm4gYWNjO1xuICB9LCB7fSBhcyB7IFtrZXk6IHN0cmluZ106IG51bWJlciB9KTtcblxuICBmb3IgKGxldCBpID0gMDsgaSA8IG5ld1RyZWVMZW5ndGg7IGkrKykge1xuICAgIGxldCBjaGlsZFZub2RlID0gbmV3VHJlZVtpXTtcbiAgICBsZXQgb2xkQ2hpbGRWbm9kZSA9IG9sZFRyZWVbb2xkS2V5ZWRMaXN0W2NoaWxkVm5vZGUucHJvcHMua2V5XV07XG4gICAgbGV0IHNob3VsZFBhdGNoID0gdHJ1ZTtcblxuICAgIGlmIChvbGRDaGlsZFZub2RlKSB7XG4gICAgICBjaGlsZFZub2RlLmRvbSA9IG9sZENoaWxkVm5vZGUuZG9tO1xuICAgICAgaWYgKFwidi1vbmNlXCIgaW4gY2hpbGRWbm9kZS5wcm9wcyB8fCAoY2hpbGRWbm9kZS5wcm9wcy5zaG91bGR1cGRhdGUgJiYgY2hpbGRWbm9kZS5wcm9wcy5zaG91bGR1cGRhdGUoY2hpbGRWbm9kZSwgb2xkQ2hpbGRWbm9kZSkgPT09IGZhbHNlKSkge1xuICAgICAgICAvLyBza2lwIHRoaXMgcGF0Y2hcbiAgICAgICAgY2hpbGRWbm9kZS5jaGlsZHJlbiA9IG9sZENoaWxkVm5vZGUuY2hpbGRyZW47XG4gICAgICAgIHNob3VsZFBhdGNoID0gZmFsc2U7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB1cGRhdGVQcm9wZXJ0aWVzKGNoaWxkVm5vZGUsIG9sZENoaWxkVm5vZGUpO1xuICAgICAgICBpZiAodmFseXJpYW5BcHAuaXNNb3VudGVkKSB7XG4gICAgICAgICAgY2hpbGRWbm9kZS5wcm9wcy5vbnVwZGF0ZSAmJiBjaGlsZFZub2RlLnByb3BzLm9udXBkYXRlKGNoaWxkVm5vZGUsIG9sZENoaWxkVm5vZGUpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGNoaWxkVm5vZGUucHJvcHMub25jcmVhdGUgJiYgY2hpbGRWbm9kZS5wcm9wcy5vbmNyZWF0ZShjaGlsZFZub2RlKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICBjaGlsZFZub2RlLmRvbSA9IGNyZWF0ZURvbUVsZW1lbnQoY2hpbGRWbm9kZS50YWcsIGNoaWxkVm5vZGUuaXNTVkcpO1xuICAgICAgdXBkYXRlUHJvcGVydGllcyhjaGlsZFZub2RlKTtcbiAgICAgIGNoaWxkVm5vZGUucHJvcHMub25jcmVhdGUgJiYgY2hpbGRWbm9kZS5wcm9wcy5vbmNyZWF0ZShjaGlsZFZub2RlKTtcbiAgICB9XG5cbiAgICBpZiAobmV3Vm5vZGUuZG9tLmNoaWxkTm9kZXNbaV0gPT09IHVuZGVmaW5lZCkge1xuICAgICAgbmV3Vm5vZGUuZG9tLmFwcGVuZENoaWxkKGNoaWxkVm5vZGUuZG9tKTtcbiAgICB9IGVsc2UgaWYgKG5ld1Zub2RlLmRvbS5jaGlsZE5vZGVzW2ldICE9PSBjaGlsZFZub2RlLmRvbSkge1xuICAgICAgb2xkVHJlZVtpXSAmJiBuZXdLZXllZExpc3Rbb2xkVHJlZVtpXS5wcm9wcy5rZXldID09PSB1bmRlZmluZWQgJiYgb25yZW1vdmUob2xkVHJlZVtpXSk7XG4gICAgICBuZXdWbm9kZS5kb20ucmVwbGFjZUNoaWxkKGNoaWxkVm5vZGUuZG9tLCBuZXdWbm9kZS5kb20uY2hpbGROb2Rlc1tpXSk7XG4gICAgfVxuXG4gICAgc2hvdWxkUGF0Y2ggJiYgcGF0Y2goY2hpbGRWbm9kZSwgb2xkQ2hpbGRWbm9kZSwgdmFseXJpYW5BcHApO1xuICB9XG5cbiAgLy8gRm9yIHRoZSByZXN0IG9mIHRoZSBjaGlsZHJlbiwgd2Ugc2hvdWxkIHJlbW92ZSB0aGVtXG4gIGZvciAobGV0IGkgPSBuZXdUcmVlTGVuZ3RoOyBpIDwgb2xkVHJlZUxlbmd0aDsgaSsrKSB7XG4gICAgaWYgKG5ld0tleWVkTGlzdFtvbGRUcmVlW2ldLnByb3BzLmtleV0gPT09IHVuZGVmaW5lZCkge1xuICAgICAgbGV0IG9sZENoaWxkVm5vZGUgPSBvbGRUcmVlW2ldO1xuICAgICAgb25yZW1vdmUob2xkQ2hpbGRWbm9kZSk7XG4gICAgICBvbGRDaGlsZFZub2RlLmRvbS5wYXJlbnROb2RlICYmIG9sZENoaWxkVm5vZGUuZG9tLnBhcmVudE5vZGUucmVtb3ZlQ2hpbGQob2xkQ2hpbGRWbm9kZS5kb20pO1xuICAgIH1cbiAgfVxufVxuXG4vLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgY29tcGxleGl0eVxuZnVuY3Rpb24gcGF0Y2hOb3JtYWxUcmVlKFxuICBuZXdWbm9kZTogVm5vZGVXaXRoRG9tLFxuICBuZXdUcmVlOiAoVm5vZGVXaXRoRG9tICYgeyBwcm9wczogUHJvcHMgJiB7IGtleTogc3RyaW5nIH0gfSlbXSxcbiAgb2xkVHJlZTogKFZub2RlV2l0aERvbSAmIHsgcHJvcHM6IFByb3BzICYgeyBrZXk6IHN0cmluZyB9IH0pW10sXG4gIG5ld1RyZWVMZW5ndGg6IG51bWJlcixcbiAgb2xkVHJlZUxlbmd0aDogbnVtYmVyLFxuICB2YWx5cmlhbkFwcDogTW91bnRlZFZhbHlyaWFuQXBwXG4pIHtcbiAgLy8gSWYgbmV3IHRyZWUgYW5kIG9sZCB0cmVlIGhhdmUgbW9yZSB0aGFuIG9uZSBjaGlsZCwgd2Ugc2hvdWxkIHVwZGF0ZSB0aGUgZG9tXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgbmV3VHJlZUxlbmd0aDsgaSsrKSB7XG4gICAgbGV0IG9sZENoaWxkVm5vZGUgPSBvbGRUcmVlW2ldO1xuICAgIGxldCBuZXdDaGlsZFZub2RlID0gbmV3VHJlZVtpXTtcblxuICAgIC8vIE9sZCBjaGlsZCBkb2VzIG5vdCBleGlzdHNcbiAgICBpZiAoIW9sZENoaWxkVm5vZGUpIHtcbiAgICAgIC8vIE5ldyBjaGlsZCBpcyBhIHRleHQgbm9kZVxuICAgICAgaWYgKG5ld0NoaWxkVm5vZGUudGFnID09PSBcIiN0ZXh0XCIpIHtcbiAgICAgICAgbmV3Q2hpbGRWbm9kZS5kb20gPSBkb2N1bWVudC5jcmVhdGVUZXh0Tm9kZShuZXdDaGlsZFZub2RlLm5vZGVWYWx1ZSBhcyBzdHJpbmcpIGFzIHVua25vd24gYXMgRG9tRWxlbWVudDtcbiAgICAgICAgbmV3Vm5vZGUuZG9tLmFwcGVuZENoaWxkKG5ld0NoaWxkVm5vZGUuZG9tKTtcbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG5cbiAgICAgIC8vIE5ldyBjaGlsZCBpcyBhIG5vcm1hbCBub2RlXG4gICAgICBuZXdDaGlsZFZub2RlLmRvbSA9IGNyZWF0ZURvbUVsZW1lbnQobmV3Q2hpbGRWbm9kZS50YWcsIG5ld0NoaWxkVm5vZGUuaXNTVkcpO1xuICAgICAgdXBkYXRlUHJvcGVydGllcyhuZXdDaGlsZFZub2RlKTtcbiAgICAgIG5ld1Zub2RlLmRvbS5hcHBlbmRDaGlsZChuZXdDaGlsZFZub2RlLmRvbSk7XG4gICAgICBuZXdDaGlsZFZub2RlLnByb3BzLm9uY3JlYXRlICYmIG5ld0NoaWxkVm5vZGUucHJvcHMub25jcmVhdGUobmV3Q2hpbGRWbm9kZSk7XG4gICAgICBwYXRjaChuZXdDaGlsZFZub2RlLCB1bmRlZmluZWQsIHZhbHlyaWFuQXBwKTtcbiAgICAgIGNvbnRpbnVlO1xuICAgIH1cblxuICAgIC8vIE9sZCBjaGlsZCBleGlzdHNcbiAgICAvLyBOZXcgY2hpbGQgaXMgYSB0ZXh0IG5vZGVcbiAgICBpZiAobmV3Q2hpbGRWbm9kZS50YWcgPT09IFwiI3RleHRcIikge1xuICAgICAgLy8gT2xkIGNoaWxkIGlzIGEgdGV4dCBub2RlXG4gICAgICBpZiAob2xkQ2hpbGRWbm9kZS50YWcgPT09IFwiI3RleHRcIikge1xuICAgICAgICBuZXdDaGlsZFZub2RlLmRvbSA9IG9sZENoaWxkVm5vZGUuZG9tO1xuICAgICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgZXFlcWVxXG4gICAgICAgIGlmIChuZXdDaGlsZFZub2RlLmRvbS5ub2RlVmFsdWUgIT0gbmV3Q2hpbGRWbm9kZS5ub2RlVmFsdWUpIHtcbiAgICAgICAgICBuZXdDaGlsZFZub2RlLmRvbS5ub2RlVmFsdWUgPSBuZXdDaGlsZFZub2RlLm5vZGVWYWx1ZSBhcyBzdHJpbmc7XG4gICAgICAgIH1cbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG5cbiAgICAgIC8vIE9sZCBjaGlsZCBpcyBhIG5vcm1hbCBub2RlXG4gICAgICBuZXdDaGlsZFZub2RlLmRvbSA9IGRvY3VtZW50LmNyZWF0ZVRleHROb2RlKG5ld0NoaWxkVm5vZGUubm9kZVZhbHVlIGFzIHN0cmluZykgYXMgdW5rbm93biBhcyBEb21FbGVtZW50O1xuICAgICAgb25yZW1vdmUob2xkQ2hpbGRWbm9kZSk7XG4gICAgICBuZXdWbm9kZS5kb20ucmVwbGFjZUNoaWxkKG5ld0NoaWxkVm5vZGUuZG9tLCBvbGRDaGlsZFZub2RlLmRvbSk7XG5cbiAgICAgIGNvbnRpbnVlO1xuICAgIH1cblxuICAgIC8vIE5ldyBjaGlsZCBpcyBhIG5vcm1hbCBub2RlXG4gICAgLy8gT2xkIGNoaWxkIGlzIHRoZSBzYW1lIHR5cGUgYXMgbmV3IGNoaWxkXG4gICAgaWYgKG9sZENoaWxkVm5vZGUudGFnID09PSBuZXdDaGlsZFZub2RlLnRhZykge1xuICAgICAgbmV3Q2hpbGRWbm9kZS5kb20gPSBvbGRDaGlsZFZub2RlLmRvbTtcbiAgICAgIC8vIElmIHdlIGhhdmUgYSB2LW9uY2UgZGlyZWN0aXZlIG9yIGEgc2hvdWxkdXBkYXRlIG1ldGhvZCB0aGF0IHJldHVybnMgZmFsc2UsIHdlIHNraXAgdGhlIHVwZGF0ZVxuICAgICAgaWYgKG5ld0NoaWxkVm5vZGUucHJvcHNbXCJ2LW9uY2VcIl0gfHwgKG5ld0NoaWxkVm5vZGUucHJvcHMuc2hvdWxkdXBkYXRlICYmIG5ld0NoaWxkVm5vZGUucHJvcHMuc2hvdWxkdXBkYXRlKG5ld0NoaWxkVm5vZGUsIG9sZENoaWxkVm5vZGUpID09PSBmYWxzZSkpIHtcbiAgICAgICAgbmV3Q2hpbGRWbm9kZS5jaGlsZHJlbiA9IG9sZENoaWxkVm5vZGUuY2hpbGRyZW47XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuXG4gICAgICAvLyBXZSB1cGRhdGUgdGhlIGRvbSBlbGVtZW50XG4gICAgICB1cGRhdGVQcm9wZXJ0aWVzKG5ld0NoaWxkVm5vZGUsIG9sZENoaWxkVm5vZGUpO1xuICAgICAgaWYgKHZhbHlyaWFuQXBwICYmIHZhbHlyaWFuQXBwLmlzTW91bnRlZCkge1xuICAgICAgICBuZXdDaGlsZFZub2RlLnByb3BzLm9udXBkYXRlICYmIG5ld0NoaWxkVm5vZGUucHJvcHMub251cGRhdGUobmV3Q2hpbGRWbm9kZSwgb2xkQ2hpbGRWbm9kZSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBuZXdDaGlsZFZub2RlLnByb3BzLm9uY3JlYXRlICYmIG5ld0NoaWxkVm5vZGUucHJvcHMub25jcmVhdGUobmV3Q2hpbGRWbm9kZSk7XG4gICAgICB9XG4gICAgICBwYXRjaChuZXdDaGlsZFZub2RlLCBvbGRDaGlsZFZub2RlLCB2YWx5cmlhbkFwcCk7XG5cbiAgICAgIGNvbnRpbnVlO1xuICAgIH1cblxuICAgIC8vIE9sZCBjaGlsZCBpcyBvZiBhIGRpZmZlcmVudCB0eXBlIHRoYW4gbmV3IGNoaWxkXG4gICAgbmV3Q2hpbGRWbm9kZS5kb20gPSBjcmVhdGVEb21FbGVtZW50KG5ld0NoaWxkVm5vZGUudGFnLCBuZXdDaGlsZFZub2RlLmlzU1ZHKTtcbiAgICB1cGRhdGVQcm9wZXJ0aWVzKG5ld0NoaWxkVm5vZGUpO1xuICAgIGlmIChvbGRDaGlsZFZub2RlLnRhZyAhPT0gXCIjdGV4dFwiKSB7XG4gICAgICBvbnJlbW92ZShvbGRDaGlsZFZub2RlKTtcbiAgICB9XG4gICAgbmV3Q2hpbGRWbm9kZS5wcm9wcy5vbmNyZWF0ZSAmJiBuZXdDaGlsZFZub2RlLnByb3BzLm9uY3JlYXRlKG5ld0NoaWxkVm5vZGUpO1xuICAgIG5ld1Zub2RlLmRvbS5yZXBsYWNlQ2hpbGQobmV3Q2hpbGRWbm9kZS5kb20sIG9sZENoaWxkVm5vZGUuZG9tKTtcbiAgICBwYXRjaChuZXdDaGlsZFZub2RlLCB1bmRlZmluZWQsIHZhbHlyaWFuQXBwKTtcbiAgfVxuXG4gIC8vIEZvciB0aGUgcmVzdCBvZiB0aGUgY2hpbGRyZW4sIHdlIHNob3VsZCByZW1vdmUgdGhlbVxuICBmb3IgKGxldCBpID0gbmV3VHJlZUxlbmd0aDsgaSA8IG9sZFRyZWVMZW5ndGg7IGkrKykge1xuICAgIGxldCBvbGRDaGlsZFZub2RlID0gb2xkVHJlZVtpXTtcbiAgICBpZiAob2xkQ2hpbGRWbm9kZS50YWcgIT09IFwiI3RleHRcIikge1xuICAgICAgb25yZW1vdmUob2xkQ2hpbGRWbm9kZSk7XG4gICAgfVxuICAgIG9sZENoaWxkVm5vZGUuZG9tLnBhcmVudE5vZGUgJiYgb2xkQ2hpbGRWbm9kZS5kb20ucGFyZW50Tm9kZS5yZW1vdmVDaGlsZChvbGRDaGlsZFZub2RlLmRvbSk7XG4gIH1cbn1cblxuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGNvbXBsZXhpdHlcbmZ1bmN0aW9uIHBhdGNoKG5ld1Zub2RlOiBWbm9kZVdpdGhEb20sIG9sZFZub2RlOiBWbm9kZVdpdGhEb20gPSBlbXB0eVZub2RlIGFzIFZub2RlV2l0aERvbSwgdmFseXJpYW5BcHA6IE1vdW50ZWRWYWx5cmlhbkFwcCkge1xuICB2LmN1cnJlbnQudm5vZGUgPSBuZXdWbm9kZTtcbiAgdi5jdXJyZW50Lm9sZFZub2RlID0gb2xkVm5vZGU7XG5cbiAgZmxhdFRyZWUobmV3Vm5vZGUpO1xuXG4gIGxldCBuZXdUcmVlID0gbmV3Vm5vZGUuY2hpbGRyZW47XG4gIGxldCBvbGRUcmVlID0gb2xkVm5vZGUuY2hpbGRyZW47XG4gIGxldCBvbGRUcmVlTGVuZ3RoID0gb2xkVHJlZS5sZW5ndGg7XG4gIGxldCBuZXdUcmVlTGVuZ3RoID0gbmV3VHJlZS5sZW5ndGg7XG5cbiAgLy8gSWYgbmV3IHRyZWUgaXMgZW1wdHksIHJlbW92ZSBhbGwgb2xkIG5vZGVzXG4gIGlmIChuZXdUcmVlTGVuZ3RoID09PSAwKSB7XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBvbGRUcmVlTGVuZ3RoOyBpKyspIHtcbiAgICAgIG9ucmVtb3ZlKG9sZFRyZWVbaV0pO1xuICAgIH1cblxuICAgIG5ld1Zub2RlLmRvbS50ZXh0Q29udGVudCA9IFwiXCI7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgLy8gSWYgdGhlIHRyZWUgaXMga2V5ZWQgbGlzdCBhbmQgaXMgbm90IGZpcnN0IHJlbmRlciBhbmQgb2xkIHRyZWUgaXMga2V5ZWQgbGlzdCB0b29cbiAgaWYgKG9sZFRyZWVMZW5ndGggJiYgXCJrZXlcIiBpbiBuZXdUcmVlWzBdLnByb3BzICYmIFwia2V5XCIgaW4gb2xkVHJlZVswXS5wcm9wcykge1xuICAgIHBhdGNoS2V5ZWRUcmVlKG5ld1Zub2RlLCBuZXdUcmVlLCBvbGRUcmVlLCBuZXdUcmVlTGVuZ3RoLCBvbGRUcmVlTGVuZ3RoLCB2YWx5cmlhbkFwcCk7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgcGF0Y2hOb3JtYWxUcmVlKG5ld1Zub2RlLCBuZXdUcmVlLCBvbGRUcmVlLCBuZXdUcmVlTGVuZ3RoLCBvbGRUcmVlTGVuZ3RoLCB2YWx5cmlhbkFwcCk7XG59XG5cbi8qKiogRGlyZWN0aXZlcyAqKiovXG5cbmV4cG9ydCBmdW5jdGlvbiBkaXJlY3RpdmUobmFtZTogc3RyaW5nLCBkaXJlY3RpdmU6IERpcmVjdGl2ZSkge1xuICBsZXQgZnVsbE5hbWUgPSBgdi0ke25hbWV9YDtcbiAgdi5kaXJlY3RpdmVzW2Z1bGxOYW1lXSA9IGRpcmVjdGl2ZTtcbiAgdi5yZXNlcnZlZFByb3BzW2Z1bGxOYW1lXSA9IHRydWU7XG59XG5cbmZ1bmN0aW9uIGhpZGVEaXJlY3RpdmUodGVzdDogYm9vbGVhbik6IERpcmVjdGl2ZSB7XG4gIHJldHVybiAoYm9vbDogYm9vbGVhbiwgdm5vZGU6IElWbm9kZSwgb2xkVm5vZGU/OiBJVm5vZGUpID0+IHtcbiAgICBsZXQgdmFsdWUgPSB0ZXN0ID8gYm9vbCA6ICFib29sO1xuICAgIGlmICh2YWx1ZSkge1xuICAgICAgbGV0IG5ld2RvbSA9IGRvY3VtZW50LmNyZWF0ZVRleHROb2RlKFwiXCIpO1xuICAgICAgaWYgKG9sZFZub2RlICYmIG9sZFZub2RlLmRvbSAmJiBvbGRWbm9kZS5kb20ucGFyZW50Tm9kZSkge1xuICAgICAgICBvbGRWbm9kZS50YWcgIT09IFwiI3RleHRcIiAmJiBvbnJlbW92ZShvbGRWbm9kZSk7XG4gICAgICAgIG9sZFZub2RlLmRvbS5wYXJlbnROb2RlLnJlcGxhY2VDaGlsZChuZXdkb20sIG9sZFZub2RlLmRvbSk7XG4gICAgICB9XG4gICAgICB2bm9kZS50YWcgPSBcIiN0ZXh0XCI7XG4gICAgICB2bm9kZS5jaGlsZHJlbiA9IFtdO1xuICAgICAgdm5vZGUucHJvcHMgPSB7fTtcbiAgICAgIHZub2RlLmRvbSA9IG5ld2RvbSBhcyB1bmtub3duIGFzIERvbUVsZW1lbnQ7XG4gICAgfVxuICB9O1xufVxuXG5jb25zdCBidWlsdEluRGlyZWN0aXZlcyA9IHtcbiAgXCJ2LWlmXCI6IGhpZGVEaXJlY3RpdmUoZmFsc2UpLFxuICBcInYtdW5sZXNzXCI6IGhpZGVEaXJlY3RpdmUodHJ1ZSksXG4gIFwidi1mb3JcIjogKHNldDogdW5rbm93bltdLCB2bm9kZTogVm5vZGVXaXRoRG9tKSA9PiB7XG4gICAgdm5vZGUuY2hpbGRyZW4gPSBzZXQubWFwKHZub2RlLmNoaWxkcmVuWzBdIGFzICh2YWx1ZTogdW5rbm93bikgPT4gRnVuY3Rpb24pO1xuICB9LFxuICBcInYtc2hvd1wiOiAoYm9vbDogYm9vbGVhbiwgdm5vZGU6IFZub2RlV2l0aERvbSkgPT4ge1xuICAgICh2bm9kZS5kb20gYXMgdW5rbm93biBhcyB7IHN0eWxlOiB7IGRpc3BsYXk6IHN0cmluZyB9IH0pLnN0eWxlLmRpc3BsYXkgPSBib29sID8gXCJcIiA6IFwibm9uZVwiO1xuICB9LFxuICBcInYtY2xhc3NcIjogKGNsYXNzZXM6IHsgW3g6IHN0cmluZ106IGJvb2xlYW4gfSwgdm5vZGU6IFZub2RlV2l0aERvbSkgPT4ge1xuICAgIGZvciAobGV0IG5hbWUgaW4gY2xhc3Nlcykge1xuICAgICAgKHZub2RlLmRvbSBhcyBEb21FbGVtZW50KS5jbGFzc0xpc3QudG9nZ2xlKG5hbWUsIGNsYXNzZXNbbmFtZV0pO1xuICAgIH1cbiAgfSxcbiAgXCJ2LWh0bWxcIjogKGh0bWw6IHN0cmluZywgdm5vZGU6IFZub2RlV2l0aERvbSkgPT4ge1xuICAgIHZub2RlLmNoaWxkcmVuID0gW3RydXN0KGh0bWwpXTtcbiAgfSxcbiAgXCJ2LW1vZGVsXCI6IChbbW9kZWwsIHByb3BlcnR5LCBldmVudF06IGFueVtdLCB2bm9kZTogVm5vZGVXaXRoRG9tLCBvbGRWbm9kZT86IFZub2RlV2l0aERvbSkgPT4ge1xuICAgIGxldCB2YWx1ZTtcbiAgICBsZXQgaGFuZGxlcjtcbiAgICBpZiAodm5vZGUubmFtZSA9PT0gXCJpbnB1dFwiKSB7XG4gICAgICBldmVudCA9IGV2ZW50IHx8IFwib25pbnB1dFwiO1xuICAgICAgc3dpdGNoICh2bm9kZS5wcm9wcy50eXBlKSB7XG4gICAgICAgIGNhc2UgXCJjaGVja2JveFwiOiB7XG4gICAgICAgICAgaWYgKEFycmF5LmlzQXJyYXkobW9kZWxbcHJvcGVydHldKSkge1xuICAgICAgICAgICAgaGFuZGxlciA9IChlOiBFdmVudCkgPT4ge1xuICAgICAgICAgICAgICBsZXQgdmFsID0gKGUudGFyZ2V0IGFzIERvbUVsZW1lbnQgJiBSZWNvcmQ8c3RyaW5nLCBhbnk+KS52YWx1ZTtcbiAgICAgICAgICAgICAgbGV0IGlkeCA9IG1vZGVsW3Byb3BlcnR5XS5pbmRleE9mKHZhbCk7XG4gICAgICAgICAgICAgIGlmIChpZHggPT09IC0xKSB7XG4gICAgICAgICAgICAgICAgbW9kZWxbcHJvcGVydHldLnB1c2godmFsKTtcbiAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBtb2RlbFtwcm9wZXJ0eV0uc3BsaWNlKGlkeCwgMSk7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICB2YWx1ZSA9IG1vZGVsW3Byb3BlcnR5XS5pbmRleE9mKHZub2RlLmRvbS52YWx1ZSkgIT09IC0xO1xuICAgICAgICAgIH0gZWxzZSBpZiAoXCJ2YWx1ZVwiIGluIHZub2RlLnByb3BzKSB7XG4gICAgICAgICAgICBoYW5kbGVyID0gKCkgPT4ge1xuICAgICAgICAgICAgICBpZiAobW9kZWxbcHJvcGVydHldID09PSB2bm9kZS5wcm9wcy52YWx1ZSkge1xuICAgICAgICAgICAgICAgIG1vZGVsW3Byb3BlcnR5XSA9IG51bGw7XG4gICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgbW9kZWxbcHJvcGVydHldID0gdm5vZGUucHJvcHMudmFsdWU7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICB2YWx1ZSA9IG1vZGVsW3Byb3BlcnR5XSA9PT0gdm5vZGUucHJvcHMudmFsdWU7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGhhbmRsZXIgPSAoKSA9PiAobW9kZWxbcHJvcGVydHldID0gIW1vZGVsW3Byb3BlcnR5XSk7XG4gICAgICAgICAgICB2YWx1ZSA9IG1vZGVsW3Byb3BlcnR5XTtcbiAgICAgICAgICB9XG4gICAgICAgICAgc2V0UHJvcGVydHkoXCJjaGVja2VkXCIsIHZhbHVlLCB2bm9kZSwgb2xkVm5vZGUpO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgICAgIGNhc2UgXCJyYWRpb1wiOiB7XG4gICAgICAgICAgc2V0UHJvcGVydHkoXCJjaGVja2VkXCIsIG1vZGVsW3Byb3BlcnR5XSA9PT0gdm5vZGUuZG9tLnZhbHVlLCB2bm9kZSwgb2xkVm5vZGUpO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgICAgIGRlZmF1bHQ6IHtcbiAgICAgICAgICBzZXRQcm9wZXJ0eShcInZhbHVlXCIsIG1vZGVsW3Byb3BlcnR5XSwgdm5vZGUsIG9sZFZub2RlKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0gZWxzZSBpZiAodm5vZGUubmFtZSA9PT0gXCJzZWxlY3RcIikge1xuICAgICAgZXZlbnQgPSBldmVudCB8fCBcIm9uY2xpY2tcIjtcbiAgICAgIGlmICh2bm9kZS5wcm9wcy5tdWx0aXBsZSkge1xuICAgICAgICBoYW5kbGVyID0gKGU6IEV2ZW50ICYgUmVjb3JkPHN0cmluZywgYW55PikgPT4ge1xuICAgICAgICAgIGxldCB2YWwgPSAoZS50YXJnZXQgYXMgRG9tRWxlbWVudCAmIFJlY29yZDxzdHJpbmcsIGFueT4pLnZhbHVlO1xuICAgICAgICAgIGlmIChlLmN0cmxLZXkpIHtcbiAgICAgICAgICAgIGxldCBpZHggPSBtb2RlbFtwcm9wZXJ0eV0uaW5kZXhPZih2YWwpO1xuICAgICAgICAgICAgaWYgKGlkeCA9PT0gLTEpIHtcbiAgICAgICAgICAgICAgbW9kZWxbcHJvcGVydHldLnB1c2godmFsKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIG1vZGVsW3Byb3BlcnR5XS5zcGxpY2UoaWR4LCAxKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgbW9kZWxbcHJvcGVydHldLnNwbGljZSgwLCBtb2RlbFtwcm9wZXJ0eV0ubGVuZ3RoKTtcbiAgICAgICAgICAgIG1vZGVsW3Byb3BlcnR5XS5wdXNoKHZhbCk7XG4gICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICB2bm9kZS5jaGlsZHJlbi5mb3JFYWNoKChjaGlsZCkgPT4ge1xuICAgICAgICAgIGlmIChjaGlsZC5uYW1lID09PSBcIm9wdGlvblwiKSB7XG4gICAgICAgICAgICBsZXQgdmFsdWUgPSBcInZhbHVlXCIgaW4gY2hpbGQucHJvcHMgPyBjaGlsZC5wcm9wcy52YWx1ZSA6IGNoaWxkLmNoaWxkcmVuLmpvaW4oXCJcIikudHJpbSgpO1xuICAgICAgICAgICAgY2hpbGQucHJvcHMuc2VsZWN0ZWQgPSBtb2RlbFtwcm9wZXJ0eV0uaW5kZXhPZih2YWx1ZSkgIT09IC0xO1xuICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB2bm9kZS5jaGlsZHJlbi5mb3JFYWNoKChjaGlsZCkgPT4ge1xuICAgICAgICAgIGlmIChjaGlsZC5uYW1lID09PSBcIm9wdGlvblwiKSB7XG4gICAgICAgICAgICBsZXQgdmFsdWUgPSBcInZhbHVlXCIgaW4gY2hpbGQucHJvcHMgPyBjaGlsZC5wcm9wcy52YWx1ZSA6IGNoaWxkLmNoaWxkcmVuLmpvaW4oXCJcIikudHJpbSgpO1xuICAgICAgICAgICAgY2hpbGQucHJvcHMuc2VsZWN0ZWQgPSB2YWx1ZSA9PT0gbW9kZWxbcHJvcGVydHldO1xuICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgfSBlbHNlIGlmICh2bm9kZS5uYW1lID09PSBcInRleHRhcmVhXCIpIHtcbiAgICAgIGV2ZW50ID0gZXZlbnQgfHwgXCJvbmlucHV0XCI7XG4gICAgICB2bm9kZS5jaGlsZHJlbiA9IFttb2RlbFtwcm9wZXJ0eV1dO1xuICAgIH1cblxuICAgIGlmICghdm5vZGUucHJvcHNbZXZlbnRdKSB7XG4gICAgICBpZiAoIWhhbmRsZXIpIHtcbiAgICAgICAgaGFuZGxlciA9IChlOiBFdmVudCkgPT4gKG1vZGVsW3Byb3BlcnR5XSA9IChlLnRhcmdldCBhcyBEb21FbGVtZW50ICYgUmVjb3JkPHN0cmluZywgYW55PikudmFsdWUpO1xuICAgICAgfVxuICAgICAgc2V0UHJvcGVydHkoZXZlbnQsIGhhbmRsZXIsIHZub2RlLCBvbGRWbm9kZSk7XG4gICAgfVxuICB9XG59O1xuXG4vKioqIEh5cGVyc2NyaXB0ICoqKi9cblxuZXhwb3J0IGNvbnN0IHY6IFZhbHlyaWFuID0gZnVuY3Rpb24gdih0YWdPckNvbXBvbmVudDogc3RyaW5nIHwgVmFseXJpYW5Db21wb25lbnQsIHByb3BzOiBQcm9wcywgLi4uY2hpbGRyZW46IENoaWxkcmVuKTogSVZub2RlIHwgVm5vZGVDb21wb25lbnQge1xuICBpZiAodHlwZW9mIHRhZ09yQ29tcG9uZW50ID09PSBcInN0cmluZ1wiKSB7XG4gICAgcmV0dXJuIG5ldyBWbm9kZSh0YWdPckNvbXBvbmVudCwgcHJvcHMgfHwge30sIGNoaWxkcmVuKTtcbiAgfVxuXG4gIGNvbnN0IHZub2RlID0gbmV3IFZub2RlKFwiX19jb21wb25lbnRfX1wiLCBwcm9wcyB8fCB7fSwgY2hpbGRyZW4pO1xuICB2bm9kZS5jb21wb25lbnQgPSB0YWdPckNvbXBvbmVudDtcbiAgcmV0dXJuIHZub2RlIGFzIFZub2RlQ29tcG9uZW50O1xufTtcblxudi5mcmFnbWVudCA9IChwcm9wczogUHJvcHMsIC4uLmNoaWxkcmVuOiBDaGlsZHJlbik6IENoaWxkcmVuID0+IHtcbiAgcmV0dXJuIGNoaWxkcmVuO1xufTtcblxudi5jdXJyZW50ID0ge30gYXMgQ3VycmVudDtcblxudi5kaXJlY3RpdmVzID0geyAuLi5idWlsdEluRGlyZWN0aXZlcyB9O1xuXG52LnJlc2VydmVkUHJvcHMgPSB7XG4gIGtleTogdHJ1ZSxcbiAgc3RhdGU6IHRydWUsXG4gIG9uY3JlYXRlOiB0cnVlLFxuICBvbnVwZGF0ZTogdHJ1ZSxcbiAgb25yZW1vdmU6IHRydWUsXG4gIHNob3VsZHVwZGF0ZTogdHJ1ZSxcbiAgXCJ2LWNsZWFudXBcIjogdHJ1ZSxcbiAgXCJ2LW9uY2VcIjogdHJ1ZSxcblxuICAvLyBCdWlsdCBpbiBkaXJlY3RpdmVzXG4gIFwidi1pZlwiOiB0cnVlLFxuICBcInYtdW5sZXNzXCI6IHRydWUsXG4gIFwidi1mb3JcIjogdHJ1ZSxcbiAgXCJ2LXNob3dcIjogdHJ1ZSxcbiAgXCJ2LWNsYXNzXCI6IHRydWUsXG4gIFwidi1odG1sXCI6IHRydWVcbn07XG5cbigoaXNOb2RlSnMgPyBnbG9iYWwgOiB3aW5kb3cpIGFzIHVua25vd24gYXMgeyB2OiBWYWx5cmlhbiB9KS52ID0gdiBhcyBWYWx5cmlhbjtcbiJdfQ== \ No newline at end of file +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL2xpYi9pbmRleC50cyJdLCJuYW1lcyI6WyJWbm9kZSIsInRhZyIsInByb3BzIiwiY2hpbGRyZW4iLCJ0aGlzIiwiaXNWbm9kZSIsIm9iamVjdCIsImlzQ29tcG9uZW50IiwiY29tcG9uZW50IiwiaXNWbm9kZUNvbXBvbmVudCIsInZub2RlIiwiaXNOb2RlSnMiLCJCb29sZWFuIiwicHJvY2VzcyIsInZlcnNpb25zIiwibm9kZSIsImNyZWF0ZURvbUVsZW1lbnQiLCJpc1NWRyIsImRvY3VtZW50IiwiY3JlYXRlRWxlbWVudE5TIiwiY3JlYXRlRWxlbWVudCIsImRvbVRvVm5vZGUiLCJkb20iLCJ2IiwidGFnTmFtZSIsInRvTG93ZXJDYXNlIiwiQXJyYXkiLCJmcm9tIiwiY2hpbGROb2RlcyIsImZpbHRlciIsImNoaWxkIiwibm9kZVR5cGUiLCJtYXAiLCJ0ZXh0Iiwibm9kZVZhbHVlIiwiU3RyaW5nIiwiZm9yRWFjaCIsImNhbGwiLCJhdHRyaWJ1dGVzIiwicHJvcCIsIm5vZGVOYW1lIiwidHJ1c3QiLCJodG1sU3RyaW5nIiwiZGl2IiwiaW5uZXJIVE1MIiwidHJpbSIsIml0ZW0iLCJWYWx5cmlhblN5bWJvbCIsIlN5bWJvbCIsIm9uQ2xlYW51cCIsImNhbGxiYWNrIiwiY3VycmVudCIsImFwcCIsImluZGV4T2YiLCJwdXNoIiwib25Vbm1vdW50Iiwib25Nb3VudCIsIm9uVXBkYXRlIiwibW91bnQiLCJjb250YWluZXIiLCJ2bm9kZUNvbXBvbmVudCIsImFwcENvbnRhaW5lciIsInF1ZXJ5U2VsZWN0b3JBbGwiLCJFcnJvciIsInVubW91bnQiLCJldmVudExpc3RlbmVyIiwiZSIsInRhcmdldCIsIm5hbWUiLCJ0eXBlIiwiZGVmYXVsdFByZXZlbnRlZCIsInVwZGF0ZSIsInBhcmVudE5vZGUiLCJpc01vdW50ZWQiLCJldmVudExpc3RlbmVyTmFtZXMiLCJtYWluVm5vZGUiLCJjYWxsQ2xlYW51cCIsInZhbHlyaWFuQXBwIiwiaSIsImxlbmd0aCIsIm9sZFZub2RlIiwicGF0Y2giLCJjYWxsTW91bnQiLCJjYWxsVXBkYXRlIiwiY2FsbFVubW91bnQiLCJSZWZsZWN0IiwiZGVsZXRlUHJvcGVydHkiLCJlbXB0eVZub2RlIiwib25yZW1vdmUiLCJzaGFyZWRTZXRBdHRyaWJ1dGUiLCJ2YWx1ZSIsInJlc2VydmVkUHJvcHMiLCJkaXJlY3RpdmVzIiwiYWRkRXZlbnRMaXN0ZW5lciIsInNsaWNlIiwicmVtb3ZlQXR0cmlidXRlIiwic2V0QXR0cmlidXRlIiwidXBkYXRlQXR0cmlidXRlcyIsIm5ld1Zub2RlIiwibmV3VHJlZSIsImNoaWxkVm5vZGUiLCJyZXN1bHQiLCJ2aWV3Iiwic3BsaWNlIiwiaXNBcnJheSIsImZsYXRUcmVlIiwib2xkVHJlZSIsIm9sZFRyZWVMZW5ndGgiLCJuZXdUcmVlTGVuZ3RoIiwib2xkS2V5ZWRMaXN0IiwicmVkdWNlIiwiYWNjIiwia2V5IiwibmV3S2V5ZWRMaXN0Iiwib2xkQ2hpbGRWbm9kZSIsInNob3VsZFBhdGNoIiwic2hvdWxkdXBkYXRlIiwib251cGRhdGUiLCJvbmNyZWF0ZSIsImFwcGVuZENoaWxkIiwicmVwbGFjZUNoaWxkIiwicmVtb3ZlQ2hpbGQiLCJwYXRjaEtleWVkVHJlZSIsIm5ld0NoaWxkVm5vZGUiLCJjcmVhdGVUZXh0Tm9kZSIsInBhdGNoTm9ybWFsVHJlZSIsInRleHRDb250ZW50IiwiZGlyZWN0aXZlIiwiZGlyZWN0aXZlMiIsImZ1bGxOYW1lIiwiaGlkZURpcmVjdGl2ZSIsInRlc3QiLCJib29sIiwibmV3ZG9tIiwiYnVpbHRJbkRpcmVjdGl2ZXMiLCJzZXQiLCJzdHlsZSIsImRpc3BsYXkiLCJjbGFzc2VzIiwiY2xhc3NMaXN0IiwidG9nZ2xlIiwiaHRtbCIsIm1vZGVsIiwicHJvcGVydHkiLCJldmVudCIsImhhbmRsZXIiLCJ2YWwiLCJpZHgiLCJtdWx0aXBsZSIsImN0cmxLZXkiLCJ2YWx1ZTIiLCJqb2luIiwic2VsZWN0ZWQiLCJwbHVnaW5zIiwiTWFwIiwidXNlIiwicGx1Z2luIiwib3B0aW9u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RXBCL0csRUFBRW9FLGNBQWdCLENBQ2hCcUIsS0FBSyxFQUNMa0QsT0FBTyxFQUNQNUMsVUFBVSxFQUNWRCxVQUFVLEVBQ1Y3QixVQUFVLEVBQ1Y0QixjQUFjLEVBQ2QsYUFBYSxFQUNiLFVBQVUsRUFHVixRQUFRLEVBQ1IsWUFBWSxFQUNaLFNBQVMsRUFDVCxVQUFVLEVBQ1YsV0FBVyxFQUNYLFVBQVUsR0FHWjdGLEVBQUVsQixRQUFVQSxFQUNaa0IsRUFBRWhCLFlBQWNBLEVBQ2hCZ0IsRUFBRWQsaUJBQW1CQSxFQUVyQmMsRUFBRVosU0FBV0EsRUFDYlksRUFBRWtCLE1BQVFBLEVBRVZsQixFQUFFMEIsVUFBWUEsRUFDZDFCLEVBQUVnQyxVQUFZQSxFQUNkaEMsRUFBRWlDLFFBQVVBLEVBQ1pqQyxFQUFFa0MsU0FBV0EsRUFFYmxDLEVBQUVtQyxNQUFRQSxFQUNWbkMsRUFBRXlDLFFBQVVBLEVBQ1p6QyxFQUFFZ0QsT0FBU0EsRUFFWGhELEVBQUV5RSxhQUFlQSxFQUNqQnpFLEVBQUV3RyxVQUFZQSxFQUNkeEcsRUFBRW9JLElBQU1BIiwic291cmNlc0NvbnRlbnQiOlsiLyoqKiBWbm9kZSAqKiovXG5cbmltcG9ydCB7XG4gIENoaWxkcmVuLFxuICBDdXJyZW50LFxuICBEaXJlY3RpdmUsXG4gIERvbUVsZW1lbnQsXG4gIElWbm9kZSxcbiAgTW91bnRlZFZhbHlyaWFuQXBwLFxuICBQbHVnaW4sXG4gIFByb3BzLFxuICBWYWx5cmlhbixcbiAgVmFseXJpYW5BcHAsXG4gIFZhbHlyaWFuQ29tcG9uZW50LFxuICBWbm9kZUNvbXBvbmVudCxcbiAgVm5vZGVXaXRoRG9tXG59IGZyb20gXCIuL2ludGVyZmFjZXNcIjtcblxuZXhwb3J0IGNvbnN0IFZub2RlID0gZnVuY3Rpb24gVm5vZGUodGhpczogSVZub2RlLCB0YWc6IHN0cmluZywgcHJvcHM6IFByb3BzLCBjaGlsZHJlbjogQ2hpbGRyZW4pIHtcbiAgdGhpcy5wcm9wcyA9IHByb3BzO1xuICB0aGlzLmNoaWxkcmVuID0gY2hpbGRyZW47XG4gIHRoaXMudGFnID0gdGFnO1xufSBhcyB1bmtub3duIGFzIElWbm9kZTtcblxuZXhwb3J0IGZ1bmN0aW9uIGlzVm5vZGUob2JqZWN0PzogdW5rbm93biB8IElWbm9kZSk6IG9iamVjdCBpcyBJVm5vZGUge1xuICByZXR1cm4gb2JqZWN0IGluc3RhbmNlb2YgVm5vZGU7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBpc0NvbXBvbmVudChjb21wb25lbnQ/OiB1bmtub3duIHwgVmFseXJpYW5Db21wb25lbnQpOiBjb21wb25lbnQgaXMgVmFseXJpYW5Db21wb25lbnQge1xuICByZXR1cm4gdHlwZW9mIGNvbXBvbmVudCA9PT0gXCJmdW5jdGlvblwiIHx8ICh0eXBlb2YgY29tcG9uZW50ID09PSBcIm9iamVjdFwiICYmIGNvbXBvbmVudCAhPT0gbnVsbCAmJiBcInZpZXdcIiBpbiBjb21wb25lbnQpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gaXNWbm9kZUNvbXBvbmVudCh2bm9kZT86IHVua25vd24gfCBWbm9kZUNvbXBvbmVudCk6IHZub2RlIGlzIFZub2RlQ29tcG9uZW50IHtcbiAgcmV0dXJuIHZub2RlIGluc3RhbmNlb2YgVm5vZGUgJiYgdm5vZGUudGFnID09PSBcIl9fY29tcG9uZW50X19cIjtcbn1cblxuLyoqKiBVdGlsICoqKi9cblxuZXhwb3J0IGNvbnN0IGlzTm9kZUpzID0gQm9vbGVhbih0eXBlb2YgcHJvY2VzcyAhPT0gXCJ1bmRlZmluZWRcIiAmJiBwcm9jZXNzLnZlcnNpb25zICYmIHByb2Nlc3MudmVyc2lvbnMubm9kZSk7XG5cbmZ1bmN0aW9uIGNyZWF0ZURvbUVsZW1lbnQodGFnOiBzdHJpbmcsIGlzU1ZHOiBib29sZWFuID0gZmFsc2UpIHtcbiAgcmV0dXJuIGlzU1ZHID8gZG9jdW1lbnQuY3JlYXRlRWxlbWVudE5TKFwiaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmdcIiwgdGFnKSA6IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQodGFnKTtcbn1cblxuZnVuY3Rpb24gZG9tVG9Wbm9kZShkb206IERvbUVsZW1lbnQpOiBWbm9kZVdpdGhEb20ge1xuICBsZXQgdm5vZGUgPSB2KFxuICAgIGRvbS50YWdOYW1lLnRvTG93ZXJDYXNlKCksXG4gICAge30sXG4gICAgLi4uQXJyYXkuZnJvbShkb20uY2hpbGROb2RlcylcbiAgICAgIC5maWx0ZXIoKGNoaWxkKSA9PiAoY2hpbGQgYXMgRG9tRWxlbWVudCkubm9kZVR5cGUgPT09IDEgfHwgKGNoaWxkIGFzIERvbUVsZW1lbnQpLm5vZGVUeXBlID09PSAzKVxuICAgICAgLm1hcCgoY2hpbGQpID0+IHtcbiAgICAgICAgaWYgKChjaGlsZCBhcyBEb21FbGVtZW50KS5ub2RlVHlwZSA9PT0gMSkge1xuICAgICAgICAgIHJldHVybiBkb21Ub1Zub2RlKGNoaWxkIGFzIERvbUVsZW1lbnQpO1xuICAgICAgICB9XG5cbiAgICAgICAgbGV0IHRleHQgPSBuZXcgVm5vZGUoXCIjdGV4dFwiLCB7fSwgW10pO1xuICAgICAgICB0ZXh0Lm5vZGVWYWx1ZSA9IFN0cmluZygoY2hpbGQgYXMgRG9tRWxlbWVudCkubm9kZVZhbHVlKTtcbiAgICAgICAgdGV4dC5kb20gPSBjaGlsZCBhcyBEb21FbGVtZW50O1xuICAgICAgICByZXR1cm4gdGV4dDtcbiAgICAgIH0pXG4gICk7XG4gIFtdLmZvckVhY2guY2FsbChkb20uYXR0cmlidXRlcywgKHByb3A6IEF0dHIpID0+ICh2bm9kZS5wcm9wc1twcm9wLm5vZGVOYW1lXSA9IHByb3Aubm9kZVZhbHVlKSk7XG4gIHZub2RlLmRvbSA9IGRvbTtcbiAgcmV0dXJuIHZub2RlIGFzIFZub2RlV2l0aERvbTtcbn1cblxuZXhwb3J0IGNvbnN0IHRydXN0ID0gKGh0bWxTdHJpbmc6IHN0cmluZyk6IElWbm9kZVtdID0+IHtcbiAgbGV0IGRpdiA9IGNyZWF0ZURvbUVsZW1lbnQoXCJkaXZcIik7XG4gIGRpdi5pbm5lckhUTUwgPSBodG1sU3RyaW5nLnRyaW0oKTtcblxuICByZXR1cm4gW10ubWFwLmNhbGwoZGl2LmNoaWxkTm9kZXMsIChpdGVtKSA9PiBkb21Ub1Zub2RlKGl0ZW0pKSBhcyBJVm5vZGVbXTtcbn07XG5cbi8qKiogTW91bnQgKioqL1xuXG5jb25zdCBWYWx5cmlhblN5bWJvbCA9IFN5bWJvbChcIlZhbHlyaWFuXCIpO1xuXG5leHBvcnQgZnVuY3Rpb24gb25DbGVhbnVwKGNhbGxiYWNrOiBGdW5jdGlvbikge1xuICBpZiAodi5jdXJyZW50LmFwcD8ub25DbGVhbnVwLmluZGV4T2YoY2FsbGJhY2spID09PSAtMSkge1xuICAgIHYuY3VycmVudC5hcHA/Lm9uQ2xlYW51cC5wdXNoKGNhbGxiYWNrKTtcbiAgfVxufVxuXG5leHBvcnQgZnVuY3Rpb24gb25Vbm1vdW50KGNhbGxiYWNrOiBGdW5jdGlvbikge1xuICBpZiAodi5jdXJyZW50LmFwcD8ub25Vbm1vdW50LmluZGV4T2YoY2FsbGJhY2spID09PSAtMSkge1xuICAgIHYuY3VycmVudC5hcHA/Lm9uVW5tb3VudC5wdXNoKGNhbGxiYWNrKTtcbiAgfVxufVxuXG5leHBvcnQgZnVuY3Rpb24gb25Nb3VudChjYWxsYmFjazogRnVuY3Rpb24pIHtcbiAgaWYgKHYuY3VycmVudC5hcHA/Lm9uTW91bnQuaW5kZXhPZihjYWxsYmFjaykgPT09IC0xKSB7XG4gICAgdi5jdXJyZW50LmFwcD8ub25Nb3VudC5wdXNoKGNhbGxiYWNrKTtcbiAgfVxufVxuXG5leHBvcnQgZnVuY3Rpb24gb25VcGRhdGUoY2FsbGJhY2s6IEZ1bmN0aW9uKSB7XG4gIGlmICh2LmN1cnJlbnQuYXBwPy5vblVwZGF0ZS5pbmRleE9mKGNhbGxiYWNrKSA9PT0gLTEpIHtcbiAgICB2LmN1cnJlbnQuYXBwPy5vblVwZGF0ZS5wdXNoKGNhbGxiYWNrKTtcbiAgfVxufVxuXG4vKlxuICAqIE1vdW50cyBhIGNvbXBvbmVudCB0byB0aGUgRE9NXG4gIG1vdW50KCcjYXBwJywgKCkgPT4gPGRpdj5IZWxsbyB3b3JsZDwvZGl2Pik7IC8vIEFwcCBpcyBhIEZ1bmN0aW9uYWwgQ29tcG9uZW50XG4gIG1vdW50KCcjYXBwJywgeyB2aWV3OiAoKSA9PiA8ZGl2PkhlbGxvIHdvcmxkPC9kaXY+IH0pOyAvLyBBcHAgaXMgYSBQT0pPIGNvbXBvbmVudCB3aXRoIGEgdmlldyBtZXRob2RcbiAgbW91bnQoJyNhcHAnLCBjbGFzc0luc3RhbmNlKTsgLy8gQXBwIGlzIGEgY2xhc3MgaW5zdGFuY2Ugd2l0aCBhIHZpZXcgbWV0aG9kXG4gIG1vdW50KCcjYXBwJywgPEFwcD48ZGl2PkhlbGxvIHdvcmxkPC9kaXY+PC9BcHA+KTsgLy8gQXBwIGlzIGEgVm5vZGUgY29tcG9uZW50IChWbm9kZSB3aXRoIHRhZyBfX2NvbXBvbmVudF9fKVxuKi9cblxuZXhwb3J0IGZ1bmN0aW9uIG1vdW50KGNvbnRhaW5lcjogRG9tRWxlbWVudCB8IHN0cmluZywgY29tcG9uZW50OiBWYWx5cmlhbkNvbXBvbmVudCB8IElWbm9kZSk6IHZvaWQgfCBzdHJpbmcge1xuICBsZXQgYXBwQ29udGFpbmVyID0gbnVsbDtcblxuICBpZiAoaXNOb2RlSnMpIHtcbiAgICBhcHBDb250YWluZXIgPSB0eXBlb2YgY29udGFpbmVyID09PSBcInN0cmluZ1wiID8gY3JlYXRlRG9tRWxlbWVudChjb250YWluZXIgPT09IFwic3ZnXCIgPyBcInN2Z1wiIDogXCJkaXZcIiwgY29udGFpbmVyID09PSBcInN2Z1wiKSA6IGNvbnRhaW5lcjtcbiAgfSBlbHNlIHtcbiAgICBhcHBDb250YWluZXIgPSB0eXBlb2YgY29udGFpbmVyID09PSBcInN0cmluZ1wiID8gZG9jdW1lbnQucXVlcnlTZWxlY3RvckFsbChjb250YWluZXIpWzBdIDogY29udGFpbmVyO1xuICB9XG5cbiAgaWYgKCFhcHBDb250YWluZXIpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoXCJDb250YWluZXIgbm90IGZvdW5kXCIpO1xuICB9XG5cbiAgbGV0IHZub2RlQ29tcG9uZW50OiBWbm9kZUNvbXBvbmVudCB8IElWbm9kZTtcblxuICBpZiAoaXNWbm9kZUNvbXBvbmVudChjb21wb25lbnQpKSB7XG4gICAgdm5vZGVDb21wb25lbnQgPSBjb21wb25lbnQ7XG4gIH0gZWxzZSBpZiAoaXNDb21wb25lbnQoY29tcG9uZW50KSkge1xuICAgIHZub2RlQ29tcG9uZW50ID0gdihjb21wb25lbnQsIHt9KTtcbiAgfSBlbHNlIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoXCJDb21wb25lbnQgbXVzdCBiZSBhIFZhbHlyaWFuIENvbXBvbmVudCBvciBhIFZub2RlIGNvbXBvbmVudFwiKTtcbiAgfVxuXG4gIGlmIChjb21wb25lbnRbVmFseXJpYW5TeW1ib2xdKSB7XG4gICAgdW5tb3VudChjb21wb25lbnQpO1xuICB9IGVsc2Uge1xuICAgIGNvbXBvbmVudFtWYWx5cmlhblN5bWJvbF0gPSB7XG4gICAgICBpc01vdW50ZWQ6IGZhbHNlLFxuICAgICAgZXZlbnRMaXN0ZW5lck5hbWVzOiB7fSxcbiAgICAgIG9uQ2xlYW51cDogW10sXG4gICAgICBvbk1vdW50OiBbXSxcbiAgICAgIG9uVXBkYXRlOiBbXSxcbiAgICAgIG9uVW5tb3VudDogW11cbiAgICB9O1xuICAgIGZ1bmN0aW9uIGV2ZW50TGlzdGVuZXIoZTogRXZlbnQpIHtcbiAgICAgIGxldCBkb20gPSBlLnRhcmdldCBhcyBEb21FbGVtZW50ICYgUmVjb3JkPHN0cmluZywgYW55PjtcbiAgICAgIGxldCBuYW1lID0gYHYtb24ke2UudHlwZX1gO1xuICAgICAgd2hpbGUgKGRvbSkge1xuICAgICAgICBpZiAoZG9tW25hbWVdKSB7XG4gICAgICAgICAgZG9tW25hbWVdKGUsIGRvbSk7XG4gICAgICAgICAgaWYgKCFlLmRlZmF1bHRQcmV2ZW50ZWQpIHtcbiAgICAgICAgICAgIHVwZGF0ZShjb21wb25lbnQpO1xuICAgICAgICAgIH1cbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgZG9tID0gZG9tLnBhcmVudE5vZGUgYXMgRG9tRWxlbWVudDtcbiAgICAgIH1cbiAgICB9XG4gICAgY29tcG9uZW50W1ZhbHlyaWFuU3ltYm9sXS5ldmVudExpc3RlbmVyID0gZXZlbnRMaXN0ZW5lcjtcbiAgfVxuXG4gIGNvbXBvbmVudFtWYWx5cmlhblN5bWJvbF0uY29tcG9uZW50ID0gdm5vZGVDb21wb25lbnQ7XG4gIGNvbXBvbmVudFtWYWx5cmlhblN5bWJvbF0uY29udGFpbmVyID0gYXBwQ29udGFpbmVyO1xuICBjb21wb25lbnRbVmFseXJpYW5TeW1ib2xdLm1haW5Wbm9kZSA9IGRvbVRvVm5vZGUoYXBwQ29udGFpbmVyKTtcbiAgY29tcG9uZW50W1ZhbHlyaWFuU3ltYm9sXS5tYWluVm5vZGUuaXNTVkcgPSBjb21wb25lbnRbVmFseXJpYW5TeW1ib2xdLnRhZyA9PT0gXCJzdmdcIjtcblxuICAvLyB1cGRhdGVcbiAgcmV0dXJuIHVwZGF0ZShjb21wb25lbnQpO1xufVxuXG5mdW5jdGlvbiBjYWxsQ2xlYW51cCh2YWx5cmlhbkFwcDogVmFseXJpYW5BcHApIHtcbiAgZm9yIChsZXQgaSA9IDA7IGkgPCB2YWx5cmlhbkFwcC5vbkNsZWFudXAubGVuZ3RoOyBpKyspIHtcbiAgICB2YWx5cmlhbkFwcC5vbkNsZWFudXBbaV0oKTtcbiAgfVxuICB2YWx5cmlhbkFwcC5vbkNsZWFudXAgPSBbXTtcbn1cblxuZnVuY3Rpb24gY2FsbFVubW91bnQodmFseXJpYW5BcHA6IFZhbHlyaWFuQXBwKSB7XG4gIGZvciAobGV0IGkgPSAwOyBpIDwgdmFseXJpYW5BcHAub25Vbm1vdW50Lmxlbmd0aDsgaSsrKSB7XG4gICAgdmFseXJpYW5BcHAub25Vbm1vdW50W2ldKCk7XG4gIH1cbiAgdmFseXJpYW5BcHAub25Vbm1vdW50ID0gW107XG59XG5cbmZ1bmN0aW9uIGNhbGxNb3VudCh2YWx5cmlhbkFwcDogVmFseXJpYW5BcHApIHtcbiAgZm9yIChsZXQgaSA9IDA7IGkgPCB2YWx5cmlhbkFwcC5vbk1vdW50Lmxlbmd0aDsgaSsrKSB7XG4gICAgdmFseXJpYW5BcHAub25Nb3VudFtpXSgpO1xuICB9XG4gIHZhbHlyaWFuQXBwLm9uTW91bnQgPSBbXTtcbn1cblxuZnVuY3Rpb24gY2FsbFVwZGF0ZSh2YWx5cmlhbkFwcDogVmFseXJpYW5BcHApIHtcbiAgZm9yIChsZXQgaSA9IDA7IGkgPCB2YWx5cmlhbkFwcC5vblVwZGF0ZS5sZW5ndGg7IGkrKykge1xuICAgIHZhbHlyaWFuQXBwLm9uVXBkYXRlW2ldKCk7XG4gIH1cbiAgdmFseXJpYW5BcHAub25VcGRhdGUgPSBbXTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHVwZGF0ZShjb21wb25lbnQ/OiBWYWx5cmlhbkNvbXBvbmVudCB8IElWbm9kZSk6IHZvaWQgfCBzdHJpbmcge1xuICBpZiAoY29tcG9uZW50ICYmIGNvbXBvbmVudFtWYWx5cmlhblN5bWJvbF0pIHtcbiAgICBsZXQgdmFseXJpYW5BcHAgPSBjb21wb25lbnRbVmFseXJpYW5TeW1ib2xdO1xuICAgIHYuY3VycmVudC5hcHAgPSB2YWx5cmlhbkFwcDtcbiAgICB2YWx5cmlhbkFwcC5vbkNsZWFudXAubGVuZ3RoICYmIGNhbGxDbGVhbnVwKHZhbHlyaWFuQXBwKTtcbiAgICBsZXQgb2xkVm5vZGU6IFZub2RlV2l0aERvbSB8IG51bGwgPSB2YWx5cmlhbkFwcC5tYWluVm5vZGUgYXMgVm5vZGVXaXRoRG9tO1xuICAgIHZhbHlyaWFuQXBwLm1haW5Wbm9kZSA9IG5ldyBWbm9kZSh2YWx5cmlhbkFwcC5tYWluVm5vZGUudGFnLCB2YWx5cmlhbkFwcC5tYWluVm5vZGUucHJvcHMsIFt2YWx5cmlhbkFwcC5jb21wb25lbnRdKSBhcyBWbm9kZVdpdGhEb207XG4gICAgdmFseXJpYW5BcHAubWFpblZub2RlLmRvbSA9IG9sZFZub2RlLmRvbTtcbiAgICB2YWx5cmlhbkFwcC5tYWluVm5vZGUuaXNTVkcgPSBvbGRWbm9kZS5pc1NWRztcbiAgICBwYXRjaCh2YWx5cmlhbkFwcC5tYWluVm5vZGUsIG9sZFZub2RlLCB2YWx5cmlhbkFwcCk7XG4gICAgb2xkVm5vZGUgPSBudWxsO1xuICAgIGlmICh2YWx5cmlhbkFwcC5pc01vdW50ZWQgPT09IGZhbHNlKSB7XG4gICAgICB2YWx5cmlhbkFwcC5vbk1vdW50Lmxlbmd0aCAmJiBjYWxsTW91bnQodmFseXJpYW5BcHApO1xuICAgICAgdmFseXJpYW5BcHAuaXNNb3VudGVkID0gdHJ1ZTtcbiAgICB9IGVsc2Uge1xuICAgICAgdmFseXJpYW5BcHAub25VcGRhdGUubGVuZ3RoICYmIGNhbGxVcGRhdGUodmFseXJpYW5BcHApO1xuICAgIH1cblxuICAgIGlmIChpc05vZGVKcykge1xuICAgICAgcmV0dXJuIHZhbHlyaWFuQXBwLm1haW5Wbm9kZS5kb20uaW5uZXJIVE1MO1xuICAgIH1cbiAgfVxufVxuXG5leHBvcnQgZnVuY3Rpb24gdW5tb3VudChjb21wb25lbnQ/OiBWYWx5cmlhbkNvbXBvbmVudCB8IElWbm9kZSk6IHZvaWQgfCBzdHJpbmcge1xuICBpZiAoIWNvbXBvbmVudCB8fCAhY29tcG9uZW50W1ZhbHlyaWFuU3ltYm9sXSkge1xuICAgIHJldHVybjtcbiAgfVxuXG4gIGxldCB2YWx5cmlhbkFwcCA9IGNvbXBvbmVudFtWYWx5cmlhblN5bWJvbF0gYXMgTW91bnRlZFZhbHlyaWFuQXBwO1xuXG4gIGlmICh2YWx5cmlhbkFwcC5pc01vdW50ZWQpIHtcbiAgICB2YWx5cmlhbkFwcC5vbkNsZWFudXAubGVuZ3RoICYmIGNhbGxDbGVhbnVwKHZhbHlyaWFuQXBwKTtcbiAgICB2YWx5cmlhbkFwcC5vblVubW91bnQubGVuZ3RoICYmIGNhbGxVbm1vdW50KHZhbHlyaWFuQXBwKTtcbiAgICBsZXQgb2xkVm5vZGU6IFZub2RlV2l0aERvbSB8IG51bGwgPSB2YWx5cmlhbkFwcC5tYWluVm5vZGUgYXMgVm5vZGVXaXRoRG9tO1xuICAgIHZhbHlyaWFuQXBwLm1haW5Wbm9kZSA9IG5ldyBWbm9kZSh2YWx5cmlhbkFwcC5tYWluVm5vZGUudGFnLCB2YWx5cmlhbkFwcC5tYWluVm5vZGUucHJvcHMsIFtdKSBhcyBWbm9kZVdpdGhEb207XG4gICAgdmFseXJpYW5BcHAubWFpblZub2RlLmRvbSA9IG9sZFZub2RlLmRvbTtcbiAgICB2YWx5cmlhbkFwcC5tYWluVm5vZGUuaXNTVkcgPSBvbGRWbm9kZS5pc1NWRztcbiAgICBwYXRjaCh2YWx5cmlhbkFwcC5tYWluVm5vZGUsIG9sZFZub2RlLCB2YWx5cmlhbkFwcCk7XG4gICAgb2xkVm5vZGUgPSBudWxsO1xuXG4gICAgaWYgKGlzTm9kZUpzKSB7XG4gICAgICByZXR1cm4gdmFseXJpYW5BcHAubWFpblZub2RlLmRvbS5pbm5lckhUTUw7XG4gICAgfVxuXG4gICAgKHZhbHlyaWFuQXBwIGFzIGFueSkgPSBudWxsO1xuICAgIFJlZmxlY3QuZGVsZXRlUHJvcGVydHkoY29tcG9uZW50LCBWYWx5cmlhblN5bWJvbCk7XG4gIH1cbn1cblxubGV0IGVtcHR5Vm5vZGUgPSBuZXcgVm5vZGUoXCJfX2VtcHR5X19cIiwge30sIFtdKTtcblxuZnVuY3Rpb24gb25yZW1vdmUodm5vZGU6IElWbm9kZSkge1xuICBmb3IgKGxldCBpID0gMDsgaSA8IHZub2RlLmNoaWxkcmVuLmxlbmd0aDsgaSsrKSB7XG4gICAgdm5vZGUuY2hpbGRyZW5baV0udGFnICE9PSBcIiN0ZXh0XCIgJiYgb25yZW1vdmUodm5vZGUuY2hpbGRyZW5baV0pO1xuICB9XG5cbiAgdm5vZGUucHJvcHMub25yZW1vdmUgJiYgdm5vZGUucHJvcHMub25yZW1vdmUodm5vZGUpO1xufVxuXG5mdW5jdGlvbiBzaGFyZWRTZXRBdHRyaWJ1dGUocHJvcDogc3RyaW5nLCB2YWx1ZTogYW55LCB2bm9kZTogVm5vZGVXaXRoRG9tLCBvbGRWbm9kZT86IFZub2RlV2l0aERvbSkge1xuICAvLyBJdCBpcyBhIHJlc2VydmVkIHByb3BcbiAgaWYgKHYucmVzZXJ2ZWRQcm9wc1twcm9wXSkge1xuICAgIC8vIElmIGl0IGlzIGEgZGlyZWN0aXZlIG5hbWUgY2FsbCB0aGUgZGlyZWN0aXZlXG4gICAgaWYgKHYuZGlyZWN0aXZlc1twcm9wXSkge1xuICAgICAgdi5kaXJlY3RpdmVzW3Byb3BdKHZub2RlLnByb3BzW3Byb3BdLCB2bm9kZSwgb2xkVm5vZGUpO1xuICAgIH1cbiAgICByZXR1cm47XG4gIH1cblxuICAvLyBJdCBpcyBub3QgYSByZXNlcnZlZCBwcm9wIHNvIHdlIGFkZCBpdCB0byB0aGUgZG9tXG4gIGlmICh0eXBlb2YgdmFsdWUgPT09IFwiZnVuY3Rpb25cIikge1xuICAgIGxldCB2YWx5cmlhbkFwcCA9IHYuY3VycmVudC5hcHAgYXMgTW91bnRlZFZhbHlyaWFuQXBwO1xuICAgIGlmIChwcm9wIGluIHZhbHlyaWFuQXBwLmV2ZW50TGlzdGVuZXJOYW1lcyA9PT0gZmFsc2UpIHtcbiAgICAgIHZhbHlyaWFuQXBwLmV2ZW50TGlzdGVuZXJOYW1lc1twcm9wXSA9IHRydWU7XG4gICAgICB2YWx5cmlhbkFwcC5jb250YWluZXIuYWRkRXZlbnRMaXN0ZW5lcihwcm9wLnNsaWNlKDIpLCB2YWx5cmlhbkFwcC5ldmVudExpc3RlbmVyKTtcbiAgICB9XG4gICAgdm5vZGUuZG9tW2B2LSR7cHJvcH1gXSA9IHZhbHVlO1xuICAgIHJldHVybjtcbiAgfVxuXG4gIGlmIChwcm9wIGluIHZub2RlLmRvbSAmJiB2bm9kZS5pc1NWRyA9PT0gZmFsc2UpIHtcbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgZXFlcWVxXG4gICAgaWYgKHZub2RlLmRvbVtwcm9wXSAhPSB2YWx1ZSkge1xuICAgICAgdm5vZGUuZG9tW3Byb3BdID0gdmFsdWU7XG4gICAgfVxuICAgIHJldHVybjtcbiAgfVxuXG4gIC8vIFVzZSBzZXQgYXR0cmlidXRlXG4gIGlmICghb2xkVm5vZGUgfHwgb2xkVm5vZGUucHJvcHNbcHJvcF0gIT09IHZhbHVlKSB7XG4gICAgaWYgKHZhbHVlID09PSBmYWxzZSkge1xuICAgICAgdm5vZGUuZG9tLnJlbW92ZUF0dHJpYnV0ZShwcm9wKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdm5vZGUuZG9tLnNldEF0dHJpYnV0ZShwcm9wLCB2YWx1ZSk7XG4gICAgfVxuICB9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBzZXRBdHRyaWJ1dGUobmFtZTogc3RyaW5nLCB2YWx1ZTogYW55LCB2bm9kZTogVm5vZGVXaXRoRG9tLCBvbGRWbm9kZT86IFZub2RlV2l0aERvbSkge1xuICBpZiAobmFtZSBpbiB2bm9kZS5wcm9wcyA9PT0gZmFsc2UpIHtcbiAgICB2bm9kZS5wcm9wc1tuYW1lXSA9IHZhbHVlO1xuICB9XG5cbiAgc2hhcmVkU2V0QXR0cmlidXRlKG5hbWUsIHZhbHVlLCB2bm9kZSwgb2xkVm5vZGUpO1xufVxuXG5mdW5jdGlvbiB1cGRhdGVBdHRyaWJ1dGVzKHZub2RlOiBWbm9kZVdpdGhEb20sIG9sZFZub2RlPzogVm5vZGVXaXRoRG9tKSB7XG4gIGZvciAobGV0IHByb3AgaW4gdm5vZGUucHJvcHMpIHtcbiAgICAvLyBXZSBhc3VtZSB0aGF0IHdlIGNsZWFuIHRoZSBwcm9wcyBpbiBzb21lIGRpcmVjdGl2ZVxuICAgIGlmIChwcm9wIGluIHZub2RlLnByb3BzID09PSBmYWxzZSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHNoYXJlZFNldEF0dHJpYnV0ZShwcm9wLCB2bm9kZS5wcm9wc1twcm9wXSwgdm5vZGUsIG9sZFZub2RlKTtcbiAgfVxuXG4gIGlmIChvbGRWbm9kZSkge1xuICAgIGZvciAobGV0IHByb3AgaW4gb2xkVm5vZGUucHJvcHMpIHtcbiAgICAgIGlmIChwcm9wIGluIHZub2RlLnByb3BzID09PSBmYWxzZSAmJiB0eXBlb2Ygb2xkVm5vZGUucHJvcHNbcHJvcF0gIT09IFwiZnVuY3Rpb25cIiAmJiBwcm9wIGluIHYucmVzZXJ2ZWRQcm9wcyA9PT0gZmFsc2UpIHtcbiAgICAgICAgaWYgKHByb3AgaW4gb2xkVm5vZGUuZG9tICYmIHZub2RlLmlzU1ZHID09PSBmYWxzZSkge1xuICAgICAgICAgIG9sZFZub2RlLmRvbVtwcm9wXSA9IG51bGw7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgb2xkVm5vZGUuZG9tLnJlbW92ZUF0dHJpYnV0ZShwcm9wKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgfVxufVxuXG5mdW5jdGlvbiBmbGF0VHJlZShuZXdWbm9kZTogSVZub2RlKTogdm9pZCB7XG4gIGxldCBuZXdUcmVlID0gbmV3Vm5vZGUuY2hpbGRyZW47XG4gIGZvciAobGV0IGkgPSAwOyBpIDwgbmV3VHJlZS5sZW5ndGg7IGkrKykge1xuICAgIGxldCBjaGlsZFZub2RlID0gbmV3VHJlZVtpXTtcbiAgICBpZiAoY2hpbGRWbm9kZSBpbnN0YW5jZW9mIFZub2RlKSB7XG4gICAgICBpZiAoY2hpbGRWbm9kZS50YWcgIT09IFwiI3RleHRcIikge1xuICAgICAgICBpZiAoY2hpbGRWbm9kZS50YWcgPT09IFwiX19jb21wb25lbnRfX1wiKSB7XG4gICAgICAgICAgbGV0IGNvbXBvbmVudCA9IGNoaWxkVm5vZGUuY29tcG9uZW50IGFzIFZhbHlyaWFuQ29tcG9uZW50O1xuICAgICAgICAgIHYuY3VycmVudC5jb21wb25lbnQgPSBjb21wb25lbnQ7XG4gICAgICAgICAgbGV0IHJlc3VsdCA9IChcInZpZXdcIiBpbiBjb21wb25lbnQgPyBjb21wb25lbnQudmlldyA6IGNvbXBvbmVudCkuY2FsbChjb21wb25lbnQsIGNoaWxkVm5vZGUucHJvcHMsIC4uLmNoaWxkVm5vZGUuY2hpbGRyZW4pO1xuXG4gICAgICAgICAgbmV3VHJlZS5zcGxpY2UoaS0tLCAxLCByZXN1bHQpO1xuICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICB9XG4gICAgICAgIGNoaWxkVm5vZGUuaXNTVkcgPSBuZXdWbm9kZS5pc1NWRyB8fCBjaGlsZFZub2RlLnRhZyA9PT0gXCJzdmdcIjtcbiAgICAgIH1cbiAgICB9IGVsc2UgaWYgKGNoaWxkVm5vZGUgPT09IG51bGwgfHwgY2hpbGRWbm9kZSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICBuZXdUcmVlLnNwbGljZShpLS0sIDEpO1xuICAgIH0gZWxzZSBpZiAoQXJyYXkuaXNBcnJheShjaGlsZFZub2RlKSkge1xuICAgICAgbmV3VHJlZS5zcGxpY2UoaS0tLCAxLCAuLi5jaGlsZFZub2RlKTtcbiAgICB9IGVsc2Uge1xuICAgICAgaWYgKGkgPiAwICYmIG5ld1RyZWVbaSAtIDFdLnRhZyA9PT0gXCIjdGV4dFwiKSB7XG4gICAgICAgIG5ld1RyZWVbaSAtIDFdLm5vZGVWYWx1ZSArPSBjaGlsZFZub2RlO1xuICAgICAgICBuZXdUcmVlLnNwbGljZShpLS0sIDEpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgbmV3VHJlZVtpXSA9IG5ldyBWbm9kZShcIiN0ZXh0XCIsIHt9LCBbXSk7XG4gICAgICAgIG5ld1RyZWVbaV0ubm9kZVZhbHVlID0gU3RyaW5nKGNoaWxkVm5vZGUpO1xuICAgICAgfVxuICAgIH1cbiAgfVxufVxuXG5mdW5jdGlvbiBwYXRjaEtleWVkVHJlZShcbiAgbmV3Vm5vZGU6IFZub2RlV2l0aERvbSxcbiAgbmV3VHJlZTogKFZub2RlV2l0aERvbSAmIHsgcHJvcHM6IFByb3BzICYgeyBrZXk6IHN0cmluZyB9IH0pW10sXG4gIG9sZFRyZWU6IChWbm9kZVdpdGhEb20gJiB7IHByb3BzOiBQcm9wcyAmIHsga2V5OiBzdHJpbmcgfSB9KVtdLFxuICBuZXdUcmVlTGVuZ3RoOiBudW1iZXIsXG4gIG9sZFRyZWVMZW5ndGg6IG51bWJlcixcbiAgdmFseXJpYW5BcHA6IE1vdW50ZWRWYWx5cmlhbkFwcFxuKSB7XG4gIGxldCBvbGRLZXllZExpc3QgPSBvbGRUcmVlLnJlZHVjZSgoYWNjLCB2bm9kZSwgaSkgPT4ge1xuICAgIGFjY1t2bm9kZS5wcm9wcy5rZXldID0gaTtcbiAgICByZXR1cm4gYWNjO1xuICB9LCB7fSBhcyB7IFtrZXk6IHN0cmluZ106IG51bWJlciB9KTtcbiAgbGV0IG5ld0tleWVkTGlzdCA9IG5ld1RyZWUucmVkdWNlKChhY2MsIHZub2RlLCBpKSA9PiB7XG4gICAgYWNjW3Zub2RlLnByb3BzLmtleV0gPSBpO1xuICAgIHJldHVybiBhY2M7XG4gIH0sIHt9IGFzIHsgW2tleTogc3RyaW5nXTogbnVtYmVyIH0pO1xuXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgbmV3VHJlZUxlbmd0aDsgaSsrKSB7XG4gICAgbGV0IGNoaWxkVm5vZGUgPSBuZXdUcmVlW2ldO1xuICAgIGxldCBvbGRDaGlsZFZub2RlID0gb2xkVHJlZVtvbGRLZXllZExpc3RbY2hpbGRWbm9kZS5wcm9wcy5rZXldXTtcbiAgICBsZXQgc2hvdWxkUGF0Y2ggPSB0cnVlO1xuXG4gICAgaWYgKG9sZENoaWxkVm5vZGUpIHtcbiAgICAgIGNoaWxkVm5vZGUuZG9tID0gb2xkQ2hpbGRWbm9kZS5kb207XG4gICAgICBpZiAoXCJ2LW9uY2VcIiBpbiBjaGlsZFZub2RlLnByb3BzIHx8IChjaGlsZFZub2RlLnByb3BzLnNob3VsZHVwZGF0ZSAmJiBjaGlsZFZub2RlLnByb3BzLnNob3VsZHVwZGF0ZShjaGlsZFZub2RlLCBvbGRDaGlsZFZub2RlKSA9PT0gZmFsc2UpKSB7XG4gICAgICAgIC8vIHNraXAgdGhpcyBwYXRjaFxuICAgICAgICBjaGlsZFZub2RlLmNoaWxkcmVuID0gb2xkQ2hpbGRWbm9kZS5jaGlsZHJlbjtcbiAgICAgICAgc2hvdWxkUGF0Y2ggPSBmYWxzZTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHVwZGF0ZUF0dHJpYnV0ZXMoY2hpbGRWbm9kZSwgb2xkQ2hpbGRWbm9kZSk7XG4gICAgICAgIGlmICh2YWx5cmlhbkFwcC5pc01vdW50ZWQpIHtcbiAgICAgICAgICBjaGlsZFZub2RlLnByb3BzLm9udXBkYXRlICYmIGNoaWxkVm5vZGUucHJvcHMub251cGRhdGUoY2hpbGRWbm9kZSwgb2xkQ2hpbGRWbm9kZSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgY2hpbGRWbm9kZS5wcm9wcy5vbmNyZWF0ZSAmJiBjaGlsZFZub2RlLnByb3BzLm9uY3JlYXRlKGNoaWxkVm5vZGUpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIGNoaWxkVm5vZGUuZG9tID0gY3JlYXRlRG9tRWxlbWVudChjaGlsZFZub2RlLnRhZywgY2hpbGRWbm9kZS5pc1NWRyk7XG4gICAgICB1cGRhdGVBdHRyaWJ1dGVzKGNoaWxkVm5vZGUpO1xuICAgICAgY2hpbGRWbm9kZS5wcm9wcy5vbmNyZWF0ZSAmJiBjaGlsZFZub2RlLnByb3BzLm9uY3JlYXRlKGNoaWxkVm5vZGUpO1xuICAgIH1cblxuICAgIGlmIChuZXdWbm9kZS5kb20uY2hpbGROb2Rlc1tpXSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICBuZXdWbm9kZS5kb20uYXBwZW5kQ2hpbGQoY2hpbGRWbm9kZS5kb20pO1xuICAgIH0gZWxzZSBpZiAobmV3Vm5vZGUuZG9tLmNoaWxkTm9kZXNbaV0gIT09IGNoaWxkVm5vZGUuZG9tKSB7XG4gICAgICBvbGRUcmVlW2ldICYmIG5ld0tleWVkTGlzdFtvbGRUcmVlW2ldLnByb3BzLmtleV0gPT09IHVuZGVmaW5lZCAmJiBvbnJlbW92ZShvbGRUcmVlW2ldKTtcbiAgICAgIG5ld1Zub2RlLmRvbS5yZXBsYWNlQ2hpbGQoY2hpbGRWbm9kZS5kb20sIG5ld1Zub2RlLmRvbS5jaGlsZE5vZGVzW2ldKTtcbiAgICB9XG5cbiAgICBzaG91bGRQYXRjaCAmJiBwYXRjaChjaGlsZFZub2RlLCBvbGRDaGlsZFZub2RlLCB2YWx5cmlhbkFwcCk7XG4gIH1cblxuICAvLyBGb3IgdGhlIHJlc3Qgb2YgdGhlIGNoaWxkcmVuLCB3ZSBzaG91bGQgcmVtb3ZlIHRoZW1cbiAgZm9yIChsZXQgaSA9IG5ld1RyZWVMZW5ndGg7IGkgPCBvbGRUcmVlTGVuZ3RoOyBpKyspIHtcbiAgICBpZiAobmV3S2V5ZWRMaXN0W29sZFRyZWVbaV0ucHJvcHMua2V5XSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICBsZXQgb2xkQ2hpbGRWbm9kZSA9IG9sZFRyZWVbaV07XG4gICAgICBvbnJlbW92ZShvbGRDaGlsZFZub2RlKTtcbiAgICAgIG9sZENoaWxkVm5vZGUuZG9tLnBhcmVudE5vZGUgJiYgb2xkQ2hpbGRWbm9kZS5kb20ucGFyZW50Tm9kZS5yZW1vdmVDaGlsZChvbGRDaGlsZFZub2RlLmRvbSk7XG4gICAgfVxuICB9XG59XG5cbi8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBjb21wbGV4aXR5XG5mdW5jdGlvbiBwYXRjaE5vcm1hbFRyZWUoXG4gIG5ld1Zub2RlOiBWbm9kZVdpdGhEb20sXG4gIG5ld1RyZWU6IChWbm9kZVdpdGhEb20gJiB7IHByb3BzOiBQcm9wcyAmIHsga2V5OiBzdHJpbmcgfSB9KVtdLFxuICBvbGRUcmVlOiAoVm5vZGVXaXRoRG9tICYgeyBwcm9wczogUHJvcHMgJiB7IGtleTogc3RyaW5nIH0gfSlbXSxcbiAgbmV3VHJlZUxlbmd0aDogbnVtYmVyLFxuICBvbGRUcmVlTGVuZ3RoOiBudW1iZXIsXG4gIHZhbHlyaWFuQXBwOiBNb3VudGVkVmFseXJpYW5BcHBcbikge1xuICAvLyBJZiBuZXcgdHJlZSBhbmQgb2xkIHRyZWUgaGF2ZSBtb3JlIHRoYW4gb25lIGNoaWxkLCB3ZSBzaG91bGQgdXBkYXRlIHRoZSBkb21cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBuZXdUcmVlTGVuZ3RoOyBpKyspIHtcbiAgICBsZXQgb2xkQ2hpbGRWbm9kZSA9IG9sZFRyZWVbaV07XG4gICAgbGV0IG5ld0NoaWxkVm5vZGUgPSBuZXdUcmVlW2ldO1xuXG4gICAgLy8gT2xkIGNoaWxkIGRvZXMgbm90IGV4aXN0c1xuICAgIGlmICghb2xkQ2hpbGRWbm9kZSkge1xuICAgICAgLy8gTmV3IGNoaWxkIGlzIGEgdGV4dCBub2RlXG4gICAgICBpZiAobmV3Q2hpbGRWbm9kZS50YWcgPT09IFwiI3RleHRcIikge1xuICAgICAgICBuZXdDaGlsZFZub2RlLmRvbSA9IGRvY3VtZW50LmNyZWF0ZVRleHROb2RlKG5ld0NoaWxkVm5vZGUubm9kZVZhbHVlIGFzIHN0cmluZykgYXMgdW5rbm93biBhcyBEb21FbGVtZW50O1xuICAgICAgICBuZXdWbm9kZS5kb20uYXBwZW5kQ2hpbGQobmV3Q2hpbGRWbm9kZS5kb20pO1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cblxuICAgICAgLy8gTmV3IGNoaWxkIGlzIGEgbm9ybWFsIG5vZGVcbiAgICAgIG5ld0NoaWxkVm5vZGUuZG9tID0gY3JlYXRlRG9tRWxlbWVudChuZXdDaGlsZFZub2RlLnRhZywgbmV3Q2hpbGRWbm9kZS5pc1NWRyk7XG4gICAgICB1cGRhdGVBdHRyaWJ1dGVzKG5ld0NoaWxkVm5vZGUpO1xuICAgICAgbmV3Vm5vZGUuZG9tLmFwcGVuZENoaWxkKG5ld0NoaWxkVm5vZGUuZG9tKTtcbiAgICAgIG5ld0NoaWxkVm5vZGUucHJvcHMub25jcmVhdGUgJiYgbmV3Q2hpbGRWbm9kZS5wcm9wcy5vbmNyZWF0ZShuZXdDaGlsZFZub2RlKTtcbiAgICAgIHBhdGNoKG5ld0NoaWxkVm5vZGUsIHVuZGVmaW5lZCwgdmFseXJpYW5BcHApO1xuICAgICAgY29udGludWU7XG4gICAgfVxuXG4gICAgLy8gT2xkIGNoaWxkIGV4aXN0c1xuICAgIC8vIE5ldyBjaGlsZCBpcyBhIHRleHQgbm9kZVxuICAgIGlmIChuZXdDaGlsZFZub2RlLnRhZyA9PT0gXCIjdGV4dFwiKSB7XG4gICAgICAvLyBPbGQgY2hpbGQgaXMgYSB0ZXh0IG5vZGVcbiAgICAgIGlmIChvbGRDaGlsZFZub2RlLnRhZyA9PT0gXCIjdGV4dFwiKSB7XG4gICAgICAgIG5ld0NoaWxkVm5vZGUuZG9tID0gb2xkQ2hpbGRWbm9kZS5kb207XG4gICAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBlcWVxZXFcbiAgICAgICAgaWYgKG5ld0NoaWxkVm5vZGUuZG9tLm5vZGVWYWx1ZSAhPSBuZXdDaGlsZFZub2RlLm5vZGVWYWx1ZSkge1xuICAgICAgICAgIG5ld0NoaWxkVm5vZGUuZG9tLm5vZGVWYWx1ZSA9IG5ld0NoaWxkVm5vZGUubm9kZVZhbHVlIGFzIHN0cmluZztcbiAgICAgICAgfVxuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cblxuICAgICAgLy8gT2xkIGNoaWxkIGlzIGEgbm9ybWFsIG5vZGVcbiAgICAgIG5ld0NoaWxkVm5vZGUuZG9tID0gZG9jdW1lbnQuY3JlYXRlVGV4dE5vZGUobmV3Q2hpbGRWbm9kZS5ub2RlVmFsdWUgYXMgc3RyaW5nKSBhcyB1bmtub3duIGFzIERvbUVsZW1lbnQ7XG4gICAgICBvbnJlbW92ZShvbGRDaGlsZFZub2RlKTtcbiAgICAgIG5ld1Zub2RlLmRvbS5yZXBsYWNlQ2hpbGQobmV3Q2hpbGRWbm9kZS5kb20sIG9sZENoaWxkVm5vZGUuZG9tKTtcblxuICAgICAgY29udGludWU7XG4gICAgfVxuXG4gICAgLy8gTmV3IGNoaWxkIGlzIGEgbm9ybWFsIG5vZGVcbiAgICAvLyBPbGQgY2hpbGQgaXMgdGhlIHNhbWUgdHlwZSBhcyBuZXcgY2hpbGRcbiAgICBpZiAob2xkQ2hpbGRWbm9kZS50YWcgPT09IG5ld0NoaWxkVm5vZGUudGFnKSB7XG4gICAgICBuZXdDaGlsZFZub2RlLmRvbSA9IG9sZENoaWxkVm5vZGUuZG9tO1xuICAgICAgLy8gSWYgd2UgaGF2ZSBhIHYtb25jZSBkaXJlY3RpdmUgb3IgYSBzaG91bGR1cGRhdGUgbWV0aG9kIHRoYXQgcmV0dXJucyBmYWxzZSwgd2Ugc2tpcCB0aGUgdXBkYXRlXG4gICAgICBpZiAobmV3Q2hpbGRWbm9kZS5wcm9wc1tcInYtb25jZVwiXSB8fCAobmV3Q2hpbGRWbm9kZS5wcm9wcy5zaG91bGR1cGRhdGUgJiYgbmV3Q2hpbGRWbm9kZS5wcm9wcy5zaG91bGR1cGRhdGUobmV3Q2hpbGRWbm9kZSwgb2xkQ2hpbGRWbm9kZSkgPT09IGZhbHNlKSkge1xuICAgICAgICBuZXdDaGlsZFZub2RlLmNoaWxkcmVuID0gb2xkQ2hpbGRWbm9kZS5jaGlsZHJlbjtcbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG5cbiAgICAgIC8vIFdlIHVwZGF0ZSB0aGUgZG9tIGVsZW1lbnRcbiAgICAgIHVwZGF0ZUF0dHJpYnV0ZXMobmV3Q2hpbGRWbm9kZSwgb2xkQ2hpbGRWbm9kZSk7XG4gICAgICBpZiAodmFseXJpYW5BcHAgJiYgdmFseXJpYW5BcHAuaXNNb3VudGVkKSB7XG4gICAgICAgIG5ld0NoaWxkVm5vZGUucHJvcHMub251cGRhdGUgJiYgbmV3Q2hpbGRWbm9kZS5wcm9wcy5vbnVwZGF0ZShuZXdDaGlsZFZub2RlLCBvbGRDaGlsZFZub2RlKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIG5ld0NoaWxkVm5vZGUucHJvcHMub25jcmVhdGUgJiYgbmV3Q2hpbGRWbm9kZS5wcm9wcy5vbmNyZWF0ZShuZXdDaGlsZFZub2RlKTtcbiAgICAgIH1cbiAgICAgIHBhdGNoKG5ld0NoaWxkVm5vZGUsIG9sZENoaWxkVm5vZGUsIHZhbHlyaWFuQXBwKTtcblxuICAgICAgY29udGludWU7XG4gICAgfVxuXG4gICAgLy8gT2xkIGNoaWxkIGlzIG9mIGEgZGlmZmVyZW50IHR5cGUgdGhhbiBuZXcgY2hpbGRcbiAgICBuZXdDaGlsZFZub2RlLmRvbSA9IGNyZWF0ZURvbUVsZW1lbnQobmV3Q2hpbGRWbm9kZS50YWcsIG5ld0NoaWxkVm5vZGUuaXNTVkcpO1xuICAgIHVwZGF0ZUF0dHJpYnV0ZXMobmV3Q2hpbGRWbm9kZSk7XG4gICAgaWYgKG9sZENoaWxkVm5vZGUudGFnICE9PSBcIiN0ZXh0XCIpIHtcbiAgICAgIG9ucmVtb3ZlKG9sZENoaWxkVm5vZGUpO1xuICAgIH1cbiAgICBuZXdDaGlsZFZub2RlLnByb3BzLm9uY3JlYXRlICYmIG5ld0NoaWxkVm5vZGUucHJvcHMub25jcmVhdGUobmV3Q2hpbGRWbm9kZSk7XG4gICAgbmV3Vm5vZGUuZG9tLnJlcGxhY2VDaGlsZChuZXdDaGlsZFZub2RlLmRvbSwgb2xkQ2hpbGRWbm9kZS5kb20pO1xuICAgIHBhdGNoKG5ld0NoaWxkVm5vZGUsIHVuZGVmaW5lZCwgdmFseXJpYW5BcHApO1xuICB9XG5cbiAgLy8gRm9yIHRoZSByZXN0IG9mIHRoZSBjaGlsZHJlbiwgd2Ugc2hvdWxkIHJlbW92ZSB0aGVtXG4gIGZvciAobGV0IGkgPSBuZXdUcmVlTGVuZ3RoOyBpIDwgb2xkVHJlZUxlbmd0aDsgaSsrKSB7XG4gICAgbGV0IG9sZENoaWxkVm5vZGUgPSBvbGRUcmVlW2ldO1xuICAgIGlmIChvbGRDaGlsZFZub2RlLnRhZyAhPT0gXCIjdGV4dFwiKSB7XG4gICAgICBvbnJlbW92ZShvbGRDaGlsZFZub2RlKTtcbiAgICB9XG4gICAgb2xkQ2hpbGRWbm9kZS5kb20ucGFyZW50Tm9kZSAmJiBvbGRDaGlsZFZub2RlLmRvbS5wYXJlbnROb2RlLnJlbW92ZUNoaWxkKG9sZENoaWxkVm5vZGUuZG9tKTtcbiAgfVxufVxuXG4vLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgY29tcGxleGl0eVxuZnVuY3Rpb24gcGF0Y2gobmV3Vm5vZGU6IFZub2RlV2l0aERvbSwgb2xkVm5vZGU6IFZub2RlV2l0aERvbSA9IGVtcHR5Vm5vZGUgYXMgVm5vZGVXaXRoRG9tLCB2YWx5cmlhbkFwcDogTW91bnRlZFZhbHlyaWFuQXBwKSB7XG4gIHYuY3VycmVudC52bm9kZSA9IG5ld1Zub2RlO1xuICB2LmN1cnJlbnQub2xkVm5vZGUgPSBvbGRWbm9kZTtcblxuICBmbGF0VHJlZShuZXdWbm9kZSk7XG5cbiAgbGV0IG5ld1RyZWUgPSBuZXdWbm9kZS5jaGlsZHJlbjtcbiAgbGV0IG9sZFRyZWUgPSBvbGRWbm9kZS5jaGlsZHJlbjtcbiAgbGV0IG9sZFRyZWVMZW5ndGggPSBvbGRUcmVlLmxlbmd0aDtcbiAgbGV0IG5ld1RyZWVMZW5ndGggPSBuZXdUcmVlLmxlbmd0aDtcblxuICAvLyBJZiBuZXcgdHJlZSBpcyBlbXB0eSwgcmVtb3ZlIGFsbCBvbGQgbm9kZXNcbiAgaWYgKG5ld1RyZWVMZW5ndGggPT09IDApIHtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IG9sZFRyZWVMZW5ndGg7IGkrKykge1xuICAgICAgb25yZW1vdmUob2xkVHJlZVtpXSk7XG4gICAgfVxuXG4gICAgbmV3Vm5vZGUuZG9tLnRleHRDb250ZW50ID0gXCJcIjtcbiAgICByZXR1cm47XG4gIH1cblxuICAvLyBJZiB0aGUgdHJlZSBpcyBrZXllZCBsaXN0IGFuZCBpcyBub3QgZmlyc3QgcmVuZGVyIGFuZCBvbGQgdHJlZSBpcyBrZXllZCBsaXN0IHRvb1xuICBpZiAob2xkVHJlZUxlbmd0aCAmJiBcImtleVwiIGluIG5ld1RyZWVbMF0ucHJvcHMgJiYgXCJrZXlcIiBpbiBvbGRUcmVlWzBdLnByb3BzKSB7XG4gICAgcGF0Y2hLZXllZFRyZWUobmV3Vm5vZGUsIG5ld1RyZWUsIG9sZFRyZWUsIG5ld1RyZWVMZW5ndGgsIG9sZFRyZWVMZW5ndGgsIHZhbHlyaWFuQXBwKTtcbiAgICByZXR1cm47XG4gIH1cblxuICBwYXRjaE5vcm1hbFRyZWUobmV3Vm5vZGUsIG5ld1RyZWUsIG9sZFRyZWUsIG5ld1RyZWVMZW5ndGgsIG9sZFRyZWVMZW5ndGgsIHZhbHlyaWFuQXBwKTtcbn1cblxuLyoqKiBEaXJlY3RpdmVzICoqKi9cblxuZXhwb3J0IGZ1bmN0aW9uIGRpcmVjdGl2ZShuYW1lOiBzdHJpbmcsIGRpcmVjdGl2ZTogRGlyZWN0aXZlKSB7XG4gIGxldCBmdWxsTmFtZSA9IGB2LSR7bmFtZX1gO1xuICB2LmRpcmVjdGl2ZXNbZnVsbE5hbWVdID0gZGlyZWN0aXZlO1xuICB2LnJlc2VydmVkUHJvcHNbZnVsbE5hbWVdID0gdHJ1ZTtcbn1cblxuZnVuY3Rpb24gaGlkZURpcmVjdGl2ZSh0ZXN0OiBib29sZWFuKTogRGlyZWN0aXZlIHtcbiAgcmV0dXJuIChib29sOiBib29sZWFuLCB2bm9kZTogSVZub2RlLCBvbGRWbm9kZT86IElWbm9kZSkgPT4ge1xuICAgIGxldCB2YWx1ZSA9IHRlc3QgPyBib29sIDogIWJvb2w7XG4gICAgaWYgKHZhbHVlKSB7XG4gICAgICBsZXQgbmV3ZG9tID0gZG9jdW1lbnQuY3JlYXRlVGV4dE5vZGUoXCJcIik7XG4gICAgICBpZiAob2xkVm5vZGUgJiYgb2xkVm5vZGUuZG9tICYmIG9sZFZub2RlLmRvbS5wYXJlbnROb2RlKSB7XG4gICAgICAgIG9sZFZub2RlLnRhZyAhPT0gXCIjdGV4dFwiICYmIG9ucmVtb3ZlKG9sZFZub2RlKTtcbiAgICAgICAgb2xkVm5vZGUuZG9tLnBhcmVudE5vZGUucmVwbGFjZUNoaWxkKG5ld2RvbSwgb2xkVm5vZGUuZG9tKTtcbiAgICAgIH1cbiAgICAgIHZub2RlLnRhZyA9IFwiI3RleHRcIjtcbiAgICAgIHZub2RlLmNoaWxkcmVuID0gW107XG4gICAgICB2bm9kZS5wcm9wcyA9IHt9O1xuICAgICAgdm5vZGUuZG9tID0gbmV3ZG9tIGFzIHVua25vd24gYXMgRG9tRWxlbWVudDtcbiAgICB9XG4gIH07XG59XG5cbmNvbnN0IGJ1aWx0SW5EaXJlY3RpdmVzID0ge1xuICBcInYtaWZcIjogaGlkZURpcmVjdGl2ZShmYWxzZSksXG4gIFwidi11bmxlc3NcIjogaGlkZURpcmVjdGl2ZSh0cnVlKSxcbiAgXCJ2LWZvclwiOiAoc2V0OiB1bmtub3duW10sIHZub2RlOiBWbm9kZVdpdGhEb20pID0+IHtcbiAgICB2bm9kZS5jaGlsZHJlbiA9IHNldC5tYXAodm5vZGUuY2hpbGRyZW5bMF0gYXMgKHZhbHVlOiB1bmtub3duKSA9PiBGdW5jdGlvbik7XG4gIH0sXG4gIFwidi1zaG93XCI6IChib29sOiBib29sZWFuLCB2bm9kZTogVm5vZGVXaXRoRG9tKSA9PiB7XG4gICAgKHZub2RlLmRvbSBhcyB1bmtub3duIGFzIHsgc3R5bGU6IHsgZGlzcGxheTogc3RyaW5nIH0gfSkuc3R5bGUuZGlzcGxheSA9IGJvb2wgPyBcIlwiIDogXCJub25lXCI7XG4gIH0sXG4gIFwidi1jbGFzc1wiOiAoY2xhc3NlczogeyBbeDogc3RyaW5nXTogYm9vbGVhbiB9LCB2bm9kZTogVm5vZGVXaXRoRG9tKSA9PiB7XG4gICAgZm9yIChsZXQgbmFtZSBpbiBjbGFzc2VzKSB7XG4gICAgICAodm5vZGUuZG9tIGFzIERvbUVsZW1lbnQpLmNsYXNzTGlzdC50b2dnbGUobmFtZSwgY2xhc3Nlc1tuYW1lXSk7XG4gICAgfVxuICB9LFxuICBcInYtaHRtbFwiOiAoaHRtbDogc3RyaW5nLCB2bm9kZTogVm5vZGVXaXRoRG9tKSA9PiB7XG4gICAgdm5vZGUuY2hpbGRyZW4gPSBbdHJ1c3QoaHRtbCldO1xuICB9LFxuICBcInYtbW9kZWxcIjogKFttb2RlbCwgcHJvcGVydHksIGV2ZW50XTogYW55W10sIHZub2RlOiBWbm9kZVdpdGhEb20sIG9sZFZub2RlPzogVm5vZGVXaXRoRG9tKSA9PiB7XG4gICAgbGV0IHZhbHVlO1xuICAgIGxldCBoYW5kbGVyO1xuICAgIGlmICh2bm9kZS5uYW1lID09PSBcImlucHV0XCIpIHtcbiAgICAgIGV2ZW50ID0gZXZlbnQgfHwgXCJvbmlucHV0XCI7XG4gICAgICBzd2l0Y2ggKHZub2RlLnByb3BzLnR5cGUpIHtcbiAgICAgICAgY2FzZSBcImNoZWNrYm94XCI6IHtcbiAgICAgICAgICBpZiAoQXJyYXkuaXNBcnJheShtb2RlbFtwcm9wZXJ0eV0pKSB7XG4gICAgICAgICAgICBoYW5kbGVyID0gKGU6IEV2ZW50KSA9PiB7XG4gICAgICAgICAgICAgIGxldCB2YWwgPSAoZS50YXJnZXQgYXMgRG9tRWxlbWVudCAmIFJlY29yZDxzdHJpbmcsIGFueT4pLnZhbHVlO1xuICAgICAgICAgICAgICBsZXQgaWR4ID0gbW9kZWxbcHJvcGVydHldLmluZGV4T2YodmFsKTtcbiAgICAgICAgICAgICAgaWYgKGlkeCA9PT0gLTEpIHtcbiAgICAgICAgICAgICAgICBtb2RlbFtwcm9wZXJ0eV0ucHVzaCh2YWwpO1xuICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIG1vZGVsW3Byb3BlcnR5XS5zcGxpY2UoaWR4LCAxKTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIHZhbHVlID0gbW9kZWxbcHJvcGVydHldLmluZGV4T2Yodm5vZGUuZG9tLnZhbHVlKSAhPT0gLTE7XG4gICAgICAgICAgfSBlbHNlIGlmIChcInZhbHVlXCIgaW4gdm5vZGUucHJvcHMpIHtcbiAgICAgICAgICAgIGhhbmRsZXIgPSAoKSA9PiB7XG4gICAgICAgICAgICAgIGlmIChtb2RlbFtwcm9wZXJ0eV0gPT09IHZub2RlLnByb3BzLnZhbHVlKSB7XG4gICAgICAgICAgICAgICAgbW9kZWxbcHJvcGVydHldID0gbnVsbDtcbiAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBtb2RlbFtwcm9wZXJ0eV0gPSB2bm9kZS5wcm9wcy52YWx1ZTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIHZhbHVlID0gbW9kZWxbcHJvcGVydHldID09PSB2bm9kZS5wcm9wcy52YWx1ZTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgaGFuZGxlciA9ICgpID0+IChtb2RlbFtwcm9wZXJ0eV0gPSAhbW9kZWxbcHJvcGVydHldKTtcbiAgICAgICAgICAgIHZhbHVlID0gbW9kZWxbcHJvcGVydHldO1xuICAgICAgICAgIH1cbiAgICAgICAgICBzZXRBdHRyaWJ1dGUoXCJjaGVja2VkXCIsIHZhbHVlLCB2bm9kZSwgb2xkVm5vZGUpO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgICAgIGNhc2UgXCJyYWRpb1wiOiB7XG4gICAgICAgICAgc2V0QXR0cmlidXRlKFwiY2hlY2tlZFwiLCBtb2RlbFtwcm9wZXJ0eV0gPT09IHZub2RlLmRvbS52YWx1ZSwgdm5vZGUsIG9sZFZub2RlKTtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgICAgICBkZWZhdWx0OiB7XG4gICAgICAgICAgc2V0QXR0cmlidXRlKFwidmFsdWVcIiwgbW9kZWxbcHJvcGVydHldLCB2bm9kZSwgb2xkVm5vZGUpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSBlbHNlIGlmICh2bm9kZS5uYW1lID09PSBcInNlbGVjdFwiKSB7XG4gICAgICBldmVudCA9IGV2ZW50IHx8IFwib25jbGlja1wiO1xuICAgICAgaWYgKHZub2RlLnByb3BzLm11bHRpcGxlKSB7XG4gICAgICAgIGhhbmRsZXIgPSAoZTogRXZlbnQgJiBSZWNvcmQ8c3RyaW5nLCBhbnk+KSA9PiB7XG4gICAgICAgICAgbGV0IHZhbCA9IChlLnRhcmdldCBhcyBEb21FbGVtZW50ICYgUmVjb3JkPHN0cmluZywgYW55PikudmFsdWU7XG4gICAgICAgICAgaWYgKGUuY3RybEtleSkge1xuICAgICAgICAgICAgbGV0IGlkeCA9IG1vZGVsW3Byb3BlcnR5XS5pbmRleE9mKHZhbCk7XG4gICAgICAgICAgICBpZiAoaWR4ID09PSAtMSkge1xuICAgICAgICAgICAgICBtb2RlbFtwcm9wZXJ0eV0ucHVzaCh2YWwpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgbW9kZWxbcHJvcGVydHldLnNwbGljZShpZHgsIDEpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBtb2RlbFtwcm9wZXJ0eV0uc3BsaWNlKDAsIG1vZGVsW3Byb3BlcnR5XS5sZW5ndGgpO1xuICAgICAgICAgICAgbW9kZWxbcHJvcGVydHldLnB1c2godmFsKTtcbiAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIHZub2RlLmNoaWxkcmVuLmZvckVhY2goKGNoaWxkKSA9PiB7XG4gICAgICAgICAgaWYgKGNoaWxkLm5hbWUgPT09IFwib3B0aW9uXCIpIHtcbiAgICAgICAgICAgIGxldCB2YWx1ZSA9IFwidmFsdWVcIiBpbiBjaGlsZC5wcm9wcyA/IGNoaWxkLnByb3BzLnZhbHVlIDogY2hpbGQuY2hpbGRyZW4uam9pbihcIlwiKS50cmltKCk7XG4gICAgICAgICAgICBjaGlsZC5wcm9wcy5zZWxlY3RlZCA9IG1vZGVsW3Byb3BlcnR5XS5pbmRleE9mKHZhbHVlKSAhPT0gLTE7XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHZub2RlLmNoaWxkcmVuLmZvckVhY2goKGNoaWxkKSA9PiB7XG4gICAgICAgICAgaWYgKGNoaWxkLm5hbWUgPT09IFwib3B0aW9uXCIpIHtcbiAgICAgICAgICAgIGxldCB2YWx1ZSA9IFwidmFsdWVcIiBpbiBjaGlsZC5wcm9wcyA/IGNoaWxkLnByb3BzLnZhbHVlIDogY2hpbGQuY2hpbGRyZW4uam9pbihcIlwiKS50cmltKCk7XG4gICAgICAgICAgICBjaGlsZC5wcm9wcy5zZWxlY3RlZCA9IHZhbHVlID09PSBtb2RlbFtwcm9wZXJ0eV07XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICB9IGVsc2UgaWYgKHZub2RlLm5hbWUgPT09IFwidGV4dGFyZWFcIikge1xuICAgICAgZXZlbnQgPSBldmVudCB8fCBcIm9uaW5wdXRcIjtcbiAgICAgIHZub2RlLmNoaWxkcmVuID0gW21vZGVsW3Byb3BlcnR5XV07XG4gICAgfVxuXG4gICAgaWYgKCF2bm9kZS5wcm9wc1tldmVudF0pIHtcbiAgICAgIGlmICghaGFuZGxlcikge1xuICAgICAgICBoYW5kbGVyID0gKGU6IEV2ZW50KSA9PiAobW9kZWxbcHJvcGVydHldID0gKGUudGFyZ2V0IGFzIERvbUVsZW1lbnQgJiBSZWNvcmQ8c3RyaW5nLCBhbnk+KS52YWx1ZSk7XG4gICAgICB9XG4gICAgICBzZXRBdHRyaWJ1dGUoZXZlbnQsIGhhbmRsZXIsIHZub2RlLCBvbGRWbm9kZSk7XG4gICAgfVxuICB9XG59O1xuXG4vKioqIFBsdWdpbnMgKioqL1xuY29uc3QgcGx1Z2lucyA9IG5ldyBNYXA8UGx1Z2luLCBhbnk+KCk7XG5cbmV4cG9ydCBmdW5jdGlvbiB1c2UocGx1Z2luOiBQbHVnaW4sIG9wdGlvbnM/OiBSZWNvcmQ8c3RyaW5nIHwgbnVtYmVyIHwgc3ltYm9sLCBhbnk+KTogdm9pZCB8IGFueSB7XG4gIGlmIChwbHVnaW5zLmhhcyhwbHVnaW4pKSB7XG4gICAgcmV0dXJuIHBsdWdpbnMuZ2V0KHBsdWdpbik7XG4gIH1cblxuICBsZXQgcmVzdWx0ID0gcGx1Z2luKHYsIG9wdGlvbnMpO1xuICBwbHVnaW5zLnNldChwbHVnaW4sIHJlc3VsdCk7XG4gIHJldHVybiByZXN1bHQ7XG59XG5cbi8qKiogSHlwZXJzY3JpcHQgKioqL1xuXG5leHBvcnQgY29uc3QgdjogVmFseXJpYW4gPSBmdW5jdGlvbiB2KHRhZ09yQ29tcG9uZW50OiBzdHJpbmcgfCBWYWx5cmlhbkNvbXBvbmVudCwgcHJvcHM6IFByb3BzLCAuLi5jaGlsZHJlbjogQ2hpbGRyZW4pOiBJVm5vZGUgfCBWbm9kZUNvbXBvbmVudCB7XG4gIGlmICh0eXBlb2YgdGFnT3JDb21wb25lbnQgPT09IFwic3RyaW5nXCIpIHtcbiAgICByZXR1cm4gbmV3IFZub2RlKHRhZ09yQ29tcG9uZW50LCBwcm9wcyB8fCB7fSwgY2hpbGRyZW4pO1xuICB9XG5cbiAgY29uc3Qgdm5vZGUgPSBuZXcgVm5vZGUoXCJfX2NvbXBvbmVudF9fXCIsIHByb3BzIHx8IHt9LCBjaGlsZHJlbik7XG4gIHZub2RlLmNvbXBvbmVudCA9IHRhZ09yQ29tcG9uZW50O1xuICByZXR1cm4gdm5vZGUgYXMgVm5vZGVDb21wb25lbnQ7XG59O1xuXG52LmZyYWdtZW50ID0gKHByb3BzOiBQcm9wcywgLi4uY2hpbGRyZW46IENoaWxkcmVuKTogQ2hpbGRyZW4gPT4ge1xuICByZXR1cm4gY2hpbGRyZW47XG59O1xuXG4vKioqIFYgcHJvcGVydGllcyBhbmQgbWV0aG9kcyAqKiovXG4vLyBUaGlzIGlzIGludGVuZGVkIHRvIG1ha2UgdGhlIHByb3BlcnRpZXMgYW5kIG1ldGhvZHMgYXZhaWxhYmxlIGZvciBwbHVnaW5zXG52LmN1cnJlbnQgPSB7fSBhcyBDdXJyZW50O1xuXG52LmRpcmVjdGl2ZXMgPSB7IC4uLmJ1aWx0SW5EaXJlY3RpdmVzIH07XG5cbnYucmVzZXJ2ZWRQcm9wcyA9IHtcbiAga2V5OiB0cnVlLFxuICBzdGF0ZTogdHJ1ZSxcbiAgb25jcmVhdGU6IHRydWUsXG4gIG9udXBkYXRlOiB0cnVlLFxuICBvbnJlbW92ZTogdHJ1ZSxcbiAgc2hvdWxkdXBkYXRlOiB0cnVlLFxuICBcInYtY2xlYW51cFwiOiB0cnVlLFxuICBcInYtb25jZVwiOiB0cnVlLFxuXG4gIC8vIEJ1aWx0IGluIGRpcmVjdGl2ZXNcbiAgXCJ2LWlmXCI6IHRydWUsXG4gIFwidi11bmxlc3NcIjogdHJ1ZSxcbiAgXCJ2LWZvclwiOiB0cnVlLFxuICBcInYtc2hvd1wiOiB0cnVlLFxuICBcInYtY2xhc3NcIjogdHJ1ZSxcbiAgXCJ2LWh0bWxcIjogdHJ1ZVxufTtcblxudi5pc1Zub2RlID0gaXNWbm9kZTtcbnYuaXNDb21wb25lbnQgPSBpc0NvbXBvbmVudDtcbnYuaXNWbm9kZUNvbXBvbmVudCA9IGlzVm5vZGVDb21wb25lbnQ7XG5cbnYuaXNOb2RlSnMgPSBpc05vZGVKcztcbnYudHJ1c3QgPSB0cnVzdDtcblxudi5vbkNsZWFudXAgPSBvbkNsZWFudXA7XG52Lm9uVW5tb3VudCA9IG9uVW5tb3VudDtcbnYub25Nb3VudCA9IG9uTW91bnQ7XG52Lm9uVXBkYXRlID0gb25VcGRhdGU7XG5cbnYubW91bnQgPSBtb3VudDtcbnYudW5tb3VudCA9IHVubW91bnQ7XG52LnVwZGF0ZSA9IHVwZGF0ZTtcblxudi5zZXRBdHRyaWJ1dGUgPSBzZXRBdHRyaWJ1dGU7XG52LmRpcmVjdGl2ZSA9IGRpcmVjdGl2ZTtcbnYudXNlID0gdXNlO1xuIl19 \ No newline at end of file diff --git a/lib/index.ts b/lib/index.ts index ddc0234..25b983f 100644 --- a/lib/index.ts +++ b/lib/index.ts @@ -7,6 +7,7 @@ import { DomElement, IVnode, MountedValyrianApp, + Plugin, Props, Valyrian, ValyrianApp, @@ -21,15 +22,15 @@ export const Vnode = function Vnode(this: IVnode, tag: string, props: Props, chi this.tag = tag; } as unknown as IVnode; -export function isVnode(component?: unknown): component is IVnode { - return component instanceof Vnode; +export function isVnode(object?: unknown | IVnode): object is IVnode { + return object instanceof Vnode; } export function isComponent(component?: unknown | ValyrianComponent): component is ValyrianComponent { return typeof component === "function" || (typeof component === "object" && component !== null && "view" in component); } -export function isVnodeComponent(vnode?: unknown): vnode is VnodeComponent { +export function isVnodeComponent(vnode?: unknown | VnodeComponent): vnode is VnodeComponent { return vnode instanceof Vnode && vnode.tag === "__component__"; } @@ -63,7 +64,7 @@ function domToVnode(dom: DomElement): VnodeWithDom { return vnode as VnodeWithDom; } -export const trust = (htmlString: string) => { +export const trust = (htmlString: string): IVnode[] => { let div = createDomElement("div"); div.innerHTML = htmlString.trim(); @@ -106,7 +107,7 @@ export function onUpdate(callback: Function) { mount('#app',
Hello world
); // App is a Vnode component (Vnode with tag __component__) */ -export function mount(container: DomElement | string, component: ValyrianComponent | IVnode) { +export function mount(container: DomElement | string, component: ValyrianComponent | IVnode): void | string { let appContainer = null; if (isNodeJs) { @@ -194,7 +195,7 @@ function callUpdate(valyrianApp: ValyrianApp) { valyrianApp.onUpdate = []; } -export function update(component?: ValyrianComponent | IVnode) { +export function update(component?: ValyrianComponent | IVnode): void | string { if (component && component[ValyrianSymbol]) { let valyrianApp = component[ValyrianSymbol]; v.current.app = valyrianApp; @@ -218,7 +219,7 @@ export function update(component?: ValyrianComponent | IVnode) { } } -export function unmount(component?: ValyrianComponent | IVnode) { +export function unmount(component?: ValyrianComponent | IVnode): void | string { if (!component || !component[ValyrianSymbol]) { return; } @@ -254,7 +255,7 @@ function onremove(vnode: IVnode) { vnode.props.onremove && vnode.props.onremove(vnode); } -function sharedUpdateProperty(prop: string, value: any, vnode: VnodeWithDom, oldVnode?: VnodeWithDom) { +function sharedSetAttribute(prop: string, value: any, vnode: VnodeWithDom, oldVnode?: VnodeWithDom) { // It is a reserved prop if (v.reservedProps[prop]) { // If it is a directive name call the directive @@ -293,22 +294,22 @@ function sharedUpdateProperty(prop: string, value: any, vnode: VnodeWithDom, old } } -export function setProperty(name: string, value: any, vnode: VnodeWithDom, oldVnode?: VnodeWithDom) { +export function setAttribute(name: string, value: any, vnode: VnodeWithDom, oldVnode?: VnodeWithDom) { if (name in vnode.props === false) { vnode.props[name] = value; } - sharedUpdateProperty(name, value, vnode, oldVnode); + sharedSetAttribute(name, value, vnode, oldVnode); } -function updateProperties(vnode: VnodeWithDom, oldVnode?: VnodeWithDom) { +function updateAttributes(vnode: VnodeWithDom, oldVnode?: VnodeWithDom) { for (let prop in vnode.props) { // We asume that we clean the props in some directive if (prop in vnode.props === false) { return; } - sharedUpdateProperty(prop, vnode.props[prop], vnode, oldVnode); + sharedSetAttribute(prop, vnode.props[prop], vnode, oldVnode); } if (oldVnode) { @@ -385,7 +386,7 @@ function patchKeyedTree( childVnode.children = oldChildVnode.children; shouldPatch = false; } else { - updateProperties(childVnode, oldChildVnode); + updateAttributes(childVnode, oldChildVnode); if (valyrianApp.isMounted) { childVnode.props.onupdate && childVnode.props.onupdate(childVnode, oldChildVnode); } else { @@ -394,7 +395,7 @@ function patchKeyedTree( } } else { childVnode.dom = createDomElement(childVnode.tag, childVnode.isSVG); - updateProperties(childVnode); + updateAttributes(childVnode); childVnode.props.oncreate && childVnode.props.oncreate(childVnode); } @@ -443,7 +444,7 @@ function patchNormalTree( // New child is a normal node newChildVnode.dom = createDomElement(newChildVnode.tag, newChildVnode.isSVG); - updateProperties(newChildVnode); + updateAttributes(newChildVnode); newVnode.dom.appendChild(newChildVnode.dom); newChildVnode.props.oncreate && newChildVnode.props.oncreate(newChildVnode); patch(newChildVnode, undefined, valyrianApp); @@ -482,7 +483,7 @@ function patchNormalTree( } // We update the dom element - updateProperties(newChildVnode, oldChildVnode); + updateAttributes(newChildVnode, oldChildVnode); if (valyrianApp && valyrianApp.isMounted) { newChildVnode.props.onupdate && newChildVnode.props.onupdate(newChildVnode, oldChildVnode); } else { @@ -495,7 +496,7 @@ function patchNormalTree( // Old child is of a different type than new child newChildVnode.dom = createDomElement(newChildVnode.tag, newChildVnode.isSVG); - updateProperties(newChildVnode); + updateAttributes(newChildVnode); if (oldChildVnode.tag !== "#text") { onremove(oldChildVnode); } @@ -618,15 +619,15 @@ const builtInDirectives = { handler = () => (model[property] = !model[property]); value = model[property]; } - setProperty("checked", value, vnode, oldVnode); + setAttribute("checked", value, vnode, oldVnode); break; } case "radio": { - setProperty("checked", model[property] === vnode.dom.value, vnode, oldVnode); + setAttribute("checked", model[property] === vnode.dom.value, vnode, oldVnode); break; } default: { - setProperty("value", model[property], vnode, oldVnode); + setAttribute("value", model[property], vnode, oldVnode); } } } else if (vnode.name === "select") { @@ -669,11 +670,24 @@ const builtInDirectives = { if (!handler) { handler = (e: Event) => (model[property] = (e.target as DomElement & Record).value); } - setProperty(event, handler, vnode, oldVnode); + setAttribute(event, handler, vnode, oldVnode); } } }; +/*** Plugins ***/ +const plugins = new Map(); + +export function use(plugin: Plugin, options?: Record): void | any { + if (plugins.has(plugin)) { + return plugins.get(plugin); + } + + let result = plugin(v, options); + plugins.set(plugin, result); + return result; +} + /*** Hyperscript ***/ export const v: Valyrian = function v(tagOrComponent: string | ValyrianComponent, props: Props, ...children: Children): IVnode | VnodeComponent { @@ -690,6 +704,8 @@ v.fragment = (props: Props, ...children: Children): Children => { return children; }; +/*** V properties and methods ***/ +// This is intended to make the properties and methods available for plugins v.current = {} as Current; v.directives = { ...builtInDirectives }; @@ -713,4 +729,22 @@ v.reservedProps = { "v-html": true }; -((isNodeJs ? global : window) as unknown as { v: Valyrian }).v = v as Valyrian; +v.isVnode = isVnode; +v.isComponent = isComponent; +v.isVnodeComponent = isVnodeComponent; + +v.isNodeJs = isNodeJs; +v.trust = trust; + +v.onCleanup = onCleanup; +v.onUnmount = onUnmount; +v.onMount = onMount; +v.onUpdate = onUpdate; + +v.mount = mount; +v.unmount = unmount; +v.update = update; + +v.setAttribute = setAttribute; +v.directive = directive; +v.use = use; diff --git a/lib/interfaces.ts b/lib/interfaces.ts index 597f5d9..60d17b5 100644 --- a/lib/interfaces.ts +++ b/lib/interfaces.ts @@ -90,12 +90,37 @@ export interface ReservedProps { [key: string]: true; } +export interface Plugin { + (valyrian: Valyrian, options?: Record): void | any; +} + export interface Valyrian { (tagOrComponent: string | ValyrianComponent, props: Props, ...children: Children): IVnode | VnodeComponent; fragment: (props: Props, ...children: Children) => Children; current: Current; directives: Directives; reservedProps: ReservedProps; + + isVnode: (object?: unknown | IVnode) => object is IVnode; + isComponent: (component?: unknown | ValyrianComponent) => component is ValyrianComponent; + isVnodeComponent: (vnode?: unknown | VnodeComponent) => vnode is VnodeComponent; + + isNodeJs: boolean; + trust: (htmlString: string) => IVnode[]; + + onCleanup: (fn: Function) => void; + onUnmount: (fn: Function) => void; + onMount: (fn: Function) => void; + onUpdate: (fn: Function) => void; + + mount: (container: DomElement | string, component: ValyrianComponent | IVnode) => void | string; + update: (component: ValyrianComponent | IVnode) => void | string; + unmount: (component: ValyrianComponent | IVnode) => void | string; + + setAttribute: (name: string, value: any, vnode: VnodeWithDom, oldVnode?: VnodeWithDom) => void; + directive: (name: string, directive: Directive) => void; + use: (plugin: Plugin, options?: Record) => void | any; + [key: string | number | symbol]: any; } diff --git a/package.json b/package.json index ed73c6b..e247e75 100644 --- a/package.json +++ b/package.json @@ -52,44 +52,42 @@ "bench": "nodemon -e js,ts,json,css,tsx -w ./bench -w ./lib -w ./plugins --exec 'buffalo-test --require ./register'" }, "dependencies": { - "clean-css": "^5.2.2", - "esbuild": "^0.14.5", + "clean-css": "^5.2.4", + "esbuild": "^0.14.22", "favicons": "^6.2.2", "form-data": "^4.0.0", - "node-fetch": "2.6.1", + "node-fetch": "2.6.7", "parse5": "^6.0.1", - "pirates": "^4.0.4", + "pirates": "^4.0.5", "purgecss": "4.1.3", "terser": "^5.10.0", - "ts-node": "^10.4.0", + "ts-node": "^10.5.0", "tsc-prog": "^2.2.1", "tslib": "^2.3.1", - "typescript": "^4.5.4" + "typescript": "^4.5.5" }, "devDependencies": { - "@release-it/conventional-changelog": "^3.3.0", - "@types/mocha": "^9.0.0", - "@types/node": "^17.0.0", - "@typescript-eslint/eslint-plugin": "^5.7.0", - "@typescript-eslint/parser": "^5.7.0", + "@release-it/conventional-changelog": "^4.1.0", + "@types/mocha": "^9.1.0", + "@types/node": "^17.0.18", + "@typescript-eslint/eslint-plugin": "^5.12.0", + "@typescript-eslint/parser": "^5.12.0", "buffalo-test": "^2.0.0", "compression": "^1.7.4", "cross-env": "^7.0.3", "cz-conventional-changelog": "3.3.0", "dayjs": "^1.10.7", - "eslint": "^8.4.1", + "eslint": "^8.9.0", "eslint-plugin-sonarjs": "^0.11.0", - "expect": "^27.4.2", - "faker": "^5.5.3", - "fastify": "^3.25.0", + "expect": "^27.5.1", + "fastify": "^3.27.1", "gzip-size": "^7.0.0", - "mocha": "^9.1.3", - "node-dev": "^7.1.0", + "mocha": "^9.2.0", + "nodemon": "^2.0.15", "nyc": "^15.1.0", - "release-it": "^14.11.8", + "release-it": "^14.12.4", "remark-cli": "^10.0.1", - "remark-toc": "^8.0.1", - "yargs": "^17.3.0" + "remark-toc": "^8.0.1" }, "nyc": { "exclude": [ diff --git a/plugins/hooks.js b/plugins/hooks.js index eaf0644..79ead22 100644 --- a/plugins/hooks.js +++ b/plugins/hooks.js @@ -1,6 +1,8 @@ +let current = {}; + function createHook({ create, update, remove }) { return (...args) => { - let { component, vnode, oldVnode, app } = v.current; + let { component, vnode, oldVnode, app } = current; // Init the components array for the current vnode if (vnode.components === undefined) { @@ -105,6 +107,13 @@ const useEffect = createHook({ } }); -const plugin = { useState, useEffect, createHook }; +function plugin(v) { + current = v.current; +} + +plugin.useState = useState; +plugin.useEffect = useEffect; +plugin.createHook = createHook; + plugin.default = plugin; module.exports = plugin; diff --git a/plugins/node.js b/plugins/node.js index 09e978a..b7439be 100644 --- a/plugins/node.js +++ b/plugins/node.js @@ -1,5 +1,4 @@ /* eslint-disable sonarjs/cognitive-complexity */ -const { mount, unmount } = require("../lib"); let fs = require("fs"); let path = require("path"); @@ -295,20 +294,32 @@ icons.options = { } }; -let plugin = { - inline, - sw, - icons, - htmlTDom: treeAdapter.htmlToDom, - domToHtml: treeAdapter.domToHtml, - domToHyperscript: treeAdapter.domToHyperscript, - htmlToHyperscript: treeAdapter.htmlToHyperscript, - render: (...args) => { - let Component = () => args; - let result = mount("div", Component); - unmount(Component); - return result; +let mount = () => {}; +let unmount = () => {}; +let isInUse = false; + +function plugin(v) { + mount = v.mount; + unmount = v.unmount; + isInUse = true; +} + +plugin.inline = inline; +plugin.sw = sw; +plugin.icons = icons; +plugin.htmlTDom = treeAdapter.htmlToDom; +plugin.domToHtml = treeAdapter.domToHtml; +plugin.domToHyperscript = treeAdapter.domToHyperscript; +plugin.htmlToHyperscript = treeAdapter.htmlToHyperscript; +plugin.render = (...args) => { + if (!isInUse) { + throw new Error("This plugin is not in use. Please invoke `v.use(nodeJsPlugin)`"); } + + let Component = () => args; + let result = mount("div", Component); + unmount(Component); + return result; }; plugin.default = plugin; diff --git a/plugins/router.js b/plugins/router.js index bd35f18..f87d778 100644 --- a/plugins/router.js +++ b/plugins/router.js @@ -1,5 +1,3 @@ -const { mount, updateProperty, directive, isNodeJs, isComponent, isVnodeComponent } = require("../lib"); - function flat(array) { return Array.isArray(array) ? array.flat(Infinity) : [array]; } @@ -104,7 +102,7 @@ async function searchComponent(router, middlewares) { for (; i < middlewares.length; i++) { response = await middlewares[i](req, response); - if (response !== undefined && (isComponent(response) || isVnodeComponent(response))) { + if (response !== undefined && (router.v.isComponent(response) || router.v.isVnodeComponent(response))) { return response; } } @@ -179,55 +177,68 @@ class Router { } if (parentComponent) { - let childComponent = isVnodeComponent(component) ? component : v(component, {}); - if (isVnodeComponent(parentComponent)) { + let childComponent = this.v.isVnodeComponent(component) ? component : this.v(component, {}); + if (this.v.isVnodeComponent(parentComponent)) { parentComponent.children.push(childComponent); } else { - parentComponent = v(parentComponent, {}, childComponent); + parentComponent = this.v(parentComponent, {}, childComponent); } component = parentComponent; } - if (!isNodeJs) { + if (!this.v.isNodeJs) { window.history.pushState(null, null, url); } - return mount(this.container, component); + if (this.v.current.component === component) { + return this.v.update(component); + } + + return this.v.mount(this.container, component); } +} - mount(elementContainer) { - if (elementContainer) { - this.container = elementContainer; - // Activate the use of the router - if (!isNodeJs) { - function onPopStateGoToRoute() { - this.go(document.location.pathname); - } - window.addEventListener("popstate", onPopStateGoToRoute.bind(this), false); - onPopStateGoToRoute(); +function plugin(v) { + const mount = v.mount; + v.mount = (elementContainer, routerOrComponent) => { + if (routerOrComponent instanceof Router === false) { + return mount(elementContainer, routerOrComponent); + } + + routerOrComponent.container = elementContainer; + routerOrComponent.v = v; + + // Activate the use of the router + if (!v.isNodeJs) { + function onPopStateGoToRoute() { + routerOrComponent.go(document.location.pathname); } + window.addEventListener("popstate", onPopStateGoToRoute, false); + onPopStateGoToRoute(); + } - directive("route", (url, vnode, oldnode) => { - vnode.props.href = url; - vnode.props.onclick = (e) => { - if (typeof url === "string" && url.length > 0) { - if (url.charAt(0) !== "/") { - let current = this.current.split("?", 2).shift().split("/"); - current.pop(); - url = `${current.join("/")}/${url}`; - } - - this.go(url); + v.directive("route", (url, vnode, oldnode) => { + vnode.props.href = url; + vnode.props.onclick = (e) => { + if (typeof url === "string" && url.length > 0) { + if (url.charAt(0) !== "/") { + let current = routerOrComponent.current.split("?", 2).shift().split("/"); + current.pop(); + url = `${current.join("/")}/${url}`; } - e.preventDefault(); - }; - updateProperty("href", vnode, oldnode); - updateProperty("onclick", vnode, oldnode); - }); - } - } + routerOrComponent.go(url); + } + e.preventDefault(); + }; + + v.setAttribute("href", vnode, oldnode); + v.setAttribute("onclick", vnode, oldnode); + }); + }; } -Router.default = Router; -module.exports = Router; +plugin.Router = Router; + +plugin.default = plugin; +module.exports = plugin; diff --git a/plugins/store.js b/plugins/store.js index 79fddef..5ab9c47 100644 --- a/plugins/store.js +++ b/plugins/store.js @@ -61,7 +61,7 @@ function Store({ state = {}, getters = {}, actions = {}, mutations = {} } = {}) frozen = false; mutations[mutation](this.state, ...args); frozen = true; - v.isMounted && v.update(); + update(); }; this.dispatch = (action, ...args) => { @@ -70,5 +70,18 @@ function Store({ state = {}, getters = {}, actions = {}, mutations = {} } = {}) }; } -Store.default = Store; -module.exports = Store; +let update = () => {}; +let current = {}; + +function plugin(v) { + current = v.current; + update = () => { + if (current.app) { + v.update(v.current.app.component); + } + }; +} + +plugin.Store = Store; +plugin.default = plugin; +module.exports = plugin; diff --git a/test/directives_test.js b/test/directives_test.js index 8b6e772..d5790c5 100644 --- a/test/directives_test.js +++ b/test/directives_test.js @@ -1,8 +1,7 @@ const expect = require("expect"); -const faker = require("faker"); const dayjs = require("dayjs"); -import { directive, mount, setProperty, trust, update } from "../lib/index"; +const { v } = require("../lib/index"); require("../plugins/node"); @@ -13,9 +12,9 @@ describe("Directives", () => { let result; let expected = "Hello world"; - directive("test", (value) => (result = `Hello ${value}`)); + v.directive("test", (value) => (result = `Hello ${value}`)); - mount("div", () =>
); + v.mount("div", () =>
); expect(result).toEqual(expected); }); @@ -25,14 +24,13 @@ describe("Directives", () => { let app = () =>
; - directive("test2", (v, vnode, old) => { - console.log("here"); + v.directive("test2", (v, vnode, old) => { newVnode = vnode; oldVnode = old; }); - mount("div", app); - update(app); + v.mount("div", app); + v.update(app); expect(newVnode).toEqual({ tag: "div", @@ -58,7 +56,7 @@ describe("Directives", () => { it("should be able to identify if this is first render or update", () => { let app = () =>
; - directive("create", (v, vnode, oldVnode) => { + v.directive("create", (v, vnode, oldVnode) => { if (!oldVnode) { vnode.children = ["First render, vnode created"]; } else { @@ -66,18 +64,18 @@ describe("Directives", () => { } }); - let result = mount("body", app); + let result = v.mount("body", app); expect(result).toEqual("
First render, vnode created
"); - let result2 = update(app); + let result2 = v.update(app); expect(result2).toEqual("
Second render, vnode updated
"); }); it("should be able to modify the children of a vnode", () => { let expected = "
Hello world
"; - directive("test3", (v, vnode) => { + v.directive("test3", (v, vnode) => { vnode.children = ["Hello world"]; }); @@ -87,34 +85,35 @@ describe("Directives", () => {
); - let result = mount("div", app); + let result = v.mount("div", app); expect(result).toEqual(expected); }); /** * Modify properties is not guaranteed because the properties are processed by place - * If the directive needs to update previous properties you need to update the property using the setProperty method + * If the directive needs to update previous properties you need to update the property using the setAttribute method */ it("Modify properties is not guaranteed", () => { let update = false; let app = () =>
; - directive("test4", (v, vnode, oldVnode) => { + v.directive("test4", (value, vnode, oldVnode) => { // Try to change u property vnode.props.u = "property changed"; if (update) { - setProperty("u", "property changed", vnode, oldVnode); + console.log(v); + v.setAttribute("u", "property changed", vnode, oldVnode); } // Try to change x property vnode.props.x = "property changed"; }); - let result = mount("div", app); + let result = v.mount("div", app); expect(result).toEqual('
'); update = true; - let result2 = mount("div", app); + let result2 = v.mount("div", app); expect(result2).toEqual('
'); }); @@ -127,14 +126,14 @@ describe("Directives", () => { let formatDate = (value) => dayjs(value).format("MMMM D, YYYY"); - directive("date-inline", (date, vnode) => (vnode.children = [formatDate(date)])); - directive("date", (_, vnode) => (vnode.children = [formatDate(vnode.children[0])])); + v.directive("date-inline", (date, vnode) => (vnode.children = [formatDate(date)])); + v.directive("date", (_, vnode) => (vnode.children = [formatDate(vnode.children[0])])); let date = "08-16-2018"; - let result = mount("div", () =>
); + let result = v.mount("div", () =>
); expect(result).toEqual(expected); - result = mount("div", () =>
{date}
); + result = v.mount("div", () =>
{date}
); expect(result).toEqual(expected); }); @@ -144,7 +143,7 @@ describe("Directives", () => { * This is not added to the base library but it shows the capabilities of valyrian directives */ it("v-switch example", () => { - directive("switch", (value, vnode) => { + v.directive("switch", (value, vnode) => { for (let i = 0, l = vnode.children.length; i < l; i++) { let [test, handler] = vnode.children[i]; let result = false; @@ -174,25 +173,25 @@ describe("Directives", () => { // Direct equality expected = "
Hello John
"; name = "John"; - result = mount("div", component); + result = v.mount("div", component); expect(result).toEqual(expected); // Comparison method expected = "
Hello John Doe
"; name = "John Doe"; - result = mount("div", component); + result = v.mount("div", component); expect(result).toEqual(expected); // Result method expected = "
Hello Jane Doe
"; name = "Jane"; - result = mount("div", component); + result = v.mount("div", component); expect(result).toEqual(expected); // If no case return the value as children expected = "
Hello Anonymous
"; name = "Hello Anonymous"; - result = mount("div", component); + result = v.mount("div", component); expect(result).toEqual(expected); }); }); @@ -206,18 +205,18 @@ describe("Directives", () => { */ describe("v-for", () => { it("should create 10 list items", () => { - let items = faker.lorem.words(10).split(" "); + let items = ["alpha", "beta", "gamma", "delta", "epsilon", "zeta", "eta", "theta", "iota", "kappa"]; let expected = "
    " + items.reduce((str, word) => str + `
  • ${word}
  • `, "") + "
"; - let result = mount("body", () =>
    {(word) =>
  • {word}
  • }
); + let result = v.mount("body", () =>
    {(word) =>
  • {word}
  • }
); expect(result).toEqual(expected); }); it("should create 10 list items getting its index", () => { - let items = faker.lorem.words(10).split(" "); + let items = ["alpha", "beta", "gamma", "delta", "epsilon", "zeta", "eta", "theta", "iota", "kappa"]; let i = 0; let expected = "
    " + items.reduce((str, word) => str + `
  • ${i++} - ${word}
  • `, "") + "
"; - let result = mount("body", () => ( + let result = v.mount("body", () => (
    {(word, i) => (
  • @@ -242,7 +241,7 @@ describe("Directives", () => { let expected = "
    Hello world
    "; values.forEach((value) => { - let result = mount("div", () => ( + let result = v.mount("div", () => (
    Hello world
    @@ -257,7 +256,7 @@ describe("Directives", () => { let expected = "
    "; values.forEach((value) => { - let result = mount("div", () => ( + let result = v.mount("div", () => (
    Hello world
    @@ -276,11 +275,11 @@ describe("Directives", () => { Hello world
); - let result1 = mount("div", app); + let result1 = v.mount("div", app); expect(result1).toEqual(expected1); value = false; - let result2 = update(app); + let result2 = v.update(app); expect(result2).toEqual(expected2); }); }); @@ -299,7 +298,7 @@ describe("Directives", () => { let expected = "
Hello world
"; values.forEach((value) => { - let result = mount("div", () => ( + let result = v.mount("div", () => (
Hello world
@@ -314,7 +313,7 @@ describe("Directives", () => { let expected = "
"; values.forEach((value) => { - let result = mount("div", () => ( + let result = v.mount("div", () => (
Hello world
@@ -332,7 +331,7 @@ describe("Directives", () => { it("should show a vnode if true", () => { let value = true; let expected = "
Hello world
"; - let result = mount("div", () => ( + let result = v.mount("div", () => (
Hello world
@@ -344,7 +343,7 @@ describe("Directives", () => { it("should hide a vnode if false", () => { let value = false; let expected = '
Hello world
'; - let result = mount("div", () => ( + let result = v.mount("div", () => (
Hello world
@@ -364,11 +363,11 @@ describe("Directives", () => { }; let app = () =>
; - let result = mount("body", app); + let result = v.mount("body", app); expect(result).toEqual('
'); classes.world = false; - let result2 = update(app); + let result2 = v.update(app); expect(result2).toEqual("
"); }); @@ -377,11 +376,11 @@ describe("Directives", () => { world: true }; let app = () =>
; - let result = mount("body", app); + let result = v.mount("body", app); expect(result).toEqual('
'); classes.world = false; - let result2 = update(app); + let result2 = v.update(app); expect(result2).toEqual('
'); }); }); @@ -395,13 +394,13 @@ describe("Directives", () => { let Store = { hello: "world" }; let app = () =>
Hello {Store.hello}
; - let result = mount("body", app); + let result = v.mount("body", app); expect(result).toEqual("
Hello world
"); // We update our store Store.hello = "John Doe"; - let result2 = update(app); + let result2 = v.update(app); expect(result2).toEqual("
Hello world
"); }); }); @@ -414,14 +413,14 @@ describe("Directives", () => { describe("v-html", () => { it("should handle direct html render", () => { // Using trust example - let Component = () =>
{trust("
Hello world
")}
; - let result = mount("body", Component); + let Component = () =>
{v.trust("
Hello world
")}
; + let result = v.mount("body", Component); expect(result).toEqual("
Hello world
"); // Using v-html directive let Component2 = () =>
; - let result2 = mount("body", Component2); + let result2 = v.mount("body", Component2); expect(result2).toEqual("
Hello world
"); }); @@ -439,11 +438,11 @@ describe("Directives", () => {
); - let result = mount("body", app); + let result = v.mount("body", app); expect(result).toEqual("
1234
"); show = false; - let result2 = update(app); + let result2 = v.update(app); expect(result2).toEqual(""); }); }); @@ -457,7 +456,7 @@ describe("Directives", () => { let state = { hello: "world" }; let Component = () =>
oldVnode.props.state.hello !== newVnode.props.state.hello} />; - let result = mount("body", Component); + let result = v.mount("body", Component); expect(result).toEqual("
"); }); }); diff --git a/test/hooks_test.js b/test/hooks_test.js index 185edfd..af4aefe 100644 --- a/test/hooks_test.js +++ b/test/hooks_test.js @@ -1,10 +1,12 @@ -import "../lib"; import "../plugins/node"; -import { mount, onCleanup, unmount, update } from "../lib/index"; -import { useEffect, useState } from "../plugins/hooks"; +import { v } from "../lib/index"; +import plugin, { useEffect, useState } from "../plugins/hooks"; import expect from "expect"; +import { v } from "../lib"; + +v.use(plugin); describe("Hooks", () => { describe("State hook", () => { @@ -12,29 +14,29 @@ describe("Hooks", () => { let Counter = () => { let [count, setCount] = useState(0); let interval = setInterval(() => setCount(count + 1), 1000); - onCleanup(() => clearInterval(interval)); + v.onCleanup(() => clearInterval(interval)); return
{count}
; }; - let result = mount("div", Counter); + let result = v.mount("div", Counter); expect(result).toEqual("
0
"); await new Promise((resolve) => setTimeout(() => resolve(), 2050)); - result = update(Counter); + result = v.update(Counter); expect(result).toEqual("
2
"); }); - it("should handle subcomponents state and onCleanup", async () => { + it("should handle subcomponents state and v.onCleanup", async () => { let Ok = () => { let [ok, setOk] = useState("ok"); let interval = setInterval(() => setOk("not ok"), 1000); - onCleanup(() => clearInterval(interval)); + v.onCleanup(() => clearInterval(interval)); return
{ok}
; }; let Counter = () => { let [count, setCount] = useState(0); let interval = setInterval(() => setCount(count + 1), 1000); - onCleanup(() => clearInterval(interval)); + v.onCleanup(() => clearInterval(interval)); return (
{count} @@ -42,10 +44,10 @@ describe("Hooks", () => { ); }; - let result = mount("div", Counter); + let result = v.mount("div", Counter); expect(result).toEqual("
0
ok
"); await new Promise((resolve) => setTimeout(() => resolve(), 2050)); - result = update(Counter); + result = v.update(Counter); expect(result).toEqual("
2
not ok
"); }); @@ -53,14 +55,14 @@ describe("Hooks", () => { let Counter = () => { let [count, setCount] = useState(0); let interval = setInterval(() => setCount(count + 1), 1000); - onCleanup(() => clearInterval(interval)); + v.onCleanup(() => clearInterval(interval)); return
{count}
; }; - let result = mount("div", Counter); + let result = v.mount("div", Counter); expect(result).toEqual("
0
"); await new Promise((resolve) => setTimeout(() => resolve(), 2050)); - result = update(Counter); + result = v.update(Counter); expect(result).toEqual("
2
"); }); }); @@ -73,24 +75,24 @@ describe("Hooks", () => { return
{count}
; }; - let response = mount("body", Component); + let response = v.mount("body", Component); expect(response).toEqual("
1
"); }); - it("should call the effect at every update", () => { + it("should call the effect at every v.update", () => { let count = 0; let Component = function () { useEffect(() => count++); return
{count}
; }; - let response = mount("body", Component); + let response = v.mount("body", Component); expect(response).toEqual("
1
"); - response = update(Component); + response = v.update(Component); expect(response).toEqual("
2
"); }); - it("should handle onCleanup", () => { + it("should handle v.onCleanup", () => { let count = 0; let Component = function () { useEffect(() => { @@ -100,9 +102,9 @@ describe("Hooks", () => { return
{count}
; }; - let response = mount("body", Component); + let response = v.mount("body", Component); expect(response).toEqual("
1
"); - response = update(Component); + response = v.update(Component); expect(response).toEqual("
0
"); }); @@ -113,9 +115,9 @@ describe("Hooks", () => { return
{count}
; }; - let response = mount("body", Component); + let response = v.mount("body", Component); expect(response).toEqual("
1
"); - response = update(Component); + response = v.update(Component); expect(response).toEqual("
1
"); }); @@ -126,9 +128,9 @@ describe("Hooks", () => { return
{count}
; }; - let response = mount("body", Component); + let response = v.mount("body", Component); expect(response).toEqual("
1
"); - response = update(Component); + response = v.update(Component); expect(response).toEqual("
1
"); }); @@ -139,13 +141,13 @@ describe("Hooks", () => { return
{count}
; }; - let response = mount("body", Component); + let response = v.mount("body", Component); expect(response).toEqual("
1
"); - response = update(Component); + response = v.update(Component); expect(response).toEqual("
2
"); }); - it("should call onCleanup even if the changes array is passed and there are changes", () => { + it("should call v.onCleanup even if the changes array is passed and there are changes", () => { let count = 0; let Component = function () { useEffect(() => { @@ -155,15 +157,15 @@ describe("Hooks", () => { return
{count}
; }; - let response = mount("body", Component); + let response = v.mount("body", Component); expect(response).toEqual("
1
"); - response = update(Component); + response = v.update(Component); expect(response).toEqual("
3
"); - response = update(Component); + response = v.update(Component); expect(response).toEqual("
5
"); }); - it("should handle onCleanup on unMount", () => { + it("should handle v.onCleanup on unMount", () => { let count = 0; let Component = function () { useEffect(() => { @@ -173,20 +175,20 @@ describe("Hooks", () => { return
{count}
; }; - let response = mount("body", Component); + let response = v.mount("body", Component); expect(response).toEqual("
1
"); expect(count).toEqual(1); - response = update(Component); + response = v.update(Component); expect(response).toEqual("
0
"); expect(count).toEqual(0); - response = unmount(Component); + response = v.unmount(Component); expect(response).toEqual(""); expect(count).toEqual(-2); }); - it("should call the effect only in the unmount", () => { + it("should call the effect only in the v.unmount", () => { let count = 0; let Component = function () { useEffect(() => { @@ -195,15 +197,15 @@ describe("Hooks", () => { return
{count}
; }; - let response = mount("body", Component); + let response = v.mount("body", Component); expect(response).toEqual("
0
"); expect(count).toEqual(0); - response = update(Component); + response = v.update(Component); expect(response).toEqual("
0
"); expect(count).toEqual(0); - response = unmount(Component); + response = v.unmount(Component); expect(response).toEqual(""); expect(count).toEqual(1); }); @@ -225,26 +227,26 @@ describe("Hooks", () => { let HooksComponent = () => { // useEffect(plusHooks, []); // Only create replaced by the next line - useEffect(plusHooks); // Create & Update + useEffect(plusHooks); // Create & v.update useEffect(plusHooks, null); // Remove return
Hello world
; }; it("should call the lifecycle", () => { - mount("body", LifecycleComponent); + v.mount("body", LifecycleComponent); expect(lifecycleCount).toEqual(1); - update(LifecycleComponent); + v.update(LifecycleComponent); expect(lifecycleCount).toEqual(2); - unmount(LifecycleComponent); + v.unmount(LifecycleComponent); expect(lifecycleCount).toEqual(3); }); it("should call the hooks", () => { - mount("body", HooksComponent); + v.mount("body", HooksComponent); expect(hooksCount).toEqual(1); - update(HooksComponent); + v.update(HooksComponent); expect(hooksCount).toEqual(2); - unmount(HooksComponent); + v.unmount(HooksComponent); expect(hooksCount).toEqual(3); }); }); diff --git a/test/hyperscript_test.js b/test/hyperscript_test.js index 8b0265e..4a53e15 100644 --- a/test/hyperscript_test.js +++ b/test/hyperscript_test.js @@ -1,7 +1,7 @@ require("../plugins/node"); import expect from "expect"; -import { trust } from "../lib"; +import { v } from "../lib"; describe("Hyperscript", () => { it("should create a div element", () => { @@ -85,7 +85,7 @@ describe("Hyperscript", () => { }); it("should create a div element from string", () => { - expect(trust('
Hola mundo
')).toEqual([ + expect(v.trust('
Hola mundo
')).toEqual([ { tag: "div", props: { diff --git a/test/keyed_test.js b/test/keyed_test.js index 6bef201..c68a42c 100644 --- a/test/keyed_test.js +++ b/test/keyed_test.js @@ -1,6 +1,5 @@ -import { mount, update } from "../lib/index"; - import expect from "expect"; +import { v } from "../lib/index"; require("../plugins/node"); @@ -46,9 +45,9 @@ describe("Keyed lists", () => { ); - let before = mount("body", component); + let before = v.mount("body", component); keys = [...test.set]; - let after = update(component); + let after = v.update(component); let afterString = getString(test.set); @@ -71,15 +70,15 @@ describe("Keyed lists", () => { ); - let before = mount("body", component); + let before = v.mount("body", component); useStrings = false; - let after = update(component); + let after = v.update(component); let afterString = getString(keys); useStrings = true; - let afterUpdate = update(component); + let afterUpdate = v.update(component); expect(before).toEqual("
    12345
"); expect(after).toEqual(afterString); @@ -99,15 +98,15 @@ describe("Keyed lists", () => { ); - let before = mount("body", component); + let before = v.mount("body", component); keys = [6, 7, 8, 9, , 10]; - let after = update(component); + let after = v.update(component); let afterString = getString(keys); keys = [1, 2, 3, 4, 5]; - let afterUpdate = update(component); + let afterUpdate = v.update(component); let afterUpdateString = getString(keys); diff --git a/test/lifecycle_test.js b/test/lifecycle_test.js index 8a6d1ed..115632a 100644 --- a/test/lifecycle_test.js +++ b/test/lifecycle_test.js @@ -1,8 +1,7 @@ import "../plugins/node"; -import { mount, update } from "../lib/index"; - import expect from "expect"; +import { v } from "../lib/index"; describe("Lifecycle", () => { it("Mount and update", () => { @@ -122,19 +121,19 @@ describe("Lifecycle", () => { "onspanremove" ]; - result.push(mount("body", Lifecycle)); + result.push(v.mount("body", Lifecycle)); s = 0; - result.push(update(Lifecycle)); + result.push(v.update(Lifecycle)); s = 1; - result.push(update(Lifecycle)); + result.push(v.update(Lifecycle)); s = 2; - result.push(update(Lifecycle)); + result.push(v.update(Lifecycle)); s = 1; - result.push(update(Lifecycle)); + result.push(v.update(Lifecycle)); s = 3; - result.push(update(Lifecycle)); + result.push(v.update(Lifecycle)); s = 0; - result.push(update(Lifecycle)); + result.push(v.update(Lifecycle)); expect(result).toEqual(expectedDom); expect(calls).toEqual(expectedLifeCycleCalls); diff --git a/test/mount_n_update_test.js b/test/mount_n_update_test.js index 4c2098d..84c8049 100644 --- a/test/mount_n_update_test.js +++ b/test/mount_n_update_test.js @@ -1,6 +1,5 @@ -import { mount, trust, update } from "../lib/index"; - import expect from "expect"; +import { v } from "../lib/index"; require("../plugins/node"); @@ -16,9 +15,9 @@ describe("Mount and update", () => { let result = {}; - result.before = mount("body", Component); + result.before = v.mount("body", Component); Component.world = "John Doe"; - result.after = update(Component); + result.after = v.update(Component); expect(result).toEqual({ before: '
Hello World
', @@ -35,9 +34,9 @@ describe("Mount and update", () => { let result = {}; - result.before = mount("body", Component); + result.before = v.mount("body", Component); Component.world = "John Doe"; - result.after = update(Component); + result.after = v.update(Component); expect(result).toEqual({ before: '
Hello World
', @@ -57,9 +56,9 @@ describe("Mount and update", () => { let result = {}; - result.before = mount("body", Component); + result.before = v.mount("body", Component); state.world = "John Doe"; - result.after = update(Component); + result.after = v.update(Component); expect(result).toEqual({ before: '
Hello World
', @@ -77,7 +76,7 @@ describe("Mount and update", () => { ); expect( - mount( + v.mount( "body", Hello John @@ -97,10 +96,10 @@ describe("Mount and update", () => { }; let result = {}; - result.before = mount("body", Component); + result.before = v.mount("body", Component); Component.world = "John Doe"; - result.after = update(Component); - result.afteragain = update(Component); + result.after = v.update(Component); + result.afteragain = v.update(Component); expect(result).toEqual({ before: '
Hello World
', @@ -120,9 +119,9 @@ describe("Mount and update", () => { let app = ; - result.before = mount("body", app); + result.before = v.mount("body", app); props.world = "John Doe"; - result.after = update(app); + result.after = v.update(app); expect(result).toEqual({ before: '
Hello World
', @@ -136,9 +135,9 @@ describe("Mount and update", () => { let result = {}; - result.before = mount("body", Component); + result.before = v.mount("body", Component); text = false; - result.after = update(Component); + result.after = v.update(Component); expect(result).toEqual({ before: "Hello world", @@ -152,9 +151,9 @@ describe("Mount and update", () => { let result = {}; - result.before = mount("body", Component); + result.before = v.mount("body", Component); text = true; - result.after = update(Component); + result.after = v.update(Component); expect(result).toEqual({ before: "
Hello world
", @@ -168,9 +167,9 @@ describe("Mount and update", () => { let result = {}; - result.before = mount("body", Component); + result.before = v.mount("body", Component); disabled = false; - result.after = update(Component); + result.after = v.update(Component); expect(result).toEqual({ before: '
Hello world
', @@ -184,9 +183,9 @@ describe("Mount and update", () => { let result = {}; - result.before = mount("body", Component); + result.before = v.mount("body", Component); disabled = true; - result.after = update(Component); + result.after = v.update(Component); expect(result).toEqual({ before: "
Hello world
", @@ -198,32 +197,32 @@ describe("Mount and update", () => { let date = new Date(); let Component = () => v("div", null, [null, "Hello", , 1, date, { hello: "world" }, ["Hello"]]); - expect(mount("body", Component)).toEqual(`
Hello1${date}[object Object]Hello
`); + expect(v.mount("body", Component)).toEqual(`
Hello1${date}[object Object]Hello
`); }); it("Should handle svgs", () => { let svg = // eslint-disable-next-line max-len ''; - let Component = () => trust(svg); + let Component = () => v.trust(svg); // eslint-disable-next-line max-len - expect(mount("body", Component)).toEqual(svg); + expect(v.mount("body", Component)).toEqual(svg); }); it("should fail silently if try to update before mount", () => { let Component = () =>
Hello world
; - update(Component); + v.update(Component); }); it("should handle text vnode as new node", () => { - let vnode = trust("Some text"); + let vnode = v.trust("Some text"); let component = () => vnode; - let result = mount("body", component); + let result = v.mount("body", component); expect(result).toEqual("Some text"); vnode.children = ["Other text"]; - let result2 = update(component); + let result2 = v.update(component); expect(result2).toEqual("Some text"); }); @@ -231,10 +230,10 @@ describe("Mount and update", () => { let state = { foo: "bar" }; let component = () =>
expect(newNode.props.state).toEqual(oldNode.props.state)} />; - let result = mount("body", component); + let result = v.mount("body", component); expect(result).toEqual("
"); - let result2 = update(component); + let result2 = v.update(component); expect(result2).toEqual("
"); }); @@ -246,7 +245,7 @@ describe("Mount and update", () => { ); - let result = mount("body", component); + let result = v.mount("body", component); expect(result).toEqual("HelloWorld"); }); }); @@ -293,10 +292,10 @@ describe.skip("performance test", () => { ); - let before = mount("body", component); + let before = v.mount("body", component); keys = [...test.set]; v.unMount(); - let after = mount("body", component); + let after = v.mount("body", component); let afterString = getString(test.set); @@ -305,7 +304,7 @@ describe.skip("performance test", () => { for (let i = 100000; i--; ) { v.unMount(); - mount("body", component); + v.mount("body", component); } }); }); diff --git a/test/node_test.js b/test/node_test.js index 1f9ace8..3e6668c 100644 --- a/test/node_test.js +++ b/test/node_test.js @@ -1,10 +1,11 @@ -import "../lib/index"; - -import { htmlToHyperscript, icons, inline, render, sw } from "../plugins/node"; +import plugin, { htmlToHyperscript, icons, inline, render, sw } from "../plugins/node"; import expect from "expect"; import fs from "fs"; import packageJson from "../package.json"; +import { v } from "../lib/index"; + +v.use(plugin); describe("Node test", () => { it("Get hyperscript string from html", () => { diff --git a/test/request_test.js b/test/request_test.js index 1699e30..adda38d 100644 --- a/test/request_test.js +++ b/test/request_test.js @@ -1,9 +1,9 @@ -import "../lib/index"; import "../plugins/node"; import expect from "expect"; import fastify from "fastify"; import request from "../plugins/request"; +import { v } from "../lib/index"; let posts = []; for (let i = 10; i--; ) { diff --git a/test/router_test.js b/test/router_test.js index c21e37a..09175d7 100644 --- a/test/router_test.js +++ b/test/router_test.js @@ -1,9 +1,11 @@ -import "../lib/index"; import "../plugins/node"; -import Router from "../plugins/router"; +import plugin, { Router } from "../plugins/router"; + import expect from "expect"; -import { update } from "../lib/index"; +import { v } from "../lib/index"; + +v.use(plugin); // eslint-disable-next-line max-lines-per-function describe("Router", () => { @@ -52,7 +54,7 @@ describe("Router", () => { router.use("/ok", subrouter); router.use(() => () => "Not found"); - router.mount("body"); + v.mount("body", router); expect(await router.go("/ok/not/found/url?hello=world")).toEqual("Not ok"); expect(await router.go("/not/found/url?hello=world")).toEqual("Not found"); }); @@ -69,13 +71,13 @@ describe("Router", () => { let result = {}; let router = new Router(); router.get("/", () => Component); - router.mount("body"); + v.mount("body", router); result.before = await router.go("/"); Component.world = "John Doe"; result.after = await router.go("/"); Component.world = "World"; - result.final = update(Component); + result.final = v.update(Component); expect(result).toEqual({ before: '
Hello World
', @@ -95,13 +97,13 @@ describe("Router", () => { let result = {}; let router = new Router(); router.get("/", () => Component); - router.mount("body"); + v.mount("body", router); result.before = await router.go("/"); Component.world = "John Doe"; result.after = await router.go("/"); Component.world = "World"; - result.final = update(Component); + result.final = v.update(Component); expect(result).toEqual({ before: '
Hello World
', @@ -123,13 +125,13 @@ describe("Router", () => { let result = {}; let router = new Router(); router.get("/", () => Component); - router.mount("body"); + v.mount("body", router); result.before = await router.go("/"); state.world = "John Doe"; result.after = await router.go("/"); state.world = "World"; - result.final = update(Component); + result.final = v.update(Component); expect(result).toEqual({ before: '
Hello World
', @@ -148,7 +150,7 @@ describe("Router", () => { let result = {}; let router = new Router(); router.get("/", () => ); - router.mount("body"); + v.mount("body", router); result.before = await router.go("/"); props.world = "John Doe"; @@ -171,7 +173,7 @@ describe("Router", () => { router.get("/", () => Hello); router.use(() => NotFound); - router.mount("body"); + v.mount("body", router); let result = {}; result.found = await router.go("/"); @@ -204,7 +206,7 @@ describe("Router", () => { ); router.get("/hello/:world/whats/:up", [({ params }) => Object.assign(Hello, params), () => Hello]); - router.mount("body"); + v.mount("body", router); let result = {}; result.before = await router.go("/hello"); @@ -238,7 +240,7 @@ describe("Router", () => { // This is the final response () => Hello ); - router.mount("body"); + v.mount("body", router); let result = await router.go("/"); @@ -279,7 +281,7 @@ describe("Router", () => { let router = new Router(); router.use("/hello/:world", subrouter); - router.mount("body"); + v.mount("body", router); let result = {}; result.before = await router.go("/hello/Mike"); @@ -302,7 +304,7 @@ describe("Router", () => { let router = new Router(); router.get("/", () => Component); - router.mount("body"); + v.mount("body", router); let result = await router.go("/", ParentComponent); @@ -314,7 +316,7 @@ describe("Router", () => { let router = new Router(); router.get("/", () => Component); - router.mount("body"); + v.mount("body", router); let err; try { @@ -331,7 +333,7 @@ describe("Router", () => { router.get("/", () => { // Component is not returned }); - router.mount("body"); + v.mount("body", router); let err; try { @@ -351,7 +353,7 @@ describe("Router", () => { let router = new Router(); router.use("/hello/:world", subrouter).get("/", () => Component); - router.mount("body"); + v.mount("body", router); expect(router.routes()).toEqual(["/hello/:world/from/:country", "/hello/:world", "/"]); }); diff --git a/test/signals_test.js b/test/signals_test.js index e3e29df..74bc501 100644 --- a/test/signals_test.js +++ b/test/signals_test.js @@ -1,10 +1,8 @@ -import "../lib/index"; import "../plugins/node"; -import { mount, update } from "../lib/index"; - import Signal from "../plugins/signals"; import expect from "expect"; +import { v } from "../lib/index"; describe("Signals", () => { it("should create a signal", async () => { @@ -123,10 +121,10 @@ describe("Hooks like pattern", () => { let Component = Counter(1000); - let result = mount("div", Component); + let result = v.mount("div", Component); expect(result).toEqual("
0
"); await new Promise((resolve) => setTimeout(() => resolve(), 2050)); - result = update(Component); + result = v.update(Component); expect(result).toEqual("
2
"); }); @@ -145,10 +143,10 @@ describe("Hooks like pattern", () => { let Component = Counter(1000); - let result = mount("div", Component); + let result = v.mount("div", Component); expect(result).toEqual("
0
"); await new Promise((resolve) => setTimeout(() => resolve(), 2050)); - result = update(Component); + result = v.update(Component); expect(result).toEqual("
2
"); }); @@ -169,10 +167,10 @@ describe("Hooks like pattern", () => { let Component = Counter(1000); - let result = mount("div", Component); + let result = v.mount("div", Component); expect(result).toEqual("
0
"); await new Promise((resolve) => setTimeout(() => resolve(), 2050)); - result = update(Component); + result = v.update(Component); expect(result).toEqual("
2
"); }); }); diff --git a/test/store_test.js b/test/store_test.js index b97041d..8854b0a 100644 --- a/test/store_test.js +++ b/test/store_test.js @@ -1,6 +1,6 @@ -import "../lib/index"; +import plugin, {Store} from "../plugins/store"; +import { use, v } from "../lib/index"; -import Store from "../plugins/store"; import expect from "expect"; function getNewStore() { diff --git a/yarn.lock b/yarn.lock index fda2094..bc7e112 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,230 +2,249 @@ # yarn lockfile v1 -"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.12.13", "@babel/code-frame@^7.16.0": - version "7.16.0" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.16.0.tgz#0dfc80309beec8411e65e706461c408b0bb9b431" - integrity sha512-IF4EOMEV+bfYwOmNxGzSnjR2EmQod7f1UXOpZM3l4i4o4QNwzjtJAu/HxdjHq0aYBvdqMuQEY1eg0nqW9ZPORA== +"@ampproject/remapping@^2.1.0": + version "2.1.2" + resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.1.2.tgz#4edca94973ded9630d20101cd8559cedb8d8bd34" + integrity sha512-hoyByceqwKirw7w3Z7gnIIZC3Wx3J484Y3L/cMpXFbr7d9ZQj2mODrirNzcJa+SM3UlpWXYvKV4RlRpFXlWgXg== + dependencies: + "@jridgewell/trace-mapping" "^0.3.0" + +"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.12.13", "@babel/code-frame@^7.16.0", "@babel/code-frame@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.16.7.tgz#44416b6bd7624b998f5b1af5d470856c40138789" + integrity sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg== dependencies: - "@babel/highlight" "^7.16.0" + "@babel/highlight" "^7.16.7" -"@babel/compat-data@^7.16.0": - version "7.16.4" - resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.16.4.tgz#081d6bbc336ec5c2435c6346b2ae1fb98b5ac68e" - integrity sha512-1o/jo7D+kC9ZjHX5v+EHrdjl3PhxMrLSOTGsOdHJ+KL8HCaEK6ehrVL2RS6oHDZp+L7xLirLrPmQtEng769J/Q== +"@babel/compat-data@^7.16.4": + version "7.17.0" + resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.17.0.tgz#86850b8597ea6962089770952075dcaabb8dba34" + integrity sha512-392byTlpGWXMv4FbyWw3sAZ/FrW/DrwqLGXpy0mbyNe9Taqv1mg9yON5/o0cnr8XYCkFTZbC1eV+c+LAROgrng== "@babel/core@^7.7.5": - version "7.16.5" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.16.5.tgz#924aa9e1ae56e1e55f7184c8bf073a50d8677f5c" - integrity sha512-wUcenlLzuWMZ9Zt8S0KmFwGlH6QKRh3vsm/dhDA3CHkiTA45YuG1XkHRcNRl73EFPXDp/d5kVOU0/y7x2w6OaQ== - dependencies: - "@babel/code-frame" "^7.16.0" - "@babel/generator" "^7.16.5" - "@babel/helper-compilation-targets" "^7.16.3" - "@babel/helper-module-transforms" "^7.16.5" - "@babel/helpers" "^7.16.5" - "@babel/parser" "^7.16.5" - "@babel/template" "^7.16.0" - "@babel/traverse" "^7.16.5" - "@babel/types" "^7.16.0" + version "7.17.4" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.17.4.tgz#a22f1ae8999122873b3d18865e98c7a3936b8c8b" + integrity sha512-R9x5r4t4+hBqZTmioSnkrW+I6NmbojwjGT8p4G2Gw1thWbXIHGDnmGdLdFw0/7ljucdIrNRp7Npgb4CyBYzzJg== + dependencies: + "@ampproject/remapping" "^2.1.0" + "@babel/code-frame" "^7.16.7" + "@babel/generator" "^7.17.3" + "@babel/helper-compilation-targets" "^7.16.7" + "@babel/helper-module-transforms" "^7.16.7" + "@babel/helpers" "^7.17.2" + "@babel/parser" "^7.17.3" + "@babel/template" "^7.16.7" + "@babel/traverse" "^7.17.3" + "@babel/types" "^7.17.0" convert-source-map "^1.7.0" debug "^4.1.0" gensync "^1.0.0-beta.2" json5 "^2.1.2" semver "^6.3.0" - source-map "^0.5.0" -"@babel/generator@^7.16.5": - version "7.16.5" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.16.5.tgz#26e1192eb8f78e0a3acaf3eede3c6fc96d22bedf" - integrity sha512-kIvCdjZqcdKqoDbVVdt5R99icaRtrtYhYK/xux5qiWCBmfdvEYMFZ68QCrpE5cbFM1JsuArUNs1ZkuKtTtUcZA== +"@babel/generator@^7.17.3": + version "7.17.3" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.17.3.tgz#a2c30b0c4f89858cb87050c3ffdfd36bdf443200" + integrity sha512-+R6Dctil/MgUsZsZAkYgK+ADNSZzJRRy0TvY65T71z/CR854xHQ1EweBYXdfT+HNeN7w0cSJJEzgxZMv40pxsg== dependencies: - "@babel/types" "^7.16.0" + "@babel/types" "^7.17.0" jsesc "^2.5.1" source-map "^0.5.0" -"@babel/helper-compilation-targets@^7.16.3": - version "7.16.3" - resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.16.3.tgz#5b480cd13f68363df6ec4dc8ac8e2da11363cbf0" - integrity sha512-vKsoSQAyBmxS35JUOOt+07cLc6Nk/2ljLIHwmq2/NM6hdioUaqEXq/S+nXvbvXbZkNDlWOymPanJGOc4CBjSJA== +"@babel/helper-compilation-targets@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.16.7.tgz#06e66c5f299601e6c7da350049315e83209d551b" + integrity sha512-mGojBwIWcwGD6rfqgRXVlVYmPAv7eOpIemUG3dGnDdCY4Pae70ROij3XmfrH6Fa1h1aiDylpglbZyktfzyo/hA== dependencies: - "@babel/compat-data" "^7.16.0" - "@babel/helper-validator-option" "^7.14.5" + "@babel/compat-data" "^7.16.4" + "@babel/helper-validator-option" "^7.16.7" browserslist "^4.17.5" semver "^6.3.0" -"@babel/helper-environment-visitor@^7.16.5": - version "7.16.5" - resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.16.5.tgz#f6a7f38b3c6d8b07c88faea083c46c09ef5451b8" - integrity sha512-ODQyc5AnxmZWm/R2W7fzhamOk1ey8gSguo5SGvF0zcB3uUzRpTRmM/jmLSm9bDMyPlvbyJ+PwPEK0BWIoZ9wjg== +"@babel/helper-environment-visitor@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.16.7.tgz#ff484094a839bde9d89cd63cba017d7aae80ecd7" + integrity sha512-SLLb0AAn6PkUeAfKJCCOl9e1R53pQlGAfc4y4XuMRZfqeMYLE0dM1LMhqbGAlGQY0lfw5/ohoYWAe9V1yibRag== dependencies: - "@babel/types" "^7.16.0" + "@babel/types" "^7.16.7" -"@babel/helper-function-name@^7.16.0": - version "7.16.0" - resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.16.0.tgz#b7dd0797d00bbfee4f07e9c4ea5b0e30c8bb1481" - integrity sha512-BZh4mEk1xi2h4HFjWUXRQX5AEx4rvaZxHgax9gcjdLWdkjsY7MKt5p0otjsg5noXw+pB+clMCjw+aEVYADMjog== +"@babel/helper-function-name@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.16.7.tgz#f1ec51551fb1c8956bc8dd95f38523b6cf375f8f" + integrity sha512-QfDfEnIUyyBSR3HtrtGECuZ6DAyCkYFp7GHl75vFtTnn6pjKeK0T1DB5lLkFvBea8MdaiUABx3osbgLyInoejA== dependencies: - "@babel/helper-get-function-arity" "^7.16.0" - "@babel/template" "^7.16.0" - "@babel/types" "^7.16.0" + "@babel/helper-get-function-arity" "^7.16.7" + "@babel/template" "^7.16.7" + "@babel/types" "^7.16.7" -"@babel/helper-get-function-arity@^7.16.0": - version "7.16.0" - resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.16.0.tgz#0088c7486b29a9cb5d948b1a1de46db66e089cfa" - integrity sha512-ASCquNcywC1NkYh/z7Cgp3w31YW8aojjYIlNg4VeJiHkqyP4AzIvr4qx7pYDb4/s8YcsZWqqOSxgkvjUz1kpDQ== +"@babel/helper-get-function-arity@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.16.7.tgz#ea08ac753117a669f1508ba06ebcc49156387419" + integrity sha512-flc+RLSOBXzNzVhcLu6ujeHUrD6tANAOU5ojrRx/as+tbzf8+stUCj7+IfRRoAbEZqj/ahXEMsjhOhgeZsrnTw== dependencies: - "@babel/types" "^7.16.0" + "@babel/types" "^7.16.7" -"@babel/helper-hoist-variables@^7.16.0": - version "7.16.0" - resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.16.0.tgz#4c9023c2f1def7e28ff46fc1dbcd36a39beaa81a" - integrity sha512-1AZlpazjUR0EQZQv3sgRNfM9mEVWPK3M6vlalczA+EECcPz3XPh6VplbErL5UoMpChhSck5wAJHthlj1bYpcmg== +"@babel/helper-hoist-variables@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.16.7.tgz#86bcb19a77a509c7b77d0e22323ef588fa58c246" + integrity sha512-m04d/0Op34H5v7pbZw6pSKP7weA6lsMvfiIAMeIvkY/R4xQtBSMFEigu9QTZ2qB/9l22vsxtM8a+Q8CzD255fg== dependencies: - "@babel/types" "^7.16.0" + "@babel/types" "^7.16.7" -"@babel/helper-module-imports@^7.16.0": - version "7.16.0" - resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.16.0.tgz#90538e60b672ecf1b448f5f4f5433d37e79a3ec3" - integrity sha512-kkH7sWzKPq0xt3H1n+ghb4xEMP8k0U7XV3kkB+ZGy69kDk2ySFW1qPi06sjKzFY3t1j6XbJSqr4mF9L7CYVyhg== +"@babel/helper-module-imports@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.16.7.tgz#25612a8091a999704461c8a222d0efec5d091437" + integrity sha512-LVtS6TqjJHFc+nYeITRo6VLXve70xmq7wPhWTqDJusJEgGmkAACWwMiTNrvfoQo6hEhFwAIixNkvB0jPXDL8Wg== dependencies: - "@babel/types" "^7.16.0" + "@babel/types" "^7.16.7" -"@babel/helper-module-transforms@^7.16.5": - version "7.16.5" - resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.16.5.tgz#530ebf6ea87b500f60840578515adda2af470a29" - integrity sha512-CkvMxgV4ZyyioElFwcuWnDCcNIeyqTkCm9BxXZi73RR1ozqlpboqsbGUNvRTflgZtFbbJ1v5Emvm+lkjMYY/LQ== +"@babel/helper-module-transforms@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.16.7.tgz#7665faeb721a01ca5327ddc6bba15a5cb34b6a41" + integrity sha512-gaqtLDxJEFCeQbYp9aLAefjhkKdjKcdh6DB7jniIGU3Pz52WAmP268zK0VgPz9hUNkMSYeH976K2/Y6yPadpng== dependencies: - "@babel/helper-environment-visitor" "^7.16.5" - "@babel/helper-module-imports" "^7.16.0" - "@babel/helper-simple-access" "^7.16.0" - "@babel/helper-split-export-declaration" "^7.16.0" - "@babel/helper-validator-identifier" "^7.15.7" - "@babel/template" "^7.16.0" - "@babel/traverse" "^7.16.5" - "@babel/types" "^7.16.0" + "@babel/helper-environment-visitor" "^7.16.7" + "@babel/helper-module-imports" "^7.16.7" + "@babel/helper-simple-access" "^7.16.7" + "@babel/helper-split-export-declaration" "^7.16.7" + "@babel/helper-validator-identifier" "^7.16.7" + "@babel/template" "^7.16.7" + "@babel/traverse" "^7.16.7" + "@babel/types" "^7.16.7" -"@babel/helper-simple-access@^7.16.0": - version "7.16.0" - resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.16.0.tgz#21d6a27620e383e37534cf6c10bba019a6f90517" - integrity sha512-o1rjBT/gppAqKsYfUdfHq5Rk03lMQrkPHG1OWzHWpLgVXRH4HnMM9Et9CVdIqwkCQlobnGHEJMsgWP/jE1zUiw== +"@babel/helper-simple-access@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.16.7.tgz#d656654b9ea08dbb9659b69d61063ccd343ff0f7" + integrity sha512-ZIzHVyoeLMvXMN/vok/a4LWRy8G2v205mNP0XOuf9XRLyX5/u9CnVulUtDgUTama3lT+bf/UqucuZjqiGuTS1g== dependencies: - "@babel/types" "^7.16.0" + "@babel/types" "^7.16.7" -"@babel/helper-split-export-declaration@^7.16.0": - version "7.16.0" - resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.16.0.tgz#29672f43663e936df370aaeb22beddb3baec7438" - integrity sha512-0YMMRpuDFNGTHNRiiqJX19GjNXA4H0E8jZ2ibccfSxaCogbm3am5WN/2nQNj0YnQwGWM1J06GOcQ2qnh3+0paw== +"@babel/helper-split-export-declaration@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.16.7.tgz#0b648c0c42da9d3920d85ad585f2778620b8726b" + integrity sha512-xbWoy/PFoxSWazIToT9Sif+jJTlrMcndIsaOKvTA6u7QEo7ilkRZpjew18/W3c7nm8fXdUDXh02VXTbZ0pGDNw== dependencies: - "@babel/types" "^7.16.0" + "@babel/types" "^7.16.7" -"@babel/helper-validator-identifier@^7.15.7": - version "7.15.7" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.15.7.tgz#220df993bfe904a4a6b02ab4f3385a5ebf6e2389" - integrity sha512-K4JvCtQqad9OY2+yTU8w+E82ywk/fe+ELNlt1G8z3bVGlZfn/hOcQQsUhGhW/N+tb3fxK800wLtKOE/aM0m72w== +"@babel/helper-validator-identifier@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz#e8c602438c4a8195751243da9031d1607d247cad" + integrity sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw== -"@babel/helper-validator-option@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.14.5.tgz#6e72a1fff18d5dfcb878e1e62f1a021c4b72d5a3" - integrity sha512-OX8D5eeX4XwcroVW45NMvoYaIuFI+GQpA2a8Gi+X/U/cDUIRsV37qQfF905F0htTRCREQIB4KqPeaveRJUl3Ow== +"@babel/helper-validator-option@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.16.7.tgz#b203ce62ce5fe153899b617c08957de860de4d23" + integrity sha512-TRtenOuRUVo9oIQGPC5G9DgK4743cdxvtOw0weQNpZXaS16SCBi5MNjZF8vba3ETURjZpTbVn7Vvcf2eAwFozQ== -"@babel/helpers@^7.16.5": - version "7.16.5" - resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.16.5.tgz#29a052d4b827846dd76ece16f565b9634c554ebd" - integrity sha512-TLgi6Lh71vvMZGEkFuIxzaPsyeYCHQ5jJOOX1f0xXn0uciFuE8cEk0wyBquMcCxBXZ5BJhE2aUB7pnWTD150Tw== +"@babel/helpers@^7.17.2": + version "7.17.2" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.17.2.tgz#23f0a0746c8e287773ccd27c14be428891f63417" + integrity sha512-0Qu7RLR1dILozr/6M0xgj+DFPmi6Bnulgm9M8BVa9ZCWxDqlSnqt3cf8IDPB5m45sVXUZ0kuQAgUrdSFFH79fQ== dependencies: - "@babel/template" "^7.16.0" - "@babel/traverse" "^7.16.5" - "@babel/types" "^7.16.0" + "@babel/template" "^7.16.7" + "@babel/traverse" "^7.17.0" + "@babel/types" "^7.17.0" -"@babel/highlight@^7.16.0": - version "7.16.0" - resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.16.0.tgz#6ceb32b2ca4b8f5f361fb7fd821e3fddf4a1725a" - integrity sha512-t8MH41kUQylBtu2+4IQA3atqevA2lRgqA2wyVB/YiWmsDSuylZZuXOUy9ric30hfzauEFfdsuk/eXTRrGrfd0g== +"@babel/highlight@^7.16.7": + version "7.16.10" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.16.10.tgz#744f2eb81579d6eea753c227b0f570ad785aba88" + integrity sha512-5FnTQLSLswEj6IkgVw5KusNUUFY9ZGqe/TRFnP/BKYHYgfh7tc+C7mwiy95/yNP7Dh9x580Vv8r7u7ZfTBFxdw== dependencies: - "@babel/helper-validator-identifier" "^7.15.7" + "@babel/helper-validator-identifier" "^7.16.7" chalk "^2.0.0" js-tokens "^4.0.0" -"@babel/parser@^7.16.0", "@babel/parser@^7.16.5": - version "7.16.6" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.16.6.tgz#8f194828193e8fa79166f34a4b4e52f3e769a314" - integrity sha512-Gr86ujcNuPDnNOY8mi383Hvi8IYrJVJYuf3XcuBM/Dgd+bINn/7tHqsj+tKkoreMbmGsFLsltI/JJd8fOFWGDQ== +"@babel/parser@^7.16.7", "@babel/parser@^7.17.3": + version "7.17.3" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.17.3.tgz#b07702b982990bf6fdc1da5049a23fece4c5c3d0" + integrity sha512-7yJPvPV+ESz2IUTPbOL+YkIGyCqOyNIzdguKQuJGnH7bg1WTIifuM21YqokFt/THWh1AkCRn9IgoykTRCBVpzA== "@babel/runtime@^7.7.2": - version "7.16.5" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.16.5.tgz#7f3e34bf8bdbbadf03fbb7b1ea0d929569c9487a" - integrity sha512-TXWihFIS3Pyv5hzR7j6ihmeLkZfrXGxAr5UfSl8CHf+6q/wpiYDkUau0czckpYG8QmnCIuPpdLtuA9VmuGGyMA== + version "7.17.2" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.17.2.tgz#66f68591605e59da47523c631416b18508779941" + integrity sha512-hzeyJyMA1YGdJTuWU0e/j4wKXrU4OMFvY2MSlaI9B7VQb0r5cxTE3EAIS2Q7Tn2RIcDkRvTA/v2JsAEhxe99uw== dependencies: regenerator-runtime "^0.13.4" -"@babel/template@^7.16.0": - version "7.16.0" - resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.16.0.tgz#d16a35ebf4cd74e202083356fab21dd89363ddd6" - integrity sha512-MnZdpFD/ZdYhXwiunMqqgyZyucaYsbL0IrjoGjaVhGilz+x8YB++kRfygSOIj1yOtWKPlx7NBp+9I1RQSgsd5A== - dependencies: - "@babel/code-frame" "^7.16.0" - "@babel/parser" "^7.16.0" - "@babel/types" "^7.16.0" - -"@babel/traverse@^7.16.5": - version "7.16.5" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.16.5.tgz#d7d400a8229c714a59b87624fc67b0f1fbd4b2b3" - integrity sha512-FOCODAzqUMROikDYLYxl4nmwiLlu85rNqBML/A5hKRVXG2LV8d0iMqgPzdYTcIpjZEBB7D6UDU9vxRZiriASdQ== - dependencies: - "@babel/code-frame" "^7.16.0" - "@babel/generator" "^7.16.5" - "@babel/helper-environment-visitor" "^7.16.5" - "@babel/helper-function-name" "^7.16.0" - "@babel/helper-hoist-variables" "^7.16.0" - "@babel/helper-split-export-declaration" "^7.16.0" - "@babel/parser" "^7.16.5" - "@babel/types" "^7.16.0" +"@babel/template@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.16.7.tgz#8d126c8701fde4d66b264b3eba3d96f07666d155" + integrity sha512-I8j/x8kHUrbYRTUxXrrMbfCa7jxkE7tZre39x3kjr9hvI82cK1FfqLygotcWN5kdPGWcLdWMHpSBavse5tWw3w== + dependencies: + "@babel/code-frame" "^7.16.7" + "@babel/parser" "^7.16.7" + "@babel/types" "^7.16.7" + +"@babel/traverse@^7.16.7", "@babel/traverse@^7.17.0", "@babel/traverse@^7.17.3": + version "7.17.3" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.17.3.tgz#0ae0f15b27d9a92ba1f2263358ea7c4e7db47b57" + integrity sha512-5irClVky7TxRWIRtxlh2WPUUOLhcPN06AGgaQSB8AEwuyEBgJVuJ5imdHm5zxk8w0QS5T+tDfnDxAlhWjpb7cw== + dependencies: + "@babel/code-frame" "^7.16.7" + "@babel/generator" "^7.17.3" + "@babel/helper-environment-visitor" "^7.16.7" + "@babel/helper-function-name" "^7.16.7" + "@babel/helper-hoist-variables" "^7.16.7" + "@babel/helper-split-export-declaration" "^7.16.7" + "@babel/parser" "^7.17.3" + "@babel/types" "^7.17.0" debug "^4.1.0" globals "^11.1.0" -"@babel/types@^7.16.0": - version "7.16.0" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.16.0.tgz#db3b313804f96aadd0b776c4823e127ad67289ba" - integrity sha512-PJgg/k3SdLsGb3hhisFvtLOw5ts113klrpLuIPtCJIU+BB24fqq6lf8RWqKJEjzqXR9AEH1rIb5XTqwBHB+kQg== +"@babel/types@^7.16.7", "@babel/types@^7.17.0": + version "7.17.0" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.17.0.tgz#a826e368bccb6b3d84acd76acad5c0d87342390b" + integrity sha512-TmKSNO4D5rzhL5bjWFcVHHLETzfQ/AmbKpKPOSjlP0WoHZ6L911fgoOKY4Alp/emzG4cHJdyN49zpgkbXFEHHw== dependencies: - "@babel/helper-validator-identifier" "^7.15.7" + "@babel/helper-validator-identifier" "^7.16.7" to-fast-properties "^2.0.0" -"@commitlint/execute-rule@^15.0.0": - version "15.0.0" - resolved "https://registry.yarnpkg.com/@commitlint/execute-rule/-/execute-rule-15.0.0.tgz#6bff7962df38e89ff9fdbc00abd79b8849c7e9f9" - integrity sha512-pyE4ApxjbWhb1TXz5vRiGwI2ssdMMgZbaaheZq1/7WC0xRnqnIhE1yUC1D2q20qPtvkZPstTYvMiRVtF+DvjUg== +"@commitlint/config-validator@^16.2.1": + version "16.2.1" + resolved "https://registry.yarnpkg.com/@commitlint/config-validator/-/config-validator-16.2.1.tgz#794e769afd4756e4cf1bfd823b6612932e39c56d" + integrity sha512-hogSe0WGg7CKmp4IfNbdNES3Rq3UEI4XRPB8JL4EPgo/ORq5nrGTVzxJh78omibNuB8Ho4501Czb1Er1MoDWpw== + dependencies: + "@commitlint/types" "^16.2.1" + ajv "^6.12.6" + +"@commitlint/execute-rule@^16.2.1": + version "16.2.1" + resolved "https://registry.yarnpkg.com/@commitlint/execute-rule/-/execute-rule-16.2.1.tgz#60be73be4b9af97a41546e7ce59fdd33787c65f8" + integrity sha512-oSls82fmUTLM6cl5V3epdVo4gHhbmBFvCvQGHBRdQ50H/690Uq1Dyd7hXMuKITCIdcnr9umyDkr8r5C6HZDF3g== "@commitlint/load@>6.1.1": - version "15.0.0" - resolved "https://registry.yarnpkg.com/@commitlint/load/-/load-15.0.0.tgz#5bd391c1387aafe92b54cf2a86b76a5228fcf4ef" - integrity sha512-Ak1YPeOhvxmY3ioe0o6m1yLGvUAYb4BdfGgShU8jiTCmU3Mnmms0Xh/kfQz8AybhezCC3AmVTyBLaBZxOHR8kg== - dependencies: - "@commitlint/execute-rule" "^15.0.0" - "@commitlint/resolve-extends" "^15.0.0" - "@commitlint/types" "^15.0.0" - "@endemolshinegroup/cosmiconfig-typescript-loader" "^3.0.2" + version "16.2.1" + resolved "https://registry.yarnpkg.com/@commitlint/load/-/load-16.2.1.tgz#301bda1bff66b3e40a85819f854eda72538d8e24" + integrity sha512-oSpz0jTyVI/A1AIImxJINTLDOMB8YF7lWGm+Jg5wVWM0r7ucpuhyViVvpSRTgvL0z09oIxlctyFGWUQQpI42uw== + dependencies: + "@commitlint/config-validator" "^16.2.1" + "@commitlint/execute-rule" "^16.2.1" + "@commitlint/resolve-extends" "^16.2.1" + "@commitlint/types" "^16.2.1" + "@types/node" ">=12" chalk "^4.0.0" cosmiconfig "^7.0.0" + cosmiconfig-typescript-loader "^1.0.0" lodash "^4.17.19" resolve-from "^5.0.0" typescript "^4.4.3" -"@commitlint/resolve-extends@^15.0.0": - version "15.0.0" - resolved "https://registry.yarnpkg.com/@commitlint/resolve-extends/-/resolve-extends-15.0.0.tgz#baf21227e2ac52cef546ec35dd6732e9b0b6e57c" - integrity sha512-7apfRJjgJsKja7lHsPfEFixKjA/fk/UeD3owkOw1174yYu4u8xBDLSeU3IinGPdMuF9m245eX8wo7vLUy+EBSg== +"@commitlint/resolve-extends@^16.2.1": + version "16.2.1" + resolved "https://registry.yarnpkg.com/@commitlint/resolve-extends/-/resolve-extends-16.2.1.tgz#2f7833a5a3a7aa79f508e59fcb0f1d33c45ed360" + integrity sha512-NbbCMPKTFf2J805kwfP9EO+vV+XvnaHRcBy6ud5dF35dxMsvdJqke54W3XazXF1ZAxC4a3LBy4i/GNVBAthsEg== dependencies: + "@commitlint/config-validator" "^16.2.1" + "@commitlint/types" "^16.2.1" import-fresh "^3.0.0" lodash "^4.17.19" resolve-from "^5.0.0" resolve-global "^1.0.0" -"@commitlint/types@^15.0.0": - version "15.0.0" - resolved "https://registry.yarnpkg.com/@commitlint/types/-/types-15.0.0.tgz#46fa7bda3e6340caf3e3a2e415bcb78ff0195eed" - integrity sha512-OMSLX+QJnyNoTwws54ULv9sOvuw9GdVezln76oyUd4YbMMJyaav62aSXDuCdWyL2sm9hTkSzyEi52PNaIj/vqw== +"@commitlint/types@^16.2.1": + version "16.2.1" + resolved "https://registry.yarnpkg.com/@commitlint/types/-/types-16.2.1.tgz#f25d373b88b01e51fc3fa44488101361945a61bd" + integrity sha512-7/z7pA7BM0i8XvMSBynO7xsB3mVQPUZbVn6zMIlp/a091XJ3qAXRXc+HwLYhiIdzzS5fuxxNIHZMGHVD4HJxdA== dependencies: chalk "^4.0.0" @@ -253,24 +272,14 @@ dependencies: "@cspotcode/source-map-consumer" "0.8.0" -"@endemolshinegroup/cosmiconfig-typescript-loader@^3.0.2": - version "3.0.2" - resolved "https://registry.yarnpkg.com/@endemolshinegroup/cosmiconfig-typescript-loader/-/cosmiconfig-typescript-loader-3.0.2.tgz#eea4635828dde372838b0909693ebd9aafeec22d" - integrity sha512-QRVtqJuS1mcT56oHpVegkKBlgtWjXw/gHNWO3eL9oyB5Sc7HBoc2OLG/nYpVfT/Jejvo3NUrD0Udk7XgoyDKkA== - dependencies: - lodash.get "^4" - make-error "^1" - ts-node "^9" - tslib "^2" - -"@eslint/eslintrc@^1.0.5": - version "1.0.5" - resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-1.0.5.tgz#33f1b838dbf1f923bfa517e008362b78ddbbf318" - integrity sha512-BLxsnmK3KyPunz5wmCCpqy0YelEoxxGmH73Is+Z74oOTMtExcjkr3dDR6quwrjh1YspA8DH9gnX1o069KiS9AQ== +"@eslint/eslintrc@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-1.1.0.tgz#583d12dbec5d4f22f333f9669f7d0b7c7815b4d3" + integrity sha512-C1DfL7XX4nPqGd6jcP01W9pVM1HYCuUkFk1432D7F0v3JSlUIeOYn9oCoi3eoLZ+iwBSb29BMFxxny0YrrEZqg== dependencies: ajv "^6.12.4" debug "^4.3.2" - espree "^9.2.0" + espree "^9.3.1" globals "^13.9.0" ignore "^4.0.6" import-fresh "^3.2.1" @@ -286,9 +295,9 @@ ajv "^6.12.6" "@humanwhocodes/config-array@^0.9.2": - version "0.9.2" - resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.9.2.tgz#68be55c737023009dfc5fe245d51181bb6476914" - integrity sha512-UXOuFCGcwciWckOpmfKDq/GyhlTf9pN/BzG//x8p8zTOFEcGuA68ANXheFS0AGvy3qgZqLBUkMs7hqzqCKOVwA== + version "0.9.3" + resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.9.3.tgz#f2564c744b387775b436418491f15fce6601f63e" + integrity sha512-3xSMlXHh03hCcCmFc0rbKp3Ivt2PFEJnQUJDDMTJQ2wkECZWdq4GePs2ctc5H8zV+cHPaq8k2vU8mrQjA6iHdQ== dependencies: "@humanwhocodes/object-schema" "^1.2.1" debug "^4.1.1" @@ -325,10 +334,10 @@ resolved "https://registry.yarnpkg.com/@istanbuljs/schema/-/schema-0.1.3.tgz#e45e384e4b8ec16bce2fd903af78450f6bf7ec98" integrity sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA== -"@jest/types@^27.4.2": - version "27.4.2" - resolved "https://registry.yarnpkg.com/@jest/types/-/types-27.4.2.tgz#96536ebd34da6392c2b7c7737d693885b5dd44a5" - integrity sha512-j35yw0PMTPpZsUoOBiuHzr1zTYoad1cVIE0ajEjcrJONxxrko/IRGKkXx3os0Nsi4Hu3+5VmDbVfq5WhG/pWAg== +"@jest/types@^27.5.1": + version "27.5.1" + resolved "https://registry.yarnpkg.com/@jest/types/-/types-27.5.1.tgz#3c79ec4a8ba61c170bf937bcf9e98a9df175ec80" + integrity sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw== dependencies: "@types/istanbul-lib-coverage" "^2.0.0" "@types/istanbul-reports" "^3.0.0" @@ -626,6 +635,24 @@ "@babel/runtime" "^7.7.2" regenerator-runtime "^0.13.3" +"@jridgewell/resolve-uri@^3.0.3": + version "3.0.5" + resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.0.5.tgz#68eb521368db76d040a6315cdb24bf2483037b9c" + integrity sha512-VPeQ7+wH0itvQxnG+lIzWgkysKIr3L9sslimFW55rHMdGu/qCQ5z5h9zq4gI8uBtqkpHhsF4Z/OwExufUCThew== + +"@jridgewell/sourcemap-codec@^1.4.10": + version "1.4.11" + resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.11.tgz#771a1d8d744eeb71b6adb35808e1a6c7b9b8c8ec" + integrity sha512-Fg32GrJo61m+VqYSdRSjRXMjQ06j8YIYfcTqndLYVAaHmroZHLJZCydsWBOTDqXS2v+mjxohBWEMfg97GXmYQg== + +"@jridgewell/trace-mapping@^0.3.0": + version "0.3.4" + resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.4.tgz#f6a0832dffd5b8a6aaa633b7d9f8e8e94c83a0c3" + integrity sha512-vFv9ttIedivx0ux3QSjhgtCVjPZd5l46ZOMDSCwnH1yUO2e964gO8LZGyv2QkqcgR6TnBU1v+1IFqmeoG+0UJQ== + dependencies: + "@jridgewell/resolve-uri" "^3.0.3" + "@jridgewell/sourcemap-codec" "^1.4.10" + "@nodelib/fs.scandir@2.1.5": version "2.1.5" resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" @@ -720,15 +747,15 @@ once "^1.4.0" "@octokit/request@^5.6.0": - version "5.6.2" - resolved "https://registry.yarnpkg.com/@octokit/request/-/request-5.6.2.tgz#1aa74d5da7b9e04ac60ef232edd9a7438dcf32d8" - integrity sha512-je66CvSEVf0jCpRISxkUcCa0UkxmFs6eGDRSbfJtAVwbLH5ceqF+YEyC8lj8ystKyZTy8adWr0qmkY52EfOeLA== + version "5.6.3" + resolved "https://registry.yarnpkg.com/@octokit/request/-/request-5.6.3.tgz#19a022515a5bba965ac06c9d1334514eb50c48b0" + integrity sha512-bFJl0I1KVc9jYTe9tdGGpAMPy32dLBXXo1dS/YwSCTL/2nd9XeHsY616RE3HPXDVk+a+dBuzyz5YdlXwcDTr2A== dependencies: "@octokit/endpoint" "^6.0.1" "@octokit/request-error" "^2.1.0" "@octokit/types" "^6.16.1" is-plain-object "^5.0.0" - node-fetch "^2.6.1" + node-fetch "^2.6.7" universal-user-agent "^6.0.0" "@octokit/rest@18.12.0": @@ -748,13 +775,13 @@ dependencies: "@octokit/openapi-types" "^11.2.0" -"@release-it/conventional-changelog@^3.3.0": - version "3.3.0" - resolved "https://registry.yarnpkg.com/@release-it/conventional-changelog/-/conventional-changelog-3.3.0.tgz#0f79e4b736412040d37c2b84bf433e393268c08e" - integrity sha512-pchCHf+wNpn15oj2hau4gisFKQat/01JuTzAwlGsQE83ZUBknU4dRlPA3xf5F5f3K70VVTQ3lx4/lgQvR+zxww== +"@release-it/conventional-changelog@^4.1.0": + version "4.1.0" + resolved "https://registry.yarnpkg.com/@release-it/conventional-changelog/-/conventional-changelog-4.1.0.tgz#86a91259c331c081f49ca915847102da6e454942" + integrity sha512-MTinrJNyzhaqJ71gg4dZCe+wzdtssUjweQT7p1lDtSqRP6BtGp98NlfBlXACnCaOaETb7bI3fknoLsztqibTpQ== dependencies: concat-stream "^2.0.0" - conventional-changelog "^3.1.24" + conventional-changelog "^3.1.25" conventional-recommended-bump "^6.1.0" prepend-file "^2.0.0" @@ -764,9 +791,9 @@ integrity sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ== "@sindresorhus/is@^4.0.0": - version "4.2.0" - resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-4.2.0.tgz#667bfc6186ae7c9e0b45a08960c551437176e1ca" - integrity sha512-VkE3KLBmJwcCaVARtQpfuKcKv8gcBmUubrfHGF84dXuuW6jgsRYxPtzcIhPyK9WAPpRt2/xY6zkD9MnRaJzSyw== + version "4.4.0" + resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-4.4.0.tgz#e277e5bdbdf7cb1e20d320f02f5e2ed113cd3185" + integrity sha512-QppPM/8l3Mawvh4rn9CNEYIU9bxpXUCRMaX9yUpvBk1nMKusLKpfXGDEKExKaPhLzcn3lzil7pR6rnJ11HgeRQ== "@szmarczak/http-timer@^1.1.2": version "1.1.2" @@ -847,9 +874,9 @@ integrity sha512-a3xgqnFTuNJDm1fjsTjHocYJ40Cz3t8utYpi5GNaxzrJC2HSD08ym+whIL7fNqiqBCdM9bcqD1H/tORWAFXoZw== "@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.0": - version "2.0.3" - resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.3.tgz#4ba8ddb720221f432e443bd5f9117fd22cfd4762" - integrity sha512-sz7iLqvVUg1gIedBOvlkxPlc8/uVzyS5OwGz1cKjXzkl3FpL3al0crU8YGU1WoHkxn0Wxbw5tyi6hvzJKNzFsw== + version "2.0.4" + resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz#8467d4b3c087805d63580480890791277ce35c44" + integrity sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g== "@types/istanbul-lib-report@*": version "3.0.0" @@ -894,25 +921,20 @@ resolved "https://registry.yarnpkg.com/@types/minimist/-/minimist-1.2.2.tgz#ee771e2ba4b3dc5b372935d549fd9617bf345b8c" integrity sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ== -"@types/mocha@^9.0.0": - version "9.0.0" - resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-9.0.0.tgz#3205bcd15ada9bc681ac20bef64e9e6df88fd297" - integrity sha512-scN0hAWyLVAvLR9AyW7HoFF5sJZglyBsbPuHO4fv7JRvfmPBMfp1ozWqOf/e4wwPNxezBZXRfWzMb6iFLgEVRA== +"@types/mocha@^9.1.0": + version "9.1.0" + resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-9.1.0.tgz#baf17ab2cca3fcce2d322ebc30454bff487efad5" + integrity sha512-QCWHkbMv4Y5U9oW10Uxbr45qMMSzl4OzijsozynUAgx3kEHUdXB00udx2dWDQ7f2TU2a2uuiFaRZjCe3unPpeg== "@types/ms@*": version "0.7.31" resolved "https://registry.yarnpkg.com/@types/ms/-/ms-0.7.31.tgz#31b7ca6407128a3d2bbc27fe2d21b345397f6197" integrity sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA== -"@types/node@*", "@types/node@^17.0.0": - version "17.0.0" - resolved "https://registry.yarnpkg.com/@types/node/-/node-17.0.0.tgz#62797cee3b8b497f6547503b2312254d4fe3c2bb" - integrity sha512-eMhwJXc931Ihh4tkU+Y7GiLzT/y/DBNpNtr4yU9O2w3SYBsr9NaOPhQlLKRmoWtI54uNwuo0IOUFQjVOTZYRvw== - -"@types/node@^16.0.0": - version "16.11.14" - resolved "https://registry.yarnpkg.com/@types/node/-/node-16.11.14.tgz#4939fb42e5b0ffb3ea7e193c28244fe7414977a6" - integrity sha512-mK6BKLpL0bG6v2CxHbm0ed6RcZrAtTHBTd/ZpnlVPVa3HkumsqLE4BC4u6TQ8D7pnrRbOU0am6epuALs+Ncnzw== +"@types/node@*", "@types/node@>=12", "@types/node@^17.0.0", "@types/node@^17.0.18": + version "17.0.18" + resolved "https://registry.yarnpkg.com/@types/node/-/node-17.0.18.tgz#3b4fed5cfb58010e3a2be4b6e74615e4847f1074" + integrity sha512-eKj4f/BsN/qcculZiRSujogjvp5O/k4lOW5m35NopjZM/QwLOR075a8pJW5hD+Rtdm2DaCVPENS6KtSQnUD6BA== "@types/normalize-package-data@^2.4.0": version "2.4.1" @@ -963,13 +985,14 @@ dependencies: "@types/yargs-parser" "*" -"@typescript-eslint/eslint-plugin@^5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.7.0.tgz#12d54709f8ea1da99a01d8a992cd0474ad0f0aa9" - integrity sha512-8RTGBpNn5a9M628wBPrCbJ+v3YTEOE2qeZb7TDkGKTDXSj36KGRg92SpFFaR/0S3rSXQxM0Og/kV9EyadsYSBg== +"@typescript-eslint/eslint-plugin@^5.12.0": + version "5.12.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.12.0.tgz#bb46dd7ce7015c0928b98af1e602118e97df6c70" + integrity sha512-fwCMkDimwHVeIOKeBHiZhRUfJXU8n6xW1FL9diDxAyGAFvKcH4csy0v7twivOQdQdA0KC8TDr7GGRd3L4Lv0rQ== dependencies: - "@typescript-eslint/experimental-utils" "5.7.0" - "@typescript-eslint/scope-manager" "5.7.0" + "@typescript-eslint/scope-manager" "5.12.0" + "@typescript-eslint/type-utils" "5.12.0" + "@typescript-eslint/utils" "5.12.0" debug "^4.3.2" functional-red-black-tree "^1.0.1" ignore "^5.1.8" @@ -977,60 +1000,69 @@ semver "^7.3.5" tsutils "^3.21.0" -"@typescript-eslint/experimental-utils@5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-5.7.0.tgz#2b1633e6613c3238036156f70c32634843ad034f" - integrity sha512-u57eZ5FbEpzN5kSjmVrSesovWslH2ZyNPnaXQMXWgH57d5+EVHEt76W75vVuI9qKZ5BMDKNfRN+pxcPEjQjb2A== +"@typescript-eslint/parser@^5.12.0": + version "5.12.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.12.0.tgz#0ca669861813df99ce54916f66f524c625ed2434" + integrity sha512-MfSwg9JMBojMUoGjUmX+D2stoQj1CBYTCP0qnnVtu9A+YQXVKNtLjasYh+jozOcrb/wau8TCfWOkQTiOAruBog== dependencies: - "@types/json-schema" "^7.0.9" - "@typescript-eslint/scope-manager" "5.7.0" - "@typescript-eslint/types" "5.7.0" - "@typescript-eslint/typescript-estree" "5.7.0" - eslint-scope "^5.1.1" - eslint-utils "^3.0.0" + "@typescript-eslint/scope-manager" "5.12.0" + "@typescript-eslint/types" "5.12.0" + "@typescript-eslint/typescript-estree" "5.12.0" + debug "^4.3.2" -"@typescript-eslint/parser@^5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.7.0.tgz#4dca6de463d86f02d252e681136a67888ea3b181" - integrity sha512-m/gWCCcS4jXw6vkrPQ1BjZ1vomP01PArgzvauBqzsoZ3urLbsRChexB8/YV8z9HwE3qlJM35FxfKZ1nfP/4x8g== +"@typescript-eslint/scope-manager@5.12.0": + version "5.12.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.12.0.tgz#59619e6e5e2b1ce6cb3948b56014d3a24da83f5e" + integrity sha512-GAMobtIJI8FGf1sLlUWNUm2IOkIjvn7laFWyRx7CLrv6nLBI7su+B7lbStqVlK5NdLvHRFiJo2HhiDF7Ki01WQ== dependencies: - "@typescript-eslint/scope-manager" "5.7.0" - "@typescript-eslint/types" "5.7.0" - "@typescript-eslint/typescript-estree" "5.7.0" - debug "^4.3.2" + "@typescript-eslint/types" "5.12.0" + "@typescript-eslint/visitor-keys" "5.12.0" -"@typescript-eslint/scope-manager@5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.7.0.tgz#70adf960e5a58994ad50438ba60d98ecadd79452" - integrity sha512-7mxR520DGq5F7sSSgM0HSSMJ+TFUymOeFRMfUfGFAVBv8BR+Jv1vHgAouYUvWRZeszVBJlLcc9fDdktxb5kmxA== +"@typescript-eslint/type-utils@5.12.0": + version "5.12.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-5.12.0.tgz#aaf45765de71c6d9707c66ccff76ec2b9aa31bb6" + integrity sha512-9j9rli3zEBV+ae7rlbBOotJcI6zfc6SHFMdKI9M3Nc0sy458LJ79Os+TPWeBBL96J9/e36rdJOfCuyRSgFAA0Q== dependencies: - "@typescript-eslint/types" "5.7.0" - "@typescript-eslint/visitor-keys" "5.7.0" + "@typescript-eslint/utils" "5.12.0" + debug "^4.3.2" + tsutils "^3.21.0" -"@typescript-eslint/types@5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.7.0.tgz#2d4cae0105ba7d08bffa69698197a762483ebcbe" - integrity sha512-5AeYIF5p2kAneIpnLFve8g50VyAjq7udM7ApZZ9JYjdPjkz0LvODfuSHIDUVnIuUoxafoWzpFyU7Sqbxgi79mA== +"@typescript-eslint/types@5.12.0": + version "5.12.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.12.0.tgz#5b4030a28222ee01e851836562c07769eecda0b8" + integrity sha512-JowqbwPf93nvf8fZn5XrPGFBdIK8+yx5UEGs2QFAYFI8IWYfrzz+6zqlurGr2ctShMaJxqwsqmra3WXWjH1nRQ== -"@typescript-eslint/typescript-estree@5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.7.0.tgz#968fad899050ccce4f08a40cd5fabc0798525006" - integrity sha512-aO1Ql+izMrTnPj5aFFlEJkpD4jRqC4Gwhygu2oHK2wfVQpmOPbyDSveJ+r/NQo+PWV43M6uEAeLVbTi09dFLhg== +"@typescript-eslint/typescript-estree@5.12.0": + version "5.12.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.12.0.tgz#cabf545fd592722f0e2b4104711e63bf89525cd2" + integrity sha512-Dd9gVeOqt38QHR0BEA8oRaT65WYqPYbIc5tRFQPkfLquVEFPD1HAtbZT98TLBkEcCkvwDYOAvuSvAD9DnQhMfQ== dependencies: - "@typescript-eslint/types" "5.7.0" - "@typescript-eslint/visitor-keys" "5.7.0" + "@typescript-eslint/types" "5.12.0" + "@typescript-eslint/visitor-keys" "5.12.0" debug "^4.3.2" globby "^11.0.4" is-glob "^4.0.3" semver "^7.3.5" tsutils "^3.21.0" -"@typescript-eslint/visitor-keys@5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.7.0.tgz#e05164239eb7cb8aa9fa06c516ede480ce260178" - integrity sha512-hdohahZ4lTFcglZSJ3DGdzxQHBSxsLVqHzkiOmKi7xVAWC4y2c1bIMKmPJSrA4aOEoRUPOKQ87Y/taC7yVHpFg== +"@typescript-eslint/utils@5.12.0": + version "5.12.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.12.0.tgz#92fd3193191621ab863add2f553a7b38b65646af" + integrity sha512-k4J2WovnMPGI4PzKgDtQdNrCnmBHpMUFy21qjX2CoPdoBcSBIMvVBr9P2YDP8jOqZOeK3ThOL6VO/sy6jtnvzw== dependencies: - "@typescript-eslint/types" "5.7.0" + "@types/json-schema" "^7.0.9" + "@typescript-eslint/scope-manager" "5.12.0" + "@typescript-eslint/types" "5.12.0" + "@typescript-eslint/typescript-estree" "5.12.0" + eslint-scope "^5.1.1" + eslint-utils "^3.0.0" + +"@typescript-eslint/visitor-keys@5.12.0": + version "5.12.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.12.0.tgz#1ac9352ed140b07ba144ebf371b743fdf537ec16" + integrity sha512-cFwTlgnMV6TgezQynx2c/4/tx9Tufbuo9LPzmWqyRC3QC4qTGkAG1C6pBr0/4I10PAI/FlYunI3vJjIcu+ZHMg== + dependencies: + "@typescript-eslint/types" "5.12.0" eslint-visitor-keys "^3.0.0" "@ungap/promise-all-settled@1.1.2": @@ -1046,18 +1078,23 @@ JSONStream@^1.0.4: jsonparse "^1.2.0" through ">=2.2.7 <3" +abbrev@1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" + integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== + abstract-logging@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/abstract-logging/-/abstract-logging-2.0.1.tgz#6b0c371df212db7129b57d2e7fcf282b8bf1c839" integrity sha512-2BjRTZxTPvheOvGbBslFSYOUkr+SjPtOnrLP33f+VIWLzezQpZcqVg7ja3L4dBXmzzgwT+a029jRx5PCi3JuiA== accepts@~1.3.5: - version "1.3.7" - resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.7.tgz#531bc726517a3b2b41f850021c6cc15eaab507cd" - integrity sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA== + version "1.3.8" + resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.8.tgz#0bf0be125b67014adcb0b0921e62db7bffe16b2e" + integrity sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw== dependencies: - mime-types "~2.1.24" - negotiator "0.6.2" + mime-types "~2.1.34" + negotiator "0.6.3" acorn-jsx@^5.3.1: version "5.3.2" @@ -1069,10 +1106,10 @@ acorn-walk@^8.1.1: resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.2.0.tgz#741210f2e2426454508853a2f44d0ab83b7f69c1" integrity sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA== -acorn@^8.4.1, acorn@^8.6.0: - version "8.6.0" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.6.0.tgz#e3692ba0eb1a0c83eaa4f37f5fa7368dd7142895" - integrity sha512-U1riIR+lBSNi3IbxtaHOIKdH8sLFv3NYfNv8sg7ZsNhcfl4HF2++BfqqrNAxoCLQW1iiylOj76ecnaUxz+z9yw== +acorn@^8.4.1, acorn@^8.7.0: + version "8.7.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.7.0.tgz#90951fde0f8f09df93549481e5fc141445b791cf" + integrity sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ== add-stream@^1.0.0: version "1.0.0" @@ -1098,9 +1135,9 @@ ajv@^6.10.0, ajv@^6.11.0, ajv@^6.12.3, ajv@^6.12.4, ajv@^6.12.6: uri-js "^4.2.2" ajv@^8.1.0: - version "8.8.2" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.8.2.tgz#01b4fef2007a28bf75f0b7fc009f62679de4abbb" - integrity sha512-x9VuX+R/jcFj1DHo/fCp99esgGDWiHENrKxaCENuCxpoMCmAt/COCGVDwA7kleEpEzJjDnvh3yGoOuLu0Dtllw== + version "8.10.0" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.10.0.tgz#e573f719bd3af069017e3b66538ab968d040e54d" + integrity sha512-bzqAEZOjkrUMl2afH8dknrq5KEk2SrwdBROR+vH1EKVQTqaUbJVPdc/gEdggTMM0Se+s+Ja4ju4TlNcStKl2Hw== dependencies: fast-deep-equal "^3.1.1" json-schema-traverse "^1.0.0" @@ -1114,7 +1151,7 @@ ansi-align@^3.0.0: dependencies: string-width "^4.1.0" -ansi-colors@4.1.1, ansi-colors@^4.1.1: +ansi-colors@4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.1.tgz#cbb9ae256bf750af1eab344f229aa27fe94ba348" integrity sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA== @@ -1545,14 +1582,14 @@ camelcase@^5.0.0, camelcase@^5.3.1: integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== camelcase@^6.0.0, camelcase@^6.2.0: - version "6.2.1" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.2.1.tgz#250fd350cfd555d0d2160b1d51510eaf8326e86e" - integrity sha512-tVI4q5jjFV5CavAU8DXfza/TJcZutVKo/5Foskmsqcm0MsL91moHvwiGNnqaa2o6PF/7yT5ikDRcVcl8Rj6LCA== + version "6.3.0" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a" + integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== caniuse-lite@^1.0.30001286: - version "1.0.30001287" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001287.tgz#5fab6a46ab9e47146d5dd35abfe47beaf8073c71" - integrity sha512-4udbs9bc0hfNrcje++AxBuc6PfLNHwh3PO9kbwnfCQWyqtlzg3py0YgFu8jyRTTo85VAz4U+VLxSlID09vNtWA== + version "1.0.30001312" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001312.tgz#e11eba4b87e24d22697dae05455d5aea28550d5f" + integrity sha512-Wiz1Psk2MEK0pX3rUzWaunLTZzqS2JYZFzNKqAiJGiuxIjRPLgV6+VDPOg6lQOUxmDwhTlh198JsTTi8Hzw6aQ== caseless@~0.12.0: version "0.12.0" @@ -1586,10 +1623,10 @@ chardet@^0.7.0: resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e" integrity sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA== -chokidar@3.5.2, chokidar@^3.0.0: - version "3.5.2" - resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.2.tgz#dba3976fcadb016f66fd365021d91600d01c1e75" - integrity sha512-ekGhOnNVPgT77r4K/U3GDhu+FQ2S8TnK/s2KbIGXi0SZWuwkZ2QNyfWdZW+TVfn84DpEP7rLeCt2UI6bJ8GwbQ== +chokidar@3.5.3, chokidar@^3.0.0, chokidar@^3.5.2: + version "3.5.3" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd" + integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw== dependencies: anymatch "~3.1.2" braces "~3.0.2" @@ -1607,11 +1644,9 @@ chownr@^1.1.1: integrity sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg== chroma-js@^2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/chroma-js/-/chroma-js-2.1.2.tgz#1075cb9ae25bcb2017c109394168b5cf3aa500ec" - integrity sha512-ri/ouYDWuxfus3UcaMxC1Tfp3IE9K5iQzxc2hSxbBRVNQFut1UuGAsZmiAf2mOUubzGJwgMSv9lHg+XqLaz1QQ== - dependencies: - cross-env "^6.0.3" + version "2.4.2" + resolved "https://registry.yarnpkg.com/chroma-js/-/chroma-js-2.4.2.tgz#dffc214ed0c11fa8eefca2c36651d8e57cbfb2b0" + integrity sha512-U9eDw6+wt7V8z5NncY2jJfZa+hUH8XEj8FQHgFJTrUFnJfXYf4Ml4adI2vXZOjqRDpFWtYVWypDfZwnJ+HIR4A== ci-info@^2.0.0: version "2.0.0" @@ -1623,10 +1658,10 @@ ci-info@^3.2.0: resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-3.3.0.tgz#b4ed1fb6818dea4803a55c623041f9165d2066b2" integrity sha512-riT/3vI5YpVH6/qomlDnJow6TBee2PBKSEpx3O32EGPYbWGIRsIlGRms3Sm74wYE1JMo8RnO04Hb12+v1J5ICw== -clean-css@^5.2.2: - version "5.2.2" - resolved "https://registry.yarnpkg.com/clean-css/-/clean-css-5.2.2.tgz#d3a7c6ee2511011e051719838bdcf8314dc4548d" - integrity sha512-/eR8ru5zyxKzpBLv9YZvMXgTSSQn7AdkMItMYynsFgGwTveCRVam9IUPFloE85B4vAIj05IuKmmEoV7/AQjT0w== +clean-css@^5.2.4: + version "5.2.4" + resolved "https://registry.yarnpkg.com/clean-css/-/clean-css-5.2.4.tgz#982b058f8581adb2ae062520808fb2429bd487a4" + integrity sha512-nKseG8wCzEuji/4yrgM/5cthL9oTDc5UOQyFMvW/Q53oP6gLH690o1NbuTh6Y18nujr7BxlsFuS7gXLnLzKJGg== dependencies: source-map "~0.6.0" @@ -1898,9 +1933,9 @@ conventional-changelog-codemirror@^2.0.8: q "^1.5.1" conventional-changelog-conventionalcommits@^4.5.0: - version "4.6.1" - resolved "https://registry.yarnpkg.com/conventional-changelog-conventionalcommits/-/conventional-changelog-conventionalcommits-4.6.1.tgz#f4c0921937050674e578dc7875f908351ccf4014" - integrity sha512-lzWJpPZhbM1R0PIzkwzGBCnAkH5RKJzJfFQZcl/D+2lsJxAwGnDKBqn/F4C1RD31GJNn8NuKWQzAZDAVXPp2Mw== + version "4.6.3" + resolved "https://registry.yarnpkg.com/conventional-changelog-conventionalcommits/-/conventional-changelog-conventionalcommits-4.6.3.tgz#0765490f56424b46f6cb4db9135902d6e5a36dc2" + integrity sha512-LTTQV4fwOM4oLPad317V/QNQ1FY4Hju5qeBIM1uTHbrnCE+Eg4CdRZ3gO2pUeR+tzWdp80M2j3qFFEDWVqOV4g== dependencies: compare-func "^2.0.0" lodash "^4.17.15" @@ -1968,13 +2003,13 @@ conventional-changelog-preset-loader@^2.3.4: integrity sha512-GEKRWkrSAZeTq5+YjUZOYxdHq+ci4dNwHvpaBC3+ENalzFWuCWa9EZXSuZBpkr72sMdKB+1fyDV4takK1Lf58g== conventional-changelog-writer@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/conventional-changelog-writer/-/conventional-changelog-writer-5.0.0.tgz#c4042f3f1542f2f41d7d2e0d6cad23aba8df8eec" - integrity sha512-HnDh9QHLNWfL6E1uHz6krZEQOgm8hN7z/m7tT16xwd802fwgMN0Wqd7AQYVkhpsjDUx/99oo+nGgvKF657XP5g== + version "5.0.1" + resolved "https://registry.yarnpkg.com/conventional-changelog-writer/-/conventional-changelog-writer-5.0.1.tgz#e0757072f045fe03d91da6343c843029e702f359" + integrity sha512-5WsuKUfxW7suLblAbFnxAcrvf6r+0b7GvNaWUwUIk0bXMnENP/PEieGKVUQrjPqwPT4o3EPAASBXiY6iHooLOQ== dependencies: conventional-commits-filter "^2.0.7" dateformat "^3.0.0" - handlebars "^4.7.6" + handlebars "^4.7.7" json-stringify-safe "^5.0.1" lodash "^4.17.15" meow "^8.0.0" @@ -1982,10 +2017,10 @@ conventional-changelog-writer@^5.0.0: split "^1.0.0" through2 "^4.0.0" -conventional-changelog@^3.1.24: - version "3.1.24" - resolved "https://registry.yarnpkg.com/conventional-changelog/-/conventional-changelog-3.1.24.tgz#ebd180b0fd1b2e1f0095c4b04fd088698348a464" - integrity sha512-ed6k8PO00UVvhExYohroVPXcOJ/K1N0/drJHx/faTH37OIZthlecuLIRX/T6uOp682CAoVoFpu+sSEaeuH6Asg== +conventional-changelog@^3.1.25: + version "3.1.25" + resolved "https://registry.yarnpkg.com/conventional-changelog/-/conventional-changelog-3.1.25.tgz#3e227a37d15684f5aa1fb52222a6e9e2536ccaff" + integrity sha512-ryhi3fd1mKf3fSjbLXOfK2D06YwKNic1nC9mWqybBHdObPd8KJ2vjaXZfYj1U23t+V8T8n0d7gwnc9XbIdFbyQ== dependencies: conventional-changelog-angular "^5.0.12" conventional-changelog-atom "^2.0.8" @@ -2013,9 +2048,9 @@ conventional-commits-filter@^2.0.7: modify-values "^1.0.0" conventional-commits-parser@^3.2.0: - version "3.2.3" - resolved "https://registry.yarnpkg.com/conventional-commits-parser/-/conventional-commits-parser-3.2.3.tgz#fc43704698239451e3ef35fd1d8ed644f46bd86e" - integrity sha512-YyRDR7On9H07ICFpRm/igcdjIqebXbvf4Cff+Pf0BrBys1i1EOzx9iFXNlAbdrLAR8jf7bkUYkDAr8pEy0q4Pw== + version "3.2.4" + resolved "https://registry.yarnpkg.com/conventional-commits-parser/-/conventional-commits-parser-3.2.4.tgz#a7d3b77758a202a9b2293d2112a8d8052c740972" + integrity sha512-nK7sAtfi+QXbxHCYfhpZsfRtaitZLIA6889kFIouLvz6repszQDgxBu7wf2WbU+Dco7sAnNCJYERCwt54WPC2Q== dependencies: JSONStream "^1.0.4" is-text-path "^1.0.1" @@ -2046,9 +2081,9 @@ convert-source-map@^1.7.0: safe-buffer "~5.1.1" cookie@^0.4.0: - version "0.4.1" - resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.1.tgz#afd713fe26ebd21ba95ceb61f9a8116e50a537d1" - integrity sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA== + version "0.4.2" + resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.2.tgz#0e41f24de5ecf317947c82fc789e06a884824432" + integrity sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA== core-util-is@1.0.2: version "1.0.2" @@ -2060,7 +2095,15 @@ core-util-is@~1.0.0: resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85" integrity sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ== -cosmiconfig@7.0.1, cosmiconfig@^7.0.0: +cosmiconfig-typescript-loader@^1.0.0: + version "1.0.5" + resolved "https://registry.yarnpkg.com/cosmiconfig-typescript-loader/-/cosmiconfig-typescript-loader-1.0.5.tgz#22373003194a1887bbccbdfd05a13501397109a8" + integrity sha512-FL/YR1nb8hyN0bAcP3MBaIoZravfZtVsN/RuPnoo6UVjqIrDxSNIpXHCGgJe0ZWy5yImpyD6jq5wCJ5f1nUv8g== + dependencies: + cosmiconfig "^7" + ts-node "^10.5.0" + +cosmiconfig@7.0.1, cosmiconfig@^7, cosmiconfig@^7.0.0: version "7.0.1" resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-7.0.1.tgz#714d756522cace867867ccb4474c5d01bbae5d6d" integrity sha512-a1YWNUV2HwGimB7dU2s1wUMurNKjpx60HxBB6xUM8Re+2s1g1IIfJvFR0/iCF+XHdE0GMTKTuLR32UQff4TEyQ== @@ -2076,13 +2119,6 @@ create-require@^1.1.0: resolved "https://registry.yarnpkg.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333" integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ== -cross-env@^6.0.3: - version "6.0.3" - resolved "https://registry.yarnpkg.com/cross-env/-/cross-env-6.0.3.tgz#4256b71e49b3a40637a0ce70768a6ef5c72ae941" - integrity sha512-+KqxF6LCvfhWvADcDPqo64yVIB31gv/jQulX2NGzKS/g3GEVz6/pt4wjHFtFWsHMddebWD/sDthJemzM4MaAag== - dependencies: - cross-spawn "^7.0.0" - cross-env@^7.0.3: version "7.0.3" resolved "https://registry.yarnpkg.com/cross-env/-/cross-env-7.0.3.tgz#865264b29677dc015ba8418918965dd232fc54cf" @@ -2156,7 +2192,7 @@ dashdash@^1.12.0: dependencies: assert-plus "^1.0.0" -dateformat@^3.0.0, dateformat@^3.0.3: +dateformat@^3.0.0: version "3.0.3" resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-3.0.3.tgz#a6e37499a4d9a9cf85ef5872044d62901c9889ae" integrity sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q== @@ -2166,11 +2202,6 @@ dayjs@^1.10.7: resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.10.7.tgz#2cf5f91add28116748440866a0a1d26f3a6ce468" integrity sha512-P6twpd70BcPK34K26uJ1KT3wlhpuOAPoMwJzpsIWUxHZ7wpmbdZL/hQqBDfz7hGurYSa5PhzdhDHtt319hL3ig== -debounce@^1.0.0: - version "1.2.1" - resolved "https://registry.yarnpkg.com/debounce/-/debounce-1.2.1.tgz#38881d8f4166a5c5848020c11827b834bcb3e0a5" - integrity sha512-XRRe6Glud4rd/ZGQfiV1ruXSfbvfJedlV9Y6zOlP+2K04vBYiJEte6stfFkCP03aMnY5tsipamumUjL14fofug== - debug@2.6.9: version "2.6.9" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" @@ -2178,20 +2209,20 @@ debug@2.6.9: dependencies: ms "2.0.0" -debug@4.3.2: - version "4.3.2" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.2.tgz#f0a49c18ac8779e31d4a0c6029dfb76873c7428b" - integrity sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw== - dependencies: - ms "2.1.2" - -debug@^4.0.0, debug@^4.1.0, debug@^4.1.1, debug@^4.3.2: +debug@4.3.3, debug@^4.0.0, debug@^4.1.0, debug@^4.1.1, debug@^4.3.2: version "4.3.3" resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.3.tgz#04266e0b70a98d4462e6e288e38259213332b664" integrity sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q== dependencies: ms "2.1.2" +debug@^3.2.7: + version "3.2.7" + resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a" + integrity sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ== + dependencies: + ms "^2.1.1" + decamelize-keys@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/decamelize-keys/-/decamelize-keys-1.1.0.tgz#d171a87933252807eb3cb61dc1c1445d078df2d9" @@ -2297,14 +2328,6 @@ delegates@^1.0.0: resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" integrity sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o= -deprecated-obj@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/deprecated-obj/-/deprecated-obj-2.0.0.tgz#e6ba93a3989f6ed18d685e7d99fb8d469b4beffc" - integrity sha512-CkdywZC2rJ8RGh+y3MM1fw1EJ4oO/oNExGbRFv0AQoMS+faTd3nO7slYjkj/6t8OnIMUE+wxh6G97YHhK1ytrw== - dependencies: - flat "^5.0.2" - lodash "^4.17.20" - deprecation@^2.0.0, deprecation@^2.3.1: version "2.3.1" resolved "https://registry.yarnpkg.com/deprecation/-/deprecation-2.3.1.tgz#6368cbdb40abf3373b525ac87e4a260c3a700919" @@ -2330,10 +2353,10 @@ detect-libc@^1.0.3: resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b" integrity sha1-+hN8S9aY7fVc1c0CrFWfkaTEups= -diff-sequences@^27.4.0: - version "27.4.0" - resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-27.4.0.tgz#d783920ad8d06ec718a060d00196dfef25b132a5" - integrity sha512-YqiQzkrsmHMH5uuh8OdQFU9/ZpADnwzml8z0O5HvRNda+5UZsaX/xN+AAxfR2hWq1Y7HZnAzO9J5lJXOuDz2Ww== +diff-sequences@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-27.5.1.tgz#eaecc0d327fd68c8d9672a1e64ab8dccb2ef5327" + integrity sha512-k1gCAXAsNgLwEL+Y8Wvl+M6oEFj5bgazfZULpS5CneoPPXRaCCW7dm+q21Ky2VEE5X+VeRDBVg1Pcvvsr4TtNQ== diff@5.0.0, diff@^5.0.0: version "5.0.0" @@ -2381,12 +2404,10 @@ duplexer@^0.1.2: resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.2.tgz#3abe43aef3835f8ae077d136ddce0f276b0400e6" integrity sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg== -dynamic-dedupe@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/dynamic-dedupe/-/dynamic-dedupe-0.3.0.tgz#06e44c223f5e4e94d78ef9db23a6515ce2f962a1" - integrity sha1-BuRMIj9eTpTXjvnbI6ZRXOL5YqE= - dependencies: - xtend "^4.0.0" +eastasianwidth@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/eastasianwidth/-/eastasianwidth-0.2.0.tgz#696ce2ec0aa0e6ea93a397ffcf24aa7840c827cb" + integrity sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA== ecc-jsbn@~0.1.1: version "0.1.2" @@ -2397,9 +2418,9 @@ ecc-jsbn@~0.1.1: safer-buffer "^2.1.0" electron-to-chromium@^1.4.17: - version "1.4.21" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.21.tgz#edf7d9477980079d840570c34ab4c4a5bef4c2bd" - integrity sha512-T04U2ciApGbm+dESFEBbewi2Xt0Dgyww8M4n4sOt9lnmFuYbaHEDWCROkx4jvAZDUWWry9YOdnAs+7468q80Qg== + version "1.4.71" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.71.tgz#17056914465da0890ce00351a3b946fd4cd51ff6" + integrity sha512-Hk61vXXKRb2cd3znPE9F+2pLWdIOmP7GjiTj45y6L3W/lO+hSnUSUhq+6lEaERWBdZOHbk2s3YV5c9xVl3boVw== emoji-regex@^8.0.0: version "8.0.0" @@ -2418,14 +2439,7 @@ end-of-stream@^1.1.0, end-of-stream@^1.4.1: dependencies: once "^1.4.0" -enquirer@^2.3.5: - version "2.3.6" - resolved "https://registry.yarnpkg.com/enquirer/-/enquirer-2.3.6.tgz#2a7fe5dd634a1e4125a975ec994ff5456dc3734d" - integrity sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg== - dependencies: - ansi-colors "^4.1.1" - -error-ex@^1.3.1: +error-ex@^1.3.1, error-ex@^1.3.2: version "1.3.2" resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== @@ -2447,170 +2461,180 @@ esbuild-android-arm64@0.13.15: resolved "https://registry.yarnpkg.com/esbuild-android-arm64/-/esbuild-android-arm64-0.13.15.tgz#3fc3ff0bab76fe35dd237476b5d2b32bb20a3d44" integrity sha512-m602nft/XXeO8YQPUDVoHfjyRVPdPgjyyXOxZ44MK/agewFFkPa8tUo6lAzSWh5Ui5PB4KR9UIFTSBKh/RrCmg== -esbuild-android-arm64@0.14.5: - version "0.14.5" - resolved "https://registry.yarnpkg.com/esbuild-android-arm64/-/esbuild-android-arm64-0.14.5.tgz#a7bc2263e099b67d1d6bc10ad504f396b439a42a" - integrity sha512-Sl6ysm7OAZZz+X3Mv3tOPhjMuSxNmztgoXH4ZZ3Yhbje5emEY6qiTnv3vBSljDlUl/yGaIjqC44qlj8s8G71xA== +esbuild-android-arm64@0.14.22: + version "0.14.22" + resolved "https://registry.yarnpkg.com/esbuild-android-arm64/-/esbuild-android-arm64-0.14.22.tgz#fb051169a63307d958aec85ad596cfc7d7770303" + integrity sha512-k1Uu4uC4UOFgrnTj2zuj75EswFSEBK+H6lT70/DdS4mTAOfs2ECv2I9ZYvr3w0WL0T4YItzJdK7fPNxcPw6YmQ== esbuild-darwin-64@0.13.15: version "0.13.15" resolved "https://registry.yarnpkg.com/esbuild-darwin-64/-/esbuild-darwin-64-0.13.15.tgz#8e9169c16baf444eacec60d09b24d11b255a8e72" integrity sha512-ihOQRGs2yyp7t5bArCwnvn2Atr6X4axqPpEdCFPVp7iUj4cVSdisgvEKdNR7yH3JDjW6aQDw40iQFoTqejqxvQ== -esbuild-darwin-64@0.14.5: - version "0.14.5" - resolved "https://registry.yarnpkg.com/esbuild-darwin-64/-/esbuild-darwin-64-0.14.5.tgz#589f4b8663feb044f2425e70618f6a9debebaf14" - integrity sha512-VHZl23sM9BOZXcLxk1vTYls8TCAY+/3llw9vHKIWAHDHzBBOlVv26ORK8gnStNMqTjCSGSMoq4T5jOZf2WrJPQ== +esbuild-darwin-64@0.14.22: + version "0.14.22" + resolved "https://registry.yarnpkg.com/esbuild-darwin-64/-/esbuild-darwin-64-0.14.22.tgz#615ea0a9de67b57a293a7128d7ac83ee307a856d" + integrity sha512-d8Ceuo6Vw6HM3fW218FB6jTY6O3r2WNcTAU0SGsBkXZ3k8SDoRLd3Nrc//EqzdgYnzDNMNtrWegK2Qsss4THhw== esbuild-darwin-arm64@0.13.15: version "0.13.15" resolved "https://registry.yarnpkg.com/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.13.15.tgz#1b07f893b632114f805e188ddfca41b2b778229a" integrity sha512-i1FZssTVxUqNlJ6cBTj5YQj4imWy3m49RZRnHhLpefFIh0To05ow9DTrXROTE1urGTQCloFUXTX8QfGJy1P8dQ== -esbuild-darwin-arm64@0.14.5: - version "0.14.5" - resolved "https://registry.yarnpkg.com/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.14.5.tgz#c4def102fddd52ccaf23cf00c3274296de6b12db" - integrity sha512-ugPOLgEQPoPLSqAFBajaczt+lcbUZR+V2fby3572h5jf/kFV6UL8LAZ1Ze58hcbKwfvbh4C09kp0PhqPgXKwOg== +esbuild-darwin-arm64@0.14.22: + version "0.14.22" + resolved "https://registry.yarnpkg.com/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.14.22.tgz#82054dcfcecb15ccfd237093b8008e7745a99ad9" + integrity sha512-YAt9Tj3SkIUkswuzHxkaNlT9+sg0xvzDvE75LlBo4DI++ogSgSmKNR6B4eUhU5EUUepVXcXdRIdqMq9ppeRqfw== esbuild-freebsd-64@0.13.15: version "0.13.15" resolved "https://registry.yarnpkg.com/esbuild-freebsd-64/-/esbuild-freebsd-64-0.13.15.tgz#0b8b7eca1690c8ec94c75680c38c07269c1f4a85" integrity sha512-G3dLBXUI6lC6Z09/x+WtXBXbOYQZ0E8TDBqvn7aMaOCzryJs8LyVXKY4CPnHFXZAbSwkCbqiPuSQ1+HhrNk7EA== -esbuild-freebsd-64@0.14.5: - version "0.14.5" - resolved "https://registry.yarnpkg.com/esbuild-freebsd-64/-/esbuild-freebsd-64-0.14.5.tgz#e5152bbf256942fe498dfe4a5f92b8bb148a64b5" - integrity sha512-uP0yOixSHF505o/Kzq9e4bvZblCZp9GGx+a7enLOVSuvIvLmtj2yhZLRPGfbVNkPJXktTKNRAnNGkXHl53M6sw== +esbuild-freebsd-64@0.14.22: + version "0.14.22" + resolved "https://registry.yarnpkg.com/esbuild-freebsd-64/-/esbuild-freebsd-64-0.14.22.tgz#778a818c5b078d5cdd6bb6c0e0797217d196999b" + integrity sha512-ek1HUv7fkXMy87Qm2G4IRohN+Qux4IcnrDBPZGXNN33KAL0pEJJzdTv0hB/42+DCYWylSrSKxk3KUXfqXOoH4A== esbuild-freebsd-arm64@0.13.15: version "0.13.15" resolved "https://registry.yarnpkg.com/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.13.15.tgz#2e1a6c696bfdcd20a99578b76350b41db1934e52" integrity sha512-KJx0fzEDf1uhNOZQStV4ujg30WlnwqUASaGSFPhznLM/bbheu9HhqZ6mJJZM32lkyfGJikw0jg7v3S0oAvtvQQ== -esbuild-freebsd-arm64@0.14.5: - version "0.14.5" - resolved "https://registry.yarnpkg.com/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.14.5.tgz#7c1ad25ae9ed101df76dc64d83fcfd2ddba5aed0" - integrity sha512-M99NPu8hlirFo6Fgx0WfX6XxUFdGclUNv3MyyfDtTdNYbccMESwLSACGpE7HvJKWscdjaqajeMu2an9adGNfCw== +esbuild-freebsd-arm64@0.14.22: + version "0.14.22" + resolved "https://registry.yarnpkg.com/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.14.22.tgz#18da93b9f3db2e036f72383bfe73b28b73bb332c" + integrity sha512-zPh9SzjRvr9FwsouNYTqgqFlsMIW07O8mNXulGeQx6O5ApgGUBZBgtzSlBQXkHi18WjrosYfsvp5nzOKiWzkjQ== esbuild-linux-32@0.13.15: version "0.13.15" resolved "https://registry.yarnpkg.com/esbuild-linux-32/-/esbuild-linux-32-0.13.15.tgz#6fd39f36fc66dd45b6b5f515728c7bbebc342a69" integrity sha512-ZvTBPk0YWCLMCXiFmD5EUtB30zIPvC5Itxz0mdTu/xZBbbHJftQgLWY49wEPSn2T/TxahYCRDWun5smRa0Tu+g== -esbuild-linux-32@0.14.5: - version "0.14.5" - resolved "https://registry.yarnpkg.com/esbuild-linux-32/-/esbuild-linux-32-0.14.5.tgz#047a2d6d9dd5f85e6e6875b048c41ab2515e12ce" - integrity sha512-hfqln4yb/jf/vPvI/A6aCvpIzqF3PdDmrKiikTohEUuRtvEZz234krtNwEAw5ssCue4NX8BJqrMpCTAHOl3LQw== +esbuild-linux-32@0.14.22: + version "0.14.22" + resolved "https://registry.yarnpkg.com/esbuild-linux-32/-/esbuild-linux-32-0.14.22.tgz#d0d5d9f5bb3536e17ac097e9512019c65b7c0234" + integrity sha512-SnpveoE4nzjb9t2hqCIzzTWBM0RzcCINDMBB67H6OXIuDa4KqFqaIgmTchNA9pJKOVLVIKd5FYxNiJStli21qg== esbuild-linux-64@0.13.15: version "0.13.15" resolved "https://registry.yarnpkg.com/esbuild-linux-64/-/esbuild-linux-64-0.13.15.tgz#9cb8e4bcd7574e67946e4ee5f1f1e12386bb6dd3" integrity sha512-eCKzkNSLywNeQTRBxJRQ0jxRCl2YWdMB3+PkWFo2BBQYC5mISLIVIjThNtn6HUNqua1pnvgP5xX0nHbZbPj5oA== -esbuild-linux-64@0.14.5: - version "0.14.5" - resolved "https://registry.yarnpkg.com/esbuild-linux-64/-/esbuild-linux-64-0.14.5.tgz#03793b5a0ae450c725616fc724b3a406cd2da2fa" - integrity sha512-T+OuYPlhytjj5DsvjUXizNjbV+/IrZiaDc9SNUfqiUOXHu0URFqchjhPVbBiBnWykCMJFB6pqNap2Oxth4iuYw== +esbuild-linux-64@0.14.22: + version "0.14.22" + resolved "https://registry.yarnpkg.com/esbuild-linux-64/-/esbuild-linux-64-0.14.22.tgz#2773d540971999ea7f38107ef92fca753f6a8c30" + integrity sha512-Zcl9Wg7gKhOWWNqAjygyqzB+fJa19glgl2JG7GtuxHyL1uEnWlpSMytTLMqtfbmRykIHdab797IOZeKwk5g0zg== esbuild-linux-arm64@0.13.15: version "0.13.15" resolved "https://registry.yarnpkg.com/esbuild-linux-arm64/-/esbuild-linux-arm64-0.13.15.tgz#3891aa3704ec579a1b92d2a586122e5b6a2bfba1" integrity sha512-bYpuUlN6qYU9slzr/ltyLTR9YTBS7qUDymO8SV7kjeNext61OdmqFAzuVZom+OLW1HPHseBfJ/JfdSlx8oTUoA== -esbuild-linux-arm64@0.14.5: - version "0.14.5" - resolved "https://registry.yarnpkg.com/esbuild-linux-arm64/-/esbuild-linux-arm64-0.14.5.tgz#9217283b5ccaf2ec9a31f9b4eaeb5787607252a3" - integrity sha512-ANOzoaH4kfbhEZT0EGY9g1tsZhDA+I0FRwBsj7D8pCU900pXF/l8YAOy5jWFQIb3vjG5+orFc5SqSzAKCisvTQ== +esbuild-linux-arm64@0.14.22: + version "0.14.22" + resolved "https://registry.yarnpkg.com/esbuild-linux-arm64/-/esbuild-linux-arm64-0.14.22.tgz#5d4480ce6d6bffab1dd76a23158f5a5ab33e7ba4" + integrity sha512-8q/FRBJtV5IHnQChO3LHh/Jf7KLrxJ/RCTGdBvlVZhBde+dk3/qS9fFsUy+rs3dEi49aAsyVitTwlKw1SUFm+A== esbuild-linux-arm@0.13.15: version "0.13.15" resolved "https://registry.yarnpkg.com/esbuild-linux-arm/-/esbuild-linux-arm-0.13.15.tgz#8a00e99e6a0c6c9a6b7f334841364d8a2b4aecfe" integrity sha512-wUHttDi/ol0tD8ZgUMDH8Ef7IbDX+/UsWJOXaAyTdkT7Yy9ZBqPg8bgB/Dn3CZ9SBpNieozrPRHm0BGww7W/jA== -esbuild-linux-arm@0.14.5: - version "0.14.5" - resolved "https://registry.yarnpkg.com/esbuild-linux-arm/-/esbuild-linux-arm-0.14.5.tgz#e048a681e7f42b12cac1db4a34a84ef17e219333" - integrity sha512-5b10jKJ3lU4BUchOw9TgRResu8UZJf8qVjAzV5muHedonCfBzClGTT4KCNuOcLTJomH3wz6gNVJt1AxMglXnJg== +esbuild-linux-arm@0.14.22: + version "0.14.22" + resolved "https://registry.yarnpkg.com/esbuild-linux-arm/-/esbuild-linux-arm-0.14.22.tgz#c6391b3f7c8fa6d3b99a7e893ce0f45f3a921eef" + integrity sha512-soPDdbpt/C0XvOOK45p4EFt8HbH5g+0uHs5nUKjHVExfgR7du734kEkXR/mE5zmjrlymk5AA79I0VIvj90WZ4g== esbuild-linux-mips64le@0.13.15: version "0.13.15" resolved "https://registry.yarnpkg.com/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.13.15.tgz#36b07cc47c3d21e48db3bb1f4d9ef8f46aead4f7" integrity sha512-KlVjIG828uFPyJkO/8gKwy9RbXhCEUeFsCGOJBepUlpa7G8/SeZgncUEz/tOOUJTcWMTmFMtdd3GElGyAtbSWg== -esbuild-linux-mips64le@0.14.5: - version "0.14.5" - resolved "https://registry.yarnpkg.com/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.14.5.tgz#c1817c00023d8a1c8fe507e60c63cf8a602bce29" - integrity sha512-sSmGfOUNNB2Nd3tzp1RHSxiJmM5/RUIEP5aAtH+PpOP7FPp15Jcfwq7UNBJ82KLN3SJcwhUeEfcCaUFBzbTKxg== +esbuild-linux-mips64le@0.14.22: + version "0.14.22" + resolved "https://registry.yarnpkg.com/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.14.22.tgz#2c8dabac355c502e86c38f9f292b3517d8e181f3" + integrity sha512-SiNDfuRXhGh1JQLLA9JPprBgPVFOsGuQ0yDfSPTNxztmVJd8W2mX++c4FfLpAwxuJe183mLuKf7qKCHQs5ZnBQ== esbuild-linux-ppc64le@0.13.15: version "0.13.15" resolved "https://registry.yarnpkg.com/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.13.15.tgz#f7e6bba40b9a11eb9dcae5b01550ea04670edad2" integrity sha512-h6gYF+OsaqEuBjeesTBtUPw0bmiDu7eAeuc2OEH9S6mV9/jPhPdhOWzdeshb0BskRZxPhxPOjqZ+/OqLcxQwEQ== -esbuild-linux-ppc64le@0.14.5: - version "0.14.5" - resolved "https://registry.yarnpkg.com/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.14.5.tgz#5fa1178c7d7ebd13056c7ccd0604653b0ccc2264" - integrity sha512-usfQrVVIQcpuc/U2NWc7/Ry+m622v+PjJ5eErNPdjWBPlcvD6kXaBTv94uQkVzZOHX3uYqprRrOjseed9ApSYA== +esbuild-linux-ppc64le@0.14.22: + version "0.14.22" + resolved "https://registry.yarnpkg.com/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.14.22.tgz#69d71b2820d5c94306072dac6094bae38e77d1c0" + integrity sha512-6t/GI9I+3o1EFm2AyN9+TsjdgWCpg2nwniEhjm2qJWtJyJ5VzTXGUU3alCO3evopu8G0hN2Bu1Jhz2YmZD0kng== + +esbuild-linux-riscv64@0.14.22: + version "0.14.22" + resolved "https://registry.yarnpkg.com/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.14.22.tgz#c0ec0fc3a23624deebf657781550d2329cec4213" + integrity sha512-AyJHipZKe88sc+tp5layovquw5cvz45QXw5SaDgAq2M911wLHiCvDtf/07oDx8eweCyzYzG5Y39Ih568amMTCQ== + +esbuild-linux-s390x@0.14.22: + version "0.14.22" + resolved "https://registry.yarnpkg.com/esbuild-linux-s390x/-/esbuild-linux-s390x-0.14.22.tgz#ec2af4572d63336cfb27f5a5c851fb1b6617dd91" + integrity sha512-Sz1NjZewTIXSblQDZWEFZYjOK6p8tV6hrshYdXZ0NHTjWE+lwxpOpWeElUGtEmiPcMT71FiuA9ODplqzzSxkzw== esbuild-netbsd-64@0.13.15: version "0.13.15" resolved "https://registry.yarnpkg.com/esbuild-netbsd-64/-/esbuild-netbsd-64-0.13.15.tgz#a2fedc549c2b629d580a732d840712b08d440038" integrity sha512-3+yE9emwoevLMyvu+iR3rsa+Xwhie7ZEHMGDQ6dkqP/ndFzRHkobHUKTe+NCApSqG5ce2z4rFu+NX/UHnxlh3w== -esbuild-netbsd-64@0.14.5: - version "0.14.5" - resolved "https://registry.yarnpkg.com/esbuild-netbsd-64/-/esbuild-netbsd-64-0.14.5.tgz#757572c7664ae6122c8e4dd89a2b6d337c3c27b2" - integrity sha512-Q5KpvPZcPnNEaTjrvuWqvEnlhI2jyi1wWwYunlEUAhx60spQOTy10sdYOA+s1M+LPb6kwvasrZZDmYyQlcVZeA== +esbuild-netbsd-64@0.14.22: + version "0.14.22" + resolved "https://registry.yarnpkg.com/esbuild-netbsd-64/-/esbuild-netbsd-64-0.14.22.tgz#0e283278e9fdbaa7f0930f93ee113d7759cd865e" + integrity sha512-TBbCtx+k32xydImsHxvFgsOCuFqCTGIxhzRNbgSL1Z2CKhzxwT92kQMhxort9N/fZM2CkRCPPs5wzQSamtzEHA== esbuild-openbsd-64@0.13.15: version "0.13.15" resolved "https://registry.yarnpkg.com/esbuild-openbsd-64/-/esbuild-openbsd-64-0.13.15.tgz#b22c0e5806d3a1fbf0325872037f885306b05cd7" integrity sha512-wTfvtwYJYAFL1fSs8yHIdf5GEE4NkbtbXtjLWjM3Cw8mmQKqsg8kTiqJ9NJQe5NX/5Qlo7Xd9r1yKMMkHllp5g== -esbuild-openbsd-64@0.14.5: - version "0.14.5" - resolved "https://registry.yarnpkg.com/esbuild-openbsd-64/-/esbuild-openbsd-64-0.14.5.tgz#046827c211daa2b6a2241a9f910321e116d2cc24" - integrity sha512-RZzRUu1RYKextJgXkHhAsuhLDvm73YP/wogpUG9MaAGvKTxnKAKRuaw2zJfnbz8iBqBQB2no2PmpVBNbqUTQrw== +esbuild-openbsd-64@0.14.22: + version "0.14.22" + resolved "https://registry.yarnpkg.com/esbuild-openbsd-64/-/esbuild-openbsd-64-0.14.22.tgz#2a73bba04e16d8ef278fbe2be85248e12a2f2cc2" + integrity sha512-vK912As725haT313ANZZZN+0EysEEQXWC/+YE4rQvOQzLuxAQc2tjbzlAFREx3C8+uMuZj/q7E5gyVB7TzpcTA== esbuild-sunos-64@0.13.15: version "0.13.15" resolved "https://registry.yarnpkg.com/esbuild-sunos-64/-/esbuild-sunos-64-0.13.15.tgz#d0b6454a88375ee8d3964daeff55c85c91c7cef4" integrity sha512-lbivT9Bx3t1iWWrSnGyBP9ODriEvWDRiweAs69vI+miJoeKwHWOComSRukttbuzjZ8r1q0mQJ8Z7yUsDJ3hKdw== -esbuild-sunos-64@0.14.5: - version "0.14.5" - resolved "https://registry.yarnpkg.com/esbuild-sunos-64/-/esbuild-sunos-64-0.14.5.tgz#3e2b0e79188069a366faec3d5b1b3065b792a733" - integrity sha512-J2ffKsBBWscQlye+/giEgKsQCppwHHFqqt/sh+ojVF+DZy1ve6RpPGwXGcGF6IaZTAI9+Vk4eHleiQxb+PC9Yw== +esbuild-sunos-64@0.14.22: + version "0.14.22" + resolved "https://registry.yarnpkg.com/esbuild-sunos-64/-/esbuild-sunos-64-0.14.22.tgz#8fe03513b8b2e682a6d79d5e3ca5849651a3c1d8" + integrity sha512-/mbJdXTW7MTcsPhtfDsDyPEOju9EOABvCjeUU2OJ7fWpX/Em/H3WYDa86tzLUbcVg++BScQDzqV/7RYw5XNY0g== esbuild-windows-32@0.13.15: version "0.13.15" resolved "https://registry.yarnpkg.com/esbuild-windows-32/-/esbuild-windows-32-0.13.15.tgz#c96d0b9bbb52f3303322582ef8e4847c5ad375a7" integrity sha512-fDMEf2g3SsJ599MBr50cY5ve5lP1wyVwTe6aLJsM01KtxyKkB4UT+fc5MXQFn3RLrAIAZOG+tHC+yXObpSn7Nw== -esbuild-windows-32@0.14.5: - version "0.14.5" - resolved "https://registry.yarnpkg.com/esbuild-windows-32/-/esbuild-windows-32-0.14.5.tgz#520f3737719177d76955b8f1c34eca8e8d005eba" - integrity sha512-OTZvuAc1JBnwmeT+hR1+Vmgz6LOD7DggpnwtKMAExruSLxUMl02Z3pyalJ7zKh3gJ/KBRM1JQZLSk4/mFWijeQ== +esbuild-windows-32@0.14.22: + version "0.14.22" + resolved "https://registry.yarnpkg.com/esbuild-windows-32/-/esbuild-windows-32-0.14.22.tgz#a75df61e3e49df292a1842be8e877a3153ee644f" + integrity sha512-1vRIkuvPTjeSVK3diVrnMLSbkuE36jxA+8zGLUOrT4bb7E/JZvDRhvtbWXWaveUc/7LbhaNFhHNvfPuSw2QOQg== esbuild-windows-64@0.13.15: version "0.13.15" resolved "https://registry.yarnpkg.com/esbuild-windows-64/-/esbuild-windows-64-0.13.15.tgz#1f79cb9b1e1bb02fb25cd414cb90d4ea2892c294" integrity sha512-9aMsPRGDWCd3bGjUIKG/ZOJPKsiztlxl/Q3C1XDswO6eNX/Jtwu4M+jb6YDH9hRSUflQWX0XKAfWzgy5Wk54JQ== -esbuild-windows-64@0.14.5: - version "0.14.5" - resolved "https://registry.yarnpkg.com/esbuild-windows-64/-/esbuild-windows-64-0.14.5.tgz#0100d8aa3c5d57e676aeb37975e948880f751650" - integrity sha512-ZM9rlBDsPEeMVJ1wcpNMXUad9VzYOFeOBUXBi+16HZTvFPy2DkcC2ZWcrByP3IESToD5lvHdjSX/w8rxphjqig== +esbuild-windows-64@0.14.22: + version "0.14.22" + resolved "https://registry.yarnpkg.com/esbuild-windows-64/-/esbuild-windows-64-0.14.22.tgz#d06cf8bbe4945b8bf95a730d871e54a22f635941" + integrity sha512-AxjIDcOmx17vr31C5hp20HIwz1MymtMjKqX4qL6whPj0dT9lwxPexmLj6G1CpR3vFhui6m75EnBEe4QL82SYqw== esbuild-windows-arm64@0.13.15: version "0.13.15" resolved "https://registry.yarnpkg.com/esbuild-windows-arm64/-/esbuild-windows-arm64-0.13.15.tgz#482173070810df22a752c686509c370c3be3b3c3" integrity sha512-zzvyCVVpbwQQATaf3IG8mu1IwGEiDxKkYUdA4FpoCHi1KtPa13jeScYDjlW0Qh+ebWzpKfR2ZwvqAQkSWNcKjA== -esbuild-windows-arm64@0.14.5: - version "0.14.5" - resolved "https://registry.yarnpkg.com/esbuild-windows-arm64/-/esbuild-windows-arm64-0.14.5.tgz#c1d575f2c6d27159de9b5d273bcde02445f17a1d" - integrity sha512-iK41mKG2LG0AKHE+9g/jDYU5ZQpJObt1uIPSGTiiiJKI5qbHdEck6Gaqq2tmBI933F2zB9yqZIX7IAdxwN/q4A== +esbuild-windows-arm64@0.14.22: + version "0.14.22" + resolved "https://registry.yarnpkg.com/esbuild-windows-arm64/-/esbuild-windows-arm64-0.14.22.tgz#f8b1b05c548073be8413a5ecb12d7c2f6e717227" + integrity sha512-5wvQ+39tHmRhNpu2Fx04l7QfeK3mQ9tKzDqqGR8n/4WUxsFxnVLfDRBGirIfk4AfWlxk60kqirlODPoT5LqMUg== esbuild@^0.13.13: version "0.13.15" @@ -2635,28 +2659,30 @@ esbuild@^0.13.13: esbuild-windows-64 "0.13.15" esbuild-windows-arm64 "0.13.15" -esbuild@^0.14.5: - version "0.14.5" - resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.14.5.tgz#45ef0287a94cc7a3d367621e4a7ba470a847669f" - integrity sha512-ofwgH4ITPXhkMo2AM39oXpSe5KIyWjxicdqYVy+tLa1lMgxzPCKwaepcrSRtYbgTUMXwquxB1C3xQYpUNaPAFA== +esbuild@^0.14.22: + version "0.14.22" + resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.14.22.tgz#2b55fde89d7aa5aaaad791816d58ff9dfc5ed085" + integrity sha512-CjFCFGgYtbFOPrwZNJf7wsuzesx8kqwAffOlbYcFDLFuUtP8xloK1GH+Ai13Qr0RZQf9tE7LMTHJ2iVGJ1SKZA== optionalDependencies: - esbuild-android-arm64 "0.14.5" - esbuild-darwin-64 "0.14.5" - esbuild-darwin-arm64 "0.14.5" - esbuild-freebsd-64 "0.14.5" - esbuild-freebsd-arm64 "0.14.5" - esbuild-linux-32 "0.14.5" - esbuild-linux-64 "0.14.5" - esbuild-linux-arm "0.14.5" - esbuild-linux-arm64 "0.14.5" - esbuild-linux-mips64le "0.14.5" - esbuild-linux-ppc64le "0.14.5" - esbuild-netbsd-64 "0.14.5" - esbuild-openbsd-64 "0.14.5" - esbuild-sunos-64 "0.14.5" - esbuild-windows-32 "0.14.5" - esbuild-windows-64 "0.14.5" - esbuild-windows-arm64 "0.14.5" + esbuild-android-arm64 "0.14.22" + esbuild-darwin-64 "0.14.22" + esbuild-darwin-arm64 "0.14.22" + esbuild-freebsd-64 "0.14.22" + esbuild-freebsd-arm64 "0.14.22" + esbuild-linux-32 "0.14.22" + esbuild-linux-64 "0.14.22" + esbuild-linux-arm "0.14.22" + esbuild-linux-arm64 "0.14.22" + esbuild-linux-mips64le "0.14.22" + esbuild-linux-ppc64le "0.14.22" + esbuild-linux-riscv64 "0.14.22" + esbuild-linux-s390x "0.14.22" + esbuild-netbsd-64 "0.14.22" + esbuild-openbsd-64 "0.14.22" + esbuild-sunos-64 "0.14.22" + esbuild-windows-32 "0.14.22" + esbuild-windows-64 "0.14.22" + esbuild-windows-arm64 "0.14.22" escalade@^3.1.1: version "3.1.1" @@ -2696,10 +2722,10 @@ eslint-scope@^5.1.1: esrecurse "^4.3.0" estraverse "^4.1.1" -eslint-scope@^7.1.0: - version "7.1.0" - resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-7.1.0.tgz#c1f6ea30ac583031f203d65c73e723b01298f153" - integrity sha512-aWwkhnS0qAXqNOgKOK0dJ2nvzEbhEvpy8OlJ9kZ0FeZnA6zpjv1/Vei+puGFFX7zkPCkHHXb7IDX3A+7yPrRWg== +eslint-scope@^7.1.1: + version "7.1.1" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-7.1.1.tgz#fff34894c2f65e5226d3041ac480b4513a163642" + integrity sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw== dependencies: esrecurse "^4.3.0" estraverse "^5.2.0" @@ -2716,29 +2742,28 @@ eslint-visitor-keys@^2.0.0: resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz#f65328259305927392c938ed44eb0a5c9b2bd303" integrity sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw== -eslint-visitor-keys@^3.0.0, eslint-visitor-keys@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.1.0.tgz#eee4acea891814cda67a7d8812d9647dd0179af2" - integrity sha512-yWJFpu4DtjsWKkt5GeNBBuZMlNcYVs6vRCLoCVEJrTjaSB6LC98gFipNK/erM2Heg/E8mIK+hXG/pJMLK+eRZA== +eslint-visitor-keys@^3.0.0, eslint-visitor-keys@^3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz#f6480fa6b1f30efe2d1968aa8ac745b862469826" + integrity sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA== -eslint@^8.4.1: - version "8.4.1" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.4.1.tgz#d6531bbf3e598dffd7c0c7d35ec52a0b30fdfa2d" - integrity sha512-TxU/p7LB1KxQ6+7aztTnO7K0i+h0tDi81YRY9VzB6Id71kNz+fFYnf5HD5UOQmxkzcoa0TlVZf9dpMtUv0GpWg== +eslint@^8.9.0: + version "8.9.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.9.0.tgz#a2a8227a99599adc4342fd9b854cb8d8d6412fdb" + integrity sha512-PB09IGwv4F4b0/atrbcMFboF/giawbBLVC7fyDamk5Wtey4Jh2K+rYaBhCAbUyEI4QzB1ly09Uglc9iCtFaG2Q== dependencies: - "@eslint/eslintrc" "^1.0.5" + "@eslint/eslintrc" "^1.1.0" "@humanwhocodes/config-array" "^0.9.2" ajv "^6.10.0" chalk "^4.0.0" cross-spawn "^7.0.2" debug "^4.3.2" doctrine "^3.0.0" - enquirer "^2.3.5" escape-string-regexp "^4.0.0" - eslint-scope "^7.1.0" + eslint-scope "^7.1.1" eslint-utils "^3.0.0" - eslint-visitor-keys "^3.1.0" - espree "^9.2.0" + eslint-visitor-keys "^3.3.0" + espree "^9.3.1" esquery "^1.4.0" esutils "^2.0.2" fast-deep-equal "^3.1.3" @@ -2746,7 +2771,7 @@ eslint@^8.4.1: functional-red-black-tree "^1.0.1" glob-parent "^6.0.1" globals "^13.6.0" - ignore "^4.0.6" + ignore "^5.2.0" import-fresh "^3.0.0" imurmurhash "^0.1.4" is-glob "^4.0.0" @@ -2757,22 +2782,20 @@ eslint@^8.4.1: minimatch "^3.0.4" natural-compare "^1.4.0" optionator "^0.9.1" - progress "^2.0.0" regexpp "^3.2.0" - semver "^7.2.1" strip-ansi "^6.0.1" strip-json-comments "^3.1.0" text-table "^0.2.0" v8-compile-cache "^2.0.3" -espree@^9.2.0: - version "9.2.0" - resolved "https://registry.yarnpkg.com/espree/-/espree-9.2.0.tgz#c50814e01611c2d0f8bd4daa83c369eabba80dbc" - integrity sha512-oP3utRkynpZWF/F2x/HZJ+AGtnIclaR7z1pYPxy7NYM2fSO6LgK/Rkny8anRSPK/VwEA1eqm2squui0T7ZMOBg== +espree@^9.3.1: + version "9.3.1" + resolved "https://registry.yarnpkg.com/espree/-/espree-9.3.1.tgz#8793b4bc27ea4c778c19908e0719e7b8f4115bcd" + integrity sha512-bvdyLmJMfwkV3NCRl5ZhJf22zBFo1y8bYh3VYb+bfzqNB4Je68P2sSuXyuFquzWLebHpNd2/d5uv7yoP9ISnGQ== dependencies: - acorn "^8.6.0" + acorn "^8.7.0" acorn-jsx "^5.3.1" - eslint-visitor-keys "^3.1.0" + eslint-visitor-keys "^3.3.0" esprima@^4.0.0: version "4.0.1" @@ -2855,17 +2878,15 @@ expand-tilde@^2.0.0, expand-tilde@^2.0.2: dependencies: homedir-polyfill "^1.0.1" -expect@^27.4.2: - version "27.4.2" - resolved "https://registry.yarnpkg.com/expect/-/expect-27.4.2.tgz#4429b0f7e307771d176de9bdf23229b101db6ef6" - integrity sha512-BjAXIDC6ZOW+WBFNg96J22D27Nq5ohn+oGcuP2rtOtcjuxNoV9McpQ60PcQWhdFOSBIQdR72e+4HdnbZTFSTyg== +expect@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/expect/-/expect-27.5.1.tgz#83ce59f1e5bdf5f9d2b94b61d2050db48f3fef74" + integrity sha512-E1q5hSUG2AmYQwQJ041nvgpkODHQvB+RKlB4IYdru6uJsyFTRyZAP463M+1lINorwbqAmUggi6+WwkD8lCS/Dw== dependencies: - "@jest/types" "^27.4.2" - ansi-styles "^5.0.0" - jest-get-type "^27.4.0" - jest-matcher-utils "^27.4.2" - jest-message-util "^27.4.2" - jest-regex-util "^27.4.0" + "@jest/types" "^27.5.1" + jest-get-type "^27.5.1" + jest-matcher-utils "^27.5.1" + jest-message-util "^27.5.1" extend@^3.0.0, extend@~3.0.2: version "3.0.2" @@ -2891,11 +2912,6 @@ extsprintf@^1.2.0: resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.1.tgz#8d172c064867f235c0c84a596806d279bf4bcc07" integrity sha512-Wrk35e8ydCKDj/ArClo1VrPVmN8zph5V4AtHwIuHhvMXsKf73UT3BOD+azBIW+3wOJ4FhEH7zyaJCFvChjYvMA== -faker@^5.5.3: - version "5.5.3" - resolved "https://registry.yarnpkg.com/faker/-/faker-5.5.3.tgz#c57974ee484431b25205c2c8dc09fda861e51e0e" - integrity sha512-wLTv2a28wjUyWkbnX7u/ABZBkUkIF2fCd73V6P2oFqEGEktDfzWx4UxrSqtPRw0xPRAcjeAOIiJWqZm3pP4u3g== - fast-decode-uri-component@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/fast-decode-uri-component/-/fast-decode-uri-component-1.0.1.tgz#46f8b6c22b30ff7a81357d4f59abfae938202543" @@ -2906,10 +2922,10 @@ fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== -fast-glob@^3.1.1, fast-glob@^3.2.7: - version "3.2.7" - resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.7.tgz#fd6cb7a2d7e9aa7a7846111e85a196d6b2f766a1" - integrity sha512-rYGMRwip6lUMvYD3BTScMwT1HtAs2d71SMv66Vrxs0IekGZEjhM0pcMfjQPnknBt2zeCwQMEupiN02ZP4DiT1Q== +fast-glob@^3.1.1, fast-glob@^3.2.7, fast-glob@^3.2.9: + version "3.2.11" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.11.tgz#a1172ad95ceb8a16e20caa5c5e56480e5129c1d9" + integrity sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew== dependencies: "@nodelib/fs.stat" "^2.0.2" "@nodelib/fs.walk" "^1.2.3" @@ -2923,9 +2939,9 @@ fast-json-stable-stringify@^2.0.0: integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== fast-json-stringify@^2.5.2: - version "2.7.12" - resolved "https://registry.yarnpkg.com/fast-json-stringify/-/fast-json-stringify-2.7.12.tgz#5bb7941695b52f545191bc396396230633f43592" - integrity sha512-4hjwZDPmgj/ZUKXhEWovGPciE/5mWtAIQQxN+2VBDFun7DRTk2oOItbu9ZZp6kqj+eZ/u7z+dgBgM74cfGRnBQ== + version "2.7.13" + resolved "https://registry.yarnpkg.com/fast-json-stringify/-/fast-json-stringify-2.7.13.tgz#277aa86c2acba4d9851bd6108ed657aa327ed8c0" + integrity sha512-ar+hQ4+OIurUGjSJD1anvYSDcUflywhKjfxnsW4TBTD7+u0tJufv6DKRWoQk3vI6YBOWMoz0TQtfbe7dxbQmvA== dependencies: ajv "^6.11.0" deepmerge "^4.2.2" @@ -2938,9 +2954,9 @@ fast-levenshtein@^2.0.6: integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc= fast-redact@^3.0.0: - version "3.0.2" - resolved "https://registry.yarnpkg.com/fast-redact/-/fast-redact-3.0.2.tgz#c940ba7162dde3aeeefc522926ae8c5231412904" - integrity sha512-YN+CYfCVRVMUZOUPeinHNKgytM1wPI/C/UCLEi56EsY2dwwvI00kIJHJoI7pMVqGoMew8SMZ2SSfHKHULHXDsg== + version "3.1.0" + resolved "https://registry.yarnpkg.com/fast-redact/-/fast-redact-3.1.0.tgz#37c26cda9cab70bc04393f7ba1feb2d176da6c6b" + integrity sha512-dir8LOnvialLxiXDPESMDHGp82CHi6ZEYTVkcvdn5d7psdv9ZkkButXrOeXST4aqreIRR+N7CYlsrwFuorurVg== fast-safe-stringify@^2.0.8: version "2.1.1" @@ -2957,21 +2973,21 @@ fastify-warning@^0.2.0: resolved "https://registry.yarnpkg.com/fastify-warning/-/fastify-warning-0.2.0.tgz#e717776026a4493dc9a2befa44db6d17f618008f" integrity sha512-s1EQguBw/9qtc1p/WTY4eq9WMRIACkj+HTcOIK1in4MV5aFaQC9ZCIt0dJ7pr5bIf4lPpHvAtP2ywpTNgs7hqw== -fastify@^3.25.0: - version "3.25.0" - resolved "https://registry.yarnpkg.com/fastify/-/fastify-3.25.0.tgz#04b682fa738c6468bc36efba9f1e943609502111" - integrity sha512-GblpjS7yuJ9jpkz1guHTyzlVQn9NYvGrMkDLtoxctEt7n1d6MSwA9i3p10HjNiY+zVurPf3YdOqXsJmVgAR3cg== +fastify@^3.27.1: + version "3.27.1" + resolved "https://registry.yarnpkg.com/fastify/-/fastify-3.27.1.tgz#7e976473c15d7dc405ad624ffafb6612a6281d10" + integrity sha512-GLn3ow5BGqg/m+ztXvztp8Xp7SuH99vAm4zfbN7407Qzi4mB055SG/lWH/gYolz5Oq2K8LtUpZqt1Ccf/YkVmA== dependencies: "@fastify/ajv-compiler" "^1.0.0" abstract-logging "^2.0.0" avvio "^7.1.2" fast-json-stringify "^2.5.2" fastify-error "^0.3.0" - fastify-warning "^0.2.0" - find-my-way "^4.1.0" + find-my-way "^4.5.0" flatstr "^1.0.12" light-my-request "^4.2.0" pino "^6.13.0" + process-warning "^1.0.0" proxy-addr "^2.0.7" rfdc "^1.1.4" secure-json-parse "^2.0.0" @@ -3047,13 +3063,6 @@ file-type@^9.0.0: resolved "https://registry.yarnpkg.com/file-type/-/file-type-9.0.0.tgz#a68d5ad07f486414dfb2c8866f73161946714a18" integrity sha512-Qe/5NJrgIOlwijpq3B7BEpzPFcgzggOTagZmkXQY4LA6bsXKTUstK7Wp12lEJ/mLKTpvIZxmIuRcLYWT6ov9lw== -filewatcher@~3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/filewatcher/-/filewatcher-3.0.1.tgz#f4a1957355ddaf443ccd78a895f3d55e23c8a034" - integrity sha1-9KGVc1Xdr0Q8zXiolfPVXiPIoDQ= - dependencies: - debounce "^1.0.0" - fill-range@^7.0.1: version "7.0.1" resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" @@ -3075,10 +3084,10 @@ find-cache-dir@^3.2.0: make-dir "^3.0.2" pkg-dir "^4.1.0" -find-my-way@^4.1.0: - version "4.5.0" - resolved "https://registry.yarnpkg.com/find-my-way/-/find-my-way-4.5.0.tgz#885ceb7a60b9be529a11dbfed02c8cf0ab7eedb7" - integrity sha512-kVEY1lW/zXETKEEwRboCWPySygBFVNJpdY7lRnFllDdYxQD6cwcaT3Ddh8P7v824jRN3cld+8+zRbnFBxeVUxA== +find-my-way@^4.5.0: + version "4.5.1" + resolved "https://registry.yarnpkg.com/find-my-way/-/find-my-way-4.5.1.tgz#758e959194b90aea0270db18fff75e2fceb2239f" + integrity sha512-kE0u7sGoUFbMXcOG/xpkmz4sRLCklERnBcg7Ftuu1iAxsfEt2S46RLJ3Sq7vshsEy2wJT2hZxE58XZK27qa8kg== dependencies: fast-decode-uri-component "^1.0.1" fast-deep-equal "^3.1.3" @@ -3157,9 +3166,9 @@ flatstr@^1.0.12: integrity sha512-4zPxDyhCyiN2wIAtSLI6gc82/EjqZc1onI4Mz/l0pWrAlsSfYH/2ZIcU+e3oA2wDwbzIWNKwa23F8rh6+DRWkw== flatted@^3.1.0: - version "3.2.4" - resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.4.tgz#28d9969ea90661b5134259f312ab6aa7929ac5e2" - integrity sha512-8/sOawo8tJ4QOBX8YlQBMxL8+RLZfxMQOif9o0KUKTNTjMYElWPE0r/m5VNFxTRd0NSw8qSy8dajrwX4RYI1Hw== + version "3.2.5" + resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.5.tgz#76c8584f4fc843db64702a6bd04ab7a8bd666da3" + integrity sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg== foreground-child@^2.0.0: version "2.0.0" @@ -3341,9 +3350,9 @@ gifwrap@^0.9.2: omggif "^1.0.10" git-raw-commits@^2.0.8: - version "2.0.10" - resolved "https://registry.yarnpkg.com/git-raw-commits/-/git-raw-commits-2.0.10.tgz#e2255ed9563b1c9c3ea6bd05806410290297bbc1" - integrity sha512-sHhX5lsbG9SOO6yXdlwgEMQ/ljIn7qMpAbJZCGfXX2fq5T8M5SrDnpYk9/4HswTildcIqatsWa91vty6VhWSaQ== + version "2.0.11" + resolved "https://registry.yarnpkg.com/git-raw-commits/-/git-raw-commits-2.0.11.tgz#bc3576638071d18655e1cc60d7f524920008d723" + integrity sha512-VnctFhw+xfj8Va1xtfEqCUD2XDrbAPSJx+hSrE5K7fGdjZruW7XV+QOrN7LF/RJyvspRiD2I0asWsxFp0ya26A== dependencies: dargs "^7.0.0" lodash "^4.17.15" @@ -3425,19 +3434,7 @@ glob@7.1.4: once "^1.3.0" path-is-absolute "^1.0.0" -glob@7.1.7: - version "7.1.7" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.7.tgz#3b193e9233f01d42d0b3f78294bbeeb418f94a90" - integrity sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ== - dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^3.0.4" - once "^1.3.0" - path-is-absolute "^1.0.0" - -glob@^7.0.0, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6, glob@^7.1.7: +glob@7.2.0, glob@^7.0.0, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6, glob@^7.1.7: version "7.2.0" resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.0.tgz#d15535af7732e02e948f4c41628bd910293f6023" integrity sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q== @@ -3497,13 +3494,13 @@ globals@^11.1.0: integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== globals@^13.6.0, globals@^13.9.0: - version "13.12.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-13.12.0.tgz#4d733760304230a0082ed96e21e5c565f898089e" - integrity sha512-uS8X6lSKN2JumVoXrbUz+uG4BYG+eiawqm3qFcT7ammfbUHeCBoJMlHcec/S3krSk73/AE/f0szYFmgAA3kYZg== + version "13.12.1" + resolved "https://registry.yarnpkg.com/globals/-/globals-13.12.1.tgz#ec206be932e6c77236677127577aa8e50bf1c5cb" + integrity sha512-317dFlgY2pdJZ9rspXDks7073GpDmXdfbM3vYYp0HAMKGDh1FfWPleI2ljVNLQX5M5lXcAslTcPTrOrMEFOjyw== dependencies: type-fest "^0.20.2" -globby@11.0.4, globby@^11.0.4: +globby@11.0.4: version "11.0.4" resolved "https://registry.yarnpkg.com/globby/-/globby-11.0.4.tgz#2cbaff77c2f2a62e71e9b2813a67b97a3a3001a5" integrity sha512-9O4MVG9ioZJ08ffbcyVYyLOJLk5JQ688pJ4eMGLpdWLHq/Wr1D9BlriLQyL0E+jbkuePVZXYFj47QM/v093wHg== @@ -3515,6 +3512,18 @@ globby@11.0.4, globby@^11.0.4: merge2 "^1.3.0" slash "^3.0.0" +globby@^11.0.4: + version "11.1.0" + resolved "https://registry.yarnpkg.com/globby/-/globby-11.1.0.tgz#bd4be98bb042f83d796f7e3811991fbe82a0d34b" + integrity sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g== + dependencies: + array-union "^2.1.0" + dir-glob "^3.0.1" + fast-glob "^3.2.9" + ignore "^5.2.0" + merge2 "^1.4.1" + slash "^3.0.0" + got@11.8.3: version "11.8.3" resolved "https://registry.yarnpkg.com/got/-/got-11.8.3.tgz#f496c8fdda5d729a90b4905d2b07dbd148170770" @@ -3549,21 +3558,16 @@ got@^9.6.0: to-readable-stream "^1.0.0" url-parse-lax "^3.0.0" -graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.4: - version "4.2.8" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.8.tgz#e412b8d33f5e006593cbd3cee6df9f2cebbe802a" - integrity sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg== +graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.9: + version "4.2.9" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.9.tgz#041b05df45755e587a24942279b9d113146e1c96" + integrity sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ== growl@1.10.5: version "1.10.5" resolved "https://registry.yarnpkg.com/growl/-/growl-1.10.5.tgz#f2735dc2283674fa67478b10181059355c369e5e" integrity sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA== -growly@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/growly/-/growly-1.3.0.tgz#f10748cbe76af964b7c96c93c6bcc28af120c081" - integrity sha1-8QdIy+dq+WS3yWyTxrzCivEgwIE= - gzip-size@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/gzip-size/-/gzip-size-7.0.0.tgz#9f9644251f15bc78460fccef4055ae5a5562ac60" @@ -3571,7 +3575,7 @@ gzip-size@^7.0.0: dependencies: duplexer "^0.1.2" -handlebars@^4.7.6: +handlebars@^4.7.7: version "4.7.7" resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.7.7.tgz#9ce33416aad02dbd6c8fafa8240d5d98004945a1" integrity sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA== @@ -3659,9 +3663,9 @@ hosted-git-info@^2.1.4: integrity sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw== hosted-git-info@^4.0.0, hosted-git-info@^4.0.1: - version "4.0.2" - resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-4.0.2.tgz#5e425507eede4fea846b7262f0838456c4209961" - integrity sha512-c9OGXbZ3guC/xOlCg1Ci/VgWlwsqDv1yMQL1CWqXDL0hDjXuNcq0zuR4xqPSuasI3kqFDhqSyTjREz5gzq0fXg== + version "4.1.0" + resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-4.1.0.tgz#827b82867e9ff1c8d0c4d9d53880397d2c86d224" + integrity sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA== dependencies: lru-cache "^6.0.0" @@ -3714,15 +3718,20 @@ ieee754@^1.1.13: resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== +ignore-by-default@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/ignore-by-default/-/ignore-by-default-1.0.1.tgz#48ca6d72f6c6a3af00a9ad4ae6876be3889e2b09" + integrity sha1-SMptcvbGo68Aqa1K5odr44ieKwk= + ignore@^4.0.6: version "4.0.6" resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc" integrity sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg== -ignore@^5.0.0, ignore@^5.1.4, ignore@^5.1.8: - version "5.1.9" - resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.1.9.tgz#9ec1a5cbe8e1446ec60d4420060d43aa6e7382fb" - integrity sha512-2zeMQpbKz5dhZ9IwL0gbxSW5w0NK/MSAMtNuhgIHEPmaU3vPdKPL0UdvUCXs5SS4JAwsBxysK5sFMW8ocFiVjQ== +ignore@^5.0.0, ignore@^5.1.4, ignore@^5.1.8, ignore@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.0.tgz#6d3bac8fa7fe0d45d9f9be7bac2fc279577e345a" + integrity sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ== image-q@^1.1.1: version "1.1.1" @@ -3908,10 +3917,10 @@ is-ci@^2.0.0: dependencies: ci-info "^2.0.0" -is-core-module@^2.2.0, is-core-module@^2.5.0: - version "2.8.0" - resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.8.0.tgz#0321336c3d0925e497fd97f5d95cb114a5ccd548" - integrity sha512-vd15qHsaqrRL7dtH6QNuy0ndJmRDrS9HAM1CAiSifNUFv4x1a0CCVsj18hJ1mShxIG6T2i1sO78MkP56r0nYRw== +is-core-module@^2.5.0, is-core-module@^2.8.1: + version "2.8.1" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.8.1.tgz#f59fdfca701d5879d0a6b100a40aa1560ce27211" + integrity sha512-SdNCUs284hr40hFTFP6l0IfZ/RSrMXF3qgoRHd3/79unUTvrFO/JoXwkGm+5J/Oe3E/b5GsnG330uUNgRpu1PA== dependencies: has "^1.0.3" @@ -3947,11 +3956,6 @@ is-fullwidth-code-point@^3.0.0: resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== -is-fullwidth-code-point@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz#fae3167c729e7463f8461ce512b080a49268aa88" - integrity sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ== - is-function@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/is-function/-/is-function-1.0.2.tgz#4f097f30abf6efadac9833b17ca5dc03f8144e08" @@ -4056,7 +4060,7 @@ is-windows@^1.0.1, is-windows@^1.0.2: resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" integrity sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA== -is-wsl@^2.1.1, is-wsl@^2.2.0: +is-wsl@^2.1.1: version "2.2.0" resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-2.2.0.tgz#74a4c76e77ca9fd3f932f290c17ea326cd157271" integrity sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww== @@ -4137,58 +4141,53 @@ istanbul-lib-source-maps@^4.0.0: source-map "^0.6.1" istanbul-reports@^3.0.2: - version "3.1.1" - resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-3.1.1.tgz#7085857f17d2441053c6ce5c3b8fdf6882289397" - integrity sha512-q1kvhAXWSsXfMjCdNHNPKZZv94OlspKnoGv+R9RGbnqOOQ0VbNfLFgQDVgi7hHenKsndGq3/o0OBdzDXthWcNw== + version "3.1.4" + resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-3.1.4.tgz#1b6f068ecbc6c331040aab5741991273e609e40c" + integrity sha512-r1/DshN4KSE7xWEknZLLLLDn5CJybV3nw01VTkp6D5jzLuELlcbudfj/eSQFvrKsJuTVCGnePO7ho82Nw9zzfw== dependencies: html-escaper "^2.0.0" istanbul-lib-report "^3.0.0" -jest-diff@^27.4.2: - version "27.4.2" - resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-27.4.2.tgz#786b2a5211d854f848e2dcc1e324448e9481f36f" - integrity sha512-ujc9ToyUZDh9KcqvQDkk/gkbf6zSaeEg9AiBxtttXW59H/AcqEYp1ciXAtJp+jXWva5nAf/ePtSsgWwE5mqp4Q== +jest-diff@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-27.5.1.tgz#a07f5011ac9e6643cf8a95a462b7b1ecf6680def" + integrity sha512-m0NvkX55LDt9T4mctTEgnZk3fmEg3NRYutvMPWM/0iPnkFj2wIeF45O1718cMSOFO1vINkqmxqD8vE37uTEbqw== dependencies: chalk "^4.0.0" - diff-sequences "^27.4.0" - jest-get-type "^27.4.0" - pretty-format "^27.4.2" + diff-sequences "^27.5.1" + jest-get-type "^27.5.1" + pretty-format "^27.5.1" -jest-get-type@^27.4.0: - version "27.4.0" - resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-27.4.0.tgz#7503d2663fffa431638337b3998d39c5e928e9b5" - integrity sha512-tk9o+ld5TWq41DkK14L4wox4s2D9MtTpKaAVzXfr5CUKm5ZK2ExcaFE0qls2W71zE/6R2TxxrK9w2r6svAFDBQ== +jest-get-type@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-27.5.1.tgz#3cd613c507b0f7ace013df407a1c1cd578bcb4f1" + integrity sha512-2KY95ksYSaK7DMBWQn6dQz3kqAf3BB64y2udeG+hv4KfSOb9qwcYQstTJc1KCbsix+wLZWZYN8t7nwX3GOBLRw== -jest-matcher-utils@^27.4.2: - version "27.4.2" - resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-27.4.2.tgz#d17c5038607978a255e0a9a5c32c24e984b6c60b" - integrity sha512-jyP28er3RRtMv+fmYC/PKG8wvAmfGcSNproVTW2Y0P/OY7/hWUOmsPfxN1jOhM+0u2xU984u2yEagGivz9OBGQ== +jest-matcher-utils@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-27.5.1.tgz#9c0cdbda8245bc22d2331729d1091308b40cf8ab" + integrity sha512-z2uTx/T6LBaCoNWNFWwChLBKYxTMcGBRjAt+2SbP929/Fflb9aa5LGma654Rz8z9HLxsrUaYzxE9T/EFIL/PAw== dependencies: chalk "^4.0.0" - jest-diff "^27.4.2" - jest-get-type "^27.4.0" - pretty-format "^27.4.2" + jest-diff "^27.5.1" + jest-get-type "^27.5.1" + pretty-format "^27.5.1" -jest-message-util@^27.4.2: - version "27.4.2" - resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-27.4.2.tgz#07f3f1bf207d69cf798ce830cc57f1a849f99388" - integrity sha512-OMRqRNd9E0DkBLZpFtZkAGYOXl6ZpoMtQJWTAREJKDOFa0M6ptB7L67tp+cszMBkvSgKOhNtQp2Vbcz3ZZKo/w== +jest-message-util@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-27.5.1.tgz#bdda72806da10d9ed6425e12afff38cd1458b6cf" + integrity sha512-rMyFe1+jnyAAf+NHwTclDz0eAaLkVDdKVHHBFWsBWHnnh5YeJMNWWsv7AbFYXfK3oTqvL7VTWkhNLu1jX24D+g== dependencies: "@babel/code-frame" "^7.12.13" - "@jest/types" "^27.4.2" + "@jest/types" "^27.5.1" "@types/stack-utils" "^2.0.0" chalk "^4.0.0" - graceful-fs "^4.2.4" + graceful-fs "^4.2.9" micromatch "^4.0.4" - pretty-format "^27.4.2" + pretty-format "^27.5.1" slash "^3.0.0" stack-utils "^2.0.3" -jest-regex-util@^27.4.0: - version "27.4.0" - resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-27.4.0.tgz#e4c45b52653128843d07ad94aec34393ea14fbca" - integrity sha512-WeCpMpNnqJYMQoOjm1nTtsgbR4XHAk1u00qDoNBQoykM280+/TmgA5Qh5giC1ecy6a5d4hbSsHzpBtu5yvlbEg== - jimp@^0.16.1: version "0.16.1" resolved "https://registry.yarnpkg.com/jimp/-/jimp-0.16.1.tgz#192f851a30e5ca11112a3d0aa53137659a78ca7a" @@ -4287,7 +4286,7 @@ json-parse-better-errors@^1.0.1: resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9" integrity sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw== -json-parse-even-better-errors@^2.3.0: +json-parse-even-better-errors@^2.3.0, json-parse-even-better-errors@^2.3.1: version "2.3.1" resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d" integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w== @@ -4368,9 +4367,9 @@ keyv@^3.0.0: json-buffer "3.0.0" keyv@^4.0.0: - version "4.0.4" - resolved "https://registry.yarnpkg.com/keyv/-/keyv-4.0.4.tgz#f040b236ea2b06ed15ed86fbef8407e1a1c8e376" - integrity sha512-vqNHbAc8BBsxk+7QBYLW0Y219rWcClspR6WSeoHYKG5mnsSoOH+BL1pWq02DDCVdvvuUny5rkBlzMRzoqc+GIg== + version "4.1.1" + resolved "https://registry.yarnpkg.com/keyv/-/keyv-4.1.1.tgz#02c538bfdbd2a9308cc932d4096f05ae42bfa06a" + integrity sha512-tGv1yP6snQVDSM4X6yxrv2zzq/EvpW+oYiUz6aueW1u9CtS8RzUQYxxmFwgZlO2jSgCxQbchhxaqXXp2hnKGpQ== dependencies: json-buffer "3.0.1" @@ -4414,9 +4413,9 @@ libnpmconfig@^1.0.0: ini "^1.3.5" light-my-request@^4.2.0: - version "4.7.0" - resolved "https://registry.yarnpkg.com/light-my-request/-/light-my-request-4.7.0.tgz#5bacd17fa0eaf96fe5eed1682c5e0d361953cf46" - integrity sha512-LTa8YZp3K2AUpqUnwwKajoIHcsKOBnzwJNQSrk7unziPwo6CjOYjyO0F9wfkxFvP+nBsCGe3eMPnedVgIIgdAw== + version "4.7.1" + resolved "https://registry.yarnpkg.com/light-my-request/-/light-my-request-4.7.1.tgz#deb33c4485a08395760f16e5a7a044e6102bb4c4" + integrity sha512-7/bT6M+iHY90L9/rW7aboVYt0o0uOqzIx4yofC67d6WE9uLksecGf3mxPuZfVjMONG+i6hCq6z5NZCxqzpA2yw== dependencies: ajv "^8.1.0" cookie "^0.4.0" @@ -4428,6 +4427,11 @@ lines-and-columns@^1.1.6: resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632" integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg== +lines-and-columns@^2.0.2: + version "2.0.3" + resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-2.0.3.tgz#b2f0badedb556b747020ab8ea7f0373e22efac1b" + integrity sha512-cNOjgCnLB+FnvWWtyRTzmB3POJ+cXxTA81LoW7u8JdmhfXzriropYwpjShnz1QLLWsQwY7nIxoDmcPTwphDK9w== + load-bmfont@^1.2.3, load-bmfont@^1.3.1, load-bmfont@^1.4.0: version "1.4.1" resolved "https://registry.yarnpkg.com/load-bmfont/-/load-bmfont-1.4.1.tgz#c0f5f4711a1e2ccff725a7b6078087ccfcddd3e9" @@ -4500,11 +4504,6 @@ lodash.flattendeep@^4.4.0: resolved "https://registry.yarnpkg.com/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz#fb030917f86a3134e5bc9bec0d69e0013ddfedb2" integrity sha1-+wMJF/hqMTTlvJvsDWngAT3f7bI= -lodash.get@^4: - version "4.4.2" - resolved "https://registry.yarnpkg.com/lodash.get/-/lodash.get-4.4.2.tgz#2d177f652fa31e939b4438d5341499dfa3825e99" - integrity sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk= - lodash.ismatch@^4.4.0: version "4.4.0" resolved "https://registry.yarnpkg.com/lodash.ismatch/-/lodash.ismatch-4.4.0.tgz#756cb5150ca3ba6f11085a78849645f188f85f37" @@ -4572,7 +4571,7 @@ make-dir@^3.0.0, make-dir@^3.0.2: dependencies: semver "^6.0.0" -make-error@^1, make-error@^1.1.1: +make-error@^1.1.1: version "1.3.6" resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2" integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw== @@ -4606,9 +4605,9 @@ mdast-util-from-markdown@^1.0.0: uvu "^0.5.0" mdast-util-to-markdown@^1.0.0: - version "1.2.6" - resolved "https://registry.yarnpkg.com/mdast-util-to-markdown/-/mdast-util-to-markdown-1.2.6.tgz#9d0d1fcb22838e4af83fb04841cbde92525972f3" - integrity sha512-doJZmTEGagHypWvJ8ltinmwUsT9ZaNgNIQW6Gl7jNdsI1QZkTHTimYW561Niy2s8AEPAqEgV0dIh2UOVlSXUJA== + version "1.3.0" + resolved "https://registry.yarnpkg.com/mdast-util-to-markdown/-/mdast-util-to-markdown-1.3.0.tgz#38b6cdc8dc417de642a469c4fc2abdf8c931bd1e" + integrity sha512-6tUSs4r+KK4JGTTiQ7FfHmVOaDrLQJPmpjD6wPMlHGUVXoG9Vjc3jIeP+uyBWRf8clwB2blM+W7+KrlMYQnftA== dependencies: "@types/mdast" "^3.0.0" "@types/unist" "^2.0.0" @@ -4659,7 +4658,7 @@ merge-stream@^2.0.0: resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== -merge2@^1.3.0: +merge2@^1.3.0, merge2@^1.4.1: version "1.4.1" resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== @@ -4789,9 +4788,9 @@ micromark-util-decode-string@^1.0.0: micromark-util-symbol "^1.0.0" micromark-util-encode@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/micromark-util-encode/-/micromark-util-encode-1.0.0.tgz#c409ecf751a28aa9564b599db35640fccec4c068" - integrity sha512-cJpFVM768h6zkd8qJ1LNRrITfY4gwFt+tziPcIf71Ui8yFzY9wG3snZQqiWVq93PG4Sw6YOtcNiKJfVIs9qfGg== + version "1.0.1" + resolved "https://registry.yarnpkg.com/micromark-util-encode/-/micromark-util-encode-1.0.1.tgz#2c1c22d3800870ad770ece5686ebca5920353383" + integrity sha512-U2s5YdnAYexjKDel31SVMPbfi+eF8y1U4pfiRW/Y8EFVCy/vgxk/2wWTxzcqE71LHtCuCzlBDRU2a5CQ5j+mQA== micromark-util-html-tag-name@^1.0.0: version "1.0.0" @@ -4877,7 +4876,7 @@ mime-db@1.51.0, "mime-db@>= 1.43.0 < 2": resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.51.0.tgz#d9ff62451859b18342d960850dc3cfb77e63fb0c" integrity sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g== -mime-types@2.1.34, mime-types@^2.1.12, mime-types@~2.1.19, mime-types@~2.1.24: +mime-types@2.1.34, mime-types@^2.1.12, mime-types@~2.1.19, mime-types@~2.1.34: version "2.1.34" resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.34.tgz#5a712f9ec1503511a945803640fafe09d3793c24" integrity sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A== @@ -4926,13 +4925,20 @@ min-indent@^1.0.0: resolved "https://registry.yarnpkg.com/min-indent/-/min-indent-1.0.1.tgz#a63f681673b30571fbe8bc25686ae746eefa9869" integrity sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg== -minimatch@3.0.4, minimatch@^3.0.4: +minimatch@3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== dependencies: brace-expansion "^1.1.7" +minimatch@^3.0.4: + version "3.1.2" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" + integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== + dependencies: + brace-expansion "^1.1.7" + minimist-options@4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/minimist-options/-/minimist-options-4.1.0.tgz#c0655713c53a8a2ebd77ffa247d342c40f010619" @@ -4966,32 +4972,32 @@ mkdirp@^0.5.1: dependencies: minimist "^1.2.5" -mocha@^9.1.3: - version "9.1.3" - resolved "https://registry.yarnpkg.com/mocha/-/mocha-9.1.3.tgz#8a623be6b323810493d8c8f6f7667440fa469fdb" - integrity sha512-Xcpl9FqXOAYqI3j79pEtHBBnQgVXIhpULjGQa7DVb0Po+VzmSIK9kanAiWLHoRR/dbZ2qpdPshuXr8l1VaHCzw== +mocha@^9.2.0: + version "9.2.0" + resolved "https://registry.yarnpkg.com/mocha/-/mocha-9.2.0.tgz#2bfba73d46e392901f877ab9a47b7c9c5d0275cc" + integrity sha512-kNn7E8g2SzVcq0a77dkphPsDSN7P+iYkqE0ZsGCYWRsoiKjOt+NvXfaagik8vuDa6W5Zw3qxe8Jfpt5qKf+6/Q== dependencies: "@ungap/promise-all-settled" "1.1.2" ansi-colors "4.1.1" browser-stdout "1.3.1" - chokidar "3.5.2" - debug "4.3.2" + chokidar "3.5.3" + debug "4.3.3" diff "5.0.0" escape-string-regexp "4.0.0" find-up "5.0.0" - glob "7.1.7" + glob "7.2.0" growl "1.10.5" he "1.2.0" js-yaml "4.1.0" log-symbols "4.1.0" minimatch "3.0.4" ms "2.1.3" - nanoid "3.1.25" + nanoid "3.2.0" serialize-javascript "6.0.0" strip-json-comments "3.1.1" supports-color "8.1.1" which "2.0.2" - workerpool "6.1.5" + workerpool "6.2.0" yargs "16.2.0" yargs-parser "20.2.4" yargs-unparser "2.0.0" @@ -5016,7 +5022,7 @@ ms@2.1.2: resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== -ms@2.1.3: +ms@2.1.3, ms@^2.1.1: version "2.1.3" resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== @@ -5031,15 +5037,15 @@ mute-stream@0.0.8: resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.8.tgz#1630c42b2251ff81e2a283de96a5497ea92e5e0d" integrity sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA== -nanoid@3.1.25: - version "3.1.25" - resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.1.25.tgz#09ca32747c0e543f0e1814b7d3793477f9c8e152" - integrity sha512-rdwtIXaXCLFAQbnfqDRnI6jaRHp9fTcYBjtFKE8eezcZ7LuLjhUaQGNeMXf1HmRoCH32CLz6XwX0TtxEOS/A3Q== +nanoid@3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.2.0.tgz#62667522da6673971cca916a6d3eff3f415ff80c" + integrity sha512-fmsZYa9lpn69Ad5eDn7FMcnnSR+8R34W9qJEijxYhTbfOWzr22n1QxCMzXLK+ODyW2973V3Fux959iQoUxzUIA== -nanoid@^3.1.30: - version "3.1.30" - resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.1.30.tgz#63f93cc548d2a113dc5dfbc63bfa09e2b9b64362" - integrity sha512-zJpuPDwOv8D2zq2WRoMe1HsfZthVewpel9CAvTfc/2mBD1uUT/agc5f7GHGWXlYkFvi1mVxe4IjvP2HNrop7nQ== +nanoid@^3.2.0: + version "3.3.1" + resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.1.tgz#6347a18cac88af88f58af0b3594b723d5e99bb35" + integrity sha512-n6Vs/3KGyxPQd6uO0eH4Bv0ojGSUvuLlIHtC3Y0kEO23YRge8H9x1GCzLn28YX0H66pMkxuaeESFq4tKISKwdw== napi-build-utils@^1.0.1: version "1.0.2" @@ -5067,10 +5073,10 @@ ndarray@^1.0.13, ndarray@^1.0.19: iota-array "^1.0.0" is-buffer "^1.0.2" -negotiator@0.6.2: - version "0.6.2" - resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.2.tgz#feacf7ccf525a77ae9634436a64883ffeca346fb" - integrity sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw== +negotiator@0.6.3: + version "0.6.3" + resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd" + integrity sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg== neo-async@^2.6.0: version "2.6.2" @@ -5106,43 +5112,13 @@ node-bitmap@0.0.1: resolved "https://registry.yarnpkg.com/node-bitmap/-/node-bitmap-0.0.1.tgz#180eac7003e0c707618ef31368f62f84b2a69091" integrity sha1-GA6scAPgxwdhjvMTaPYvhLKmkJE= -node-dev@^7.1.0: - version "7.1.0" - resolved "https://registry.yarnpkg.com/node-dev/-/node-dev-7.1.0.tgz#b3294e4171b3cd7caa894480e006cd9e4d16ff0c" - integrity sha512-wvlX+XQVGdwin0CQrWWCNvhb6Sf2FB/zNLFleg3o5Ml6jhAwWXKMX1JSP/1RSyf0atLXxD/L3vl7pNVJgClv/w== - dependencies: - dateformat "^3.0.3" - dynamic-dedupe "^0.3.0" - filewatcher "~3.0.0" - minimist "^1.2.5" - node-notifier "^8.0.1" - resolve "^1.0.0" - semver "^7.3.5" - -node-fetch@2.6.1: - version "2.6.1" - resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.1.tgz#045bd323631f76ed2e2b55573394416b639a0052" - integrity sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw== - -node-fetch@^2.6.1: - version "2.6.6" - resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.6.tgz#1751a7c01834e8e1697758732e9efb6eeadfaf89" - integrity sha512-Z8/6vRlTUChSdIgMa51jxQ4lrw/Jy5SOW10ObaA47/RElsAN2c5Pn8bTgFGWn/ibwzXTE8qwr1Yzx28vsecXEA== +node-fetch@2.6.7, node-fetch@^2.6.7: + version "2.6.7" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad" + integrity sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ== dependencies: whatwg-url "^5.0.0" -node-notifier@^8.0.1: - version "8.0.2" - resolved "https://registry.yarnpkg.com/node-notifier/-/node-notifier-8.0.2.tgz#f3167a38ef0d2c8a866a83e318c1ba0efeb702c5" - integrity sha512-oJP/9NAdd9+x2Q+rfphB2RJCHjod70RcRLjosiPMMu5gjIfwVnOUGq2nbTjTUbmy0DJ/tFIVT30+Qe3nzl4TJg== - dependencies: - growly "^1.3.0" - is-wsl "^2.2.0" - semver "^7.3.2" - shellwords "^0.1.1" - uuid "^8.3.0" - which "^2.0.2" - node-preload@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/node-preload/-/node-preload-0.2.1.tgz#c03043bb327f417a18fee7ab7ee57b408a144301" @@ -5151,9 +5127,32 @@ node-preload@^0.2.1: process-on-spawn "^1.0.0" node-releases@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.1.tgz#3d1d395f204f1f2f29a54358b9fb678765ad2fc5" - integrity sha512-CqyzN6z7Q6aMeF/ktcMVTzhAHCEpf8SOarwpzpf8pNBY2k5/oM34UHldUwp8VKI7uxct2HxSRdJjBaZeESzcxA== + version "2.0.2" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.2.tgz#7139fe71e2f4f11b47d4d2986aaf8c48699e0c01" + integrity sha512-XxYDdcQ6eKqp/YjI+tb2C5WM2LgjnZrfYg4vgQt49EK268b6gYCHsBLrK2qvJo4FmCtqmKezb0WZFK4fkrZNsg== + +nodemon@^2.0.15: + version "2.0.15" + resolved "https://registry.yarnpkg.com/nodemon/-/nodemon-2.0.15.tgz#504516ce3b43d9dc9a955ccd9ec57550a31a8d4e" + integrity sha512-gdHMNx47Gw7b3kWxJV64NI+Q5nfl0y5DgDbiVtShiwa7Z0IZ07Ll4RLFo6AjrhzMtoEZn5PDE3/c2AbVsiCkpA== + dependencies: + chokidar "^3.5.2" + debug "^3.2.7" + ignore-by-default "^1.0.1" + minimatch "^3.0.4" + pstree.remy "^1.1.8" + semver "^5.7.1" + supports-color "^5.5.0" + touch "^3.1.0" + undefsafe "^2.0.5" + update-notifier "^5.1.0" + +nopt@~1.0.10: + version "1.0.10" + resolved "https://registry.yarnpkg.com/nopt/-/nopt-1.0.10.tgz#6ddd21bd2a31417b92727dd585f8a6f37608ebee" + integrity sha1-bd0hvSoxQXuScn3Vhfim83YI6+4= + dependencies: + abbrev "1" normalize-package-data@^2.3.2, normalize-package-data@^2.5.0: version "2.5.0" @@ -5256,9 +5255,9 @@ object-assign@^4.0.1, object-assign@^4.1.0: integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= object-inspect@^1.9.0: - version "1.11.1" - resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.11.1.tgz#d4bd7d7de54b9a75599f59a00bd698c1f1c6549b" - integrity sha512-If7BjFlpkzzBeV1cqgT3OSWT3azyoxDGajR+iGnFBfVV2EWyDyWaZZW2ERDjUaY2QM8i5jI3Sj7mhsM4DDAqWA== + version "1.12.0" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.0.tgz#6e2c120e868fd1fd18cb4f18c31741d0d6e776f0" + integrity sha512-Ho2z80bVIvJloH+YzRmpZVQe87+qASmBUKZDWgx9cu+KDrX2ZDH/3tMy+gXbZETVGs2M8YdxObOh7XAtim9Y0g== omggif@^1.0.10, omggif@^1.0.9: version "1.0.10" @@ -5488,6 +5487,16 @@ parse-json@^4.0.0: error-ex "^1.3.1" json-parse-better-errors "^1.0.1" +parse-json@^6.0.0: + version "6.0.2" + resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-6.0.2.tgz#6bf79c201351cc12d5d66eba48d5a097c13dc200" + integrity sha512-SA5aMiaIjXkAiBrW/yPgLgQAQg42f7K3ACO+2l/zOvtQBwX58DMUsFJXelW2fx3yMBmWOVkR6j1MGsdSbCA4UA== + dependencies: + "@babel/code-frame" "^7.16.0" + error-ex "^1.3.2" + json-parse-even-better-errors "^2.3.1" + lines-and-columns "^2.0.2" + parse-passwd@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/parse-passwd/-/parse-passwd-1.0.0.tgz#6d5b934a456993b23d37f40a382d6f1666a8e5c6" @@ -5545,7 +5554,7 @@ path-key@^3.0.0, path-key@^3.1.0: resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== -path-parse@^1.0.6: +path-parse@^1.0.7: version "1.0.7" resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== @@ -5578,9 +5587,9 @@ picocolors@^1.0.0: integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.2.3: - version "2.3.0" - resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.0.tgz#f1f061de8f6a4bf022892e2d128234fb98302972" - integrity sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw== + version "2.3.1" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" + integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== pify@^2.3.0: version "2.3.0" @@ -5610,22 +5619,22 @@ pino-std-serializers@^3.1.0: integrity sha512-EqX4pwDPrt3MuOAAUBMU0Tk5kR/YcCM5fNPEzgCO2zJ5HfX0vbiH9HbJglnyeQsN96Kznae6MWD47pZB5avTrg== pino@^6.13.0: - version "6.13.3" - resolved "https://registry.yarnpkg.com/pino/-/pino-6.13.3.tgz#60b93bcda1541f92fb37b3f2be0a25cf1d05b6fe" - integrity sha512-tJy6qVgkh9MwNgqX1/oYi3ehfl2Y9H0uHyEEMsBe74KinESIjdMrMQDWpcZPpPicg3VV35d/GLQZmo4QgU2Xkg== + version "6.14.0" + resolved "https://registry.yarnpkg.com/pino/-/pino-6.14.0.tgz#b745ea87a99a6c4c9b374e4f29ca7910d4c69f78" + integrity sha512-iuhEDel3Z3hF9Jfe44DPXR8l07bhjuFY3GMHIXbjnY9XcafbyDDwl2sN2vw2GjMPf5Nkoe+OFao7ffn9SXaKDg== dependencies: fast-redact "^3.0.0" fast-safe-stringify "^2.0.8" - fastify-warning "^0.2.0" flatstr "^1.0.12" pino-std-serializers "^3.1.0" + process-warning "^1.0.0" quick-format-unescaped "^4.0.3" sonic-boom "^1.0.2" -pirates@^4.0.1, pirates@^4.0.4: - version "4.0.4" - resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.4.tgz#07df81e61028e402735cdd49db701e4885b4e6e6" - integrity sha512-ZIrVPH+A52Dw84R0L3/VS9Op04PuQ2SEoJL6bkshmiTic/HldyW9Tf7oH5mhJZBK7NmDx27vSMrYEXPXclpDKw== +pirates@^4.0.1, pirates@^4.0.5: + version "4.0.5" + resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.5.tgz#feec352ea5c3268fb23a37c702ab1699f35a5f3b" + integrity sha512-8V9+HQPupnaXMA23c5hvl69zXvTwTzyAYasnkb0Tts4XvO4CliqONMOnvlq26rkhLC3nWDFBJf73LU1e1VZLaQ== pixelmatch@^4.0.0, pixelmatch@^4.0.2: version "4.0.2" @@ -5652,21 +5661,21 @@ pngjs@^5.0.0: integrity sha512-40QW5YalBNfQo5yRYmiw7Yz6TKKVr3h6970B2YE+3fQpsWcrbj1PzJgxeJ19DRQjhMbKPIuMY8rFaXc8moolVw== postcss-selector-parser@^6.0.6: - version "6.0.7" - resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.0.7.tgz#48404830a635113a71fd79397de8209ed05a66fc" - integrity sha512-U+b/Deoi4I/UmE6KOVPpnhS7I7AYdKbhGcat+qTQ27gycvaACvNEw11ba6RrkwVmDVRW7sigWgLj4/KbbJjeDA== + version "6.0.9" + resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.0.9.tgz#ee71c3b9ff63d9cd130838876c13a2ec1a992b2f" + integrity sha512-UO3SgnZOVTwu4kyLR22UQ1xZh086RyNZppb7lLAKBFK8a32ttG5i87Y/P3+2bRSjZNyJ1B7hfFNo273tKe9YxQ== dependencies: cssesc "^3.0.0" util-deprecate "^1.0.2" postcss@^8.3.5: - version "8.4.5" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.5.tgz#bae665764dfd4c6fcc24dc0fdf7e7aa00cc77f95" - integrity sha512-jBDboWM8qpaqwkMwItqTQTiFikhs/67OYVvblFFTM7MrZjt6yMKd6r2kgXizEbTTljacm4NldIlZnhbjr84QYg== + version "8.4.6" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.6.tgz#c5ff3c3c457a23864f32cb45ac9b741498a09ae1" + integrity sha512-OovjwIzs9Te46vlEx7+uXB0PLijpwjXGKXjVGGPIGubGpq7uh5Xgf6D6FiJ/SzJMBosHDp6a2hiXOS97iBXcaA== dependencies: - nanoid "^3.1.30" + nanoid "^3.2.0" picocolors "^1.0.0" - source-map-js "^1.0.1" + source-map-js "^1.0.2" prebuild-install@^6.1.2: version "6.1.4" @@ -5693,11 +5702,10 @@ prelude-ls@^1.2.1: integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== prepend-file@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/prepend-file/-/prepend-file-2.0.0.tgz#2d3256376a64ca3b5640153890a89cadbebaf1a9" - integrity sha512-U6on3jv5hQ+CNEO7gFn00PUlm3F/oXIQTMg6jpeQTQHLYSZl/Cxb4NpH44FA0By+maPXpfUaqmCoPUTu/Z3/8g== + version "2.0.1" + resolved "https://registry.yarnpkg.com/prepend-file/-/prepend-file-2.0.1.tgz#6a624b474a65ab1f87dc24d1757d5a6d989eb2db" + integrity sha512-0hXWjmOpz5YBIk6xujS0lYtCw6IAA0wCR3fw49UGTLc3E9BIhcxgqdMa8rzGvrtt2F8wFiGP42oEpQ8fo9zhRw== dependencies: - path-exists "^4.0.0" temp-write "^4.0.0" prepend-http@^2.0.0: @@ -5705,12 +5713,11 @@ prepend-http@^2.0.0: resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-2.0.0.tgz#e92434bfa5ea8c19f41cdfd401d741a3c819d897" integrity sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc= -pretty-format@^27.4.2: - version "27.4.2" - resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-27.4.2.tgz#e4ce92ad66c3888423d332b40477c87d1dac1fb8" - integrity sha512-p0wNtJ9oLuvgOQDEIZ9zQjZffK7KtyR6Si0jnXULIDwrlNF8Cuir3AZP0hHv0jmKuNN/edOnbMjnzd4uTcmWiw== +pretty-format@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-27.5.1.tgz#2181879fdea51a7a5851fb39d920faa63f01d88e" + integrity sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ== dependencies: - "@jest/types" "^27.4.2" ansi-regex "^5.0.1" ansi-styles "^5.0.0" react-is "^17.0.1" @@ -5727,16 +5734,16 @@ process-on-spawn@^1.0.0: dependencies: fromentries "^1.2.0" +process-warning@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/process-warning/-/process-warning-1.0.0.tgz#980a0b25dc38cd6034181be4b7726d89066b4616" + integrity sha512-du4wfLyj4yCZq1VupnVSZmRsPJsNuxoDQFdCFHLaYiEbFBD7QE0a+I4D7hOxrVnh78QE/YipFAj9lXHiXocV+Q== + process@^0.11.10: version "0.11.10" resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182" integrity sha1-czIwDoQBYb2j5podHZGn1LwW8YI= -progress@^2.0.0: - version "2.0.3" - resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8" - integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA== - protocols@^1.1.0, protocols@^1.4.0: version "1.4.8" resolved "https://registry.yarnpkg.com/protocols/-/protocols-1.4.8.tgz#48eea2d8f58d9644a4a32caae5d5db290a075ce8" @@ -5755,6 +5762,11 @@ psl@^1.1.28: resolved "https://registry.yarnpkg.com/psl/-/psl-1.8.0.tgz#9326f8bcfb013adcc005fdff056acce020e51c24" integrity sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ== +pstree.remy@^1.1.8: + version "1.1.8" + resolved "https://registry.yarnpkg.com/pstree.remy/-/pstree.remy-1.1.8.tgz#c242224f4a67c21f686839bbdb4ac282b8373d3a" + integrity sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w== + pump@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64" @@ -5791,16 +5803,16 @@ q@^1.5.1: integrity sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc= qs@^6.9.4: - version "6.10.2" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.10.2.tgz#c1431bea37fc5b24c5bdbafa20f16bdf2a4b9ffe" - integrity sha512-mSIdjzqznWgfd4pMii7sHtaYF8rx8861hBO80SraY5GT0XQibWZWJSid0avzHGkDIZLImux2S5mXO0Hfct2QCw== + version "6.10.3" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.10.3.tgz#d6cde1b2ffca87b5aa57889816c5f81535e22e8e" + integrity sha512-wr7M2E0OFRfIfJZjKGieI8lBKb7fRCH4Fv5KNPEs7gJ8jadvotdsS08PzOKR7opXhZ/Xkjtt3WF9g38drmyRqQ== dependencies: side-channel "^1.0.4" qs@~6.5.2: - version "6.5.2" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36" - integrity sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA== + version "6.5.3" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.3.tgz#3aeeffc91967ef6e35c0e488ef46fb296ab76aad" + integrity sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA== query-string@^6.13.8: version "6.14.1" @@ -5970,18 +5982,17 @@ registry-url@^5.0.0: dependencies: rc "^1.2.8" -release-it@^14.11.8: - version "14.11.8" - resolved "https://registry.yarnpkg.com/release-it/-/release-it-14.11.8.tgz#6da25daa93286d832cae4f10008a3bf0c08c2725" - integrity sha512-951DJ0kwjwU7CwGU3BCvRBgLxuJsOPRrZkqx0AsugJdSyPpUdwY9nlU0RAoSKqgh+VTerzecXLIIwgsGIpNxlA== +release-it@^14.12.4: + version "14.12.4" + resolved "https://registry.yarnpkg.com/release-it/-/release-it-14.12.4.tgz#0fd13de85e382323c634a0697a601437e042123a" + integrity sha512-lqf9PMsj7ycCqFHGag8Uv7cE1hNsKa+yKUMe+Fkh9fdOfxu2F01On+YUefRCP0DuQthmr/WyLCYdrjThMEkWFQ== dependencies: "@iarna/toml" "2.2.5" "@octokit/rest" "18.12.0" async-retry "1.3.3" chalk "4.1.2" cosmiconfig "7.0.1" - debug "4.3.2" - deprecated-obj "2.0.0" + debug "4.3.3" execa "5.1.1" form-data "4.0.0" git-url-parse "11.6.0" @@ -5998,7 +6009,7 @@ release-it@^14.11.8: os-name "4.0.1" parse-json "5.2.0" semver "7.3.5" - shelljs "0.8.4" + shelljs "0.8.5" update-notifier "5.1.0" url-join "4.0.1" uuid "8.3.2" @@ -6150,13 +6161,14 @@ resolve-global@^1.0.0: dependencies: global-dirs "^0.1.1" -resolve@^1.0.0, resolve@^1.1.6, resolve@^1.10.0: - version "1.20.0" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.20.0.tgz#629a013fb3f70755d6f0b7935cc1c2c5378b1975" - integrity sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A== +resolve@^1.1.6, resolve@^1.10.0: + version "1.22.0" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.0.tgz#5e0b8c67c15df57a89bdbabe603a002f21731198" + integrity sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw== dependencies: - is-core-module "^2.2.0" - path-parse "^1.0.6" + is-core-module "^2.8.1" + path-parse "^1.0.7" + supports-preserve-symlinks-flag "^1.0.0" responselike@^1.0.2: version "1.0.2" @@ -6235,16 +6247,16 @@ rxjs@^6.4.0: tslib "^1.9.0" rxjs@^7.2.0: - version "7.4.0" - resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-7.4.0.tgz#a12a44d7eebf016f5ff2441b87f28c9a51cebc68" - integrity sha512-7SQDi7xeTMCJpqViXh8gL/lebcwlp3d831F05+9B44A4B0WfsEwUQHR64gsH1kvJ+Ep/J9K2+n1hVl1CsGN23w== + version "7.5.4" + resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-7.5.4.tgz#3d6bd407e6b7ce9a123e76b1e770dc5761aa368d" + integrity sha512-h5M3Hk78r6wAheJF0a5YahB1yRQKCsZ4MsGdZ5O9ETbVtjPcScGfrMmoOq7EBsCRzd4BDkvDJ7ogP8Sz5tTFiQ== dependencies: - tslib "~2.1.0" + tslib "^2.1.0" sade@^1.7.3: - version "1.7.4" - resolved "https://registry.yarnpkg.com/sade/-/sade-1.7.4.tgz#ea681e0c65d248d2095c90578c03ca0bb1b54691" - integrity sha512-y5yauMD93rX840MwUJr7C1ysLFBgMspsdTo4UVrDg3fXDvtwOyIqykhVAAm6fk/3au77773itJStObgK+LKaiA== + version "1.8.1" + resolved "https://registry.yarnpkg.com/sade/-/sade-1.8.1.tgz#0a78e81d658d394887be57d2a409bf703a3b2701" + integrity sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A== dependencies: mri "^1.1.0" @@ -6292,12 +6304,12 @@ semver-store@^0.3.0: resolved "https://registry.yarnpkg.com/semver-store/-/semver-store-0.3.0.tgz#ce602ff07df37080ec9f4fb40b29576547befbe9" integrity sha512-TcZvGMMy9vodEFSse30lWinkj+JgOBvPn8wRItpQRSayhc+4ssDs335uklkfvQQJgL/WvmHLVj4Ycv2s7QCQMg== -"semver@2 || 3 || 4 || 5", semver@^5.4.1: +"semver@2 || 3 || 4 || 5", semver@^5.4.1, semver@^5.7.1: version "5.7.1" resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== -semver@7.3.5, semver@^7.0.0, semver@^7.2.1, semver@^7.3.2, semver@^7.3.4, semver@^7.3.5: +semver@7.3.5, semver@^7.0.0, semver@^7.3.2, semver@^7.3.4, semver@^7.3.5: version "7.3.5" resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.5.tgz#0b621c879348d8998e4b0e4be94b3f12e6018ef7" integrity sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ== @@ -6364,20 +6376,15 @@ shebang-regex@^3.0.0: resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== -shelljs@0.8.4: - version "0.8.4" - resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.8.4.tgz#de7684feeb767f8716b326078a8a00875890e3c2" - integrity sha512-7gk3UZ9kOfPLIAbslLzyWeGiEqx9e3rxwZM0KE6EL8GlGwjym9Mrlx5/p33bWTu9YG6vcS4MBxYZDHYr5lr8BQ== +shelljs@0.8.5: + version "0.8.5" + resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.8.5.tgz#de055408d8361bed66c669d2f000538ced8ee20c" + integrity sha512-TiwcRcrkhHvbrZbnRcFYMLl30Dfov3HKqzp5tO5b4pt6G/SezKcYhmDg15zXVBswHmctSAQKznqNW2LO5tTDow== dependencies: glob "^7.0.0" interpret "^1.0.0" rechoir "^0.6.2" -shellwords@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/shellwords/-/shellwords-0.1.1.tgz#d6b9181c1a48d397324c84871efbcfc73fc0654b" - integrity sha512-vFwSUfQvqybiICwZY5+DAWIPLKsWO31Q91JSKl3UYv+K5c2QRPzn0qzec6QPu1Qc9eHYItiP3NdJqNVqetYAww== - side-channel@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.4.tgz#efce5c8fdc104ee751b25c58d4290011fa5ea2cf" @@ -6388,9 +6395,9 @@ side-channel@^1.0.4: object-inspect "^1.9.0" signal-exit@^3.0.0, signal-exit@^3.0.2, signal-exit@^3.0.3: - version "3.0.6" - resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.6.tgz#24e630c4b0f03fea446a2bd299e62b4a6ca8d0af" - integrity sha512-sDl4qMFpijcGw22U5w63KmD3cZJfBuFlVNbVMKje2keoKML7X2UzWbc4XrmEbDwg0NXJc3yv4/ox7b+JWb57kQ== + version "3.0.7" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" + integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== simple-concat@^1.0.0: version "1.0.1" @@ -6398,9 +6405,9 @@ simple-concat@^1.0.0: integrity sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q== simple-get@^3.0.3, simple-get@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/simple-get/-/simple-get-3.1.0.tgz#b45be062435e50d159540b576202ceec40b9c6b3" - integrity sha512-bCR6cP+aTdScaQCnQKbPKtJOKDp/hj9EDLJo3Nw4y1QksqaovlW/bnptB6/c1e+qmNIDHRK+oXFDdEqBT8WzUA== + version "3.1.1" + resolved "https://registry.yarnpkg.com/simple-get/-/simple-get-3.1.1.tgz#cc7ba77cfbe761036fbfce3d021af25fc5584d55" + integrity sha512-CQ5LTKGfCpvE1K0n2us+kuMPbk/q0EKl82s4aheV9oXjFEz6W/Y7oQFVJuU6QG77hRT4Ghb5RURteF5vnWjupA== dependencies: decompress-response "^4.2.0" once "^1.3.1" @@ -6426,12 +6433,12 @@ sonic-boom@^1.0.2: atomic-sleep "^1.0.0" flatstr "^1.0.12" -source-map-js@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.1.tgz#a1741c131e3c77d048252adfa24e23b908670caf" - integrity sha512-4+TN2b3tqOCd/kaGRJ/sTYA0tR0mdXx26ipdolxcwtJVqEnqNYvlCAt1q3ypy4QMlYus+Zh34RNtYLoq2oQ4IA== +source-map-js@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c" + integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw== -source-map-support@^0.5.17, source-map-support@~0.5.20: +source-map-support@~0.5.20: version "0.5.21" resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f" integrity sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w== @@ -6517,9 +6524,9 @@ sprintf-js@~1.0.2: integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw= sshpk@^1.7.0: - version "1.16.1" - resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.16.1.tgz#fb661c0bef29b39db40769ee39fa70093d6f6877" - integrity sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg== + version "1.17.0" + resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.17.0.tgz#578082d92d4fe612b13007496e543fa0fbcbe4c5" + integrity sha512-/9HIEs1ZXGhSPE8X6Ccm7Nam1z8KcoCqPdI7ecm1N33EzAetWahvQWVqLZtaZQ+IDKX4IyA2o0gBzqIMkAagHQ== dependencies: asn1 "~0.2.3" assert-plus "^1.0.0" @@ -6556,9 +6563,9 @@ strict-uri-encode@^2.0.0: integrity sha1-ucczDHBChi9rFC3CdLvMWGbONUY= string-kit@^0.16.0: - version "0.16.0" - resolved "https://registry.yarnpkg.com/string-kit/-/string-kit-0.16.0.tgz#63a1d7b7afd0d2b2214b6ab0d82040b2047d0676" - integrity sha512-xiJvm0KiJrOYDFzANh/LnMXEujnveaxcmspx9rg4r5qaIvex9b77h7fa6Ba+/0kEZXMvYcOS6Y7vJzK8lAUbUg== + version "0.16.1" + resolved "https://registry.yarnpkg.com/string-kit/-/string-kit-0.16.1.tgz#984ef9b08a9fa375af1dc8f1c58eb75c8a6f3594" + integrity sha512-LEwNbaW3iUZnfDIeUghvmxUoDnU6QClll/TFKENBMfFRZH481XijeLQPvhdNGIATVIunCXxjSJvVoFSBkfG1mg== string-similarity@^4.0.1: version "4.0.4" @@ -6592,12 +6599,12 @@ string-width@^2.1.0: strip-ansi "^4.0.0" string-width@^5.0.0: - version "5.0.1" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-5.0.1.tgz#0d8158335a6cfd8eb95da9b6b262ce314a036ffd" - integrity sha512-5ohWO/M4//8lErlUUtrFy3b11GtNOuMOU0ysKCDXFcfXuuvUXu95akgj/i8ofmaGdN0hCqyl6uu9i8dS/mQp5g== + version "5.1.0" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-5.1.0.tgz#5ab00980cfb29f43e736b113a120a73a0fb569d3" + integrity sha512-7x54QnN21P+XL/v8SuNKvfgsUre6PXpN7mc77N3HlZv+f1SBRGmjxtOud2Z6FZ8DmdkD/IdjCaf9XXbnqmTZGQ== dependencies: + eastasianwidth "^0.2.0" emoji-regex "^9.2.2" - is-fullwidth-code-point "^4.0.0" strip-ansi "^7.0.1" string_decoder@^1.1.1: @@ -6693,7 +6700,7 @@ supports-color@8.1.1: dependencies: has-flag "^4.0.0" -supports-color@^5.3.0: +supports-color@^5.3.0, supports-color@^5.5.0: version "5.5.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== @@ -6712,6 +6719,11 @@ supports-color@^9.0.0: resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-9.2.1.tgz#599dc9d45acf74c6176e0d880bab1d7d718fe891" integrity sha512-Obv7ycoCTG51N7y175StI9BlAXrmgZrFhZOb0/PyjHBher/NmsdBgbbQ1Inhq+gIhz6+7Gb+jWF2Vqi7Mf1xnQ== +supports-preserve-symlinks-flag@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" + integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== + tar-fs@^2.0.0, tar-fs@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/tar-fs/-/tar-fs-2.1.1.tgz#489a15ab85f1f0befabb370b7de4f9eb5cbe8784" @@ -6750,9 +6762,9 @@ temp-write@^4.0.0: uuid "^3.3.2" terminal-kit@^2.2.3: - version "2.3.0" - resolved "https://registry.yarnpkg.com/terminal-kit/-/terminal-kit-2.3.0.tgz#ed8d7a7f1eee5efdcf994b67f712e4c2352f7387" - integrity sha512-Jyz6zm9r/h6brAv8205zhCcN+sUlMPjXqUSLPhcK4yFXWJ6maYvL8SykBWTjOg3YZ+kNU/MhNGIsWJja1rX7Ag== + version "2.4.0" + resolved "https://registry.yarnpkg.com/terminal-kit/-/terminal-kit-2.4.0.tgz#d572601ee3e25bcf1c05e223990436fce8f1a075" + integrity sha512-lQCKNFYCaVoFM23pcurnQ7wOnsz4u588JNu2sfNOnB8IU6Tl4vdOdHNe7bL2aIiB0kA7m94gS4VI0+3CRI1G/A== dependencies: "@cronvel/get-pixels" "^3.4.0" chroma-js "^2.1.2" @@ -6862,17 +6874,19 @@ to-regex-range@^5.0.1: is-number "^7.0.0" to-vfile@^7.0.0: - version "7.2.2" - resolved "https://registry.yarnpkg.com/to-vfile/-/to-vfile-7.2.2.tgz#5976568397ef664bc8df210676d082478822afbf" - integrity sha512-7WL+coet3qyaYb5vrVrfLtOUHgNv9E1D5SIsyVKmHKcgZefy77WMQRk7FByqGKNInoHOlY6xkTGymo29AwjUKg== + version "7.2.3" + resolved "https://registry.yarnpkg.com/to-vfile/-/to-vfile-7.2.3.tgz#4e54ad10878901703f1a956a33ba4f131c31eef7" + integrity sha512-QO0A9aE6Z/YkmQadJ0syxpmNXtcQiu0qAtCKYKD5cS3EfgfFTAXfgLX6AOaBrSfWSek5nfsMf3gBZ9KGVFcLuw== dependencies: is-buffer "^2.0.0" vfile "^5.1.0" -totalist@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/totalist/-/totalist-2.0.0.tgz#db6f1e19c0fa63e71339bbb8fba89653c18c7eec" - integrity sha512-+Y17F0YzxfACxTyjfhnJQEe7afPA0GSpYlFkl2VFMxYP7jshQf9gXV7cH47EfToBumFThfKBvfAcoUn6fdNeRQ== +touch@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/touch/-/touch-3.1.0.tgz#fe365f5f75ec9ed4e56825e0bb76d24ab74af83b" + integrity sha512-WBx8Uy5TLtOSRtIq+M03/sKDrXCLHxwDcquSP2c43Le03/9serjQBIztjRz6FkJez9D/hleyAXTBGLwwZUw9lA== + dependencies: + nopt "~1.0.10" tough-cookie@~2.5.0: version "2.5.0" @@ -6902,10 +6916,10 @@ trough@^2.0.0: resolved "https://registry.yarnpkg.com/trough/-/trough-2.0.2.tgz#94a3aa9d5ce379fc561f6244905b3f36b7458d96" integrity sha512-FnHq5sTMxC0sk957wHDzRnemFnNBvt/gSY99HzK8F7UP5WAbvP70yX5bd7CjEQkN+TjdxwI7g7lJ6podqrG2/w== -ts-node@^10.4.0: - version "10.4.0" - resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-10.4.0.tgz#680f88945885f4e6cf450e7f0d6223dd404895f7" - integrity sha512-g0FlPvvCXSIO1JDF6S232P5jPYqBkRL9qly81ZgAOSU7rwI0stphCgd2kLiCrU9DjQCrJMWEqcNSjQL02s6d8A== +ts-node@^10.5.0: + version "10.5.0" + resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-10.5.0.tgz#618bef5854c1fbbedf5e31465cbb224a1d524ef9" + integrity sha512-6kEJKwVxAJ35W4akuiysfKwKmjkbYxwQMTBaAxo9KKAx/Yd26mPUyhGz3ji+EsJoAgrLqVsYHNuuYwQe22lbtw== dependencies: "@cspotcode/source-map-support" "0.7.0" "@tsconfig/node10" "^1.0.7" @@ -6918,18 +6932,7 @@ ts-node@^10.4.0: create-require "^1.1.0" diff "^4.0.1" make-error "^1.1.1" - yn "3.1.1" - -ts-node@^9: - version "9.1.1" - resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-9.1.1.tgz#51a9a450a3e959401bda5f004a72d54b936d376d" - integrity sha512-hPlt7ZACERQGf03M253ytLY3dHbGNGrAq9qIHWUY9XHYl1z7wYngSr3OQ5xmui8o2AaxsONxIzjafLUiWBo1Fg== - dependencies: - arg "^4.1.0" - create-require "^1.1.0" - diff "^4.0.1" - make-error "^1.1.1" - source-map-support "^0.5.17" + v8-compile-cache-lib "^3.0.0" yn "3.1.1" tsc-prog@^2.2.1: @@ -6942,16 +6945,11 @@ tslib@^1.8.1, tslib@^1.9.0: resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== -tslib@^2, tslib@^2.3.1: +tslib@^2.1.0, tslib@^2.3.1: version "2.3.1" resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.3.1.tgz#e8a335add5ceae51aa261d32a490158ef042ef01" integrity sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw== -tslib@~2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.1.0.tgz#da60860f1c2ecaa5703ab7d39bc05b6bf988b97a" - integrity sha512-hcVC3wYEziELGGmEEXue7D75zbwIIVUMWAVbHItGPx0ziyXxrOMQx4rQEVEV45Ut/1IotuEvwqPopzIOkDMf0A== - tsutils@^3.21.0: version "3.21.0" resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.21.0.tgz#b48717d394cea6c1e096983eed58e9d61715b623" @@ -7020,15 +7018,20 @@ typedarray@^0.0.6: resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= -typescript@^4.4.3, typescript@^4.5.4: - version "4.5.4" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.5.4.tgz#a17d3a0263bf5c8723b9c52f43c5084edf13c2e8" - integrity sha512-VgYs2A2QIRuGphtzFV7aQJduJ2gyfTljngLzjpfW9FoYZF6xuw1W0vW9ghCKLfcWrCFxK81CSGRAvS1pn4fIUg== +typescript@^4.4.3, typescript@^4.5.5: + version "4.5.5" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.5.5.tgz#d8c953832d28924a9e3d37c73d729c846c5896f3" + integrity sha512-TCTIul70LyWe6IJWT8QSYeA54WQe8EjQFU4wY52Fasj5UKx88LNYKCgBEHcOMOrFF1rKGbD8v/xcNWVUq9SymA== uglify-js@^3.1.4: - version "3.14.5" - resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.14.5.tgz#cdabb7d4954231d80cb4a927654c4655e51f4859" - integrity sha512-qZukoSxOG0urUTvjc2ERMTcAy+BiFh3weWAkeurLwjrCba73poHmG3E36XEjd/JGukMzwTL7uCxZiAexj8ppvQ== + version "3.15.1" + resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.15.1.tgz#9403dc6fa5695a6172a91bc983ea39f0f7c9086d" + integrity sha512-FAGKF12fWdkpvNJZENacOH0e/83eG6JyVQyanIJaBXCN1J11TUQv1T1/z8S+Z0CG0ZPk1nPcreF/c7lrTd0TEQ== + +undefsafe@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/undefsafe/-/undefsafe-2.0.5.tgz#38733b9327bdcd226db889fb723a6efd162e6e2c" + integrity sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA== unified-args@^9.0.0: version "9.0.2" @@ -7046,15 +7049,15 @@ unified-args@^9.0.0: unified-engine "^9.0.0" unified-engine@^9.0.0: - version "9.0.4" - resolved "https://registry.yarnpkg.com/unified-engine/-/unified-engine-9.0.4.tgz#ee02b6a7f11e69a56f79cb8595065b8c3f02bda8" - integrity sha512-NFI+jC3DWZ23eBsWkOW2havz47DPG/DSyJEvBH+qA5cQHF6zlgiJYev7ksb/naOypZZ+cfhaCxCRo2BqrysYEw== + version "9.0.5" + resolved "https://registry.yarnpkg.com/unified-engine/-/unified-engine-9.0.5.tgz#7e417f2560942793ce41753ad53ee7428aaea40c" + integrity sha512-frQ6lUNlkTwVC0JELJqSSITpE7MLrLJqAWmDrUFj5Do6A4/3n6eX5Jyg8fhe4Dbwwh38spqUJd39FtRFG34QWg== dependencies: "@types/concat-stream" "^1.0.0" "@types/debug" "^4.0.0" "@types/is-empty" "^1.0.0" "@types/js-yaml" "^4.0.0" - "@types/node" "^16.0.0" + "@types/node" "^17.0.0" "@types/unist" "^2.0.0" concat-stream "^2.0.0" debug "^4.0.0" @@ -7066,7 +7069,7 @@ unified-engine@^9.0.0: is-plain-obj "^4.0.0" js-yaml "^4.0.0" load-plugin "^4.0.0" - parse-json "^5.0.0" + parse-json "^6.0.0" to-vfile "^7.0.0" trough "^2.0.0" unist-util-inspect "^7.0.0" @@ -7167,7 +7170,7 @@ universalify@^2.0.0: resolved "https://registry.yarnpkg.com/universalify/-/universalify-2.0.0.tgz#75a4984efedc4b08975c5aeb73f530d02df25717" integrity sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ== -update-notifier@5.1.0: +update-notifier@5.1.0, update-notifier@^5.1.0: version "5.1.0" resolved "https://registry.yarnpkg.com/update-notifier/-/update-notifier-5.1.0.tgz#4ab0d7c7f36a231dd7316cf7729313f0214d9ad9" integrity sha512-ItnICHbeMh9GqUy31hFPrD1kcuZ3rpxDZbf4KUDavXwS0bW5m7SLbDQpGX3UYr072cbrF5hFUs3r5tUsPwjfHw== @@ -7225,7 +7228,7 @@ util-deprecate@^1.0.1, util-deprecate@^1.0.2, util-deprecate@~1.0.1: resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= -uuid@8.3.2, uuid@^8.3.0: +uuid@8.3.2: version "8.3.2" resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg== @@ -7236,15 +7239,19 @@ uuid@^3.3.2, uuid@^3.3.3: integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A== uvu@^0.5.0: - version "0.5.2" - resolved "https://registry.yarnpkg.com/uvu/-/uvu-0.5.2.tgz#c145e7f4b5becf80099cf22fd8a4a05f0112b2c0" - integrity sha512-m2hLe7I2eROhh+tm3WE5cTo/Cv3WQA7Oc9f7JB6uWv+/zVKvfAm53bMyOoGOSZeQ7Ov2Fu9pLhFr7p07bnT20w== + version "0.5.3" + resolved "https://registry.yarnpkg.com/uvu/-/uvu-0.5.3.tgz#3d83c5bc1230f153451877bfc7f4aea2392219ae" + integrity sha512-brFwqA3FXzilmtnIyJ+CxdkInkY/i4ErvP7uV0DnUVxQcQ55reuHphorpF+tZoVHK2MniZ/VJzI7zJQoc9T9Yw== dependencies: dequal "^2.0.0" diff "^5.0.0" kleur "^4.0.3" sade "^1.7.3" - totalist "^2.0.0" + +v8-compile-cache-lib@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.0.tgz#0582bcb1c74f3a2ee46487ceecf372e46bce53e8" + integrity sha512-mpSYqfsFvASnSn5qMiwrr4VKfumbPyONLCOPmsR3A6pTY/r0+tSaVbgPWSAIuzbk3lCTa+FForeTiO+wBQGkjA== v8-compile-cache@^2.0.3: version "2.3.0" @@ -7274,9 +7281,9 @@ verror@1.10.0: extsprintf "^1.2.0" vfile-message@^3.0.0: - version "3.0.2" - resolved "https://registry.yarnpkg.com/vfile-message/-/vfile-message-3.0.2.tgz#db7eaebe7fecb853010f2ef1664427f52baf8f74" - integrity sha512-UUjZYIOg9lDRwwiBAuezLIsu9KlXntdxwG+nXnjuQAHvBpcX3x0eN8h+I7TkY5nkCXj+cWVp4ZqebtGBvok8ww== + version "3.1.0" + resolved "https://registry.yarnpkg.com/vfile-message/-/vfile-message-3.1.0.tgz#5437035aa43185ff4b9210d32fada6c640e59143" + integrity sha512-4QJbBk+DkPEhBXq3f260xSaWtjE4gPKOfulzfMFF8ZNwaPZieWsg3iVlcmF04+eebzpcpeXOOFMfrYzJHVYg+g== dependencies: "@types/unist" "^2.0.0" unist-util-stringify-position "^3.0.0" @@ -7308,9 +7315,9 @@ vfile-statistics@^2.0.0: vfile-message "^3.0.0" vfile@^5.0.0, vfile@^5.1.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/vfile/-/vfile-5.2.0.tgz#a32a646ff9251c274dbe8675644a39031025b369" - integrity sha512-ftCpb6pU8Jrzcqku8zE6N3Gi4/RkDhRwEXSWudzZzA2eEOn/cBpsfk9aulCUR+j1raRSAykYQap9u6j6rhUaCA== + version "5.3.0" + resolved "https://registry.yarnpkg.com/vfile/-/vfile-5.3.0.tgz#4990c78cb3157005590ee8c930b71cd7fa6a006e" + integrity sha512-Tj44nY/48OQvarrE4FAjUfrv7GZOYzPbl5OD65HxVKwLJKMPU7zmfV8cCgCnzKWnSfYG2f3pxu+ALqs7j22xQQ== dependencies: "@types/unist" "^2.0.0" is-buffer "^2.0.0" @@ -7354,7 +7361,7 @@ which-module@^2.0.0: resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" integrity sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho= -which@2.0.2, which@^2.0.1, which@^2.0.2: +which@2.0.2, which@^2.0.1: version "2.0.2" resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== @@ -7399,10 +7406,10 @@ wordwrap@^1.0.0: resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb" integrity sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus= -workerpool@6.1.5: - version "6.1.5" - resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-6.1.5.tgz#0f7cf076b6215fd7e1da903ff6f22ddd1886b581" - integrity sha512-XdKkCK0Zqc6w3iTxLckiuJ81tiD/o5rBE/m+nXpRCB+/Sq4DqkfXZ/x0jW02DG1tGsfUGXbTJyZDP+eu67haSw== +workerpool@6.2.0: + version "6.2.0" + resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-6.2.0.tgz#827d93c9ba23ee2019c3ffaff5c27fccea289e8b" + integrity sha512-Rsk5qQHJ9eowMH28Jwhe8HEbmdYDX4lwoMWshiCXugjtHqMD9ZbiqSDLxcsfdqsETPzVUtX5s1Z5kStiIM6l4A== wrap-ansi@^6.2.0: version "6.2.0" @@ -7558,10 +7565,10 @@ yargs@^15.0.2: y18n "^4.0.0" yargs-parser "^18.1.2" -yargs@^17.2.1, yargs@^17.3.0: - version "17.3.0" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.3.0.tgz#295c4ffd0eef148ef3e48f7a2e0f58d0e4f26b1c" - integrity sha512-GQl1pWyDoGptFPJx9b9L6kmR33TGusZvXIZUT+BOz9f7X2L94oeAskFYLEg/FkhV06zZPBYLvLZRWeYId29lew== +yargs@^17.2.1: + version "17.3.1" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.3.1.tgz#da56b28f32e2fd45aefb402ed9c26f42be4c07b9" + integrity sha512-WUANQeVgjLbNsEmGk20f+nlHgOqzRFpiGWVaBrYGYIGANIIu3lWjoyi0fNlFmJkvfhCZ6BXINe7/W2O2bV4iaA== dependencies: cliui "^7.0.2" escalade "^3.1.1" From fa8448f9349a5415dd52b8495f9692db63ee3bbf Mon Sep 17 00:00:00 2001 From: Masquerade Circus Date: Thu, 17 Feb 2022 08:01:54 -0600 Subject: [PATCH 09/19] Update --- lib/index.ts | 343 ++++++++++++++++++++++++--------------------------- 1 file changed, 159 insertions(+), 184 deletions(-) diff --git a/lib/index.ts b/lib/index.ts index 25b983f..c65d86b 100644 --- a/lib/index.ts +++ b/lib/index.ts @@ -4,11 +4,13 @@ import { Children, Current, Directive, + Directives, DomElement, IVnode, MountedValyrianApp, Plugin, Props, + ReservedProps, Valyrian, ValyrianApp, ValyrianComponent, @@ -71,6 +73,25 @@ export const trust = (htmlString: string): IVnode[] => { return [].map.call(div.childNodes, (item) => domToVnode(item)) as IVnode[]; }; +const reservedProps: ReservedProps = { + key: true, + state: true, + oncreate: true, + onupdate: true, + onremove: true, + shouldupdate: true, + "v-cleanup": true, + "v-once": true, + + // Built in directives + "v-if": true, + "v-unless": true, + "v-for": true, + "v-show": true, + "v-class": true, + "v-html": true +}; + /*** Mount ***/ const ValyrianSymbol = Symbol("Valyrian"); @@ -257,10 +278,10 @@ function onremove(vnode: IVnode) { function sharedSetAttribute(prop: string, value: any, vnode: VnodeWithDom, oldVnode?: VnodeWithDom) { // It is a reserved prop - if (v.reservedProps[prop]) { + if (reservedProps[prop]) { // If it is a directive name call the directive - if (v.directives[prop]) { - v.directives[prop](vnode.props[prop], vnode, oldVnode); + if (directives[prop]) { + directives[prop](vnode.props[prop], vnode, oldVnode); } return; } @@ -268,7 +289,7 @@ function sharedSetAttribute(prop: string, value: any, vnode: VnodeWithDom, oldVn // It is not a reserved prop so we add it to the dom if (typeof value === "function") { let valyrianApp = v.current.app as MountedValyrianApp; - if (prop in valyrianApp.eventListenerNames === false) { + if (!valyrianApp.eventListenerNames[prop]) { valyrianApp.eventListenerNames[prop] = true; valyrianApp.container.addEventListener(prop.slice(2), valyrianApp.eventListener); } @@ -302,7 +323,7 @@ export function setAttribute(name: string, value: any, vnode: VnodeWithDom, oldV sharedSetAttribute(name, value, vnode, oldVnode); } -function updateAttributes(vnode: VnodeWithDom, oldVnode?: VnodeWithDom) { +function setAttributes(vnode: VnodeWithDom, oldVnode?: VnodeWithDom) { for (let prop in vnode.props) { // We asume that we clean the props in some directive if (prop in vnode.props === false) { @@ -311,22 +332,27 @@ function updateAttributes(vnode: VnodeWithDom, oldVnode?: VnodeWithDom) { sharedSetAttribute(prop, vnode.props[prop], vnode, oldVnode); } +} - if (oldVnode) { - for (let prop in oldVnode.props) { - if (prop in vnode.props === false && typeof oldVnode.props[prop] !== "function" && prop in v.reservedProps === false) { - if (prop in oldVnode.dom && vnode.isSVG === false) { - oldVnode.dom[prop] = null; - } else { - oldVnode.dom.removeAttribute(prop); - } +function removeAttributes(vnode: VnodeWithDom, oldVnode: VnodeWithDom) { + for (let prop in oldVnode.props) { + if (prop in vnode.props === false && typeof oldVnode.props[prop] !== "function" && prop in v.reservedProps === false) { + if (prop in oldVnode.dom && vnode.isSVG === false) { + oldVnode.dom[prop] = null; + } else { + oldVnode.dom.removeAttribute(prop); } } } } -function flatTree(newVnode: IVnode): void { +// eslint-disable-next-line complexity +function patch(newVnode: VnodeWithDom, oldVnode: VnodeWithDom = emptyVnode as VnodeWithDom, valyrianApp: MountedValyrianApp) { + v.current.vnode = newVnode; + v.current.oldVnode = oldVnode; let newTree = newVnode.children; + let oldTree = oldVnode.children; + for (let i = 0; i < newTree.length; i++) { let childVnode = newTree[i]; if (childVnode instanceof Vnode) { @@ -346,163 +372,160 @@ function flatTree(newVnode: IVnode): void { } else if (Array.isArray(childVnode)) { newTree.splice(i--, 1, ...childVnode); } else { - if (i > 0 && newTree[i - 1].tag === "#text") { - newTree[i - 1].nodeValue += childVnode; - newTree.splice(i--, 1); - } else { - newTree[i] = new Vnode("#text", {}, []); - newTree[i].nodeValue = String(childVnode); - } + newTree[i] = new Vnode("#text", {}, []); + newTree[i].nodeValue = String(childVnode); } } -} -function patchKeyedTree( - newVnode: VnodeWithDom, - newTree: (VnodeWithDom & { props: Props & { key: string } })[], - oldTree: (VnodeWithDom & { props: Props & { key: string } })[], - newTreeLength: number, - oldTreeLength: number, - valyrianApp: MountedValyrianApp -) { - let oldKeyedList = oldTree.reduce((acc, vnode, i) => { - acc[vnode.props.key] = i; - return acc; - }, {} as { [key: string]: number }); - let newKeyedList = newTree.reduce((acc, vnode, i) => { - acc[vnode.props.key] = i; - return acc; - }, {} as { [key: string]: number }); + let oldTreeLength = oldTree.length; + let newTreeLength = newTree.length; - for (let i = 0; i < newTreeLength; i++) { - let childVnode = newTree[i]; - let oldChildVnode = oldTree[oldKeyedList[childVnode.props.key]]; - let shouldPatch = true; + // If new tree is empty, remove all old nodes + if (newTreeLength === 0) { + for (let i = 0; i < oldTreeLength; i++) { + onremove(oldTree[i]); + } - if (oldChildVnode) { - childVnode.dom = oldChildVnode.dom; - if ("v-once" in childVnode.props || (childVnode.props.shouldupdate && childVnode.props.shouldupdate(childVnode, oldChildVnode) === false)) { - // skip this patch - childVnode.children = oldChildVnode.children; - shouldPatch = false; - } else { - updateAttributes(childVnode, oldChildVnode); - if (valyrianApp.isMounted) { - childVnode.props.onupdate && childVnode.props.onupdate(childVnode, oldChildVnode); + newVnode.dom.textContent = ""; + return; + } + + // If the tree is keyed list and is not first render and old tree is keyed list too + if (oldTreeLength && "key" in newTree[0].props && "key" in oldTree[0].props) { + let oldKeyedList = oldTree.reduce((acc, vnode, i) => { + acc[vnode.props.key] = i; + return acc; + }, {} as { [key: string]: number }); + let newKeyedList = newTree.reduce((acc, vnode, i) => { + acc[vnode.props.key] = i; + return acc; + }, {} as { [key: string]: number }); + + for (let i = 0; i < newTreeLength; i++) { + let childVnode = newTree[i]; + let oldChildVnode = oldTree[oldKeyedList[childVnode.props.key]]; + let shouldPatch = true; + + if (oldChildVnode) { + childVnode.dom = oldChildVnode.dom; + if ("v-once" in childVnode.props || (childVnode.props.shouldupdate && childVnode.props.shouldupdate(childVnode, oldChildVnode) === false)) { + // skip this patch + childVnode.children = oldChildVnode.children; + shouldPatch = false; } else { - childVnode.props.oncreate && childVnode.props.oncreate(childVnode); + setAttributes(childVnode, oldChildVnode); + removeAttributes(childVnode, oldChildVnode); + if (valyrianApp.isMounted) { + childVnode.props.onupdate && childVnode.props.onupdate(childVnode, oldChildVnode); + } else { + childVnode.props.oncreate && childVnode.props.oncreate(childVnode); + } } + } else { + childVnode.dom = createDomElement(childVnode.tag, childVnode.isSVG); + setAttributes(childVnode); + childVnode.props.oncreate && childVnode.props.oncreate(childVnode); } - } else { - childVnode.dom = createDomElement(childVnode.tag, childVnode.isSVG); - updateAttributes(childVnode); - childVnode.props.oncreate && childVnode.props.oncreate(childVnode); - } - if (newVnode.dom.childNodes[i] === undefined) { - newVnode.dom.appendChild(childVnode.dom); - } else if (newVnode.dom.childNodes[i] !== childVnode.dom) { - oldTree[i] && newKeyedList[oldTree[i].props.key] === undefined && onremove(oldTree[i]); - newVnode.dom.replaceChild(childVnode.dom, newVnode.dom.childNodes[i]); - } + if (newVnode.dom.childNodes[i] === undefined) { + newVnode.dom.appendChild(childVnode.dom); + } else if (newVnode.dom.childNodes[i] !== childVnode.dom) { + oldTree[i] && newKeyedList[oldTree[i].props.key] === undefined && onremove(oldTree[i]); + newVnode.dom.replaceChild(childVnode.dom, newVnode.dom.childNodes[i]); + } - shouldPatch && patch(childVnode, oldChildVnode, valyrianApp); - } + shouldPatch && patch(childVnode, oldChildVnode, valyrianApp); + } - // For the rest of the children, we should remove them - for (let i = newTreeLength; i < oldTreeLength; i++) { - if (newKeyedList[oldTree[i].props.key] === undefined) { - let oldChildVnode = oldTree[i]; - onremove(oldChildVnode); - oldChildVnode.dom.parentNode && oldChildVnode.dom.parentNode.removeChild(oldChildVnode.dom); + // For the rest of the children, we should remove them + for (let i = newTreeLength; i < oldTreeLength; i++) { + if (newKeyedList[oldTree[i].props.key] === undefined) { + let oldChildVnode = oldTree[i]; + onremove(oldChildVnode); + oldChildVnode.dom.parentNode && oldChildVnode.dom.parentNode.removeChild(oldChildVnode.dom); + } } + + return; } -} -// eslint-disable-next-line complexity -function patchNormalTree( - newVnode: VnodeWithDom, - newTree: (VnodeWithDom & { props: Props & { key: string } })[], - oldTree: (VnodeWithDom & { props: Props & { key: string } })[], - newTreeLength: number, - oldTreeLength: number, - valyrianApp: MountedValyrianApp -) { // If new tree and old tree have more than one child, we should update the dom for (let i = 0; i < newTreeLength; i++) { let oldChildVnode = oldTree[i]; let newChildVnode = newTree[i]; - // Old child does not exists - if (!oldChildVnode) { + // Old child exists + if (oldChildVnode) { // New child is a text node if (newChildVnode.tag === "#text") { + // Old child is a text node + if (oldChildVnode.tag === "#text") { + newChildVnode.dom = oldChildVnode.dom; + // eslint-disable-next-line eqeqeq + if (newChildVnode.dom.nodeValue != newChildVnode.nodeValue) { + newChildVnode.dom.nodeValue = newChildVnode.nodeValue as string; + } + continue; + } + + // Old child is a normal node newChildVnode.dom = document.createTextNode(newChildVnode.nodeValue as string) as unknown as DomElement; - newVnode.dom.appendChild(newChildVnode.dom); + onremove(oldChildVnode); + newVnode.dom.replaceChild(newChildVnode.dom, oldChildVnode.dom); + continue; } // New child is a normal node + // Old child is the same type as new child + if (oldChildVnode.tag === newChildVnode.tag) { + newChildVnode.dom = oldChildVnode.dom; + // If we have a v-once directive or a shouldupdate method that returns false, we skip the update + if (newChildVnode.props["v-once"] || (newChildVnode.props.shouldupdate && newChildVnode.props.shouldupdate(newChildVnode, oldChildVnode) === false)) { + newChildVnode.children = oldChildVnode.children; + continue; + } + + // We update the dom element + setAttributes(newChildVnode, oldChildVnode); + removeAttributes(newChildVnode, oldChildVnode); + if (valyrianApp.isMounted) { + newChildVnode.props.onupdate && newChildVnode.props.onupdate(newChildVnode, oldChildVnode); + } else { + newChildVnode.props.oncreate && newChildVnode.props.oncreate(newChildVnode); + } + patch(newChildVnode, oldChildVnode, valyrianApp); + + continue; + } + + // Old child is of a different type than new child newChildVnode.dom = createDomElement(newChildVnode.tag, newChildVnode.isSVG); - updateAttributes(newChildVnode); - newVnode.dom.appendChild(newChildVnode.dom); + setAttributes(newChildVnode); + if (oldChildVnode.tag !== "#text") { + onremove(oldChildVnode); + } newChildVnode.props.oncreate && newChildVnode.props.oncreate(newChildVnode); + newVnode.dom.replaceChild(newChildVnode.dom, oldChildVnode.dom); patch(newChildVnode, undefined, valyrianApp); continue; } - // Old child exists + // Old child does not exists // New child is a text node if (newChildVnode.tag === "#text") { - // Old child is a text node - if (oldChildVnode.tag === "#text") { - newChildVnode.dom = oldChildVnode.dom; - // eslint-disable-next-line eqeqeq - if (newChildVnode.dom.nodeValue != newChildVnode.nodeValue) { - newChildVnode.dom.nodeValue = newChildVnode.nodeValue as string; - } - continue; - } - - // Old child is a normal node newChildVnode.dom = document.createTextNode(newChildVnode.nodeValue as string) as unknown as DomElement; - onremove(oldChildVnode); - newVnode.dom.replaceChild(newChildVnode.dom, oldChildVnode.dom); - + newVnode.dom.appendChild(newChildVnode.dom); continue; } // New child is a normal node - // Old child is the same type as new child - if (oldChildVnode.tag === newChildVnode.tag) { - newChildVnode.dom = oldChildVnode.dom; - // If we have a v-once directive or a shouldupdate method that returns false, we skip the update - if (newChildVnode.props["v-once"] || (newChildVnode.props.shouldupdate && newChildVnode.props.shouldupdate(newChildVnode, oldChildVnode) === false)) { - newChildVnode.children = oldChildVnode.children; - continue; - } - - // We update the dom element - updateAttributes(newChildVnode, oldChildVnode); - if (valyrianApp && valyrianApp.isMounted) { - newChildVnode.props.onupdate && newChildVnode.props.onupdate(newChildVnode, oldChildVnode); - } else { - newChildVnode.props.oncreate && newChildVnode.props.oncreate(newChildVnode); - } - patch(newChildVnode, oldChildVnode, valyrianApp); - - continue; - } - - // Old child is of a different type than new child newChildVnode.dom = createDomElement(newChildVnode.tag, newChildVnode.isSVG); - updateAttributes(newChildVnode); - if (oldChildVnode.tag !== "#text") { - onremove(oldChildVnode); - } + setAttributes(newChildVnode); + newVnode.dom.appendChild(newChildVnode.dom); newChildVnode.props.oncreate && newChildVnode.props.oncreate(newChildVnode); - newVnode.dom.replaceChild(newChildVnode.dom, oldChildVnode.dom); patch(newChildVnode, undefined, valyrianApp); + } // For the rest of the children, we should remove them @@ -515,37 +538,6 @@ function patchNormalTree( } } -// eslint-disable-next-line complexity -function patch(newVnode: VnodeWithDom, oldVnode: VnodeWithDom = emptyVnode as VnodeWithDom, valyrianApp: MountedValyrianApp) { - v.current.vnode = newVnode; - v.current.oldVnode = oldVnode; - - flatTree(newVnode); - - let newTree = newVnode.children; - let oldTree = oldVnode.children; - let oldTreeLength = oldTree.length; - let newTreeLength = newTree.length; - - // If new tree is empty, remove all old nodes - if (newTreeLength === 0) { - for (let i = 0; i < oldTreeLength; i++) { - onremove(oldTree[i]); - } - - newVnode.dom.textContent = ""; - return; - } - - // If the tree is keyed list and is not first render and old tree is keyed list too - if (oldTreeLength && "key" in newTree[0].props && "key" in oldTree[0].props) { - patchKeyedTree(newVnode, newTree, oldTree, newTreeLength, oldTreeLength, valyrianApp); - return; - } - - patchNormalTree(newVnode, newTree, oldTree, newTreeLength, oldTreeLength, valyrianApp); -} - /*** Directives ***/ export function directive(name: string, directive: Directive) { @@ -571,7 +563,7 @@ function hideDirective(test: boolean): Directive { }; } -const builtInDirectives = { +const directives: Directives = { "v-if": hideDirective(false), "v-unless": hideDirective(true), "v-for": (set: unknown[], vnode: VnodeWithDom) => { @@ -647,15 +639,15 @@ const builtInDirectives = { model[property].push(val); } }; - vnode.children.forEach((child) => { - if (child.name === "option") { + vnode.children.forEach((child: IVnode) => { + if (child.tag === "option") { let value = "value" in child.props ? child.props.value : child.children.join("").trim(); child.props.selected = model[property].indexOf(value) !== -1; } }); } else { - vnode.children.forEach((child) => { - if (child.name === "option") { + vnode.children.forEach((child: IVnode) => { + if (child.tag === "option") { let value = "value" in child.props ? child.props.value : child.children.join("").trim(); child.props.selected = value === model[property]; } @@ -708,26 +700,9 @@ v.fragment = (props: Props, ...children: Children): Children => { // This is intended to make the properties and methods available for plugins v.current = {} as Current; -v.directives = { ...builtInDirectives }; +v.directives = directives; -v.reservedProps = { - key: true, - state: true, - oncreate: true, - onupdate: true, - onremove: true, - shouldupdate: true, - "v-cleanup": true, - "v-once": true, - - // Built in directives - "v-if": true, - "v-unless": true, - "v-for": true, - "v-show": true, - "v-class": true, - "v-html": true -}; +v.reservedProps = reservedProps; v.isVnode = isVnode; v.isComponent = isComponent; From 8ee2c0b01c5ff0e70587dc197617db13018d6b4b Mon Sep 17 00:00:00 2001 From: Masquerade Circus Date: Thu, 17 Feb 2022 15:40:23 -0600 Subject: [PATCH 10/19] Updated --- bench/.buffalo-test.json | 1000 +++++++++++++++++++++++++++++++++ bench/mount_n_update_bench.js | 70 +++ dist/@types/lib/index.d.ts | 2 +- dist/index.cjs | 317 +++++------ dist/index.js | 317 +++++------ dist/index.min.js | 2 +- dist/index.min.js.map | 2 +- lib/index.ts | 138 +++-- plugins/utils/tree-adapter.js | 16 +- 9 files changed, 1448 insertions(+), 416 deletions(-) diff --git a/bench/.buffalo-test.json b/bench/.buffalo-test.json index 2941bf0..6f24d53 100644 --- a/bench/.buffalo-test.json +++ b/bench/.buffalo-test.json @@ -1,4 +1,1004 @@ [ + { + "tag": "fa8448f9349a5415dd52b8495f9692db63ee3bbf", + "timestamp": "2022-02-17T21:36:15.314Z", + "suites": { + "Matching keyed list": { + "Removed at the end": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "Matching keyed list -> stress": { + "Removed at the end": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "hyperscript": { + "Valyrian 5.0.8": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "Valyrian next": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "Set.has vs [].indexOf": { + "Set.has": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "[].indexOf": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "Object.keys for loop vs Object.keys for of vs for in": { + "Object.keys for loop": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "Object.keys for of": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "for in": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "typeof function vs startsWith vs charAt vs string[0]": { + "typeof function": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "startsWith": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "charAt": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "string[0]": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "Array.isArray vs typeof object & Array.isArray": { + "Array.isArray": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "typeof object & Array.isArray": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "string comparison vs instance comparison vs property comparison": { + "string comparison": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "instance comparison": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "property comparison": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "property string comparison": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "typeof comparison": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "Object with property equals true vs set vs map vs string array": { + "Object with property equals true": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "key in object": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "set": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "map": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "string array": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "For loop if/continue vs if/else": { + "for loop if/continue": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "for loop if/else": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "map array of strings vs reduce with object keys equals index": { + "map array of strings": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "reduce with object keys equals index": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "array by for": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "object by for": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "object map by for": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "Symbol access vs direct access": { + "Direct access access": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "Symbol access access": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "Mount and update: Mount multiple types": { + "Valyrian 5.0.8": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "Valyrian next": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "Mount and update: Mount single text": { + "Valyrian 5.0.8": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "Valyrian next": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "Mount and update: Mount single text in div": { + "Valyrian 5.0.8": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "Valyrian next": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "Mount and update: Update multiple types": { + "Valyrian 5.0.8": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "Valyrian next": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "Mount and update: Update single text": { + "Valyrian 5.0.8": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "Valyrian next": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "Mount and update: Render list": { + "vOld": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "VNext": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "Mount and update: Render keyed list": { + "vOld": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "VNext": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "Mount and update: Render keyed list -> stress": { + "vOld": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "VNext": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "Mount and update: Render keyed list -> swap keys on large set": { + "vOld": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "VNext": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "Mount and update: Update class": { + "vOld update": { + "hz": 343839.9611446381, + "meanTime": 0.002908329784214188, + "medianTime": 0.0027740001678466797, + "standardDeviation": 0.003164911735255947, + "maxTime": 1.486952000297606, + "minTime": 0.0026079993695020676 + }, + "VNext update": { + "hz": 15151981.639382496, + "meanTime": 0.00006599796804141019, + "medianTime": 0.00006200000643730164, + "standardDeviation": 0.0003279280705585636, + "maxTime": 0.3116029994562268, + "minTime": 0.000045999884605407715 + } + }, + "Lifecycle vs hooks": { + "Hooks": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "Lifecycle": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + } + } + }, + { + "tag": null, + "timestamp": "2022-02-17T15:26:02.135Z", + "suites": { + "Matching keyed list": { + "Removed at the end": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "Matching keyed list -> stress": { + "Removed at the end": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "hyperscript": { + "Valyrian 5.0.8": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "Valyrian next": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "Set.has vs [].indexOf": { + "Set.has": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "[].indexOf": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "Object.keys for loop vs Object.keys for of vs for in": { + "Object.keys for loop": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "Object.keys for of": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "for in": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "typeof function vs startsWith vs charAt vs string[0]": { + "typeof function": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "startsWith": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "charAt": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "string[0]": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "Array.isArray vs typeof object & Array.isArray": { + "Array.isArray": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "typeof object & Array.isArray": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "string comparison vs instance comparison vs property comparison": { + "string comparison": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "instance comparison": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "property comparison": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "property string comparison": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "typeof comparison": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "Object with property equals true vs set vs map vs string array": { + "Object with property equals true": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "key in object": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "set": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "map": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "string array": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "For loop if/continue vs if/else": { + "for loop if/continue": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "for loop if/else": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "map array of strings vs reduce with object keys equals index": { + "map array of strings": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "reduce with object keys equals index": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "array by for": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "object by for": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "object map by for": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "Symbol access vs direct access": { + "Direct access access": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "Symbol access access": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "Mount and update: Mount multiple types": { + "Valyrian 5.0.8": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "Valyrian next": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "Mount and update: Mount single text": { + "Valyrian 5.0.8": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "Valyrian next": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "Mount and update: Mount single text in div": { + "Valyrian 5.0.8": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "Valyrian next": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "Mount and update: Update multiple types": { + "Valyrian 5.0.8": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "Valyrian next": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "Mount and update: Update single text": { + "Valyrian 5.0.8": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "Valyrian next": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "Mount and update: Render list": { + "vOld": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "VNext": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "Mount and update: Render keyed list": { + "vOld": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "VNext": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "Mount and update: Render keyed list -> stress": { + "vOld": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "VNext": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "Mount and update: Render keyed list -> swap keys on large set": { + "vOld": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "VNext": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "Mount and update: Update class": { + "vOld update": { + "hz": 336267.528779135, + "meanTime": 0.002973822669202215, + "medianTime": 0.0028290003538131714, + "standardDeviation": 0.0035730363859830215, + "maxTime": 1.5123089998960495, + "minTime": 0.0026619993150234222 + }, + "VNext update": { + "hz": 1300819.330335408, + "meanTime": 0.0007687462637429875, + "medianTime": 0.0006870003417134285, + "standardDeviation": 0.0037972006213699955, + "maxTime": 1.9422189993783832, + "minTime": 0.0006299996748566628 + } + }, + "Lifecycle vs hooks": { + "Hooks": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "Lifecycle": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + } + } + }, { "tag": "342faa488ecfc4dbe4b76e77863c8f675e754329", "timestamp": "2022-02-17T11:07:35.317Z", diff --git a/bench/mount_n_update_bench.js b/bench/mount_n_update_bench.js index ea48204..1995024 100644 --- a/bench/mount_n_update_bench.js +++ b/bench/mount_n_update_bench.js @@ -11,6 +11,7 @@ use(plugin); const useEffect = plugin.useEffect; console.log(vOld); +console.log(v); let VNext = v; @@ -688,6 +689,75 @@ compare("Mount and update: Render keyed list -> swap keys on large set", () => { }); }); +compare("Mount and update: Update class", () => { + // Init with 1000 words + let words = [...Array(1000).keys()].map((key) => `word ${key}`); + let useData = false; + let updateClass = false; + let updateClass2 = false; + let Component = () => + vOld( + "div", + {}, + useData + ? words.map((word) => + vOld( + "span", + { class: updateClass === word ? "selected" : false, onbeforeupdate: (vnode, oldVnode) => vnode.props.class !== oldVnode.props.class }, + word + ) + ) + : vOld( + "div", + { class: updateClass === "test" ? "test" : false, onbeforeupdate: (vnode, oldVnode) => vnode.props.class !== oldVnode.props.class }, + "test" + ) + ); + let Component2 = () => ( +
+ {useData ? ( + words.map((word) => ( + vnode.props.class !== oldVnode.props.class}> + {word} + + )) + ) : ( +
vnode.props.class !== oldVnode.props.class}> + test +
+ )} +
+ ); + + before(() => { + let before = vOld.mount("body", Component); + expect(before).toEqual("
test
"); + let before2 = mount("body", Component2); + expect(before2).toEqual("
test
"); + + updateClass = "test"; + updateClass2 = "test"; + + let after = vOld.update(); + expect(after).toEqual('
test
'); + let after2 = update(Component2); + expect(after2).toEqual('
test
'); + useData = true; + updateClass = false; + updateClass2 = false; + }); + + benchmark("vOld update", () => { + vOld.update(); + updateClass = updateClass === "word 10" ? "word 100" : "word 10"; + }); + + benchmark("VNext update", () => { + update(Component2); + updateClass2 = updateClass2 === "word 10" ? "word 100" : "word 10"; + }); +}); + compare("Lifecycle vs hooks", () => { let lifecycleCount = 0; let plusLifeCycle = () => (lifecycleCount += 1); diff --git a/dist/@types/lib/index.d.ts b/dist/@types/lib/index.d.ts index 1a121c3..651d188 100644 --- a/dist/@types/lib/index.d.ts +++ b/dist/@types/lib/index.d.ts @@ -1,9 +1,9 @@ import { Directive, DomElement, IVnode, Plugin, Valyrian, ValyrianComponent, VnodeComponent, VnodeWithDom } from "./interfaces"; +export declare const isNodeJs: boolean; export declare const Vnode: IVnode; export declare function isVnode(object?: unknown | IVnode): object is IVnode; export declare function isComponent(component?: unknown | ValyrianComponent): component is ValyrianComponent; export declare function isVnodeComponent(vnode?: unknown | VnodeComponent): vnode is VnodeComponent; -export declare const isNodeJs: boolean; export declare const trust: (htmlString: string) => IVnode[]; export declare function onCleanup(callback: Function): void; export declare function onUnmount(callback: Function): void; diff --git a/dist/index.cjs b/dist/index.cjs index 0ce4e6a..3dec4ea 100644 --- a/dist/index.cjs +++ b/dist/index.cjs @@ -42,6 +42,11 @@ __export(lib_exports, { use: () => use, v: () => v }); +var ComponentString = "__component__"; +var TextString = "#text"; +var isNodeJs = Boolean(typeof process !== "undefined" && process.versions && process.versions.node); +var ValyrianSymbol = Symbol("Valyrian"); +var Und = void 0; var Vnode = function Vnode2(tag, props, children) { this.props = props; this.children = children; @@ -54,9 +59,8 @@ function isComponent(component) { return typeof component === "function" || typeof component === "object" && component !== null && "view" in component; } function isVnodeComponent(vnode) { - return vnode instanceof Vnode && vnode.tag === "__component__"; + return vnode instanceof Vnode && vnode.tag === ComponentString; } -var isNodeJs = Boolean(typeof process !== "undefined" && process.versions && process.versions.node); function createDomElement(tag, isSVG = false) { return isSVG ? document.createElementNS("http://www.w3.org/2000/svg", tag) : document.createElement(tag); } @@ -65,7 +69,7 @@ function domToVnode(dom) { if (child.nodeType === 1) { return domToVnode(child); } - let text = new Vnode("#text", {}, []); + let text = new Vnode(TextString, {}, []); text.nodeValue = String(child.nodeValue); text.dom = child; return text; @@ -79,25 +83,40 @@ var trust = (htmlString) => { div.innerHTML = htmlString.trim(); return [].map.call(div.childNodes, (item) => domToVnode(item)); }; -var ValyrianSymbol = Symbol("Valyrian"); +var reservedProps = { + key: true, + state: true, + oncreate: true, + onupdate: true, + onremove: true, + shouldupdate: true, + "v-once": true, + "v-if": true, + "v-unless": true, + "v-for": true, + "v-show": true, + "v-class": true, + "v-html": true +}; +var current = {}; function onCleanup(callback) { - if (v.current.app?.onCleanup.indexOf(callback) === -1) { - v.current.app?.onCleanup.push(callback); + if (current.app?.onCleanup.indexOf(callback) === -1) { + current.app?.onCleanup.push(callback); } } function onUnmount(callback) { - if (v.current.app?.onUnmount.indexOf(callback) === -1) { - v.current.app?.onUnmount.push(callback); + if (current.app?.onUnmount.indexOf(callback) === -1) { + current.app?.onUnmount.push(callback); } } function onMount(callback) { - if (v.current.app?.onMount.indexOf(callback) === -1) { - v.current.app?.onMount.push(callback); + if (current.app?.onMount.indexOf(callback) === -1) { + current.app?.onMount.push(callback); } } function onUpdate(callback) { - if (v.current.app?.onUpdate.indexOf(callback) === -1) { - v.current.app?.onUpdate.push(callback); + if (current.app?.onUpdate.indexOf(callback) === -1) { + current.app?.onUpdate.push(callback); } } function mount(container, component) { @@ -148,7 +167,6 @@ function mount(container, component) { component[ValyrianSymbol].component = vnodeComponent; component[ValyrianSymbol].container = appContainer; component[ValyrianSymbol].mainVnode = domToVnode(appContainer); - component[ValyrianSymbol].mainVnode.isSVG = component[ValyrianSymbol].tag === "svg"; return update(component); } function callCleanup(valyrianApp) { @@ -178,12 +196,11 @@ function callUpdate(valyrianApp) { function update(component) { if (component && component[ValyrianSymbol]) { let valyrianApp = component[ValyrianSymbol]; - v.current.app = valyrianApp; + current.app = valyrianApp; valyrianApp.onCleanup.length && callCleanup(valyrianApp); let oldVnode = valyrianApp.mainVnode; valyrianApp.mainVnode = new Vnode(valyrianApp.mainVnode.tag, valyrianApp.mainVnode.props, [valyrianApp.component]); valyrianApp.mainVnode.dom = oldVnode.dom; - valyrianApp.mainVnode.isSVG = oldVnode.isSVG; patch(valyrianApp.mainVnode, oldVnode, valyrianApp); oldVnode = null; if (valyrianApp.isMounted === false) { @@ -221,19 +238,19 @@ function unmount(component) { var emptyVnode = new Vnode("__empty__", {}, []); function onremove(vnode) { for (let i = 0; i < vnode.children.length; i++) { - vnode.children[i].tag !== "#text" && onremove(vnode.children[i]); + vnode.children[i].tag !== TextString && onremove(vnode.children[i]); } vnode.props.onremove && vnode.props.onremove(vnode); } function sharedSetAttribute(prop, value, vnode, oldVnode) { - if (v.reservedProps[prop]) { - if (v.directives[prop]) { - v.directives[prop](vnode.props[prop], vnode, oldVnode); + if (reservedProps[prop]) { + if (directives[prop]) { + return directives[prop](vnode.props[prop], vnode, oldVnode); } return; } if (typeof value === "function") { - let valyrianApp = v.current.app; + let valyrianApp = current.app; if (prop in valyrianApp.eventListenerNames === false) { valyrianApp.eventListenerNames[prop] = true; valyrianApp.container.addEventListener(prop.slice(2), valyrianApp.eventListener); @@ -256,21 +273,18 @@ function sharedSetAttribute(prop, value, vnode, oldVnode) { } } function setAttribute(name, value, vnode, oldVnode) { - if (name in vnode.props === false) { - vnode.props[name] = value; - } + vnode.props[name] = value; sharedSetAttribute(name, value, vnode, oldVnode); } -function updateAttributes(vnode, oldVnode) { +function setAttributes(vnode, oldVnode) { for (let prop in vnode.props) { - if (prop in vnode.props === false) { + if (sharedSetAttribute(prop, vnode.props[prop], vnode, oldVnode) === false) { return; } - sharedSetAttribute(prop, vnode.props[prop], vnode, oldVnode); } if (oldVnode) { for (let prop in oldVnode.props) { - if (prop in vnode.props === false && typeof oldVnode.props[prop] !== "function" && prop in v.reservedProps === false) { + if (prop in vnode.props === false && typeof oldVnode.props[prop] !== "function" && prop in reservedProps === false) { if (prop in oldVnode.dom && vnode.isSVG === false) { oldVnode.dom[prop] = null; } else { @@ -280,170 +294,151 @@ function updateAttributes(vnode, oldVnode) { } } } -function flatTree(newVnode) { +function patch(newVnode, oldVnode = emptyVnode, valyrianApp) { + current.vnode = newVnode; + current.oldVnode = oldVnode === emptyVnode ? Und : oldVnode; let newTree = newVnode.children; + let oldTree = oldVnode.children; for (let i = 0; i < newTree.length; i++) { let childVnode = newTree[i]; if (childVnode instanceof Vnode) { - if (childVnode.tag !== "#text") { - if (childVnode.tag === "__component__") { + if (childVnode.tag !== TextString) { + if (childVnode.tag === ComponentString) { let component = childVnode.component; - v.current.component = component; + current.component = component; let result = ("view" in component ? component.view : component).call(component, childVnode.props, ...childVnode.children); newTree.splice(i--, 1, result); continue; } childVnode.isSVG = newVnode.isSVG || childVnode.tag === "svg"; } - } else if (childVnode === null || childVnode === void 0) { - newTree.splice(i--, 1); } else if (Array.isArray(childVnode)) { newTree.splice(i--, 1, ...childVnode); + } else if (childVnode === null || childVnode === Und) { + newTree.splice(i--, 1); } else { - if (i > 0 && newTree[i - 1].tag === "#text") { - newTree[i - 1].nodeValue += childVnode; - newTree.splice(i--, 1); - } else { - newTree[i] = new Vnode("#text", {}, []); - newTree[i].nodeValue = String(childVnode); - } + newTree[i] = new Vnode(TextString, {}, []); + newTree[i].nodeValue = childVnode; } } -} -function patchKeyedTree(newVnode, newTree, oldTree, newTreeLength, oldTreeLength, valyrianApp) { - let oldKeyedList = oldTree.reduce((acc, vnode, i) => { - acc[vnode.props.key] = i; - return acc; - }, {}); - let newKeyedList = newTree.reduce((acc, vnode, i) => { - acc[vnode.props.key] = i; - return acc; - }, {}); - for (let i = 0; i < newTreeLength; i++) { - let childVnode = newTree[i]; - let oldChildVnode = oldTree[oldKeyedList[childVnode.props.key]]; - let shouldPatch = true; - if (oldChildVnode) { - childVnode.dom = oldChildVnode.dom; - if ("v-once" in childVnode.props || childVnode.props.shouldupdate && childVnode.props.shouldupdate(childVnode, oldChildVnode) === false) { - childVnode.children = oldChildVnode.children; - shouldPatch = false; - } else { - updateAttributes(childVnode, oldChildVnode); - if (valyrianApp.isMounted) { - childVnode.props.onupdate && childVnode.props.onupdate(childVnode, oldChildVnode); + let oldTreeLength = oldTree.length; + let newTreeLength = newTree.length; + if (newTreeLength === 0) { + for (let i = 0; i < oldTreeLength; i++) { + onremove(oldTree[i]); + } + newVnode.dom.textContent = ""; + return; + } + if (oldTreeLength && "key" in newTree[0].props && "key" in oldTree[0].props) { + let oldKeyedList = oldTree.reduce((acc, vnode, i) => { + acc[vnode.props.key] = i; + return acc; + }, {}); + let newKeyedList = newTree.reduce((acc, vnode, i) => { + acc[vnode.props.key] = i; + return acc; + }, {}); + for (let i = 0; i < newTreeLength; i++) { + let childVnode = newTree[i]; + let oldChildVnode = oldTree[oldKeyedList[childVnode.props.key]]; + let shouldPatch = true; + if (oldChildVnode) { + childVnode.dom = oldChildVnode.dom; + if ("v-once" in childVnode.props || childVnode.props.shouldupdate && childVnode.props.shouldupdate(childVnode, oldChildVnode) === false) { + childVnode.children = oldChildVnode.children; + shouldPatch = false; } else { - childVnode.props.oncreate && childVnode.props.oncreate(childVnode); + setAttributes(childVnode, oldChildVnode); + if (valyrianApp.isMounted) { + childVnode.props.onupdate && childVnode.props.onupdate(childVnode, oldChildVnode); + } else { + childVnode.props.oncreate && childVnode.props.oncreate(childVnode); + } } + } else { + childVnode.dom = createDomElement(childVnode.tag, childVnode.isSVG); + setAttributes(childVnode); + childVnode.props.oncreate && childVnode.props.oncreate(childVnode); } - } else { - childVnode.dom = createDomElement(childVnode.tag, childVnode.isSVG); - updateAttributes(childVnode); - childVnode.props.oncreate && childVnode.props.oncreate(childVnode); - } - if (newVnode.dom.childNodes[i] === void 0) { - newVnode.dom.appendChild(childVnode.dom); - } else if (newVnode.dom.childNodes[i] !== childVnode.dom) { - oldTree[i] && newKeyedList[oldTree[i].props.key] === void 0 && onremove(oldTree[i]); - newVnode.dom.replaceChild(childVnode.dom, newVnode.dom.childNodes[i]); + if (newVnode.dom.childNodes[i] === Und) { + newVnode.dom.appendChild(childVnode.dom); + } else if (newVnode.dom.childNodes[i] !== childVnode.dom) { + oldTree[i] && newKeyedList[oldTree[i].props.key] === Und && onremove(oldTree[i]); + newVnode.dom.replaceChild(childVnode.dom, newVnode.dom.childNodes[i]); + } + shouldPatch && patch(childVnode, oldChildVnode, valyrianApp); } - shouldPatch && patch(childVnode, oldChildVnode, valyrianApp); - } - for (let i = newTreeLength; i < oldTreeLength; i++) { - if (newKeyedList[oldTree[i].props.key] === void 0) { - let oldChildVnode = oldTree[i]; - onremove(oldChildVnode); - oldChildVnode.dom.parentNode && oldChildVnode.dom.parentNode.removeChild(oldChildVnode.dom); + for (let i = newTreeLength; i < oldTreeLength; i++) { + if (newKeyedList[oldTree[i].props.key] === Und) { + let oldChildVnode = oldTree[i]; + onremove(oldChildVnode); + oldChildVnode.dom.parentNode && oldChildVnode.dom.parentNode.removeChild(oldChildVnode.dom); + } } + return; } -} -function patchNormalTree(newVnode, newTree, oldTree, newTreeLength, oldTreeLength, valyrianApp) { for (let i = 0; i < newTreeLength; i++) { - let oldChildVnode = oldTree[i]; let newChildVnode = newTree[i]; - if (!oldChildVnode) { - if (newChildVnode.tag === "#text") { + if (i < oldTreeLength) { + let oldChildVnode = oldTree[i]; + if (newChildVnode.tag === TextString) { + if (oldChildVnode.tag === TextString) { + newChildVnode.dom = oldChildVnode.dom; + if (newChildVnode.dom.nodeValue != newChildVnode.nodeValue) { + newChildVnode.dom.nodeValue = newChildVnode.nodeValue; + } + continue; + } newChildVnode.dom = document.createTextNode(newChildVnode.nodeValue); - newVnode.dom.appendChild(newChildVnode.dom); + onremove(oldChildVnode); + newVnode.dom.replaceChild(newChildVnode.dom, oldChildVnode.dom); continue; } - newChildVnode.dom = createDomElement(newChildVnode.tag, newChildVnode.isSVG); - updateAttributes(newChildVnode); - newVnode.dom.appendChild(newChildVnode.dom); - newChildVnode.props.oncreate && newChildVnode.props.oncreate(newChildVnode); - patch(newChildVnode, void 0, valyrianApp); - continue; - } - if (newChildVnode.tag === "#text") { - if (oldChildVnode.tag === "#text") { + if (oldChildVnode.tag === newChildVnode.tag) { newChildVnode.dom = oldChildVnode.dom; - if (newChildVnode.dom.nodeValue != newChildVnode.nodeValue) { - newChildVnode.dom.nodeValue = newChildVnode.nodeValue; + if (newChildVnode.props["v-once"] || newChildVnode.props.shouldupdate && newChildVnode.props.shouldupdate(newChildVnode, oldChildVnode) === false) { + newChildVnode.children = oldChildVnode.children; + continue; } + setAttributes(newChildVnode, oldChildVnode); + if (valyrianApp.isMounted) { + newChildVnode.props.onupdate && newChildVnode.props.onupdate(newChildVnode, oldChildVnode); + } else { + newChildVnode.props.oncreate && newChildVnode.props.oncreate(newChildVnode); + } + patch(newChildVnode, oldChildVnode, valyrianApp); continue; } - newChildVnode.dom = document.createTextNode(newChildVnode.nodeValue); - onremove(oldChildVnode); + newChildVnode.dom = createDomElement(newChildVnode.tag, newChildVnode.isSVG); + setAttributes(newChildVnode); + oldChildVnode.tag !== TextString && onremove(oldChildVnode); + newChildVnode.props.oncreate && newChildVnode.props.oncreate(newChildVnode); newVnode.dom.replaceChild(newChildVnode.dom, oldChildVnode.dom); + patch(newChildVnode, emptyVnode, valyrianApp); continue; } - if (oldChildVnode.tag === newChildVnode.tag) { - newChildVnode.dom = oldChildVnode.dom; - if (newChildVnode.props["v-once"] || newChildVnode.props.shouldupdate && newChildVnode.props.shouldupdate(newChildVnode, oldChildVnode) === false) { - newChildVnode.children = oldChildVnode.children; - continue; - } - updateAttributes(newChildVnode, oldChildVnode); - if (valyrianApp && valyrianApp.isMounted) { - newChildVnode.props.onupdate && newChildVnode.props.onupdate(newChildVnode, oldChildVnode); - } else { - newChildVnode.props.oncreate && newChildVnode.props.oncreate(newChildVnode); - } - patch(newChildVnode, oldChildVnode, valyrianApp); + if (newChildVnode.tag === TextString) { + newChildVnode.dom = document.createTextNode(newChildVnode.nodeValue); + newVnode.dom.appendChild(newChildVnode.dom); continue; } newChildVnode.dom = createDomElement(newChildVnode.tag, newChildVnode.isSVG); - updateAttributes(newChildVnode); - if (oldChildVnode.tag !== "#text") { - onremove(oldChildVnode); - } + setAttributes(newChildVnode); + newVnode.dom.appendChild(newChildVnode.dom); newChildVnode.props.oncreate && newChildVnode.props.oncreate(newChildVnode); - newVnode.dom.replaceChild(newChildVnode.dom, oldChildVnode.dom); - patch(newChildVnode, void 0, valyrianApp); + patch(newChildVnode, emptyVnode, valyrianApp); } for (let i = newTreeLength; i < oldTreeLength; i++) { let oldChildVnode = oldTree[i]; - if (oldChildVnode.tag !== "#text") { - onremove(oldChildVnode); - } + oldChildVnode.tag !== TextString && onremove(oldChildVnode); oldChildVnode.dom.parentNode && oldChildVnode.dom.parentNode.removeChild(oldChildVnode.dom); } } -function patch(newVnode, oldVnode = emptyVnode, valyrianApp) { - v.current.vnode = newVnode; - v.current.oldVnode = oldVnode; - flatTree(newVnode); - let newTree = newVnode.children; - let oldTree = oldVnode.children; - let oldTreeLength = oldTree.length; - let newTreeLength = newTree.length; - if (newTreeLength === 0) { - for (let i = 0; i < oldTreeLength; i++) { - onremove(oldTree[i]); - } - newVnode.dom.textContent = ""; - return; - } - if (oldTreeLength && "key" in newTree[0].props && "key" in oldTree[0].props) { - patchKeyedTree(newVnode, newTree, oldTree, newTreeLength, oldTreeLength, valyrianApp); - return; - } - patchNormalTree(newVnode, newTree, oldTree, newTreeLength, oldTreeLength, valyrianApp); -} function directive(name, directive2) { let fullName = `v-${name}`; - v.directives[fullName] = directive2; - v.reservedProps[fullName] = true; + directives[fullName] = directive2; + reservedProps[fullName] = true; } function hideDirective(test) { return (bool, vnode, oldVnode) => { @@ -451,17 +446,18 @@ function hideDirective(test) { if (value) { let newdom = document.createTextNode(""); if (oldVnode && oldVnode.dom && oldVnode.dom.parentNode) { - oldVnode.tag !== "#text" && onremove(oldVnode); + oldVnode.tag !== TextString && onremove(oldVnode); oldVnode.dom.parentNode.replaceChild(newdom, oldVnode.dom); } - vnode.tag = "#text"; + vnode.tag = TextString; vnode.children = []; vnode.props = {}; vnode.dom = newdom; + return false; } }; } -var builtInDirectives = { +var directives = { "v-if": hideDirective(false), "v-unless": hideDirective(true), "v-for": (set, vnode) => { @@ -538,14 +534,14 @@ var builtInDirectives = { } }; vnode.children.forEach((child) => { - if (child.name === "option") { + if (child.tag === "option") { let value2 = "value" in child.props ? child.props.value : child.children.join("").trim(); child.props.selected = model[property].indexOf(value2) !== -1; } }); } else { vnode.children.forEach((child) => { - if (child.name === "option") { + if (child.tag === "option") { let value2 = "value" in child.props ? child.props.value : child.children.join("").trim(); child.props.selected = value2 === model[property]; } @@ -583,24 +579,9 @@ var v = function v2(tagOrComponent, props, ...children) { v.fragment = (props, ...children) => { return children; }; -v.current = {}; -v.directives = { ...builtInDirectives }; -v.reservedProps = { - key: true, - state: true, - oncreate: true, - onupdate: true, - onremove: true, - shouldupdate: true, - "v-cleanup": true, - "v-once": true, - "v-if": true, - "v-unless": true, - "v-for": true, - "v-show": true, - "v-class": true, - "v-html": true -}; +v.current = current; +v.directives = directives; +v.reservedProps = reservedProps; v.isVnode = isVnode; v.isComponent = isComponent; v.isVnodeComponent = isVnodeComponent; diff --git a/dist/index.js b/dist/index.js index f204653..f9c0e8b 100644 --- a/dist/index.js +++ b/dist/index.js @@ -1,4 +1,9 @@ // lib/index.ts +var ComponentString = "__component__"; +var TextString = "#text"; +var isNodeJs = Boolean(typeof process !== "undefined" && process.versions && process.versions.node); +var ValyrianSymbol = Symbol("Valyrian"); +var Und = void 0; var Vnode = function Vnode2(tag, props, children) { this.props = props; this.children = children; @@ -11,9 +16,8 @@ function isComponent(component) { return typeof component === "function" || typeof component === "object" && component !== null && "view" in component; } function isVnodeComponent(vnode) { - return vnode instanceof Vnode && vnode.tag === "__component__"; + return vnode instanceof Vnode && vnode.tag === ComponentString; } -var isNodeJs = Boolean(typeof process !== "undefined" && process.versions && process.versions.node); function createDomElement(tag, isSVG = false) { return isSVG ? document.createElementNS("http://www.w3.org/2000/svg", tag) : document.createElement(tag); } @@ -22,7 +26,7 @@ function domToVnode(dom) { if (child.nodeType === 1) { return domToVnode(child); } - let text = new Vnode("#text", {}, []); + let text = new Vnode(TextString, {}, []); text.nodeValue = String(child.nodeValue); text.dom = child; return text; @@ -36,25 +40,40 @@ var trust = (htmlString) => { div.innerHTML = htmlString.trim(); return [].map.call(div.childNodes, (item) => domToVnode(item)); }; -var ValyrianSymbol = Symbol("Valyrian"); +var reservedProps = { + key: true, + state: true, + oncreate: true, + onupdate: true, + onremove: true, + shouldupdate: true, + "v-once": true, + "v-if": true, + "v-unless": true, + "v-for": true, + "v-show": true, + "v-class": true, + "v-html": true +}; +var current = {}; function onCleanup(callback) { - if (v.current.app?.onCleanup.indexOf(callback) === -1) { - v.current.app?.onCleanup.push(callback); + if (current.app?.onCleanup.indexOf(callback) === -1) { + current.app?.onCleanup.push(callback); } } function onUnmount(callback) { - if (v.current.app?.onUnmount.indexOf(callback) === -1) { - v.current.app?.onUnmount.push(callback); + if (current.app?.onUnmount.indexOf(callback) === -1) { + current.app?.onUnmount.push(callback); } } function onMount(callback) { - if (v.current.app?.onMount.indexOf(callback) === -1) { - v.current.app?.onMount.push(callback); + if (current.app?.onMount.indexOf(callback) === -1) { + current.app?.onMount.push(callback); } } function onUpdate(callback) { - if (v.current.app?.onUpdate.indexOf(callback) === -1) { - v.current.app?.onUpdate.push(callback); + if (current.app?.onUpdate.indexOf(callback) === -1) { + current.app?.onUpdate.push(callback); } } function mount(container, component) { @@ -105,7 +124,6 @@ function mount(container, component) { component[ValyrianSymbol].component = vnodeComponent; component[ValyrianSymbol].container = appContainer; component[ValyrianSymbol].mainVnode = domToVnode(appContainer); - component[ValyrianSymbol].mainVnode.isSVG = component[ValyrianSymbol].tag === "svg"; return update(component); } function callCleanup(valyrianApp) { @@ -135,12 +153,11 @@ function callUpdate(valyrianApp) { function update(component) { if (component && component[ValyrianSymbol]) { let valyrianApp = component[ValyrianSymbol]; - v.current.app = valyrianApp; + current.app = valyrianApp; valyrianApp.onCleanup.length && callCleanup(valyrianApp); let oldVnode = valyrianApp.mainVnode; valyrianApp.mainVnode = new Vnode(valyrianApp.mainVnode.tag, valyrianApp.mainVnode.props, [valyrianApp.component]); valyrianApp.mainVnode.dom = oldVnode.dom; - valyrianApp.mainVnode.isSVG = oldVnode.isSVG; patch(valyrianApp.mainVnode, oldVnode, valyrianApp); oldVnode = null; if (valyrianApp.isMounted === false) { @@ -178,19 +195,19 @@ function unmount(component) { var emptyVnode = new Vnode("__empty__", {}, []); function onremove(vnode) { for (let i = 0; i < vnode.children.length; i++) { - vnode.children[i].tag !== "#text" && onremove(vnode.children[i]); + vnode.children[i].tag !== TextString && onremove(vnode.children[i]); } vnode.props.onremove && vnode.props.onremove(vnode); } function sharedSetAttribute(prop, value, vnode, oldVnode) { - if (v.reservedProps[prop]) { - if (v.directives[prop]) { - v.directives[prop](vnode.props[prop], vnode, oldVnode); + if (reservedProps[prop]) { + if (directives[prop]) { + return directives[prop](vnode.props[prop], vnode, oldVnode); } return; } if (typeof value === "function") { - let valyrianApp = v.current.app; + let valyrianApp = current.app; if (prop in valyrianApp.eventListenerNames === false) { valyrianApp.eventListenerNames[prop] = true; valyrianApp.container.addEventListener(prop.slice(2), valyrianApp.eventListener); @@ -213,21 +230,18 @@ function sharedSetAttribute(prop, value, vnode, oldVnode) { } } function setAttribute(name, value, vnode, oldVnode) { - if (name in vnode.props === false) { - vnode.props[name] = value; - } + vnode.props[name] = value; sharedSetAttribute(name, value, vnode, oldVnode); } -function updateAttributes(vnode, oldVnode) { +function setAttributes(vnode, oldVnode) { for (let prop in vnode.props) { - if (prop in vnode.props === false) { + if (sharedSetAttribute(prop, vnode.props[prop], vnode, oldVnode) === false) { return; } - sharedSetAttribute(prop, vnode.props[prop], vnode, oldVnode); } if (oldVnode) { for (let prop in oldVnode.props) { - if (prop in vnode.props === false && typeof oldVnode.props[prop] !== "function" && prop in v.reservedProps === false) { + if (prop in vnode.props === false && typeof oldVnode.props[prop] !== "function" && prop in reservedProps === false) { if (prop in oldVnode.dom && vnode.isSVG === false) { oldVnode.dom[prop] = null; } else { @@ -237,170 +251,151 @@ function updateAttributes(vnode, oldVnode) { } } } -function flatTree(newVnode) { +function patch(newVnode, oldVnode = emptyVnode, valyrianApp) { + current.vnode = newVnode; + current.oldVnode = oldVnode === emptyVnode ? Und : oldVnode; let newTree = newVnode.children; + let oldTree = oldVnode.children; for (let i = 0; i < newTree.length; i++) { let childVnode = newTree[i]; if (childVnode instanceof Vnode) { - if (childVnode.tag !== "#text") { - if (childVnode.tag === "__component__") { + if (childVnode.tag !== TextString) { + if (childVnode.tag === ComponentString) { let component = childVnode.component; - v.current.component = component; + current.component = component; let result = ("view" in component ? component.view : component).call(component, childVnode.props, ...childVnode.children); newTree.splice(i--, 1, result); continue; } childVnode.isSVG = newVnode.isSVG || childVnode.tag === "svg"; } - } else if (childVnode === null || childVnode === void 0) { - newTree.splice(i--, 1); } else if (Array.isArray(childVnode)) { newTree.splice(i--, 1, ...childVnode); + } else if (childVnode === null || childVnode === Und) { + newTree.splice(i--, 1); } else { - if (i > 0 && newTree[i - 1].tag === "#text") { - newTree[i - 1].nodeValue += childVnode; - newTree.splice(i--, 1); - } else { - newTree[i] = new Vnode("#text", {}, []); - newTree[i].nodeValue = String(childVnode); - } + newTree[i] = new Vnode(TextString, {}, []); + newTree[i].nodeValue = childVnode; } } -} -function patchKeyedTree(newVnode, newTree, oldTree, newTreeLength, oldTreeLength, valyrianApp) { - let oldKeyedList = oldTree.reduce((acc, vnode, i) => { - acc[vnode.props.key] = i; - return acc; - }, {}); - let newKeyedList = newTree.reduce((acc, vnode, i) => { - acc[vnode.props.key] = i; - return acc; - }, {}); - for (let i = 0; i < newTreeLength; i++) { - let childVnode = newTree[i]; - let oldChildVnode = oldTree[oldKeyedList[childVnode.props.key]]; - let shouldPatch = true; - if (oldChildVnode) { - childVnode.dom = oldChildVnode.dom; - if ("v-once" in childVnode.props || childVnode.props.shouldupdate && childVnode.props.shouldupdate(childVnode, oldChildVnode) === false) { - childVnode.children = oldChildVnode.children; - shouldPatch = false; - } else { - updateAttributes(childVnode, oldChildVnode); - if (valyrianApp.isMounted) { - childVnode.props.onupdate && childVnode.props.onupdate(childVnode, oldChildVnode); + let oldTreeLength = oldTree.length; + let newTreeLength = newTree.length; + if (newTreeLength === 0) { + for (let i = 0; i < oldTreeLength; i++) { + onremove(oldTree[i]); + } + newVnode.dom.textContent = ""; + return; + } + if (oldTreeLength && "key" in newTree[0].props && "key" in oldTree[0].props) { + let oldKeyedList = oldTree.reduce((acc, vnode, i) => { + acc[vnode.props.key] = i; + return acc; + }, {}); + let newKeyedList = newTree.reduce((acc, vnode, i) => { + acc[vnode.props.key] = i; + return acc; + }, {}); + for (let i = 0; i < newTreeLength; i++) { + let childVnode = newTree[i]; + let oldChildVnode = oldTree[oldKeyedList[childVnode.props.key]]; + let shouldPatch = true; + if (oldChildVnode) { + childVnode.dom = oldChildVnode.dom; + if ("v-once" in childVnode.props || childVnode.props.shouldupdate && childVnode.props.shouldupdate(childVnode, oldChildVnode) === false) { + childVnode.children = oldChildVnode.children; + shouldPatch = false; } else { - childVnode.props.oncreate && childVnode.props.oncreate(childVnode); + setAttributes(childVnode, oldChildVnode); + if (valyrianApp.isMounted) { + childVnode.props.onupdate && childVnode.props.onupdate(childVnode, oldChildVnode); + } else { + childVnode.props.oncreate && childVnode.props.oncreate(childVnode); + } } + } else { + childVnode.dom = createDomElement(childVnode.tag, childVnode.isSVG); + setAttributes(childVnode); + childVnode.props.oncreate && childVnode.props.oncreate(childVnode); } - } else { - childVnode.dom = createDomElement(childVnode.tag, childVnode.isSVG); - updateAttributes(childVnode); - childVnode.props.oncreate && childVnode.props.oncreate(childVnode); - } - if (newVnode.dom.childNodes[i] === void 0) { - newVnode.dom.appendChild(childVnode.dom); - } else if (newVnode.dom.childNodes[i] !== childVnode.dom) { - oldTree[i] && newKeyedList[oldTree[i].props.key] === void 0 && onremove(oldTree[i]); - newVnode.dom.replaceChild(childVnode.dom, newVnode.dom.childNodes[i]); + if (newVnode.dom.childNodes[i] === Und) { + newVnode.dom.appendChild(childVnode.dom); + } else if (newVnode.dom.childNodes[i] !== childVnode.dom) { + oldTree[i] && newKeyedList[oldTree[i].props.key] === Und && onremove(oldTree[i]); + newVnode.dom.replaceChild(childVnode.dom, newVnode.dom.childNodes[i]); + } + shouldPatch && patch(childVnode, oldChildVnode, valyrianApp); } - shouldPatch && patch(childVnode, oldChildVnode, valyrianApp); - } - for (let i = newTreeLength; i < oldTreeLength; i++) { - if (newKeyedList[oldTree[i].props.key] === void 0) { - let oldChildVnode = oldTree[i]; - onremove(oldChildVnode); - oldChildVnode.dom.parentNode && oldChildVnode.dom.parentNode.removeChild(oldChildVnode.dom); + for (let i = newTreeLength; i < oldTreeLength; i++) { + if (newKeyedList[oldTree[i].props.key] === Und) { + let oldChildVnode = oldTree[i]; + onremove(oldChildVnode); + oldChildVnode.dom.parentNode && oldChildVnode.dom.parentNode.removeChild(oldChildVnode.dom); + } } + return; } -} -function patchNormalTree(newVnode, newTree, oldTree, newTreeLength, oldTreeLength, valyrianApp) { for (let i = 0; i < newTreeLength; i++) { - let oldChildVnode = oldTree[i]; let newChildVnode = newTree[i]; - if (!oldChildVnode) { - if (newChildVnode.tag === "#text") { + if (i < oldTreeLength) { + let oldChildVnode = oldTree[i]; + if (newChildVnode.tag === TextString) { + if (oldChildVnode.tag === TextString) { + newChildVnode.dom = oldChildVnode.dom; + if (newChildVnode.dom.nodeValue != newChildVnode.nodeValue) { + newChildVnode.dom.nodeValue = newChildVnode.nodeValue; + } + continue; + } newChildVnode.dom = document.createTextNode(newChildVnode.nodeValue); - newVnode.dom.appendChild(newChildVnode.dom); + onremove(oldChildVnode); + newVnode.dom.replaceChild(newChildVnode.dom, oldChildVnode.dom); continue; } - newChildVnode.dom = createDomElement(newChildVnode.tag, newChildVnode.isSVG); - updateAttributes(newChildVnode); - newVnode.dom.appendChild(newChildVnode.dom); - newChildVnode.props.oncreate && newChildVnode.props.oncreate(newChildVnode); - patch(newChildVnode, void 0, valyrianApp); - continue; - } - if (newChildVnode.tag === "#text") { - if (oldChildVnode.tag === "#text") { + if (oldChildVnode.tag === newChildVnode.tag) { newChildVnode.dom = oldChildVnode.dom; - if (newChildVnode.dom.nodeValue != newChildVnode.nodeValue) { - newChildVnode.dom.nodeValue = newChildVnode.nodeValue; + if (newChildVnode.props["v-once"] || newChildVnode.props.shouldupdate && newChildVnode.props.shouldupdate(newChildVnode, oldChildVnode) === false) { + newChildVnode.children = oldChildVnode.children; + continue; } + setAttributes(newChildVnode, oldChildVnode); + if (valyrianApp.isMounted) { + newChildVnode.props.onupdate && newChildVnode.props.onupdate(newChildVnode, oldChildVnode); + } else { + newChildVnode.props.oncreate && newChildVnode.props.oncreate(newChildVnode); + } + patch(newChildVnode, oldChildVnode, valyrianApp); continue; } - newChildVnode.dom = document.createTextNode(newChildVnode.nodeValue); - onremove(oldChildVnode); + newChildVnode.dom = createDomElement(newChildVnode.tag, newChildVnode.isSVG); + setAttributes(newChildVnode); + oldChildVnode.tag !== TextString && onremove(oldChildVnode); + newChildVnode.props.oncreate && newChildVnode.props.oncreate(newChildVnode); newVnode.dom.replaceChild(newChildVnode.dom, oldChildVnode.dom); + patch(newChildVnode, emptyVnode, valyrianApp); continue; } - if (oldChildVnode.tag === newChildVnode.tag) { - newChildVnode.dom = oldChildVnode.dom; - if (newChildVnode.props["v-once"] || newChildVnode.props.shouldupdate && newChildVnode.props.shouldupdate(newChildVnode, oldChildVnode) === false) { - newChildVnode.children = oldChildVnode.children; - continue; - } - updateAttributes(newChildVnode, oldChildVnode); - if (valyrianApp && valyrianApp.isMounted) { - newChildVnode.props.onupdate && newChildVnode.props.onupdate(newChildVnode, oldChildVnode); - } else { - newChildVnode.props.oncreate && newChildVnode.props.oncreate(newChildVnode); - } - patch(newChildVnode, oldChildVnode, valyrianApp); + if (newChildVnode.tag === TextString) { + newChildVnode.dom = document.createTextNode(newChildVnode.nodeValue); + newVnode.dom.appendChild(newChildVnode.dom); continue; } newChildVnode.dom = createDomElement(newChildVnode.tag, newChildVnode.isSVG); - updateAttributes(newChildVnode); - if (oldChildVnode.tag !== "#text") { - onremove(oldChildVnode); - } + setAttributes(newChildVnode); + newVnode.dom.appendChild(newChildVnode.dom); newChildVnode.props.oncreate && newChildVnode.props.oncreate(newChildVnode); - newVnode.dom.replaceChild(newChildVnode.dom, oldChildVnode.dom); - patch(newChildVnode, void 0, valyrianApp); + patch(newChildVnode, emptyVnode, valyrianApp); } for (let i = newTreeLength; i < oldTreeLength; i++) { let oldChildVnode = oldTree[i]; - if (oldChildVnode.tag !== "#text") { - onremove(oldChildVnode); - } + oldChildVnode.tag !== TextString && onremove(oldChildVnode); oldChildVnode.dom.parentNode && oldChildVnode.dom.parentNode.removeChild(oldChildVnode.dom); } } -function patch(newVnode, oldVnode = emptyVnode, valyrianApp) { - v.current.vnode = newVnode; - v.current.oldVnode = oldVnode; - flatTree(newVnode); - let newTree = newVnode.children; - let oldTree = oldVnode.children; - let oldTreeLength = oldTree.length; - let newTreeLength = newTree.length; - if (newTreeLength === 0) { - for (let i = 0; i < oldTreeLength; i++) { - onremove(oldTree[i]); - } - newVnode.dom.textContent = ""; - return; - } - if (oldTreeLength && "key" in newTree[0].props && "key" in oldTree[0].props) { - patchKeyedTree(newVnode, newTree, oldTree, newTreeLength, oldTreeLength, valyrianApp); - return; - } - patchNormalTree(newVnode, newTree, oldTree, newTreeLength, oldTreeLength, valyrianApp); -} function directive(name, directive2) { let fullName = `v-${name}`; - v.directives[fullName] = directive2; - v.reservedProps[fullName] = true; + directives[fullName] = directive2; + reservedProps[fullName] = true; } function hideDirective(test) { return (bool, vnode, oldVnode) => { @@ -408,17 +403,18 @@ function hideDirective(test) { if (value) { let newdom = document.createTextNode(""); if (oldVnode && oldVnode.dom && oldVnode.dom.parentNode) { - oldVnode.tag !== "#text" && onremove(oldVnode); + oldVnode.tag !== TextString && onremove(oldVnode); oldVnode.dom.parentNode.replaceChild(newdom, oldVnode.dom); } - vnode.tag = "#text"; + vnode.tag = TextString; vnode.children = []; vnode.props = {}; vnode.dom = newdom; + return false; } }; } -var builtInDirectives = { +var directives = { "v-if": hideDirective(false), "v-unless": hideDirective(true), "v-for": (set, vnode) => { @@ -495,14 +491,14 @@ var builtInDirectives = { } }; vnode.children.forEach((child) => { - if (child.name === "option") { + if (child.tag === "option") { let value2 = "value" in child.props ? child.props.value : child.children.join("").trim(); child.props.selected = model[property].indexOf(value2) !== -1; } }); } else { vnode.children.forEach((child) => { - if (child.name === "option") { + if (child.tag === "option") { let value2 = "value" in child.props ? child.props.value : child.children.join("").trim(); child.props.selected = value2 === model[property]; } @@ -540,24 +536,9 @@ var v = function v2(tagOrComponent, props, ...children) { v.fragment = (props, ...children) => { return children; }; -v.current = {}; -v.directives = { ...builtInDirectives }; -v.reservedProps = { - key: true, - state: true, - oncreate: true, - onupdate: true, - onremove: true, - shouldupdate: true, - "v-cleanup": true, - "v-once": true, - "v-if": true, - "v-unless": true, - "v-for": true, - "v-show": true, - "v-class": true, - "v-html": true -}; +v.current = current; +v.directives = directives; +v.reservedProps = reservedProps; v.isVnode = isVnode; v.isComponent = isComponent; v.isVnodeComponent = isVnodeComponent; diff --git a/dist/index.min.js b/dist/index.min.js index 91d167e..cd2faf4 100644 --- a/dist/index.min.js +++ b/dist/index.min.js @@ -1 +1 @@ -(()=>{var e=function(e,n,o){this.props=n,this.children=o,this.tag=e};function n(n){return n instanceof e}function o(e){return"function"==typeof e||"object"==typeof e&&null!==e&&"view"in e}function t(n){return n instanceof e&&"__component__"===n.tag}var r=Boolean("undefined"!=typeof process&&process.versions&&process.versions.node);function i(e,n=!1){return n?document.createElementNS("http://www.w3.org/2000/svg",e):document.createElement(e)}function p(n){let o=k(n.tagName.toLowerCase(),{},...Array.from(n.childNodes).filter(e=>1===e.nodeType||3===e.nodeType).map(n=>{if(1===n.nodeType)return p(n);let o=new e("#text",{},[]);return o.nodeValue=String(n.nodeValue),o.dom=n,o}));return[].forEach.call(n.attributes,e=>o.props[e.nodeName]=e.nodeValue),o.dom=n,o}var d=e=>{let n=i("div");return n.innerHTML=e.trim(),[].map.call(n.childNodes,e=>p(e))},l=Symbol("Valyrian");function a(e){-1===k.current.app?.onCleanup.indexOf(e)&&k.current.app?.onCleanup.push(e)}function s(e){-1===k.current.app?.onUnmount.indexOf(e)&&k.current.app?.onUnmount.push(e)}function u(e){-1===k.current.app?.onMount.indexOf(e)&&k.current.app?.onMount.push(e)}function c(e){-1===k.current.app?.onUpdate.indexOf(e)&&k.current.app?.onUpdate.push(e)}function m(e,n){let d,a=null;if(a=r?"string"==typeof e?i("svg"===e?"svg":"div","svg"===e):e:"string"==typeof e?document.querySelectorAll(e)[0]:e,!a)throw new Error("Container not found");if(t(n))d=n;else{if(!o(n))throw new Error("Component must be a Valyrian Component or a Vnode component");d=k(n,{})}if(n[l])h(n);else{let e=function(e){let o=e.target,t=`v-on${e.type}`;for(;o;){if(o[t])return o[t](e,o),void(e.defaultPrevented||v(n));o=o.parentNode}};n[l]={isMounted:!1,eventListenerNames:{},onCleanup:[],onMount:[],onUpdate:[],onUnmount:[]},n[l].eventListener=e}return n[l].component=d,n[l].container=a,n[l].mainVnode=p(a),n[l].mainVnode.isSVG="svg"===n[l].tag,v(n)}function f(e){for(let n=0;n0&&"#text"===o[t-1].tag?(o[t-1].nodeValue+=r,o.splice(t--,1)):(o[t]=new e("#text",{},[]),o[t].nodeValue=String(r))}}(n);let r=n.children,p=o.children,d=p.length,l=r.length;if(0!==l)d&&"key"in r[0].props&&"key"in p[0].props?function(e,n,o,t,r,p){let d=o.reduce((e,n,o)=>(e[n.props.key]=o,e),{}),l=n.reduce((e,n,o)=>(e[n.props.key]=o,e),{});for(let r=0;r{if(e?n:!n){let e=document.createTextNode("");t&&t.dom&&t.dom.parentNode&&("#text"!==t.tag&&V(t),t.dom.parentNode.replaceChild(e,t.dom)),o.tag="#text",o.children=[],o.props={},o.dom=e}}}var U={"v-if":M(!1),"v-unless":M(!0),"v-for":(e,n)=>{n.children=e.map(n.children[0])},"v-show":(e,n)=>{n.dom.style.display=e?"":"none"},"v-class":(e,n)=>{for(let o in e)n.dom.classList.toggle(o,e[o])},"v-html":(e,n)=>{n.children=[d(e)]},"v-model":([e,n,o],t,r)=>{let i,p;if("input"===t.name)switch(o=o||"oninput",t.props.type){case"checkbox":Array.isArray(e[n])?(p=o=>{let t=o.target.value,r=e[n].indexOf(t);-1===r?e[n].push(t):e[n].splice(r,1)},i=-1!==e[n].indexOf(t.dom.value)):"value"in t.props?(p=()=>{e[n]===t.props.value?e[n]=null:e[n]=t.props.value},i=e[n]===t.props.value):(p=()=>e[n]=!e[n],i=e[n]),C("checked",i,t,r);break;case"radio":C("checked",e[n]===t.dom.value,t,r);break;default:C("value",e[n],t,r)}else"select"===t.name?(o=o||"onclick",t.props.multiple?(p=o=>{let t=o.target.value;if(o.ctrlKey){let o=e[n].indexOf(t);-1===o?e[n].push(t):e[n].splice(o,1)}else e[n].splice(0,e[n].length),e[n].push(t)},t.children.forEach(o=>{if("option"===o.name){let t="value"in o.props?o.props.value:o.children.join("").trim();o.props.selected=-1!==e[n].indexOf(t)}})):t.children.forEach(o=>{if("option"===o.name){let t="value"in o.props?o.props.value:o.children.join("").trim();o.props.selected=t===e[n]}})):"textarea"===t.name&&(o=o||"oninput",t.children=[e[n]]);t.props[o]||(p||(p=o=>e[n]=o.target.value),C(o,p,t,r))}},S=new Map;function _(e,n){if(S.has(e))return S.get(e);let o=e(k,n);return S.set(e,o),o}var k=function(n,o,...t){if("string"==typeof n)return new e(n,o||{},t);const r=new e("__component__",o||{},t);return r.component=n,r};k.fragment=(e,...n)=>n,k.current={},k.directives={...U},k.reservedProps={key:!0,state:!0,oncreate:!0,onupdate:!0,onremove:!0,shouldupdate:!0,"v-cleanup":!0,"v-once":!0,"v-if":!0,"v-unless":!0,"v-for":!0,"v-show":!0,"v-class":!0,"v-html":!0},k.isVnode=n,k.isComponent=o,k.isVnodeComponent=t,k.isNodeJs=r,k.trust=d,k.onCleanup=a,k.onUnmount=s,k.onMount=u,k.onUpdate=c,k.mount=m,k.unmount=h,k.update=v,k.setAttribute=C,k.directive=N,k.use=_;var b={Vnode:e,directive:N,isComponent:o,isNodeJs:r,isVnode:n,isVnodeComponent:t,mount:m,onCleanup:a,onMount:u,onUnmount:s,onUpdate:c,setAttribute:C,trust:d,unmount:h,update:v,use:_,v:k};"undefined"!=typeof module?module.exports=b:self.Valyrian=b})(); \ No newline at end of file +(()=>{var e="__component__",n="#text",o=Boolean("undefined"!=typeof process&&process.versions&&process.versions.node),t=Symbol("Valyrian"),r=void 0,i=function(e,n,o){this.props=n,this.children=o,this.tag=e};function p(e){return e instanceof i}function d(e){return"function"==typeof e||"object"==typeof e&&null!==e&&"view"in e}function l(n){return n instanceof i&&n.tag===e}function a(e,n=!1){return n?document.createElementNS("http://www.w3.org/2000/svg",e):document.createElement(e)}function s(e){let o=T(e.tagName.toLowerCase(),{},...Array.from(e.childNodes).filter(e=>1===e.nodeType||3===e.nodeType).map(e=>{if(1===e.nodeType)return s(e);let o=new i(n,{},[]);return o.nodeValue=String(e.nodeValue),o.dom=e,o}));return[].forEach.call(e.attributes,e=>o.props[e.nodeName]=e.nodeValue),o.dom=e,o}var u=e=>{let n=a("div");return n.innerHTML=e.trim(),[].map.call(n.childNodes,e=>s(e))},m={key:!0,state:!0,oncreate:!0,onupdate:!0,onremove:!0,shouldupdate:!0,"v-once":!0,"v-if":!0,"v-unless":!0,"v-for":!0,"v-show":!0,"v-class":!0,"v-html":!0},c={};function f(e){-1===c.app?.onCleanup.indexOf(e)&&c.app?.onCleanup.push(e)}function h(e){-1===c.app?.onUnmount.indexOf(e)&&c.app?.onUnmount.push(e)}function v(e){-1===c.app?.onMount.indexOf(e)&&c.app?.onMount.push(e)}function g(e){-1===c.app?.onUpdate.indexOf(e)&&c.app?.onUpdate.push(e)}function V(e,n){let r,i=null;if(i=o?"string"==typeof e?a("svg"===e?"svg":"div","svg"===e):e:"string"==typeof e?document.querySelectorAll(e)[0]:e,!i)throw new Error("Container not found");if(l(n))r=n;else{if(!d(n))throw new Error("Component must be a Valyrian Component or a Vnode component");r=T(n,{})}if(n[t])w(n);else{let e=function(e){let o=e.target,t=`v-on${e.type}`;for(;o;){if(o[t])return o[t](e,o),void(e.defaultPrevented||C(n));o=o.parentNode}};n[t]={isMounted:!1,eventListenerNames:{},onCleanup:[],onMount:[],onUpdate:[],onUnmount:[]},n[t].eventListener=e}return n[t].component=r,n[t].container=i,n[t].mainVnode=s(i),C(n)}function y(e){for(let n=0;n(e[n.props.key]=o,e),{}),n=d.reduce((e,n,o)=>(e[n.props.key]=o,e),{});for(let t=0;t{if(e?o:!o){let e=document.createTextNode("");return r&&r.dom&&r.dom.parentNode&&(r.tag!==n&&M(r),r.dom.parentNode.replaceChild(e,r.dom)),t.tag=n,t.children=[],t.props={},t.dom=e,!1}}}var A={"v-if":_(!1),"v-unless":_(!0),"v-for":(e,n)=>{n.children=e.map(n.children[0])},"v-show":(e,n)=>{n.dom.style.display=e?"":"none"},"v-class":(e,n)=>{for(let o in e)n.dom.classList.toggle(o,e[o])},"v-html":(e,n)=>{n.children=[u(e)]},"v-model":([e,n,o],t,r)=>{let i,p;if("input"===t.name)switch(o=o||"oninput",t.props.type){case"checkbox":Array.isArray(e[n])?(p=o=>{let t=o.target.value,r=e[n].indexOf(t);-1===r?e[n].push(t):e[n].splice(r,1)},i=-1!==e[n].indexOf(t.dom.value)):"value"in t.props?(p=()=>{e[n]===t.props.value?e[n]=null:e[n]=t.props.value},i=e[n]===t.props.value):(p=()=>e[n]=!e[n],i=e[n]),x("checked",i,t,r);break;case"radio":x("checked",e[n]===t.dom.value,t,r);break;default:x("value",e[n],t,r)}else"select"===t.name?(o=o||"onclick",t.props.multiple?(p=o=>{let t=o.target.value;if(o.ctrlKey){let o=e[n].indexOf(t);-1===o?e[n].push(t):e[n].splice(o,1)}else e[n].splice(0,e[n].length),e[n].push(t)},t.children.forEach(o=>{if("option"===o.tag){let t="value"in o.props?o.props.value:o.children.join("").trim();o.props.selected=-1!==e[n].indexOf(t)}})):t.children.forEach(o=>{if("option"===o.tag){let t="value"in o.props?o.props.value:o.children.join("").trim();o.props.selected=t===e[n]}})):"textarea"===t.name&&(o=o||"oninput",t.children=[e[n]]);t.props[o]||(p||(p=o=>e[n]=o.target.value),x(o,p,t,r))}},L=new Map;function G(e,n){if(L.has(e))return L.get(e);let o=e(T,n);return L.set(e,o),o}var T=function(e,n,...o){if("string"==typeof e)return new i(e,n||{},o);const t=new i("__component__",n||{},o);return t.component=e,t};T.fragment=(e,...n)=>n,T.current=c,T.directives=A,T.reservedProps=m,T.isVnode=p,T.isComponent=d,T.isVnodeComponent=l,T.isNodeJs=o,T.trust=u,T.onCleanup=f,T.onUnmount=h,T.onMount=v,T.onUpdate=g,T.mount=V,T.unmount=w,T.update=C,T.setAttribute=x,T.directive=b,T.use=G;var E={Vnode:i,directive:b,isComponent:d,isNodeJs:o,isVnode:p,isVnodeComponent:l,mount:V,onCleanup:f,onMount:v,onUnmount:h,onUpdate:g,setAttribute:x,trust:u,unmount:w,update:C,use:G,v:T};"undefined"!=typeof module?module.exports=E:self.Valyrian=E})(); \ No newline at end of file diff --git a/dist/index.min.js.map b/dist/index.min.js.map index 87ece03..ca19402 100644 --- a/dist/index.min.js.map +++ b/dist/index.min.js.map @@ -1 +1 @@ -//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL2xpYi9pbmRleC50cyJdLCJuYW1lcyI6WyJWbm9kZSIsInRhZyIsInByb3BzIiwiY2hpbGRyZW4iLCJ0aGlzIiwiaXNWbm9kZSIsIm9iamVjdCIsImlzQ29tcG9uZW50IiwiY29tcG9uZW50IiwiaXNWbm9kZUNvbXBvbmVudCIsInZub2RlIiwiaXNOb2RlSnMiLCJCb29sZWFuIiwicHJvY2VzcyIsInZlcnNpb25zIiwibm9kZSIsImNyZWF0ZURvbUVsZW1lbnQiLCJpc1NWRyIsImRvY3VtZW50IiwiY3JlYXRlRWxlbWVudE5TIiwiY3JlYXRlRWxlbWVudCIsImRvbVRvVm5vZGUiLCJkb20iLCJ2IiwidGFnTmFtZSIsInRvTG93ZXJDYXNlIiwiQXJyYXkiLCJmcm9tIiwiY2hpbGROb2RlcyIsImZpbHRlciIsImNoaWxkIiwibm9kZVR5cGUiLCJtYXAiLCJ0ZXh0Iiwibm9kZVZhbHVlIiwiU3RyaW5nIiwiZm9yRWFjaCIsImNhbGwiLCJhdHRyaWJ1dGVzIiwicHJvcCIsIm5vZGVOYW1lIiwidHJ1c3QiLCJodG1sU3RyaW5nIiwiZGl2IiwiaW5uZXJIVE1MIiwidHJpbSIsIml0ZW0iLCJWYWx5cmlhblN5bWJvbCIsIlN5bWJvbCIsIm9uQ2xlYW51cCIsImNhbGxiYWNrIiwiY3VycmVudCIsImFwcCIsImluZGV4T2YiLCJwdXNoIiwib25Vbm1vdW50Iiwib25Nb3VudCIsIm9uVXBkYXRlIiwibW91bnQiLCJjb250YWluZXIiLCJ2bm9kZUNvbXBvbmVudCIsImFwcENvbnRhaW5lciIsInF1ZXJ5U2VsZWN0b3JBbGwiLCJFcnJvciIsInVubW91bnQiLCJldmVudExpc3RlbmVyIiwiZSIsInRhcmdldCIsIm5hbWUiLCJ0eXBlIiwiZGVmYXVsdFByZXZlbnRlZCIsInVwZGF0ZSIsInBhcmVudE5vZGUiLCJpc01vdW50ZWQiLCJldmVudExpc3RlbmVyTmFtZXMiLCJtYWluVm5vZGUiLCJjYWxsQ2xlYW51cCIsInZhbHlyaWFuQXBwIiwiaSIsImxlbmd0aCIsIm9sZFZub2RlIiwicGF0Y2giLCJjYWxsTW91bnQiLCJjYWxsVXBkYXRlIiwiY2FsbFVubW91bnQiLCJSZWZsZWN0IiwiZGVsZXRlUHJvcGVydHkiLCJlbXB0eVZub2RlIiwib25yZW1vdmUiLCJzaGFyZWRTZXRBdHRyaWJ1dGUiLCJ2YWx1ZSIsInJlc2VydmVkUHJvcHMiLCJkaXJlY3RpdmVzIiwiYWRkRXZlbnRMaXN0ZW5lciIsInNsaWNlIiwicmVtb3ZlQXR0cmlidXRlIiwic2V0QXR0cmlidXRlIiwidXBkYXRlQXR0cmlidXRlcyIsIm5ld1Zub2RlIiwibmV3VHJlZSIsImNoaWxkVm5vZGUiLCJyZXN1bHQiLCJ2aWV3Iiwic3BsaWNlIiwiaXNBcnJheSIsImZsYXRUcmVlIiwib2xkVHJlZSIsIm9sZFRyZWVMZW5ndGgiLCJuZXdUcmVlTGVuZ3RoIiwib2xkS2V5ZWRMaXN0IiwicmVkdWNlIiwiYWNjIiwia2V5IiwibmV3S2V5ZWRMaXN0Iiwib2xkQ2hpbGRWbm9kZSIsInNob3VsZFBhdGNoIiwic2hvdWxkdXBkYXRlIiwib251cGRhdGUiLCJvbmNyZWF0ZSIsImFwcGVuZENoaWxkIiwicmVwbGFjZUNoaWxkIiwicmVtb3ZlQ2hpbGQiLCJwYXRjaEtleWVkVHJlZSIsIm5ld0NoaWxkVm5vZGUiLCJjcmVhdGVUZXh0Tm9kZSIsInBhdGNoTm9ybWFsVHJlZSIsInRleHRDb250ZW50IiwiZGlyZWN0aXZlIiwiZGlyZWN0aXZlMiIsImZ1bGxOYW1lIiwiaGlkZURpcmVjdGl2ZSIsInRlc3QiLCJib29sIiwibmV3ZG9tIiwiYnVpbHRJbkRpcmVjdGl2ZXMiLCJzZXQiLCJzdHlsZSIsImRpc3BsYXkiLCJjbGFzc2VzIiwiY2xhc3NMaXN0IiwidG9nZ2xlIiwiaHRtbCIsIm1vZGVsIiwicHJvcGVydHkiLCJldmVudCIsImhhbmRsZXIiLCJ2YWwiLCJpZHgiLCJtdWx0aXBsZSIsImN0cmxLZXkiLCJ2YWx1ZTIiLCJqb2luIiwic2VsZWN0ZWQiLCJwbHVnaW5zIiwiTWFwIiwidXNlIiwicGx1Z2luIiwib3B0aW9u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RXBCL0csRUFBRW9FLGNBQWdCLENBQ2hCcUIsS0FBSyxFQUNMa0QsT0FBTyxFQUNQNUMsVUFBVSxFQUNWRCxVQUFVLEVBQ1Y3QixVQUFVLEVBQ1Y0QixjQUFjLEVBQ2QsYUFBYSxFQUNiLFVBQVUsRUFHVixRQUFRLEVBQ1IsWUFBWSxFQUNaLFNBQVMsRUFDVCxVQUFVLEVBQ1YsV0FBVyxFQUNYLFVBQVUsR0FHWjdGLEVBQUVsQixRQUFVQSxFQUNaa0IsRUFBRWhCLFlBQWNBLEVBQ2hCZ0IsRUFBRWQsaUJBQW1CQSxFQUVyQmMsRUFBRVosU0FBV0EsRUFDYlksRUFBRWtCLE1BQVFBLEVBRVZsQixFQUFFMEIsVUFBWUEsRUFDZDFCLEVBQUVnQyxVQUFZQSxFQUNkaEMsRUFBRWlDLFFBQVVBLEVBQ1pqQyxFQUFFa0MsU0FBV0EsRUFFYmxDLEVBQUVtQyxNQUFRQSxFQUNWbkMsRUFBRXlDLFFBQVVBLEVBQ1p6QyxFQUFFZ0QsT0FBU0EsRUFFWGhELEVBQUV5RSxhQUFlQSxFQUNqQnpFLEVBQUV3RyxVQUFZQSxFQUNkeEcsRUFBRW9JLElBQU1BIiwic291cmNlc0NvbnRlbnQiOlsiLyoqKiBWbm9kZSAqKiovXG5cbmltcG9ydCB7XG4gIENoaWxkcmVuLFxuICBDdXJyZW50LFxuICBEaXJlY3RpdmUsXG4gIERvbUVsZW1lbnQsXG4gIElWbm9kZSxcbiAgTW91bnRlZFZhbHlyaWFuQXBwLFxuICBQbHVnaW4sXG4gIFByb3BzLFxuICBWYWx5cmlhbixcbiAgVmFseXJpYW5BcHAsXG4gIFZhbHlyaWFuQ29tcG9uZW50LFxuICBWbm9kZUNvbXBvbmVudCxcbiAgVm5vZGVXaXRoRG9tXG59IGZyb20gXCIuL2ludGVyZmFjZXNcIjtcblxuZXhwb3J0IGNvbnN0IFZub2RlID0gZnVuY3Rpb24gVm5vZGUodGhpczogSVZub2RlLCB0YWc6IHN0cmluZywgcHJvcHM6IFByb3BzLCBjaGlsZHJlbjogQ2hpbGRyZW4pIHtcbiAgdGhpcy5wcm9wcyA9IHByb3BzO1xuICB0aGlzLmNoaWxkcmVuID0gY2hpbGRyZW47XG4gIHRoaXMudGFnID0gdGFnO1xufSBhcyB1bmtub3duIGFzIElWbm9kZTtcblxuZXhwb3J0IGZ1bmN0aW9uIGlzVm5vZGUob2JqZWN0PzogdW5rbm93biB8IElWbm9kZSk6IG9iamVjdCBpcyBJVm5vZGUge1xuICByZXR1cm4gb2JqZWN0IGluc3RhbmNlb2YgVm5vZGU7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBpc0NvbXBvbmVudChjb21wb25lbnQ/OiB1bmtub3duIHwgVmFseXJpYW5Db21wb25lbnQpOiBjb21wb25lbnQgaXMgVmFseXJpYW5Db21wb25lbnQge1xuICByZXR1cm4gdHlwZW9mIGNvbXBvbmVudCA9PT0gXCJmdW5jdGlvblwiIHx8ICh0eXBlb2YgY29tcG9uZW50ID09PSBcIm9iamVjdFwiICYmIGNvbXBvbmVudCAhPT0gbnVsbCAmJiBcInZpZXdcIiBpbiBjb21wb25lbnQpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gaXNWbm9kZUNvbXBvbmVudCh2bm9kZT86IHVua25vd24gfCBWbm9kZUNvbXBvbmVudCk6IHZub2RlIGlzIFZub2RlQ29tcG9uZW50IHtcbiAgcmV0dXJuIHZub2RlIGluc3RhbmNlb2YgVm5vZGUgJiYgdm5vZGUudGFnID09PSBcIl9fY29tcG9uZW50X19cIjtcbn1cblxuLyoqKiBVdGlsICoqKi9cblxuZXhwb3J0IGNvbnN0IGlzTm9kZUpzID0gQm9vbGVhbih0eXBlb2YgcHJvY2VzcyAhPT0gXCJ1bmRlZmluZWRcIiAmJiBwcm9jZXNzLnZlcnNpb25zICYmIHByb2Nlc3MudmVyc2lvbnMubm9kZSk7XG5cbmZ1bmN0aW9uIGNyZWF0ZURvbUVsZW1lbnQodGFnOiBzdHJpbmcsIGlzU1ZHOiBib29sZWFuID0gZmFsc2UpIHtcbiAgcmV0dXJuIGlzU1ZHID8gZG9jdW1lbnQuY3JlYXRlRWxlbWVudE5TKFwiaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmdcIiwgdGFnKSA6IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQodGFnKTtcbn1cblxuZnVuY3Rpb24gZG9tVG9Wbm9kZShkb206IERvbUVsZW1lbnQpOiBWbm9kZVdpdGhEb20ge1xuICBsZXQgdm5vZGUgPSB2KFxuICAgIGRvbS50YWdOYW1lLnRvTG93ZXJDYXNlKCksXG4gICAge30sXG4gICAgLi4uQXJyYXkuZnJvbShkb20uY2hpbGROb2RlcylcbiAgICAgIC5maWx0ZXIoKGNoaWxkKSA9PiAoY2hpbGQgYXMgRG9tRWxlbWVudCkubm9kZVR5cGUgPT09IDEgfHwgKGNoaWxkIGFzIERvbUVsZW1lbnQpLm5vZGVUeXBlID09PSAzKVxuICAgICAgLm1hcCgoY2hpbGQpID0+IHtcbiAgICAgICAgaWYgKChjaGlsZCBhcyBEb21FbGVtZW50KS5ub2RlVHlwZSA9PT0gMSkge1xuICAgICAgICAgIHJldHVybiBkb21Ub1Zub2RlKGNoaWxkIGFzIERvbUVsZW1lbnQpO1xuICAgICAgICB9XG5cbiAgICAgICAgbGV0IHRleHQgPSBuZXcgVm5vZGUoXCIjdGV4dFwiLCB7fSwgW10pO1xuICAgICAgICB0ZXh0Lm5vZGVWYWx1ZSA9IFN0cmluZygoY2hpbGQgYXMgRG9tRWxlbWVudCkubm9kZVZhbHVlKTtcbiAgICAgICAgdGV4dC5kb20gPSBjaGlsZCBhcyBEb21FbGVtZW50O1xuICAgICAgICByZXR1cm4gdGV4dDtcbiAgICAgIH0pXG4gICk7XG4gIFtdLmZvckVhY2guY2FsbChkb20uYXR0cmlidXRlcywgKHByb3A6IEF0dHIpID0+ICh2bm9kZS5wcm9wc1twcm9wLm5vZGVOYW1lXSA9IHByb3Aubm9kZVZhbHVlKSk7XG4gIHZub2RlLmRvbSA9IGRvbTtcbiAgcmV0dXJuIHZub2RlIGFzIFZub2RlV2l0aERvbTtcbn1cblxuZXhwb3J0IGNvbnN0IHRydXN0ID0gKGh0bWxTdHJpbmc6IHN0cmluZyk6IElWbm9kZVtdID0+IHtcbiAgbGV0IGRpdiA9IGNyZWF0ZURvbUVsZW1lbnQoXCJkaXZcIik7XG4gIGRpdi5pbm5lckhUTUwgPSBodG1sU3RyaW5nLnRyaW0oKTtcblxuICByZXR1cm4gW10ubWFwLmNhbGwoZGl2LmNoaWxkTm9kZXMsIChpdGVtKSA9PiBkb21Ub1Zub2RlKGl0ZW0pKSBhcyBJVm5vZGVbXTtcbn07XG5cbi8qKiogTW91bnQgKioqL1xuXG5jb25zdCBWYWx5cmlhblN5bWJvbCA9IFN5bWJvbChcIlZhbHlyaWFuXCIpO1xuXG5leHBvcnQgZnVuY3Rpb24gb25DbGVhbnVwKGNhbGxiYWNrOiBGdW5jdGlvbikge1xuICBpZiAodi5jdXJyZW50LmFwcD8ub25DbGVhbnVwLmluZGV4T2YoY2FsbGJhY2spID09PSAtMSkge1xuICAgIHYuY3VycmVudC5hcHA/Lm9uQ2xlYW51cC5wdXNoKGNhbGxiYWNrKTtcbiAgfVxufVxuXG5leHBvcnQgZnVuY3Rpb24gb25Vbm1vdW50KGNhbGxiYWNrOiBGdW5jdGlvbikge1xuICBpZiAodi5jdXJyZW50LmFwcD8ub25Vbm1vdW50LmluZGV4T2YoY2FsbGJhY2spID09PSAtMSkge1xuICAgIHYuY3VycmVudC5hcHA/Lm9uVW5tb3VudC5wdXNoKGNhbGxiYWNrKTtcbiAgfVxufVxuXG5leHBvcnQgZnVuY3Rpb24gb25Nb3VudChjYWxsYmFjazogRnVuY3Rpb24pIHtcbiAgaWYgKHYuY3VycmVudC5hcHA/Lm9uTW91bnQuaW5kZXhPZihjYWxsYmFjaykgPT09IC0xKSB7XG4gICAgdi5jdXJyZW50LmFwcD8ub25Nb3VudC5wdXNoKGNhbGxiYWNrKTtcbiAgfVxufVxuXG5leHBvcnQgZnVuY3Rpb24gb25VcGRhdGUoY2FsbGJhY2s6IEZ1bmN0aW9uKSB7XG4gIGlmICh2LmN1cnJlbnQuYXBwPy5vblVwZGF0ZS5pbmRleE9mKGNhbGxiYWNrKSA9PT0gLTEpIHtcbiAgICB2LmN1cnJlbnQuYXBwPy5vblVwZGF0ZS5wdXNoKGNhbGxiYWNrKTtcbiAgfVxufVxuXG4vKlxuICAqIE1vdW50cyBhIGNvbXBvbmVudCB0byB0aGUgRE9NXG4gIG1vdW50KCcjYXBwJywgKCkgPT4gPGRpdj5IZWxsbyB3b3JsZDwvZGl2Pik7IC8vIEFwcCBpcyBhIEZ1bmN0aW9uYWwgQ29tcG9uZW50XG4gIG1vdW50KCcjYXBwJywgeyB2aWV3OiAoKSA9PiA8ZGl2PkhlbGxvIHdvcmxkPC9kaXY+IH0pOyAvLyBBcHAgaXMgYSBQT0pPIGNvbXBvbmVudCB3aXRoIGEgdmlldyBtZXRob2RcbiAgbW91bnQoJyNhcHAnLCBjbGFzc0luc3RhbmNlKTsgLy8gQXBwIGlzIGEgY2xhc3MgaW5zdGFuY2Ugd2l0aCBhIHZpZXcgbWV0aG9kXG4gIG1vdW50KCcjYXBwJywgPEFwcD48ZGl2PkhlbGxvIHdvcmxkPC9kaXY+PC9BcHA+KTsgLy8gQXBwIGlzIGEgVm5vZGUgY29tcG9uZW50IChWbm9kZSB3aXRoIHRhZyBfX2NvbXBvbmVudF9fKVxuKi9cblxuZXhwb3J0IGZ1bmN0aW9uIG1vdW50KGNvbnRhaW5lcjogRG9tRWxlbWVudCB8IHN0cmluZywgY29tcG9uZW50OiBWYWx5cmlhbkNvbXBvbmVudCB8IElWbm9kZSk6IHZvaWQgfCBzdHJpbmcge1xuICBsZXQgYXBwQ29udGFpbmVyID0gbnVsbDtcblxuICBpZiAoaXNOb2RlSnMpIHtcbiAgICBhcHBDb250YWluZXIgPSB0eXBlb2YgY29udGFpbmVyID09PSBcInN0cmluZ1wiID8gY3JlYXRlRG9tRWxlbWVudChjb250YWluZXIgPT09IFwic3ZnXCIgPyBcInN2Z1wiIDogXCJkaXZcIiwgY29udGFpbmVyID09PSBcInN2Z1wiKSA6IGNvbnRhaW5lcjtcbiAgfSBlbHNlIHtcbiAgICBhcHBDb250YWluZXIgPSB0eXBlb2YgY29udGFpbmVyID09PSBcInN0cmluZ1wiID8gZG9jdW1lbnQucXVlcnlTZWxlY3RvckFsbChjb250YWluZXIpWzBdIDogY29udGFpbmVyO1xuICB9XG5cbiAgaWYgKCFhcHBDb250YWluZXIpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoXCJDb250YWluZXIgbm90IGZvdW5kXCIpO1xuICB9XG5cbiAgbGV0IHZub2RlQ29tcG9uZW50OiBWbm9kZUNvbXBvbmVudCB8IElWbm9kZTtcblxuICBpZiAoaXNWbm9kZUNvbXBvbmVudChjb21wb25lbnQpKSB7XG4gICAgdm5vZGVDb21wb25lbnQgPSBjb21wb25lbnQ7XG4gIH0gZWxzZSBpZiAoaXNDb21wb25lbnQoY29tcG9uZW50KSkge1xuICAgIHZub2RlQ29tcG9uZW50ID0gdihjb21wb25lbnQsIHt9KTtcbiAgfSBlbHNlIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoXCJDb21wb25lbnQgbXVzdCBiZSBhIFZhbHlyaWFuIENvbXBvbmVudCBvciBhIFZub2RlIGNvbXBvbmVudFwiKTtcbiAgfVxuXG4gIGlmIChjb21wb25lbnRbVmFseXJpYW5TeW1ib2xdKSB7XG4gICAgdW5tb3VudChjb21wb25lbnQpO1xuICB9IGVsc2Uge1xuICAgIGNvbXBvbmVudFtWYWx5cmlhblN5bWJvbF0gPSB7XG4gICAgICBpc01vdW50ZWQ6IGZhbHNlLFxuICAgICAgZXZlbnRMaXN0ZW5lck5hbWVzOiB7fSxcbiAgICAgIG9uQ2xlYW51cDogW10sXG4gICAgICBvbk1vdW50OiBbXSxcbiAgICAgIG9uVXBkYXRlOiBbXSxcbiAgICAgIG9uVW5tb3VudDogW11cbiAgICB9O1xuICAgIGZ1bmN0aW9uIGV2ZW50TGlzdGVuZXIoZTogRXZlbnQpIHtcbiAgICAgIGxldCBkb20gPSBlLnRhcmdldCBhcyBEb21FbGVtZW50ICYgUmVjb3JkPHN0cmluZywgYW55PjtcbiAgICAgIGxldCBuYW1lID0gYHYtb24ke2UudHlwZX1gO1xuICAgICAgd2hpbGUgKGRvbSkge1xuICAgICAgICBpZiAoZG9tW25hbWVdKSB7XG4gICAgICAgICAgZG9tW25hbWVdKGUsIGRvbSk7XG4gICAgICAgICAgaWYgKCFlLmRlZmF1bHRQcmV2ZW50ZWQpIHtcbiAgICAgICAgICAgIHVwZGF0ZShjb21wb25lbnQpO1xuICAgICAgICAgIH1cbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgZG9tID0gZG9tLnBhcmVudE5vZGUgYXMgRG9tRWxlbWVudDtcbiAgICAgIH1cbiAgICB9XG4gICAgY29tcG9uZW50W1ZhbHlyaWFuU3ltYm9sXS5ldmVudExpc3RlbmVyID0gZXZlbnRMaXN0ZW5lcjtcbiAgfVxuXG4gIGNvbXBvbmVudFtWYWx5cmlhblN5bWJvbF0uY29tcG9uZW50ID0gdm5vZGVDb21wb25lbnQ7XG4gIGNvbXBvbmVudFtWYWx5cmlhblN5bWJvbF0uY29udGFpbmVyID0gYXBwQ29udGFpbmVyO1xuICBjb21wb25lbnRbVmFseXJpYW5TeW1ib2xdLm1haW5Wbm9kZSA9IGRvbVRvVm5vZGUoYXBwQ29udGFpbmVyKTtcbiAgY29tcG9uZW50W1ZhbHlyaWFuU3ltYm9sXS5tYWluVm5vZGUuaXNTVkcgPSBjb21wb25lbnRbVmFseXJpYW5TeW1ib2xdLnRhZyA9PT0gXCJzdmdcIjtcblxuICAvLyB1cGRhdGVcbiAgcmV0dXJuIHVwZGF0ZShjb21wb25lbnQpO1xufVxuXG5mdW5jdGlvbiBjYWxsQ2xlYW51cCh2YWx5cmlhbkFwcDogVmFseXJpYW5BcHApIHtcbiAgZm9yIChsZXQgaSA9IDA7IGkgPCB2YWx5cmlhbkFwcC5vbkNsZWFudXAubGVuZ3RoOyBpKyspIHtcbiAgICB2YWx5cmlhbkFwcC5vbkNsZWFudXBbaV0oKTtcbiAgfVxuICB2YWx5cmlhbkFwcC5vbkNsZWFudXAgPSBbXTtcbn1cblxuZnVuY3Rpb24gY2FsbFVubW91bnQodmFseXJpYW5BcHA6IFZhbHlyaWFuQXBwKSB7XG4gIGZvciAobGV0IGkgPSAwOyBpIDwgdmFseXJpYW5BcHAub25Vbm1vdW50Lmxlbmd0aDsgaSsrKSB7XG4gICAgdmFseXJpYW5BcHAub25Vbm1vdW50W2ldKCk7XG4gIH1cbiAgdmFseXJpYW5BcHAub25Vbm1vdW50ID0gW107XG59XG5cbmZ1bmN0aW9uIGNhbGxNb3VudCh2YWx5cmlhbkFwcDogVmFseXJpYW5BcHApIHtcbiAgZm9yIChsZXQgaSA9IDA7IGkgPCB2YWx5cmlhbkFwcC5vbk1vdW50Lmxlbmd0aDsgaSsrKSB7XG4gICAgdmFseXJpYW5BcHAub25Nb3VudFtpXSgpO1xuICB9XG4gIHZhbHlyaWFuQXBwLm9uTW91bnQgPSBbXTtcbn1cblxuZnVuY3Rpb24gY2FsbFVwZGF0ZSh2YWx5cmlhbkFwcDogVmFseXJpYW5BcHApIHtcbiAgZm9yIChsZXQgaSA9IDA7IGkgPCB2YWx5cmlhbkFwcC5vblVwZGF0ZS5sZW5ndGg7IGkrKykge1xuICAgIHZhbHlyaWFuQXBwLm9uVXBkYXRlW2ldKCk7XG4gIH1cbiAgdmFseXJpYW5BcHAub25VcGRhdGUgPSBbXTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHVwZGF0ZShjb21wb25lbnQ/OiBWYWx5cmlhbkNvbXBvbmVudCB8IElWbm9kZSk6IHZvaWQgfCBzdHJpbmcge1xuICBpZiAoY29tcG9uZW50ICYmIGNvbXBvbmVudFtWYWx5cmlhblN5bWJvbF0pIHtcbiAgICBsZXQgdmFseXJpYW5BcHAgPSBjb21wb25lbnRbVmFseXJpYW5TeW1ib2xdO1xuICAgIHYuY3VycmVudC5hcHAgPSB2YWx5cmlhbkFwcDtcbiAgICB2YWx5cmlhbkFwcC5vbkNsZWFudXAubGVuZ3RoICYmIGNhbGxDbGVhbnVwKHZhbHlyaWFuQXBwKTtcbiAgICBsZXQgb2xkVm5vZGU6IFZub2RlV2l0aERvbSB8IG51bGwgPSB2YWx5cmlhbkFwcC5tYWluVm5vZGUgYXMgVm5vZGVXaXRoRG9tO1xuICAgIHZhbHlyaWFuQXBwLm1haW5Wbm9kZSA9IG5ldyBWbm9kZSh2YWx5cmlhbkFwcC5tYWluVm5vZGUudGFnLCB2YWx5cmlhbkFwcC5tYWluVm5vZGUucHJvcHMsIFt2YWx5cmlhbkFwcC5jb21wb25lbnRdKSBhcyBWbm9kZVdpdGhEb207XG4gICAgdmFseXJpYW5BcHAubWFpblZub2RlLmRvbSA9IG9sZFZub2RlLmRvbTtcbiAgICB2YWx5cmlhbkFwcC5tYWluVm5vZGUuaXNTVkcgPSBvbGRWbm9kZS5pc1NWRztcbiAgICBwYXRjaCh2YWx5cmlhbkFwcC5tYWluVm5vZGUsIG9sZFZub2RlLCB2YWx5cmlhbkFwcCk7XG4gICAgb2xkVm5vZGUgPSBudWxsO1xuICAgIGlmICh2YWx5cmlhbkFwcC5pc01vdW50ZWQgPT09IGZhbHNlKSB7XG4gICAgICB2YWx5cmlhbkFwcC5vbk1vdW50Lmxlbmd0aCAmJiBjYWxsTW91bnQodmFseXJpYW5BcHApO1xuICAgICAgdmFseXJpYW5BcHAuaXNNb3VudGVkID0gdHJ1ZTtcbiAgICB9IGVsc2Uge1xuICAgICAgdmFseXJpYW5BcHAub25VcGRhdGUubGVuZ3RoICYmIGNhbGxVcGRhdGUodmFseXJpYW5BcHApO1xuICAgIH1cblxuICAgIGlmIChpc05vZGVKcykge1xuICAgICAgcmV0dXJuIHZhbHlyaWFuQXBwLm1haW5Wbm9kZS5kb20uaW5uZXJIVE1MO1xuICAgIH1cbiAgfVxufVxuXG5leHBvcnQgZnVuY3Rpb24gdW5tb3VudChjb21wb25lbnQ/OiBWYWx5cmlhbkNvbXBvbmVudCB8IElWbm9kZSk6IHZvaWQgfCBzdHJpbmcge1xuICBpZiAoIWNvbXBvbmVudCB8fCAhY29tcG9uZW50W1ZhbHlyaWFuU3ltYm9sXSkge1xuICAgIHJldHVybjtcbiAgfVxuXG4gIGxldCB2YWx5cmlhbkFwcCA9IGNvbXBvbmVudFtWYWx5cmlhblN5bWJvbF0gYXMgTW91bnRlZFZhbHlyaWFuQXBwO1xuXG4gIGlmICh2YWx5cmlhbkFwcC5pc01vdW50ZWQpIHtcbiAgICB2YWx5cmlhbkFwcC5vbkNsZWFudXAubGVuZ3RoICYmIGNhbGxDbGVhbnVwKHZhbHlyaWFuQXBwKTtcbiAgICB2YWx5cmlhbkFwcC5vblVubW91bnQubGVuZ3RoICYmIGNhbGxVbm1vdW50KHZhbHlyaWFuQXBwKTtcbiAgICBsZXQgb2xkVm5vZGU6IFZub2RlV2l0aERvbSB8IG51bGwgPSB2YWx5cmlhbkFwcC5tYWluVm5vZGUgYXMgVm5vZGVXaXRoRG9tO1xuICAgIHZhbHlyaWFuQXBwLm1haW5Wbm9kZSA9IG5ldyBWbm9kZSh2YWx5cmlhbkFwcC5tYWluVm5vZGUudGFnLCB2YWx5cmlhbkFwcC5tYWluVm5vZGUucHJvcHMsIFtdKSBhcyBWbm9kZVdpdGhEb207XG4gICAgdmFseXJpYW5BcHAubWFpblZub2RlLmRvbSA9IG9sZFZub2RlLmRvbTtcbiAgICB2YWx5cmlhbkFwcC5tYWluVm5vZGUuaXNTVkcgPSBvbGRWbm9kZS5pc1NWRztcbiAgICBwYXRjaCh2YWx5cmlhbkFwcC5tYWluVm5vZGUsIG9sZFZub2RlLCB2YWx5cmlhbkFwcCk7XG4gICAgb2xkVm5vZGUgPSBudWxsO1xuXG4gICAgaWYgKGlzTm9kZUpzKSB7XG4gICAgICByZXR1cm4gdmFseXJpYW5BcHAubWFpblZub2RlLmRvbS5pbm5lckhUTUw7XG4gICAgfVxuXG4gICAgKHZhbHlyaWFuQXBwIGFzIGFueSkgPSBudWxsO1xuICAgIFJlZmxlY3QuZGVsZXRlUHJvcGVydHkoY29tcG9uZW50LCBWYWx5cmlhblN5bWJvbCk7XG4gIH1cbn1cblxubGV0IGVtcHR5Vm5vZGUgPSBuZXcgVm5vZGUoXCJfX2VtcHR5X19cIiwge30sIFtdKTtcblxuZnVuY3Rpb24gb25yZW1vdmUodm5vZGU6IElWbm9kZSkge1xuICBmb3IgKGxldCBpID0gMDsgaSA8IHZub2RlLmNoaWxkcmVuLmxlbmd0aDsgaSsrKSB7XG4gICAgdm5vZGUuY2hpbGRyZW5baV0udGFnICE9PSBcIiN0ZXh0XCIgJiYgb25yZW1vdmUodm5vZGUuY2hpbGRyZW5baV0pO1xuICB9XG5cbiAgdm5vZGUucHJvcHMub25yZW1vdmUgJiYgdm5vZGUucHJvcHMub25yZW1vdmUodm5vZGUpO1xufVxuXG5mdW5jdGlvbiBzaGFyZWRTZXRBdHRyaWJ1dGUocHJvcDogc3RyaW5nLCB2YWx1ZTogYW55LCB2bm9kZTogVm5vZGVXaXRoRG9tLCBvbGRWbm9kZT86IFZub2RlV2l0aERvbSkge1xuICAvLyBJdCBpcyBhIHJlc2VydmVkIHByb3BcbiAgaWYgKHYucmVzZXJ2ZWRQcm9wc1twcm9wXSkge1xuICAgIC8vIElmIGl0IGlzIGEgZGlyZWN0aXZlIG5hbWUgY2FsbCB0aGUgZGlyZWN0aXZlXG4gICAgaWYgKHYuZGlyZWN0aXZlc1twcm9wXSkge1xuICAgICAgdi5kaXJlY3RpdmVzW3Byb3BdKHZub2RlLnByb3BzW3Byb3BdLCB2bm9kZSwgb2xkVm5vZGUpO1xuICAgIH1cbiAgICByZXR1cm47XG4gIH1cblxuICAvLyBJdCBpcyBub3QgYSByZXNlcnZlZCBwcm9wIHNvIHdlIGFkZCBpdCB0byB0aGUgZG9tXG4gIGlmICh0eXBlb2YgdmFsdWUgPT09IFwiZnVuY3Rpb25cIikge1xuICAgIGxldCB2YWx5cmlhbkFwcCA9IHYuY3VycmVudC5hcHAgYXMgTW91bnRlZFZhbHlyaWFuQXBwO1xuICAgIGlmIChwcm9wIGluIHZhbHlyaWFuQXBwLmV2ZW50TGlzdGVuZXJOYW1lcyA9PT0gZmFsc2UpIHtcbiAgICAgIHZhbHlyaWFuQXBwLmV2ZW50TGlzdGVuZXJOYW1lc1twcm9wXSA9IHRydWU7XG4gICAgICB2YWx5cmlhbkFwcC5jb250YWluZXIuYWRkRXZlbnRMaXN0ZW5lcihwcm9wLnNsaWNlKDIpLCB2YWx5cmlhbkFwcC5ldmVudExpc3RlbmVyKTtcbiAgICB9XG4gICAgdm5vZGUuZG9tW2B2LSR7cHJvcH1gXSA9IHZhbHVlO1xuICAgIHJldHVybjtcbiAgfVxuXG4gIGlmIChwcm9wIGluIHZub2RlLmRvbSAmJiB2bm9kZS5pc1NWRyA9PT0gZmFsc2UpIHtcbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgZXFlcWVxXG4gICAgaWYgKHZub2RlLmRvbVtwcm9wXSAhPSB2YWx1ZSkge1xuICAgICAgdm5vZGUuZG9tW3Byb3BdID0gdmFsdWU7XG4gICAgfVxuICAgIHJldHVybjtcbiAgfVxuXG4gIC8vIFVzZSBzZXQgYXR0cmlidXRlXG4gIGlmICghb2xkVm5vZGUgfHwgb2xkVm5vZGUucHJvcHNbcHJvcF0gIT09IHZhbHVlKSB7XG4gICAgaWYgKHZhbHVlID09PSBmYWxzZSkge1xuICAgICAgdm5vZGUuZG9tLnJlbW92ZUF0dHJpYnV0ZShwcm9wKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdm5vZGUuZG9tLnNldEF0dHJpYnV0ZShwcm9wLCB2YWx1ZSk7XG4gICAgfVxuICB9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBzZXRBdHRyaWJ1dGUobmFtZTogc3RyaW5nLCB2YWx1ZTogYW55LCB2bm9kZTogVm5vZGVXaXRoRG9tLCBvbGRWbm9kZT86IFZub2RlV2l0aERvbSkge1xuICBpZiAobmFtZSBpbiB2bm9kZS5wcm9wcyA9PT0gZmFsc2UpIHtcbiAgICB2bm9kZS5wcm9wc1tuYW1lXSA9IHZhbHVlO1xuICB9XG5cbiAgc2hhcmVkU2V0QXR0cmlidXRlKG5hbWUsIHZhbHVlLCB2bm9kZSwgb2xkVm5vZGUpO1xufVxuXG5mdW5jdGlvbiB1cGRhdGVBdHRyaWJ1dGVzKHZub2RlOiBWbm9kZVdpdGhEb20sIG9sZFZub2RlPzogVm5vZGVXaXRoRG9tKSB7XG4gIGZvciAobGV0IHByb3AgaW4gdm5vZGUucHJvcHMpIHtcbiAgICAvLyBXZSBhc3VtZSB0aGF0IHdlIGNsZWFuIHRoZSBwcm9wcyBpbiBzb21lIGRpcmVjdGl2ZVxuICAgIGlmIChwcm9wIGluIHZub2RlLnByb3BzID09PSBmYWxzZSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHNoYXJlZFNldEF0dHJpYnV0ZShwcm9wLCB2bm9kZS5wcm9wc1twcm9wXSwgdm5vZGUsIG9sZFZub2RlKTtcbiAgfVxuXG4gIGlmIChvbGRWbm9kZSkge1xuICAgIGZvciAobGV0IHByb3AgaW4gb2xkVm5vZGUucHJvcHMpIHtcbiAgICAgIGlmIChwcm9wIGluIHZub2RlLnByb3BzID09PSBmYWxzZSAmJiB0eXBlb2Ygb2xkVm5vZGUucHJvcHNbcHJvcF0gIT09IFwiZnVuY3Rpb25cIiAmJiBwcm9wIGluIHYucmVzZXJ2ZWRQcm9wcyA9PT0gZmFsc2UpIHtcbiAgICAgICAgaWYgKHByb3AgaW4gb2xkVm5vZGUuZG9tICYmIHZub2RlLmlzU1ZHID09PSBmYWxzZSkge1xuICAgICAgICAgIG9sZFZub2RlLmRvbVtwcm9wXSA9IG51bGw7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgb2xkVm5vZGUuZG9tLnJlbW92ZUF0dHJpYnV0ZShwcm9wKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgfVxufVxuXG5mdW5jdGlvbiBmbGF0VHJlZShuZXdWbm9kZTogSVZub2RlKTogdm9pZCB7XG4gIGxldCBuZXdUcmVlID0gbmV3Vm5vZGUuY2hpbGRyZW47XG4gIGZvciAobGV0IGkgPSAwOyBpIDwgbmV3VHJlZS5sZW5ndGg7IGkrKykge1xuICAgIGxldCBjaGlsZFZub2RlID0gbmV3VHJlZVtpXTtcbiAgICBpZiAoY2hpbGRWbm9kZSBpbnN0YW5jZW9mIFZub2RlKSB7XG4gICAgICBpZiAoY2hpbGRWbm9kZS50YWcgIT09IFwiI3RleHRcIikge1xuICAgICAgICBpZiAoY2hpbGRWbm9kZS50YWcgPT09IFwiX19jb21wb25lbnRfX1wiKSB7XG4gICAgICAgICAgbGV0IGNvbXBvbmVudCA9IGNoaWxkVm5vZGUuY29tcG9uZW50IGFzIFZhbHlyaWFuQ29tcG9uZW50O1xuICAgICAgICAgIHYuY3VycmVudC5jb21wb25lbnQgPSBjb21wb25lbnQ7XG4gICAgICAgICAgbGV0IHJlc3VsdCA9IChcInZpZXdcIiBpbiBjb21wb25lbnQgPyBjb21wb25lbnQudmlldyA6IGNvbXBvbmVudCkuY2FsbChjb21wb25lbnQsIGNoaWxkVm5vZGUucHJvcHMsIC4uLmNoaWxkVm5vZGUuY2hpbGRyZW4pO1xuXG4gICAgICAgICAgbmV3VHJlZS5zcGxpY2UoaS0tLCAxLCByZXN1bHQpO1xuICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICB9XG4gICAgICAgIGNoaWxkVm5vZGUuaXNTVkcgPSBuZXdWbm9kZS5pc1NWRyB8fCBjaGlsZFZub2RlLnRhZyA9PT0gXCJzdmdcIjtcbiAgICAgIH1cbiAgICB9IGVsc2UgaWYgKGNoaWxkVm5vZGUgPT09IG51bGwgfHwgY2hpbGRWbm9kZSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICBuZXdUcmVlLnNwbGljZShpLS0sIDEpO1xuICAgIH0gZWxzZSBpZiAoQXJyYXkuaXNBcnJheShjaGlsZFZub2RlKSkge1xuICAgICAgbmV3VHJlZS5zcGxpY2UoaS0tLCAxLCAuLi5jaGlsZFZub2RlKTtcbiAgICB9IGVsc2Uge1xuICAgICAgaWYgKGkgPiAwICYmIG5ld1RyZWVbaSAtIDFdLnRhZyA9PT0gXCIjdGV4dFwiKSB7XG4gICAgICAgIG5ld1RyZWVbaSAtIDFdLm5vZGVWYWx1ZSArPSBjaGlsZFZub2RlO1xuICAgICAgICBuZXdUcmVlLnNwbGljZShpLS0sIDEpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgbmV3VHJlZVtpXSA9IG5ldyBWbm9kZShcIiN0ZXh0XCIsIHt9LCBbXSk7XG4gICAgICAgIG5ld1RyZWVbaV0ubm9kZVZhbHVlID0gU3RyaW5nKGNoaWxkVm5vZGUpO1xuICAgICAgfVxuICAgIH1cbiAgfVxufVxuXG5mdW5jdGlvbiBwYXRjaEtleWVkVHJlZShcbiAgbmV3Vm5vZGU6IFZub2RlV2l0aERvbSxcbiAgbmV3VHJlZTogKFZub2RlV2l0aERvbSAmIHsgcHJvcHM6IFByb3BzICYgeyBrZXk6IHN0cmluZyB9IH0pW10sXG4gIG9sZFRyZWU6IChWbm9kZVdpdGhEb20gJiB7IHByb3BzOiBQcm9wcyAmIHsga2V5OiBzdHJpbmcgfSB9KVtdLFxuICBuZXdUcmVlTGVuZ3RoOiBudW1iZXIsXG4gIG9sZFRyZWVMZW5ndGg6IG51bWJlcixcbiAgdmFseXJpYW5BcHA6IE1vdW50ZWRWYWx5cmlhbkFwcFxuKSB7XG4gIGxldCBvbGRLZXllZExpc3QgPSBvbGRUcmVlLnJlZHVjZSgoYWNjLCB2bm9kZSwgaSkgPT4ge1xuICAgIGFjY1t2bm9kZS5wcm9wcy5rZXldID0gaTtcbiAgICByZXR1cm4gYWNjO1xuICB9LCB7fSBhcyB7IFtrZXk6IHN0cmluZ106IG51bWJlciB9KTtcbiAgbGV0IG5ld0tleWVkTGlzdCA9IG5ld1RyZWUucmVkdWNlKChhY2MsIHZub2RlLCBpKSA9PiB7XG4gICAgYWNjW3Zub2RlLnByb3BzLmtleV0gPSBpO1xuICAgIHJldHVybiBhY2M7XG4gIH0sIHt9IGFzIHsgW2tleTogc3RyaW5nXTogbnVtYmVyIH0pO1xuXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgbmV3VHJlZUxlbmd0aDsgaSsrKSB7XG4gICAgbGV0IGNoaWxkVm5vZGUgPSBuZXdUcmVlW2ldO1xuICAgIGxldCBvbGRDaGlsZFZub2RlID0gb2xkVHJlZVtvbGRLZXllZExpc3RbY2hpbGRWbm9kZS5wcm9wcy5rZXldXTtcbiAgICBsZXQgc2hvdWxkUGF0Y2ggPSB0cnVlO1xuXG4gICAgaWYgKG9sZENoaWxkVm5vZGUpIHtcbiAgICAgIGNoaWxkVm5vZGUuZG9tID0gb2xkQ2hpbGRWbm9kZS5kb207XG4gICAgICBpZiAoXCJ2LW9uY2VcIiBpbiBjaGlsZFZub2RlLnByb3BzIHx8IChjaGlsZFZub2RlLnByb3BzLnNob3VsZHVwZGF0ZSAmJiBjaGlsZFZub2RlLnByb3BzLnNob3VsZHVwZGF0ZShjaGlsZFZub2RlLCBvbGRDaGlsZFZub2RlKSA9PT0gZmFsc2UpKSB7XG4gICAgICAgIC8vIHNraXAgdGhpcyBwYXRjaFxuICAgICAgICBjaGlsZFZub2RlLmNoaWxkcmVuID0gb2xkQ2hpbGRWbm9kZS5jaGlsZHJlbjtcbiAgICAgICAgc2hvdWxkUGF0Y2ggPSBmYWxzZTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHVwZGF0ZUF0dHJpYnV0ZXMoY2hpbGRWbm9kZSwgb2xkQ2hpbGRWbm9kZSk7XG4gICAgICAgIGlmICh2YWx5cmlhbkFwcC5pc01vdW50ZWQpIHtcbiAgICAgICAgICBjaGlsZFZub2RlLnByb3BzLm9udXBkYXRlICYmIGNoaWxkVm5vZGUucHJvcHMub251cGRhdGUoY2hpbGRWbm9kZSwgb2xkQ2hpbGRWbm9kZSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgY2hpbGRWbm9kZS5wcm9wcy5vbmNyZWF0ZSAmJiBjaGlsZFZub2RlLnByb3BzLm9uY3JlYXRlKGNoaWxkVm5vZGUpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIGNoaWxkVm5vZGUuZG9tID0gY3JlYXRlRG9tRWxlbWVudChjaGlsZFZub2RlLnRhZywgY2hpbGRWbm9kZS5pc1NWRyk7XG4gICAgICB1cGRhdGVBdHRyaWJ1dGVzKGNoaWxkVm5vZGUpO1xuICAgICAgY2hpbGRWbm9kZS5wcm9wcy5vbmNyZWF0ZSAmJiBjaGlsZFZub2RlLnByb3BzLm9uY3JlYXRlKGNoaWxkVm5vZGUpO1xuICAgIH1cblxuICAgIGlmIChuZXdWbm9kZS5kb20uY2hpbGROb2Rlc1tpXSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICBuZXdWbm9kZS5kb20uYXBwZW5kQ2hpbGQoY2hpbGRWbm9kZS5kb20pO1xuICAgIH0gZWxzZSBpZiAobmV3Vm5vZGUuZG9tLmNoaWxkTm9kZXNbaV0gIT09IGNoaWxkVm5vZGUuZG9tKSB7XG4gICAgICBvbGRUcmVlW2ldICYmIG5ld0tleWVkTGlzdFtvbGRUcmVlW2ldLnByb3BzLmtleV0gPT09IHVuZGVmaW5lZCAmJiBvbnJlbW92ZShvbGRUcmVlW2ldKTtcbiAgICAgIG5ld1Zub2RlLmRvbS5yZXBsYWNlQ2hpbGQoY2hpbGRWbm9kZS5kb20sIG5ld1Zub2RlLmRvbS5jaGlsZE5vZGVzW2ldKTtcbiAgICB9XG5cbiAgICBzaG91bGRQYXRjaCAmJiBwYXRjaChjaGlsZFZub2RlLCBvbGRDaGlsZFZub2RlLCB2YWx5cmlhbkFwcCk7XG4gIH1cblxuICAvLyBGb3IgdGhlIHJlc3Qgb2YgdGhlIGNoaWxkcmVuLCB3ZSBzaG91bGQgcmVtb3ZlIHRoZW1cbiAgZm9yIChsZXQgaSA9IG5ld1RyZWVMZW5ndGg7IGkgPCBvbGRUcmVlTGVuZ3RoOyBpKyspIHtcbiAgICBpZiAobmV3S2V5ZWRMaXN0W29sZFRyZWVbaV0ucHJvcHMua2V5XSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICBsZXQgb2xkQ2hpbGRWbm9kZSA9IG9sZFRyZWVbaV07XG4gICAgICBvbnJlbW92ZShvbGRDaGlsZFZub2RlKTtcbiAgICAgIG9sZENoaWxkVm5vZGUuZG9tLnBhcmVudE5vZGUgJiYgb2xkQ2hpbGRWbm9kZS5kb20ucGFyZW50Tm9kZS5yZW1vdmVDaGlsZChvbGRDaGlsZFZub2RlLmRvbSk7XG4gICAgfVxuICB9XG59XG5cbi8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBjb21wbGV4aXR5XG5mdW5jdGlvbiBwYXRjaE5vcm1hbFRyZWUoXG4gIG5ld1Zub2RlOiBWbm9kZVdpdGhEb20sXG4gIG5ld1RyZWU6IChWbm9kZVdpdGhEb20gJiB7IHByb3BzOiBQcm9wcyAmIHsga2V5OiBzdHJpbmcgfSB9KVtdLFxuICBvbGRUcmVlOiAoVm5vZGVXaXRoRG9tICYgeyBwcm9wczogUHJvcHMgJiB7IGtleTogc3RyaW5nIH0gfSlbXSxcbiAgbmV3VHJlZUxlbmd0aDogbnVtYmVyLFxuICBvbGRUcmVlTGVuZ3RoOiBudW1iZXIsXG4gIHZhbHlyaWFuQXBwOiBNb3VudGVkVmFseXJpYW5BcHBcbikge1xuICAvLyBJZiBuZXcgdHJlZSBhbmQgb2xkIHRyZWUgaGF2ZSBtb3JlIHRoYW4gb25lIGNoaWxkLCB3ZSBzaG91bGQgdXBkYXRlIHRoZSBkb21cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBuZXdUcmVlTGVuZ3RoOyBpKyspIHtcbiAgICBsZXQgb2xkQ2hpbGRWbm9kZSA9IG9sZFRyZWVbaV07XG4gICAgbGV0IG5ld0NoaWxkVm5vZGUgPSBuZXdUcmVlW2ldO1xuXG4gICAgLy8gT2xkIGNoaWxkIGRvZXMgbm90IGV4aXN0c1xuICAgIGlmICghb2xkQ2hpbGRWbm9kZSkge1xuICAgICAgLy8gTmV3IGNoaWxkIGlzIGEgdGV4dCBub2RlXG4gICAgICBpZiAobmV3Q2hpbGRWbm9kZS50YWcgPT09IFwiI3RleHRcIikge1xuICAgICAgICBuZXdDaGlsZFZub2RlLmRvbSA9IGRvY3VtZW50LmNyZWF0ZVRleHROb2RlKG5ld0NoaWxkVm5vZGUubm9kZVZhbHVlIGFzIHN0cmluZykgYXMgdW5rbm93biBhcyBEb21FbGVtZW50O1xuICAgICAgICBuZXdWbm9kZS5kb20uYXBwZW5kQ2hpbGQobmV3Q2hpbGRWbm9kZS5kb20pO1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cblxuICAgICAgLy8gTmV3IGNoaWxkIGlzIGEgbm9ybWFsIG5vZGVcbiAgICAgIG5ld0NoaWxkVm5vZGUuZG9tID0gY3JlYXRlRG9tRWxlbWVudChuZXdDaGlsZFZub2RlLnRhZywgbmV3Q2hpbGRWbm9kZS5pc1NWRyk7XG4gICAgICB1cGRhdGVBdHRyaWJ1dGVzKG5ld0NoaWxkVm5vZGUpO1xuICAgICAgbmV3Vm5vZGUuZG9tLmFwcGVuZENoaWxkKG5ld0NoaWxkVm5vZGUuZG9tKTtcbiAgICAgIG5ld0NoaWxkVm5vZGUucHJvcHMub25jcmVhdGUgJiYgbmV3Q2hpbGRWbm9kZS5wcm9wcy5vbmNyZWF0ZShuZXdDaGlsZFZub2RlKTtcbiAgICAgIHBhdGNoKG5ld0NoaWxkVm5vZGUsIHVuZGVmaW5lZCwgdmFseXJpYW5BcHApO1xuICAgICAgY29udGludWU7XG4gICAgfVxuXG4gICAgLy8gT2xkIGNoaWxkIGV4aXN0c1xuICAgIC8vIE5ldyBjaGlsZCBpcyBhIHRleHQgbm9kZVxuICAgIGlmIChuZXdDaGlsZFZub2RlLnRhZyA9PT0gXCIjdGV4dFwiKSB7XG4gICAgICAvLyBPbGQgY2hpbGQgaXMgYSB0ZXh0IG5vZGVcbiAgICAgIGlmIChvbGRDaGlsZFZub2RlLnRhZyA9PT0gXCIjdGV4dFwiKSB7XG4gICAgICAgIG5ld0NoaWxkVm5vZGUuZG9tID0gb2xkQ2hpbGRWbm9kZS5kb207XG4gICAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBlcWVxZXFcbiAgICAgICAgaWYgKG5ld0NoaWxkVm5vZGUuZG9tLm5vZGVWYWx1ZSAhPSBuZXdDaGlsZFZub2RlLm5vZGVWYWx1ZSkge1xuICAgICAgICAgIG5ld0NoaWxkVm5vZGUuZG9tLm5vZGVWYWx1ZSA9IG5ld0NoaWxkVm5vZGUubm9kZVZhbHVlIGFzIHN0cmluZztcbiAgICAgICAgfVxuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cblxuICAgICAgLy8gT2xkIGNoaWxkIGlzIGEgbm9ybWFsIG5vZGVcbiAgICAgIG5ld0NoaWxkVm5vZGUuZG9tID0gZG9jdW1lbnQuY3JlYXRlVGV4dE5vZGUobmV3Q2hpbGRWbm9kZS5ub2RlVmFsdWUgYXMgc3RyaW5nKSBhcyB1bmtub3duIGFzIERvbUVsZW1lbnQ7XG4gICAgICBvbnJlbW92ZShvbGRDaGlsZFZub2RlKTtcbiAgICAgIG5ld1Zub2RlLmRvbS5yZXBsYWNlQ2hpbGQobmV3Q2hpbGRWbm9kZS5kb20sIG9sZENoaWxkVm5vZGUuZG9tKTtcblxuICAgICAgY29udGludWU7XG4gICAgfVxuXG4gICAgLy8gTmV3IGNoaWxkIGlzIGEgbm9ybWFsIG5vZGVcbiAgICAvLyBPbGQgY2hpbGQgaXMgdGhlIHNhbWUgdHlwZSBhcyBuZXcgY2hpbGRcbiAgICBpZiAob2xkQ2hpbGRWbm9kZS50YWcgPT09IG5ld0NoaWxkVm5vZGUudGFnKSB7XG4gICAgICBuZXdDaGlsZFZub2RlLmRvbSA9IG9sZENoaWxkVm5vZGUuZG9tO1xuICAgICAgLy8gSWYgd2UgaGF2ZSBhIHYtb25jZSBkaXJlY3RpdmUgb3IgYSBzaG91bGR1cGRhdGUgbWV0aG9kIHRoYXQgcmV0dXJucyBmYWxzZSwgd2Ugc2tpcCB0aGUgdXBkYXRlXG4gICAgICBpZiAobmV3Q2hpbGRWbm9kZS5wcm9wc1tcInYtb25jZVwiXSB8fCAobmV3Q2hpbGRWbm9kZS5wcm9wcy5zaG91bGR1cGRhdGUgJiYgbmV3Q2hpbGRWbm9kZS5wcm9wcy5zaG91bGR1cGRhdGUobmV3Q2hpbGRWbm9kZSwgb2xkQ2hpbGRWbm9kZSkgPT09IGZhbHNlKSkge1xuICAgICAgICBuZXdDaGlsZFZub2RlLmNoaWxkcmVuID0gb2xkQ2hpbGRWbm9kZS5jaGlsZHJlbjtcbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG5cbiAgICAgIC8vIFdlIHVwZGF0ZSB0aGUgZG9tIGVsZW1lbnRcbiAgICAgIHVwZGF0ZUF0dHJpYnV0ZXMobmV3Q2hpbGRWbm9kZSwgb2xkQ2hpbGRWbm9kZSk7XG4gICAgICBpZiAodmFseXJpYW5BcHAgJiYgdmFseXJpYW5BcHAuaXNNb3VudGVkKSB7XG4gICAgICAgIG5ld0NoaWxkVm5vZGUucHJvcHMub251cGRhdGUgJiYgbmV3Q2hpbGRWbm9kZS5wcm9wcy5vbnVwZGF0ZShuZXdDaGlsZFZub2RlLCBvbGRDaGlsZFZub2RlKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIG5ld0NoaWxkVm5vZGUucHJvcHMub25jcmVhdGUgJiYgbmV3Q2hpbGRWbm9kZS5wcm9wcy5vbmNyZWF0ZShuZXdDaGlsZFZub2RlKTtcbiAgICAgIH1cbiAgICAgIHBhdGNoKG5ld0NoaWxkVm5vZGUsIG9sZENoaWxkVm5vZGUsIHZhbHlyaWFuQXBwKTtcblxuICAgICAgY29udGludWU7XG4gICAgfVxuXG4gICAgLy8gT2xkIGNoaWxkIGlzIG9mIGEgZGlmZmVyZW50IHR5cGUgdGhhbiBuZXcgY2hpbGRcbiAgICBuZXdDaGlsZFZub2RlLmRvbSA9IGNyZWF0ZURvbUVsZW1lbnQobmV3Q2hpbGRWbm9kZS50YWcsIG5ld0NoaWxkVm5vZGUuaXNTVkcpO1xuICAgIHVwZGF0ZUF0dHJpYnV0ZXMobmV3Q2hpbGRWbm9kZSk7XG4gICAgaWYgKG9sZENoaWxkVm5vZGUudGFnICE9PSBcIiN0ZXh0XCIpIHtcbiAgICAgIG9ucmVtb3ZlKG9sZENoaWxkVm5vZGUpO1xuICAgIH1cbiAgICBuZXdDaGlsZFZub2RlLnByb3BzLm9uY3JlYXRlICYmIG5ld0NoaWxkVm5vZGUucHJvcHMub25jcmVhdGUobmV3Q2hpbGRWbm9kZSk7XG4gICAgbmV3Vm5vZGUuZG9tLnJlcGxhY2VDaGlsZChuZXdDaGlsZFZub2RlLmRvbSwgb2xkQ2hpbGRWbm9kZS5kb20pO1xuICAgIHBhdGNoKG5ld0NoaWxkVm5vZGUsIHVuZGVmaW5lZCwgdmFseXJpYW5BcHApO1xuICB9XG5cbiAgLy8gRm9yIHRoZSByZXN0IG9mIHRoZSBjaGlsZHJlbiwgd2Ugc2hvdWxkIHJlbW92ZSB0aGVtXG4gIGZvciAobGV0IGkgPSBuZXdUcmVlTGVuZ3RoOyBpIDwgb2xkVHJlZUxlbmd0aDsgaSsrKSB7XG4gICAgbGV0IG9sZENoaWxkVm5vZGUgPSBvbGRUcmVlW2ldO1xuICAgIGlmIChvbGRDaGlsZFZub2RlLnRhZyAhPT0gXCIjdGV4dFwiKSB7XG4gICAgICBvbnJlbW92ZShvbGRDaGlsZFZub2RlKTtcbiAgICB9XG4gICAgb2xkQ2hpbGRWbm9kZS5kb20ucGFyZW50Tm9kZSAmJiBvbGRDaGlsZFZub2RlLmRvbS5wYXJlbnROb2RlLnJlbW92ZUNoaWxkKG9sZENoaWxkVm5vZGUuZG9tKTtcbiAgfVxufVxuXG4vLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgY29tcGxleGl0eVxuZnVuY3Rpb24gcGF0Y2gobmV3Vm5vZGU6IFZub2RlV2l0aERvbSwgb2xkVm5vZGU6IFZub2RlV2l0aERvbSA9IGVtcHR5Vm5vZGUgYXMgVm5vZGVXaXRoRG9tLCB2YWx5cmlhbkFwcDogTW91bnRlZFZhbHlyaWFuQXBwKSB7XG4gIHYuY3VycmVudC52bm9kZSA9IG5ld1Zub2RlO1xuICB2LmN1cnJlbnQub2xkVm5vZGUgPSBvbGRWbm9kZTtcblxuICBmbGF0VHJlZShuZXdWbm9kZSk7XG5cbiAgbGV0IG5ld1RyZWUgPSBuZXdWbm9kZS5jaGlsZHJlbjtcbiAgbGV0IG9sZFRyZWUgPSBvbGRWbm9kZS5jaGlsZHJlbjtcbiAgbGV0IG9sZFRyZWVMZW5ndGggPSBvbGRUcmVlLmxlbmd0aDtcbiAgbGV0IG5ld1RyZWVMZW5ndGggPSBuZXdUcmVlLmxlbmd0aDtcblxuICAvLyBJZiBuZXcgdHJlZSBpcyBlbXB0eSwgcmVtb3ZlIGFsbCBvbGQgbm9kZXNcbiAgaWYgKG5ld1RyZWVMZW5ndGggPT09IDApIHtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IG9sZFRyZWVMZW5ndGg7IGkrKykge1xuICAgICAgb25yZW1vdmUob2xkVHJlZVtpXSk7XG4gICAgfVxuXG4gICAgbmV3Vm5vZGUuZG9tLnRleHRDb250ZW50ID0gXCJcIjtcbiAgICByZXR1cm47XG4gIH1cblxuICAvLyBJZiB0aGUgdHJlZSBpcyBrZXllZCBsaXN0IGFuZCBpcyBub3QgZmlyc3QgcmVuZGVyIGFuZCBvbGQgdHJlZSBpcyBrZXllZCBsaXN0IHRvb1xuICBpZiAob2xkVHJlZUxlbmd0aCAmJiBcImtleVwiIGluIG5ld1RyZWVbMF0ucHJvcHMgJiYgXCJrZXlcIiBpbiBvbGRUcmVlWzBdLnByb3BzKSB7XG4gICAgcGF0Y2hLZXllZFRyZWUobmV3Vm5vZGUsIG5ld1RyZWUsIG9sZFRyZWUsIG5ld1RyZWVMZW5ndGgsIG9sZFRyZWVMZW5ndGgsIHZhbHlyaWFuQXBwKTtcbiAgICByZXR1cm47XG4gIH1cblxuICBwYXRjaE5vcm1hbFRyZWUobmV3Vm5vZGUsIG5ld1RyZWUsIG9sZFRyZWUsIG5ld1RyZWVMZW5ndGgsIG9sZFRyZWVMZW5ndGgsIHZhbHlyaWFuQXBwKTtcbn1cblxuLyoqKiBEaXJlY3RpdmVzICoqKi9cblxuZXhwb3J0IGZ1bmN0aW9uIGRpcmVjdGl2ZShuYW1lOiBzdHJpbmcsIGRpcmVjdGl2ZTogRGlyZWN0aXZlKSB7XG4gIGxldCBmdWxsTmFtZSA9IGB2LSR7bmFtZX1gO1xuICB2LmRpcmVjdGl2ZXNbZnVsbE5hbWVdID0gZGlyZWN0aXZlO1xuICB2LnJlc2VydmVkUHJvcHNbZnVsbE5hbWVdID0gdHJ1ZTtcbn1cblxuZnVuY3Rpb24gaGlkZURpcmVjdGl2ZSh0ZXN0OiBib29sZWFuKTogRGlyZWN0aXZlIHtcbiAgcmV0dXJuIChib29sOiBib29sZWFuLCB2bm9kZTogSVZub2RlLCBvbGRWbm9kZT86IElWbm9kZSkgPT4ge1xuICAgIGxldCB2YWx1ZSA9IHRlc3QgPyBib29sIDogIWJvb2w7XG4gICAgaWYgKHZhbHVlKSB7XG4gICAgICBsZXQgbmV3ZG9tID0gZG9jdW1lbnQuY3JlYXRlVGV4dE5vZGUoXCJcIik7XG4gICAgICBpZiAob2xkVm5vZGUgJiYgb2xkVm5vZGUuZG9tICYmIG9sZFZub2RlLmRvbS5wYXJlbnROb2RlKSB7XG4gICAgICAgIG9sZFZub2RlLnRhZyAhPT0gXCIjdGV4dFwiICYmIG9ucmVtb3ZlKG9sZFZub2RlKTtcbiAgICAgICAgb2xkVm5vZGUuZG9tLnBhcmVudE5vZGUucmVwbGFjZUNoaWxkKG5ld2RvbSwgb2xkVm5vZGUuZG9tKTtcbiAgICAgIH1cbiAgICAgIHZub2RlLnRhZyA9IFwiI3RleHRcIjtcbiAgICAgIHZub2RlLmNoaWxkcmVuID0gW107XG4gICAgICB2bm9kZS5wcm9wcyA9IHt9O1xuICAgICAgdm5vZGUuZG9tID0gbmV3ZG9tIGFzIHVua25vd24gYXMgRG9tRWxlbWVudDtcbiAgICB9XG4gIH07XG59XG5cbmNvbnN0IGJ1aWx0SW5EaXJlY3RpdmVzID0ge1xuICBcInYtaWZcIjogaGlkZURpcmVjdGl2ZShmYWxzZSksXG4gIFwidi11bmxlc3NcIjogaGlkZURpcmVjdGl2ZSh0cnVlKSxcbiAgXCJ2LWZvclwiOiAoc2V0OiB1bmtub3duW10sIHZub2RlOiBWbm9kZVdpdGhEb20pID0+IHtcbiAgICB2bm9kZS5jaGlsZHJlbiA9IHNldC5tYXAodm5vZGUuY2hpbGRyZW5bMF0gYXMgKHZhbHVlOiB1bmtub3duKSA9PiBGdW5jdGlvbik7XG4gIH0sXG4gIFwidi1zaG93XCI6IChib29sOiBib29sZWFuLCB2bm9kZTogVm5vZGVXaXRoRG9tKSA9PiB7XG4gICAgKHZub2RlLmRvbSBhcyB1bmtub3duIGFzIHsgc3R5bGU6IHsgZGlzcGxheTogc3RyaW5nIH0gfSkuc3R5bGUuZGlzcGxheSA9IGJvb2wgPyBcIlwiIDogXCJub25lXCI7XG4gIH0sXG4gIFwidi1jbGFzc1wiOiAoY2xhc3NlczogeyBbeDogc3RyaW5nXTogYm9vbGVhbiB9LCB2bm9kZTogVm5vZGVXaXRoRG9tKSA9PiB7XG4gICAgZm9yIChsZXQgbmFtZSBpbiBjbGFzc2VzKSB7XG4gICAgICAodm5vZGUuZG9tIGFzIERvbUVsZW1lbnQpLmNsYXNzTGlzdC50b2dnbGUobmFtZSwgY2xhc3Nlc1tuYW1lXSk7XG4gICAgfVxuICB9LFxuICBcInYtaHRtbFwiOiAoaHRtbDogc3RyaW5nLCB2bm9kZTogVm5vZGVXaXRoRG9tKSA9PiB7XG4gICAgdm5vZGUuY2hpbGRyZW4gPSBbdHJ1c3QoaHRtbCldO1xuICB9LFxuICBcInYtbW9kZWxcIjogKFttb2RlbCwgcHJvcGVydHksIGV2ZW50XTogYW55W10sIHZub2RlOiBWbm9kZVdpdGhEb20sIG9sZFZub2RlPzogVm5vZGVXaXRoRG9tKSA9PiB7XG4gICAgbGV0IHZhbHVlO1xuICAgIGxldCBoYW5kbGVyO1xuICAgIGlmICh2bm9kZS5uYW1lID09PSBcImlucHV0XCIpIHtcbiAgICAgIGV2ZW50ID0gZXZlbnQgfHwgXCJvbmlucHV0XCI7XG4gICAgICBzd2l0Y2ggKHZub2RlLnByb3BzLnR5cGUpIHtcbiAgICAgICAgY2FzZSBcImNoZWNrYm94XCI6IHtcbiAgICAgICAgICBpZiAoQXJyYXkuaXNBcnJheShtb2RlbFtwcm9wZXJ0eV0pKSB7XG4gICAgICAgICAgICBoYW5kbGVyID0gKGU6IEV2ZW50KSA9PiB7XG4gICAgICAgICAgICAgIGxldCB2YWwgPSAoZS50YXJnZXQgYXMgRG9tRWxlbWVudCAmIFJlY29yZDxzdHJpbmcsIGFueT4pLnZhbHVlO1xuICAgICAgICAgICAgICBsZXQgaWR4ID0gbW9kZWxbcHJvcGVydHldLmluZGV4T2YodmFsKTtcbiAgICAgICAgICAgICAgaWYgKGlkeCA9PT0gLTEpIHtcbiAgICAgICAgICAgICAgICBtb2RlbFtwcm9wZXJ0eV0ucHVzaCh2YWwpO1xuICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIG1vZGVsW3Byb3BlcnR5XS5zcGxpY2UoaWR4LCAxKTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIHZhbHVlID0gbW9kZWxbcHJvcGVydHldLmluZGV4T2Yodm5vZGUuZG9tLnZhbHVlKSAhPT0gLTE7XG4gICAgICAgICAgfSBlbHNlIGlmIChcInZhbHVlXCIgaW4gdm5vZGUucHJvcHMpIHtcbiAgICAgICAgICAgIGhhbmRsZXIgPSAoKSA9PiB7XG4gICAgICAgICAgICAgIGlmIChtb2RlbFtwcm9wZXJ0eV0gPT09IHZub2RlLnByb3BzLnZhbHVlKSB7XG4gICAgICAgICAgICAgICAgbW9kZWxbcHJvcGVydHldID0gbnVsbDtcbiAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBtb2RlbFtwcm9wZXJ0eV0gPSB2bm9kZS5wcm9wcy52YWx1ZTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIHZhbHVlID0gbW9kZWxbcHJvcGVydHldID09PSB2bm9kZS5wcm9wcy52YWx1ZTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgaGFuZGxlciA9ICgpID0+IChtb2RlbFtwcm9wZXJ0eV0gPSAhbW9kZWxbcHJvcGVydHldKTtcbiAgICAgICAgICAgIHZhbHVlID0gbW9kZWxbcHJvcGVydHldO1xuICAgICAgICAgIH1cbiAgICAgICAgICBzZXRBdHRyaWJ1dGUoXCJjaGVja2VkXCIsIHZhbHVlLCB2bm9kZSwgb2xkVm5vZGUpO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgICAgIGNhc2UgXCJyYWRpb1wiOiB7XG4gICAgICAgICAgc2V0QXR0cmlidXRlKFwiY2hlY2tlZFwiLCBtb2RlbFtwcm9wZXJ0eV0gPT09IHZub2RlLmRvbS52YWx1ZSwgdm5vZGUsIG9sZFZub2RlKTtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgICAgICBkZWZhdWx0OiB7XG4gICAgICAgICAgc2V0QXR0cmlidXRlKFwidmFsdWVcIiwgbW9kZWxbcHJvcGVydHldLCB2bm9kZSwgb2xkVm5vZGUpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSBlbHNlIGlmICh2bm9kZS5uYW1lID09PSBcInNlbGVjdFwiKSB7XG4gICAgICBldmVudCA9IGV2ZW50IHx8IFwib25jbGlja1wiO1xuICAgICAgaWYgKHZub2RlLnByb3BzLm11bHRpcGxlKSB7XG4gICAgICAgIGhhbmRsZXIgPSAoZTogRXZlbnQgJiBSZWNvcmQ8c3RyaW5nLCBhbnk+KSA9PiB7XG4gICAgICAgICAgbGV0IHZhbCA9IChlLnRhcmdldCBhcyBEb21FbGVtZW50ICYgUmVjb3JkPHN0cmluZywgYW55PikudmFsdWU7XG4gICAgICAgICAgaWYgKGUuY3RybEtleSkge1xuICAgICAgICAgICAgbGV0IGlkeCA9IG1vZGVsW3Byb3BlcnR5XS5pbmRleE9mKHZhbCk7XG4gICAgICAgICAgICBpZiAoaWR4ID09PSAtMSkge1xuICAgICAgICAgICAgICBtb2RlbFtwcm9wZXJ0eV0ucHVzaCh2YWwpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgbW9kZWxbcHJvcGVydHldLnNwbGljZShpZHgsIDEpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBtb2RlbFtwcm9wZXJ0eV0uc3BsaWNlKDAsIG1vZGVsW3Byb3BlcnR5XS5sZW5ndGgpO1xuICAgICAgICAgICAgbW9kZWxbcHJvcGVydHldLnB1c2godmFsKTtcbiAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIHZub2RlLmNoaWxkcmVuLmZvckVhY2goKGNoaWxkKSA9PiB7XG4gICAgICAgICAgaWYgKGNoaWxkLm5hbWUgPT09IFwib3B0aW9uXCIpIHtcbiAgICAgICAgICAgIGxldCB2YWx1ZSA9IFwidmFsdWVcIiBpbiBjaGlsZC5wcm9wcyA/IGNoaWxkLnByb3BzLnZhbHVlIDogY2hpbGQuY2hpbGRyZW4uam9pbihcIlwiKS50cmltKCk7XG4gICAgICAgICAgICBjaGlsZC5wcm9wcy5zZWxlY3RlZCA9IG1vZGVsW3Byb3BlcnR5XS5pbmRleE9mKHZhbHVlKSAhPT0gLTE7XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHZub2RlLmNoaWxkcmVuLmZvckVhY2goKGNoaWxkKSA9PiB7XG4gICAgICAgICAgaWYgKGNoaWxkLm5hbWUgPT09IFwib3B0aW9uXCIpIHtcbiAgICAgICAgICAgIGxldCB2YWx1ZSA9IFwidmFsdWVcIiBpbiBjaGlsZC5wcm9wcyA/IGNoaWxkLnByb3BzLnZhbHVlIDogY2hpbGQuY2hpbGRyZW4uam9pbihcIlwiKS50cmltKCk7XG4gICAgICAgICAgICBjaGlsZC5wcm9wcy5zZWxlY3RlZCA9IHZhbHVlID09PSBtb2RlbFtwcm9wZXJ0eV07XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICB9IGVsc2UgaWYgKHZub2RlLm5hbWUgPT09IFwidGV4dGFyZWFcIikge1xuICAgICAgZXZlbnQgPSBldmVudCB8fCBcIm9uaW5wdXRcIjtcbiAgICAgIHZub2RlLmNoaWxkcmVuID0gW21vZGVsW3Byb3BlcnR5XV07XG4gICAgfVxuXG4gICAgaWYgKCF2bm9kZS5wcm9wc1tldmVudF0pIHtcbiAgICAgIGlmICghaGFuZGxlcikge1xuICAgICAgICBoYW5kbGVyID0gKGU6IEV2ZW50KSA9PiAobW9kZWxbcHJvcGVydHldID0gKGUudGFyZ2V0IGFzIERvbUVsZW1lbnQgJiBSZWNvcmQ8c3RyaW5nLCBhbnk+KS52YWx1ZSk7XG4gICAgICB9XG4gICAgICBzZXRBdHRyaWJ1dGUoZXZlbnQsIGhhbmRsZXIsIHZub2RlLCBvbGRWbm9kZSk7XG4gICAgfVxuICB9XG59O1xuXG4vKioqIFBsdWdpbnMgKioqL1xuY29uc3QgcGx1Z2lucyA9IG5ldyBNYXA8UGx1Z2luLCBhbnk+KCk7XG5cbmV4cG9ydCBmdW5jdGlvbiB1c2UocGx1Z2luOiBQbHVnaW4sIG9wdGlvbnM/OiBSZWNvcmQ8c3RyaW5nIHwgbnVtYmVyIHwgc3ltYm9sLCBhbnk+KTogdm9pZCB8IGFueSB7XG4gIGlmIChwbHVnaW5zLmhhcyhwbHVnaW4pKSB7XG4gICAgcmV0dXJuIHBsdWdpbnMuZ2V0KHBsdWdpbik7XG4gIH1cblxuICBsZXQgcmVzdWx0ID0gcGx1Z2luKHYsIG9wdGlvbnMpO1xuICBwbHVnaW5zLnNldChwbHVnaW4sIHJlc3VsdCk7XG4gIHJldHVybiByZXN1bHQ7XG59XG5cbi8qKiogSHlwZXJzY3JpcHQgKioqL1xuXG5leHBvcnQgY29uc3QgdjogVmFseXJpYW4gPSBmdW5jdGlvbiB2KHRhZ09yQ29tcG9uZW50OiBzdHJpbmcgfCBWYWx5cmlhbkNvbXBvbmVudCwgcHJvcHM6IFByb3BzLCAuLi5jaGlsZHJlbjogQ2hpbGRyZW4pOiBJVm5vZGUgfCBWbm9kZUNvbXBvbmVudCB7XG4gIGlmICh0eXBlb2YgdGFnT3JDb21wb25lbnQgPT09IFwic3RyaW5nXCIpIHtcbiAgICByZXR1cm4gbmV3IFZub2RlKHRhZ09yQ29tcG9uZW50LCBwcm9wcyB8fCB7fSwgY2hpbGRyZW4pO1xuICB9XG5cbiAgY29uc3Qgdm5vZGUgPSBuZXcgVm5vZGUoXCJfX2NvbXBvbmVudF9fXCIsIHByb3BzIHx8IHt9LCBjaGlsZHJlbik7XG4gIHZub2RlLmNvbXBvbmVudCA9IHRhZ09yQ29tcG9uZW50O1xuICByZXR1cm4gdm5vZGUgYXMgVm5vZGVDb21wb25lbnQ7XG59O1xuXG52LmZyYWdtZW50ID0gKHByb3BzOiBQcm9wcywgLi4uY2hpbGRyZW46IENoaWxkcmVuKTogQ2hpbGRyZW4gPT4ge1xuICByZXR1cm4gY2hpbGRyZW47XG59O1xuXG4vKioqIFYgcHJvcGVydGllcyBhbmQgbWV0aG9kcyAqKiovXG4vLyBUaGlzIGlzIGludGVuZGVkIHRvIG1ha2UgdGhlIHByb3BlcnRpZXMgYW5kIG1ldGhvZHMgYXZhaWxhYmxlIGZvciBwbHVnaW5zXG52LmN1cnJlbnQgPSB7fSBhcyBDdXJyZW50O1xuXG52LmRpcmVjdGl2ZXMgPSB7IC4uLmJ1aWx0SW5EaXJlY3RpdmVzIH07XG5cbnYucmVzZXJ2ZWRQcm9wcyA9IHtcbiAga2V5OiB0cnVlLFxuICBzdGF0ZTogdHJ1ZSxcbiAgb25jcmVhdGU6IHRydWUsXG4gIG9udXBkYXRlOiB0cnVlLFxuICBvbnJlbW92ZTogdHJ1ZSxcbiAgc2hvdWxkdXBkYXRlOiB0cnVlLFxuICBcInYtY2xlYW51cFwiOiB0cnVlLFxuICBcInYtb25jZVwiOiB0cnVlLFxuXG4gIC8vIEJ1aWx0IGluIGRpcmVjdGl2ZXNcbiAgXCJ2LWlmXCI6IHRydWUsXG4gIFwidi11bmxlc3NcIjogdHJ1ZSxcbiAgXCJ2LWZvclwiOiB0cnVlLFxuICBcInYtc2hvd1wiOiB0cnVlLFxuICBcInYtY2xhc3NcIjogdHJ1ZSxcbiAgXCJ2LWh0bWxcIjogdHJ1ZVxufTtcblxudi5pc1Zub2RlID0gaXNWbm9kZTtcbnYuaXNDb21wb25lbnQgPSBpc0NvbXBvbmVudDtcbnYuaXNWbm9kZUNvbXBvbmVudCA9IGlzVm5vZGVDb21wb25lbnQ7XG5cbnYuaXNOb2RlSnMgPSBpc05vZGVKcztcbnYudHJ1c3QgPSB0cnVzdDtcblxudi5vbkNsZWFudXAgPSBvbkNsZWFudXA7XG52Lm9uVW5tb3VudCA9IG9uVW5tb3VudDtcbnYub25Nb3VudCA9IG9uTW91bnQ7XG52Lm9uVXBkYXRlID0gb25VcGRhdGU7XG5cbnYubW91bnQgPSBtb3VudDtcbnYudW5tb3VudCA9IHVubW91bnQ7XG52LnVwZGF0ZSA9IHVwZGF0ZTtcblxudi5zZXRBdHRyaWJ1dGUgPSBzZXRBdHRyaWJ1dGU7XG52LmRpcmVjdGl2ZSA9IGRpcmVjdGl2ZTtcbnYudXNlID0gdXNlO1xuIl19 \ No newline at end of file +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL2xpYi9pbmRleC50cyJdLCJuYW1lcyI6WyJDb21wb25lbnRTdHJpbmciLCJUZXh0U3RyaW5nIiwiaXNOb2RlSnMiLCJCb29sZWFuIiwicHJvY2VzcyIsInZlcnNpb25zIiwibm9kZSIsIlZhbHlyaWFuU3ltYm9sIiwiU3ltYm9sIiwiVW5kIiwiVm5vZGUiLCJ0YWciLCJwcm9wcyIsImNoaWxkcmVuIiwidGhpcyIsImlzVm5vZGUiLCJvYmplY3QiLCJpc0NvbXBvbmVudCIsImNvbXBvbmVudCIsImlzVm5vZGVDb21wb25lbnQiLCJ2bm9kZSIsImNyZWF0ZURvbUVsZW1lbnQiLCJpc1NWRyIsImRvY3VtZW50IiwiY3JlYXRlRWxlbWVudE5TIiwiY3JlYXRlRWxlbWVudCIsImRvbVRvVm5vZGUiLCJkb20iLCJ2IiwidGFnTmFtZSIsInRvTG93ZXJDYXNlIiwiQXJyYXkiLCJmcm9tIiwiY2hpbGROb2RlcyIsImZpbHRlciIsImNoaWxkIiwibm9kZVR5cGUiLCJtYXAiLCJ0ZXh0Iiwibm9kZVZhbHVlIiwiU3RyaW5nIiwiZm9yRWFjaCIsImNhbGwiLCJhdHRyaWJ1dGVzIiwicHJvcCIsIm5vZGVOYW1lIiwidHJ1c3QiLCJodG1sU3RyaW5nIiwiZGl2IiwiaW5uZXJIVE1MIiwidHJpbSIsIml0ZW0iLCJyZXNlcnZlZFByb3BzIiwia2V5Iiwic3RhdGUiLCJvbmNyZWF0ZSIsIm9udXBkYXRlIiwib25yZW1vdmUiLCJzaG91bGR1cGRhdGUiLCJjdXJyZW50Iiwib25DbGVhbnVwIiwiY2FsbGJhY2siLCJhcHAiLCJpbmRleE9mIiwicHVzaCIsIm9uVW5tb3VudCIsIm9uTW91bnQiLCJvblVwZGF0ZSIsIm1vdW50IiwiY29udGFpbmVyIiwidm5vZGVDb21wb25lbnQiLCJhcHBDb250YWluZXIiLCJxdWVyeVNlbGVjdG9yQWxsIiwiRXJyb3IiLCJ1bm1vdW50IiwiZXZlbnRMaXN0ZW5lciIsImUiLCJ0YXJnZXQiLCJuYW1lIiwidHlwZSIsImRlZmF1bHRQcmV2ZW50ZWQiLCJ1cGRhdGUiLCJwYXJlbnROb2RlIiwiaXNNb3VudGVkIiwiZXZlbnRMaXN0ZW5lck5hbWVzIiwibWFpblZub2RlIiwiY2FsbENsZWFudXAiLCJ2YWx5cmlhbkFwcCIsImkiLCJsZW5ndGgiLCJvbGRWbm9kZSIsInBhdGNoIiwiY2FsbE1vdW50IiwiY2FsbFVwZGF0ZSIsImNhbGxVbm1vdW50IiwiUmVmbGVjdCIsImRlbGV0ZVByb3BlcnR5IiwiZW1wdHlWbm9kZSIsInNoYXJlZFNldEF0dHJpYnV0ZSIsInZhbHVlIiwiZGlyZWN0aXZlcyIsImFkZEV2ZW50TGlzdGVuZXIiLCJzbGljZSIsInJlbW92ZUF0dHJpYnV0ZSIsInNldEF0dHJpYnV0ZSIsInNldEF0dHJpYnV0ZXMiLCJuZXdWbm9kZSIsIm5ld1RyZWUiLCJvbGRUcmVlIiwiY2hpbGRWbm9kZSIsInJlc3VsdCIsInZpZXciLCJzcGxpY2UiLCJpc0FycmF5Iiwib2xkVHJlZUxlbmd0aCIsIm5ld1RyZWVMZW5ndGgiLCJvbGRLZXllZExpc3QiLCJyZWR1Y2UiLCJhY2MiLCJuZXdLZXllZExpc3QiLCJvbGRDaGlsZFZub2RlIiwic2hvdWxkUGF0Y2giLCJhcHBlbmRDaGlsZCIsInJlcGxhY2VDaGlsZCIsInJlbW92ZUNoaWxkIiwibmV3Q2hpbGRWbm9kZSIsImNyZWF0ZVRleHROb2RlIiwidGV4dENvbnRlbnQiLCJkaXJlY3RpdmUiLCJkaXJlY3RpdmUyIiwiZnVsbE5hbWUiLCJoaWRlRGlyZWN0aXZlIiwidGVzdCIsImJvb2wiLCJuZXdkb20iLCJzZXQiLCJzdHlsZSIsImRpc3BsYXkiLCJjbGFzc2VzIiwiY2xhc3NMaXN0IiwidG9nZ2xlIiwiaHRtbCIsIm1vZGVsIiwicHJvcGVydHkiLCJldmVudCIsImhhbmRsZXIiLCJ2YWwiLCJpZHgiLCJtdWx0aXBsZSIsImN0cmxLZXkiLCJ2YWx1ZTIiLCJqb2luIiwic2VsZWN0ZWQiLCJwbHVnaW5zIiwiTWFwIiwidXNlIiwicGx1Z2luIiwib3B0aW9ucyIsImhhcyIsImdldCIsInRhZ09yQ29t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QUVDLE9BQTRDc0IsT0FFNUZLLEVBQWF3QyxFQUFPQyxFQUFTN0gsRUFBT3NFLE1BTXBDK0QsRUFBVSxJQUFJQyxJQUViLFNBQUFDLEVBQWFDLEVBQWdCQyxHQUNsQyxHQUFJSixFQUFRSyxJQUFJRixHQUNkLE9BQU9ILEVBQVFNLElBQUlILEdBR3JCLElBQUk5QyxFQUFTOEMsRUFBT2hJLEVBQUdpSSxHQUV2QixPQURBSixFQUFRbEIsSUFBSXFCLEVBQVE5QyxHQUNiQSxFQUtGLElBQU1sRixFQUFjLFNBQVdvSSxFQUE0Q3BKLEtBQWlCQyxHQUNqRyxHQUE4QixpQkFBbkJtSixFQUNULE9BQU8sSUFBSXRKLEVBQU1zSixFQUFnQnBKLEdBQVMsR0FBSUMsR0FHaEQsTUFBTU8sRUFBUSxJQUFJVixFQUFNLGdCQUFpQkUsR0FBUyxHQUFJQyxHQUV0RCxPQURBTyxFQUFNRixVQUFZOEksRUFDWDVJLEdBR1RRLEVBQUVxSSxTQUFXLENBQUNySixLQUFpQkMsSUFDdEJBLEVBS1RlLEVBQUUrQixRQUFVQSxFQUVaL0IsRUFBRXdFLFdBQWFBLEVBRWZ4RSxFQUFFd0IsY0FBZ0JBLEVBRWxCeEIsRUFBRWIsUUFBVUEsRUFDWmEsRUFBRVgsWUFBY0EsRUFDaEJXLEVBQUVULGlCQUFtQkEsRUFFckJTLEVBQUUxQixTQUFXQSxFQUNiMEIsRUFBRWtCLE1BQVFBLEVBRVZsQixFQUFFZ0MsVUFBWUEsRUFDZGhDLEVBQUVxQyxVQUFZQSxFQUNkckMsRUFBRXNDLFFBQVVBLEVBQ1p0QyxFQUFFdUMsU0FBV0EsRUFFYnZDLEVBQUV3QyxNQUFRQSxFQUNWeEMsRUFBRThDLFFBQVVBLEVBQ1o5QyxFQUFFcUQsT0FBU0EsRUFFWHJELEVBQUU0RSxhQUFlQSxFQUNqQjVFLEVBQUVvRyxVQUFZQSxFQUNkcEcsRUFBRStILElBQU1BIiwic291cmNlc0NvbnRlbnQiOlsiLyoqKiBWbm9kZSAqKiovXG5cbmltcG9ydCB7XG4gIENoaWxkcmVuLFxuICBDdXJyZW50LFxuICBEaXJlY3RpdmUsXG4gIERpcmVjdGl2ZXMsXG4gIERvbUVsZW1lbnQsXG4gIElWbm9kZSxcbiAgTW91bnRlZFZhbHlyaWFuQXBwLFxuICBQbHVnaW4sXG4gIFByb3BzLFxuICBSZXNlcnZlZFByb3BzLFxuICBWYWx5cmlhbixcbiAgVmFseXJpYW5BcHAsXG4gIFZhbHlyaWFuQ29tcG9uZW50LFxuICBWbm9kZUNvbXBvbmVudCxcbiAgVm5vZGVXaXRoRG9tXG59IGZyb20gXCIuL2ludGVyZmFjZXNcIjtcblxuLyoqKiBDb25zdGFudHMgKioqL1xuY29uc3QgQ29tcG9uZW50U3RyaW5nID0gXCJfX2NvbXBvbmVudF9fXCI7XG5jb25zdCBUZXh0U3RyaW5nID0gXCIjdGV4dFwiO1xuZXhwb3J0IGNvbnN0IGlzTm9kZUpzID0gQm9vbGVhbih0eXBlb2YgcHJvY2VzcyAhPT0gXCJ1bmRlZmluZWRcIiAmJiBwcm9jZXNzLnZlcnNpb25zICYmIHByb2Nlc3MudmVyc2lvbnMubm9kZSk7XG5jb25zdCBWYWx5cmlhblN5bWJvbCA9IFN5bWJvbChcIlZhbHlyaWFuXCIpO1xuY29uc3QgVW5kID0gdW5kZWZpbmVkO1xuXG4vKioqIFZub2RlICoqKi9cblxuZXhwb3J0IGNvbnN0IFZub2RlID0gZnVuY3Rpb24gVm5vZGUodGhpczogSVZub2RlLCB0YWc6IHN0cmluZywgcHJvcHM6IFByb3BzLCBjaGlsZHJlbjogQ2hpbGRyZW4pIHtcbiAgdGhpcy5wcm9wcyA9IHByb3BzO1xuICB0aGlzLmNoaWxkcmVuID0gY2hpbGRyZW47XG4gIHRoaXMudGFnID0gdGFnO1xufSBhcyB1bmtub3duIGFzIElWbm9kZTtcblxuZXhwb3J0IGZ1bmN0aW9uIGlzVm5vZGUob2JqZWN0PzogdW5rbm93biB8IElWbm9kZSk6IG9iamVjdCBpcyBJVm5vZGUge1xuICByZXR1cm4gb2JqZWN0IGluc3RhbmNlb2YgVm5vZGU7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBpc0NvbXBvbmVudChjb21wb25lbnQ/OiB1bmtub3duIHwgVmFseXJpYW5Db21wb25lbnQpOiBjb21wb25lbnQgaXMgVmFseXJpYW5Db21wb25lbnQge1xuICByZXR1cm4gdHlwZW9mIGNvbXBvbmVudCA9PT0gXCJmdW5jdGlvblwiIHx8ICh0eXBlb2YgY29tcG9uZW50ID09PSBcIm9iamVjdFwiICYmIGNvbXBvbmVudCAhPT0gbnVsbCAmJiBcInZpZXdcIiBpbiBjb21wb25lbnQpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gaXNWbm9kZUNvbXBvbmVudCh2bm9kZT86IHVua25vd24gfCBWbm9kZUNvbXBvbmVudCk6IHZub2RlIGlzIFZub2RlQ29tcG9uZW50IHtcbiAgcmV0dXJuIHZub2RlIGluc3RhbmNlb2YgVm5vZGUgJiYgdm5vZGUudGFnID09PSBDb21wb25lbnRTdHJpbmc7XG59XG5cbi8qKiogVXRpbCAqKiovXG5cbmZ1bmN0aW9uIGNyZWF0ZURvbUVsZW1lbnQodGFnOiBzdHJpbmcsIGlzU1ZHOiBib29sZWFuID0gZmFsc2UpIHtcbiAgcmV0dXJuIGlzU1ZHID8gZG9jdW1lbnQuY3JlYXRlRWxlbWVudE5TKFwiaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmdcIiwgdGFnKSA6IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQodGFnKTtcbn1cblxuZnVuY3Rpb24gZG9tVG9Wbm9kZShkb206IERvbUVsZW1lbnQpOiBWbm9kZVdpdGhEb20ge1xuICBsZXQgdm5vZGUgPSB2KFxuICAgIGRvbS50YWdOYW1lLnRvTG93ZXJDYXNlKCksXG4gICAge30sXG4gICAgLi4uQXJyYXkuZnJvbShkb20uY2hpbGROb2RlcylcbiAgICAgIC5maWx0ZXIoKGNoaWxkKSA9PiAoY2hpbGQgYXMgRG9tRWxlbWVudCkubm9kZVR5cGUgPT09IDEgfHwgKGNoaWxkIGFzIERvbUVsZW1lbnQpLm5vZGVUeXBlID09PSAzKVxuICAgICAgLm1hcCgoY2hpbGQpID0+IHtcbiAgICAgICAgaWYgKChjaGlsZCBhcyBEb21FbGVtZW50KS5ub2RlVHlwZSA9PT0gMSkge1xuICAgICAgICAgIHJldHVybiBkb21Ub1Zub2RlKGNoaWxkIGFzIERvbUVsZW1lbnQpO1xuICAgICAgICB9XG5cbiAgICAgICAgbGV0IHRleHQgPSBuZXcgVm5vZGUoVGV4dFN0cmluZywge30sIFtdKTtcbiAgICAgICAgdGV4dC5ub2RlVmFsdWUgPSBTdHJpbmcoKGNoaWxkIGFzIERvbUVsZW1lbnQpLm5vZGVWYWx1ZSk7XG4gICAgICAgIHRleHQuZG9tID0gY2hpbGQgYXMgRG9tRWxlbWVudDtcbiAgICAgICAgcmV0dXJuIHRleHQ7XG4gICAgICB9KVxuICApO1xuICBbXS5mb3JFYWNoLmNhbGwoZG9tLmF0dHJpYnV0ZXMsIChwcm9wOiBBdHRyKSA9PiAodm5vZGUucHJvcHNbcHJvcC5ub2RlTmFtZV0gPSBwcm9wLm5vZGVWYWx1ZSkpO1xuICB2bm9kZS5kb20gPSBkb207XG4gIHJldHVybiB2bm9kZSBhcyBWbm9kZVdpdGhEb207XG59XG5cbmV4cG9ydCBjb25zdCB0cnVzdCA9IChodG1sU3RyaW5nOiBzdHJpbmcpOiBJVm5vZGVbXSA9PiB7XG4gIGxldCBkaXYgPSBjcmVhdGVEb21FbGVtZW50KFwiZGl2XCIpO1xuICBkaXYuaW5uZXJIVE1MID0gaHRtbFN0cmluZy50cmltKCk7XG5cbiAgcmV0dXJuIFtdLm1hcC5jYWxsKGRpdi5jaGlsZE5vZGVzLCAoaXRlbSkgPT4gZG9tVG9Wbm9kZShpdGVtKSkgYXMgSVZub2RlW107XG59O1xuXG5jb25zdCByZXNlcnZlZFByb3BzOiBSZXNlcnZlZFByb3BzID0ge1xuICBrZXk6IHRydWUsXG4gIHN0YXRlOiB0cnVlLFxuICBvbmNyZWF0ZTogdHJ1ZSxcbiAgb251cGRhdGU6IHRydWUsXG4gIG9ucmVtb3ZlOiB0cnVlLFxuICBzaG91bGR1cGRhdGU6IHRydWUsXG4gIFwidi1vbmNlXCI6IHRydWUsXG5cbiAgLy8gQnVpbHQgaW4gZGlyZWN0aXZlc1xuICBcInYtaWZcIjogdHJ1ZSxcbiAgXCJ2LXVubGVzc1wiOiB0cnVlLFxuICBcInYtZm9yXCI6IHRydWUsXG4gIFwidi1zaG93XCI6IHRydWUsXG4gIFwidi1jbGFzc1wiOiB0cnVlLFxuICBcInYtaHRtbFwiOiB0cnVlXG59O1xuXG4vKioqIE1vdW50ICoqKi9cblxuY29uc3QgY3VycmVudDogQ3VycmVudCA9IHt9O1xuXG5leHBvcnQgZnVuY3Rpb24gb25DbGVhbnVwKGNhbGxiYWNrOiBGdW5jdGlvbikge1xuICBpZiAoY3VycmVudC5hcHA/Lm9uQ2xlYW51cC5pbmRleE9mKGNhbGxiYWNrKSA9PT0gLTEpIHtcbiAgICBjdXJyZW50LmFwcD8ub25DbGVhbnVwLnB1c2goY2FsbGJhY2spO1xuICB9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBvblVubW91bnQoY2FsbGJhY2s6IEZ1bmN0aW9uKSB7XG4gIGlmIChjdXJyZW50LmFwcD8ub25Vbm1vdW50LmluZGV4T2YoY2FsbGJhY2spID09PSAtMSkge1xuICAgIGN1cnJlbnQuYXBwPy5vblVubW91bnQucHVzaChjYWxsYmFjayk7XG4gIH1cbn1cblxuZXhwb3J0IGZ1bmN0aW9uIG9uTW91bnQoY2FsbGJhY2s6IEZ1bmN0aW9uKSB7XG4gIGlmIChjdXJyZW50LmFwcD8ub25Nb3VudC5pbmRleE9mKGNhbGxiYWNrKSA9PT0gLTEpIHtcbiAgICBjdXJyZW50LmFwcD8ub25Nb3VudC5wdXNoKGNhbGxiYWNrKTtcbiAgfVxufVxuXG5leHBvcnQgZnVuY3Rpb24gb25VcGRhdGUoY2FsbGJhY2s6IEZ1bmN0aW9uKSB7XG4gIGlmIChjdXJyZW50LmFwcD8ub25VcGRhdGUuaW5kZXhPZihjYWxsYmFjaykgPT09IC0xKSB7XG4gICAgY3VycmVudC5hcHA/Lm9uVXBkYXRlLnB1c2goY2FsbGJhY2spO1xuICB9XG59XG5cbi8qXG4gICogTW91bnRzIGEgY29tcG9uZW50IHRvIHRoZSBET01cbiAgbW91bnQoJyNhcHAnLCAoKSA9PiA8ZGl2PkhlbGxvIHdvcmxkPC9kaXY+KTsgLy8gQXBwIGlzIGEgRnVuY3Rpb25hbCBDb21wb25lbnRcbiAgbW91bnQoJyNhcHAnLCB7IHZpZXc6ICgpID0+IDxkaXY+SGVsbG8gd29ybGQ8L2Rpdj4gfSk7IC8vIEFwcCBpcyBhIFBPSk8gY29tcG9uZW50IHdpdGggYSB2aWV3IG1ldGhvZFxuICBtb3VudCgnI2FwcCcsIGNsYXNzSW5zdGFuY2UpOyAvLyBBcHAgaXMgYSBjbGFzcyBpbnN0YW5jZSB3aXRoIGEgdmlldyBtZXRob2RcbiAgbW91bnQoJyNhcHAnLCA8QXBwPjxkaXY+SGVsbG8gd29ybGQ8L2Rpdj48L0FwcD4pOyAvLyBBcHAgaXMgYSBWbm9kZSBjb21wb25lbnQgKFZub2RlIHdpdGggdGFnIF9fY29tcG9uZW50X18pXG4qL1xuXG5leHBvcnQgZnVuY3Rpb24gbW91bnQoY29udGFpbmVyOiBEb21FbGVtZW50IHwgc3RyaW5nLCBjb21wb25lbnQ6IFZhbHlyaWFuQ29tcG9uZW50IHwgSVZub2RlKTogdm9pZCB8IHN0cmluZyB7XG4gIGxldCBhcHBDb250YWluZXIgPSBudWxsO1xuXG4gIGlmIChpc05vZGVKcykge1xuICAgIGFwcENvbnRhaW5lciA9IHR5cGVvZiBjb250YWluZXIgPT09IFwic3RyaW5nXCIgPyBjcmVhdGVEb21FbGVtZW50KGNvbnRhaW5lciA9PT0gXCJzdmdcIiA/IFwic3ZnXCIgOiBcImRpdlwiLCBjb250YWluZXIgPT09IFwic3ZnXCIpIDogY29udGFpbmVyO1xuICB9IGVsc2Uge1xuICAgIGFwcENvbnRhaW5lciA9IHR5cGVvZiBjb250YWluZXIgPT09IFwic3RyaW5nXCIgPyBkb2N1bWVudC5xdWVyeVNlbGVjdG9yQWxsKGNvbnRhaW5lcilbMF0gOiBjb250YWluZXI7XG4gIH1cblxuICBpZiAoIWFwcENvbnRhaW5lcikge1xuICAgIHRocm93IG5ldyBFcnJvcihcIkNvbnRhaW5lciBub3QgZm91bmRcIik7XG4gIH1cblxuICBsZXQgdm5vZGVDb21wb25lbnQ6IFZub2RlQ29tcG9uZW50IHwgSVZub2RlO1xuXG4gIGlmIChpc1Zub2RlQ29tcG9uZW50KGNvbXBvbmVudCkpIHtcbiAgICB2bm9kZUNvbXBvbmVudCA9IGNvbXBvbmVudDtcbiAgfSBlbHNlIGlmIChpc0NvbXBvbmVudChjb21wb25lbnQpKSB7XG4gICAgdm5vZGVDb21wb25lbnQgPSB2KGNvbXBvbmVudCwge30pO1xuICB9IGVsc2Uge1xuICAgIHRocm93IG5ldyBFcnJvcihcIkNvbXBvbmVudCBtdXN0IGJlIGEgVmFseXJpYW4gQ29tcG9uZW50IG9yIGEgVm5vZGUgY29tcG9uZW50XCIpO1xuICB9XG5cbiAgaWYgKGNvbXBvbmVudFtWYWx5cmlhblN5bWJvbF0pIHtcbiAgICB1bm1vdW50KGNvbXBvbmVudCk7XG4gIH0gZWxzZSB7XG4gICAgY29tcG9uZW50W1ZhbHlyaWFuU3ltYm9sXSA9IHtcbiAgICAgIGlzTW91bnRlZDogZmFsc2UsXG4gICAgICBldmVudExpc3RlbmVyTmFtZXM6IHt9LFxuICAgICAgb25DbGVhbnVwOiBbXSxcbiAgICAgIG9uTW91bnQ6IFtdLFxuICAgICAgb25VcGRhdGU6IFtdLFxuICAgICAgb25Vbm1vdW50OiBbXVxuICAgIH07XG4gICAgZnVuY3Rpb24gZXZlbnRMaXN0ZW5lcihlOiBFdmVudCkge1xuICAgICAgbGV0IGRvbSA9IGUudGFyZ2V0IGFzIERvbUVsZW1lbnQgJiBSZWNvcmQ8c3RyaW5nLCBhbnk+O1xuICAgICAgbGV0IG5hbWUgPSBgdi1vbiR7ZS50eXBlfWA7XG4gICAgICB3aGlsZSAoZG9tKSB7XG4gICAgICAgIGlmIChkb21bbmFtZV0pIHtcbiAgICAgICAgICBkb21bbmFtZV0oZSwgZG9tKTtcbiAgICAgICAgICBpZiAoIWUuZGVmYXVsdFByZXZlbnRlZCkge1xuICAgICAgICAgICAgdXBkYXRlKGNvbXBvbmVudCk7XG4gICAgICAgICAgfVxuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBkb20gPSBkb20ucGFyZW50Tm9kZSBhcyBEb21FbGVtZW50O1xuICAgICAgfVxuICAgIH1cbiAgICBjb21wb25lbnRbVmFseXJpYW5TeW1ib2xdLmV2ZW50TGlzdGVuZXIgPSBldmVudExpc3RlbmVyO1xuICB9XG5cbiAgY29tcG9uZW50W1ZhbHlyaWFuU3ltYm9sXS5jb21wb25lbnQgPSB2bm9kZUNvbXBvbmVudDtcbiAgY29tcG9uZW50W1ZhbHlyaWFuU3ltYm9sXS5jb250YWluZXIgPSBhcHBDb250YWluZXI7XG4gIGNvbXBvbmVudFtWYWx5cmlhblN5bWJvbF0ubWFpblZub2RlID0gZG9tVG9Wbm9kZShhcHBDb250YWluZXIpO1xuXG4gIC8vIHVwZGF0ZVxuICByZXR1cm4gdXBkYXRlKGNvbXBvbmVudCk7XG59XG5cbmZ1bmN0aW9uIGNhbGxDbGVhbnVwKHZhbHlyaWFuQXBwOiBWYWx5cmlhbkFwcCkge1xuICBmb3IgKGxldCBpID0gMDsgaSA8IHZhbHlyaWFuQXBwLm9uQ2xlYW51cC5sZW5ndGg7IGkrKykge1xuICAgIHZhbHlyaWFuQXBwLm9uQ2xlYW51cFtpXSgpO1xuICB9XG4gIHZhbHlyaWFuQXBwLm9uQ2xlYW51cCA9IFtdO1xufVxuXG5mdW5jdGlvbiBjYWxsVW5tb3VudCh2YWx5cmlhbkFwcDogVmFseXJpYW5BcHApIHtcbiAgZm9yIChsZXQgaSA9IDA7IGkgPCB2YWx5cmlhbkFwcC5vblVubW91bnQubGVuZ3RoOyBpKyspIHtcbiAgICB2YWx5cmlhbkFwcC5vblVubW91bnRbaV0oKTtcbiAgfVxuICB2YWx5cmlhbkFwcC5vblVubW91bnQgPSBbXTtcbn1cblxuZnVuY3Rpb24gY2FsbE1vdW50KHZhbHlyaWFuQXBwOiBWYWx5cmlhbkFwcCkge1xuICBmb3IgKGxldCBpID0gMDsgaSA8IHZhbHlyaWFuQXBwLm9uTW91bnQubGVuZ3RoOyBpKyspIHtcbiAgICB2YWx5cmlhbkFwcC5vbk1vdW50W2ldKCk7XG4gIH1cbiAgdmFseXJpYW5BcHAub25Nb3VudCA9IFtdO1xufVxuXG5mdW5jdGlvbiBjYWxsVXBkYXRlKHZhbHlyaWFuQXBwOiBWYWx5cmlhbkFwcCkge1xuICBmb3IgKGxldCBpID0gMDsgaSA8IHZhbHlyaWFuQXBwLm9uVXBkYXRlLmxlbmd0aDsgaSsrKSB7XG4gICAgdmFseXJpYW5BcHAub25VcGRhdGVbaV0oKTtcbiAgfVxuICB2YWx5cmlhbkFwcC5vblVwZGF0ZSA9IFtdO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gdXBkYXRlKGNvbXBvbmVudD86IFZhbHlyaWFuQ29tcG9uZW50IHwgSVZub2RlKTogdm9pZCB8IHN0cmluZyB7XG4gIGlmIChjb21wb25lbnQgJiYgY29tcG9uZW50W1ZhbHlyaWFuU3ltYm9sXSkge1xuICAgIGxldCB2YWx5cmlhbkFwcCA9IGNvbXBvbmVudFtWYWx5cmlhblN5bWJvbF07XG4gICAgY3VycmVudC5hcHAgPSB2YWx5cmlhbkFwcDtcbiAgICB2YWx5cmlhbkFwcC5vbkNsZWFudXAubGVuZ3RoICYmIGNhbGxDbGVhbnVwKHZhbHlyaWFuQXBwKTtcbiAgICBsZXQgb2xkVm5vZGU6IFZub2RlV2l0aERvbSB8IG51bGwgPSB2YWx5cmlhbkFwcC5tYWluVm5vZGUgYXMgVm5vZGVXaXRoRG9tO1xuICAgIHZhbHlyaWFuQXBwLm1haW5Wbm9kZSA9IG5ldyBWbm9kZSh2YWx5cmlhbkFwcC5tYWluVm5vZGUudGFnLCB2YWx5cmlhbkFwcC5tYWluVm5vZGUucHJvcHMsIFt2YWx5cmlhbkFwcC5jb21wb25lbnRdKSBhcyBWbm9kZVdpdGhEb207XG4gICAgdmFseXJpYW5BcHAubWFpblZub2RlLmRvbSA9IG9sZFZub2RlLmRvbTtcbiAgICBwYXRjaCh2YWx5cmlhbkFwcC5tYWluVm5vZGUsIG9sZFZub2RlLCB2YWx5cmlhbkFwcCk7XG4gICAgb2xkVm5vZGUgPSBudWxsO1xuICAgIGlmICh2YWx5cmlhbkFwcC5pc01vdW50ZWQgPT09IGZhbHNlKSB7XG4gICAgICB2YWx5cmlhbkFwcC5vbk1vdW50Lmxlbmd0aCAmJiBjYWxsTW91bnQodmFseXJpYW5BcHApO1xuICAgICAgdmFseXJpYW5BcHAuaXNNb3VudGVkID0gdHJ1ZTtcbiAgICB9IGVsc2Uge1xuICAgICAgdmFseXJpYW5BcHAub25VcGRhdGUubGVuZ3RoICYmIGNhbGxVcGRhdGUodmFseXJpYW5BcHApO1xuICAgIH1cblxuICAgIGlmIChpc05vZGVKcykge1xuICAgICAgcmV0dXJuIHZhbHlyaWFuQXBwLm1haW5Wbm9kZS5kb20uaW5uZXJIVE1MO1xuICAgIH1cbiAgfVxufVxuXG5leHBvcnQgZnVuY3Rpb24gdW5tb3VudChjb21wb25lbnQ/OiBWYWx5cmlhbkNvbXBvbmVudCB8IElWbm9kZSk6IHZvaWQgfCBzdHJpbmcge1xuICBpZiAoIWNvbXBvbmVudCB8fCAhY29tcG9uZW50W1ZhbHlyaWFuU3ltYm9sXSkge1xuICAgIHJldHVybjtcbiAgfVxuXG4gIGxldCB2YWx5cmlhbkFwcCA9IGNvbXBvbmVudFtWYWx5cmlhblN5bWJvbF0gYXMgTW91bnRlZFZhbHlyaWFuQXBwO1xuXG4gIGlmICh2YWx5cmlhbkFwcC5pc01vdW50ZWQpIHtcbiAgICB2YWx5cmlhbkFwcC5vbkNsZWFudXAubGVuZ3RoICYmIGNhbGxDbGVhbnVwKHZhbHlyaWFuQXBwKTtcbiAgICB2YWx5cmlhbkFwcC5vblVubW91bnQubGVuZ3RoICYmIGNhbGxVbm1vdW50KHZhbHlyaWFuQXBwKTtcbiAgICBsZXQgb2xkVm5vZGU6IFZub2RlV2l0aERvbSB8IG51bGwgPSB2YWx5cmlhbkFwcC5tYWluVm5vZGUgYXMgVm5vZGVXaXRoRG9tO1xuICAgIHZhbHlyaWFuQXBwLm1haW5Wbm9kZSA9IG5ldyBWbm9kZSh2YWx5cmlhbkFwcC5tYWluVm5vZGUudGFnLCB2YWx5cmlhbkFwcC5tYWluVm5vZGUucHJvcHMsIFtdKSBhcyBWbm9kZVdpdGhEb207XG4gICAgdmFseXJpYW5BcHAubWFpblZub2RlLmRvbSA9IG9sZFZub2RlLmRvbTtcbiAgICB2YWx5cmlhbkFwcC5tYWluVm5vZGUuaXNTVkcgPSBvbGRWbm9kZS5pc1NWRztcbiAgICBwYXRjaCh2YWx5cmlhbkFwcC5tYWluVm5vZGUsIG9sZFZub2RlLCB2YWx5cmlhbkFwcCk7XG4gICAgb2xkVm5vZGUgPSBudWxsO1xuXG4gICAgaWYgKGlzTm9kZUpzKSB7XG4gICAgICByZXR1cm4gdmFseXJpYW5BcHAubWFpblZub2RlLmRvbS5pbm5lckhUTUw7XG4gICAgfVxuXG4gICAgKHZhbHlyaWFuQXBwIGFzIGFueSkgPSBudWxsO1xuICAgIFJlZmxlY3QuZGVsZXRlUHJvcGVydHkoY29tcG9uZW50LCBWYWx5cmlhblN5bWJvbCk7XG4gIH1cbn1cblxubGV0IGVtcHR5Vm5vZGUgPSBuZXcgVm5vZGUoXCJfX2VtcHR5X19cIiwge30sIFtdKTtcblxuZnVuY3Rpb24gb25yZW1vdmUodm5vZGU6IElWbm9kZSkge1xuICBmb3IgKGxldCBpID0gMDsgaSA8IHZub2RlLmNoaWxkcmVuLmxlbmd0aDsgaSsrKSB7XG4gICAgdm5vZGUuY2hpbGRyZW5baV0udGFnICE9PSBUZXh0U3RyaW5nICYmIG9ucmVtb3ZlKHZub2RlLmNoaWxkcmVuW2ldKTtcbiAgfVxuXG4gIHZub2RlLnByb3BzLm9ucmVtb3ZlICYmIHZub2RlLnByb3BzLm9ucmVtb3ZlKHZub2RlKTtcbn1cblxuZnVuY3Rpb24gc2hhcmVkU2V0QXR0cmlidXRlKHByb3A6IHN0cmluZywgdmFsdWU6IGFueSwgdm5vZGU6IFZub2RlV2l0aERvbSwgb2xkVm5vZGU/OiBWbm9kZVdpdGhEb20pOiB2b2lkIHwgYm9vbGVhbiB7XG4gIC8vIEl0IGlzIGEgcmVzZXJ2ZWQgcHJvcFxuICBpZiAocmVzZXJ2ZWRQcm9wc1twcm9wXSkge1xuICAgIC8vIElmIGl0IGlzIGEgZGlyZWN0aXZlIG5hbWUgY2FsbCB0aGUgZGlyZWN0aXZlXG4gICAgaWYgKGRpcmVjdGl2ZXNbcHJvcF0pIHtcbiAgICAgIHJldHVybiBkaXJlY3RpdmVzW3Byb3BdKHZub2RlLnByb3BzW3Byb3BdLCB2bm9kZSwgb2xkVm5vZGUpO1xuICAgIH1cblxuICAgIHJldHVybjtcbiAgfVxuXG4gIC8vIEl0IGlzIG5vdCBhIHJlc2VydmVkIHByb3Agc28gd2UgYWRkIGl0IHRvIHRoZSBkb21cbiAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gXCJmdW5jdGlvblwiKSB7XG4gICAgbGV0IHZhbHlyaWFuQXBwID0gY3VycmVudC5hcHAgYXMgTW91bnRlZFZhbHlyaWFuQXBwO1xuICAgIGlmIChwcm9wIGluIHZhbHlyaWFuQXBwLmV2ZW50TGlzdGVuZXJOYW1lcyA9PT0gZmFsc2UpIHtcbiAgICAgIHZhbHlyaWFuQXBwLmV2ZW50TGlzdGVuZXJOYW1lc1twcm9wXSA9IHRydWU7XG4gICAgICB2YWx5cmlhbkFwcC5jb250YWluZXIuYWRkRXZlbnRMaXN0ZW5lcihwcm9wLnNsaWNlKDIpLCB2YWx5cmlhbkFwcC5ldmVudExpc3RlbmVyKTtcbiAgICB9XG4gICAgdm5vZGUuZG9tW2B2LSR7cHJvcH1gXSA9IHZhbHVlO1xuICAgIHJldHVybjtcbiAgfVxuXG4gIGlmIChwcm9wIGluIHZub2RlLmRvbSAmJiB2bm9kZS5pc1NWRyA9PT0gZmFsc2UpIHtcbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgZXFlcWVxXG4gICAgaWYgKHZub2RlLmRvbVtwcm9wXSAhPSB2YWx1ZSkge1xuICAgICAgdm5vZGUuZG9tW3Byb3BdID0gdmFsdWU7XG4gICAgfVxuICAgIHJldHVybjtcbiAgfVxuXG4gIC8vIFVzZSBzZXQgYXR0cmlidXRlXG4gIGlmICghb2xkVm5vZGUgfHwgb2xkVm5vZGUucHJvcHNbcHJvcF0gIT09IHZhbHVlKSB7XG4gICAgaWYgKHZhbHVlID09PSBmYWxzZSkge1xuICAgICAgdm5vZGUuZG9tLnJlbW92ZUF0dHJpYnV0ZShwcm9wKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdm5vZGUuZG9tLnNldEF0dHJpYnV0ZShwcm9wLCB2YWx1ZSk7XG4gICAgfVxuICB9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBzZXRBdHRyaWJ1dGUobmFtZTogc3RyaW5nLCB2YWx1ZTogYW55LCB2bm9kZTogVm5vZGVXaXRoRG9tLCBvbGRWbm9kZT86IFZub2RlV2l0aERvbSkge1xuICB2bm9kZS5wcm9wc1tuYW1lXSA9IHZhbHVlO1xuXG4gIHNoYXJlZFNldEF0dHJpYnV0ZShuYW1lLCB2YWx1ZSwgdm5vZGUsIG9sZFZub2RlKTtcbn1cblxuZnVuY3Rpb24gc2V0QXR0cmlidXRlcyh2bm9kZTogVm5vZGVXaXRoRG9tLCBvbGRWbm9kZT86IFZub2RlV2l0aERvbSkge1xuICBmb3IgKGxldCBwcm9wIGluIHZub2RlLnByb3BzKSB7XG4gICAgaWYgKHNoYXJlZFNldEF0dHJpYnV0ZShwcm9wLCB2bm9kZS5wcm9wc1twcm9wXSwgdm5vZGUsIG9sZFZub2RlKSA9PT0gZmFsc2UpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gIH1cblxuICBpZiAob2xkVm5vZGUpIHtcbiAgICBmb3IgKGxldCBwcm9wIGluIG9sZFZub2RlLnByb3BzKSB7XG4gICAgICBpZiAocHJvcCBpbiB2bm9kZS5wcm9wcyA9PT0gZmFsc2UgJiYgdHlwZW9mIG9sZFZub2RlLnByb3BzW3Byb3BdICE9PSBcImZ1bmN0aW9uXCIgJiYgcHJvcCBpbiByZXNlcnZlZFByb3BzID09PSBmYWxzZSkge1xuICAgICAgICBpZiAocHJvcCBpbiBvbGRWbm9kZS5kb20gJiYgdm5vZGUuaXNTVkcgPT09IGZhbHNlKSB7XG4gICAgICAgICAgb2xkVm5vZGUuZG9tW3Byb3BdID0gbnVsbDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBvbGRWbm9kZS5kb20ucmVtb3ZlQXR0cmlidXRlKHByb3ApO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICB9XG59XG5cbi8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBjb21wbGV4aXR5XG5mdW5jdGlvbiBwYXRjaChuZXdWbm9kZTogVm5vZGVXaXRoRG9tLCBvbGRWbm9kZTogVm5vZGVXaXRoRG9tIHwgSVZub2RlID0gZW1wdHlWbm9kZSwgdmFseXJpYW5BcHA6IE1vdW50ZWRWYWx5cmlhbkFwcCkge1xuICBjdXJyZW50LnZub2RlID0gbmV3Vm5vZGU7XG4gIGN1cnJlbnQub2xkVm5vZGUgPSBvbGRWbm9kZSA9PT0gZW1wdHlWbm9kZSA/IFVuZCA6IChvbGRWbm9kZSBhcyBWbm9kZVdpdGhEb20pO1xuICBsZXQgbmV3VHJlZSA9IG5ld1Zub2RlLmNoaWxkcmVuO1xuICBsZXQgb2xkVHJlZSA9IG9sZFZub2RlLmNoaWxkcmVuO1xuXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgbmV3VHJlZS5sZW5ndGg7IGkrKykge1xuICAgIGxldCBjaGlsZFZub2RlID0gbmV3VHJlZVtpXTtcbiAgICBpZiAoY2hpbGRWbm9kZSBpbnN0YW5jZW9mIFZub2RlKSB7XG4gICAgICBpZiAoY2hpbGRWbm9kZS50YWcgIT09IFRleHRTdHJpbmcpIHtcbiAgICAgICAgaWYgKGNoaWxkVm5vZGUudGFnID09PSBDb21wb25lbnRTdHJpbmcpIHtcbiAgICAgICAgICBsZXQgY29tcG9uZW50ID0gY2hpbGRWbm9kZS5jb21wb25lbnQgYXMgVmFseXJpYW5Db21wb25lbnQ7XG4gICAgICAgICAgY3VycmVudC5jb21wb25lbnQgPSBjb21wb25lbnQ7XG4gICAgICAgICAgbGV0IHJlc3VsdCA9IChcInZpZXdcIiBpbiBjb21wb25lbnQgPyBjb21wb25lbnQudmlldyA6IGNvbXBvbmVudCkuY2FsbChjb21wb25lbnQsIGNoaWxkVm5vZGUucHJvcHMsIC4uLmNoaWxkVm5vZGUuY2hpbGRyZW4pO1xuXG4gICAgICAgICAgbmV3VHJlZS5zcGxpY2UoaS0tLCAxLCByZXN1bHQpO1xuICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICB9XG4gICAgICAgIGNoaWxkVm5vZGUuaXNTVkcgPSBuZXdWbm9kZS5pc1NWRyB8fCBjaGlsZFZub2RlLnRhZyA9PT0gXCJzdmdcIjtcbiAgICAgIH1cbiAgICB9IGVsc2UgaWYgKEFycmF5LmlzQXJyYXkoY2hpbGRWbm9kZSkpIHtcbiAgICAgIG5ld1RyZWUuc3BsaWNlKGktLSwgMSwgLi4uY2hpbGRWbm9kZSk7XG4gICAgfSBlbHNlIGlmIChjaGlsZFZub2RlID09PSBudWxsIHx8IGNoaWxkVm5vZGUgPT09IFVuZCkge1xuICAgICAgbmV3VHJlZS5zcGxpY2UoaS0tLCAxKTtcbiAgICB9IGVsc2Uge1xuICAgICAgbmV3VHJlZVtpXSA9IG5ldyBWbm9kZShUZXh0U3RyaW5nLCB7fSwgW10pO1xuICAgICAgbmV3VHJlZVtpXS5ub2RlVmFsdWUgPSBjaGlsZFZub2RlO1xuICAgIH1cbiAgfVxuXG4gIGxldCBvbGRUcmVlTGVuZ3RoID0gb2xkVHJlZS5sZW5ndGg7XG4gIGxldCBuZXdUcmVlTGVuZ3RoID0gbmV3VHJlZS5sZW5ndGg7XG5cbiAgLy8gSWYgbmV3IHRyZWUgaXMgZW1wdHksIHJlbW92ZSBhbGwgb2xkIG5vZGVzXG4gIGlmIChuZXdUcmVlTGVuZ3RoID09PSAwKSB7XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBvbGRUcmVlTGVuZ3RoOyBpKyspIHtcbiAgICAgIG9ucmVtb3ZlKG9sZFRyZWVbaV0pO1xuICAgIH1cblxuICAgIG5ld1Zub2RlLmRvbS50ZXh0Q29udGVudCA9IFwiXCI7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgLy8gSWYgdGhlIHRyZWUgaXMga2V5ZWQgbGlzdCBhbmQgaXMgbm90IGZpcnN0IHJlbmRlciBhbmQgb2xkIHRyZWUgaXMga2V5ZWQgbGlzdCB0b29cbiAgaWYgKG9sZFRyZWVMZW5ndGggJiYgXCJrZXlcIiBpbiBuZXdUcmVlWzBdLnByb3BzICYmIFwia2V5XCIgaW4gb2xkVHJlZVswXS5wcm9wcykge1xuICAgIGxldCBvbGRLZXllZExpc3QgPSBvbGRUcmVlLnJlZHVjZSgoYWNjLCB2bm9kZSwgaSkgPT4ge1xuICAgICAgYWNjW3Zub2RlLnByb3BzLmtleV0gPSBpO1xuICAgICAgcmV0dXJuIGFjYztcbiAgICB9LCB7fSBhcyB7IFtrZXk6IHN0cmluZ106IG51bWJlciB9KTtcbiAgICBsZXQgbmV3S2V5ZWRMaXN0ID0gbmV3VHJlZS5yZWR1Y2UoKGFjYywgdm5vZGUsIGkpID0+IHtcbiAgICAgIGFjY1t2bm9kZS5wcm9wcy5rZXldID0gaTtcbiAgICAgIHJldHVybiBhY2M7XG4gICAgfSwge30gYXMgeyBba2V5OiBzdHJpbmddOiBudW1iZXIgfSk7XG5cbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IG5ld1RyZWVMZW5ndGg7IGkrKykge1xuICAgICAgbGV0IGNoaWxkVm5vZGUgPSBuZXdUcmVlW2ldO1xuICAgICAgbGV0IG9sZENoaWxkVm5vZGUgPSBvbGRUcmVlW29sZEtleWVkTGlzdFtjaGlsZFZub2RlLnByb3BzLmtleV1dO1xuICAgICAgbGV0IHNob3VsZFBhdGNoID0gdHJ1ZTtcblxuICAgICAgaWYgKG9sZENoaWxkVm5vZGUpIHtcbiAgICAgICAgY2hpbGRWbm9kZS5kb20gPSBvbGRDaGlsZFZub2RlLmRvbTtcbiAgICAgICAgaWYgKFwidi1vbmNlXCIgaW4gY2hpbGRWbm9kZS5wcm9wcyB8fCAoY2hpbGRWbm9kZS5wcm9wcy5zaG91bGR1cGRhdGUgJiYgY2hpbGRWbm9kZS5wcm9wcy5zaG91bGR1cGRhdGUoY2hpbGRWbm9kZSwgb2xkQ2hpbGRWbm9kZSkgPT09IGZhbHNlKSkge1xuICAgICAgICAgIC8vIHNraXAgdGhpcyBwYXRjaFxuICAgICAgICAgIGNoaWxkVm5vZGUuY2hpbGRyZW4gPSBvbGRDaGlsZFZub2RlLmNoaWxkcmVuO1xuICAgICAgICAgIHNob3VsZFBhdGNoID0gZmFsc2U7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgc2V0QXR0cmlidXRlcyhjaGlsZFZub2RlLCBvbGRDaGlsZFZub2RlKTtcbiAgICAgICAgICBpZiAodmFseXJpYW5BcHAuaXNNb3VudGVkKSB7XG4gICAgICAgICAgICBjaGlsZFZub2RlLnByb3BzLm9udXBkYXRlICYmIGNoaWxkVm5vZGUucHJvcHMub251cGRhdGUoY2hpbGRWbm9kZSwgb2xkQ2hpbGRWbm9kZSk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGNoaWxkVm5vZGUucHJvcHMub25jcmVhdGUgJiYgY2hpbGRWbm9kZS5wcm9wcy5vbmNyZWF0ZShjaGlsZFZub2RlKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGNoaWxkVm5vZGUuZG9tID0gY3JlYXRlRG9tRWxlbWVudChjaGlsZFZub2RlLnRhZywgY2hpbGRWbm9kZS5pc1NWRyk7XG4gICAgICAgIHNldEF0dHJpYnV0ZXMoY2hpbGRWbm9kZSk7XG4gICAgICAgIGNoaWxkVm5vZGUucHJvcHMub25jcmVhdGUgJiYgY2hpbGRWbm9kZS5wcm9wcy5vbmNyZWF0ZShjaGlsZFZub2RlKTtcbiAgICAgIH1cblxuICAgICAgaWYgKG5ld1Zub2RlLmRvbS5jaGlsZE5vZGVzW2ldID09PSBVbmQpIHtcbiAgICAgICAgbmV3Vm5vZGUuZG9tLmFwcGVuZENoaWxkKGNoaWxkVm5vZGUuZG9tKTtcbiAgICAgIH0gZWxzZSBpZiAobmV3Vm5vZGUuZG9tLmNoaWxkTm9kZXNbaV0gIT09IGNoaWxkVm5vZGUuZG9tKSB7XG4gICAgICAgIG9sZFRyZWVbaV0gJiYgbmV3S2V5ZWRMaXN0W29sZFRyZWVbaV0ucHJvcHMua2V5XSA9PT0gVW5kICYmIG9ucmVtb3ZlKG9sZFRyZWVbaV0pO1xuICAgICAgICBuZXdWbm9kZS5kb20ucmVwbGFjZUNoaWxkKGNoaWxkVm5vZGUuZG9tLCBuZXdWbm9kZS5kb20uY2hpbGROb2Rlc1tpXSk7XG4gICAgICB9XG5cbiAgICAgIHNob3VsZFBhdGNoICYmIHBhdGNoKGNoaWxkVm5vZGUsIG9sZENoaWxkVm5vZGUsIHZhbHlyaWFuQXBwKTtcbiAgICB9XG5cbiAgICAvLyBGb3IgdGhlIHJlc3Qgb2YgdGhlIGNoaWxkcmVuLCB3ZSBzaG91bGQgcmVtb3ZlIHRoZW1cbiAgICBmb3IgKGxldCBpID0gbmV3VHJlZUxlbmd0aDsgaSA8IG9sZFRyZWVMZW5ndGg7IGkrKykge1xuICAgICAgaWYgKG5ld0tleWVkTGlzdFtvbGRUcmVlW2ldLnByb3BzLmtleV0gPT09IFVuZCkge1xuICAgICAgICBsZXQgb2xkQ2hpbGRWbm9kZSA9IG9sZFRyZWVbaV07XG4gICAgICAgIG9ucmVtb3ZlKG9sZENoaWxkVm5vZGUpO1xuICAgICAgICBvbGRDaGlsZFZub2RlLmRvbS5wYXJlbnROb2RlICYmIG9sZENoaWxkVm5vZGUuZG9tLnBhcmVudE5vZGUucmVtb3ZlQ2hpbGQob2xkQ2hpbGRWbm9kZS5kb20pO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybjtcbiAgfVxuXG4gIC8vIElmIG5ldyB0cmVlIGFuZCBvbGQgdHJlZSBoYXZlIG1vcmUgdGhhbiBvbmUgY2hpbGQsIHdlIHNob3VsZCB1cGRhdGUgdGhlIGRvbVxuICBmb3IgKGxldCBpID0gMDsgaSA8IG5ld1RyZWVMZW5ndGg7IGkrKykge1xuICAgIGxldCBuZXdDaGlsZFZub2RlID0gbmV3VHJlZVtpXTtcblxuICAgIC8vIE9sZCBjaGlsZCBleGlzdHNcbiAgICBpZiAoaSA8IG9sZFRyZWVMZW5ndGgpIHtcbiAgICAgIGxldCBvbGRDaGlsZFZub2RlID0gb2xkVHJlZVtpXTtcbiAgICAgIC8vIE5ldyBjaGlsZCBpcyBhIHRleHQgbm9kZVxuICAgICAgaWYgKG5ld0NoaWxkVm5vZGUudGFnID09PSBUZXh0U3RyaW5nKSB7XG4gICAgICAgIC8vIE9sZCBjaGlsZCBpcyBhIHRleHQgbm9kZVxuICAgICAgICBpZiAob2xkQ2hpbGRWbm9kZS50YWcgPT09IFRleHRTdHJpbmcpIHtcbiAgICAgICAgICBuZXdDaGlsZFZub2RlLmRvbSA9IG9sZENoaWxkVm5vZGUuZG9tO1xuICAgICAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBlcWVxZXFcbiAgICAgICAgICBpZiAobmV3Q2hpbGRWbm9kZS5kb20ubm9kZVZhbHVlICE9IG5ld0NoaWxkVm5vZGUubm9kZVZhbHVlKSB7XG4gICAgICAgICAgICBuZXdDaGlsZFZub2RlLmRvbS5ub2RlVmFsdWUgPSBuZXdDaGlsZFZub2RlLm5vZGVWYWx1ZSBhcyBzdHJpbmc7XG4gICAgICAgICAgfVxuICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gT2xkIGNoaWxkIGlzIGEgbm9ybWFsIG5vZGVcbiAgICAgICAgbmV3Q2hpbGRWbm9kZS5kb20gPSBkb2N1bWVudC5jcmVhdGVUZXh0Tm9kZShuZXdDaGlsZFZub2RlLm5vZGVWYWx1ZSBhcyBzdHJpbmcpIGFzIHVua25vd24gYXMgRG9tRWxlbWVudDtcbiAgICAgICAgb25yZW1vdmUob2xkQ2hpbGRWbm9kZSk7XG4gICAgICAgIG5ld1Zub2RlLmRvbS5yZXBsYWNlQ2hpbGQobmV3Q2hpbGRWbm9kZS5kb20sIG9sZENoaWxkVm5vZGUuZG9tKTtcblxuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cblxuICAgICAgLy8gTmV3IGNoaWxkIGlzIGEgbm9ybWFsIG5vZGVcbiAgICAgIC8vIE9sZCBjaGlsZCBpcyB0aGUgc2FtZSB0eXBlIGFzIG5ldyBjaGlsZFxuICAgICAgaWYgKG9sZENoaWxkVm5vZGUudGFnID09PSBuZXdDaGlsZFZub2RlLnRhZykge1xuICAgICAgICBuZXdDaGlsZFZub2RlLmRvbSA9IG9sZENoaWxkVm5vZGUuZG9tO1xuICAgICAgICAvLyBJZiB3ZSBoYXZlIGEgdi1vbmNlIGRpcmVjdGl2ZSBvciBhIHNob3VsZHVwZGF0ZSBtZXRob2QgdGhhdCByZXR1cm5zIGZhbHNlLCB3ZSBza2lwIHRoZSB1cGRhdGVcbiAgICAgICAgaWYgKG5ld0NoaWxkVm5vZGUucHJvcHNbXCJ2LW9uY2VcIl0gfHwgKG5ld0NoaWxkVm5vZGUucHJvcHMuc2hvdWxkdXBkYXRlICYmIG5ld0NoaWxkVm5vZGUucHJvcHMuc2hvdWxkdXBkYXRlKG5ld0NoaWxkVm5vZGUsIG9sZENoaWxkVm5vZGUpID09PSBmYWxzZSkpIHtcbiAgICAgICAgICBuZXdDaGlsZFZub2RlLmNoaWxkcmVuID0gb2xkQ2hpbGRWbm9kZS5jaGlsZHJlbjtcbiAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFdlIHVwZGF0ZSB0aGUgZG9tIGVsZW1lbnRcbiAgICAgICAgc2V0QXR0cmlidXRlcyhuZXdDaGlsZFZub2RlLCBvbGRDaGlsZFZub2RlKTtcbiAgICAgICAgaWYgKHZhbHlyaWFuQXBwLmlzTW91bnRlZCkge1xuICAgICAgICAgIG5ld0NoaWxkVm5vZGUucHJvcHMub251cGRhdGUgJiYgbmV3Q2hpbGRWbm9kZS5wcm9wcy5vbnVwZGF0ZShuZXdDaGlsZFZub2RlLCBvbGRDaGlsZFZub2RlKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBuZXdDaGlsZFZub2RlLnByb3BzLm9uY3JlYXRlICYmIG5ld0NoaWxkVm5vZGUucHJvcHMub25jcmVhdGUobmV3Q2hpbGRWbm9kZSk7XG4gICAgICAgIH1cblxuICAgICAgICBwYXRjaChuZXdDaGlsZFZub2RlLCBvbGRDaGlsZFZub2RlLCB2YWx5cmlhbkFwcCk7XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuXG4gICAgICAvLyBPbGQgY2hpbGQgaXMgb2YgYSBkaWZmZXJlbnQgdHlwZSB0aGFuIG5ldyBjaGlsZFxuICAgICAgbmV3Q2hpbGRWbm9kZS5kb20gPSBjcmVhdGVEb21FbGVtZW50KG5ld0NoaWxkVm5vZGUudGFnLCBuZXdDaGlsZFZub2RlLmlzU1ZHKTtcbiAgICAgIHNldEF0dHJpYnV0ZXMobmV3Q2hpbGRWbm9kZSk7XG4gICAgICBvbGRDaGlsZFZub2RlLnRhZyAhPT0gVGV4dFN0cmluZyAmJiBvbnJlbW92ZShvbGRDaGlsZFZub2RlKTtcbiAgICAgIG5ld0NoaWxkVm5vZGUucHJvcHMub25jcmVhdGUgJiYgbmV3Q2hpbGRWbm9kZS5wcm9wcy5vbmNyZWF0ZShuZXdDaGlsZFZub2RlKTtcbiAgICAgIG5ld1Zub2RlLmRvbS5yZXBsYWNlQ2hpbGQobmV3Q2hpbGRWbm9kZS5kb20sIG9sZENoaWxkVm5vZGUuZG9tKTtcbiAgICAgIHBhdGNoKG5ld0NoaWxkVm5vZGUsIGVtcHR5Vm5vZGUsIHZhbHlyaWFuQXBwKTtcbiAgICAgIGNvbnRpbnVlO1xuICAgIH1cblxuICAgIC8vIE9sZCBjaGlsZCBkb2VzIG5vdCBleGlzdHNcbiAgICAvLyBOZXcgY2hpbGQgaXMgYSB0ZXh0IG5vZGVcbiAgICBpZiAobmV3Q2hpbGRWbm9kZS50YWcgPT09IFRleHRTdHJpbmcpIHtcbiAgICAgIG5ld0NoaWxkVm5vZGUuZG9tID0gZG9jdW1lbnQuY3JlYXRlVGV4dE5vZGUobmV3Q2hpbGRWbm9kZS5ub2RlVmFsdWUgYXMgc3RyaW5nKSBhcyB1bmtub3duIGFzIERvbUVsZW1lbnQ7XG4gICAgICBuZXdWbm9kZS5kb20uYXBwZW5kQ2hpbGQobmV3Q2hpbGRWbm9kZS5kb20pO1xuICAgICAgY29udGludWU7XG4gICAgfVxuXG4gICAgLy8gTmV3IGNoaWxkIGlzIGEgbm9ybWFsIG5vZGVcbiAgICBuZXdDaGlsZFZub2RlLmRvbSA9IGNyZWF0ZURvbUVsZW1lbnQobmV3Q2hpbGRWbm9kZS50YWcsIG5ld0NoaWxkVm5vZGUuaXNTVkcpO1xuICAgIHNldEF0dHJpYnV0ZXMobmV3Q2hpbGRWbm9kZSk7XG4gICAgbmV3Vm5vZGUuZG9tLmFwcGVuZENoaWxkKG5ld0NoaWxkVm5vZGUuZG9tKTtcbiAgICBuZXdDaGlsZFZub2RlLnByb3BzLm9uY3JlYXRlICYmIG5ld0NoaWxkVm5vZGUucHJvcHMub25jcmVhdGUobmV3Q2hpbGRWbm9kZSk7XG4gICAgcGF0Y2gobmV3Q2hpbGRWbm9kZSwgZW1wdHlWbm9kZSwgdmFseXJpYW5BcHApO1xuICB9XG5cbiAgLy8gRm9yIHRoZSByZXN0IG9mIHRoZSBjaGlsZHJlbiwgd2Ugc2hvdWxkIHJlbW92ZSB0aGVtXG4gIGZvciAobGV0IGkgPSBuZXdUcmVlTGVuZ3RoOyBpIDwgb2xkVHJlZUxlbmd0aDsgaSsrKSB7XG4gICAgbGV0IG9sZENoaWxkVm5vZGUgPSBvbGRUcmVlW2ldO1xuICAgIG9sZENoaWxkVm5vZGUudGFnICE9PSBUZXh0U3RyaW5nICYmIG9ucmVtb3ZlKG9sZENoaWxkVm5vZGUpO1xuICAgIG9sZENoaWxkVm5vZGUuZG9tLnBhcmVudE5vZGUgJiYgb2xkQ2hpbGRWbm9kZS5kb20ucGFyZW50Tm9kZS5yZW1vdmVDaGlsZChvbGRDaGlsZFZub2RlLmRvbSk7XG4gIH1cbn1cblxuLyoqKiBEaXJlY3RpdmVzICoqKi9cblxuZXhwb3J0IGZ1bmN0aW9uIGRpcmVjdGl2ZShuYW1lOiBzdHJpbmcsIGRpcmVjdGl2ZTogRGlyZWN0aXZlKSB7XG4gIGxldCBmdWxsTmFtZSA9IGB2LSR7bmFtZX1gO1xuICBkaXJlY3RpdmVzW2Z1bGxOYW1lXSA9IGRpcmVjdGl2ZTtcbiAgcmVzZXJ2ZWRQcm9wc1tmdWxsTmFtZV0gPSB0cnVlO1xufVxuXG5mdW5jdGlvbiBoaWRlRGlyZWN0aXZlKHRlc3Q6IGJvb2xlYW4pOiBEaXJlY3RpdmUge1xuICByZXR1cm4gKGJvb2w6IGJvb2xlYW4sIHZub2RlOiBJVm5vZGUsIG9sZFZub2RlPzogSVZub2RlKSA9PiB7XG4gICAgbGV0IHZhbHVlID0gdGVzdCA/IGJvb2wgOiAhYm9vbDtcbiAgICBpZiAodmFsdWUpIHtcbiAgICAgIGxldCBuZXdkb20gPSBkb2N1bWVudC5jcmVhdGVUZXh0Tm9kZShcIlwiKTtcbiAgICAgIGlmIChvbGRWbm9kZSAmJiBvbGRWbm9kZS5kb20gJiYgb2xkVm5vZGUuZG9tLnBhcmVudE5vZGUpIHtcbiAgICAgICAgb2xkVm5vZGUudGFnICE9PSBUZXh0U3RyaW5nICYmIG9ucmVtb3ZlKG9sZFZub2RlKTtcbiAgICAgICAgb2xkVm5vZGUuZG9tLnBhcmVudE5vZGUucmVwbGFjZUNoaWxkKG5ld2RvbSwgb2xkVm5vZGUuZG9tKTtcbiAgICAgIH1cbiAgICAgIHZub2RlLnRhZyA9IFRleHRTdHJpbmc7XG4gICAgICB2bm9kZS5jaGlsZHJlbiA9IFtdO1xuICAgICAgdm5vZGUucHJvcHMgPSB7fTtcbiAgICAgIHZub2RlLmRvbSA9IG5ld2RvbSBhcyB1bmtub3duIGFzIERvbUVsZW1lbnQ7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICB9O1xufVxuXG5jb25zdCBkaXJlY3RpdmVzOiBEaXJlY3RpdmVzID0ge1xuICBcInYtaWZcIjogaGlkZURpcmVjdGl2ZShmYWxzZSksXG4gIFwidi11bmxlc3NcIjogaGlkZURpcmVjdGl2ZSh0cnVlKSxcbiAgXCJ2LWZvclwiOiAoc2V0OiB1bmtub3duW10sIHZub2RlOiBWbm9kZVdpdGhEb20pID0+IHtcbiAgICB2bm9kZS5jaGlsZHJlbiA9IHNldC5tYXAodm5vZGUuY2hpbGRyZW5bMF0gYXMgKHZhbHVlOiB1bmtub3duKSA9PiBGdW5jdGlvbik7XG4gIH0sXG4gIFwidi1zaG93XCI6IChib29sOiBib29sZWFuLCB2bm9kZTogVm5vZGVXaXRoRG9tKSA9PiB7XG4gICAgKHZub2RlLmRvbSBhcyB1bmtub3duIGFzIHsgc3R5bGU6IHsgZGlzcGxheTogc3RyaW5nIH0gfSkuc3R5bGUuZGlzcGxheSA9IGJvb2wgPyBcIlwiIDogXCJub25lXCI7XG4gIH0sXG4gIFwidi1jbGFzc1wiOiAoY2xhc3NlczogeyBbeDogc3RyaW5nXTogYm9vbGVhbiB9LCB2bm9kZTogVm5vZGVXaXRoRG9tKSA9PiB7XG4gICAgZm9yIChsZXQgbmFtZSBpbiBjbGFzc2VzKSB7XG4gICAgICAodm5vZGUuZG9tIGFzIERvbUVsZW1lbnQpLmNsYXNzTGlzdC50b2dnbGUobmFtZSwgY2xhc3Nlc1tuYW1lXSk7XG4gICAgfVxuICB9LFxuICBcInYtaHRtbFwiOiAoaHRtbDogc3RyaW5nLCB2bm9kZTogVm5vZGVXaXRoRG9tKSA9PiB7XG4gICAgdm5vZGUuY2hpbGRyZW4gPSBbdHJ1c3QoaHRtbCldO1xuICB9LFxuICBcInYtbW9kZWxcIjogKFttb2RlbCwgcHJvcGVydHksIGV2ZW50XTogYW55W10sIHZub2RlOiBWbm9kZVdpdGhEb20sIG9sZFZub2RlPzogVm5vZGVXaXRoRG9tKSA9PiB7XG4gICAgbGV0IHZhbHVlO1xuICAgIGxldCBoYW5kbGVyO1xuICAgIGlmICh2bm9kZS5uYW1lID09PSBcImlucHV0XCIpIHtcbiAgICAgIGV2ZW50ID0gZXZlbnQgfHwgXCJvbmlucHV0XCI7XG4gICAgICBzd2l0Y2ggKHZub2RlLnByb3BzLnR5cGUpIHtcbiAgICAgICAgY2FzZSBcImNoZWNrYm94XCI6IHtcbiAgICAgICAgICBpZiAoQXJyYXkuaXNBcnJheShtb2RlbFtwcm9wZXJ0eV0pKSB7XG4gICAgICAgICAgICBoYW5kbGVyID0gKGU6IEV2ZW50KSA9PiB7XG4gICAgICAgICAgICAgIGxldCB2YWwgPSAoZS50YXJnZXQgYXMgRG9tRWxlbWVudCAmIFJlY29yZDxzdHJpbmcsIGFueT4pLnZhbHVlO1xuICAgICAgICAgICAgICBsZXQgaWR4ID0gbW9kZWxbcHJvcGVydHldLmluZGV4T2YodmFsKTtcbiAgICAgICAgICAgICAgaWYgKGlkeCA9PT0gLTEpIHtcbiAgICAgICAgICAgICAgICBtb2RlbFtwcm9wZXJ0eV0ucHVzaCh2YWwpO1xuICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIG1vZGVsW3Byb3BlcnR5XS5zcGxpY2UoaWR4LCAxKTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIHZhbHVlID0gbW9kZWxbcHJvcGVydHldLmluZGV4T2Yodm5vZGUuZG9tLnZhbHVlKSAhPT0gLTE7XG4gICAgICAgICAgfSBlbHNlIGlmIChcInZhbHVlXCIgaW4gdm5vZGUucHJvcHMpIHtcbiAgICAgICAgICAgIGhhbmRsZXIgPSAoKSA9PiB7XG4gICAgICAgICAgICAgIGlmIChtb2RlbFtwcm9wZXJ0eV0gPT09IHZub2RlLnByb3BzLnZhbHVlKSB7XG4gICAgICAgICAgICAgICAgbW9kZWxbcHJvcGVydHldID0gbnVsbDtcbiAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBtb2RlbFtwcm9wZXJ0eV0gPSB2bm9kZS5wcm9wcy52YWx1ZTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIHZhbHVlID0gbW9kZWxbcHJvcGVydHldID09PSB2bm9kZS5wcm9wcy52YWx1ZTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgaGFuZGxlciA9ICgpID0+IChtb2RlbFtwcm9wZXJ0eV0gPSAhbW9kZWxbcHJvcGVydHldKTtcbiAgICAgICAgICAgIHZhbHVlID0gbW9kZWxbcHJvcGVydHldO1xuICAgICAgICAgIH1cbiAgICAgICAgICBzZXRBdHRyaWJ1dGUoXCJjaGVja2VkXCIsIHZhbHVlLCB2bm9kZSwgb2xkVm5vZGUpO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgICAgIGNhc2UgXCJyYWRpb1wiOiB7XG4gICAgICAgICAgc2V0QXR0cmlidXRlKFwiY2hlY2tlZFwiLCBtb2RlbFtwcm9wZXJ0eV0gPT09IHZub2RlLmRvbS52YWx1ZSwgdm5vZGUsIG9sZFZub2RlKTtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgICAgICBkZWZhdWx0OiB7XG4gICAgICAgICAgc2V0QXR0cmlidXRlKFwidmFsdWVcIiwgbW9kZWxbcHJvcGVydHldLCB2bm9kZSwgb2xkVm5vZGUpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSBlbHNlIGlmICh2bm9kZS5uYW1lID09PSBcInNlbGVjdFwiKSB7XG4gICAgICBldmVudCA9IGV2ZW50IHx8IFwib25jbGlja1wiO1xuICAgICAgaWYgKHZub2RlLnByb3BzLm11bHRpcGxlKSB7XG4gICAgICAgIGhhbmRsZXIgPSAoZTogRXZlbnQgJiBSZWNvcmQ8c3RyaW5nLCBhbnk+KSA9PiB7XG4gICAgICAgICAgbGV0IHZhbCA9IChlLnRhcmdldCBhcyBEb21FbGVtZW50ICYgUmVjb3JkPHN0cmluZywgYW55PikudmFsdWU7XG4gICAgICAgICAgaWYgKGUuY3RybEtleSkge1xuICAgICAgICAgICAgbGV0IGlkeCA9IG1vZGVsW3Byb3BlcnR5XS5pbmRleE9mKHZhbCk7XG4gICAgICAgICAgICBpZiAoaWR4ID09PSAtMSkge1xuICAgICAgICAgICAgICBtb2RlbFtwcm9wZXJ0eV0ucHVzaCh2YWwpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgbW9kZWxbcHJvcGVydHldLnNwbGljZShpZHgsIDEpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBtb2RlbFtwcm9wZXJ0eV0uc3BsaWNlKDAsIG1vZGVsW3Byb3BlcnR5XS5sZW5ndGgpO1xuICAgICAgICAgICAgbW9kZWxbcHJvcGVydHldLnB1c2godmFsKTtcbiAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIHZub2RlLmNoaWxkcmVuLmZvckVhY2goKGNoaWxkOiBJVm5vZGUpID0+IHtcbiAgICAgICAgICBpZiAoY2hpbGQudGFnID09PSBcIm9wdGlvblwiKSB7XG4gICAgICAgICAgICBsZXQgdmFsdWUgPSBcInZhbHVlXCIgaW4gY2hpbGQucHJvcHMgPyBjaGlsZC5wcm9wcy52YWx1ZSA6IGNoaWxkLmNoaWxkcmVuLmpvaW4oXCJcIikudHJpbSgpO1xuICAgICAgICAgICAgY2hpbGQucHJvcHMuc2VsZWN0ZWQgPSBtb2RlbFtwcm9wZXJ0eV0uaW5kZXhPZih2YWx1ZSkgIT09IC0xO1xuICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB2bm9kZS5jaGlsZHJlbi5mb3JFYWNoKChjaGlsZDogSVZub2RlKSA9PiB7XG4gICAgICAgICAgaWYgKGNoaWxkLnRhZyA9PT0gXCJvcHRpb25cIikge1xuICAgICAgICAgICAgbGV0IHZhbHVlID0gXCJ2YWx1ZVwiIGluIGNoaWxkLnByb3BzID8gY2hpbGQucHJvcHMudmFsdWUgOiBjaGlsZC5jaGlsZHJlbi5qb2luKFwiXCIpLnRyaW0oKTtcbiAgICAgICAgICAgIGNoaWxkLnByb3BzLnNlbGVjdGVkID0gdmFsdWUgPT09IG1vZGVsW3Byb3BlcnR5XTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgIH0gZWxzZSBpZiAodm5vZGUubmFtZSA9PT0gXCJ0ZXh0YXJlYVwiKSB7XG4gICAgICBldmVudCA9IGV2ZW50IHx8IFwib25pbnB1dFwiO1xuICAgICAgdm5vZGUuY2hpbGRyZW4gPSBbbW9kZWxbcHJvcGVydHldXTtcbiAgICB9XG5cbiAgICBpZiAoIXZub2RlLnByb3BzW2V2ZW50XSkge1xuICAgICAgaWYgKCFoYW5kbGVyKSB7XG4gICAgICAgIGhhbmRsZXIgPSAoZTogRXZlbnQpID0+IChtb2RlbFtwcm9wZXJ0eV0gPSAoZS50YXJnZXQgYXMgRG9tRWxlbWVudCAmIFJlY29yZDxzdHJpbmcsIGFueT4pLnZhbHVlKTtcbiAgICAgIH1cbiAgICAgIHNldEF0dHJpYnV0ZShldmVudCwgaGFuZGxlciwgdm5vZGUsIG9sZFZub2RlKTtcbiAgICB9XG4gIH1cbn07XG5cbi8qKiogUGx1Z2lucyAqKiovXG5jb25zdCBwbHVnaW5zID0gbmV3IE1hcDxQbHVnaW4sIGFueT4oKTtcblxuZXhwb3J0IGZ1bmN0aW9uIHVzZShwbHVnaW46IFBsdWdpbiwgb3B0aW9ucz86IFJlY29yZDxzdHJpbmcgfCBudW1iZXIgfCBzeW1ib2wsIGFueT4pOiB2b2lkIHwgYW55IHtcbiAgaWYgKHBsdWdpbnMuaGFzKHBsdWdpbikpIHtcbiAgICByZXR1cm4gcGx1Z2lucy5nZXQocGx1Z2luKTtcbiAgfVxuXG4gIGxldCByZXN1bHQgPSBwbHVnaW4odiwgb3B0aW9ucyk7XG4gIHBsdWdpbnMuc2V0KHBsdWdpbiwgcmVzdWx0KTtcbiAgcmV0dXJuIHJlc3VsdDtcbn1cblxuLyoqKiBIeXBlcnNjcmlwdCAqKiovXG5cbmV4cG9ydCBjb25zdCB2OiBWYWx5cmlhbiA9IGZ1bmN0aW9uIHYodGFnT3JDb21wb25lbnQ6IHN0cmluZyB8IFZhbHlyaWFuQ29tcG9uZW50LCBwcm9wczogUHJvcHMsIC4uLmNoaWxkcmVuOiBDaGlsZHJlbik6IElWbm9kZSB8IFZub2RlQ29tcG9uZW50IHtcbiAgaWYgKHR5cGVvZiB0YWdPckNvbXBvbmVudCA9PT0gXCJzdHJpbmdcIikge1xuICAgIHJldHVybiBuZXcgVm5vZGUodGFnT3JDb21wb25lbnQsIHByb3BzIHx8IHt9LCBjaGlsZHJlbik7XG4gIH1cblxuICBjb25zdCB2bm9kZSA9IG5ldyBWbm9kZShcIl9fY29tcG9uZW50X19cIiwgcHJvcHMgfHwge30sIGNoaWxkcmVuKTtcbiAgdm5vZGUuY29tcG9uZW50ID0gdGFnT3JDb21wb25lbnQ7XG4gIHJldHVybiB2bm9kZSBhcyBWbm9kZUNvbXBvbmVudDtcbn07XG5cbnYuZnJhZ21lbnQgPSAocHJvcHM6IFByb3BzLCAuLi5jaGlsZHJlbjogQ2hpbGRyZW4pOiBDaGlsZHJlbiA9PiB7XG4gIHJldHVybiBjaGlsZHJlbjtcbn07XG5cbi8qKiogViBwcm9wZXJ0aWVzIGFuZCBtZXRob2RzICoqKi9cbi8vIFRoaXMgaXMgaW50ZW5kZWQgdG8gbWFrZSB0aGUgcHJvcGVydGllcyBhbmQgbWV0aG9kcyBhdmFpbGFibGUgZm9yIHBsdWdpbnNcbnYuY3VycmVudCA9IGN1cnJlbnQ7XG5cbnYuZGlyZWN0aXZlcyA9IGRpcmVjdGl2ZXM7XG5cbnYucmVzZXJ2ZWRQcm9wcyA9IHJlc2VydmVkUHJvcHM7XG5cbnYuaXNWbm9kZSA9IGlzVm5vZGU7XG52LmlzQ29tcG9uZW50ID0gaXNDb21wb25lbnQ7XG52LmlzVm5vZGVDb21wb25lbnQgPSBpc1Zub2RlQ29tcG9uZW50O1xuXG52LmlzTm9kZUpzID0gaXNOb2RlSnM7XG52LnRydXN0ID0gdHJ1c3Q7XG5cbnYub25DbGVhbnVwID0gb25DbGVhbnVwO1xudi5vblVubW91bnQgPSBvblVubW91bnQ7XG52Lm9uTW91bnQgPSBvbk1vdW50O1xudi5vblVwZGF0ZSA9IG9uVXBkYXRlO1xuXG52Lm1vdW50ID0gbW91bnQ7XG52LnVubW91bnQgPSB1bm1vdW50O1xudi51cGRhdGUgPSB1cGRhdGU7XG5cbnYuc2V0QXR0cmlidXRlID0gc2V0QXR0cmlidXRlO1xudi5kaXJlY3RpdmUgPSBkaXJlY3RpdmU7XG52LnVzZSA9IHVzZTtcbiJdfQ== \ No newline at end of file diff --git a/lib/index.ts b/lib/index.ts index c65d86b..0883d1c 100644 --- a/lib/index.ts +++ b/lib/index.ts @@ -18,6 +18,15 @@ import { VnodeWithDom } from "./interfaces"; +/*** Constants ***/ +const ComponentString = "__component__"; +const TextString = "#text"; +export const isNodeJs = Boolean(typeof process !== "undefined" && process.versions && process.versions.node); +const ValyrianSymbol = Symbol("Valyrian"); +const Und = undefined; + +/*** Vnode ***/ + export const Vnode = function Vnode(this: IVnode, tag: string, props: Props, children: Children) { this.props = props; this.children = children; @@ -33,13 +42,11 @@ export function isComponent(component?: unknown | ValyrianComponent): component } export function isVnodeComponent(vnode?: unknown | VnodeComponent): vnode is VnodeComponent { - return vnode instanceof Vnode && vnode.tag === "__component__"; + return vnode instanceof Vnode && vnode.tag === ComponentString; } /*** Util ***/ -export const isNodeJs = Boolean(typeof process !== "undefined" && process.versions && process.versions.node); - function createDomElement(tag: string, isSVG: boolean = false) { return isSVG ? document.createElementNS("http://www.w3.org/2000/svg", tag) : document.createElement(tag); } @@ -55,7 +62,7 @@ function domToVnode(dom: DomElement): VnodeWithDom { return domToVnode(child as DomElement); } - let text = new Vnode("#text", {}, []); + let text = new Vnode(TextString, {}, []); text.nodeValue = String((child as DomElement).nodeValue); text.dom = child as DomElement; return text; @@ -80,7 +87,6 @@ const reservedProps: ReservedProps = { onupdate: true, onremove: true, shouldupdate: true, - "v-cleanup": true, "v-once": true, // Built in directives @@ -94,29 +100,29 @@ const reservedProps: ReservedProps = { /*** Mount ***/ -const ValyrianSymbol = Symbol("Valyrian"); +const current: Current = {}; export function onCleanup(callback: Function) { - if (v.current.app?.onCleanup.indexOf(callback) === -1) { - v.current.app?.onCleanup.push(callback); + if (current.app?.onCleanup.indexOf(callback) === -1) { + current.app?.onCleanup.push(callback); } } export function onUnmount(callback: Function) { - if (v.current.app?.onUnmount.indexOf(callback) === -1) { - v.current.app?.onUnmount.push(callback); + if (current.app?.onUnmount.indexOf(callback) === -1) { + current.app?.onUnmount.push(callback); } } export function onMount(callback: Function) { - if (v.current.app?.onMount.indexOf(callback) === -1) { - v.current.app?.onMount.push(callback); + if (current.app?.onMount.indexOf(callback) === -1) { + current.app?.onMount.push(callback); } } export function onUpdate(callback: Function) { - if (v.current.app?.onUpdate.indexOf(callback) === -1) { - v.current.app?.onUpdate.push(callback); + if (current.app?.onUpdate.indexOf(callback) === -1) { + current.app?.onUpdate.push(callback); } } @@ -182,7 +188,6 @@ export function mount(container: DomElement | string, component: ValyrianCompone component[ValyrianSymbol].component = vnodeComponent; component[ValyrianSymbol].container = appContainer; component[ValyrianSymbol].mainVnode = domToVnode(appContainer); - component[ValyrianSymbol].mainVnode.isSVG = component[ValyrianSymbol].tag === "svg"; // update return update(component); @@ -219,12 +224,11 @@ function callUpdate(valyrianApp: ValyrianApp) { export function update(component?: ValyrianComponent | IVnode): void | string { if (component && component[ValyrianSymbol]) { let valyrianApp = component[ValyrianSymbol]; - v.current.app = valyrianApp; + current.app = valyrianApp; valyrianApp.onCleanup.length && callCleanup(valyrianApp); let oldVnode: VnodeWithDom | null = valyrianApp.mainVnode as VnodeWithDom; valyrianApp.mainVnode = new Vnode(valyrianApp.mainVnode.tag, valyrianApp.mainVnode.props, [valyrianApp.component]) as VnodeWithDom; valyrianApp.mainVnode.dom = oldVnode.dom; - valyrianApp.mainVnode.isSVG = oldVnode.isSVG; patch(valyrianApp.mainVnode, oldVnode, valyrianApp); oldVnode = null; if (valyrianApp.isMounted === false) { @@ -270,26 +274,27 @@ let emptyVnode = new Vnode("__empty__", {}, []); function onremove(vnode: IVnode) { for (let i = 0; i < vnode.children.length; i++) { - vnode.children[i].tag !== "#text" && onremove(vnode.children[i]); + vnode.children[i].tag !== TextString && onremove(vnode.children[i]); } vnode.props.onremove && vnode.props.onremove(vnode); } -function sharedSetAttribute(prop: string, value: any, vnode: VnodeWithDom, oldVnode?: VnodeWithDom) { +function sharedSetAttribute(prop: string, value: any, vnode: VnodeWithDom, oldVnode?: VnodeWithDom): void | boolean { // It is a reserved prop if (reservedProps[prop]) { // If it is a directive name call the directive if (directives[prop]) { - directives[prop](vnode.props[prop], vnode, oldVnode); + return directives[prop](vnode.props[prop], vnode, oldVnode); } + return; } // It is not a reserved prop so we add it to the dom if (typeof value === "function") { - let valyrianApp = v.current.app as MountedValyrianApp; - if (!valyrianApp.eventListenerNames[prop]) { + let valyrianApp = current.app as MountedValyrianApp; + if (prop in valyrianApp.eventListenerNames === false) { valyrianApp.eventListenerNames[prop] = true; valyrianApp.container.addEventListener(prop.slice(2), valyrianApp.eventListener); } @@ -316,50 +321,45 @@ function sharedSetAttribute(prop: string, value: any, vnode: VnodeWithDom, oldVn } export function setAttribute(name: string, value: any, vnode: VnodeWithDom, oldVnode?: VnodeWithDom) { - if (name in vnode.props === false) { - vnode.props[name] = value; - } + vnode.props[name] = value; sharedSetAttribute(name, value, vnode, oldVnode); } function setAttributes(vnode: VnodeWithDom, oldVnode?: VnodeWithDom) { for (let prop in vnode.props) { - // We asume that we clean the props in some directive - if (prop in vnode.props === false) { + if (sharedSetAttribute(prop, vnode.props[prop], vnode, oldVnode) === false) { return; } - - sharedSetAttribute(prop, vnode.props[prop], vnode, oldVnode); } -} -function removeAttributes(vnode: VnodeWithDom, oldVnode: VnodeWithDom) { - for (let prop in oldVnode.props) { - if (prop in vnode.props === false && typeof oldVnode.props[prop] !== "function" && prop in v.reservedProps === false) { - if (prop in oldVnode.dom && vnode.isSVG === false) { - oldVnode.dom[prop] = null; - } else { - oldVnode.dom.removeAttribute(prop); + if (oldVnode) { + for (let prop in oldVnode.props) { + if (prop in vnode.props === false && typeof oldVnode.props[prop] !== "function" && prop in reservedProps === false) { + if (prop in oldVnode.dom && vnode.isSVG === false) { + oldVnode.dom[prop] = null; + } else { + oldVnode.dom.removeAttribute(prop); + } } } } } // eslint-disable-next-line complexity -function patch(newVnode: VnodeWithDom, oldVnode: VnodeWithDom = emptyVnode as VnodeWithDom, valyrianApp: MountedValyrianApp) { - v.current.vnode = newVnode; - v.current.oldVnode = oldVnode; +function patch(newVnode: VnodeWithDom, oldVnode: VnodeWithDom | IVnode = emptyVnode, valyrianApp: MountedValyrianApp) { + current.vnode = newVnode; + current.oldVnode = oldVnode === emptyVnode ? Und : (oldVnode as VnodeWithDom); let newTree = newVnode.children; let oldTree = oldVnode.children; for (let i = 0; i < newTree.length; i++) { let childVnode = newTree[i]; if (childVnode instanceof Vnode) { - if (childVnode.tag !== "#text") { - if (childVnode.tag === "__component__") { + if (childVnode.tag !== TextString) { + if (childVnode.tag === ComponentString) { let component = childVnode.component as ValyrianComponent; - v.current.component = component; + current.component = component; let result = ("view" in component ? component.view : component).call(component, childVnode.props, ...childVnode.children); newTree.splice(i--, 1, result); @@ -367,13 +367,13 @@ function patch(newVnode: VnodeWithDom, oldVnode: VnodeWithDom = emptyVnode as Vn } childVnode.isSVG = newVnode.isSVG || childVnode.tag === "svg"; } - } else if (childVnode === null || childVnode === undefined) { - newTree.splice(i--, 1); } else if (Array.isArray(childVnode)) { newTree.splice(i--, 1, ...childVnode); + } else if (childVnode === null || childVnode === Und) { + newTree.splice(i--, 1); } else { - newTree[i] = new Vnode("#text", {}, []); - newTree[i].nodeValue = String(childVnode); + newTree[i] = new Vnode(TextString, {}, []); + newTree[i].nodeValue = childVnode; } } @@ -414,7 +414,6 @@ function patch(newVnode: VnodeWithDom, oldVnode: VnodeWithDom = emptyVnode as Vn shouldPatch = false; } else { setAttributes(childVnode, oldChildVnode); - removeAttributes(childVnode, oldChildVnode); if (valyrianApp.isMounted) { childVnode.props.onupdate && childVnode.props.onupdate(childVnode, oldChildVnode); } else { @@ -427,10 +426,10 @@ function patch(newVnode: VnodeWithDom, oldVnode: VnodeWithDom = emptyVnode as Vn childVnode.props.oncreate && childVnode.props.oncreate(childVnode); } - if (newVnode.dom.childNodes[i] === undefined) { + if (newVnode.dom.childNodes[i] === Und) { newVnode.dom.appendChild(childVnode.dom); } else if (newVnode.dom.childNodes[i] !== childVnode.dom) { - oldTree[i] && newKeyedList[oldTree[i].props.key] === undefined && onremove(oldTree[i]); + oldTree[i] && newKeyedList[oldTree[i].props.key] === Und && onremove(oldTree[i]); newVnode.dom.replaceChild(childVnode.dom, newVnode.dom.childNodes[i]); } @@ -439,7 +438,7 @@ function patch(newVnode: VnodeWithDom, oldVnode: VnodeWithDom = emptyVnode as Vn // For the rest of the children, we should remove them for (let i = newTreeLength; i < oldTreeLength; i++) { - if (newKeyedList[oldTree[i].props.key] === undefined) { + if (newKeyedList[oldTree[i].props.key] === Und) { let oldChildVnode = oldTree[i]; onremove(oldChildVnode); oldChildVnode.dom.parentNode && oldChildVnode.dom.parentNode.removeChild(oldChildVnode.dom); @@ -451,15 +450,15 @@ function patch(newVnode: VnodeWithDom, oldVnode: VnodeWithDom = emptyVnode as Vn // If new tree and old tree have more than one child, we should update the dom for (let i = 0; i < newTreeLength; i++) { - let oldChildVnode = oldTree[i]; let newChildVnode = newTree[i]; // Old child exists - if (oldChildVnode) { + if (i < oldTreeLength) { + let oldChildVnode = oldTree[i]; // New child is a text node - if (newChildVnode.tag === "#text") { + if (newChildVnode.tag === TextString) { // Old child is a text node - if (oldChildVnode.tag === "#text") { + if (oldChildVnode.tag === TextString) { newChildVnode.dom = oldChildVnode.dom; // eslint-disable-next-line eqeqeq if (newChildVnode.dom.nodeValue != newChildVnode.nodeValue) { @@ -488,32 +487,29 @@ function patch(newVnode: VnodeWithDom, oldVnode: VnodeWithDom = emptyVnode as Vn // We update the dom element setAttributes(newChildVnode, oldChildVnode); - removeAttributes(newChildVnode, oldChildVnode); if (valyrianApp.isMounted) { newChildVnode.props.onupdate && newChildVnode.props.onupdate(newChildVnode, oldChildVnode); } else { newChildVnode.props.oncreate && newChildVnode.props.oncreate(newChildVnode); } - patch(newChildVnode, oldChildVnode, valyrianApp); + patch(newChildVnode, oldChildVnode, valyrianApp); continue; } // Old child is of a different type than new child newChildVnode.dom = createDomElement(newChildVnode.tag, newChildVnode.isSVG); setAttributes(newChildVnode); - if (oldChildVnode.tag !== "#text") { - onremove(oldChildVnode); - } + oldChildVnode.tag !== TextString && onremove(oldChildVnode); newChildVnode.props.oncreate && newChildVnode.props.oncreate(newChildVnode); newVnode.dom.replaceChild(newChildVnode.dom, oldChildVnode.dom); - patch(newChildVnode, undefined, valyrianApp); + patch(newChildVnode, emptyVnode, valyrianApp); continue; } // Old child does not exists // New child is a text node - if (newChildVnode.tag === "#text") { + if (newChildVnode.tag === TextString) { newChildVnode.dom = document.createTextNode(newChildVnode.nodeValue as string) as unknown as DomElement; newVnode.dom.appendChild(newChildVnode.dom); continue; @@ -524,16 +520,13 @@ function patch(newVnode: VnodeWithDom, oldVnode: VnodeWithDom = emptyVnode as Vn setAttributes(newChildVnode); newVnode.dom.appendChild(newChildVnode.dom); newChildVnode.props.oncreate && newChildVnode.props.oncreate(newChildVnode); - patch(newChildVnode, undefined, valyrianApp); - + patch(newChildVnode, emptyVnode, valyrianApp); } // For the rest of the children, we should remove them for (let i = newTreeLength; i < oldTreeLength; i++) { let oldChildVnode = oldTree[i]; - if (oldChildVnode.tag !== "#text") { - onremove(oldChildVnode); - } + oldChildVnode.tag !== TextString && onremove(oldChildVnode); oldChildVnode.dom.parentNode && oldChildVnode.dom.parentNode.removeChild(oldChildVnode.dom); } } @@ -542,8 +535,8 @@ function patch(newVnode: VnodeWithDom, oldVnode: VnodeWithDom = emptyVnode as Vn export function directive(name: string, directive: Directive) { let fullName = `v-${name}`; - v.directives[fullName] = directive; - v.reservedProps[fullName] = true; + directives[fullName] = directive; + reservedProps[fullName] = true; } function hideDirective(test: boolean): Directive { @@ -552,13 +545,14 @@ function hideDirective(test: boolean): Directive { if (value) { let newdom = document.createTextNode(""); if (oldVnode && oldVnode.dom && oldVnode.dom.parentNode) { - oldVnode.tag !== "#text" && onremove(oldVnode); + oldVnode.tag !== TextString && onremove(oldVnode); oldVnode.dom.parentNode.replaceChild(newdom, oldVnode.dom); } - vnode.tag = "#text"; + vnode.tag = TextString; vnode.children = []; vnode.props = {}; vnode.dom = newdom as unknown as DomElement; + return false; } }; } @@ -698,7 +692,7 @@ v.fragment = (props: Props, ...children: Children): Children => { /*** V properties and methods ***/ // This is intended to make the properties and methods available for plugins -v.current = {} as Current; +v.current = current; v.directives = directives; diff --git a/plugins/utils/tree-adapter.js b/plugins/utils/tree-adapter.js index 77dbe2d..c9a20b9 100644 --- a/plugins/utils/tree-adapter.js +++ b/plugins/utils/tree-adapter.js @@ -174,13 +174,20 @@ class Node { class Text extends Node { constructor(text) { super(3, "#text"); - this.textContent = text; + this.node_value = String(text); } + node_value = ""; set textContent(text) { - this.nodeValue = String(text); + this.node_value = String(text); } get textContent() { - return this.nodeValue; + return this.node_value; + } + set nodeValue(text) { + this.node_value = String(text); + } + get nodeValue() { + return this.node_value; } } @@ -363,8 +370,7 @@ class Element extends Node { cloneNode() { let div = document.createElement("div"); div.innerHTML = this.outerHTML; - let el = div.firstChild; - return el; + return div.firstChild; } get firstChild() { From 755645ed54c82d26f1cb848803cf642500af032a Mon Sep 17 00:00:00 2001 From: Masquerade Circus Date: Fri, 18 Feb 2022 12:13:06 -0600 Subject: [PATCH 11/19] Updated --- bench/.buffalo-test.json | 500 +++++++++++++++++++++++++++++++++++++++ bench/index-old.js | 2 +- lib/index.ts | 6 +- lib/interfaces.ts | 4 +- plugins/store.js | 10 +- plugins/sw.js | 3 +- 6 files changed, 517 insertions(+), 8 deletions(-) diff --git a/bench/.buffalo-test.json b/bench/.buffalo-test.json index 6f24d53..bcded1a 100644 --- a/bench/.buffalo-test.json +++ b/bench/.buffalo-test.json @@ -1,4 +1,504 @@ [ + { + "tag": "8ee2c0b01c5ff0e70587dc197617db13018d6b4b", + "timestamp": "2022-02-18T17:56:28.277Z", + "suites": { + "Matching keyed list": { + "Removed at the end": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "Matching keyed list -> stress": { + "Removed at the end": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "hyperscript": { + "Valyrian 5.0.8": { + "hz": 15826318.698386787, + "meanTime": 0.00006318588795396445, + "medianTime": 0.00005600042641162872, + "standardDeviation": 0.00041938183081103626, + "maxTime": 0.6461410000920296, + "minTime": 0.000048998743295669556 + }, + "Valyrian next": { + "hz": 15979429.301208284, + "meanTime": 0.00006258045773414354, + "medianTime": 0.000058999285101890564, + "standardDeviation": 0.00029970880865018906, + "maxTime": 0.43538499996066093, + "minTime": 0.000048998743295669556 + } + }, + "Set.has vs [].indexOf": { + "Set.has": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "[].indexOf": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "Object.keys for loop vs Object.keys for of vs for in": { + "Object.keys for loop": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "Object.keys for of": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "for in": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "typeof function vs startsWith vs charAt vs string[0]": { + "typeof function": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "startsWith": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "charAt": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "string[0]": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "Array.isArray vs typeof object & Array.isArray": { + "Array.isArray": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "typeof object & Array.isArray": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "string comparison vs instance comparison vs property comparison": { + "string comparison": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "instance comparison": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "property comparison": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "property string comparison": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "typeof comparison": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "Object with property equals true vs set vs map vs string array": { + "Object with property equals true": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "key in object": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "set": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "map": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "string array": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "For loop if/continue vs if/else": { + "for loop if/continue": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "for loop if/else": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "map array of strings vs reduce with object keys equals index": { + "map array of strings": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "reduce with object keys equals index": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "array by for": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "object by for": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "object map by for": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "Symbol access vs direct access": { + "Direct access access": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "Symbol access access": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "Mount and update: Mount multiple types": { + "Valyrian 5.0.8": { + "hz": 149820.98145979192, + "meanTime": 0.006674632553173963, + "medianTime": 0.006341999396681786, + "standardDeviation": 0.004890587577619386, + "maxTime": 0.9418930001556873, + "minTime": 0.006046999245882034 + }, + "Valyrian next": { + "hz": 219.64299441340884, + "meanTime": 4.552842683057828, + "medianTime": 3.944251000881195, + "standardDeviation": 1.0526752445177507, + "maxTime": 15.64694899879396, + "minTime": 3.682345001026988 + } + }, + "Mount and update: Mount single text": { + "Valyrian 5.0.8": { + "hz": 1274748.8365707635, + "meanTime": 0.0007844682586180091, + "medianTime": 0.0006980001926422119, + "standardDeviation": 0.0036275670281757278, + "maxTime": 0.9234349988400936, + "minTime": 0.0006140004843473434 + }, + "Valyrian next": { + "hz": 1030333.0270050403, + "meanTime": 0.0009705599779779825, + "medianTime": 0.0008430015295743942, + "standardDeviation": 0.004477517876345002, + "maxTime": 1.7103610001504421, + "minTime": 0.0007469989359378815 + } + }, + "Mount and update: Mount single text in div": { + "Valyrian 5.0.8": { + "hz": 743806.3525947747, + "meanTime": 0.0013444359496413167, + "medianTime": 0.001202000305056572, + "standardDeviation": 0.006539302106062292, + "maxTime": 2.5767620000988245, + "minTime": 0.001058001071214676 + }, + "Valyrian next": { + "hz": 637604.4110100463, + "meanTime": 0.0015683705801468237, + "medianTime": 0.001338999718427658, + "standardDeviation": 0.007384922171649113, + "maxTime": 0.7896369993686676, + "minTime": 0.001166999340057373 + } + }, + "Mount and update: Update multiple types": { + "Valyrian 5.0.8": { + "hz": 64423.19587500971, + "meanTime": 0.015522359398936746, + "medianTime": 0.014667998999357224, + "standardDeviation": 0.012813584170645464, + "maxTime": 1.7863989993929863, + "minTime": 0.01405400037765503 + }, + "Valyrian next": { + "hz": 89.96917279162383, + "meanTime": 11.114918243341906, + "medianTime": 10.660915000364184, + "standardDeviation": 1.1566958434652994, + "maxTime": 24.305686999112368, + "minTime": 10.167387999594212 + } + }, + "Mount and update: Update single text": { + "Valyrian 5.0.8": { + "hz": 514879.7401684514, + "meanTime": 0.001942201104422624, + "medianTime": 0.0017949994653463364, + "standardDeviation": 0.00574504795924177, + "maxTime": 2.413348000496626, + "minTime": 0.001687999814748764 + }, + "Valyrian next": { + "hz": 580988.2352304558, + "meanTime": 0.0017212052488521361, + "medianTime": 0.0014730002731084824, + "standardDeviation": 0.011352834819472118, + "maxTime": 11.02280700020492, + "minTime": 0.0013829991221427917 + } + }, + "Mount and update: Render list": { + "vOld": { + "hz": 31094.44763656415, + "meanTime": 0.032160082458711825, + "medianTime": 0.029333001002669334, + "standardDeviation": 0.029701970732171276, + "maxTime": 2.286031000316143, + "minTime": 0.028245000168681145 + }, + "VNext": { + "hz": 32169.03522978382, + "meanTime": 0.031085793927514066, + "medianTime": 0.027785999700427055, + "standardDeviation": 0.030112827696981346, + "maxTime": 2.3631319999694824, + "minTime": 0.025744998827576637 + } + }, + "Mount and update: Render keyed list": { + "vOld": { + "hz": 8121.695124710499, + "meanTime": 0.12312700546434822, + "medianTime": 0.10807999968528748, + "standardDeviation": 0.09909183315302132, + "maxTime": 4.288349000737071, + "minTime": 0.10346500016748905 + }, + "VNext": { + "hz": 9303.114026787878, + "meanTime": 0.10749088930013617, + "medianTime": 0.0928729996085167, + "standardDeviation": 0.2119213107791509, + "maxTime": 41.89445700123906, + "minTime": 0.0864850003272295 + } + }, + "Mount and update: Render keyed list -> stress": { + "vOld": { + "hz": 4290.273506833652, + "meanTime": 0.23308537285727252, + "medianTime": 0.20196899957954884, + "standardDeviation": 0.1631035158995494, + "maxTime": 2.762967998161912, + "minTime": 0.19378499872982502 + }, + "VNext": { + "hz": 4795.642477616159, + "meanTime": 0.20852263375919647, + "medianTime": 0.18345599994063377, + "standardDeviation": 0.23749080001876208, + "maxTime": 29.148431001231074, + "minTime": 0.1677969992160797 + } + }, + "Mount and update: Render keyed list -> swap keys on large set": { + "vOld": { + "hz": 742.0811925014037, + "meanTime": 1.347561439509341, + "medianTime": 1.1005080007016659, + "standardDeviation": 0.6366548325131208, + "maxTime": 5.304254999384284, + "minTime": 0.9995709992945194 + }, + "VNext": { + "hz": 802.2642801718677, + "meanTime": 1.2464720475723683, + "medianTime": 1.0820850003510714, + "standardDeviation": 0.6140147044979994, + "maxTime": 27.181886000558734, + "minTime": 0.9548999983817339 + } + }, + "Mount and update: Update class": { + "vOld update": { + "hz": 1229456.450397081, + "meanTime": 0.0008133675655425023, + "medianTime": 0.0007619988173246384, + "standardDeviation": 0.004122510886838122, + "maxTime": 5.169614000245929, + "minTime": 0.0007060002535581589 + }, + "VNext update": { + "hz": 13965456.945974354, + "meanTime": 0.00007160524742359091, + "medianTime": 0.00006899982690811157, + "standardDeviation": 0.0004713339294665467, + "maxTime": 0.8383689988404512, + "minTime": 0.00005499832332134247 + } + }, + "Lifecycle vs hooks": { + "Hooks": { + "hz": 361475.5865528843, + "meanTime": 0.002766438556850364, + "medianTime": 0.002394000068306923, + "standardDeviation": 0.011011801340114655, + "maxTime": 2.7585150003433228, + "minTime": 0.002167999744415283 + }, + "Lifecycle": { + "hz": 366956.53041034855, + "meanTime": 0.0027251184190175103, + "medianTime": 0.0022840015590190887, + "standardDeviation": 0.02169705587130068, + "maxTime": 19.725862000137568, + "minTime": 0.002002999186515808 + } + } + } + }, { "tag": "fa8448f9349a5415dd52b8495f9692db63ee3bbf", "timestamp": "2022-02-17T21:36:15.314Z", diff --git a/bench/index-old.js b/bench/index-old.js index 5263fa1..3fd6915 100644 --- a/bench/index-old.js +++ b/bench/index-old.js @@ -458,4 +458,4 @@ function valyrian() { const v = valyrian(); -module.exports = v; +module.exports = { v }; diff --git a/lib/index.ts b/lib/index.ts index 0883d1c..015eddf 100644 --- a/lib/index.ts +++ b/lib/index.ts @@ -73,11 +73,11 @@ function domToVnode(dom: DomElement): VnodeWithDom { return vnode as VnodeWithDom; } -export const trust = (htmlString: string): IVnode[] => { +export const trust = (htmlString: string): Children => { let div = createDomElement("div"); div.innerHTML = htmlString.trim(); - return [].map.call(div.childNodes, (item) => domToVnode(item)) as IVnode[]; + return [].map.call(div.childNodes, (item) => domToVnode(item)) as Children; }; const reservedProps: ReservedProps = { @@ -383,7 +383,7 @@ function patch(newVnode: VnodeWithDom, oldVnode: VnodeWithDom | IVnode = emptyVn // If new tree is empty, remove all old nodes if (newTreeLength === 0) { for (let i = 0; i < oldTreeLength; i++) { - onremove(oldTree[i]); + oldTree[i].tag !== TextString && onremove(oldTree[i]); } newVnode.dom.textContent = ""; diff --git a/lib/interfaces.ts b/lib/interfaces.ts index 60d17b5..3788aee 100644 --- a/lib/interfaces.ts +++ b/lib/interfaces.ts @@ -17,7 +17,7 @@ export interface Props { export interface Children extends Array {} export interface IVnode { - new (tag: string, props: Props, children: IVnode[]): IVnode; + new (tag: string, props: Props, children: Children): IVnode; tag: string; props: Props; children: Children; @@ -106,7 +106,7 @@ export interface Valyrian { isVnodeComponent: (vnode?: unknown | VnodeComponent) => vnode is VnodeComponent; isNodeJs: boolean; - trust: (htmlString: string) => IVnode[]; + trust: (htmlString: string) => Children; onCleanup: (fn: Function) => void; onUnmount: (fn: Function) => void; diff --git a/plugins/store.js b/plugins/store.js index 5ab9c47..59d2146 100644 --- a/plugins/store.js +++ b/plugins/store.js @@ -73,13 +73,21 @@ function Store({ state = {}, getters = {}, actions = {}, mutations = {} } = {}) let update = () => {}; let current = {}; -function plugin(v) { +function plugin(v, options) { current = v.current; update = () => { if (current.app) { v.update(v.current.app.component); } }; + + if (options) { + v.store = new Store(options); + v.commit = v.store.commit; + v.dispatch = v.store.dispatch; + v.state = v.store.state; + v.getters = v.store.getters; + } } plugin.Store = Store; diff --git a/plugins/sw.js b/plugins/sw.js index 61b1150..7713465 100644 --- a/plugins/sw.js +++ b/plugins/sw.js @@ -6,7 +6,8 @@ class Sw { constructor(file, options) { if (Boolean(typeof process !== "undefined" && process.versions && process.versions.node)) { - throw new Error("Not supported in Node.js"); + console.info('Service Worker registration not supported in node.js'); + return; } if (file) { From 64a1d67f8022c1b214a70b783fe2704485ebc416 Mon Sep 17 00:00:00 2001 From: Masquerade Circus Date: Fri, 18 Feb 2022 17:47:14 -0600 Subject: [PATCH 12/19] Update keyed lists --- lib/index.ts | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/lib/index.ts b/lib/index.ts index 015eddf..87e7a0d 100644 --- a/lib/index.ts +++ b/lib/index.ts @@ -392,14 +392,15 @@ function patch(newVnode: VnodeWithDom, oldVnode: VnodeWithDom | IVnode = emptyVn // If the tree is keyed list and is not first render and old tree is keyed list too if (oldTreeLength && "key" in newTree[0].props && "key" in oldTree[0].props) { - let oldKeyedList = oldTree.reduce((acc, vnode, i) => { - acc[vnode.props.key] = i; - return acc; - }, {} as { [key: string]: number }); - let newKeyedList = newTree.reduce((acc, vnode, i) => { - acc[vnode.props.key] = i; - return acc; - }, {} as { [key: string]: number }); + let oldKeyedList: {[key: string]: number} = {}; + for (let i = 0; i < oldTreeLength; i++) { + oldKeyedList[oldTree[i].props.key] = i; + } + + let newKeyedList: {[key: string]: number} = {}; + for (let i = 0; i < newTreeLength; i++) { + newKeyedList[newTree[i].props.key] = i; + } for (let i = 0; i < newTreeLength; i++) { let childVnode = newTree[i]; From 5020819ecd7d6f03e2e3b5bb7599df97963194f2 Mon Sep 17 00:00:00 2001 From: Masquerade Circus Date: Fri, 18 Feb 2022 20:11:48 -0600 Subject: [PATCH 13/19] Implement useRef useCallback and useMemo --- bench/.buffalo-test.json | 500 +++++++++++++++++++++++++++++++++++++++ plugins/hooks.js | 54 ++++- test/hooks_test.js | 105 +++++++- 3 files changed, 652 insertions(+), 7 deletions(-) diff --git a/bench/.buffalo-test.json b/bench/.buffalo-test.json index bcded1a..db6763a 100644 --- a/bench/.buffalo-test.json +++ b/bench/.buffalo-test.json @@ -1,4 +1,504 @@ [ + { + "tag": "755645ed54c82d26f1cb848803cf642500af032a", + "timestamp": "2022-02-18T21:56:17.184Z", + "suites": { + "Matching keyed list": { + "Removed at the end": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "Matching keyed list -> stress": { + "Removed at the end": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "hyperscript": { + "Valyrian 5.0.8": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "Valyrian next": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "Set.has vs [].indexOf": { + "Set.has": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "[].indexOf": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "Object.keys for loop vs Object.keys for of vs for in": { + "Object.keys for loop": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "Object.keys for of": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "for in": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "typeof function vs startsWith vs charAt vs string[0]": { + "typeof function": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "startsWith": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "charAt": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "string[0]": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "Array.isArray vs typeof object & Array.isArray": { + "Array.isArray": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "typeof object & Array.isArray": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "string comparison vs instance comparison vs property comparison": { + "string comparison": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "instance comparison": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "property comparison": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "property string comparison": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "typeof comparison": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "Object with property equals true vs set vs map vs string array": { + "Object with property equals true": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "key in object": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "set": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "map": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "string array": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "For loop if/continue vs if/else": { + "for loop if/continue": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "for loop if/else": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "map array of strings vs reduce with object keys equals index": { + "map array of strings": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "reduce with object keys equals index": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "array by for": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "object by for": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "object map by for": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "Symbol access vs direct access": { + "Direct access access": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "Symbol access access": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "Mount and update: Mount multiple types": { + "Valyrian 5.0.8": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "Valyrian next": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "Mount and update: Mount single text": { + "Valyrian 5.0.8": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "Valyrian next": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "Mount and update: Mount single text in div": { + "Valyrian 5.0.8": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "Valyrian next": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "Mount and update: Update multiple types": { + "Valyrian 5.0.8": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "Valyrian next": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "Mount and update: Update single text": { + "Valyrian 5.0.8": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "Valyrian next": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "Mount and update: Render list": { + "vOld": { + "hz": 8700.091887036857, + "meanTime": 0.11494131475668673, + "medianTime": 0.10851800069212914, + "standardDeviation": 0.06136097328472064, + "maxTime": 9.930821999907494, + "minTime": 0.10422899946570396 + }, + "VNext": { + "hz": 37589.16774011621, + "meanTime": 0.026603408910614745, + "medianTime": 0.024797998368740082, + "standardDeviation": 0.017901167663638386, + "maxTime": 3.530186999589205, + "minTime": 0.02287200093269348 + } + }, + "Mount and update: Render keyed list": { + "vOld": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "VNext": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "Mount and update: Render keyed list -> stress": { + "vOld": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "VNext": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "Mount and update: Render keyed list -> swap keys on large set": { + "vOld": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "VNext": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "Mount and update: Update class": { + "vOld update": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "VNext update": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "Lifecycle vs hooks": { + "Hooks": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "Lifecycle": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + } + } + }, { "tag": "8ee2c0b01c5ff0e70587dc197617db13018d6b4b", "timestamp": "2022-02-18T17:56:28.277Z", diff --git a/plugins/hooks.js b/plugins/hooks.js index 79ead22..8de6998 100644 --- a/plugins/hooks.js +++ b/plugins/hooks.js @@ -1,8 +1,10 @@ -let current = {}; +let v = { + current: {} +}; -function createHook({ create, update, remove }) { +function createHook({ create, update, remove, returnValue }) { return (...args) => { - let { component, vnode, oldVnode, app } = current; + let { component, vnode, oldVnode, app } = v.current; // Init the components array for the current vnode if (vnode.components === undefined) { @@ -41,6 +43,10 @@ function createHook({ create, update, remove }) { } } + if (returnValue) { + return returnValue(hook); + } + return hook; }; } @@ -107,13 +113,49 @@ const useEffect = createHook({ } }); -function plugin(v) { - current = v.current; +const useRef = createHook({ + create: (initialValue) => { + v.directive("ref", (ref, vnode) => { + ref.current = vnode.dom; + }); + return { current: initialValue }; + } +}); + +const useCallback = createHook({ + create: (callback) => { + return callback; + } +}); + +const useMemo = createHook({ + create: (callback, changes) => { + return { callback, changes, value: callback() }; + }, + update: (hook, callback, changes) => { + for (let i = 0, l = changes.length; i < l; i++) { + if (changes[i] !== hook.changes[i]) { + hook.changes = changes; + hook.value = callback(); + return; + } + } + }, + returnValue: (hook) => { + return hook.value; + } +}); + +function plugin(vInstance) { + v = vInstance; } +plugin.createHook = createHook; plugin.useState = useState; plugin.useEffect = useEffect; -plugin.createHook = createHook; +plugin.useRef = useRef; +plugin.useCallback = useCallback; +plugin.useMemo = useMemo; plugin.default = plugin; module.exports = plugin; diff --git a/test/hooks_test.js b/test/hooks_test.js index af4aefe..6aab4b8 100644 --- a/test/hooks_test.js +++ b/test/hooks_test.js @@ -1,7 +1,7 @@ import "../plugins/node"; import { v } from "../lib/index"; -import plugin, { useEffect, useState } from "../plugins/hooks"; +import plugin, { useEffect, useState, useRef, useCallback, useMemo } from "../plugins/hooks"; import expect from "expect"; import { v } from "../lib"; @@ -251,4 +251,107 @@ describe("Hooks", () => { }); }); }); + + describe("Ref hook", () => { + it("should return a ref", () => { + let ref; + let updated = false; + let Component = function () { + ref = useRef(null); + if (!updated) { + expect(ref.current).toEqual(null); + } + return
Hello world
; + }; + + let response = v.mount("body", Component); + expect(response).toEqual("
Hello world
"); + expect(ref.current).not.toEqual(null); + + let refCurrent = ref.current; + updated = true; + v.update(Component); + expect(refCurrent === ref.current).toEqual(true); + }); + }); + + describe("Callback hook", () => { + it("should test the callback problem", () => { + let callback; + let Component = function () { + callback = () => {}; + return
Hello world
; + }; + + let response = v.mount("body", Component); + expect(response).toEqual("
Hello world
"); + expect(callback).not.toEqual(null); + + let oldCallback = callback; + v.update(Component); + expect(oldCallback === callback).toEqual(false); + }); + + it("should call the callback", () => { + let callback; + let Component = function () { + callback = useCallback(() => {}, []); + return
Hello world
; + }; + let response = v.mount("body", Component); + expect(response).toEqual("
Hello world
"); + expect(callback).not.toEqual(null); + let oldCallback = callback; + v.update(Component); + expect(oldCallback === callback).toEqual(true); + }); + }); + + describe("Memo hook", () => { + it("should test the memo problem", () => { + let computedTimes = 0; + let color = "red"; + let Component = function () { + computedTimes++; + return
Hello world
; + }; + + let response = v.mount("body", Component); + expect(response).toEqual('
Hello world
'); + expect(computedTimes).toEqual(1); + + let response2 = v.update(Component); + expect(response2).toEqual('
Hello world
'); + expect(computedTimes).toEqual(2); + + color = "blue"; + let response3 = v.update(Component); + expect(response3).toEqual('
Hello world
'); + expect(computedTimes).toEqual(3); + }); + + it("should use the memo", () => { + let computedTimes = 0; + let color = "red"; + let Component = function () { + return useMemo(() => { + computedTimes++; + return
; + }, [color]); + }; + + let response = v.mount("body", Component); + expect(response).toEqual('
'); + expect(computedTimes).toEqual(1); + + let response2 = v.update(Component); + expect(response2).toEqual('
'); + expect(computedTimes).toEqual(1); + + color = "blue"; + let response3 = v.update(Component); + expect(response3).toEqual('
'); + expect(computedTimes).toEqual(2); + }); + }); }); From b8683777fb260acbdba2cab3a34b304584e4563d Mon Sep 17 00:00:00 2001 From: Masquerade Circus Date: Fri, 18 Feb 2022 20:33:14 -0600 Subject: [PATCH 14/19] Update benchmarks --- bench/.buffalo-test.json | 518 ++++++++++++++++++++++++++++++++++ bench/mount_n_update_bench.js | 68 ++++- 2 files changed, 583 insertions(+), 3 deletions(-) diff --git a/bench/.buffalo-test.json b/bench/.buffalo-test.json index db6763a..114d896 100644 --- a/bench/.buffalo-test.json +++ b/bench/.buffalo-test.json @@ -1,4 +1,522 @@ [ + { + "tag": "5020819ecd7d6f03e2e3b5bb7599df97963194f2", + "timestamp": "2022-02-19T02:32:51.142Z", + "suites": { + "Matching keyed list": { + "Removed at the end": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "Matching keyed list -> stress": { + "Removed at the end": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "hyperscript": { + "Valyrian 5.0.8": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "Valyrian next": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "Set.has vs [].indexOf": { + "Set.has": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "[].indexOf": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "Object.keys for loop vs Object.keys for of vs for in": { + "Object.keys for loop": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "Object.keys for of": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "for in": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "typeof function vs startsWith vs charAt vs string[0]": { + "typeof function": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "startsWith": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "charAt": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "string[0]": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "Array.isArray vs typeof object & Array.isArray": { + "Array.isArray": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "typeof object & Array.isArray": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "string comparison vs instance comparison vs property comparison": { + "string comparison": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "instance comparison": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "property comparison": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "property string comparison": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "typeof comparison": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "Object with property equals true vs set vs map vs string array": { + "Object with property equals true": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "key in object": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "set": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "map": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "string array": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "For loop if/continue vs if/else": { + "for loop if/continue": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "for loop if/else": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "map array of strings vs reduce with object keys equals index": { + "map array of strings": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "reduce with object keys equals index": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "array by for": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "object by for": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "object map by for": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "Symbol access vs direct access": { + "Direct access access": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "Symbol access access": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "Mount and update: Mount multiple types": { + "Valyrian 5.0.8": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "Valyrian next": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "Mount and update: Mount single text": { + "Valyrian 5.0.8": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "Valyrian next": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "Mount and update: Mount single text in div": { + "Valyrian 5.0.8": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "Valyrian next": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "Mount and update: Update multiple types": { + "Valyrian 5.0.8": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "Valyrian next": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "Mount and update: Update single text": { + "Valyrian 5.0.8": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "Valyrian next": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "Mount and update: Render list": { + "vOld": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "VNext": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "Mount and update: Render keyed list": { + "vOld": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "VNext": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "Mount and update: Render keyed list -> stress": { + "vOld": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "VNext": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "Mount and update: Render keyed list -> swap keys on large set": { + "vOld": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "VNext": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "Mount and update: Update class": { + "vOld update": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "VNext update": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "Mount and update: Update class with hooks vs shouldupdate property": { + "shouldupdate property": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "useMemo hook": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + }, + "Lifecycle vs hooks": { + "Hooks": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + }, + "Lifecycle": { + "hz": 0, + "meanTime": 0, + "medianTime": 0, + "standardDeviation": 0, + "maxTime": 0, + "minTime": 0 + } + } + } + }, { "tag": "755645ed54c82d26f1cb848803cf642500af032a", "timestamp": "2022-02-18T21:56:17.184Z", diff --git a/bench/mount_n_update_bench.js b/bench/mount_n_update_bench.js index 1995024..bed46d4 100644 --- a/bench/mount_n_update_bench.js +++ b/bench/mount_n_update_bench.js @@ -9,6 +9,7 @@ const plugin = require("../plugins/hooks"); use(plugin); const useEffect = plugin.useEffect; +const useMemo = plugin.useMemo; console.log(vOld); console.log(v); @@ -689,7 +690,7 @@ compare("Mount and update: Render keyed list -> swap keys on large set", () => { }); }); -compare("Mount and update: Update class", () => { +compare.only("Mount and update: Update class", () => { // Init with 1000 words let words = [...Array(1000).keys()].map((key) => `word ${key}`); let useData = false; @@ -717,12 +718,12 @@ compare("Mount and update: Update class", () => {
{useData ? ( words.map((word) => ( - vnode.props.class !== oldVnode.props.class}> + vnode.props.class !== oldVnode.props.class}> {word} )) ) : ( -
vnode.props.class !== oldVnode.props.class}> +
vnode.props.class !== oldVnode.props.class}> test
)} @@ -758,6 +759,67 @@ compare("Mount and update: Update class", () => { }); }); +compare("Mount and update: Update class with hooks vs shouldupdate property", () => { + // Init with 1000 words + let words = [...Array(1000).keys()].map((key) => `word ${key}`); + let useData = false; + let updateClass = false; + let updateClass2 = false; + let Component = () => ( +
+ {useData ? ( + words.map((word) => ( + vnode.props.class !== oldVnode.props.class}> + {word} + + )) + ) : ( +
vnode.props.class !== oldVnode.props.class}> + test +
+ )} +
+ ); + + let Component2 = () => ( +
+ {useData + ? words.map((word) => + useMemo(() => {word}, [updateClass2 === word ? "selected" : false]) + ) + : useMemo(() =>
test
, [updateClass2 === "test" ? "test" : false])} +
+ ); + + before(() => { + let before = mount("body", Component); + expect(before).toEqual("
test
"); + let before2 = mount("body", Component2); + expect(before2).toEqual("
test
"); + + updateClass = "test"; + updateClass2 = "test"; + + let after = update(Component); + expect(after).toEqual('
test
'); + let after2 = update(Component2); + expect(after2).toEqual('
test
'); + useData = true; + updateClass = false; + updateClass2 = false; + }); + + benchmark("shouldupdate property", () => { + update(Component); + updateClass = updateClass === "word 10" ? "word 100" : "word 10"; + }); + + benchmark("useMemo hook", () => { + update(Component2); + updateClass2 = updateClass2 === "word 10" ? "word 100" : "word 10"; + }); +}); + compare("Lifecycle vs hooks", () => { let lifecycleCount = 0; let plusLifeCycle = () => (lifecycleCount += 1); From cc572c7a35f8702f51103a2c6bbf4c0ba8a2d49d Mon Sep 17 00:00:00 2001 From: Masquerade Circus Date: Fri, 18 Feb 2022 20:38:07 -0600 Subject: [PATCH 15/19] Remove dot only and build source --- bench/mount_n_update_bench.js | 3 ++- dist/@types/lib/index.d.ts | 4 ++-- dist/@types/lib/interfaces.d.ts | 4 ++-- dist/index.cjs | 18 +++++++++--------- dist/index.js | 18 +++++++++--------- dist/index.min.js | 2 +- dist/index.min.js.map | 2 +- 7 files changed, 26 insertions(+), 25 deletions(-) diff --git a/bench/mount_n_update_bench.js b/bench/mount_n_update_bench.js index bed46d4..3d65ee8 100644 --- a/bench/mount_n_update_bench.js +++ b/bench/mount_n_update_bench.js @@ -1,3 +1,4 @@ +/* eslint-disable indent */ let { compare, benchmark, before, afterCycle } = require("buffalo-test"); const { mount, update, unmount, v, use } = require("../lib/index"); @@ -690,7 +691,7 @@ compare("Mount and update: Render keyed list -> swap keys on large set", () => { }); }); -compare.only("Mount and update: Update class", () => { +compare("Mount and update: Update class", () => { // Init with 1000 words let words = [...Array(1000).keys()].map((key) => `word ${key}`); let useData = false; diff --git a/dist/@types/lib/index.d.ts b/dist/@types/lib/index.d.ts index 651d188..fc9e427 100644 --- a/dist/@types/lib/index.d.ts +++ b/dist/@types/lib/index.d.ts @@ -1,10 +1,10 @@ -import { Directive, DomElement, IVnode, Plugin, Valyrian, ValyrianComponent, VnodeComponent, VnodeWithDom } from "./interfaces"; +import { Children, Directive, DomElement, IVnode, Plugin, Valyrian, ValyrianComponent, VnodeComponent, VnodeWithDom } from "./interfaces"; export declare const isNodeJs: boolean; export declare const Vnode: IVnode; export declare function isVnode(object?: unknown | IVnode): object is IVnode; export declare function isComponent(component?: unknown | ValyrianComponent): component is ValyrianComponent; export declare function isVnodeComponent(vnode?: unknown | VnodeComponent): vnode is VnodeComponent; -export declare const trust: (htmlString: string) => IVnode[]; +export declare const trust: (htmlString: string) => Children; export declare function onCleanup(callback: Function): void; export declare function onUnmount(callback: Function): void; export declare function onMount(callback: Function): void; diff --git a/dist/@types/lib/interfaces.d.ts b/dist/@types/lib/interfaces.d.ts index 4c92e5d..bae3c23 100644 --- a/dist/@types/lib/interfaces.d.ts +++ b/dist/@types/lib/interfaces.d.ts @@ -21,7 +21,7 @@ export interface Props { export interface Children extends Array { } export interface IVnode { - new (tag: string, props: Props, children: IVnode[]): IVnode; + new (tag: string, props: Props, children: Children): IVnode; tag: string; props: Props; children: Children; @@ -93,7 +93,7 @@ export interface Valyrian { isComponent: (component?: unknown | ValyrianComponent) => component is ValyrianComponent; isVnodeComponent: (vnode?: unknown | VnodeComponent) => vnode is VnodeComponent; isNodeJs: boolean; - trust: (htmlString: string) => IVnode[]; + trust: (htmlString: string) => Children; onCleanup: (fn: Function) => void; onUnmount: (fn: Function) => void; onMount: (fn: Function) => void; diff --git a/dist/index.cjs b/dist/index.cjs index 3dec4ea..7456cef 100644 --- a/dist/index.cjs +++ b/dist/index.cjs @@ -325,20 +325,20 @@ function patch(newVnode, oldVnode = emptyVnode, valyrianApp) { let newTreeLength = newTree.length; if (newTreeLength === 0) { for (let i = 0; i < oldTreeLength; i++) { - onremove(oldTree[i]); + oldTree[i].tag !== TextString && onremove(oldTree[i]); } newVnode.dom.textContent = ""; return; } if (oldTreeLength && "key" in newTree[0].props && "key" in oldTree[0].props) { - let oldKeyedList = oldTree.reduce((acc, vnode, i) => { - acc[vnode.props.key] = i; - return acc; - }, {}); - let newKeyedList = newTree.reduce((acc, vnode, i) => { - acc[vnode.props.key] = i; - return acc; - }, {}); + let oldKeyedList = {}; + for (let i = 0; i < oldTreeLength; i++) { + oldKeyedList[oldTree[i].props.key] = i; + } + let newKeyedList = {}; + for (let i = 0; i < newTreeLength; i++) { + newKeyedList[newTree[i].props.key] = i; + } for (let i = 0; i < newTreeLength; i++) { let childVnode = newTree[i]; let oldChildVnode = oldTree[oldKeyedList[childVnode.props.key]]; diff --git a/dist/index.js b/dist/index.js index f9c0e8b..679bb72 100644 --- a/dist/index.js +++ b/dist/index.js @@ -282,20 +282,20 @@ function patch(newVnode, oldVnode = emptyVnode, valyrianApp) { let newTreeLength = newTree.length; if (newTreeLength === 0) { for (let i = 0; i < oldTreeLength; i++) { - onremove(oldTree[i]); + oldTree[i].tag !== TextString && onremove(oldTree[i]); } newVnode.dom.textContent = ""; return; } if (oldTreeLength && "key" in newTree[0].props && "key" in oldTree[0].props) { - let oldKeyedList = oldTree.reduce((acc, vnode, i) => { - acc[vnode.props.key] = i; - return acc; - }, {}); - let newKeyedList = newTree.reduce((acc, vnode, i) => { - acc[vnode.props.key] = i; - return acc; - }, {}); + let oldKeyedList = {}; + for (let i = 0; i < oldTreeLength; i++) { + oldKeyedList[oldTree[i].props.key] = i; + } + let newKeyedList = {}; + for (let i = 0; i < newTreeLength; i++) { + newKeyedList[newTree[i].props.key] = i; + } for (let i = 0; i < newTreeLength; i++) { let childVnode = newTree[i]; let oldChildVnode = oldTree[oldKeyedList[childVnode.props.key]]; diff --git a/dist/index.min.js b/dist/index.min.js index cd2faf4..2532cda 100644 --- a/dist/index.min.js +++ b/dist/index.min.js @@ -1 +1 @@ -(()=>{var e="__component__",n="#text",o=Boolean("undefined"!=typeof process&&process.versions&&process.versions.node),t=Symbol("Valyrian"),r=void 0,i=function(e,n,o){this.props=n,this.children=o,this.tag=e};function p(e){return e instanceof i}function d(e){return"function"==typeof e||"object"==typeof e&&null!==e&&"view"in e}function l(n){return n instanceof i&&n.tag===e}function a(e,n=!1){return n?document.createElementNS("http://www.w3.org/2000/svg",e):document.createElement(e)}function s(e){let o=T(e.tagName.toLowerCase(),{},...Array.from(e.childNodes).filter(e=>1===e.nodeType||3===e.nodeType).map(e=>{if(1===e.nodeType)return s(e);let o=new i(n,{},[]);return o.nodeValue=String(e.nodeValue),o.dom=e,o}));return[].forEach.call(e.attributes,e=>o.props[e.nodeName]=e.nodeValue),o.dom=e,o}var u=e=>{let n=a("div");return n.innerHTML=e.trim(),[].map.call(n.childNodes,e=>s(e))},m={key:!0,state:!0,oncreate:!0,onupdate:!0,onremove:!0,shouldupdate:!0,"v-once":!0,"v-if":!0,"v-unless":!0,"v-for":!0,"v-show":!0,"v-class":!0,"v-html":!0},c={};function f(e){-1===c.app?.onCleanup.indexOf(e)&&c.app?.onCleanup.push(e)}function h(e){-1===c.app?.onUnmount.indexOf(e)&&c.app?.onUnmount.push(e)}function v(e){-1===c.app?.onMount.indexOf(e)&&c.app?.onMount.push(e)}function g(e){-1===c.app?.onUpdate.indexOf(e)&&c.app?.onUpdate.push(e)}function V(e,n){let r,i=null;if(i=o?"string"==typeof e?a("svg"===e?"svg":"div","svg"===e):e:"string"==typeof e?document.querySelectorAll(e)[0]:e,!i)throw new Error("Container not found");if(l(n))r=n;else{if(!d(n))throw new Error("Component must be a Valyrian Component or a Vnode component");r=T(n,{})}if(n[t])w(n);else{let e=function(e){let o=e.target,t=`v-on${e.type}`;for(;o;){if(o[t])return o[t](e,o),void(e.defaultPrevented||C(n));o=o.parentNode}};n[t]={isMounted:!1,eventListenerNames:{},onCleanup:[],onMount:[],onUpdate:[],onUnmount:[]},n[t].eventListener=e}return n[t].component=r,n[t].container=i,n[t].mainVnode=s(i),C(n)}function y(e){for(let n=0;n(e[n.props.key]=o,e),{}),n=d.reduce((e,n,o)=>(e[n.props.key]=o,e),{});for(let t=0;t{if(e?o:!o){let e=document.createTextNode("");return r&&r.dom&&r.dom.parentNode&&(r.tag!==n&&M(r),r.dom.parentNode.replaceChild(e,r.dom)),t.tag=n,t.children=[],t.props={},t.dom=e,!1}}}var A={"v-if":_(!1),"v-unless":_(!0),"v-for":(e,n)=>{n.children=e.map(n.children[0])},"v-show":(e,n)=>{n.dom.style.display=e?"":"none"},"v-class":(e,n)=>{for(let o in e)n.dom.classList.toggle(o,e[o])},"v-html":(e,n)=>{n.children=[u(e)]},"v-model":([e,n,o],t,r)=>{let i,p;if("input"===t.name)switch(o=o||"oninput",t.props.type){case"checkbox":Array.isArray(e[n])?(p=o=>{let t=o.target.value,r=e[n].indexOf(t);-1===r?e[n].push(t):e[n].splice(r,1)},i=-1!==e[n].indexOf(t.dom.value)):"value"in t.props?(p=()=>{e[n]===t.props.value?e[n]=null:e[n]=t.props.value},i=e[n]===t.props.value):(p=()=>e[n]=!e[n],i=e[n]),x("checked",i,t,r);break;case"radio":x("checked",e[n]===t.dom.value,t,r);break;default:x("value",e[n],t,r)}else"select"===t.name?(o=o||"onclick",t.props.multiple?(p=o=>{let t=o.target.value;if(o.ctrlKey){let o=e[n].indexOf(t);-1===o?e[n].push(t):e[n].splice(o,1)}else e[n].splice(0,e[n].length),e[n].push(t)},t.children.forEach(o=>{if("option"===o.tag){let t="value"in o.props?o.props.value:o.children.join("").trim();o.props.selected=-1!==e[n].indexOf(t)}})):t.children.forEach(o=>{if("option"===o.tag){let t="value"in o.props?o.props.value:o.children.join("").trim();o.props.selected=t===e[n]}})):"textarea"===t.name&&(o=o||"oninput",t.children=[e[n]]);t.props[o]||(p||(p=o=>e[n]=o.target.value),x(o,p,t,r))}},L=new Map;function G(e,n){if(L.has(e))return L.get(e);let o=e(T,n);return L.set(e,o),o}var T=function(e,n,...o){if("string"==typeof e)return new i(e,n||{},o);const t=new i("__component__",n||{},o);return t.component=e,t};T.fragment=(e,...n)=>n,T.current=c,T.directives=A,T.reservedProps=m,T.isVnode=p,T.isComponent=d,T.isVnodeComponent=l,T.isNodeJs=o,T.trust=u,T.onCleanup=f,T.onUnmount=h,T.onMount=v,T.onUpdate=g,T.mount=V,T.unmount=w,T.update=C,T.setAttribute=x,T.directive=b,T.use=G;var E={Vnode:i,directive:b,isComponent:d,isNodeJs:o,isVnode:p,isVnodeComponent:l,mount:V,onCleanup:f,onMount:v,onUnmount:h,onUpdate:g,setAttribute:x,trust:u,unmount:w,update:C,use:G,v:T};"undefined"!=typeof module?module.exports=E:self.Valyrian=E})(); \ No newline at end of file +(()=>{var e="__component__",n="#text",o=Boolean("undefined"!=typeof process&&process.versions&&process.versions.node),t=Symbol("Valyrian"),r=void 0,i=function(e,n,o){this.props=n,this.children=o,this.tag=e};function p(e){return e instanceof i}function d(e){return"function"==typeof e||"object"==typeof e&&null!==e&&"view"in e}function l(n){return n instanceof i&&n.tag===e}function a(e,n=!1){return n?document.createElementNS("http://www.w3.org/2000/svg",e):document.createElement(e)}function s(e){let o=T(e.tagName.toLowerCase(),{},...Array.from(e.childNodes).filter(e=>1===e.nodeType||3===e.nodeType).map(e=>{if(1===e.nodeType)return s(e);let o=new i(n,{},[]);return o.nodeValue=String(e.nodeValue),o.dom=e,o}));return[].forEach.call(e.attributes,e=>o.props[e.nodeName]=e.nodeValue),o.dom=e,o}var u=e=>{let n=a("div");return n.innerHTML=e.trim(),[].map.call(n.childNodes,e=>s(e))},m={key:!0,state:!0,oncreate:!0,onupdate:!0,onremove:!0,shouldupdate:!0,"v-once":!0,"v-if":!0,"v-unless":!0,"v-for":!0,"v-show":!0,"v-class":!0,"v-html":!0},c={};function f(e){-1===c.app?.onCleanup.indexOf(e)&&c.app?.onCleanup.push(e)}function h(e){-1===c.app?.onUnmount.indexOf(e)&&c.app?.onUnmount.push(e)}function v(e){-1===c.app?.onMount.indexOf(e)&&c.app?.onMount.push(e)}function g(e){-1===c.app?.onUpdate.indexOf(e)&&c.app?.onUpdate.push(e)}function V(e,n){let r,i=null;if(i=o?"string"==typeof e?a("svg"===e?"svg":"div","svg"===e):e:"string"==typeof e?document.querySelectorAll(e)[0]:e,!i)throw new Error("Container not found");if(l(n))r=n;else{if(!d(n))throw new Error("Component must be a Valyrian Component or a Vnode component");r=T(n,{})}if(n[t])w(n);else{let e=function(e){let o=e.target,t=`v-on${e.type}`;for(;o;){if(o[t])return o[t](e,o),void(e.defaultPrevented||C(n));o=o.parentNode}};n[t]={isMounted:!1,eventListenerNames:{},onCleanup:[],onMount:[],onUpdate:[],onUnmount:[]},n[t].eventListener=e}return n[t].component=r,n[t].container=i,n[t].mainVnode=s(i),C(n)}function y(e){for(let n=0;n{if(e?o:!o){let e=document.createTextNode("");return r&&r.dom&&r.dom.parentNode&&(r.tag!==n&&M(r),r.dom.parentNode.replaceChild(e,r.dom)),t.tag=n,t.children=[],t.props={},t.dom=e,!1}}}var A={"v-if":_(!1),"v-unless":_(!0),"v-for":(e,n)=>{n.children=e.map(n.children[0])},"v-show":(e,n)=>{n.dom.style.display=e?"":"none"},"v-class":(e,n)=>{for(let o in e)n.dom.classList.toggle(o,e[o])},"v-html":(e,n)=>{n.children=[u(e)]},"v-model":([e,n,o],t,r)=>{let i,p;if("input"===t.name)switch(o=o||"oninput",t.props.type){case"checkbox":Array.isArray(e[n])?(p=o=>{let t=o.target.value,r=e[n].indexOf(t);-1===r?e[n].push(t):e[n].splice(r,1)},i=-1!==e[n].indexOf(t.dom.value)):"value"in t.props?(p=()=>{e[n]===t.props.value?e[n]=null:e[n]=t.props.value},i=e[n]===t.props.value):(p=()=>e[n]=!e[n],i=e[n]),x("checked",i,t,r);break;case"radio":x("checked",e[n]===t.dom.value,t,r);break;default:x("value",e[n],t,r)}else"select"===t.name?(o=o||"onclick",t.props.multiple?(p=o=>{let t=o.target.value;if(o.ctrlKey){let o=e[n].indexOf(t);-1===o?e[n].push(t):e[n].splice(o,1)}else e[n].splice(0,e[n].length),e[n].push(t)},t.children.forEach(o=>{if("option"===o.tag){let t="value"in o.props?o.props.value:o.children.join("").trim();o.props.selected=-1!==e[n].indexOf(t)}})):t.children.forEach(o=>{if("option"===o.tag){let t="value"in o.props?o.props.value:o.children.join("").trim();o.props.selected=t===e[n]}})):"textarea"===t.name&&(o=o||"oninput",t.children=[e[n]]);t.props[o]||(p||(p=o=>e[n]=o.target.value),x(o,p,t,r))}},L=new Map;function G(e,n){if(L.has(e))return L.get(e);let o=e(T,n);return L.set(e,o),o}var T=function(e,n,...o){if("string"==typeof e)return new i(e,n||{},o);const t=new i("__component__",n||{},o);return t.component=e,t};T.fragment=(e,...n)=>n,T.current=c,T.directives=A,T.reservedProps=m,T.isVnode=p,T.isComponent=d,T.isVnodeComponent=l,T.isNodeJs=o,T.trust=u,T.onCleanup=f,T.onUnmount=h,T.onMount=v,T.onUpdate=g,T.mount=V,T.unmount=w,T.update=C,T.setAttribute=x,T.directive=b,T.use=G;var E={Vnode:i,directive:b,isComponent:d,isNodeJs:o,isVnode:p,isVnodeComponent:l,mount:V,onCleanup:f,onMount:v,onUnmount:h,onUpdate:g,setAttribute:x,trust:u,unmount:w,update:C,use:G,v:T};"undefined"!=typeof module?module.exports=E:self.Valyrian=E})(); \ No newline at end of file diff --git a/dist/index.min.js.map b/dist/index.min.js.map index ca19402..8adfa30 100644 --- a/dist/index.min.js.map +++ b/dist/index.min.js.map @@ -1 +1 @@ -//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL2xpYi9pbmRleC50cyJdLCJuYW1lcyI6WyJDb21wb25lbnRTdHJpbmciLCJUZXh0U3RyaW5nIiwiaXNOb2RlSnMiLCJCb29sZWFuIiwicHJvY2VzcyIsInZlcnNpb25zIiwibm9kZSIsIlZhbHlyaWFuU3ltYm9sIiwiU3ltYm9sIiwiVW5kIiwiVm5vZGUiLCJ0YWciLCJwcm9wcyIsImNoaWxkcmVuIiwidGhpcyIsImlzVm5vZGUiLCJvYmplY3QiLCJpc0NvbXBvbmVudCIsImNvbXBvbmVudCIsImlzVm5vZGVDb21wb25lbnQiLCJ2bm9kZSIsImNyZWF0ZURvbUVsZW1lbnQiLCJpc1NWRyIsImRvY3VtZW50IiwiY3JlYXRlRWxlbWVudE5TIiwiY3JlYXRlRWxlbWVudCIsImRvbVRvVm5vZGUiLCJkb20iLCJ2IiwidGFnTmFtZSIsInRvTG93ZXJDYXNlIiwiQXJyYXkiLCJmcm9tIiwiY2hpbGROb2RlcyIsImZpbHRlciIsImNoaWxkIiwibm9kZVR5cGUiLCJtYXAiLCJ0ZXh0Iiwibm9kZVZhbHVlIiwiU3RyaW5nIiwiZm9yRWFjaCIsImNhbGwiLCJhdHRyaWJ1dGVzIiwicHJvcCIsIm5vZGVOYW1lIiwidHJ1c3QiLCJodG1sU3RyaW5nIiwiZGl2IiwiaW5uZXJIVE1MIiwidHJpbSIsIml0ZW0iLCJyZXNlcnZlZFByb3BzIiwia2V5Iiwic3RhdGUiLCJvbmNyZWF0ZSIsIm9udXBkYXRlIiwib25yZW1vdmUiLCJzaG91bGR1cGRhdGUiLCJjdXJyZW50Iiwib25DbGVhbnVwIiwiY2FsbGJhY2siLCJhcHAiLCJpbmRleE9mIiwicHVzaCIsIm9uVW5tb3VudCIsIm9uTW91bnQiLCJvblVwZGF0ZSIsIm1vdW50IiwiY29udGFpbmVyIiwidm5vZGVDb21wb25lbnQiLCJhcHBDb250YWluZXIiLCJxdWVyeVNlbGVjdG9yQWxsIiwiRXJyb3IiLCJ1bm1vdW50IiwiZXZlbnRMaXN0ZW5lciIsImUiLCJ0YXJnZXQiLCJuYW1lIiwidHlwZSIsImRlZmF1bHRQcmV2ZW50ZWQiLCJ1cGRhdGUiLCJwYXJlbnROb2RlIiwiaXNNb3VudGVkIiwiZXZlbnRMaXN0ZW5lck5hbWVzIiwibWFpblZub2RlIiwiY2FsbENsZWFudXAiLCJ2YWx5cmlhbkFwcCIsImkiLCJsZW5ndGgiLCJvbGRWbm9kZSIsInBhdGNoIiwiY2FsbE1vdW50IiwiY2FsbFVwZGF0ZSIsImNhbGxVbm1vdW50IiwiUmVmbGVjdCIsImRlbGV0ZVByb3BlcnR5IiwiZW1wdHlWbm9kZSIsInNoYXJlZFNldEF0dHJpYnV0ZSIsInZhbHVlIiwiZGlyZWN0aXZlcyIsImFkZEV2ZW50TGlzdGVuZXIiLCJzbGljZSIsInJlbW92ZUF0dHJpYnV0ZSIsInNldEF0dHJpYnV0ZSIsInNldEF0dHJpYnV0ZXMiLCJuZXdWbm9kZSIsIm5ld1RyZWUiLCJvbGRUcmVlIiwiY2hpbGRWbm9kZSIsInJlc3VsdCIsInZpZXciLCJzcGxpY2UiLCJpc0FycmF5Iiwib2xkVHJlZUxlbmd0aCIsIm5ld1RyZWVMZW5ndGgiLCJvbGRLZXllZExpc3QiLCJyZWR1Y2UiLCJhY2MiLCJuZXdLZXllZExpc3QiLCJvbGRDaGlsZFZub2RlIiwic2hvdWxkUGF0Y2giLCJhcHBlbmRDaGlsZCIsInJlcGxhY2VDaGlsZCIsInJlbW92ZUNoaWxkIiwibmV3Q2hpbGRWbm9kZSIsImNyZWF0ZVRleHROb2RlIiwidGV4dENvbnRlbnQiLCJkaXJlY3RpdmUiLCJkaXJlY3RpdmUyIiwiZnVsbE5hbWUiLCJoaWRlRGlyZWN0aXZlIiwidGVzdCIsImJvb2wiLCJuZXdkb20iLCJzZXQiLCJzdHlsZSIsImRpc3BsYXkiLCJjbGFzc2VzIiwiY2xhc3NMaXN0IiwidG9nZ2xlIiwiaHRtbCIsIm1vZGVsIiwicHJvcGVydHkiLCJldmVudCIsImhhbmRsZXIiLCJ2YWwiLCJpZHgiLCJtdWx0aXBsZSIsImN0cmxLZXkiLCJ2YWx1ZTIiLCJqb2luIiwic2VsZWN0ZWQiLCJwbHVnaW5zIiwiTWFwIiwidXNlIiwicGx1Z2luIiwib3B0aW9ucyIsImhhcyIsImdldCIsInRhZ09yQ29t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QUVDLE9BQTRDc0IsT0FFNUZLLEVBQWF3QyxFQUFPQyxFQUFTN0gsRUFBT3NFLE1BTXBDK0QsRUFBVSxJQUFJQyxJQUViLFNBQUFDLEVBQWFDLEVBQWdCQyxHQUNsQyxHQUFJSixFQUFRSyxJQUFJRixHQUNkLE9BQU9ILEVBQVFNLElBQUlILEdBR3JCLElBQUk5QyxFQUFTOEMsRUFBT2hJLEVBQUdpSSxHQUV2QixPQURBSixFQUFRbEIsSUFBSXFCLEVBQVE5QyxHQUNiQSxFQUtGLElBQU1sRixFQUFjLFNBQVdvSSxFQUE0Q3BKLEtBQWlCQyxHQUNqRyxHQUE4QixpQkFBbkJtSixFQUNULE9BQU8sSUFBSXRKLEVBQU1zSixFQUFnQnBKLEdBQVMsR0FBSUMsR0FHaEQsTUFBTU8sRUFBUSxJQUFJVixFQUFNLGdCQUFpQkUsR0FBUyxHQUFJQyxHQUV0RCxPQURBTyxFQUFNRixVQUFZOEksRUFDWDVJLEdBR1RRLEVBQUVxSSxTQUFXLENBQUNySixLQUFpQkMsSUFDdEJBLEVBS1RlLEVBQUUrQixRQUFVQSxFQUVaL0IsRUFBRXdFLFdBQWFBLEVBRWZ4RSxFQUFFd0IsY0FBZ0JBLEVBRWxCeEIsRUFBRWIsUUFBVUEsRUFDWmEsRUFBRVgsWUFBY0EsRUFDaEJXLEVBQUVULGlCQUFtQkEsRUFFckJTLEVBQUUxQixTQUFXQSxFQUNiMEIsRUFBRWtCLE1BQVFBLEVBRVZsQixFQUFFZ0MsVUFBWUEsRUFDZGhDLEVBQUVxQyxVQUFZQSxFQUNkckMsRUFBRXNDLFFBQVVBLEVBQ1p0QyxFQUFFdUMsU0FBV0EsRUFFYnZDLEVBQUV3QyxNQUFRQSxFQUNWeEMsRUFBRThDLFFBQVVBLEVBQ1o5QyxFQUFFcUQsT0FBU0EsRUFFWHJELEVBQUU0RSxhQUFlQSxFQUNqQjVFLEVBQUVvRyxVQUFZQSxFQUNkcEcsRUFBRStILElBQU1BIiwic291cmNlc0NvbnRlbnQiOlsiLyoqKiBWbm9kZSAqKiovXG5cbmltcG9ydCB7XG4gIENoaWxkcmVuLFxuICBDdXJyZW50LFxuICBEaXJlY3RpdmUsXG4gIERpcmVjdGl2ZXMsXG4gIERvbUVsZW1lbnQsXG4gIElWbm9kZSxcbiAgTW91bnRlZFZhbHlyaWFuQXBwLFxuICBQbHVnaW4sXG4gIFByb3BzLFxuICBSZXNlcnZlZFByb3BzLFxuICBWYWx5cmlhbixcbiAgVmFseXJpYW5BcHAsXG4gIFZhbHlyaWFuQ29tcG9uZW50LFxuICBWbm9kZUNvbXBvbmVudCxcbiAgVm5vZGVXaXRoRG9tXG59IGZyb20gXCIuL2ludGVyZmFjZXNcIjtcblxuLyoqKiBDb25zdGFudHMgKioqL1xuY29uc3QgQ29tcG9uZW50U3RyaW5nID0gXCJfX2NvbXBvbmVudF9fXCI7XG5jb25zdCBUZXh0U3RyaW5nID0gXCIjdGV4dFwiO1xuZXhwb3J0IGNvbnN0IGlzTm9kZUpzID0gQm9vbGVhbih0eXBlb2YgcHJvY2VzcyAhPT0gXCJ1bmRlZmluZWRcIiAmJiBwcm9jZXNzLnZlcnNpb25zICYmIHByb2Nlc3MudmVyc2lvbnMubm9kZSk7XG5jb25zdCBWYWx5cmlhblN5bWJvbCA9IFN5bWJvbChcIlZhbHlyaWFuXCIpO1xuY29uc3QgVW5kID0gdW5kZWZpbmVkO1xuXG4vKioqIFZub2RlICoqKi9cblxuZXhwb3J0IGNvbnN0IFZub2RlID0gZnVuY3Rpb24gVm5vZGUodGhpczogSVZub2RlLCB0YWc6IHN0cmluZywgcHJvcHM6IFByb3BzLCBjaGlsZHJlbjogQ2hpbGRyZW4pIHtcbiAgdGhpcy5wcm9wcyA9IHByb3BzO1xuICB0aGlzLmNoaWxkcmVuID0gY2hpbGRyZW47XG4gIHRoaXMudGFnID0gdGFnO1xufSBhcyB1bmtub3duIGFzIElWbm9kZTtcblxuZXhwb3J0IGZ1bmN0aW9uIGlzVm5vZGUob2JqZWN0PzogdW5rbm93biB8IElWbm9kZSk6IG9iamVjdCBpcyBJVm5vZGUge1xuICByZXR1cm4gb2JqZWN0IGluc3RhbmNlb2YgVm5vZGU7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBpc0NvbXBvbmVudChjb21wb25lbnQ/OiB1bmtub3duIHwgVmFseXJpYW5Db21wb25lbnQpOiBjb21wb25lbnQgaXMgVmFseXJpYW5Db21wb25lbnQge1xuICByZXR1cm4gdHlwZW9mIGNvbXBvbmVudCA9PT0gXCJmdW5jdGlvblwiIHx8ICh0eXBlb2YgY29tcG9uZW50ID09PSBcIm9iamVjdFwiICYmIGNvbXBvbmVudCAhPT0gbnVsbCAmJiBcInZpZXdcIiBpbiBjb21wb25lbnQpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gaXNWbm9kZUNvbXBvbmVudCh2bm9kZT86IHVua25vd24gfCBWbm9kZUNvbXBvbmVudCk6IHZub2RlIGlzIFZub2RlQ29tcG9uZW50IHtcbiAgcmV0dXJuIHZub2RlIGluc3RhbmNlb2YgVm5vZGUgJiYgdm5vZGUudGFnID09PSBDb21wb25lbnRTdHJpbmc7XG59XG5cbi8qKiogVXRpbCAqKiovXG5cbmZ1bmN0aW9uIGNyZWF0ZURvbUVsZW1lbnQodGFnOiBzdHJpbmcsIGlzU1ZHOiBib29sZWFuID0gZmFsc2UpIHtcbiAgcmV0dXJuIGlzU1ZHID8gZG9jdW1lbnQuY3JlYXRlRWxlbWVudE5TKFwiaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmdcIiwgdGFnKSA6IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQodGFnKTtcbn1cblxuZnVuY3Rpb24gZG9tVG9Wbm9kZShkb206IERvbUVsZW1lbnQpOiBWbm9kZVdpdGhEb20ge1xuICBsZXQgdm5vZGUgPSB2KFxuICAgIGRvbS50YWdOYW1lLnRvTG93ZXJDYXNlKCksXG4gICAge30sXG4gICAgLi4uQXJyYXkuZnJvbShkb20uY2hpbGROb2RlcylcbiAgICAgIC5maWx0ZXIoKGNoaWxkKSA9PiAoY2hpbGQgYXMgRG9tRWxlbWVudCkubm9kZVR5cGUgPT09IDEgfHwgKGNoaWxkIGFzIERvbUVsZW1lbnQpLm5vZGVUeXBlID09PSAzKVxuICAgICAgLm1hcCgoY2hpbGQpID0+IHtcbiAgICAgICAgaWYgKChjaGlsZCBhcyBEb21FbGVtZW50KS5ub2RlVHlwZSA9PT0gMSkge1xuICAgICAgICAgIHJldHVybiBkb21Ub1Zub2RlKGNoaWxkIGFzIERvbUVsZW1lbnQpO1xuICAgICAgICB9XG5cbiAgICAgICAgbGV0IHRleHQgPSBuZXcgVm5vZGUoVGV4dFN0cmluZywge30sIFtdKTtcbiAgICAgICAgdGV4dC5ub2RlVmFsdWUgPSBTdHJpbmcoKGNoaWxkIGFzIERvbUVsZW1lbnQpLm5vZGVWYWx1ZSk7XG4gICAgICAgIHRleHQuZG9tID0gY2hpbGQgYXMgRG9tRWxlbWVudDtcbiAgICAgICAgcmV0dXJuIHRleHQ7XG4gICAgICB9KVxuICApO1xuICBbXS5mb3JFYWNoLmNhbGwoZG9tLmF0dHJpYnV0ZXMsIChwcm9wOiBBdHRyKSA9PiAodm5vZGUucHJvcHNbcHJvcC5ub2RlTmFtZV0gPSBwcm9wLm5vZGVWYWx1ZSkpO1xuICB2bm9kZS5kb20gPSBkb207XG4gIHJldHVybiB2bm9kZSBhcyBWbm9kZVdpdGhEb207XG59XG5cbmV4cG9ydCBjb25zdCB0cnVzdCA9IChodG1sU3RyaW5nOiBzdHJpbmcpOiBJVm5vZGVbXSA9PiB7XG4gIGxldCBkaXYgPSBjcmVhdGVEb21FbGVtZW50KFwiZGl2XCIpO1xuICBkaXYuaW5uZXJIVE1MID0gaHRtbFN0cmluZy50cmltKCk7XG5cbiAgcmV0dXJuIFtdLm1hcC5jYWxsKGRpdi5jaGlsZE5vZGVzLCAoaXRlbSkgPT4gZG9tVG9Wbm9kZShpdGVtKSkgYXMgSVZub2RlW107XG59O1xuXG5jb25zdCByZXNlcnZlZFByb3BzOiBSZXNlcnZlZFByb3BzID0ge1xuICBrZXk6IHRydWUsXG4gIHN0YXRlOiB0cnVlLFxuICBvbmNyZWF0ZTogdHJ1ZSxcbiAgb251cGRhdGU6IHRydWUsXG4gIG9ucmVtb3ZlOiB0cnVlLFxuICBzaG91bGR1cGRhdGU6IHRydWUsXG4gIFwidi1vbmNlXCI6IHRydWUsXG5cbiAgLy8gQnVpbHQgaW4gZGlyZWN0aXZlc1xuICBcInYtaWZcIjogdHJ1ZSxcbiAgXCJ2LXVubGVzc1wiOiB0cnVlLFxuICBcInYtZm9yXCI6IHRydWUsXG4gIFwidi1zaG93XCI6IHRydWUsXG4gIFwidi1jbGFzc1wiOiB0cnVlLFxuICBcInYtaHRtbFwiOiB0cnVlXG59O1xuXG4vKioqIE1vdW50ICoqKi9cblxuY29uc3QgY3VycmVudDogQ3VycmVudCA9IHt9O1xuXG5leHBvcnQgZnVuY3Rpb24gb25DbGVhbnVwKGNhbGxiYWNrOiBGdW5jdGlvbikge1xuICBpZiAoY3VycmVudC5hcHA/Lm9uQ2xlYW51cC5pbmRleE9mKGNhbGxiYWNrKSA9PT0gLTEpIHtcbiAgICBjdXJyZW50LmFwcD8ub25DbGVhbnVwLnB1c2goY2FsbGJhY2spO1xuICB9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBvblVubW91bnQoY2FsbGJhY2s6IEZ1bmN0aW9uKSB7XG4gIGlmIChjdXJyZW50LmFwcD8ub25Vbm1vdW50LmluZGV4T2YoY2FsbGJhY2spID09PSAtMSkge1xuICAgIGN1cnJlbnQuYXBwPy5vblVubW91bnQucHVzaChjYWxsYmFjayk7XG4gIH1cbn1cblxuZXhwb3J0IGZ1bmN0aW9uIG9uTW91bnQoY2FsbGJhY2s6IEZ1bmN0aW9uKSB7XG4gIGlmIChjdXJyZW50LmFwcD8ub25Nb3VudC5pbmRleE9mKGNhbGxiYWNrKSA9PT0gLTEpIHtcbiAgICBjdXJyZW50LmFwcD8ub25Nb3VudC5wdXNoKGNhbGxiYWNrKTtcbiAgfVxufVxuXG5leHBvcnQgZnVuY3Rpb24gb25VcGRhdGUoY2FsbGJhY2s6IEZ1bmN0aW9uKSB7XG4gIGlmIChjdXJyZW50LmFwcD8ub25VcGRhdGUuaW5kZXhPZihjYWxsYmFjaykgPT09IC0xKSB7XG4gICAgY3VycmVudC5hcHA/Lm9uVXBkYXRlLnB1c2goY2FsbGJhY2spO1xuICB9XG59XG5cbi8qXG4gICogTW91bnRzIGEgY29tcG9uZW50IHRvIHRoZSBET01cbiAgbW91bnQoJyNhcHAnLCAoKSA9PiA8ZGl2PkhlbGxvIHdvcmxkPC9kaXY+KTsgLy8gQXBwIGlzIGEgRnVuY3Rpb25hbCBDb21wb25lbnRcbiAgbW91bnQoJyNhcHAnLCB7IHZpZXc6ICgpID0+IDxkaXY+SGVsbG8gd29ybGQ8L2Rpdj4gfSk7IC8vIEFwcCBpcyBhIFBPSk8gY29tcG9uZW50IHdpdGggYSB2aWV3IG1ldGhvZFxuICBtb3VudCgnI2FwcCcsIGNsYXNzSW5zdGFuY2UpOyAvLyBBcHAgaXMgYSBjbGFzcyBpbnN0YW5jZSB3aXRoIGEgdmlldyBtZXRob2RcbiAgbW91bnQoJyNhcHAnLCA8QXBwPjxkaXY+SGVsbG8gd29ybGQ8L2Rpdj48L0FwcD4pOyAvLyBBcHAgaXMgYSBWbm9kZSBjb21wb25lbnQgKFZub2RlIHdpdGggdGFnIF9fY29tcG9uZW50X18pXG4qL1xuXG5leHBvcnQgZnVuY3Rpb24gbW91bnQoY29udGFpbmVyOiBEb21FbGVtZW50IHwgc3RyaW5nLCBjb21wb25lbnQ6IFZhbHlyaWFuQ29tcG9uZW50IHwgSVZub2RlKTogdm9pZCB8IHN0cmluZyB7XG4gIGxldCBhcHBDb250YWluZXIgPSBudWxsO1xuXG4gIGlmIChpc05vZGVKcykge1xuICAgIGFwcENvbnRhaW5lciA9IHR5cGVvZiBjb250YWluZXIgPT09IFwic3RyaW5nXCIgPyBjcmVhdGVEb21FbGVtZW50KGNvbnRhaW5lciA9PT0gXCJzdmdcIiA/IFwic3ZnXCIgOiBcImRpdlwiLCBjb250YWluZXIgPT09IFwic3ZnXCIpIDogY29udGFpbmVyO1xuICB9IGVsc2Uge1xuICAgIGFwcENvbnRhaW5lciA9IHR5cGVvZiBjb250YWluZXIgPT09IFwic3RyaW5nXCIgPyBkb2N1bWVudC5xdWVyeVNlbGVjdG9yQWxsKGNvbnRhaW5lcilbMF0gOiBjb250YWluZXI7XG4gIH1cblxuICBpZiAoIWFwcENvbnRhaW5lcikge1xuICAgIHRocm93IG5ldyBFcnJvcihcIkNvbnRhaW5lciBub3QgZm91bmRcIik7XG4gIH1cblxuICBsZXQgdm5vZGVDb21wb25lbnQ6IFZub2RlQ29tcG9uZW50IHwgSVZub2RlO1xuXG4gIGlmIChpc1Zub2RlQ29tcG9uZW50KGNvbXBvbmVudCkpIHtcbiAgICB2bm9kZUNvbXBvbmVudCA9IGNvbXBvbmVudDtcbiAgfSBlbHNlIGlmIChpc0NvbXBvbmVudChjb21wb25lbnQpKSB7XG4gICAgdm5vZGVDb21wb25lbnQgPSB2KGNvbXBvbmVudCwge30pO1xuICB9IGVsc2Uge1xuICAgIHRocm93IG5ldyBFcnJvcihcIkNvbXBvbmVudCBtdXN0IGJlIGEgVmFseXJpYW4gQ29tcG9uZW50IG9yIGEgVm5vZGUgY29tcG9uZW50XCIpO1xuICB9XG5cbiAgaWYgKGNvbXBvbmVudFtWYWx5cmlhblN5bWJvbF0pIHtcbiAgICB1bm1vdW50KGNvbXBvbmVudCk7XG4gIH0gZWxzZSB7XG4gICAgY29tcG9uZW50W1ZhbHlyaWFuU3ltYm9sXSA9IHtcbiAgICAgIGlzTW91bnRlZDogZmFsc2UsXG4gICAgICBldmVudExpc3RlbmVyTmFtZXM6IHt9LFxuICAgICAgb25DbGVhbnVwOiBbXSxcbiAgICAgIG9uTW91bnQ6IFtdLFxuICAgICAgb25VcGRhdGU6IFtdLFxuICAgICAgb25Vbm1vdW50OiBbXVxuICAgIH07XG4gICAgZnVuY3Rpb24gZXZlbnRMaXN0ZW5lcihlOiBFdmVudCkge1xuICAgICAgbGV0IGRvbSA9IGUudGFyZ2V0IGFzIERvbUVsZW1lbnQgJiBSZWNvcmQ8c3RyaW5nLCBhbnk+O1xuICAgICAgbGV0IG5hbWUgPSBgdi1vbiR7ZS50eXBlfWA7XG4gICAgICB3aGlsZSAoZG9tKSB7XG4gICAgICAgIGlmIChkb21bbmFtZV0pIHtcbiAgICAgICAgICBkb21bbmFtZV0oZSwgZG9tKTtcbiAgICAgICAgICBpZiAoIWUuZGVmYXVsdFByZXZlbnRlZCkge1xuICAgICAgICAgICAgdXBkYXRlKGNvbXBvbmVudCk7XG4gICAgICAgICAgfVxuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBkb20gPSBkb20ucGFyZW50Tm9kZSBhcyBEb21FbGVtZW50O1xuICAgICAgfVxuICAgIH1cbiAgICBjb21wb25lbnRbVmFseXJpYW5TeW1ib2xdLmV2ZW50TGlzdGVuZXIgPSBldmVudExpc3RlbmVyO1xuICB9XG5cbiAgY29tcG9uZW50W1ZhbHlyaWFuU3ltYm9sXS5jb21wb25lbnQgPSB2bm9kZUNvbXBvbmVudDtcbiAgY29tcG9uZW50W1ZhbHlyaWFuU3ltYm9sXS5jb250YWluZXIgPSBhcHBDb250YWluZXI7XG4gIGNvbXBvbmVudFtWYWx5cmlhblN5bWJvbF0ubWFpblZub2RlID0gZG9tVG9Wbm9kZShhcHBDb250YWluZXIpO1xuXG4gIC8vIHVwZGF0ZVxuICByZXR1cm4gdXBkYXRlKGNvbXBvbmVudCk7XG59XG5cbmZ1bmN0aW9uIGNhbGxDbGVhbnVwKHZhbHlyaWFuQXBwOiBWYWx5cmlhbkFwcCkge1xuICBmb3IgKGxldCBpID0gMDsgaSA8IHZhbHlyaWFuQXBwLm9uQ2xlYW51cC5sZW5ndGg7IGkrKykge1xuICAgIHZhbHlyaWFuQXBwLm9uQ2xlYW51cFtpXSgpO1xuICB9XG4gIHZhbHlyaWFuQXBwLm9uQ2xlYW51cCA9IFtdO1xufVxuXG5mdW5jdGlvbiBjYWxsVW5tb3VudCh2YWx5cmlhbkFwcDogVmFseXJpYW5BcHApIHtcbiAgZm9yIChsZXQgaSA9IDA7IGkgPCB2YWx5cmlhbkFwcC5vblVubW91bnQubGVuZ3RoOyBpKyspIHtcbiAgICB2YWx5cmlhbkFwcC5vblVubW91bnRbaV0oKTtcbiAgfVxuICB2YWx5cmlhbkFwcC5vblVubW91bnQgPSBbXTtcbn1cblxuZnVuY3Rpb24gY2FsbE1vdW50KHZhbHlyaWFuQXBwOiBWYWx5cmlhbkFwcCkge1xuICBmb3IgKGxldCBpID0gMDsgaSA8IHZhbHlyaWFuQXBwLm9uTW91bnQubGVuZ3RoOyBpKyspIHtcbiAgICB2YWx5cmlhbkFwcC5vbk1vdW50W2ldKCk7XG4gIH1cbiAgdmFseXJpYW5BcHAub25Nb3VudCA9IFtdO1xufVxuXG5mdW5jdGlvbiBjYWxsVXBkYXRlKHZhbHlyaWFuQXBwOiBWYWx5cmlhbkFwcCkge1xuICBmb3IgKGxldCBpID0gMDsgaSA8IHZhbHlyaWFuQXBwLm9uVXBkYXRlLmxlbmd0aDsgaSsrKSB7XG4gICAgdmFseXJpYW5BcHAub25VcGRhdGVbaV0oKTtcbiAgfVxuICB2YWx5cmlhbkFwcC5vblVwZGF0ZSA9IFtdO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gdXBkYXRlKGNvbXBvbmVudD86IFZhbHlyaWFuQ29tcG9uZW50IHwgSVZub2RlKTogdm9pZCB8IHN0cmluZyB7XG4gIGlmIChjb21wb25lbnQgJiYgY29tcG9uZW50W1ZhbHlyaWFuU3ltYm9sXSkge1xuICAgIGxldCB2YWx5cmlhbkFwcCA9IGNvbXBvbmVudFtWYWx5cmlhblN5bWJvbF07XG4gICAgY3VycmVudC5hcHAgPSB2YWx5cmlhbkFwcDtcbiAgICB2YWx5cmlhbkFwcC5vbkNsZWFudXAubGVuZ3RoICYmIGNhbGxDbGVhbnVwKHZhbHlyaWFuQXBwKTtcbiAgICBsZXQgb2xkVm5vZGU6IFZub2RlV2l0aERvbSB8IG51bGwgPSB2YWx5cmlhbkFwcC5tYWluVm5vZGUgYXMgVm5vZGVXaXRoRG9tO1xuICAgIHZhbHlyaWFuQXBwLm1haW5Wbm9kZSA9IG5ldyBWbm9kZSh2YWx5cmlhbkFwcC5tYWluVm5vZGUudGFnLCB2YWx5cmlhbkFwcC5tYWluVm5vZGUucHJvcHMsIFt2YWx5cmlhbkFwcC5jb21wb25lbnRdKSBhcyBWbm9kZVdpdGhEb207XG4gICAgdmFseXJpYW5BcHAubWFpblZub2RlLmRvbSA9IG9sZFZub2RlLmRvbTtcbiAgICBwYXRjaCh2YWx5cmlhbkFwcC5tYWluVm5vZGUsIG9sZFZub2RlLCB2YWx5cmlhbkFwcCk7XG4gICAgb2xkVm5vZGUgPSBudWxsO1xuICAgIGlmICh2YWx5cmlhbkFwcC5pc01vdW50ZWQgPT09IGZhbHNlKSB7XG4gICAgICB2YWx5cmlhbkFwcC5vbk1vdW50Lmxlbmd0aCAmJiBjYWxsTW91bnQodmFseXJpYW5BcHApO1xuICAgICAgdmFseXJpYW5BcHAuaXNNb3VudGVkID0gdHJ1ZTtcbiAgICB9IGVsc2Uge1xuICAgICAgdmFseXJpYW5BcHAub25VcGRhdGUubGVuZ3RoICYmIGNhbGxVcGRhdGUodmFseXJpYW5BcHApO1xuICAgIH1cblxuICAgIGlmIChpc05vZGVKcykge1xuICAgICAgcmV0dXJuIHZhbHlyaWFuQXBwLm1haW5Wbm9kZS5kb20uaW5uZXJIVE1MO1xuICAgIH1cbiAgfVxufVxuXG5leHBvcnQgZnVuY3Rpb24gdW5tb3VudChjb21wb25lbnQ/OiBWYWx5cmlhbkNvbXBvbmVudCB8IElWbm9kZSk6IHZvaWQgfCBzdHJpbmcge1xuICBpZiAoIWNvbXBvbmVudCB8fCAhY29tcG9uZW50W1ZhbHlyaWFuU3ltYm9sXSkge1xuICAgIHJldHVybjtcbiAgfVxuXG4gIGxldCB2YWx5cmlhbkFwcCA9IGNvbXBvbmVudFtWYWx5cmlhblN5bWJvbF0gYXMgTW91bnRlZFZhbHlyaWFuQXBwO1xuXG4gIGlmICh2YWx5cmlhbkFwcC5pc01vdW50ZWQpIHtcbiAgICB2YWx5cmlhbkFwcC5vbkNsZWFudXAubGVuZ3RoICYmIGNhbGxDbGVhbnVwKHZhbHlyaWFuQXBwKTtcbiAgICB2YWx5cmlhbkFwcC5vblVubW91bnQubGVuZ3RoICYmIGNhbGxVbm1vdW50KHZhbHlyaWFuQXBwKTtcbiAgICBsZXQgb2xkVm5vZGU6IFZub2RlV2l0aERvbSB8IG51bGwgPSB2YWx5cmlhbkFwcC5tYWluVm5vZGUgYXMgVm5vZGVXaXRoRG9tO1xuICAgIHZhbHlyaWFuQXBwLm1haW5Wbm9kZSA9IG5ldyBWbm9kZSh2YWx5cmlhbkFwcC5tYWluVm5vZGUudGFnLCB2YWx5cmlhbkFwcC5tYWluVm5vZGUucHJvcHMsIFtdKSBhcyBWbm9kZVdpdGhEb207XG4gICAgdmFseXJpYW5BcHAubWFpblZub2RlLmRvbSA9IG9sZFZub2RlLmRvbTtcbiAgICB2YWx5cmlhbkFwcC5tYWluVm5vZGUuaXNTVkcgPSBvbGRWbm9kZS5pc1NWRztcbiAgICBwYXRjaCh2YWx5cmlhbkFwcC5tYWluVm5vZGUsIG9sZFZub2RlLCB2YWx5cmlhbkFwcCk7XG4gICAgb2xkVm5vZGUgPSBudWxsO1xuXG4gICAgaWYgKGlzTm9kZUpzKSB7XG4gICAgICByZXR1cm4gdmFseXJpYW5BcHAubWFpblZub2RlLmRvbS5pbm5lckhUTUw7XG4gICAgfVxuXG4gICAgKHZhbHlyaWFuQXBwIGFzIGFueSkgPSBudWxsO1xuICAgIFJlZmxlY3QuZGVsZXRlUHJvcGVydHkoY29tcG9uZW50LCBWYWx5cmlhblN5bWJvbCk7XG4gIH1cbn1cblxubGV0IGVtcHR5Vm5vZGUgPSBuZXcgVm5vZGUoXCJfX2VtcHR5X19cIiwge30sIFtdKTtcblxuZnVuY3Rpb24gb25yZW1vdmUodm5vZGU6IElWbm9kZSkge1xuICBmb3IgKGxldCBpID0gMDsgaSA8IHZub2RlLmNoaWxkcmVuLmxlbmd0aDsgaSsrKSB7XG4gICAgdm5vZGUuY2hpbGRyZW5baV0udGFnICE9PSBUZXh0U3RyaW5nICYmIG9ucmVtb3ZlKHZub2RlLmNoaWxkcmVuW2ldKTtcbiAgfVxuXG4gIHZub2RlLnByb3BzLm9ucmVtb3ZlICYmIHZub2RlLnByb3BzLm9ucmVtb3ZlKHZub2RlKTtcbn1cblxuZnVuY3Rpb24gc2hhcmVkU2V0QXR0cmlidXRlKHByb3A6IHN0cmluZywgdmFsdWU6IGFueSwgdm5vZGU6IFZub2RlV2l0aERvbSwgb2xkVm5vZGU/OiBWbm9kZVdpdGhEb20pOiB2b2lkIHwgYm9vbGVhbiB7XG4gIC8vIEl0IGlzIGEgcmVzZXJ2ZWQgcHJvcFxuICBpZiAocmVzZXJ2ZWRQcm9wc1twcm9wXSkge1xuICAgIC8vIElmIGl0IGlzIGEgZGlyZWN0aXZlIG5hbWUgY2FsbCB0aGUgZGlyZWN0aXZlXG4gICAgaWYgKGRpcmVjdGl2ZXNbcHJvcF0pIHtcbiAgICAgIHJldHVybiBkaXJlY3RpdmVzW3Byb3BdKHZub2RlLnByb3BzW3Byb3BdLCB2bm9kZSwgb2xkVm5vZGUpO1xuICAgIH1cblxuICAgIHJldHVybjtcbiAgfVxuXG4gIC8vIEl0IGlzIG5vdCBhIHJlc2VydmVkIHByb3Agc28gd2UgYWRkIGl0IHRvIHRoZSBkb21cbiAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gXCJmdW5jdGlvblwiKSB7XG4gICAgbGV0IHZhbHlyaWFuQXBwID0gY3VycmVudC5hcHAgYXMgTW91bnRlZFZhbHlyaWFuQXBwO1xuICAgIGlmIChwcm9wIGluIHZhbHlyaWFuQXBwLmV2ZW50TGlzdGVuZXJOYW1lcyA9PT0gZmFsc2UpIHtcbiAgICAgIHZhbHlyaWFuQXBwLmV2ZW50TGlzdGVuZXJOYW1lc1twcm9wXSA9IHRydWU7XG4gICAgICB2YWx5cmlhbkFwcC5jb250YWluZXIuYWRkRXZlbnRMaXN0ZW5lcihwcm9wLnNsaWNlKDIpLCB2YWx5cmlhbkFwcC5ldmVudExpc3RlbmVyKTtcbiAgICB9XG4gICAgdm5vZGUuZG9tW2B2LSR7cHJvcH1gXSA9IHZhbHVlO1xuICAgIHJldHVybjtcbiAgfVxuXG4gIGlmIChwcm9wIGluIHZub2RlLmRvbSAmJiB2bm9kZS5pc1NWRyA9PT0gZmFsc2UpIHtcbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgZXFlcWVxXG4gICAgaWYgKHZub2RlLmRvbVtwcm9wXSAhPSB2YWx1ZSkge1xuICAgICAgdm5vZGUuZG9tW3Byb3BdID0gdmFsdWU7XG4gICAgfVxuICAgIHJldHVybjtcbiAgfVxuXG4gIC8vIFVzZSBzZXQgYXR0cmlidXRlXG4gIGlmICghb2xkVm5vZGUgfHwgb2xkVm5vZGUucHJvcHNbcHJvcF0gIT09IHZhbHVlKSB7XG4gICAgaWYgKHZhbHVlID09PSBmYWxzZSkge1xuICAgICAgdm5vZGUuZG9tLnJlbW92ZUF0dHJpYnV0ZShwcm9wKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdm5vZGUuZG9tLnNldEF0dHJpYnV0ZShwcm9wLCB2YWx1ZSk7XG4gICAgfVxuICB9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBzZXRBdHRyaWJ1dGUobmFtZTogc3RyaW5nLCB2YWx1ZTogYW55LCB2bm9kZTogVm5vZGVXaXRoRG9tLCBvbGRWbm9kZT86IFZub2RlV2l0aERvbSkge1xuICB2bm9kZS5wcm9wc1tuYW1lXSA9IHZhbHVlO1xuXG4gIHNoYXJlZFNldEF0dHJpYnV0ZShuYW1lLCB2YWx1ZSwgdm5vZGUsIG9sZFZub2RlKTtcbn1cblxuZnVuY3Rpb24gc2V0QXR0cmlidXRlcyh2bm9kZTogVm5vZGVXaXRoRG9tLCBvbGRWbm9kZT86IFZub2RlV2l0aERvbSkge1xuICBmb3IgKGxldCBwcm9wIGluIHZub2RlLnByb3BzKSB7XG4gICAgaWYgKHNoYXJlZFNldEF0dHJpYnV0ZShwcm9wLCB2bm9kZS5wcm9wc1twcm9wXSwgdm5vZGUsIG9sZFZub2RlKSA9PT0gZmFsc2UpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gIH1cblxuICBpZiAob2xkVm5vZGUpIHtcbiAgICBmb3IgKGxldCBwcm9wIGluIG9sZFZub2RlLnByb3BzKSB7XG4gICAgICBpZiAocHJvcCBpbiB2bm9kZS5wcm9wcyA9PT0gZmFsc2UgJiYgdHlwZW9mIG9sZFZub2RlLnByb3BzW3Byb3BdICE9PSBcImZ1bmN0aW9uXCIgJiYgcHJvcCBpbiByZXNlcnZlZFByb3BzID09PSBmYWxzZSkge1xuICAgICAgICBpZiAocHJvcCBpbiBvbGRWbm9kZS5kb20gJiYgdm5vZGUuaXNTVkcgPT09IGZhbHNlKSB7XG4gICAgICAgICAgb2xkVm5vZGUuZG9tW3Byb3BdID0gbnVsbDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBvbGRWbm9kZS5kb20ucmVtb3ZlQXR0cmlidXRlKHByb3ApO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICB9XG59XG5cbi8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBjb21wbGV4aXR5XG5mdW5jdGlvbiBwYXRjaChuZXdWbm9kZTogVm5vZGVXaXRoRG9tLCBvbGRWbm9kZTogVm5vZGVXaXRoRG9tIHwgSVZub2RlID0gZW1wdHlWbm9kZSwgdmFseXJpYW5BcHA6IE1vdW50ZWRWYWx5cmlhbkFwcCkge1xuICBjdXJyZW50LnZub2RlID0gbmV3Vm5vZGU7XG4gIGN1cnJlbnQub2xkVm5vZGUgPSBvbGRWbm9kZSA9PT0gZW1wdHlWbm9kZSA/IFVuZCA6IChvbGRWbm9kZSBhcyBWbm9kZVdpdGhEb20pO1xuICBsZXQgbmV3VHJlZSA9IG5ld1Zub2RlLmNoaWxkcmVuO1xuICBsZXQgb2xkVHJlZSA9IG9sZFZub2RlLmNoaWxkcmVuO1xuXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgbmV3VHJlZS5sZW5ndGg7IGkrKykge1xuICAgIGxldCBjaGlsZFZub2RlID0gbmV3VHJlZVtpXTtcbiAgICBpZiAoY2hpbGRWbm9kZSBpbnN0YW5jZW9mIFZub2RlKSB7XG4gICAgICBpZiAoY2hpbGRWbm9kZS50YWcgIT09IFRleHRTdHJpbmcpIHtcbiAgICAgICAgaWYgKGNoaWxkVm5vZGUudGFnID09PSBDb21wb25lbnRTdHJpbmcpIHtcbiAgICAgICAgICBsZXQgY29tcG9uZW50ID0gY2hpbGRWbm9kZS5jb21wb25lbnQgYXMgVmFseXJpYW5Db21wb25lbnQ7XG4gICAgICAgICAgY3VycmVudC5jb21wb25lbnQgPSBjb21wb25lbnQ7XG4gICAgICAgICAgbGV0IHJlc3VsdCA9IChcInZpZXdcIiBpbiBjb21wb25lbnQgPyBjb21wb25lbnQudmlldyA6IGNvbXBvbmVudCkuY2FsbChjb21wb25lbnQsIGNoaWxkVm5vZGUucHJvcHMsIC4uLmNoaWxkVm5vZGUuY2hpbGRyZW4pO1xuXG4gICAgICAgICAgbmV3VHJlZS5zcGxpY2UoaS0tLCAxLCByZXN1bHQpO1xuICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICB9XG4gICAgICAgIGNoaWxkVm5vZGUuaXNTVkcgPSBuZXdWbm9kZS5pc1NWRyB8fCBjaGlsZFZub2RlLnRhZyA9PT0gXCJzdmdcIjtcbiAgICAgIH1cbiAgICB9IGVsc2UgaWYgKEFycmF5LmlzQXJyYXkoY2hpbGRWbm9kZSkpIHtcbiAgICAgIG5ld1RyZWUuc3BsaWNlKGktLSwgMSwgLi4uY2hpbGRWbm9kZSk7XG4gICAgfSBlbHNlIGlmIChjaGlsZFZub2RlID09PSBudWxsIHx8IGNoaWxkVm5vZGUgPT09IFVuZCkge1xuICAgICAgbmV3VHJlZS5zcGxpY2UoaS0tLCAxKTtcbiAgICB9IGVsc2Uge1xuICAgICAgbmV3VHJlZVtpXSA9IG5ldyBWbm9kZShUZXh0U3RyaW5nLCB7fSwgW10pO1xuICAgICAgbmV3VHJlZVtpXS5ub2RlVmFsdWUgPSBjaGlsZFZub2RlO1xuICAgIH1cbiAgfVxuXG4gIGxldCBvbGRUcmVlTGVuZ3RoID0gb2xkVHJlZS5sZW5ndGg7XG4gIGxldCBuZXdUcmVlTGVuZ3RoID0gbmV3VHJlZS5sZW5ndGg7XG5cbiAgLy8gSWYgbmV3IHRyZWUgaXMgZW1wdHksIHJlbW92ZSBhbGwgb2xkIG5vZGVzXG4gIGlmIChuZXdUcmVlTGVuZ3RoID09PSAwKSB7XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBvbGRUcmVlTGVuZ3RoOyBpKyspIHtcbiAgICAgIG9ucmVtb3ZlKG9sZFRyZWVbaV0pO1xuICAgIH1cblxuICAgIG5ld1Zub2RlLmRvbS50ZXh0Q29udGVudCA9IFwiXCI7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgLy8gSWYgdGhlIHRyZWUgaXMga2V5ZWQgbGlzdCBhbmQgaXMgbm90IGZpcnN0IHJlbmRlciBhbmQgb2xkIHRyZWUgaXMga2V5ZWQgbGlzdCB0b29cbiAgaWYgKG9sZFRyZWVMZW5ndGggJiYgXCJrZXlcIiBpbiBuZXdUcmVlWzBdLnByb3BzICYmIFwia2V5XCIgaW4gb2xkVHJlZVswXS5wcm9wcykge1xuICAgIGxldCBvbGRLZXllZExpc3QgPSBvbGRUcmVlLnJlZHVjZSgoYWNjLCB2bm9kZSwgaSkgPT4ge1xuICAgICAgYWNjW3Zub2RlLnByb3BzLmtleV0gPSBpO1xuICAgICAgcmV0dXJuIGFjYztcbiAgICB9LCB7fSBhcyB7IFtrZXk6IHN0cmluZ106IG51bWJlciB9KTtcbiAgICBsZXQgbmV3S2V5ZWRMaXN0ID0gbmV3VHJlZS5yZWR1Y2UoKGFjYywgdm5vZGUsIGkpID0+IHtcbiAgICAgIGFjY1t2bm9kZS5wcm9wcy5rZXldID0gaTtcbiAgICAgIHJldHVybiBhY2M7XG4gICAgfSwge30gYXMgeyBba2V5OiBzdHJpbmddOiBudW1iZXIgfSk7XG5cbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IG5ld1RyZWVMZW5ndGg7IGkrKykge1xuICAgICAgbGV0IGNoaWxkVm5vZGUgPSBuZXdUcmVlW2ldO1xuICAgICAgbGV0IG9sZENoaWxkVm5vZGUgPSBvbGRUcmVlW29sZEtleWVkTGlzdFtjaGlsZFZub2RlLnByb3BzLmtleV1dO1xuICAgICAgbGV0IHNob3VsZFBhdGNoID0gdHJ1ZTtcblxuICAgICAgaWYgKG9sZENoaWxkVm5vZGUpIHtcbiAgICAgICAgY2hpbGRWbm9kZS5kb20gPSBvbGRDaGlsZFZub2RlLmRvbTtcbiAgICAgICAgaWYgKFwidi1vbmNlXCIgaW4gY2hpbGRWbm9kZS5wcm9wcyB8fCAoY2hpbGRWbm9kZS5wcm9wcy5zaG91bGR1cGRhdGUgJiYgY2hpbGRWbm9kZS5wcm9wcy5zaG91bGR1cGRhdGUoY2hpbGRWbm9kZSwgb2xkQ2hpbGRWbm9kZSkgPT09IGZhbHNlKSkge1xuICAgICAgICAgIC8vIHNraXAgdGhpcyBwYXRjaFxuICAgICAgICAgIGNoaWxkVm5vZGUuY2hpbGRyZW4gPSBvbGRDaGlsZFZub2RlLmNoaWxkcmVuO1xuICAgICAgICAgIHNob3VsZFBhdGNoID0gZmFsc2U7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgc2V0QXR0cmlidXRlcyhjaGlsZFZub2RlLCBvbGRDaGlsZFZub2RlKTtcbiAgICAgICAgICBpZiAodmFseXJpYW5BcHAuaXNNb3VudGVkKSB7XG4gICAgICAgICAgICBjaGlsZFZub2RlLnByb3BzLm9udXBkYXRlICYmIGNoaWxkVm5vZGUucHJvcHMub251cGRhdGUoY2hpbGRWbm9kZSwgb2xkQ2hpbGRWbm9kZSk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGNoaWxkVm5vZGUucHJvcHMub25jcmVhdGUgJiYgY2hpbGRWbm9kZS5wcm9wcy5vbmNyZWF0ZShjaGlsZFZub2RlKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGNoaWxkVm5vZGUuZG9tID0gY3JlYXRlRG9tRWxlbWVudChjaGlsZFZub2RlLnRhZywgY2hpbGRWbm9kZS5pc1NWRyk7XG4gICAgICAgIHNldEF0dHJpYnV0ZXMoY2hpbGRWbm9kZSk7XG4gICAgICAgIGNoaWxkVm5vZGUucHJvcHMub25jcmVhdGUgJiYgY2hpbGRWbm9kZS5wcm9wcy5vbmNyZWF0ZShjaGlsZFZub2RlKTtcbiAgICAgIH1cblxuICAgICAgaWYgKG5ld1Zub2RlLmRvbS5jaGlsZE5vZGVzW2ldID09PSBVbmQpIHtcbiAgICAgICAgbmV3Vm5vZGUuZG9tLmFwcGVuZENoaWxkKGNoaWxkVm5vZGUuZG9tKTtcbiAgICAgIH0gZWxzZSBpZiAobmV3Vm5vZGUuZG9tLmNoaWxkTm9kZXNbaV0gIT09IGNoaWxkVm5vZGUuZG9tKSB7XG4gICAgICAgIG9sZFRyZWVbaV0gJiYgbmV3S2V5ZWRMaXN0W29sZFRyZWVbaV0ucHJvcHMua2V5XSA9PT0gVW5kICYmIG9ucmVtb3ZlKG9sZFRyZWVbaV0pO1xuICAgICAgICBuZXdWbm9kZS5kb20ucmVwbGFjZUNoaWxkKGNoaWxkVm5vZGUuZG9tLCBuZXdWbm9kZS5kb20uY2hpbGROb2Rlc1tpXSk7XG4gICAgICB9XG5cbiAgICAgIHNob3VsZFBhdGNoICYmIHBhdGNoKGNoaWxkVm5vZGUsIG9sZENoaWxkVm5vZGUsIHZhbHlyaWFuQXBwKTtcbiAgICB9XG5cbiAgICAvLyBGb3IgdGhlIHJlc3Qgb2YgdGhlIGNoaWxkcmVuLCB3ZSBzaG91bGQgcmVtb3ZlIHRoZW1cbiAgICBmb3IgKGxldCBpID0gbmV3VHJlZUxlbmd0aDsgaSA8IG9sZFRyZWVMZW5ndGg7IGkrKykge1xuICAgICAgaWYgKG5ld0tleWVkTGlzdFtvbGRUcmVlW2ldLnByb3BzLmtleV0gPT09IFVuZCkge1xuICAgICAgICBsZXQgb2xkQ2hpbGRWbm9kZSA9IG9sZFRyZWVbaV07XG4gICAgICAgIG9ucmVtb3ZlKG9sZENoaWxkVm5vZGUpO1xuICAgICAgICBvbGRDaGlsZFZub2RlLmRvbS5wYXJlbnROb2RlICYmIG9sZENoaWxkVm5vZGUuZG9tLnBhcmVudE5vZGUucmVtb3ZlQ2hpbGQob2xkQ2hpbGRWbm9kZS5kb20pO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybjtcbiAgfVxuXG4gIC8vIElmIG5ldyB0cmVlIGFuZCBvbGQgdHJlZSBoYXZlIG1vcmUgdGhhbiBvbmUgY2hpbGQsIHdlIHNob3VsZCB1cGRhdGUgdGhlIGRvbVxuICBmb3IgKGxldCBpID0gMDsgaSA8IG5ld1RyZWVMZW5ndGg7IGkrKykge1xuICAgIGxldCBuZXdDaGlsZFZub2RlID0gbmV3VHJlZVtpXTtcblxuICAgIC8vIE9sZCBjaGlsZCBleGlzdHNcbiAgICBpZiAoaSA8IG9sZFRyZWVMZW5ndGgpIHtcbiAgICAgIGxldCBvbGRDaGlsZFZub2RlID0gb2xkVHJlZVtpXTtcbiAgICAgIC8vIE5ldyBjaGlsZCBpcyBhIHRleHQgbm9kZVxuICAgICAgaWYgKG5ld0NoaWxkVm5vZGUudGFnID09PSBUZXh0U3RyaW5nKSB7XG4gICAgICAgIC8vIE9sZCBjaGlsZCBpcyBhIHRleHQgbm9kZVxuICAgICAgICBpZiAob2xkQ2hpbGRWbm9kZS50YWcgPT09IFRleHRTdHJpbmcpIHtcbiAgICAgICAgICBuZXdDaGlsZFZub2RlLmRvbSA9IG9sZENoaWxkVm5vZGUuZG9tO1xuICAgICAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBlcWVxZXFcbiAgICAgICAgICBpZiAobmV3Q2hpbGRWbm9kZS5kb20ubm9kZVZhbHVlICE9IG5ld0NoaWxkVm5vZGUubm9kZVZhbHVlKSB7XG4gICAgICAgICAgICBuZXdDaGlsZFZub2RlLmRvbS5ub2RlVmFsdWUgPSBuZXdDaGlsZFZub2RlLm5vZGVWYWx1ZSBhcyBzdHJpbmc7XG4gICAgICAgICAgfVxuICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gT2xkIGNoaWxkIGlzIGEgbm9ybWFsIG5vZGVcbiAgICAgICAgbmV3Q2hpbGRWbm9kZS5kb20gPSBkb2N1bWVudC5jcmVhdGVUZXh0Tm9kZShuZXdDaGlsZFZub2RlLm5vZGVWYWx1ZSBhcyBzdHJpbmcpIGFzIHVua25vd24gYXMgRG9tRWxlbWVudDtcbiAgICAgICAgb25yZW1vdmUob2xkQ2hpbGRWbm9kZSk7XG4gICAgICAgIG5ld1Zub2RlLmRvbS5yZXBsYWNlQ2hpbGQobmV3Q2hpbGRWbm9kZS5kb20sIG9sZENoaWxkVm5vZGUuZG9tKTtcblxuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cblxuICAgICAgLy8gTmV3IGNoaWxkIGlzIGEgbm9ybWFsIG5vZGVcbiAgICAgIC8vIE9sZCBjaGlsZCBpcyB0aGUgc2FtZSB0eXBlIGFzIG5ldyBjaGlsZFxuICAgICAgaWYgKG9sZENoaWxkVm5vZGUudGFnID09PSBuZXdDaGlsZFZub2RlLnRhZykge1xuICAgICAgICBuZXdDaGlsZFZub2RlLmRvbSA9IG9sZENoaWxkVm5vZGUuZG9tO1xuICAgICAgICAvLyBJZiB3ZSBoYXZlIGEgdi1vbmNlIGRpcmVjdGl2ZSBvciBhIHNob3VsZHVwZGF0ZSBtZXRob2QgdGhhdCByZXR1cm5zIGZhbHNlLCB3ZSBza2lwIHRoZSB1cGRhdGVcbiAgICAgICAgaWYgKG5ld0NoaWxkVm5vZGUucHJvcHNbXCJ2LW9uY2VcIl0gfHwgKG5ld0NoaWxkVm5vZGUucHJvcHMuc2hvdWxkdXBkYXRlICYmIG5ld0NoaWxkVm5vZGUucHJvcHMuc2hvdWxkdXBkYXRlKG5ld0NoaWxkVm5vZGUsIG9sZENoaWxkVm5vZGUpID09PSBmYWxzZSkpIHtcbiAgICAgICAgICBuZXdDaGlsZFZub2RlLmNoaWxkcmVuID0gb2xkQ2hpbGRWbm9kZS5jaGlsZHJlbjtcbiAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFdlIHVwZGF0ZSB0aGUgZG9tIGVsZW1lbnRcbiAgICAgICAgc2V0QXR0cmlidXRlcyhuZXdDaGlsZFZub2RlLCBvbGRDaGlsZFZub2RlKTtcbiAgICAgICAgaWYgKHZhbHlyaWFuQXBwLmlzTW91bnRlZCkge1xuICAgICAgICAgIG5ld0NoaWxkVm5vZGUucHJvcHMub251cGRhdGUgJiYgbmV3Q2hpbGRWbm9kZS5wcm9wcy5vbnVwZGF0ZShuZXdDaGlsZFZub2RlLCBvbGRDaGlsZFZub2RlKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBuZXdDaGlsZFZub2RlLnByb3BzLm9uY3JlYXRlICYmIG5ld0NoaWxkVm5vZGUucHJvcHMub25jcmVhdGUobmV3Q2hpbGRWbm9kZSk7XG4gICAgICAgIH1cblxuICAgICAgICBwYXRjaChuZXdDaGlsZFZub2RlLCBvbGRDaGlsZFZub2RlLCB2YWx5cmlhbkFwcCk7XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuXG4gICAgICAvLyBPbGQgY2hpbGQgaXMgb2YgYSBkaWZmZXJlbnQgdHlwZSB0aGFuIG5ldyBjaGlsZFxuICAgICAgbmV3Q2hpbGRWbm9kZS5kb20gPSBjcmVhdGVEb21FbGVtZW50KG5ld0NoaWxkVm5vZGUudGFnLCBuZXdDaGlsZFZub2RlLmlzU1ZHKTtcbiAgICAgIHNldEF0dHJpYnV0ZXMobmV3Q2hpbGRWbm9kZSk7XG4gICAgICBvbGRDaGlsZFZub2RlLnRhZyAhPT0gVGV4dFN0cmluZyAmJiBvbnJlbW92ZShvbGRDaGlsZFZub2RlKTtcbiAgICAgIG5ld0NoaWxkVm5vZGUucHJvcHMub25jcmVhdGUgJiYgbmV3Q2hpbGRWbm9kZS5wcm9wcy5vbmNyZWF0ZShuZXdDaGlsZFZub2RlKTtcbiAgICAgIG5ld1Zub2RlLmRvbS5yZXBsYWNlQ2hpbGQobmV3Q2hpbGRWbm9kZS5kb20sIG9sZENoaWxkVm5vZGUuZG9tKTtcbiAgICAgIHBhdGNoKG5ld0NoaWxkVm5vZGUsIGVtcHR5Vm5vZGUsIHZhbHlyaWFuQXBwKTtcbiAgICAgIGNvbnRpbnVlO1xuICAgIH1cblxuICAgIC8vIE9sZCBjaGlsZCBkb2VzIG5vdCBleGlzdHNcbiAgICAvLyBOZXcgY2hpbGQgaXMgYSB0ZXh0IG5vZGVcbiAgICBpZiAobmV3Q2hpbGRWbm9kZS50YWcgPT09IFRleHRTdHJpbmcpIHtcbiAgICAgIG5ld0NoaWxkVm5vZGUuZG9tID0gZG9jdW1lbnQuY3JlYXRlVGV4dE5vZGUobmV3Q2hpbGRWbm9kZS5ub2RlVmFsdWUgYXMgc3RyaW5nKSBhcyB1bmtub3duIGFzIERvbUVsZW1lbnQ7XG4gICAgICBuZXdWbm9kZS5kb20uYXBwZW5kQ2hpbGQobmV3Q2hpbGRWbm9kZS5kb20pO1xuICAgICAgY29udGludWU7XG4gICAgfVxuXG4gICAgLy8gTmV3IGNoaWxkIGlzIGEgbm9ybWFsIG5vZGVcbiAgICBuZXdDaGlsZFZub2RlLmRvbSA9IGNyZWF0ZURvbUVsZW1lbnQobmV3Q2hpbGRWbm9kZS50YWcsIG5ld0NoaWxkVm5vZGUuaXNTVkcpO1xuICAgIHNldEF0dHJpYnV0ZXMobmV3Q2hpbGRWbm9kZSk7XG4gICAgbmV3Vm5vZGUuZG9tLmFwcGVuZENoaWxkKG5ld0NoaWxkVm5vZGUuZG9tKTtcbiAgICBuZXdDaGlsZFZub2RlLnByb3BzLm9uY3JlYXRlICYmIG5ld0NoaWxkVm5vZGUucHJvcHMub25jcmVhdGUobmV3Q2hpbGRWbm9kZSk7XG4gICAgcGF0Y2gobmV3Q2hpbGRWbm9kZSwgZW1wdHlWbm9kZSwgdmFseXJpYW5BcHApO1xuICB9XG5cbiAgLy8gRm9yIHRoZSByZXN0IG9mIHRoZSBjaGlsZHJlbiwgd2Ugc2hvdWxkIHJlbW92ZSB0aGVtXG4gIGZvciAobGV0IGkgPSBuZXdUcmVlTGVuZ3RoOyBpIDwgb2xkVHJlZUxlbmd0aDsgaSsrKSB7XG4gICAgbGV0IG9sZENoaWxkVm5vZGUgPSBvbGRUcmVlW2ldO1xuICAgIG9sZENoaWxkVm5vZGUudGFnICE9PSBUZXh0U3RyaW5nICYmIG9ucmVtb3ZlKG9sZENoaWxkVm5vZGUpO1xuICAgIG9sZENoaWxkVm5vZGUuZG9tLnBhcmVudE5vZGUgJiYgb2xkQ2hpbGRWbm9kZS5kb20ucGFyZW50Tm9kZS5yZW1vdmVDaGlsZChvbGRDaGlsZFZub2RlLmRvbSk7XG4gIH1cbn1cblxuLyoqKiBEaXJlY3RpdmVzICoqKi9cblxuZXhwb3J0IGZ1bmN0aW9uIGRpcmVjdGl2ZShuYW1lOiBzdHJpbmcsIGRpcmVjdGl2ZTogRGlyZWN0aXZlKSB7XG4gIGxldCBmdWxsTmFtZSA9IGB2LSR7bmFtZX1gO1xuICBkaXJlY3RpdmVzW2Z1bGxOYW1lXSA9IGRpcmVjdGl2ZTtcbiAgcmVzZXJ2ZWRQcm9wc1tmdWxsTmFtZV0gPSB0cnVlO1xufVxuXG5mdW5jdGlvbiBoaWRlRGlyZWN0aXZlKHRlc3Q6IGJvb2xlYW4pOiBEaXJlY3RpdmUge1xuICByZXR1cm4gKGJvb2w6IGJvb2xlYW4sIHZub2RlOiBJVm5vZGUsIG9sZFZub2RlPzogSVZub2RlKSA9PiB7XG4gICAgbGV0IHZhbHVlID0gdGVzdCA/IGJvb2wgOiAhYm9vbDtcbiAgICBpZiAodmFsdWUpIHtcbiAgICAgIGxldCBuZXdkb20gPSBkb2N1bWVudC5jcmVhdGVUZXh0Tm9kZShcIlwiKTtcbiAgICAgIGlmIChvbGRWbm9kZSAmJiBvbGRWbm9kZS5kb20gJiYgb2xkVm5vZGUuZG9tLnBhcmVudE5vZGUpIHtcbiAgICAgICAgb2xkVm5vZGUudGFnICE9PSBUZXh0U3RyaW5nICYmIG9ucmVtb3ZlKG9sZFZub2RlKTtcbiAgICAgICAgb2xkVm5vZGUuZG9tLnBhcmVudE5vZGUucmVwbGFjZUNoaWxkKG5ld2RvbSwgb2xkVm5vZGUuZG9tKTtcbiAgICAgIH1cbiAgICAgIHZub2RlLnRhZyA9IFRleHRTdHJpbmc7XG4gICAgICB2bm9kZS5jaGlsZHJlbiA9IFtdO1xuICAgICAgdm5vZGUucHJvcHMgPSB7fTtcbiAgICAgIHZub2RlLmRvbSA9IG5ld2RvbSBhcyB1bmtub3duIGFzIERvbUVsZW1lbnQ7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICB9O1xufVxuXG5jb25zdCBkaXJlY3RpdmVzOiBEaXJlY3RpdmVzID0ge1xuICBcInYtaWZcIjogaGlkZURpcmVjdGl2ZShmYWxzZSksXG4gIFwidi11bmxlc3NcIjogaGlkZURpcmVjdGl2ZSh0cnVlKSxcbiAgXCJ2LWZvclwiOiAoc2V0OiB1bmtub3duW10sIHZub2RlOiBWbm9kZVdpdGhEb20pID0+IHtcbiAgICB2bm9kZS5jaGlsZHJlbiA9IHNldC5tYXAodm5vZGUuY2hpbGRyZW5bMF0gYXMgKHZhbHVlOiB1bmtub3duKSA9PiBGdW5jdGlvbik7XG4gIH0sXG4gIFwidi1zaG93XCI6IChib29sOiBib29sZWFuLCB2bm9kZTogVm5vZGVXaXRoRG9tKSA9PiB7XG4gICAgKHZub2RlLmRvbSBhcyB1bmtub3duIGFzIHsgc3R5bGU6IHsgZGlzcGxheTogc3RyaW5nIH0gfSkuc3R5bGUuZGlzcGxheSA9IGJvb2wgPyBcIlwiIDogXCJub25lXCI7XG4gIH0sXG4gIFwidi1jbGFzc1wiOiAoY2xhc3NlczogeyBbeDogc3RyaW5nXTogYm9vbGVhbiB9LCB2bm9kZTogVm5vZGVXaXRoRG9tKSA9PiB7XG4gICAgZm9yIChsZXQgbmFtZSBpbiBjbGFzc2VzKSB7XG4gICAgICAodm5vZGUuZG9tIGFzIERvbUVsZW1lbnQpLmNsYXNzTGlzdC50b2dnbGUobmFtZSwgY2xhc3Nlc1tuYW1lXSk7XG4gICAgfVxuICB9LFxuICBcInYtaHRtbFwiOiAoaHRtbDogc3RyaW5nLCB2bm9kZTogVm5vZGVXaXRoRG9tKSA9PiB7XG4gICAgdm5vZGUuY2hpbGRyZW4gPSBbdHJ1c3QoaHRtbCldO1xuICB9LFxuICBcInYtbW9kZWxcIjogKFttb2RlbCwgcHJvcGVydHksIGV2ZW50XTogYW55W10sIHZub2RlOiBWbm9kZVdpdGhEb20sIG9sZFZub2RlPzogVm5vZGVXaXRoRG9tKSA9PiB7XG4gICAgbGV0IHZhbHVlO1xuICAgIGxldCBoYW5kbGVyO1xuICAgIGlmICh2bm9kZS5uYW1lID09PSBcImlucHV0XCIpIHtcbiAgICAgIGV2ZW50ID0gZXZlbnQgfHwgXCJvbmlucHV0XCI7XG4gICAgICBzd2l0Y2ggKHZub2RlLnByb3BzLnR5cGUpIHtcbiAgICAgICAgY2FzZSBcImNoZWNrYm94XCI6IHtcbiAgICAgICAgICBpZiAoQXJyYXkuaXNBcnJheShtb2RlbFtwcm9wZXJ0eV0pKSB7XG4gICAgICAgICAgICBoYW5kbGVyID0gKGU6IEV2ZW50KSA9PiB7XG4gICAgICAgICAgICAgIGxldCB2YWwgPSAoZS50YXJnZXQgYXMgRG9tRWxlbWVudCAmIFJlY29yZDxzdHJpbmcsIGFueT4pLnZhbHVlO1xuICAgICAgICAgICAgICBsZXQgaWR4ID0gbW9kZWxbcHJvcGVydHldLmluZGV4T2YodmFsKTtcbiAgICAgICAgICAgICAgaWYgKGlkeCA9PT0gLTEpIHtcbiAgICAgICAgICAgICAgICBtb2RlbFtwcm9wZXJ0eV0ucHVzaCh2YWwpO1xuICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIG1vZGVsW3Byb3BlcnR5XS5zcGxpY2UoaWR4LCAxKTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIHZhbHVlID0gbW9kZWxbcHJvcGVydHldLmluZGV4T2Yodm5vZGUuZG9tLnZhbHVlKSAhPT0gLTE7XG4gICAgICAgICAgfSBlbHNlIGlmIChcInZhbHVlXCIgaW4gdm5vZGUucHJvcHMpIHtcbiAgICAgICAgICAgIGhhbmRsZXIgPSAoKSA9PiB7XG4gICAgICAgICAgICAgIGlmIChtb2RlbFtwcm9wZXJ0eV0gPT09IHZub2RlLnByb3BzLnZhbHVlKSB7XG4gICAgICAgICAgICAgICAgbW9kZWxbcHJvcGVydHldID0gbnVsbDtcbiAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBtb2RlbFtwcm9wZXJ0eV0gPSB2bm9kZS5wcm9wcy52YWx1ZTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIHZhbHVlID0gbW9kZWxbcHJvcGVydHldID09PSB2bm9kZS5wcm9wcy52YWx1ZTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgaGFuZGxlciA9ICgpID0+IChtb2RlbFtwcm9wZXJ0eV0gPSAhbW9kZWxbcHJvcGVydHldKTtcbiAgICAgICAgICAgIHZhbHVlID0gbW9kZWxbcHJvcGVydHldO1xuICAgICAgICAgIH1cbiAgICAgICAgICBzZXRBdHRyaWJ1dGUoXCJjaGVja2VkXCIsIHZhbHVlLCB2bm9kZSwgb2xkVm5vZGUpO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgICAgIGNhc2UgXCJyYWRpb1wiOiB7XG4gICAgICAgICAgc2V0QXR0cmlidXRlKFwiY2hlY2tlZFwiLCBtb2RlbFtwcm9wZXJ0eV0gPT09IHZub2RlLmRvbS52YWx1ZSwgdm5vZGUsIG9sZFZub2RlKTtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgICAgICBkZWZhdWx0OiB7XG4gICAgICAgICAgc2V0QXR0cmlidXRlKFwidmFsdWVcIiwgbW9kZWxbcHJvcGVydHldLCB2bm9kZSwgb2xkVm5vZGUpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSBlbHNlIGlmICh2bm9kZS5uYW1lID09PSBcInNlbGVjdFwiKSB7XG4gICAgICBldmVudCA9IGV2ZW50IHx8IFwib25jbGlja1wiO1xuICAgICAgaWYgKHZub2RlLnByb3BzLm11bHRpcGxlKSB7XG4gICAgICAgIGhhbmRsZXIgPSAoZTogRXZlbnQgJiBSZWNvcmQ8c3RyaW5nLCBhbnk+KSA9PiB7XG4gICAgICAgICAgbGV0IHZhbCA9IChlLnRhcmdldCBhcyBEb21FbGVtZW50ICYgUmVjb3JkPHN0cmluZywgYW55PikudmFsdWU7XG4gICAgICAgICAgaWYgKGUuY3RybEtleSkge1xuICAgICAgICAgICAgbGV0IGlkeCA9IG1vZGVsW3Byb3BlcnR5XS5pbmRleE9mKHZhbCk7XG4gICAgICAgICAgICBpZiAoaWR4ID09PSAtMSkge1xuICAgICAgICAgICAgICBtb2RlbFtwcm9wZXJ0eV0ucHVzaCh2YWwpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgbW9kZWxbcHJvcGVydHldLnNwbGljZShpZHgsIDEpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBtb2RlbFtwcm9wZXJ0eV0uc3BsaWNlKDAsIG1vZGVsW3Byb3BlcnR5XS5sZW5ndGgpO1xuICAgICAgICAgICAgbW9kZWxbcHJvcGVydHldLnB1c2godmFsKTtcbiAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIHZub2RlLmNoaWxkcmVuLmZvckVhY2goKGNoaWxkOiBJVm5vZGUpID0+IHtcbiAgICAgICAgICBpZiAoY2hpbGQudGFnID09PSBcIm9wdGlvblwiKSB7XG4gICAgICAgICAgICBsZXQgdmFsdWUgPSBcInZhbHVlXCIgaW4gY2hpbGQucHJvcHMgPyBjaGlsZC5wcm9wcy52YWx1ZSA6IGNoaWxkLmNoaWxkcmVuLmpvaW4oXCJcIikudHJpbSgpO1xuICAgICAgICAgICAgY2hpbGQucHJvcHMuc2VsZWN0ZWQgPSBtb2RlbFtwcm9wZXJ0eV0uaW5kZXhPZih2YWx1ZSkgIT09IC0xO1xuICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB2bm9kZS5jaGlsZHJlbi5mb3JFYWNoKChjaGlsZDogSVZub2RlKSA9PiB7XG4gICAgICAgICAgaWYgKGNoaWxkLnRhZyA9PT0gXCJvcHRpb25cIikge1xuICAgICAgICAgICAgbGV0IHZhbHVlID0gXCJ2YWx1ZVwiIGluIGNoaWxkLnByb3BzID8gY2hpbGQucHJvcHMudmFsdWUgOiBjaGlsZC5jaGlsZHJlbi5qb2luKFwiXCIpLnRyaW0oKTtcbiAgICAgICAgICAgIGNoaWxkLnByb3BzLnNlbGVjdGVkID0gdmFsdWUgPT09IG1vZGVsW3Byb3BlcnR5XTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgIH0gZWxzZSBpZiAodm5vZGUubmFtZSA9PT0gXCJ0ZXh0YXJlYVwiKSB7XG4gICAgICBldmVudCA9IGV2ZW50IHx8IFwib25pbnB1dFwiO1xuICAgICAgdm5vZGUuY2hpbGRyZW4gPSBbbW9kZWxbcHJvcGVydHldXTtcbiAgICB9XG5cbiAgICBpZiAoIXZub2RlLnByb3BzW2V2ZW50XSkge1xuICAgICAgaWYgKCFoYW5kbGVyKSB7XG4gICAgICAgIGhhbmRsZXIgPSAoZTogRXZlbnQpID0+IChtb2RlbFtwcm9wZXJ0eV0gPSAoZS50YXJnZXQgYXMgRG9tRWxlbWVudCAmIFJlY29yZDxzdHJpbmcsIGFueT4pLnZhbHVlKTtcbiAgICAgIH1cbiAgICAgIHNldEF0dHJpYnV0ZShldmVudCwgaGFuZGxlciwgdm5vZGUsIG9sZFZub2RlKTtcbiAgICB9XG4gIH1cbn07XG5cbi8qKiogUGx1Z2lucyAqKiovXG5jb25zdCBwbHVnaW5zID0gbmV3IE1hcDxQbHVnaW4sIGFueT4oKTtcblxuZXhwb3J0IGZ1bmN0aW9uIHVzZShwbHVnaW46IFBsdWdpbiwgb3B0aW9ucz86IFJlY29yZDxzdHJpbmcgfCBudW1iZXIgfCBzeW1ib2wsIGFueT4pOiB2b2lkIHwgYW55IHtcbiAgaWYgKHBsdWdpbnMuaGFzKHBsdWdpbikpIHtcbiAgICByZXR1cm4gcGx1Z2lucy5nZXQocGx1Z2luKTtcbiAgfVxuXG4gIGxldCByZXN1bHQgPSBwbHVnaW4odiwgb3B0aW9ucyk7XG4gIHBsdWdpbnMuc2V0KHBsdWdpbiwgcmVzdWx0KTtcbiAgcmV0dXJuIHJlc3VsdDtcbn1cblxuLyoqKiBIeXBlcnNjcmlwdCAqKiovXG5cbmV4cG9ydCBjb25zdCB2OiBWYWx5cmlhbiA9IGZ1bmN0aW9uIHYodGFnT3JDb21wb25lbnQ6IHN0cmluZyB8IFZhbHlyaWFuQ29tcG9uZW50LCBwcm9wczogUHJvcHMsIC4uLmNoaWxkcmVuOiBDaGlsZHJlbik6IElWbm9kZSB8IFZub2RlQ29tcG9uZW50IHtcbiAgaWYgKHR5cGVvZiB0YWdPckNvbXBvbmVudCA9PT0gXCJzdHJpbmdcIikge1xuICAgIHJldHVybiBuZXcgVm5vZGUodGFnT3JDb21wb25lbnQsIHByb3BzIHx8IHt9LCBjaGlsZHJlbik7XG4gIH1cblxuICBjb25zdCB2bm9kZSA9IG5ldyBWbm9kZShcIl9fY29tcG9uZW50X19cIiwgcHJvcHMgfHwge30sIGNoaWxkcmVuKTtcbiAgdm5vZGUuY29tcG9uZW50ID0gdGFnT3JDb21wb25lbnQ7XG4gIHJldHVybiB2bm9kZSBhcyBWbm9kZUNvbXBvbmVudDtcbn07XG5cbnYuZnJhZ21lbnQgPSAocHJvcHM6IFByb3BzLCAuLi5jaGlsZHJlbjogQ2hpbGRyZW4pOiBDaGlsZHJlbiA9PiB7XG4gIHJldHVybiBjaGlsZHJlbjtcbn07XG5cbi8qKiogViBwcm9wZXJ0aWVzIGFuZCBtZXRob2RzICoqKi9cbi8vIFRoaXMgaXMgaW50ZW5kZWQgdG8gbWFrZSB0aGUgcHJvcGVydGllcyBhbmQgbWV0aG9kcyBhdmFpbGFibGUgZm9yIHBsdWdpbnNcbnYuY3VycmVudCA9IGN1cnJlbnQ7XG5cbnYuZGlyZWN0aXZlcyA9IGRpcmVjdGl2ZXM7XG5cbnYucmVzZXJ2ZWRQcm9wcyA9IHJlc2VydmVkUHJvcHM7XG5cbnYuaXNWbm9kZSA9IGlzVm5vZGU7XG52LmlzQ29tcG9uZW50ID0gaXNDb21wb25lbnQ7XG52LmlzVm5vZGVDb21wb25lbnQgPSBpc1Zub2RlQ29tcG9uZW50O1xuXG52LmlzTm9kZUpzID0gaXNOb2RlSnM7XG52LnRydXN0ID0gdHJ1c3Q7XG5cbnYub25DbGVhbnVwID0gb25DbGVhbnVwO1xudi5vblVubW91bnQgPSBvblVubW91bnQ7XG52Lm9uTW91bnQgPSBvbk1vdW50O1xudi5vblVwZGF0ZSA9IG9uVXBkYXRlO1xuXG52Lm1vdW50ID0gbW91bnQ7XG52LnVubW91bnQgPSB1bm1vdW50O1xudi51cGRhdGUgPSB1cGRhdGU7XG5cbnYuc2V0QXR0cmlidXRlID0gc2V0QXR0cmlidXRlO1xudi5kaXJlY3RpdmUgPSBkaXJlY3RpdmU7XG52LnVzZSA9IHVzZTtcbiJdfQ== \ No newline at end of file +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL2xpYi9pbmRleC50cyJdLCJuYW1lcyI6WyJDb21wb25lbnRTdHJpbmciLCJUZXh0U3RyaW5nIiwiaXNOb2RlSnMiLCJCb29sZWFuIiwicHJvY2VzcyIsInZlcnNpb25zIiwibm9kZSIsIlZhbHlyaWFuU3ltYm9sIiwiU3ltYm9sIiwiVW5kIiwiVm5vZGUiLCJ0YWciLCJwcm9wcyIsImNoaWxkcmVuIiwidGhpcyIsImlzVm5vZGUiLCJvYmplY3QiLCJpc0NvbXBvbmVudCIsImNvbXBvbmVudCIsImlzVm5vZGVDb21wb25lbnQiLCJ2bm9kZSIsImNyZWF0ZURvbUVsZW1lbnQiLCJpc1NWRyIsImRvY3VtZW50IiwiY3JlYXRlRWxlbWVudE5TIiwiY3JlYXRlRWxlbWVudCIsImRvbVRvVm5vZGUiLCJkb20iLCJ2IiwidGFnTmFtZSIsInRvTG93ZXJDYXNlIiwiQXJyYXkiLCJmcm9tIiwiY2hpbGROb2RlcyIsImZpbHRlciIsImNoaWxkIiwibm9kZVR5cGUiLCJtYXAiLCJ0ZXh0Iiwibm9kZVZhbHVlIiwiU3RyaW5nIiwiZm9yRWFjaCIsImNhbGwiLCJhdHRyaWJ1dGVzIiwicHJvcCIsIm5vZGVOYW1lIiwidHJ1c3QiLCJodG1sU3RyaW5nIiwiZGl2IiwiaW5uZXJIVE1MIiwidHJpbSIsIml0ZW0iLCJyZXNlcnZlZFByb3BzIiwia2V5Iiwic3RhdGUiLCJvbmNyZWF0ZSIsIm9udXBkYXRlIiwib25yZW1vdmUiLCJzaG91bGR1cGRhdGUiLCJjdXJyZW50Iiwib25DbGVhbnVwIiwiY2FsbGJhY2siLCJhcHAiLCJpbmRleE9mIiwicHVzaCIsIm9uVW5tb3VudCIsIm9uTW91bnQiLCJvblVwZGF0ZSIsIm1vdW50IiwiY29udGFpbmVyIiwidm5vZGVDb21wb25lbnQiLCJhcHBDb250YWluZXIiLCJxdWVyeVNlbGVjdG9yQWxsIiwiRXJyb3IiLCJ1bm1vdW50IiwiZXZlbnRMaXN0ZW5lciIsImUiLCJ0YXJnZXQiLCJuYW1lIiwidHlwZSIsImRlZmF1bHRQcmV2ZW50ZWQiLCJ1cGRhdGUiLCJwYXJlbnROb2RlIiwiaXNNb3VudGVkIiwiZXZlbnRMaXN0ZW5lck5hbWVzIiwibWFpblZub2RlIiwiY2FsbENsZWFudXAiLCJ2YWx5cmlhbkFwcCIsImkiLCJsZW5ndGgiLCJvbGRWbm9kZSIsInBhdGNoIiwiY2FsbE1vdW50IiwiY2FsbFVwZGF0ZSIsImNhbGxVbm1vdW50IiwiUmVmbGVjdCIsImRlbGV0ZVByb3BlcnR5IiwiZW1wdHlWbm9kZSIsInNoYXJlZFNldEF0dHJpYnV0ZSIsInZhbHVlIiwiZGlyZWN0aXZlcyIsImFkZEV2ZW50TGlzdGVuZXIiLCJzbGljZSIsInJlbW92ZUF0dHJpYnV0ZSIsInNldEF0dHJpYnV0ZSIsInNldEF0dHJpYnV0ZXMiLCJuZXdWbm9kZSIsIm5ld1RyZWUiLCJvbGRUcmVlIiwiY2hpbGRWbm9kZSIsInJlc3VsdCIsInZpZXciLCJzcGxpY2UiLCJpc0FycmF5Iiwib2xkVHJlZUxlbmd0aCIsIm5ld1RyZWVMZW5ndGgiLCJvbGRLZXllZExpc3QiLCJuZXdLZXllZExpc3QiLCJvbGRDaGlsZFZub2RlIiwic2hvdWxkUGF0Y2giLCJhcHBlbmRDaGlsZCIsInJlcGxhY2VDaGlsZCIsInJlbW92ZUNoaWxkIiwibmV3Q2hpbGRWbm9kZSIsImNyZWF0ZVRleHROb2RlIiwidGV4dENvbnRlbnQiLCJkaXJlY3RpdmUiLCJkaXJlY3RpdmUyIiwiZnVsbE5hbWUiLCJoaWRlRGlyZWN0aXZlIiwidGVzdCIsImJvb2wiLCJuZXdkb20iLCJzZXQiLCJzdHlsZSIsImRpc3BsYXkiLCJjbGFzc2VzIiwiY2xhc3NMaXN0IiwidG9nZ2xlIiwiaHRtbCIsIm1vZGVsIiwicHJvcGVydHkiLCJldmVudCIsImhhbmRsZXIiLCJ2YWwiLCJpZHgiLCJtdWx0aXBsZSIsImN0cmxLZXkiLCJ2YWx1ZTIiLCJqb2luIiwic2VsZWN0ZWQiLCJwbHVnaW5zIiwiTWFwIiwidXNlIiwicGx1Z2luIiwib3B0aW9ucyIsImhhcyIsImdldCIsInRhZ09yQ29tcG9uZW50IiwiZnJhZ21l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LEVBQVduRSxHQUFjZ0UsRUFBTUMsR0FBYWpFLEVBQUVDLE9BQTRDc0IsT0FFNUZLLEVBQWFzQyxFQUFPQyxFQUFTM0gsRUFBT3NFLE1BTXBDNkQsRUFBVSxJQUFJQyxJQUViLFNBQUFDLEVBQWFDLEVBQWdCQyxHQUNsQyxHQUFJSixFQUFRSyxJQUFJRixHQUNkLE9BQU9ILEVBQVFNLElBQUlILEdBR3JCLElBQUk1QyxFQUFTNEMsRUFBTzlILEVBQUcrSCxHQUV2QixPQURBSixFQUFRbEIsSUFBSXFCLEVBQVE1QyxHQUNiQSxFQUtGLElBQU1sRixFQUFjLFNBQVdrSSxFQUE0Q2xKLEtBQWlCQyxHQUNqRyxHQUE4QixpQkFBbkJpSixFQUNULE9BQU8sSUFBSXBKLEVBQU1vSixFQUFnQmxKLEdBQVMsR0FBSUMsR0FHaEQsTUFBTU8sRUFBUSxJQUFJVixFQUFNLGdCQUFpQkUsR0FBUyxHQUFJQyxHQUV0RCxPQURBTyxFQUFNRixVQUFZNEksRUFDWDFJLEdBR1RRLEVBQUVtSSxTQUFXLENBQUNuSixLQUFpQkMsSUFDdEJBLEVBS1RlLEVBQUUrQixRQUFVQSxFQUVaL0IsRUFBRXdFLFdBQWFBLEVBRWZ4RSxFQUFFd0IsY0FBZ0JBLEVBRWxCeEIsRUFBRWIsUUFBVUEsRUFDWmEsRUFBRVgsWUFBY0EsRUFDaEJXLEVBQUVULGlCQUFtQkEsRUFFckJTLEVBQUUxQixTQUFXQSxFQUNiMEIsRUFBRWtCLE1BQVFBLEVBRVZsQixFQUFFZ0MsVUFBWUEsRUFDZGhDLEVBQUVxQyxVQUFZQSxFQUNkckMsRUFBRXNDLFFBQVVBLEVBQ1p0QyxFQUFFdUMsU0FBV0EsRUFFYnZDLEVBQUV3QyxNQUFRQSxFQUNWeEMsRUFBRThDLFFBQVVBLEVBQ1o5QyxFQUFFcUQsT0FBU0EsRUFFWHJELEVBQUU0RSxhQUFlQSxFQUNqQjVFLEVBQUVrRyxVQUFZQSxFQUNkbEcsRUFBRTZILElBQU1BIiwic291cmNlc0NvbnRlbnQiOlsiLyoqKiBWbm9kZSAqKiovXG5cbmltcG9ydCB7XG4gIENoaWxkcmVuLFxuICBDdXJyZW50LFxuICBEaXJlY3RpdmUsXG4gIERpcmVjdGl2ZXMsXG4gIERvbUVsZW1lbnQsXG4gIElWbm9kZSxcbiAgTW91bnRlZFZhbHlyaWFuQXBwLFxuICBQbHVnaW4sXG4gIFByb3BzLFxuICBSZXNlcnZlZFByb3BzLFxuICBWYWx5cmlhbixcbiAgVmFseXJpYW5BcHAsXG4gIFZhbHlyaWFuQ29tcG9uZW50LFxuICBWbm9kZUNvbXBvbmVudCxcbiAgVm5vZGVXaXRoRG9tXG59IGZyb20gXCIuL2ludGVyZmFjZXNcIjtcblxuLyoqKiBDb25zdGFudHMgKioqL1xuY29uc3QgQ29tcG9uZW50U3RyaW5nID0gXCJfX2NvbXBvbmVudF9fXCI7XG5jb25zdCBUZXh0U3RyaW5nID0gXCIjdGV4dFwiO1xuZXhwb3J0IGNvbnN0IGlzTm9kZUpzID0gQm9vbGVhbih0eXBlb2YgcHJvY2VzcyAhPT0gXCJ1bmRlZmluZWRcIiAmJiBwcm9jZXNzLnZlcnNpb25zICYmIHByb2Nlc3MudmVyc2lvbnMubm9kZSk7XG5jb25zdCBWYWx5cmlhblN5bWJvbCA9IFN5bWJvbChcIlZhbHlyaWFuXCIpO1xuY29uc3QgVW5kID0gdW5kZWZpbmVkO1xuXG4vKioqIFZub2RlICoqKi9cblxuZXhwb3J0IGNvbnN0IFZub2RlID0gZnVuY3Rpb24gVm5vZGUodGhpczogSVZub2RlLCB0YWc6IHN0cmluZywgcHJvcHM6IFByb3BzLCBjaGlsZHJlbjogQ2hpbGRyZW4pIHtcbiAgdGhpcy5wcm9wcyA9IHByb3BzO1xuICB0aGlzLmNoaWxkcmVuID0gY2hpbGRyZW47XG4gIHRoaXMudGFnID0gdGFnO1xufSBhcyB1bmtub3duIGFzIElWbm9kZTtcblxuZXhwb3J0IGZ1bmN0aW9uIGlzVm5vZGUob2JqZWN0PzogdW5rbm93biB8IElWbm9kZSk6IG9iamVjdCBpcyBJVm5vZGUge1xuICByZXR1cm4gb2JqZWN0IGluc3RhbmNlb2YgVm5vZGU7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBpc0NvbXBvbmVudChjb21wb25lbnQ/OiB1bmtub3duIHwgVmFseXJpYW5Db21wb25lbnQpOiBjb21wb25lbnQgaXMgVmFseXJpYW5Db21wb25lbnQge1xuICByZXR1cm4gdHlwZW9mIGNvbXBvbmVudCA9PT0gXCJmdW5jdGlvblwiIHx8ICh0eXBlb2YgY29tcG9uZW50ID09PSBcIm9iamVjdFwiICYmIGNvbXBvbmVudCAhPT0gbnVsbCAmJiBcInZpZXdcIiBpbiBjb21wb25lbnQpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gaXNWbm9kZUNvbXBvbmVudCh2bm9kZT86IHVua25vd24gfCBWbm9kZUNvbXBvbmVudCk6IHZub2RlIGlzIFZub2RlQ29tcG9uZW50IHtcbiAgcmV0dXJuIHZub2RlIGluc3RhbmNlb2YgVm5vZGUgJiYgdm5vZGUudGFnID09PSBDb21wb25lbnRTdHJpbmc7XG59XG5cbi8qKiogVXRpbCAqKiovXG5cbmZ1bmN0aW9uIGNyZWF0ZURvbUVsZW1lbnQodGFnOiBzdHJpbmcsIGlzU1ZHOiBib29sZWFuID0gZmFsc2UpIHtcbiAgcmV0dXJuIGlzU1ZHID8gZG9jdW1lbnQuY3JlYXRlRWxlbWVudE5TKFwiaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmdcIiwgdGFnKSA6IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQodGFnKTtcbn1cblxuZnVuY3Rpb24gZG9tVG9Wbm9kZShkb206IERvbUVsZW1lbnQpOiBWbm9kZVdpdGhEb20ge1xuICBsZXQgdm5vZGUgPSB2KFxuICAgIGRvbS50YWdOYW1lLnRvTG93ZXJDYXNlKCksXG4gICAge30sXG4gICAgLi4uQXJyYXkuZnJvbShkb20uY2hpbGROb2RlcylcbiAgICAgIC5maWx0ZXIoKGNoaWxkKSA9PiAoY2hpbGQgYXMgRG9tRWxlbWVudCkubm9kZVR5cGUgPT09IDEgfHwgKGNoaWxkIGFzIERvbUVsZW1lbnQpLm5vZGVUeXBlID09PSAzKVxuICAgICAgLm1hcCgoY2hpbGQpID0+IHtcbiAgICAgICAgaWYgKChjaGlsZCBhcyBEb21FbGVtZW50KS5ub2RlVHlwZSA9PT0gMSkge1xuICAgICAgICAgIHJldHVybiBkb21Ub1Zub2RlKGNoaWxkIGFzIERvbUVsZW1lbnQpO1xuICAgICAgICB9XG5cbiAgICAgICAgbGV0IHRleHQgPSBuZXcgVm5vZGUoVGV4dFN0cmluZywge30sIFtdKTtcbiAgICAgICAgdGV4dC5ub2RlVmFsdWUgPSBTdHJpbmcoKGNoaWxkIGFzIERvbUVsZW1lbnQpLm5vZGVWYWx1ZSk7XG4gICAgICAgIHRleHQuZG9tID0gY2hpbGQgYXMgRG9tRWxlbWVudDtcbiAgICAgICAgcmV0dXJuIHRleHQ7XG4gICAgICB9KVxuICApO1xuICBbXS5mb3JFYWNoLmNhbGwoZG9tLmF0dHJpYnV0ZXMsIChwcm9wOiBBdHRyKSA9PiAodm5vZGUucHJvcHNbcHJvcC5ub2RlTmFtZV0gPSBwcm9wLm5vZGVWYWx1ZSkpO1xuICB2bm9kZS5kb20gPSBkb207XG4gIHJldHVybiB2bm9kZSBhcyBWbm9kZVdpdGhEb207XG59XG5cbmV4cG9ydCBjb25zdCB0cnVzdCA9IChodG1sU3RyaW5nOiBzdHJpbmcpOiBDaGlsZHJlbiA9PiB7XG4gIGxldCBkaXYgPSBjcmVhdGVEb21FbGVtZW50KFwiZGl2XCIpO1xuICBkaXYuaW5uZXJIVE1MID0gaHRtbFN0cmluZy50cmltKCk7XG5cbiAgcmV0dXJuIFtdLm1hcC5jYWxsKGRpdi5jaGlsZE5vZGVzLCAoaXRlbSkgPT4gZG9tVG9Wbm9kZShpdGVtKSkgYXMgQ2hpbGRyZW47XG59O1xuXG5jb25zdCByZXNlcnZlZFByb3BzOiBSZXNlcnZlZFByb3BzID0ge1xuICBrZXk6IHRydWUsXG4gIHN0YXRlOiB0cnVlLFxuICBvbmNyZWF0ZTogdHJ1ZSxcbiAgb251cGRhdGU6IHRydWUsXG4gIG9ucmVtb3ZlOiB0cnVlLFxuICBzaG91bGR1cGRhdGU6IHRydWUsXG4gIFwidi1vbmNlXCI6IHRydWUsXG5cbiAgLy8gQnVpbHQgaW4gZGlyZWN0aXZlc1xuICBcInYtaWZcIjogdHJ1ZSxcbiAgXCJ2LXVubGVzc1wiOiB0cnVlLFxuICBcInYtZm9yXCI6IHRydWUsXG4gIFwidi1zaG93XCI6IHRydWUsXG4gIFwidi1jbGFzc1wiOiB0cnVlLFxuICBcInYtaHRtbFwiOiB0cnVlXG59O1xuXG4vKioqIE1vdW50ICoqKi9cblxuY29uc3QgY3VycmVudDogQ3VycmVudCA9IHt9O1xuXG5leHBvcnQgZnVuY3Rpb24gb25DbGVhbnVwKGNhbGxiYWNrOiBGdW5jdGlvbikge1xuICBpZiAoY3VycmVudC5hcHA/Lm9uQ2xlYW51cC5pbmRleE9mKGNhbGxiYWNrKSA9PT0gLTEpIHtcbiAgICBjdXJyZW50LmFwcD8ub25DbGVhbnVwLnB1c2goY2FsbGJhY2spO1xuICB9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBvblVubW91bnQoY2FsbGJhY2s6IEZ1bmN0aW9uKSB7XG4gIGlmIChjdXJyZW50LmFwcD8ub25Vbm1vdW50LmluZGV4T2YoY2FsbGJhY2spID09PSAtMSkge1xuICAgIGN1cnJlbnQuYXBwPy5vblVubW91bnQucHVzaChjYWxsYmFjayk7XG4gIH1cbn1cblxuZXhwb3J0IGZ1bmN0aW9uIG9uTW91bnQoY2FsbGJhY2s6IEZ1bmN0aW9uKSB7XG4gIGlmIChjdXJyZW50LmFwcD8ub25Nb3VudC5pbmRleE9mKGNhbGxiYWNrKSA9PT0gLTEpIHtcbiAgICBjdXJyZW50LmFwcD8ub25Nb3VudC5wdXNoKGNhbGxiYWNrKTtcbiAgfVxufVxuXG5leHBvcnQgZnVuY3Rpb24gb25VcGRhdGUoY2FsbGJhY2s6IEZ1bmN0aW9uKSB7XG4gIGlmIChjdXJyZW50LmFwcD8ub25VcGRhdGUuaW5kZXhPZihjYWxsYmFjaykgPT09IC0xKSB7XG4gICAgY3VycmVudC5hcHA/Lm9uVXBkYXRlLnB1c2goY2FsbGJhY2spO1xuICB9XG59XG5cbi8qXG4gICogTW91bnRzIGEgY29tcG9uZW50IHRvIHRoZSBET01cbiAgbW91bnQoJyNhcHAnLCAoKSA9PiA8ZGl2PkhlbGxvIHdvcmxkPC9kaXY+KTsgLy8gQXBwIGlzIGEgRnVuY3Rpb25hbCBDb21wb25lbnRcbiAgbW91bnQoJyNhcHAnLCB7IHZpZXc6ICgpID0+IDxkaXY+SGVsbG8gd29ybGQ8L2Rpdj4gfSk7IC8vIEFwcCBpcyBhIFBPSk8gY29tcG9uZW50IHdpdGggYSB2aWV3IG1ldGhvZFxuICBtb3VudCgnI2FwcCcsIGNsYXNzSW5zdGFuY2UpOyAvLyBBcHAgaXMgYSBjbGFzcyBpbnN0YW5jZSB3aXRoIGEgdmlldyBtZXRob2RcbiAgbW91bnQoJyNhcHAnLCA8QXBwPjxkaXY+SGVsbG8gd29ybGQ8L2Rpdj48L0FwcD4pOyAvLyBBcHAgaXMgYSBWbm9kZSBjb21wb25lbnQgKFZub2RlIHdpdGggdGFnIF9fY29tcG9uZW50X18pXG4qL1xuXG5leHBvcnQgZnVuY3Rpb24gbW91bnQoY29udGFpbmVyOiBEb21FbGVtZW50IHwgc3RyaW5nLCBjb21wb25lbnQ6IFZhbHlyaWFuQ29tcG9uZW50IHwgSVZub2RlKTogdm9pZCB8IHN0cmluZyB7XG4gIGxldCBhcHBDb250YWluZXIgPSBudWxsO1xuXG4gIGlmIChpc05vZGVKcykge1xuICAgIGFwcENvbnRhaW5lciA9IHR5cGVvZiBjb250YWluZXIgPT09IFwic3RyaW5nXCIgPyBjcmVhdGVEb21FbGVtZW50KGNvbnRhaW5lciA9PT0gXCJzdmdcIiA/IFwic3ZnXCIgOiBcImRpdlwiLCBjb250YWluZXIgPT09IFwic3ZnXCIpIDogY29udGFpbmVyO1xuICB9IGVsc2Uge1xuICAgIGFwcENvbnRhaW5lciA9IHR5cGVvZiBjb250YWluZXIgPT09IFwic3RyaW5nXCIgPyBkb2N1bWVudC5xdWVyeVNlbGVjdG9yQWxsKGNvbnRhaW5lcilbMF0gOiBjb250YWluZXI7XG4gIH1cblxuICBpZiAoIWFwcENvbnRhaW5lcikge1xuICAgIHRocm93IG5ldyBFcnJvcihcIkNvbnRhaW5lciBub3QgZm91bmRcIik7XG4gIH1cblxuICBsZXQgdm5vZGVDb21wb25lbnQ6IFZub2RlQ29tcG9uZW50IHwgSVZub2RlO1xuXG4gIGlmIChpc1Zub2RlQ29tcG9uZW50KGNvbXBvbmVudCkpIHtcbiAgICB2bm9kZUNvbXBvbmVudCA9IGNvbXBvbmVudDtcbiAgfSBlbHNlIGlmIChpc0NvbXBvbmVudChjb21wb25lbnQpKSB7XG4gICAgdm5vZGVDb21wb25lbnQgPSB2KGNvbXBvbmVudCwge30pO1xuICB9IGVsc2Uge1xuICAgIHRocm93IG5ldyBFcnJvcihcIkNvbXBvbmVudCBtdXN0IGJlIGEgVmFseXJpYW4gQ29tcG9uZW50IG9yIGEgVm5vZGUgY29tcG9uZW50XCIpO1xuICB9XG5cbiAgaWYgKGNvbXBvbmVudFtWYWx5cmlhblN5bWJvbF0pIHtcbiAgICB1bm1vdW50KGNvbXBvbmVudCk7XG4gIH0gZWxzZSB7XG4gICAgY29tcG9uZW50W1ZhbHlyaWFuU3ltYm9sXSA9IHtcbiAgICAgIGlzTW91bnRlZDogZmFsc2UsXG4gICAgICBldmVudExpc3RlbmVyTmFtZXM6IHt9LFxuICAgICAgb25DbGVhbnVwOiBbXSxcbiAgICAgIG9uTW91bnQ6IFtdLFxuICAgICAgb25VcGRhdGU6IFtdLFxuICAgICAgb25Vbm1vdW50OiBbXVxuICAgIH07XG4gICAgZnVuY3Rpb24gZXZlbnRMaXN0ZW5lcihlOiBFdmVudCkge1xuICAgICAgbGV0IGRvbSA9IGUudGFyZ2V0IGFzIERvbUVsZW1lbnQgJiBSZWNvcmQ8c3RyaW5nLCBhbnk+O1xuICAgICAgbGV0IG5hbWUgPSBgdi1vbiR7ZS50eXBlfWA7XG4gICAgICB3aGlsZSAoZG9tKSB7XG4gICAgICAgIGlmIChkb21bbmFtZV0pIHtcbiAgICAgICAgICBkb21bbmFtZV0oZSwgZG9tKTtcbiAgICAgICAgICBpZiAoIWUuZGVmYXVsdFByZXZlbnRlZCkge1xuICAgICAgICAgICAgdXBkYXRlKGNvbXBvbmVudCk7XG4gICAgICAgICAgfVxuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBkb20gPSBkb20ucGFyZW50Tm9kZSBhcyBEb21FbGVtZW50O1xuICAgICAgfVxuICAgIH1cbiAgICBjb21wb25lbnRbVmFseXJpYW5TeW1ib2xdLmV2ZW50TGlzdGVuZXIgPSBldmVudExpc3RlbmVyO1xuICB9XG5cbiAgY29tcG9uZW50W1ZhbHlyaWFuU3ltYm9sXS5jb21wb25lbnQgPSB2bm9kZUNvbXBvbmVudDtcbiAgY29tcG9uZW50W1ZhbHlyaWFuU3ltYm9sXS5jb250YWluZXIgPSBhcHBDb250YWluZXI7XG4gIGNvbXBvbmVudFtWYWx5cmlhblN5bWJvbF0ubWFpblZub2RlID0gZG9tVG9Wbm9kZShhcHBDb250YWluZXIpO1xuXG4gIC8vIHVwZGF0ZVxuICByZXR1cm4gdXBkYXRlKGNvbXBvbmVudCk7XG59XG5cbmZ1bmN0aW9uIGNhbGxDbGVhbnVwKHZhbHlyaWFuQXBwOiBWYWx5cmlhbkFwcCkge1xuICBmb3IgKGxldCBpID0gMDsgaSA8IHZhbHlyaWFuQXBwLm9uQ2xlYW51cC5sZW5ndGg7IGkrKykge1xuICAgIHZhbHlyaWFuQXBwLm9uQ2xlYW51cFtpXSgpO1xuICB9XG4gIHZhbHlyaWFuQXBwLm9uQ2xlYW51cCA9IFtdO1xufVxuXG5mdW5jdGlvbiBjYWxsVW5tb3VudCh2YWx5cmlhbkFwcDogVmFseXJpYW5BcHApIHtcbiAgZm9yIChsZXQgaSA9IDA7IGkgPCB2YWx5cmlhbkFwcC5vblVubW91bnQubGVuZ3RoOyBpKyspIHtcbiAgICB2YWx5cmlhbkFwcC5vblVubW91bnRbaV0oKTtcbiAgfVxuICB2YWx5cmlhbkFwcC5vblVubW91bnQgPSBbXTtcbn1cblxuZnVuY3Rpb24gY2FsbE1vdW50KHZhbHlyaWFuQXBwOiBWYWx5cmlhbkFwcCkge1xuICBmb3IgKGxldCBpID0gMDsgaSA8IHZhbHlyaWFuQXBwLm9uTW91bnQubGVuZ3RoOyBpKyspIHtcbiAgICB2YWx5cmlhbkFwcC5vbk1vdW50W2ldKCk7XG4gIH1cbiAgdmFseXJpYW5BcHAub25Nb3VudCA9IFtdO1xufVxuXG5mdW5jdGlvbiBjYWxsVXBkYXRlKHZhbHlyaWFuQXBwOiBWYWx5cmlhbkFwcCkge1xuICBmb3IgKGxldCBpID0gMDsgaSA8IHZhbHlyaWFuQXBwLm9uVXBkYXRlLmxlbmd0aDsgaSsrKSB7XG4gICAgdmFseXJpYW5BcHAub25VcGRhdGVbaV0oKTtcbiAgfVxuICB2YWx5cmlhbkFwcC5vblVwZGF0ZSA9IFtdO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gdXBkYXRlKGNvbXBvbmVudD86IFZhbHlyaWFuQ29tcG9uZW50IHwgSVZub2RlKTogdm9pZCB8IHN0cmluZyB7XG4gIGlmIChjb21wb25lbnQgJiYgY29tcG9uZW50W1ZhbHlyaWFuU3ltYm9sXSkge1xuICAgIGxldCB2YWx5cmlhbkFwcCA9IGNvbXBvbmVudFtWYWx5cmlhblN5bWJvbF07XG4gICAgY3VycmVudC5hcHAgPSB2YWx5cmlhbkFwcDtcbiAgICB2YWx5cmlhbkFwcC5vbkNsZWFudXAubGVuZ3RoICYmIGNhbGxDbGVhbnVwKHZhbHlyaWFuQXBwKTtcbiAgICBsZXQgb2xkVm5vZGU6IFZub2RlV2l0aERvbSB8IG51bGwgPSB2YWx5cmlhbkFwcC5tYWluVm5vZGUgYXMgVm5vZGVXaXRoRG9tO1xuICAgIHZhbHlyaWFuQXBwLm1haW5Wbm9kZSA9IG5ldyBWbm9kZSh2YWx5cmlhbkFwcC5tYWluVm5vZGUudGFnLCB2YWx5cmlhbkFwcC5tYWluVm5vZGUucHJvcHMsIFt2YWx5cmlhbkFwcC5jb21wb25lbnRdKSBhcyBWbm9kZVdpdGhEb207XG4gICAgdmFseXJpYW5BcHAubWFpblZub2RlLmRvbSA9IG9sZFZub2RlLmRvbTtcbiAgICBwYXRjaCh2YWx5cmlhbkFwcC5tYWluVm5vZGUsIG9sZFZub2RlLCB2YWx5cmlhbkFwcCk7XG4gICAgb2xkVm5vZGUgPSBudWxsO1xuICAgIGlmICh2YWx5cmlhbkFwcC5pc01vdW50ZWQgPT09IGZhbHNlKSB7XG4gICAgICB2YWx5cmlhbkFwcC5vbk1vdW50Lmxlbmd0aCAmJiBjYWxsTW91bnQodmFseXJpYW5BcHApO1xuICAgICAgdmFseXJpYW5BcHAuaXNNb3VudGVkID0gdHJ1ZTtcbiAgICB9IGVsc2Uge1xuICAgICAgdmFseXJpYW5BcHAub25VcGRhdGUubGVuZ3RoICYmIGNhbGxVcGRhdGUodmFseXJpYW5BcHApO1xuICAgIH1cblxuICAgIGlmIChpc05vZGVKcykge1xuICAgICAgcmV0dXJuIHZhbHlyaWFuQXBwLm1haW5Wbm9kZS5kb20uaW5uZXJIVE1MO1xuICAgIH1cbiAgfVxufVxuXG5leHBvcnQgZnVuY3Rpb24gdW5tb3VudChjb21wb25lbnQ/OiBWYWx5cmlhbkNvbXBvbmVudCB8IElWbm9kZSk6IHZvaWQgfCBzdHJpbmcge1xuICBpZiAoIWNvbXBvbmVudCB8fCAhY29tcG9uZW50W1ZhbHlyaWFuU3ltYm9sXSkge1xuICAgIHJldHVybjtcbiAgfVxuXG4gIGxldCB2YWx5cmlhbkFwcCA9IGNvbXBvbmVudFtWYWx5cmlhblN5bWJvbF0gYXMgTW91bnRlZFZhbHlyaWFuQXBwO1xuXG4gIGlmICh2YWx5cmlhbkFwcC5pc01vdW50ZWQpIHtcbiAgICB2YWx5cmlhbkFwcC5vbkNsZWFudXAubGVuZ3RoICYmIGNhbGxDbGVhbnVwKHZhbHlyaWFuQXBwKTtcbiAgICB2YWx5cmlhbkFwcC5vblVubW91bnQubGVuZ3RoICYmIGNhbGxVbm1vdW50KHZhbHlyaWFuQXBwKTtcbiAgICBsZXQgb2xkVm5vZGU6IFZub2RlV2l0aERvbSB8IG51bGwgPSB2YWx5cmlhbkFwcC5tYWluVm5vZGUgYXMgVm5vZGVXaXRoRG9tO1xuICAgIHZhbHlyaWFuQXBwLm1haW5Wbm9kZSA9IG5ldyBWbm9kZSh2YWx5cmlhbkFwcC5tYWluVm5vZGUudGFnLCB2YWx5cmlhbkFwcC5tYWluVm5vZGUucHJvcHMsIFtdKSBhcyBWbm9kZVdpdGhEb207XG4gICAgdmFseXJpYW5BcHAubWFpblZub2RlLmRvbSA9IG9sZFZub2RlLmRvbTtcbiAgICB2YWx5cmlhbkFwcC5tYWluVm5vZGUuaXNTVkcgPSBvbGRWbm9kZS5pc1NWRztcbiAgICBwYXRjaCh2YWx5cmlhbkFwcC5tYWluVm5vZGUsIG9sZFZub2RlLCB2YWx5cmlhbkFwcCk7XG4gICAgb2xkVm5vZGUgPSBudWxsO1xuXG4gICAgaWYgKGlzTm9kZUpzKSB7XG4gICAgICByZXR1cm4gdmFseXJpYW5BcHAubWFpblZub2RlLmRvbS5pbm5lckhUTUw7XG4gICAgfVxuXG4gICAgKHZhbHlyaWFuQXBwIGFzIGFueSkgPSBudWxsO1xuICAgIFJlZmxlY3QuZGVsZXRlUHJvcGVydHkoY29tcG9uZW50LCBWYWx5cmlhblN5bWJvbCk7XG4gIH1cbn1cblxubGV0IGVtcHR5Vm5vZGUgPSBuZXcgVm5vZGUoXCJfX2VtcHR5X19cIiwge30sIFtdKTtcblxuZnVuY3Rpb24gb25yZW1vdmUodm5vZGU6IElWbm9kZSkge1xuICBmb3IgKGxldCBpID0gMDsgaSA8IHZub2RlLmNoaWxkcmVuLmxlbmd0aDsgaSsrKSB7XG4gICAgdm5vZGUuY2hpbGRyZW5baV0udGFnICE9PSBUZXh0U3RyaW5nICYmIG9ucmVtb3ZlKHZub2RlLmNoaWxkcmVuW2ldKTtcbiAgfVxuXG4gIHZub2RlLnByb3BzLm9ucmVtb3ZlICYmIHZub2RlLnByb3BzLm9ucmVtb3ZlKHZub2RlKTtcbn1cblxuZnVuY3Rpb24gc2hhcmVkU2V0QXR0cmlidXRlKHByb3A6IHN0cmluZywgdmFsdWU6IGFueSwgdm5vZGU6IFZub2RlV2l0aERvbSwgb2xkVm5vZGU/OiBWbm9kZVdpdGhEb20pOiB2b2lkIHwgYm9vbGVhbiB7XG4gIC8vIEl0IGlzIGEgcmVzZXJ2ZWQgcHJvcFxuICBpZiAocmVzZXJ2ZWRQcm9wc1twcm9wXSkge1xuICAgIC8vIElmIGl0IGlzIGEgZGlyZWN0aXZlIG5hbWUgY2FsbCB0aGUgZGlyZWN0aXZlXG4gICAgaWYgKGRpcmVjdGl2ZXNbcHJvcF0pIHtcbiAgICAgIHJldHVybiBkaXJlY3RpdmVzW3Byb3BdKHZub2RlLnByb3BzW3Byb3BdLCB2bm9kZSwgb2xkVm5vZGUpO1xuICAgIH1cblxuICAgIHJldHVybjtcbiAgfVxuXG4gIC8vIEl0IGlzIG5vdCBhIHJlc2VydmVkIHByb3Agc28gd2UgYWRkIGl0IHRvIHRoZSBkb21cbiAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gXCJmdW5jdGlvblwiKSB7XG4gICAgbGV0IHZhbHlyaWFuQXBwID0gY3VycmVudC5hcHAgYXMgTW91bnRlZFZhbHlyaWFuQXBwO1xuICAgIGlmIChwcm9wIGluIHZhbHlyaWFuQXBwLmV2ZW50TGlzdGVuZXJOYW1lcyA9PT0gZmFsc2UpIHtcbiAgICAgIHZhbHlyaWFuQXBwLmV2ZW50TGlzdGVuZXJOYW1lc1twcm9wXSA9IHRydWU7XG4gICAgICB2YWx5cmlhbkFwcC5jb250YWluZXIuYWRkRXZlbnRMaXN0ZW5lcihwcm9wLnNsaWNlKDIpLCB2YWx5cmlhbkFwcC5ldmVudExpc3RlbmVyKTtcbiAgICB9XG4gICAgdm5vZGUuZG9tW2B2LSR7cHJvcH1gXSA9IHZhbHVlO1xuICAgIHJldHVybjtcbiAgfVxuXG4gIGlmIChwcm9wIGluIHZub2RlLmRvbSAmJiB2bm9kZS5pc1NWRyA9PT0gZmFsc2UpIHtcbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgZXFlcWVxXG4gICAgaWYgKHZub2RlLmRvbVtwcm9wXSAhPSB2YWx1ZSkge1xuICAgICAgdm5vZGUuZG9tW3Byb3BdID0gdmFsdWU7XG4gICAgfVxuICAgIHJldHVybjtcbiAgfVxuXG4gIC8vIFVzZSBzZXQgYXR0cmlidXRlXG4gIGlmICghb2xkVm5vZGUgfHwgb2xkVm5vZGUucHJvcHNbcHJvcF0gIT09IHZhbHVlKSB7XG4gICAgaWYgKHZhbHVlID09PSBmYWxzZSkge1xuICAgICAgdm5vZGUuZG9tLnJlbW92ZUF0dHJpYnV0ZShwcm9wKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdm5vZGUuZG9tLnNldEF0dHJpYnV0ZShwcm9wLCB2YWx1ZSk7XG4gICAgfVxuICB9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBzZXRBdHRyaWJ1dGUobmFtZTogc3RyaW5nLCB2YWx1ZTogYW55LCB2bm9kZTogVm5vZGVXaXRoRG9tLCBvbGRWbm9kZT86IFZub2RlV2l0aERvbSkge1xuICB2bm9kZS5wcm9wc1tuYW1lXSA9IHZhbHVlO1xuXG4gIHNoYXJlZFNldEF0dHJpYnV0ZShuYW1lLCB2YWx1ZSwgdm5vZGUsIG9sZFZub2RlKTtcbn1cblxuZnVuY3Rpb24gc2V0QXR0cmlidXRlcyh2bm9kZTogVm5vZGVXaXRoRG9tLCBvbGRWbm9kZT86IFZub2RlV2l0aERvbSkge1xuICBmb3IgKGxldCBwcm9wIGluIHZub2RlLnByb3BzKSB7XG4gICAgaWYgKHNoYXJlZFNldEF0dHJpYnV0ZShwcm9wLCB2bm9kZS5wcm9wc1twcm9wXSwgdm5vZGUsIG9sZFZub2RlKSA9PT0gZmFsc2UpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gIH1cblxuICBpZiAob2xkVm5vZGUpIHtcbiAgICBmb3IgKGxldCBwcm9wIGluIG9sZFZub2RlLnByb3BzKSB7XG4gICAgICBpZiAocHJvcCBpbiB2bm9kZS5wcm9wcyA9PT0gZmFsc2UgJiYgdHlwZW9mIG9sZFZub2RlLnByb3BzW3Byb3BdICE9PSBcImZ1bmN0aW9uXCIgJiYgcHJvcCBpbiByZXNlcnZlZFByb3BzID09PSBmYWxzZSkge1xuICAgICAgICBpZiAocHJvcCBpbiBvbGRWbm9kZS5kb20gJiYgdm5vZGUuaXNTVkcgPT09IGZhbHNlKSB7XG4gICAgICAgICAgb2xkVm5vZGUuZG9tW3Byb3BdID0gbnVsbDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBvbGRWbm9kZS5kb20ucmVtb3ZlQXR0cmlidXRlKHByb3ApO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICB9XG59XG5cbi8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBjb21wbGV4aXR5XG5mdW5jdGlvbiBwYXRjaChuZXdWbm9kZTogVm5vZGVXaXRoRG9tLCBvbGRWbm9kZTogVm5vZGVXaXRoRG9tIHwgSVZub2RlID0gZW1wdHlWbm9kZSwgdmFseXJpYW5BcHA6IE1vdW50ZWRWYWx5cmlhbkFwcCkge1xuICBjdXJyZW50LnZub2RlID0gbmV3Vm5vZGU7XG4gIGN1cnJlbnQub2xkVm5vZGUgPSBvbGRWbm9kZSA9PT0gZW1wdHlWbm9kZSA/IFVuZCA6IChvbGRWbm9kZSBhcyBWbm9kZVdpdGhEb20pO1xuICBsZXQgbmV3VHJlZSA9IG5ld1Zub2RlLmNoaWxkcmVuO1xuICBsZXQgb2xkVHJlZSA9IG9sZFZub2RlLmNoaWxkcmVuO1xuXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgbmV3VHJlZS5sZW5ndGg7IGkrKykge1xuICAgIGxldCBjaGlsZFZub2RlID0gbmV3VHJlZVtpXTtcbiAgICBpZiAoY2hpbGRWbm9kZSBpbnN0YW5jZW9mIFZub2RlKSB7XG4gICAgICBpZiAoY2hpbGRWbm9kZS50YWcgIT09IFRleHRTdHJpbmcpIHtcbiAgICAgICAgaWYgKGNoaWxkVm5vZGUudGFnID09PSBDb21wb25lbnRTdHJpbmcpIHtcbiAgICAgICAgICBsZXQgY29tcG9uZW50ID0gY2hpbGRWbm9kZS5jb21wb25lbnQgYXMgVmFseXJpYW5Db21wb25lbnQ7XG4gICAgICAgICAgY3VycmVudC5jb21wb25lbnQgPSBjb21wb25lbnQ7XG4gICAgICAgICAgbGV0IHJlc3VsdCA9IChcInZpZXdcIiBpbiBjb21wb25lbnQgPyBjb21wb25lbnQudmlldyA6IGNvbXBvbmVudCkuY2FsbChjb21wb25lbnQsIGNoaWxkVm5vZGUucHJvcHMsIC4uLmNoaWxkVm5vZGUuY2hpbGRyZW4pO1xuXG4gICAgICAgICAgbmV3VHJlZS5zcGxpY2UoaS0tLCAxLCByZXN1bHQpO1xuICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICB9XG4gICAgICAgIGNoaWxkVm5vZGUuaXNTVkcgPSBuZXdWbm9kZS5pc1NWRyB8fCBjaGlsZFZub2RlLnRhZyA9PT0gXCJzdmdcIjtcbiAgICAgIH1cbiAgICB9IGVsc2UgaWYgKEFycmF5LmlzQXJyYXkoY2hpbGRWbm9kZSkpIHtcbiAgICAgIG5ld1RyZWUuc3BsaWNlKGktLSwgMSwgLi4uY2hpbGRWbm9kZSk7XG4gICAgfSBlbHNlIGlmIChjaGlsZFZub2RlID09PSBudWxsIHx8IGNoaWxkVm5vZGUgPT09IFVuZCkge1xuICAgICAgbmV3VHJlZS5zcGxpY2UoaS0tLCAxKTtcbiAgICB9IGVsc2Uge1xuICAgICAgbmV3VHJlZVtpXSA9IG5ldyBWbm9kZShUZXh0U3RyaW5nLCB7fSwgW10pO1xuICAgICAgbmV3VHJlZVtpXS5ub2RlVmFsdWUgPSBjaGlsZFZub2RlO1xuICAgIH1cbiAgfVxuXG4gIGxldCBvbGRUcmVlTGVuZ3RoID0gb2xkVHJlZS5sZW5ndGg7XG4gIGxldCBuZXdUcmVlTGVuZ3RoID0gbmV3VHJlZS5sZW5ndGg7XG5cbiAgLy8gSWYgbmV3IHRyZWUgaXMgZW1wdHksIHJlbW92ZSBhbGwgb2xkIG5vZGVzXG4gIGlmIChuZXdUcmVlTGVuZ3RoID09PSAwKSB7XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBvbGRUcmVlTGVuZ3RoOyBpKyspIHtcbiAgICAgIG9sZFRyZWVbaV0udGFnICE9PSBUZXh0U3RyaW5nICYmIG9ucmVtb3ZlKG9sZFRyZWVbaV0pO1xuICAgIH1cblxuICAgIG5ld1Zub2RlLmRvbS50ZXh0Q29udGVudCA9IFwiXCI7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgLy8gSWYgdGhlIHRyZWUgaXMga2V5ZWQgbGlzdCBhbmQgaXMgbm90IGZpcnN0IHJlbmRlciBhbmQgb2xkIHRyZWUgaXMga2V5ZWQgbGlzdCB0b29cbiAgaWYgKG9sZFRyZWVMZW5ndGggJiYgXCJrZXlcIiBpbiBuZXdUcmVlWzBdLnByb3BzICYmIFwia2V5XCIgaW4gb2xkVHJlZVswXS5wcm9wcykge1xuICAgIGxldCBvbGRLZXllZExpc3Q6IHtba2V5OiBzdHJpbmddOiBudW1iZXJ9ID0ge307XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBvbGRUcmVlTGVuZ3RoOyBpKyspIHtcbiAgICAgIG9sZEtleWVkTGlzdFtvbGRUcmVlW2ldLnByb3BzLmtleV0gPSBpO1xuICAgIH1cblxuICAgIGxldCBuZXdLZXllZExpc3Q6IHtba2V5OiBzdHJpbmddOiBudW1iZXJ9ID0ge307XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBuZXdUcmVlTGVuZ3RoOyBpKyspIHtcbiAgICAgIG5ld0tleWVkTGlzdFtuZXdUcmVlW2ldLnByb3BzLmtleV0gPSBpO1xuICAgIH1cblxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbmV3VHJlZUxlbmd0aDsgaSsrKSB7XG4gICAgICBsZXQgY2hpbGRWbm9kZSA9IG5ld1RyZWVbaV07XG4gICAgICBsZXQgb2xkQ2hpbGRWbm9kZSA9IG9sZFRyZWVbb2xkS2V5ZWRMaXN0W2NoaWxkVm5vZGUucHJvcHMua2V5XV07XG4gICAgICBsZXQgc2hvdWxkUGF0Y2ggPSB0cnVlO1xuXG4gICAgICBpZiAob2xkQ2hpbGRWbm9kZSkge1xuICAgICAgICBjaGlsZFZub2RlLmRvbSA9IG9sZENoaWxkVm5vZGUuZG9tO1xuICAgICAgICBpZiAoXCJ2LW9uY2VcIiBpbiBjaGlsZFZub2RlLnByb3BzIHx8IChjaGlsZFZub2RlLnByb3BzLnNob3VsZHVwZGF0ZSAmJiBjaGlsZFZub2RlLnByb3BzLnNob3VsZHVwZGF0ZShjaGlsZFZub2RlLCBvbGRDaGlsZFZub2RlKSA9PT0gZmFsc2UpKSB7XG4gICAgICAgICAgLy8gc2tpcCB0aGlzIHBhdGNoXG4gICAgICAgICAgY2hpbGRWbm9kZS5jaGlsZHJlbiA9IG9sZENoaWxkVm5vZGUuY2hpbGRyZW47XG4gICAgICAgICAgc2hvdWxkUGF0Y2ggPSBmYWxzZTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBzZXRBdHRyaWJ1dGVzKGNoaWxkVm5vZGUsIG9sZENoaWxkVm5vZGUpO1xuICAgICAgICAgIGlmICh2YWx5cmlhbkFwcC5pc01vdW50ZWQpIHtcbiAgICAgICAgICAgIGNoaWxkVm5vZGUucHJvcHMub251cGRhdGUgJiYgY2hpbGRWbm9kZS5wcm9wcy5vbnVwZGF0ZShjaGlsZFZub2RlLCBvbGRDaGlsZFZub2RlKTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgY2hpbGRWbm9kZS5wcm9wcy5vbmNyZWF0ZSAmJiBjaGlsZFZub2RlLnByb3BzLm9uY3JlYXRlKGNoaWxkVm5vZGUpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgY2hpbGRWbm9kZS5kb20gPSBjcmVhdGVEb21FbGVtZW50KGNoaWxkVm5vZGUudGFnLCBjaGlsZFZub2RlLmlzU1ZHKTtcbiAgICAgICAgc2V0QXR0cmlidXRlcyhjaGlsZFZub2RlKTtcbiAgICAgICAgY2hpbGRWbm9kZS5wcm9wcy5vbmNyZWF0ZSAmJiBjaGlsZFZub2RlLnByb3BzLm9uY3JlYXRlKGNoaWxkVm5vZGUpO1xuICAgICAgfVxuXG4gICAgICBpZiAobmV3Vm5vZGUuZG9tLmNoaWxkTm9kZXNbaV0gPT09IFVuZCkge1xuICAgICAgICBuZXdWbm9kZS5kb20uYXBwZW5kQ2hpbGQoY2hpbGRWbm9kZS5kb20pO1xuICAgICAgfSBlbHNlIGlmIChuZXdWbm9kZS5kb20uY2hpbGROb2Rlc1tpXSAhPT0gY2hpbGRWbm9kZS5kb20pIHtcbiAgICAgICAgb2xkVHJlZVtpXSAmJiBuZXdLZXllZExpc3Rbb2xkVHJlZVtpXS5wcm9wcy5rZXldID09PSBVbmQgJiYgb25yZW1vdmUob2xkVHJlZVtpXSk7XG4gICAgICAgIG5ld1Zub2RlLmRvbS5yZXBsYWNlQ2hpbGQoY2hpbGRWbm9kZS5kb20sIG5ld1Zub2RlLmRvbS5jaGlsZE5vZGVzW2ldKTtcbiAgICAgIH1cblxuICAgICAgc2hvdWxkUGF0Y2ggJiYgcGF0Y2goY2hpbGRWbm9kZSwgb2xkQ2hpbGRWbm9kZSwgdmFseXJpYW5BcHApO1xuICAgIH1cblxuICAgIC8vIEZvciB0aGUgcmVzdCBvZiB0aGUgY2hpbGRyZW4sIHdlIHNob3VsZCByZW1vdmUgdGhlbVxuICAgIGZvciAobGV0IGkgPSBuZXdUcmVlTGVuZ3RoOyBpIDwgb2xkVHJlZUxlbmd0aDsgaSsrKSB7XG4gICAgICBpZiAobmV3S2V5ZWRMaXN0W29sZFRyZWVbaV0ucHJvcHMua2V5XSA9PT0gVW5kKSB7XG4gICAgICAgIGxldCBvbGRDaGlsZFZub2RlID0gb2xkVHJlZVtpXTtcbiAgICAgICAgb25yZW1vdmUob2xkQ2hpbGRWbm9kZSk7XG4gICAgICAgIG9sZENoaWxkVm5vZGUuZG9tLnBhcmVudE5vZGUgJiYgb2xkQ2hpbGRWbm9kZS5kb20ucGFyZW50Tm9kZS5yZW1vdmVDaGlsZChvbGRDaGlsZFZub2RlLmRvbSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuO1xuICB9XG5cbiAgLy8gSWYgbmV3IHRyZWUgYW5kIG9sZCB0cmVlIGhhdmUgbW9yZSB0aGFuIG9uZSBjaGlsZCwgd2Ugc2hvdWxkIHVwZGF0ZSB0aGUgZG9tXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgbmV3VHJlZUxlbmd0aDsgaSsrKSB7XG4gICAgbGV0IG5ld0NoaWxkVm5vZGUgPSBuZXdUcmVlW2ldO1xuXG4gICAgLy8gT2xkIGNoaWxkIGV4aXN0c1xuICAgIGlmIChpIDwgb2xkVHJlZUxlbmd0aCkge1xuICAgICAgbGV0IG9sZENoaWxkVm5vZGUgPSBvbGRUcmVlW2ldO1xuICAgICAgLy8gTmV3IGNoaWxkIGlzIGEgdGV4dCBub2RlXG4gICAgICBpZiAobmV3Q2hpbGRWbm9kZS50YWcgPT09IFRleHRTdHJpbmcpIHtcbiAgICAgICAgLy8gT2xkIGNoaWxkIGlzIGEgdGV4dCBub2RlXG4gICAgICAgIGlmIChvbGRDaGlsZFZub2RlLnRhZyA9PT0gVGV4dFN0cmluZykge1xuICAgICAgICAgIG5ld0NoaWxkVm5vZGUuZG9tID0gb2xkQ2hpbGRWbm9kZS5kb207XG4gICAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGVxZXFlcVxuICAgICAgICAgIGlmIChuZXdDaGlsZFZub2RlLmRvbS5ub2RlVmFsdWUgIT0gbmV3Q2hpbGRWbm9kZS5ub2RlVmFsdWUpIHtcbiAgICAgICAgICAgIG5ld0NoaWxkVm5vZGUuZG9tLm5vZGVWYWx1ZSA9IG5ld0NoaWxkVm5vZGUubm9kZVZhbHVlIGFzIHN0cmluZztcbiAgICAgICAgICB9XG4gICAgICAgICAgY29udGludWU7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBPbGQgY2hpbGQgaXMgYSBub3JtYWwgbm9kZVxuICAgICAgICBuZXdDaGlsZFZub2RlLmRvbSA9IGRvY3VtZW50LmNyZWF0ZVRleHROb2RlKG5ld0NoaWxkVm5vZGUubm9kZVZhbHVlIGFzIHN0cmluZykgYXMgdW5rbm93biBhcyBEb21FbGVtZW50O1xuICAgICAgICBvbnJlbW92ZShvbGRDaGlsZFZub2RlKTtcbiAgICAgICAgbmV3Vm5vZGUuZG9tLnJlcGxhY2VDaGlsZChuZXdDaGlsZFZub2RlLmRvbSwgb2xkQ2hpbGRWbm9kZS5kb20pO1xuXG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuXG4gICAgICAvLyBOZXcgY2hpbGQgaXMgYSBub3JtYWwgbm9kZVxuICAgICAgLy8gT2xkIGNoaWxkIGlzIHRoZSBzYW1lIHR5cGUgYXMgbmV3IGNoaWxkXG4gICAgICBpZiAob2xkQ2hpbGRWbm9kZS50YWcgPT09IG5ld0NoaWxkVm5vZGUudGFnKSB7XG4gICAgICAgIG5ld0NoaWxkVm5vZGUuZG9tID0gb2xkQ2hpbGRWbm9kZS5kb207XG4gICAgICAgIC8vIElmIHdlIGhhdmUgYSB2LW9uY2UgZGlyZWN0aXZlIG9yIGEgc2hvdWxkdXBkYXRlIG1ldGhvZCB0aGF0IHJldHVybnMgZmFsc2UsIHdlIHNraXAgdGhlIHVwZGF0ZVxuICAgICAgICBpZiAobmV3Q2hpbGRWbm9kZS5wcm9wc1tcInYtb25jZVwiXSB8fCAobmV3Q2hpbGRWbm9kZS5wcm9wcy5zaG91bGR1cGRhdGUgJiYgbmV3Q2hpbGRWbm9kZS5wcm9wcy5zaG91bGR1cGRhdGUobmV3Q2hpbGRWbm9kZSwgb2xkQ2hpbGRWbm9kZSkgPT09IGZhbHNlKSkge1xuICAgICAgICAgIG5ld0NoaWxkVm5vZGUuY2hpbGRyZW4gPSBvbGRDaGlsZFZub2RlLmNoaWxkcmVuO1xuICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gV2UgdXBkYXRlIHRoZSBkb20gZWxlbWVudFxuICAgICAgICBzZXRBdHRyaWJ1dGVzKG5ld0NoaWxkVm5vZGUsIG9sZENoaWxkVm5vZGUpO1xuICAgICAgICBpZiAodmFseXJpYW5BcHAuaXNNb3VudGVkKSB7XG4gICAgICAgICAgbmV3Q2hpbGRWbm9kZS5wcm9wcy5vbnVwZGF0ZSAmJiBuZXdDaGlsZFZub2RlLnByb3BzLm9udXBkYXRlKG5ld0NoaWxkVm5vZGUsIG9sZENoaWxkVm5vZGUpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIG5ld0NoaWxkVm5vZGUucHJvcHMub25jcmVhdGUgJiYgbmV3Q2hpbGRWbm9kZS5wcm9wcy5vbmNyZWF0ZShuZXdDaGlsZFZub2RlKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHBhdGNoKG5ld0NoaWxkVm5vZGUsIG9sZENoaWxkVm5vZGUsIHZhbHlyaWFuQXBwKTtcbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG5cbiAgICAgIC8vIE9sZCBjaGlsZCBpcyBvZiBhIGRpZmZlcmVudCB0eXBlIHRoYW4gbmV3IGNoaWxkXG4gICAgICBuZXdDaGlsZFZub2RlLmRvbSA9IGNyZWF0ZURvbUVsZW1lbnQobmV3Q2hpbGRWbm9kZS50YWcsIG5ld0NoaWxkVm5vZGUuaXNTVkcpO1xuICAgICAgc2V0QXR0cmlidXRlcyhuZXdDaGlsZFZub2RlKTtcbiAgICAgIG9sZENoaWxkVm5vZGUudGFnICE9PSBUZXh0U3RyaW5nICYmIG9ucmVtb3ZlKG9sZENoaWxkVm5vZGUpO1xuICAgICAgbmV3Q2hpbGRWbm9kZS5wcm9wcy5vbmNyZWF0ZSAmJiBuZXdDaGlsZFZub2RlLnByb3BzLm9uY3JlYXRlKG5ld0NoaWxkVm5vZGUpO1xuICAgICAgbmV3Vm5vZGUuZG9tLnJlcGxhY2VDaGlsZChuZXdDaGlsZFZub2RlLmRvbSwgb2xkQ2hpbGRWbm9kZS5kb20pO1xuICAgICAgcGF0Y2gobmV3Q2hpbGRWbm9kZSwgZW1wdHlWbm9kZSwgdmFseXJpYW5BcHApO1xuICAgICAgY29udGludWU7XG4gICAgfVxuXG4gICAgLy8gT2xkIGNoaWxkIGRvZXMgbm90IGV4aXN0c1xuICAgIC8vIE5ldyBjaGlsZCBpcyBhIHRleHQgbm9kZVxuICAgIGlmIChuZXdDaGlsZFZub2RlLnRhZyA9PT0gVGV4dFN0cmluZykge1xuICAgICAgbmV3Q2hpbGRWbm9kZS5kb20gPSBkb2N1bWVudC5jcmVhdGVUZXh0Tm9kZShuZXdDaGlsZFZub2RlLm5vZGVWYWx1ZSBhcyBzdHJpbmcpIGFzIHVua25vd24gYXMgRG9tRWxlbWVudDtcbiAgICAgIG5ld1Zub2RlLmRvbS5hcHBlbmRDaGlsZChuZXdDaGlsZFZub2RlLmRvbSk7XG4gICAgICBjb250aW51ZTtcbiAgICB9XG5cbiAgICAvLyBOZXcgY2hpbGQgaXMgYSBub3JtYWwgbm9kZVxuICAgIG5ld0NoaWxkVm5vZGUuZG9tID0gY3JlYXRlRG9tRWxlbWVudChuZXdDaGlsZFZub2RlLnRhZywgbmV3Q2hpbGRWbm9kZS5pc1NWRyk7XG4gICAgc2V0QXR0cmlidXRlcyhuZXdDaGlsZFZub2RlKTtcbiAgICBuZXdWbm9kZS5kb20uYXBwZW5kQ2hpbGQobmV3Q2hpbGRWbm9kZS5kb20pO1xuICAgIG5ld0NoaWxkVm5vZGUucHJvcHMub25jcmVhdGUgJiYgbmV3Q2hpbGRWbm9kZS5wcm9wcy5vbmNyZWF0ZShuZXdDaGlsZFZub2RlKTtcbiAgICBwYXRjaChuZXdDaGlsZFZub2RlLCBlbXB0eVZub2RlLCB2YWx5cmlhbkFwcCk7XG4gIH1cblxuICAvLyBGb3IgdGhlIHJlc3Qgb2YgdGhlIGNoaWxkcmVuLCB3ZSBzaG91bGQgcmVtb3ZlIHRoZW1cbiAgZm9yIChsZXQgaSA9IG5ld1RyZWVMZW5ndGg7IGkgPCBvbGRUcmVlTGVuZ3RoOyBpKyspIHtcbiAgICBsZXQgb2xkQ2hpbGRWbm9kZSA9IG9sZFRyZWVbaV07XG4gICAgb2xkQ2hpbGRWbm9kZS50YWcgIT09IFRleHRTdHJpbmcgJiYgb25yZW1vdmUob2xkQ2hpbGRWbm9kZSk7XG4gICAgb2xkQ2hpbGRWbm9kZS5kb20ucGFyZW50Tm9kZSAmJiBvbGRDaGlsZFZub2RlLmRvbS5wYXJlbnROb2RlLnJlbW92ZUNoaWxkKG9sZENoaWxkVm5vZGUuZG9tKTtcbiAgfVxufVxuXG4vKioqIERpcmVjdGl2ZXMgKioqL1xuXG5leHBvcnQgZnVuY3Rpb24gZGlyZWN0aXZlKG5hbWU6IHN0cmluZywgZGlyZWN0aXZlOiBEaXJlY3RpdmUpIHtcbiAgbGV0IGZ1bGxOYW1lID0gYHYtJHtuYW1lfWA7XG4gIGRpcmVjdGl2ZXNbZnVsbE5hbWVdID0gZGlyZWN0aXZlO1xuICByZXNlcnZlZFByb3BzW2Z1bGxOYW1lXSA9IHRydWU7XG59XG5cbmZ1bmN0aW9uIGhpZGVEaXJlY3RpdmUodGVzdDogYm9vbGVhbik6IERpcmVjdGl2ZSB7XG4gIHJldHVybiAoYm9vbDogYm9vbGVhbiwgdm5vZGU6IElWbm9kZSwgb2xkVm5vZGU/OiBJVm5vZGUpID0+IHtcbiAgICBsZXQgdmFsdWUgPSB0ZXN0ID8gYm9vbCA6ICFib29sO1xuICAgIGlmICh2YWx1ZSkge1xuICAgICAgbGV0IG5ld2RvbSA9IGRvY3VtZW50LmNyZWF0ZVRleHROb2RlKFwiXCIpO1xuICAgICAgaWYgKG9sZFZub2RlICYmIG9sZFZub2RlLmRvbSAmJiBvbGRWbm9kZS5kb20ucGFyZW50Tm9kZSkge1xuICAgICAgICBvbGRWbm9kZS50YWcgIT09IFRleHRTdHJpbmcgJiYgb25yZW1vdmUob2xkVm5vZGUpO1xuICAgICAgICBvbGRWbm9kZS5kb20ucGFyZW50Tm9kZS5yZXBsYWNlQ2hpbGQobmV3ZG9tLCBvbGRWbm9kZS5kb20pO1xuICAgICAgfVxuICAgICAgdm5vZGUudGFnID0gVGV4dFN0cmluZztcbiAgICAgIHZub2RlLmNoaWxkcmVuID0gW107XG4gICAgICB2bm9kZS5wcm9wcyA9IHt9O1xuICAgICAgdm5vZGUuZG9tID0gbmV3ZG9tIGFzIHVua25vd24gYXMgRG9tRWxlbWVudDtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gIH07XG59XG5cbmNvbnN0IGRpcmVjdGl2ZXM6IERpcmVjdGl2ZXMgPSB7XG4gIFwidi1pZlwiOiBoaWRlRGlyZWN0aXZlKGZhbHNlKSxcbiAgXCJ2LXVubGVzc1wiOiBoaWRlRGlyZWN0aXZlKHRydWUpLFxuICBcInYtZm9yXCI6IChzZXQ6IHVua25vd25bXSwgdm5vZGU6IFZub2RlV2l0aERvbSkgPT4ge1xuICAgIHZub2RlLmNoaWxkcmVuID0gc2V0Lm1hcCh2bm9kZS5jaGlsZHJlblswXSBhcyAodmFsdWU6IHVua25vd24pID0+IEZ1bmN0aW9uKTtcbiAgfSxcbiAgXCJ2LXNob3dcIjogKGJvb2w6IGJvb2xlYW4sIHZub2RlOiBWbm9kZVdpdGhEb20pID0+IHtcbiAgICAodm5vZGUuZG9tIGFzIHVua25vd24gYXMgeyBzdHlsZTogeyBkaXNwbGF5OiBzdHJpbmcgfSB9KS5zdHlsZS5kaXNwbGF5ID0gYm9vbCA/IFwiXCIgOiBcIm5vbmVcIjtcbiAgfSxcbiAgXCJ2LWNsYXNzXCI6IChjbGFzc2VzOiB7IFt4OiBzdHJpbmddOiBib29sZWFuIH0sIHZub2RlOiBWbm9kZVdpdGhEb20pID0+IHtcbiAgICBmb3IgKGxldCBuYW1lIGluIGNsYXNzZXMpIHtcbiAgICAgICh2bm9kZS5kb20gYXMgRG9tRWxlbWVudCkuY2xhc3NMaXN0LnRvZ2dsZShuYW1lLCBjbGFzc2VzW25hbWVdKTtcbiAgICB9XG4gIH0sXG4gIFwidi1odG1sXCI6IChodG1sOiBzdHJpbmcsIHZub2RlOiBWbm9kZVdpdGhEb20pID0+IHtcbiAgICB2bm9kZS5jaGlsZHJlbiA9IFt0cnVzdChodG1sKV07XG4gIH0sXG4gIFwidi1tb2RlbFwiOiAoW21vZGVsLCBwcm9wZXJ0eSwgZXZlbnRdOiBhbnlbXSwgdm5vZGU6IFZub2RlV2l0aERvbSwgb2xkVm5vZGU/OiBWbm9kZVdpdGhEb20pID0+IHtcbiAgICBsZXQgdmFsdWU7XG4gICAgbGV0IGhhbmRsZXI7XG4gICAgaWYgKHZub2RlLm5hbWUgPT09IFwiaW5wdXRcIikge1xuICAgICAgZXZlbnQgPSBldmVudCB8fCBcIm9uaW5wdXRcIjtcbiAgICAgIHN3aXRjaCAodm5vZGUucHJvcHMudHlwZSkge1xuICAgICAgICBjYXNlIFwiY2hlY2tib3hcIjoge1xuICAgICAgICAgIGlmIChBcnJheS5pc0FycmF5KG1vZGVsW3Byb3BlcnR5XSkpIHtcbiAgICAgICAgICAgIGhhbmRsZXIgPSAoZTogRXZlbnQpID0+IHtcbiAgICAgICAgICAgICAgbGV0IHZhbCA9IChlLnRhcmdldCBhcyBEb21FbGVtZW50ICYgUmVjb3JkPHN0cmluZywgYW55PikudmFsdWU7XG4gICAgICAgICAgICAgIGxldCBpZHggPSBtb2RlbFtwcm9wZXJ0eV0uaW5kZXhPZih2YWwpO1xuICAgICAgICAgICAgICBpZiAoaWR4ID09PSAtMSkge1xuICAgICAgICAgICAgICAgIG1vZGVsW3Byb3BlcnR5XS5wdXNoKHZhbCk7XG4gICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgbW9kZWxbcHJvcGVydHldLnNwbGljZShpZHgsIDEpO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgdmFsdWUgPSBtb2RlbFtwcm9wZXJ0eV0uaW5kZXhPZih2bm9kZS5kb20udmFsdWUpICE9PSAtMTtcbiAgICAgICAgICB9IGVsc2UgaWYgKFwidmFsdWVcIiBpbiB2bm9kZS5wcm9wcykge1xuICAgICAgICAgICAgaGFuZGxlciA9ICgpID0+IHtcbiAgICAgICAgICAgICAgaWYgKG1vZGVsW3Byb3BlcnR5XSA9PT0gdm5vZGUucHJvcHMudmFsdWUpIHtcbiAgICAgICAgICAgICAgICBtb2RlbFtwcm9wZXJ0eV0gPSBudWxsO1xuICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIG1vZGVsW3Byb3BlcnR5XSA9IHZub2RlLnByb3BzLnZhbHVlO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgdmFsdWUgPSBtb2RlbFtwcm9wZXJ0eV0gPT09IHZub2RlLnByb3BzLnZhbHVlO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBoYW5kbGVyID0gKCkgPT4gKG1vZGVsW3Byb3BlcnR5XSA9ICFtb2RlbFtwcm9wZXJ0eV0pO1xuICAgICAgICAgICAgdmFsdWUgPSBtb2RlbFtwcm9wZXJ0eV07XG4gICAgICAgICAgfVxuICAgICAgICAgIHNldEF0dHJpYnV0ZShcImNoZWNrZWRcIiwgdmFsdWUsIHZub2RlLCBvbGRWbm9kZSk7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICAgICAgY2FzZSBcInJhZGlvXCI6IHtcbiAgICAgICAgICBzZXRBdHRyaWJ1dGUoXCJjaGVja2VkXCIsIG1vZGVsW3Byb3BlcnR5XSA9PT0gdm5vZGUuZG9tLnZhbHVlLCB2bm9kZSwgb2xkVm5vZGUpO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgICAgIGRlZmF1bHQ6IHtcbiAgICAgICAgICBzZXRBdHRyaWJ1dGUoXCJ2YWx1ZVwiLCBtb2RlbFtwcm9wZXJ0eV0sIHZub2RlLCBvbGRWbm9kZSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9IGVsc2UgaWYgKHZub2RlLm5hbWUgPT09IFwic2VsZWN0XCIpIHtcbiAgICAgIGV2ZW50ID0gZXZlbnQgfHwgXCJvbmNsaWNrXCI7XG4gICAgICBpZiAodm5vZGUucHJvcHMubXVsdGlwbGUpIHtcbiAgICAgICAgaGFuZGxlciA9IChlOiBFdmVudCAmIFJlY29yZDxzdHJpbmcsIGFueT4pID0+IHtcbiAgICAgICAgICBsZXQgdmFsID0gKGUudGFyZ2V0IGFzIERvbUVsZW1lbnQgJiBSZWNvcmQ8c3RyaW5nLCBhbnk+KS52YWx1ZTtcbiAgICAgICAgICBpZiAoZS5jdHJsS2V5KSB7XG4gICAgICAgICAgICBsZXQgaWR4ID0gbW9kZWxbcHJvcGVydHldLmluZGV4T2YodmFsKTtcbiAgICAgICAgICAgIGlmIChpZHggPT09IC0xKSB7XG4gICAgICAgICAgICAgIG1vZGVsW3Byb3BlcnR5XS5wdXNoKHZhbCk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICBtb2RlbFtwcm9wZXJ0eV0uc3BsaWNlKGlkeCwgMSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIG1vZGVsW3Byb3BlcnR5XS5zcGxpY2UoMCwgbW9kZWxbcHJvcGVydHldLmxlbmd0aCk7XG4gICAgICAgICAgICBtb2RlbFtwcm9wZXJ0eV0ucHVzaCh2YWwpO1xuICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgdm5vZGUuY2hpbGRyZW4uZm9yRWFjaCgoY2hpbGQ6IElWbm9kZSkgPT4ge1xuICAgICAgICAgIGlmIChjaGlsZC50YWcgPT09IFwib3B0aW9uXCIpIHtcbiAgICAgICAgICAgIGxldCB2YWx1ZSA9IFwidmFsdWVcIiBpbiBjaGlsZC5wcm9wcyA/IGNoaWxkLnByb3BzLnZhbHVlIDogY2hpbGQuY2hpbGRyZW4uam9pbihcIlwiKS50cmltKCk7XG4gICAgICAgICAgICBjaGlsZC5wcm9wcy5zZWxlY3RlZCA9IG1vZGVsW3Byb3BlcnR5XS5pbmRleE9mKHZhbHVlKSAhPT0gLTE7XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHZub2RlLmNoaWxkcmVuLmZvckVhY2goKGNoaWxkOiBJVm5vZGUpID0+IHtcbiAgICAgICAgICBpZiAoY2hpbGQudGFnID09PSBcIm9wdGlvblwiKSB7XG4gICAgICAgICAgICBsZXQgdmFsdWUgPSBcInZhbHVlXCIgaW4gY2hpbGQucHJvcHMgPyBjaGlsZC5wcm9wcy52YWx1ZSA6IGNoaWxkLmNoaWxkcmVuLmpvaW4oXCJcIikudHJpbSgpO1xuICAgICAgICAgICAgY2hpbGQucHJvcHMuc2VsZWN0ZWQgPSB2YWx1ZSA9PT0gbW9kZWxbcHJvcGVydHldO1xuICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgfSBlbHNlIGlmICh2bm9kZS5uYW1lID09PSBcInRleHRhcmVhXCIpIHtcbiAgICAgIGV2ZW50ID0gZXZlbnQgfHwgXCJvbmlucHV0XCI7XG4gICAgICB2bm9kZS5jaGlsZHJlbiA9IFttb2RlbFtwcm9wZXJ0eV1dO1xuICAgIH1cblxuICAgIGlmICghdm5vZGUucHJvcHNbZXZlbnRdKSB7XG4gICAgICBpZiAoIWhhbmRsZXIpIHtcbiAgICAgICAgaGFuZGxlciA9IChlOiBFdmVudCkgPT4gKG1vZGVsW3Byb3BlcnR5XSA9IChlLnRhcmdldCBhcyBEb21FbGVtZW50ICYgUmVjb3JkPHN0cmluZywgYW55PikudmFsdWUpO1xuICAgICAgfVxuICAgICAgc2V0QXR0cmlidXRlKGV2ZW50LCBoYW5kbGVyLCB2bm9kZSwgb2xkVm5vZGUpO1xuICAgIH1cbiAgfVxufTtcblxuLyoqKiBQbHVnaW5zICoqKi9cbmNvbnN0IHBsdWdpbnMgPSBuZXcgTWFwPFBsdWdpbiwgYW55PigpO1xuXG5leHBvcnQgZnVuY3Rpb24gdXNlKHBsdWdpbjogUGx1Z2luLCBvcHRpb25zPzogUmVjb3JkPHN0cmluZyB8IG51bWJlciB8IHN5bWJvbCwgYW55Pik6IHZvaWQgfCBhbnkge1xuICBpZiAocGx1Z2lucy5oYXMocGx1Z2luKSkge1xuICAgIHJldHVybiBwbHVnaW5zLmdldChwbHVnaW4pO1xuICB9XG5cbiAgbGV0IHJlc3VsdCA9IHBsdWdpbih2LCBvcHRpb25zKTtcbiAgcGx1Z2lucy5zZXQocGx1Z2luLCByZXN1bHQpO1xuICByZXR1cm4gcmVzdWx0O1xufVxuXG4vKioqIEh5cGVyc2NyaXB0ICoqKi9cblxuZXhwb3J0IGNvbnN0IHY6IFZhbHlyaWFuID0gZnVuY3Rpb24gdih0YWdPckNvbXBvbmVudDogc3RyaW5nIHwgVmFseXJpYW5Db21wb25lbnQsIHByb3BzOiBQcm9wcywgLi4uY2hpbGRyZW46IENoaWxkcmVuKTogSVZub2RlIHwgVm5vZGVDb21wb25lbnQge1xuICBpZiAodHlwZW9mIHRhZ09yQ29tcG9uZW50ID09PSBcInN0cmluZ1wiKSB7XG4gICAgcmV0dXJuIG5ldyBWbm9kZSh0YWdPckNvbXBvbmVudCwgcHJvcHMgfHwge30sIGNoaWxkcmVuKTtcbiAgfVxuXG4gIGNvbnN0IHZub2RlID0gbmV3IFZub2RlKFwiX19jb21wb25lbnRfX1wiLCBwcm9wcyB8fCB7fSwgY2hpbGRyZW4pO1xuICB2bm9kZS5jb21wb25lbnQgPSB0YWdPckNvbXBvbmVudDtcbiAgcmV0dXJuIHZub2RlIGFzIFZub2RlQ29tcG9uZW50O1xufTtcblxudi5mcmFnbWVudCA9IChwcm9wczogUHJvcHMsIC4uLmNoaWxkcmVuOiBDaGlsZHJlbik6IENoaWxkcmVuID0+IHtcbiAgcmV0dXJuIGNoaWxkcmVuO1xufTtcblxuLyoqKiBWIHByb3BlcnRpZXMgYW5kIG1ldGhvZHMgKioqL1xuLy8gVGhpcyBpcyBpbnRlbmRlZCB0byBtYWtlIHRoZSBwcm9wZXJ0aWVzIGFuZCBtZXRob2RzIGF2YWlsYWJsZSBmb3IgcGx1Z2luc1xudi5jdXJyZW50ID0gY3VycmVudDtcblxudi5kaXJlY3RpdmVzID0gZGlyZWN0aXZlcztcblxudi5yZXNlcnZlZFByb3BzID0gcmVzZXJ2ZWRQcm9wcztcblxudi5pc1Zub2RlID0gaXNWbm9kZTtcbnYuaXNDb21wb25lbnQgPSBpc0NvbXBvbmVudDtcbnYuaXNWbm9kZUNvbXBvbmVudCA9IGlzVm5vZGVDb21wb25lbnQ7XG5cbnYuaXNOb2RlSnMgPSBpc05vZGVKcztcbnYudHJ1c3QgPSB0cnVzdDtcblxudi5vbkNsZWFudXAgPSBvbkNsZWFudXA7XG52Lm9uVW5tb3VudCA9IG9uVW5tb3VudDtcbnYub25Nb3VudCA9IG9uTW91bnQ7XG52Lm9uVXBkYXRlID0gb25VcGRhdGU7XG5cbnYubW91bnQgPSBtb3VudDtcbnYudW5tb3VudCA9IHVubW91bnQ7XG52LnVwZGF0ZSA9IHVwZGF0ZTtcblxudi5zZXRBdHRyaWJ1dGUgPSBzZXRBdHRyaWJ1dGU7XG52LmRpcmVjdGl2ZSA9IGRpcmVjdGl2ZTtcbnYudXNlID0gdXNlO1xuIl19 \ No newline at end of file From 7d7947c092d77526ceb8093990d5b5dce10e82b1 Mon Sep 17 00:00:00 2001 From: Masquerade Circus Date: Fri, 11 Mar 2022 18:02:08 -0600 Subject: [PATCH 16/19] Update tests and benchmarks --- CHANGELOG.md | 9 +- README.md | 1 - bench/.buffalo-test.json | 2818 +---------------- bench/equalize_arrays.test.js | 263 -- bench/hyperscript-test-.js.bak | 44 - bench/index-old.js | 461 --- ...iterations.test.js => iterations_bench.js} | 0 bench/mount_n_update.test.js.bak | 630 ---- bench/mount_n_update_bench.js | 16 +- dist/@types/lib/index.d.ts | 20 +- dist/@types/lib/interfaces.d.ts | 1 + dist/index.cjs | 16 - dist/index.js | 16 - dist/index.min.js | 2 +- dist/index.min.js.map | 2 +- lib/index.ts | 40 +- package.json | 7 +- plugins/node.js | 9 +- plugins/store.js | 10 +- test/directives_test.js | 3 +- test/hooks_test.js | 3 +- test/hyperscript_test.js | 5 +- test/keyed_test.js | 3 +- test/lifecycle_test.js | 5 +- test/mount_n_update_test.js | 3 +- test/request_test.js | 5 +- test/router_test.js | 4 +- test/signals_test.js | 5 +- test/store_test.js | 5 +- tsconfig.json | 5 +- types/lib/index.d.ts | 103 - yarn.lock | 44 +- 32 files changed, 241 insertions(+), 4317 deletions(-) delete mode 100644 bench/equalize_arrays.test.js delete mode 100644 bench/hyperscript-test-.js.bak delete mode 100644 bench/index-old.js rename bench/{iterations.test.js => iterations_bench.js} (100%) delete mode 100644 bench/mount_n_update.test.js.bak delete mode 100644 types/lib/index.d.ts diff --git a/CHANGELOG.md b/CHANGELOG.md index 7606e07..1976c72 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,19 +1,16 @@ ### [5.0.17](https://github.com/Masquerade-Circus/valyrian.js/compare/5.0.16...5.0.17) (2021-12-17) - ### Performance Improvements -* **lib:** small performance improvements ([8f1ae1e](https://github.com/Masquerade-Circus/valyrian.js/commit/8f1ae1ed31d6fade49775f76180d4f480838e513)) - +* **lib:** small performance improvements ([8f1ae1e](https://github.com/Masquerade-Circus/valyrian.js/commit/8f1ae1ed31d6fade49775f76180d4f480838e513)) ### Tests -* update benchmarks ([eb403de](https://github.com/Masquerade-Circus/valyrian.js/commit/eb403de31678765d0b7d8dfce6add04a38ffd3dd)) - +* update benchmarks ([eb403de](https://github.com/Masquerade-Circus/valyrian.js/commit/eb403de31678765d0b7d8dfce6add04a38ffd3dd)) ### Build System -* update dependencies ([5c97e8d](https://github.com/Masquerade-Circus/valyrian.js/commit/5c97e8d83a73d1d864530e3357e7a4e6ca5c9212)) +* update dependencies ([5c97e8d](https://github.com/Masquerade-Circus/valyrian.js/commit/5c97e8d83a73d1d864530e3357e7a4e6ca5c9212)) ### [5.0.16](https://github.com/Masquerade-Circus/valyrian.js/compare/5.0.15...5.0.16) (2021-08-04) diff --git a/README.md b/README.md index 2bfebae..aab9613 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,6 @@ ![](https://img.shields.io/github/issues/masquerade-circus/valyrian.js.svg) ![](https://img.shields.io/snyk/vulnerabilities/npm/valyrian.js.svg) [![Codacy Badge](https://api.codacy.com/project/badge/Grade/521f72fc6d61426783692b62d64a3643)](https://www.codacy.com/app/Masquerade-Circus/valyrian.js?utm_source=github.com\&utm_medium=referral\&utm_content=Masquerade-Circus/valyrian.js\&utm_campaign=Badge_Grade) -[![Maintainability](https://api.codeclimate.com/v1/badges/c1263dd7fb4f90194625/maintainability)](https://codeclimate.com/github/Masquerade-Circus/valyrian.js/maintainability) [![Coverage Status](https://coveralls.io/repos/github/Masquerade-Circus/valyrian.js/badge.svg?branch=master)](https://coveralls.io/github/Masquerade-Circus/valyrian.js?branch=master) [![License](https://img.shields.io/github/license/masquerade-circus/valyrian.js.svg)](https://github.com/masquerade-circus/valyrian.js/blob/master/LICENSE) diff --git a/bench/.buffalo-test.json b/bench/.buffalo-test.json index 114d896..7a0cf40 100644 --- a/bench/.buffalo-test.json +++ b/bench/.buffalo-test.json @@ -1,44 +1,24 @@ [ { - "tag": "5020819ecd7d6f03e2e3b5bb7599df97963194f2", - "timestamp": "2022-02-19T02:32:51.142Z", + "tag": "cc572c7a35f8702f51103a2c6bbf4c0ba8a2d49d", + "timestamp": "2022-03-11T15:30:14.026Z", "suites": { - "Matching keyed list": { - "Removed at the end": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "Matching keyed list -> stress": { - "Removed at the end": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, "hyperscript": { "Valyrian 5.0.8": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 + "hz": 1080326.7077752561, + "meanTime": 0.0009256459113737224, + "medianTime": 0.000880001112818718, + "standardDeviation": 0.0019245132562002675, + "maxTime": 1.0293420013040304, + "minTime": 0.0008110012859106064 }, "Valyrian next": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 + "hz": 16115471.232596528, + "meanTime": 0.0000620521724476362, + "medianTime": 0.00005799904465675354, + "standardDeviation": 0.0003135987904997287, + "maxTime": 0.38400099985301495, + "minTime": 0.000048998743295669556 } }, "Set.has vs [].indexOf": { @@ -301,2700 +281,218 @@ }, "Mount and update: Mount multiple types": { "Valyrian 5.0.8": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 + "hz": 231.12463957243787, + "meanTime": 4.326669808333374, + "medianTime": 3.8601179998368025, + "standardDeviation": 0.9841018665650515, + "maxTime": 16.50512699969113, + "minTime": 3.4267710000276566 }, "Valyrian next": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 + "hz": 190.72752224077007, + "meanTime": 5.243081796750984, + "medianTime": 4.557700000703335, + "standardDeviation": 1.4485380371450673, + "maxTime": 21.492678999900818, + "minTime": 4.197591999545693 } }, "Mount and update: Mount single text": { "Valyrian 5.0.8": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 + "hz": 308291.664552809, + "meanTime": 0.0032436816008325924, + "medianTime": 0.002925001084804535, + "standardDeviation": 0.009799869368766293, + "maxTime": 2.0299989990890026, + "minTime": 0.002689000219106674 }, "Valyrian next": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 + "hz": 991469.4670056179, + "meanTime": 0.0010086039290954118, + "medianTime": 0.0008969996124505997, + "standardDeviation": 0.004353378616590844, + "maxTime": 1.675339998677373, + "minTime": 0.0007819999009370804 } }, "Mount and update: Mount single text in div": { "Valyrian 5.0.8": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 + "hz": 230963.46085280567, + "meanTime": 0.0043296891911284, + "medianTime": 0.004048001021146774, + "standardDeviation": 0.007079474560488834, + "maxTime": 0.8394400011748075, + "minTime": 0.0038300007581710815 }, "Valyrian next": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 + "hz": 622554.7973912942, + "meanTime": 0.0016062843049163274, + "medianTime": 0.0014120005071163177, + "standardDeviation": 0.007555544120265702, + "maxTime": 4.195627000182867, + "minTime": 0.001238001510500908 } }, "Mount and update: Update multiple types": { "Valyrian 5.0.8": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 + "hz": 137.8959353535325, + "meanTime": 7.251845367568209, + "medianTime": 6.874644000083208, + "standardDeviation": 1.056586388734975, + "maxTime": 28.21982100047171, + "minTime": 6.408681999891996 }, "Valyrian next": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 + "hz": 84.54008104717887, + "meanTime": 11.828708792483118, + "medianTime": 11.467360999435186, + "standardDeviation": 1.1468001569640918, + "maxTime": 25.269207000732422, + "minTime": 10.522560000419617 } }, "Mount and update: Update single text": { "Valyrian 5.0.8": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 + "hz": 120376.38304877312, + "meanTime": 0.00830727734687649, + "medianTime": 0.007910998538136482, + "standardDeviation": 0.007917335864379938, + "maxTime": 2.3376929983496666, + "minTime": 0.007453998550772667 }, "Valyrian next": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 + "hz": 587749.2525940249, + "meanTime": 0.0017014058215923048, + "medianTime": 0.0014800000935792923, + "standardDeviation": 0.006738557866547813, + "maxTime": 0.9990600012242794, + "minTime": 0.001343999058008194 } }, "Mount and update: Render list": { "vOld": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 + "hz": 8372.462761654158, + "meanTime": 0.11943916962879732, + "medianTime": 0.11290699988603592, + "standardDeviation": 0.040672784902507815, + "maxTime": 2.5568989999592304, + "minTime": 0.10850599966943264 }, "VNext": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 + "hz": 32843.46647722804, + "meanTime": 0.030447455986211087, + "medianTime": 0.027370000258088112, + "standardDeviation": 0.033472306541327115, + "maxTime": 3.8741210009902716, + "minTime": 0.024598998948931694 } }, "Mount and update: Render keyed list": { "vOld": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 + "hz": 3184.865886451974, + "meanTime": 0.3139849637794409, + "medianTime": 0.29534799978137016, + "standardDeviation": 0.11912784123862281, + "maxTime": 3.687518000602722, + "minTime": 0.26649999991059303 }, "VNext": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 + "hz": 9117.675382791396, + "meanTime": 0.10967707864302664, + "medianTime": 0.0962739996612072, + "standardDeviation": 0.09252007605668011, + "maxTime": 3.1177280005067587, + "minTime": 0.08741600066423416 } }, "Mount and update: Render keyed list -> stress": { "vOld": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 + "hz": 1710.918236731253, + "meanTime": 0.5844814664612624, + "medianTime": 0.5567669998854399, + "standardDeviation": 0.19120539283918606, + "maxTime": 2.271033000200987, + "minTime": 0.49701100029051304 }, "VNext": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 + "hz": 4725.658694760313, + "meanTime": 0.21161071177416468, + "medianTime": 0.1804379988461733, + "standardDeviation": 0.3219729930676698, + "maxTime": 46.89825800061226, + "minTime": 0.16306399926543236 } }, "Mount and update: Render keyed list -> swap keys on large set": { "vOld": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 + "hz": 310.0796208804964, + "meanTime": 3.2249781432279176, + "medianTime": 2.9686950016766787, + "standardDeviation": 1.007842372830396, + "maxTime": 20.209640000015497, + "minTime": 2.839145001024008 }, "VNext": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 + "hz": 781.1533956129919, + "meanTime": 1.2801582962015718, + "medianTime": 1.1108550000935793, + "standardDeviation": 0.709011674133977, + "maxTime": 22.38246599957347, + "minTime": 0.9737960007041693 } }, "Mount and update: Update class": { "vOld update": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 + "hz": 982.8274054593915, + "meanTime": 1.0174726451920433, + "medianTime": 0.9915020000189543, + "standardDeviation": 0.1735599056885286, + "maxTime": 5.256726000458002, + "minTime": 0.8852149993181229 }, "VNext update": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 + "hz": 4136.14385283788, + "meanTime": 0.24177108813898787, + "medianTime": 0.2136400006711483, + "standardDeviation": 0.14183725449488108, + "maxTime": 5.079613000154495, + "minTime": 0.18483399972319603 } }, "Mount and update: Update class with hooks vs shouldupdate property": { "shouldupdate property": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 + "hz": 4305.22836471938, + "meanTime": 0.23227571577731654, + "medianTime": 0.20516799949109554, + "standardDeviation": 0.1395912633754471, + "maxTime": 4.750409999862313, + "minTime": 0.178294001147151 }, "useMemo hook": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "Lifecycle vs hooks": { - "Hooks": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "Lifecycle": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - } - } - }, - { - "tag": "755645ed54c82d26f1cb848803cf642500af032a", - "timestamp": "2022-02-18T21:56:17.184Z", - "suites": { - "Matching keyed list": { - "Removed at the end": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "Matching keyed list -> stress": { - "Removed at the end": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "hyperscript": { - "Valyrian 5.0.8": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "Valyrian next": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "Set.has vs [].indexOf": { - "Set.has": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "[].indexOf": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "Object.keys for loop vs Object.keys for of vs for in": { - "Object.keys for loop": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "Object.keys for of": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "for in": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "typeof function vs startsWith vs charAt vs string[0]": { - "typeof function": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "startsWith": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "charAt": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "string[0]": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "Array.isArray vs typeof object & Array.isArray": { - "Array.isArray": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "typeof object & Array.isArray": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "string comparison vs instance comparison vs property comparison": { - "string comparison": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "instance comparison": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "property comparison": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "property string comparison": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "typeof comparison": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "Object with property equals true vs set vs map vs string array": { - "Object with property equals true": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "key in object": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "set": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "map": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "string array": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "For loop if/continue vs if/else": { - "for loop if/continue": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "for loop if/else": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "map array of strings vs reduce with object keys equals index": { - "map array of strings": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "reduce with object keys equals index": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "array by for": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "object by for": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "object map by for": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "Symbol access vs direct access": { - "Direct access access": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "Symbol access access": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "Mount and update: Mount multiple types": { - "Valyrian 5.0.8": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "Valyrian next": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "Mount and update: Mount single text": { - "Valyrian 5.0.8": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "Valyrian next": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "Mount and update: Mount single text in div": { - "Valyrian 5.0.8": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "Valyrian next": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "Mount and update: Update multiple types": { - "Valyrian 5.0.8": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "Valyrian next": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "Mount and update: Update single text": { - "Valyrian 5.0.8": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "Valyrian next": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "Mount and update: Render list": { - "vOld": { - "hz": 8700.091887036857, - "meanTime": 0.11494131475668673, - "medianTime": 0.10851800069212914, - "standardDeviation": 0.06136097328472064, - "maxTime": 9.930821999907494, - "minTime": 0.10422899946570396 - }, - "VNext": { - "hz": 37589.16774011621, - "meanTime": 0.026603408910614745, - "medianTime": 0.024797998368740082, - "standardDeviation": 0.017901167663638386, - "maxTime": 3.530186999589205, - "minTime": 0.02287200093269348 - } - }, - "Mount and update: Render keyed list": { - "vOld": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "VNext": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "Mount and update: Render keyed list -> stress": { - "vOld": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "VNext": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "Mount and update: Render keyed list -> swap keys on large set": { - "vOld": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "VNext": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "Mount and update: Update class": { - "vOld update": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "VNext update": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "Lifecycle vs hooks": { - "Hooks": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "Lifecycle": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - } - } - }, - { - "tag": "8ee2c0b01c5ff0e70587dc197617db13018d6b4b", - "timestamp": "2022-02-18T17:56:28.277Z", - "suites": { - "Matching keyed list": { - "Removed at the end": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "Matching keyed list -> stress": { - "Removed at the end": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "hyperscript": { - "Valyrian 5.0.8": { - "hz": 15826318.698386787, - "meanTime": 0.00006318588795396445, - "medianTime": 0.00005600042641162872, - "standardDeviation": 0.00041938183081103626, - "maxTime": 0.6461410000920296, - "minTime": 0.000048998743295669556 - }, - "Valyrian next": { - "hz": 15979429.301208284, - "meanTime": 0.00006258045773414354, - "medianTime": 0.000058999285101890564, - "standardDeviation": 0.00029970880865018906, - "maxTime": 0.43538499996066093, - "minTime": 0.000048998743295669556 - } - }, - "Set.has vs [].indexOf": { - "Set.has": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "[].indexOf": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "Object.keys for loop vs Object.keys for of vs for in": { - "Object.keys for loop": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "Object.keys for of": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "for in": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "typeof function vs startsWith vs charAt vs string[0]": { - "typeof function": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "startsWith": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "charAt": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "string[0]": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "Array.isArray vs typeof object & Array.isArray": { - "Array.isArray": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "typeof object & Array.isArray": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "string comparison vs instance comparison vs property comparison": { - "string comparison": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "instance comparison": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "property comparison": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "property string comparison": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "typeof comparison": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "Object with property equals true vs set vs map vs string array": { - "Object with property equals true": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "key in object": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "set": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "map": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "string array": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "For loop if/continue vs if/else": { - "for loop if/continue": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "for loop if/else": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "map array of strings vs reduce with object keys equals index": { - "map array of strings": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "reduce with object keys equals index": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "array by for": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "object by for": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "object map by for": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "Symbol access vs direct access": { - "Direct access access": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "Symbol access access": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "Mount and update: Mount multiple types": { - "Valyrian 5.0.8": { - "hz": 149820.98145979192, - "meanTime": 0.006674632553173963, - "medianTime": 0.006341999396681786, - "standardDeviation": 0.004890587577619386, - "maxTime": 0.9418930001556873, - "minTime": 0.006046999245882034 - }, - "Valyrian next": { - "hz": 219.64299441340884, - "meanTime": 4.552842683057828, - "medianTime": 3.944251000881195, - "standardDeviation": 1.0526752445177507, - "maxTime": 15.64694899879396, - "minTime": 3.682345001026988 - } - }, - "Mount and update: Mount single text": { - "Valyrian 5.0.8": { - "hz": 1274748.8365707635, - "meanTime": 0.0007844682586180091, - "medianTime": 0.0006980001926422119, - "standardDeviation": 0.0036275670281757278, - "maxTime": 0.9234349988400936, - "minTime": 0.0006140004843473434 - }, - "Valyrian next": { - "hz": 1030333.0270050403, - "meanTime": 0.0009705599779779825, - "medianTime": 0.0008430015295743942, - "standardDeviation": 0.004477517876345002, - "maxTime": 1.7103610001504421, - "minTime": 0.0007469989359378815 - } - }, - "Mount and update: Mount single text in div": { - "Valyrian 5.0.8": { - "hz": 743806.3525947747, - "meanTime": 0.0013444359496413167, - "medianTime": 0.001202000305056572, - "standardDeviation": 0.006539302106062292, - "maxTime": 2.5767620000988245, - "minTime": 0.001058001071214676 - }, - "Valyrian next": { - "hz": 637604.4110100463, - "meanTime": 0.0015683705801468237, - "medianTime": 0.001338999718427658, - "standardDeviation": 0.007384922171649113, - "maxTime": 0.7896369993686676, - "minTime": 0.001166999340057373 - } - }, - "Mount and update: Update multiple types": { - "Valyrian 5.0.8": { - "hz": 64423.19587500971, - "meanTime": 0.015522359398936746, - "medianTime": 0.014667998999357224, - "standardDeviation": 0.012813584170645464, - "maxTime": 1.7863989993929863, - "minTime": 0.01405400037765503 - }, - "Valyrian next": { - "hz": 89.96917279162383, - "meanTime": 11.114918243341906, - "medianTime": 10.660915000364184, - "standardDeviation": 1.1566958434652994, - "maxTime": 24.305686999112368, - "minTime": 10.167387999594212 - } - }, - "Mount and update: Update single text": { - "Valyrian 5.0.8": { - "hz": 514879.7401684514, - "meanTime": 0.001942201104422624, - "medianTime": 0.0017949994653463364, - "standardDeviation": 0.00574504795924177, - "maxTime": 2.413348000496626, - "minTime": 0.001687999814748764 - }, - "Valyrian next": { - "hz": 580988.2352304558, - "meanTime": 0.0017212052488521361, - "medianTime": 0.0014730002731084824, - "standardDeviation": 0.011352834819472118, - "maxTime": 11.02280700020492, - "minTime": 0.0013829991221427917 - } - }, - "Mount and update: Render list": { - "vOld": { - "hz": 31094.44763656415, - "meanTime": 0.032160082458711825, - "medianTime": 0.029333001002669334, - "standardDeviation": 0.029701970732171276, - "maxTime": 2.286031000316143, - "minTime": 0.028245000168681145 - }, - "VNext": { - "hz": 32169.03522978382, - "meanTime": 0.031085793927514066, - "medianTime": 0.027785999700427055, - "standardDeviation": 0.030112827696981346, - "maxTime": 2.3631319999694824, - "minTime": 0.025744998827576637 - } - }, - "Mount and update: Render keyed list": { - "vOld": { - "hz": 8121.695124710499, - "meanTime": 0.12312700546434822, - "medianTime": 0.10807999968528748, - "standardDeviation": 0.09909183315302132, - "maxTime": 4.288349000737071, - "minTime": 0.10346500016748905 - }, - "VNext": { - "hz": 9303.114026787878, - "meanTime": 0.10749088930013617, - "medianTime": 0.0928729996085167, - "standardDeviation": 0.2119213107791509, - "maxTime": 41.89445700123906, - "minTime": 0.0864850003272295 - } - }, - "Mount and update: Render keyed list -> stress": { - "vOld": { - "hz": 4290.273506833652, - "meanTime": 0.23308537285727252, - "medianTime": 0.20196899957954884, - "standardDeviation": 0.1631035158995494, - "maxTime": 2.762967998161912, - "minTime": 0.19378499872982502 - }, - "VNext": { - "hz": 4795.642477616159, - "meanTime": 0.20852263375919647, - "medianTime": 0.18345599994063377, - "standardDeviation": 0.23749080001876208, - "maxTime": 29.148431001231074, - "minTime": 0.1677969992160797 - } - }, - "Mount and update: Render keyed list -> swap keys on large set": { - "vOld": { - "hz": 742.0811925014037, - "meanTime": 1.347561439509341, - "medianTime": 1.1005080007016659, - "standardDeviation": 0.6366548325131208, - "maxTime": 5.304254999384284, - "minTime": 0.9995709992945194 - }, - "VNext": { - "hz": 802.2642801718677, - "meanTime": 1.2464720475723683, - "medianTime": 1.0820850003510714, - "standardDeviation": 0.6140147044979994, - "maxTime": 27.181886000558734, - "minTime": 0.9548999983817339 - } - }, - "Mount and update: Update class": { - "vOld update": { - "hz": 1229456.450397081, - "meanTime": 0.0008133675655425023, - "medianTime": 0.0007619988173246384, - "standardDeviation": 0.004122510886838122, - "maxTime": 5.169614000245929, - "minTime": 0.0007060002535581589 - }, - "VNext update": { - "hz": 13965456.945974354, - "meanTime": 0.00007160524742359091, - "medianTime": 0.00006899982690811157, - "standardDeviation": 0.0004713339294665467, - "maxTime": 0.8383689988404512, - "minTime": 0.00005499832332134247 - } - }, - "Lifecycle vs hooks": { - "Hooks": { - "hz": 361475.5865528843, - "meanTime": 0.002766438556850364, - "medianTime": 0.002394000068306923, - "standardDeviation": 0.011011801340114655, - "maxTime": 2.7585150003433228, - "minTime": 0.002167999744415283 - }, - "Lifecycle": { - "hz": 366956.53041034855, - "meanTime": 0.0027251184190175103, - "medianTime": 0.0022840015590190887, - "standardDeviation": 0.02169705587130068, - "maxTime": 19.725862000137568, - "minTime": 0.002002999186515808 - } - } - } - }, - { - "tag": "fa8448f9349a5415dd52b8495f9692db63ee3bbf", - "timestamp": "2022-02-17T21:36:15.314Z", - "suites": { - "Matching keyed list": { - "Removed at the end": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "Matching keyed list -> stress": { - "Removed at the end": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "hyperscript": { - "Valyrian 5.0.8": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "Valyrian next": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "Set.has vs [].indexOf": { - "Set.has": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "[].indexOf": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "Object.keys for loop vs Object.keys for of vs for in": { - "Object.keys for loop": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "Object.keys for of": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "for in": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "typeof function vs startsWith vs charAt vs string[0]": { - "typeof function": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "startsWith": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "charAt": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "string[0]": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "Array.isArray vs typeof object & Array.isArray": { - "Array.isArray": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "typeof object & Array.isArray": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "string comparison vs instance comparison vs property comparison": { - "string comparison": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "instance comparison": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "property comparison": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "property string comparison": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "typeof comparison": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "Object with property equals true vs set vs map vs string array": { - "Object with property equals true": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "key in object": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "set": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "map": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "string array": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "For loop if/continue vs if/else": { - "for loop if/continue": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "for loop if/else": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "map array of strings vs reduce with object keys equals index": { - "map array of strings": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "reduce with object keys equals index": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "array by for": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "object by for": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "object map by for": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "Symbol access vs direct access": { - "Direct access access": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "Symbol access access": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "Mount and update: Mount multiple types": { - "Valyrian 5.0.8": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "Valyrian next": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "Mount and update: Mount single text": { - "Valyrian 5.0.8": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "Valyrian next": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "Mount and update: Mount single text in div": { - "Valyrian 5.0.8": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "Valyrian next": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "Mount and update: Update multiple types": { - "Valyrian 5.0.8": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "Valyrian next": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "Mount and update: Update single text": { - "Valyrian 5.0.8": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "Valyrian next": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "Mount and update: Render list": { - "vOld": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "VNext": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "Mount and update: Render keyed list": { - "vOld": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "VNext": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "Mount and update: Render keyed list -> stress": { - "vOld": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "VNext": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "Mount and update: Render keyed list -> swap keys on large set": { - "vOld": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "VNext": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "Mount and update: Update class": { - "vOld update": { - "hz": 343839.9611446381, - "meanTime": 0.002908329784214188, - "medianTime": 0.0027740001678466797, - "standardDeviation": 0.003164911735255947, - "maxTime": 1.486952000297606, - "minTime": 0.0026079993695020676 - }, - "VNext update": { - "hz": 15151981.639382496, - "meanTime": 0.00006599796804141019, - "medianTime": 0.00006200000643730164, - "standardDeviation": 0.0003279280705585636, - "maxTime": 0.3116029994562268, - "minTime": 0.000045999884605407715 - } - }, - "Lifecycle vs hooks": { - "Hooks": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "Lifecycle": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - } - } - }, - { - "tag": null, - "timestamp": "2022-02-17T15:26:02.135Z", - "suites": { - "Matching keyed list": { - "Removed at the end": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "Matching keyed list -> stress": { - "Removed at the end": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "hyperscript": { - "Valyrian 5.0.8": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "Valyrian next": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "Set.has vs [].indexOf": { - "Set.has": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "[].indexOf": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "Object.keys for loop vs Object.keys for of vs for in": { - "Object.keys for loop": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "Object.keys for of": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "for in": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "typeof function vs startsWith vs charAt vs string[0]": { - "typeof function": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "startsWith": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "charAt": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "string[0]": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "Array.isArray vs typeof object & Array.isArray": { - "Array.isArray": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "typeof object & Array.isArray": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "string comparison vs instance comparison vs property comparison": { - "string comparison": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "instance comparison": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "property comparison": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "property string comparison": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "typeof comparison": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "Object with property equals true vs set vs map vs string array": { - "Object with property equals true": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "key in object": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "set": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "map": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "string array": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "For loop if/continue vs if/else": { - "for loop if/continue": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "for loop if/else": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "map array of strings vs reduce with object keys equals index": { - "map array of strings": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "reduce with object keys equals index": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "array by for": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "object by for": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "object map by for": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "Symbol access vs direct access": { - "Direct access access": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "Symbol access access": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "Mount and update: Mount multiple types": { - "Valyrian 5.0.8": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "Valyrian next": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "Mount and update: Mount single text": { - "Valyrian 5.0.8": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "Valyrian next": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "Mount and update: Mount single text in div": { - "Valyrian 5.0.8": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "Valyrian next": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "Mount and update: Update multiple types": { - "Valyrian 5.0.8": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "Valyrian next": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "Mount and update: Update single text": { - "Valyrian 5.0.8": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "Valyrian next": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "Mount and update: Render list": { - "vOld": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "VNext": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "Mount and update: Render keyed list": { - "vOld": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "VNext": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "Mount and update: Render keyed list -> stress": { - "vOld": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "VNext": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "Mount and update: Render keyed list -> swap keys on large set": { - "vOld": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "VNext": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "Mount and update: Update class": { - "vOld update": { - "hz": 336267.528779135, - "meanTime": 0.002973822669202215, - "medianTime": 0.0028290003538131714, - "standardDeviation": 0.0035730363859830215, - "maxTime": 1.5123089998960495, - "minTime": 0.0026619993150234222 - }, - "VNext update": { - "hz": 1300819.330335408, - "meanTime": 0.0007687462637429875, - "medianTime": 0.0006870003417134285, - "standardDeviation": 0.0037972006213699955, - "maxTime": 1.9422189993783832, - "minTime": 0.0006299996748566628 - } - }, - "Lifecycle vs hooks": { - "Hooks": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "Lifecycle": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - } - } - }, - { - "tag": "342faa488ecfc4dbe4b76e77863c8f675e754329", - "timestamp": "2022-02-17T11:07:35.317Z", - "suites": { - "Matching keyed list": { - "Removed at the end": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "Matching keyed list -> stress": { - "Removed at the end": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "hyperscript": { - "Valyrian 5.0.8": { - "hz": 1085513.3179712752, - "meanTime": 0.000921223151705691, - "medianTime": 0.0008530020713806152, - "standardDeviation": 0.019500465849231124, - "maxTime": 30.582818999886513, - "minTime": 0.0007930099964141846 - }, - "Valyrian next": { - "hz": 15794164.980239976, - "meanTime": 0.00006331452161295621, - "medianTime": 0.00005599856376647949, - "standardDeviation": 0.00031702862230284404, - "maxTime": 0.29975299537181854, - "minTime": 0.000048995018005371094 - } - }, - "Set.has vs [].indexOf": { - "Set.has": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "[].indexOf": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "Object.keys for loop vs Object.keys for of vs for in": { - "Object.keys for loop": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "Object.keys for of": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "for in": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "typeof function vs startsWith vs charAt vs string[0]": { - "typeof function": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "startsWith": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "charAt": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "string[0]": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "Array.isArray vs typeof object & Array.isArray": { - "Array.isArray": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "typeof object & Array.isArray": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "string comparison vs instance comparison vs property comparison": { - "string comparison": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "instance comparison": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "property comparison": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "property string comparison": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "typeof comparison": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "Object with property equals true vs set vs map vs string array": { - "Object with property equals true": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "key in object": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "set": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "map": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "string array": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "For loop if/continue vs if/else": { - "for loop if/continue": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "for loop if/else": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "map array of strings vs reduce with object keys equals index": { - "map array of strings": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "reduce with object keys equals index": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "array by for": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "object by for": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "object map by for": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "Symbol access vs direct access": { - "Direct access access": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - }, - "Symbol access access": { - "hz": 0, - "meanTime": 0, - "medianTime": 0, - "standardDeviation": 0, - "maxTime": 0, - "minTime": 0 - } - }, - "Mount and update: Mount multiple types": { - "Valyrian 5.0.8": { - "hz": 260.633209072662, - "meanTime": 3.83680960518431, - "medianTime": 3.3641090095043182, - "standardDeviation": 0.8308150696566404, - "maxTime": 15.718204006552696, - "minTime": 3.1520179957151413 - }, - "Valyrian next": { - "hz": 222.65166867343356, - "meanTime": 4.4913204826087085, - "medianTime": 3.889599993824959, - "standardDeviation": 1.058344812867983, - "maxTime": 16.027059003710747, - "minTime": 3.5659329891204834 - } - }, - "Mount and update: Mount single text": { - "Valyrian 5.0.8": { - "hz": 347427.4290566243, - "meanTime": 0.00287829893775318, - "medianTime": 0.002673998475074768, - "standardDeviation": 0.006783133364727264, - "maxTime": 1.7252160012722015, - "minTime": 0.0024939924478530884 - }, - "Valyrian next": { - "hz": 1223910.384040943, - "meanTime": 0.0008170532851419515, - "medianTime": 0.0007089972496032715, - "standardDeviation": 0.0044411061831852415, - "maxTime": 1.6371040046215057, - "minTime": 0.0005789995193481445 - } - }, - "Mount and update: Mount single text in div": { - "Valyrian 5.0.8": { - "hz": 244343.36900502432, - "meanTime": 0.0040926013424143195, - "medianTime": 0.003850996494293213, - "standardDeviation": 0.005545521371988312, - "maxTime": 0.6497730016708374, - "minTime": 0.003649994730949402 - }, - "Valyrian next": { - "hz": 688361.7972213569, - "meanTime": 0.001452724430723208, - "medianTime": 0.0012419968843460083, - "standardDeviation": 0.007049924359907374, - "maxTime": 0.8489640057086945, - "minTime": 0.0010669976472854614 - } - }, - "Mount and update: Update multiple types": { - "Valyrian 5.0.8": { - "hz": 147.96662836834977, - "meanTime": 6.758280640892815, - "medianTime": 6.411444008350372, - "standardDeviation": 0.9741160663847195, - "maxTime": 24.285806000232697, - "minTime": 6.045272007584572 - }, - "Valyrian next": { - "hz": 88.94506469757148, - "meanTime": 11.242894739580796, - "medianTime": 10.90294100344181, - "standardDeviation": 1.1068453900004576, - "maxTime": 26.234234005212784, - "minTime": 10.178460001945496 - } - }, - "Mount and update: Update single text": { - "Valyrian 5.0.8": { - "hz": 121862.49891824297, - "meanTime": 0.008205969915904119, - "medianTime": 0.007762998342514038, - "standardDeviation": 0.009811824354673024, - "maxTime": 2.545636996626854, - "minTime": 0.007499009370803833 - }, - "Valyrian next": { - "hz": 602961.8000913017, - "meanTime": 0.0016584798570134594, - "medianTime": 0.001458004117012024, - "standardDeviation": 0.006942679619133388, - "maxTime": 1.9876960068941116, - "minTime": 0.0013519972562789917 - } - }, - "Mount and update: Render list": { - "vOld": { - "hz": 8595.287795706112, - "meanTime": 0.1163428175726196, - "medianTime": 0.11025500297546387, - "standardDeviation": 0.03396247127309931, - "maxTime": 2.3573189973831177, - "minTime": 0.10783299803733826 - }, - "VNext": { - "hz": 32325.596447472642, - "meanTime": 0.030935237393838848, - "medianTime": 0.027564987540245056, - "standardDeviation": 0.03658583480612852, - "maxTime": 2.6248089969158173, - "minTime": 0.024625003337860107 - } - }, - "Mount and update: Render keyed list": { - "vOld": { - "hz": 3504.474806096515, - "meanTime": 0.28534946185384547, - "medianTime": 0.27035000920295715, - "standardDeviation": 0.0721601162287672, - "maxTime": 4.122464999556541, - "minTime": 0.2602820098400116 - }, - "VNext": { - "hz": 9998.200945039185, - "meanTime": 0.1000179937867893, - "medianTime": 0.08610399067401886, - "standardDeviation": 0.10939394451753234, - "maxTime": 19.21594300866127, - "minTime": 0.07930800318717957 - } - }, - "Mount and update: Render keyed list -> stress": { - "vOld": { - "hz": 1855.192833444841, - "meanTime": 0.5390275242402354, - "medianTime": 0.5236269980669022, - "standardDeviation": 0.08498791322802589, - "maxTime": 2.095083996653557, - "minTime": 0.4774570018053055 - }, - "VNext": { - "hz": 5438.111021666333, - "meanTime": 0.18388738222074444, - "medianTime": 0.16006000339984894, - "standardDeviation": 0.13763924133347213, - "maxTime": 10.381516993045807, - "minTime": 0.15018099546432495 - } - }, - "Mount and update: Render keyed list -> swap keys on large set": { - "vOld": { - "hz": 328.8444144098936, - "meanTime": 3.0409517576708276, - "medianTime": 2.869830995798111, - "standardDeviation": 0.650294589183712, - "maxTime": 17.199512004852295, - "minTime": 2.7187130004167557 - }, - "VNext": { - "hz": 856.8353339507644, - "meanTime": 1.16708539012872, - "medianTime": 0.9925249963998795, - "standardDeviation": 0.6296643229410056, - "maxTime": 17.963095992803574, - "minTime": 0.8711500018835068 + "hz": 2022.8663221151528, + "meanTime": 0.4943480392487717, + "medianTime": 0.4481320008635521, + "standardDeviation": 0.28033136821875804, + "maxTime": 14.368340998888016, + "minTime": 0.38005900010466576 } }, "Lifecycle vs hooks": { "Hooks": { - "hz": 370117.74095190957, - "meanTime": 0.002701842925519025, - "medianTime": 0.0024130046367645264, - "standardDeviation": 0.00803690626128436, - "maxTime": 4.156716004014015, - "minTime": 0.0020949989557266235 + "hz": 312912.4994451379, + "meanTime": 0.0031957815739966223, + "medianTime": 0.0026869997382164, + "standardDeviation": 0.01864210814178492, + "maxTime": 14.44373599998653, + "minTime": 0.0024319998919963837 }, "Lifecycle": { - "hz": 392517.0967079169, - "meanTime": 0.0025476597284222967, - "medianTime": 0.002181008458137512, - "standardDeviation": 0.010177234514366527, - "maxTime": 1.0994060039520264, - "minTime": 0.001976996660232544 + "hz": 355303.66081815877, + "meanTime": 0.0028144939393455644, + "medianTime": 0.0024609994143247604, + "standardDeviation": 0.010571937974029605, + "maxTime": 1.3473349995911121, + "minTime": 0.0021550003439188004 } } } diff --git a/bench/equalize_arrays.test.js b/bench/equalize_arrays.test.js deleted file mode 100644 index a8827bf..0000000 --- a/bench/equalize_arrays.test.js +++ /dev/null @@ -1,263 +0,0 @@ -/* eslint-disable eqeqeq */ -let { compare, benchmark, before } = require("buffalo-test"); -let expect = require("expect"); - -type Set = number[]; - -type Movement = { - key: number, - currentIndex: number, - indexInNewKeyedListArray: number, - indexInOldKeyedListArray: number, - oldKeyedListBeforeMovement: Set, - oldKeyedListAfterMovement: Set, - newKeyedList: Set -}; - -let getCurrentLineInCode = () => { - let error = new Error(); - let stack = error.stack.split("\n"); - return stack[2]; -}; - -// Para igualar las listas de elementos, -// 1. Se deben mover los elementos de la lista anterior para igualarla a la lista nueva -// 2. Se debe obtener el máximo de longitud de las listas -// 3. Ciclar sobre toda la lista de elementos hasta el máximo de longitud -// 3.1. Si el indice actual es mayor a la longitud de la lista nueva todos los elementos restantes de la lista anterior se deben eliminar -// 3.1.1 Eliminar todos los elementos restantes de la lista anterior -// 3.1.2. Como ya eliminamos todos los elementos restantes entonces ya no necesitamos proseguir más y terminamos el ciclo -// 3.2. Si el indice actual es mayor a la longitud de la lista anterior el nuevo elemento se tiene que agregar -// 3.3. Si el nuevo elemento es diferente al elemento de la lista anterior entonces tenemos una operación de movimiento -// 3.3.1. Debemos tomar el nuevo elemento de la lista nueva en la posición del indice actual -// 3.3.2. Buscar el nuevo elemento en la lista anterior -// 3.3.3. Se debe mover el nuevo elemento a la posición del indice actual -// 3.3.4. Si el nuevo elemento está en la lista nueva, tomarlo (quitarlo) de su posición actual en la lista anterior -// 3.3.5. Buscar el antiguo elemento en la lista nueva para decidir si podemos reemplazarlo o insertar el nuevo elemento antes del antiguo elemento -// 3.3.6. Si el antiguo elemento no está en la lista nueva, eliminarlo de la lista anterior reemplazandolo con el nuevo elemento -// 3.3.7. Si el antiguo elemento está en la lista nueva, se debe mover el nuevo elemento antes del antiguo elemento -// 3.4. Si los elementos son iguales no necesitamos hacer nada - -function matchKeyedList(oldKeyedList: Set, newKeyedList: Set): Movement[] { - // 1. Se deben mover los elementos de la lista anterior para igualarla a la lista nueva - let movements: Movement[] = []; - - // 2. Se debe obtener el máximo de longitud de las listas - const oldListLength = oldKeyedList.length; - const newListLength = newKeyedList.length; - const maxListLength = Math.max(oldListLength, newListLength); - - // 3. Ciclar sobre toda la lista de elementos hasta el máximo de longitud - for (let i = 0; i < maxListLength; i++) { - // 3.1. Si el indice actual es mayor a la longitud de la lista nueva todos los elementos restantes de la lista anterior se deben eliminar - if (i >= newListLength) { - // 3.1.1 Eliminar todos los elementos restantes de la lista anterior - for (let k = oldKeyedList.length - 1; k > newListLength - 1; k--) { - let movement = { - key: k, - currentIndex: k, - indexInNewKeyedListArray: -1, - indexInOldKeyedListArray: k, - oldKeyedListBeforeMovement: [...oldKeyedList], - newKeyedList: newKeyedList, - line: getCurrentLineInCode(), - operation: "remove" - }; - - oldKeyedList.pop(); - movement.oldKeyedListAfterMovement = [...oldKeyedList]; - movements.push(movement); - } - - // 3.1.2. Como ya eliminamos todos los elementos restantes entonces ya no necesitamos proseguir más y terminamos el ciclo - break; - } - - // 3.2. Si el indice actual es mayor a la longitud de la lista anterior el nuevo elemento se tiene que agregar - if (i >= oldKeyedList.length) { - let movement = { - key: newKeyedList[i], - currentIndex: i, - indexInNewKeyedListArray: i, - indexInOldKeyedListArray: -1, - oldKeyedListBeforeMovement: [...oldKeyedList], - newKeyedList: newKeyedList, - operation: "add", - line: getCurrentLineInCode() - }; - - oldKeyedList.push(newKeyedList[i]); - movement.oldKeyedListAfterMovement = [...oldKeyedList]; - movements.push(movement); - - continue; - } - - let newKey = newKeyedList[i]; - let oldKey = oldKeyedList[i]; - - // 3.3. Si el nuevo elemento es diferente al elemento de la lista anterior entonces tenemos una operación de movimiento - if (newKey !== oldKey) { - // 3.3.1. Debemos tomar el nuevo elemento de la lista nueva en la posición del indice actual - // 3.3.2. Buscar el nuevo elemento en la lista anterior - const oldIndex = oldKeyedList.indexOf(newKey); - - let movement = { - key: newKey, - currentIndex: i, - indexInNewKeyedListArray: i, - indexInOldKeyedListArray: oldIndex, - oldKeyedListBeforeMovement: [...oldKeyedList], - newKeyedList: newKeyedList - }; - - // 3.3.3. Si el nuevo elemento está en la lista nueva, tomarlo (quitarlo) de su posición actual en la lista anterior - oldIndex !== -1 && oldKeyedList.splice(oldIndex, 1); - - // 3.3.4. Buscar el antiguo elemento en la lista nueva para decidir si podemos reemplazarlo o insertar el nuevo elemento antes del antiguo elemento - const oldKeyIndexInNewKeyedList = newKeyedList.indexOf(oldKeyedList[i]); - - // 3.3.5. Si el antiguo elemento no está en la lista nueva, eliminarlo de la lista anterior reemplazandolo con el nuevo elemento - if (oldKeyIndexInNewKeyedList === -1) { - movement.line = getCurrentLineInCode(); - movement.operation = "replace"; - oldKeyedList.splice(i, 1, newKey); - movement.oldKeyedListAfterMovement = [...oldKeyedList]; - movements.push(movement); - continue; - } - - // 3.3.6. Si el antiguo elemento está en la lista nueva, se debe mover el nuevo elemento antes del antiguo elemento - movement.line = getCurrentLineInCode(); - movement.operation = "move"; - oldKeyedList.splice(i, oldKeyIndexInNewKeyedList !== i + 1 ? 1 : 0, newKey); - movement.oldKeyedListAfterMovement = [...oldKeyedList]; - movements.push(movement); - - // 3.3.7. if the old element is in the new list then move the old element to the new position - if (oldKeyIndexInNewKeyedList !== i + 1) { - movement = { - key: oldKey, - currentIndex: i, - indexInNewKeyedListArray: oldKeyIndexInNewKeyedList, - indexInOldKeyedListArray: i, - oldKeyedListBeforeMovement: [...oldKeyedList], - newKeyedList: newKeyedList, - line: getCurrentLineInCode(), - operation: "move" - }; - oldKeyedList.splice(oldKeyIndexInNewKeyedList, 0, oldKey); - movement.oldKeyedListAfterMovement = [...oldKeyedList]; - movements.push(movement); - } - } - - // 3.4. Si los elementos son iguales no necesitamos hacer nada - } - return movements; -} - -compare.skip("Matching keyed list", () => { - let set = [1, 2, 3, 4, 5]; - let tests = [ - { name: "Removed at the end", set: [1, 2, 3, 4], movements: 1 }, // Removed at the end - { name: "Removed at the start", set: [2, 3, 4, 5], movements: 1 }, // Remmoved at the start - { name: "Removed at the center", set: [1, 3, 5], movements: 2 }, // Removed at the center - { name: "Added at the end", set: [1, 2, 3, 4, 5, 6], movements: 1 }, // Added at the end - { name: "Added at the start", set: [6, 1, 2, 3, 4, 5], movements: 1 }, // Added at the start - { name: "Added at the center", set: [1, 2, 6, 3, 4, 5], movements: 1 }, // Added at the center - { name: "Reversed", set: [5, 4, 3, 2, 1], movements: 4 }, // Reversed - { name: "Switch positions", set: [5, 2, 3, 4, 1], movements: 2 }, // Switch positions, - { name: "Mixed positions", set: [1, 3, 2, 6, 5, 4], movements: 3 }, - { name: "Replaced with undefined", set: [1, 3, 2, 5, 4], movements: 2 }, - { - name: "Added, remove and replaced with undefined", - set: [6, 7, 8, 9, 10], - movements: 5 - }, - { name: "Removed all at the end", set: [1], movements: 4 } // Removed at the end - ]; - - before(() => { - for (let test of tests) { - test.oldSet = [...set]; - } - - // let oldKeyedList = [3, 6, 4, 8]; - // let newKeyedList = [4, 6, 8, 3]; - // console.log(oldKeyedList); - // console.log(newKeyedList); - // console.log(equalizeArrays([...oldKeyedList], newKeyedList)); - // console.log(calculateMovements([...oldKeyedList], newKeyedList)); - // console.log("-------------------"); - - function logMatchFromTest(test) { - let movements = matchKeyedList([...set], test.set); - console.log(test.name, movements, test.set); - expect(movements[movements.length - 1].oldKeyedListAfterMovement).toEqual(test.set); - expect(movements.length).toEqual(test.movements); - } - - // logMatchFromTest(tests[0]); - for (let test of tests) { - logMatchFromTest(test); - } - }); - - benchmark(tests[0].name, () => { - tests[0].oldSet = set; - }); -}); - -compare.skip("Matching keyed list -> stress", () => { - let set = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; - let tests = [ - { name: "Removed at the end", set: [1, 2, 3, 4, 5, 6, 7, 8, 9], movements: 1 }, // Removed at the end - { name: "Removed at the start", set: [2, 3, 4, 5, 6, 7, 8, 9, 10], movements: 1 }, // Remmoved at the start - { name: "Removed at the center", set: [1, 2, 3, 5, 6, 8, 9, 10], movements: 2 }, // Removed at the center - { name: "Added at the end", set: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11], movements: 1 }, // Added at the end - { name: "Added at the start", set: [11, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10], movements: 1 }, // Added at the start - { name: "Added at the center", set: [1, 2, 3, 4, 5, 11, 6, 7, 8, 9, 10], movements: 1 }, // Added at the center - { name: "Reversed", set: [10, 9, 8, 7, 6, 5, 4, 3, 2, 1], movements: 9 }, // Reversed - { name: "Switch positions", set: [10, 2, 3, 4, 5, 6, 7, 8, 9, 1], movements: 2 }, // Switch positions, - { name: "Switch different positions", set: [10, 6, 3, 4, 2, 5, 7, 8, 9, 1], movements: 4 }, // Switch positions, - { name: "Mixed positions", set: [1, 3, 2, 6, 5, 4, 7, 8, 9, 10], movements: 3 }, - { name: "Replaced with undefined", set: [1, 3, 2, 5, 4, 6, 7, 8, 9, 10], movements: 2 }, - { - name: "Added, remove and replaced with undefined", - set: [11, 12, 13, 14, 15, 16, 17, 18, 19, 20], - movements: 10 - }, - { name: "Removed all at the end", set: [1], movements: 9 } // Removed at the end - ]; - - before(() => { - for (let test of tests) { - test.oldSet = [...set]; - } - - // let oldKeyedList = [3, 6, 4, 8]; - // let newKeyedList = [4, 6, 8, 3]; - // console.log(oldKeyedList); - // console.log(newKeyedList); - // console.log(equalizeArrays([...oldKeyedList], newKeyedList)); - // console.log(calculateMovements([...oldKeyedList], newKeyedList)); - // console.log("-------------------"); - - function logMatchFromTest(test) { - let movements = matchKeyedList([...set], test.set); - console.log(test.name, movements, test.set); - expect(movements[movements.length - 1].oldKeyedListAfterMovement).toEqual(test.set); - expect(movements.length).toEqual(test.movements); - } - - // logMatchFromTest(tests[0]); - for (let test of tests) { - logMatchFromTest(test); - } - }); - - benchmark(tests[0].name, () => { - tests[0].oldSet = set; - }); -}); diff --git a/bench/hyperscript-test-.js.bak b/bench/hyperscript-test-.js.bak deleted file mode 100644 index 71c7a48..0000000 --- a/bench/hyperscript-test-.js.bak +++ /dev/null @@ -1,44 +0,0 @@ -let { compare, benchmark, before } = require("buffalo-test"); - -import "../lib/index.ts"; - -import expect from "expect"; -import fs from "fs"; -import nodePlugin from "../plugins/node.mjs"; -import vOld from "./index-old"; - -let VNext = v; - -VNext.usePlugin(nodePlugin); - -compare("hyperscript", () => { - let date = new Date(); - before(async () => { - VNext.inline.extensions("ts"); - await VNext.inline.ts("./lib/index.ts", { compact: true }); - await VNext.inline.js("./bench/index-old.js", { compact: true }); - console.log(VNext.inline.ts()[0].raw.length); - console.log(VNext.inline.js()[0].raw.length); - - let compiled = fs.readFileSync("./dist/valyrian.min.js", "utf8"); - console.log(compiled.length); - - expect(vOld("div", null, [null, "Hello", , 1, date, { hello: "world" }, ["Hello"]])).toEqual({ - name: "div", - props: {}, - children: [[null, "Hello", undefined, 1, date, { hello: "world" }, ["Hello"]]] - }); - expect(VNext("div", null, [null, "Hello", , 1, date, { hello: "world" }, ["Hello"]])).toEqual({ - name: "div", - props: {}, - children: [[null, "Hello", undefined, 1, date, { hello: "world" }, ["Hello"]]] - }); - }); - - benchmark("Valyrian 5.0.8", () => { - vOld("div", null, [null, "Hello", , 1, date, { hello: "world" }, ["Hello"]]); - }); - benchmark("Valyrian next", () => { - VNext("div", null, [null, "Hello", , 1, date, { hello: "world" }, ["Hello"]]); - }); -}); diff --git a/bench/index-old.js b/bench/index-old.js deleted file mode 100644 index 3fd6915..0000000 --- a/bench/index-old.js +++ /dev/null @@ -1,461 +0,0 @@ -function Vnode(name, props, children) { - this.props = props || {}; - this.children = children; - this.name = name; -} - -function TextVnode(dom) { - this.dom = dom; -} - -function Component(component, props, children) { - this.props = props; - this.children = children; - this.component = component; -} - -function POJOComponent(component, props, children) { - this.props = props; - this.children = children; - this.component = component; -} - -const isArray = Array.isArray; -const UND = void 0; -const emptyNode = new Vnode("empty", null, []); -const createElement = (tag, isSVG = false) => (isSVG ? document.createElementNS("http://www.w3.org/2000/svg", tag) : document.createElement(tag)); - -//eslint-disable-next-line max-lines-per-function -function valyrian() { - let oncreate = "oncreate"; - let onupdate = "onupdate"; - let onremove = "onremove"; - let onbeforeupdate = "onbeforeupdate"; - let functionstr = "function"; - let once = "v-once"; - let mainNode; - let oldMainNode; - let mountedComponent; - let directives = {}; - let mainContainer; - - let lifecycleCall = (vnode, methodName, oldNode) => { - if (vnode.props[methodName]) { - return vnode.props[methodName](vnode, oldNode); - } - }; - - let callRemove = (vnode) => { - if (vnode instanceof Vnode) { - for (let i = 0, l = vnode.children.length; i < l; i++) { - callRemove(vnode.children[i]); - } - - vnode.props[onremove] && vnode.props[onremove](vnode); - } - }; - - function v(tagOrComponent, props, ...children) { - if (typeof tagOrComponent === "string") { - return new Vnode(tagOrComponent, props, children); - } - if ("view" in tagOrComponent) { - return new POJOComponent(tagOrComponent, props, children); - } - return new Component(tagOrComponent, props, children); - } - - // eslint-disable-next-line no-new-func - v.isNode = new Function("try {return this===global;}catch(e){return false;}")(); - - // Hydrates the current dom before mount - v.domToVnode = (dom) => { - if (dom.nodeType === 3) { - return new TextVnode(dom); - } - - if (dom.nodeType === 1) { - let props = {}; - [].forEach.call(dom.attributes, (prop) => (props[prop.nodeName] = prop.nodeValue)); - - let vnode = new Vnode(dom.nodeName, props, []); - vnode.dom = dom; - - for (let i = 0, l = dom.childNodes.length; i < l; i++) { - let childVnode = v.domToVnode(dom.childNodes[i]); - childVnode && vnode.children.push(childVnode); - } - return vnode; - } - }; - - v.trust = (htmlString) => { - let div = createElement("div"); - div.innerHTML = htmlString.trim(); - - return [].map.call(div.childNodes, (item) => v.domToVnode(item)); - }; - - // Plugin system - let plugins = new Map(); - v.usePlugin = (plugin, options) => !plugins.has(plugin) && plugins.set(plugin, true) && plugin(v, options); - const reservedWords = ["key", once, oncreate, onbeforeupdate, onupdate, onremove, "data"]; - v.reservedWords = reservedWords; - - let attachedListeners = {}; - function eventListener(e) { - let dom = e.target; - let name = `__on${e.type}`; - while (dom) { - if (dom[name]) { - dom[name](e, dom); - if (!e.defaultPrevented) { - v.update(); - } - return; - } - dom = dom.parentNode; - } - } - - const addProps = (newNode) => { - for (let name in newNode.props) { - let value = newNode.props[name]; - if (reservedWords.indexOf(name) !== -1) { - if (directives[name]) { - directives[name](value, newNode); - } - } else if (typeof value === "function") { - name = `__${name}`; - if (!attachedListeners[name]) { - mainContainer.addEventListener(name.slice(4), eventListener); - attachedListeners[name] = true; - } - newNode.dom[name] = value; - } else if (!newNode.isSVG && name in newNode.dom) { - if (newNode.dom[name] != value) { - newNode.dom[name] = value; - } - } else { - newNode.dom.setAttribute(name, value); - } - } - }; - - const updateProperty = (name, newNode, oldNode) => { - if (name in newNode.props) { - let value = newNode.props[name]; - if (reservedWords.indexOf(name) !== -1) { - if (directives[name]) { - directives[name](value, newNode, oldNode); - } - } else if (typeof value === functionstr) { - name = `__${name}`; - if (!attachedListeners[name]) { - mainContainer.addEventListener(name.slice(4), eventListener); - attachedListeners[name] = true; - } - newNode.dom[name] = value; - } else if (name in newNode.dom && !newNode.isSVG) { - if (newNode.dom[name] !== value) { - newNode.dom[name] = value; - } - } else if (!oldNode || value !== oldNode.props[name]) { - newNode.dom.setAttribute(name, value); - } - } - }; - - v.updateProperty = updateProperty; - - const updateProps = (newNode, oldNode) => { - for (let name in newNode.props) { - updateProperty(name, newNode, oldNode); - } - }; - - let removeProps = (newNode, oldNode) => { - for (let name in oldNode.props) { - if (reservedWords.indexOf(name) === -1 && name in newNode.props === false && typeof oldNode.props[name] !== functionstr) { - if (name in newNode.dom) { - newNode.dom[name] = UND; - } else { - newNode.dom.removeAttribute(name); - } - } - } - }; - - let moveDom = (dom, $parent, oldDom) => { - if (dom !== oldDom) { - oldDom ? $parent.replaceChild(dom, oldDom) : $parent.appendChild(dom); - } - }; - - let removeVnode = (vnode) => { - callRemove(vnode); - vnode.dom && vnode.dom.parentNode && vnode.dom.parentNode.removeChild(vnode.dom); - }; - - let updateKeyedNode = ($parent, newNode, newIndex, compareNode) => { - let oldDom = $parent.childNodes[newIndex]; - // Moved or updated - if (compareNode) { - newNode.dom = compareNode.dom; - if (once in newNode.props || lifecycleCall(newNode, onbeforeupdate, compareNode) === false) { - newNode.children = compareNode.children; - moveDom(newNode.dom, $parent, oldDom); - } else { - removeProps(newNode, compareNode); - updateProps(newNode, compareNode); - moveDom(newNode.dom, $parent, oldDom); - lifecycleCall(newNode, v.isMounted ? onupdate : oncreate, compareNode); - patch(newNode, compareNode); - } - } else { - newNode.dom = createElement(newNode.name, newNode.isSVG); - addProps(newNode); - moveDom(newNode.dom, $parent, oldDom); - lifecycleCall(newNode, oncreate); - patch(newNode); - } - }; - - let vnodesToCleanup = []; - - v.onCleanup = (callback) => { - let parentVnode = v.current.parentVnode; - if (!parentVnode.onCleanup) { - parentVnode.onCleanup = []; - } - - parentVnode.onCleanup.push(callback); - - if (vnodesToCleanup.indexOf(parentVnode) === -1) { - vnodesToCleanup.push(parentVnode); - } - }; - - let cleanupVnodes = () => { - for (let l = vnodesToCleanup.length; l--; ) { - for (let callback of vnodesToCleanup[l].onCleanup) { - callback(); - } - } - vnodesToCleanup = []; - }; - - const current = { - parentVnode: UND, - oldParentVnode: UND, - component: UND - }; - - v.current = current; - - // eslint-disable-next-line complexity,sonarjs/cognitive-complexity - let patch = (parentNode, oldParentNode = emptyNode) => { - let newTree = isArray(parentNode.children) ? parentNode.children : [parentNode.children]; - let oldTree = oldParentNode.children; - current.parentVnode = parentNode; - current.oldParentVnode = oldParentNode; - - // Flatten children - for (let i = 0; i < newTree.length; i++) { - let childVnode = newTree[i]; - - if (childVnode instanceof Vnode) { - childVnode.isSVG = parentNode.isSVG || childVnode.name === "svg"; - } else if (childVnode === null || childVnode === UND) { - newTree.splice(i--, 1); - } else if (childVnode instanceof Component) { - current.component = childVnode; - newTree.splice(i--, 1, childVnode.component.call(childVnode.component, childVnode.props, ...childVnode.children)); - } else if (childVnode instanceof POJOComponent) { - current.component = childVnode; - newTree.splice(i--, 1, childVnode.component.view.call(childVnode.component, childVnode.props, ...childVnode.children)); - } else if (isArray(childVnode)) { - newTree.splice(i--, 1, ...childVnode); - } - } - - if (newTree.length === 0) { - if (oldTree.length > 0) { - for (let i = oldTree.length; i--; ) { - callRemove(oldTree[i]); - } - parentNode.dom.textContent = ""; - } - - // Is keyed list - } else if (oldTree.length && newTree[0] instanceof Vnode && "key" in newTree[0].props) { - let oldKeys = oldTree.map((vnode) => vnode.props.key); - let newKeys = newTree.map((vnode) => vnode.props.key); - - for (let i = 0, l = newKeys.length; i < l; i++) { - let key = newKeys[i]; - let newNode = newTree[i]; - - // Updated: Same key - if (key === oldKeys[i]) { - oldTree[i].processed = true; - updateKeyedNode(parentNode.dom, newNode, i, oldTree[i]); - } else { - let oldIndex = oldKeys.indexOf(key); - let newIndex = i >= oldKeys.length ? UND : i; - - // Moved: Key exists in old keys - if (oldIndex !== -1) { - oldTree[oldIndex].processed = true; - updateKeyedNode(parentNode.dom, newNode, newIndex, oldTree[oldIndex]); - // Added: Key does not exists in old keys - } else { - updateKeyedNode(parentNode.dom, newNode, newIndex); - } - } - } - - // Delete unprocessed old keys - let l = oldTree.length; - - while (l--) { - !oldTree[l].processed && removeVnode(oldTree[l]); - } - - // Not keyed list or first render so use the simple algorithm - } else { - let i = oldTree.length; - let l = newTree.length; - - // Remove deleted nodes - while (i-- > l) { - removeVnode(oldTree[i]); - } - - for (i = 0; i < l; i++) { - let newNode = newTree[i]; - let oldNode = oldTree[i]; - // Is vnode - if (newNode instanceof Vnode) { - if (oldNode && newNode.name === oldNode.name) { - newNode.dom = oldNode.dom; - if (once in newNode.props || lifecycleCall(newNode, onbeforeupdate, oldNode) === false) { - newNode.children = oldNode.children; - } else { - removeProps(newNode, oldNode); - updateProps(newNode, oldNode); - lifecycleCall(newNode, v.isMounted ? onupdate : oncreate, oldNode); - patch(newNode, oldNode); - } - } else { - newNode.dom = createElement(newNode.name, newNode.isSVG); - addProps(newNode); - if (oldNode) { - callRemove(oldNode); - parentNode.dom.replaceChild(newNode.dom, parentNode.dom.childNodes[i]); - } else { - parentNode.dom.appendChild(newNode.dom); - } - lifecycleCall(newNode, oncreate); - patch(newNode); - } - } else { - let dom; - // If we are getting a TextVnode could be from the domToVnode method - let value = newNode instanceof TextVnode ? newNode.dom.nodeValue : String(newNode); - if (oldNode instanceof TextVnode) { - dom = oldNode.dom; - if (value != dom.nodeValue) { - dom.nodeValue = value; - } - } else { - dom = document.createTextNode(value); - if (oldNode) { - callRemove(oldNode); - parentNode.dom.replaceChild(dom, oldNode.dom); - } else { - parentNode.dom.appendChild(dom); - } - } - newTree[i] = new TextVnode(dom); - } - } - } - - parentNode.children = newTree; - }; - - v.update = (props, ...children) => { - if (mainNode) { - if (mountedComponent) { - cleanupVnodes(); - oldMainNode = mainNode; - mainNode = new Vnode(mainNode.name, mainNode.props, [v(mountedComponent, props, ...children)]); - mainNode.dom = oldMainNode.dom; - mainNode.isSVG = mainNode.name === "svg"; - patch(mainNode, oldMainNode); - v.isMounted = true; - } - - return v.isNode && mainNode.dom.innerHTML; - } - }; - - v.mount = (container, component, props, ...children) => { - mainContainer = v.isNode ? createElement("div") : typeof container === "string" ? document.querySelectorAll(container)[0] : container; - - mainNode = v.domToVnode(mainContainer); - mountedComponent = component; - - return v.update(props, ...children); - }; - - v.unMount = () => { - mainContainer = null; - mountedComponent = () => ""; - let result = v.update(); - v.isMounted = false; - return result; - }; - - v.directive = (directive, handler) => { - let directiveName = `v-${directive}`; - if (v.reservedWords.indexOf(directiveName) === -1) { - v.reservedWords.push(directiveName); - directives[directiveName] = handler; - } - }; - - let hideDirective = (test) => (bool, vnode, oldnode) => { - let value = test ? bool : !bool; - if (value) { - let newdom = document.createTextNode(""); - if (oldnode && oldnode.dom && oldnode.dom.parentNode) { - callRemove(oldnode); - oldnode.dom.parentNode.replaceChild(newdom, oldnode.dom); - } - vnode.name = ""; - vnode.children = []; - vnode.props = {}; - vnode.dom = newdom; - } - }; - - v.directive("if", hideDirective(false)); - v.directive("unless", hideDirective(true)); - v.directive("for", (set, vnode) => (vnode.children = set.map(vnode.children[0]))); - v.directive("show", (bool, vnode) => (vnode.dom.style.display = bool ? "" : "none")); - v.directive("class", (classes, vnode) => { - for (let name in classes) { - vnode.dom.classList.toggle(name, classes[name]); - } - }); - v.directive("html", (html, vnode) => (vnode.children = v.trust(html))); - v.newInstance = valyrian; - - return v; -} - -const v = valyrian(); - -module.exports = { v }; diff --git a/bench/iterations.test.js b/bench/iterations_bench.js similarity index 100% rename from bench/iterations.test.js rename to bench/iterations_bench.js diff --git a/bench/mount_n_update.test.js.bak b/bench/mount_n_update.test.js.bak deleted file mode 100644 index bc8d034..0000000 --- a/bench/mount_n_update.test.js.bak +++ /dev/null @@ -1,630 +0,0 @@ -let { compare, benchmark, before } = require("buffalo-test"); - -import "../lib/index.ts"; - -import expect from "expect"; -import nodePlugin from "../plugins/node.mjs"; -import vOld from "./index-old"; - -let VNext = v; - -let data = { - before: [], - update1: [], - update2: [] -}; - -function createNode({ className, i }) { - return { - class: className, - data: i, - onbeforeupdate(n, o) { - return n.props.data !== o.props.data || n.props.class !== o.props.class; - }, - id: className + i, - style: "font-size:" + i + "px", - autocomplete: "off", - focus: false, - onclick() { - // console.log("clicked", this); - } - }; -} - -for (let i = 1000; i--; ) { - data.before.push(createNode({ className: "ok", i })); - if (i % 3) { - data.before.push(createNode({ className: "ok", i: i + 3 })); - } else { - data.before.push(createNode({ className: "not-ok", i })); - } - data.update2.push(createNode({ className: "ok", i: 1000 - i })); -} - -compare("Mount and update: Mount multiple types", () => { - let date = new Date(); - let useData = false; - let Component = () => vOld("div", null, [null, "Hello", , 1, date, { hello: "world" }, ["Hello"]], useData ? data.before : null); - let Component2 = () => VNext("div", null, [null, "Hello", , 1, date, { hello: "world" }, ["Hello"]], useData ? data.before : null); - let Component3 = () => VNext("div", null, [null, "Hello", , 1, date, { hello: "world" }, ["Hello"]], useData ? data.before : null); - - before(() => { - expect(vOld.mount("body", Component)).toEqual(`
Hello1${date}[object Object]Hello
`); - expect(VNext.mount("body", Component2)).toEqual(`
Hello1${date}[object Object]Hello
`); - expect(VNext.mount("body", Component3)).toEqual(`
Hello1${date}[object Object]Hello
`); - useData = true; - }); - - benchmark("Valyrian 5.0.8", () => { - vOld.unMount(); - vOld.mount("body", Component); - }); - - benchmark("Valyrian next", () => { - VNext.mount("body", Component2); - }); -}); - -compare("Mount and update: Mount single text", () => { - let Component = () => vOld("div", null, ["hello world"]); - let Component2 = () => VNext("div", null, ["hello world"]); - - before(() => { - expect(vOld.mount("body", Component)).toEqual(`
hello world
`); - expect(VNext.mount("body", Component2)).toEqual(`
hello world
`); - }); - - benchmark("Valyrian 5.0.8", () => { - vOld.unMount(); - vOld.mount("body", Component); - }); - - benchmark("Valyrian next", () => { - VNext.mount("body", Component2); - }); -}); - -compare("Mount and update: Update multiple types", () => { - let date = new Date(); - let useData = false; - let updateData = false; - let Component = () => - vOld("div", null, [null, "Hello", , 1, date, { hello: "world" }, ["Hello"]], useData ? (updateData ? data.update1 : data.before) : null); - let Component2 = () => - VNext("div", null, [null, "Hello", , 1, date, { hello: "world" }, ["Hello"]], useData ? (updateData ? data.update1 : data.before) : null); - - before(() => { - expect(vOld.mount("body", Component)).toEqual(`
Hello1${date}[object Object]Hello
`); - expect(vOld.update()).toEqual(`
Hello1${date}[object Object]Hello
`); - - expect(VNext.mount("body", Component2)).toEqual(`
Hello1${date}[object Object]Hello
`); - expect(VNext.update()).toEqual(`
Hello1${date}[object Object]Hello
`); - vOld.unMount(); - useData = true; - }); - - benchmark("Valyrian 5.0.8", () => { - vOld.unMount(); - vOld.mount("body", Component); - updateData = true; - vOld.update(); - updateData = false; - vOld.update(); - updateData = true; - vOld.update(); - updateData = false; - }); - - benchmark("Valyrian next", () => { - VNext.mount("body", Component2); - updateData = true; - VNext.update(); - updateData = false; - VNext.update(); - updateData = true; - VNext.update(); - updateData = false; - }); -}); - -compare("Mount and update: Update single text", () => { - let updateData = false; - let Component = () => vOld("div", null, [updateData ? "hello moon" : "hello world"]); - let Component2 = () => VNext("div", null, [updateData ? "hello moon" : "hello world"]); - - before(() => { - expect(vOld.mount("body", Component)).toEqual(`
hello world
`); - expect(VNext.mount("body", Component2)).toEqual(`
hello world
`); - updateData = true; - expect(vOld.update()).toEqual(`
hello moon
`); - expect(VNext.update()).toEqual(`
hello moon
`); - updateData = false; - }); - - benchmark("Valyrian 5.0.8", () => { - vOld.unMount(); - vOld.mount("body", Component); - updateData = true; - vOld.update(); - updateData = false; - vOld.update(); - updateData = true; - vOld.update(); - }); - - benchmark("Valyrian next", () => { - VNext.mount("body", Component2); - updateData = true; - VNext.update(); - updateData = false; - VNext.update(); - updateData = true; - VNext.update(); - }); -}); - -compare("Mount and update: Render list", () => { - let set = [1, 2, 3, 4, 5]; - let tests = [ - { name: "Removed at the end", set: [1, 2, 3, 4] }, // Removed at the end - { name: "Removed at the start", set: [2, 3, 4, 5] }, // Remmoved at the start - { name: "Removed at the center", set: [1, 3, 5] }, // Removed at the center - { name: "Added at the end", set: [1, 2, 3, 4, 5, 6] }, // Added at the end - { name: "Added at the start", set: [6, 1, 2, 3, 4, 5] }, // Added at the start - { name: "Added at the center", set: [1, 2, 6, 3, 4, 5] }, // Added at the center - { name: "Reversed", set: [5, 4, 3, 2, 1] }, // Reversed - { name: "Switch positions", set: [5, 2, 3, 4, 1] }, // Switch positions, - { name: "Mixed positions", set: [1, 3, 2, 6, 5, 4] }, - { name: "Replaced with undefined", set: [1, 3, 2, , 5, 4] }, - { - name: "Added, remove and replaced with undefined", - set: [6, 7, 8, 9, , 10] - }, - { name: "Removed all at the end", set: [1] } // Removed at the end - ]; - - function getString(set) { - let str = "
    "; - for (let key of set) { - str += key ? `
  • ${key}
  • ` : ""; - } - str += "
"; - return str; - } - let beforeString = getString(set); - - tests.forEach((test) => { - before(() => { - let keys = [...set]; - let component = () => - vOld( - "ul", - null, - keys.map((key) => { - if (key) { - return vOld("li", null, key); - } - }) - ); - - let before = vOld.mount("body", component); - keys = [...test.set]; - let after = vOld.update(); - - let afterString = getString(test.set); - - expect(before).toEqual(beforeString); - expect(after).toEqual(afterString); - }); - - before(() => { - let keys = [...set]; - let component = () => - VNext( - "ul", - null, - keys.map((key) => { - if (key) { - return VNext("li", null, key); - } - }) - ); - - let before = VNext.mount("body", component); - keys = [...test.set]; - let after = VNext.update(); - - let afterString = getString(test.set); - - expect(before).toEqual(beforeString); - expect(after).toEqual(afterString); - }); - }); - - benchmark(`vOld`, () => { - let keys = [...set]; - let component = () => - vOld( - "ul", - null, - keys.map((key) => { - if (key) { - return vOld("li", null, key); - } - }) - ); - - vOld.unMount(); - vOld.mount("body", component); - for (let test of tests) { - keys = [...test.set]; - vOld.update(); - } - }); - - benchmark(`VNext`, () => { - let keys = [...set]; - let component = () => - VNext( - "ul", - null, - keys.map((key) => { - if (key) { - return VNext("li", null, key); - } - }) - ); - - VNext.mount("body", component); - for (let test of tests) { - keys = [...test.set]; - VNext.update(); - } - }); -}); - -compare("Mount and update: Render keyed list", () => { - let set = [1, 2, 3, 4, 5]; - let tests = [ - { name: "Removed at the end", set: [1, 2, 3, 4] }, // Removed at the end - { name: "Removed at the start", set: [2, 3, 4, 5] }, // Remmoved at the start - { name: "Removed at the center", set: [1, 3, 5] }, // Removed at the center - { name: "Added at the end", set: [1, 2, 3, 4, 5, 6] }, // Added at the end - { name: "Added at the start", set: [6, 1, 2, 3, 4, 5] }, // Added at the start - { name: "Added at the center", set: [1, 2, 6, 3, 4, 5] }, // Added at the center - { name: "Reversed", set: [5, 4, 3, 2, 1] }, // Reversed - { name: "Switch positions", set: [5, 2, 3, 4, 1] }, // Switch positions, - { name: "Mixed positions", set: [1, 3, 2, 6, 5, 4] }, - { name: "Replaced with undefined", set: [1, 3, 2, , 5, 4] }, - { - name: "Added, remove and replaced with undefined", - set: [6, 7, 8, 9, , 10] - }, - { name: "Removed all at the end", set: [1] } // Removed at the end - ]; - - function getString(set) { - let str = `
    `; - for (let key of set) { - str += key ? `
  • ${key}
  • ` : ""; - } - str += "
"; - return str; - } - let beforeString = getString(set); - - tests.forEach((test) => { - before(() => { - let keys = [...set]; - let component = () => - vOld( - "ul", - null, - keys.map((key) => { - if (key) { - return vOld("li", { key }, key); - } - }) - ); - - let before = vOld.mount("body", component); - keys = [...test.set]; - let after = vOld.update(); - - let afterString = getString(test.set); - - expect(before).toEqual(beforeString); - expect(after).toEqual(afterString); - }); - - before(() => { - let keys = [...set]; - let component = () => - VNext( - "ul", - null, - keys.map((key) => { - if (key) { - return VNext("li", { key }, key); - } - }) - ); - - console.log(test.name); - let before = VNext.mount("body", component); - keys = [...test.set]; - let after = VNext.update(); - - let afterString = getString(test.set); - - expect(before).toEqual(beforeString); - expect(after).toEqual(afterString); - }); - }); - - benchmark(`vOld`, () => { - let keys = [...set]; - let component = () => - vOld( - "ul", - null, - keys.map((key) => { - if (key) { - return vOld("li", { key }, key); - } - }) - ); - - for (let test of tests) { - vOld.unMount(); - vOld.mount("body", component); - keys = [...test.set]; - vOld.update(); - } - }); - - benchmark(`VNext`, () => { - let keys = [...set]; - let component = () => - VNext( - "ul", - null, - keys.map((key) => { - if (key) { - return VNext("li", { key }, key); - } - }) - ); - - for (let test of tests) { - VNext.mount("body", component); - keys = [...test.set]; - VNext.update(); - } - }); -}); - -compare("Mount and update: Render keyed list -> stress", () => { - let set = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; - - let tests = [ - { name: "Removed at the end", set: [1, 2, 3, 4, 5, 6, 7, 8, 9], movements: 1 }, // Removed at the end - { name: "Removed at the start", set: [2, 3, 4, 5, 6, 7, 8, 9, 10], movements: 1 }, // Remmoved at the start - { name: "Removed at the center", set: [1, 2, 3, 5, 6, 8, 9, 10], movements: 2 }, // Removed at the center - { name: "Added at the end", set: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11], movements: 1 }, // Added at the end - { name: "Added at the start", set: [11, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10], movements: 1 }, // Added at the start - { name: "Added at the center", set: [1, 2, 3, 4, 5, 11, 6, 7, 8, 9, 10], movements: 1 }, // Added at the center - { name: "Reversed", set: [10, 9, 8, 7, 6, 5, 4, 3, 2, 1], movements: 9 }, // Reversed - { name: "Switch positions", set: [10, 2, 3, 4, 5, 6, 7, 8, 9, 1], movements: 2 }, // Switch positions, - { name: "Switch different positions", set: [10, 6, 3, 4, 2, 5, 7, 8, 9, 1], movements: 4 }, // Switch positions, - { name: "Mixed positions", set: [1, 3, 2, 6, 5, 4, 7, 8, 9, 10], movements: 3 }, - { name: "Replaced with undefined", set: [1, 3, 2, , 5, 4, 6, 7, 8, 9, 10], movements: 2 }, - { - name: "Added, remove and replaced with undefined", - set: [11, 12, 13, 14, 15, 16, 17, , 18, 19, 20], - movements: 10 - }, - { name: "Removed all at the end", set: [1], movements: 9 }, // Removed at the end - { name: "Switch positions in large list", set: [10, 2, 3, 4, 5, 6, 7, 8, 9, 1], movements: 2 } // Switch positions - ]; - - function getString(set) { - let str = `
    `; - for (let key of set) { - str += key ? `
  • ${key}
  • ` : ""; - } - str += "
"; - return str; - } - let beforeString = getString(set); - - tests.forEach((test) => { - before(() => { - let keys = [...set]; - let component = () => - vOld( - "ul", - null, - keys.map((key) => { - if (key) { - return vOld("li", { key }, key); - } - }) - ); - - let before = vOld.mount("body", component); - keys = [...test.set]; - let after = vOld.update(); - - let afterString = getString(test.set); - - expect(before).toEqual(beforeString); - expect(after).toEqual(afterString); - }); - - before(() => { - let keys = [...set]; - let component = () => - VNext( - "ul", - null, - keys.map((key) => { - if (key) { - return VNext("li", { key }, key); - } - }) - ); - - console.log(test.name); - let before = VNext.mount("body", component); - keys = [...test.set]; - let after = VNext.update(); - - let afterString = getString(test.set); - - expect(before).toEqual(beforeString); - expect(after).toEqual(afterString); - }); - }); - - benchmark(`vOld`, () => { - let keys = [...set]; - let component = () => - vOld( - "ul", - null, - keys.map((key) => { - if (key) { - return vOld("li", { key }, key); - } - }) - ); - - for (let test of tests) { - vOld.unMount(); - vOld.mount("body", component); - keys = [...test.set]; - vOld.update(); - } - }); - - benchmark(`VNext`, () => { - let keys = [...set]; - let component = () => - VNext( - "ul", - null, - keys.map((key) => { - if (key) { - return VNext("li", { key }, key); - } - }) - ); - - for (let test of tests) { - VNext.mount("body", component); - keys = [...test.set]; - VNext.update(); - } - }); -}); - -compare("Mount and update: Render keyed list -> swap keys on large set", () => { - let set = [...Array(1000).keys()]; - let updatedLargeSet = [...set]; - updatedLargeSet[1] = 998; - updatedLargeSet[998] = 1; - - function getString(set) { - let str = `
    `; - for (let key of set) { - str += key !== undefined ? `
  • ${key}
  • ` : ""; - } - str += "
"; - return str; - } - let beforeString = getString(set); - - before(() => { - let keys = [...set]; - let component = () => - vOld( - "ul", - null, - keys.map((key) => { - if (key !== undefined) { - return vOld("li", { key }, key); - } - }) - ); - - let before = vOld.mount("body", component); - keys = [...updatedLargeSet]; - let after = vOld.update(); - - let afterString = getString(updatedLargeSet); - - expect(before).toEqual(beforeString); - expect(after).toEqual(afterString); - }); - - before(() => { - let keys = [...set]; - let component = () => - VNext( - "ul", - null, - keys.map((key) => { - if (key !== undefined) { - return VNext("li", { key }, key); - } - }) - ); - - let before = VNext.mount("body", component); - keys = [...updatedLargeSet]; - let after = VNext.update(); - - let afterString = getString(updatedLargeSet); - - expect(before).toEqual(beforeString); - expect(after).toEqual(afterString); - }); - - benchmark(`vOld`, () => { - let keys = [...set]; - let component = () => - vOld( - "ul", - null, - keys.map((key) => { - if (key !== undefined) { - return vOld("li", { key }, key); - } - }) - ); - - vOld.unMount(); - vOld.mount("body", component); - keys = [...updatedLargeSet]; - vOld.update(); - }); - - benchmark(`VNext`, () => { - let keys = [...set]; - let component = () => - VNext( - "ul", - null, - keys.map((key) => { - if (key !== undefined) { - return VNext("li", { key }, key); - } - }) - ); - - VNext.mount("body", component); - keys = [...updatedLargeSet]; - VNext.update(); - }); -}); diff --git a/bench/mount_n_update_bench.js b/bench/mount_n_update_bench.js index 3d65ee8..c160db6 100644 --- a/bench/mount_n_update_bench.js +++ b/bench/mount_n_update_bench.js @@ -695,8 +695,8 @@ compare("Mount and update: Update class", () => { // Init with 1000 words let words = [...Array(1000).keys()].map((key) => `word ${key}`); let useData = false; - let updateClass = false; - let updateClass2 = false; + let updateClass = ""; + let updateClass2 = ""; let Component = () => vOld( "div", @@ -745,8 +745,8 @@ compare("Mount and update: Update class", () => { let after2 = update(Component2); expect(after2).toEqual('
test
'); useData = true; - updateClass = false; - updateClass2 = false; + updateClass = ""; + updateClass2 = ""; }); benchmark("vOld update", () => { @@ -764,8 +764,8 @@ compare("Mount and update: Update class with hooks vs shouldupdate property", () // Init with 1000 words let words = [...Array(1000).keys()].map((key) => `word ${key}`); let useData = false; - let updateClass = false; - let updateClass2 = false; + let updateClass = ""; + let updateClass2 = ""; let Component = () => (
{useData ? ( @@ -806,8 +806,8 @@ compare("Mount and update: Update class with hooks vs shouldupdate property", () let after2 = update(Component2); expect(after2).toEqual('
test
'); useData = true; - updateClass = false; - updateClass2 = false; + updateClass = ""; + updateClass2 = ""; }); benchmark("shouldupdate property", () => { diff --git a/dist/@types/lib/index.d.ts b/dist/@types/lib/index.d.ts index fc9e427..86ba9a2 100644 --- a/dist/@types/lib/index.d.ts +++ b/dist/@types/lib/index.d.ts @@ -1,18 +1,4 @@ -import { Children, Directive, DomElement, IVnode, Plugin, Valyrian, ValyrianComponent, VnodeComponent, VnodeWithDom } from "./interfaces"; -export declare const isNodeJs: boolean; -export declare const Vnode: IVnode; -export declare function isVnode(object?: unknown | IVnode): object is IVnode; -export declare function isComponent(component?: unknown | ValyrianComponent): component is ValyrianComponent; -export declare function isVnodeComponent(vnode?: unknown | VnodeComponent): vnode is VnodeComponent; -export declare const trust: (htmlString: string) => Children; -export declare function onCleanup(callback: Function): void; -export declare function onUnmount(callback: Function): void; -export declare function onMount(callback: Function): void; -export declare function onUpdate(callback: Function): void; -export declare function mount(container: DomElement | string, component: ValyrianComponent | IVnode): void | string; -export declare function update(component?: ValyrianComponent | IVnode): void | string; -export declare function unmount(component?: ValyrianComponent | IVnode): void | string; -export declare function setAttribute(name: string, value: any, vnode: VnodeWithDom, oldVnode?: VnodeWithDom): void; -export declare function directive(name: string, directive: Directive): void; -export declare function use(plugin: Plugin, options?: Record): void | any; +/*** Vnode ***/ +import { Valyrian } from "./interfaces"; +/*** Hyperscript ***/ export declare const v: Valyrian; diff --git a/dist/@types/lib/interfaces.d.ts b/dist/@types/lib/interfaces.d.ts index bae3c23..f502b5e 100644 --- a/dist/@types/lib/interfaces.d.ts +++ b/dist/@types/lib/interfaces.d.ts @@ -1,3 +1,4 @@ +/*** Interfaces ***/ export interface DomElement extends Element { [key: string]: any; } diff --git a/dist/index.cjs b/dist/index.cjs index 7456cef..0cf5367 100644 --- a/dist/index.cjs +++ b/dist/index.cjs @@ -24,22 +24,6 @@ var __toCommonJS = /* @__PURE__ */ ((cache) => { // lib/index.ts var lib_exports = {}; __export(lib_exports, { - Vnode: () => Vnode, - directive: () => directive, - isComponent: () => isComponent, - isNodeJs: () => isNodeJs, - isVnode: () => isVnode, - isVnodeComponent: () => isVnodeComponent, - mount: () => mount, - onCleanup: () => onCleanup, - onMount: () => onMount, - onUnmount: () => onUnmount, - onUpdate: () => onUpdate, - setAttribute: () => setAttribute, - trust: () => trust, - unmount: () => unmount, - update: () => update, - use: () => use, v: () => v }); var ComponentString = "__component__"; diff --git a/dist/index.js b/dist/index.js index 679bb72..c436b4b 100644 --- a/dist/index.js +++ b/dist/index.js @@ -555,21 +555,5 @@ v.setAttribute = setAttribute; v.directive = directive; v.use = use; export { - Vnode, - directive, - isComponent, - isNodeJs, - isVnode, - isVnodeComponent, - mount, - onCleanup, - onMount, - onUnmount, - onUpdate, - setAttribute, - trust, - unmount, - update, - use, v }; diff --git a/dist/index.min.js b/dist/index.min.js index 2532cda..0a6c24b 100644 --- a/dist/index.min.js +++ b/dist/index.min.js @@ -1 +1 @@ -(()=>{var e="__component__",n="#text",o=Boolean("undefined"!=typeof process&&process.versions&&process.versions.node),t=Symbol("Valyrian"),r=void 0,i=function(e,n,o){this.props=n,this.children=o,this.tag=e};function p(e){return e instanceof i}function d(e){return"function"==typeof e||"object"==typeof e&&null!==e&&"view"in e}function l(n){return n instanceof i&&n.tag===e}function a(e,n=!1){return n?document.createElementNS("http://www.w3.org/2000/svg",e):document.createElement(e)}function s(e){let o=T(e.tagName.toLowerCase(),{},...Array.from(e.childNodes).filter(e=>1===e.nodeType||3===e.nodeType).map(e=>{if(1===e.nodeType)return s(e);let o=new i(n,{},[]);return o.nodeValue=String(e.nodeValue),o.dom=e,o}));return[].forEach.call(e.attributes,e=>o.props[e.nodeName]=e.nodeValue),o.dom=e,o}var u=e=>{let n=a("div");return n.innerHTML=e.trim(),[].map.call(n.childNodes,e=>s(e))},m={key:!0,state:!0,oncreate:!0,onupdate:!0,onremove:!0,shouldupdate:!0,"v-once":!0,"v-if":!0,"v-unless":!0,"v-for":!0,"v-show":!0,"v-class":!0,"v-html":!0},c={};function f(e){-1===c.app?.onCleanup.indexOf(e)&&c.app?.onCleanup.push(e)}function h(e){-1===c.app?.onUnmount.indexOf(e)&&c.app?.onUnmount.push(e)}function v(e){-1===c.app?.onMount.indexOf(e)&&c.app?.onMount.push(e)}function g(e){-1===c.app?.onUpdate.indexOf(e)&&c.app?.onUpdate.push(e)}function V(e,n){let r,i=null;if(i=o?"string"==typeof e?a("svg"===e?"svg":"div","svg"===e):e:"string"==typeof e?document.querySelectorAll(e)[0]:e,!i)throw new Error("Container not found");if(l(n))r=n;else{if(!d(n))throw new Error("Component must be a Valyrian Component or a Vnode component");r=T(n,{})}if(n[t])w(n);else{let e=function(e){let o=e.target,t=`v-on${e.type}`;for(;o;){if(o[t])return o[t](e,o),void(e.defaultPrevented||C(n));o=o.parentNode}};n[t]={isMounted:!1,eventListenerNames:{},onCleanup:[],onMount:[],onUpdate:[],onUnmount:[]},n[t].eventListener=e}return n[t].component=r,n[t].container=i,n[t].mainVnode=s(i),C(n)}function y(e){for(let n=0;n{if(e?o:!o){let e=document.createTextNode("");return r&&r.dom&&r.dom.parentNode&&(r.tag!==n&&M(r),r.dom.parentNode.replaceChild(e,r.dom)),t.tag=n,t.children=[],t.props={},t.dom=e,!1}}}var A={"v-if":_(!1),"v-unless":_(!0),"v-for":(e,n)=>{n.children=e.map(n.children[0])},"v-show":(e,n)=>{n.dom.style.display=e?"":"none"},"v-class":(e,n)=>{for(let o in e)n.dom.classList.toggle(o,e[o])},"v-html":(e,n)=>{n.children=[u(e)]},"v-model":([e,n,o],t,r)=>{let i,p;if("input"===t.name)switch(o=o||"oninput",t.props.type){case"checkbox":Array.isArray(e[n])?(p=o=>{let t=o.target.value,r=e[n].indexOf(t);-1===r?e[n].push(t):e[n].splice(r,1)},i=-1!==e[n].indexOf(t.dom.value)):"value"in t.props?(p=()=>{e[n]===t.props.value?e[n]=null:e[n]=t.props.value},i=e[n]===t.props.value):(p=()=>e[n]=!e[n],i=e[n]),x("checked",i,t,r);break;case"radio":x("checked",e[n]===t.dom.value,t,r);break;default:x("value",e[n],t,r)}else"select"===t.name?(o=o||"onclick",t.props.multiple?(p=o=>{let t=o.target.value;if(o.ctrlKey){let o=e[n].indexOf(t);-1===o?e[n].push(t):e[n].splice(o,1)}else e[n].splice(0,e[n].length),e[n].push(t)},t.children.forEach(o=>{if("option"===o.tag){let t="value"in o.props?o.props.value:o.children.join("").trim();o.props.selected=-1!==e[n].indexOf(t)}})):t.children.forEach(o=>{if("option"===o.tag){let t="value"in o.props?o.props.value:o.children.join("").trim();o.props.selected=t===e[n]}})):"textarea"===t.name&&(o=o||"oninput",t.children=[e[n]]);t.props[o]||(p||(p=o=>e[n]=o.target.value),x(o,p,t,r))}},L=new Map;function G(e,n){if(L.has(e))return L.get(e);let o=e(T,n);return L.set(e,o),o}var T=function(e,n,...o){if("string"==typeof e)return new i(e,n||{},o);const t=new i("__component__",n||{},o);return t.component=e,t};T.fragment=(e,...n)=>n,T.current=c,T.directives=A,T.reservedProps=m,T.isVnode=p,T.isComponent=d,T.isVnodeComponent=l,T.isNodeJs=o,T.trust=u,T.onCleanup=f,T.onUnmount=h,T.onMount=v,T.onUpdate=g,T.mount=V,T.unmount=w,T.update=C,T.setAttribute=x,T.directive=b,T.use=G;var E={Vnode:i,directive:b,isComponent:d,isNodeJs:o,isVnode:p,isVnodeComponent:l,mount:V,onCleanup:f,onMount:v,onUnmount:h,onUpdate:g,setAttribute:x,trust:u,unmount:w,update:C,use:G,v:T};"undefined"!=typeof module?module.exports=E:self.Valyrian=E})(); \ No newline at end of file +(()=>{var e="__component__",n="#text",o=Boolean("undefined"!=typeof process&&process.versions&&process.versions.node),t=Symbol("Valyrian"),r=void 0,i=function(e,n,o){this.props=n,this.children=o,this.tag=e};function p(e){return"function"==typeof e||"object"==typeof e&&null!==e&&"view"in e}function d(n){return n instanceof i&&n.tag===e}function l(e,n=!1){return n?document.createElementNS("http://www.w3.org/2000/svg",e):document.createElement(e)}function a(e){let o=U(e.tagName.toLowerCase(),{},...Array.from(e.childNodes).filter(e=>1===e.nodeType||3===e.nodeType).map(e=>{if(1===e.nodeType)return a(e);let o=new i(n,{},[]);return o.nodeValue=String(e.nodeValue),o.dom=e,o}));return[].forEach.call(e.attributes,e=>o.props[e.nodeName]=e.nodeValue),o.dom=e,o}var s=e=>{let n=l("div");return n.innerHTML=e.trim(),[].map.call(n.childNodes,e=>a(e))},u={key:!0,state:!0,oncreate:!0,onupdate:!0,onremove:!0,shouldupdate:!0,"v-once":!0,"v-if":!0,"v-unless":!0,"v-for":!0,"v-show":!0,"v-class":!0,"v-html":!0},c={};function m(e){for(let n=0;n{if(e?o:!o){let e=document.createTextNode("");return r&&r.dom&&r.dom.parentNode&&(r.tag!==n&&g(r),r.dom.parentNode.replaceChild(e,r.dom)),t.tag=n,t.children=[],t.props={},t.dom=e,!1}}}var M={"v-if":N(!1),"v-unless":N(!0),"v-for":(e,n)=>{n.children=e.map(n.children[0])},"v-show":(e,n)=>{n.dom.style.display=e?"":"none"},"v-class":(e,n)=>{for(let o in e)n.dom.classList.toggle(o,e[o])},"v-html":(e,n)=>{n.children=[s(e)]},"v-model":([e,n,o],t,r)=>{let i,p;if("input"===t.name)switch(o=o||"oninput",t.props.type){case"checkbox":Array.isArray(e[n])?(p=o=>{let t=o.target.value,r=e[n].indexOf(t);-1===r?e[n].push(t):e[n].splice(r,1)},i=-1!==e[n].indexOf(t.dom.value)):"value"in t.props?(p=()=>{e[n]===t.props.value?e[n]=null:e[n]=t.props.value},i=e[n]===t.props.value):(p=()=>e[n]=!e[n],i=e[n]),y("checked",i,t,r);break;case"radio":y("checked",e[n]===t.dom.value,t,r);break;default:y("value",e[n],t,r)}else"select"===t.name?(o=o||"onclick",t.props.multiple?(p=o=>{let t=o.target.value;if(o.ctrlKey){let o=e[n].indexOf(t);-1===o?e[n].push(t):e[n].splice(o,1)}else e[n].splice(0,e[n].length),e[n].push(t)},t.children.forEach(o=>{if("option"===o.tag){let t="value"in o.props?o.props.value:o.children.join("").trim();o.props.selected=-1!==e[n].indexOf(t)}})):t.children.forEach(o=>{if("option"===o.tag){let t="value"in o.props?o.props.value:o.children.join("").trim();o.props.selected=t===e[n]}})):"textarea"===t.name&&(o=o||"oninput",t.children=[e[n]]);t.props[o]||(p||(p=o=>e[n]=o.target.value),y(o,p,t,r))}},x=new Map;var U=function(e,n,...o){if("string"==typeof e)return new i(e,n||{},o);const t=new i("__component__",n||{},o);return t.component=e,t};U.fragment=(e,...n)=>n,U.current=c,U.directives=M,U.reservedProps=u,U.isVnode=function(e){return e instanceof i},U.isComponent=p,U.isVnodeComponent=d,U.isNodeJs=o,U.trust=s,U.onCleanup=function(e){-1===c.app?.onCleanup.indexOf(e)&&c.app?.onCleanup.push(e)},U.onUnmount=function(e){-1===c.app?.onUnmount.indexOf(e)&&c.app?.onUnmount.push(e)},U.onMount=function(e){-1===c.app?.onMount.indexOf(e)&&c.app?.onMount.push(e)},U.onUpdate=function(e){-1===c.app?.onUpdate.indexOf(e)&&c.app?.onUpdate.push(e)},U.mount=function(e,n){let r,i=null;if(i=o?"string"==typeof e?l("svg"===e?"svg":"div","svg"===e):e:"string"==typeof e?document.querySelectorAll(e)[0]:e,!i)throw new Error("Container not found");if(d(n))r=n;else{if(!p(n))throw new Error("Component must be a Valyrian Component or a Vnode component");r=U(n,{})}if(n[t])h(n);else{let e=function(e){let o=e.target,t=`v-on${e.type}`;for(;o;){if(o[t])return o[t](e,o),void(e.defaultPrevented||f(n));o=o.parentNode}};n[t]={isMounted:!1,eventListenerNames:{},onCleanup:[],onMount:[],onUpdate:[],onUnmount:[]},n[t].eventListener=e}return n[t].component=r,n[t].container=i,n[t].mainVnode=a(i),f(n)},U.unmount=h,U.update=f,U.setAttribute=y,U.directive=function(e,n){let o=`v-${e}`;M[o]=n,u[o]=!0},U.use=function(e,n){if(x.has(e))return x.get(e);let o=e(U,n);return x.set(e,o),o};var k={v:U};"undefined"!=typeof module?module.exports=k:self.Valyrian=k})(); \ No newline at end of file diff --git a/dist/index.min.js.map b/dist/index.min.js.map index 8adfa30..683f413 100644 --- a/dist/index.min.js.map +++ b/dist/index.min.js.map @@ -1 +1 @@ -//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL2xpYi9pbmRleC50cyJdLCJuYW1lcyI6WyJDb21wb25lbnRTdHJpbmciLCJUZXh0U3RyaW5nIiwiaXNOb2RlSnMiLCJCb29sZWFuIiwicHJvY2VzcyIsInZlcnNpb25zIiwibm9kZSIsIlZhbHlyaWFuU3ltYm9sIiwiU3ltYm9sIiwiVW5kIiwiVm5vZGUiLCJ0YWciLCJwcm9wcyIsImNoaWxkcmVuIiwidGhpcyIsImlzVm5vZGUiLCJvYmplY3QiLCJpc0NvbXBvbmVudCIsImNvbXBvbmVudCIsImlzVm5vZGVDb21wb25lbnQiLCJ2bm9kZSIsImNyZWF0ZURvbUVsZW1lbnQiLCJpc1NWRyIsImRvY3VtZW50IiwiY3JlYXRlRWxlbWVudE5TIiwiY3JlYXRlRWxlbWVudCIsImRvbVRvVm5vZGUiLCJkb20iLCJ2IiwidGFnTmFtZSIsInRvTG93ZXJDYXNlIiwiQXJyYXkiLCJmcm9tIiwiY2hpbGROb2RlcyIsImZpbHRlciIsImNoaWxkIiwibm9kZVR5cGUiLCJtYXAiLCJ0ZXh0Iiwibm9kZVZhbHVlIiwiU3RyaW5nIiwiZm9yRWFjaCIsImNhbGwiLCJhdHRyaWJ1dGVzIiwicHJvcCIsIm5vZGVOYW1lIiwidHJ1c3QiLCJodG1sU3RyaW5nIiwiZGl2IiwiaW5uZXJIVE1MIiwidHJpbSIsIml0ZW0iLCJyZXNlcnZlZFByb3BzIiwia2V5Iiwic3RhdGUiLCJvbmNyZWF0ZSIsIm9udXBkYXRlIiwib25yZW1vdmUiLCJzaG91bGR1cGRhdGUiLCJjdXJyZW50Iiwib25DbGVhbnVwIiwiY2FsbGJhY2siLCJhcHAiLCJpbmRleE9mIiwicHVzaCIsIm9uVW5tb3VudCIsIm9uTW91bnQiLCJvblVwZGF0ZSIsIm1vdW50IiwiY29udGFpbmVyIiwidm5vZGVDb21wb25lbnQiLCJhcHBDb250YWluZXIiLCJxdWVyeVNlbGVjdG9yQWxsIiwiRXJyb3IiLCJ1bm1vdW50IiwiZXZlbnRMaXN0ZW5lciIsImUiLCJ0YXJnZXQiLCJuYW1lIiwidHlwZSIsImRlZmF1bHRQcmV2ZW50ZWQiLCJ1cGRhdGUiLCJwYXJlbnROb2RlIiwiaXNNb3VudGVkIiwiZXZlbnRMaXN0ZW5lck5hbWVzIiwibWFpblZub2RlIiwiY2FsbENsZWFudXAiLCJ2YWx5cmlhbkFwcCIsImkiLCJsZW5ndGgiLCJvbGRWbm9kZSIsInBhdGNoIiwiY2FsbE1vdW50IiwiY2FsbFVwZGF0ZSIsImNhbGxVbm1vdW50IiwiUmVmbGVjdCIsImRlbGV0ZVByb3BlcnR5IiwiZW1wdHlWbm9kZSIsInNoYXJlZFNldEF0dHJpYnV0ZSIsInZhbHVlIiwiZGlyZWN0aXZlcyIsImFkZEV2ZW50TGlzdGVuZXIiLCJzbGljZSIsInJlbW92ZUF0dHJpYnV0ZSIsInNldEF0dHJpYnV0ZSIsInNldEF0dHJpYnV0ZXMiLCJuZXdWbm9kZSIsIm5ld1RyZWUiLCJvbGRUcmVlIiwiY2hpbGRWbm9kZSIsInJlc3VsdCIsInZpZXciLCJzcGxpY2UiLCJpc0FycmF5Iiwib2xkVHJlZUxlbmd0aCIsIm5ld1RyZWVMZW5ndGgiLCJvbGRLZXllZExpc3QiLCJuZXdLZXllZExpc3QiLCJvbGRDaGlsZFZub2RlIiwic2hvdWxkUGF0Y2giLCJhcHBlbmRDaGlsZCIsInJlcGxhY2VDaGlsZCIsInJlbW92ZUNoaWxkIiwibmV3Q2hpbGRWbm9kZSIsImNyZWF0ZVRleHROb2RlIiwidGV4dENvbnRlbnQiLCJkaXJlY3RpdmUiLCJkaXJlY3RpdmUyIiwiZnVsbE5hbWUiLCJoaWRlRGlyZWN0aXZlIiwidGVzdCIsImJvb2wiLCJuZXdkb20iLCJzZXQiLCJzdHlsZSIsImRpc3BsYXkiLCJjbGFzc2VzIiwiY2xhc3NMaXN0IiwidG9nZ2xlIiwiaHRtbCIsIm1vZGVsIiwicHJvcGVydHkiLCJldmVudCIsImhhbmRsZXIiLCJ2YWwiLCJpZHgiLCJtdWx0aXBsZSIsImN0cmxLZXkiLCJ2YWx1ZTIiLCJqb2luIiwic2VsZWN0ZWQiLCJwbHVnaW5zIiwiTWFwIiwidXNlIiwicGx1Z2luIiwib3B0aW9ucyIsImhhcyIsImdldCIsInRhZ09yQ29tcG9uZW50IiwiZnJhZ21l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LEVBQVduRSxHQUFjZ0UsRUFBTUMsR0FBYWpFLEVBQUVDLE9BQTRDc0IsT0FFNUZLLEVBQWFzQyxFQUFPQyxFQUFTM0gsRUFBT3NFLE1BTXBDNkQsRUFBVSxJQUFJQyxJQUViLFNBQUFDLEVBQWFDLEVBQWdCQyxHQUNsQyxHQUFJSixFQUFRSyxJQUFJRixHQUNkLE9BQU9ILEVBQVFNLElBQUlILEdBR3JCLElBQUk1QyxFQUFTNEMsRUFBTzlILEVBQUcrSCxHQUV2QixPQURBSixFQUFRbEIsSUFBSXFCLEVBQVE1QyxHQUNiQSxFQUtGLElBQU1sRixFQUFjLFNBQVdrSSxFQUE0Q2xKLEtBQWlCQyxHQUNqRyxHQUE4QixpQkFBbkJpSixFQUNULE9BQU8sSUFBSXBKLEVBQU1vSixFQUFnQmxKLEdBQVMsR0FBSUMsR0FHaEQsTUFBTU8sRUFBUSxJQUFJVixFQUFNLGdCQUFpQkUsR0FBUyxHQUFJQyxHQUV0RCxPQURBTyxFQUFNRixVQUFZNEksRUFDWDFJLEdBR1RRLEVBQUVtSSxTQUFXLENBQUNuSixLQUFpQkMsSUFDdEJBLEVBS1RlLEVBQUUrQixRQUFVQSxFQUVaL0IsRUFBRXdFLFdBQWFBLEVBRWZ4RSxFQUFFd0IsY0FBZ0JBLEVBRWxCeEIsRUFBRWIsUUFBVUEsRUFDWmEsRUFBRVgsWUFBY0EsRUFDaEJXLEVBQUVULGlCQUFtQkEsRUFFckJTLEVBQUUxQixTQUFXQSxFQUNiMEIsRUFBRWtCLE1BQVFBLEVBRVZsQixFQUFFZ0MsVUFBWUEsRUFDZGhDLEVBQUVxQyxVQUFZQSxFQUNkckMsRUFBRXNDLFFBQVVBLEVBQ1p0QyxFQUFFdUMsU0FBV0EsRUFFYnZDLEVBQUV3QyxNQUFRQSxFQUNWeEMsRUFBRThDLFFBQVVBLEVBQ1o5QyxFQUFFcUQsT0FBU0EsRUFFWHJELEVBQUU0RSxhQUFlQSxFQUNqQjVFLEVBQUVrRyxVQUFZQSxFQUNkbEcsRUFBRTZILElBQU1BIiwic291cmNlc0NvbnRlbnQiOlsiLyoqKiBWbm9kZSAqKiovXG5cbmltcG9ydCB7XG4gIENoaWxkcmVuLFxuICBDdXJyZW50LFxuICBEaXJlY3RpdmUsXG4gIERpcmVjdGl2ZXMsXG4gIERvbUVsZW1lbnQsXG4gIElWbm9kZSxcbiAgTW91bnRlZFZhbHlyaWFuQXBwLFxuICBQbHVnaW4sXG4gIFByb3BzLFxuICBSZXNlcnZlZFByb3BzLFxuICBWYWx5cmlhbixcbiAgVmFseXJpYW5BcHAsXG4gIFZhbHlyaWFuQ29tcG9uZW50LFxuICBWbm9kZUNvbXBvbmVudCxcbiAgVm5vZGVXaXRoRG9tXG59IGZyb20gXCIuL2ludGVyZmFjZXNcIjtcblxuLyoqKiBDb25zdGFudHMgKioqL1xuY29uc3QgQ29tcG9uZW50U3RyaW5nID0gXCJfX2NvbXBvbmVudF9fXCI7XG5jb25zdCBUZXh0U3RyaW5nID0gXCIjdGV4dFwiO1xuZXhwb3J0IGNvbnN0IGlzTm9kZUpzID0gQm9vbGVhbih0eXBlb2YgcHJvY2VzcyAhPT0gXCJ1bmRlZmluZWRcIiAmJiBwcm9jZXNzLnZlcnNpb25zICYmIHByb2Nlc3MudmVyc2lvbnMubm9kZSk7XG5jb25zdCBWYWx5cmlhblN5bWJvbCA9IFN5bWJvbChcIlZhbHlyaWFuXCIpO1xuY29uc3QgVW5kID0gdW5kZWZpbmVkO1xuXG4vKioqIFZub2RlICoqKi9cblxuZXhwb3J0IGNvbnN0IFZub2RlID0gZnVuY3Rpb24gVm5vZGUodGhpczogSVZub2RlLCB0YWc6IHN0cmluZywgcHJvcHM6IFByb3BzLCBjaGlsZHJlbjogQ2hpbGRyZW4pIHtcbiAgdGhpcy5wcm9wcyA9IHByb3BzO1xuICB0aGlzLmNoaWxkcmVuID0gY2hpbGRyZW47XG4gIHRoaXMudGFnID0gdGFnO1xufSBhcyB1bmtub3duIGFzIElWbm9kZTtcblxuZXhwb3J0IGZ1bmN0aW9uIGlzVm5vZGUob2JqZWN0PzogdW5rbm93biB8IElWbm9kZSk6IG9iamVjdCBpcyBJVm5vZGUge1xuICByZXR1cm4gb2JqZWN0IGluc3RhbmNlb2YgVm5vZGU7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBpc0NvbXBvbmVudChjb21wb25lbnQ/OiB1bmtub3duIHwgVmFseXJpYW5Db21wb25lbnQpOiBjb21wb25lbnQgaXMgVmFseXJpYW5Db21wb25lbnQge1xuICByZXR1cm4gdHlwZW9mIGNvbXBvbmVudCA9PT0gXCJmdW5jdGlvblwiIHx8ICh0eXBlb2YgY29tcG9uZW50ID09PSBcIm9iamVjdFwiICYmIGNvbXBvbmVudCAhPT0gbnVsbCAmJiBcInZpZXdcIiBpbiBjb21wb25lbnQpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gaXNWbm9kZUNvbXBvbmVudCh2bm9kZT86IHVua25vd24gfCBWbm9kZUNvbXBvbmVudCk6IHZub2RlIGlzIFZub2RlQ29tcG9uZW50IHtcbiAgcmV0dXJuIHZub2RlIGluc3RhbmNlb2YgVm5vZGUgJiYgdm5vZGUudGFnID09PSBDb21wb25lbnRTdHJpbmc7XG59XG5cbi8qKiogVXRpbCAqKiovXG5cbmZ1bmN0aW9uIGNyZWF0ZURvbUVsZW1lbnQodGFnOiBzdHJpbmcsIGlzU1ZHOiBib29sZWFuID0gZmFsc2UpIHtcbiAgcmV0dXJuIGlzU1ZHID8gZG9jdW1lbnQuY3JlYXRlRWxlbWVudE5TKFwiaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmdcIiwgdGFnKSA6IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQodGFnKTtcbn1cblxuZnVuY3Rpb24gZG9tVG9Wbm9kZShkb206IERvbUVsZW1lbnQpOiBWbm9kZVdpdGhEb20ge1xuICBsZXQgdm5vZGUgPSB2KFxuICAgIGRvbS50YWdOYW1lLnRvTG93ZXJDYXNlKCksXG4gICAge30sXG4gICAgLi4uQXJyYXkuZnJvbShkb20uY2hpbGROb2RlcylcbiAgICAgIC5maWx0ZXIoKGNoaWxkKSA9PiAoY2hpbGQgYXMgRG9tRWxlbWVudCkubm9kZVR5cGUgPT09IDEgfHwgKGNoaWxkIGFzIERvbUVsZW1lbnQpLm5vZGVUeXBlID09PSAzKVxuICAgICAgLm1hcCgoY2hpbGQpID0+IHtcbiAgICAgICAgaWYgKChjaGlsZCBhcyBEb21FbGVtZW50KS5ub2RlVHlwZSA9PT0gMSkge1xuICAgICAgICAgIHJldHVybiBkb21Ub1Zub2RlKGNoaWxkIGFzIERvbUVsZW1lbnQpO1xuICAgICAgICB9XG5cbiAgICAgICAgbGV0IHRleHQgPSBuZXcgVm5vZGUoVGV4dFN0cmluZywge30sIFtdKTtcbiAgICAgICAgdGV4dC5ub2RlVmFsdWUgPSBTdHJpbmcoKGNoaWxkIGFzIERvbUVsZW1lbnQpLm5vZGVWYWx1ZSk7XG4gICAgICAgIHRleHQuZG9tID0gY2hpbGQgYXMgRG9tRWxlbWVudDtcbiAgICAgICAgcmV0dXJuIHRleHQ7XG4gICAgICB9KVxuICApO1xuICBbXS5mb3JFYWNoLmNhbGwoZG9tLmF0dHJpYnV0ZXMsIChwcm9wOiBBdHRyKSA9PiAodm5vZGUucHJvcHNbcHJvcC5ub2RlTmFtZV0gPSBwcm9wLm5vZGVWYWx1ZSkpO1xuICB2bm9kZS5kb20gPSBkb207XG4gIHJldHVybiB2bm9kZSBhcyBWbm9kZVdpdGhEb207XG59XG5cbmV4cG9ydCBjb25zdCB0cnVzdCA9IChodG1sU3RyaW5nOiBzdHJpbmcpOiBDaGlsZHJlbiA9PiB7XG4gIGxldCBkaXYgPSBjcmVhdGVEb21FbGVtZW50KFwiZGl2XCIpO1xuICBkaXYuaW5uZXJIVE1MID0gaHRtbFN0cmluZy50cmltKCk7XG5cbiAgcmV0dXJuIFtdLm1hcC5jYWxsKGRpdi5jaGlsZE5vZGVzLCAoaXRlbSkgPT4gZG9tVG9Wbm9kZShpdGVtKSkgYXMgQ2hpbGRyZW47XG59O1xuXG5jb25zdCByZXNlcnZlZFByb3BzOiBSZXNlcnZlZFByb3BzID0ge1xuICBrZXk6IHRydWUsXG4gIHN0YXRlOiB0cnVlLFxuICBvbmNyZWF0ZTogdHJ1ZSxcbiAgb251cGRhdGU6IHRydWUsXG4gIG9ucmVtb3ZlOiB0cnVlLFxuICBzaG91bGR1cGRhdGU6IHRydWUsXG4gIFwidi1vbmNlXCI6IHRydWUsXG5cbiAgLy8gQnVpbHQgaW4gZGlyZWN0aXZlc1xuICBcInYtaWZcIjogdHJ1ZSxcbiAgXCJ2LXVubGVzc1wiOiB0cnVlLFxuICBcInYtZm9yXCI6IHRydWUsXG4gIFwidi1zaG93XCI6IHRydWUsXG4gIFwidi1jbGFzc1wiOiB0cnVlLFxuICBcInYtaHRtbFwiOiB0cnVlXG59O1xuXG4vKioqIE1vdW50ICoqKi9cblxuY29uc3QgY3VycmVudDogQ3VycmVudCA9IHt9O1xuXG5leHBvcnQgZnVuY3Rpb24gb25DbGVhbnVwKGNhbGxiYWNrOiBGdW5jdGlvbikge1xuICBpZiAoY3VycmVudC5hcHA/Lm9uQ2xlYW51cC5pbmRleE9mKGNhbGxiYWNrKSA9PT0gLTEpIHtcbiAgICBjdXJyZW50LmFwcD8ub25DbGVhbnVwLnB1c2goY2FsbGJhY2spO1xuICB9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBvblVubW91bnQoY2FsbGJhY2s6IEZ1bmN0aW9uKSB7XG4gIGlmIChjdXJyZW50LmFwcD8ub25Vbm1vdW50LmluZGV4T2YoY2FsbGJhY2spID09PSAtMSkge1xuICAgIGN1cnJlbnQuYXBwPy5vblVubW91bnQucHVzaChjYWxsYmFjayk7XG4gIH1cbn1cblxuZXhwb3J0IGZ1bmN0aW9uIG9uTW91bnQoY2FsbGJhY2s6IEZ1bmN0aW9uKSB7XG4gIGlmIChjdXJyZW50LmFwcD8ub25Nb3VudC5pbmRleE9mKGNhbGxiYWNrKSA9PT0gLTEpIHtcbiAgICBjdXJyZW50LmFwcD8ub25Nb3VudC5wdXNoKGNhbGxiYWNrKTtcbiAgfVxufVxuXG5leHBvcnQgZnVuY3Rpb24gb25VcGRhdGUoY2FsbGJhY2s6IEZ1bmN0aW9uKSB7XG4gIGlmIChjdXJyZW50LmFwcD8ub25VcGRhdGUuaW5kZXhPZihjYWxsYmFjaykgPT09IC0xKSB7XG4gICAgY3VycmVudC5hcHA/Lm9uVXBkYXRlLnB1c2goY2FsbGJhY2spO1xuICB9XG59XG5cbi8qXG4gICogTW91bnRzIGEgY29tcG9uZW50IHRvIHRoZSBET01cbiAgbW91bnQoJyNhcHAnLCAoKSA9PiA8ZGl2PkhlbGxvIHdvcmxkPC9kaXY+KTsgLy8gQXBwIGlzIGEgRnVuY3Rpb25hbCBDb21wb25lbnRcbiAgbW91bnQoJyNhcHAnLCB7IHZpZXc6ICgpID0+IDxkaXY+SGVsbG8gd29ybGQ8L2Rpdj4gfSk7IC8vIEFwcCBpcyBhIFBPSk8gY29tcG9uZW50IHdpdGggYSB2aWV3IG1ldGhvZFxuICBtb3VudCgnI2FwcCcsIGNsYXNzSW5zdGFuY2UpOyAvLyBBcHAgaXMgYSBjbGFzcyBpbnN0YW5jZSB3aXRoIGEgdmlldyBtZXRob2RcbiAgbW91bnQoJyNhcHAnLCA8QXBwPjxkaXY+SGVsbG8gd29ybGQ8L2Rpdj48L0FwcD4pOyAvLyBBcHAgaXMgYSBWbm9kZSBjb21wb25lbnQgKFZub2RlIHdpdGggdGFnIF9fY29tcG9uZW50X18pXG4qL1xuXG5leHBvcnQgZnVuY3Rpb24gbW91bnQoY29udGFpbmVyOiBEb21FbGVtZW50IHwgc3RyaW5nLCBjb21wb25lbnQ6IFZhbHlyaWFuQ29tcG9uZW50IHwgSVZub2RlKTogdm9pZCB8IHN0cmluZyB7XG4gIGxldCBhcHBDb250YWluZXIgPSBudWxsO1xuXG4gIGlmIChpc05vZGVKcykge1xuICAgIGFwcENvbnRhaW5lciA9IHR5cGVvZiBjb250YWluZXIgPT09IFwic3RyaW5nXCIgPyBjcmVhdGVEb21FbGVtZW50KGNvbnRhaW5lciA9PT0gXCJzdmdcIiA/IFwic3ZnXCIgOiBcImRpdlwiLCBjb250YWluZXIgPT09IFwic3ZnXCIpIDogY29udGFpbmVyO1xuICB9IGVsc2Uge1xuICAgIGFwcENvbnRhaW5lciA9IHR5cGVvZiBjb250YWluZXIgPT09IFwic3RyaW5nXCIgPyBkb2N1bWVudC5xdWVyeVNlbGVjdG9yQWxsKGNvbnRhaW5lcilbMF0gOiBjb250YWluZXI7XG4gIH1cblxuICBpZiAoIWFwcENvbnRhaW5lcikge1xuICAgIHRocm93IG5ldyBFcnJvcihcIkNvbnRhaW5lciBub3QgZm91bmRcIik7XG4gIH1cblxuICBsZXQgdm5vZGVDb21wb25lbnQ6IFZub2RlQ29tcG9uZW50IHwgSVZub2RlO1xuXG4gIGlmIChpc1Zub2RlQ29tcG9uZW50KGNvbXBvbmVudCkpIHtcbiAgICB2bm9kZUNvbXBvbmVudCA9IGNvbXBvbmVudDtcbiAgfSBlbHNlIGlmIChpc0NvbXBvbmVudChjb21wb25lbnQpKSB7XG4gICAgdm5vZGVDb21wb25lbnQgPSB2KGNvbXBvbmVudCwge30pO1xuICB9IGVsc2Uge1xuICAgIHRocm93IG5ldyBFcnJvcihcIkNvbXBvbmVudCBtdXN0IGJlIGEgVmFseXJpYW4gQ29tcG9uZW50IG9yIGEgVm5vZGUgY29tcG9uZW50XCIpO1xuICB9XG5cbiAgaWYgKGNvbXBvbmVudFtWYWx5cmlhblN5bWJvbF0pIHtcbiAgICB1bm1vdW50KGNvbXBvbmVudCk7XG4gIH0gZWxzZSB7XG4gICAgY29tcG9uZW50W1ZhbHlyaWFuU3ltYm9sXSA9IHtcbiAgICAgIGlzTW91bnRlZDogZmFsc2UsXG4gICAgICBldmVudExpc3RlbmVyTmFtZXM6IHt9LFxuICAgICAgb25DbGVhbnVwOiBbXSxcbiAgICAgIG9uTW91bnQ6IFtdLFxuICAgICAgb25VcGRhdGU6IFtdLFxuICAgICAgb25Vbm1vdW50OiBbXVxuICAgIH07XG4gICAgZnVuY3Rpb24gZXZlbnRMaXN0ZW5lcihlOiBFdmVudCkge1xuICAgICAgbGV0IGRvbSA9IGUudGFyZ2V0IGFzIERvbUVsZW1lbnQgJiBSZWNvcmQ8c3RyaW5nLCBhbnk+O1xuICAgICAgbGV0IG5hbWUgPSBgdi1vbiR7ZS50eXBlfWA7XG4gICAgICB3aGlsZSAoZG9tKSB7XG4gICAgICAgIGlmIChkb21bbmFtZV0pIHtcbiAgICAgICAgICBkb21bbmFtZV0oZSwgZG9tKTtcbiAgICAgICAgICBpZiAoIWUuZGVmYXVsdFByZXZlbnRlZCkge1xuICAgICAgICAgICAgdXBkYXRlKGNvbXBvbmVudCk7XG4gICAgICAgICAgfVxuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBkb20gPSBkb20ucGFyZW50Tm9kZSBhcyBEb21FbGVtZW50O1xuICAgICAgfVxuICAgIH1cbiAgICBjb21wb25lbnRbVmFseXJpYW5TeW1ib2xdLmV2ZW50TGlzdGVuZXIgPSBldmVudExpc3RlbmVyO1xuICB9XG5cbiAgY29tcG9uZW50W1ZhbHlyaWFuU3ltYm9sXS5jb21wb25lbnQgPSB2bm9kZUNvbXBvbmVudDtcbiAgY29tcG9uZW50W1ZhbHlyaWFuU3ltYm9sXS5jb250YWluZXIgPSBhcHBDb250YWluZXI7XG4gIGNvbXBvbmVudFtWYWx5cmlhblN5bWJvbF0ubWFpblZub2RlID0gZG9tVG9Wbm9kZShhcHBDb250YWluZXIpO1xuXG4gIC8vIHVwZGF0ZVxuICByZXR1cm4gdXBkYXRlKGNvbXBvbmVudCk7XG59XG5cbmZ1bmN0aW9uIGNhbGxDbGVhbnVwKHZhbHlyaWFuQXBwOiBWYWx5cmlhbkFwcCkge1xuICBmb3IgKGxldCBpID0gMDsgaSA8IHZhbHlyaWFuQXBwLm9uQ2xlYW51cC5sZW5ndGg7IGkrKykge1xuICAgIHZhbHlyaWFuQXBwLm9uQ2xlYW51cFtpXSgpO1xuICB9XG4gIHZhbHlyaWFuQXBwLm9uQ2xlYW51cCA9IFtdO1xufVxuXG5mdW5jdGlvbiBjYWxsVW5tb3VudCh2YWx5cmlhbkFwcDogVmFseXJpYW5BcHApIHtcbiAgZm9yIChsZXQgaSA9IDA7IGkgPCB2YWx5cmlhbkFwcC5vblVubW91bnQubGVuZ3RoOyBpKyspIHtcbiAgICB2YWx5cmlhbkFwcC5vblVubW91bnRbaV0oKTtcbiAgfVxuICB2YWx5cmlhbkFwcC5vblVubW91bnQgPSBbXTtcbn1cblxuZnVuY3Rpb24gY2FsbE1vdW50KHZhbHlyaWFuQXBwOiBWYWx5cmlhbkFwcCkge1xuICBmb3IgKGxldCBpID0gMDsgaSA8IHZhbHlyaWFuQXBwLm9uTW91bnQubGVuZ3RoOyBpKyspIHtcbiAgICB2YWx5cmlhbkFwcC5vbk1vdW50W2ldKCk7XG4gIH1cbiAgdmFseXJpYW5BcHAub25Nb3VudCA9IFtdO1xufVxuXG5mdW5jdGlvbiBjYWxsVXBkYXRlKHZhbHlyaWFuQXBwOiBWYWx5cmlhbkFwcCkge1xuICBmb3IgKGxldCBpID0gMDsgaSA8IHZhbHlyaWFuQXBwLm9uVXBkYXRlLmxlbmd0aDsgaSsrKSB7XG4gICAgdmFseXJpYW5BcHAub25VcGRhdGVbaV0oKTtcbiAgfVxuICB2YWx5cmlhbkFwcC5vblVwZGF0ZSA9IFtdO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gdXBkYXRlKGNvbXBvbmVudD86IFZhbHlyaWFuQ29tcG9uZW50IHwgSVZub2RlKTogdm9pZCB8IHN0cmluZyB7XG4gIGlmIChjb21wb25lbnQgJiYgY29tcG9uZW50W1ZhbHlyaWFuU3ltYm9sXSkge1xuICAgIGxldCB2YWx5cmlhbkFwcCA9IGNvbXBvbmVudFtWYWx5cmlhblN5bWJvbF07XG4gICAgY3VycmVudC5hcHAgPSB2YWx5cmlhbkFwcDtcbiAgICB2YWx5cmlhbkFwcC5vbkNsZWFudXAubGVuZ3RoICYmIGNhbGxDbGVhbnVwKHZhbHlyaWFuQXBwKTtcbiAgICBsZXQgb2xkVm5vZGU6IFZub2RlV2l0aERvbSB8IG51bGwgPSB2YWx5cmlhbkFwcC5tYWluVm5vZGUgYXMgVm5vZGVXaXRoRG9tO1xuICAgIHZhbHlyaWFuQXBwLm1haW5Wbm9kZSA9IG5ldyBWbm9kZSh2YWx5cmlhbkFwcC5tYWluVm5vZGUudGFnLCB2YWx5cmlhbkFwcC5tYWluVm5vZGUucHJvcHMsIFt2YWx5cmlhbkFwcC5jb21wb25lbnRdKSBhcyBWbm9kZVdpdGhEb207XG4gICAgdmFseXJpYW5BcHAubWFpblZub2RlLmRvbSA9IG9sZFZub2RlLmRvbTtcbiAgICBwYXRjaCh2YWx5cmlhbkFwcC5tYWluVm5vZGUsIG9sZFZub2RlLCB2YWx5cmlhbkFwcCk7XG4gICAgb2xkVm5vZGUgPSBudWxsO1xuICAgIGlmICh2YWx5cmlhbkFwcC5pc01vdW50ZWQgPT09IGZhbHNlKSB7XG4gICAgICB2YWx5cmlhbkFwcC5vbk1vdW50Lmxlbmd0aCAmJiBjYWxsTW91bnQodmFseXJpYW5BcHApO1xuICAgICAgdmFseXJpYW5BcHAuaXNNb3VudGVkID0gdHJ1ZTtcbiAgICB9IGVsc2Uge1xuICAgICAgdmFseXJpYW5BcHAub25VcGRhdGUubGVuZ3RoICYmIGNhbGxVcGRhdGUodmFseXJpYW5BcHApO1xuICAgIH1cblxuICAgIGlmIChpc05vZGVKcykge1xuICAgICAgcmV0dXJuIHZhbHlyaWFuQXBwLm1haW5Wbm9kZS5kb20uaW5uZXJIVE1MO1xuICAgIH1cbiAgfVxufVxuXG5leHBvcnQgZnVuY3Rpb24gdW5tb3VudChjb21wb25lbnQ/OiBWYWx5cmlhbkNvbXBvbmVudCB8IElWbm9kZSk6IHZvaWQgfCBzdHJpbmcge1xuICBpZiAoIWNvbXBvbmVudCB8fCAhY29tcG9uZW50W1ZhbHlyaWFuU3ltYm9sXSkge1xuICAgIHJldHVybjtcbiAgfVxuXG4gIGxldCB2YWx5cmlhbkFwcCA9IGNvbXBvbmVudFtWYWx5cmlhblN5bWJvbF0gYXMgTW91bnRlZFZhbHlyaWFuQXBwO1xuXG4gIGlmICh2YWx5cmlhbkFwcC5pc01vdW50ZWQpIHtcbiAgICB2YWx5cmlhbkFwcC5vbkNsZWFudXAubGVuZ3RoICYmIGNhbGxDbGVhbnVwKHZhbHlyaWFuQXBwKTtcbiAgICB2YWx5cmlhbkFwcC5vblVubW91bnQubGVuZ3RoICYmIGNhbGxVbm1vdW50KHZhbHlyaWFuQXBwKTtcbiAgICBsZXQgb2xkVm5vZGU6IFZub2RlV2l0aERvbSB8IG51bGwgPSB2YWx5cmlhbkFwcC5tYWluVm5vZGUgYXMgVm5vZGVXaXRoRG9tO1xuICAgIHZhbHlyaWFuQXBwLm1haW5Wbm9kZSA9IG5ldyBWbm9kZSh2YWx5cmlhbkFwcC5tYWluVm5vZGUudGFnLCB2YWx5cmlhbkFwcC5tYWluVm5vZGUucHJvcHMsIFtdKSBhcyBWbm9kZVdpdGhEb207XG4gICAgdmFseXJpYW5BcHAubWFpblZub2RlLmRvbSA9IG9sZFZub2RlLmRvbTtcbiAgICB2YWx5cmlhbkFwcC5tYWluVm5vZGUuaXNTVkcgPSBvbGRWbm9kZS5pc1NWRztcbiAgICBwYXRjaCh2YWx5cmlhbkFwcC5tYWluVm5vZGUsIG9sZFZub2RlLCB2YWx5cmlhbkFwcCk7XG4gICAgb2xkVm5vZGUgPSBudWxsO1xuXG4gICAgaWYgKGlzTm9kZUpzKSB7XG4gICAgICByZXR1cm4gdmFseXJpYW5BcHAubWFpblZub2RlLmRvbS5pbm5lckhUTUw7XG4gICAgfVxuXG4gICAgKHZhbHlyaWFuQXBwIGFzIGFueSkgPSBudWxsO1xuICAgIFJlZmxlY3QuZGVsZXRlUHJvcGVydHkoY29tcG9uZW50LCBWYWx5cmlhblN5bWJvbCk7XG4gIH1cbn1cblxubGV0IGVtcHR5Vm5vZGUgPSBuZXcgVm5vZGUoXCJfX2VtcHR5X19cIiwge30sIFtdKTtcblxuZnVuY3Rpb24gb25yZW1vdmUodm5vZGU6IElWbm9kZSkge1xuICBmb3IgKGxldCBpID0gMDsgaSA8IHZub2RlLmNoaWxkcmVuLmxlbmd0aDsgaSsrKSB7XG4gICAgdm5vZGUuY2hpbGRyZW5baV0udGFnICE9PSBUZXh0U3RyaW5nICYmIG9ucmVtb3ZlKHZub2RlLmNoaWxkcmVuW2ldKTtcbiAgfVxuXG4gIHZub2RlLnByb3BzLm9ucmVtb3ZlICYmIHZub2RlLnByb3BzLm9ucmVtb3ZlKHZub2RlKTtcbn1cblxuZnVuY3Rpb24gc2hhcmVkU2V0QXR0cmlidXRlKHByb3A6IHN0cmluZywgdmFsdWU6IGFueSwgdm5vZGU6IFZub2RlV2l0aERvbSwgb2xkVm5vZGU/OiBWbm9kZVdpdGhEb20pOiB2b2lkIHwgYm9vbGVhbiB7XG4gIC8vIEl0IGlzIGEgcmVzZXJ2ZWQgcHJvcFxuICBpZiAocmVzZXJ2ZWRQcm9wc1twcm9wXSkge1xuICAgIC8vIElmIGl0IGlzIGEgZGlyZWN0aXZlIG5hbWUgY2FsbCB0aGUgZGlyZWN0aXZlXG4gICAgaWYgKGRpcmVjdGl2ZXNbcHJvcF0pIHtcbiAgICAgIHJldHVybiBkaXJlY3RpdmVzW3Byb3BdKHZub2RlLnByb3BzW3Byb3BdLCB2bm9kZSwgb2xkVm5vZGUpO1xuICAgIH1cblxuICAgIHJldHVybjtcbiAgfVxuXG4gIC8vIEl0IGlzIG5vdCBhIHJlc2VydmVkIHByb3Agc28gd2UgYWRkIGl0IHRvIHRoZSBkb21cbiAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gXCJmdW5jdGlvblwiKSB7XG4gICAgbGV0IHZhbHlyaWFuQXBwID0gY3VycmVudC5hcHAgYXMgTW91bnRlZFZhbHlyaWFuQXBwO1xuICAgIGlmIChwcm9wIGluIHZhbHlyaWFuQXBwLmV2ZW50TGlzdGVuZXJOYW1lcyA9PT0gZmFsc2UpIHtcbiAgICAgIHZhbHlyaWFuQXBwLmV2ZW50TGlzdGVuZXJOYW1lc1twcm9wXSA9IHRydWU7XG4gICAgICB2YWx5cmlhbkFwcC5jb250YWluZXIuYWRkRXZlbnRMaXN0ZW5lcihwcm9wLnNsaWNlKDIpLCB2YWx5cmlhbkFwcC5ldmVudExpc3RlbmVyKTtcbiAgICB9XG4gICAgdm5vZGUuZG9tW2B2LSR7cHJvcH1gXSA9IHZhbHVlO1xuICAgIHJldHVybjtcbiAgfVxuXG4gIGlmIChwcm9wIGluIHZub2RlLmRvbSAmJiB2bm9kZS5pc1NWRyA9PT0gZmFsc2UpIHtcbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgZXFlcWVxXG4gICAgaWYgKHZub2RlLmRvbVtwcm9wXSAhPSB2YWx1ZSkge1xuICAgICAgdm5vZGUuZG9tW3Byb3BdID0gdmFsdWU7XG4gICAgfVxuICAgIHJldHVybjtcbiAgfVxuXG4gIC8vIFVzZSBzZXQgYXR0cmlidXRlXG4gIGlmICghb2xkVm5vZGUgfHwgb2xkVm5vZGUucHJvcHNbcHJvcF0gIT09IHZhbHVlKSB7XG4gICAgaWYgKHZhbHVlID09PSBmYWxzZSkge1xuICAgICAgdm5vZGUuZG9tLnJlbW92ZUF0dHJpYnV0ZShwcm9wKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdm5vZGUuZG9tLnNldEF0dHJpYnV0ZShwcm9wLCB2YWx1ZSk7XG4gICAgfVxuICB9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBzZXRBdHRyaWJ1dGUobmFtZTogc3RyaW5nLCB2YWx1ZTogYW55LCB2bm9kZTogVm5vZGVXaXRoRG9tLCBvbGRWbm9kZT86IFZub2RlV2l0aERvbSkge1xuICB2bm9kZS5wcm9wc1tuYW1lXSA9IHZhbHVlO1xuXG4gIHNoYXJlZFNldEF0dHJpYnV0ZShuYW1lLCB2YWx1ZSwgdm5vZGUsIG9sZFZub2RlKTtcbn1cblxuZnVuY3Rpb24gc2V0QXR0cmlidXRlcyh2bm9kZTogVm5vZGVXaXRoRG9tLCBvbGRWbm9kZT86IFZub2RlV2l0aERvbSkge1xuICBmb3IgKGxldCBwcm9wIGluIHZub2RlLnByb3BzKSB7XG4gICAgaWYgKHNoYXJlZFNldEF0dHJpYnV0ZShwcm9wLCB2bm9kZS5wcm9wc1twcm9wXSwgdm5vZGUsIG9sZFZub2RlKSA9PT0gZmFsc2UpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gIH1cblxuICBpZiAob2xkVm5vZGUpIHtcbiAgICBmb3IgKGxldCBwcm9wIGluIG9sZFZub2RlLnByb3BzKSB7XG4gICAgICBpZiAocHJvcCBpbiB2bm9kZS5wcm9wcyA9PT0gZmFsc2UgJiYgdHlwZW9mIG9sZFZub2RlLnByb3BzW3Byb3BdICE9PSBcImZ1bmN0aW9uXCIgJiYgcHJvcCBpbiByZXNlcnZlZFByb3BzID09PSBmYWxzZSkge1xuICAgICAgICBpZiAocHJvcCBpbiBvbGRWbm9kZS5kb20gJiYgdm5vZGUuaXNTVkcgPT09IGZhbHNlKSB7XG4gICAgICAgICAgb2xkVm5vZGUuZG9tW3Byb3BdID0gbnVsbDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBvbGRWbm9kZS5kb20ucmVtb3ZlQXR0cmlidXRlKHByb3ApO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICB9XG59XG5cbi8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBjb21wbGV4aXR5XG5mdW5jdGlvbiBwYXRjaChuZXdWbm9kZTogVm5vZGVXaXRoRG9tLCBvbGRWbm9kZTogVm5vZGVXaXRoRG9tIHwgSVZub2RlID0gZW1wdHlWbm9kZSwgdmFseXJpYW5BcHA6IE1vdW50ZWRWYWx5cmlhbkFwcCkge1xuICBjdXJyZW50LnZub2RlID0gbmV3Vm5vZGU7XG4gIGN1cnJlbnQub2xkVm5vZGUgPSBvbGRWbm9kZSA9PT0gZW1wdHlWbm9kZSA/IFVuZCA6IChvbGRWbm9kZSBhcyBWbm9kZVdpdGhEb20pO1xuICBsZXQgbmV3VHJlZSA9IG5ld1Zub2RlLmNoaWxkcmVuO1xuICBsZXQgb2xkVHJlZSA9IG9sZFZub2RlLmNoaWxkcmVuO1xuXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgbmV3VHJlZS5sZW5ndGg7IGkrKykge1xuICAgIGxldCBjaGlsZFZub2RlID0gbmV3VHJlZVtpXTtcbiAgICBpZiAoY2hpbGRWbm9kZSBpbnN0YW5jZW9mIFZub2RlKSB7XG4gICAgICBpZiAoY2hpbGRWbm9kZS50YWcgIT09IFRleHRTdHJpbmcpIHtcbiAgICAgICAgaWYgKGNoaWxkVm5vZGUudGFnID09PSBDb21wb25lbnRTdHJpbmcpIHtcbiAgICAgICAgICBsZXQgY29tcG9uZW50ID0gY2hpbGRWbm9kZS5jb21wb25lbnQgYXMgVmFseXJpYW5Db21wb25lbnQ7XG4gICAgICAgICAgY3VycmVudC5jb21wb25lbnQgPSBjb21wb25lbnQ7XG4gICAgICAgICAgbGV0IHJlc3VsdCA9IChcInZpZXdcIiBpbiBjb21wb25lbnQgPyBjb21wb25lbnQudmlldyA6IGNvbXBvbmVudCkuY2FsbChjb21wb25lbnQsIGNoaWxkVm5vZGUucHJvcHMsIC4uLmNoaWxkVm5vZGUuY2hpbGRyZW4pO1xuXG4gICAgICAgICAgbmV3VHJlZS5zcGxpY2UoaS0tLCAxLCByZXN1bHQpO1xuICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICB9XG4gICAgICAgIGNoaWxkVm5vZGUuaXNTVkcgPSBuZXdWbm9kZS5pc1NWRyB8fCBjaGlsZFZub2RlLnRhZyA9PT0gXCJzdmdcIjtcbiAgICAgIH1cbiAgICB9IGVsc2UgaWYgKEFycmF5LmlzQXJyYXkoY2hpbGRWbm9kZSkpIHtcbiAgICAgIG5ld1RyZWUuc3BsaWNlKGktLSwgMSwgLi4uY2hpbGRWbm9kZSk7XG4gICAgfSBlbHNlIGlmIChjaGlsZFZub2RlID09PSBudWxsIHx8IGNoaWxkVm5vZGUgPT09IFVuZCkge1xuICAgICAgbmV3VHJlZS5zcGxpY2UoaS0tLCAxKTtcbiAgICB9IGVsc2Uge1xuICAgICAgbmV3VHJlZVtpXSA9IG5ldyBWbm9kZShUZXh0U3RyaW5nLCB7fSwgW10pO1xuICAgICAgbmV3VHJlZVtpXS5ub2RlVmFsdWUgPSBjaGlsZFZub2RlO1xuICAgIH1cbiAgfVxuXG4gIGxldCBvbGRUcmVlTGVuZ3RoID0gb2xkVHJlZS5sZW5ndGg7XG4gIGxldCBuZXdUcmVlTGVuZ3RoID0gbmV3VHJlZS5sZW5ndGg7XG5cbiAgLy8gSWYgbmV3IHRyZWUgaXMgZW1wdHksIHJlbW92ZSBhbGwgb2xkIG5vZGVzXG4gIGlmIChuZXdUcmVlTGVuZ3RoID09PSAwKSB7XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBvbGRUcmVlTGVuZ3RoOyBpKyspIHtcbiAgICAgIG9sZFRyZWVbaV0udGFnICE9PSBUZXh0U3RyaW5nICYmIG9ucmVtb3ZlKG9sZFRyZWVbaV0pO1xuICAgIH1cblxuICAgIG5ld1Zub2RlLmRvbS50ZXh0Q29udGVudCA9IFwiXCI7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgLy8gSWYgdGhlIHRyZWUgaXMga2V5ZWQgbGlzdCBhbmQgaXMgbm90IGZpcnN0IHJlbmRlciBhbmQgb2xkIHRyZWUgaXMga2V5ZWQgbGlzdCB0b29cbiAgaWYgKG9sZFRyZWVMZW5ndGggJiYgXCJrZXlcIiBpbiBuZXdUcmVlWzBdLnByb3BzICYmIFwia2V5XCIgaW4gb2xkVHJlZVswXS5wcm9wcykge1xuICAgIGxldCBvbGRLZXllZExpc3Q6IHtba2V5OiBzdHJpbmddOiBudW1iZXJ9ID0ge307XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBvbGRUcmVlTGVuZ3RoOyBpKyspIHtcbiAgICAgIG9sZEtleWVkTGlzdFtvbGRUcmVlW2ldLnByb3BzLmtleV0gPSBpO1xuICAgIH1cblxuICAgIGxldCBuZXdLZXllZExpc3Q6IHtba2V5OiBzdHJpbmddOiBudW1iZXJ9ID0ge307XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBuZXdUcmVlTGVuZ3RoOyBpKyspIHtcbiAgICAgIG5ld0tleWVkTGlzdFtuZXdUcmVlW2ldLnByb3BzLmtleV0gPSBpO1xuICAgIH1cblxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbmV3VHJlZUxlbmd0aDsgaSsrKSB7XG4gICAgICBsZXQgY2hpbGRWbm9kZSA9IG5ld1RyZWVbaV07XG4gICAgICBsZXQgb2xkQ2hpbGRWbm9kZSA9IG9sZFRyZWVbb2xkS2V5ZWRMaXN0W2NoaWxkVm5vZGUucHJvcHMua2V5XV07XG4gICAgICBsZXQgc2hvdWxkUGF0Y2ggPSB0cnVlO1xuXG4gICAgICBpZiAob2xkQ2hpbGRWbm9kZSkge1xuICAgICAgICBjaGlsZFZub2RlLmRvbSA9IG9sZENoaWxkVm5vZGUuZG9tO1xuICAgICAgICBpZiAoXCJ2LW9uY2VcIiBpbiBjaGlsZFZub2RlLnByb3BzIHx8IChjaGlsZFZub2RlLnByb3BzLnNob3VsZHVwZGF0ZSAmJiBjaGlsZFZub2RlLnByb3BzLnNob3VsZHVwZGF0ZShjaGlsZFZub2RlLCBvbGRDaGlsZFZub2RlKSA9PT0gZmFsc2UpKSB7XG4gICAgICAgICAgLy8gc2tpcCB0aGlzIHBhdGNoXG4gICAgICAgICAgY2hpbGRWbm9kZS5jaGlsZHJlbiA9IG9sZENoaWxkVm5vZGUuY2hpbGRyZW47XG4gICAgICAgICAgc2hvdWxkUGF0Y2ggPSBmYWxzZTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBzZXRBdHRyaWJ1dGVzKGNoaWxkVm5vZGUsIG9sZENoaWxkVm5vZGUpO1xuICAgICAgICAgIGlmICh2YWx5cmlhbkFwcC5pc01vdW50ZWQpIHtcbiAgICAgICAgICAgIGNoaWxkVm5vZGUucHJvcHMub251cGRhdGUgJiYgY2hpbGRWbm9kZS5wcm9wcy5vbnVwZGF0ZShjaGlsZFZub2RlLCBvbGRDaGlsZFZub2RlKTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgY2hpbGRWbm9kZS5wcm9wcy5vbmNyZWF0ZSAmJiBjaGlsZFZub2RlLnByb3BzLm9uY3JlYXRlKGNoaWxkVm5vZGUpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgY2hpbGRWbm9kZS5kb20gPSBjcmVhdGVEb21FbGVtZW50KGNoaWxkVm5vZGUudGFnLCBjaGlsZFZub2RlLmlzU1ZHKTtcbiAgICAgICAgc2V0QXR0cmlidXRlcyhjaGlsZFZub2RlKTtcbiAgICAgICAgY2hpbGRWbm9kZS5wcm9wcy5vbmNyZWF0ZSAmJiBjaGlsZFZub2RlLnByb3BzLm9uY3JlYXRlKGNoaWxkVm5vZGUpO1xuICAgICAgfVxuXG4gICAgICBpZiAobmV3Vm5vZGUuZG9tLmNoaWxkTm9kZXNbaV0gPT09IFVuZCkge1xuICAgICAgICBuZXdWbm9kZS5kb20uYXBwZW5kQ2hpbGQoY2hpbGRWbm9kZS5kb20pO1xuICAgICAgfSBlbHNlIGlmIChuZXdWbm9kZS5kb20uY2hpbGROb2Rlc1tpXSAhPT0gY2hpbGRWbm9kZS5kb20pIHtcbiAgICAgICAgb2xkVHJlZVtpXSAmJiBuZXdLZXllZExpc3Rbb2xkVHJlZVtpXS5wcm9wcy5rZXldID09PSBVbmQgJiYgb25yZW1vdmUob2xkVHJlZVtpXSk7XG4gICAgICAgIG5ld1Zub2RlLmRvbS5yZXBsYWNlQ2hpbGQoY2hpbGRWbm9kZS5kb20sIG5ld1Zub2RlLmRvbS5jaGlsZE5vZGVzW2ldKTtcbiAgICAgIH1cblxuICAgICAgc2hvdWxkUGF0Y2ggJiYgcGF0Y2goY2hpbGRWbm9kZSwgb2xkQ2hpbGRWbm9kZSwgdmFseXJpYW5BcHApO1xuICAgIH1cblxuICAgIC8vIEZvciB0aGUgcmVzdCBvZiB0aGUgY2hpbGRyZW4sIHdlIHNob3VsZCByZW1vdmUgdGhlbVxuICAgIGZvciAobGV0IGkgPSBuZXdUcmVlTGVuZ3RoOyBpIDwgb2xkVHJlZUxlbmd0aDsgaSsrKSB7XG4gICAgICBpZiAobmV3S2V5ZWRMaXN0W29sZFRyZWVbaV0ucHJvcHMua2V5XSA9PT0gVW5kKSB7XG4gICAgICAgIGxldCBvbGRDaGlsZFZub2RlID0gb2xkVHJlZVtpXTtcbiAgICAgICAgb25yZW1vdmUob2xkQ2hpbGRWbm9kZSk7XG4gICAgICAgIG9sZENoaWxkVm5vZGUuZG9tLnBhcmVudE5vZGUgJiYgb2xkQ2hpbGRWbm9kZS5kb20ucGFyZW50Tm9kZS5yZW1vdmVDaGlsZChvbGRDaGlsZFZub2RlLmRvbSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuO1xuICB9XG5cbiAgLy8gSWYgbmV3IHRyZWUgYW5kIG9sZCB0cmVlIGhhdmUgbW9yZSB0aGFuIG9uZSBjaGlsZCwgd2Ugc2hvdWxkIHVwZGF0ZSB0aGUgZG9tXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgbmV3VHJlZUxlbmd0aDsgaSsrKSB7XG4gICAgbGV0IG5ld0NoaWxkVm5vZGUgPSBuZXdUcmVlW2ldO1xuXG4gICAgLy8gT2xkIGNoaWxkIGV4aXN0c1xuICAgIGlmIChpIDwgb2xkVHJlZUxlbmd0aCkge1xuICAgICAgbGV0IG9sZENoaWxkVm5vZGUgPSBvbGRUcmVlW2ldO1xuICAgICAgLy8gTmV3IGNoaWxkIGlzIGEgdGV4dCBub2RlXG4gICAgICBpZiAobmV3Q2hpbGRWbm9kZS50YWcgPT09IFRleHRTdHJpbmcpIHtcbiAgICAgICAgLy8gT2xkIGNoaWxkIGlzIGEgdGV4dCBub2RlXG4gICAgICAgIGlmIChvbGRDaGlsZFZub2RlLnRhZyA9PT0gVGV4dFN0cmluZykge1xuICAgICAgICAgIG5ld0NoaWxkVm5vZGUuZG9tID0gb2xkQ2hpbGRWbm9kZS5kb207XG4gICAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGVxZXFlcVxuICAgICAgICAgIGlmIChuZXdDaGlsZFZub2RlLmRvbS5ub2RlVmFsdWUgIT0gbmV3Q2hpbGRWbm9kZS5ub2RlVmFsdWUpIHtcbiAgICAgICAgICAgIG5ld0NoaWxkVm5vZGUuZG9tLm5vZGVWYWx1ZSA9IG5ld0NoaWxkVm5vZGUubm9kZVZhbHVlIGFzIHN0cmluZztcbiAgICAgICAgICB9XG4gICAgICAgICAgY29udGludWU7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBPbGQgY2hpbGQgaXMgYSBub3JtYWwgbm9kZVxuICAgICAgICBuZXdDaGlsZFZub2RlLmRvbSA9IGRvY3VtZW50LmNyZWF0ZVRleHROb2RlKG5ld0NoaWxkVm5vZGUubm9kZVZhbHVlIGFzIHN0cmluZykgYXMgdW5rbm93biBhcyBEb21FbGVtZW50O1xuICAgICAgICBvbnJlbW92ZShvbGRDaGlsZFZub2RlKTtcbiAgICAgICAgbmV3Vm5vZGUuZG9tLnJlcGxhY2VDaGlsZChuZXdDaGlsZFZub2RlLmRvbSwgb2xkQ2hpbGRWbm9kZS5kb20pO1xuXG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuXG4gICAgICAvLyBOZXcgY2hpbGQgaXMgYSBub3JtYWwgbm9kZVxuICAgICAgLy8gT2xkIGNoaWxkIGlzIHRoZSBzYW1lIHR5cGUgYXMgbmV3IGNoaWxkXG4gICAgICBpZiAob2xkQ2hpbGRWbm9kZS50YWcgPT09IG5ld0NoaWxkVm5vZGUudGFnKSB7XG4gICAgICAgIG5ld0NoaWxkVm5vZGUuZG9tID0gb2xkQ2hpbGRWbm9kZS5kb207XG4gICAgICAgIC8vIElmIHdlIGhhdmUgYSB2LW9uY2UgZGlyZWN0aXZlIG9yIGEgc2hvdWxkdXBkYXRlIG1ldGhvZCB0aGF0IHJldHVybnMgZmFsc2UsIHdlIHNraXAgdGhlIHVwZGF0ZVxuICAgICAgICBpZiAobmV3Q2hpbGRWbm9kZS5wcm9wc1tcInYtb25jZVwiXSB8fCAobmV3Q2hpbGRWbm9kZS5wcm9wcy5zaG91bGR1cGRhdGUgJiYgbmV3Q2hpbGRWbm9kZS5wcm9wcy5zaG91bGR1cGRhdGUobmV3Q2hpbGRWbm9kZSwgb2xkQ2hpbGRWbm9kZSkgPT09IGZhbHNlKSkge1xuICAgICAgICAgIG5ld0NoaWxkVm5vZGUuY2hpbGRyZW4gPSBvbGRDaGlsZFZub2RlLmNoaWxkcmVuO1xuICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gV2UgdXBkYXRlIHRoZSBkb20gZWxlbWVudFxuICAgICAgICBzZXRBdHRyaWJ1dGVzKG5ld0NoaWxkVm5vZGUsIG9sZENoaWxkVm5vZGUpO1xuICAgICAgICBpZiAodmFseXJpYW5BcHAuaXNNb3VudGVkKSB7XG4gICAgICAgICAgbmV3Q2hpbGRWbm9kZS5wcm9wcy5vbnVwZGF0ZSAmJiBuZXdDaGlsZFZub2RlLnByb3BzLm9udXBkYXRlKG5ld0NoaWxkVm5vZGUsIG9sZENoaWxkVm5vZGUpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIG5ld0NoaWxkVm5vZGUucHJvcHMub25jcmVhdGUgJiYgbmV3Q2hpbGRWbm9kZS5wcm9wcy5vbmNyZWF0ZShuZXdDaGlsZFZub2RlKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHBhdGNoKG5ld0NoaWxkVm5vZGUsIG9sZENoaWxkVm5vZGUsIHZhbHlyaWFuQXBwKTtcbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG5cbiAgICAgIC8vIE9sZCBjaGlsZCBpcyBvZiBhIGRpZmZlcmVudCB0eXBlIHRoYW4gbmV3IGNoaWxkXG4gICAgICBuZXdDaGlsZFZub2RlLmRvbSA9IGNyZWF0ZURvbUVsZW1lbnQobmV3Q2hpbGRWbm9kZS50YWcsIG5ld0NoaWxkVm5vZGUuaXNTVkcpO1xuICAgICAgc2V0QXR0cmlidXRlcyhuZXdDaGlsZFZub2RlKTtcbiAgICAgIG9sZENoaWxkVm5vZGUudGFnICE9PSBUZXh0U3RyaW5nICYmIG9ucmVtb3ZlKG9sZENoaWxkVm5vZGUpO1xuICAgICAgbmV3Q2hpbGRWbm9kZS5wcm9wcy5vbmNyZWF0ZSAmJiBuZXdDaGlsZFZub2RlLnByb3BzLm9uY3JlYXRlKG5ld0NoaWxkVm5vZGUpO1xuICAgICAgbmV3Vm5vZGUuZG9tLnJlcGxhY2VDaGlsZChuZXdDaGlsZFZub2RlLmRvbSwgb2xkQ2hpbGRWbm9kZS5kb20pO1xuICAgICAgcGF0Y2gobmV3Q2hpbGRWbm9kZSwgZW1wdHlWbm9kZSwgdmFseXJpYW5BcHApO1xuICAgICAgY29udGludWU7XG4gICAgfVxuXG4gICAgLy8gT2xkIGNoaWxkIGRvZXMgbm90IGV4aXN0c1xuICAgIC8vIE5ldyBjaGlsZCBpcyBhIHRleHQgbm9kZVxuICAgIGlmIChuZXdDaGlsZFZub2RlLnRhZyA9PT0gVGV4dFN0cmluZykge1xuICAgICAgbmV3Q2hpbGRWbm9kZS5kb20gPSBkb2N1bWVudC5jcmVhdGVUZXh0Tm9kZShuZXdDaGlsZFZub2RlLm5vZGVWYWx1ZSBhcyBzdHJpbmcpIGFzIHVua25vd24gYXMgRG9tRWxlbWVudDtcbiAgICAgIG5ld1Zub2RlLmRvbS5hcHBlbmRDaGlsZChuZXdDaGlsZFZub2RlLmRvbSk7XG4gICAgICBjb250aW51ZTtcbiAgICB9XG5cbiAgICAvLyBOZXcgY2hpbGQgaXMgYSBub3JtYWwgbm9kZVxuICAgIG5ld0NoaWxkVm5vZGUuZG9tID0gY3JlYXRlRG9tRWxlbWVudChuZXdDaGlsZFZub2RlLnRhZywgbmV3Q2hpbGRWbm9kZS5pc1NWRyk7XG4gICAgc2V0QXR0cmlidXRlcyhuZXdDaGlsZFZub2RlKTtcbiAgICBuZXdWbm9kZS5kb20uYXBwZW5kQ2hpbGQobmV3Q2hpbGRWbm9kZS5kb20pO1xuICAgIG5ld0NoaWxkVm5vZGUucHJvcHMub25jcmVhdGUgJiYgbmV3Q2hpbGRWbm9kZS5wcm9wcy5vbmNyZWF0ZShuZXdDaGlsZFZub2RlKTtcbiAgICBwYXRjaChuZXdDaGlsZFZub2RlLCBlbXB0eVZub2RlLCB2YWx5cmlhbkFwcCk7XG4gIH1cblxuICAvLyBGb3IgdGhlIHJlc3Qgb2YgdGhlIGNoaWxkcmVuLCB3ZSBzaG91bGQgcmVtb3ZlIHRoZW1cbiAgZm9yIChsZXQgaSA9IG5ld1RyZWVMZW5ndGg7IGkgPCBvbGRUcmVlTGVuZ3RoOyBpKyspIHtcbiAgICBsZXQgb2xkQ2hpbGRWbm9kZSA9IG9sZFRyZWVbaV07XG4gICAgb2xkQ2hpbGRWbm9kZS50YWcgIT09IFRleHRTdHJpbmcgJiYgb25yZW1vdmUob2xkQ2hpbGRWbm9kZSk7XG4gICAgb2xkQ2hpbGRWbm9kZS5kb20ucGFyZW50Tm9kZSAmJiBvbGRDaGlsZFZub2RlLmRvbS5wYXJlbnROb2RlLnJlbW92ZUNoaWxkKG9sZENoaWxkVm5vZGUuZG9tKTtcbiAgfVxufVxuXG4vKioqIERpcmVjdGl2ZXMgKioqL1xuXG5leHBvcnQgZnVuY3Rpb24gZGlyZWN0aXZlKG5hbWU6IHN0cmluZywgZGlyZWN0aXZlOiBEaXJlY3RpdmUpIHtcbiAgbGV0IGZ1bGxOYW1lID0gYHYtJHtuYW1lfWA7XG4gIGRpcmVjdGl2ZXNbZnVsbE5hbWVdID0gZGlyZWN0aXZlO1xuICByZXNlcnZlZFByb3BzW2Z1bGxOYW1lXSA9IHRydWU7XG59XG5cbmZ1bmN0aW9uIGhpZGVEaXJlY3RpdmUodGVzdDogYm9vbGVhbik6IERpcmVjdGl2ZSB7XG4gIHJldHVybiAoYm9vbDogYm9vbGVhbiwgdm5vZGU6IElWbm9kZSwgb2xkVm5vZGU/OiBJVm5vZGUpID0+IHtcbiAgICBsZXQgdmFsdWUgPSB0ZXN0ID8gYm9vbCA6ICFib29sO1xuICAgIGlmICh2YWx1ZSkge1xuICAgICAgbGV0IG5ld2RvbSA9IGRvY3VtZW50LmNyZWF0ZVRleHROb2RlKFwiXCIpO1xuICAgICAgaWYgKG9sZFZub2RlICYmIG9sZFZub2RlLmRvbSAmJiBvbGRWbm9kZS5kb20ucGFyZW50Tm9kZSkge1xuICAgICAgICBvbGRWbm9kZS50YWcgIT09IFRleHRTdHJpbmcgJiYgb25yZW1vdmUob2xkVm5vZGUpO1xuICAgICAgICBvbGRWbm9kZS5kb20ucGFyZW50Tm9kZS5yZXBsYWNlQ2hpbGQobmV3ZG9tLCBvbGRWbm9kZS5kb20pO1xuICAgICAgfVxuICAgICAgdm5vZGUudGFnID0gVGV4dFN0cmluZztcbiAgICAgIHZub2RlLmNoaWxkcmVuID0gW107XG4gICAgICB2bm9kZS5wcm9wcyA9IHt9O1xuICAgICAgdm5vZGUuZG9tID0gbmV3ZG9tIGFzIHVua25vd24gYXMgRG9tRWxlbWVudDtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gIH07XG59XG5cbmNvbnN0IGRpcmVjdGl2ZXM6IERpcmVjdGl2ZXMgPSB7XG4gIFwidi1pZlwiOiBoaWRlRGlyZWN0aXZlKGZhbHNlKSxcbiAgXCJ2LXVubGVzc1wiOiBoaWRlRGlyZWN0aXZlKHRydWUpLFxuICBcInYtZm9yXCI6IChzZXQ6IHVua25vd25bXSwgdm5vZGU6IFZub2RlV2l0aERvbSkgPT4ge1xuICAgIHZub2RlLmNoaWxkcmVuID0gc2V0Lm1hcCh2bm9kZS5jaGlsZHJlblswXSBhcyAodmFsdWU6IHVua25vd24pID0+IEZ1bmN0aW9uKTtcbiAgfSxcbiAgXCJ2LXNob3dcIjogKGJvb2w6IGJvb2xlYW4sIHZub2RlOiBWbm9kZVdpdGhEb20pID0+IHtcbiAgICAodm5vZGUuZG9tIGFzIHVua25vd24gYXMgeyBzdHlsZTogeyBkaXNwbGF5OiBzdHJpbmcgfSB9KS5zdHlsZS5kaXNwbGF5ID0gYm9vbCA/IFwiXCIgOiBcIm5vbmVcIjtcbiAgfSxcbiAgXCJ2LWNsYXNzXCI6IChjbGFzc2VzOiB7IFt4OiBzdHJpbmddOiBib29sZWFuIH0sIHZub2RlOiBWbm9kZVdpdGhEb20pID0+IHtcbiAgICBmb3IgKGxldCBuYW1lIGluIGNsYXNzZXMpIHtcbiAgICAgICh2bm9kZS5kb20gYXMgRG9tRWxlbWVudCkuY2xhc3NMaXN0LnRvZ2dsZShuYW1lLCBjbGFzc2VzW25hbWVdKTtcbiAgICB9XG4gIH0sXG4gIFwidi1odG1sXCI6IChodG1sOiBzdHJpbmcsIHZub2RlOiBWbm9kZVdpdGhEb20pID0+IHtcbiAgICB2bm9kZS5jaGlsZHJlbiA9IFt0cnVzdChodG1sKV07XG4gIH0sXG4gIFwidi1tb2RlbFwiOiAoW21vZGVsLCBwcm9wZXJ0eSwgZXZlbnRdOiBhbnlbXSwgdm5vZGU6IFZub2RlV2l0aERvbSwgb2xkVm5vZGU/OiBWbm9kZVdpdGhEb20pID0+IHtcbiAgICBsZXQgdmFsdWU7XG4gICAgbGV0IGhhbmRsZXI7XG4gICAgaWYgKHZub2RlLm5hbWUgPT09IFwiaW5wdXRcIikge1xuICAgICAgZXZlbnQgPSBldmVudCB8fCBcIm9uaW5wdXRcIjtcbiAgICAgIHN3aXRjaCAodm5vZGUucHJvcHMudHlwZSkge1xuICAgICAgICBjYXNlIFwiY2hlY2tib3hcIjoge1xuICAgICAgICAgIGlmIChBcnJheS5pc0FycmF5KG1vZGVsW3Byb3BlcnR5XSkpIHtcbiAgICAgICAgICAgIGhhbmRsZXIgPSAoZTogRXZlbnQpID0+IHtcbiAgICAgICAgICAgICAgbGV0IHZhbCA9IChlLnRhcmdldCBhcyBEb21FbGVtZW50ICYgUmVjb3JkPHN0cmluZywgYW55PikudmFsdWU7XG4gICAgICAgICAgICAgIGxldCBpZHggPSBtb2RlbFtwcm9wZXJ0eV0uaW5kZXhPZih2YWwpO1xuICAgICAgICAgICAgICBpZiAoaWR4ID09PSAtMSkge1xuICAgICAgICAgICAgICAgIG1vZGVsW3Byb3BlcnR5XS5wdXNoKHZhbCk7XG4gICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgbW9kZWxbcHJvcGVydHldLnNwbGljZShpZHgsIDEpO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgdmFsdWUgPSBtb2RlbFtwcm9wZXJ0eV0uaW5kZXhPZih2bm9kZS5kb20udmFsdWUpICE9PSAtMTtcbiAgICAgICAgICB9IGVsc2UgaWYgKFwidmFsdWVcIiBpbiB2bm9kZS5wcm9wcykge1xuICAgICAgICAgICAgaGFuZGxlciA9ICgpID0+IHtcbiAgICAgICAgICAgICAgaWYgKG1vZGVsW3Byb3BlcnR5XSA9PT0gdm5vZGUucHJvcHMudmFsdWUpIHtcbiAgICAgICAgICAgICAgICBtb2RlbFtwcm9wZXJ0eV0gPSBudWxsO1xuICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIG1vZGVsW3Byb3BlcnR5XSA9IHZub2RlLnByb3BzLnZhbHVlO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgdmFsdWUgPSBtb2RlbFtwcm9wZXJ0eV0gPT09IHZub2RlLnByb3BzLnZhbHVlO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBoYW5kbGVyID0gKCkgPT4gKG1vZGVsW3Byb3BlcnR5XSA9ICFtb2RlbFtwcm9wZXJ0eV0pO1xuICAgICAgICAgICAgdmFsdWUgPSBtb2RlbFtwcm9wZXJ0eV07XG4gICAgICAgICAgfVxuICAgICAgICAgIHNldEF0dHJpYnV0ZShcImNoZWNrZWRcIiwgdmFsdWUsIHZub2RlLCBvbGRWbm9kZSk7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICAgICAgY2FzZSBcInJhZGlvXCI6IHtcbiAgICAgICAgICBzZXRBdHRyaWJ1dGUoXCJjaGVja2VkXCIsIG1vZGVsW3Byb3BlcnR5XSA9PT0gdm5vZGUuZG9tLnZhbHVlLCB2bm9kZSwgb2xkVm5vZGUpO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgICAgIGRlZmF1bHQ6IHtcbiAgICAgICAgICBzZXRBdHRyaWJ1dGUoXCJ2YWx1ZVwiLCBtb2RlbFtwcm9wZXJ0eV0sIHZub2RlLCBvbGRWbm9kZSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9IGVsc2UgaWYgKHZub2RlLm5hbWUgPT09IFwic2VsZWN0XCIpIHtcbiAgICAgIGV2ZW50ID0gZXZlbnQgfHwgXCJvbmNsaWNrXCI7XG4gICAgICBpZiAodm5vZGUucHJvcHMubXVsdGlwbGUpIHtcbiAgICAgICAgaGFuZGxlciA9IChlOiBFdmVudCAmIFJlY29yZDxzdHJpbmcsIGFueT4pID0+IHtcbiAgICAgICAgICBsZXQgdmFsID0gKGUudGFyZ2V0IGFzIERvbUVsZW1lbnQgJiBSZWNvcmQ8c3RyaW5nLCBhbnk+KS52YWx1ZTtcbiAgICAgICAgICBpZiAoZS5jdHJsS2V5KSB7XG4gICAgICAgICAgICBsZXQgaWR4ID0gbW9kZWxbcHJvcGVydHldLmluZGV4T2YodmFsKTtcbiAgICAgICAgICAgIGlmIChpZHggPT09IC0xKSB7XG4gICAgICAgICAgICAgIG1vZGVsW3Byb3BlcnR5XS5wdXNoKHZhbCk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICBtb2RlbFtwcm9wZXJ0eV0uc3BsaWNlKGlkeCwgMSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIG1vZGVsW3Byb3BlcnR5XS5zcGxpY2UoMCwgbW9kZWxbcHJvcGVydHldLmxlbmd0aCk7XG4gICAgICAgICAgICBtb2RlbFtwcm9wZXJ0eV0ucHVzaCh2YWwpO1xuICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgdm5vZGUuY2hpbGRyZW4uZm9yRWFjaCgoY2hpbGQ6IElWbm9kZSkgPT4ge1xuICAgICAgICAgIGlmIChjaGlsZC50YWcgPT09IFwib3B0aW9uXCIpIHtcbiAgICAgICAgICAgIGxldCB2YWx1ZSA9IFwidmFsdWVcIiBpbiBjaGlsZC5wcm9wcyA/IGNoaWxkLnByb3BzLnZhbHVlIDogY2hpbGQuY2hpbGRyZW4uam9pbihcIlwiKS50cmltKCk7XG4gICAgICAgICAgICBjaGlsZC5wcm9wcy5zZWxlY3RlZCA9IG1vZGVsW3Byb3BlcnR5XS5pbmRleE9mKHZhbHVlKSAhPT0gLTE7XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHZub2RlLmNoaWxkcmVuLmZvckVhY2goKGNoaWxkOiBJVm5vZGUpID0+IHtcbiAgICAgICAgICBpZiAoY2hpbGQudGFnID09PSBcIm9wdGlvblwiKSB7XG4gICAgICAgICAgICBsZXQgdmFsdWUgPSBcInZhbHVlXCIgaW4gY2hpbGQucHJvcHMgPyBjaGlsZC5wcm9wcy52YWx1ZSA6IGNoaWxkLmNoaWxkcmVuLmpvaW4oXCJcIikudHJpbSgpO1xuICAgICAgICAgICAgY2hpbGQucHJvcHMuc2VsZWN0ZWQgPSB2YWx1ZSA9PT0gbW9kZWxbcHJvcGVydHldO1xuICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgfSBlbHNlIGlmICh2bm9kZS5uYW1lID09PSBcInRleHRhcmVhXCIpIHtcbiAgICAgIGV2ZW50ID0gZXZlbnQgfHwgXCJvbmlucHV0XCI7XG4gICAgICB2bm9kZS5jaGlsZHJlbiA9IFttb2RlbFtwcm9wZXJ0eV1dO1xuICAgIH1cblxuICAgIGlmICghdm5vZGUucHJvcHNbZXZlbnRdKSB7XG4gICAgICBpZiAoIWhhbmRsZXIpIHtcbiAgICAgICAgaGFuZGxlciA9IChlOiBFdmVudCkgPT4gKG1vZGVsW3Byb3BlcnR5XSA9IChlLnRhcmdldCBhcyBEb21FbGVtZW50ICYgUmVjb3JkPHN0cmluZywgYW55PikudmFsdWUpO1xuICAgICAgfVxuICAgICAgc2V0QXR0cmlidXRlKGV2ZW50LCBoYW5kbGVyLCB2bm9kZSwgb2xkVm5vZGUpO1xuICAgIH1cbiAgfVxufTtcblxuLyoqKiBQbHVnaW5zICoqKi9cbmNvbnN0IHBsdWdpbnMgPSBuZXcgTWFwPFBsdWdpbiwgYW55PigpO1xuXG5leHBvcnQgZnVuY3Rpb24gdXNlKHBsdWdpbjogUGx1Z2luLCBvcHRpb25zPzogUmVjb3JkPHN0cmluZyB8IG51bWJlciB8IHN5bWJvbCwgYW55Pik6IHZvaWQgfCBhbnkge1xuICBpZiAocGx1Z2lucy5oYXMocGx1Z2luKSkge1xuICAgIHJldHVybiBwbHVnaW5zLmdldChwbHVnaW4pO1xuICB9XG5cbiAgbGV0IHJlc3VsdCA9IHBsdWdpbih2LCBvcHRpb25zKTtcbiAgcGx1Z2lucy5zZXQocGx1Z2luLCByZXN1bHQpO1xuICByZXR1cm4gcmVzdWx0O1xufVxuXG4vKioqIEh5cGVyc2NyaXB0ICoqKi9cblxuZXhwb3J0IGNvbnN0IHY6IFZhbHlyaWFuID0gZnVuY3Rpb24gdih0YWdPckNvbXBvbmVudDogc3RyaW5nIHwgVmFseXJpYW5Db21wb25lbnQsIHByb3BzOiBQcm9wcywgLi4uY2hpbGRyZW46IENoaWxkcmVuKTogSVZub2RlIHwgVm5vZGVDb21wb25lbnQge1xuICBpZiAodHlwZW9mIHRhZ09yQ29tcG9uZW50ID09PSBcInN0cmluZ1wiKSB7XG4gICAgcmV0dXJuIG5ldyBWbm9kZSh0YWdPckNvbXBvbmVudCwgcHJvcHMgfHwge30sIGNoaWxkcmVuKTtcbiAgfVxuXG4gIGNvbnN0IHZub2RlID0gbmV3IFZub2RlKFwiX19jb21wb25lbnRfX1wiLCBwcm9wcyB8fCB7fSwgY2hpbGRyZW4pO1xuICB2bm9kZS5jb21wb25lbnQgPSB0YWdPckNvbXBvbmVudDtcbiAgcmV0dXJuIHZub2RlIGFzIFZub2RlQ29tcG9uZW50O1xufTtcblxudi5mcmFnbWVudCA9IChwcm9wczogUHJvcHMsIC4uLmNoaWxkcmVuOiBDaGlsZHJlbik6IENoaWxkcmVuID0+IHtcbiAgcmV0dXJuIGNoaWxkcmVuO1xufTtcblxuLyoqKiBWIHByb3BlcnRpZXMgYW5kIG1ldGhvZHMgKioqL1xuLy8gVGhpcyBpcyBpbnRlbmRlZCB0byBtYWtlIHRoZSBwcm9wZXJ0aWVzIGFuZCBtZXRob2RzIGF2YWlsYWJsZSBmb3IgcGx1Z2luc1xudi5jdXJyZW50ID0gY3VycmVudDtcblxudi5kaXJlY3RpdmVzID0gZGlyZWN0aXZlcztcblxudi5yZXNlcnZlZFByb3BzID0gcmVzZXJ2ZWRQcm9wcztcblxudi5pc1Zub2RlID0gaXNWbm9kZTtcbnYuaXNDb21wb25lbnQgPSBpc0NvbXBvbmVudDtcbnYuaXNWbm9kZUNvbXBvbmVudCA9IGlzVm5vZGVDb21wb25lbnQ7XG5cbnYuaXNOb2RlSnMgPSBpc05vZGVKcztcbnYudHJ1c3QgPSB0cnVzdDtcblxudi5vbkNsZWFudXAgPSBvbkNsZWFudXA7XG52Lm9uVW5tb3VudCA9IG9uVW5tb3VudDtcbnYub25Nb3VudCA9IG9uTW91bnQ7XG52Lm9uVXBkYXRlID0gb25VcGRhdGU7XG5cbnYubW91bnQgPSBtb3VudDtcbnYudW5tb3VudCA9IHVubW91bnQ7XG52LnVwZGF0ZSA9IHVwZGF0ZTtcblxudi5zZXRBdHRyaWJ1dGUgPSBzZXRBdHRyaWJ1dGU7XG52LmRpcmVjdGl2ZSA9IGRpcmVjdGl2ZTtcbnYudXNlID0gdXNlO1xuIl19 \ No newline at end of file +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL2xpYi9pbmRleC50cyJdLCJuYW1lcyI6WyJDb21wb25lbnRTdHJpbmciLCJUZXh0U3RyaW5nIiwiaXNOb2RlSnMiLCJCb29sZWFuIiwicHJvY2VzcyIsInZlcnNpb25zIiwibm9kZSIsIlZhbHlyaWFuU3ltYm9sIiwiU3ltYm9sIiwiVW5kIiwiVm5vZGUiLCJ0YWciLCJwcm9wcyIsImNoaWxkcmVuIiwidGhpcyIsImlzQ29tcG9uZW50IiwiY29tcG9uZW50IiwiaXNWbm9kZUNvbXBvbmVudCIsInZub2RlIiwiY3JlYXRlRG9tRWxlbWVudCIsImlzU1ZHIiwiZG9jdW1lbnQiLCJjcmVhdGVFbGVtZW50TlMiLCJjcmVhdGVFbGVtZW50IiwiZG9tVG9Wbm9kZSIsImRvbSIsInYiLCJ0YWdOYW1lIiwidG9Mb3dlckNhc2UiLCJBcnJheSIsImZyb20iLCJjaGlsZE5vZGVzIiwiZmlsdGVyIiwiY2hpbGQiLCJub2RlVHlwZSIsIm1hcCIsInRleHQiLCJub2RlVmFsdWUiLCJTdHJpbmciLCJmb3JFYWNoIiwiY2FsbCIsImF0dHJpYnV0ZXMiLCJwcm9wIiwibm9kZU5hbWUiLCJ0cnVzdCIsImh0bWxTdHJpbmciLCJkaXYiLCJpbm5lckhUTUwiLCJ0cmltIiwiaXRlbSIsInJlc2VydmVkUHJvcHMiLCJrZXkiLCJzdGF0ZSIsIm9uY3JlYXRlIiwib251cGRhdGUiLCJvbnJlbW92ZSIsInNob3VsZHVwZGF0ZSIsImN1cnJlbnQiLCJjYWxsQ2xlYW51cCIsInZhbHlyaWFuQXBwIiwiaSIsIm9uQ2xlYW51cCIsImxlbmd0aCIsInVwZGF0ZSIsImFwcCIsIm9sZFZub2RlIiwibWFpblZub2RlIiwicGF0Y2giLCJpc01vdW50ZWQiLCJvbk1vdW50IiwiY2FsbE1vdW50Iiwib25VcGRhdGUiLCJjYWxsVXBkYXRlIiwidW5tb3VudCIsIm9uVW5tb3VudCIsImNhbGxVbm1vdW50IiwiUmVmbGVjdCIsImRlbGV0ZVByb3BlcnR5IiwiZW1wdHlWbm9kZSIsInNoYXJlZFNldEF0dHJpYnV0ZSIsInZhbHVlIiwiZGlyZWN0aXZlcyIsImV2ZW50TGlzdGVuZXJOYW1lcyIsImNvbnRhaW5lciIsImFkZEV2ZW50TGlzdGVuZXIiLCJzbGljZSIsImV2ZW50TGlzdGVuZXIiLCJyZW1vdmVBdHRyaWJ1dGUiLCJzZXRBdHRyaWJ1dGUiLCJuYW1lIiwic2V0QXR0cmlidXRlcyIsIm5ld1Zub2RlIiwibmV3VHJlZSIsIm9sZFRyZWUiLCJjaGlsZFZub2RlIiwicmVzdWx0IiwidmlldyIsInNwbGljZSIsImlzQXJyYXkiLCJvbGRUcmVlTGVuZ3RoIiwibmV3VHJlZUxlbmd0aCIsIm9sZEtleWVkTGlzdCIsIm5ld0tleWVkTGlzdCIsIm9sZENoaWxkVm5vZGUiLCJzaG91bGRQYXRjaCIsImFwcGVuZENoaWxkIiwicmVwbGFjZUNoaWxkIiwicGFyZW50Tm9kZSIsInJlbW92ZUNoaWxkIiwibmV3Q2hpbGRWbm9kZSIsImNyZWF0ZVRleHROb2RlIiwidGV4dENvbnRlbnQiLCJoaWRlRGlyZWN0aXZlIiwidGVzdCIsImJvb2wiLCJuZXdkb20iLCJzZXQiLCJzdHlsZSIsImRpc3BsYXkiLCJjbGFzc2VzIiwiY2xhc3NMaXN0IiwidG9nZ2xlIiwiaHRtbCIsIm1vZGVsIiwicHJvcGVydHkiLCJldmVudCIsImhhbmRsZXIiLCJ0eXBlIiwiZSIsInZhbCIsInRhcmdldCIsImlkeCIsImluZGV4T2YiLCJwdXNoIiwibXVsdGlwbGUiLCJjdHJsS2V5IiwidmFsdWUyIiwiam9pbiIsInNlbGVjdGVkIiwicGx1Z2lucyIsIk1hcCIsInRhZ09yQ29tcG9uZW50IiwiZnJhZ21lbnQiLCJpc1Zub2RlIiwib2JqZWN0IiwiY2FsbGJhY2siLCJtb3VudCIsInZub2RlQ29tcG9uZW50IiwiYXBwQ29udGFpbmVyIiwicXVlcnlTZWxlY3RvckFsbCIsIkVycm9yIiwiZGVmYXVsdFByZXZlbnRlZCIsImRpcmVjdGl2ZSIsImRpcmVjdGl2ZTIiLCJmdWxsTmFtZSIsInVzZSIsInBsdWdpbiIsIm9wdGlvbnMiLCJoYXMiLCJn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Q3JCLElBQUl2RyxFQUFNdUcsRUFBRUUsT0FDUnpDLEVBQU8sT0FBT3VDLEVBQUVELE9BQ3BCLEtBQU90RyxHQUFLLENBQ1YsR0FBSUEsRUFBSWdFLEdBS04sT0FKQWhFLEVBQUlnRSxHQUFNdUMsRUFBR3ZHLFFBQ1J1RyxFQUFFdUIsa0JBQ0x4RixFQUFPL0MsSUFJWFMsRUFBTUEsRUFBSWtGLGFBbkJkM0YsRUFBVVQsR0FBa0IsQ0FDMUI2RCxXQUFXLEVBQ1hjLG1CQUFvQixHQUNwQnJCLFVBQVcsR0FDWFEsUUFBUyxHQUNURSxTQUFVLEdBQ1ZHLFVBQVcsSUFnQmIxRCxFQUFVVCxHQUFnQitFLGNBQWdCQSxFQVE1QyxPQUxBdEUsRUFBVVQsR0FBZ0JTLFVBQVltSSxFQUN0Q25JLEVBQVVULEdBQWdCNEUsVUFBWWlFLEVBQ3RDcEksRUFBVVQsR0FBZ0IyRCxVQUFZMUMsRUFBVzRILEdBRzFDckYsRUFBTy9DLElBMGdCaEJVLEVBQUUrQyxRQUFVQSxFQUNaL0MsRUFBRXFDLE9BQVNBLEVBRVhyQyxFQUFFOEQsYUFBZUEsRUFDakI5RCxFQUFFOEgsVUF0TEYsU0FBbUIvRCxFQUFjZ0UsR0FDL0IsSUFBSUMsRUFBVyxLQUFLakUsSUFDcEJSLEVBQVd5RSxHQUFZRCxFQUN2QnZHLEVBQWN3RyxJQUFZLEdBb0w1QmhJLEVBQUVpSSxJQXBERixTQUFhQyxFQUFnQkMsR0FDM0IsR0FBSWxCLEVBQVFtQixJQUFJRixHQUNkLE9BQU9qQixFQUFRb0IsSUFBSUgsR0FHckIsSUFBSTdELEVBQVM2RCxFQUFPbEksRUFBR21JLEdBRXZCLE9BREFsQixFQUFRdkIsSUFBSXdDLEVBQVE3RCxHQUNiQSIsInNvdXJjZXNDb250ZW50IjpbIi8qIGVzbGludC1kaXNhYmxlIG5vLXVzZS1iZWZvcmUtZGVmaW5lICovXG4vKiBlc2xpbnQtZGlzYWJsZSBzb25hcmpzL2NvZ25pdGl2ZS1jb21wbGV4aXR5ICovXG4vKioqIFZub2RlICoqKi9cblxuaW1wb3J0IHtcbiAgQ2hpbGRyZW4sXG4gIEN1cnJlbnQsXG4gIERpcmVjdGl2ZSxcbiAgRGlyZWN0aXZlcyxcbiAgRG9tRWxlbWVudCxcbiAgSVZub2RlLFxuICBNb3VudGVkVmFseXJpYW5BcHAsXG4gIFBsdWdpbixcbiAgUHJvcHMsXG4gIFJlc2VydmVkUHJvcHMsXG4gIFZhbHlyaWFuLFxuICBWYWx5cmlhbkFwcCxcbiAgVmFseXJpYW5Db21wb25lbnQsXG4gIFZub2RlQ29tcG9uZW50LFxuICBWbm9kZVdpdGhEb21cbn0gZnJvbSBcIi4vaW50ZXJmYWNlc1wiO1xuXG4vKioqIENvbnN0YW50cyAqKiovXG5jb25zdCBDb21wb25lbnRTdHJpbmcgPSBcIl9fY29tcG9uZW50X19cIjtcbmNvbnN0IFRleHRTdHJpbmcgPSBcIiN0ZXh0XCI7XG5jb25zdCBpc05vZGVKcyA9IEJvb2xlYW4odHlwZW9mIHByb2Nlc3MgIT09IFwidW5kZWZpbmVkXCIgJiYgcHJvY2Vzcy52ZXJzaW9ucyAmJiBwcm9jZXNzLnZlcnNpb25zLm5vZGUpO1xuY29uc3QgVmFseXJpYW5TeW1ib2wgPSBTeW1ib2woXCJWYWx5cmlhblwiKTtcbmNvbnN0IFVuZCA9IHVuZGVmaW5lZDtcblxuLyoqKiBWbm9kZSAqKiovXG5cbmNvbnN0IFZub2RlID0gZnVuY3Rpb24gVm5vZGUodGhpczogSVZub2RlLCB0YWc6IHN0cmluZywgcHJvcHM6IFByb3BzLCBjaGlsZHJlbjogQ2hpbGRyZW4pIHtcbiAgdGhpcy5wcm9wcyA9IHByb3BzO1xuICB0aGlzLmNoaWxkcmVuID0gY2hpbGRyZW47XG4gIHRoaXMudGFnID0gdGFnO1xufSBhcyB1bmtub3duIGFzIElWbm9kZTtcblxuZnVuY3Rpb24gaXNWbm9kZShvYmplY3Q/OiB1bmtub3duIHwgSVZub2RlKTogb2JqZWN0IGlzIElWbm9kZSB7XG4gIHJldHVybiBvYmplY3QgaW5zdGFuY2VvZiBWbm9kZTtcbn1cblxuZnVuY3Rpb24gaXNDb21wb25lbnQoY29tcG9uZW50PzogdW5rbm93biB8IFZhbHlyaWFuQ29tcG9uZW50KTogY29tcG9uZW50IGlzIFZhbHlyaWFuQ29tcG9uZW50IHtcbiAgcmV0dXJuIHR5cGVvZiBjb21wb25lbnQgPT09IFwiZnVuY3Rpb25cIiB8fCAodHlwZW9mIGNvbXBvbmVudCA9PT0gXCJvYmplY3RcIiAmJiBjb21wb25lbnQgIT09IG51bGwgJiYgXCJ2aWV3XCIgaW4gY29tcG9uZW50KTtcbn1cblxuZnVuY3Rpb24gaXNWbm9kZUNvbXBvbmVudCh2bm9kZT86IHVua25vd24gfCBWbm9kZUNvbXBvbmVudCk6IHZub2RlIGlzIFZub2RlQ29tcG9uZW50IHtcbiAgcmV0dXJuIHZub2RlIGluc3RhbmNlb2YgVm5vZGUgJiYgdm5vZGUudGFnID09PSBDb21wb25lbnRTdHJpbmc7XG59XG5cbi8qKiogVXRpbCAqKiovXG5cbmZ1bmN0aW9uIGNyZWF0ZURvbUVsZW1lbnQodGFnOiBzdHJpbmcsIGlzU1ZHOiBib29sZWFuID0gZmFsc2UpIHtcbiAgcmV0dXJuIGlzU1ZHID8gZG9jdW1lbnQuY3JlYXRlRWxlbWVudE5TKFwiaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmdcIiwgdGFnKSA6IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQodGFnKTtcbn1cblxuZnVuY3Rpb24gZG9tVG9Wbm9kZShkb206IERvbUVsZW1lbnQpOiBWbm9kZVdpdGhEb20ge1xuICBsZXQgdm5vZGUgPSB2KFxuICAgIGRvbS50YWdOYW1lLnRvTG93ZXJDYXNlKCksXG4gICAge30sXG4gICAgLi4uQXJyYXkuZnJvbShkb20uY2hpbGROb2RlcylcbiAgICAgIC5maWx0ZXIoKGNoaWxkKSA9PiAoY2hpbGQgYXMgRG9tRWxlbWVudCkubm9kZVR5cGUgPT09IDEgfHwgKGNoaWxkIGFzIERvbUVsZW1lbnQpLm5vZGVUeXBlID09PSAzKVxuICAgICAgLm1hcCgoY2hpbGQpID0+IHtcbiAgICAgICAgaWYgKChjaGlsZCBhcyBEb21FbGVtZW50KS5ub2RlVHlwZSA9PT0gMSkge1xuICAgICAgICAgIHJldHVybiBkb21Ub1Zub2RlKGNoaWxkIGFzIERvbUVsZW1lbnQpO1xuICAgICAgICB9XG5cbiAgICAgICAgbGV0IHRleHQgPSBuZXcgVm5vZGUoVGV4dFN0cmluZywge30sIFtdKTtcbiAgICAgICAgdGV4dC5ub2RlVmFsdWUgPSBTdHJpbmcoKGNoaWxkIGFzIERvbUVsZW1lbnQpLm5vZGVWYWx1ZSk7XG4gICAgICAgIHRleHQuZG9tID0gY2hpbGQgYXMgRG9tRWxlbWVudDtcbiAgICAgICAgcmV0dXJuIHRleHQ7XG4gICAgICB9KVxuICApO1xuICBbXS5mb3JFYWNoLmNhbGwoZG9tLmF0dHJpYnV0ZXMsIChwcm9wOiBBdHRyKSA9PiAodm5vZGUucHJvcHNbcHJvcC5ub2RlTmFtZV0gPSBwcm9wLm5vZGVWYWx1ZSkpO1xuICB2bm9kZS5kb20gPSBkb207XG4gIHJldHVybiB2bm9kZSBhcyBWbm9kZVdpdGhEb207XG59XG5cbmNvbnN0IHRydXN0ID0gKGh0bWxTdHJpbmc6IHN0cmluZyk6IENoaWxkcmVuID0+IHtcbiAgbGV0IGRpdiA9IGNyZWF0ZURvbUVsZW1lbnQoXCJkaXZcIik7XG4gIGRpdi5pbm5lckhUTUwgPSBodG1sU3RyaW5nLnRyaW0oKTtcblxuICByZXR1cm4gW10ubWFwLmNhbGwoZGl2LmNoaWxkTm9kZXMsIChpdGVtKSA9PiBkb21Ub1Zub2RlKGl0ZW0pKSBhcyBDaGlsZHJlbjtcbn07XG5cbmNvbnN0IHJlc2VydmVkUHJvcHM6IFJlc2VydmVkUHJvcHMgPSB7XG4gIGtleTogdHJ1ZSxcbiAgc3RhdGU6IHRydWUsXG4gIG9uY3JlYXRlOiB0cnVlLFxuICBvbnVwZGF0ZTogdHJ1ZSxcbiAgb25yZW1vdmU6IHRydWUsXG4gIHNob3VsZHVwZGF0ZTogdHJ1ZSxcbiAgXCJ2LW9uY2VcIjogdHJ1ZSxcblxuICAvLyBCdWlsdCBpbiBkaXJlY3RpdmVzXG4gIFwidi1pZlwiOiB0cnVlLFxuICBcInYtdW5sZXNzXCI6IHRydWUsXG4gIFwidi1mb3JcIjogdHJ1ZSxcbiAgXCJ2LXNob3dcIjogdHJ1ZSxcbiAgXCJ2LWNsYXNzXCI6IHRydWUsXG4gIFwidi1odG1sXCI6IHRydWVcbn07XG5cbi8qKiogTW91bnQgKioqL1xuXG5jb25zdCBjdXJyZW50OiBDdXJyZW50ID0ge307XG5cbmZ1bmN0aW9uIG9uQ2xlYW51cChjYWxsYmFjazogRnVuY3Rpb24pIHtcbiAgaWYgKGN1cnJlbnQuYXBwPy5vbkNsZWFudXAuaW5kZXhPZihjYWxsYmFjaykgPT09IC0xKSB7XG4gICAgY3VycmVudC5hcHA/Lm9uQ2xlYW51cC5wdXNoKGNhbGxiYWNrKTtcbiAgfVxufVxuXG5mdW5jdGlvbiBvblVubW91bnQoY2FsbGJhY2s6IEZ1bmN0aW9uKSB7XG4gIGlmIChjdXJyZW50LmFwcD8ub25Vbm1vdW50LmluZGV4T2YoY2FsbGJhY2spID09PSAtMSkge1xuICAgIGN1cnJlbnQuYXBwPy5vblVubW91bnQucHVzaChjYWxsYmFjayk7XG4gIH1cbn1cblxuZnVuY3Rpb24gb25Nb3VudChjYWxsYmFjazogRnVuY3Rpb24pIHtcbiAgaWYgKGN1cnJlbnQuYXBwPy5vbk1vdW50LmluZGV4T2YoY2FsbGJhY2spID09PSAtMSkge1xuICAgIGN1cnJlbnQuYXBwPy5vbk1vdW50LnB1c2goY2FsbGJhY2spO1xuICB9XG59XG5cbmZ1bmN0aW9uIG9uVXBkYXRlKGNhbGxiYWNrOiBGdW5jdGlvbikge1xuICBpZiAoY3VycmVudC5hcHA/Lm9uVXBkYXRlLmluZGV4T2YoY2FsbGJhY2spID09PSAtMSkge1xuICAgIGN1cnJlbnQuYXBwPy5vblVwZGF0ZS5wdXNoKGNhbGxiYWNrKTtcbiAgfVxufVxuXG4vKlxuICAqIE1vdW50cyBhIGNvbXBvbmVudCB0byB0aGUgRE9NXG4gIG1vdW50KCcjYXBwJywgKCkgPT4gPGRpdj5IZWxsbyB3b3JsZDwvZGl2Pik7IC8vIEFwcCBpcyBhIEZ1bmN0aW9uYWwgQ29tcG9uZW50XG4gIG1vdW50KCcjYXBwJywgeyB2aWV3OiAoKSA9PiA8ZGl2PkhlbGxvIHdvcmxkPC9kaXY+IH0pOyAvLyBBcHAgaXMgYSBQT0pPIGNvbXBvbmVudCB3aXRoIGEgdmlldyBtZXRob2RcbiAgbW91bnQoJyNhcHAnLCBjbGFzc0luc3RhbmNlKTsgLy8gQXBwIGlzIGEgY2xhc3MgaW5zdGFuY2Ugd2l0aCBhIHZpZXcgbWV0aG9kXG4gIG1vdW50KCcjYXBwJywgPEFwcD48ZGl2PkhlbGxvIHdvcmxkPC9kaXY+PC9BcHA+KTsgLy8gQXBwIGlzIGEgVm5vZGUgY29tcG9uZW50IChWbm9kZSB3aXRoIHRhZyBfX2NvbXBvbmVudF9fKVxuKi9cblxuZnVuY3Rpb24gbW91bnQoY29udGFpbmVyOiBEb21FbGVtZW50IHwgc3RyaW5nLCBjb21wb25lbnQ6IFZhbHlyaWFuQ29tcG9uZW50IHwgSVZub2RlKTogdm9pZCB8IHN0cmluZyB7XG4gIGxldCBhcHBDb250YWluZXIgPSBudWxsO1xuXG4gIGlmIChpc05vZGVKcykge1xuICAgIGFwcENvbnRhaW5lciA9IHR5cGVvZiBjb250YWluZXIgPT09IFwic3RyaW5nXCIgPyBjcmVhdGVEb21FbGVtZW50KGNvbnRhaW5lciA9PT0gXCJzdmdcIiA/IFwic3ZnXCIgOiBcImRpdlwiLCBjb250YWluZXIgPT09IFwic3ZnXCIpIDogY29udGFpbmVyO1xuICB9IGVsc2Uge1xuICAgIGFwcENvbnRhaW5lciA9IHR5cGVvZiBjb250YWluZXIgPT09IFwic3RyaW5nXCIgPyBkb2N1bWVudC5xdWVyeVNlbGVjdG9yQWxsKGNvbnRhaW5lcilbMF0gOiBjb250YWluZXI7XG4gIH1cblxuICBpZiAoIWFwcENvbnRhaW5lcikge1xuICAgIHRocm93IG5ldyBFcnJvcihcIkNvbnRhaW5lciBub3QgZm91bmRcIik7XG4gIH1cblxuICBsZXQgdm5vZGVDb21wb25lbnQ6IFZub2RlQ29tcG9uZW50IHwgSVZub2RlO1xuXG4gIGlmIChpc1Zub2RlQ29tcG9uZW50KGNvbXBvbmVudCkpIHtcbiAgICB2bm9kZUNvbXBvbmVudCA9IGNvbXBvbmVudDtcbiAgfSBlbHNlIGlmIChpc0NvbXBvbmVudChjb21wb25lbnQpKSB7XG4gICAgdm5vZGVDb21wb25lbnQgPSB2KGNvbXBvbmVudCwge30pO1xuICB9IGVsc2Uge1xuICAgIHRocm93IG5ldyBFcnJvcihcIkNvbXBvbmVudCBtdXN0IGJlIGEgVmFseXJpYW4gQ29tcG9uZW50IG9yIGEgVm5vZGUgY29tcG9uZW50XCIpO1xuICB9XG5cbiAgaWYgKGNvbXBvbmVudFtWYWx5cmlhblN5bWJvbF0pIHtcbiAgICB1bm1vdW50KGNvbXBvbmVudCk7XG4gIH0gZWxzZSB7XG4gICAgY29tcG9uZW50W1ZhbHlyaWFuU3ltYm9sXSA9IHtcbiAgICAgIGlzTW91bnRlZDogZmFsc2UsXG4gICAgICBldmVudExpc3RlbmVyTmFtZXM6IHt9LFxuICAgICAgb25DbGVhbnVwOiBbXSxcbiAgICAgIG9uTW91bnQ6IFtdLFxuICAgICAgb25VcGRhdGU6IFtdLFxuICAgICAgb25Vbm1vdW50OiBbXVxuICAgIH07XG4gICAgZnVuY3Rpb24gZXZlbnRMaXN0ZW5lcihlOiBFdmVudCkge1xuICAgICAgbGV0IGRvbSA9IGUudGFyZ2V0IGFzIERvbUVsZW1lbnQgJiBSZWNvcmQ8c3RyaW5nLCBhbnk+O1xuICAgICAgbGV0IG5hbWUgPSBgdi1vbiR7ZS50eXBlfWA7XG4gICAgICB3aGlsZSAoZG9tKSB7XG4gICAgICAgIGlmIChkb21bbmFtZV0pIHtcbiAgICAgICAgICBkb21bbmFtZV0oZSwgZG9tKTtcbiAgICAgICAgICBpZiAoIWUuZGVmYXVsdFByZXZlbnRlZCkge1xuICAgICAgICAgICAgdXBkYXRlKGNvbXBvbmVudCk7XG4gICAgICAgICAgfVxuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBkb20gPSBkb20ucGFyZW50Tm9kZSBhcyBEb21FbGVtZW50O1xuICAgICAgfVxuICAgIH1cbiAgICBjb21wb25lbnRbVmFseXJpYW5TeW1ib2xdLmV2ZW50TGlzdGVuZXIgPSBldmVudExpc3RlbmVyO1xuICB9XG5cbiAgY29tcG9uZW50W1ZhbHlyaWFuU3ltYm9sXS5jb21wb25lbnQgPSB2bm9kZUNvbXBvbmVudDtcbiAgY29tcG9uZW50W1ZhbHlyaWFuU3ltYm9sXS5jb250YWluZXIgPSBhcHBDb250YWluZXI7XG4gIGNvbXBvbmVudFtWYWx5cmlhblN5bWJvbF0ubWFpblZub2RlID0gZG9tVG9Wbm9kZShhcHBDb250YWluZXIpO1xuXG4gIC8vIHVwZGF0ZVxuICByZXR1cm4gdXBkYXRlKGNvbXBvbmVudCk7XG59XG5cbmZ1bmN0aW9uIGNhbGxDbGVhbnVwKHZhbHlyaWFuQXBwOiBWYWx5cmlhbkFwcCkge1xuICBmb3IgKGxldCBpID0gMDsgaSA8IHZhbHlyaWFuQXBwLm9uQ2xlYW51cC5sZW5ndGg7IGkrKykge1xuICAgIHZhbHlyaWFuQXBwLm9uQ2xlYW51cFtpXSgpO1xuICB9XG4gIHZhbHlyaWFuQXBwLm9uQ2xlYW51cCA9IFtdO1xufVxuXG5mdW5jdGlvbiBjYWxsVW5tb3VudCh2YWx5cmlhbkFwcDogVmFseXJpYW5BcHApIHtcbiAgZm9yIChsZXQgaSA9IDA7IGkgPCB2YWx5cmlhbkFwcC5vblVubW91bnQubGVuZ3RoOyBpKyspIHtcbiAgICB2YWx5cmlhbkFwcC5vblVubW91bnRbaV0oKTtcbiAgfVxuICB2YWx5cmlhbkFwcC5vblVubW91bnQgPSBbXTtcbn1cblxuZnVuY3Rpb24gY2FsbE1vdW50KHZhbHlyaWFuQXBwOiBWYWx5cmlhbkFwcCkge1xuICBmb3IgKGxldCBpID0gMDsgaSA8IHZhbHlyaWFuQXBwLm9uTW91bnQubGVuZ3RoOyBpKyspIHtcbiAgICB2YWx5cmlhbkFwcC5vbk1vdW50W2ldKCk7XG4gIH1cbiAgdmFseXJpYW5BcHAub25Nb3VudCA9IFtdO1xufVxuXG5mdW5jdGlvbiBjYWxsVXBkYXRlKHZhbHlyaWFuQXBwOiBWYWx5cmlhbkFwcCkge1xuICBmb3IgKGxldCBpID0gMDsgaSA8IHZhbHlyaWFuQXBwLm9uVXBkYXRlLmxlbmd0aDsgaSsrKSB7XG4gICAgdmFseXJpYW5BcHAub25VcGRhdGVbaV0oKTtcbiAgfVxuICB2YWx5cmlhbkFwcC5vblVwZGF0ZSA9IFtdO1xufVxuXG5mdW5jdGlvbiB1cGRhdGUoY29tcG9uZW50PzogVmFseXJpYW5Db21wb25lbnQgfCBJVm5vZGUpOiB2b2lkIHwgc3RyaW5nIHtcbiAgaWYgKGNvbXBvbmVudCAmJiBjb21wb25lbnRbVmFseXJpYW5TeW1ib2xdKSB7XG4gICAgbGV0IHZhbHlyaWFuQXBwID0gY29tcG9uZW50W1ZhbHlyaWFuU3ltYm9sXTtcbiAgICBjdXJyZW50LmFwcCA9IHZhbHlyaWFuQXBwO1xuICAgIHZhbHlyaWFuQXBwLm9uQ2xlYW51cC5sZW5ndGggJiYgY2FsbENsZWFudXAodmFseXJpYW5BcHApO1xuICAgIGxldCBvbGRWbm9kZTogVm5vZGVXaXRoRG9tIHwgbnVsbCA9IHZhbHlyaWFuQXBwLm1haW5Wbm9kZSBhcyBWbm9kZVdpdGhEb207XG4gICAgdmFseXJpYW5BcHAubWFpblZub2RlID0gbmV3IFZub2RlKHZhbHlyaWFuQXBwLm1haW5Wbm9kZS50YWcsIHZhbHlyaWFuQXBwLm1haW5Wbm9kZS5wcm9wcywgW3ZhbHlyaWFuQXBwLmNvbXBvbmVudF0pIGFzIFZub2RlV2l0aERvbTtcbiAgICB2YWx5cmlhbkFwcC5tYWluVm5vZGUuZG9tID0gb2xkVm5vZGUuZG9tO1xuICAgIHBhdGNoKHZhbHlyaWFuQXBwLm1haW5Wbm9kZSwgb2xkVm5vZGUsIHZhbHlyaWFuQXBwKTtcbiAgICBvbGRWbm9kZSA9IG51bGw7XG4gICAgaWYgKHZhbHlyaWFuQXBwLmlzTW91bnRlZCA9PT0gZmFsc2UpIHtcbiAgICAgIHZhbHlyaWFuQXBwLm9uTW91bnQubGVuZ3RoICYmIGNhbGxNb3VudCh2YWx5cmlhbkFwcCk7XG4gICAgICB2YWx5cmlhbkFwcC5pc01vdW50ZWQgPSB0cnVlO1xuICAgIH0gZWxzZSB7XG4gICAgICB2YWx5cmlhbkFwcC5vblVwZGF0ZS5sZW5ndGggJiYgY2FsbFVwZGF0ZSh2YWx5cmlhbkFwcCk7XG4gICAgfVxuXG4gICAgaWYgKGlzTm9kZUpzKSB7XG4gICAgICByZXR1cm4gdmFseXJpYW5BcHAubWFpblZub2RlLmRvbS5pbm5lckhUTUw7XG4gICAgfVxuICB9XG59XG5cbmZ1bmN0aW9uIHVubW91bnQoY29tcG9uZW50PzogVmFseXJpYW5Db21wb25lbnQgfCBJVm5vZGUpOiB2b2lkIHwgc3RyaW5nIHtcbiAgaWYgKCFjb21wb25lbnQgfHwgIWNvbXBvbmVudFtWYWx5cmlhblN5bWJvbF0pIHtcbiAgICByZXR1cm47XG4gIH1cblxuICBsZXQgdmFseXJpYW5BcHAgPSBjb21wb25lbnRbVmFseXJpYW5TeW1ib2xdIGFzIE1vdW50ZWRWYWx5cmlhbkFwcDtcblxuICBpZiAodmFseXJpYW5BcHAuaXNNb3VudGVkKSB7XG4gICAgdmFseXJpYW5BcHAub25DbGVhbnVwLmxlbmd0aCAmJiBjYWxsQ2xlYW51cCh2YWx5cmlhbkFwcCk7XG4gICAgdmFseXJpYW5BcHAub25Vbm1vdW50Lmxlbmd0aCAmJiBjYWxsVW5tb3VudCh2YWx5cmlhbkFwcCk7XG4gICAgbGV0IG9sZFZub2RlOiBWbm9kZVdpdGhEb20gfCBudWxsID0gdmFseXJpYW5BcHAubWFpblZub2RlIGFzIFZub2RlV2l0aERvbTtcbiAgICB2YWx5cmlhbkFwcC5tYWluVm5vZGUgPSBuZXcgVm5vZGUodmFseXJpYW5BcHAubWFpblZub2RlLnRhZywgdmFseXJpYW5BcHAubWFpblZub2RlLnByb3BzLCBbXSkgYXMgVm5vZGVXaXRoRG9tO1xuICAgIHZhbHlyaWFuQXBwLm1haW5Wbm9kZS5kb20gPSBvbGRWbm9kZS5kb207XG4gICAgdmFseXJpYW5BcHAubWFpblZub2RlLmlzU1ZHID0gb2xkVm5vZGUuaXNTVkc7XG4gICAgcGF0Y2godmFseXJpYW5BcHAubWFpblZub2RlLCBvbGRWbm9kZSwgdmFseXJpYW5BcHApO1xuICAgIG9sZFZub2RlID0gbnVsbDtcblxuICAgIGlmIChpc05vZGVKcykge1xuICAgICAgcmV0dXJuIHZhbHlyaWFuQXBwLm1haW5Wbm9kZS5kb20uaW5uZXJIVE1MO1xuICAgIH1cblxuICAgICh2YWx5cmlhbkFwcCBhcyBhbnkpID0gbnVsbDtcbiAgICBSZWZsZWN0LmRlbGV0ZVByb3BlcnR5KGNvbXBvbmVudCwgVmFseXJpYW5TeW1ib2wpO1xuICB9XG59XG5cbmxldCBlbXB0eVZub2RlID0gbmV3IFZub2RlKFwiX19lbXB0eV9fXCIsIHt9LCBbXSk7XG5cbmZ1bmN0aW9uIG9ucmVtb3ZlKHZub2RlOiBJVm5vZGUpIHtcbiAgZm9yIChsZXQgaSA9IDA7IGkgPCB2bm9kZS5jaGlsZHJlbi5sZW5ndGg7IGkrKykge1xuICAgIHZub2RlLmNoaWxkcmVuW2ldLnRhZyAhPT0gVGV4dFN0cmluZyAmJiBvbnJlbW92ZSh2bm9kZS5jaGlsZHJlbltpXSk7XG4gIH1cblxuICB2bm9kZS5wcm9wcy5vbnJlbW92ZSAmJiB2bm9kZS5wcm9wcy5vbnJlbW92ZSh2bm9kZSk7XG59XG5cbmZ1bmN0aW9uIHNoYXJlZFNldEF0dHJpYnV0ZShwcm9wOiBzdHJpbmcsIHZhbHVlOiBhbnksIHZub2RlOiBWbm9kZVdpdGhEb20sIG9sZFZub2RlPzogVm5vZGVXaXRoRG9tKTogdm9pZCB8IGJvb2xlYW4ge1xuICAvLyBJdCBpcyBhIHJlc2VydmVkIHByb3BcbiAgaWYgKHJlc2VydmVkUHJvcHNbcHJvcF0pIHtcbiAgICAvLyBJZiBpdCBpcyBhIGRpcmVjdGl2ZSBuYW1lIGNhbGwgdGhlIGRpcmVjdGl2ZVxuICAgIGlmIChkaXJlY3RpdmVzW3Byb3BdKSB7XG4gICAgICByZXR1cm4gZGlyZWN0aXZlc1twcm9wXSh2bm9kZS5wcm9wc1twcm9wXSwgdm5vZGUsIG9sZFZub2RlKTtcbiAgICB9XG5cbiAgICByZXR1cm47XG4gIH1cblxuICAvLyBJdCBpcyBub3QgYSByZXNlcnZlZCBwcm9wIHNvIHdlIGFkZCBpdCB0byB0aGUgZG9tXG4gIGlmICh0eXBlb2YgdmFsdWUgPT09IFwiZnVuY3Rpb25cIikge1xuICAgIGxldCB2YWx5cmlhbkFwcCA9IGN1cnJlbnQuYXBwIGFzIE1vdW50ZWRWYWx5cmlhbkFwcDtcbiAgICBpZiAocHJvcCBpbiB2YWx5cmlhbkFwcC5ldmVudExpc3RlbmVyTmFtZXMgPT09IGZhbHNlKSB7XG4gICAgICB2YWx5cmlhbkFwcC5ldmVudExpc3RlbmVyTmFtZXNbcHJvcF0gPSB0cnVlO1xuICAgICAgdmFseXJpYW5BcHAuY29udGFpbmVyLmFkZEV2ZW50TGlzdGVuZXIocHJvcC5zbGljZSgyKSwgdmFseXJpYW5BcHAuZXZlbnRMaXN0ZW5lcik7XG4gICAgfVxuICAgIHZub2RlLmRvbVtgdi0ke3Byb3B9YF0gPSB2YWx1ZTtcbiAgICByZXR1cm47XG4gIH1cblxuICBpZiAocHJvcCBpbiB2bm9kZS5kb20gJiYgdm5vZGUuaXNTVkcgPT09IGZhbHNlKSB7XG4gICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGVxZXFlcVxuICAgIGlmICh2bm9kZS5kb21bcHJvcF0gIT0gdmFsdWUpIHtcbiAgICAgIHZub2RlLmRvbVtwcm9wXSA9IHZhbHVlO1xuICAgIH1cbiAgICByZXR1cm47XG4gIH1cblxuICAvLyBVc2Ugc2V0IGF0dHJpYnV0ZVxuICBpZiAoIW9sZFZub2RlIHx8IG9sZFZub2RlLnByb3BzW3Byb3BdICE9PSB2YWx1ZSkge1xuICAgIGlmICh2YWx1ZSA9PT0gZmFsc2UpIHtcbiAgICAgIHZub2RlLmRvbS5yZW1vdmVBdHRyaWJ1dGUocHJvcCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHZub2RlLmRvbS5zZXRBdHRyaWJ1dGUocHJvcCwgdmFsdWUpO1xuICAgIH1cbiAgfVxufVxuXG5mdW5jdGlvbiBzZXRBdHRyaWJ1dGUobmFtZTogc3RyaW5nLCB2YWx1ZTogYW55LCB2bm9kZTogVm5vZGVXaXRoRG9tLCBvbGRWbm9kZT86IFZub2RlV2l0aERvbSkge1xuICB2bm9kZS5wcm9wc1tuYW1lXSA9IHZhbHVlO1xuXG4gIHNoYXJlZFNldEF0dHJpYnV0ZShuYW1lLCB2YWx1ZSwgdm5vZGUsIG9sZFZub2RlKTtcbn1cblxuZnVuY3Rpb24gc2V0QXR0cmlidXRlcyh2bm9kZTogVm5vZGVXaXRoRG9tLCBvbGRWbm9kZT86IFZub2RlV2l0aERvbSkge1xuICBmb3IgKGxldCBwcm9wIGluIHZub2RlLnByb3BzKSB7XG4gICAgaWYgKHNoYXJlZFNldEF0dHJpYnV0ZShwcm9wLCB2bm9kZS5wcm9wc1twcm9wXSwgdm5vZGUsIG9sZFZub2RlKSA9PT0gZmFsc2UpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gIH1cblxuICBpZiAob2xkVm5vZGUpIHtcbiAgICBmb3IgKGxldCBwcm9wIGluIG9sZFZub2RlLnByb3BzKSB7XG4gICAgICBpZiAocHJvcCBpbiB2bm9kZS5wcm9wcyA9PT0gZmFsc2UgJiYgdHlwZW9mIG9sZFZub2RlLnByb3BzW3Byb3BdICE9PSBcImZ1bmN0aW9uXCIgJiYgcHJvcCBpbiByZXNlcnZlZFByb3BzID09PSBmYWxzZSkge1xuICAgICAgICBpZiAocHJvcCBpbiBvbGRWbm9kZS5kb20gJiYgdm5vZGUuaXNTVkcgPT09IGZhbHNlKSB7XG4gICAgICAgICAgb2xkVm5vZGUuZG9tW3Byb3BdID0gbnVsbDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBvbGRWbm9kZS5kb20ucmVtb3ZlQXR0cmlidXRlKHByb3ApO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICB9XG59XG5cbi8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBjb21wbGV4aXR5XG5mdW5jdGlvbiBwYXRjaChuZXdWbm9kZTogVm5vZGVXaXRoRG9tLCBvbGRWbm9kZTogVm5vZGVXaXRoRG9tIHwgSVZub2RlID0gZW1wdHlWbm9kZSwgdmFseXJpYW5BcHA6IE1vdW50ZWRWYWx5cmlhbkFwcCkge1xuICBjdXJyZW50LnZub2RlID0gbmV3Vm5vZGU7XG4gIGN1cnJlbnQub2xkVm5vZGUgPSBvbGRWbm9kZSA9PT0gZW1wdHlWbm9kZSA/IFVuZCA6IChvbGRWbm9kZSBhcyBWbm9kZVdpdGhEb20pO1xuICBsZXQgbmV3VHJlZSA9IG5ld1Zub2RlLmNoaWxkcmVuO1xuICBsZXQgb2xkVHJlZSA9IG9sZFZub2RlLmNoaWxkcmVuO1xuXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgbmV3VHJlZS5sZW5ndGg7IGkrKykge1xuICAgIGxldCBjaGlsZFZub2RlID0gbmV3VHJlZVtpXTtcbiAgICBpZiAoY2hpbGRWbm9kZSBpbnN0YW5jZW9mIFZub2RlKSB7XG4gICAgICBpZiAoY2hpbGRWbm9kZS50YWcgIT09IFRleHRTdHJpbmcpIHtcbiAgICAgICAgaWYgKGNoaWxkVm5vZGUudGFnID09PSBDb21wb25lbnRTdHJpbmcpIHtcbiAgICAgICAgICBsZXQgY29tcG9uZW50ID0gY2hpbGRWbm9kZS5jb21wb25lbnQgYXMgVmFseXJpYW5Db21wb25lbnQ7XG4gICAgICAgICAgY3VycmVudC5jb21wb25lbnQgPSBjb21wb25lbnQ7XG4gICAgICAgICAgbGV0IHJlc3VsdCA9IChcInZpZXdcIiBpbiBjb21wb25lbnQgPyBjb21wb25lbnQudmlldyA6IGNvbXBvbmVudCkuY2FsbChjb21wb25lbnQsIGNoaWxkVm5vZGUucHJvcHMsIC4uLmNoaWxkVm5vZGUuY2hpbGRyZW4pO1xuXG4gICAgICAgICAgbmV3VHJlZS5zcGxpY2UoaS0tLCAxLCByZXN1bHQpO1xuICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICB9XG4gICAgICAgIGNoaWxkVm5vZGUuaXNTVkcgPSBuZXdWbm9kZS5pc1NWRyB8fCBjaGlsZFZub2RlLnRhZyA9PT0gXCJzdmdcIjtcbiAgICAgIH1cbiAgICB9IGVsc2UgaWYgKEFycmF5LmlzQXJyYXkoY2hpbGRWbm9kZSkpIHtcbiAgICAgIG5ld1RyZWUuc3BsaWNlKGktLSwgMSwgLi4uY2hpbGRWbm9kZSk7XG4gICAgfSBlbHNlIGlmIChjaGlsZFZub2RlID09PSBudWxsIHx8IGNoaWxkVm5vZGUgPT09IFVuZCkge1xuICAgICAgbmV3VHJlZS5zcGxpY2UoaS0tLCAxKTtcbiAgICB9IGVsc2Uge1xuICAgICAgbmV3VHJlZVtpXSA9IG5ldyBWbm9kZShUZXh0U3RyaW5nLCB7fSwgW10pO1xuICAgICAgbmV3VHJlZVtpXS5ub2RlVmFsdWUgPSBjaGlsZFZub2RlO1xuICAgIH1cbiAgfVxuXG4gIGxldCBvbGRUcmVlTGVuZ3RoID0gb2xkVHJlZS5sZW5ndGg7XG4gIGxldCBuZXdUcmVlTGVuZ3RoID0gbmV3VHJlZS5sZW5ndGg7XG5cbiAgLy8gSWYgbmV3IHRyZWUgaXMgZW1wdHksIHJlbW92ZSBhbGwgb2xkIG5vZGVzXG4gIGlmIChuZXdUcmVlTGVuZ3RoID09PSAwKSB7XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBvbGRUcmVlTGVuZ3RoOyBpKyspIHtcbiAgICAgIG9sZFRyZWVbaV0udGFnICE9PSBUZXh0U3RyaW5nICYmIG9ucmVtb3ZlKG9sZFRyZWVbaV0pO1xuICAgIH1cblxuICAgIG5ld1Zub2RlLmRvbS50ZXh0Q29udGVudCA9IFwiXCI7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgLy8gSWYgdGhlIHRyZWUgaXMga2V5ZWQgbGlzdCBhbmQgaXMgbm90IGZpcnN0IHJlbmRlciBhbmQgb2xkIHRyZWUgaXMga2V5ZWQgbGlzdCB0b29cbiAgaWYgKG9sZFRyZWVMZW5ndGggJiYgXCJrZXlcIiBpbiBuZXdUcmVlWzBdLnByb3BzICYmIFwia2V5XCIgaW4gb2xkVHJlZVswXS5wcm9wcykge1xuICAgIGxldCBvbGRLZXllZExpc3Q6IHsgW2tleTogc3RyaW5nXTogbnVtYmVyIH0gPSB7fTtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IG9sZFRyZWVMZW5ndGg7IGkrKykge1xuICAgICAgb2xkS2V5ZWRMaXN0W29sZFRyZWVbaV0ucHJvcHMua2V5XSA9IGk7XG4gICAgfVxuXG4gICAgbGV0IG5ld0tleWVkTGlzdDogeyBba2V5OiBzdHJpbmddOiBudW1iZXIgfSA9IHt9O1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbmV3VHJlZUxlbmd0aDsgaSsrKSB7XG4gICAgICBuZXdLZXllZExpc3RbbmV3VHJlZVtpXS5wcm9wcy5rZXldID0gaTtcbiAgICB9XG5cbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IG5ld1RyZWVMZW5ndGg7IGkrKykge1xuICAgICAgbGV0IGNoaWxkVm5vZGUgPSBuZXdUcmVlW2ldO1xuICAgICAgbGV0IG9sZENoaWxkVm5vZGUgPSBvbGRUcmVlW29sZEtleWVkTGlzdFtjaGlsZFZub2RlLnByb3BzLmtleV1dO1xuICAgICAgbGV0IHNob3VsZFBhdGNoID0gdHJ1ZTtcblxuICAgICAgaWYgKG9sZENoaWxkVm5vZGUpIHtcbiAgICAgICAgY2hpbGRWbm9kZS5kb20gPSBvbGRDaGlsZFZub2RlLmRvbTtcbiAgICAgICAgaWYgKFwidi1vbmNlXCIgaW4gY2hpbGRWbm9kZS5wcm9wcyB8fCAoY2hpbGRWbm9kZS5wcm9wcy5zaG91bGR1cGRhdGUgJiYgY2hpbGRWbm9kZS5wcm9wcy5zaG91bGR1cGRhdGUoY2hpbGRWbm9kZSwgb2xkQ2hpbGRWbm9kZSkgPT09IGZhbHNlKSkge1xuICAgICAgICAgIC8vIHNraXAgdGhpcyBwYXRjaFxuICAgICAgICAgIGNoaWxkVm5vZGUuY2hpbGRyZW4gPSBvbGRDaGlsZFZub2RlLmNoaWxkcmVuO1xuICAgICAgICAgIHNob3VsZFBhdGNoID0gZmFsc2U7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgc2V0QXR0cmlidXRlcyhjaGlsZFZub2RlLCBvbGRDaGlsZFZub2RlKTtcbiAgICAgICAgICBpZiAodmFseXJpYW5BcHAuaXNNb3VudGVkKSB7XG4gICAgICAgICAgICBjaGlsZFZub2RlLnByb3BzLm9udXBkYXRlICYmIGNoaWxkVm5vZGUucHJvcHMub251cGRhdGUoY2hpbGRWbm9kZSwgb2xkQ2hpbGRWbm9kZSk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGNoaWxkVm5vZGUucHJvcHMub25jcmVhdGUgJiYgY2hpbGRWbm9kZS5wcm9wcy5vbmNyZWF0ZShjaGlsZFZub2RlKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGNoaWxkVm5vZGUuZG9tID0gY3JlYXRlRG9tRWxlbWVudChjaGlsZFZub2RlLnRhZywgY2hpbGRWbm9kZS5pc1NWRyk7XG4gICAgICAgIHNldEF0dHJpYnV0ZXMoY2hpbGRWbm9kZSk7XG4gICAgICAgIGNoaWxkVm5vZGUucHJvcHMub25jcmVhdGUgJiYgY2hpbGRWbm9kZS5wcm9wcy5vbmNyZWF0ZShjaGlsZFZub2RlKTtcbiAgICAgIH1cblxuICAgICAgaWYgKG5ld1Zub2RlLmRvbS5jaGlsZE5vZGVzW2ldID09PSBVbmQpIHtcbiAgICAgICAgbmV3Vm5vZGUuZG9tLmFwcGVuZENoaWxkKGNoaWxkVm5vZGUuZG9tKTtcbiAgICAgIH0gZWxzZSBpZiAobmV3Vm5vZGUuZG9tLmNoaWxkTm9kZXNbaV0gIT09IGNoaWxkVm5vZGUuZG9tKSB7XG4gICAgICAgIG9sZFRyZWVbaV0gJiYgbmV3S2V5ZWRMaXN0W29sZFRyZWVbaV0ucHJvcHMua2V5XSA9PT0gVW5kICYmIG9ucmVtb3ZlKG9sZFRyZWVbaV0pO1xuICAgICAgICBuZXdWbm9kZS5kb20ucmVwbGFjZUNoaWxkKGNoaWxkVm5vZGUuZG9tLCBuZXdWbm9kZS5kb20uY2hpbGROb2Rlc1tpXSk7XG4gICAgICB9XG5cbiAgICAgIHNob3VsZFBhdGNoICYmIHBhdGNoKGNoaWxkVm5vZGUsIG9sZENoaWxkVm5vZGUsIHZhbHlyaWFuQXBwKTtcbiAgICB9XG5cbiAgICAvLyBGb3IgdGhlIHJlc3Qgb2YgdGhlIGNoaWxkcmVuLCB3ZSBzaG91bGQgcmVtb3ZlIHRoZW1cbiAgICBmb3IgKGxldCBpID0gbmV3VHJlZUxlbmd0aDsgaSA8IG9sZFRyZWVMZW5ndGg7IGkrKykge1xuICAgICAgaWYgKG5ld0tleWVkTGlzdFtvbGRUcmVlW2ldLnByb3BzLmtleV0gPT09IFVuZCkge1xuICAgICAgICBsZXQgb2xkQ2hpbGRWbm9kZSA9IG9sZFRyZWVbaV07XG4gICAgICAgIG9ucmVtb3ZlKG9sZENoaWxkVm5vZGUpO1xuICAgICAgICBvbGRDaGlsZFZub2RlLmRvbS5wYXJlbnROb2RlICYmIG9sZENoaWxkVm5vZGUuZG9tLnBhcmVudE5vZGUucmVtb3ZlQ2hpbGQob2xkQ2hpbGRWbm9kZS5kb20pO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybjtcbiAgfVxuXG4gIC8vIElmIG5ldyB0cmVlIGFuZCBvbGQgdHJlZSBoYXZlIG1vcmUgdGhhbiBvbmUgY2hpbGQsIHdlIHNob3VsZCB1cGRhdGUgdGhlIGRvbVxuICBmb3IgKGxldCBpID0gMDsgaSA8IG5ld1RyZWVMZW5ndGg7IGkrKykge1xuICAgIGxldCBuZXdDaGlsZFZub2RlID0gbmV3VHJlZVtpXTtcblxuICAgIC8vIE9sZCBjaGlsZCBleGlzdHNcbiAgICBpZiAoaSA8IG9sZFRyZWVMZW5ndGgpIHtcbiAgICAgIGxldCBvbGRDaGlsZFZub2RlID0gb2xkVHJlZVtpXTtcbiAgICAgIC8vIE5ldyBjaGlsZCBpcyBhIHRleHQgbm9kZVxuICAgICAgaWYgKG5ld0NoaWxkVm5vZGUudGFnID09PSBUZXh0U3RyaW5nKSB7XG4gICAgICAgIC8vIE9sZCBjaGlsZCBpcyBhIHRleHQgbm9kZVxuICAgICAgICBpZiAob2xkQ2hpbGRWbm9kZS50YWcgPT09IFRleHRTdHJpbmcpIHtcbiAgICAgICAgICBuZXdDaGlsZFZub2RlLmRvbSA9IG9sZENoaWxkVm5vZGUuZG9tO1xuICAgICAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBlcWVxZXFcbiAgICAgICAgICBpZiAobmV3Q2hpbGRWbm9kZS5kb20ubm9kZVZhbHVlICE9IG5ld0NoaWxkVm5vZGUubm9kZVZhbHVlKSB7XG4gICAgICAgICAgICBuZXdDaGlsZFZub2RlLmRvbS5ub2RlVmFsdWUgPSBuZXdDaGlsZFZub2RlLm5vZGVWYWx1ZSBhcyBzdHJpbmc7XG4gICAgICAgICAgfVxuICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gT2xkIGNoaWxkIGlzIGEgbm9ybWFsIG5vZGVcbiAgICAgICAgbmV3Q2hpbGRWbm9kZS5kb20gPSBkb2N1bWVudC5jcmVhdGVUZXh0Tm9kZShuZXdDaGlsZFZub2RlLm5vZGVWYWx1ZSBhcyBzdHJpbmcpIGFzIHVua25vd24gYXMgRG9tRWxlbWVudDtcbiAgICAgICAgb25yZW1vdmUob2xkQ2hpbGRWbm9kZSk7XG4gICAgICAgIG5ld1Zub2RlLmRvbS5yZXBsYWNlQ2hpbGQobmV3Q2hpbGRWbm9kZS5kb20sIG9sZENoaWxkVm5vZGUuZG9tKTtcblxuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cblxuICAgICAgLy8gTmV3IGNoaWxkIGlzIGEgbm9ybWFsIG5vZGVcbiAgICAgIC8vIE9sZCBjaGlsZCBpcyB0aGUgc2FtZSB0eXBlIGFzIG5ldyBjaGlsZFxuICAgICAgaWYgKG9sZENoaWxkVm5vZGUudGFnID09PSBuZXdDaGlsZFZub2RlLnRhZykge1xuICAgICAgICBuZXdDaGlsZFZub2RlLmRvbSA9IG9sZENoaWxkVm5vZGUuZG9tO1xuICAgICAgICAvLyBJZiB3ZSBoYXZlIGEgdi1vbmNlIGRpcmVjdGl2ZSBvciBhIHNob3VsZHVwZGF0ZSBtZXRob2QgdGhhdCByZXR1cm5zIGZhbHNlLCB3ZSBza2lwIHRoZSB1cGRhdGVcbiAgICAgICAgaWYgKG5ld0NoaWxkVm5vZGUucHJvcHNbXCJ2LW9uY2VcIl0gfHwgKG5ld0NoaWxkVm5vZGUucHJvcHMuc2hvdWxkdXBkYXRlICYmIG5ld0NoaWxkVm5vZGUucHJvcHMuc2hvdWxkdXBkYXRlKG5ld0NoaWxkVm5vZGUsIG9sZENoaWxkVm5vZGUpID09PSBmYWxzZSkpIHtcbiAgICAgICAgICBuZXdDaGlsZFZub2RlLmNoaWxkcmVuID0gb2xkQ2hpbGRWbm9kZS5jaGlsZHJlbjtcbiAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFdlIHVwZGF0ZSB0aGUgZG9tIGVsZW1lbnRcbiAgICAgICAgc2V0QXR0cmlidXRlcyhuZXdDaGlsZFZub2RlLCBvbGRDaGlsZFZub2RlKTtcbiAgICAgICAgaWYgKHZhbHlyaWFuQXBwLmlzTW91bnRlZCkge1xuICAgICAgICAgIG5ld0NoaWxkVm5vZGUucHJvcHMub251cGRhdGUgJiYgbmV3Q2hpbGRWbm9kZS5wcm9wcy5vbnVwZGF0ZShuZXdDaGlsZFZub2RlLCBvbGRDaGlsZFZub2RlKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBuZXdDaGlsZFZub2RlLnByb3BzLm9uY3JlYXRlICYmIG5ld0NoaWxkVm5vZGUucHJvcHMub25jcmVhdGUobmV3Q2hpbGRWbm9kZSk7XG4gICAgICAgIH1cblxuICAgICAgICBwYXRjaChuZXdDaGlsZFZub2RlLCBvbGRDaGlsZFZub2RlLCB2YWx5cmlhbkFwcCk7XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuXG4gICAgICAvLyBPbGQgY2hpbGQgaXMgb2YgYSBkaWZmZXJlbnQgdHlwZSB0aGFuIG5ldyBjaGlsZFxuICAgICAgbmV3Q2hpbGRWbm9kZS5kb20gPSBjcmVhdGVEb21FbGVtZW50KG5ld0NoaWxkVm5vZGUudGFnLCBuZXdDaGlsZFZub2RlLmlzU1ZHKTtcbiAgICAgIHNldEF0dHJpYnV0ZXMobmV3Q2hpbGRWbm9kZSk7XG4gICAgICBvbGRDaGlsZFZub2RlLnRhZyAhPT0gVGV4dFN0cmluZyAmJiBvbnJlbW92ZShvbGRDaGlsZFZub2RlKTtcbiAgICAgIG5ld0NoaWxkVm5vZGUucHJvcHMub25jcmVhdGUgJiYgbmV3Q2hpbGRWbm9kZS5wcm9wcy5vbmNyZWF0ZShuZXdDaGlsZFZub2RlKTtcbiAgICAgIG5ld1Zub2RlLmRvbS5yZXBsYWNlQ2hpbGQobmV3Q2hpbGRWbm9kZS5kb20sIG9sZENoaWxkVm5vZGUuZG9tKTtcbiAgICAgIHBhdGNoKG5ld0NoaWxkVm5vZGUsIGVtcHR5Vm5vZGUsIHZhbHlyaWFuQXBwKTtcbiAgICAgIGNvbnRpbnVlO1xuICAgIH1cblxuICAgIC8vIE9sZCBjaGlsZCBkb2VzIG5vdCBleGlzdHNcbiAgICAvLyBOZXcgY2hpbGQgaXMgYSB0ZXh0IG5vZGVcbiAgICBpZiAobmV3Q2hpbGRWbm9kZS50YWcgPT09IFRleHRTdHJpbmcpIHtcbiAgICAgIG5ld0NoaWxkVm5vZGUuZG9tID0gZG9jdW1lbnQuY3JlYXRlVGV4dE5vZGUobmV3Q2hpbGRWbm9kZS5ub2RlVmFsdWUgYXMgc3RyaW5nKSBhcyB1bmtub3duIGFzIERvbUVsZW1lbnQ7XG4gICAgICBuZXdWbm9kZS5kb20uYXBwZW5kQ2hpbGQobmV3Q2hpbGRWbm9kZS5kb20pO1xuICAgICAgY29udGludWU7XG4gICAgfVxuXG4gICAgLy8gTmV3IGNoaWxkIGlzIGEgbm9ybWFsIG5vZGVcbiAgICBuZXdDaGlsZFZub2RlLmRvbSA9IGNyZWF0ZURvbUVsZW1lbnQobmV3Q2hpbGRWbm9kZS50YWcsIG5ld0NoaWxkVm5vZGUuaXNTVkcpO1xuICAgIHNldEF0dHJpYnV0ZXMobmV3Q2hpbGRWbm9kZSk7XG4gICAgbmV3Vm5vZGUuZG9tLmFwcGVuZENoaWxkKG5ld0NoaWxkVm5vZGUuZG9tKTtcbiAgICBuZXdDaGlsZFZub2RlLnByb3BzLm9uY3JlYXRlICYmIG5ld0NoaWxkVm5vZGUucHJvcHMub25jcmVhdGUobmV3Q2hpbGRWbm9kZSk7XG4gICAgcGF0Y2gobmV3Q2hpbGRWbm9kZSwgZW1wdHlWbm9kZSwgdmFseXJpYW5BcHApO1xuICB9XG5cbiAgLy8gRm9yIHRoZSByZXN0IG9mIHRoZSBjaGlsZHJlbiwgd2Ugc2hvdWxkIHJlbW92ZSB0aGVtXG4gIGZvciAobGV0IGkgPSBuZXdUcmVlTGVuZ3RoOyBpIDwgb2xkVHJlZUxlbmd0aDsgaSsrKSB7XG4gICAgbGV0IG9sZENoaWxkVm5vZGUgPSBvbGRUcmVlW2ldO1xuICAgIG9sZENoaWxkVm5vZGUudGFnICE9PSBUZXh0U3RyaW5nICYmIG9ucmVtb3ZlKG9sZENoaWxkVm5vZGUpO1xuICAgIG9sZENoaWxkVm5vZGUuZG9tLnBhcmVudE5vZGUgJiYgb2xkQ2hpbGRWbm9kZS5kb20ucGFyZW50Tm9kZS5yZW1vdmVDaGlsZChvbGRDaGlsZFZub2RlLmRvbSk7XG4gIH1cbn1cblxuLyoqKiBEaXJlY3RpdmVzICoqKi9cblxuZnVuY3Rpb24gZGlyZWN0aXZlKG5hbWU6IHN0cmluZywgZGlyZWN0aXZlOiBEaXJlY3RpdmUpIHtcbiAgbGV0IGZ1bGxOYW1lID0gYHYtJHtuYW1lfWA7XG4gIGRpcmVjdGl2ZXNbZnVsbE5hbWVdID0gZGlyZWN0aXZlO1xuICByZXNlcnZlZFByb3BzW2Z1bGxOYW1lXSA9IHRydWU7XG59XG5cbmZ1bmN0aW9uIGhpZGVEaXJlY3RpdmUodGVzdDogYm9vbGVhbik6IERpcmVjdGl2ZSB7XG4gIHJldHVybiAoYm9vbDogYm9vbGVhbiwgdm5vZGU6IElWbm9kZSwgb2xkVm5vZGU/OiBJVm5vZGUpID0+IHtcbiAgICBsZXQgdmFsdWUgPSB0ZXN0ID8gYm9vbCA6ICFib29sO1xuICAgIGlmICh2YWx1ZSkge1xuICAgICAgbGV0IG5ld2RvbSA9IGRvY3VtZW50LmNyZWF0ZVRleHROb2RlKFwiXCIpO1xuICAgICAgaWYgKG9sZFZub2RlICYmIG9sZFZub2RlLmRvbSAmJiBvbGRWbm9kZS5kb20ucGFyZW50Tm9kZSkge1xuICAgICAgICBvbGRWbm9kZS50YWcgIT09IFRleHRTdHJpbmcgJiYgb25yZW1vdmUob2xkVm5vZGUpO1xuICAgICAgICBvbGRWbm9kZS5kb20ucGFyZW50Tm9kZS5yZXBsYWNlQ2hpbGQobmV3ZG9tLCBvbGRWbm9kZS5kb20pO1xuICAgICAgfVxuICAgICAgdm5vZGUudGFnID0gVGV4dFN0cmluZztcbiAgICAgIHZub2RlLmNoaWxkcmVuID0gW107XG4gICAgICB2bm9kZS5wcm9wcyA9IHt9O1xuICAgICAgdm5vZGUuZG9tID0gbmV3ZG9tIGFzIHVua25vd24gYXMgRG9tRWxlbWVudDtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gIH07XG59XG5cbmNvbnN0IGRpcmVjdGl2ZXM6IERpcmVjdGl2ZXMgPSB7XG4gIFwidi1pZlwiOiBoaWRlRGlyZWN0aXZlKGZhbHNlKSxcbiAgXCJ2LXVubGVzc1wiOiBoaWRlRGlyZWN0aXZlKHRydWUpLFxuICBcInYtZm9yXCI6IChzZXQ6IHVua25vd25bXSwgdm5vZGU6IFZub2RlV2l0aERvbSkgPT4ge1xuICAgIHZub2RlLmNoaWxkcmVuID0gc2V0Lm1hcCh2bm9kZS5jaGlsZHJlblswXSk7XG4gIH0sXG4gIFwidi1zaG93XCI6IChib29sOiBib29sZWFuLCB2bm9kZTogVm5vZGVXaXRoRG9tKSA9PiB7XG4gICAgKHZub2RlLmRvbSBhcyB1bmtub3duIGFzIHsgc3R5bGU6IHsgZGlzcGxheTogc3RyaW5nIH0gfSkuc3R5bGUuZGlzcGxheSA9IGJvb2wgPyBcIlwiIDogXCJub25lXCI7XG4gIH0sXG4gIFwidi1jbGFzc1wiOiAoY2xhc3NlczogeyBbeDogc3RyaW5nXTogYm9vbGVhbiB9LCB2bm9kZTogVm5vZGVXaXRoRG9tKSA9PiB7XG4gICAgZm9yIChsZXQgbmFtZSBpbiBjbGFzc2VzKSB7XG4gICAgICAodm5vZGUuZG9tIGFzIERvbUVsZW1lbnQpLmNsYXNzTGlzdC50b2dnbGUobmFtZSwgY2xhc3Nlc1tuYW1lXSk7XG4gICAgfVxuICB9LFxuICBcInYtaHRtbFwiOiAoaHRtbDogc3RyaW5nLCB2bm9kZTogVm5vZGVXaXRoRG9tKSA9PiB7XG4gICAgdm5vZGUuY2hpbGRyZW4gPSBbdHJ1c3QoaHRtbCldO1xuICB9LFxuICBcInYtbW9kZWxcIjogKFttb2RlbCwgcHJvcGVydHksIGV2ZW50XTogYW55W10sIHZub2RlOiBWbm9kZVdpdGhEb20sIG9sZFZub2RlPzogVm5vZGVXaXRoRG9tKSA9PiB7XG4gICAgbGV0IHZhbHVlO1xuICAgIGxldCBoYW5kbGVyO1xuICAgIGlmICh2bm9kZS5uYW1lID09PSBcImlucHV0XCIpIHtcbiAgICAgIGV2ZW50ID0gZXZlbnQgfHwgXCJvbmlucHV0XCI7XG4gICAgICBzd2l0Y2ggKHZub2RlLnByb3BzLnR5cGUpIHtcbiAgICAgICAgY2FzZSBcImNoZWNrYm94XCI6IHtcbiAgICAgICAgICBpZiAoQXJyYXkuaXNBcnJheShtb2RlbFtwcm9wZXJ0eV0pKSB7XG4gICAgICAgICAgICBoYW5kbGVyID0gKGU6IEV2ZW50KSA9PiB7XG4gICAgICAgICAgICAgIGxldCB2YWwgPSAoZS50YXJnZXQgYXMgRG9tRWxlbWVudCAmIFJlY29yZDxzdHJpbmcsIGFueT4pLnZhbHVlO1xuICAgICAgICAgICAgICBsZXQgaWR4ID0gbW9kZWxbcHJvcGVydHldLmluZGV4T2YodmFsKTtcbiAgICAgICAgICAgICAgaWYgKGlkeCA9PT0gLTEpIHtcbiAgICAgICAgICAgICAgICBtb2RlbFtwcm9wZXJ0eV0ucHVzaCh2YWwpO1xuICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIG1vZGVsW3Byb3BlcnR5XS5zcGxpY2UoaWR4LCAxKTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIHZhbHVlID0gbW9kZWxbcHJvcGVydHldLmluZGV4T2Yodm5vZGUuZG9tLnZhbHVlKSAhPT0gLTE7XG4gICAgICAgICAgfSBlbHNlIGlmIChcInZhbHVlXCIgaW4gdm5vZGUucHJvcHMpIHtcbiAgICAgICAgICAgIGhhbmRsZXIgPSAoKSA9PiB7XG4gICAgICAgICAgICAgIGlmIChtb2RlbFtwcm9wZXJ0eV0gPT09IHZub2RlLnByb3BzLnZhbHVlKSB7XG4gICAgICAgICAgICAgICAgbW9kZWxbcHJvcGVydHldID0gbnVsbDtcbiAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBtb2RlbFtwcm9wZXJ0eV0gPSB2bm9kZS5wcm9wcy52YWx1ZTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIHZhbHVlID0gbW9kZWxbcHJvcGVydHldID09PSB2bm9kZS5wcm9wcy52YWx1ZTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgaGFuZGxlciA9ICgpID0+IChtb2RlbFtwcm9wZXJ0eV0gPSAhbW9kZWxbcHJvcGVydHldKTtcbiAgICAgICAgICAgIHZhbHVlID0gbW9kZWxbcHJvcGVydHldO1xuICAgICAgICAgIH1cbiAgICAgICAgICBzZXRBdHRyaWJ1dGUoXCJjaGVja2VkXCIsIHZhbHVlLCB2bm9kZSwgb2xkVm5vZGUpO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgICAgIGNhc2UgXCJyYWRpb1wiOiB7XG4gICAgICAgICAgc2V0QXR0cmlidXRlKFwiY2hlY2tlZFwiLCBtb2RlbFtwcm9wZXJ0eV0gPT09IHZub2RlLmRvbS52YWx1ZSwgdm5vZGUsIG9sZFZub2RlKTtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgICAgICBkZWZhdWx0OiB7XG4gICAgICAgICAgc2V0QXR0cmlidXRlKFwidmFsdWVcIiwgbW9kZWxbcHJvcGVydHldLCB2bm9kZSwgb2xkVm5vZGUpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSBlbHNlIGlmICh2bm9kZS5uYW1lID09PSBcInNlbGVjdFwiKSB7XG4gICAgICBldmVudCA9IGV2ZW50IHx8IFwib25jbGlja1wiO1xuICAgICAgaWYgKHZub2RlLnByb3BzLm11bHRpcGxlKSB7XG4gICAgICAgIGhhbmRsZXIgPSAoZTogRXZlbnQgJiBSZWNvcmQ8c3RyaW5nLCBhbnk+KSA9PiB7XG4gICAgICAgICAgbGV0IHZhbCA9IChlLnRhcmdldCBhcyBEb21FbGVtZW50ICYgUmVjb3JkPHN0cmluZywgYW55PikudmFsdWU7XG4gICAgICAgICAgaWYgKGUuY3RybEtleSkge1xuICAgICAgICAgICAgbGV0IGlkeCA9IG1vZGVsW3Byb3BlcnR5XS5pbmRleE9mKHZhbCk7XG4gICAgICAgICAgICBpZiAoaWR4ID09PSAtMSkge1xuICAgICAgICAgICAgICBtb2RlbFtwcm9wZXJ0eV0ucHVzaCh2YWwpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgbW9kZWxbcHJvcGVydHldLnNwbGljZShpZHgsIDEpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBtb2RlbFtwcm9wZXJ0eV0uc3BsaWNlKDAsIG1vZGVsW3Byb3BlcnR5XS5sZW5ndGgpO1xuICAgICAgICAgICAgbW9kZWxbcHJvcGVydHldLnB1c2godmFsKTtcbiAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIHZub2RlLmNoaWxkcmVuLmZvckVhY2goKGNoaWxkOiBJVm5vZGUpID0+IHtcbiAgICAgICAgICBpZiAoY2hpbGQudGFnID09PSBcIm9wdGlvblwiKSB7XG4gICAgICAgICAgICBsZXQgdmFsdWUgPSBcInZhbHVlXCIgaW4gY2hpbGQucHJvcHMgPyBjaGlsZC5wcm9wcy52YWx1ZSA6IGNoaWxkLmNoaWxkcmVuLmpvaW4oXCJcIikudHJpbSgpO1xuICAgICAgICAgICAgY2hpbGQucHJvcHMuc2VsZWN0ZWQgPSBtb2RlbFtwcm9wZXJ0eV0uaW5kZXhPZih2YWx1ZSkgIT09IC0xO1xuICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB2bm9kZS5jaGlsZHJlbi5mb3JFYWNoKChjaGlsZDogSVZub2RlKSA9PiB7XG4gICAgICAgICAgaWYgKGNoaWxkLnRhZyA9PT0gXCJvcHRpb25cIikge1xuICAgICAgICAgICAgbGV0IHZhbHVlID0gXCJ2YWx1ZVwiIGluIGNoaWxkLnByb3BzID8gY2hpbGQucHJvcHMudmFsdWUgOiBjaGlsZC5jaGlsZHJlbi5qb2luKFwiXCIpLnRyaW0oKTtcbiAgICAgICAgICAgIGNoaWxkLnByb3BzLnNlbGVjdGVkID0gdmFsdWUgPT09IG1vZGVsW3Byb3BlcnR5XTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgIH0gZWxzZSBpZiAodm5vZGUubmFtZSA9PT0gXCJ0ZXh0YXJlYVwiKSB7XG4gICAgICBldmVudCA9IGV2ZW50IHx8IFwib25pbnB1dFwiO1xuICAgICAgdm5vZGUuY2hpbGRyZW4gPSBbbW9kZWxbcHJvcGVydHldXTtcbiAgICB9XG5cbiAgICBpZiAoIXZub2RlLnByb3BzW2V2ZW50XSkge1xuICAgICAgaWYgKCFoYW5kbGVyKSB7XG4gICAgICAgIGhhbmRsZXIgPSAoZTogRXZlbnQpID0+IChtb2RlbFtwcm9wZXJ0eV0gPSAoZS50YXJnZXQgYXMgRG9tRWxlbWVudCAmIFJlY29yZDxzdHJpbmcsIGFueT4pLnZhbHVlKTtcbiAgICAgIH1cbiAgICAgIHNldEF0dHJpYnV0ZShldmVudCwgaGFuZGxlciwgdm5vZGUsIG9sZFZub2RlKTtcbiAgICB9XG4gIH1cbn07XG5cbi8qKiogUGx1Z2lucyAqKiovXG5jb25zdCBwbHVnaW5zID0gbmV3IE1hcDxQbHVnaW4sIGFueT4oKTtcblxuZnVuY3Rpb24gdXNlKHBsdWdpbjogUGx1Z2luLCBvcHRpb25zPzogUmVjb3JkPHN0cmluZyB8IG51bWJlciB8IHN5bWJvbCwgYW55Pik6IHZvaWQgfCBhbnkge1xuICBpZiAocGx1Z2lucy5oYXMocGx1Z2luKSkge1xuICAgIHJldHVybiBwbHVnaW5zLmdldChwbHVnaW4pO1xuICB9XG5cbiAgbGV0IHJlc3VsdCA9IHBsdWdpbih2LCBvcHRpb25zKTtcbiAgcGx1Z2lucy5zZXQocGx1Z2luLCByZXN1bHQpO1xuICByZXR1cm4gcmVzdWx0O1xufVxuXG4vKioqIEh5cGVyc2NyaXB0ICoqKi9cblxuZXhwb3J0IGNvbnN0IHY6IFZhbHlyaWFuID0gZnVuY3Rpb24gdih0YWdPckNvbXBvbmVudDogc3RyaW5nIHwgVmFseXJpYW5Db21wb25lbnQsIHByb3BzOiBQcm9wcywgLi4uY2hpbGRyZW46IENoaWxkcmVuKTogSVZub2RlIHwgVm5vZGVDb21wb25lbnQge1xuICBpZiAodHlwZW9mIHRhZ09yQ29tcG9uZW50ID09PSBcInN0cmluZ1wiKSB7XG4gICAgcmV0dXJuIG5ldyBWbm9kZSh0YWdPckNvbXBvbmVudCwgcHJvcHMgfHwge30sIGNoaWxkcmVuKTtcbiAgfVxuXG4gIGNvbnN0IHZub2RlID0gbmV3IFZub2RlKFwiX19jb21wb25lbnRfX1wiLCBwcm9wcyB8fCB7fSwgY2hpbGRyZW4pO1xuICB2bm9kZS5jb21wb25lbnQgPSB0YWdPckNvbXBvbmVudDtcbiAgcmV0dXJuIHZub2RlIGFzIFZub2RlQ29tcG9uZW50O1xufTtcblxudi5mcmFnbWVudCA9IChwcm9wczogUHJvcHMsIC4uLmNoaWxkcmVuOiBDaGlsZHJlbik6IENoaWxkcmVuID0+IHtcbiAgcmV0dXJuIGNoaWxkcmVuO1xufTtcblxuLyoqKiBWIHByb3BlcnRpZXMgYW5kIG1ldGhvZHMgKioqL1xuLy8gVGhpcyBpcyBpbnRlbmRlZCB0byBtYWtlIHRoZSBwcm9wZXJ0aWVzIGFuZCBtZXRob2RzIGF2YWlsYWJsZSBmb3IgcGx1Z2luc1xudi5jdXJyZW50ID0gY3VycmVudDtcblxudi5kaXJlY3RpdmVzID0gZGlyZWN0aXZlcztcblxudi5yZXNlcnZlZFByb3BzID0gcmVzZXJ2ZWRQcm9wcztcblxudi5pc1Zub2RlID0gaXNWbm9kZTtcbnYuaXNDb21wb25lbnQgPSBpc0NvbXBvbmVudDtcbnYuaXNWbm9kZUNvbXBvbmVudCA9IGlzVm5vZGVDb21wb25lbnQ7XG5cbnYuaXNOb2RlSnMgPSBpc05vZGVKcztcbnYudHJ1c3QgPSB0cnVzdDtcblxudi5vbkNsZWFudXAgPSBvbkNsZWFudXA7XG52Lm9uVW5tb3VudCA9IG9uVW5tb3VudDtcbnYub25Nb3VudCA9IG9uTW91bnQ7XG52Lm9uVXBkYXRlID0gb25VcGRhdGU7XG5cbnYubW91bnQgPSBtb3VudDtcbnYudW5tb3VudCA9IHVubW91bnQ7XG52LnVwZGF0ZSA9IHVwZGF0ZTtcblxudi5zZXRBdHRyaWJ1dGUgPSBzZXRBdHRyaWJ1dGU7XG52LmRpcmVjdGl2ZSA9IGRpcmVjdGl2ZTtcbnYudXNlID0gdXNlO1xuIl19 \ No newline at end of file diff --git a/lib/index.ts b/lib/index.ts index 87e7a0d..3680816 100644 --- a/lib/index.ts +++ b/lib/index.ts @@ -1,3 +1,5 @@ +/* eslint-disable no-use-before-define */ +/* eslint-disable sonarjs/cognitive-complexity */ /*** Vnode ***/ import { @@ -21,27 +23,27 @@ import { /*** Constants ***/ const ComponentString = "__component__"; const TextString = "#text"; -export const isNodeJs = Boolean(typeof process !== "undefined" && process.versions && process.versions.node); +const isNodeJs = Boolean(typeof process !== "undefined" && process.versions && process.versions.node); const ValyrianSymbol = Symbol("Valyrian"); const Und = undefined; /*** Vnode ***/ -export const Vnode = function Vnode(this: IVnode, tag: string, props: Props, children: Children) { +const Vnode = function Vnode(this: IVnode, tag: string, props: Props, children: Children) { this.props = props; this.children = children; this.tag = tag; } as unknown as IVnode; -export function isVnode(object?: unknown | IVnode): object is IVnode { +function isVnode(object?: unknown | IVnode): object is IVnode { return object instanceof Vnode; } -export function isComponent(component?: unknown | ValyrianComponent): component is ValyrianComponent { +function isComponent(component?: unknown | ValyrianComponent): component is ValyrianComponent { return typeof component === "function" || (typeof component === "object" && component !== null && "view" in component); } -export function isVnodeComponent(vnode?: unknown | VnodeComponent): vnode is VnodeComponent { +function isVnodeComponent(vnode?: unknown | VnodeComponent): vnode is VnodeComponent { return vnode instanceof Vnode && vnode.tag === ComponentString; } @@ -73,7 +75,7 @@ function domToVnode(dom: DomElement): VnodeWithDom { return vnode as VnodeWithDom; } -export const trust = (htmlString: string): Children => { +const trust = (htmlString: string): Children => { let div = createDomElement("div"); div.innerHTML = htmlString.trim(); @@ -102,25 +104,25 @@ const reservedProps: ReservedProps = { const current: Current = {}; -export function onCleanup(callback: Function) { +function onCleanup(callback: Function) { if (current.app?.onCleanup.indexOf(callback) === -1) { current.app?.onCleanup.push(callback); } } -export function onUnmount(callback: Function) { +function onUnmount(callback: Function) { if (current.app?.onUnmount.indexOf(callback) === -1) { current.app?.onUnmount.push(callback); } } -export function onMount(callback: Function) { +function onMount(callback: Function) { if (current.app?.onMount.indexOf(callback) === -1) { current.app?.onMount.push(callback); } } -export function onUpdate(callback: Function) { +function onUpdate(callback: Function) { if (current.app?.onUpdate.indexOf(callback) === -1) { current.app?.onUpdate.push(callback); } @@ -134,7 +136,7 @@ export function onUpdate(callback: Function) { mount('#app',
Hello world
); // App is a Vnode component (Vnode with tag __component__) */ -export function mount(container: DomElement | string, component: ValyrianComponent | IVnode): void | string { +function mount(container: DomElement | string, component: ValyrianComponent | IVnode): void | string { let appContainer = null; if (isNodeJs) { @@ -221,7 +223,7 @@ function callUpdate(valyrianApp: ValyrianApp) { valyrianApp.onUpdate = []; } -export function update(component?: ValyrianComponent | IVnode): void | string { +function update(component?: ValyrianComponent | IVnode): void | string { if (component && component[ValyrianSymbol]) { let valyrianApp = component[ValyrianSymbol]; current.app = valyrianApp; @@ -244,7 +246,7 @@ export function update(component?: ValyrianComponent | IVnode): void | string { } } -export function unmount(component?: ValyrianComponent | IVnode): void | string { +function unmount(component?: ValyrianComponent | IVnode): void | string { if (!component || !component[ValyrianSymbol]) { return; } @@ -320,7 +322,7 @@ function sharedSetAttribute(prop: string, value: any, vnode: VnodeWithDom, oldVn } } -export function setAttribute(name: string, value: any, vnode: VnodeWithDom, oldVnode?: VnodeWithDom) { +function setAttribute(name: string, value: any, vnode: VnodeWithDom, oldVnode?: VnodeWithDom) { vnode.props[name] = value; sharedSetAttribute(name, value, vnode, oldVnode); @@ -392,12 +394,12 @@ function patch(newVnode: VnodeWithDom, oldVnode: VnodeWithDom | IVnode = emptyVn // If the tree is keyed list and is not first render and old tree is keyed list too if (oldTreeLength && "key" in newTree[0].props && "key" in oldTree[0].props) { - let oldKeyedList: {[key: string]: number} = {}; + let oldKeyedList: { [key: string]: number } = {}; for (let i = 0; i < oldTreeLength; i++) { oldKeyedList[oldTree[i].props.key] = i; } - let newKeyedList: {[key: string]: number} = {}; + let newKeyedList: { [key: string]: number } = {}; for (let i = 0; i < newTreeLength; i++) { newKeyedList[newTree[i].props.key] = i; } @@ -534,7 +536,7 @@ function patch(newVnode: VnodeWithDom, oldVnode: VnodeWithDom | IVnode = emptyVn /*** Directives ***/ -export function directive(name: string, directive: Directive) { +function directive(name: string, directive: Directive) { let fullName = `v-${name}`; directives[fullName] = directive; reservedProps[fullName] = true; @@ -562,7 +564,7 @@ const directives: Directives = { "v-if": hideDirective(false), "v-unless": hideDirective(true), "v-for": (set: unknown[], vnode: VnodeWithDom) => { - vnode.children = set.map(vnode.children[0] as (value: unknown) => Function); + vnode.children = set.map(vnode.children[0]); }, "v-show": (bool: boolean, vnode: VnodeWithDom) => { (vnode.dom as unknown as { style: { display: string } }).style.display = bool ? "" : "none"; @@ -665,7 +667,7 @@ const directives: Directives = { /*** Plugins ***/ const plugins = new Map(); -export function use(plugin: Plugin, options?: Record): void | any { +function use(plugin: Plugin, options?: Record): void | any { if (plugins.has(plugin)) { return plugins.get(plugin); } diff --git a/package.json b/package.json index e247e75..95ffc00 100644 --- a/package.json +++ b/package.json @@ -68,7 +68,6 @@ }, "devDependencies": { "@release-it/conventional-changelog": "^4.1.0", - "@types/mocha": "^9.1.0", "@types/node": "^17.0.18", "@typescript-eslint/eslint-plugin": "^5.12.0", "@typescript-eslint/parser": "^5.12.0", @@ -187,6 +186,8 @@ } }, "resolutions": { - "minimist": "^1.2.5" + "minimist": "^1.2.5", + "jpeg-js": "^0.4.0", + "ansi-regex": "^5.0.1" } -} +} \ No newline at end of file diff --git a/plugins/node.js b/plugins/node.js index b7439be..46e6e6b 100644 --- a/plugins/node.js +++ b/plugins/node.js @@ -13,10 +13,6 @@ let CleanCSS = require("clean-css"); const tsc = require("tsc-prog"); -global.fetch = fetch; -global.FormData = FormData; -global.document = treeAdapter.createDocument(); - let errorHandler = (resolve, reject) => (err) => { if (err) { return reject(err); @@ -302,6 +298,9 @@ function plugin(v) { mount = v.mount; unmount = v.unmount; isInUse = true; + global.fetch = fetch; + global.FormData = FormData; + global.document = treeAdapter.createDocument(); } plugin.inline = inline; @@ -313,7 +312,7 @@ plugin.domToHyperscript = treeAdapter.domToHyperscript; plugin.htmlToHyperscript = treeAdapter.htmlToHyperscript; plugin.render = (...args) => { if (!isInUse) { - throw new Error("This plugin is not in use. Please invoke `v.use(nodeJsPlugin)`"); + throw new Error("This plugin is not in use. Please invoke `v.use(nodePlugin)`"); } let Component = () => args; diff --git a/plugins/store.js b/plugins/store.js index 59d2146..18ce469 100644 --- a/plugins/store.js +++ b/plugins/store.js @@ -1,3 +1,6 @@ +let update = () => {}; +let current = {}; + function keyExists(objectname, object, key) { if (key in object === false) { throw new Error(`The ${objectname} "${key}" does not exists.`); @@ -70,9 +73,6 @@ function Store({ state = {}, getters = {}, actions = {}, mutations = {} } = {}) }; } -let update = () => {}; -let current = {}; - function plugin(v, options) { current = v.current; update = () => { @@ -83,8 +83,8 @@ function plugin(v, options) { if (options) { v.store = new Store(options); - v.commit = v.store.commit; - v.dispatch = v.store.dispatch; + v.commit = v.store.commit.bind(v.store); + v.dispatch = v.store.dispatch.bind(v.store); v.state = v.store.state; v.getters = v.store.getters; } diff --git a/test/directives_test.js b/test/directives_test.js index d5790c5..deaf13c 100644 --- a/test/directives_test.js +++ b/test/directives_test.js @@ -3,7 +3,8 @@ const dayjs = require("dayjs"); const { v } = require("../lib/index"); -require("../plugins/node"); +const plugin = require("../plugins/node"); +v.use(plugin); // eslint-disable-next-line max-lines-per-function describe("Directives", () => { diff --git a/test/hooks_test.js b/test/hooks_test.js index 6aab4b8..ed426a6 100644 --- a/test/hooks_test.js +++ b/test/hooks_test.js @@ -1,4 +1,4 @@ -import "../plugins/node"; +import nodePlugin from "../plugins/node"; import { v } from "../lib/index"; import plugin, { useEffect, useState, useRef, useCallback, useMemo } from "../plugins/hooks"; @@ -7,6 +7,7 @@ import expect from "expect"; import { v } from "../lib"; v.use(plugin); +v.use(nodePlugin); describe("Hooks", () => { describe("State hook", () => { diff --git a/test/hyperscript_test.js b/test/hyperscript_test.js index 4a53e15..9e2a203 100644 --- a/test/hyperscript_test.js +++ b/test/hyperscript_test.js @@ -1,8 +1,9 @@ -require("../plugins/node"); - import expect from "expect"; +import nodePlugin from "../plugins/node"; import { v } from "../lib"; +v.use(nodePlugin); + describe("Hyperscript", () => { it("should create a div element", () => { expect(v("div")).toEqual({ diff --git a/test/keyed_test.js b/test/keyed_test.js index c68a42c..799aa7c 100644 --- a/test/keyed_test.js +++ b/test/keyed_test.js @@ -1,7 +1,8 @@ import expect from "expect"; +import nodePlugin from "../plugins/node"; import { v } from "../lib/index"; -require("../plugins/node"); +v.use(nodePlugin); describe("Keyed lists", () => { let set = [1, 2, 3, 4, 5]; diff --git a/test/lifecycle_test.js b/test/lifecycle_test.js index 115632a..62cd4e6 100644 --- a/test/lifecycle_test.js +++ b/test/lifecycle_test.js @@ -1,8 +1,9 @@ -import "../plugins/node"; - import expect from "expect"; +import nodePlugin from "../plugins/node"; import { v } from "../lib/index"; +v.use(nodePlugin); + describe("Lifecycle", () => { it("Mount and update", () => { let s = 1; diff --git a/test/mount_n_update_test.js b/test/mount_n_update_test.js index 84c8049..03b4026 100644 --- a/test/mount_n_update_test.js +++ b/test/mount_n_update_test.js @@ -1,7 +1,8 @@ import expect from "expect"; +import nodePlugin from "../plugins/node"; import { v } from "../lib/index"; -require("../plugins/node"); +v.use(nodePlugin); describe("Mount and update", () => { it("Mount and update with POJO component", () => { diff --git a/test/request_test.js b/test/request_test.js index adda38d..e00d058 100644 --- a/test/request_test.js +++ b/test/request_test.js @@ -1,10 +1,11 @@ -import "../plugins/node"; - import expect from "expect"; import fastify from "fastify"; +import nodePlugin from "../plugins/node"; import request from "../plugins/request"; import { v } from "../lib/index"; +v.use(nodePlugin); + let posts = []; for (let i = 10; i--; ) { posts.push({ diff --git a/test/router_test.js b/test/router_test.js index 09175d7..ecd44d8 100644 --- a/test/router_test.js +++ b/test/router_test.js @@ -1,11 +1,11 @@ -import "../plugins/node"; - import plugin, { Router } from "../plugins/router"; import expect from "expect"; +import nodePlugin from "../plugins/node"; import { v } from "../lib/index"; v.use(plugin); +v.use(nodePlugin); // eslint-disable-next-line max-lines-per-function describe("Router", () => { diff --git a/test/signals_test.js b/test/signals_test.js index 74bc501..91a3f06 100644 --- a/test/signals_test.js +++ b/test/signals_test.js @@ -1,9 +1,10 @@ -import "../plugins/node"; - import Signal from "../plugins/signals"; import expect from "expect"; +import nodePlugin from "../plugins/node"; import { v } from "../lib/index"; +v.use(nodePlugin); + describe("Signals", () => { it("should create a signal", async () => { // Create signal diff --git a/test/store_test.js b/test/store_test.js index 8854b0a..5adf936 100644 --- a/test/store_test.js +++ b/test/store_test.js @@ -1,7 +1,10 @@ import plugin, {Store} from "../plugins/store"; -import { use, v } from "../lib/index"; import expect from "expect"; +import { v } from "../lib/index"; + +v.use(plugin); + function getNewStore() { let mainModule = { diff --git a/tsconfig.json b/tsconfig.json index 9518268..229dafb 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -8,7 +8,10 @@ "inlineSourceMap": true, "allowJs": false, "resolveJsonModule": true, - "removeComments": true + "removeComments": false, + "jsx": "react", + "jsxFragmentFactory": "v.fragment", + "jsxFactory": "v" }, "include": ["./lib", "./plugins"], "exclude": ["test*/**/*", "**/*.test.ts", "**/*.spec.ts"] diff --git a/types/lib/index.d.ts b/types/lib/index.d.ts deleted file mode 100644 index 136c280..0000000 --- a/types/lib/index.d.ts +++ /dev/null @@ -1,103 +0,0 @@ -export interface DomElement extends Element { - [key: string]: any; -} -export interface Props { - key?: string | number; - data?: string; - oncreate?: { - (vnode: IVnode): never; - }; - onupdate?: { - (vnode: IVnode, oldVnode: IVnode): never; - }; - onremove?: { - (oldVnode: IVnode): never; - }; - shouldupdate?: { - (vnode: IVnode, oldVnode: IVnode): undefined | boolean; - }; - "v-cleanup"?: Function; - [key: string | number | symbol]: any; -} -export interface Children extends Array { -} -export interface IVnode { - new (tag: string, props: Props, children: IVnode[]): IVnode; - tag: string; - props: Props; - children: Children; - dom?: DomElement; - isSVG?: boolean; - processed?: boolean; - component?: Component | POJOComponent; - nodeValue?: string; - [key: string | number | symbol]: any; -} -export interface Component { - (props?: Record | null, children?: Children): IVnode | Children; - [key: string | number | symbol]: any; -} -export interface POJOComponent { - view: Component; - [key: string | number | symbol]: any; -} -export declare type ValyrianComponent = Component | POJOComponent; -export interface VnodeComponent extends IVnode { - tag: "__component__"; - component: ValyrianComponent; -} -export interface VnodeWithDom extends IVnode { - dom: DomElement; -} -export interface Directive { - (value: any, vnode: VnodeWithDom, oldVnode?: VnodeWithDom): void; -} -export interface ValyrianApp { - isMounted: boolean; - eventListenerNames: Record; - cleanup: Function[]; - eventListener?: EventListener; - mainVnode?: VnodeWithDom; - component?: VnodeComponent; - container?: DomElement; - [key: string | number | symbol]: any; -} -export interface MountedValyrianApp extends ValyrianApp { - eventListener: EventListener; - mainVnode: VnodeWithDom; - container: DomElement; - component: VnodeComponent; -} -export interface Current { - app?: ValyrianApp; - component?: ValyrianComponent; - vnode?: VnodeWithDom; - oldVnode?: VnodeWithDom; -} -export interface Directives { - [key: string]: Directive; -} -export interface ReservedProps { - [key: string]: true; -} -export interface Valyrian { - (tagOrComponent: string | ValyrianComponent, props: Props, ...children: Children): IVnode | VnodeComponent; - fragment: (props: Props, ...children: Children) => Children; - current: Current; - directives: Directives; - reservedProps: ReservedProps; -} -export declare const Vnode: IVnode; -export declare function isVnode(component?: unknown): component is IVnode; -export declare function isComponent(component?: unknown | ValyrianComponent): component is ValyrianComponent; -export declare function isVnodeComponent(vnode?: unknown): vnode is VnodeComponent; -export declare const isNodeJs: boolean; -export declare const trust: (htmlString: string) => IVnode[]; -export declare function cleanup(callback: Function): void; -export declare function mount(container: DomElement | string, component: ValyrianComponent | IVnode): any; -export declare function update(component?: ValyrianComponent | IVnode): any; -export declare function unmount(component?: ValyrianComponent | IVnode): string | undefined; -export declare function onremove(vnode: IVnode): void; -export declare function updateProperty(name: string, value: any, vnode: VnodeWithDom, oldVnode?: VnodeWithDom): void; -export declare function directive(name: string, directive: Directive): void; -export declare const valyrian: Valyrian; diff --git a/yarn.lock b/yarn.lock index bc7e112..d8f888a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -921,11 +921,6 @@ resolved "https://registry.yarnpkg.com/@types/minimist/-/minimist-1.2.2.tgz#ee771e2ba4b3dc5b372935d549fd9617bf345b8c" integrity sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ== -"@types/mocha@^9.1.0": - version "9.1.0" - resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-9.1.0.tgz#baf17ab2cca3fcce2d322ebc30454bff487efad5" - integrity sha512-QCWHkbMv4Y5U9oW10Uxbr45qMMSzl4OzijsozynUAgx3kEHUdXB00udx2dWDQ7f2TU2a2uuiFaRZjCe3unPpeg== - "@types/ms@*": version "0.7.31" resolved "https://registry.yarnpkg.com/@types/ms/-/ms-0.7.31.tgz#31b7ca6407128a3d2bbc27fe2d21b345397f6197" @@ -1168,31 +1163,11 @@ ansi-escapes@^4.2.1: dependencies: type-fest "^0.21.3" -ansi-regex@^2.0.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" - integrity sha1-w7M6te42DYbg5ijwRorn7yfWVN8= - -ansi-regex@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998" - integrity sha1-7QMXwyIGT3lGbAKWa922Bas32Zg= - -ansi-regex@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.0.tgz#8b9f8f08cf1acb843756a839ca8c7e3168c51997" - integrity sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg== - -ansi-regex@^5.0.1: +ansi-regex@^2.0.0, ansi-regex@^3.0.0, ansi-regex@^4.1.0, ansi-regex@^5.0.1, ansi-regex@^6.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== -ansi-regex@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-6.0.1.tgz#3183e38fae9a65d7cb5e53945cd5897d0260a06a" - integrity sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA== - ansi-styles@^3.2.1: version "3.2.1" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" @@ -4221,22 +4196,7 @@ jimp@^0.2.21: tinycolor2 "^1.1.2" url-regex "^3.0.0" -jpeg-js@0.4.2: - version "0.4.2" - resolved "https://registry.yarnpkg.com/jpeg-js/-/jpeg-js-0.4.2.tgz#8b345b1ae4abde64c2da2fe67ea216a114ac279d" - integrity sha512-+az2gi/hvex7eLTMTlbRLOhH6P6WFdk2ITI8HJsaH2VqYO0I594zXSYEP+tf4FW+8Cy68ScDXoAsQdyQanv3sw== - -jpeg-js@^0.1.1: - version "0.1.2" - resolved "https://registry.yarnpkg.com/jpeg-js/-/jpeg-js-0.1.2.tgz#135b992c0575c985cfa0f494a3227ed238583ece" - integrity sha1-E1uZLAV1yYXPoPSUoyJ+0jhYPs4= - -jpeg-js@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/jpeg-js/-/jpeg-js-0.2.0.tgz#53e448ec9d263e683266467e9442d2c5a2ef5482" - integrity sha1-U+RI7J0mPmgyZkZ+lELSxaLvVII= - -jpeg-js@^0.4.1: +jpeg-js@0.4.2, jpeg-js@^0.1.1, jpeg-js@^0.2.0, jpeg-js@^0.4.0, jpeg-js@^0.4.1: version "0.4.3" resolved "https://registry.yarnpkg.com/jpeg-js/-/jpeg-js-0.4.3.tgz#6158e09f1983ad773813704be80680550eff977b" integrity sha512-ru1HWKek8octvUHFHvE5ZzQ1yAsJmIvRdGWvSoKV52XKyuyYA437QWDttXT8eZXDSbuMpHlLzPDZUPd6idIz+Q== From e517bb5e6640dd4e00bb34c20822817870a3788a Mon Sep 17 00:00:00 2001 From: Masquerade Circus Date: Fri, 11 Mar 2022 18:20:31 -0600 Subject: [PATCH 17/19] fix: Fix infinite test --- test/hooks_test.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/test/hooks_test.js b/test/hooks_test.js index ed426a6..a58d416 100644 --- a/test/hooks_test.js +++ b/test/hooks_test.js @@ -9,7 +9,7 @@ import { v } from "../lib"; v.use(plugin); v.use(nodePlugin); -describe("Hooks", () => { +describe.only("Hooks", () => { describe("State hook", () => { it("should handle a component state", async () => { let Counter = () => { @@ -24,6 +24,7 @@ describe("Hooks", () => { await new Promise((resolve) => setTimeout(() => resolve(), 2050)); result = v.update(Counter); expect(result).toEqual("
2
"); + v.unmount(Counter); }); it("should handle subcomponents state and v.onCleanup", async () => { @@ -50,6 +51,7 @@ describe("Hooks", () => { await new Promise((resolve) => setTimeout(() => resolve(), 2050)); result = v.update(Counter); expect(result).toEqual("
2
not ok
"); + v.unmount(Counter); }); it("array getter-setter based state", async () => { @@ -65,6 +67,7 @@ describe("Hooks", () => { await new Promise((resolve) => setTimeout(() => resolve(), 2050)); result = v.update(Counter); expect(result).toEqual("
2
"); + v.unmount(Counter); }); }); From 5a36d1f883332a320bad792bb5b15302ccafae09 Mon Sep 17 00:00:00 2001 From: Masquerade Circus Date: Fri, 11 Mar 2022 18:38:38 -0600 Subject: [PATCH 18/19] style: Fix coding style issues --- lib/interfaces.ts | 2 ++ plugins/sw.js | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/interfaces.ts b/lib/interfaces.ts index 3788aee..a629d58 100644 --- a/lib/interfaces.ts +++ b/lib/interfaces.ts @@ -1,3 +1,5 @@ +/* eslint-disable no-use-before-define */ +/* eslint-disable no-unused-vars */ /*** Interfaces ***/ export interface DomElement extends Element { diff --git a/plugins/sw.js b/plugins/sw.js index 7713465..59bee16 100644 --- a/plugins/sw.js +++ b/plugins/sw.js @@ -6,7 +6,7 @@ class Sw { constructor(file, options) { if (Boolean(typeof process !== "undefined" && process.versions && process.versions.node)) { - console.info('Service Worker registration not supported in node.js'); + throw new Error("Service Worker registration not supported in node.js"); return; } From d099ef6e1323f88e67321a1bc5bbac21c5c13e16 Mon Sep 17 00:00:00 2001 From: Masquerade Circus Date: Fri, 11 Mar 2022 18:51:02 -0600 Subject: [PATCH 19/19] Restart action checks