Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improved mix behaviour #197

Merged
merged 1 commit into from
Mar 9, 2016
Merged

Improved mix behaviour #197

merged 1 commit into from
Mar 9, 2016

Conversation

miripiruni
Copy link
Contributor

Related: bem/bem-core#805

+15 test cases
–1 bug

Fixed (degradation)

1. bemhtml should duplicate block class if mix several block with mods to elem in the same block.

Because block class must have for mix block with mods to block elem.

Example:

({
    block: 'b',
    content: {
        elem: 'e',
        mix: [
            { block: 'b', mods: { m1: 'v1' } },
            { block: 'b', mods: { m2: 'v2' } }
        ]
    }
});

4.3.4 result:

<div class="b"><div class="b__e b b_m1_v1 b b_m2_v2"></div></div>

demo

5.0.0 result:

<div class="b"><div class="b__e b b"></div></div>

demo;

This PR result:

<div class="b"><div class="b__e b b_m1_v1 b b_m2_v2"></div></div>

Improved

2. bemhtml should not duplicate block class if mix is the same block with mods.

({
    block: 'b',
    mix: [
        { block: 'b', mods: { m1: 'v1' } },
        { block: 'b', mods: { m2: 'v2' } }
    ]
});

4.3.4 result:

<div class="b b b_m1_v1 b b_m2_v2"></div>

demo

5.0.0 result:

<div class="b b b_m1_v1 b b_m2_v2"></div>

demo

This PR result:

<div class="b b_m1_v1 b_m2_v2"></div>

3. bemhtml should not duplicate elem class if mix is the same elem.

Weird case, but for completeness why not to check it

({
    block: 'b',
    elem: 'e',
    mix: { elem: 'e' }
});

4.3.4 result:

<div class="b__e b__e"></div>

demo

5.0.0 result:

<div class="b__e b__e"></div>

demo

This PR result:

<div class="b__e"></div>

4. bemhtml should not duplicate elem class if mix is the same block elem.

Weird case, but for completeness why not to check it.

({
    block: 'b',
    elem: 'e',
    mix: { block: 'b', elem: 'e' }
});

4.3.4 result:

<div class="b__e b__e"></div>

demo

5.0.0 result:

<div class="b__e b__e"></div>

demo

This PR result:

<div class="b__e"></div>

5. bemhtml should not duplicate elem class if mix the same elem to elem in block.

Weird case, but for completeness why not to check it.

({
    block: 'b',
    content: {
        elem: 'e',
        mix: { elem: 'e' }
    }
});

4.3.4 result:

<div class="b"><div class="b__e b__e"></div></div>

demo

5.0.0 result:

<div class="b"><div class="b__e b__e"></div></div>

demo

This PR result:

<div class="b"><div class="b__e"></div></div>

6. bemhtml should not duplicate elem class if mix is the same block elem with elemMods.

({
    block: 'b',
    elem: 'e',
    mix: { elem: 'e', elemMods: { modname: 'modval' } }
});

4.3.4 result:

<div class="b__e b__e b__e_modname_modval"></div>

demo

5.0.0 result:

<div class="b__e b__e b__e_modname_modval"></div>

demo

This PR result:

<div class="b__e b__e_modname_modval"></div>

7. bemhtml should not duplicate block elem elemMods class

({
    block: 'b',
    elem: 'e',
    mix: { block: 'b', elem: 'e', elemMods: { modname: 'modval' } }
});

4.3.4 result:

<div class="b__e b__e b__e_modname_modval"></div>

demo

5.0.0 result:

<div class="b__e b__e b__e_modname_modval"></div>

demo

This PR result:

<div class="b__e b__e_modname_modval"></div>

“Who cares” cases (zero cost but enjoyable)

Weird cases, but for completeness why not to check it.

8. bemhtml should duplicate block mods class if mix is the same block with mods.

But who cares? It’s pretty rare case.
To fix this we need to compare each key/value pairs. It’s too expensive.
I believe that developers should not want to do this.

({
    block: 'b',
    mods: { m: 'v' },
    mix: { block: 'b', mods: { m: 'v' } }
});

4.3.4 result:

<div class="b b_m_v b b_m_v"></div>

demo

5.0.0 result:

<div class="b b_m_v b b_m_v"></div>

demo

This PR result:

<div class="b b_m_v b_m_v"></div>

9. bemhtml should duplicate elem elemMod class

({
    block: 'b',
    content: {
        elem: 'e',
        elemMods: { modname: 'modval' },
        mix: { elem: 'e', elemMods: { modname: 'modval' } }
    }
});

But who cares? It’s pretty rare case.
To fix this we need to compare each key/value pairs. It’s too expensive.
I believe that developers should not want to do this.

4.3.4 result:

<div class="b">
    <div class="b__e b__e_modname_modval b__e b__e_modname_modval"></div>
</div>

demo

5.0.0 result:

<div class="b">
    <div class="b__e b__e_modname_modval b__e b__e_modname_modval"></div>
</div>

demo

This PR result:

<div class="b">
    <div class="b__e b__e_modname_modval b__e_modname_modval"></div>
</div>

@@ -213,7 +213,8 @@ BEMHTML.prototype.renderMix = function renderMix(entity,
if (typeof item === 'string')
item = { block: item, elem: undefined };

var hasItem = item.block || item.elem;
var hasItem = (item.block || item.elem) &&
!(item.mods && item.block === entity.block);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pretty scared about this condition. Can we add more tests for edge cases?

Like:

{ block: 'b', elem: 'e', mix: { elem: 'e' } } // 1
{ block: 'b', elem: 'e', mix: { block: 'b', elem: 'e' } } // 2
{ block: 'b', content: { elem: 'e', mix: { elem: 'e' } } } // 3

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@zxqfox it’s defferent cases:

  1. elem with mixed the same elem
  2. elem with mixed elem with elemMods
  3. block with mixed the same block
  4. block with mixed block with mods

Now 1, 2, 3 will render as duplicates but who cares? No degradation with current version, don’t afraid.

This PR about number 4 only. The reason is “I want to mix block (for CSS purposes) with mods without apply templates”.

//cc @tadatuta

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rewrite condition then.
item.elem || item.block && !(item.mods && item.block === entity.block)

@qfox
Copy link
Member

qfox commented Feb 15, 2016

👍

@miripiruni
Copy link
Contributor Author

I remember this issue and return to PR at monday.

@miripiruni miripiruni changed the title Do not repeat block class on mix with same block’s mod Improved mix behaviour Feb 29, 2016
@miripiruni
Copy link
Contributor Author

🆙

This issue is much more interesting than it seems at first sight. See updated PR description.

@miripiruni
Copy link
Contributor Author

I tried to run bench.

prev — 5.0.0.
next — this PR.

miri$ node ./run.js --compare

render:basic:next x 553,115 ops/sec ±0.58% (88 runs sampled)
render:basic:prev x 541,073 ops/sec ±0.92% (87 runs sampled)
render:islands:next x 917 ops/sec ±0.94% (87 runs sampled)
render:islands:prev x 972 ops/sec ±1.38% (86 runs sampled)
render:showcase:next x 1,766 ops/sec ±1.41% (84 runs sampled)
render:showcase:prev x 1,890 ops/sec ±1.38% (86 runs sampled)

JFYI.

@tadatuta
Copy link
Member

tadatuta commented Mar 1, 2016

try benches few times. for me it often results in different timing each time I try.

@miripiruni
Copy link
Contributor Author

@tadatuta yes, of course I tried to run it several times. I saw no degradation.


if (item.elem) {
if (item.elem !== entity.elem && item.elem !== context.elem) {
hasItem = true;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

at least hasItem = item.elem !== entity.elem && item.elem !== context.elem

@miripiruni
Copy link
Contributor Author

miri$ node ./run.js --compare --min-samples 1000
render:basic:next x 576,966 ops/sec ±0.98% (1038 runs sampled)
render:basic:prev x 578,712 ops/sec ±0.37% (1037 runs sampled)
render:islands:next x 990 ops/sec ±0.15% (1037 runs sampled)
render:islands:prev x 1,015 ops/sec ±0.20% (1037 runs sampled)
render:showcase:next x 1,939 ops/sec ±0.18% (1036 runs sampled)
render:showcase:prev x 1,908 ops/sec ±0.23% (1037 runs sampled)

@miripiruni miripiruni added this to the 5.1.0 milestone Mar 2, 2016
@qfox
Copy link
Member

qfox commented Mar 2, 2016

Nice! Thanks for fixing all these stuff. LGTM

@miripiruni
Copy link
Contributor Author

May I merge?

@qfox
Copy link
Member

qfox commented Mar 3, 2016

/cc @veged @indutny @arikon

@veged
Copy link
Member

veged commented Mar 3, 2016

LGTM

@miripiruni
Copy link
Contributor Author

@veged thank you for your attention! 🎱

miripiruni added a commit that referenced this pull request Mar 9, 2016
Improved mix behaviour
@miripiruni miripiruni merged commit 65ffa96 into master Mar 9, 2016
@miripiruni miripiruni deleted the cls branch March 9, 2016 10:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants