10a63377c7b9a139a5edffd8bf030fec_use (v10)

Revision 10 of this benchmark created on


Setup

'use strict';
// @bem-react/classname
function r(r){function t(t,i,a,o){var f=i?e+t+r.e+i:e+t,v=f;if(a){var s=' '+v+r.m;for(var u in a)if(a.hasOwnProperty(u)){var p=a[u];!0===p?v+=s+u:p&&(v+=s+u+n+p)}}if(void 0!==o)for(var y=0,c=(o=Array.isArray(o)?o:[o]).length;y<c;y++){var l=o[y];if(l&&'string'==typeof l.valueOf())for(var g=l.valueOf().split(' '),d=0;d<g.length;d++){var h=g[d];h!==f&&(v+=' '+h)}}return v}var e=r.n||'',n=r.v||r.m;return function(r,e){return function(n,i,a){return'string'==typeof n?'string'==typeof i||Array.isArray(i)?t(r,n,void 0,i):t(r,n,i,a):t(r,e,n,i)}}}var cn=r({e:'-',m:'_'});

//////////////////////////////////// v1 ////////////////////////////////////
const isMix = (val) => Array.isArray(val) || typeof val === 'string';

const getMod = (arg0) => isMix(arg0) ? {} : (arg0 || {});

const getMix = (arg0, arg1) => isMix(arg0) ? arg0 : (arg1 || []);


const getKeyMeta = (key) => {
    const chunks = key.split('-');
    const [blockOriginal, elementOriginal = '', blockIncorrect] = chunks;
    const [block, blockMod, blockModValue] = blockOriginal.split('_');
    const [element, elementMod, elementModValue] = elementOriginal.split('_');
    if (block && !element && !blockIncorrect) {
        if (blockMod)
            return { type: 'block-mod', block, mod: [blockMod, blockModValue] };
        return { type: 'block', block };
    } else if (!blockMod && element && !blockIncorrect) {
        if (elementMod)
            return { type: 'element-mod', block, element, mod: [elementMod, elementModValue] };
        return { type: 'element', block, element };
    }
    return { type: 'exception' };
};

const createBlockApiV1 = (block, element) => ((mod, mix) => cn(block, element)(getMod(mod), getMix(mod, mix)));

const getClassesApiV1 = (classes) => {
    return Object.values(classes).reduce((classesApi, key) => {
        const keyMeta = getKeyMeta(key);
        const type = keyMeta.type;

        if (type === 'exception') return classesApi;

        const blockKey = keyMeta.block;
        classesApi[blockKey] = classesApi[blockKey] || createBlockApiV1(blockKey);

        if (type === 'element' || type === 'element-mod') {
            const elementKey = keyMeta.element;

            classesApi[blockKey][elementKey] = createBlockApiV1(blockKey, elementKey);
        }

        return classesApi;
    }, {});
};

//////////////////////////////////// v2 ////////////////////////////////////
function createBlockApiV2(cnBlock, element = '') {
    return cnBlock.bind(null, element);
}

function getClassesApiV2(blocks) {
    const api = {};

    for (const blockName in blocks) {
        const cnBlock = cn(blockName);
        const blockApi = api[blockName] = createBlockApiV2(cnBlock);

        blocks[blockName].forEach(elementName => {
            blockApi[elementName] = createBlockApiV2(cnBlock, elementName);
        });
    }

    return api;
}

//////////////////////////////////// v3 ////////////////////////////////////
function getClassesApiV3() {
    return new Proxy({}, {
    get(target, blockName) {
            if (blockName in target) {
                return target[blockName];
            }

            const cnBlock = cn(blockName);

            return target[blockName] = new Proxy(cnBlock.bind(null, ''), {
                get: (_, elementName) => {
                    return elementName in cnBlock ? cnBlock[elementName] : (cnBlock[elementName] = cnBlock.bind(null, elementName));
                },
            });
        },
    });
}

Test runner

Ready to run.

Testing in
TestOps/sec
Old
const v1 = getClassesApiV1({
	"WeatherForecast-Tile": "WeatherForecast-Tile",
    "WeatherForecast-TileDay": "WeatherForecast-TileDay",
    "WeatherForecast-TileNight": "WeatherForecast-TileNight",
    "WeatherForecast-Icon": "WeatherForecast-Icon",
	"WeatherForecast-Icon_size_s": "WeatherForecast-Icon_size_s",
	"WeatherForecast-Icon_size_m": "WeatherForecast-Icon_size_m"
});

v1.WeatherForecast();
v1.WeatherForecast.Tile();
v1.WeatherForecast.Tile();
v1.WeatherForecast.Tile({ type: 'mini' });
v1.WeatherForecast.Tile();
v1.WeatherForecast.Tile();
ready
New
const v2 = getClassesApiV2({
	WeatherForecast: ["Tile", "TileDay", "TileNight", "Icon"],
});


v2.WeatherForecast();
v2.WeatherForecast.Tile();
v2.WeatherForecast.Tile();
v2.WeatherForecast.Tile({ type: 'mini' });
v2.WeatherForecast.Tile();
v2.WeatherForecast.Tile();
ready
Proxy
const v3 = getClassesApiV3();

v3.WeatherForecast();
v3.WeatherForecast.Tile();
v3.WeatherForecast.Tile();
v3.WeatherForecast.Tile({ type: 'mini' });
v3.WeatherForecast.Tile();
v3.WeatherForecast.Tile();
ready

Revisions

You can edit these tests or add more tests to this page by appending /edit to the URL.