less 2.6.0 → 2.7.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (144) hide show
  1. package/.travis.yml +3 -2
  2. package/CHANGELOG.md +30 -2
  3. package/Gruntfile.js +2 -3
  4. package/README.md +2 -2
  5. package/appveyor.yml +1 -0
  6. package/bin/lessc +47 -23
  7. package/dist/less.js +914 -582
  8. package/dist/less.min.js +9 -12
  9. package/lib/less/environment/abstract-file-manager.js +2 -2
  10. package/lib/less/functions/color.js +6 -3
  11. package/lib/less/index.js +1 -1
  12. package/lib/less/parser/parser-input.js +69 -69
  13. package/lib/less/parser/parser.js +111 -51
  14. package/lib/less/tree/anonymous.js +1 -1
  15. package/lib/less/tree/call.js +7 -4
  16. package/lib/less/tree/comment.js +2 -0
  17. package/lib/less/tree/directive.js +1 -0
  18. package/lib/less/tree/extend.js +1 -0
  19. package/lib/less/tree/import.js +1 -0
  20. package/lib/less/tree/media.js +1 -0
  21. package/lib/less/tree/mixin-call.js +1 -0
  22. package/lib/less/tree/mixin-definition.js +2 -1
  23. package/lib/less/tree/rule.js +1 -0
  24. package/lib/less/tree/ruleset-call.js +1 -0
  25. package/lib/less/tree/ruleset.js +86 -85
  26. package/lib/less/tree/unit.js +2 -2
  27. package/lib/less/visitors/extend-visitor.js +5 -5
  28. package/lib/less/visitors/to-css-visitor.js +20 -10
  29. package/lib/less-browser/error-reporting.js +10 -10
  30. package/lib/less-browser/index.js +48 -25
  31. package/lib/less-node/file-manager.js +1 -1
  32. package/lib/less-node/lessc-helper.js +2 -2
  33. package/lib/source-map/source-map-0.1.31.js +1 -1
  34. package/package.json +29 -22
  35. package/test/browser/common.js +29 -8
  36. package/test/browser/less/console-errors/test-error.txt +1 -1
  37. package/test/browser/less.js +13 -16
  38. package/test/browser/runner-production-options.js +1 -1
  39. package/test/css/comments2.css +6 -0
  40. package/test/css/no-strict-math/mixins-guards.css +12 -0
  41. package/test/css/no-strict-math/no-sm-operations.css +3 -0
  42. package/test/css/operations.css +1 -1
  43. package/test/css/plugin.css +5 -0
  44. package/test/less/comments.less +1 -1
  45. package/test/less/comments2.less +11 -0
  46. package/test/less/errors/detached-ruleset-3.txt +1 -1
  47. package/test/less/errors/functions-1.less +2 -0
  48. package/test/less/errors/functions-1.txt +3 -0
  49. package/test/less/errors/functions-10-keyword.less +2 -0
  50. package/test/less/errors/functions-10-keyword.txt +3 -0
  51. package/test/less/errors/functions-11-operation.less +2 -0
  52. package/test/less/errors/functions-11-operation.txt +3 -0
  53. package/test/less/errors/functions-12-quoted.less +2 -0
  54. package/test/less/errors/functions-12-quoted.txt +3 -0
  55. package/test/less/errors/functions-13-selector.less +2 -0
  56. package/test/less/errors/functions-13-selector.txt +3 -0
  57. package/test/less/errors/functions-14-url.less +2 -0
  58. package/test/less/errors/functions-14-url.txt +3 -0
  59. package/test/less/errors/functions-15-value.less +2 -0
  60. package/test/less/errors/functions-15-value.txt +3 -0
  61. package/test/less/errors/functions-2-alpha.less +2 -0
  62. package/test/less/errors/functions-2-alpha.txt +3 -0
  63. package/test/less/errors/functions-3-assignment.less +2 -0
  64. package/test/less/errors/functions-3-assignment.txt +3 -0
  65. package/test/less/errors/functions-4-call.less +2 -0
  66. package/test/less/errors/functions-4-call.txt +3 -0
  67. package/test/less/errors/functions-5-color-2.less +1 -0
  68. package/test/less/errors/functions-5-color-2.txt +2 -0
  69. package/test/less/errors/functions-5-color.less +2 -0
  70. package/test/less/errors/functions-5-color.txt +3 -0
  71. package/test/less/errors/functions-6-condition.less +2 -0
  72. package/test/less/errors/functions-6-condition.txt +3 -0
  73. package/test/less/errors/functions-7-dimension.less +2 -0
  74. package/test/less/errors/functions-7-dimension.txt +3 -0
  75. package/test/less/errors/functions-8-element.less +2 -0
  76. package/test/less/errors/functions-8-element.txt +3 -0
  77. package/test/less/errors/functions-9-expression.less +2 -0
  78. package/test/less/errors/functions-9-expression.txt +3 -0
  79. package/test/less/errors/property-in-root.txt +1 -1
  80. package/test/less/errors/property-in-root2.txt +1 -1
  81. package/test/less/errors/property-in-root3.txt +1 -1
  82. package/test/less/errors/root-func-undefined-1.less +1 -0
  83. package/test/less/errors/root-func-undefined-1.txt +2 -0
  84. package/test/less/errors/root-func-undefined-2.less +2 -0
  85. package/test/less/errors/root-func-undefined-2.txt +3 -0
  86. package/test/less/extend-chaining.less +1 -1
  87. package/test/less/merge.less +4 -4
  88. package/test/less/mixins-guards.less +1 -1
  89. package/test/less/no-strict-math/mixins-guards.less +25 -0
  90. package/test/less/no-strict-math/no-sm-operations.less +4 -1
  91. package/test/less/operations.less +1 -1
  92. package/test/less/plugin/plugin-tree-nodes.js +80 -0
  93. package/test/less/plugin.less +8 -0
  94. package/test/less-bom/comments.less +1 -1
  95. package/test/less-bom/comments2.less +11 -0
  96. package/test/less-bom/errors/detached-ruleset-3.txt +1 -1
  97. package/test/less-bom/errors/functions-1.less +2 -0
  98. package/test/less-bom/errors/functions-1.txt +3 -0
  99. package/test/less-bom/errors/functions-10-keyword.less +2 -0
  100. package/test/less-bom/errors/functions-10-keyword.txt +3 -0
  101. package/test/less-bom/errors/functions-11-operation.less +2 -0
  102. package/test/less-bom/errors/functions-11-operation.txt +3 -0
  103. package/test/less-bom/errors/functions-12-quoted.less +2 -0
  104. package/test/less-bom/errors/functions-12-quoted.txt +3 -0
  105. package/test/less-bom/errors/functions-13-selector.less +2 -0
  106. package/test/less-bom/errors/functions-13-selector.txt +3 -0
  107. package/test/less-bom/errors/functions-14-url.less +2 -0
  108. package/test/less-bom/errors/functions-14-url.txt +3 -0
  109. package/test/less-bom/errors/functions-15-value.less +2 -0
  110. package/test/less-bom/errors/functions-15-value.txt +3 -0
  111. package/test/less-bom/errors/functions-2-alpha.less +2 -0
  112. package/test/less-bom/errors/functions-2-alpha.txt +3 -0
  113. package/test/less-bom/errors/functions-3-assignment.less +2 -0
  114. package/test/less-bom/errors/functions-3-assignment.txt +3 -0
  115. package/test/less-bom/errors/functions-4-call.less +2 -0
  116. package/test/less-bom/errors/functions-4-call.txt +3 -0
  117. package/test/less-bom/errors/functions-5-color-2.less +1 -0
  118. package/test/less-bom/errors/functions-5-color-2.txt +2 -0
  119. package/test/less-bom/errors/functions-5-color.less +2 -0
  120. package/test/less-bom/errors/functions-5-color.txt +3 -0
  121. package/test/less-bom/errors/functions-6-condition.less +2 -0
  122. package/test/less-bom/errors/functions-6-condition.txt +3 -0
  123. package/test/less-bom/errors/functions-7-dimension.less +2 -0
  124. package/test/less-bom/errors/functions-7-dimension.txt +3 -0
  125. package/test/less-bom/errors/functions-8-element.less +2 -0
  126. package/test/less-bom/errors/functions-8-element.txt +3 -0
  127. package/test/less-bom/errors/functions-9-expression.less +2 -0
  128. package/test/less-bom/errors/functions-9-expression.txt +3 -0
  129. package/test/less-bom/errors/property-in-root.txt +1 -1
  130. package/test/less-bom/errors/property-in-root2.txt +1 -1
  131. package/test/less-bom/errors/property-in-root3.txt +1 -1
  132. package/test/less-bom/errors/root-func-undefined-1.less +1 -0
  133. package/test/less-bom/errors/root-func-undefined-1.txt +2 -0
  134. package/test/less-bom/errors/root-func-undefined-2.less +2 -0
  135. package/test/less-bom/errors/root-func-undefined-2.txt +3 -0
  136. package/test/less-bom/extend-chaining.less +1 -1
  137. package/test/less-bom/merge.less +4 -4
  138. package/test/less-bom/mixins-guards.less +1 -1
  139. package/test/less-bom/no-strict-math/mixins-guards.less +25 -0
  140. package/test/less-bom/no-strict-math/no-sm-operations.less +4 -1
  141. package/test/less-bom/operations.less +1 -1
  142. package/test/less-bom/plugin/plugin-tree-nodes.js +80 -0
  143. package/test/less-bom/plugin.less +8 -0
  144. package/test/sourcemaps/maps/import-map.map +1 -0
package/dist/less.js CHANGED
@@ -1,13 +1,13 @@
1
1
  /*!
2
- * Less - Leaner CSS v2.6.0
2
+ * Less - Leaner CSS v2.7.2
3
3
  * http://lesscss.org
4
4
  *
5
- * Copyright (c) 2009-2016, Alexis Sellier <self@cloudhead.net>
6
- * Licensed under the License.
5
+ * Copyright (c) 2009-2017, Alexis Sellier <self@cloudhead.net>
6
+ * Licensed under the Apache-2.0 License.
7
7
  *
8
8
  */
9
9
 
10
- /** * @license
10
+ /** * @license Apache-2.0
11
11
  */
12
12
 
13
13
  (function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.less = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
@@ -328,16 +328,6 @@ module.exports = function(window, less, options) {
328
328
  }
329
329
  }
330
330
 
331
- function error(e, rootHref) {
332
- if (!options.errorReporting || options.errorReporting === "html") {
333
- errorHTML(e, rootHref);
334
- } else if (options.errorReporting === "console") {
335
- errorConsole(e, rootHref);
336
- } else if (typeof options.errorReporting === 'function') {
337
- options.errorReporting("add", e, rootHref);
338
- }
339
- }
340
-
341
331
  function removeErrorHTML(path) {
342
332
  var node = window.document.getElementById('less-error-message:' + utils.extractId(path));
343
333
  if (node) {
@@ -387,6 +377,16 @@ module.exports = function(window, less, options) {
387
377
  less.logger.error(content);
388
378
  }
389
379
 
380
+ function error(e, rootHref) {
381
+ if (!options.errorReporting || options.errorReporting === "html") {
382
+ errorHTML(e, rootHref);
383
+ } else if (options.errorReporting === "console") {
384
+ errorConsole(e, rootHref);
385
+ } else if (typeof options.errorReporting === 'function') {
386
+ options.errorReporting("add", e, rootHref);
387
+ }
388
+ }
389
+
390
390
  return {
391
391
  add: error,
392
392
  remove: removeError
@@ -772,34 +772,57 @@ module.exports = function(window, options) {
772
772
  fileManager.clearFileCache();
773
773
  }
774
774
  return new Promise(function (resolve, reject) {
775
- var startTime, endTime, totalMilliseconds;
775
+ var startTime, endTime, totalMilliseconds, remainingSheets;
776
776
  startTime = endTime = new Date();
777
777
 
778
- loadStyleSheets(function (e, css, _, sheet, webInfo) {
779
- if (e) {
780
- errors.add(e, e.href || sheet.href);
781
- reject(e);
782
- return;
783
- }
784
- if (webInfo.local) {
785
- less.logger.info("loading " + sheet.href + " from cache.");
786
- } else {
787
- less.logger.info("rendered " + sheet.href + " successfully.");
788
- }
789
- browser.createCSS(window.document, css, sheet);
790
- less.logger.info("css for " + sheet.href + " generated in " + (new Date() - endTime) + 'ms');
791
- if (webInfo.remaining === 0) {
792
- totalMilliseconds = new Date() - startTime;
793
- less.logger.info("less has finished. css generated in " + totalMilliseconds + 'ms');
794
- resolve({
795
- startTime: startTime,
796
- endTime: endTime,
797
- totalMilliseconds: totalMilliseconds,
798
- sheets: less.sheets.length
799
- });
800
- }
778
+ // Set counter for remaining unprocessed sheets
779
+ remainingSheets = less.sheets.length;
780
+
781
+ if (remainingSheets === 0) {
782
+
801
783
  endTime = new Date();
802
- }, reload, modifyVars);
784
+ totalMilliseconds = endTime - startTime;
785
+ less.logger.info("Less has finished and no sheets were loaded.");
786
+ resolve({
787
+ startTime: startTime,
788
+ endTime: endTime,
789
+ totalMilliseconds: totalMilliseconds,
790
+ sheets: less.sheets.length
791
+ });
792
+
793
+ } else {
794
+ // Relies on less.sheets array, callback seems to be guaranteed to be called for every element of the array
795
+ loadStyleSheets(function (e, css, _, sheet, webInfo) {
796
+ if (e) {
797
+ errors.add(e, e.href || sheet.href);
798
+ reject(e);
799
+ return;
800
+ }
801
+ if (webInfo.local) {
802
+ less.logger.info("Loading " + sheet.href + " from cache.");
803
+ } else {
804
+ less.logger.info("Rendered " + sheet.href + " successfully.");
805
+ }
806
+ browser.createCSS(window.document, css, sheet);
807
+ less.logger.info("CSS for " + sheet.href + " generated in " + (new Date() - endTime) + 'ms');
808
+
809
+ // Count completed sheet
810
+ remainingSheets--;
811
+
812
+ // Check if the last remaining sheet was processed and then call the promise
813
+ if (remainingSheets === 0) {
814
+ totalMilliseconds = new Date() - startTime;
815
+ less.logger.info("Less has finished. CSS generated in " + totalMilliseconds + 'ms');
816
+ resolve({
817
+ startTime: startTime,
818
+ endTime: endTime,
819
+ totalMilliseconds: totalMilliseconds,
820
+ sheets: less.sheets.length
821
+ });
822
+ }
823
+ endTime = new Date();
824
+ }, reload, modifyVars);
825
+ }
803
826
 
804
827
  loadStyles(modifyVars);
805
828
  });
@@ -1242,13 +1265,13 @@ abstractFileManager.prototype.pathDiff = function pathDiff(url, baseUrl) {
1242
1265
  };
1243
1266
  // helper function, not part of API
1244
1267
  abstractFileManager.prototype.extractUrlParts = function extractUrlParts(url, baseUrl) {
1245
- // urlParts[1] = protocol&hostname || /
1268
+ // urlParts[1] = protocol://hostname/ OR /
1246
1269
  // urlParts[2] = / if path relative to host base
1247
1270
  // urlParts[3] = directories
1248
1271
  // urlParts[4] = filename
1249
1272
  // urlParts[5] = parameters
1250
1273
 
1251
- var urlPartsRegex = /^((?:[a-z-]+:)?\/+?(?:[^\/\?#]*\/)|([\/\\]))?((?:[^\/\\\?#]*[\/\\])*)([^\/\\\?#]*)([#\?].*)?$/i,
1274
+ var urlPartsRegex = /^((?:[a-z-]+:)?\/{2}(?:[^\/\?#]*\/)|([\/\\]))?((?:[^\/\\\?#]*[\/\\])*)([^\/\\\?#]*)([#\?].*)?$/i,
1252
1275
  urlParts = url.match(urlPartsRegex),
1253
1276
  returner = {}, directories = [], i, baseUrlParts;
1254
1277
 
@@ -1472,6 +1495,9 @@ colorFunctions = {
1472
1495
  return colorFunctions.hsla(h, s, l, 1.0);
1473
1496
  },
1474
1497
  hsla: function (h, s, l, a) {
1498
+
1499
+ var m1, m2;
1500
+
1475
1501
  function hue(h) {
1476
1502
  h = h < 0 ? h + 1 : (h > 1 ? h - 1 : h);
1477
1503
  if (h * 6 < 1) {
@@ -1491,8 +1517,8 @@ colorFunctions = {
1491
1517
  h = (number(h) % 360) / 360;
1492
1518
  s = clamp(number(s)); l = clamp(number(l)); a = clamp(number(a));
1493
1519
 
1494
- var m2 = l <= 0.5 ? l * (s + 1) : l + s - l * s;
1495
- var m1 = l * 2 - m2;
1520
+ m2 = l <= 0.5 ? l * (s + 1) : l + s - l * s;
1521
+ m1 = l * 2 - m2;
1496
1522
 
1497
1523
  return colorFunctions.rgba(hue(h + 1 / 3) * 255,
1498
1524
  hue(h) * 255,
@@ -1663,7 +1689,7 @@ colorFunctions = {
1663
1689
  return hsla(hsl);
1664
1690
  },
1665
1691
  //
1666
- // Copyright (c) 2006-2009 Hampton Catlin, Nathan Weizenbaum, and Chris Eppstein
1692
+ // Copyright (c) 2006-2009 Hampton Catlin, Natalie Weizenbaum, and Chris Eppstein
1667
1693
  // http://sass-lang.com
1668
1694
  //
1669
1695
  mix: function (color1, color2, weight) {
@@ -2451,7 +2477,7 @@ module.exports = function(environment, fileManagers) {
2451
2477
  var SourceMapOutput, SourceMapBuilder, ParseTree, ImportManager, Environment;
2452
2478
 
2453
2479
  var less = {
2454
- version: [2, 6, 0],
2480
+ version: [2, 7, 2],
2455
2481
  data: require('./data'),
2456
2482
  tree: require('./tree'),
2457
2483
  Environment: (Environment = require("./environment/environment")),
@@ -2817,6 +2843,74 @@ module.exports = function() {
2817
2843
  currentPos, // index of current chunk, in `input`
2818
2844
  parserInput = {};
2819
2845
 
2846
+ var CHARCODE_SPACE = 32,
2847
+ CHARCODE_TAB = 9,
2848
+ CHARCODE_LF = 10,
2849
+ CHARCODE_CR = 13,
2850
+ CHARCODE_PLUS = 43,
2851
+ CHARCODE_COMMA = 44,
2852
+ CHARCODE_FORWARD_SLASH = 47,
2853
+ CHARCODE_9 = 57;
2854
+
2855
+ function skipWhitespace(length) {
2856
+ var oldi = parserInput.i, oldj = j,
2857
+ curr = parserInput.i - currentPos,
2858
+ endIndex = parserInput.i + current.length - curr,
2859
+ mem = (parserInput.i += length),
2860
+ inp = input,
2861
+ c, nextChar, comment;
2862
+
2863
+ for (; parserInput.i < endIndex; parserInput.i++) {
2864
+ c = inp.charCodeAt(parserInput.i);
2865
+
2866
+ if (parserInput.autoCommentAbsorb && c === CHARCODE_FORWARD_SLASH) {
2867
+ nextChar = inp.charAt(parserInput.i + 1);
2868
+ if (nextChar === '/') {
2869
+ comment = {index: parserInput.i, isLineComment: true};
2870
+ var nextNewLine = inp.indexOf("\n", parserInput.i + 2);
2871
+ if (nextNewLine < 0) {
2872
+ nextNewLine = endIndex;
2873
+ }
2874
+ parserInput.i = nextNewLine;
2875
+ comment.text = inp.substr(comment.index, parserInput.i - comment.index);
2876
+ parserInput.commentStore.push(comment);
2877
+ continue;
2878
+ } else if (nextChar === '*') {
2879
+ var nextStarSlash = inp.indexOf("*/", parserInput.i + 2);
2880
+ if (nextStarSlash >= 0) {
2881
+ comment = {
2882
+ index: parserInput.i,
2883
+ text: inp.substr(parserInput.i, nextStarSlash + 2 - parserInput.i),
2884
+ isLineComment: false
2885
+ };
2886
+ parserInput.i += comment.text.length - 1;
2887
+ parserInput.commentStore.push(comment);
2888
+ continue;
2889
+ }
2890
+ }
2891
+ break;
2892
+ }
2893
+
2894
+ if ((c !== CHARCODE_SPACE) && (c !== CHARCODE_LF) && (c !== CHARCODE_TAB) && (c !== CHARCODE_CR)) {
2895
+ break;
2896
+ }
2897
+ }
2898
+
2899
+ current = current.slice(length + parserInput.i - mem + curr);
2900
+ currentPos = parserInput.i;
2901
+
2902
+ if (!current.length) {
2903
+ if (j < chunks.length - 1) {
2904
+ current = chunks[++j];
2905
+ skipWhitespace(0); // skip space at the beginning of a chunk
2906
+ return true; // things changed
2907
+ }
2908
+ parserInput.finished = true;
2909
+ }
2910
+
2911
+ return oldi !== parserInput.i || oldj !== j;
2912
+ }
2913
+
2820
2914
  parserInput.save = function() {
2821
2915
  currentPos = parserInput.i;
2822
2916
  saveStack.push( { current: current, i: parserInput.i, j: j });
@@ -2911,78 +3005,10 @@ module.exports = function() {
2911
3005
  return null;
2912
3006
  };
2913
3007
 
2914
- var CHARCODE_SPACE = 32,
2915
- CHARCODE_TAB = 9,
2916
- CHARCODE_LF = 10,
2917
- CHARCODE_CR = 13,
2918
- CHARCODE_PLUS = 43,
2919
- CHARCODE_COMMA = 44,
2920
- CHARCODE_FORWARD_SLASH = 47,
2921
- CHARCODE_9 = 57;
2922
-
2923
3008
  parserInput.autoCommentAbsorb = true;
2924
3009
  parserInput.commentStore = [];
2925
3010
  parserInput.finished = false;
2926
3011
 
2927
- var skipWhitespace = function(length) {
2928
- var oldi = parserInput.i, oldj = j,
2929
- curr = parserInput.i - currentPos,
2930
- endIndex = parserInput.i + current.length - curr,
2931
- mem = (parserInput.i += length),
2932
- inp = input,
2933
- c, nextChar, comment;
2934
-
2935
- for (; parserInput.i < endIndex; parserInput.i++) {
2936
- c = inp.charCodeAt(parserInput.i);
2937
-
2938
- if (parserInput.autoCommentAbsorb && c === CHARCODE_FORWARD_SLASH) {
2939
- nextChar = inp.charAt(parserInput.i + 1);
2940
- if (nextChar === '/') {
2941
- comment = {index: parserInput.i, isLineComment: true};
2942
- var nextNewLine = inp.indexOf("\n", parserInput.i + 2);
2943
- if (nextNewLine < 0) {
2944
- nextNewLine = endIndex;
2945
- }
2946
- parserInput.i = nextNewLine;
2947
- comment.text = inp.substr(comment.i, parserInput.i - comment.i);
2948
- parserInput.commentStore.push(comment);
2949
- continue;
2950
- } else if (nextChar === '*') {
2951
- var nextStarSlash = inp.indexOf("*/", parserInput.i + 2);
2952
- if (nextStarSlash >= 0) {
2953
- comment = {
2954
- index: parserInput.i,
2955
- text: inp.substr(parserInput.i, nextStarSlash + 2 - parserInput.i),
2956
- isLineComment: false
2957
- };
2958
- parserInput.i += comment.text.length - 1;
2959
- parserInput.commentStore.push(comment);
2960
- continue;
2961
- }
2962
- }
2963
- break;
2964
- }
2965
-
2966
- if ((c !== CHARCODE_SPACE) && (c !== CHARCODE_LF) && (c !== CHARCODE_TAB) && (c !== CHARCODE_CR)) {
2967
- break;
2968
- }
2969
- }
2970
-
2971
- current = current.slice(length + parserInput.i - mem + curr);
2972
- currentPos = parserInput.i;
2973
-
2974
- if (!current.length) {
2975
- if (j < chunks.length - 1) {
2976
- current = chunks[++j];
2977
- skipWhitespace(0); // skip space at the beginning of a chunk
2978
- return true; // things changed
2979
- }
2980
- parserInput.finished = true;
2981
- }
2982
-
2983
- return oldi !== parserInput.i || oldj !== j;
2984
- };
2985
-
2986
3012
  // Same as $(), but don't change the state of the parser,
2987
3013
  // just return the match.
2988
3014
  parserInput.peek = function(tok) {
@@ -3023,7 +3049,7 @@ module.exports = function() {
3023
3049
  input = str;
3024
3050
  parserInput.i = j = currentPos = furthest = 0;
3025
3051
 
3026
- // chunking apparantly makes things quicker (but my tests indicate
3052
+ // chunking apparently makes things quicker (but my tests indicate
3027
3053
  // it might actually make things slower in node at least)
3028
3054
  // and it is a non-perfect parse - it can't recognise
3029
3055
  // unquoted urls, meaning it can't distinguish comments
@@ -3108,9 +3134,21 @@ var Parser = function Parser(context, imports, fileInfo) {
3108
3134
  var parsers,
3109
3135
  parserInput = getParserInput();
3110
3136
 
3137
+ function error(msg, type) {
3138
+ throw new LessError(
3139
+ {
3140
+ index: parserInput.i,
3141
+ filename: fileInfo.filename,
3142
+ type: type || 'Syntax',
3143
+ message: msg
3144
+ },
3145
+ imports
3146
+ );
3147
+ }
3148
+
3111
3149
  function expect(arg, msg, index) {
3112
3150
  // some older browsers return typeof 'function' for RegExp
3113
- var result = (Object.prototype.toString.call(arg) === '[object Function]') ? arg.call(parsers) : parserInput.$re(arg);
3151
+ var result = (arg instanceof Function) ? arg.call(parsers) : parserInput.$re(arg);
3114
3152
  if (result) {
3115
3153
  return result;
3116
3154
  }
@@ -3126,18 +3164,6 @@ var Parser = function Parser(context, imports, fileInfo) {
3126
3164
  error(msg || "expected '" + arg + "' got '" + parserInput.currentChar() + "'");
3127
3165
  }
3128
3166
 
3129
- function error(msg, type) {
3130
- throw new LessError(
3131
- {
3132
- index: parserInput.i,
3133
- filename: fileInfo.filename,
3134
- type: type || 'Syntax',
3135
- message: msg
3136
- },
3137
- imports
3138
- );
3139
- }
3140
-
3141
3167
  function getDebugInfo(index) {
3142
3168
  var filename = fileInfo.filename;
3143
3169
 
@@ -3328,7 +3354,7 @@ var Parser = function Parser(context, imports, fileInfo) {
3328
3354
  }
3329
3355
 
3330
3356
  node = mixin.definition() || this.rule() || this.ruleset() ||
3331
- mixin.call() || this.rulesetCall() || this.directive();
3357
+ mixin.call() || this.rulesetCall() || this.entities.call() || this.directive();
3332
3358
  if (node) {
3333
3359
  root.push(node);
3334
3360
  } else {
@@ -3392,26 +3418,6 @@ var Parser = function Parser(context, imports, fileInfo) {
3392
3418
  }
3393
3419
  },
3394
3420
 
3395
- namedColor: function () {
3396
- parserInput.save();
3397
- var autoCommentAbsorb = parserInput.autoCommentAbsorb;
3398
- parserInput.autoCommentAbsorb = false;
3399
- var k = parserInput.$re(/^[_A-Za-z-][_A-Za-z0-9-]*/);
3400
- parserInput.autoCommentAbsorb = autoCommentAbsorb;
3401
- if (!k) {
3402
- parserInput.forget();
3403
- return ;
3404
- }
3405
- var result = tree.Color.fromKeyword(k);
3406
- if (!result) {
3407
- parserInput.restore();
3408
- } else {
3409
- parserInput.forget();
3410
- return result;
3411
- }
3412
-
3413
- },
3414
-
3415
3421
  //
3416
3422
  // A function call
3417
3423
  //
@@ -3457,19 +3463,51 @@ var Parser = function Parser(context, imports, fileInfo) {
3457
3463
  return new(tree.Call)(name, args, index, fileInfo);
3458
3464
  },
3459
3465
  arguments: function () {
3460
- var args = [], arg;
3466
+ var argsSemiColon = [], argsComma = [],
3467
+ expressions = [],
3468
+ isSemiColonSeparated, value, arg;
3469
+
3470
+ parserInput.save();
3461
3471
 
3462
3472
  while (true) {
3463
- arg = this.assignment() || parsers.expression();
3473
+
3474
+ arg = parsers.detachedRuleset() || this.assignment() || parsers.expression();
3475
+
3464
3476
  if (!arg) {
3465
3477
  break;
3466
3478
  }
3467
- args.push(arg);
3468
- if (! parserInput.$char(',')) {
3469
- break;
3479
+
3480
+ value = arg;
3481
+
3482
+ if (arg.value && arg.value.length == 1) {
3483
+ value = arg.value[0];
3484
+ }
3485
+
3486
+ if (value) {
3487
+ expressions.push(value);
3488
+ }
3489
+
3490
+ argsComma.push(value);
3491
+
3492
+ if (parserInput.$char(',')) {
3493
+ continue;
3494
+ }
3495
+
3496
+ if (parserInput.$char(';') || isSemiColonSeparated) {
3497
+
3498
+ isSemiColonSeparated = true;
3499
+
3500
+ if (expressions.length > 1) {
3501
+ value = new(tree.Value)(expressions);
3502
+ }
3503
+ argsSemiColon.push(value);
3504
+
3505
+ expressions = [];
3470
3506
  }
3471
3507
  }
3472
- return args;
3508
+
3509
+ parserInput.forget();
3510
+ return isSemiColonSeparated ? argsSemiColon : argsComma;
3473
3511
  },
3474
3512
  literal: function () {
3475
3513
  return this.dimension() ||
@@ -3549,7 +3587,7 @@ var Parser = function Parser(context, imports, fileInfo) {
3549
3587
  }
3550
3588
  },
3551
3589
 
3552
- // A variable entity useing the protective {} e.g. @{var}
3590
+ // A variable entity using the protective {} e.g. @{var}
3553
3591
  variableCurly: function () {
3554
3592
  var curly, index = parserInput.i;
3555
3593
 
@@ -3578,8 +3616,24 @@ var Parser = function Parser(context, imports, fileInfo) {
3578
3616
  }
3579
3617
  return new(tree.Color)(rgb[1], undefined, '#' + colorCandidateString);
3580
3618
  }
3619
+ },
3581
3620
 
3582
- return this.namedColor();
3621
+ colorKeyword: function () {
3622
+ parserInput.save();
3623
+ var autoCommentAbsorb = parserInput.autoCommentAbsorb;
3624
+ parserInput.autoCommentAbsorb = false;
3625
+ var k = parserInput.$re(/^[_A-Za-z-][_A-Za-z0-9-]+/);
3626
+ parserInput.autoCommentAbsorb = autoCommentAbsorb;
3627
+ if (!k) {
3628
+ parserInput.forget();
3629
+ return;
3630
+ }
3631
+ parserInput.restore();
3632
+ var color = tree.Color.fromKeyword(k);
3633
+ if (color) {
3634
+ parserInput.$str(k);
3635
+ return color;
3636
+ }
3583
3637
  },
3584
3638
 
3585
3639
  //
@@ -3658,7 +3712,7 @@ var Parser = function Parser(context, imports, fileInfo) {
3658
3712
  rulesetCall: function () {
3659
3713
  var name;
3660
3714
 
3661
- if (parserInput.currentChar() === '@' && (name = parserInput.$re(/^(@[\w-]+)\s*\(\s*\)\s*;/))) {
3715
+ if (parserInput.currentChar() === '@' && (name = parserInput.$re(/^(@[\w-]+)\(\s*\)\s*;/))) {
3662
3716
  return new tree.RulesetCall(name[1]);
3663
3717
  }
3664
3718
  },
@@ -3970,7 +4024,7 @@ var Parser = function Parser(context, imports, fileInfo) {
3970
4024
  //
3971
4025
  // A Rule terminator. Note that we use `peek()` to check for '}',
3972
4026
  // because the `block` rule will be expecting it, but we still need to make sure
3973
- // it's there, if ';' was ommitted.
4027
+ // it's there, if ';' was omitted.
3974
4028
  //
3975
4029
  end: function () {
3976
4030
  return parserInput.$char(';') || parserInput.peek('}');
@@ -4392,10 +4446,10 @@ var Parser = function Parser(context, imports, fileInfo) {
4392
4446
  },
4393
4447
 
4394
4448
  media: function () {
4395
- var features, rules, media, debugInfo;
4449
+ var features, rules, media, debugInfo, index = parserInput.i;
4396
4450
 
4397
4451
  if (context.dumpLineNumbers) {
4398
- debugInfo = getDebugInfo(parserInput.i);
4452
+ debugInfo = getDebugInfo(index);
4399
4453
  }
4400
4454
 
4401
4455
  parserInput.save();
@@ -4411,7 +4465,7 @@ var Parser = function Parser(context, imports, fileInfo) {
4411
4465
 
4412
4466
  parserInput.forget();
4413
4467
 
4414
- media = new(tree.Media)(rules, features, parserInput.i, fileInfo);
4468
+ media = new(tree.Media)(rules, features, index, fileInfo);
4415
4469
  if (context.dumpLineNumbers) {
4416
4470
  media.debugInfo = debugInfo;
4417
4471
  }
@@ -4711,12 +4765,44 @@ var Parser = function Parser(context, imports, fileInfo) {
4711
4765
  }
4712
4766
  },
4713
4767
  parenthesisCondition: function () {
4714
- var body;
4715
- if (!parserInput.$str("(")) {
4716
- return ;
4768
+ function tryConditionFollowedByParenthesis(me) {
4769
+ var body;
4770
+ parserInput.save();
4771
+ body = me.condition();
4772
+ if (!body) {
4773
+ parserInput.restore();
4774
+ return ;
4775
+ }
4776
+ if (!parserInput.$char(')')) {
4777
+ parserInput.restore();
4778
+ return ;
4779
+ }
4780
+ parserInput.forget();
4781
+ return body;
4717
4782
  }
4718
- body = this.condition() || this.atomicCondition();
4719
- expectChar(')');
4783
+
4784
+ var body;
4785
+ parserInput.save();
4786
+ if (!parserInput.$str("(")) {
4787
+ parserInput.restore();
4788
+ return ;
4789
+ }
4790
+ body = tryConditionFollowedByParenthesis(this);
4791
+ if (body) {
4792
+ parserInput.forget();
4793
+ return body;
4794
+ }
4795
+
4796
+ body = this.atomicCondition();
4797
+ if (!body) {
4798
+ parserInput.restore();
4799
+ return ;
4800
+ }
4801
+ if (!parserInput.$char(')')) {
4802
+ parserInput.restore("expected ')' got '" + parserInput.currentChar() + "'");
4803
+ return ;
4804
+ }
4805
+ parserInput.forget();
4720
4806
  return body;
4721
4807
  },
4722
4808
  atomicCondition: function () {
@@ -4773,8 +4859,8 @@ var Parser = function Parser(context, imports, fileInfo) {
4773
4859
  }
4774
4860
 
4775
4861
  var o = this.sub() || entities.dimension() ||
4776
- entities.variable() ||
4777
- entities.call() || entities.color();
4862
+ entities.color() || entities.variable() ||
4863
+ entities.call() || entities.colorKeyword();
4778
4864
 
4779
4865
  if (negate) {
4780
4866
  o.parensInOp = true;
@@ -5411,7 +5497,7 @@ var Anonymous = function (value, index, currentFileInfo, mapLines, rulesetLike,
5411
5497
  this.mapLines = mapLines;
5412
5498
  this.currentFileInfo = currentFileInfo;
5413
5499
  this.rulesetLike = (typeof rulesetLike === 'undefined') ? false : rulesetLike;
5414
-
5500
+ this.allowRoot = true;
5415
5501
  this.copyVisibilityInfo(visibilityInfo);
5416
5502
  };
5417
5503
  Anonymous.prototype = new Node();
@@ -5522,18 +5608,21 @@ Call.prototype.eval = function (context) {
5522
5608
  var args = this.args.map(function (a) { return a.eval(context); }),
5523
5609
  result, funcCaller = new FunctionCaller(this.name, context, this.index, this.currentFileInfo);
5524
5610
 
5525
- if (funcCaller.isValid()) { // 1.
5611
+ if (funcCaller.isValid()) {
5526
5612
  try {
5527
5613
  result = funcCaller.call(args);
5528
- if (result != null) {
5529
- return result;
5530
- }
5531
5614
  } catch (e) {
5532
5615
  throw { type: e.type || "Runtime",
5533
5616
  message: "error evaluating function `" + this.name + "`" +
5534
5617
  (e.message ? ': ' + e.message : ''),
5535
5618
  index: this.index, filename: this.currentFileInfo.filename };
5536
5619
  }
5620
+
5621
+ if (result != null) {
5622
+ result.index = this.index;
5623
+ result.currentFileInfo = this.currentFileInfo;
5624
+ return result;
5625
+ }
5537
5626
  }
5538
5627
 
5539
5628
  return new Call(this.name, args, this.index, this.currentFileInfo);
@@ -5775,7 +5864,9 @@ var Node = require("./node"),
5775
5864
  var Comment = function (value, isLineComment, index, currentFileInfo) {
5776
5865
  this.value = value;
5777
5866
  this.isLineComment = isLineComment;
5867
+ this.index = index;
5778
5868
  this.currentFileInfo = currentFileInfo;
5869
+ this.allowRoot = true;
5779
5870
  };
5780
5871
  Comment.prototype = new Node();
5781
5872
  Comment.prototype.type = "Comment";
@@ -6078,6 +6169,7 @@ var Directive = function (name, value, rules, index, currentFileInfo, debugInfo,
6078
6169
  this.debugInfo = debugInfo;
6079
6170
  this.isRooted = isRooted || false;
6080
6171
  this.copyVisibilityInfo(visibilityInfo);
6172
+ this.allowRoot = true;
6081
6173
  };
6082
6174
 
6083
6175
  Directive.prototype = new Node();
@@ -6319,6 +6411,7 @@ var Extend = function Extend(selector, option, index, currentFileInfo, visibilit
6319
6411
  this.parent_ids = [this.object_id];
6320
6412
  this.currentFileInfo = currentFileInfo || {};
6321
6413
  this.copyVisibilityInfo(visibilityInfo);
6414
+ this.allowRoot = true;
6322
6415
 
6323
6416
  switch(option) {
6324
6417
  case "all":
@@ -6391,6 +6484,7 @@ var Import = function (path, features, options, index, currentFileInfo, visibili
6391
6484
  this.path = path;
6392
6485
  this.features = features;
6393
6486
  this.currentFileInfo = currentFileInfo;
6487
+ this.allowRoot = true;
6394
6488
 
6395
6489
  if (this.options.less !== undefined || this.options.inline) {
6396
6490
  this.css = !this.options.less || this.options.inline;
@@ -6702,6 +6796,7 @@ var Media = function (value, features, index, currentFileInfo, visibilityInfo) {
6702
6796
  this.rules = [new Ruleset(selectors, value)];
6703
6797
  this.rules[0].allowImports = true;
6704
6798
  this.copyVisibilityInfo(visibilityInfo);
6799
+ this.allowRoot = true;
6705
6800
  };
6706
6801
  Media.prototype = new Directive();
6707
6802
  Media.prototype.type = "Media";
@@ -6842,6 +6937,7 @@ var MixinCall = function (elements, args, index, currentFileInfo, important) {
6842
6937
  this.index = index;
6843
6938
  this.currentFileInfo = currentFileInfo;
6844
6939
  this.important = important;
6940
+ this.allowRoot = true;
6845
6941
  };
6846
6942
  MixinCall.prototype = new Node();
6847
6943
  MixinCall.prototype.type = "MixinCall";
@@ -7044,6 +7140,7 @@ var Definition = function (name, params, rules, condition, variadic, frames, vis
7044
7140
  this.optionalParameters = optionalParameters;
7045
7141
  this.frames = frames;
7046
7142
  this.copyVisibilityInfo(visibilityInfo);
7143
+ this.allowRoot = true;
7047
7144
  };
7048
7145
  Definition.prototype = new Ruleset();
7049
7146
  Definition.prototype.type = "MixinDefinition";
@@ -7144,7 +7241,7 @@ Definition.prototype.makeImportant = function() {
7144
7241
  return r;
7145
7242
  }
7146
7243
  });
7147
- var result = new Definition (this.name, this.params, rules, this.condition, this.variadic, this.frames);
7244
+ var result = new Definition(this.name, this.params, rules, this.condition, this.variadic, this.frames);
7148
7245
  return result;
7149
7246
  };
7150
7247
  Definition.prototype.eval = function (context) {
@@ -7503,6 +7600,7 @@ var Rule = function (name, value, important, merge, index, currentFileInfo, inli
7503
7600
  this.inline = inline || false;
7504
7601
  this.variable = (variable !== undefined) ? variable
7505
7602
  : (name.charAt && (name.charAt(0) === '@'));
7603
+ this.allowRoot = true;
7506
7604
  };
7507
7605
 
7508
7606
  function evalName(context, name) {
@@ -7590,6 +7688,7 @@ var Node = require("./node"),
7590
7688
 
7591
7689
  var RulesetCall = function (variable) {
7592
7690
  this.variable = variable;
7691
+ this.allowRoot = true;
7593
7692
  };
7594
7693
  RulesetCall.prototype = new Node();
7595
7694
  RulesetCall.prototype.type = "RulesetCall";
@@ -7616,6 +7715,7 @@ var Ruleset = function (selectors, rules, strictImports, visibilityInfo) {
7616
7715
  this._lookups = {};
7617
7716
  this.strictImports = strictImports;
7618
7717
  this.copyVisibilityInfo(visibilityInfo);
7718
+ this.allowRoot = true;
7619
7719
  };
7620
7720
  Ruleset.prototype = new Node();
7621
7721
  Ruleset.prototype.type = "Ruleset";
@@ -8065,6 +8165,91 @@ Ruleset.prototype.joinSelector = function (paths, context, selector) {
8065
8165
  return selector;
8066
8166
  }
8067
8167
 
8168
+ // joins selector path from `beginningPath` with selector path in `addPath`
8169
+ // `replacedElement` contains element that is being replaced by `addPath`
8170
+ // returns concatenated path
8171
+ function addReplacementIntoPath(beginningPath, addPath, replacedElement, originalSelector) {
8172
+ var newSelectorPath, lastSelector, newJoinedSelector;
8173
+ // our new selector path
8174
+ newSelectorPath = [];
8175
+
8176
+ //construct the joined selector - if & is the first thing this will be empty,
8177
+ // if not newJoinedSelector will be the last set of elements in the selector
8178
+ if (beginningPath.length > 0) {
8179
+ newSelectorPath = beginningPath.slice(0);
8180
+ lastSelector = newSelectorPath.pop();
8181
+ newJoinedSelector = originalSelector.createDerived(lastSelector.elements.slice(0));
8182
+ }
8183
+ else {
8184
+ newJoinedSelector = originalSelector.createDerived([]);
8185
+ }
8186
+
8187
+ if (addPath.length > 0) {
8188
+ // /deep/ is a combinator that is valid without anything in front of it
8189
+ // so if the & does not have a combinator that is "" or " " then
8190
+ // and there is a combinator on the parent, then grab that.
8191
+ // this also allows + a { & .b { .a & { ... though not sure why you would want to do that
8192
+ var combinator = replacedElement.combinator, parentEl = addPath[0].elements[0];
8193
+ if (combinator.emptyOrWhitespace && !parentEl.combinator.emptyOrWhitespace) {
8194
+ combinator = parentEl.combinator;
8195
+ }
8196
+ // join the elements so far with the first part of the parent
8197
+ newJoinedSelector.elements.push(new Element(combinator, parentEl.value, replacedElement.index, replacedElement.currentFileInfo));
8198
+ newJoinedSelector.elements = newJoinedSelector.elements.concat(addPath[0].elements.slice(1));
8199
+ }
8200
+
8201
+ // now add the joined selector - but only if it is not empty
8202
+ if (newJoinedSelector.elements.length !== 0) {
8203
+ newSelectorPath.push(newJoinedSelector);
8204
+ }
8205
+
8206
+ //put together the parent selectors after the join (e.g. the rest of the parent)
8207
+ if (addPath.length > 1) {
8208
+ var restOfPath = addPath.slice(1);
8209
+ restOfPath = restOfPath.map(function (selector) {
8210
+ return selector.createDerived(selector.elements, []);
8211
+ });
8212
+ newSelectorPath = newSelectorPath.concat(restOfPath);
8213
+ }
8214
+ return newSelectorPath;
8215
+ }
8216
+
8217
+ // joins selector path from `beginningPath` with every selector path in `addPaths` array
8218
+ // `replacedElement` contains element that is being replaced by `addPath`
8219
+ // returns array with all concatenated paths
8220
+ function addAllReplacementsIntoPath( beginningPath, addPaths, replacedElement, originalSelector, result) {
8221
+ var j;
8222
+ for (j = 0; j < beginningPath.length; j++) {
8223
+ var newSelectorPath = addReplacementIntoPath(beginningPath[j], addPaths, replacedElement, originalSelector);
8224
+ result.push(newSelectorPath);
8225
+ }
8226
+ return result;
8227
+ }
8228
+
8229
+ function mergeElementsOnToSelectors(elements, selectors) {
8230
+ var i, sel;
8231
+
8232
+ if (elements.length === 0) {
8233
+ return ;
8234
+ }
8235
+ if (selectors.length === 0) {
8236
+ selectors.push([ new Selector(elements) ]);
8237
+ return;
8238
+ }
8239
+
8240
+ for (i = 0; i < selectors.length; i++) {
8241
+ sel = selectors[i];
8242
+
8243
+ // if the previous thing in sel is a parent this needs to join on to it
8244
+ if (sel.length > 0) {
8245
+ sel[sel.length - 1] = sel[sel.length - 1].createDerived(sel[sel.length - 1].elements.concat(elements));
8246
+ }
8247
+ else {
8248
+ sel.push(new Selector(elements));
8249
+ }
8250
+ }
8251
+ }
8252
+
8068
8253
  // replace all parent selectors inside `inSelector` by content of `context` array
8069
8254
  // resulting selectors are returned inside `paths` array
8070
8255
  // returns true if `inSelector` contained at least one parent selector
@@ -8185,91 +8370,6 @@ Ruleset.prototype.joinSelector = function (paths, context, selector) {
8185
8370
  return hadParentSelector;
8186
8371
  }
8187
8372
 
8188
- // joins selector path from `beginningPath` with selector path in `addPath`
8189
- // `replacedElement` contains element that is being replaced by `addPath`
8190
- // returns concatenated path
8191
- function addReplacementIntoPath(beginningPath, addPath, replacedElement, originalSelector) {
8192
- var newSelectorPath, lastSelector, newJoinedSelector;
8193
- // our new selector path
8194
- newSelectorPath = [];
8195
-
8196
- //construct the joined selector - if & is the first thing this will be empty,
8197
- // if not newJoinedSelector will be the last set of elements in the selector
8198
- if (beginningPath.length > 0) {
8199
- newSelectorPath = beginningPath.slice(0);
8200
- lastSelector = newSelectorPath.pop();
8201
- newJoinedSelector = originalSelector.createDerived(lastSelector.elements.slice(0));
8202
- }
8203
- else {
8204
- newJoinedSelector = originalSelector.createDerived([]);
8205
- }
8206
-
8207
- if (addPath.length > 0) {
8208
- // /deep/ is a combinator that is valid without anything in front of it
8209
- // so if the & does not have a combinator that is "" or " " then
8210
- // and there is a combinator on the parent, then grab that.
8211
- // this also allows + a { & .b { .a & { ... though not sure why you would want to do that
8212
- var combinator = replacedElement.combinator, parentEl = addPath[0].elements[0];
8213
- if (combinator.emptyOrWhitespace && !parentEl.combinator.emptyOrWhitespace) {
8214
- combinator = parentEl.combinator;
8215
- }
8216
- // join the elements so far with the first part of the parent
8217
- newJoinedSelector.elements.push(new Element(combinator, parentEl.value, replacedElement.index, replacedElement.currentFileInfo));
8218
- newJoinedSelector.elements = newJoinedSelector.elements.concat(addPath[0].elements.slice(1));
8219
- }
8220
-
8221
- // now add the joined selector - but only if it is not empty
8222
- if (newJoinedSelector.elements.length !== 0) {
8223
- newSelectorPath.push(newJoinedSelector);
8224
- }
8225
-
8226
- //put together the parent selectors after the join (e.g. the rest of the parent)
8227
- if (addPath.length > 1) {
8228
- var restOfPath = addPath.slice(1);
8229
- restOfPath = restOfPath.map(function (selector) {
8230
- return selector.createDerived(selector.elements, []);
8231
- });
8232
- newSelectorPath = newSelectorPath.concat(restOfPath);
8233
- }
8234
- return newSelectorPath;
8235
- }
8236
-
8237
- // joins selector path from `beginningPath` with every selector path in `addPaths` array
8238
- // `replacedElement` contains element that is being replaced by `addPath`
8239
- // returns array with all concatenated paths
8240
- function addAllReplacementsIntoPath( beginningPath, addPaths, replacedElement, originalSelector, result) {
8241
- var j;
8242
- for (j = 0; j < beginningPath.length; j++) {
8243
- var newSelectorPath = addReplacementIntoPath(beginningPath[j], addPaths, replacedElement, originalSelector);
8244
- result.push(newSelectorPath);
8245
- }
8246
- return result;
8247
- }
8248
-
8249
- function mergeElementsOnToSelectors(elements, selectors) {
8250
- var i, sel;
8251
-
8252
- if (elements.length === 0) {
8253
- return ;
8254
- }
8255
- if (selectors.length === 0) {
8256
- selectors.push([ new Selector(elements) ]);
8257
- return;
8258
- }
8259
-
8260
- for (i = 0; i < selectors.length; i++) {
8261
- sel = selectors[i];
8262
-
8263
- // if the previous thing in sel is a parent this needs to join on to it
8264
- if (sel.length > 0) {
8265
- sel[sel.length - 1] = sel[sel.length - 1].createDerived(sel[sel.length - 1].elements.concat(elements));
8266
- }
8267
- else {
8268
- sel.push(new Selector(elements));
8269
- }
8270
- }
8271
- }
8272
-
8273
8373
  function deriveSelector(visibilityInfo, deriveFrom) {
8274
8374
  var newSelector = deriveFrom.createDerived(deriveFrom.elements, deriveFrom.extendList, deriveFrom.evaldCondition);
8275
8375
  newSelector.copyVisibilityInfo(visibilityInfo);
@@ -8498,7 +8598,7 @@ Unit.prototype.map = function(callback) {
8498
8598
  }
8499
8599
  };
8500
8600
  Unit.prototype.usedUnits = function() {
8501
- var group, result = {}, mapUnit;
8601
+ var group, result = {}, mapUnit, groupName;
8502
8602
 
8503
8603
  mapUnit = function (atomicUnit) {
8504
8604
  /*jshint loopfunc:true */
@@ -8509,7 +8609,7 @@ Unit.prototype.usedUnits = function() {
8509
8609
  return atomicUnit;
8510
8610
  };
8511
8611
 
8512
- for (var groupName in unitConversions) {
8612
+ for (groupName in unitConversions) {
8513
8613
  if (unitConversions.hasOwnProperty(groupName)) {
8514
8614
  group = unitConversions[groupName];
8515
8615
 
@@ -8823,7 +8923,7 @@ var ProcessExtendsVisitor = function() {
8823
8923
  ProcessExtendsVisitor.prototype = {
8824
8924
  run: function(root) {
8825
8925
  var extendFinder = new ExtendFinderVisitor();
8826
- this.extendIndicies = {};
8926
+ this.extendIndices = {};
8827
8927
  extendFinder.run(root);
8828
8928
  if (!extendFinder.foundExtends) { return root; }
8829
8929
  root.allExtends = root.allExtends.concat(this.doExtendChaining(root.allExtends, root.allExtends));
@@ -8833,7 +8933,7 @@ ProcessExtendsVisitor.prototype = {
8833
8933
  return newRoot;
8834
8934
  },
8835
8935
  checkExtendsForNonMatched: function(extendList) {
8836
- var indicies = this.extendIndicies;
8936
+ var indices = this.extendIndices;
8837
8937
  extendList.filter(function(extend) {
8838
8938
  return !extend.hasFoundMatches && extend.parent_ids.length == 1;
8839
8939
  }).forEach(function(extend) {
@@ -8843,8 +8943,8 @@ ProcessExtendsVisitor.prototype = {
8843
8943
  }
8844
8944
  catch(_) {}
8845
8945
 
8846
- if (!indicies[extend.index + ' ' + selector]) {
8847
- indicies[extend.index + ' ' + selector] = true;
8946
+ if (!indices[extend.index + ' ' + selector]) {
8947
+ indices[extend.index + ' ' + selector] = true;
8848
8948
  logger.warn("extend '" + selector + "' has no matches");
8849
8949
  }
8850
8950
  });
@@ -8868,7 +8968,7 @@ ProcessExtendsVisitor.prototype = {
8868
8968
  // a target extend is the one on the ruleset we are looking at copy/edit/pasting in place
8869
8969
  // e.g. .a:extend(.b) {} and .b:extend(.c) {} then the first extend extends the second one
8870
8970
  // and the second is the target.
8871
- // the seperation into two lists allows us to process a subset of chains with a bigger set, as is the
8971
+ // the separation into two lists allows us to process a subset of chains with a bigger set, as is the
8872
8972
  // case when processing media queries
8873
8973
  for (extendIndex = 0; extendIndex < extendsList.length; extendIndex++) {
8874
8974
  for (targetExtendIndex = 0; targetExtendIndex < extendsListTarget.length; targetExtendIndex++) {
@@ -9685,7 +9785,6 @@ ToCSSVisitor.prototype = {
9685
9785
  } else {
9686
9786
  return this.visitDirectiveWithoutBody(directiveNode, visitArgs);
9687
9787
  }
9688
- return directiveNode;
9689
9788
  },
9690
9789
 
9691
9790
  visitDirectiveWithBody: function(directiveNode, visitArgs) {
@@ -9740,13 +9839,24 @@ ToCSSVisitor.prototype = {
9740
9839
  return directiveNode;
9741
9840
  },
9742
9841
 
9743
- checkPropertiesInRoot: function(rules) {
9744
- var ruleNode;
9842
+ checkValidNodes: function(rules, isRoot) {
9843
+ if (!rules) {
9844
+ return;
9845
+ }
9846
+
9745
9847
  for (var i = 0; i < rules.length; i++) {
9746
- ruleNode = rules[i];
9747
- if (ruleNode instanceof tree.Rule && !ruleNode.variable) {
9748
- throw { message: "properties must be inside selector blocks, they cannot be in the root.",
9749
- index: ruleNode.index, filename: ruleNode.currentFileInfo ? ruleNode.currentFileInfo.filename : null};
9848
+ var ruleNode = rules[i];
9849
+ if (isRoot && ruleNode instanceof tree.Rule && !ruleNode.variable) {
9850
+ throw { message: "Properties must be inside selector blocks. They cannot be in the root",
9851
+ index: ruleNode.index, filename: ruleNode.currentFileInfo && ruleNode.currentFileInfo.filename};
9852
+ }
9853
+ if (ruleNode instanceof tree.Call) {
9854
+ throw { message: "Function '" + ruleNode.name + "' is undefined",
9855
+ index: ruleNode.index, filename: ruleNode.currentFileInfo && ruleNode.currentFileInfo.filename};
9856
+ }
9857
+ if (ruleNode.type && !ruleNode.allowRoot) {
9858
+ throw { message: ruleNode.type + " node returned by a function is not valid here",
9859
+ index: ruleNode.index, filename: ruleNode.currentFileInfo && ruleNode.currentFileInfo.filename};
9750
9860
  }
9751
9861
  }
9752
9862
  },
@@ -9754,9 +9864,9 @@ ToCSSVisitor.prototype = {
9754
9864
  visitRuleset: function (rulesetNode, visitArgs) {
9755
9865
  //at this point rulesets are nested into each other
9756
9866
  var rule, rulesets = [];
9757
- if (rulesetNode.firstRoot) {
9758
- this.checkPropertiesInRoot(rulesetNode.rules);
9759
- }
9867
+
9868
+ this.checkValidNodes(rulesetNode.rules, rulesetNode.firstRoot);
9869
+
9760
9870
  if (! rulesetNode.root) {
9761
9871
  //remove invisible paths
9762
9872
  this._compileRulesetPaths(rulesetNode);
@@ -10078,145 +10188,487 @@ Visitor.prototype = {
10078
10188
  module.exports = Visitor;
10079
10189
 
10080
10190
  },{"../tree":62}],92:[function(require,module,exports){
10081
- // shim for using process in browser
10191
+ "use strict";
10082
10192
 
10083
- var process = module.exports = {};
10084
- var queue = [];
10085
- var draining = false;
10193
+ // rawAsap provides everything we need except exception management.
10194
+ var rawAsap = require("./raw");
10195
+ // RawTasks are recycled to reduce GC churn.
10196
+ var freeTasks = [];
10197
+ // We queue errors to ensure they are thrown in right order (FIFO).
10198
+ // Array-as-queue is good enough here, since we are just dealing with exceptions.
10199
+ var pendingErrors = [];
10200
+ var requestErrorThrow = rawAsap.makeRequestCallFromTimer(throwFirstError);
10086
10201
 
10087
- function drainQueue() {
10088
- if (draining) {
10089
- return;
10202
+ function throwFirstError() {
10203
+ if (pendingErrors.length) {
10204
+ throw pendingErrors.shift();
10090
10205
  }
10091
- draining = true;
10092
- var currentQueue;
10093
- var len = queue.length;
10094
- while(len) {
10095
- currentQueue = queue;
10096
- queue = [];
10097
- var i = -1;
10098
- while (++i < len) {
10099
- currentQueue[i]();
10100
- }
10101
- len = queue.length;
10206
+ }
10207
+
10208
+ /**
10209
+ * Calls a task as soon as possible after returning, in its own event, with priority
10210
+ * over other events like animation, reflow, and repaint. An error thrown from an
10211
+ * event will not interrupt, nor even substantially slow down the processing of
10212
+ * other events, but will be rather postponed to a lower priority event.
10213
+ * @param {{call}} task A callable object, typically a function that takes no
10214
+ * arguments.
10215
+ */
10216
+ module.exports = asap;
10217
+ function asap(task) {
10218
+ var rawTask;
10219
+ if (freeTasks.length) {
10220
+ rawTask = freeTasks.pop();
10221
+ } else {
10222
+ rawTask = new RawTask();
10102
10223
  }
10103
- draining = false;
10224
+ rawTask.task = task;
10225
+ rawAsap(rawTask);
10226
+ }
10227
+
10228
+ // We wrap tasks with recyclable task objects. A task object implements
10229
+ // `call`, just like a function.
10230
+ function RawTask() {
10231
+ this.task = null;
10104
10232
  }
10105
- process.nextTick = function (fun) {
10106
- queue.push(fun);
10107
- if (!draining) {
10108
- setTimeout(drainQueue, 0);
10233
+
10234
+ // The sole purpose of wrapping the task is to catch the exception and recycle
10235
+ // the task object after its single use.
10236
+ RawTask.prototype.call = function () {
10237
+ try {
10238
+ this.task.call();
10239
+ } catch (error) {
10240
+ if (asap.onerror) {
10241
+ // This hook exists purely for testing purposes.
10242
+ // Its name will be periodically randomized to break any code that
10243
+ // depends on its existence.
10244
+ asap.onerror(error);
10245
+ } else {
10246
+ // In a web browser, exceptions are not fatal. However, to avoid
10247
+ // slowing down the queue of pending tasks, we rethrow the error in a
10248
+ // lower priority turn.
10249
+ pendingErrors.push(error);
10250
+ requestErrorThrow();
10251
+ }
10252
+ } finally {
10253
+ this.task = null;
10254
+ freeTasks[freeTasks.length] = this;
10109
10255
  }
10110
10256
  };
10111
10257
 
10112
- process.title = 'browser';
10113
- process.browser = true;
10114
- process.env = {};
10115
- process.argv = [];
10116
- process.version = ''; // empty string to avoid regexp issues
10117
- process.versions = {};
10258
+ },{"./raw":93}],93:[function(require,module,exports){
10259
+ (function (global){
10260
+ "use strict";
10118
10261
 
10119
- function noop() {}
10262
+ // Use the fastest means possible to execute a task in its own turn, with
10263
+ // priority over other events including IO, animation, reflow, and redraw
10264
+ // events in browsers.
10265
+ //
10266
+ // An exception thrown by a task will permanently interrupt the processing of
10267
+ // subsequent tasks. The higher level `asap` function ensures that if an
10268
+ // exception is thrown by a task, that the task queue will continue flushing as
10269
+ // soon as possible, but if you use `rawAsap` directly, you are responsible to
10270
+ // either ensure that no exceptions are thrown from your task, or to manually
10271
+ // call `rawAsap.requestFlush` if an exception is thrown.
10272
+ module.exports = rawAsap;
10273
+ function rawAsap(task) {
10274
+ if (!queue.length) {
10275
+ requestFlush();
10276
+ flushing = true;
10277
+ }
10278
+ // Equivalent to push, but avoids a function call.
10279
+ queue[queue.length] = task;
10280
+ }
10281
+
10282
+ var queue = [];
10283
+ // Once a flush has been requested, no further calls to `requestFlush` are
10284
+ // necessary until the next `flush` completes.
10285
+ var flushing = false;
10286
+ // `requestFlush` is an implementation-specific method that attempts to kick
10287
+ // off a `flush` event as quickly as possible. `flush` will attempt to exhaust
10288
+ // the event queue before yielding to the browser's own event loop.
10289
+ var requestFlush;
10290
+ // The position of the next task to execute in the task queue. This is
10291
+ // preserved between calls to `flush` so that it can be resumed if
10292
+ // a task throws an exception.
10293
+ var index = 0;
10294
+ // If a task schedules additional tasks recursively, the task queue can grow
10295
+ // unbounded. To prevent memory exhaustion, the task queue will periodically
10296
+ // truncate already-completed tasks.
10297
+ var capacity = 1024;
10298
+
10299
+ // The flush function processes all tasks that have been scheduled with
10300
+ // `rawAsap` unless and until one of those tasks throws an exception.
10301
+ // If a task throws an exception, `flush` ensures that its state will remain
10302
+ // consistent and will resume where it left off when called again.
10303
+ // However, `flush` does not make any arrangements to be called again if an
10304
+ // exception is thrown.
10305
+ function flush() {
10306
+ while (index < queue.length) {
10307
+ var currentIndex = index;
10308
+ // Advance the index before calling the task. This ensures that we will
10309
+ // begin flushing on the next task the task throws an error.
10310
+ index = index + 1;
10311
+ queue[currentIndex].call();
10312
+ // Prevent leaking memory for long chains of recursive calls to `asap`.
10313
+ // If we call `asap` within tasks scheduled by `asap`, the queue will
10314
+ // grow, but to avoid an O(n) walk for every task we execute, we don't
10315
+ // shift tasks off the queue after they have been executed.
10316
+ // Instead, we periodically shift 1024 tasks off the queue.
10317
+ if (index > capacity) {
10318
+ // Manually shift all values starting at the index back to the
10319
+ // beginning of the queue.
10320
+ for (var scan = 0, newLength = queue.length - index; scan < newLength; scan++) {
10321
+ queue[scan] = queue[scan + index];
10322
+ }
10323
+ queue.length -= index;
10324
+ index = 0;
10325
+ }
10326
+ }
10327
+ queue.length = 0;
10328
+ index = 0;
10329
+ flushing = false;
10330
+ }
10120
10331
 
10121
- process.on = noop;
10122
- process.addListener = noop;
10123
- process.once = noop;
10124
- process.off = noop;
10125
- process.removeListener = noop;
10126
- process.removeAllListeners = noop;
10127
- process.emit = noop;
10332
+ // `requestFlush` is implemented using a strategy based on data collected from
10333
+ // every available SauceLabs Selenium web driver worker at time of writing.
10334
+ // https://docs.google.com/spreadsheets/d/1mG-5UYGup5qxGdEMWkhP6BWCz053NUb2E1QoUTU16uA/edit#gid=783724593
10128
10335
 
10129
- process.binding = function (name) {
10130
- throw new Error('process.binding is not supported');
10131
- };
10336
+ // Safari 6 and 6.1 for desktop, iPad, and iPhone are the only browsers that
10337
+ // have WebKitMutationObserver but not un-prefixed MutationObserver.
10338
+ // Must use `global` instead of `window` to work in both frames and web
10339
+ // workers. `global` is a provision of Browserify, Mr, Mrs, or Mop.
10340
+ var BrowserMutationObserver = global.MutationObserver || global.WebKitMutationObserver;
10132
10341
 
10133
- // TODO(shtylman)
10134
- process.cwd = function () { return '/' };
10135
- process.chdir = function (dir) {
10136
- throw new Error('process.chdir is not supported');
10137
- };
10138
- process.umask = function() { return 0; };
10342
+ // MutationObservers are desirable because they have high priority and work
10343
+ // reliably everywhere they are implemented.
10344
+ // They are implemented in all modern browsers.
10345
+ //
10346
+ // - Android 4-4.3
10347
+ // - Chrome 26-34
10348
+ // - Firefox 14-29
10349
+ // - Internet Explorer 11
10350
+ // - iPad Safari 6-7.1
10351
+ // - iPhone Safari 7-7.1
10352
+ // - Safari 6-7
10353
+ if (typeof BrowserMutationObserver === "function") {
10354
+ requestFlush = makeRequestCallFromMutationObserver(flush);
10355
+
10356
+ // MessageChannels are desirable because they give direct access to the HTML
10357
+ // task queue, are implemented in Internet Explorer 10, Safari 5.0-1, and Opera
10358
+ // 11-12, and in web workers in many engines.
10359
+ // Although message channels yield to any queued rendering and IO tasks, they
10360
+ // would be better than imposing the 4ms delay of timers.
10361
+ // However, they do not work reliably in Internet Explorer or Safari.
10362
+
10363
+ // Internet Explorer 10 is the only browser that has setImmediate but does
10364
+ // not have MutationObservers.
10365
+ // Although setImmediate yields to the browser's renderer, it would be
10366
+ // preferrable to falling back to setTimeout since it does not have
10367
+ // the minimum 4ms penalty.
10368
+ // Unfortunately there appears to be a bug in Internet Explorer 10 Mobile (and
10369
+ // Desktop to a lesser extent) that renders both setImmediate and
10370
+ // MessageChannel useless for the purposes of ASAP.
10371
+ // https://github.com/kriskowal/q/issues/396
10372
+
10373
+ // Timers are implemented universally.
10374
+ // We fall back to timers in workers in most engines, and in foreground
10375
+ // contexts in the following browsers.
10376
+ // However, note that even this simple case requires nuances to operate in a
10377
+ // broad spectrum of browsers.
10378
+ //
10379
+ // - Firefox 3-13
10380
+ // - Internet Explorer 6-9
10381
+ // - iPad Safari 4.3
10382
+ // - Lynx 2.8.7
10383
+ } else {
10384
+ requestFlush = makeRequestCallFromTimer(flush);
10385
+ }
10139
10386
 
10140
- },{}],93:[function(require,module,exports){
10387
+ // `requestFlush` requests that the high priority event queue be flushed as
10388
+ // soon as possible.
10389
+ // This is useful to prevent an error thrown in a task from stalling the event
10390
+ // queue if the exception handled by Node.js’s
10391
+ // `process.on("uncaughtException")` or by a domain.
10392
+ rawAsap.requestFlush = requestFlush;
10393
+
10394
+ // To request a high priority event, we induce a mutation observer by toggling
10395
+ // the text of a text node between "1" and "-1".
10396
+ function makeRequestCallFromMutationObserver(callback) {
10397
+ var toggle = 1;
10398
+ var observer = new BrowserMutationObserver(callback);
10399
+ var node = document.createTextNode("");
10400
+ observer.observe(node, {characterData: true});
10401
+ return function requestCall() {
10402
+ toggle = -toggle;
10403
+ node.data = toggle;
10404
+ };
10405
+ }
10406
+
10407
+ // The message channel technique was discovered by Malte Ubl and was the
10408
+ // original foundation for this library.
10409
+ // http://www.nonblocking.io/2011/06/windownexttick.html
10410
+
10411
+ // Safari 6.0.5 (at least) intermittently fails to create message ports on a
10412
+ // page's first load. Thankfully, this version of Safari supports
10413
+ // MutationObservers, so we don't need to fall back in that case.
10414
+
10415
+ // function makeRequestCallFromMessageChannel(callback) {
10416
+ // var channel = new MessageChannel();
10417
+ // channel.port1.onmessage = callback;
10418
+ // return function requestCall() {
10419
+ // channel.port2.postMessage(0);
10420
+ // };
10421
+ // }
10422
+
10423
+ // For reasons explained above, we are also unable to use `setImmediate`
10424
+ // under any circumstances.
10425
+ // Even if we were, there is another bug in Internet Explorer 10.
10426
+ // It is not sufficient to assign `setImmediate` to `requestFlush` because
10427
+ // `setImmediate` must be called *by name* and therefore must be wrapped in a
10428
+ // closure.
10429
+ // Never forget.
10430
+
10431
+ // function makeRequestCallFromSetImmediate(callback) {
10432
+ // return function requestCall() {
10433
+ // setImmediate(callback);
10434
+ // };
10435
+ // }
10436
+
10437
+ // Safari 6.0 has a problem where timers will get lost while the user is
10438
+ // scrolling. This problem does not impact ASAP because Safari 6.0 supports
10439
+ // mutation observers, so that implementation is used instead.
10440
+ // However, if we ever elect to use timers in Safari, the prevalent work-around
10441
+ // is to add a scroll event listener that calls for a flush.
10442
+
10443
+ // `setTimeout` does not call the passed callback if the delay is less than
10444
+ // approximately 7 in web workers in Firefox 8 through 18, and sometimes not
10445
+ // even then.
10446
+
10447
+ function makeRequestCallFromTimer(callback) {
10448
+ return function requestCall() {
10449
+ // We dispatch a timeout with a specified delay of 0 for engines that
10450
+ // can reliably accommodate that request. This will usually be snapped
10451
+ // to a 4 milisecond delay, but once we're flushing, there's no delay
10452
+ // between events.
10453
+ var timeoutHandle = setTimeout(handleTimer, 0);
10454
+ // However, since this timer gets frequently dropped in Firefox
10455
+ // workers, we enlist an interval handle that will try to fire
10456
+ // an event 20 times per second until it succeeds.
10457
+ var intervalHandle = setInterval(handleTimer, 50);
10458
+
10459
+ function handleTimer() {
10460
+ // Whichever timer succeeds will cancel both timers and
10461
+ // execute the callback.
10462
+ clearTimeout(timeoutHandle);
10463
+ clearInterval(intervalHandle);
10464
+ callback();
10465
+ }
10466
+ };
10467
+ }
10468
+
10469
+ // This is for `asap.js` only.
10470
+ // Its name will be periodically randomized to break any code that depends on
10471
+ // its existence.
10472
+ rawAsap.makeRequestCallFromTimer = makeRequestCallFromTimer;
10473
+
10474
+ // ASAP was originally a nextTick shim included in Q. This was factored out
10475
+ // into this ASAP package. It was later adapted to RSVP which made further
10476
+ // amendments. These decisions, particularly to marginalize MessageChannel and
10477
+ // to capture the MutationObserver implementation in a closure, were integrated
10478
+ // back into ASAP proper.
10479
+ // https://github.com/tildeio/rsvp.js/blob/cddf7232546a9cf858524b75cde6f9edf72620a7/lib/rsvp/asap.js
10480
+
10481
+ }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
10482
+ },{}],94:[function(require,module,exports){
10141
10483
  'use strict';
10142
10484
 
10143
- var asap = require('asap')
10485
+ var asap = require('asap/raw');
10144
10486
 
10145
- module.exports = Promise;
10146
- function Promise(fn) {
10147
- if (typeof this !== 'object') throw new TypeError('Promises must be constructed via new')
10148
- if (typeof fn !== 'function') throw new TypeError('not a function')
10149
- var state = null
10150
- var value = null
10151
- var deferreds = []
10152
- var self = this
10153
-
10154
- this.then = function(onFulfilled, onRejected) {
10155
- return new self.constructor(function(resolve, reject) {
10156
- handle(new Handler(onFulfilled, onRejected, resolve, reject))
10157
- })
10487
+ function noop() {}
10488
+
10489
+ // States:
10490
+ //
10491
+ // 0 - pending
10492
+ // 1 - fulfilled with _value
10493
+ // 2 - rejected with _value
10494
+ // 3 - adopted the state of another promise, _value
10495
+ //
10496
+ // once the state is no longer pending (0) it is immutable
10497
+
10498
+ // All `_` prefixed properties will be reduced to `_{random number}`
10499
+ // at build time to obfuscate them and discourage their use.
10500
+ // We don't use symbols or Object.defineProperty to fully hide them
10501
+ // because the performance isn't good enough.
10502
+
10503
+
10504
+ // to avoid using try/catch inside critical functions, we
10505
+ // extract them to here.
10506
+ var LAST_ERROR = null;
10507
+ var IS_ERROR = {};
10508
+ function getThen(obj) {
10509
+ try {
10510
+ return obj.then;
10511
+ } catch (ex) {
10512
+ LAST_ERROR = ex;
10513
+ return IS_ERROR;
10158
10514
  }
10515
+ }
10159
10516
 
10160
- function handle(deferred) {
10161
- if (state === null) {
10162
- deferreds.push(deferred)
10163
- return
10164
- }
10165
- asap(function() {
10166
- var cb = state ? deferred.onFulfilled : deferred.onRejected
10167
- if (cb === null) {
10168
- (state ? deferred.resolve : deferred.reject)(value)
10169
- return
10170
- }
10171
- var ret
10172
- try {
10173
- ret = cb(value)
10174
- }
10175
- catch (e) {
10176
- deferred.reject(e)
10177
- return
10178
- }
10179
- deferred.resolve(ret)
10180
- })
10517
+ function tryCallOne(fn, a) {
10518
+ try {
10519
+ return fn(a);
10520
+ } catch (ex) {
10521
+ LAST_ERROR = ex;
10522
+ return IS_ERROR;
10523
+ }
10524
+ }
10525
+ function tryCallTwo(fn, a, b) {
10526
+ try {
10527
+ fn(a, b);
10528
+ } catch (ex) {
10529
+ LAST_ERROR = ex;
10530
+ return IS_ERROR;
10181
10531
  }
10532
+ }
10182
10533
 
10183
- function resolve(newValue) {
10184
- try { //Promise Resolution Procedure: https://github.com/promises-aplus/promises-spec#the-promise-resolution-procedure
10185
- if (newValue === self) throw new TypeError('A promise cannot be resolved with itself.')
10186
- if (newValue && (typeof newValue === 'object' || typeof newValue === 'function')) {
10187
- var then = newValue.then
10188
- if (typeof then === 'function') {
10189
- doResolve(then.bind(newValue), resolve, reject)
10190
- return
10191
- }
10192
- }
10193
- state = true
10194
- value = newValue
10195
- finale()
10196
- } catch (e) { reject(e) }
10534
+ module.exports = Promise;
10535
+
10536
+ function Promise(fn) {
10537
+ if (typeof this !== 'object') {
10538
+ throw new TypeError('Promises must be constructed via new');
10539
+ }
10540
+ if (typeof fn !== 'function') {
10541
+ throw new TypeError('not a function');
10197
10542
  }
10543
+ this._45 = 0;
10544
+ this._81 = 0;
10545
+ this._65 = null;
10546
+ this._54 = null;
10547
+ if (fn === noop) return;
10548
+ doResolve(fn, this);
10549
+ }
10550
+ Promise._10 = null;
10551
+ Promise._97 = null;
10552
+ Promise._61 = noop;
10198
10553
 
10199
- function reject(newValue) {
10200
- state = false
10201
- value = newValue
10202
- finale()
10554
+ Promise.prototype.then = function(onFulfilled, onRejected) {
10555
+ if (this.constructor !== Promise) {
10556
+ return safeThen(this, onFulfilled, onRejected);
10203
10557
  }
10558
+ var res = new Promise(noop);
10559
+ handle(this, new Handler(onFulfilled, onRejected, res));
10560
+ return res;
10561
+ };
10204
10562
 
10205
- function finale() {
10206
- for (var i = 0, len = deferreds.length; i < len; i++)
10207
- handle(deferreds[i])
10208
- deferreds = null
10563
+ function safeThen(self, onFulfilled, onRejected) {
10564
+ return new self.constructor(function (resolve, reject) {
10565
+ var res = new Promise(noop);
10566
+ res.then(resolve, reject);
10567
+ handle(self, new Handler(onFulfilled, onRejected, res));
10568
+ });
10569
+ };
10570
+ function handle(self, deferred) {
10571
+ while (self._81 === 3) {
10572
+ self = self._65;
10573
+ }
10574
+ if (Promise._10) {
10575
+ Promise._10(self);
10576
+ }
10577
+ if (self._81 === 0) {
10578
+ if (self._45 === 0) {
10579
+ self._45 = 1;
10580
+ self._54 = deferred;
10581
+ return;
10582
+ }
10583
+ if (self._45 === 1) {
10584
+ self._45 = 2;
10585
+ self._54 = [self._54, deferred];
10586
+ return;
10587
+ }
10588
+ self._54.push(deferred);
10589
+ return;
10209
10590
  }
10591
+ handleResolved(self, deferred);
10592
+ }
10210
10593
 
10211
- doResolve(fn, resolve, reject)
10594
+ function handleResolved(self, deferred) {
10595
+ asap(function() {
10596
+ var cb = self._81 === 1 ? deferred.onFulfilled : deferred.onRejected;
10597
+ if (cb === null) {
10598
+ if (self._81 === 1) {
10599
+ resolve(deferred.promise, self._65);
10600
+ } else {
10601
+ reject(deferred.promise, self._65);
10602
+ }
10603
+ return;
10604
+ }
10605
+ var ret = tryCallOne(cb, self._65);
10606
+ if (ret === IS_ERROR) {
10607
+ reject(deferred.promise, LAST_ERROR);
10608
+ } else {
10609
+ resolve(deferred.promise, ret);
10610
+ }
10611
+ });
10612
+ }
10613
+ function resolve(self, newValue) {
10614
+ // Promise Resolution Procedure: https://github.com/promises-aplus/promises-spec#the-promise-resolution-procedure
10615
+ if (newValue === self) {
10616
+ return reject(
10617
+ self,
10618
+ new TypeError('A promise cannot be resolved with itself.')
10619
+ );
10620
+ }
10621
+ if (
10622
+ newValue &&
10623
+ (typeof newValue === 'object' || typeof newValue === 'function')
10624
+ ) {
10625
+ var then = getThen(newValue);
10626
+ if (then === IS_ERROR) {
10627
+ return reject(self, LAST_ERROR);
10628
+ }
10629
+ if (
10630
+ then === self.then &&
10631
+ newValue instanceof Promise
10632
+ ) {
10633
+ self._81 = 3;
10634
+ self._65 = newValue;
10635
+ finale(self);
10636
+ return;
10637
+ } else if (typeof then === 'function') {
10638
+ doResolve(then.bind(newValue), self);
10639
+ return;
10640
+ }
10641
+ }
10642
+ self._81 = 1;
10643
+ self._65 = newValue;
10644
+ finale(self);
10212
10645
  }
10213
10646
 
10647
+ function reject(self, newValue) {
10648
+ self._81 = 2;
10649
+ self._65 = newValue;
10650
+ if (Promise._97) {
10651
+ Promise._97(self, newValue);
10652
+ }
10653
+ finale(self);
10654
+ }
10655
+ function finale(self) {
10656
+ if (self._45 === 1) {
10657
+ handle(self, self._54);
10658
+ self._54 = null;
10659
+ }
10660
+ if (self._45 === 2) {
10661
+ for (var i = 0; i < self._54.length; i++) {
10662
+ handle(self, self._54[i]);
10663
+ }
10664
+ self._54 = null;
10665
+ }
10666
+ }
10214
10667
 
10215
- function Handler(onFulfilled, onRejected, resolve, reject){
10216
- this.onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : null
10217
- this.onRejected = typeof onRejected === 'function' ? onRejected : null
10218
- this.resolve = resolve
10219
- this.reject = reject
10668
+ function Handler(onFulfilled, onRejected, promise){
10669
+ this.onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : null;
10670
+ this.onRejected = typeof onRejected === 'function' ? onRejected : null;
10671
+ this.promise = promise;
10220
10672
  }
10221
10673
 
10222
10674
  /**
@@ -10225,253 +10677,133 @@ function Handler(onFulfilled, onRejected, resolve, reject){
10225
10677
  *
10226
10678
  * Makes no guarantees about asynchrony.
10227
10679
  */
10228
- function doResolve(fn, onFulfilled, onRejected) {
10680
+ function doResolve(fn, promise) {
10229
10681
  var done = false;
10230
- try {
10231
- fn(function (value) {
10232
- if (done) return
10233
- done = true
10234
- onFulfilled(value)
10235
- }, function (reason) {
10236
- if (done) return
10237
- done = true
10238
- onRejected(reason)
10239
- })
10240
- } catch (ex) {
10241
- if (done) return
10242
- done = true
10243
- onRejected(ex)
10682
+ var res = tryCallTwo(fn, function (value) {
10683
+ if (done) return;
10684
+ done = true;
10685
+ resolve(promise, value);
10686
+ }, function (reason) {
10687
+ if (done) return;
10688
+ done = true;
10689
+ reject(promise, reason);
10690
+ })
10691
+ if (!done && res === IS_ERROR) {
10692
+ done = true;
10693
+ reject(promise, LAST_ERROR);
10244
10694
  }
10245
10695
  }
10246
10696
 
10247
- },{"asap":95}],94:[function(require,module,exports){
10697
+ },{"asap/raw":93}],95:[function(require,module,exports){
10248
10698
  'use strict';
10249
10699
 
10250
10700
  //This file contains the ES6 extensions to the core Promises/A+ API
10251
10701
 
10252
- var Promise = require('./core.js')
10253
- var asap = require('asap')
10702
+ var Promise = require('./core.js');
10254
10703
 
10255
- module.exports = Promise
10704
+ module.exports = Promise;
10256
10705
 
10257
10706
  /* Static Functions */
10258
10707
 
10259
- function ValuePromise(value) {
10260
- this.then = function (onFulfilled) {
10261
- if (typeof onFulfilled !== 'function') return this
10262
- return new Promise(function (resolve, reject) {
10263
- asap(function () {
10264
- try {
10265
- resolve(onFulfilled(value))
10266
- } catch (ex) {
10267
- reject(ex);
10268
- }
10269
- })
10270
- })
10271
- }
10708
+ var TRUE = valuePromise(true);
10709
+ var FALSE = valuePromise(false);
10710
+ var NULL = valuePromise(null);
10711
+ var UNDEFINED = valuePromise(undefined);
10712
+ var ZERO = valuePromise(0);
10713
+ var EMPTYSTRING = valuePromise('');
10714
+
10715
+ function valuePromise(value) {
10716
+ var p = new Promise(Promise._61);
10717
+ p._81 = 1;
10718
+ p._65 = value;
10719
+ return p;
10272
10720
  }
10273
- ValuePromise.prototype = Promise.prototype
10274
-
10275
- var TRUE = new ValuePromise(true)
10276
- var FALSE = new ValuePromise(false)
10277
- var NULL = new ValuePromise(null)
10278
- var UNDEFINED = new ValuePromise(undefined)
10279
- var ZERO = new ValuePromise(0)
10280
- var EMPTYSTRING = new ValuePromise('')
10281
-
10282
10721
  Promise.resolve = function (value) {
10283
- if (value instanceof Promise) return value
10722
+ if (value instanceof Promise) return value;
10284
10723
 
10285
- if (value === null) return NULL
10286
- if (value === undefined) return UNDEFINED
10287
- if (value === true) return TRUE
10288
- if (value === false) return FALSE
10289
- if (value === 0) return ZERO
10290
- if (value === '') return EMPTYSTRING
10724
+ if (value === null) return NULL;
10725
+ if (value === undefined) return UNDEFINED;
10726
+ if (value === true) return TRUE;
10727
+ if (value === false) return FALSE;
10728
+ if (value === 0) return ZERO;
10729
+ if (value === '') return EMPTYSTRING;
10291
10730
 
10292
10731
  if (typeof value === 'object' || typeof value === 'function') {
10293
10732
  try {
10294
- var then = value.then
10733
+ var then = value.then;
10295
10734
  if (typeof then === 'function') {
10296
- return new Promise(then.bind(value))
10735
+ return new Promise(then.bind(value));
10297
10736
  }
10298
10737
  } catch (ex) {
10299
10738
  return new Promise(function (resolve, reject) {
10300
- reject(ex)
10301
- })
10739
+ reject(ex);
10740
+ });
10302
10741
  }
10303
10742
  }
10304
-
10305
- return new ValuePromise(value)
10306
- }
10743
+ return valuePromise(value);
10744
+ };
10307
10745
 
10308
10746
  Promise.all = function (arr) {
10309
- var args = Array.prototype.slice.call(arr)
10747
+ var args = Array.prototype.slice.call(arr);
10310
10748
 
10311
10749
  return new Promise(function (resolve, reject) {
10312
- if (args.length === 0) return resolve([])
10313
- var remaining = args.length
10750
+ if (args.length === 0) return resolve([]);
10751
+ var remaining = args.length;
10314
10752
  function res(i, val) {
10315
- try {
10316
- if (val && (typeof val === 'object' || typeof val === 'function')) {
10317
- var then = val.then
10753
+ if (val && (typeof val === 'object' || typeof val === 'function')) {
10754
+ if (val instanceof Promise && val.then === Promise.prototype.then) {
10755
+ while (val._81 === 3) {
10756
+ val = val._65;
10757
+ }
10758
+ if (val._81 === 1) return res(i, val._65);
10759
+ if (val._81 === 2) reject(val._65);
10760
+ val.then(function (val) {
10761
+ res(i, val);
10762
+ }, reject);
10763
+ return;
10764
+ } else {
10765
+ var then = val.then;
10318
10766
  if (typeof then === 'function') {
10319
- then.call(val, function (val) { res(i, val) }, reject)
10320
- return
10767
+ var p = new Promise(then.bind(val));
10768
+ p.then(function (val) {
10769
+ res(i, val);
10770
+ }, reject);
10771
+ return;
10321
10772
  }
10322
10773
  }
10323
- args[i] = val
10324
- if (--remaining === 0) {
10325
- resolve(args);
10326
- }
10327
- } catch (ex) {
10328
- reject(ex)
10774
+ }
10775
+ args[i] = val;
10776
+ if (--remaining === 0) {
10777
+ resolve(args);
10329
10778
  }
10330
10779
  }
10331
10780
  for (var i = 0; i < args.length; i++) {
10332
- res(i, args[i])
10781
+ res(i, args[i]);
10333
10782
  }
10334
- })
10335
- }
10783
+ });
10784
+ };
10336
10785
 
10337
10786
  Promise.reject = function (value) {
10338
- return new Promise(function (resolve, reject) {
10787
+ return new Promise(function (resolve, reject) {
10339
10788
  reject(value);
10340
10789
  });
10341
- }
10790
+ };
10342
10791
 
10343
10792
  Promise.race = function (values) {
10344
- return new Promise(function (resolve, reject) {
10793
+ return new Promise(function (resolve, reject) {
10345
10794
  values.forEach(function(value){
10346
10795
  Promise.resolve(value).then(resolve, reject);
10347
- })
10796
+ });
10348
10797
  });
10349
- }
10798
+ };
10350
10799
 
10351
10800
  /* Prototype Methods */
10352
10801
 
10353
10802
  Promise.prototype['catch'] = function (onRejected) {
10354
10803
  return this.then(null, onRejected);
10355
- }
10356
-
10357
- },{"./core.js":93,"asap":95}],95:[function(require,module,exports){
10358
- (function (process){
10359
-
10360
- // Use the fastest possible means to execute a task in a future turn
10361
- // of the event loop.
10362
-
10363
- // linked list of tasks (single, with head node)
10364
- var head = {task: void 0, next: null};
10365
- var tail = head;
10366
- var flushing = false;
10367
- var requestFlush = void 0;
10368
- var isNodeJS = false;
10369
-
10370
- function flush() {
10371
- /* jshint loopfunc: true */
10372
-
10373
- while (head.next) {
10374
- head = head.next;
10375
- var task = head.task;
10376
- head.task = void 0;
10377
- var domain = head.domain;
10378
-
10379
- if (domain) {
10380
- head.domain = void 0;
10381
- domain.enter();
10382
- }
10383
-
10384
- try {
10385
- task();
10386
-
10387
- } catch (e) {
10388
- if (isNodeJS) {
10389
- // In node, uncaught exceptions are considered fatal errors.
10390
- // Re-throw them synchronously to interrupt flushing!
10391
-
10392
- // Ensure continuation if the uncaught exception is suppressed
10393
- // listening "uncaughtException" events (as domains does).
10394
- // Continue in next event to avoid tick recursion.
10395
- if (domain) {
10396
- domain.exit();
10397
- }
10398
- setTimeout(flush, 0);
10399
- if (domain) {
10400
- domain.enter();
10401
- }
10402
-
10403
- throw e;
10404
-
10405
- } else {
10406
- // In browsers, uncaught exceptions are not fatal.
10407
- // Re-throw them asynchronously to avoid slow-downs.
10408
- setTimeout(function() {
10409
- throw e;
10410
- }, 0);
10411
- }
10412
- }
10413
-
10414
- if (domain) {
10415
- domain.exit();
10416
- }
10417
- }
10418
-
10419
- flushing = false;
10420
- }
10421
-
10422
- if (typeof process !== "undefined" && process.nextTick) {
10423
- // Node.js before 0.9. Note that some fake-Node environments, like the
10424
- // Mocha test runner, introduce a `process` global without a `nextTick`.
10425
- isNodeJS = true;
10426
-
10427
- requestFlush = function () {
10428
- process.nextTick(flush);
10429
- };
10430
-
10431
- } else if (typeof setImmediate === "function") {
10432
- // In IE10, Node.js 0.9+, or https://github.com/NobleJS/setImmediate
10433
- if (typeof window !== "undefined") {
10434
- requestFlush = setImmediate.bind(window, flush);
10435
- } else {
10436
- requestFlush = function () {
10437
- setImmediate(flush);
10438
- };
10439
- }
10440
-
10441
- } else if (typeof MessageChannel !== "undefined") {
10442
- // modern browsers
10443
- // http://www.nonblocking.io/2011/06/windownexttick.html
10444
- var channel = new MessageChannel();
10445
- channel.port1.onmessage = flush;
10446
- requestFlush = function () {
10447
- channel.port2.postMessage(0);
10448
- };
10449
-
10450
- } else {
10451
- // old browsers
10452
- requestFlush = function () {
10453
- setTimeout(flush, 0);
10454
- };
10455
- }
10456
-
10457
- function asap(task) {
10458
- tail = tail.next = {
10459
- task: task,
10460
- domain: isNodeJS && process.domain,
10461
- next: null
10462
- };
10463
-
10464
- if (!flushing) {
10465
- flushing = true;
10466
- requestFlush();
10467
- }
10468
10804
  };
10469
10805
 
10470
- module.exports = asap;
10471
-
10472
-
10473
- }).call(this,require('_process'))
10474
- },{"_process":92}],96:[function(require,module,exports){
10806
+ },{"./core.js":94}],96:[function(require,module,exports){
10475
10807
  // should work in any browser without browserify
10476
10808
 
10477
10809
  if (typeof Promise.prototype.done !== 'function') {
@@ -10496,5 +10828,5 @@ if (typeof Promise === 'undefined') {
10496
10828
 
10497
10829
  require('./polyfill-done.js');
10498
10830
 
10499
- },{"./lib/core.js":93,"./lib/es6-extensions.js":94,"./polyfill-done.js":96,"asap":95}]},{},[2])(2)
10831
+ },{"./lib/core.js":94,"./lib/es6-extensions.js":95,"./polyfill-done.js":96,"asap":92}]},{},[2])(2)
10500
10832
  });