Skip to content

Commit aff90d0

Browse files
committed
Increase perf on large codebases - Fix #15 - v0.4.0
1 parent 1cc039c commit aff90d0

File tree

8 files changed

+72
-12
lines changed

8 files changed

+72
-12
lines changed

CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,12 @@
11

2+
# v0.4.0 - 2015-7-2
3+
4+
- Fix #15
5+
- Remove slowness from cloning the `root` with `node.clone().removeAll()`. Now using `./lib/shallow-clone-node.js` to avoid cloning children which will get removed right after.
6+
- Thank you to @ddprrt for bringing up the slowness issue in this article, [PostCSS misconceptions](https://medium.com/@ddprrt/postcss-misconceptions-faf5dc5038df).
7+
8+
9+
210
# v0.3.9 - 2015-6-29
311

412
- Remove `opts` global leak. Fix #13

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ CSS variables or CSS Custom Properties limited subset polyfill/shim.
88

99
We strive for the most complete transformation but we/no plugin can achieve true complete parity according to the [specification](http://dev.w3.org/csswg/css-variables/) because of the DOM cascade unknowns.
1010

11-
## Latest Version: v0.3.9
11+
## Latest Version: v0.4.0
1212
### [Changelog](https://github.com/MadLittleMods/postcss-css-variables/blob/master/CHANGELOG.md)
1313

1414
### Install
@@ -236,6 +236,7 @@ The main features that we`postcss-css-variables` add/provide are:
236236
- Proper value substitution based on explicit DOM/structure traversal
237237
- At-rule support `@media`, `@support`, etc
238238
- Nested rules which can be fully deduced with [`postcss-nested`](https://github.com/postcss/postcss-nested).
239+
- Pseudo class/element support `:hover`, etc
239240

240241

241242

index.js

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// PostCSS CSS Variables (postcss-css-variables)
2-
// v0.3.8
2+
// v0.4.0
33
//
44
// https://github.com/MadLittleMods/postcss-css-variables
55

@@ -9,6 +9,7 @@
99
var postcss = require('postcss');
1010
var extend = require('extend');
1111

12+
var shallowCloneNode = require('./lib/shallow-clone-node');
1213
var resolveValue = require('./lib/resolve-value');
1314
var resolveDecl = require('./lib/resolve-decl');
1415

@@ -23,7 +24,7 @@ var RE_VAR_PROP = (/(--(.+))/);
2324

2425
function eachCssVariableDeclaration(css, cb) {
2526
// Loop through all of the declarations and grab the variables and put them in the map
26-
css.eachDecl(function(decl, index) {
27+
css.eachDecl(function(decl) {
2728
// If declaration is a variable
2829
if(RE_VAR_PROP.test(decl.prop)) {
2930
cb(decl);
@@ -137,7 +138,7 @@ module.exports = postcss.plugin('postcss-css-variables', function(options) {
137138
// Split out each selector piece into its own declaration for easier logic down the road
138139
decl.parent.selectors.forEach(function(selector) {
139140
// Create a detached clone
140-
var splitOutRule = decl.parent.clone().removeAll();
141+
var splitOutRule = shallowCloneNode(decl.parent);
141142
splitOutRule.selector = selector;
142143
splitOutRule.parent = decl.parent.parent;
143144

lib/clone-splice-parent-onto-node-when.js

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
2+
var shallowCloneNode = require('./shallow-clone-node');
3+
14
// Splice on a parent scope onto a node
25
// And return a detached clone
36
var cloneSpliceParentOntoNodeWhen = function(node, parent, /*optional*/whenCb) {
@@ -15,7 +18,7 @@ var cloneSpliceParentOntoNodeWhen = function(node, parent, /*optional*/whenCb) {
1518
cloneList.push(current.clone());
1619
}
1720
else {
18-
cloneList.push(current.clone().removeAll());
21+
cloneList.push(shallowCloneNode(current));
1922
}
2023

2124
isWhenNow = whenCb(current);
@@ -28,7 +31,7 @@ var cloneSpliceParentOntoNodeWhen = function(node, parent, /*optional*/whenCb) {
2831
var cloneParentList = [];
2932
var currentParent = parent;
3033
while(currentParent) {
31-
cloneParentList.push(currentParent.clone().removeAll());
34+
cloneParentList.push(shallowCloneNode(currentParent));
3235

3336
currentParent = currentParent.parent;
3437
}

lib/resolve-decl.js

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ var gatherVariableDependencies = require('./gather-variable-dependencies');
55
var isUnderScope = require('./is-under-scope');
66
var isNodeUnderScope = require('./is-node-under-scope');
77

8+
var shallowCloneNode = require('./shallow-clone-node');
89
var findNodeAncestorWithSelector = require('./find-node-ancestor-with-selector');
910
var cloneSpliceParentOntoNodeWhen = require('./clone-splice-parent-onto-node-when');
1011

@@ -43,7 +44,7 @@ function eachMapItemDependencyOfDecl(variablesUsedList, map, decl, cb) {
4344
// TODO: use regex from `isUnderScope`
4445
else if(isUnderScope.RE_PSEUDO_SELECTOR.test(mapItem.parent.selector)) {
4546
// Create a detached clone
46-
var ruleClone = decl.parent.clone().removeAll();
47+
var ruleClone = shallowCloneNode(decl.parent);
4748
ruleClone.parent = decl.parent.parent;
4849

4950
// Add the declaration to it
@@ -91,7 +92,7 @@ function resolveDecl(decl, map, /*optional*/shouldPreserve, /*optional*/logResol
9192
// Resolve the cascade dependencies
9293
// Now find any at-rule declarations that need to be added below each rule
9394
eachMapItemDependencyOfDecl(valueResults.variablesUsed, map, decl, function(mimicDecl, mapItem) {
94-
var ruleClone = decl.parent.clone().removeAll();
95+
var ruleClone = shallowCloneNode(decl.parent);
9596
var declClone = decl.clone();
9697
// No mangle resolve
9798
declClone.value = _logResolveValueResult(resolveValue(mimicDecl, map, true)).value;
@@ -102,7 +103,7 @@ function resolveDecl(decl, map, /*optional*/shouldPreserve, /*optional*/logResol
102103

103104
if(mapItem.isUnderAtRule) {
104105
// Create the clean atRule for which we place the declaration under
105-
var atRuleNode = mapItem.parent.parent.clone().removeAll();
106+
var atRuleNode = shallowCloneNode(mapItem.parent.parent);
106107

107108
// Add the rule to the atRule
108109
atRuleNode.append(ruleClone);
@@ -113,7 +114,7 @@ function resolveDecl(decl, map, /*optional*/shouldPreserve, /*optional*/logResol
113114
var currentAtRuleNode = mapItem.parent.parent;
114115
while(currentAtRuleNode.parent.type === 'atrule') {
115116
// Create a new clean clone of that at rule to nest under
116-
var newParentAtRuleNode = currentAtRuleNode.parent.clone().removeAll();
117+
var newParentAtRuleNode = shallowCloneNode(currentAtRuleNode.parent);
117118

118119
// Append the old parent
119120
newParentAtRuleNode.append(parentAtRuleNode);

lib/shallow-clone-node.js

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
// Inspired by the PostCSS clone: https://github.com/postcss/postcss/blob/caba908d0f4e362466252202e6be84660c33d8a5/lib/node.js#L17
2+
var shallowCloneNode = function(obj, parent) {
3+
var cloned = new obj.constructor();
4+
5+
Object.keys(obj).forEach(function(i) {
6+
if (!obj.hasOwnProperty(i)) {
7+
return;
8+
}
9+
10+
var value = obj[i];
11+
var type = typeof value;
12+
13+
if (i === 'parent' && type === 'object') {
14+
if (parent) {
15+
cloned[i] = parent;
16+
}
17+
}
18+
else if(i === 'source') {
19+
cloned[i] = value;
20+
}
21+
else if (value instanceof Array) {
22+
if(i === 'nodes') {
23+
cloned[i] = [];
24+
}
25+
else {
26+
cloned[i] = value.map(function(j) {
27+
shallowCloneNode(j, cloned);
28+
});
29+
}
30+
}
31+
else if (
32+
i !== 'before' && i !== 'after' &&
33+
i !== 'between' && i !== 'semicolon'
34+
) {
35+
if(type === 'object') {
36+
value = shallowCloneNode(value);
37+
}
38+
39+
cloned[i] = value;
40+
}
41+
});
42+
43+
return cloned;
44+
};
45+
46+
module.exports = shallowCloneNode;

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "postcss-css-variables",
3-
"version": "0.3.9",
3+
"version": "0.4.0",
44
"description": "PostCSS plugin to transform CSS Custom Properties(CSS variables) syntax into a static representation",
55
"keywords": [
66
"postcss",

test/test.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ chai.use(chaiAsPromised);
66
var postcss = require('postcss');
77

88
var Promise = require('bluebird');
9-
var fs = Promise.promisifyAll(require("fs"));
9+
var fs = Promise.promisifyAll(require('fs'));
1010
var CleanCSS = require('clean-css');
1111

1212
var cssvariables = require('../');

0 commit comments

Comments
 (0)