index.js 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. /*!
  2. * Stylus - Stack
  3. * Copyright (c) Automattic <developer.wordpress.com>
  4. * MIT Licensed
  5. */
  6. /**
  7. * Initialize a new `Stack`.
  8. *
  9. * @api private
  10. */
  11. var Stack = module.exports = function Stack() {
  12. Array.apply(this, arguments);
  13. };
  14. /**
  15. * Inherit from `Array.prototype`.
  16. */
  17. Stack.prototype.__proto__ = Array.prototype;
  18. /**
  19. * Push the given `frame`.
  20. *
  21. * @param {Frame} frame
  22. * @api public
  23. */
  24. Stack.prototype.push = function(frame){
  25. frame.stack = this;
  26. frame.parent = this.currentFrame;
  27. return [].push.apply(this, arguments);
  28. };
  29. /**
  30. * Return the current stack `Frame`.
  31. *
  32. * @return {Frame}
  33. * @api private
  34. */
  35. Stack.prototype.__defineGetter__('currentFrame', function(){
  36. return this[this.length - 1];
  37. });
  38. /**
  39. * Lookup stack frame for the given `block`.
  40. *
  41. * @param {Block} block
  42. * @return {Frame}
  43. * @api private
  44. */
  45. Stack.prototype.getBlockFrame = function(block){
  46. for (var i = 0; i < this.length; ++i) {
  47. if (block == this[i].block) {
  48. return this[i];
  49. }
  50. }
  51. };
  52. /**
  53. * Lookup the given local variable `name`, relative
  54. * to the lexical scope of the current frame's `Block`.
  55. *
  56. * When the result of a lookup is an identifier
  57. * a recursive lookup is performed, defaulting to
  58. * returning the identifier itself.
  59. *
  60. * @param {String} name
  61. * @return {Node}
  62. * @api private
  63. */
  64. Stack.prototype.lookup = function(name){
  65. var block = this.currentFrame.block
  66. , val
  67. , ret;
  68. do {
  69. var frame = this.getBlockFrame(block);
  70. if (frame && (val = frame.lookup(name))) {
  71. return val;
  72. }
  73. } while (block = block.parent);
  74. };
  75. /**
  76. * Custom inspect.
  77. *
  78. * @return {String}
  79. * @api private
  80. */
  81. Stack.prototype.inspect = function(){
  82. return this.reverse().map(function(frame){
  83. return frame.inspect();
  84. }).join('\n');
  85. };
  86. /**
  87. * Return stack string formatted as:
  88. *
  89. * at <context> (<filename>:<lineno>:<column>)
  90. *
  91. * @return {String}
  92. * @api private
  93. */
  94. Stack.prototype.toString = function(){
  95. var block
  96. , node
  97. , buf = []
  98. , location
  99. , len = this.length;
  100. while (len--) {
  101. block = this[len].block;
  102. if (node = block.node) {
  103. location = '(' + node.filename + ':' + (node.lineno + 1) + ':' + node.column + ')';
  104. switch (node.nodeName) {
  105. case 'function':
  106. buf.push(' at ' + node.name + '() ' + location);
  107. break;
  108. case 'group':
  109. buf.push(' at "' + node.nodes[0].val + '" ' + location);
  110. break;
  111. }
  112. }
  113. }
  114. return buf.join('\n');
  115. };