Skip to content

Commit

Permalink
refactor: use a Map instead of an Object in dom/data (#32180)
Browse files Browse the repository at this point in the history
Co-authored-by: XhmikosR <[email protected]>
Co-authored-by: Rohit Sharma <[email protected]>
  • Loading branch information
3 people authored Mar 2, 2021
1 parent 6d93a13 commit 48a95f7
Show file tree
Hide file tree
Showing 15 changed files with 126 additions and 161 deletions.
2 changes: 1 addition & 1 deletion .bundlewatch.config.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
},
{
"path": "./dist/js/bootstrap.bundle.min.js",
"maxSize": "21.75 kB"
"maxSize": "22 kB"
},
{
"path": "./dist/js/bootstrap.esm.js",
Expand Down
2 changes: 1 addition & 1 deletion js/src/alert.js
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ class Alert extends BaseComponent {

static jQueryInterface(config) {
return this.each(function () {
let data = Data.getData(this, DATA_KEY)
let data = Data.get(this, DATA_KEY)

if (!data) {
data = new Alert(this)
Expand Down
6 changes: 3 additions & 3 deletions js/src/base-component.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,18 +24,18 @@ class BaseComponent {
}

this._element = element
Data.setData(this._element, this.constructor.DATA_KEY, this)
Data.set(this._element, this.constructor.DATA_KEY, this)
}

dispose() {
Data.removeData(this._element, this.constructor.DATA_KEY)
Data.remove(this._element, this.constructor.DATA_KEY)
this._element = null
}

/** Static */

static getInstance(element) {
return Data.getData(element, this.DATA_KEY)
return Data.get(element, this.DATA_KEY)
}

static get VERSION() {
Expand Down
4 changes: 2 additions & 2 deletions js/src/button.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ class Button extends BaseComponent {

static jQueryInterface(config) {
return this.each(function () {
let data = Data.getData(this, DATA_KEY)
let data = Data.get(this, DATA_KEY)

if (!data) {
data = new Button(this)
Expand All @@ -75,7 +75,7 @@ EventHandler.on(document, EVENT_CLICK_DATA_API, SELECTOR_DATA_TOGGLE, event => {

const button = event.target.closest(SELECTOR_DATA_TOGGLE)

let data = Data.getData(button, DATA_KEY)
let data = Data.get(button, DATA_KEY)
if (!data) {
data = new Button(button)
}
Expand Down
6 changes: 3 additions & 3 deletions js/src/carousel.js
Original file line number Diff line number Diff line change
Expand Up @@ -527,7 +527,7 @@ class Carousel extends BaseComponent {
// Static

static carouselInterface(element, config) {
let data = Data.getData(element, DATA_KEY)
let data = Data.get(element, DATA_KEY)
let _config = {
...Default,
...Manipulator.getDataAttributes(element)
Expand Down Expand Up @@ -586,7 +586,7 @@ class Carousel extends BaseComponent {
Carousel.carouselInterface(target, config)

if (slideIndex) {
Data.getData(target, DATA_KEY).to(slideIndex)
Data.get(target, DATA_KEY).to(slideIndex)
}

event.preventDefault()
Expand All @@ -605,7 +605,7 @@ EventHandler.on(window, EVENT_LOAD_DATA_API, () => {
const carousels = SelectorEngine.find(SELECTOR_DATA_RIDE)

for (let i = 0, len = carousels.length; i < len; i++) {
Carousel.carouselInterface(carousels[i], Data.getData(carousels[i], DATA_KEY))
Carousel.carouselInterface(carousels[i], Data.get(carousels[i], DATA_KEY))
}
})

Expand Down
8 changes: 4 additions & 4 deletions js/src/collapse.js
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ class Collapse extends BaseComponent {
const container = SelectorEngine.findOne(this._selector)
if (actives) {
const tempActiveData = actives.find(elem => container !== elem)
activesData = tempActiveData ? Data.getData(tempActiveData, DATA_KEY) : null
activesData = tempActiveData ? Data.get(tempActiveData, DATA_KEY) : null

if (activesData && activesData._isTransitioning) {
return
Expand All @@ -166,7 +166,7 @@ class Collapse extends BaseComponent {
}

if (!activesData) {
Data.setData(elemActive, DATA_KEY, null)
Data.set(elemActive, DATA_KEY, null)
}
})
}
Expand Down Expand Up @@ -332,7 +332,7 @@ class Collapse extends BaseComponent {
// Static

static collapseInterface(element, config) {
let data = Data.getData(element, DATA_KEY)
let data = Data.get(element, DATA_KEY)
const _config = {
...Default,
...Manipulator.getDataAttributes(element),
Expand Down Expand Up @@ -380,7 +380,7 @@ EventHandler.on(document, EVENT_CLICK_DATA_API, SELECTOR_DATA_TOGGLE, function (
const selectorElements = SelectorEngine.find(selector)

selectorElements.forEach(element => {
const data = Data.getData(element, DATA_KEY)
const data = Data.get(element, DATA_KEY)
let config
if (data) {
// update parent attribute
Expand Down
80 changes: 35 additions & 45 deletions js/src/dom/data.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,57 +11,47 @@
* ------------------------------------------------------------------------
*/

const mapData = (() => {
const storeData = {}
let id = 1
return {
set(element, key, data) {
if (typeof element.bsKey === 'undefined') {
element.bsKey = {
key,
id
}
id++
}
const elementMap = new Map()

storeData[element.bsKey.id] = data
},
get(element, key) {
if (!element || typeof element.bsKey === 'undefined') {
return null
}

const keyProperties = element.bsKey
if (keyProperties.key === key) {
return storeData[keyProperties.id]
}
export default {
set(element, key, instance) {
if (!elementMap.has(element)) {
elementMap.set(element, new Map())
}

return null
},
delete(element, key) {
if (typeof element.bsKey === 'undefined') {
return
}
const instanceMap = elementMap.get(element)

const keyProperties = element.bsKey
if (keyProperties.key === key) {
delete storeData[keyProperties.id]
delete element.bsKey
}
// make it clear we only want one instance per element
// can be removed later when multiple key/instances are fine to be used
if (!instanceMap.has(key) && instanceMap.size !== 0) {
// eslint-disable-next-line no-console
console.error(`Bootstrap doesn't allow more than one instance per element. Bound instance: ${Array.from(instanceMap.keys())[0]}.`)
return
}
}
})()

const Data = {
setData(instance, key, data) {
mapData.set(instance, key, data)
instanceMap.set(key, instance)
},
getData(instance, key) {
return mapData.get(instance, key)

get(element, key) {
if (elementMap.has(element)) {
return elementMap.get(element).get(key) || null
}

return null
},
removeData(instance, key) {
mapData.delete(instance, key)

remove(element, key) {
if (!elementMap.has(element)) {
return
}

const instanceMap = elementMap.get(element)

instanceMap.delete(key)

// free up element references if there are no instances left for an element
if (instanceMap.size === 0) {
elementMap.delete(element)
}
}
}

export default Data
4 changes: 2 additions & 2 deletions js/src/dropdown.js
Original file line number Diff line number Diff line change
Expand Up @@ -357,7 +357,7 @@ class Dropdown extends BaseComponent {
// Static

static dropdownInterface(element, config) {
let data = Data.getData(element, DATA_KEY)
let data = Data.get(element, DATA_KEY)
const _config = typeof config === 'object' ? config : null

if (!data) {
Expand Down Expand Up @@ -387,7 +387,7 @@ class Dropdown extends BaseComponent {
const toggles = SelectorEngine.find(SELECTOR_DATA_TOGGLE)

for (let i = 0, len = toggles.length; i < len; i++) {
const context = Data.getData(toggles[i], DATA_KEY)
const context = Data.get(toggles[i], DATA_KEY)
const relatedTarget = {
relatedTarget: toggles[i]
}
Expand Down
4 changes: 2 additions & 2 deletions js/src/modal.js
Original file line number Diff line number Diff line change
Expand Up @@ -508,7 +508,7 @@ class Modal extends BaseComponent {

static jQueryInterface(config, relatedTarget) {
return this.each(function () {
let data = Data.getData(this, DATA_KEY)
let data = Data.get(this, DATA_KEY)
const _config = {
...Default,
...Manipulator.getDataAttributes(this),
Expand Down Expand Up @@ -556,7 +556,7 @@ EventHandler.on(document, EVENT_CLICK_DATA_API, SELECTOR_DATA_TOGGLE, function (
})
})

let data = Data.getData(target, DATA_KEY)
let data = Data.get(target, DATA_KEY)
if (!data) {
const config = {
...Manipulator.getDataAttributes(target),
Expand Down
4 changes: 2 additions & 2 deletions js/src/popover.js
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ class Popover extends Tooltip {

static jQueryInterface(config) {
return this.each(function () {
let data = Data.getData(this, DATA_KEY)
let data = Data.get(this, DATA_KEY)
const _config = typeof config === 'object' ? config : null

if (!data && /dispose|hide/.test(config)) {
Expand All @@ -145,7 +145,7 @@ class Popover extends Tooltip {

if (!data) {
data = new Popover(this, _config)
Data.setData(this, DATA_KEY, data)
Data.set(this, DATA_KEY, data)
}

if (typeof config === 'string') {
Expand Down
2 changes: 1 addition & 1 deletion js/src/scrollspy.js
Original file line number Diff line number Diff line change
Expand Up @@ -278,7 +278,7 @@ class ScrollSpy extends BaseComponent {

static jQueryInterface(config) {
return this.each(function () {
let data = Data.getData(this, DATA_KEY)
let data = Data.get(this, DATA_KEY)
const _config = typeof config === 'object' && config

if (!data) {
Expand Down
4 changes: 2 additions & 2 deletions js/src/tab.js
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ class Tab extends BaseComponent {

static jQueryInterface(config) {
return this.each(function () {
const data = Data.getData(this, DATA_KEY) || new Tab(this)
const data = Data.get(this, DATA_KEY) || new Tab(this)

if (typeof config === 'string') {
if (typeof data[config] === 'undefined') {
Expand All @@ -204,7 +204,7 @@ class Tab extends BaseComponent {
EventHandler.on(document, EVENT_CLICK_DATA_API, SELECTOR_DATA_TOGGLE, function (event) {
event.preventDefault()

const data = Data.getData(this, DATA_KEY) || new Tab(this)
const data = Data.get(this, DATA_KEY) || new Tab(this)
data.show()
})

Expand Down
2 changes: 1 addition & 1 deletion js/src/toast.js
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,7 @@ class Toast extends BaseComponent {

static jQueryInterface(config) {
return this.each(function () {
let data = Data.getData(this, DATA_KEY)
let data = Data.get(this, DATA_KEY)
const _config = typeof config === 'object' && config

if (!data) {
Expand Down
8 changes: 4 additions & 4 deletions js/src/tooltip.js
Original file line number Diff line number Diff line change
Expand Up @@ -275,7 +275,7 @@ class Tooltip extends BaseComponent {
this._addAttachmentClass(attachment)

const container = this._getContainer()
Data.setData(tip, this.constructor.DATA_KEY, this)
Data.set(tip, this.constructor.DATA_KEY, this)

if (!this._element.ownerDocument.documentElement.contains(this.tip)) {
container.appendChild(tip)
Expand Down Expand Up @@ -465,11 +465,11 @@ class Tooltip extends BaseComponent {

_initializeOnDelegatedTarget(event, context) {
const dataKey = this.constructor.DATA_KEY
context = context || Data.getData(event.delegateTarget, dataKey)
context = context || Data.get(event.delegateTarget, dataKey)

if (!context) {
context = new this.constructor(event.delegateTarget, this._getDelegateConfig())
Data.setData(event.delegateTarget, dataKey, context)
Data.set(event.delegateTarget, dataKey, context)
}

return context
Expand Down Expand Up @@ -761,7 +761,7 @@ class Tooltip extends BaseComponent {

static jQueryInterface(config) {
return this.each(function () {
let data = Data.getData(this, DATA_KEY)
let data = Data.get(this, DATA_KEY)
const _config = typeof config === 'object' && config

if (!data && /dispose|hide/.test(config)) {
Expand Down
Loading

0 comments on commit 48a95f7

Please sign in to comment.