From 5010b716183892332c6a6f7094144f02d3c814ec Mon Sep 17 00:00:00 2001 From: Renzo Date: Wed, 22 Nov 2023 19:25:33 +0800 Subject: [PATCH 1/7] =?UTF-8?q?JSY-35201=20fix:=20=E4=BA=A4=E5=8F=89?= =?UTF-8?q?=E8=A1=A8=E6=80=A7=E8=83=BD=E9=97=AE=E9=A2=98=20-=20=E5=90=8C?= =?UTF-8?q?=20JSY-22136=20=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/fineui/src/base/collection/collection.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/packages/fineui/src/base/collection/collection.js b/packages/fineui/src/base/collection/collection.js index 2019bfa7a..9f933ed20 100644 --- a/packages/fineui/src/base/collection/collection.js +++ b/packages/fineui/src/base/collection/collection.js @@ -124,6 +124,12 @@ export class CollectionView extends Widget { this.element.scrollLeft(scrollLeft); } } + + destroyed() { + each(this.renderedCells, (i, cell) => { + cell.el._destroy(); + }); + } _calculateSizeAndPositionData() { const { items, cellSizeAndPositionGetter } = this.options; From 816f59ec0a260db00dd3d6b1835cfcc2f4700a7c Mon Sep 17 00:00:00 2001 From: jian Date: Thu, 23 Nov 2023 14:34:38 +0800 Subject: [PATCH 2/7] =?UTF-8?q?BI-134635=20fix:=20=E7=A9=BA=E7=99=BD?= =?UTF-8?q?=E9=97=AE=E9=A2=98=EF=BC=8C=E9=AB=98=E5=BA=A6=E5=88=9D=E5=A7=8B?= =?UTF-8?q?=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../fineui/src/base/list/virtualgrouplist.js | 20 +++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/packages/fineui/src/base/list/virtualgrouplist.js b/packages/fineui/src/base/list/virtualgrouplist.js index e2e0d5ddf..bdccaed3d 100644 --- a/packages/fineui/src/base/list/virtualgrouplist.js +++ b/packages/fineui/src/base/list/virtualgrouplist.js @@ -26,6 +26,7 @@ export class VirtualGroupList extends Widget { init() { this.renderedIndex = -1; + this._initSummaryHeight(); } static xtype = "bi.virtual_group_list"; @@ -44,7 +45,7 @@ export class VirtualGroupList extends Widget { }, { type: VirtualGroup.xtype, - height: rowHeight * items.length, + height: this.summaryHeight, ref: (ref) => { this.container = ref; }, @@ -83,8 +84,10 @@ export class VirtualGroupList extends Widget { o.scrollTop = this.element.scrollTop(); if (!this.ticking) { requestAnimationFrame(() => { + const start = new Date().getTime(); this._calculateBlocksToRender(); this.ticking = false; + console.log(new Date().getTime() - start); }); this.ticking = true; } @@ -200,16 +203,21 @@ export class VirtualGroupList extends Widget { _restore() { const o = this.options; this.renderedIndex = -1; - if (isFunction(o.rowHeight)) { - this.summaryHeight = sum(o.items, o.rowHeight); - } else { - this.summaryHeight = this._isAutoHeight() ? 0 : o.rowHeight * o.items.length; - } + this._initSummaryHeight(); // 依赖于cache的占位元素也要初始化 this.topBlank.setHeight(0); this.bottomBlank.setHeight(0); } + _initSummaryHeight() { + const { rowHeight, items } = this.options; + if (isFunction(rowHeight)) { + this.summaryHeight = sum(items, rowHeight); + } else { + this.summaryHeight = this._isAutoHeight() ? 0 : rowHeight * items.length; + } + } + // 暂时只支持固定行高的场景 scrollTo(scrollTop) { this.options.scrollTop = scrollTop; From 4e019804a4870dbf8a388fbeced0bc50f1a7eaf8 Mon Sep 17 00:00:00 2001 From: jian Date: Thu, 23 Nov 2023 14:36:48 +0800 Subject: [PATCH 3/7] =?UTF-8?q?=E6=97=A0jira=E4=BB=BB=E5=8A=A1=20=E5=A4=9A?= =?UTF-8?q?=E6=8F=90=E4=BA=A4=E7=9A=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/fineui/src/base/list/virtualgrouplist.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/fineui/src/base/list/virtualgrouplist.js b/packages/fineui/src/base/list/virtualgrouplist.js index bdccaed3d..caf29c909 100644 --- a/packages/fineui/src/base/list/virtualgrouplist.js +++ b/packages/fineui/src/base/list/virtualgrouplist.js @@ -84,10 +84,8 @@ export class VirtualGroupList extends Widget { o.scrollTop = this.element.scrollTop(); if (!this.ticking) { requestAnimationFrame(() => { - const start = new Date().getTime(); this._calculateBlocksToRender(); this.ticking = false; - console.log(new Date().getTime() - start); }); this.ticking = true; } From f9b49d724175a0ced0a5acf10ce1d933e9c7646f Mon Sep 17 00:00:00 2001 From: jian Date: Thu, 23 Nov 2023 15:14:22 +0800 Subject: [PATCH 4/7] =?UTF-8?q?Revert=20"=E6=97=A0jira=E4=BB=BB=E5=8A=A1?= =?UTF-8?q?=20=E5=A4=9A=E6=8F=90=E4=BA=A4=E7=9A=84"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 4e019804a4870dbf8a388fbeced0bc50f1a7eaf8. --- packages/fineui/src/base/list/virtualgrouplist.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/fineui/src/base/list/virtualgrouplist.js b/packages/fineui/src/base/list/virtualgrouplist.js index caf29c909..bdccaed3d 100644 --- a/packages/fineui/src/base/list/virtualgrouplist.js +++ b/packages/fineui/src/base/list/virtualgrouplist.js @@ -84,8 +84,10 @@ export class VirtualGroupList extends Widget { o.scrollTop = this.element.scrollTop(); if (!this.ticking) { requestAnimationFrame(() => { + const start = new Date().getTime(); this._calculateBlocksToRender(); this.ticking = false; + console.log(new Date().getTime() - start); }); this.ticking = true; } From 17e768f7d324cf2231d12c1f271a366f4b5fce7d Mon Sep 17 00:00:00 2001 From: jian Date: Thu, 23 Nov 2023 15:14:25 +0800 Subject: [PATCH 5/7] =?UTF-8?q?Revert=20"BI-134635=20fix:=20=E7=A9=BA?= =?UTF-8?q?=E7=99=BD=E9=97=AE=E9=A2=98=EF=BC=8C=E9=AB=98=E5=BA=A6=E5=88=9D?= =?UTF-8?q?=E5=A7=8B=E5=8C=96"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 816f59ec0a260db00dd3d6b1835cfcc2f4700a7c. --- .../fineui/src/base/list/virtualgrouplist.js | 20 ++++++------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/packages/fineui/src/base/list/virtualgrouplist.js b/packages/fineui/src/base/list/virtualgrouplist.js index bdccaed3d..e2e0d5ddf 100644 --- a/packages/fineui/src/base/list/virtualgrouplist.js +++ b/packages/fineui/src/base/list/virtualgrouplist.js @@ -26,7 +26,6 @@ export class VirtualGroupList extends Widget { init() { this.renderedIndex = -1; - this._initSummaryHeight(); } static xtype = "bi.virtual_group_list"; @@ -45,7 +44,7 @@ export class VirtualGroupList extends Widget { }, { type: VirtualGroup.xtype, - height: this.summaryHeight, + height: rowHeight * items.length, ref: (ref) => { this.container = ref; }, @@ -84,10 +83,8 @@ export class VirtualGroupList extends Widget { o.scrollTop = this.element.scrollTop(); if (!this.ticking) { requestAnimationFrame(() => { - const start = new Date().getTime(); this._calculateBlocksToRender(); this.ticking = false; - console.log(new Date().getTime() - start); }); this.ticking = true; } @@ -203,21 +200,16 @@ export class VirtualGroupList extends Widget { _restore() { const o = this.options; this.renderedIndex = -1; - this._initSummaryHeight(); + if (isFunction(o.rowHeight)) { + this.summaryHeight = sum(o.items, o.rowHeight); + } else { + this.summaryHeight = this._isAutoHeight() ? 0 : o.rowHeight * o.items.length; + } // 依赖于cache的占位元素也要初始化 this.topBlank.setHeight(0); this.bottomBlank.setHeight(0); } - _initSummaryHeight() { - const { rowHeight, items } = this.options; - if (isFunction(rowHeight)) { - this.summaryHeight = sum(items, rowHeight); - } else { - this.summaryHeight = this._isAutoHeight() ? 0 : rowHeight * items.length; - } - } - // 暂时只支持固定行高的场景 scrollTo(scrollTop) { this.options.scrollTop = scrollTop; From 54e7191a97c572f94ffb5c9950a80b350efe0dd1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=BF=A0=E5=B1=8F=E5=B1=B1=E6=9C=80=E9=80=9F=E4=B8=8B?= =?UTF-8?q?=E5=B1=B1=E4=BC=A0=E8=AF=B4?= Date: Thu, 23 Nov 2023 16:57:12 +0800 Subject: [PATCH 6/7] =?UTF-8?q?=E6=97=A0JIRA=20Dep=E7=9A=84subs=E6=8D=A2?= =?UTF-8?q?=E6=88=90Set=E5=AE=9E=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/fineui/src/fix/fix.js | 712 ++++++++++++++------------------- 1 file changed, 301 insertions(+), 411 deletions(-) diff --git a/packages/fineui/src/fix/fix.js b/packages/fineui/src/fix/fix.js index 92cba70f8..1006e02e1 100644 --- a/packages/fineui/src/fix/fix.js +++ b/packages/fineui/src/fix/fix.js @@ -1,11 +1,5 @@ import { _ } from "@/core"; -function _classCallCheck(instance, Constructor) { - if (!(instance instanceof Constructor)) { - throw new TypeError("Cannot call a class as a function"); - } -} - function noop(a, b, c) { } @@ -23,13 +17,10 @@ function isPlainObject(obj) { function isConfigurable(obj, key) { let configurable = true; - const property = - Object.getOwnPropertyDescriptor && - Object.getOwnPropertyDescriptor(obj, key); + const property = Object.getOwnPropertyDescriptor && Object.getOwnPropertyDescriptor(obj, key); if (property && property.configurable === false) { configurable = false; } - return configurable; } @@ -42,17 +33,17 @@ function isExtensible(obj) { name += "?"; } obj[name] = true; - const returnValue = obj.hasOwnProperty(name); + let returnValue = obj.hasOwnProperty(name); delete obj[name]; - return returnValue; } + function remove(arr, item) { if (arr && arr.length) { - const _index = arr.indexOf(item); - if (_index > -1) { - return arr.splice(_index, 1); + const index = arr.indexOf(item); + if (index > -1) { + return arr.splice(index, 1); } } } @@ -65,21 +56,19 @@ function parsePath(path) { // return // } const segments = path.split("."); - - return function(obj) { + return function (obj) { for (let i = 0; i < segments.length; i++) { if (!obj) return; obj = obj[segments[i]]; } - return obj; }; } -const nextTick = (function() { +const nextTick = (function () { const callbacks = []; let pending = false; - let timerFunc = void 0; + let timerFunc; function nextTickHandler() { pending = false; @@ -100,37 +89,37 @@ const nextTick = (function() { // same loop is by using MessageChannel. /* istanbul ignore if */ if (typeof setImmediate !== "undefined" && isNative(setImmediate)) { - timerFunc = function timerFunc() { + timerFunc = () => { setImmediate(nextTickHandler); }; - } else if ( - typeof MessageChannel !== "undefined" && - (isNative(MessageChannel) || - // PhantomJS - MessageChannel.toString() === "[object MessageChannelConstructor]") - ) { + } else if (typeof MessageChannel !== "undefined" && ( + isNative(MessageChannel) || + // PhantomJS + MessageChannel.toString() === "[object MessageChannelConstructor]" + )) { const channel = new MessageChannel(); const port = channel.port2; channel.port1.onmessage = nextTickHandler; - timerFunc = function timerFunc() { + timerFunc = () => { port.postMessage(1); }; - } else if (typeof Promise !== "undefined" && isNative(Promise)) { + } else /* istanbul ignore next */ + if (typeof Promise !== "undefined" && isNative(Promise)) { // use microtask in non-DOM environments, e.g. Weex const p = Promise.resolve(); - timerFunc = function timerFunc() { + timerFunc = () => { p.then(nextTickHandler); }; } else { // fallback to setTimeout - timerFunc = function timerFunc() { + timerFunc = () => { setTimeout(nextTickHandler, 0); }; } return function queueNextTick(cb, ctx) { - let _resolve = void 0; + let _resolve; callbacks.push(() => { if (cb) { try { @@ -155,7 +144,7 @@ const nextTick = (function() { }; })(); -let falsy; +var falsy; const $$skipArray = { __ob__: falsy, $accessors: falsy, @@ -169,44 +158,38 @@ let uid = 0; * A dep is an observable that can have multiple * directives subscribing to it. */ - -const Dep = (function() { - function Dep() { - _classCallCheck(this, Dep); - +class Dep { + constructor() { this.id = uid++; - this.subs = []; + this.subs = new Set(); } - Dep.prototype.addSub = function addSub(sub) { - this.subs.push(sub); - }; + addSub(sub) { + this.subs.add(sub); + } - Dep.prototype.removeSub = function removeSub(sub) { - remove(this.subs, sub); - }; + removeSub(sub) { + this.subs.delete(sub); + } - Dep.prototype.depend = function depend() { + depend() { if (Dep.target) { Dep.target.addDep(this); } - }; + } - Dep.prototype.notify = function notify(options) { + notify(options) { // stabilize the subscriber list first - const subs = this.subs.slice(); + const subs = [...this.subs.values()]; for (let i = 0, l = subs.length; i < l; i++) { subs[i].update(options); } - }; - - return Dep; -})(); + } +} // the current target watcher being evaluated. // this is globally unique because there could be only one // watcher being evaluated at any time. - Dep.target = null; const targetStack = []; @@ -219,8 +202,8 @@ function popTarget() { Dep.target = targetStack.pop(); } -// 如果浏览器不支持ecma262v5的Object.defineProperties或者存在BUG,比如IE8 -// 标准浏览器使用__defineGetter__, __defineSetter__实现 +//如果浏览器不支持ecma262v5的Object.defineProperties或者存在BUG,比如IE8 +//标准浏览器使用__defineGetter__, __defineSetter__实现 let canHideProperty = true; try { Object.defineProperty({}, "_", { @@ -233,13 +216,14 @@ try { canHideProperty = false; } + let createViewModel = Object.defineProperties; -let defineProperty = void 0; +let defineProperty; /* istanbul ignore if*/ if (!canHideProperty) { if ("__defineGetter__" in {}) { - defineProperty = function defineProperty(obj, prop, desc) { + defineProperty = function (obj, prop, desc) { if ("value" in desc) { obj[prop] = desc.value; } @@ -249,22 +233,20 @@ if (!canHideProperty) { if ("set" in desc) { obj.__defineSetter__(prop, desc.set); } - return obj; }; - createViewModel = function createViewModel(obj, descs) { - for (const prop in descs) { + createViewModel = function (obj, descs) { + for (var prop in descs) { if (descs.hasOwnProperty(prop)) { defineProperty(obj, prop, descs[prop]); } } - return obj; }; } } -const createViewModel$1 = createViewModel; +var createViewModel$1 = createViewModel; const queue = []; const activatedChildren = []; @@ -281,9 +263,7 @@ function resetSchedulerState() { function flushSchedulerQueue() { flushing = true; - let watcher = void 0, - id = void 0, - options = void 0; + let watcher, id, options; // Sort queue before flush. // This ensures that: @@ -308,12 +288,13 @@ function flushSchedulerQueue() { resetSchedulerState(); } + function queueWatcher(watcher, options) { const id = watcher.id; if (has[id] == null) { has[id] = true; if (!flushing) { - queue.push({ watcher, options }); + queue.push({ watcher: watcher, options: options }); } else { // if already flushing, splice the watcher based on its id // if already past its id, it will be run next immediately. @@ -321,7 +302,7 @@ function queueWatcher(watcher, options) { while (i > index && queue[i].watcher.id > watcher.id) { i--; } - queue.splice(i + 1, 0, { watcher, options }); + queue.splice(i + 1, 0, { watcher: watcher, options: options }); } // queue the flush if (!waiting) { @@ -333,10 +314,11 @@ function queueWatcher(watcher, options) { let uid$1 = 0; -const Watcher = (function() { - function Watcher(vm, expOrFn, cb, options) { - _classCallCheck(this, Watcher); - +class Watcher { + constructor(vm, + expOrFn, + cb, + options) { this.vm = vm; // vm._watchers || (vm._watchers = []) // vm._watchers.push(this) @@ -364,16 +346,18 @@ const Watcher = (function() { } else { this.getter = parsePath(expOrFn); if (!this.getter) { - this.getter = function() { + this.getter = function () { }; } } - this.value = this.lazy ? undefined : this.get(); + this.value = this.lazy + ? undefined + : this.get(); } - Watcher.prototype.get = function get() { + get() { pushTarget(this); - let value = void 0; + let value; const vm = this.vm; try { value = this.getter.call(vm, vm); @@ -391,11 +375,10 @@ const Watcher = (function() { popTarget(); this.cleanupDeps(); } - return value; - }; + } - Watcher.prototype.addDep = function addDep(dep) { + addDep(dep) { const id = dep.id; if (!this.newDepIds.has(id)) { this.newDepIds.add(id); @@ -404,9 +387,9 @@ const Watcher = (function() { dep.addSub(this); } } - }; + } - Watcher.prototype.cleanupDeps = function cleanupDeps() { + cleanupDeps() { let i = this.deps.length; while (i--) { const dep = this.deps[i]; @@ -422,9 +405,9 @@ const Watcher = (function() { this.deps = this.newDeps; this.newDeps = tmp; this.newDeps.length = 0; - }; + } - Watcher.prototype.update = function update(options) { + update(options) { /* istanbul ignore else */ if (this.lazy) { this.dirty = true; @@ -433,9 +416,9 @@ const Watcher = (function() { } else { queueWatcher(this, options); } - }; + } - Watcher.prototype.run = function run(options) { + run(options) { if (this.active) { const value = this.get(); if ( @@ -443,8 +426,7 @@ const Watcher = (function() { // Deep watchers and watchers on Object/Arrays should fire even // when the value is the same, because the value may // have mutated. - (_.isObject(value) && options && options.refresh) || - this.deep + (_.isObject(value) && options && options.refresh) || this.deep ) { // set new value const oldValue = this.value; @@ -464,21 +446,21 @@ const Watcher = (function() { } } } - }; + } - Watcher.prototype.evaluate = function evaluate() { + evaluate() { this.value = this.get(); this.dirty = false; - }; + } - Watcher.prototype.depend = function depend() { + depend() { let i = this.deps.length; while (i--) { this.deps[i].depend(); } - }; + } - Watcher.prototype.teardown = function teardown() { + teardown() { if (this.active) { // remove self from vm's watcher list // this is a somewhat expensive operation so we skip it @@ -490,10 +472,8 @@ const Watcher = (function() { } this.active = false; } - }; - - return Watcher; -})(); + } +} const seenObjects = new Set(); @@ -503,10 +483,9 @@ function traverse(val) { } function _traverse(val, seen) { - let i = void 0, - keys = void 0; + let i, keys; const isA = _.isArray(val); - if (!isA && !_.isObject(val)) { + if ((!isA && !_.isObject(val))) { return; } if (val.__ob__) { @@ -518,65 +497,55 @@ function _traverse(val, seen) { } if (isA) { i = val.length; - while (i--) { - _traverse(val[i], seen); - } + while (i--) _traverse(val[i], seen); } else { keys = _.keys(val); i = keys.length; - while (i--) { - _traverse(val[keys[i]], seen); - } + while (i--) _traverse(val[keys[i]], seen); } } const arrayProto = Array.prototype; const arrayMethods = []; -_.each( - ["push", "pop", "shift", "unshift", "splice", "sort", "reverse"], - (method) => { - const original = arrayProto[method]; - arrayMethods[method] = function mutator() { - for ( - var _len = arguments.length, args = Array(_len), _key2 = 0; - _key2 < _len; - _key2++ - ) { - args[_key2] = arguments[_key2]; - } - - const ob = this.__ob__; - let inserted = void 0; - switch (method) { - case "push": - case "unshift": - inserted = args; - break; - case "splice": - inserted = args.slice(2); - break; - } - if (inserted) inserted = ob.observeArray(inserted); - switch (method) { - case "push": - case "unshift": - args = inserted; - break; - case "splice": - if (args.length > 2) { - args = [args[0], args[1]].concat( - inserted ? inserted : [] - ); - } - break; - } - const result = original.apply(this, args); - notify(ob.parent, ob.parentKey, ob.dep, true); - - return result; - }; - } -); +_.each([ + "push", + "pop", + "shift", + "unshift", + "splice", + "sort", + "reverse" +], function (method) { + const original = arrayProto[method]; + arrayMethods[method] = function mutator(...args) { + const ob = this.__ob__; + let inserted; + switch (method) { + case "push": + case "unshift": + inserted = args; + break; + case "splice": + inserted = args.slice(2); + break; + } + if (inserted) inserted = ob.observeArray(inserted); + switch (method) { + case "push": + case "unshift": + args = inserted; + break; + case "splice": + if (args.length > 2) { + args = [args[0], args[1]].concat(inserted ? inserted : []); + } + break; + } + const result = original.apply(this, args); + notify(ob.parent, ob.parentKey, ob.dep, true); + return result; + }; +}); const arrayKeys = _.keys(arrayMethods); @@ -599,16 +568,15 @@ function def(obj, key, val, enumerable) { * object's property keys into getter/setters that * collect dependencies and dispatches updates. */ - -const Observer = (function() { - function Observer(value) { - _classCallCheck(this, Observer); - +class Observer { + constructor(value) { this.value = value; this.dep = new Dep(); this.vmCount = 0; if (_.isArray(value)) { - const augment = hasProto ? protoAugment : copyAugment; + const augment = hasProto + ? protoAugment + : copyAugment; augment(value, arrayMethods, arrayKeys); this.model = this.observeArray(value); } else { @@ -617,26 +585,21 @@ const Observer = (function() { def(this.model, "__ob__", this); } - Observer.prototype.walk = function walk(obj) { + walk(obj) { return defineReactive(obj, this); - }; + } - Observer.prototype.observeArray = function observeArray(items) { + observeArray(items) { for (let i = 0, l = items.length; i < l; i++) { const ob = observe(items[i], this, i); items[i] = ob ? ob.model : items[i]; } - return items; - }; - - return Observer; -})(); + } +} function protoAugment(target, src, keys) { - /* eslint-disable no-proto */ Object.setPrototypeOf(target, src); - /* eslint-enable no-proto */ } /* istanbul ignore next */ @@ -651,12 +614,11 @@ function observe(value, parentObserver, parentKey) { if (!_.isObject(value)) { return; } - let ob = void 0; + let ob; if (value.__ob__ instanceof Observer) { ob = value.__ob__; } else if ( - observerState.shouldConvert && - isExtensible(value) && + observerState.shouldConvert && isExtensible(value) && (_.isArray(value) || isPlainObject(value)) ) { ob = new Observer(value); @@ -665,39 +627,33 @@ function observe(value, parentObserver, parentKey) { ob.parent = parentObserver || ob.parent; ob.parentKey = parentKey; } - return ob; } function notify(observer, key, dep, refresh) { - dep.notify({ observer, key, refresh }); + dep.notify({ observer: observer, key: key, refresh: refresh }); if (observer) { - // 触发a.*绑定的依赖 - _.each(observer._deps, (dep) => { - dep.notify({ observer, key }); + //触发a.*绑定的依赖 + _.each(observer._deps, function (dep) { + dep.notify({ observer: observer, key: key }); }); - // 触发a.**绑定的依赖 - let parent = observer, - root = observer, - route = key || ""; + //触发a.**绑定的依赖 + let parent = observer, root = observer, route = key || ""; while (parent) { - _.each(parent._scopeDeps, (dep) => { - dep.notify({ observer, key }); + _.each(parent._scopeDeps, function (dep) { + dep.notify({ observer: observer, key: key }); }); if (parent.parentKey != null) { - route = `${parent.parentKey}.${route}`; + route = parent.parentKey + "." + route; } root = parent; parent = parent.parent; } - for (const _key in root._globalDeps) { + for (let _key in root._globalDeps) { const reg = new RegExp(_key); if (reg.test(route)) { for (let i = 0; i < root._globalDeps[_key].length; i++) { - root._globalDeps[_key][i].notify({ - observer, - key: _key - }); + root._globalDeps[_key][i].notify({ observer: observer, key: _key }); } } } @@ -706,14 +662,14 @@ function notify(observer, key, dep, refresh) { function defineReactive(obj, observer, shallow) { const props = {}; - let model = void 0; - _.each(obj, (val, key) => { + let model; + _.each(obj, function (val, key) { if (key in $$skipArray) { return; } - const configurable = isConfigurable(obj, key); - const dep = (observer && observer[`__dep${key}`]) || new Dep(); - observer && (observer[`__dep${key}`] = dep); + let configurable = isConfigurable(obj, key); + const dep = (observer && observer["__dep" + key]) || new Dep(); + observer && (observer["__dep" + key] = dep); let childOb = configurable && !shallow && observe(val, observer, key); props[key] = { enumerable: true, @@ -729,20 +685,15 @@ function defineReactive(obj, observer, shallow) { } } } - return value; }, set: function reactiveSetter(newVal) { const value = childOb ? childOb.model : val; - if ( - newVal === value || - (newVal !== newVal && value !== value) - ) { + if (newVal === value || (newVal !== newVal && value !== value)) { return; } val = newVal; - childOb = - configurable && !shallow && observe(newVal, observer, key); + childOb = configurable && !shallow && observe(newVal, observer, key); if (childOb && value && value.__ob__) { childOb._scopeDeps = value.__ob__._scopeDeps; childOb._deps = value.__ob__._deps; @@ -752,14 +703,14 @@ function defineReactive(obj, observer, shallow) { } }; }); - - return (model = createViewModel$1(obj, props)); + return model = createViewModel$1(obj, props); } function defineReactiveProperty(obj, key, val, shallow) { + const dep = new Dep(); - const configurable = isConfigurable(obj, key); + let configurable = isConfigurable(obj, key); if (!configurable) { return; } @@ -783,7 +734,6 @@ function defineReactiveProperty(obj, key, val, shallow) { } } } - return value; }, set: function reactiveSetter(newVal) { @@ -809,24 +759,20 @@ function set(target, key, val) { if (_.isArray(target)) { target.length = Math.max(target.length, key); target.splice(key, 1, val); - return val; } if (_.has(target, key)) { target[key] = val; - return val; } - const ob = target.__ob__; + const ob = (target).__ob__; if (!ob) { target[key] = val; - return val; } ob.value[key] = val; target = defineReactive(ob.value, ob); notify(ob, key, ob.dep); - return target; } @@ -840,22 +786,19 @@ function freeze() { function del(target, key) { if (_.isArray(target)) { target.splice(key, 1); - return; } - const ob = target.__ob__; + const ob = (target).__ob__; if (!_.has(target, key)) { return; } if (!ob) { delete target[key]; - return target; } delete ob.value[key]; target = defineReactive(ob.value, ob); notify(ob, key, ob.dep); - return target; } @@ -864,7 +807,7 @@ function del(target, key) { * we cannot intercept array element access like property getters. */ function dependArray(value) { - for (var e, i = 0, l = value.length; i < l; i++) { + for (let e, i = 0, l = value.length; i < l; i++) { e = value[i]; e && e.__ob__ && e.__ob__.dep.depend(); if (_.isArray(e)) { @@ -873,7 +816,7 @@ function dependArray(value) { } } -let falsy$1; +var falsy$1; const operators = { "||": falsy$1, "&&": falsy$1, @@ -890,16 +833,13 @@ function runBinaryFunction(binarys) { expr += "false"; } } - - return new Function(`return ${expr}`)(); + return new Function("return " + expr)(); } -function routeToRegExp(route) { - route = route - .replace(/\*\*/g, "[a-zA-Z0-9_]+") - .replace(/\*./g, "[a-zA-Z0-9_]+."); - return `^${route}$`; +function routeToRegExp(route) { + route = route.replace(/\*\*/g, "[a-zA-Z0-9_]+").replace(/\*./g, "[a-zA-Z0-9_]+."); + return "^" + route + "$"; } function watch(model, expOrFn, cb, options) { @@ -912,26 +852,20 @@ function watch(model, expOrFn, cb, options) { } options = options || {}; options.user = true; - let exps = void 0; - if ( - _.isFunction(expOrFn) || - !(exps = expOrFn.match(/[a-zA-Z0-9_.*]+|[|][|]|[&][&]|[(]|[)]/g)) || - (exps.length === 1 && expOrFn.indexOf("*") < 0) - ) { + let exps; + if (_.isFunction(expOrFn) || !(exps = expOrFn.match(/[a-zA-Z0-9BI._.*]+|[|][|]|[&][&]|[(]|[)]/g)) || (exps.length === 1 && expOrFn.indexOf("*") < 0)) { const watcher = new Watcher(model, expOrFn, cb, options); if (options.immediate) { cb(watcher.value); } - return function unwatchFn() { watcher.teardown(); }; } const watchers = []; let fns = exps.slice(); - let complete = false, - running = false; - const callback = function callback(index, newValue, oldValue, attrs) { + let complete = false, running = false; + const callback = function (index, newValue, oldValue, attrs) { if (complete === true) { return; } @@ -947,7 +881,7 @@ function watch(model, expOrFn, cb, options) { } else { if (!running) { running = true; - nextTick(() => { + nextTick(function () { complete = false; running = false; fns = exps.slice(); @@ -955,62 +889,42 @@ function watch(model, expOrFn, cb, options) { } } }; - _.each(exps, (exp, i) => { + _.each(exps, function (exp, i) { if (_.has(operators, exp)) { return; } if (exp.indexOf("*") >= 0) { - // a.**或a.*形式 - if ( - /^[1-9a-zA-Z.]+(\*\*$|\*$)/.test(exp) || - exp === "**" || - exp === "*" - ) { + //a.**或a.*形式 + if (/^[1-9a-zA-Z.]+(\*\*$|\*$)/.test(exp) || exp === "**" || exp === "*") { const isGlobal = exp.indexOf("**") >= 0; if (isGlobal) { - // a.**的形式 + //a.**的形式 exp = exp.replace(".**", ""); } else { - // a.*的形式 + //a.*的形式 exp = exp.replace(".*", ""); } - const getter = - exp === "**" || exp === "*" - ? function(m) { - return m; - } - : parsePath(exp); + const getter = (exp === "**" || exp === "*") ? function (m) { + return m; + } : parsePath(exp); const v = getter.call(model, model); if (v.__ob__) { - const _dep = new Dep(); + const dep = new Dep(); if (isGlobal) { - (v.__ob__._scopeDeps || (v.__ob__._scopeDeps = [])).push( - _dep - ); + (v.__ob__._scopeDeps || (v.__ob__._scopeDeps = [])).push(dep); } else { - (v.__ob__._deps || (v.__ob__._deps = [])).push(_dep); + (v.__ob__._deps || (v.__ob__._deps = [])).push(dep); } - const _w = new Watcher( - model, - () => { - _dep.depend(); - - return NaN; - }, - (newValue, oldValue, attrs) => { - callback( - i, - newValue, - oldValue, - _.extend({ index: i }, attrs) - ); - }, - options - ); - watchers.push(() => { - _w.teardown(); - v.__ob__._scopeDeps && remove(v.__ob__._scopeDeps, _dep); - v.__ob__._deps && remove(v.__ob__._deps, _dep); + const w = new Watcher(model, function () { + dep.depend(); + return NaN; + }, function (newValue, oldValue, attrs) { + callback(i, newValue, oldValue, _.extend({ index: i }, attrs)); + }, options); + watchers.push(function unwatchFn() { + w.teardown(); + v.__ob__._scopeDeps && remove(v.__ob__._scopeDeps, dep); + v.__ob__._deps && remove(v.__ob__._deps, dep); }); } @@ -1018,87 +932,71 @@ function watch(model, expOrFn, cb, options) { } // **.a.**的情况,场景:a.b.c, 如果用b.**监听, a被重新赋值b上的_scopeDes就不存在了 if (/^(\*\*\.)+[1-9a-zA-Z]+(\.\*\*$)/.test(exp)) { - // 先获取到能获取到的对象 - const _paths = exp.split("."); - const _currentModel = model[_paths[1]]; + //先获取到能获取到的对象 + const paths = exp.split("."); + const currentModel = model[paths[1]]; - if (!_currentModel.__ob__) { + if (!currentModel.__ob__) { return; } - exp = `${_paths[1]}.**`; - // 补全路径 - let _parent = _currentModel.__ob__.parent, - _root = _currentModel.__ob__; - while (_parent) { - exp = `*.${exp}`; - _root = _parent; - _parent = _parent.parent; + exp = paths[1] + ".**"; + //补全路径 + let parent = currentModel.__ob__.parent, root = currentModel.__ob__; + while (parent) { + exp = "*." + exp; + root = parent; + parent = parent.parent; } - const _regStr = routeToRegExp(exp); - const _dep2 = new Dep(); - _root._globalDeps || (_root._globalDeps = {}); - if (_.isArray(_root._globalDeps[_regStr])) { - _root._globalDeps[_regStr].push(_dep2); + const regStr = routeToRegExp(exp); + const dep = new Dep(); + root._globalDeps || (root._globalDeps = {}); + if (_.isArray(root._globalDeps[regStr])) { + root._globalDeps[regStr].push(dep); } else { - _root._globalDeps[_regStr] = [_dep2]; + root._globalDeps[regStr] = [dep]; } - const _w2 = new Watcher( - _currentModel, - () => { - _dep2.depend(); - - return NaN; - }, - (newValue, oldValue, attrs) => { - callback( - i, - newValue, - oldValue, - _.extend({ index: i }, attrs) - ); - }, - options - ); - watchers.push(() => { - if (_root._globalDeps) { - remove(_root._globalDeps[_regStr], _dep2); - - if (_root._globalDeps[_regStr].length === 0) { - delete _root._globalDeps[_regStr]; - _w2.teardown(); + const w = new Watcher(currentModel, function () { + dep.depend(); + return NaN; + }, function (newValue, oldValue, attrs) { + callback(i, newValue, oldValue, _.extend({ index: i }, attrs)); + }, options); + watchers.push(function unwatchFn() { + if (root._globalDeps) { + remove(root._globalDeps[regStr], dep); + + if (root._globalDeps[regStr].length === 0) { + delete root._globalDeps[regStr]; + w.teardown(); } } }); - return; } // 再有结尾有*的就不支持了 if (exp[exp.length - 1] === "*") { throw new Error("not support"); } - // 其他含有*的情况,如*.a,*.*.a,a.*.a + //其他含有*的情况,如*.a,*.*.a,a.*.a let currentModel = model; - // 先获取到能获取到的对象 + //先获取到能获取到的对象 const paths = exp.split("."); - for (let _i = 0, len = paths.length; _i < len; _i++) { - if (paths[_i] === "*") { + for (let i = 0, len = paths.length; i < len; i++) { + if (paths[i] === "*") { break; } - currentModel = model[paths[_i]]; + currentModel = model[paths[i]]; } - + exp = exp.substr(exp.indexOf("*")); if (!currentModel.__ob__) { return; } - - exp = exp.substr(exp.indexOf("*")); - // 补全路径 - let parent = currentModel.__ob__.parent, - root = currentModel.__ob__; + //补全路径 + let parent = currentModel.__ob__.parent, root = currentModel.__ob__; while (parent) { - exp = `*.${exp}`; + exp = "*." + exp; root = parent; parent = parent.parent; } @@ -1111,24 +1009,13 @@ function watch(model, expOrFn, cb, options) { root._globalDeps[regStr] = [dep]; } - const w = new Watcher( - currentModel, - () => { - dep.depend(); - - return NaN; - }, - (newValue, oldValue, attrs) => { - callback( - i, - newValue, - oldValue, - _.extend({ index: i }, attrs) - ); - }, - options - ); - watchers.push(() => { + const w = new Watcher(currentModel, function () { + dep.depend(); + return NaN; + }, function (newValue, oldValue, attrs) { + callback(i, newValue, oldValue, _.extend({ index: i }, attrs)); + }, options); + watchers.push(function unwatchFn() { if (root._globalDeps) { remove(root._globalDeps[regStr], dep); if (root._globalDeps[regStr].length === 0) { @@ -1137,27 +1024,21 @@ function watch(model, expOrFn, cb, options) { } } }); - return; } - const watcher = new Watcher( - model, - exp, - (newValue, oldValue, attrs) => { - callback(i, newValue, oldValue, _.extend({ index: i }, attrs)); - }, - options - ); - watchers.push(() => { + const watcher = new Watcher(model, exp, function (newValue, oldValue, attrs) { + callback(i, newValue, oldValue, _.extend({ index: i }, attrs)); + }, options); + watchers.push(function unwatchFn() { watcher.teardown(); }); }); - return watchers; } const mixinInjection = {}; + function getMixins(type) { return mixinInjection[type]; } @@ -1185,9 +1066,17 @@ function initComputed(vm, computed) { function defineComputedWatcher(vm, userDef) { const context = vm.$$model ? vm.model : vm; - const getter = typeof userDef === "function" ? userDef : userDef.get; - - return new Watcher(context, getter || noop, noop, computedWatcherOptions); + const getter = + typeof userDef === "function" + ? userDef + : userDef.get; + + return new Watcher( + context, + getter || noop, + noop, + computedWatcherOptions + ); } function defineOneComputedGetter(vm, key, userDef) { @@ -1209,7 +1098,6 @@ function defineOneComputedGetter(vm, key, userDef) { : noop; sharedPropertyDefinition.set = userDef.set ? userDef.set : noop; } - return sharedPropertyDefinition; } @@ -1233,7 +1121,6 @@ function createComputedGetter(vm, key) { if (REACTIVE && Dep.target) { watcher.depend(); } - return watcher.value; } }; @@ -1241,7 +1128,7 @@ function createComputedGetter(vm, key) { function initWatch(vm, watch$$1) { vm._watchers || (vm._watchers = []); - for (const key in watch$$1) { + for (let key in watch$$1) { const handler = watch$$1[key]; if (_.isArray(handler)) { for (let i = 0; i < handler.length; i++) { @@ -1261,7 +1148,6 @@ function createWatcher(vm, keyOrFn, cb, options) { if (typeof cb === "string") { cb = vm[cb]; } - return watch( vm.model, keyOrFn, @@ -1282,7 +1168,7 @@ function initMethods(vm, methods) { function initMixins(vm, mixins) { mixins = (mixins || []).slice(0); - _.each(mixins.reverse(), (mixinType) => { + _.each(mixins.reverse(), function (mixinType) { const mixin$$1 = getMixins(mixinType); for (const key in mixin$$1) { @@ -1327,14 +1213,13 @@ function defineProps(vm, keys) { // } // }) // } - - const _loop = function _loop(i, len) { + for (let i = 0, len = keys.length; i < len; i++) { const key = keys[i]; if (!(key in $$skipArray)) { props[key] = { enumerable: true, configurable: true, - get: function get() { + get: function () { if (vm.$$computed && key in vm.$$computed) { return vm.$$computed[key]; } @@ -1352,7 +1237,7 @@ function defineProps(vm, keys) { p = p._parent; } }, - set: function set(val) { + set: function (val) { if (vm.$$state && key in vm.$$state) { return (vm.$$state[key] = val); } @@ -1369,35 +1254,26 @@ function defineProps(vm, keys) { } }; } - }; - - for (let i = 0, len = keys.length; i < len; i++) { - _loop(i, len); } vm.model = createViewModel$1({}, props); } function defineContext(vm, keys) { const props = {}; - - const _loop2 = function _loop2(i, len) { + for (let i = 0, len = keys.length; i < len; i++) { const key = keys[i]; if (!(key in $$skipArray)) { props[key] = { enumerable: true, configurable: true, - get: function get() { + get: function () { return vm.model[key]; }, - set: function set(val) { + set: function (val) { return (vm.model[key] = val); } }; } - }; - - for (let i = 0, len = keys.length; i < len; i++) { - _loop2(i, len); } vm.$$context = createViewModel$1({}, props); } @@ -1415,22 +1291,14 @@ function getInjectValue(vm, key) { function getInjectValues(vm) { const inject = vm.inject || []; const result = {}; - _.each(inject, (key) => { + _.each(inject, function (key) { result[key] = getInjectValue(vm, key); }); - return result; } -const Model = (function() { - function Model() { - _classCallCheck(this, Model); - } - - Model.prototype._constructor = function _constructor( - model, - destroyHandler - ) { +class Model { + _constructor(model, destroyHandler) { if (model instanceof Observer || model instanceof Model) { model = model.model; } @@ -1470,22 +1338,23 @@ const Model = (function() { if (this.$$model) { return this.model; } - }; + } - Model.prototype._init = function _init() { - }; + _init() { - Model.prototype.init = function init() { + } + + init() { this._init(); - }; + } - Model.prototype.destroy = function destroy() { - for (const _key3 in this._computedWatchers) { - this._computedWatchers[_key3].teardown(); + destroy() { + for (const key in this._computedWatchers) { + this._computedWatchers[key].teardown(); } - _.each(this._watchers, (unwatches) => { + _.each(this._watchers, function (unwatches) { unwatches = _.isArray(unwatches) ? unwatches : [unwatches]; - _.each(unwatches, (unwatch) => { + _.each(unwatches, function (unwatch) { unwatch(); }); }); @@ -1495,10 +1364,8 @@ const Model = (function() { this.$$computed = null; this.$$state = null; this._destroyHandler && this._destroyHandler(); - }; - - return Model; -})(); + } +} function define(model) { return REACTIVE ? new Observer(model).model : model; @@ -1514,7 +1381,7 @@ function config(options) { } function toJSON(model) { - let result = void 0; + let result; if (_.isArray(model)) { result = []; for (let i = 0, len = model.length; i < len; i++) { @@ -1522,15 +1389,14 @@ function toJSON(model) { } } else if (model && isPlainObject(model)) { result = {}; - for (const _key4 in model) { - if (!_.has($$skipArray, _key4)) { - result[_key4] = toJSON(model[_key4]); + for (let key in model) { + if (!_.has($$skipArray, key)) { + result[key] = toJSON(model[key]); } } } else { result = model; } - return result; } @@ -1559,3 +1425,27 @@ export const Fix = { watch, toJSON }; + + +window.testT = function (count = 5000) { + const subsArray = []; + + const subsSet = new Set(); + + for (let i = 0; i < count; i++) { + subsArray.push("" + i); + subsSet.add("" + i); + } + + console.time("array"); + for (let i = count; i >= 0; i--) { + remove(subsArray, "" + 1); + } + console.timeEnd("array"); + + console.time("set"); + for (let i = count; i >= 0; i--) { + subsSet.delete("" + 1); + } + console.timeEnd("set"); +}; From 659ddd7483f3ce33f5a40724042053d004ff55fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=BF=A0=E5=B1=8F=E5=B1=B1=E6=9C=80=E9=80=9F=E4=B8=8B?= =?UTF-8?q?=E5=B1=B1=E4=BC=A0=E8=AF=B4?= Date: Thu, 23 Nov 2023 17:51:36 +0800 Subject: [PATCH 7/7] =?UTF-8?q?=E6=97=A0JIRA=20=E6=9B=B4=E6=96=B0subs?= =?UTF-8?q?=E5=AE=9E=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/fineui/src/fix/fix.js | 146 ++++++++++++++++----------------- 1 file changed, 71 insertions(+), 75 deletions(-) diff --git a/packages/fineui/src/fix/fix.js b/packages/fineui/src/fix/fix.js index 1006e02e1..a28f5e4a8 100644 --- a/packages/fineui/src/fix/fix.js +++ b/packages/fineui/src/fix/fix.js @@ -1,5 +1,72 @@ import { _ } from "@/core"; +let uid = 0; + +const pendingCleanupDeps = []; + +const cleanupDeps = () => { + for (let i = 0; i < pendingCleanupDeps.length; i++) { + const dep = pendingCleanupDeps[i]; + dep.subs = dep.subs.filter(s => s); + dep._pending = false; + } + pendingCleanupDeps.length = 0; +}; + + +/** + * A dep is an observable that can have multiple + * directives subscribing to it. + */ +class Dep { + constructor() { + this.id = uid++; + this._pending = false; + this.subs = []; + } + + addSub(sub) { + this.subs.push(sub); + } + + removeSub(sub) { + this.subs[this.subs.indexOf(sub)] = null; + if (!this._pending) { + this._pending = true; + pendingCleanupDeps.push(this); + } + } + + depend() { + if (Dep.target) { + Dep.target.addDep(this); + } + } + + notify(options) { + // stabilize the subscriber list first + const subs = this.subs.filter(s => s); + for (let i = 0, l = subs.length; i < l; i++) { + subs[i].update(options); + } + } +} + +// the current target watcher being evaluated. +// this is globally unique because there could be only one +// watcher being evaluated at any time. +Dep.target = null; +const targetStack = []; + +function pushTarget(_target) { + if (Dep.target) targetStack.push(Dep.target); + Dep.target = _target; +} + +function popTarget() { + Dep.target = targetStack.pop(); +} + function noop(a, b, c) { } @@ -7,6 +74,7 @@ function isNative(Ctor) { return typeof Ctor === "function" && /native code/.test(Ctor.toString()); } + const hasProto = "__proto__" in {}; const _toString = Object.prototype.toString; @@ -152,56 +220,6 @@ const $$skipArray = { $vbsetter: falsy }; -let uid = 0; - -/** - * A dep is an observable that can have multiple - * directives subscribing to it. - */ -class Dep { - constructor() { - this.id = uid++; - this.subs = new Set(); - } - - addSub(sub) { - this.subs.add(sub); - } - - removeSub(sub) { - this.subs.delete(sub); - } - - depend() { - if (Dep.target) { - Dep.target.addDep(this); - } - } - - notify(options) { - // stabilize the subscriber list first - const subs = [...this.subs.values()]; - for (let i = 0, l = subs.length; i < l; i++) { - subs[i].update(options); - } - } -} - -// the current target watcher being evaluated. -// this is globally unique because there could be only one -// watcher being evaluated at any time. -Dep.target = null; -const targetStack = []; - -function pushTarget(_target) { - if (Dep.target) targetStack.push(Dep.target); - Dep.target = _target; -} - -function popTarget() { - Dep.target = targetStack.pop(); -} - //如果浏览器不支持ecma262v5的Object.defineProperties或者存在BUG,比如IE8 //标准浏览器使用__defineGetter__, __defineSetter__实现 let canHideProperty = true; @@ -286,6 +304,7 @@ function flushSchedulerQueue() { } resetSchedulerState(); + cleanupDeps(); } @@ -853,7 +872,7 @@ function watch(model, expOrFn, cb, options) { options = options || {}; options.user = true; let exps; - if (_.isFunction(expOrFn) || !(exps = expOrFn.match(/[a-zA-Z0-9BI._.*]+|[|][|]|[&][&]|[(]|[)]/g)) || (exps.length === 1 && expOrFn.indexOf("*") < 0)) { + if (_.isFunction(expOrFn) || !(exps = expOrFn.match(/[a-zA-Z0-9_.*]+|[|][|]|[&][&]|[(]|[)]/g)) || (exps.length === 1 && expOrFn.indexOf("*") < 0)) { const watcher = new Watcher(model, expOrFn, cb, options); if (options.immediate) { cb(watcher.value); @@ -1420,32 +1439,9 @@ export const Fix = { freeze, del, Watcher, + cleanupDeps, pushTarget, popTarget, watch, toJSON }; - - -window.testT = function (count = 5000) { - const subsArray = []; - - const subsSet = new Set(); - - for (let i = 0; i < count; i++) { - subsArray.push("" + i); - subsSet.add("" + i); - } - - console.time("array"); - for (let i = count; i >= 0; i--) { - remove(subsArray, "" + 1); - } - console.timeEnd("array"); - - console.time("set"); - for (let i = count; i >= 0; i--) { - subsSet.delete("" + 1); - } - console.timeEnd("set"); -};