Skip to content

Commit

Permalink
Increase perf on large codebases - Fix #15 - v0.4.0
Browse files Browse the repository at this point in the history
  • Loading branch information
MadLittleMods committed Jul 2, 2015
1 parent 1cc039c commit aff90d0
Show file tree
Hide file tree
Showing 8 changed files with 72 additions and 12 deletions.
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,12 @@

# v0.4.0 - 2015-7-2

- Fix #15
- 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.
- Thank you to @ddprrt for bringing up the slowness issue in this article, [PostCSS misconceptions](https://medium.com/@ddprrt/postcss-misconceptions-faf5dc5038df).



# v0.3.9 - 2015-6-29

- Remove `opts` global leak. Fix #13
Expand Down
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ CSS variables or CSS Custom Properties limited subset polyfill/shim.

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.

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

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



Expand Down
7 changes: 4 additions & 3 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// PostCSS CSS Variables (postcss-css-variables)
// v0.3.8
// v0.4.0
//
// https://github.com/MadLittleMods/postcss-css-variables

Expand All @@ -9,6 +9,7 @@
var postcss = require('postcss');
var extend = require('extend');

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

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

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

Expand Down
7 changes: 5 additions & 2 deletions lib/clone-splice-parent-onto-node-when.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@

var shallowCloneNode = require('./shallow-clone-node');

// Splice on a parent scope onto a node
// And return a detached clone
var cloneSpliceParentOntoNodeWhen = function(node, parent, /*optional*/whenCb) {
Expand All @@ -15,7 +18,7 @@ var cloneSpliceParentOntoNodeWhen = function(node, parent, /*optional*/whenCb) {
cloneList.push(current.clone());
}
else {
cloneList.push(current.clone().removeAll());
cloneList.push(shallowCloneNode(current));
}

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

currentParent = currentParent.parent;
}
Expand Down
9 changes: 5 additions & 4 deletions lib/resolve-decl.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ var gatherVariableDependencies = require('./gather-variable-dependencies');
var isUnderScope = require('./is-under-scope');
var isNodeUnderScope = require('./is-node-under-scope');

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

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

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

if(mapItem.isUnderAtRule) {
// Create the clean atRule for which we place the declaration under
var atRuleNode = mapItem.parent.parent.clone().removeAll();
var atRuleNode = shallowCloneNode(mapItem.parent.parent);

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

// Append the old parent
newParentAtRuleNode.append(parentAtRuleNode);
Expand Down
46 changes: 46 additions & 0 deletions lib/shallow-clone-node.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
// Inspired by the PostCSS clone: https://github.com/postcss/postcss/blob/caba908d0f4e362466252202e6be84660c33d8a5/lib/node.js#L17
var shallowCloneNode = function(obj, parent) {
var cloned = new obj.constructor();

Object.keys(obj).forEach(function(i) {
if (!obj.hasOwnProperty(i)) {
return;
}

var value = obj[i];
var type = typeof value;

if (i === 'parent' && type === 'object') {
if (parent) {
cloned[i] = parent;
}
}
else if(i === 'source') {
cloned[i] = value;
}
else if (value instanceof Array) {
if(i === 'nodes') {
cloned[i] = [];
}
else {
cloned[i] = value.map(function(j) {
shallowCloneNode(j, cloned);
});
}
}
else if (
i !== 'before' && i !== 'after' &&
i !== 'between' && i !== 'semicolon'
) {
if(type === 'object') {
value = shallowCloneNode(value);
}

cloned[i] = value;
}
});

return cloned;
};

module.exports = shallowCloneNode;
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "postcss-css-variables",
"version": "0.3.9",
"version": "0.4.0",
"description": "PostCSS plugin to transform CSS Custom Properties(CSS variables) syntax into a static representation",
"keywords": [
"postcss",
Expand Down
2 changes: 1 addition & 1 deletion test/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ chai.use(chaiAsPromised);
var postcss = require('postcss');

var Promise = require('bluebird');
var fs = Promise.promisifyAll(require("fs"));
var fs = Promise.promisifyAll(require('fs'));
var CleanCSS = require('clean-css');

var cssvariables = require('../');
Expand Down

0 comments on commit aff90d0

Please sign in to comment.