From 561ee085919334eafa38cbafaa395784f7f050e0 Mon Sep 17 00:00:00 2001 From: Artur Arseniev Date: Wed, 1 Nov 2023 23:21:26 +0400 Subject: [PATCH] Prevent crash if block category id is an object builtin method name. Closes #5478 --- src/block_manager/model/Categories.ts | 19 ++++++++++++++++--- src/block_manager/view/BlocksView.ts | 11 +++++------ src/utils/mixins.ts | 8 +++++++- 3 files changed, 28 insertions(+), 10 deletions(-) diff --git a/src/block_manager/model/Categories.ts b/src/block_manager/model/Categories.ts index 5af3bff2f..fbc3d6f93 100644 --- a/src/block_manager/model/Categories.ts +++ b/src/block_manager/model/Categories.ts @@ -1,6 +1,19 @@ -import { Collection } from '../../common'; -import Category from './Category'; +import { isArray, isString } from 'underscore'; +import { AddOptions, Collection } from '../../common'; +import { normalizeKey } from '../../utils/mixins'; +import Category, { BlockCategoryProperties } from './Category'; -export default class Categories extends Collection {} +export default class Categories extends Collection { + /** @ts-ignore */ + add(model: (BlockCategoryProperties | Category)[] | BlockCategoryProperties | Category, opts?: AddOptions) { + const models = isArray(model) ? model : [model]; + models.forEach(md => md && (md.id = normalizeKey(`${md.id}`))); + return super.add(model, opts); + } + + get(id: string | Category) { + return super.get(isString(id) ? normalizeKey(id) : id); + } +} Categories.prototype.model = Category; diff --git a/src/block_manager/view/BlocksView.ts b/src/block_manager/view/BlocksView.ts index d70bd85c6..4cbe61915 100644 --- a/src/block_manager/view/BlocksView.ts +++ b/src/block_manager/view/BlocksView.ts @@ -19,7 +19,7 @@ export default class BlocksView extends View { em: EditorModel; config: BlocksViewConfig; categories: Categories; - renderedCategories: Record; + renderedCategories = new Map(); ppfx: string; noCatClass: string; blockContClass: string; @@ -34,7 +34,6 @@ export default class BlocksView extends View { bindAll(this, 'getSorter', 'onDrag', 'onDrop', 'onMove'); this.config = config || {}; this.categories = opts.categories || ''; - this.renderedCategories = {}; const ppfx = this.config.pStylePrefix || ''; this.ppfx = ppfx; this.noCatClass = `${ppfx}blocks-no-cat`; @@ -126,7 +125,7 @@ export default class BlocksView extends View { * @private * */ add(model: Block, fragment?: DocumentFragment) { - const { config } = this; + const { config, renderedCategories } = this; const view = new BlockView( { model, @@ -148,13 +147,13 @@ export default class BlocksView extends View { const catModel = this.categories.add(category); const catId = catModel.get('id')!; const categories = this.getCategoriesEl(); - let catView = this.renderedCategories[catId]; + let catView = renderedCategories.get(catId); // @ts-ignore model.set('category', catModel, { silent: true }); if (!catView && categories) { catView = new CategoryView({ model: catModel }, config).render(); - this.renderedCategories[catId] = catView; + renderedCategories.set(catId, catView); categories.appendChild(catView.el); } @@ -191,7 +190,7 @@ export default class BlocksView extends View { const frag = document.createDocumentFragment(); delete this.catsEl; delete this.blocksEl; - this.renderedCategories = {}; + this.renderedCategories = new Map(); this.el.innerHTML = `
diff --git a/src/utils/mixins.ts b/src/utils/mixins.ts index da205a310..5adf2e1ff 100644 --- a/src/utils/mixins.ts +++ b/src/utils/mixins.ts @@ -1,10 +1,16 @@ -import { isArray, isElement, isUndefined, keys } from 'underscore'; +import { isArray, isElement, isFunction, isUndefined, keys } from 'underscore'; import ComponentView from '../dom_components/view/ComponentView'; import EditorModel from '../editor/model/Editor'; import { isTextNode } from './dom'; import Component from '../dom_components/model/Component'; import { ObjectAny } from '../common'; +const obj: ObjectAny = {}; + +export const isBultInMethod = (key: string) => isFunction(obj[key]); + +export const normalizeKey = (key: string) => (isBultInMethod(key) ? `_${key}` : key); + export const wait = (mls: number = 0) => new Promise(res => setTimeout(res, mls)); export const isDef = (value: any) => typeof value !== 'undefined';