Diglin_UIOptimization - Version 1.4.0

Version Notes

- Version 1.4.0: Move themes files to the folder app/design/frontend/base/default, update yuicompressor to version 2.4.7, generate css/js file per store and not globally
- Version 1.3.1: fix Paypal donation button
- Version 1.3.0: improve canonical url generation, improve some configuration parameters, remove the option JS Packer because incompatible with Magento
- Version 1.2.0: improve compatibility with compilation feature of Magento, add a js/css flush button directly in the configuration page
- Version 1.1.0: rewrite some classes of the minify libraries to respect PHP 5 and prevent some errors, change the module name, make it compatible with compilation feature of Magento, add canonical url feature for SEO
- Version 1.0.10: fix type for css files stored in /js/ folder
- Version 1.0.9: make correct package for Magento prior to 1.5
- Version 1.0.8: make it compatible with 1.5 and some improvements.
- Version 1.0.2: add cron task to allow to update compressed/minified js/css files periodically
- Version 1.0.1: fix a missing config element class, this class seems to exists only since 1.4.1 or more

Download this release

Release Info

Developer Magento Core Team
Extension Diglin_UIOptimization
Version 1.4.0
Comparing to
See all releases


Code changes from version 1.3.0 to 1.4.0

Files changed (104) hide show
  1. app/code/community/Diglin/UIOptimization/Block/Adminhtml/Config/Source/Hint.php +2 -3
  2. app/code/community/Diglin/UIOptimization/Block/Optimize/Head.php +3 -3
  3. app/code/community/Diglin/UIOptimization/Helper/Data.php +13 -12
  4. app/code/community/Diglin/UIOptimization/etc/config.xml +1 -1
  5. app/design/frontend/{default → base}/default/layout/uioptimization.xml +0 -0
  6. app/design/frontend/{default → base}/default/template/uioptimization/canonicalurl.phtml +23 -23
  7. app/design/frontend/{default → base}/default/template/uioptimization/w3ccssvalidator.phtml +0 -0
  8. app/design/frontend/{default → base}/default/template/uioptimization/w3chtmlvalidator.phtml +0 -0
  9. lib/Diglin/.DS_Store +0 -0
  10. lib/Diglin/yuicompressor-2.4.6/LICENSE.TXT +0 -54
  11. lib/Diglin/yuicompressor-2.4.6/ant.properties +0 -8
  12. lib/Diglin/yuicompressor-2.4.6/build.xml +0 -69
  13. lib/Diglin/yuicompressor-2.4.6/doc/CHANGELOG +0 -257
  14. lib/Diglin/yuicompressor-2.4.6/doc/README +0 -145
  15. lib/Diglin/yuicompressor-2.4.6/lib/jargs-1.0.jar +0 -0
  16. lib/Diglin/yuicompressor-2.4.6/ports/js/cssmin.js +0 -231
  17. lib/Diglin/yuicompressor-2.4.6/src/com/yahoo/platform/yui/compressor/Bootstrap.java +0 -23
  18. lib/Diglin/yuicompressor-2.4.6/src/com/yahoo/platform/yui/compressor/CssCompressor.java +0 -304
  19. lib/Diglin/yuicompressor-2.4.6/src/com/yahoo/platform/yui/compressor/JarClassLoader.java +0 -158
  20. lib/Diglin/yuicompressor-2.4.6/src/com/yahoo/platform/yui/compressor/JavaScriptCompressor.java +0 -1317
  21. lib/Diglin/yuicompressor-2.4.6/src/com/yahoo/platform/yui/compressor/JavaScriptIdentifier.java +0 -55
  22. lib/Diglin/yuicompressor-2.4.6/src/com/yahoo/platform/yui/compressor/JavaScriptToken.java +0 -28
  23. lib/Diglin/yuicompressor-2.4.6/src/com/yahoo/platform/yui/compressor/ScriptOrFnScope.java +0 -160
  24. lib/Diglin/yuicompressor-2.4.6/src/com/yahoo/platform/yui/compressor/YUICompressor.java +0 -255
  25. lib/Diglin/yuicompressor-2.4.6/src/org/mozilla/javascript/Decompiler.java +0 -908
  26. lib/Diglin/yuicompressor-2.4.6/src/org/mozilla/javascript/Decompiler.java.orig +0 -910
  27. lib/Diglin/yuicompressor-2.4.6/src/org/mozilla/javascript/Parser.java +0 -2160
  28. lib/Diglin/yuicompressor-2.4.6/src/org/mozilla/javascript/Parser.java.orig +0 -2159
  29. lib/Diglin/yuicompressor-2.4.6/src/org/mozilla/javascript/Token.java +0 -406
  30. lib/Diglin/yuicompressor-2.4.6/src/org/mozilla/javascript/Token.java.orig +0 -417
  31. lib/Diglin/yuicompressor-2.4.6/src/org/mozilla/javascript/TokenStream.java +0 -1365
  32. lib/Diglin/yuicompressor-2.4.6/src/org/mozilla/javascript/TokenStream.java.orig +0 -1398
  33. lib/Diglin/yuicompressor-2.4.6/tests/README +0 -6
  34. lib/Diglin/yuicompressor-2.4.6/tests/_munge.js +0 -8
  35. lib/Diglin/yuicompressor-2.4.6/tests/_munge.js.min +0 -1
  36. lib/Diglin/yuicompressor-2.4.6/tests/_string_combo.js +0 -5
  37. lib/Diglin/yuicompressor-2.4.6/tests/_string_combo.js.min +0 -1
  38. lib/Diglin/yuicompressor-2.4.6/tests/_syntax_error.js +0 -73
  39. lib/Diglin/yuicompressor-2.4.6/tests/_syntax_error.js.min +0 -1
  40. lib/Diglin/yuicompressor-2.4.6/tests/background-position.css +0 -2
  41. lib/Diglin/yuicompressor-2.4.6/tests/background-position.css.min +0 -1
  42. lib/Diglin/yuicompressor-2.4.6/tests/border-none.css +0 -5
  43. lib/Diglin/yuicompressor-2.4.6/tests/border-none.css.min +0 -1
  44. lib/Diglin/yuicompressor-2.4.6/tests/box-model-hack.css +0 -9
  45. lib/Diglin/yuicompressor-2.4.6/tests/box-model-hack.css.min +0 -1
  46. lib/Diglin/yuicompressor-2.4.6/tests/bug2527974.css +0 -10
  47. lib/Diglin/yuicompressor-2.4.6/tests/bug2527974.css.min +0 -1
  48. lib/Diglin/yuicompressor-2.4.6/tests/bug2527991.css +0 -19
  49. lib/Diglin/yuicompressor-2.4.6/tests/bug2527991.css.min +0 -1
  50. lib/Diglin/yuicompressor-2.4.6/tests/bug2527998.css +0 -4
  51. lib/Diglin/yuicompressor-2.4.6/tests/bug2527998.css.min +0 -1
  52. lib/Diglin/yuicompressor-2.4.6/tests/bug2528034.css +0 -5
  53. lib/Diglin/yuicompressor-2.4.6/tests/bug2528034.css.min +0 -1
  54. lib/Diglin/yuicompressor-2.4.6/tests/charset-media.css +0 -9
  55. lib/Diglin/yuicompressor-2.4.6/tests/charset-media.css.min +0 -1
  56. lib/Diglin/yuicompressor-2.4.6/tests/color.css +0 -7
  57. lib/Diglin/yuicompressor-2.4.6/tests/color.css.min +0 -1
  58. lib/Diglin/yuicompressor-2.4.6/tests/comment.css +0 -3
  59. lib/Diglin/yuicompressor-2.4.6/tests/comment.css.min +0 -1
  60. lib/Diglin/yuicompressor-2.4.6/tests/concat-charset.css +0 -15
  61. lib/Diglin/yuicompressor-2.4.6/tests/concat-charset.css.min +0 -1
  62. lib/Diglin/yuicompressor-2.4.6/tests/decimals.css +0 -3
  63. lib/Diglin/yuicompressor-2.4.6/tests/decimals.css.min +0 -1
  64. lib/Diglin/yuicompressor-2.4.6/tests/dollar-header.css +0 -7
  65. lib/Diglin/yuicompressor-2.4.6/tests/dollar-header.css.min +0 -3
  66. lib/Diglin/yuicompressor-2.4.6/tests/float.js +0 -2
  67. lib/Diglin/yuicompressor-2.4.6/tests/float.js.min +0 -1
  68. lib/Diglin/yuicompressor-2.4.6/tests/font-face.css +0 -6
  69. lib/Diglin/yuicompressor-2.4.6/tests/font-face.css.min +0 -1
  70. lib/Diglin/yuicompressor-2.4.6/tests/ie5mac.css +0 -5
  71. lib/Diglin/yuicompressor-2.4.6/tests/ie5mac.css.min +0 -1
  72. lib/Diglin/yuicompressor-2.4.6/tests/media-empty-class.css +0 -16
  73. lib/Diglin/yuicompressor-2.4.6/tests/media-empty-class.css.min +0 -1
  74. lib/Diglin/yuicompressor-2.4.6/tests/media-multi.css +0 -3
  75. lib/Diglin/yuicompressor-2.4.6/tests/media-multi.css.min +0 -1
  76. lib/Diglin/yuicompressor-2.4.6/tests/media-test.css +0 -3
  77. lib/Diglin/yuicompressor-2.4.6/tests/media-test.css.min +0 -1
  78. lib/Diglin/yuicompressor-2.4.6/tests/opacity-filter.css +0 -14
  79. lib/Diglin/yuicompressor-2.4.6/tests/opacity-filter.css.min +0 -1
  80. lib/Diglin/yuicompressor-2.4.6/tests/preserve-new-line.css +0 -6
  81. lib/Diglin/yuicompressor-2.4.6/tests/preserve-new-line.css.min +0 -3
  82. lib/Diglin/yuicompressor-2.4.6/tests/preserve-strings.css +0 -7
  83. lib/Diglin/yuicompressor-2.4.6/tests/preserve-strings.css.min +0 -1
  84. lib/Diglin/yuicompressor-2.4.6/tests/pseudo-first.css +0 -16
  85. lib/Diglin/yuicompressor-2.4.6/tests/pseudo-first.css.min +0 -1
  86. lib/Diglin/yuicompressor-2.4.6/tests/pseudo.css +0 -4
  87. lib/Diglin/yuicompressor-2.4.6/tests/pseudo.css.min +0 -1
  88. lib/Diglin/yuicompressor-2.4.6/tests/special-comments.css +0 -13
  89. lib/Diglin/yuicompressor-2.4.6/tests/special-comments.css.min +0 -9
  90. lib/Diglin/yuicompressor-2.4.6/tests/star-underscore-hacks.css +0 -5
  91. lib/Diglin/yuicompressor-2.4.6/tests/star-underscore-hacks.css.min +0 -1
  92. lib/Diglin/yuicompressor-2.4.6/tests/string-in-comment.css +0 -8
  93. lib/Diglin/yuicompressor-2.4.6/tests/string-in-comment.css.min +0 -1
  94. lib/Diglin/yuicompressor-2.4.6/tests/suite.rhino +0 -3
  95. lib/Diglin/yuicompressor-2.4.6/tests/suite.sh +0 -62
  96. lib/Diglin/yuicompressor-2.4.6/tests/webkit-transform.css +0 -2
  97. lib/Diglin/yuicompressor-2.4.6/tests/webkit-transform.css.min +0 -1
  98. lib/Diglin/yuicompressor-2.4.6/tests/zeros.css +0 -6
  99. lib/Diglin/yuicompressor-2.4.6/tests/zeros.css.min +0 -1
  100. lib/Diglin/yuicompressor/.DS_Store +0 -0
  101. lib/Diglin/{yuicompressor-2.4.6/build/yuicompressor-2.4.6.jar → yuicompressor/yuicompressor-2.4.7.jar} +0 -0
  102. lib/Diglin/{yuicompressor-2.4.6/lib/rhino-1.6R7.jar → yuicompressor/yuicompressor.jar} +0 -0
  103. package.xml +7 -5
  104. skin/frontend/{default → base}/default/css/w3c-validator.css +0 -0
app/code/community/Diglin/UIOptimization/Block/Adminhtml/Config/Source/Hint.php CHANGED
@@ -35,9 +35,8 @@ class Diglin_UIOptimization_Block_Adminhtml_Config_Source_Hint
35
  'label' => Mage::helper('adminhtml')->__('Flush JavaScript/CSS Cache'),
36
  'onclick' => "setLocation('" . $this->getUrl('*/cache/cleanMedia') ."');",
37
  ));
38
-
39
- return '<p><form action="https://www.paypal.com/cgi-bin/webscr" method="post"> <input name="cmd" type="hidden" value="_s-xclick" /> <input name="hosted_button_id" type="hidden" value="9SFPE62WPWG2U" /> <input alt="PayPal - The safer, easier way to pay online!" name="submit" src="https://www.paypal.com/en_US/i/btn/btn_donate_LG.gif" type="image" /> <img src="https://www.paypal.com/fr_FR/i/scr/pixel.gif" border="0" alt="" width="1" height="1" /> </form>Please, Invite me for a drink for the hard work done. Thank you in advance for your donation</p>
40
  <p><strong>Diglin_UIOptimization Version: '.$version.'</strong></p><p>' . $block->toHtml() .' ('. $this->__('You will be redirected to the Cache Management page with a successful message') .')</p>';
41
-
42
  }
43
  }
35
  'label' => Mage::helper('adminhtml')->__('Flush JavaScript/CSS Cache'),
36
  'onclick' => "setLocation('" . $this->getUrl('*/cache/cleanMedia') ."');",
37
  ));
38
+
39
+ return '<p><a href="javascript:window.open(\'https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=Y66QHLU5VX5BC\')"><img src="https://www.paypal.com/en_US/i/btn/btn_donate_LG.gif" border="0" alt="Donate via Paypal" /> </a>Please, Invite me for a drink for the hard work done. Thank you in advance for your donation</p>
40
  <p><strong>Diglin_UIOptimization Version: '.$version.'</strong></p><p>' . $block->toHtml() .' ('. $this->__('You will be redirected to the Cache Management page with a successful message') .')</p>';
 
41
  }
42
  }
app/code/community/Diglin/UIOptimization/Block/Optimize/Head.php CHANGED
@@ -106,7 +106,7 @@ class Diglin_UIOptimization_Block_Optimize_Head extends Mage_Page_Block_Html_Hea
106
  $minifier = 'Diglin_Minify_YUICompressor';
107
  $method = 'minifyCss';
108
  // init Minify class with YUI Compressor
109
- Diglin_Minify_YUICompressor::$jarFile = Mage::getBaseDir('lib') . DS . 'Diglin' . DS . 'yuicompressor-2.4.6' . DS . 'build' . DS . 'yuicompressor-2.4.6.jar' ;
110
  Diglin_Minify_YUICompressor::$tempDir = Mage::getBaseDir('tmp');
111
  if(strlen($config['java_path']) > 0){
112
  Diglin_Minify_YUICompressor::$javaExecutable = $config['java_path'];
@@ -206,7 +206,7 @@ class Diglin_UIOptimization_Block_Optimize_Head extends Mage_Page_Block_Html_Hea
206
  case 'yuicompressor':
207
  $minifier = 'Diglin_Minify_YUICompressor';
208
  $method = 'minifyJs';
209
- Diglin_Minify_YUICompressor::$jarFile = Mage::getBaseDir('lib') . DS . 'Diglin' . DS .'yuicompressor-2.4.6' . DS . 'build' . DS . 'yuicompressor-2.4.6.jar' ;
210
  Diglin_Minify_YUICompressor::$tempDir = Mage::getBaseDir('tmp');
211
  if(strlen($config['java_path']) > 0){
212
  Diglin_Minify_YUICompressor::$javaExecutable = $config['java_path'];
@@ -366,4 +366,4 @@ class Diglin_UIOptimization_Block_Optimize_Head extends Mage_Page_Block_Html_Hea
366
  }
367
  return $this->_data['urlKey'];
368
  }
369
- }
106
  $minifier = 'Diglin_Minify_YUICompressor';
107
  $method = 'minifyCss';
108
  // init Minify class with YUI Compressor
109
+ Diglin_Minify_YUICompressor::$jarFile = Mage::getBaseDir('lib') . DS . 'Diglin' . DS . 'yuicompressor' . DS . 'yuicompressor.jar' ;
110
  Diglin_Minify_YUICompressor::$tempDir = Mage::getBaseDir('tmp');
111
  if(strlen($config['java_path']) > 0){
112
  Diglin_Minify_YUICompressor::$javaExecutable = $config['java_path'];
206
  case 'yuicompressor':
207
  $minifier = 'Diglin_Minify_YUICompressor';
208
  $method = 'minifyJs';
209
+ Diglin_Minify_YUICompressor::$jarFile = Mage::getBaseDir('lib') . DS . 'Diglin' . DS .'yuicompressor' . DS . 'yuicompressor.jar' ;
210
  Diglin_Minify_YUICompressor::$tempDir = Mage::getBaseDir('tmp');
211
  if(strlen($config['java_path']) > 0){
212
  Diglin_Minify_YUICompressor::$javaExecutable = $config['java_path'];
366
  }
367
  return $this->_data['urlKey'];
368
  }
369
+ }
app/code/community/Diglin/UIOptimization/Helper/Data.php CHANGED
@@ -19,7 +19,7 @@ class Diglin_UIOptimization_Helper_Data extends Mage_Core_Helper_Abstract
19
  {
20
  /**
21
  * Retreive some basic information depending on the type of file: original path, destination path, type, name, static
22
- *
23
  * @param string $name
24
  * @param string $type
25
  * @param bool $static
@@ -29,23 +29,24 @@ class Diglin_UIOptimization_Helper_Data extends Mage_Core_Helper_Abstract
29
  {
30
  $info = array();
31
  $designPackage = Mage::getDesign();
32
-
33
  $orgname = $name;
34
  if(!$static){
35
  $info['orgskin_path'] = $designPackage->getFilename ( $orgname, array ('_type' => 'skin' ) );
36
  }else{
37
  $info['orgskin_path'] = Mage::getBaseDir() . DS . 'js'. DS . $name;
38
  }
39
-
40
  $orgpath = explode ( DS, $info['orgskin_path'] );
41
  if (count ( $orgpath ) > 1 && !$static) {
42
  // Get the theme of the original file
43
  $info['theme_name'] = $orgpath [count ( $orgpath ) - (count ( explode ( '/', $orgname ) ) + 1)];
44
  }
45
  $suffixFilename = (Mage::app()->getStore()->isCurrentlySecure())?'-ssl':'';
 
46
  $name = substr ( $name, 0, strpos($name, '.' . $type) );
47
  $name = $name . $suffixFilename .'_cp.'.$type;
48
-
49
  $file_path = explode('/', $name);
50
  if(count($file_path) > 1){
51
  $name = array_pop($file_path);
@@ -58,30 +59,30 @@ class Diglin_UIOptimization_Helper_Data extends Mage_Core_Helper_Abstract
58
  $info['new_name'] = $name;
59
  $info['type'] = $type;
60
  $info['static'] = $static;
61
-
62
  $targetDir = $this->initMergerDir ( $type );
63
  if (! $targetDir) {
64
  $info['success'] = false;
65
  return $info;
66
  }
67
-
68
  if(!$static){
69
  $info['targetPath'] = $targetDir . DS . 'skin' . DS . $info['theme_name'] . DS . $info['file_path'];
70
  }else{
71
  $info['targetPath'] = $targetDir . DS . $info['file_path'];
72
  }
73
  $info['targetPathFile'] = $info['targetPath'] . DS . $name;
74
-
75
  if(!file_exists($info['targetPath'])){
76
  $ioFile = new Diglin_Io_File();
77
  $ioFile->mkdir($info['targetPath'], 0755, true);
78
  }
79
-
80
  return $info;
81
  }
82
  /**
83
  * Provide the path URL of the filesystem for js or css files compressed or not
84
- *
85
  * @param array $info
86
  * @param string|array $mergeCallback
87
  * @return string
@@ -105,7 +106,7 @@ class Diglin_UIOptimization_Helper_Data extends Mage_Core_Helper_Abstract
105
  }
106
  }
107
  }
108
-
109
  /**
110
  * Make sure merger dir exists and writeable
111
  * Also can clean it up
@@ -131,10 +132,10 @@ class Diglin_UIOptimization_Helper_Data extends Mage_Core_Helper_Abstract
131
  }
132
  return false;
133
  }
134
-
135
  /**
136
  * Add trailing slash if necessary
137
- *
138
  * @param string $url
139
  */
140
  public function getTrailingSlash ($url)
19
  {
20
  /**
21
  * Retreive some basic information depending on the type of file: original path, destination path, type, name, static
22
+ *
23
  * @param string $name
24
  * @param string $type
25
  * @param bool $static
29
  {
30
  $info = array();
31
  $designPackage = Mage::getDesign();
32
+
33
  $orgname = $name;
34
  if(!$static){
35
  $info['orgskin_path'] = $designPackage->getFilename ( $orgname, array ('_type' => 'skin' ) );
36
  }else{
37
  $info['orgskin_path'] = Mage::getBaseDir() . DS . 'js'. DS . $name;
38
  }
39
+
40
  $orgpath = explode ( DS, $info['orgskin_path'] );
41
  if (count ( $orgpath ) > 1 && !$static) {
42
  // Get the theme of the original file
43
  $info['theme_name'] = $orgpath [count ( $orgpath ) - (count ( explode ( '/', $orgname ) ) + 1)];
44
  }
45
  $suffixFilename = (Mage::app()->getStore()->isCurrentlySecure())?'-ssl':'';
46
+ $suffixFilename.= '_'.Mage::app()->getStore()->getId();
47
  $name = substr ( $name, 0, strpos($name, '.' . $type) );
48
  $name = $name . $suffixFilename .'_cp.'.$type;
49
+
50
  $file_path = explode('/', $name);
51
  if(count($file_path) > 1){
52
  $name = array_pop($file_path);
59
  $info['new_name'] = $name;
60
  $info['type'] = $type;
61
  $info['static'] = $static;
62
+
63
  $targetDir = $this->initMergerDir ( $type );
64
  if (! $targetDir) {
65
  $info['success'] = false;
66
  return $info;
67
  }
68
+
69
  if(!$static){
70
  $info['targetPath'] = $targetDir . DS . 'skin' . DS . $info['theme_name'] . DS . $info['file_path'];
71
  }else{
72
  $info['targetPath'] = $targetDir . DS . $info['file_path'];
73
  }
74
  $info['targetPathFile'] = $info['targetPath'] . DS . $name;
75
+
76
  if(!file_exists($info['targetPath'])){
77
  $ioFile = new Diglin_Io_File();
78
  $ioFile->mkdir($info['targetPath'], 0755, true);
79
  }
80
+
81
  return $info;
82
  }
83
  /**
84
  * Provide the path URL of the filesystem for js or css files compressed or not
85
+ *
86
  * @param array $info
87
  * @param string|array $mergeCallback
88
  * @return string
106
  }
107
  }
108
  }
109
+
110
  /**
111
  * Make sure merger dir exists and writeable
112
  * Also can clean it up
132
  }
133
  return false;
134
  }
135
+
136
  /**
137
  * Add trailing slash if necessary
138
+ *
139
  * @param string $url
140
  */
141
  public function getTrailingSlash ($url)
app/code/community/Diglin/UIOptimization/etc/config.xml CHANGED
@@ -2,7 +2,7 @@
2
  <config>
3
  <modules>
4
  <Diglin_UIOptimization>
5
- <version>1.3.0</version>
6
  </Diglin_UIOptimization>
7
  </modules>
8
 
2
  <config>
3
  <modules>
4
  <Diglin_UIOptimization>
5
+ <version>1.4.0</version>
6
  </Diglin_UIOptimization>
7
  </modules>
8
 
app/design/frontend/{default → base}/default/layout/uioptimization.xml RENAMED
File without changes
app/design/frontend/{default → base}/default/template/uioptimization/canonicalurl.phtml RENAMED
@@ -1,24 +1,24 @@
1
- <?php
2
- /**
3
- * Diglin
4
- *
5
- * NOTICE OF LICENSE
6
- *
7
- * This source file is subject to the Open Software License (OSL 3.0)
8
- * that is bundled with this package in the file LICENSE.txt.
9
- * It is also available through the world-wide-web at this URL:
10
- * http://opensource.org/licenses/osl-3.0.php
11
- *
12
- *
13
- * @category Diglin
14
- * @package Diglin_UIOptimization
15
- * @copyright Copyright (c) 2011-2012 Diglin (http://www.diglin.com)
16
- * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
17
- */
18
-
19
- /*@var $this Rissip_UIOptimization_Block_Optimize_Head */
20
- $canonicalUrl = htmlspecialchars($this->getCanonicalUrl());
21
- if(Mage::getStoreConfigFlag('uioptimization/seo/enabled') && $canonicalUrl) :
22
- ?>
23
- <link rel="canonical" href="<?php echo $canonicalUrl; ?>" />
24
  <?php endif; ?>
1
+ <?php
2
+ /**
3
+ * Diglin
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is subject to the Open Software License (OSL 3.0)
8
+ * that is bundled with this package in the file LICENSE.txt.
9
+ * It is also available through the world-wide-web at this URL:
10
+ * http://opensource.org/licenses/osl-3.0.php
11
+ *
12
+ *
13
+ * @category Diglin
14
+ * @package Diglin_UIOptimization
15
+ * @copyright Copyright (c) 2011-2012 Diglin (http://www.diglin.com)
16
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
17
+ */
18
+
19
+ /*@var $this Rissip_UIOptimization_Block_Optimize_Head */
20
+ $canonicalUrl = htmlspecialchars($this->getCanonicalUrl());
21
+ if(Mage::getStoreConfigFlag('uioptimization/seo/enabled') && $canonicalUrl) :
22
+ ?>
23
+ <link rel="canonical" href="<?php echo $canonicalUrl; ?>" />
24
  <?php endif; ?>
app/design/frontend/{default → base}/default/template/uioptimization/w3ccssvalidator.phtml RENAMED
File without changes
app/design/frontend/{default → base}/default/template/uioptimization/w3chtmlvalidator.phtml RENAMED
File without changes
lib/Diglin/.DS_Store ADDED
Binary file
lib/Diglin/yuicompressor-2.4.6/LICENSE.TXT DELETED
@@ -1,54 +0,0 @@
1
- YUI Compressor Copyright License Agreement (BSD License)
2
-
3
- Copyright (c) 2010, Yahoo! Inc.
4
- All rights reserved.
5
-
6
- Redistribution and use of this software in source and binary forms,
7
- with or without modification, are permitted provided that the following
8
- conditions are met:
9
-
10
- * Redistributions of source code must retain the above
11
- copyright notice, this list of conditions and the
12
- following disclaimer.
13
-
14
- * Redistributions in binary form must reproduce the above
15
- copyright notice, this list of conditions and the
16
- following disclaimer in the documentation and/or other
17
- materials provided with the distribution.
18
-
19
- * Neither the name of Yahoo! Inc. nor the names of its
20
- contributors may be used to endorse or promote products
21
- derived from this software without specific prior
22
- written permission of Yahoo! Inc.
23
-
24
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
25
- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26
- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
27
- DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
28
- FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29
- DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
30
- SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
31
- CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
32
- OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
33
- OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
-
35
- This software also requires access to software from the following sources:
36
-
37
- The Jarg Library v 1.0 ( http://jargs.sourceforge.net/ ) is available
38
- under a BSD License � Copyright (c) 2001-2003 Steve Purcell,
39
- Copyright (c) 2002 Vidar Holen, Copyright (c) 2002 Michal Ceresna and
40
- Copyright (c) 2005 Ewan Mellor.
41
-
42
- The Rhino Library ( http://www.mozilla.org/rhino/ ) is dually available
43
- under an MPL 1.1/GPL 2.0 license, with portions subject to a BSD license.
44
-
45
- Additionally, this software contains modified versions of the following
46
- component files from the Rhino Library:
47
-
48
- [org/mozilla/javascript/Decompiler.java]
49
- [org/mozilla/javascript/Parser.java]
50
- [org/mozilla/javascript/Token.java]
51
- [org/mozilla/javascript/TokenStream.java]
52
-
53
- The modified versions of these files are distributed under the MPL v 1.1
54
- ( http://www.mozilla.org/MPL/MPL-1.1.html )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
lib/Diglin/yuicompressor-2.4.6/ant.properties DELETED
@@ -1,8 +0,0 @@
1
- src.dir = src
2
- lib.dir = lib
3
- doc.dir = doc
4
- build.dir = build
5
- product.name = yuicompressor
6
- version.number = 2.4.6
7
- jar.name = ${product.name}-${version.number}.jar
8
- dist.package.name = ${product.name}-${version.number}
 
 
 
 
 
 
 
 
lib/Diglin/yuicompressor-2.4.6/build.xml DELETED
@@ -1,69 +0,0 @@
1
- <?xml version="1.0" encoding="iso-8859-1"?>
2
- <project name="YUI Compressor" default="build.jar" basedir=".">
3
-
4
- <target name="clean" depends="-load.properties">
5
- <delete dir="${build.dir}" quiet="true"/>
6
- </target>
7
-
8
- <target name="-load.properties">
9
- <property file="ant.properties"/>
10
- </target>
11
-
12
- <target name="-init" depends="-load.properties">
13
- <mkdir dir="${build.dir}"/>
14
- </target>
15
-
16
- <target name="build.classes" depends="-init">
17
- <mkdir dir="${build.dir}/classes"/>
18
- <javac srcdir="${src.dir}"
19
- destdir="${build.dir}/classes"
20
- includes="**/*.java"
21
- deprecation="off"
22
- debug="on"
23
- source="1.4">
24
- <classpath>
25
- <pathelement location="${lib.dir}/jargs-1.0.jar"/>
26
- <pathelement location="${lib.dir}/rhino-1.6R7.jar"/>
27
- </classpath>
28
- </javac>
29
- </target>
30
-
31
- <target name="build.jar" depends="build.classes">
32
- <mkdir dir="${build.dir}/jar"/>
33
- <!-- The order is important here. Rhino MUST be unjarred first!
34
- (some of our own classes will override the Rhino classes) -->
35
- <unjar src="${lib.dir}/jargs-1.0.jar" dest="${build.dir}/jar"/>
36
- <unjar src="${lib.dir}/rhino-1.6R7.jar" dest="${build.dir}/jar"/>
37
- <copy todir="${build.dir}/jar">
38
- <fileset dir="${build.dir}/classes" includes="**/*.class"/>
39
- </copy>
40
- <jar destfile="${build.dir}/${jar.name}" basedir="${build.dir}/jar">
41
- <manifest>
42
- <attribute name="Main-Class" value="com.yahoo.platform.yui.compressor.Bootstrap"/>
43
- </manifest>
44
- </jar>
45
- </target>
46
-
47
- <target name="build.dist.package" depends="build.jar">
48
- <mkdir dir="${build.dir}/${dist.package.name}"/>
49
- <mkdir dir="${build.dir}/${dist.package.name}/build"/>
50
- <copy file="${build.dir}/${jar.name}" todir="${build.dir}/${dist.package.name}/build"/>
51
- <copy todir="${build.dir}/${dist.package.name}">
52
- <fileset dir=".">
53
- <include name="ant.properties"/>
54
- <include name="build.xml"/>
55
- <include name="LICENSE.TXT"/>
56
- <include name="doc/**/*"/>
57
- <include name="lib/**/*"/>
58
- <include name="ports/**/*"/>
59
- <include name="src/**/*"/>
60
- <include name="tests/**/*"/>
61
- <exclude name="**/.git"/>
62
- </fileset>
63
- </copy>
64
- <zip destfile="${build.dir}/${dist.package.name}.zip"
65
- basedir="${build.dir}"
66
- includes="${dist.package.name}/**/*"/>
67
- </target>
68
-
69
- </project>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
lib/Diglin/yuicompressor-2.4.6/doc/CHANGELOG DELETED
@@ -1,257 +0,0 @@
1
- YUI Compressor 2.4.6, 2011-04-15
2
- -------------------------------
3
- + Show usage information when started without arguments.
4
-
5
- YUI Compressor 2.4.5, 2011-03-13
6
- -------------------------------
7
- + Default file encoding changed from system default to UTF-8.
8
- + Errors/messages/usage info all are sent to stderr.
9
- + Removed unnecessary warning about short undeclared global symbols.
10
- + Added support for processing multiple files with a single invokation
11
- + $ in CSS files doesn't throw exceptions
12
- + white space in ! important comments preserved in CSS
13
- + fix in greedy empty CSS declaration blocks removal
14
- + safe handling of strings and comments in CSS files
15
- + shorter alpha opacity CSS filers
16
- + shorter Mac/IE5 hack -> /*\*/ hack {mac: 1} /**/
17
- + JS port of the CSS minifier
18
- + safe @media queries handling
19
- + stripping the trailing ; in CSS declaration blocks
20
- + shorter border:none->0 where applicable
21
- + fixed transform-origin: 0 0 [bug 2528060]
22
- + tests++
23
-
24
- YUI Compressor 2.4.4, 2010-10-20
25
- + Interim 2.4.5 release
26
-
27
- YUI Compressor 2.4.3, 2009-12-07
28
- -------------------------------
29
- + Changed custodian to ci-tools@
30
-
31
-
32
- YUI Compressor 2.4.2, 2008-11-10
33
- --------------------------------
34
- + Preserved comments shouldn't prevent obfuscation (Thanks to Matjaz Lipus)
35
-
36
-
37
- YUI Compressor 2.4.1, 2008-10-28
38
- --------------------------------
39
-
40
- + Use preferentially lower case letters for obfuscated variable names.
41
- Since JavaScript keywords use lower case letters most often, this
42
- improves the efficiency of any compression algorithm (gzipping)
43
- used after minification.
44
- + Don't append a semi-colon at the end of a JavaScript file when the
45
- last token is a special comment.
46
-
47
- YUI Compressor 2.4, 2008-10-21
48
- ------------------------------
49
-
50
- + Allowed the YUI Compressor (which uses a modified version of Rhino)
51
- to work alongside the original (unmodified) rhino library by using
52
- a custom class loader.
53
- + Added all that's necessary to build the YUI Compressor to the
54
- downloable package.
55
- + Fixed unnecessary white space after return / typeof when possible.
56
-
57
- YUI Compressor 2.3.6, 2008-07-10
58
- --------------------------------
59
-
60
- + Fixed a few minor bugs with the CSS compressor
61
- + Changed packaging. The original Rhino library, which is used to build the
62
- YUI Compressor, is not part of the downloadable archive. Too many people
63
- put it in their classpath, generating a lot of invalid bugs.
64
-
65
- YUI Compressor 2.3.5, 2008-02-08
66
- --------------------------------
67
-
68
- + Added a warning when more than one 'var' statement is used in a single scope.
69
- Automatic coalescence is extremely complicated, and would be unsafe if not
70
- done properly.
71
-
72
- YUI Compressor 2.3.4, 2008-02-07
73
- --------------------------------
74
-
75
- + Expanded the list of reserved words used by isValidIdentifier()
76
-
77
- YUI Compressor 2.3.3, 2008-02-04
78
- --------------------------------
79
-
80
- + C-style comments starting with /*! are preserved. This is especially
81
- useful with comments containing copyright/license information.
82
-
83
- YUI Compressor 2.3.2, 2008-02-01
84
- --------------------------------
85
-
86
- + Compressing an empty JS file throws an error [SourceForge bug #1884207]
87
- + When a string is the first token in a function body, it was removed from
88
- the compressed file [SourceForge bug #1884314]
89
-
90
- YUI Compressor 2.3.1, 2008-01-30
91
- --------------------------------
92
-
93
- + Added test against list of reserved words in method isValidIdentifier.
94
-
95
- YUI Compressor 2.3, 2008-01-28
96
- ------------------------------
97
-
98
- + Always output a ';' at the end of a minified JavaScript file. This allows
99
- the concatenating of several minified files without the fear of introducing
100
- a syntax error.
101
- + Removed all System.exit() statements. Throw exceptions instead. This is
102
- especially useful when running the compressor from within a J2EE container.
103
- [SourceForge bug #1834750]
104
- + Transform obj["foo"] into obj.foo whenever possible, saving 3 bytes.
105
- + Transform 'foo': ... into foo: ... whenever possible, saving 2 bytes.
106
- + Added support for multi-line string literals [SourceForge bug #1871453]
107
- + Added support for unescaped slashes inside character classes in regexp.
108
- + Minor performance improvements.
109
- + Preserve the escaping for an octal representation of a character in string
110
- literals [SourceForge bug #1844894]
111
-
112
- var a = '\001';
113
-
114
- + CSS: Preserve comments that hide CSS rules from IE Mac:
115
-
116
- /* Hides from IE-mac \*/
117
- ...
118
- /* End hide from IE-mac */
119
-
120
- + CSS: Added support for box model hack [SourceForge bug #1862107]
121
-
122
- div.content {
123
- width:400px;
124
- voice-family: "\"}\"";
125
- voice-family:inherit;
126
- width:300px;
127
- }
128
-
129
- YUI Compressor 2.2.5, 2007-10-09
130
- --------------------------------
131
-
132
- + Remove line terminator after escape in string literals.
133
-
134
- YUI Compressor 2.2.4, 2007-10-01
135
- --------------------------------
136
-
137
- + Fixed the way quote characters are counted in string literals
138
- [SourceForge bug #1804576]
139
- + Do not use a regular expression using non-greedy matching to remove CSS
140
- comments (if the comment is more than 800 characters long or so, a stack
141
- overflow exception gets thrown) Instead, use good old parsing...
142
- + Fix unnecessary quote escaping in string literals.
143
-
144
- YUI Compressor 2.2.3, 2007-09-28
145
- --------------------------------
146
-
147
- + Transform </script into <\/script instead of replacing all </ into <\/.
148
- + Fixed bug related to the shortening of hexadecimal color codes (the string
149
- "1px solid #aabbcc" became "1px solid#abc", missing a required white space)
150
- + Added --preserve-strings option to specify that concatenated string literals
151
- should never be merged.
152
- + Do not convert \uXXXX and \xXX escape sequences to their unicode equivalent.
153
-
154
- YUI Compressor 2.2.2, 2007-09-27
155
- --------------------------------
156
-
157
- + Fixed regression related to the optimization of the amount of escaping
158
- in string literals and the concatenation of string literals.
159
- + Modified the Rhino tokenizer to handle JScript conditional comments
160
- natively (instead of hacking around the fact that Rhino is not keeping
161
- track of comments)
162
- + Transform </ into <\/ in string literals. This is especially useful if the
163
- code is written to a script block in an HTML document. This renders the old
164
- hack '<scr'+'ipt ...><'+'/script>' completely useless.
165
- + When converting decimal rgb color values to hexadecimal color values,
166
- prepend a '0' if the value is less than 16. Otherwise, rgb(0,124,114)
167
- for instance becomes #07c72, which is incorrect.
168
- + In CSS files, do not change color names into their corresponding color
169
- codes (and vice-versa) due to the high potential of introducing bugs
170
- (rolled back from 2.2.1)
171
-
172
- YUI Compressor 2.2.1, 2007-09-25
173
- --------------------------------
174
-
175
- + Optimize quote escaping in JavaScript string literals by using the best quote
176
- character (' or " depending on the occurrence of this character in the string)
177
- + Fixed minor bug in the CSS compressor. Colors should not be shortened in
178
- filter: chroma(color="#FFFFFF");
179
- Otherwise, it makes the filter break in Internet Explorer.
180
- + In CSS files, change color names into their corresponding color codes
181
- (and vice-versa) if that change yields any savings.
182
-
183
- YUI Compressor 2.2, 2007-09-18
184
- ------------------------------
185
-
186
- + Don't obfuscate function argument named $super if it is the first function
187
- argument listed. This is to support Prototype 1.6's heretic implementation.
188
- + Added support for stdin/stdout (see README for more info)
189
- + Shorten colors from rgb(51,102,153) to #336699 in CSS files.
190
- + Shorten values from 0.8em to .8em in CSS files.
191
- + Added support for Internet Explorer's conditional comments in JavaScript
192
- files. Note that the presence of a conditional comment inside a function
193
- (i.e. not in the global scope) will reduce the level of compression for the
194
- same reason the use of 'eval' or 'with' reduces the level of compression
195
- (conditional comments, which do not get parsed, may refer to local variables,
196
- which get obfuscated) In any case, the use of Internet Explorer's conditional
197
- comment is to be avoided.
198
-
199
- YUI Compressor 2.1.2, 2007-08-31
200
- --------------------------------
201
-
202
- + Added --preserve-semi option
203
- + Modified --line-break option
204
-
205
- YUI Compressor 2.1.1, 2007-08-30
206
- --------------------------------
207
-
208
- + Fixed missing space in CSS background:url('foo.png')no-repeat
209
- causing a background not to appear on Internet Explorer.
210
-
211
- YUI Compressor 2.1, 2007-08-29
212
- ------------------------------
213
-
214
- + Pass the --line-break option to the CSS compressor.
215
- + Allow the output file to overwrite the input file (with version 2.0,
216
- in this case, the output file was always empty)
217
- + Remove spaces before and after '(' and ')' as in background:url('xxx');
218
- + Merge (if possible) string literals that are appended in JavaScript files.
219
- This not only makes the code smaller, it makes the code faster,
220
- but allows you to maintain some readability in your source code.
221
- + Handle constructs such as a + ++ b or a + + "1" (in which case the
222
- space between the operators must be kept!) and other similar cases...
223
- + Pass ErrorReporter instance to the constructor of class JavaScriptCompressor
224
- (as suggested by David Bernard for his integration of the YUI Compressor
225
- as a maven plugin)
226
-
227
- YUI Compressor 2.0, 2007-08-27
228
- ------------------------------
229
-
230
- + Switched from Rhino 1.6R6 to Rhino 1.6R7
231
- + Integrated Isaac Schlueter's CSS compressor.
232
- + Refactored code to make it easier to use the compressor from a servlet
233
- environment or another Java app (no need to pass in file names anymore)
234
- + Output a white-space character after 'throw' only when necessary.
235
- + Output a white-space character after 'break' and 'continue' when followed
236
- by a label.
237
-
238
- YUI Compressor 1.1, 2007-08-20
239
- ------------------------------
240
-
241
- + Java source now in package com.yahoo.platform.yui.compressor
242
- + Added --line-break option that adds a line feed character after each
243
- semi-colon character (may help debugging with the MS Script debugger)
244
- + Added support for missing JavaScript features (get, set, const)
245
- + Do not show the entire stack trace when the input file cannot be found.
246
- + Removed the randomization of obfuscated symbols. When compressed code is
247
- checked in CVS, unchanged files would otherwise end up being versioned.
248
- + Added web-based front-end to the YUI Compressor as part of the dist package.
249
- + Added a public entry point that makes the YUI Compressor easy to integrate
250
- with an already existing Java application.
251
- + Simplified code by using the same parsing routines used to build the symbol
252
- tree while looking for undeclared symbols.
253
- + Count how many times each identifier is used, and display a warning when an
254
- identifier seems to be unused (code cannot safely be removed automatically)
255
- + Remove ';' when followed by a '}'. This yields an additional ~1.5% savings
256
- on yahoo-dom-event.js compared to the JSMin version.
257
- + Output a white-space character after 'return' and 'case' only when necessary.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
lib/Diglin/yuicompressor-2.4.6/doc/README DELETED
@@ -1,145 +0,0 @@
1
- ==============================================================================
2
- YUI Compressor
3
- ==============================================================================
4
-
5
- NAME
6
-
7
- YUI Compressor - The Yahoo! JavaScript and CSS Compressor
8
-
9
- SYNOPSIS
10
-
11
- Usage: java -jar yuicompressor-x.y.z.jar [options] [input file]
12
-
13
- Global Options
14
- -h, --help Displays this information
15
- --type <js|css> Specifies the type of the input file
16
- --charset <charset> Read the input file using <charset>
17
- --line-break <column> Insert a line break after the specified column number
18
- -v, --verbose Display informational messages and warnings
19
- -o <file> Place the output into <file> or a file pattern.
20
- Defaults to stdout.
21
-
22
- JavaScript Options
23
- --nomunge Minify only, do not obfuscate
24
- --preserve-semi Preserve all semicolons
25
- --disable-optimizations Disable all micro optimizations
26
-
27
- DESCRIPTION
28
-
29
- The YUI Compressor is a JavaScript compressor which, in addition to removing
30
- comments and white-spaces, obfuscates local variables using the smallest
31
- possible variable name. This obfuscation is safe, even when using constructs
32
- such as 'eval' or 'with' (although the compression is not optimal is those
33
- cases) Compared to jsmin, the average savings is around 20%.
34
-
35
- The YUI Compressor is also able to safely compress CSS files. The decision
36
- on which compressor is being used is made on the file extension (js or css)
37
-
38
- GLOBAL OPTIONS
39
-
40
- -h, --help
41
- Prints help on how to use the YUI Compressor
42
-
43
- --line-break
44
- Some source control tools don't like files containing lines longer than,
45
- say 8000 characters. The linebreak option is used in that case to split
46
- long lines after a specific column. It can also be used to make the code
47
- more readable, easier to debug (especially with the MS Script Debugger)
48
- Specify 0 to get a line break after each semi-colon in JavaScript, and
49
- after each rule in CSS.
50
-
51
- --type js|css
52
- The type of compressor (JavaScript or CSS) is chosen based on the
53
- extension of the input file name (.js or .css) This option is required
54
- if no input file has been specified. Otherwise, this option is only
55
- required if the input file extension is neither 'js' nor 'css'.
56
-
57
- --charset character-set
58
- If a supported character set is specified, the YUI Compressor will use it
59
- to read the input file. Otherwise, it will assume that the platform's
60
- default character set is being used. The output file is encoded using
61
- the same character set.
62
-
63
- -o outfile
64
-
65
- Place output in file outfile. If not specified, the YUI Compressor will
66
- default to the standard output, which you can redirect to a file.
67
- Supports a filter syntax for expressing the output pattern when there are
68
- multiple input files. ex:
69
- java -jar yuicompressor.jar -o '.css$:-min.css' *.css
70
- ... will minify all .css files and save them as -min.css
71
-
72
- -v, --verbose
73
- Display informational messages and warnings.
74
-
75
- JAVASCRIPT ONLY OPTIONS
76
-
77
- --nomunge
78
- Minify only. Do not obfuscate local symbols.
79
-
80
- --preserve-semi
81
- Preserve unnecessary semicolons (such as right before a '}') This option
82
- is useful when compressed code has to be run through JSLint (which is the
83
- case of YUI for example)
84
-
85
- --disable-optimizations
86
- Disable all the built-in micro optimizations.
87
-
88
- NOTES
89
-
90
- + If no input file is specified, it defaults to stdin.
91
-
92
- + Supports wildcards for specifying multiple input files.
93
-
94
- + The YUI Compressor requires Java version >= 1.4.
95
-
96
- + It is possible to prevent a local variable, nested function or function
97
- argument from being obfuscated by using "hints". A hint is a string that
98
- is located at the very beginning of a function body like so:
99
-
100
- function fn (arg1, arg2, arg3) {
101
- "arg2:nomunge, localVar:nomunge, nestedFn:nomunge";
102
-
103
- ...
104
- var localVar;
105
- ...
106
-
107
- function nestedFn () {
108
- ....
109
- }
110
-
111
- ...
112
- }
113
-
114
- The hint itself disappears from the compressed file.
115
-
116
- + C-style comments starting with /*! are preserved. This is useful with
117
- comments containing copyright/license information. For example:
118
-
119
- /*!
120
- * TERMS OF USE - EASING EQUATIONS
121
- * Open source under the BSD License.
122
- * Copyright 2001 Robert Penner All rights reserved.
123
- */
124
-
125
- becomes:
126
-
127
- /*
128
- * TERMS OF USE - EASING EQUATIONS
129
- * Open source under the BSD License.
130
- * Copyright 2001 Robert Penner All rights reserved.
131
- */
132
-
133
- MODIFIED RHINO FILES
134
-
135
- YUI Compressor uses a modified version of the Rhino library
136
- (http://www.mozilla.org/rhino/) The changes were made to support
137
- JScript conditional comments, preserved comments, unescaped slash
138
- characters in regular expressions, and to allow for the optimization
139
- of escaped quotes in string literals.
140
-
141
- COPYRIGHT AND LICENSE
142
-
143
- Copyright (c) 2011 Yahoo! Inc. All rights reserved.
144
- The copyrights embodied in the content of this file are licensed
145
- by Yahoo! Inc. under the BSD (revised) open source license.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
lib/Diglin/yuicompressor-2.4.6/lib/jargs-1.0.jar DELETED
Binary file
lib/Diglin/yuicompressor-2.4.6/ports/js/cssmin.js DELETED
@@ -1,231 +0,0 @@
1
- /**
2
- * cssmin.js
3
- * Author: Stoyan Stefanov - http://phpied.com/
4
- * This is a JavaScript port of the CSS minification tool
5
- * distributed with YUICompressor, itself a port
6
- * of the cssmin utility by Isaac Schlueter - http://foohack.com/
7
- * Permission is hereby granted to use the JavaScript version under the same
8
- * conditions as the YUICompressor (original YUICompressor note below).
9
- */
10
-
11
- /*
12
- * YUI Compressor
13
- * http://developer.yahoo.com/yui/compressor/
14
- * Author: Julien Lecomte - http://www.julienlecomte.net/
15
- * Copyright (c) 2011 Yahoo! Inc. All rights reserved.
16
- * The copyrights embodied in the content of this file are licensed
17
- * by Yahoo! Inc. under the BSD (revised) open source license.
18
- */
19
- var YAHOO = YAHOO || {};
20
- YAHOO.compressor = YAHOO.compressor || {};
21
- YAHOO.compressor.cssmin = function (css, linebreakpos) {
22
-
23
- var startIndex = 0,
24
- endIndex = 0,
25
- i = 0, max = 0,
26
- preservedTokens = [],
27
- comments = [],
28
- token = '',
29
- totallen = css.length,
30
- placeholder = '';
31
-
32
- // collect all comment blocks...
33
- while ((startIndex = css.indexOf("/*", startIndex)) >= 0) {
34
- endIndex = css.indexOf("*/", startIndex + 2);
35
- if (endIndex < 0) {
36
- endIndex = totallen;
37
- }
38
- token = css.slice(startIndex + 2, endIndex);
39
- comments.push(token);
40
- css = css.slice(0, startIndex + 2) + "___YUICSSMIN_PRESERVE_CANDIDATE_COMMENT_" + (comments.length - 1) + "___" + css.slice(endIndex);
41
- startIndex += 2;
42
- }
43
-
44
- // preserve strings so their content doesn't get accidentally minified
45
- css = css.replace(/("([^\\"]|\\.|\\)*")|('([^\\']|\\.|\\)*')/g, function (match) {
46
- var i, max, quote = match.substring(0, 1);
47
-
48
- match = match.slice(1, -1);
49
-
50
- // maybe the string contains a comment-like substring?
51
- // one, maybe more? put'em back then
52
- if (match.indexOf("___YUICSSMIN_PRESERVE_CANDIDATE_COMMENT_") >= 0) {
53
- for (i = 0, max = comments.length; i < max; i = i + 1) {
54
- match = match.replace("___YUICSSMIN_PRESERVE_CANDIDATE_COMMENT_" + i + "___", comments[i]);
55
- }
56
- }
57
-
58
- // minify alpha opacity in filter strings
59
- match = match.replace(/progid:DXImageTransform\.Microsoft\.Alpha\(Opacity=/gi, "alpha(opacity=");
60
-
61
- preservedTokens.push(match);
62
- return quote + "___YUICSSMIN_PRESERVED_TOKEN_" + (preservedTokens.length - 1) + "___" + quote;
63
- });
64
-
65
- // strings are safe, now wrestle the comments
66
- for (i = 0, max = comments.length; i < max; i = i + 1) {
67
-
68
- token = comments[i];
69
- placeholder = "___YUICSSMIN_PRESERVE_CANDIDATE_COMMENT_" + i + "___";
70
-
71
- // ! in the first position of the comment means preserve
72
- // so push to the preserved tokens keeping the !
73
- if (token.charAt(0) === "!") {
74
- preservedTokens.push(token);
75
- css = css.replace(placeholder, "___YUICSSMIN_PRESERVED_TOKEN_" + (preservedTokens.length - 1) + "___");
76
- continue;
77
- }
78
-
79
- // \ in the last position looks like hack for Mac/IE5
80
- // shorten that to /*\*/ and the next one to /**/
81
- if (token.charAt(token.length - 1) === "\\") {
82
- preservedTokens.push("\\");
83
- css = css.replace(placeholder, "___YUICSSMIN_PRESERVED_TOKEN_" + (preservedTokens.length - 1) + "___");
84
- i = i + 1; // attn: advancing the loop
85
- preservedTokens.push("");
86
- css = css.replace("___YUICSSMIN_PRESERVE_CANDIDATE_COMMENT_" + i + "___", "___YUICSSMIN_PRESERVED_TOKEN_" + (preservedTokens.length - 1) + "___");
87
- continue;
88
- }
89
-
90
- // keep empty comments after child selectors (IE7 hack)
91
- // e.g. html >/**/ body
92
- if (token.length === 0) {
93
- startIndex = css.indexOf(placeholder);
94
- if (startIndex > 2) {
95
- if (css.charAt(startIndex - 3) === '>') {
96
- preservedTokens.push("");
97
- css = css.replace(placeholder, "___YUICSSMIN_PRESERVED_TOKEN_" + (preservedTokens.length - 1) + "___");
98
- }
99
- }
100
- }
101
-
102
- // in all other cases kill the comment
103
- css = css.replace("/*" + placeholder + "*/", "");
104
- }
105
-
106
-
107
- // Normalize all whitespace strings to single spaces. Easier to work with that way.
108
- css = css.replace(/\s+/g, " ");
109
-
110
- // Remove the spaces before the things that should not have spaces before them.
111
- // But, be careful not to turn "p :link {...}" into "p:link{...}"
112
- // Swap out any pseudo-class colons with the token, and then swap back.
113
- css = css.replace(/(^|\})(([^\{:])+:)+([^\{]*\{)/g, function (m) {
114
- return m.replace(":", "___YUICSSMIN_PSEUDOCLASSCOLON___");
115
- });
116
- css = css.replace(/\s+([!{};:>+\(\)\],])/g, '$1');
117
- css = css.replace(/___YUICSSMIN_PSEUDOCLASSCOLON___/g, ":");
118
-
119
- // retain space for special IE6 cases
120
- css = css.replace(/:first-(line|letter)(\{|,)/g, ":first-$1 $2");
121
-
122
- // no space after the end of a preserved comment
123
- css = css.replace(/\*\/ /g, '*/');
124
-
125
-
126
- // If there is a @charset, then only allow one, and push to the top of the file.
127
- css = css.replace(/^(.*)(@charset "[^"]*";)/gi, '$2$1');
128
- css = css.replace(/^(\s*@charset [^;]+;\s*)+/gi, '$1');
129
-
130
- // Put the space back in some cases, to support stuff like
131
- // @media screen and (-webkit-min-device-pixel-ratio:0){
132
- css = css.replace(/\band\(/gi, "and (");
133
-
134
-
135
- // Remove the spaces after the things that should not have spaces after them.
136
- css = css.replace(/([!{}:;>+\(\[,])\s+/g, '$1');
137
-
138
- // remove unnecessary semicolons
139
- css = css.replace(/;+\}/g, "}");
140
-
141
- // Replace 0(px,em,%) with 0.
142
- css = css.replace(/([\s:])(0)(px|em|%|in|cm|mm|pc|pt|ex)/gi, "$1$2");
143
-
144
- // Replace 0 0 0 0; with 0.
145
- css = css.replace(/:0 0 0 0(;|\})/g, ":0$1");
146
- css = css.replace(/:0 0 0(;|\})/g, ":0$1");
147
- css = css.replace(/:0 0(;|\})/g, ":0$1");
148
-
149
- // Replace background-position:0; with background-position:0 0;
150
- // same for transform-origin
151
- css = css.replace(/(background-position|transform-origin|webkit-transform-origin|moz-transform-origin|o-transform-origin|ms-transform-origin):0(;|\})/gi, function(all, prop, tail) {
152
- return prop.toLowerCase() + ":0 0" + tail;
153
- });
154
-
155
- // Replace 0.6 to .6, but only when preceded by : or a white-space
156
- css = css.replace(/(:|\s)0+\.(\d+)/g, "$1.$2");
157
-
158
- // Shorten colors from rgb(51,102,153) to #336699
159
- // This makes it more likely that it'll get further compressed in the next step.
160
- css = css.replace(/rgb\s*\(\s*([0-9,\s]+)\s*\)/gi, function () {
161
- var i, rgbcolors = arguments[1].split(',');
162
- for (i = 0; i < rgbcolors.length; i = i + 1) {
163
- rgbcolors[i] = parseInt(rgbcolors[i], 10).toString(16);
164
- if (rgbcolors[i].length === 1) {
165
- rgbcolors[i] = '0' + rgbcolors[i];
166
- }
167
- }
168
- return '#' + rgbcolors.join('');
169
- });
170
-
171
-
172
- // Shorten colors from #AABBCC to #ABC. Note that we want to make sure
173
- // the color is not preceded by either ", " or =. Indeed, the property
174
- // filter: chroma(color="#FFFFFF");
175
- // would become
176
- // filter: chroma(color="#FFF");
177
- // which makes the filter break in IE.
178
- css = css.replace(/([^"'=\s])(\s*)#([0-9a-f])([0-9a-f])([0-9a-f])([0-9a-f])([0-9a-f])([0-9a-f])/gi, function () {
179
- var group = arguments;
180
- if (
181
- group[3].toLowerCase() === group[4].toLowerCase() &&
182
- group[5].toLowerCase() === group[6].toLowerCase() &&
183
- group[7].toLowerCase() === group[8].toLowerCase()
184
- ) {
185
- return (group[1] + group[2] + '#' + group[3] + group[5] + group[7]).toLowerCase();
186
- } else {
187
- return group[0].toLowerCase();
188
- }
189
- });
190
-
191
- // border: none -> border:0
192
- css = css.replace(/(border|border-top|border-right|border-bottom|border-right|outline|background):none(;|\})/gi, function(all, prop, tail) {
193
- return prop.toLowerCase() + ":0" + tail;
194
- });
195
-
196
- // shorter opacity IE filter
197
- css = css.replace(/progid:DXImageTransform\.Microsoft\.Alpha\(Opacity=/gi, "alpha(opacity=");
198
-
199
- // Remove empty rules.
200
- css = css.replace(/[^\};\{\/]+\{\}/g, "");
201
-
202
- if (linebreakpos >= 0) {
203
- // Some source control tools don't like it when files containing lines longer
204
- // than, say 8000 characters, are checked in. The linebreak option is used in
205
- // that case to split long lines after a specific column.
206
- startIndex = 0;
207
- i = 0;
208
- while (i < css.length) {
209
- i = i + 1;
210
- if (css[i - 1] === '}' && i - startIndex > linebreakpos) {
211
- css = css.slice(0, i) + '\n' + css.slice(i);
212
- startIndex = i;
213
- }
214
- }
215
- }
216
-
217
- // Replace multiple semi-colons in a row by a single one
218
- // See SF bug #1980989
219
- css = css.replace(/;;+/g, ";");
220
-
221
- // restore preserved comments and strings
222
- for (i = 0, max = preservedTokens.length; i < max; i = i + 1) {
223
- css = css.replace("___YUICSSMIN_PRESERVED_TOKEN_" + i + "___", preservedTokens[i]);
224
- }
225
-
226
- // Trim the final string (for any leading or trailing white spaces)
227
- css = css.replace(/^\s+|\s+$/g, "");
228
-
229
- return css;
230
-
231
- };
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
lib/Diglin/yuicompressor-2.4.6/src/com/yahoo/platform/yui/compressor/Bootstrap.java DELETED
@@ -1,23 +0,0 @@
1
- /*
2
- * YUI Compressor
3
- * http://developer.yahoo.com/yui/compressor/
4
- * Author: Julien Lecomte - http://www.julienlecomte.net/
5
- * Copyright (c) 2011 Yahoo! Inc. All rights reserved.
6
- * The copyrights embodied in the content of this file are licensed
7
- * by Yahoo! Inc. under the BSD (revised) open source license.
8
- */
9
-
10
- package com.yahoo.platform.yui.compressor;
11
-
12
- import java.lang.reflect.Method;
13
-
14
- public class Bootstrap {
15
-
16
- public static void main(String args[]) throws Exception {
17
- ClassLoader loader = new JarClassLoader();
18
- Thread.currentThread().setContextClassLoader(loader);
19
- Class c = loader.loadClass(YUICompressor.class.getName());
20
- Method main = c.getMethod("main", new Class[]{String[].class});
21
- main.invoke(null, new Object[]{args});
22
- }
23
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
lib/Diglin/yuicompressor-2.4.6/src/com/yahoo/platform/yui/compressor/CssCompressor.java DELETED
@@ -1,304 +0,0 @@
1
- /*
2
- * YUI Compressor
3
- * http://developer.yahoo.com/yui/compressor/
4
- * Author: Julien Lecomte - http://www.julienlecomte.net/
5
- * Author: Isaac Schlueter - http://foohack.com/
6
- * Author: Stoyan Stefanov - http://phpied.com/
7
- * Copyright (c) 2011 Yahoo! Inc. All rights reserved.
8
- * The copyrights embodied in the content of this file are licensed
9
- * by Yahoo! Inc. under the BSD (revised) open source license.
10
- */
11
- package com.yahoo.platform.yui.compressor;
12
-
13
- import java.io.IOException;
14
- import java.io.Reader;
15
- import java.io.Writer;
16
- import java.util.regex.Pattern;
17
- import java.util.regex.Matcher;
18
- import java.util.ArrayList;
19
-
20
- public class CssCompressor {
21
-
22
- private StringBuffer srcsb = new StringBuffer();
23
-
24
- public CssCompressor(Reader in) throws IOException {
25
- // Read the stream...
26
- int c;
27
- while ((c = in.read()) != -1) {
28
- srcsb.append((char) c);
29
- }
30
- }
31
-
32
- public void compress(Writer out, int linebreakpos)
33
- throws IOException {
34
-
35
- Pattern p;
36
- Matcher m;
37
- String css = srcsb.toString();
38
- StringBuffer sb = new StringBuffer(css);
39
-
40
- int startIndex = 0;
41
- int endIndex = 0;
42
- int i = 0;
43
- int max = 0;
44
- ArrayList preservedTokens = new ArrayList(0);
45
- ArrayList comments = new ArrayList(0);
46
- String token;
47
- int totallen = css.length();
48
- String placeholder;
49
-
50
- // // leave data urls alone to increase parse performance.
51
- // sb = new StringBuffer();
52
- // p = Pattern.compile("url\\(.*data\\:(.*)\\)");
53
- // m = p.matcher(css);
54
- // while (m.find()) {
55
- // token = m.group();
56
- // token = token.substring(1, token.length() - 1);
57
- // preservedTokens.add(token);
58
- // String preserver = "___YUICSSMIN_PRESERVED_TOKEN_" + (preservedTokens.size() - 1) + "___";
59
- // m.appendReplacement(sb, preserver);
60
- // }
61
- // m.appendTail(sb);
62
- // css = sb.toString();
63
-
64
- // collect all comment blocks...
65
- while ((startIndex = sb.indexOf("/*", startIndex)) >= 0) {
66
- endIndex = sb.indexOf("*/", startIndex + 2);
67
- if (endIndex < 0) {
68
- endIndex = totallen;
69
- }
70
-
71
- token = sb.substring(startIndex + 2, endIndex);
72
- comments.add(token);
73
- sb.replace(startIndex + 2, endIndex, "___YUICSSMIN_PRESERVE_CANDIDATE_COMMENT_" + (comments.size() - 1) + "___");
74
- startIndex += 2;
75
- }
76
- css = sb.toString();
77
-
78
- // preserve strings so their content doesn't get accidentally minified
79
- sb = new StringBuffer();
80
- p = Pattern.compile("(\"([^\\\\\"]|\\\\.|\\\\)*\")|(\'([^\\\\\']|\\\\.|\\\\)*\')");
81
- m = p.matcher(css);
82
- while (m.find()) {
83
- token = m.group();
84
- char quote = token.charAt(0);
85
- token = token.substring(1, token.length() - 1);
86
-
87
- // maybe the string contains a comment-like substring?
88
- // one, maybe more? put'em back then
89
- if (token.indexOf("___YUICSSMIN_PRESERVE_CANDIDATE_COMMENT_") >= 0) {
90
- for (i = 0, max = comments.size(); i < max; i += 1) {
91
- token = token.replace("___YUICSSMIN_PRESERVE_CANDIDATE_COMMENT_" + i + "___", comments.get(i).toString());
92
- }
93
- }
94
-
95
- // minify alpha opacity in filter strings
96
- token = token.replaceAll("(?i)progid:DXImageTransform.Microsoft.Alpha\\(Opacity=", "alpha(opacity=");
97
-
98
- preservedTokens.add(token);
99
- String preserver = quote + "___YUICSSMIN_PRESERVED_TOKEN_" + (preservedTokens.size() - 1) + "___" + quote;
100
- m.appendReplacement(sb, preserver);
101
- }
102
- m.appendTail(sb);
103
- css = sb.toString();
104
-
105
-
106
- // strings are safe, now wrestle the comments
107
- for (i = 0, max = comments.size(); i < max; i += 1) {
108
-
109
- token = comments.get(i).toString();
110
- placeholder = "___YUICSSMIN_PRESERVE_CANDIDATE_COMMENT_" + i + "___";
111
-
112
- // ! in the first position of the comment means preserve
113
- // so push to the preserved tokens while stripping the !
114
- if (token.startsWith("!")) {
115
- preservedTokens.add(token);
116
- css = css.replace(placeholder, "___YUICSSMIN_PRESERVED_TOKEN_" + (preservedTokens.size() - 1) + "___");
117
- continue;
118
- }
119
-
120
- // \ in the last position looks like hack for Mac/IE5
121
- // shorten that to /*\*/ and the next one to /**/
122
- if (token.endsWith("\\")) {
123
- preservedTokens.add("\\");
124
- css = css.replace(placeholder, "___YUICSSMIN_PRESERVED_TOKEN_" + (preservedTokens.size() - 1) + "___");
125
- i = i + 1; // attn: advancing the loop
126
- preservedTokens.add("");
127
- css = css.replace("___YUICSSMIN_PRESERVE_CANDIDATE_COMMENT_" + i + "___", "___YUICSSMIN_PRESERVED_TOKEN_" + (preservedTokens.size() - 1) + "___");
128
- continue;
129
- }
130
-
131
- // keep empty comments after child selectors (IE7 hack)
132
- // e.g. html >/**/ body
133
- if (token.length() == 0) {
134
- startIndex = css.indexOf(placeholder);
135
- if (startIndex > 2) {
136
- if (css.charAt(startIndex - 3) == '>') {
137
- preservedTokens.add("");
138
- css = css.replace(placeholder, "___YUICSSMIN_PRESERVED_TOKEN_" + (preservedTokens.size() - 1) + "___");
139
- }
140
- }
141
- }
142
-
143
- // in all other cases kill the comment
144
- css = css.replace("/*" + placeholder + "*/", "");
145
- }
146
-
147
-
148
- // Normalize all whitespace strings to single spaces. Easier to work with that way.
149
- css = css.replaceAll("\\s+", " ");
150
-
151
- // Remove the spaces before the things that should not have spaces before them.
152
- // But, be careful not to turn "p :link {...}" into "p:link{...}"
153
- // Swap out any pseudo-class colons with the token, and then swap back.
154
- sb = new StringBuffer();
155
- p = Pattern.compile("(^|\\})(([^\\{:])+:)+([^\\{]*\\{)");
156
- m = p.matcher(css);
157
- while (m.find()) {
158
- String s = m.group();
159
- s = s.replaceAll(":", "___YUICSSMIN_PSEUDOCLASSCOLON___");
160
- s = s.replaceAll( "\\\\", "\\\\\\\\" ).replaceAll( "\\$", "\\\\\\$" );
161
- m.appendReplacement(sb, s);
162
- }
163
- m.appendTail(sb);
164
- css = sb.toString();
165
- // Remove spaces before the things that should not have spaces before them.
166
- css = css.replaceAll("\\s+([!{};:>+\\(\\)\\],])", "$1");
167
- // bring back the colon
168
- css = css.replaceAll("___YUICSSMIN_PSEUDOCLASSCOLON___", ":");
169
-
170
- // retain space for special IE6 cases
171
- css = css.replaceAll(":first\\-(line|letter)(\\{|,)", ":first-$1 $2");
172
-
173
- // no space after the end of a preserved comment
174
- css = css.replaceAll("\\*/ ", "*/");
175
-
176
- // If there is a @charset, then only allow one, and push to the top of the file.
177
- css = css.replaceAll("^(.*)(@charset \"[^\"]*\";)", "$2$1");
178
- css = css.replaceAll("^(\\s*@charset [^;]+;\\s*)+", "$1");
179
-
180
- // Put the space back in some cases, to support stuff like
181
- // @media screen and (-webkit-min-device-pixel-ratio:0){
182
- css = css.replaceAll("\\band\\(", "and (");
183
-
184
- // Remove the spaces after the things that should not have spaces after them.
185
- css = css.replaceAll("([!{}:;>+\\(\\[,])\\s+", "$1");
186
-
187
- // remove unnecessary semicolons
188
- css = css.replaceAll(";+}", "}");
189
-
190
- // Replace 0(px,em,%) with 0.
191
- css = css.replaceAll("([\\s:])(0)(px|em|%|in|cm|mm|pc|pt|ex)", "$1$2");
192
-
193
- // Replace 0 0 0 0; with 0.
194
- css = css.replaceAll(":0 0 0 0(;|})", ":0$1");
195
- css = css.replaceAll(":0 0 0(;|})", ":0$1");
196
- css = css.replaceAll(":0 0(;|})", ":0$1");
197
-
198
-
199
- // Replace background-position:0; with background-position:0 0;
200
- // same for transform-origin
201
- sb = new StringBuffer();
202
- p = Pattern.compile("(?i)(background-position|transform-origin|webkit-transform-origin|moz-transform-origin|o-transform-origin|ms-transform-origin):0(;|})");
203
- m = p.matcher(css);
204
- while (m.find()) {
205
- m.appendReplacement(sb, m.group(1).toLowerCase() + ":0 0" + m.group(2));
206
- }
207
- m.appendTail(sb);
208
- css = sb.toString();
209
-
210
- // Replace 0.6 to .6, but only when preceded by : or a white-space
211
- css = css.replaceAll("(:|\\s)0+\\.(\\d+)", "$1.$2");
212
-
213
- // Shorten colors from rgb(51,102,153) to #336699
214
- // This makes it more likely that it'll get further compressed in the next step.
215
- p = Pattern.compile("rgb\\s*\\(\\s*([0-9,\\s]+)\\s*\\)");
216
- m = p.matcher(css);
217
- sb = new StringBuffer();
218
- while (m.find()) {
219
- String[] rgbcolors = m.group(1).split(",");
220
- StringBuffer hexcolor = new StringBuffer("#");
221
- for (i = 0; i < rgbcolors.length; i++) {
222
- int val = Integer.parseInt(rgbcolors[i]);
223
- if (val < 16) {
224
- hexcolor.append("0");
225
- }
226
- hexcolor.append(Integer.toHexString(val));
227
- }
228
- m.appendReplacement(sb, hexcolor.toString());
229
- }
230
- m.appendTail(sb);
231
- css = sb.toString();
232
-
233
- // Shorten colors from #AABBCC to #ABC. Note that we want to make sure
234
- // the color is not preceded by either ", " or =. Indeed, the property
235
- // filter: chroma(color="#FFFFFF");
236
- // would become
237
- // filter: chroma(color="#FFF");
238
- // which makes the filter break in IE.
239
- p = Pattern.compile("([^\"'=\\s])(\\s*)#([0-9a-fA-F])([0-9a-fA-F])([0-9a-fA-F])([0-9a-fA-F])([0-9a-fA-F])([0-9a-fA-F])");
240
- m = p.matcher(css);
241
- sb = new StringBuffer();
242
- while (m.find()) {
243
- // Test for AABBCC pattern
244
- if (m.group(3).equalsIgnoreCase(m.group(4)) &&
245
- m.group(5).equalsIgnoreCase(m.group(6)) &&
246
- m.group(7).equalsIgnoreCase(m.group(8))) {
247
- m.appendReplacement(sb, (m.group(1) + m.group(2) + "#" + m.group(3) + m.group(5) + m.group(7)).toLowerCase());
248
- } else {
249
- m.appendReplacement(sb, m.group().toLowerCase());
250
- }
251
- }
252
- m.appendTail(sb);
253
- css = sb.toString();
254
-
255
- // border: none -> border:0
256
- sb = new StringBuffer();
257
- p = Pattern.compile("(?i)(border|border-top|border-right|border-bottom|border-right|outline|background):none(;|})");
258
- m = p.matcher(css);
259
- while (m.find()) {
260
- m.appendReplacement(sb, m.group(1).toLowerCase() + ":0" + m.group(2));
261
- }
262
- m.appendTail(sb);
263
- css = sb.toString();
264
-
265
- // shorter opacity IE filter
266
- css = css.replaceAll("(?i)progid:DXImageTransform.Microsoft.Alpha\\(Opacity=", "alpha(opacity=");
267
-
268
- // Remove empty rules.
269
- css = css.replaceAll("[^\\}\\{/;]+\\{\\}", "");
270
-
271
- if (linebreakpos >= 0) {
272
- // Some source control tools don't like it when files containing lines longer
273
- // than, say 8000 characters, are checked in. The linebreak option is used in
274
- // that case to split long lines after a specific column.
275
- i = 0;
276
- int linestartpos = 0;
277
- sb = new StringBuffer(css);
278
- while (i < sb.length()) {
279
- char c = sb.charAt(i++);
280
- if (c == '}' && i - linestartpos > linebreakpos) {
281
- sb.insert(i, '\n');
282
- linestartpos = i;
283
- }
284
- }
285
-
286
- css = sb.toString();
287
- }
288
-
289
- // Replace multiple semi-colons in a row by a single one
290
- // See SF bug #1980989
291
- css = css.replaceAll(";;+", ";");
292
-
293
- // restore preserved comments and strings
294
- for(i = 0, max = preservedTokens.size(); i < max; i++) {
295
- css = css.replace("___YUICSSMIN_PRESERVED_TOKEN_" + i + "___", preservedTokens.get(i).toString());
296
- }
297
-
298
- // Trim the final string (for any leading or trailing white spaces)
299
- css = css.trim();
300
-
301
- // Write the output...
302
- out.write(css);
303
- }
304
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
lib/Diglin/yuicompressor-2.4.6/src/com/yahoo/platform/yui/compressor/JarClassLoader.java DELETED
@@ -1,158 +0,0 @@
1
- /*
2
- * YUI Compressor
3
- * http://developer.yahoo.com/yui/compressor/
4
- * Author: Julien Lecomte - http://www.julienlecomte.net/
5
- * Copyright (c) 2011 Yahoo! Inc. All rights reserved.
6
- * The copyrights embodied in the content of this file are licensed
7
- * by Yahoo! Inc. under the BSD (revised) open source license.
8
- */
9
- package com.yahoo.platform.yui.compressor;
10
-
11
- import java.io.ByteArrayOutputStream;
12
- import java.io.IOException;
13
- import java.io.InputStream;
14
- import java.io.OutputStream;
15
- import java.util.Enumeration;
16
- import java.util.jar.JarEntry;
17
- import java.util.jar.JarFile;
18
-
19
- public class JarClassLoader extends ClassLoader {
20
-
21
- private static String jarPath;
22
-
23
- public Class loadClass(String name) throws ClassNotFoundException {
24
-
25
- // First check if the class is already loaded
26
- Class c = findLoadedClass(name);
27
- if (c == null) {
28
- c = findClass(name);
29
- }
30
-
31
- if (c == null) {
32
- c = ClassLoader.getSystemClassLoader().loadClass(name);
33
- }
34
-
35
- return c;
36
- }
37
-
38
- private static String getJarPath() {
39
-
40
- if (jarPath != null) {
41
- return jarPath;
42
- }
43
-
44
- String classname = JarClassLoader.class.getName().replace('.', '/') + ".class";
45
- String classpath = System.getProperty("java.class.path");
46
- String classpaths[] = classpath.split(System.getProperty("path.separator"));
47
-
48
- for (int i = 0; i < classpaths.length; i++) {
49
-
50
- String path = classpaths[i];
51
- JarFile jarFile = null;
52
- JarEntry jarEntry = null;
53
-
54
- try {
55
- jarFile = new JarFile(path);
56
- jarEntry = findJarEntry(jarFile, classname);
57
- } catch (IOException ioe) {
58
- /* ignore */
59
- } finally {
60
- if (jarFile != null) {
61
- try {
62
- jarFile.close();
63
- } catch (IOException ioe) {
64
- /* ignore */
65
- }
66
- }
67
- }
68
-
69
- if (jarEntry != null) {
70
- jarPath = path;
71
- break;
72
- }
73
- }
74
-
75
- return jarPath;
76
- }
77
-
78
- private static JarEntry findJarEntry(JarFile jarFile, String entryName) {
79
-
80
- Enumeration entries = jarFile.entries();
81
-
82
- while (entries.hasMoreElements()) {
83
- JarEntry entry = (JarEntry) entries.nextElement();
84
- if (entry.getName().equals(entryName)) {
85
- return entry;
86
- }
87
- }
88
-
89
- return null;
90
- }
91
-
92
- protected Class findClass(String name) {
93
-
94
- Class c = null;
95
- String jarPath = getJarPath();
96
-
97
- if (jarPath != null) {
98
- JarFile jarFile = null;
99
- try {
100
- jarFile = new JarFile(jarPath);
101
- c = loadClassData(jarFile, name);
102
- } catch (IOException ioe) {
103
- /* ignore */
104
- } finally {
105
- if (jarFile != null) {
106
- try {
107
- jarFile.close();
108
- } catch (IOException ioe) {
109
- /* ignore */
110
- }
111
- }
112
- }
113
- }
114
-
115
- return c;
116
- }
117
-
118
- private Class loadClassData(JarFile jarFile, String className) {
119
-
120
- String entryName = className.replace('.', '/') + ".class";
121
- JarEntry jarEntry = findJarEntry(jarFile, entryName);
122
- if (jarEntry == null) {
123
- return null;
124
- }
125
-
126
- // Create the necessary package if needed...
127
- int index = className.lastIndexOf('.');
128
- if (index >= 0) {
129
- String packageName = className.substring(0, index);
130
- if (getPackage(packageName) == null) {
131
- definePackage(packageName, "", "", "", "", "", "", null);
132
- }
133
- }
134
-
135
- // Read the Jar File entry and define the class...
136
- Class c = null;
137
- try {
138
- InputStream is = jarFile.getInputStream(jarEntry);
139
- ByteArrayOutputStream os = new ByteArrayOutputStream();
140
- copy(is, os);
141
- byte[] bytes = os.toByteArray();
142
- c = defineClass(className, bytes, 0, bytes.length);
143
- } catch (IOException ioe) {
144
- /* ignore */
145
- }
146
-
147
- return c;
148
- }
149
-
150
- private void copy(InputStream in, OutputStream out) throws IOException {
151
- byte[] buf = new byte[1024];
152
- while (true) {
153
- int len = in.read(buf);
154
- if (len < 0) break;
155
- out.write(buf, 0, len);
156
- }
157
- }
158
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
lib/Diglin/yuicompressor-2.4.6/src/com/yahoo/platform/yui/compressor/JavaScriptCompressor.java DELETED
@@ -1,1317 +0,0 @@
1
- /*
2
- * YUI Compressor
3
- * http://developer.yahoo.com/yui/compressor/
4
- * Author: Julien Lecomte - http://www.julienlecomte.net/
5
- * Copyright (c) 2011 Yahoo! Inc. All rights reserved.
6
- * The copyrights embodied in the content of this file are licensed
7
- * by Yahoo! Inc. under the BSD (revised) open source license.
8
- */
9
- package com.yahoo.platform.yui.compressor;
10
-
11
- import org.mozilla.javascript.*;
12
-
13
- import java.io.IOException;
14
- import java.io.Reader;
15
- import java.io.Writer;
16
- import java.util.*;
17
- import java.util.regex.Matcher;
18
- import java.util.regex.Pattern;
19
-
20
- public class JavaScriptCompressor {
21
-
22
- static final ArrayList ones;
23
- static final ArrayList twos;
24
- static final ArrayList threes;
25
-
26
- static final Set builtin = new HashSet();
27
- static final Map literals = new Hashtable();
28
- static final Set reserved = new HashSet();
29
-
30
- static {
31
-
32
- // This list contains all the 3 characters or less built-in global
33
- // symbols available in a browser. Please add to this list if you
34
- // see anything missing.
35
- builtin.add("NaN");
36
- builtin.add("top");
37
-
38
- ones = new ArrayList();
39
- for (char c = 'a'; c <= 'z'; c++)
40
- ones.add(Character.toString(c));
41
- for (char c = 'A'; c <= 'Z'; c++)
42
- ones.add(Character.toString(c));
43
-
44
- twos = new ArrayList();
45
- for (int i = 0; i < ones.size(); i++) {
46
- String one = (String) ones.get(i);
47
- for (char c = 'a'; c <= 'z'; c++)
48
- twos.add(one + Character.toString(c));
49
- for (char c = 'A'; c <= 'Z'; c++)
50
- twos.add(one + Character.toString(c));
51
- for (char c = '0'; c <= '9'; c++)
52
- twos.add(one + Character.toString(c));
53
- }
54
-
55
- // Remove two-letter JavaScript reserved words and built-in globals...
56
- twos.remove("as");
57
- twos.remove("is");
58
- twos.remove("do");
59
- twos.remove("if");
60
- twos.remove("in");
61
- twos.removeAll(builtin);
62
-
63
- threes = new ArrayList();
64
- for (int i = 0; i < twos.size(); i++) {
65
- String two = (String) twos.get(i);
66
- for (char c = 'a'; c <= 'z'; c++)
67
- threes.add(two + Character.toString(c));
68
- for (char c = 'A'; c <= 'Z'; c++)
69
- threes.add(two + Character.toString(c));
70
- for (char c = '0'; c <= '9'; c++)
71
- threes.add(two + Character.toString(c));
72
- }
73
-
74
- // Remove three-letter JavaScript reserved words and built-in globals...
75
- threes.remove("for");
76
- threes.remove("int");
77
- threes.remove("new");
78
- threes.remove("try");
79
- threes.remove("use");
80
- threes.remove("var");
81
- threes.removeAll(builtin);
82
-
83
- // That's up to ((26+26)*(1+(26+26+10)))*(1+(26+26+10))-8
84
- // (206,380 symbols per scope)
85
-
86
- // The following list comes from org/mozilla/javascript/Decompiler.java...
87
- literals.put(new Integer(Token.GET), "get ");
88
- literals.put(new Integer(Token.SET), "set ");
89
- literals.put(new Integer(Token.TRUE), "true");
90
- literals.put(new Integer(Token.FALSE), "false");
91
- literals.put(new Integer(Token.NULL), "null");
92
- literals.put(new Integer(Token.THIS), "this");
93
- literals.put(new Integer(Token.FUNCTION), "function");
94
- literals.put(new Integer(Token.COMMA), ",");
95
- literals.put(new Integer(Token.LC), "{");
96
- literals.put(new Integer(Token.RC), "}");
97
- literals.put(new Integer(Token.LP), "(");
98
- literals.put(new Integer(Token.RP), ")");
99
- literals.put(new Integer(Token.LB), "[");
100
- literals.put(new Integer(Token.RB), "]");
101
- literals.put(new Integer(Token.DOT), ".");
102
- literals.put(new Integer(Token.NEW), "new ");
103
- literals.put(new Integer(Token.DELPROP), "delete ");
104
- literals.put(new Integer(Token.IF), "if");
105
- literals.put(new Integer(Token.ELSE), "else");
106
- literals.put(new Integer(Token.FOR), "for");
107
- literals.put(new Integer(Token.IN), " in ");
108
- literals.put(new Integer(Token.WITH), "with");
109
- literals.put(new Integer(Token.WHILE), "while");
110
- literals.put(new Integer(Token.DO), "do");
111
- literals.put(new Integer(Token.TRY), "try");
112
- literals.put(new Integer(Token.CATCH), "catch");
113
- literals.put(new Integer(Token.FINALLY), "finally");
114
- literals.put(new Integer(Token.THROW), "throw");
115
- literals.put(new Integer(Token.SWITCH), "switch");
116
- literals.put(new Integer(Token.BREAK), "break");
117
- literals.put(new Integer(Token.CONTINUE), "continue");
118
- literals.put(new Integer(Token.CASE), "case");
119
- literals.put(new Integer(Token.DEFAULT), "default");
120
- literals.put(new Integer(Token.RETURN), "return");
121
- literals.put(new Integer(Token.VAR), "var ");
122
- literals.put(new Integer(Token.SEMI), ";");
123
- literals.put(new Integer(Token.ASSIGN), "=");
124
- literals.put(new Integer(Token.ASSIGN_ADD), "+=");
125
- literals.put(new Integer(Token.ASSIGN_SUB), "-=");
126
- literals.put(new Integer(Token.ASSIGN_MUL), "*=");
127
- literals.put(new Integer(Token.ASSIGN_DIV), "/=");
128
- literals.put(new Integer(Token.ASSIGN_MOD), "%=");
129
- literals.put(new Integer(Token.ASSIGN_BITOR), "|=");
130
- literals.put(new Integer(Token.ASSIGN_BITXOR), "^=");
131
- literals.put(new Integer(Token.ASSIGN_BITAND), "&=");
132
- literals.put(new Integer(Token.ASSIGN_LSH), "<<=");
133
- literals.put(new Integer(Token.ASSIGN_RSH), ">>=");
134
- literals.put(new Integer(Token.ASSIGN_URSH), ">>>=");
135
- literals.put(new Integer(Token.HOOK), "?");
136
- literals.put(new Integer(Token.OBJECTLIT), ":");
137
- literals.put(new Integer(Token.COLON), ":");
138
- literals.put(new Integer(Token.OR), "||");
139
- literals.put(new Integer(Token.AND), "&&");
140
- literals.put(new Integer(Token.BITOR), "|");
141
- literals.put(new Integer(Token.BITXOR), "^");
142
- literals.put(new Integer(Token.BITAND), "&");
143
- literals.put(new Integer(Token.SHEQ), "===");
144
- literals.put(new Integer(Token.SHNE), "!==");
145
- literals.put(new Integer(Token.EQ), "==");
146
- literals.put(new Integer(Token.NE), "!=");
147
- literals.put(new Integer(Token.LE), "<=");
148
- literals.put(new Integer(Token.LT), "<");
149
- literals.put(new Integer(Token.GE), ">=");
150
- literals.put(new Integer(Token.GT), ">");
151
- literals.put(new Integer(Token.INSTANCEOF), " instanceof ");
152
- literals.put(new Integer(Token.LSH), "<<");
153
- literals.put(new Integer(Token.RSH), ">>");
154
- literals.put(new Integer(Token.URSH), ">>>");
155
- literals.put(new Integer(Token.TYPEOF), "typeof");
156
- literals.put(new Integer(Token.VOID), "void ");
157
- literals.put(new Integer(Token.CONST), "const ");
158
- literals.put(new Integer(Token.NOT), "!");
159
- literals.put(new Integer(Token.BITNOT), "~");
160
- literals.put(new Integer(Token.POS), "+");
161
- literals.put(new Integer(Token.NEG), "-");
162
- literals.put(new Integer(Token.INC), "++");
163
- literals.put(new Integer(Token.DEC), "--");
164
- literals.put(new Integer(Token.ADD), "+");
165
- literals.put(new Integer(Token.SUB), "-");
166
- literals.put(new Integer(Token.MUL), "*");
167
- literals.put(new Integer(Token.DIV), "/");
168
- literals.put(new Integer(Token.MOD), "%");
169
- literals.put(new Integer(Token.COLONCOLON), "::");
170
- literals.put(new Integer(Token.DOTDOT), "..");
171
- literals.put(new Integer(Token.DOTQUERY), ".(");
172
- literals.put(new Integer(Token.XMLATTR), "@");
173
-
174
- // See http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Reserved_Words
175
-
176
- // JavaScript 1.5 reserved words
177
- reserved.add("break");
178
- reserved.add("case");
179
- reserved.add("catch");
180
- reserved.add("continue");
181
- reserved.add("default");
182
- reserved.add("delete");
183
- reserved.add("do");
184
- reserved.add("else");
185
- reserved.add("finally");
186
- reserved.add("for");
187
- reserved.add("function");
188
- reserved.add("if");
189
- reserved.add("in");
190
- reserved.add("instanceof");
191
- reserved.add("new");
192
- reserved.add("return");
193
- reserved.add("switch");
194
- reserved.add("this");
195
- reserved.add("throw");
196
- reserved.add("try");
197
- reserved.add("typeof");
198
- reserved.add("var");
199
- reserved.add("void");
200
- reserved.add("while");
201
- reserved.add("with");
202
- // Words reserved for future use
203
- reserved.add("abstract");
204
- reserved.add("boolean");
205
- reserved.add("byte");
206
- reserved.add("char");
207
- reserved.add("class");
208
- reserved.add("const");
209
- reserved.add("debugger");
210
- reserved.add("double");
211
- reserved.add("enum");
212
- reserved.add("export");
213
- reserved.add("extends");
214
- reserved.add("final");
215
- reserved.add("float");
216
- reserved.add("goto");
217
- reserved.add("implements");
218
- reserved.add("import");
219
- reserved.add("int");
220
- reserved.add("interface");
221
- reserved.add("long");
222
- reserved.add("native");
223
- reserved.add("package");
224
- reserved.add("private");
225
- reserved.add("protected");
226
- reserved.add("public");
227
- reserved.add("short");
228
- reserved.add("static");
229
- reserved.add("super");
230
- reserved.add("synchronized");
231
- reserved.add("throws");
232
- reserved.add("transient");
233
- reserved.add("volatile");
234
- // These are not reserved, but should be taken into account
235
- // in isValidIdentifier (See jslint source code)
236
- reserved.add("arguments");
237
- reserved.add("eval");
238
- reserved.add("true");
239
- reserved.add("false");
240
- reserved.add("Infinity");
241
- reserved.add("NaN");
242
- reserved.add("null");
243
- reserved.add("undefined");
244
- }
245
-
246
- private static int countChar(String haystack, char needle) {
247
- int idx = 0;
248
- int count = 0;
249
- int length = haystack.length();
250
- while (idx < length) {
251
- char c = haystack.charAt(idx++);
252
- if (c == needle) {
253
- count++;
254
- }
255
- }
256
- return count;
257
- }
258
-
259
- private static int printSourceString(String source, int offset, StringBuffer sb) {
260
- int length = source.charAt(offset);
261
- ++offset;
262
- if ((0x8000 & length) != 0) {
263
- length = ((0x7FFF & length) << 16) | source.charAt(offset);
264
- ++offset;
265
- }
266
- if (sb != null) {
267
- String str = source.substring(offset, offset + length);
268
- sb.append(str);
269
- }
270
- return offset + length;
271
- }
272
-
273
- private static int printSourceNumber(String source,
274
- int offset, StringBuffer sb) {
275
- double number = 0.0;
276
- char type = source.charAt(offset);
277
- ++offset;
278
- if (type == 'S') {
279
- if (sb != null) {
280
- number = source.charAt(offset);
281
- }
282
- ++offset;
283
- } else if (type == 'J' || type == 'D') {
284
- if (sb != null) {
285
- long lbits;
286
- lbits = (long) source.charAt(offset) << 48;
287
- lbits |= (long) source.charAt(offset + 1) << 32;
288
- lbits |= (long) source.charAt(offset + 2) << 16;
289
- lbits |= (long) source.charAt(offset + 3);
290
- if (type == 'J') {
291
- number = lbits;
292
- } else {
293
- number = Double.longBitsToDouble(lbits);
294
- }
295
- }
296
- offset += 4;
297
- } else {
298
- // Bad source
299
- throw new RuntimeException();
300
- }
301
- if (sb != null) {
302
- sb.append(ScriptRuntime.numberToString(number, 10));
303
- }
304
- return offset;
305
- }
306
-
307
- private static ArrayList parse(Reader in, ErrorReporter reporter)
308
- throws IOException, EvaluatorException {
309
-
310
- CompilerEnvirons env = new CompilerEnvirons();
311
- Parser parser = new Parser(env, reporter);
312
- parser.parse(in, null, 1);
313
- String source = parser.getEncodedSource();
314
-
315
- int offset = 0;
316
- int length = source.length();
317
- ArrayList tokens = new ArrayList();
318
- StringBuffer sb = new StringBuffer();
319
-
320
- while (offset < length) {
321
- int tt = source.charAt(offset++);
322
- switch (tt) {
323
-
324
- case Token.CONDCOMMENT:
325
- case Token.KEEPCOMMENT:
326
- case Token.NAME:
327
- case Token.REGEXP:
328
- case Token.STRING:
329
- sb.setLength(0);
330
- offset = printSourceString(source, offset, sb);
331
- tokens.add(new JavaScriptToken(tt, sb.toString()));
332
- break;
333
-
334
- case Token.NUMBER:
335
- sb.setLength(0);
336
- offset = printSourceNumber(source, offset, sb);
337
- tokens.add(new JavaScriptToken(tt, sb.toString()));
338
- break;
339
-
340
- default:
341
- String literal = (String) literals.get(new Integer(tt));
342
- if (literal != null) {
343
- tokens.add(new JavaScriptToken(tt, literal));
344
- }
345
- break;
346
- }
347
- }
348
-
349
- return tokens;
350
- }
351
-
352
- private static void processStringLiterals(ArrayList tokens, boolean merge) {
353
-
354
- String tv;
355
- int i, length = tokens.size();
356
- JavaScriptToken token, prevToken, nextToken;
357
-
358
- if (merge) {
359
-
360
- // Concatenate string literals that are being appended wherever
361
- // it is safe to do so. Note that we take care of the case:
362
- // "a" + "b".toUpperCase()
363
-
364
- for (i = 0; i < length; i++) {
365
- token = (JavaScriptToken) tokens.get(i);
366
- switch (token.getType()) {
367
-
368
- case Token.ADD:
369
- if (i > 0 && i < length) {
370
- prevToken = (JavaScriptToken) tokens.get(i - 1);
371
- nextToken = (JavaScriptToken) tokens.get(i + 1);
372
- if (prevToken.getType() == Token.STRING && nextToken.getType() == Token.STRING &&
373
- (i == length - 1 || ((JavaScriptToken) tokens.get(i + 2)).getType() != Token.DOT)) {
374
- tokens.set(i - 1, new JavaScriptToken(Token.STRING,
375
- prevToken.getValue() + nextToken.getValue()));
376
- tokens.remove(i + 1);
377
- tokens.remove(i);
378
- i = i - 1;
379
- length = length - 2;
380
- break;
381
- }
382
- }
383
- }
384
- }
385
-
386
- }
387
-
388
- // Second pass...
389
-
390
- for (i = 0; i < length; i++) {
391
- token = (JavaScriptToken) tokens.get(i);
392
- if (token.getType() == Token.STRING) {
393
- tv = token.getValue();
394
-
395
- // Finally, add the quoting characters and escape the string. We use
396
- // the quoting character that minimizes the amount of escaping to save
397
- // a few additional bytes.
398
-
399
- char quotechar;
400
- int singleQuoteCount = countChar(tv, '\'');
401
- int doubleQuoteCount = countChar(tv, '"');
402
- if (doubleQuoteCount <= singleQuoteCount) {
403
- quotechar = '"';
404
- } else {
405
- quotechar = '\'';
406
- }
407
-
408
- tv = quotechar + escapeString(tv, quotechar) + quotechar;
409
-
410
- // String concatenation transforms the old script scheme:
411
- // '<scr'+'ipt ...><'+'/script>'
412
- // into the following:
413
- // '<script ...></script>'
414
- // which breaks if this code is embedded inside an HTML document.
415
- // Since this is not the right way to do this, let's fix the code by
416
- // transforming all "</script" into "<\/script"
417
-
418
- if (tv.indexOf("</script") >= 0) {
419
- tv = tv.replaceAll("<\\/script", "<\\\\/script");
420
- }
421
-
422
- tokens.set(i, new JavaScriptToken(Token.STRING, tv));
423
- }
424
- }
425
- }
426
-
427
- // Add necessary escaping that was removed in Rhino's tokenizer.
428
- private static String escapeString(String s, char quotechar) {
429
-
430
- assert quotechar == '"' || quotechar == '\'';
431
-
432
- if (s == null) {
433
- return null;
434
- }
435
-
436
- StringBuffer sb = new StringBuffer();
437
- for (int i = 0, L = s.length(); i < L; i++) {
438
- int c = s.charAt(i);
439
- if (c == quotechar) {
440
- sb.append("\\");
441
- }
442
- sb.append((char) c);
443
- }
444
-
445
- return sb.toString();
446
- }
447
-
448
- /*
449
- * Simple check to see whether a string is a valid identifier name.
450
- * If a string matches this pattern, it means it IS a valid
451
- * identifier name. If a string doesn't match it, it does not
452
- * necessarily mean it is not a valid identifier name.
453
- */
454
- private static final Pattern SIMPLE_IDENTIFIER_NAME_PATTERN = Pattern.compile("^[a-zA-Z_][a-zA-Z0-9_]*$");
455
-
456
- private static boolean isValidIdentifier(String s) {
457
- Matcher m = SIMPLE_IDENTIFIER_NAME_PATTERN.matcher(s);
458
- return (m.matches() && !reserved.contains(s));
459
- }
460
-
461
- /*
462
- * Transforms obj["foo"] into obj.foo whenever possible, saving 3 bytes.
463
- */
464
- private static void optimizeObjectMemberAccess(ArrayList tokens) {
465
-
466
- String tv;
467
- int i, length;
468
- JavaScriptToken token;
469
-
470
- for (i = 0, length = tokens.size(); i < length; i++) {
471
-
472
- if (((JavaScriptToken) tokens.get(i)).getType() == Token.LB &&
473
- i > 0 && i < length - 2 &&
474
- ((JavaScriptToken) tokens.get(i - 1)).getType() == Token.NAME &&
475
- ((JavaScriptToken) tokens.get(i + 1)).getType() == Token.STRING &&
476
- ((JavaScriptToken) tokens.get(i + 2)).getType() == Token.RB) {
477
- token = (JavaScriptToken) tokens.get(i + 1);
478
- tv = token.getValue();
479
- tv = tv.substring(1, tv.length() - 1);
480
- if (isValidIdentifier(tv)) {
481
- tokens.set(i, new JavaScriptToken(Token.DOT, "."));
482
- tokens.set(i + 1, new JavaScriptToken(Token.NAME, tv));
483
- tokens.remove(i + 2);
484
- i = i + 2;
485
- length = length - 1;
486
- }
487
- }
488
- }
489
- }
490
-
491
- /*
492
- * Transforms 'foo': ... into foo: ... whenever possible, saving 2 bytes.
493
- */
494
- private static void optimizeObjLitMemberDecl(ArrayList tokens) {
495
-
496
- String tv;
497
- int i, length;
498
- JavaScriptToken token;
499
-
500
- for (i = 0, length = tokens.size(); i < length; i++) {
501
- if (((JavaScriptToken) tokens.get(i)).getType() == Token.OBJECTLIT &&
502
- i > 0 && ((JavaScriptToken) tokens.get(i - 1)).getType() == Token.STRING) {
503
- token = (JavaScriptToken) tokens.get(i - 1);
504
- tv = token.getValue();
505
- tv = tv.substring(1, tv.length() - 1);
506
- if (isValidIdentifier(tv)) {
507
- tokens.set(i - 1, new JavaScriptToken(Token.NAME, tv));
508
- }
509
- }
510
- }
511
- }
512
-
513
- private ErrorReporter logger;
514
-
515
- private boolean munge;
516
- private boolean verbose;
517
-
518
- private static final int BUILDING_SYMBOL_TREE = 1;
519
- private static final int CHECKING_SYMBOL_TREE = 2;
520
-
521
- private int mode;
522
- private int offset;
523
- private int braceNesting;
524
- private ArrayList tokens;
525
- private Stack scopes = new Stack();
526
- private ScriptOrFnScope globalScope = new ScriptOrFnScope(-1, null);
527
- private Hashtable indexedScopes = new Hashtable();
528
-
529
- public JavaScriptCompressor(Reader in, ErrorReporter reporter)
530
- throws IOException, EvaluatorException {
531
-
532
- this.logger = reporter;
533
- this.tokens = parse(in, reporter);
534
- }
535
-
536
- public void compress(Writer out, int linebreak, boolean munge, boolean verbose,
537
- boolean preserveAllSemiColons, boolean disableOptimizations)
538
- throws IOException {
539
-
540
- this.munge = munge;
541
- this.verbose = verbose;
542
-
543
- processStringLiterals(this.tokens, !disableOptimizations);
544
-
545
- if (!disableOptimizations) {
546
- optimizeObjectMemberAccess(this.tokens);
547
- optimizeObjLitMemberDecl(this.tokens);
548
- }
549
-
550
- buildSymbolTree();
551
- // DO NOT TOUCH this.tokens BETWEEN THESE TWO PHASES (BECAUSE OF this.indexedScopes)
552
- mungeSymboltree();
553
- StringBuffer sb = printSymbolTree(linebreak, preserveAllSemiColons);
554
-
555
- out.write(sb.toString());
556
- }
557
-
558
- private ScriptOrFnScope getCurrentScope() {
559
- return (ScriptOrFnScope) scopes.peek();
560
- }
561
-
562
- private void enterScope(ScriptOrFnScope scope) {
563
- scopes.push(scope);
564
- }
565
-
566
- private void leaveCurrentScope() {
567
- scopes.pop();
568
- }
569
-
570
- private JavaScriptToken consumeToken() {
571
- return (JavaScriptToken) tokens.get(offset++);
572
- }
573
-
574
- private JavaScriptToken getToken(int delta) {
575
- return (JavaScriptToken) tokens.get(offset + delta);
576
- }
577
-
578
- /*
579
- * Returns the identifier for the specified symbol defined in
580
- * the specified scope or in any scope above it. Returns null
581
- * if this symbol does not have a corresponding identifier.
582
- */
583
- private JavaScriptIdentifier getIdentifier(String symbol, ScriptOrFnScope scope) {
584
- JavaScriptIdentifier identifier;
585
- while (scope != null) {
586
- identifier = scope.getIdentifier(symbol);
587
- if (identifier != null) {
588
- return identifier;
589
- }
590
- scope = scope.getParentScope();
591
- }
592
- return null;
593
- }
594
-
595
- /*
596
- * If either 'eval' or 'with' is used in a local scope, we must make
597
- * sure that all containing local scopes don't get munged. Otherwise,
598
- * the obfuscation would potentially introduce bugs.
599
- */
600
- private void protectScopeFromObfuscation(ScriptOrFnScope scope) {
601
- assert scope != null;
602
-
603
- if (scope == globalScope) {
604
- // The global scope does not get obfuscated,
605
- // so we don't need to worry about it...
606
- return;
607
- }
608
-
609
- // Find the highest local scope containing the specified scope.
610
- while (scope.getParentScope() != globalScope) {
611
- scope = scope.getParentScope();
612
- }
613
-
614
- assert scope.getParentScope() == globalScope;
615
- scope.preventMunging();
616
- }
617
-
618
- private String getDebugString(int max) {
619
- assert max > 0;
620
- StringBuffer result = new StringBuffer();
621
- int start = Math.max(offset - max, 0);
622
- int end = Math.min(offset + max, tokens.size());
623
- for (int i = start; i < end; i++) {
624
- JavaScriptToken token = (JavaScriptToken) tokens.get(i);
625
- if (i == offset - 1) {
626
- result.append(" ---> ");
627
- }
628
- result.append(token.getValue());
629
- if (i == offset - 1) {
630
- result.append(" <--- ");
631
- }
632
- }
633
- return result.toString();
634
- }
635
-
636
- private void warn(String message, boolean showDebugString) {
637
- if (verbose) {
638
- if (showDebugString) {
639
- message = message + "\n" + getDebugString(10);
640
- }
641
- logger.warning(message, null, -1, null, -1);
642
- }
643
- }
644
-
645
- private void parseFunctionDeclaration() {
646
-
647
- String symbol;
648
- JavaScriptToken token;
649
- ScriptOrFnScope currentScope, fnScope;
650
- JavaScriptIdentifier identifier;
651
-
652
- currentScope = getCurrentScope();
653
-
654
- token = consumeToken();
655
- if (token.getType() == Token.NAME) {
656
- if (mode == BUILDING_SYMBOL_TREE) {
657
- // Get the name of the function and declare it in the current scope.
658
- symbol = token.getValue();
659
- if (currentScope.getIdentifier(symbol) != null) {
660
- warn("The function " + symbol + " has already been declared in the same scope...", true);
661
- }
662
- currentScope.declareIdentifier(symbol);
663
- }
664
- token = consumeToken();
665
- }
666
-
667
- assert token.getType() == Token.LP;
668
- if (mode == BUILDING_SYMBOL_TREE) {
669
- fnScope = new ScriptOrFnScope(braceNesting, currentScope);
670
- indexedScopes.put(new Integer(offset), fnScope);
671
- } else {
672
- fnScope = (ScriptOrFnScope) indexedScopes.get(new Integer(offset));
673
- }
674
-
675
- // Parse function arguments.
676
- int argpos = 0;
677
- while ((token = consumeToken()).getType() != Token.RP) {
678
- assert token.getType() == Token.NAME ||
679
- token.getType() == Token.COMMA;
680
- if (token.getType() == Token.NAME && mode == BUILDING_SYMBOL_TREE) {
681
- symbol = token.getValue();
682
- identifier = fnScope.declareIdentifier(symbol);
683
- if (symbol.equals("$super") && argpos == 0) {
684
- // Exception for Prototype 1.6...
685
- identifier.preventMunging();
686
- }
687
- argpos++;
688
- }
689
- }
690
-
691
- token = consumeToken();
692
- assert token.getType() == Token.LC;
693
- braceNesting++;
694
-
695
- token = getToken(0);
696
- if (token.getType() == Token.STRING &&
697
- getToken(1).getType() == Token.SEMI) {
698
- // This is a hint. Hints are empty statements that look like
699
- // "localvar1:nomunge, localvar2:nomunge"; They allow developers
700
- // to prevent specific symbols from getting obfuscated (some heretic
701
- // implementations, such as Prototype 1.6, require specific variable
702
- // names, such as $super for example, in order to work appropriately.
703
- // Note: right now, only "nomunge" is supported in the right hand side
704
- // of a hint. However, in the future, the right hand side may contain
705
- // other values.
706
- consumeToken();
707
- String hints = token.getValue();
708
- // Remove the leading and trailing quotes...
709
- hints = hints.substring(1, hints.length() - 1).trim();
710
- StringTokenizer st1 = new StringTokenizer(hints, ",");
711
- while (st1.hasMoreTokens()) {
712
- String hint = st1.nextToken();
713
- int idx = hint.indexOf(':');
714
- if (idx <= 0 || idx >= hint.length() - 1) {
715
- if (mode == BUILDING_SYMBOL_TREE) {
716
- // No need to report the error twice, hence the test...
717
- warn("Invalid hint syntax: " + hint, true);
718
- }
719
- break;
720
- }
721
- String variableName = hint.substring(0, idx).trim();
722
- String variableType = hint.substring(idx + 1).trim();
723
- if (mode == BUILDING_SYMBOL_TREE) {
724
- fnScope.addHint(variableName, variableType);
725
- } else if (mode == CHECKING_SYMBOL_TREE) {
726
- identifier = fnScope.getIdentifier(variableName);
727
- if (identifier != null) {
728
- if (variableType.equals("nomunge")) {
729
- identifier.preventMunging();
730
- } else {
731
- warn("Unsupported hint value: " + hint, true);
732
- }
733
- } else {
734
- warn("Hint refers to an unknown identifier: " + hint, true);
735
- }
736
- }
737
- }
738
- }
739
-
740
- parseScope(fnScope);
741
- }
742
-
743
- private void parseCatch() {
744
-
745
- String symbol;
746
- JavaScriptToken token;
747
- ScriptOrFnScope currentScope;
748
- JavaScriptIdentifier identifier;
749
-
750
- token = getToken(-1);
751
- assert token.getType() == Token.CATCH;
752
- token = consumeToken();
753
- assert token.getType() == Token.LP;
754
- token = consumeToken();
755
- assert token.getType() == Token.NAME;
756
-
757
- symbol = token.getValue();
758
- currentScope = getCurrentScope();
759
-
760
- if (mode == BUILDING_SYMBOL_TREE) {
761
- // We must declare the exception identifier in the containing function
762
- // scope to avoid errors related to the obfuscation process. No need to
763
- // display a warning if the symbol was already declared here...
764
- currentScope.declareIdentifier(symbol);
765
- } else {
766
- identifier = getIdentifier(symbol, currentScope);
767
- identifier.incrementRefcount();
768
- }
769
-
770
- token = consumeToken();
771
- assert token.getType() == Token.RP;
772
- }
773
-
774
- private void parseExpression() {
775
-
776
- // Parse the expression until we encounter a comma or a semi-colon
777
- // in the same brace nesting, bracket nesting and paren nesting.
778
- // Parse functions if any...
779
-
780
- String symbol;
781
- JavaScriptToken token;
782
- ScriptOrFnScope currentScope;
783
- JavaScriptIdentifier identifier;
784
-
785
- int expressionBraceNesting = braceNesting;
786
- int bracketNesting = 0;
787
- int parensNesting = 0;
788
-
789
- int length = tokens.size();
790
-
791
- while (offset < length) {
792
-
793
- token = consumeToken();
794
- currentScope = getCurrentScope();
795
-
796
- switch (token.getType()) {
797
-
798
- case Token.SEMI:
799
- case Token.COMMA:
800
- if (braceNesting == expressionBraceNesting &&
801
- bracketNesting == 0 &&
802
- parensNesting == 0) {
803
- return;
804
- }
805
- break;
806
-
807
- case Token.FUNCTION:
808
- parseFunctionDeclaration();
809
- break;
810
-
811
- case Token.LC:
812
- braceNesting++;
813
- break;
814
-
815
- case Token.RC:
816
- braceNesting--;
817
- assert braceNesting >= expressionBraceNesting;
818
- break;
819
-
820
- case Token.LB:
821
- bracketNesting++;
822
- break;
823
-
824
- case Token.RB:
825
- bracketNesting--;
826
- break;
827
-
828
- case Token.LP:
829
- parensNesting++;
830
- break;
831
-
832
- case Token.RP:
833
- parensNesting--;
834
- break;
835
-
836
- case Token.CONDCOMMENT:
837
- if (mode == BUILDING_SYMBOL_TREE) {
838
- protectScopeFromObfuscation(currentScope);
839
- warn("Using JScript conditional comments is not recommended." + (munge ? " Moreover, using JScript conditional comments reduces the level of compression!" : ""), true);
840
- }
841
- break;
842
-
843
- case Token.NAME:
844
- symbol = token.getValue();
845
-
846
- if (mode == BUILDING_SYMBOL_TREE) {
847
-
848
- if (symbol.equals("eval")) {
849
-
850
- protectScopeFromObfuscation(currentScope);
851
- warn("Using 'eval' is not recommended." + (munge ? " Moreover, using 'eval' reduces the level of compression!" : ""), true);
852
-
853
- }
854
-
855
- } else if (mode == CHECKING_SYMBOL_TREE) {
856
-
857
- if ((offset < 2 ||
858
- (getToken(-2).getType() != Token.DOT &&
859
- getToken(-2).getType() != Token.GET &&
860
- getToken(-2).getType() != Token.SET)) &&
861
- getToken(0).getType() != Token.OBJECTLIT) {
862
-
863
- identifier = getIdentifier(symbol, currentScope);
864
-
865
- if (identifier == null) {
866
-
867
- if (symbol.length() <= 3 && !builtin.contains(symbol)) {
868
- // Here, we found an undeclared and un-namespaced symbol that is
869
- // 3 characters or less in length. Declare it in the global scope.
870
- // We don't need to declare longer symbols since they won't cause
871
- // any conflict with other munged symbols.
872
- globalScope.declareIdentifier(symbol);
873
-
874
- // I removed the warning since was only being done when
875
- // for identifiers 3 chars or less, and was just causing
876
- // noise for people who happen to rely on an externally
877
- // declared variable that happen to be that short. We either
878
- // should always warn or never warn -- the fact that we
879
- // declare the short symbols in the global space doesn't
880
- // change anything.
881
- // warn("Found an undeclared symbol: " + symbol, true);
882
- }
883
-
884
- } else {
885
-
886
- identifier.incrementRefcount();
887
- }
888
- }
889
- }
890
- break;
891
- }
892
- }
893
- }
894
-
895
- private void parseScope(ScriptOrFnScope scope) {
896
-
897
- String symbol;
898
- JavaScriptToken token;
899
- JavaScriptIdentifier identifier;
900
-
901
- int length = tokens.size();
902
-
903
- enterScope(scope);
904
-
905
- while (offset < length) {
906
-
907
- token = consumeToken();
908
-
909
- switch (token.getType()) {
910
-
911
- case Token.VAR:
912
-
913
- if (mode == BUILDING_SYMBOL_TREE && scope.incrementVarCount() > 1) {
914
- warn("Try to use a single 'var' statement per scope.", true);
915
- }
916
-
917
- /* FALLSTHROUGH */
918
-
919
- case Token.CONST:
920
-
921
- // The var keyword is followed by at least one symbol name.
922
- // If several symbols follow, they are comma separated.
923
- for (; ;) {
924
- token = consumeToken();
925
-
926
- assert token.getType() == Token.NAME;
927
-
928
- if (mode == BUILDING_SYMBOL_TREE) {
929
- symbol = token.getValue();
930
- if (scope.getIdentifier(symbol) == null) {
931
- scope.declareIdentifier(symbol);
932
- } else {
933
- warn("The variable " + symbol + " has already been declared in the same scope...", true);
934
- }
935
- }
936
-
937
- token = getToken(0);
938
-
939
- assert token.getType() == Token.SEMI ||
940
- token.getType() == Token.ASSIGN ||
941
- token.getType() == Token.COMMA ||
942
- token.getType() == Token.IN;
943
-
944
- if (token.getType() == Token.IN) {
945
- break;
946
- } else {
947
- parseExpression();
948
- token = getToken(-1);
949
- if (token.getType() == Token.SEMI) {
950
- break;
951
- }
952
- }
953
- }
954
- break;
955
-
956
- case Token.FUNCTION:
957
- parseFunctionDeclaration();
958
- break;
959
-
960
- case Token.LC:
961
- braceNesting++;
962
- break;
963
-
964
- case Token.RC:
965
- braceNesting--;
966
- assert braceNesting >= scope.getBraceNesting();
967
- if (braceNesting == scope.getBraceNesting()) {
968
- leaveCurrentScope();
969
- return;
970
- }
971
- break;
972
-
973
- case Token.WITH:
974
- if (mode == BUILDING_SYMBOL_TREE) {
975
- // Inside a 'with' block, it is impossible to figure out
976
- // statically whether a symbol is a local variable or an
977
- // object member. As a consequence, the only thing we can
978
- // do is turn the obfuscation off for the highest scope
979
- // containing the 'with' block.
980
- protectScopeFromObfuscation(scope);
981
- warn("Using 'with' is not recommended." + (munge ? " Moreover, using 'with' reduces the level of compression!" : ""), true);
982
- }
983
- break;
984
-
985
- case Token.CATCH:
986
- parseCatch();
987
- break;
988
-
989
- case Token.CONDCOMMENT:
990
- if (mode == BUILDING_SYMBOL_TREE) {
991
- protectScopeFromObfuscation(scope);
992
- warn("Using JScript conditional comments is not recommended." + (munge ? " Moreover, using JScript conditional comments reduces the level of compression." : ""), true);
993
- }
994
- break;
995
-
996
- case Token.NAME:
997
- symbol = token.getValue();
998
-
999
- if (mode == BUILDING_SYMBOL_TREE) {
1000
-
1001
- if (symbol.equals("eval")) {
1002
-
1003
- protectScopeFromObfuscation(scope);
1004
- warn("Using 'eval' is not recommended." + (munge ? " Moreover, using 'eval' reduces the level of compression!" : ""), true);
1005
-
1006
- }
1007
-
1008
- } else if (mode == CHECKING_SYMBOL_TREE) {
1009
-
1010
- if ((offset < 2 || getToken(-2).getType() != Token.DOT) &&
1011
- getToken(0).getType() != Token.OBJECTLIT) {
1012
-
1013
- identifier = getIdentifier(symbol, scope);
1014
-
1015
- if (identifier == null) {
1016
-
1017
- if (symbol.length() <= 3 && !builtin.contains(symbol)) {
1018
- // Here, we found an undeclared and un-namespaced symbol that is
1019
- // 3 characters or less in length. Declare it in the global scope.
1020
- // We don't need to declare longer symbols since they won't cause
1021
- // any conflict with other munged symbols.
1022
- globalScope.declareIdentifier(symbol);
1023
- // warn("Found an undeclared symbol: " + symbol, true);
1024
- }
1025
-
1026
- } else {
1027
-
1028
- identifier.incrementRefcount();
1029
- }
1030
- }
1031
- }
1032
- break;
1033
- }
1034
- }
1035
- }
1036
-
1037
- private void buildSymbolTree() {
1038
- offset = 0;
1039
- braceNesting = 0;
1040
- scopes.clear();
1041
- indexedScopes.clear();
1042
- indexedScopes.put(new Integer(0), globalScope);
1043
- mode = BUILDING_SYMBOL_TREE;
1044
- parseScope(globalScope);
1045
- }
1046
-
1047
- private void mungeSymboltree() {
1048
-
1049
- if (!munge) {
1050
- return;
1051
- }
1052
-
1053
- // One problem with obfuscation resides in the use of undeclared
1054
- // and un-namespaced global symbols that are 3 characters or less
1055
- // in length. Here is an example:
1056
- //
1057
- // var declaredGlobalVar;
1058
- //
1059
- // function declaredGlobalFn() {
1060
- // var localvar;
1061
- // localvar = abc; // abc is an undeclared global symbol
1062
- // }
1063
- //
1064
- // In the example above, there is a slim chance that localvar may be
1065
- // munged to 'abc', conflicting with the undeclared global symbol
1066
- // abc, creating a potential bug. The following code detects such
1067
- // global symbols. This must be done AFTER the entire file has been
1068
- // parsed, and BEFORE munging the symbol tree. Note that declaring
1069
- // extra symbols in the global scope won't hurt.
1070
- //
1071
- // Note: Since we go through all the tokens to do this, we also use
1072
- // the opportunity to count how many times each identifier is used.
1073
-
1074
- offset = 0;
1075
- braceNesting = 0;
1076
- scopes.clear();
1077
- mode = CHECKING_SYMBOL_TREE;
1078
- parseScope(globalScope);
1079
- globalScope.munge();
1080
- }
1081
-
1082
- private StringBuffer printSymbolTree(int linebreakpos, boolean preserveAllSemiColons)
1083
- throws IOException {
1084
-
1085
- offset = 0;
1086
- braceNesting = 0;
1087
- scopes.clear();
1088
-
1089
- String symbol;
1090
- JavaScriptToken token;
1091
- ScriptOrFnScope currentScope;
1092
- JavaScriptIdentifier identifier;
1093
-
1094
- int length = tokens.size();
1095
- StringBuffer result = new StringBuffer();
1096
-
1097
- int linestartpos = 0;
1098
-
1099
- enterScope(globalScope);
1100
-
1101
- while (offset < length) {
1102
-
1103
- token = consumeToken();
1104
- symbol = token.getValue();
1105
- currentScope = getCurrentScope();
1106
-
1107
- switch (token.getType()) {
1108
-
1109
- case Token.NAME:
1110
-
1111
- if (offset >= 2 && getToken(-2).getType() == Token.DOT ||
1112
- getToken(0).getType() == Token.OBJECTLIT) {
1113
-
1114
- result.append(symbol);
1115
-
1116
- } else {
1117
-
1118
- identifier = getIdentifier(symbol, currentScope);
1119
- if (identifier != null) {
1120
- if (identifier.getMungedValue() != null) {
1121
- result.append(identifier.getMungedValue());
1122
- } else {
1123
- result.append(symbol);
1124
- }
1125
- if (currentScope != globalScope && identifier.getRefcount() == 0) {
1126
- warn("The symbol " + symbol + " is declared but is apparently never used.\nThis code can probably be written in a more compact way.", true);
1127
- }
1128
- } else {
1129
- result.append(symbol);
1130
- }
1131
- }
1132
- break;
1133
-
1134
- case Token.REGEXP:
1135
- case Token.NUMBER:
1136
- case Token.STRING:
1137
- result.append(symbol);
1138
- break;
1139
-
1140
- case Token.ADD:
1141
- case Token.SUB:
1142
- result.append((String) literals.get(new Integer(token.getType())));
1143
- if (offset < length) {
1144
- token = getToken(0);
1145
- if (token.getType() == Token.INC ||
1146
- token.getType() == Token.DEC ||
1147
- token.getType() == Token.ADD ||
1148
- token.getType() == Token.DEC) {
1149
- // Handle the case x +/- ++/-- y
1150
- // We must keep a white space here. Otherwise, x +++ y would be
1151
- // interpreted as x ++ + y by the compiler, which is a bug (due
1152
- // to the implicit assignment being done on the wrong variable)
1153
- result.append(' ');
1154
- } else if (token.getType() == Token.POS && getToken(-1).getType() == Token.ADD ||
1155
- token.getType() == Token.NEG && getToken(-1).getType() == Token.SUB) {
1156
- // Handle the case x + + y and x - - y
1157
- result.append(' ');
1158
- }
1159
- }
1160
- break;
1161
-
1162
- case Token.FUNCTION:
1163
- result.append("function");
1164
- token = consumeToken();
1165
- if (token.getType() == Token.NAME) {
1166
- result.append(' ');
1167
- symbol = token.getValue();
1168
- identifier = getIdentifier(symbol, currentScope);
1169
- assert identifier != null;
1170
- if (identifier.getMungedValue() != null) {
1171
- result.append(identifier.getMungedValue());
1172
- } else {
1173
- result.append(symbol);
1174
- }
1175
- if (currentScope != globalScope && identifier.getRefcount() == 0) {
1176
- warn("The symbol " + symbol + " is declared but is apparently never used.\nThis code can probably be written in a more compact way.", true);
1177
- }
1178
- token = consumeToken();
1179
- }
1180
- assert token.getType() == Token.LP;
1181
- result.append('(');
1182
- currentScope = (ScriptOrFnScope) indexedScopes.get(new Integer(offset));
1183
- enterScope(currentScope);
1184
- while ((token = consumeToken()).getType() != Token.RP) {
1185
- assert token.getType() == Token.NAME || token.getType() == Token.COMMA;
1186
- if (token.getType() == Token.NAME) {
1187
- symbol = token.getValue();
1188
- identifier = getIdentifier(symbol, currentScope);
1189
- assert identifier != null;
1190
- if (identifier.getMungedValue() != null) {
1191
- result.append(identifier.getMungedValue());
1192
- } else {
1193
- result.append(symbol);
1194
- }
1195
- } else if (token.getType() == Token.COMMA) {
1196
- result.append(',');
1197
- }
1198
- }
1199
- result.append(')');
1200
- token = consumeToken();
1201
- assert token.getType() == Token.LC;
1202
- result.append('{');
1203
- braceNesting++;
1204
- token = getToken(0);
1205
- if (token.getType() == Token.STRING &&
1206
- getToken(1).getType() == Token.SEMI) {
1207
- // This is a hint. Skip it!
1208
- consumeToken();
1209
- consumeToken();
1210
- }
1211
- break;
1212
-
1213
- case Token.RETURN:
1214
- case Token.TYPEOF:
1215
- result.append(literals.get(new Integer(token.getType())));
1216
- // No space needed after 'return' and 'typeof' when followed
1217
- // by '(', '[', '{', a string or a regexp.
1218
- if (offset < length) {
1219
- token = getToken(0);
1220
- if (token.getType() != Token.LP &&
1221
- token.getType() != Token.LB &&
1222
- token.getType() != Token.LC &&
1223
- token.getType() != Token.STRING &&
1224
- token.getType() != Token.REGEXP &&
1225
- token.getType() != Token.SEMI) {
1226
- result.append(' ');
1227
- }
1228
- }
1229
- break;
1230
-
1231
- case Token.CASE:
1232
- case Token.THROW:
1233
- result.append(literals.get(new Integer(token.getType())));
1234
- // White-space needed after 'case' and 'throw' when not followed by a string.
1235
- if (offset < length && getToken(0).getType() != Token.STRING) {
1236
- result.append(' ');
1237
- }
1238
- break;
1239
-
1240
- case Token.BREAK:
1241
- case Token.CONTINUE:
1242
- result.append(literals.get(new Integer(token.getType())));
1243
- if (offset < length && getToken(0).getType() != Token.SEMI) {
1244
- // If 'break' or 'continue' is not followed by a semi-colon, it must
1245
- // be followed by a label, hence the need for a white space.
1246
- result.append(' ');
1247
- }
1248
- break;
1249
-
1250
- case Token.LC:
1251
- result.append('{');
1252
- braceNesting++;
1253
- break;
1254
-
1255
- case Token.RC:
1256
- result.append('}');
1257
- braceNesting--;
1258
- assert braceNesting >= currentScope.getBraceNesting();
1259
- if (braceNesting == currentScope.getBraceNesting()) {
1260
- leaveCurrentScope();
1261
- }
1262
- break;
1263
-
1264
- case Token.SEMI:
1265
- // No need to output a semi-colon if the next character is a right-curly...
1266
- if (preserveAllSemiColons || offset < length && getToken(0).getType() != Token.RC) {
1267
- result.append(';');
1268
- }
1269
-
1270
- if (linebreakpos >= 0 && result.length() - linestartpos > linebreakpos) {
1271
- // Some source control tools don't like it when files containing lines longer
1272
- // than, say 8000 characters, are checked in. The linebreak option is used in
1273
- // that case to split long lines after a specific column.
1274
- result.append('\n');
1275
- linestartpos = result.length();
1276
- }
1277
- break;
1278
-
1279
- case Token.CONDCOMMENT:
1280
- case Token.KEEPCOMMENT:
1281
- if (result.length() > 0 && result.charAt(result.length() - 1) != '\n') {
1282
- result.append("\n");
1283
- }
1284
- result.append("/*");
1285
- result.append(symbol);
1286
- result.append("*/\n");
1287
- break;
1288
-
1289
- default:
1290
- String literal = (String) literals.get(new Integer(token.getType()));
1291
- if (literal != null) {
1292
- result.append(literal);
1293
- } else {
1294
- warn("This symbol cannot be printed: " + symbol, true);
1295
- }
1296
- break;
1297
- }
1298
- }
1299
-
1300
- // Append a semi-colon at the end, even if unnecessary semi-colons are
1301
- // supposed to be removed. This is especially useful when concatenating
1302
- // several minified files (the absence of an ending semi-colon at the
1303
- // end of one file may very likely cause a syntax error)
1304
- if (!preserveAllSemiColons &&
1305
- result.length() > 0 &&
1306
- getToken(-1).getType() != Token.CONDCOMMENT &&
1307
- getToken(-1).getType() != Token.KEEPCOMMENT) {
1308
- if (result.charAt(result.length() - 1) == '\n') {
1309
- result.setCharAt(result.length() - 1, ';');
1310
- } else {
1311
- result.append(';');
1312
- }
1313
- }
1314
-
1315
- return result;
1316
- }
1317
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
lib/Diglin/yuicompressor-2.4.6/src/com/yahoo/platform/yui/compressor/JavaScriptIdentifier.java DELETED
@@ -1,55 +0,0 @@
1
- /*
2
- * YUI Compressor
3
- * http://developer.yahoo.com/yui/compressor/
4
- * Author: Julien Lecomte - http://www.julienlecomte.net/
5
- * Copyright (c) 2011 Yahoo! Inc. All rights reserved.
6
- * The copyrights embodied in the content of this file are licensed
7
- * by Yahoo! Inc. under the BSD (revised) open source license.
8
- */
9
- package com.yahoo.platform.yui.compressor;
10
-
11
- import org.mozilla.javascript.Token;
12
-
13
- /**
14
- * JavaScriptIdentifier represents a variable/function identifier.
15
- */
16
- class JavaScriptIdentifier extends JavaScriptToken {
17
-
18
- private int refcount = 0;
19
- private String mungedValue;
20
- private ScriptOrFnScope declaredScope;
21
- private boolean markedForMunging = true;
22
-
23
- JavaScriptIdentifier(String value, ScriptOrFnScope declaredScope) {
24
- super(Token.NAME, value);
25
- this.declaredScope = declaredScope;
26
- }
27
-
28
- ScriptOrFnScope getDeclaredScope() {
29
- return declaredScope;
30
- }
31
-
32
- void setMungedValue(String value) {
33
- mungedValue = value;
34
- }
35
-
36
- String getMungedValue() {
37
- return mungedValue;
38
- }
39
-
40
- void preventMunging() {
41
- markedForMunging = false;
42
- }
43
-
44
- boolean isMarkedForMunging() {
45
- return markedForMunging;
46
- }
47
-
48
- void incrementRefcount() {
49
- refcount++;
50
- }
51
-
52
- int getRefcount() {
53
- return refcount;
54
- }
55
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
lib/Diglin/yuicompressor-2.4.6/src/com/yahoo/platform/yui/compressor/JavaScriptToken.java DELETED
@@ -1,28 +0,0 @@
1
- /*
2
- * YUI Compressor
3
- * http://developer.yahoo.com/yui/compressor/
4
- * Author: Julien Lecomte - http://www.julienlecomte.net/
5
- * Copyright (c) 2011 Yahoo! Inc. All rights reserved.
6
- * The copyrights embodied in the content of this file are licensed
7
- * by Yahoo! Inc. under the BSD (revised) open source license.
8
- */
9
- package com.yahoo.platform.yui.compressor;
10
-
11
- public class JavaScriptToken {
12
-
13
- private int type;
14
- private String value;
15
-
16
- JavaScriptToken(int type, String value) {
17
- this.type = type;
18
- this.value = value;
19
- }
20
-
21
- int getType() {
22
- return type;
23
- }
24
-
25
- String getValue() {
26
- return value;
27
- }
28
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
lib/Diglin/yuicompressor-2.4.6/src/com/yahoo/platform/yui/compressor/ScriptOrFnScope.java DELETED
@@ -1,160 +0,0 @@
1
- /*
2
- * YUI Compressor
3
- * http://developer.yahoo.com/yui/compressor/
4
- * Author: Julien Lecomte - http://www.julienlecomte.net/
5
- * Copyright (c) 2011 Yahoo! Inc. All rights reserved.
6
- * The copyrights embodied in the content of this file are licensed
7
- * by Yahoo! Inc. under the BSD (revised) open source license.
8
- */
9
- package com.yahoo.platform.yui.compressor;
10
-
11
- import java.util.ArrayList;
12
- import java.util.Enumeration;
13
- import java.util.Hashtable;
14
-
15
- class ScriptOrFnScope {
16
-
17
- private int braceNesting;
18
- private ScriptOrFnScope parentScope;
19
- private ArrayList subScopes;
20
- private Hashtable identifiers = new Hashtable();
21
- private Hashtable hints = new Hashtable();
22
- private boolean markedForMunging = true;
23
- private int varcount = 0;
24
-
25
- ScriptOrFnScope(int braceNesting, ScriptOrFnScope parentScope) {
26
- this.braceNesting = braceNesting;
27
- this.parentScope = parentScope;
28
- this.subScopes = new ArrayList();
29
- if (parentScope != null) {
30
- parentScope.subScopes.add(this);
31
- }
32
- }
33
-
34
- int getBraceNesting() {
35
- return braceNesting;
36
- }
37
-
38
- ScriptOrFnScope getParentScope() {
39
- return parentScope;
40
- }
41
-
42
- JavaScriptIdentifier declareIdentifier(String symbol) {
43
- JavaScriptIdentifier identifier = (JavaScriptIdentifier) identifiers.get(symbol);
44
- if (identifier == null) {
45
- identifier = new JavaScriptIdentifier(symbol, this);
46
- identifiers.put(symbol, identifier);
47
- }
48
- return identifier;
49
- }
50
-
51
- JavaScriptIdentifier getIdentifier(String symbol) {
52
- return (JavaScriptIdentifier) identifiers.get(symbol);
53
- }
54
-
55
- void addHint(String variableName, String variableType) {
56
- hints.put(variableName, variableType);
57
- }
58
-
59
- void preventMunging() {
60
- if (parentScope != null) {
61
- // The symbols in the global scope don't get munged,
62
- // but the sub-scopes it contains do get munged.
63
- markedForMunging = false;
64
- }
65
- }
66
-
67
- private ArrayList getUsedSymbols() {
68
- ArrayList result = new ArrayList();
69
- Enumeration elements = identifiers.elements();
70
- while (elements.hasMoreElements()) {
71
- JavaScriptIdentifier identifier = (JavaScriptIdentifier) elements.nextElement();
72
- String mungedValue = identifier.getMungedValue();
73
- if (mungedValue == null) {
74
- mungedValue = identifier.getValue();
75
- }
76
- result.add(mungedValue);
77
- }
78
- return result;
79
- }
80
-
81
- private ArrayList getAllUsedSymbols() {
82
- ArrayList result = new ArrayList();
83
- ScriptOrFnScope scope = this;
84
- while (scope != null) {
85
- result.addAll(scope.getUsedSymbols());
86
- scope = scope.parentScope;
87
- }
88
- return result;
89
- }
90
-
91
- int incrementVarCount() {
92
- varcount++;
93
- return varcount;
94
- }
95
-
96
- void munge() {
97
-
98
- if (!markedForMunging) {
99
- // Stop right here if this scope was flagged as unsafe for munging.
100
- return;
101
- }
102
-
103
- int pickFromSet = 1;
104
-
105
- // Do not munge symbols in the global scope!
106
- if (parentScope != null) {
107
-
108
- ArrayList freeSymbols = new ArrayList();
109
-
110
- freeSymbols.addAll(JavaScriptCompressor.ones);
111
- freeSymbols.removeAll(getAllUsedSymbols());
112
- if (freeSymbols.size() == 0) {
113
- pickFromSet = 2;
114
- freeSymbols.addAll(JavaScriptCompressor.twos);
115
- freeSymbols.removeAll(getAllUsedSymbols());
116
- }
117
- if (freeSymbols.size() == 0) {
118
- pickFromSet = 3;
119
- freeSymbols.addAll(JavaScriptCompressor.threes);
120
- freeSymbols.removeAll(getAllUsedSymbols());
121
- }
122
- if (freeSymbols.size() == 0) {
123
- throw new IllegalStateException("The YUI Compressor ran out of symbols. Aborting...");
124
- }
125
-
126
- Enumeration elements = identifiers.elements();
127
- while (elements.hasMoreElements()) {
128
- if (freeSymbols.size() == 0) {
129
- pickFromSet++;
130
- if (pickFromSet == 2) {
131
- freeSymbols.addAll(JavaScriptCompressor.twos);
132
- } else if (pickFromSet == 3) {
133
- freeSymbols.addAll(JavaScriptCompressor.threes);
134
- } else {
135
- throw new IllegalStateException("The YUI Compressor ran out of symbols. Aborting...");
136
- }
137
- // It is essential to remove the symbols already used in
138
- // the containing scopes, or some of the variables declared
139
- // in the containing scopes will be redeclared, which can
140
- // lead to errors.
141
- freeSymbols.removeAll(getAllUsedSymbols());
142
- }
143
-
144
- String mungedValue;
145
- JavaScriptIdentifier identifier = (JavaScriptIdentifier) elements.nextElement();
146
- if (identifier.isMarkedForMunging()) {
147
- mungedValue = (String) freeSymbols.remove(0);
148
- } else {
149
- mungedValue = identifier.getValue();
150
- }
151
- identifier.setMungedValue(mungedValue);
152
- }
153
- }
154
-
155
- for (int i = 0; i < subScopes.size(); i++) {
156
- ScriptOrFnScope scope = (ScriptOrFnScope) subScopes.get(i);
157
- scope.munge();
158
- }
159
- }
160
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
lib/Diglin/yuicompressor-2.4.6/src/com/yahoo/platform/yui/compressor/YUICompressor.java DELETED
@@ -1,255 +0,0 @@
1
- /*
2
- * YUI Compressor
3
- * http://developer.yahoo.com/yui/compressor/
4
- * Author: Julien Lecomte - http://www.julienlecomte.net/
5
- * Copyright (c) 2011 Yahoo! Inc. All rights reserved.
6
- * The copyrights embodied in the content of this file are licensed
7
- * by Yahoo! Inc. under the BSD (revised) open source license.
8
- */
9
- package com.yahoo.platform.yui.compressor;
10
-
11
- import jargs.gnu.CmdLineParser;
12
- import org.mozilla.javascript.ErrorReporter;
13
- import org.mozilla.javascript.EvaluatorException;
14
-
15
- import java.io.*;
16
- import java.nio.charset.Charset;
17
-
18
- public class YUICompressor {
19
-
20
- public static void main(String args[]) {
21
-
22
- CmdLineParser parser = new CmdLineParser();
23
- CmdLineParser.Option typeOpt = parser.addStringOption("type");
24
- CmdLineParser.Option verboseOpt = parser.addBooleanOption('v', "verbose");
25
- CmdLineParser.Option nomungeOpt = parser.addBooleanOption("nomunge");
26
- CmdLineParser.Option linebreakOpt = parser.addStringOption("line-break");
27
- CmdLineParser.Option preserveSemiOpt = parser.addBooleanOption("preserve-semi");
28
- CmdLineParser.Option disableOptimizationsOpt = parser.addBooleanOption("disable-optimizations");
29
- CmdLineParser.Option helpOpt = parser.addBooleanOption('h', "help");
30
- CmdLineParser.Option charsetOpt = parser.addStringOption("charset");
31
- CmdLineParser.Option outputFilenameOpt = parser.addStringOption('o', "output");
32
-
33
- Reader in = null;
34
- Writer out = null;
35
-
36
- try {
37
-
38
- parser.parse(args);
39
-
40
- Boolean help = (Boolean) parser.getOptionValue(helpOpt);
41
- if (help != null && help.booleanValue()) {
42
- usage();
43
- System.exit(0);
44
- }
45
-
46
- boolean verbose = parser.getOptionValue(verboseOpt) != null;
47
-
48
- String charset = (String) parser.getOptionValue(charsetOpt);
49
- if (charset == null || !Charset.isSupported(charset)) {
50
- // charset = System.getProperty("file.encoding");
51
- // if (charset == null) {
52
- // charset = "UTF-8";
53
- // }
54
-
55
- // UTF-8 seems to be a better choice than what the system is reporting
56
- charset = "UTF-8";
57
-
58
-
59
- if (verbose) {
60
- System.err.println("\n[INFO] Using charset " + charset);
61
- }
62
- }
63
-
64
- int linebreakpos = -1;
65
- String linebreakstr = (String) parser.getOptionValue(linebreakOpt);
66
- if (linebreakstr != null) {
67
- try {
68
- linebreakpos = Integer.parseInt(linebreakstr, 10);
69
- } catch (NumberFormatException e) {
70
- usage();
71
- System.exit(1);
72
- }
73
- }
74
-
75
- String type = (String) parser.getOptionValue(typeOpt);
76
- if (type != null && !type.equalsIgnoreCase("js") && !type.equalsIgnoreCase("css")) {
77
- usage();
78
- System.exit(1);
79
- }
80
-
81
- String[] fileArgs = parser.getRemainingArgs();
82
- java.util.List files = java.util.Arrays.asList(fileArgs);
83
- if (files.isEmpty()) {
84
- if (type == null) {
85
- usage();
86
- System.exit(1);
87
- }
88
- files = new java.util.ArrayList();
89
- files.add("-"); // read from stdin
90
- }
91
-
92
- String output = (String) parser.getOptionValue(outputFilenameOpt);
93
- String pattern[] = output != null ? output.split(":") : new String[0];
94
-
95
- java.util.Iterator filenames = files.iterator();
96
- while(filenames.hasNext()) {
97
- String inputFilename = (String)filenames.next();
98
-
99
- try {
100
- if (inputFilename.equals("-")) {
101
-
102
- in = new InputStreamReader(System.in, charset);
103
-
104
- } else {
105
-
106
- if (type == null) {
107
- int idx = inputFilename.lastIndexOf('.');
108
- if (idx >= 0 && idx < inputFilename.length() - 1) {
109
- type = inputFilename.substring(idx + 1);
110
- }
111
- }
112
-
113
- if (type == null || !type.equalsIgnoreCase("js") && !type.equalsIgnoreCase("css")) {
114
- usage();
115
- System.exit(1);
116
- }
117
-
118
- in = new InputStreamReader(new FileInputStream(inputFilename), charset);
119
- }
120
-
121
- String outputFilename = output;
122
- // if a substitution pattern was passed in
123
- if (pattern.length > 1 && files.size() > 1) {
124
- outputFilename = inputFilename.replaceFirst(pattern[0], pattern[1]);
125
- }
126
-
127
- if (type.equalsIgnoreCase("js")) {
128
-
129
- try {
130
-
131
- JavaScriptCompressor compressor = new JavaScriptCompressor(in, new ErrorReporter() {
132
-
133
- public void warning(String message, String sourceName,
134
- int line, String lineSource, int lineOffset) {
135
- if (line < 0) {
136
- System.err.println("\n[WARNING] " + message);
137
- } else {
138
- System.err.println("\n[WARNING] " + line + ':' + lineOffset + ':' + message);
139
- }
140
- }
141
-
142
- public void error(String message, String sourceName,
143
- int line, String lineSource, int lineOffset) {
144
- if (line < 0) {
145
- System.err.println("\n[ERROR] " + message);
146
- } else {
147
- System.err.println("\n[ERROR] " + line + ':' + lineOffset + ':' + message);
148
- }
149
- }
150
-
151
- public EvaluatorException runtimeError(String message, String sourceName,
152
- int line, String lineSource, int lineOffset) {
153
- error(message, sourceName, line, lineSource, lineOffset);
154
- return new EvaluatorException(message);
155
- }
156
- });
157
-
158
- // Close the input stream first, and then open the output stream,
159
- // in case the output file should override the input file.
160
- in.close(); in = null;
161
-
162
- if (outputFilename == null) {
163
- out = new OutputStreamWriter(System.out, charset);
164
- } else {
165
- out = new OutputStreamWriter(new FileOutputStream(outputFilename), charset);
166
- }
167
-
168
- boolean munge = parser.getOptionValue(nomungeOpt) == null;
169
- boolean preserveAllSemiColons = parser.getOptionValue(preserveSemiOpt) != null;
170
- boolean disableOptimizations = parser.getOptionValue(disableOptimizationsOpt) != null;
171
-
172
- compressor.compress(out, linebreakpos, munge, verbose,
173
- preserveAllSemiColons, disableOptimizations);
174
-
175
- } catch (EvaluatorException e) {
176
-
177
- e.printStackTrace();
178
- // Return a special error code used specifically by the web front-end.
179
- System.exit(2);
180
-
181
- }
182
-
183
- } else if (type.equalsIgnoreCase("css")) {
184
-
185
- CssCompressor compressor = new CssCompressor(in);
186
-
187
- // Close the input stream first, and then open the output stream,
188
- // in case the output file should override the input file.
189
- in.close(); in = null;
190
-
191
- if (outputFilename == null) {
192
- out = new OutputStreamWriter(System.out, charset);
193
- } else {
194
- out = new OutputStreamWriter(new FileOutputStream(outputFilename), charset);
195
- }
196
-
197
- compressor.compress(out, linebreakpos);
198
- }
199
-
200
- } catch (IOException e) {
201
-
202
- e.printStackTrace();
203
- System.exit(1);
204
-
205
- } finally {
206
-
207
- if (in != null) {
208
- try {
209
- in.close();
210
- } catch (IOException e) {
211
- e.printStackTrace();
212
- }
213
- }
214
-
215
- if (out != null) {
216
- try {
217
- out.close();
218
- } catch (IOException e) {
219
- e.printStackTrace();
220
- }
221
- }
222
- }
223
- }
224
- } catch (CmdLineParser.OptionException e) {
225
-
226
- usage();
227
- System.exit(1);
228
- }
229
- }
230
-
231
- private static void usage() {
232
- System.err.println(
233
- "\nUsage: java -jar yuicompressor-x.y.z.jar [options] [input file]\n\n"
234
-
235
- + "Global Options\n"
236
- + " -h, --help Displays this information\n"
237
- + " --type <js|css> Specifies the type of the input file\n"
238
- + " --charset <charset> Read the input file using <charset>\n"
239
- + " --line-break <column> Insert a line break after the specified column number\n"
240
- + " -v, --verbose Display informational messages and warnings\n"
241
- + " -o <file> Place the output into <file>. Defaults to stdout.\n"
242
- + " Multiple files can be processed using the following syntax:\n"
243
- + " java -jar yuicompressor.jar -o '.css$:-min.css' *.css\n"
244
- + " java -jar yuicompressor.jar -o '.js$:-min.js' *.js\n\n"
245
-
246
- + "JavaScript Options\n"
247
- + " --nomunge Minify only, do not obfuscate\n"
248
- + " --preserve-semi Preserve all semicolons\n"
249
- + " --disable-optimizations Disable all micro optimizations\n\n"
250
-
251
- + "If no input file is specified, it defaults to stdin. In this case, the 'type'\n"
252
- + "option is required. Otherwise, the 'type' option is required only if the input\n"
253
- + "file extension is neither 'js' nor 'css'.");
254
- }
255
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
lib/Diglin/yuicompressor-2.4.6/src/org/mozilla/javascript/Decompiler.java DELETED
@@ -1,908 +0,0 @@
1
- /* ***** BEGIN LICENSE BLOCK *****
2
- *
3
- * Version: MPL 1.1
4
- *
5
- * The contents of this file are subject to the Mozilla Public License
6
- * Version 1.1 (the "License"); you may not use this file except in
7
- * compliance with the License. You may obtain a copy of the License
8
- * at http://www.mozilla.org/MPL/
9
- *
10
- * Software distributed under the License is distributed on an "AS IS"
11
- * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.
12
- * See the License for the specific language governing rights and
13
- * limitations under the License.
14
- *
15
- * The Original Code is org/mozilla/javascript/Decompiler.java,
16
- * a component of the Rhino Library ( http://www.mozilla.org/rhino/ )
17
- * This file is a modification of the Original Code developed
18
- * for YUI Compressor.
19
- *
20
- * The Initial Developer of the Original Code is Mozilla Foundation
21
- *
22
- * Copyright (c) 2009 Mozilla Foundation. All Rights Reserved.
23
- *
24
- * Contributor(s): Yahoo! Inc. 2009
25
- *
26
- * ***** END LICENSE BLOCK ***** */
27
-
28
- package org.mozilla.javascript;
29
-
30
- /**
31
- * The following class save decompilation information about the source.
32
- * Source information is returned from the parser as a String
33
- * associated with function nodes and with the toplevel script. When
34
- * saved in the constant pool of a class, this string will be UTF-8
35
- * encoded, and token values will occupy a single byte.
36
-
37
- * Source is saved (mostly) as token numbers. The tokens saved pretty
38
- * much correspond to the token stream of a 'canonical' representation
39
- * of the input program, as directed by the parser. (There were a few
40
- * cases where tokens could have been left out where decompiler could
41
- * easily reconstruct them, but I left them in for clarity). (I also
42
- * looked adding source collection to TokenStream instead, where I
43
- * could have limited the changes to a few lines in getToken... but
44
- * this wouldn't have saved any space in the resulting source
45
- * representation, and would have meant that I'd have to duplicate
46
- * parser logic in the decompiler to disambiguate situations where
47
- * newlines are important.) The function decompile expands the
48
- * tokens back into their string representations, using simple
49
- * lookahead to correct spacing and indentation.
50
- *
51
- * Assignments are saved as two-token pairs (Token.ASSIGN, op). Number tokens
52
- * are stored inline, as a NUMBER token, a character representing the type, and
53
- * either 1 or 4 characters representing the bit-encoding of the number. String
54
- * types NAME, STRING and OBJECT are currently stored as a token type,
55
- * followed by a character giving the length of the string (assumed to
56
- * be less than 2^16), followed by the characters of the string
57
- * inlined into the source string. Changing this to some reference to
58
- * to the string in the compiled class' constant pool would probably
59
- * save a lot of space... but would require some method of deriving
60
- * the final constant pool entry from information available at parse
61
- * time.
62
- */
63
- public class Decompiler
64
- {
65
- /**
66
- * Flag to indicate that the decompilation should omit the
67
- * function header and trailing brace.
68
- */
69
- public static final int ONLY_BODY_FLAG = 1 << 0;
70
-
71
- /**
72
- * Flag to indicate that the decompilation generates toSource result.
73
- */
74
- public static final int TO_SOURCE_FLAG = 1 << 1;
75
-
76
- /**
77
- * Decompilation property to specify initial ident value.
78
- */
79
- public static final int INITIAL_INDENT_PROP = 1;
80
-
81
- /**
82
- * Decompilation property to specify default identation offset.
83
- */
84
- public static final int INDENT_GAP_PROP = 2;
85
-
86
- /**
87
- * Decompilation property to specify identation offset for case labels.
88
- */
89
- public static final int CASE_GAP_PROP = 3;
90
-
91
- // Marker to denote the last RC of function so it can be distinguished from
92
- // the last RC of object literals in case of function expressions
93
- private static final int FUNCTION_END = Token.LAST_TOKEN + 1;
94
-
95
- String getEncodedSource()
96
- {
97
- return sourceToString(0);
98
- }
99
-
100
- int getCurrentOffset()
101
- {
102
- return sourceTop;
103
- }
104
-
105
- int markFunctionStart(int functionType)
106
- {
107
- int savedOffset = getCurrentOffset();
108
- addToken(Token.FUNCTION);
109
- append((char)functionType);
110
- return savedOffset;
111
- }
112
-
113
- int markFunctionEnd(int functionStart)
114
- {
115
- int offset = getCurrentOffset();
116
- append((char)FUNCTION_END);
117
- return offset;
118
- }
119
-
120
- void addToken(int token)
121
- {
122
- if (!(0 <= token && token <= Token.LAST_TOKEN))
123
- throw new IllegalArgumentException();
124
-
125
- append((char)token);
126
- }
127
-
128
- void addEOL(int token)
129
- {
130
- if (!(0 <= token && token <= Token.LAST_TOKEN))
131
- throw new IllegalArgumentException();
132
-
133
- append((char)token);
134
- append((char)Token.EOL);
135
- }
136
-
137
- void addName(String str)
138
- {
139
- addToken(Token.NAME);
140
- appendString(str);
141
- }
142
-
143
- void addString(String str)
144
- {
145
- addToken(Token.STRING);
146
- appendString(str);
147
- }
148
-
149
- void addRegexp(String regexp, String flags)
150
- {
151
- addToken(Token.REGEXP);
152
- appendString('/' + regexp + '/' + flags);
153
- }
154
-
155
- void addJScriptConditionalComment(String str)
156
- {
157
- addToken(Token.CONDCOMMENT);
158
- appendString(str);
159
- }
160
-
161
- void addPreservedComment(String str)
162
- {
163
- addToken(Token.KEEPCOMMENT);
164
- appendString(str);
165
- }
166
-
167
- void addNumber(double n)
168
- {
169
- addToken(Token.NUMBER);
170
-
171
- /* encode the number in the source stream.
172
- * Save as NUMBER type (char | char char char char)
173
- * where type is
174
- * 'D' - double, 'S' - short, 'J' - long.
175
-
176
- * We need to retain float vs. integer type info to keep the
177
- * behavior of liveconnect type-guessing the same after
178
- * decompilation. (Liveconnect tries to present 1.0 to Java
179
- * as a float/double)
180
- * OPT: This is no longer true. We could compress the format.
181
-
182
- * This may not be the most space-efficient encoding;
183
- * the chars created below may take up to 3 bytes in
184
- * constant pool UTF-8 encoding, so a Double could take
185
- * up to 12 bytes.
186
- */
187
-
188
- long lbits = (long)n;
189
- if (lbits != n) {
190
- // if it's floating point, save as a Double bit pattern.
191
- // (12/15/97 our scanner only returns Double for f.p.)
192
- lbits = Double.doubleToLongBits(n);
193
- append('D');
194
- append((char)(lbits >> 48));
195
- append((char)(lbits >> 32));
196
- append((char)(lbits >> 16));
197
- append((char)lbits);
198
- }
199
- else {
200
- // we can ignore negative values, bc they're already prefixed
201
- // by NEG
202
- if (lbits < 0) Kit.codeBug();
203
-
204
- // will it fit in a char?
205
- // this gives a short encoding for integer values up to 2^16.
206
- if (lbits <= Character.MAX_VALUE) {
207
- append('S');
208
- append((char)lbits);
209
- }
210
- else { // Integral, but won't fit in a char. Store as a long.
211
- append('J');
212
- append((char)(lbits >> 48));
213
- append((char)(lbits >> 32));
214
- append((char)(lbits >> 16));
215
- append((char)lbits);
216
- }
217
- }
218
- }
219
-
220
- private void appendString(String str)
221
- {
222
- int L = str.length();
223
- int lengthEncodingSize = 1;
224
- if (L >= 0x8000) {
225
- lengthEncodingSize = 2;
226
- }
227
- int nextTop = sourceTop + lengthEncodingSize + L;
228
- if (nextTop > sourceBuffer.length) {
229
- increaseSourceCapacity(nextTop);
230
- }
231
- if (L >= 0x8000) {
232
- // Use 2 chars to encode strings exceeding 32K, were the highest
233
- // bit in the first char indicates presence of the next byte
234
- sourceBuffer[sourceTop] = (char)(0x8000 | (L >>> 16));
235
- ++sourceTop;
236
- }
237
- sourceBuffer[sourceTop] = (char)L;
238
- ++sourceTop;
239
- str.getChars(0, L, sourceBuffer, sourceTop);
240
- sourceTop = nextTop;
241
- }
242
-
243
- private void append(char c)
244
- {
245
- if (sourceTop == sourceBuffer.length) {
246
- increaseSourceCapacity(sourceTop + 1);
247
- }
248
- sourceBuffer[sourceTop] = c;
249
- ++sourceTop;
250
- }
251
-
252
- private void increaseSourceCapacity(int minimalCapacity)
253
- {
254
- // Call this only when capacity increase is must
255
- if (minimalCapacity <= sourceBuffer.length) Kit.codeBug();
256
- int newCapacity = sourceBuffer.length * 2;
257
- if (newCapacity < minimalCapacity) {
258
- newCapacity = minimalCapacity;
259
- }
260
- char[] tmp = new char[newCapacity];
261
- System.arraycopy(sourceBuffer, 0, tmp, 0, sourceTop);
262
- sourceBuffer = tmp;
263
- }
264
-
265
- private String sourceToString(int offset)
266
- {
267
- if (offset < 0 || sourceTop < offset) Kit.codeBug();
268
- return new String(sourceBuffer, offset, sourceTop - offset);
269
- }
270
-
271
- /**
272
- * Decompile the source information associated with this js
273
- * function/script back into a string. For the most part, this
274
- * just means translating tokens back to their string
275
- * representations; there's a little bit of lookahead logic to
276
- * decide the proper spacing/indentation. Most of the work in
277
- * mapping the original source to the prettyprinted decompiled
278
- * version is done by the parser.
279
- *
280
- * @param source encoded source tree presentation
281
- *
282
- * @param flags flags to select output format
283
- *
284
- * @param properties indentation properties
285
- *
286
- */
287
- public static String decompile(String source, int flags,
288
- UintMap properties)
289
- {
290
- int length = source.length();
291
- if (length == 0) { return ""; }
292
-
293
- int indent = properties.getInt(INITIAL_INDENT_PROP, 0);
294
- if (indent < 0) throw new IllegalArgumentException();
295
- int indentGap = properties.getInt(INDENT_GAP_PROP, 4);
296
- if (indentGap < 0) throw new IllegalArgumentException();
297
- int caseGap = properties.getInt(CASE_GAP_PROP, 2);
298
- if (caseGap < 0) throw new IllegalArgumentException();
299
-
300
- StringBuffer result = new StringBuffer();
301
- boolean justFunctionBody = (0 != (flags & Decompiler.ONLY_BODY_FLAG));
302
- boolean toSource = (0 != (flags & Decompiler.TO_SOURCE_FLAG));
303
-
304
- // Spew tokens in source, for debugging.
305
- // as TYPE number char
306
- if (printSource) {
307
- System.err.println("length:" + length);
308
- for (int i = 0; i < length; ++i) {
309
- // Note that tokenToName will fail unless Context.printTrees
310
- // is true.
311
- String tokenname = null;
312
- if (Token.printNames) {
313
- tokenname = Token.name(source.charAt(i));
314
- }
315
- if (tokenname == null) {
316
- tokenname = "---";
317
- }
318
- String pad = tokenname.length() > 7
319
- ? "\t"
320
- : "\t\t";
321
- System.err.println
322
- (tokenname
323
- + pad + (int)source.charAt(i)
324
- + "\t'" + ScriptRuntime.escapeString
325
- (source.substring(i, i+1))
326
- + "'");
327
- }
328
- System.err.println();
329
- }
330
-
331
- int braceNesting = 0;
332
- boolean afterFirstEOL = false;
333
- int i = 0;
334
- int topFunctionType;
335
- if (source.charAt(i) == Token.SCRIPT) {
336
- ++i;
337
- topFunctionType = -1;
338
- } else {
339
- topFunctionType = source.charAt(i + 1);
340
- }
341
-
342
- if (!toSource) {
343
- // add an initial newline to exactly match js.
344
- result.append('\n');
345
- for (int j = 0; j < indent; j++)
346
- result.append(' ');
347
- } else {
348
- if (topFunctionType == FunctionNode.FUNCTION_EXPRESSION) {
349
- result.append('(');
350
- }
351
- }
352
-
353
- while (i < length) {
354
- switch(source.charAt(i)) {
355
- case Token.GET:
356
- case Token.SET:
357
- result.append(source.charAt(i) == Token.GET ? "get " : "set ");
358
- ++i;
359
- i = printSourceString(source, i + 1, false, result);
360
- // Now increment one more to get past the FUNCTION token
361
- ++i;
362
- break;
363
-
364
- case Token.NAME:
365
- case Token.REGEXP: // re-wrapped in '/'s in parser...
366
- i = printSourceString(source, i + 1, false, result);
367
- continue;
368
-
369
- case Token.STRING:
370
- i = printSourceString(source, i + 1, true, result);
371
- continue;
372
-
373
- case Token.NUMBER:
374
- i = printSourceNumber(source, i + 1, result);
375
- continue;
376
-
377
- case Token.TRUE:
378
- result.append("true");
379
- break;
380
-
381
- case Token.FALSE:
382
- result.append("false");
383
- break;
384
-
385
- case Token.NULL:
386
- result.append("null");
387
- break;
388
-
389
- case Token.THIS:
390
- result.append("this");
391
- break;
392
-
393
- case Token.FUNCTION:
394
- ++i; // skip function type
395
- result.append("function ");
396
- break;
397
-
398
- case FUNCTION_END:
399
- // Do nothing
400
- break;
401
-
402
- case Token.COMMA:
403
- result.append(", ");
404
- break;
405
-
406
- case Token.LC:
407
- ++braceNesting;
408
- if (Token.EOL == getNext(source, length, i))
409
- indent += indentGap;
410
- result.append('{');
411
- break;
412
-
413
- case Token.RC: {
414
- --braceNesting;
415
- /* don't print the closing RC if it closes the
416
- * toplevel function and we're called from
417
- * decompileFunctionBody.
418
- */
419
- if (justFunctionBody && braceNesting == 0)
420
- break;
421
-
422
- result.append('}');
423
- switch (getNext(source, length, i)) {
424
- case Token.EOL:
425
- case FUNCTION_END:
426
- indent -= indentGap;
427
- break;
428
- case Token.WHILE:
429
- case Token.ELSE:
430
- indent -= indentGap;
431
- result.append(' ');
432
- break;
433
- }
434
- break;
435
- }
436
- case Token.LP:
437
- result.append('(');
438
- break;
439
-
440
- case Token.RP:
441
- result.append(')');
442
- if (Token.LC == getNext(source, length, i))
443
- result.append(' ');
444
- break;
445
-
446
- case Token.LB:
447
- result.append('[');
448
- break;
449
-
450
- case Token.RB:
451
- result.append(']');
452
- break;
453
-
454
- case Token.EOL: {
455
- if (toSource) break;
456
- boolean newLine = true;
457
- if (!afterFirstEOL) {
458
- afterFirstEOL = true;
459
- if (justFunctionBody) {
460
- /* throw away just added 'function name(...) {'
461
- * and restore the original indent
462
- */
463
- result.setLength(0);
464
- indent -= indentGap;
465
- newLine = false;
466
- }
467
- }
468
- if (newLine) {
469
- result.append('\n');
470
- }
471
-
472
- /* add indent if any tokens remain,
473
- * less setback if next token is
474
- * a label, case or default.
475
- */
476
- if (i + 1 < length) {
477
- int less = 0;
478
- int nextToken = source.charAt(i + 1);
479
- if (nextToken == Token.CASE
480
- || nextToken == Token.DEFAULT)
481
- {
482
- less = indentGap - caseGap;
483
- } else if (nextToken == Token.RC) {
484
- less = indentGap;
485
- }
486
-
487
- /* elaborate check against label... skip past a
488
- * following inlined NAME and look for a COLON.
489
- */
490
- else if (nextToken == Token.NAME) {
491
- int afterName = getSourceStringEnd(source, i + 2);
492
- if (source.charAt(afterName) == Token.COLON)
493
- less = indentGap;
494
- }
495
-
496
- for (; less < indent; less++)
497
- result.append(' ');
498
- }
499
- break;
500
- }
501
- case Token.DOT:
502
- result.append('.');
503
- break;
504
-
505
- case Token.NEW:
506
- result.append("new ");
507
- break;
508
-
509
- case Token.DELPROP:
510
- result.append("delete ");
511
- break;
512
-
513
- case Token.IF:
514
- result.append("if ");
515
- break;
516
-
517
- case Token.ELSE:
518
- result.append("else ");
519
- break;
520
-
521
- case Token.FOR:
522
- result.append("for ");
523
- break;
524
-
525
- case Token.IN:
526
- result.append(" in ");
527
- break;
528
-
529
- case Token.WITH:
530
- result.append("with ");
531
- break;
532
-
533
- case Token.WHILE:
534
- result.append("while ");
535
- break;
536
-
537
- case Token.DO:
538
- result.append("do ");
539
- break;
540
-
541
- case Token.TRY:
542
- result.append("try ");
543
- break;
544
-
545
- case Token.CATCH:
546
- result.append("catch ");
547
- break;
548
-
549
- case Token.FINALLY:
550
- result.append("finally ");
551
- break;
552
-
553
- case Token.THROW:
554
- result.append("throw ");
555
- break;
556
-
557
- case Token.SWITCH:
558
- result.append("switch ");
559
- break;
560
-
561
- case Token.BREAK:
562
- result.append("break");
563
- if (Token.NAME == getNext(source, length, i))
564
- result.append(' ');
565
- break;
566
-
567
- case Token.CONTINUE:
568
- result.append("continue");
569
- if (Token.NAME == getNext(source, length, i))
570
- result.append(' ');
571
- break;
572
-
573
- case Token.CASE:
574
- result.append("case ");
575
- break;
576
-
577
- case Token.DEFAULT:
578
- result.append("default");
579
- break;
580
-
581
- case Token.RETURN:
582
- result.append("return");
583
- if (Token.SEMI != getNext(source, length, i))
584
- result.append(' ');
585
- break;
586
-
587
- case Token.VAR:
588
- result.append("var ");
589
- break;
590
-
591
- case Token.SEMI:
592
- result.append(';');
593
- if (Token.EOL != getNext(source, length, i)) {
594
- // separators in FOR
595
- result.append(' ');
596
- }
597
- break;
598
-
599
- case Token.ASSIGN:
600
- result.append(" = ");
601
- break;
602
-
603
- case Token.ASSIGN_ADD:
604
- result.append(" += ");
605
- break;
606
-
607
- case Token.ASSIGN_SUB:
608
- result.append(" -= ");
609
- break;
610
-
611
- case Token.ASSIGN_MUL:
612
- result.append(" *= ");
613
- break;
614
-
615
- case Token.ASSIGN_DIV:
616
- result.append(" /= ");
617
- break;
618
-
619
- case Token.ASSIGN_MOD:
620
- result.append(" %= ");
621
- break;
622
-
623
- case Token.ASSIGN_BITOR:
624
- result.append(" |= ");
625
- break;
626
-
627
- case Token.ASSIGN_BITXOR:
628
- result.append(" ^= ");
629
- break;
630
-
631
- case Token.ASSIGN_BITAND:
632
- result.append(" &= ");
633
- break;
634
-
635
- case Token.ASSIGN_LSH:
636
- result.append(" <<= ");
637
- break;
638
-
639
- case Token.ASSIGN_RSH:
640
- result.append(" >>= ");
641
- break;
642
-
643
- case Token.ASSIGN_URSH:
644
- result.append(" >>>= ");
645
- break;
646
-
647
- case Token.HOOK:
648
- result.append(" ? ");
649
- break;
650
-
651
- case Token.OBJECTLIT:
652
- // pun OBJECTLIT to mean colon in objlit property
653
- // initialization.
654
- // This needs to be distinct from COLON in the general case
655
- // to distinguish from the colon in a ternary... which needs
656
- // different spacing.
657
- result.append(':');
658
- break;
659
-
660
- case Token.COLON:
661
- if (Token.EOL == getNext(source, length, i))
662
- // it's the end of a label
663
- result.append(':');
664
- else
665
- // it's the middle part of a ternary
666
- result.append(" : ");
667
- break;
668
-
669
- case Token.OR:
670
- result.append(" || ");
671
- break;
672
-
673
- case Token.AND:
674
- result.append(" && ");
675
- break;
676
-
677
- case Token.BITOR:
678
- result.append(" | ");
679
- break;
680
-
681
- case Token.BITXOR:
682
- result.append(" ^ ");
683
- break;
684
-
685
- case Token.BITAND:
686
- result.append(" & ");
687
- break;
688
-
689
- case Token.SHEQ:
690
- result.append(" === ");
691
- break;
692
-
693
- case Token.SHNE:
694
- result.append(" !== ");
695
- break;
696
-
697
- case Token.EQ:
698
- result.append(" == ");
699
- break;
700
-
701
- case Token.NE:
702
- result.append(" != ");
703
- break;
704
-
705
- case Token.LE:
706
- result.append(" <= ");
707
- break;
708
-
709
- case Token.LT:
710
- result.append(" < ");
711
- break;
712
-
713
- case Token.GE:
714
- result.append(" >= ");
715
- break;
716
-
717
- case Token.GT:
718
- result.append(" > ");
719
- break;
720
-
721
- case Token.INSTANCEOF:
722
- result.append(" instanceof ");
723
- break;
724
-
725
- case Token.LSH:
726
- result.append(" << ");
727
- break;
728
-
729
- case Token.RSH:
730
- result.append(" >> ");
731
- break;
732
-
733
- case Token.URSH:
734
- result.append(" >>> ");
735
- break;
736
-
737
- case Token.TYPEOF:
738
- result.append("typeof ");
739
- break;
740
-
741
- case Token.VOID:
742
- result.append("void ");
743
- break;
744
-
745
- case Token.CONST:
746
- result.append("const ");
747
- break;
748
-
749
- case Token.NOT:
750
- result.append('!');
751
- break;
752
-
753
- case Token.BITNOT:
754
- result.append('~');
755
- break;
756
-
757
- case Token.POS:
758
- result.append('+');
759
- break;
760
-
761
- case Token.NEG:
762
- result.append('-');
763
- break;
764
-
765
- case Token.INC:
766
- result.append("++");
767
- break;
768
-
769
- case Token.DEC:
770
- result.append("--");
771
- break;
772
-
773
- case Token.ADD:
774
- result.append(" + ");
775
- break;
776
-
777
- case Token.SUB:
778
- result.append(" - ");
779
- break;
780
-
781
- case Token.MUL:
782
- result.append(" * ");
783
- break;
784
-
785
- case Token.DIV:
786
- result.append(" / ");
787
- break;
788
-
789
- case Token.MOD:
790
- result.append(" % ");
791
- break;
792
-
793
- case Token.COLONCOLON:
794
- result.append("::");
795
- break;
796
-
797
- case Token.DOTDOT:
798
- result.append("..");
799
- break;
800
-
801
- case Token.DOTQUERY:
802
- result.append(".(");
803
- break;
804
-
805
- case Token.XMLATTR:
806
- result.append('@');
807
- break;
808
-
809
- default:
810
- // If we don't know how to decompile it, raise an exception.
811
- throw new RuntimeException("Token: " +
812
- Token.name(source.charAt(i)));
813
- }
814
- ++i;
815
- }
816
-
817
- if (!toSource) {
818
- // add that trailing newline if it's an outermost function.
819
- if (!justFunctionBody)
820
- result.append('\n');
821
- } else {
822
- if (topFunctionType == FunctionNode.FUNCTION_EXPRESSION) {
823
- result.append(')');
824
- }
825
- }
826
-
827
- return result.toString();
828
- }
829
-
830
- private static int getNext(String source, int length, int i)
831
- {
832
- return (i + 1 < length) ? source.charAt(i + 1) : Token.EOF;
833
- }
834
-
835
- private static int getSourceStringEnd(String source, int offset)
836
- {
837
- return printSourceString(source, offset, false, null);
838
- }
839
-
840
- private static int printSourceString(String source, int offset,
841
- boolean asQuotedString,
842
- StringBuffer sb)
843
- {
844
- int length = source.charAt(offset);
845
- ++offset;
846
- if ((0x8000 & length) != 0) {
847
- length = ((0x7FFF & length) << 16) | source.charAt(offset);
848
- ++offset;
849
- }
850
- if (sb != null) {
851
- String str = source.substring(offset, offset + length);
852
- if (!asQuotedString) {
853
- sb.append(str);
854
- } else {
855
- sb.append('"');
856
- sb.append(ScriptRuntime.escapeString(str));
857
- sb.append('"');
858
- }
859
- }
860
- return offset + length;
861
- }
862
-
863
- private static int printSourceNumber(String source, int offset,
864
- StringBuffer sb)
865
- {
866
- double number = 0.0;
867
- char type = source.charAt(offset);
868
- ++offset;
869
- if (type == 'S') {
870
- if (sb != null) {
871
- int ival = source.charAt(offset);
872
- number = ival;
873
- }
874
- ++offset;
875
- } else if (type == 'J' || type == 'D') {
876
- if (sb != null) {
877
- long lbits;
878
- lbits = (long)source.charAt(offset) << 48;
879
- lbits |= (long)source.charAt(offset + 1) << 32;
880
- lbits |= (long)source.charAt(offset + 2) << 16;
881
- lbits |= source.charAt(offset + 3);
882
- if (type == 'J') {
883
- number = lbits;
884
- } else {
885
- number = Double.longBitsToDouble(lbits);
886
- }
887
- }
888
- offset += 4;
889
- } else {
890
- // Bad source
891
- throw new RuntimeException();
892
- }
893
- if (sb != null) {
894
- sb.append(ScriptRuntime.numberToString(number, 10));
895
- }
896
- return offset;
897
- }
898
-
899
- private char[] sourceBuffer = new char[128];
900
-
901
- // Per script/function source buffer top: parent source does not include a
902
- // nested functions source and uses function index as a reference instead.
903
- private int sourceTop;
904
-
905
- // whether to do a debug print of the source information, when decompiling.
906
- private static final boolean printSource = false;
907
-
908
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
lib/Diglin/yuicompressor-2.4.6/src/org/mozilla/javascript/Decompiler.java.orig DELETED
@@ -1,910 +0,0 @@
1
- /* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2
- *
3
- * ***** BEGIN LICENSE BLOCK *****
4
- * Version: MPL 1.1/GPL 2.0
5
- *
6
- * The contents of this file are subject to the Mozilla Public License Version
7
- * 1.1 (the "License"); you may not use this file except in compliance with
8
- * the License. You may obtain a copy of the License at
9
- * http://www.mozilla.org/MPL/
10
- *
11
- * Software distributed under the License is distributed on an "AS IS" basis,
12
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13
- * for the specific language governing rights and limitations under the
14
- * License.
15
- *
16
- * The Original Code is Rhino code, released
17
- * May 6, 1999.
18
- *
19
- * The Initial Developer of the Original Code is
20
- * Netscape Communications Corporation.
21
- * Portions created by the Initial Developer are Copyright (C) 1997-1999
22
- * the Initial Developer. All Rights Reserved.
23
- *
24
- * Contributor(s):
25
- * Mike Ang
26
- * Igor Bukanov
27
- * Bob Jervis
28
- * Mike McCabe
29
- *
30
- * Alternatively, the contents of this file may be used under the terms of
31
- * the GNU General Public License Version 2 or later (the "GPL"), in which
32
- * case the provisions of the GPL are applicable instead of those above. If
33
- * you wish to allow use of your version of this file only under the terms of
34
- * the GPL and not to allow others to use your version of this file under the
35
- * MPL, indicate your decision by deleting the provisions above and replacing
36
- * them with the notice and other provisions required by the GPL. If you do
37
- * not delete the provisions above, a recipient may use your version of this
38
- * file under either the MPL or the GPL.
39
- *
40
- * ***** END LICENSE BLOCK ***** */
41
-
42
- package org.mozilla.javascript;
43
-
44
- /**
45
- * The following class save decompilation information about the source.
46
- * Source information is returned from the parser as a String
47
- * associated with function nodes and with the toplevel script. When
48
- * saved in the constant pool of a class, this string will be UTF-8
49
- * encoded, and token values will occupy a single byte.
50
-
51
- * Source is saved (mostly) as token numbers. The tokens saved pretty
52
- * much correspond to the token stream of a 'canonical' representation
53
- * of the input program, as directed by the parser. (There were a few
54
- * cases where tokens could have been left out where decompiler could
55
- * easily reconstruct them, but I left them in for clarity). (I also
56
- * looked adding source collection to TokenStream instead, where I
57
- * could have limited the changes to a few lines in getToken... but
58
- * this wouldn't have saved any space in the resulting source
59
- * representation, and would have meant that I'd have to duplicate
60
- * parser logic in the decompiler to disambiguate situations where
61
- * newlines are important.) The function decompile expands the
62
- * tokens back into their string representations, using simple
63
- * lookahead to correct spacing and indentation.
64
- *
65
- * Assignments are saved as two-token pairs (Token.ASSIGN, op). Number tokens
66
- * are stored inline, as a NUMBER token, a character representing the type, and
67
- * either 1 or 4 characters representing the bit-encoding of the number. String
68
- * types NAME, STRING and OBJECT are currently stored as a token type,
69
- * followed by a character giving the length of the string (assumed to
70
- * be less than 2^16), followed by the characters of the string
71
- * inlined into the source string. Changing this to some reference to
72
- * to the string in the compiled class' constant pool would probably
73
- * save a lot of space... but would require some method of deriving
74
- * the final constant pool entry from information available at parse
75
- * time.
76
- */
77
- public class Decompiler
78
- {
79
- /**
80
- * Flag to indicate that the decompilation should omit the
81
- * function header and trailing brace.
82
- */
83
- public static final int ONLY_BODY_FLAG = 1 << 0;
84
-
85
- /**
86
- * Flag to indicate that the decompilation generates toSource result.
87
- */
88
- public static final int TO_SOURCE_FLAG = 1 << 1;
89
-
90
- /**
91
- * Decompilation property to specify initial ident value.
92
- */
93
- public static final int INITIAL_INDENT_PROP = 1;
94
-
95
- /**
96
- * Decompilation property to specify default identation offset.
97
- */
98
- public static final int INDENT_GAP_PROP = 2;
99
-
100
- /**
101
- * Decompilation property to specify identation offset for case labels.
102
- */
103
- public static final int CASE_GAP_PROP = 3;
104
-
105
- // Marker to denote the last RC of function so it can be distinguished from
106
- // the last RC of object literals in case of function expressions
107
- private static final int FUNCTION_END = Token.LAST_TOKEN + 1;
108
-
109
- String getEncodedSource()
110
- {
111
- return sourceToString(0);
112
- }
113
-
114
- int getCurrentOffset()
115
- {
116
- return sourceTop;
117
- }
118
-
119
- int markFunctionStart(int functionType)
120
- {
121
- int savedOffset = getCurrentOffset();
122
- addToken(Token.FUNCTION);
123
- append((char)functionType);
124
- return savedOffset;
125
- }
126
-
127
- int markFunctionEnd(int functionStart)
128
- {
129
- int offset = getCurrentOffset();
130
- append((char)FUNCTION_END);
131
- return offset;
132
- }
133
-
134
- void addToken(int token)
135
- {
136
- if (!(0 <= token && token <= Token.LAST_TOKEN))
137
- throw new IllegalArgumentException();
138
-
139
- append((char)token);
140
- }
141
-
142
- void addEOL(int token)
143
- {
144
- if (!(0 <= token && token <= Token.LAST_TOKEN))
145
- throw new IllegalArgumentException();
146
-
147
- append((char)token);
148
- append((char)Token.EOL);
149
- }
150
-
151
- void addName(String str)
152
- {
153
- addToken(Token.NAME);
154
- appendString(str);
155
- }
156
-
157
- void addString(String str)
158
- {
159
- addToken(Token.STRING);
160
- appendString(str);
161
- }
162
-
163
- void addRegexp(String regexp, String flags)
164
- {
165
- addToken(Token.REGEXP);
166
- appendString('/' + regexp + '/' + flags);
167
- }
168
-
169
- void addNumber(double n)
170
- {
171
- addToken(Token.NUMBER);
172
-
173
- /* encode the number in the source stream.
174
- * Save as NUMBER type (char | char char char char)
175
- * where type is
176
- * 'D' - double, 'S' - short, 'J' - long.
177
-
178
- * We need to retain float vs. integer type info to keep the
179
- * behavior of liveconnect type-guessing the same after
180
- * decompilation. (Liveconnect tries to present 1.0 to Java
181
- * as a float/double)
182
- * OPT: This is no longer true. We could compress the format.
183
-
184
- * This may not be the most space-efficient encoding;
185
- * the chars created below may take up to 3 bytes in
186
- * constant pool UTF-8 encoding, so a Double could take
187
- * up to 12 bytes.
188
- */
189
-
190
- long lbits = (long)n;
191
- if (lbits != n) {
192
- // if it's floating point, save as a Double bit pattern.
193
- // (12/15/97 our scanner only returns Double for f.p.)
194
- lbits = Double.doubleToLongBits(n);
195
- append('D');
196
- append((char)(lbits >> 48));
197
- append((char)(lbits >> 32));
198
- append((char)(lbits >> 16));
199
- append((char)lbits);
200
- }
201
- else {
202
- // we can ignore negative values, bc they're already prefixed
203
- // by NEG
204
- if (lbits < 0) Kit.codeBug();
205
-
206
- // will it fit in a char?
207
- // this gives a short encoding for integer values up to 2^16.
208
- if (lbits <= Character.MAX_VALUE) {
209
- append('S');
210
- append((char)lbits);
211
- }
212
- else { // Integral, but won't fit in a char. Store as a long.
213
- append('J');
214
- append((char)(lbits >> 48));
215
- append((char)(lbits >> 32));
216
- append((char)(lbits >> 16));
217
- append((char)lbits);
218
- }
219
- }
220
- }
221
-
222
- private void appendString(String str)
223
- {
224
- int L = str.length();
225
- int lengthEncodingSize = 1;
226
- if (L >= 0x8000) {
227
- lengthEncodingSize = 2;
228
- }
229
- int nextTop = sourceTop + lengthEncodingSize + L;
230
- if (nextTop > sourceBuffer.length) {
231
- increaseSourceCapacity(nextTop);
232
- }
233
- if (L >= 0x8000) {
234
- // Use 2 chars to encode strings exceeding 32K, were the highest
235
- // bit in the first char indicates presence of the next byte
236
- sourceBuffer[sourceTop] = (char)(0x8000 | (L >>> 16));
237
- ++sourceTop;
238
- }
239
- sourceBuffer[sourceTop] = (char)L;
240
- ++sourceTop;
241
- str.getChars(0, L, sourceBuffer, sourceTop);
242
- sourceTop = nextTop;
243
- }
244
-
245
- private void append(char c)
246
- {
247
- if (sourceTop == sourceBuffer.length) {
248
- increaseSourceCapacity(sourceTop + 1);
249
- }
250
- sourceBuffer[sourceTop] = c;
251
- ++sourceTop;
252
- }
253
-
254
- private void increaseSourceCapacity(int minimalCapacity)
255
- {
256
- // Call this only when capacity increase is must
257
- if (minimalCapacity <= sourceBuffer.length) Kit.codeBug();
258
- int newCapacity = sourceBuffer.length * 2;
259
- if (newCapacity < minimalCapacity) {
260
- newCapacity = minimalCapacity;
261
- }
262
- char[] tmp = new char[newCapacity];
263
- System.arraycopy(sourceBuffer, 0, tmp, 0, sourceTop);
264
- sourceBuffer = tmp;
265
- }
266
-
267
- private String sourceToString(int offset)
268
- {
269
- if (offset < 0 || sourceTop < offset) Kit.codeBug();
270
- return new String(sourceBuffer, offset, sourceTop - offset);
271
- }
272
-
273
- /**
274
- * Decompile the source information associated with this js
275
- * function/script back into a string. For the most part, this
276
- * just means translating tokens back to their string
277
- * representations; there's a little bit of lookahead logic to
278
- * decide the proper spacing/indentation. Most of the work in
279
- * mapping the original source to the prettyprinted decompiled
280
- * version is done by the parser.
281
- *
282
- * @param source encoded source tree presentation
283
- *
284
- * @param flags flags to select output format
285
- *
286
- * @param properties indentation properties
287
- *
288
- */
289
- public static String decompile(String source, int flags,
290
- UintMap properties)
291
- {
292
- int length = source.length();
293
- if (length == 0) { return ""; }
294
-
295
- int indent = properties.getInt(INITIAL_INDENT_PROP, 0);
296
- if (indent < 0) throw new IllegalArgumentException();
297
- int indentGap = properties.getInt(INDENT_GAP_PROP, 4);
298
- if (indentGap < 0) throw new IllegalArgumentException();
299
- int caseGap = properties.getInt(CASE_GAP_PROP, 2);
300
- if (caseGap < 0) throw new IllegalArgumentException();
301
-
302
- StringBuffer result = new StringBuffer();
303
- boolean justFunctionBody = (0 != (flags & Decompiler.ONLY_BODY_FLAG));
304
- boolean toSource = (0 != (flags & Decompiler.TO_SOURCE_FLAG));
305
-
306
- // Spew tokens in source, for debugging.
307
- // as TYPE number char
308
- if (printSource) {
309
- System.err.println("length:" + length);
310
- for (int i = 0; i < length; ++i) {
311
- // Note that tokenToName will fail unless Context.printTrees
312
- // is true.
313
- String tokenname = null;
314
- if (Token.printNames) {
315
- tokenname = Token.name(source.charAt(i));
316
- }
317
- if (tokenname == null) {
318
- tokenname = "---";
319
- }
320
- String pad = tokenname.length() > 7
321
- ? "\t"
322
- : "\t\t";
323
- System.err.println
324
- (tokenname
325
- + pad + (int)source.charAt(i)
326
- + "\t'" + ScriptRuntime.escapeString
327
- (source.substring(i, i+1))
328
- + "'");
329
- }
330
- System.err.println();
331
- }
332
-
333
- int braceNesting = 0;
334
- boolean afterFirstEOL = false;
335
- int i = 0;
336
- int topFunctionType;
337
- if (source.charAt(i) == Token.SCRIPT) {
338
- ++i;
339
- topFunctionType = -1;
340
- } else {
341
- topFunctionType = source.charAt(i + 1);
342
- }
343
-
344
- if (!toSource) {
345
- // add an initial newline to exactly match js.
346
- result.append('\n');
347
- for (int j = 0; j < indent; j++)
348
- result.append(' ');
349
- } else {
350
- if (topFunctionType == FunctionNode.FUNCTION_EXPRESSION) {
351
- result.append('(');
352
- }
353
- }
354
-
355
- while (i < length) {
356
- switch(source.charAt(i)) {
357
- case Token.GET:
358
- case Token.SET:
359
- result.append(source.charAt(i) == Token.GET ? "get " : "set ");
360
- ++i;
361
- i = printSourceString(source, i + 1, false, result);
362
- // Now increment one more to get past the FUNCTION token
363
- ++i;
364
- break;
365
-
366
- case Token.NAME:
367
- case Token.REGEXP: // re-wrapped in '/'s in parser...
368
- i = printSourceString(source, i + 1, false, result);
369
- continue;
370
-
371
- case Token.STRING:
372
- i = printSourceString(source, i + 1, true, result);
373
- continue;
374
-
375
- case Token.NUMBER:
376
- i = printSourceNumber(source, i + 1, result);
377
- continue;
378
-
379
- case Token.TRUE:
380
- result.append("true");
381
- break;
382
-
383
- case Token.FALSE:
384
- result.append("false");
385
- break;
386
-
387
- case Token.NULL:
388
- result.append("null");
389
- break;
390
-
391
- case Token.THIS:
392
- result.append("this");
393
- break;
394
-
395
- case Token.FUNCTION:
396
- ++i; // skip function type
397
- result.append("function ");
398
- break;
399
-
400
- case FUNCTION_END:
401
- // Do nothing
402
- break;
403
-
404
- case Token.COMMA:
405
- result.append(", ");
406
- break;
407
-
408
- case Token.LC:
409
- ++braceNesting;
410
- if (Token.EOL == getNext(source, length, i))
411
- indent += indentGap;
412
- result.append('{');
413
- break;
414
-
415
- case Token.RC: {
416
- --braceNesting;
417
- /* don't print the closing RC if it closes the
418
- * toplevel function and we're called from
419
- * decompileFunctionBody.
420
- */
421
- if (justFunctionBody && braceNesting == 0)
422
- break;
423
-
424
- result.append('}');
425
- switch (getNext(source, length, i)) {
426
- case Token.EOL:
427
- case FUNCTION_END:
428
- indent -= indentGap;
429
- break;
430
- case Token.WHILE:
431
- case Token.ELSE:
432
- indent -= indentGap;
433
- result.append(' ');
434
- break;
435
- }
436
- break;
437
- }
438
- case Token.LP:
439
- result.append('(');
440
- break;
441
-
442
- case Token.RP:
443
- result.append(')');
444
- if (Token.LC == getNext(source, length, i))
445
- result.append(' ');
446
- break;
447
-
448
- case Token.LB:
449
- result.append('[');
450
- break;
451
-
452
- case Token.RB:
453
- result.append(']');
454
- break;
455
-
456
- case Token.EOL: {
457
- if (toSource) break;
458
- boolean newLine = true;
459
- if (!afterFirstEOL) {
460
- afterFirstEOL = true;
461
- if (justFunctionBody) {
462
- /* throw away just added 'function name(...) {'
463
- * and restore the original indent
464
- */
465
- result.setLength(0);
466
- indent -= indentGap;
467
- newLine = false;
468
- }
469
- }
470
- if (newLine) {
471
- result.append('\n');
472
- }
473
-
474
- /* add indent if any tokens remain,
475
- * less setback if next token is
476
- * a label, case or default.
477
- */
478
- if (i + 1 < length) {
479
- int less = 0;
480
- int nextToken = source.charAt(i + 1);
481
- if (nextToken == Token.CASE
482
- || nextToken == Token.DEFAULT)
483
- {
484
- less = indentGap - caseGap;
485
- } else if (nextToken == Token.RC) {
486
- less = indentGap;
487
- }
488
-
489
- /* elaborate check against label... skip past a
490
- * following inlined NAME and look for a COLON.
491
- */
492
- else if (nextToken == Token.NAME) {
493
- int afterName = getSourceStringEnd(source, i + 2);
494
- if (source.charAt(afterName) == Token.COLON)
495
- less = indentGap;
496
- }
497
-
498
- for (; less < indent; less++)
499
- result.append(' ');
500
- }
501
- break;
502
- }
503
- case Token.DOT:
504
- result.append('.');
505
- break;
506
-
507
- case Token.NEW:
508
- result.append("new ");
509
- break;
510
-
511
- case Token.DELPROP:
512
- result.append("delete ");
513
- break;
514
-
515
- case Token.IF:
516
- result.append("if ");
517
- break;
518
-
519
- case Token.ELSE:
520
- result.append("else ");
521
- break;
522
-
523
- case Token.FOR:
524
- result.append("for ");
525
- break;
526
-
527
- case Token.IN:
528
- result.append(" in ");
529
- break;
530
-
531
- case Token.WITH:
532
- result.append("with ");
533
- break;
534
-
535
- case Token.WHILE:
536
- result.append("while ");
537
- break;
538
-
539
- case Token.DO:
540
- result.append("do ");
541
- break;
542
-
543
- case Token.TRY:
544
- result.append("try ");
545
- break;
546
-
547
- case Token.CATCH:
548
- result.append("catch ");
549
- break;
550
-
551
- case Token.FINALLY:
552
- result.append("finally ");
553
- break;
554
-
555
- case Token.THROW:
556
- result.append("throw ");
557
- break;
558
-
559
- case Token.SWITCH:
560
- result.append("switch ");
561
- break;
562
-
563
- case Token.BREAK:
564
- result.append("break");
565
- if (Token.NAME == getNext(source, length, i))
566
- result.append(' ');
567
- break;
568
-
569
- case Token.CONTINUE:
570
- result.append("continue");
571
- if (Token.NAME == getNext(source, length, i))
572
- result.append(' ');
573
- break;
574
-
575
- case Token.CASE:
576
- result.append("case ");
577
- break;
578
-
579
- case Token.DEFAULT:
580
- result.append("default");
581
- break;
582
-
583
- case Token.RETURN:
584
- result.append("return");
585
- if (Token.SEMI != getNext(source, length, i))
586
- result.append(' ');
587
- break;
588
-
589
- case Token.VAR:
590
- result.append("var ");
591
- break;
592
-
593
- case Token.SEMI:
594
- result.append(';');
595
- if (Token.EOL != getNext(source, length, i)) {
596
- // separators in FOR
597
- result.append(' ');
598
- }
599
- break;
600
-
601
- case Token.ASSIGN:
602
- result.append(" = ");
603
- break;
604
-
605
- case Token.ASSIGN_ADD:
606
- result.append(" += ");
607
- break;
608
-
609
- case Token.ASSIGN_SUB:
610
- result.append(" -= ");
611
- break;
612
-
613
- case Token.ASSIGN_MUL:
614
- result.append(" *= ");
615
- break;
616
-
617
- case Token.ASSIGN_DIV:
618
- result.append(" /= ");
619
- break;
620
-
621
- case Token.ASSIGN_MOD:
622
- result.append(" %= ");
623
- break;
624
-
625
- case Token.ASSIGN_BITOR:
626
- result.append(" |= ");
627
- break;
628
-
629
- case Token.ASSIGN_BITXOR:
630
- result.append(" ^= ");
631
- break;
632
-
633
- case Token.ASSIGN_BITAND:
634
- result.append(" &= ");
635
- break;
636
-
637
- case Token.ASSIGN_LSH:
638
- result.append(" <<= ");
639
- break;
640
-
641
- case Token.ASSIGN_RSH:
642
- result.append(" >>= ");
643
- break;
644
-
645
- case Token.ASSIGN_URSH:
646
- result.append(" >>>= ");
647
- break;
648
-
649
- case Token.HOOK:
650
- result.append(" ? ");
651
- break;
652
-
653
- case Token.OBJECTLIT:
654
- // pun OBJECTLIT to mean colon in objlit property
655
- // initialization.
656
- // This needs to be distinct from COLON in the general case
657
- // to distinguish from the colon in a ternary... which needs
658
- // different spacing.
659
- result.append(':');
660
- break;
661
-
662
- case Token.COLON:
663
- if (Token.EOL == getNext(source, length, i))
664
- // it's the end of a label
665
- result.append(':');
666
- else
667
- // it's the middle part of a ternary
668
- result.append(" : ");
669
- break;
670
-
671
- case Token.OR:
672
- result.append(" || ");
673
- break;
674
-
675
- case Token.AND:
676
- result.append(" && ");
677
- break;
678
-
679
- case Token.BITOR:
680
- result.append(" | ");
681
- break;
682
-
683
- case Token.BITXOR:
684
- result.append(" ^ ");
685
- break;
686
-
687
- case Token.BITAND:
688
- result.append(" & ");
689
- break;
690
-
691
- case Token.SHEQ:
692
- result.append(" === ");
693
- break;
694
-
695
- case Token.SHNE:
696
- result.append(" !== ");
697
- break;
698
-
699
- case Token.EQ:
700
- result.append(" == ");
701
- break;
702
-
703
- case Token.NE:
704
- result.append(" != ");
705
- break;
706
-
707
- case Token.LE:
708
- result.append(" <= ");
709
- break;
710
-
711
- case Token.LT:
712
- result.append(" < ");
713
- break;
714
-
715
- case Token.GE:
716
- result.append(" >= ");
717
- break;
718
-
719
- case Token.GT:
720
- result.append(" > ");
721
- break;
722
-
723
- case Token.INSTANCEOF:
724
- result.append(" instanceof ");
725
- break;
726
-
727
- case Token.LSH:
728
- result.append(" << ");
729
- break;
730
-
731
- case Token.RSH:
732
- result.append(" >> ");
733
- break;
734
-
735
- case Token.URSH:
736
- result.append(" >>> ");
737
- break;
738
-
739
- case Token.TYPEOF:
740
- result.append("typeof ");
741
- break;
742
-
743
- case Token.VOID:
744
- result.append("void ");
745
- break;
746
-
747
- case Token.CONST:
748
- result.append("const ");
749
- break;
750
-
751
- case Token.NOT:
752
- result.append('!');
753
- break;
754
-
755
- case Token.BITNOT:
756
- result.append('~');
757
- break;
758
-
759
- case Token.POS:
760
- result.append('+');
761
- break;
762
-
763
- case Token.NEG:
764
- result.append('-');
765
- break;
766
-
767
- case Token.INC:
768
- result.append("++");
769
- break;
770
-
771
- case Token.DEC:
772
- result.append("--");
773
- break;
774
-
775
- case Token.ADD:
776
- result.append(" + ");
777
- break;
778
-
779
- case Token.SUB:
780
- result.append(" - ");
781
- break;
782
-
783
- case Token.MUL:
784
- result.append(" * ");
785
- break;
786
-
787
- case Token.DIV:
788
- result.append(" / ");
789
- break;
790
-
791
- case Token.MOD:
792
- result.append(" % ");
793
- break;
794
-
795
- case Token.COLONCOLON:
796
- result.append("::");
797
- break;
798
-
799
- case Token.DOTDOT:
800
- result.append("..");
801
- break;
802
-
803
- case Token.DOTQUERY:
804
- result.append(".(");
805
- break;
806
-
807
- case Token.XMLATTR:
808
- result.append('@');
809
- break;
810
-
811
- default:
812
- // If we don't know how to decompile it, raise an exception.
813
- throw new RuntimeException("Token: " +
814
- Token.name(source.charAt(i)));
815
- }
816
- ++i;
817
- }
818
-
819
- if (!toSource) {
820
- // add that trailing newline if it's an outermost function.
821
- if (!justFunctionBody)
822
- result.append('\n');
823
- } else {
824
- if (topFunctionType == FunctionNode.FUNCTION_EXPRESSION) {
825
- result.append(')');
826
- }
827
- }
828
-
829
- return result.toString();
830
- }
831
-
832
- private static int getNext(String source, int length, int i)
833
- {
834
- return (i + 1 < length) ? source.charAt(i + 1) : Token.EOF;
835
- }
836
-
837
- private static int getSourceStringEnd(String source, int offset)
838
- {
839
- return printSourceString(source, offset, false, null);
840
- }
841
-
842
- private static int printSourceString(String source, int offset,
843
- boolean asQuotedString,
844
- StringBuffer sb)
845
- {
846
- int length = source.charAt(offset);
847
- ++offset;
848
- if ((0x8000 & length) != 0) {
849
- length = ((0x7FFF & length) << 16) | source.charAt(offset);
850
- ++offset;
851
- }
852
- if (sb != null) {
853
- String str = source.substring(offset, offset + length);
854
- if (!asQuotedString) {
855
- sb.append(str);
856
- } else {
857
- sb.append('"');
858
- sb.append(ScriptRuntime.escapeString(str));
859
- sb.append('"');
860
- }
861
- }
862
- return offset + length;
863
- }
864
-
865
- private static int printSourceNumber(String source, int offset,
866
- StringBuffer sb)
867
- {
868
- double number = 0.0;
869
- char type = source.charAt(offset);
870
- ++offset;
871
- if (type == 'S') {
872
- if (sb != null) {
873
- int ival = source.charAt(offset);
874
- number = ival;
875
- }
876
- ++offset;
877
- } else if (type == 'J' || type == 'D') {
878
- if (sb != null) {
879
- long lbits;
880
- lbits = (long)source.charAt(offset) << 48;
881
- lbits |= (long)source.charAt(offset + 1) << 32;
882
- lbits |= (long)source.charAt(offset + 2) << 16;
883
- lbits |= source.charAt(offset + 3);
884
- if (type == 'J') {
885
- number = lbits;
886
- } else {
887
- number = Double.longBitsToDouble(lbits);
888
- }
889
- }
890
- offset += 4;
891
- } else {
892
- // Bad source
893
- throw new RuntimeException();
894
- }
895
- if (sb != null) {
896
- sb.append(ScriptRuntime.numberToString(number, 10));
897
- }
898
- return offset;
899
- }
900
-
901
- private char[] sourceBuffer = new char[128];
902
-
903
- // Per script/function source buffer top: parent source does not include a
904
- // nested functions source and uses function index as a reference instead.
905
- private int sourceTop;
906
-
907
- // whether to do a debug print of the source information, when decompiling.
908
- private static final boolean printSource = false;
909
-
910
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
lib/Diglin/yuicompressor-2.4.6/src/org/mozilla/javascript/Parser.java DELETED
@@ -1,2160 +0,0 @@
1
- /* ***** BEGIN LICENSE BLOCK *****
2
- *
3
- * Version: MPL 1.1
4
- *
5
- * The contents of this file are subject to the Mozilla Public License
6
- * Version 1.1 (the "License"); you may not use this file except in
7
- * compliance with the License. You may obtain a copy of the License
8
- * at http://www.mozilla.org/MPL/
9
- *
10
- * Software distributed under the License is distributed on an "AS IS"
11
- * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.
12
- * See the License for the specific language governing rights and
13
- * limitations under the License.
14
- *
15
- * The Original Code is org/mozilla/javascript/Parser.java,
16
- * a component of the Rhino Library ( http://www.mozilla.org/rhino/ )
17
- * This file is a modification of the Original Code developed
18
- * for YUI Compressor.
19
- *
20
- * The Initial Developer of the Original Code is Mozilla Foundation
21
- *
22
- * Copyright (c) 2009 Mozilla Foundation. All Rights Reserved.
23
- *
24
- * Contributor(s): Yahoo! Inc. 2009
25
- *
26
- * ***** END LICENSE BLOCK ***** */
27
-
28
- package org.mozilla.javascript;
29
-
30
- import java.io.Reader;
31
- import java.io.IOException;
32
- import java.util.Hashtable;
33
-
34
- /**
35
- * This class implements the JavaScript parser.
36
- *
37
- * It is based on the C source files jsparse.c and jsparse.h
38
- * in the jsref package.
39
- *
40
- * @see TokenStream
41
- *
42
- * @author Mike McCabe
43
- * @author Brendan Eich
44
- */
45
-
46
- public class Parser
47
- {
48
- // TokenInformation flags : currentFlaggedToken stores them together
49
- // with token type
50
- final static int
51
- CLEAR_TI_MASK = 0xFFFF, // mask to clear token information bits
52
- TI_AFTER_EOL = 1 << 16, // first token of the source line
53
- TI_CHECK_LABEL = 1 << 17; // indicates to check for label
54
-
55
- CompilerEnvirons compilerEnv;
56
- private ErrorReporter errorReporter;
57
- private String sourceURI;
58
- boolean calledByCompileFunction;
59
-
60
- private TokenStream ts;
61
- private int currentFlaggedToken;
62
- private int syntaxErrorCount;
63
-
64
- private IRFactory nf;
65
-
66
- private int nestingOfFunction;
67
-
68
- private Decompiler decompiler;
69
- private String encodedSource;
70
-
71
- // The following are per function variables and should be saved/restored
72
- // during function parsing.
73
- // XXX Move to separated class?
74
- ScriptOrFnNode currentScriptOrFn;
75
- private int nestingOfWith;
76
- private Hashtable labelSet; // map of label names into nodes
77
- private ObjArray loopSet;
78
- private ObjArray loopAndSwitchSet;
79
- private boolean hasReturnValue;
80
- private int functionEndFlags;
81
- // end of per function variables
82
-
83
- // Exception to unwind
84
- private static class ParserException extends RuntimeException
85
- {
86
- static final long serialVersionUID = 5882582646773765630L;
87
- }
88
-
89
- public Parser(CompilerEnvirons compilerEnv, ErrorReporter errorReporter)
90
- {
91
- this.compilerEnv = compilerEnv;
92
- this.errorReporter = errorReporter;
93
- }
94
-
95
- protected Decompiler createDecompiler(CompilerEnvirons compilerEnv)
96
- {
97
- return new Decompiler();
98
- }
99
-
100
- void addStrictWarning(String messageId, String messageArg)
101
- {
102
- if (compilerEnv.isStrictMode())
103
- addWarning(messageId, messageArg);
104
- }
105
-
106
- void addWarning(String messageId, String messageArg)
107
- {
108
- String message = ScriptRuntime.getMessage1(messageId, messageArg);
109
- if (compilerEnv.reportWarningAsError()) {
110
- ++syntaxErrorCount;
111
- errorReporter.error(message, sourceURI, ts.getLineno(),
112
- ts.getLine(), ts.getOffset());
113
- } else
114
- errorReporter.warning(message, sourceURI, ts.getLineno(),
115
- ts.getLine(), ts.getOffset());
116
- }
117
-
118
- void addError(String messageId)
119
- {
120
- ++syntaxErrorCount;
121
- String message = ScriptRuntime.getMessage0(messageId);
122
- errorReporter.error(message, sourceURI, ts.getLineno(),
123
- ts.getLine(), ts.getOffset());
124
- }
125
-
126
- void addError(String messageId, String messageArg)
127
- {
128
- ++syntaxErrorCount;
129
- String message = ScriptRuntime.getMessage1(messageId, messageArg);
130
- errorReporter.error(message, sourceURI, ts.getLineno(),
131
- ts.getLine(), ts.getOffset());
132
- }
133
-
134
- RuntimeException reportError(String messageId)
135
- {
136
- addError(messageId);
137
-
138
- // Throw a ParserException exception to unwind the recursive descent
139
- // parse.
140
- throw new ParserException();
141
- }
142
-
143
- private int peekToken()
144
- throws IOException
145
- {
146
- int tt = currentFlaggedToken;
147
- if (tt == Token.EOF) {
148
-
149
- while ((tt = ts.getToken()) == Token.CONDCOMMENT || tt == Token.KEEPCOMMENT) {
150
- if (tt == Token.CONDCOMMENT) {
151
- /* Support for JScript conditional comments */
152
- decompiler.addJScriptConditionalComment(ts.getString());
153
- } else {
154
- /* Support for preserved comments */
155
- decompiler.addPreservedComment(ts.getString());
156
- }
157
- }
158
-
159
- if (tt == Token.EOL) {
160
- do {
161
- tt = ts.getToken();
162
-
163
- if (tt == Token.CONDCOMMENT) {
164
- /* Support for JScript conditional comments */
165
- decompiler.addJScriptConditionalComment(ts.getString());
166
- } else if (tt == Token.KEEPCOMMENT) {
167
- /* Support for preserved comments */
168
- decompiler.addPreservedComment(ts.getString());
169
- }
170
-
171
- } while (tt == Token.EOL || tt == Token.CONDCOMMENT || tt == Token.KEEPCOMMENT);
172
- tt |= TI_AFTER_EOL;
173
- }
174
- currentFlaggedToken = tt;
175
- }
176
- return tt & CLEAR_TI_MASK;
177
- }
178
-
179
- private int peekFlaggedToken()
180
- throws IOException
181
- {
182
- peekToken();
183
- return currentFlaggedToken;
184
- }
185
-
186
- private void consumeToken()
187
- {
188
- currentFlaggedToken = Token.EOF;
189
- }
190
-
191
- private int nextToken()
192
- throws IOException
193
- {
194
- int tt = peekToken();
195
- consumeToken();
196
- return tt;
197
- }
198
-
199
- private int nextFlaggedToken()
200
- throws IOException
201
- {
202
- peekToken();
203
- int ttFlagged = currentFlaggedToken;
204
- consumeToken();
205
- return ttFlagged;
206
- }
207
-
208
- private boolean matchToken(int toMatch)
209
- throws IOException
210
- {
211
- int tt = peekToken();
212
- if (tt != toMatch) {
213
- return false;
214
- }
215
- consumeToken();
216
- return true;
217
- }
218
-
219
- private int peekTokenOrEOL()
220
- throws IOException
221
- {
222
- int tt = peekToken();
223
- // Check for last peeked token flags
224
- if ((currentFlaggedToken & TI_AFTER_EOL) != 0) {
225
- tt = Token.EOL;
226
- }
227
- return tt;
228
- }
229
-
230
- private void setCheckForLabel()
231
- {
232
- if ((currentFlaggedToken & CLEAR_TI_MASK) != Token.NAME)
233
- throw Kit.codeBug();
234
- currentFlaggedToken |= TI_CHECK_LABEL;
235
- }
236
-
237
- private void mustMatchToken(int toMatch, String messageId)
238
- throws IOException, ParserException
239
- {
240
- if (!matchToken(toMatch)) {
241
- reportError(messageId);
242
- }
243
- }
244
-
245
- private void mustHaveXML()
246
- {
247
- if (!compilerEnv.isXmlAvailable()) {
248
- reportError("msg.XML.not.available");
249
- }
250
- }
251
-
252
- public String getEncodedSource()
253
- {
254
- return encodedSource;
255
- }
256
-
257
- public boolean eof()
258
- {
259
- return ts.eof();
260
- }
261
-
262
- boolean insideFunction()
263
- {
264
- return nestingOfFunction != 0;
265
- }
266
-
267
- private Node enterLoop(Node loopLabel)
268
- {
269
- Node loop = nf.createLoopNode(loopLabel, ts.getLineno());
270
- if (loopSet == null) {
271
- loopSet = new ObjArray();
272
- if (loopAndSwitchSet == null) {
273
- loopAndSwitchSet = new ObjArray();
274
- }
275
- }
276
- loopSet.push(loop);
277
- loopAndSwitchSet.push(loop);
278
- return loop;
279
- }
280
-
281
- private void exitLoop()
282
- {
283
- loopSet.pop();
284
- loopAndSwitchSet.pop();
285
- }
286
-
287
- private Node enterSwitch(Node switchSelector, int lineno)
288
- {
289
- Node switchNode = nf.createSwitch(switchSelector, lineno);
290
- if (loopAndSwitchSet == null) {
291
- loopAndSwitchSet = new ObjArray();
292
- }
293
- loopAndSwitchSet.push(switchNode);
294
- return switchNode;
295
- }
296
-
297
- private void exitSwitch()
298
- {
299
- loopAndSwitchSet.pop();
300
- }
301
-
302
- /*
303
- * Build a parse tree from the given sourceString.
304
- *
305
- * @return an Object representing the parsed
306
- * program. If the parse fails, null will be returned. (The
307
- * parse failure will result in a call to the ErrorReporter from
308
- * CompilerEnvirons.)
309
- */
310
- public ScriptOrFnNode parse(String sourceString,
311
- String sourceURI, int lineno)
312
- {
313
- this.sourceURI = sourceURI;
314
- this.ts = new TokenStream(this, null, sourceString, lineno);
315
- try {
316
- return parse();
317
- } catch (IOException ex) {
318
- // Should never happen
319
- throw new IllegalStateException();
320
- }
321
- }
322
-
323
- /*
324
- * Build a parse tree from the given sourceString.
325
- *
326
- * @return an Object representing the parsed
327
- * program. If the parse fails, null will be returned. (The
328
- * parse failure will result in a call to the ErrorReporter from
329
- * CompilerEnvirons.)
330
- */
331
- public ScriptOrFnNode parse(Reader sourceReader,
332
- String sourceURI, int lineno)
333
- throws IOException
334
- {
335
- this.sourceURI = sourceURI;
336
- this.ts = new TokenStream(this, sourceReader, null, lineno);
337
- return parse();
338
- }
339
-
340
- private ScriptOrFnNode parse()
341
- throws IOException
342
- {
343
- this.decompiler = createDecompiler(compilerEnv);
344
- this.nf = new IRFactory(this);
345
- currentScriptOrFn = nf.createScript();
346
- int sourceStartOffset = decompiler.getCurrentOffset();
347
- this.encodedSource = null;
348
- decompiler.addToken(Token.SCRIPT);
349
-
350
- this.currentFlaggedToken = Token.EOF;
351
- this.syntaxErrorCount = 0;
352
-
353
- int baseLineno = ts.getLineno(); // line number where source starts
354
-
355
- /* so we have something to add nodes to until
356
- * we've collected all the source */
357
- Node pn = nf.createLeaf(Token.BLOCK);
358
-
359
- try {
360
- for (;;) {
361
- int tt = peekToken();
362
-
363
- if (tt <= Token.EOF) {
364
- break;
365
- }
366
-
367
- Node n;
368
- if (tt == Token.FUNCTION) {
369
- consumeToken();
370
- try {
371
- n = function(calledByCompileFunction
372
- ? FunctionNode.FUNCTION_EXPRESSION
373
- : FunctionNode.FUNCTION_STATEMENT);
374
- } catch (ParserException e) {
375
- break;
376
- }
377
- } else {
378
- n = statement();
379
- }
380
- nf.addChildToBack(pn, n);
381
- }
382
- } catch (StackOverflowError ex) {
383
- String msg = ScriptRuntime.getMessage0(
384
- "msg.too.deep.parser.recursion");
385
- throw Context.reportRuntimeError(msg, sourceURI,
386
- ts.getLineno(), null, 0);
387
- }
388
-
389
- if (this.syntaxErrorCount != 0) {
390
- String msg = String.valueOf(this.syntaxErrorCount);
391
- msg = ScriptRuntime.getMessage1("msg.got.syntax.errors", msg);
392
- throw errorReporter.runtimeError(msg, sourceURI, baseLineno,
393
- null, 0);
394
- }
395
-
396
- currentScriptOrFn.setSourceName(sourceURI);
397
- currentScriptOrFn.setBaseLineno(baseLineno);
398
- currentScriptOrFn.setEndLineno(ts.getLineno());
399
-
400
- int sourceEndOffset = decompiler.getCurrentOffset();
401
- currentScriptOrFn.setEncodedSourceBounds(sourceStartOffset,
402
- sourceEndOffset);
403
-
404
- nf.initScript(currentScriptOrFn, pn);
405
-
406
- if (compilerEnv.isGeneratingSource()) {
407
- encodedSource = decompiler.getEncodedSource();
408
- }
409
- this.decompiler = null; // It helps GC
410
-
411
- return currentScriptOrFn;
412
- }
413
-
414
- /*
415
- * The C version of this function takes an argument list,
416
- * which doesn't seem to be needed for tree generation...
417
- * it'd only be useful for checking argument hiding, which
418
- * I'm not doing anyway...
419
- */
420
- private Node parseFunctionBody()
421
- throws IOException
422
- {
423
- ++nestingOfFunction;
424
- Node pn = nf.createBlock(ts.getLineno());
425
- try {
426
- bodyLoop: for (;;) {
427
- Node n;
428
- int tt = peekToken();
429
- switch (tt) {
430
- case Token.ERROR:
431
- case Token.EOF:
432
- case Token.RC:
433
- break bodyLoop;
434
-
435
- case Token.FUNCTION:
436
- consumeToken();
437
- n = function(FunctionNode.FUNCTION_STATEMENT);
438
- break;
439
- default:
440
- n = statement();
441
- break;
442
- }
443
- nf.addChildToBack(pn, n);
444
- }
445
- } catch (ParserException e) {
446
- // Ignore it
447
- } finally {
448
- --nestingOfFunction;
449
- }
450
-
451
- return pn;
452
- }
453
-
454
- private Node function(int functionType)
455
- throws IOException, ParserException
456
- {
457
- int syntheticType = functionType;
458
- int baseLineno = ts.getLineno(); // line number where source starts
459
-
460
- int functionSourceStart = decompiler.markFunctionStart(functionType);
461
- String name;
462
- Node memberExprNode = null;
463
- if (matchToken(Token.NAME)) {
464
- name = ts.getString();
465
- decompiler.addName(name);
466
- if (!matchToken(Token.LP)) {
467
- if (compilerEnv.isAllowMemberExprAsFunctionName()) {
468
- // Extension to ECMA: if 'function <name>' does not follow
469
- // by '(', assume <name> starts memberExpr
470
- Node memberExprHead = nf.createName(name);
471
- name = "";
472
- memberExprNode = memberExprTail(false, memberExprHead);
473
- }
474
- mustMatchToken(Token.LP, "msg.no.paren.parms");
475
- }
476
- } else if (matchToken(Token.LP)) {
477
- // Anonymous function
478
- name = "";
479
- } else {
480
- name = "";
481
- if (compilerEnv.isAllowMemberExprAsFunctionName()) {
482
- // Note that memberExpr can not start with '(' like
483
- // in function (1+2).toString(), because 'function (' already
484
- // processed as anonymous function
485
- memberExprNode = memberExpr(false);
486
- }
487
- mustMatchToken(Token.LP, "msg.no.paren.parms");
488
- }
489
-
490
- if (memberExprNode != null) {
491
- syntheticType = FunctionNode.FUNCTION_EXPRESSION;
492
- }
493
-
494
- boolean nested = insideFunction();
495
-
496
- FunctionNode fnNode = nf.createFunction(name);
497
- if (nested || nestingOfWith > 0) {
498
- // 1. Nested functions are not affected by the dynamic scope flag
499
- // as dynamic scope is already a parent of their scope.
500
- // 2. Functions defined under the with statement also immune to
501
- // this setup, in which case dynamic scope is ignored in favor
502
- // of with object.
503
- fnNode.itsIgnoreDynamicScope = true;
504
- }
505
-
506
- int functionIndex = currentScriptOrFn.addFunction(fnNode);
507
-
508
- int functionSourceEnd;
509
-
510
- ScriptOrFnNode savedScriptOrFn = currentScriptOrFn;
511
- currentScriptOrFn = fnNode;
512
- int savedNestingOfWith = nestingOfWith;
513
- nestingOfWith = 0;
514
- Hashtable savedLabelSet = labelSet;
515
- labelSet = null;
516
- ObjArray savedLoopSet = loopSet;
517
- loopSet = null;
518
- ObjArray savedLoopAndSwitchSet = loopAndSwitchSet;
519
- loopAndSwitchSet = null;
520
- boolean savedHasReturnValue = hasReturnValue;
521
- int savedFunctionEndFlags = functionEndFlags;
522
-
523
- Node body;
524
- try {
525
- decompiler.addToken(Token.LP);
526
- if (!matchToken(Token.RP)) {
527
- boolean first = true;
528
- do {
529
- if (!first)
530
- decompiler.addToken(Token.COMMA);
531
- first = false;
532
- mustMatchToken(Token.NAME, "msg.no.parm");
533
- String s = ts.getString();
534
- if (fnNode.hasParamOrVar(s)) {
535
- addWarning("msg.dup.parms", s);
536
- }
537
- fnNode.addParam(s);
538
- decompiler.addName(s);
539
- } while (matchToken(Token.COMMA));
540
-
541
- mustMatchToken(Token.RP, "msg.no.paren.after.parms");
542
- }
543
- decompiler.addToken(Token.RP);
544
-
545
- mustMatchToken(Token.LC, "msg.no.brace.body");
546
- decompiler.addEOL(Token.LC);
547
- body = parseFunctionBody();
548
- mustMatchToken(Token.RC, "msg.no.brace.after.body");
549
-
550
- if (compilerEnv.isStrictMode() && !body.hasConsistentReturnUsage())
551
- {
552
- String msg = name.length() > 0 ? "msg.no.return.value"
553
- : "msg.anon.no.return.value";
554
- addStrictWarning(msg, name);
555
- }
556
-
557
- decompiler.addToken(Token.RC);
558
- functionSourceEnd = decompiler.markFunctionEnd(functionSourceStart);
559
- if (functionType != FunctionNode.FUNCTION_EXPRESSION) {
560
- // Add EOL only if function is not part of expression
561
- // since it gets SEMI + EOL from Statement in that case
562
- decompiler.addToken(Token.EOL);
563
- }
564
- }
565
- finally {
566
- hasReturnValue = savedHasReturnValue;
567
- functionEndFlags = savedFunctionEndFlags;
568
- loopAndSwitchSet = savedLoopAndSwitchSet;
569
- loopSet = savedLoopSet;
570
- labelSet = savedLabelSet;
571
- nestingOfWith = savedNestingOfWith;
572
- currentScriptOrFn = savedScriptOrFn;
573
- }
574
-
575
- fnNode.setEncodedSourceBounds(functionSourceStart, functionSourceEnd);
576
- fnNode.setSourceName(sourceURI);
577
- fnNode.setBaseLineno(baseLineno);
578
- fnNode.setEndLineno(ts.getLineno());
579
-
580
- if (name != null) {
581
- int index = currentScriptOrFn.getParamOrVarIndex(name);
582
- if (index >= 0 && index < currentScriptOrFn.getParamCount())
583
- addStrictWarning("msg.var.hides.arg", name);
584
- }
585
-
586
- Node pn = nf.initFunction(fnNode, functionIndex, body, syntheticType);
587
- if (memberExprNode != null) {
588
- pn = nf.createAssignment(Token.ASSIGN, memberExprNode, pn);
589
- if (functionType != FunctionNode.FUNCTION_EXPRESSION) {
590
- // XXX check JScript behavior: should it be createExprStatement?
591
- pn = nf.createExprStatementNoReturn(pn, baseLineno);
592
- }
593
- }
594
- return pn;
595
- }
596
-
597
- private Node statements()
598
- throws IOException
599
- {
600
- Node pn = nf.createBlock(ts.getLineno());
601
-
602
- int tt;
603
- while((tt = peekToken()) > Token.EOF && tt != Token.RC) {
604
- nf.addChildToBack(pn, statement());
605
- }
606
-
607
- return pn;
608
- }
609
-
610
- private Node condition()
611
- throws IOException, ParserException
612
- {
613
- mustMatchToken(Token.LP, "msg.no.paren.cond");
614
- decompiler.addToken(Token.LP);
615
- Node pn = expr(false);
616
- mustMatchToken(Token.RP, "msg.no.paren.after.cond");
617
- decompiler.addToken(Token.RP);
618
-
619
- // Report strict warning on code like "if (a = 7) ...". Suppress the
620
- // warning if the condition is parenthesized, like "if ((a = 7)) ...".
621
- if (pn.getProp(Node.PARENTHESIZED_PROP) == null &&
622
- (pn.getType() == Token.SETNAME || pn.getType() == Token.SETPROP ||
623
- pn.getType() == Token.SETELEM))
624
- {
625
- addStrictWarning("msg.equal.as.assign", "");
626
- }
627
- return pn;
628
- }
629
-
630
- // match a NAME; return null if no match.
631
- private Node matchJumpLabelName()
632
- throws IOException, ParserException
633
- {
634
- Node label = null;
635
-
636
- int tt = peekTokenOrEOL();
637
- if (tt == Token.NAME) {
638
- consumeToken();
639
- String name = ts.getString();
640
- decompiler.addName(name);
641
- if (labelSet != null) {
642
- label = (Node)labelSet.get(name);
643
- }
644
- if (label == null) {
645
- reportError("msg.undef.label");
646
- }
647
- }
648
-
649
- return label;
650
- }
651
-
652
- private Node statement()
653
- throws IOException
654
- {
655
- try {
656
- Node pn = statementHelper(null);
657
- if (pn != null) {
658
- if (compilerEnv.isStrictMode() && !pn.hasSideEffects())
659
- addStrictWarning("msg.no.side.effects", "");
660
- return pn;
661
- }
662
- } catch (ParserException e) { }
663
-
664
- // skip to end of statement
665
- int lineno = ts.getLineno();
666
- guessingStatementEnd: for (;;) {
667
- int tt = peekTokenOrEOL();
668
- consumeToken();
669
- switch (tt) {
670
- case Token.ERROR:
671
- case Token.EOF:
672
- case Token.EOL:
673
- case Token.SEMI:
674
- break guessingStatementEnd;
675
- }
676
- }
677
- return nf.createExprStatement(nf.createName("error"), lineno);
678
- }
679
-
680
- /**
681
- * Whether the "catch (e: e instanceof Exception) { ... }" syntax
682
- * is implemented.
683
- */
684
-
685
- private Node statementHelper(Node statementLabel)
686
- throws IOException, ParserException
687
- {
688
- Node pn = null;
689
-
690
- int tt;
691
-
692
- tt = peekToken();
693
-
694
- switch(tt) {
695
- case Token.IF: {
696
- consumeToken();
697
-
698
- decompiler.addToken(Token.IF);
699
- int lineno = ts.getLineno();
700
- Node cond = condition();
701
- decompiler.addEOL(Token.LC);
702
- Node ifTrue = statement();
703
- Node ifFalse = null;
704
- if (matchToken(Token.ELSE)) {
705
- decompiler.addToken(Token.RC);
706
- decompiler.addToken(Token.ELSE);
707
- decompiler.addEOL(Token.LC);
708
- ifFalse = statement();
709
- }
710
- decompiler.addEOL(Token.RC);
711
- pn = nf.createIf(cond, ifTrue, ifFalse, lineno);
712
- return pn;
713
- }
714
-
715
- case Token.SWITCH: {
716
- consumeToken();
717
-
718
- decompiler.addToken(Token.SWITCH);
719
- int lineno = ts.getLineno();
720
- mustMatchToken(Token.LP, "msg.no.paren.switch");
721
- decompiler.addToken(Token.LP);
722
- pn = enterSwitch(expr(false), lineno);
723
- try {
724
- mustMatchToken(Token.RP, "msg.no.paren.after.switch");
725
- decompiler.addToken(Token.RP);
726
- mustMatchToken(Token.LC, "msg.no.brace.switch");
727
- decompiler.addEOL(Token.LC);
728
-
729
- boolean hasDefault = false;
730
- switchLoop: for (;;) {
731
- tt = nextToken();
732
- Node caseExpression;
733
- switch (tt) {
734
- case Token.RC:
735
- break switchLoop;
736
-
737
- case Token.CASE:
738
- decompiler.addToken(Token.CASE);
739
- caseExpression = expr(false);
740
- mustMatchToken(Token.COLON, "msg.no.colon.case");
741
- decompiler.addEOL(Token.COLON);
742
- break;
743
-
744
- case Token.DEFAULT:
745
- if (hasDefault) {
746
- reportError("msg.double.switch.default");
747
- }
748
- decompiler.addToken(Token.DEFAULT);
749
- hasDefault = true;
750
- caseExpression = null;
751
- mustMatchToken(Token.COLON, "msg.no.colon.case");
752
- decompiler.addEOL(Token.COLON);
753
- break;
754
-
755
- default:
756
- reportError("msg.bad.switch");
757
- break switchLoop;
758
- }
759
-
760
- Node block = nf.createLeaf(Token.BLOCK);
761
- while ((tt = peekToken()) != Token.RC
762
- && tt != Token.CASE
763
- && tt != Token.DEFAULT
764
- && tt != Token.EOF)
765
- {
766
- nf.addChildToBack(block, statement());
767
- }
768
-
769
- // caseExpression == null => add default lable
770
- nf.addSwitchCase(pn, caseExpression, block);
771
- }
772
- decompiler.addEOL(Token.RC);
773
- nf.closeSwitch(pn);
774
- } finally {
775
- exitSwitch();
776
- }
777
- return pn;
778
- }
779
-
780
- case Token.WHILE: {
781
- consumeToken();
782
- decompiler.addToken(Token.WHILE);
783
-
784
- Node loop = enterLoop(statementLabel);
785
- try {
786
- Node cond = condition();
787
- decompiler.addEOL(Token.LC);
788
- Node body = statement();
789
- decompiler.addEOL(Token.RC);
790
- pn = nf.createWhile(loop, cond, body);
791
- } finally {
792
- exitLoop();
793
- }
794
- return pn;
795
- }
796
-
797
- case Token.DO: {
798
- consumeToken();
799
- decompiler.addToken(Token.DO);
800
- decompiler.addEOL(Token.LC);
801
-
802
- Node loop = enterLoop(statementLabel);
803
- try {
804
- Node body = statement();
805
- decompiler.addToken(Token.RC);
806
- mustMatchToken(Token.WHILE, "msg.no.while.do");
807
- decompiler.addToken(Token.WHILE);
808
- Node cond = condition();
809
- pn = nf.createDoWhile(loop, body, cond);
810
- } finally {
811
- exitLoop();
812
- }
813
- // Always auto-insert semicon to follow SpiderMonkey:
814
- // It is required by EMAScript but is ignored by the rest of
815
- // world, see bug 238945
816
- matchToken(Token.SEMI);
817
- decompiler.addEOL(Token.SEMI);
818
- return pn;
819
- }
820
-
821
- case Token.FOR: {
822
- consumeToken();
823
- boolean isForEach = false;
824
- decompiler.addToken(Token.FOR);
825
-
826
- Node loop = enterLoop(statementLabel);
827
- try {
828
-
829
- Node init; // Node init is also foo in 'foo in Object'
830
- Node cond; // Node cond is also object in 'foo in Object'
831
- Node incr = null; // to kill warning
832
- Node body;
833
-
834
- // See if this is a for each () instead of just a for ()
835
- if (matchToken(Token.NAME)) {
836
- decompiler.addName(ts.getString());
837
- if (ts.getString().equals("each")) {
838
- isForEach = true;
839
- } else {
840
- reportError("msg.no.paren.for");
841
- }
842
- }
843
-
844
- mustMatchToken(Token.LP, "msg.no.paren.for");
845
- decompiler.addToken(Token.LP);
846
- tt = peekToken();
847
- if (tt == Token.SEMI) {
848
- init = nf.createLeaf(Token.EMPTY);
849
- } else {
850
- if (tt == Token.VAR) {
851
- // set init to a var list or initial
852
- consumeToken(); // consume the 'var' token
853
- init = variables(Token.FOR);
854
- }
855
- else {
856
- init = expr(true);
857
- }
858
- }
859
-
860
- if (matchToken(Token.IN)) {
861
- decompiler.addToken(Token.IN);
862
- // 'cond' is the object over which we're iterating
863
- cond = expr(false);
864
- } else { // ordinary for loop
865
- mustMatchToken(Token.SEMI, "msg.no.semi.for");
866
- decompiler.addToken(Token.SEMI);
867
- if (peekToken() == Token.SEMI) {
868
- // no loop condition
869
- cond = nf.createLeaf(Token.EMPTY);
870
- } else {
871
- cond = expr(false);
872
- }
873
-
874
- mustMatchToken(Token.SEMI, "msg.no.semi.for.cond");
875
- decompiler.addToken(Token.SEMI);
876
- if (peekToken() == Token.RP) {
877
- incr = nf.createLeaf(Token.EMPTY);
878
- } else {
879
- incr = expr(false);
880
- }
881
- }
882
-
883
- mustMatchToken(Token.RP, "msg.no.paren.for.ctrl");
884
- decompiler.addToken(Token.RP);
885
- decompiler.addEOL(Token.LC);
886
- body = statement();
887
- decompiler.addEOL(Token.RC);
888
-
889
- if (incr == null) {
890
- // cond could be null if 'in obj' got eaten
891
- // by the init node.
892
- pn = nf.createForIn(loop, init, cond, body, isForEach);
893
- } else {
894
- pn = nf.createFor(loop, init, cond, incr, body);
895
- }
896
- } finally {
897
- exitLoop();
898
- }
899
- return pn;
900
- }
901
-
902
- case Token.TRY: {
903
- consumeToken();
904
- int lineno = ts.getLineno();
905
-
906
- Node tryblock;
907
- Node catchblocks = null;
908
- Node finallyblock = null;
909
-
910
- decompiler.addToken(Token.TRY);
911
- decompiler.addEOL(Token.LC);
912
- tryblock = statement();
913
- decompiler.addEOL(Token.RC);
914
-
915
- catchblocks = nf.createLeaf(Token.BLOCK);
916
-
917
- boolean sawDefaultCatch = false;
918
- int peek = peekToken();
919
- if (peek == Token.CATCH) {
920
- while (matchToken(Token.CATCH)) {
921
- if (sawDefaultCatch) {
922
- reportError("msg.catch.unreachable");
923
- }
924
- decompiler.addToken(Token.CATCH);
925
- mustMatchToken(Token.LP, "msg.no.paren.catch");
926
- decompiler.addToken(Token.LP);
927
-
928
- mustMatchToken(Token.NAME, "msg.bad.catchcond");
929
- String varName = ts.getString();
930
- decompiler.addName(varName);
931
-
932
- Node catchCond = null;
933
- if (matchToken(Token.IF)) {
934
- decompiler.addToken(Token.IF);
935
- catchCond = expr(false);
936
- } else {
937
- sawDefaultCatch = true;
938
- }
939
-
940
- mustMatchToken(Token.RP, "msg.bad.catchcond");
941
- decompiler.addToken(Token.RP);
942
- mustMatchToken(Token.LC, "msg.no.brace.catchblock");
943
- decompiler.addEOL(Token.LC);
944
-
945
- nf.addChildToBack(catchblocks,
946
- nf.createCatch(varName, catchCond,
947
- statements(),
948
- ts.getLineno()));
949
-
950
- mustMatchToken(Token.RC, "msg.no.brace.after.body");
951
- decompiler.addEOL(Token.RC);
952
- }
953
- } else if (peek != Token.FINALLY) {
954
- mustMatchToken(Token.FINALLY, "msg.try.no.catchfinally");
955
- }
956
-
957
- if (matchToken(Token.FINALLY)) {
958
- decompiler.addToken(Token.FINALLY);
959
- decompiler.addEOL(Token.LC);
960
- finallyblock = statement();
961
- decompiler.addEOL(Token.RC);
962
- }
963
-
964
- pn = nf.createTryCatchFinally(tryblock, catchblocks,
965
- finallyblock, lineno);
966
-
967
- return pn;
968
- }
969
-
970
- case Token.THROW: {
971
- consumeToken();
972
- if (peekTokenOrEOL() == Token.EOL) {
973
- // ECMAScript does not allow new lines before throw expression,
974
- // see bug 256617
975
- reportError("msg.bad.throw.eol");
976
- }
977
-
978
- int lineno = ts.getLineno();
979
- decompiler.addToken(Token.THROW);
980
- pn = nf.createThrow(expr(false), lineno);
981
- break;
982
- }
983
-
984
- case Token.BREAK: {
985
- consumeToken();
986
- int lineno = ts.getLineno();
987
-
988
- decompiler.addToken(Token.BREAK);
989
-
990
- // matchJumpLabelName only matches if there is one
991
- Node breakStatement = matchJumpLabelName();
992
- if (breakStatement == null) {
993
- if (loopAndSwitchSet == null || loopAndSwitchSet.size() == 0) {
994
- reportError("msg.bad.break");
995
- return null;
996
- }
997
- breakStatement = (Node)loopAndSwitchSet.peek();
998
- }
999
- pn = nf.createBreak(breakStatement, lineno);
1000
- break;
1001
- }
1002
-
1003
- case Token.CONTINUE: {
1004
- consumeToken();
1005
- int lineno = ts.getLineno();
1006
-
1007
- decompiler.addToken(Token.CONTINUE);
1008
-
1009
- Node loop;
1010
- // matchJumpLabelName only matches if there is one
1011
- Node label = matchJumpLabelName();
1012
- if (label == null) {
1013
- if (loopSet == null || loopSet.size() == 0) {
1014
- reportError("msg.continue.outside");
1015
- return null;
1016
- }
1017
- loop = (Node)loopSet.peek();
1018
- } else {
1019
- loop = nf.getLabelLoop(label);
1020
- if (loop == null) {
1021
- reportError("msg.continue.nonloop");
1022
- return null;
1023
- }
1024
- }
1025
- pn = nf.createContinue(loop, lineno);
1026
- break;
1027
- }
1028
-
1029
- case Token.WITH: {
1030
- consumeToken();
1031
-
1032
- decompiler.addToken(Token.WITH);
1033
- int lineno = ts.getLineno();
1034
- mustMatchToken(Token.LP, "msg.no.paren.with");
1035
- decompiler.addToken(Token.LP);
1036
- Node obj = expr(false);
1037
- mustMatchToken(Token.RP, "msg.no.paren.after.with");
1038
- decompiler.addToken(Token.RP);
1039
- decompiler.addEOL(Token.LC);
1040
-
1041
- ++nestingOfWith;
1042
- Node body;
1043
- try {
1044
- body = statement();
1045
- } finally {
1046
- --nestingOfWith;
1047
- }
1048
-
1049
- decompiler.addEOL(Token.RC);
1050
-
1051
- pn = nf.createWith(obj, body, lineno);
1052
- return pn;
1053
- }
1054
-
1055
- case Token.CONST:
1056
- case Token.VAR: {
1057
- consumeToken();
1058
- pn = variables(tt);
1059
- break;
1060
- }
1061
-
1062
- case Token.RETURN: {
1063
- if (!insideFunction()) {
1064
- reportError("msg.bad.return");
1065
- }
1066
- consumeToken();
1067
- decompiler.addToken(Token.RETURN);
1068
- int lineno = ts.getLineno();
1069
-
1070
- Node retExpr;
1071
- /* This is ugly, but we don't want to require a semicolon. */
1072
- tt = peekTokenOrEOL();
1073
- switch (tt) {
1074
- case Token.SEMI:
1075
- case Token.RC:
1076
- case Token.EOF:
1077
- case Token.EOL:
1078
- case Token.ERROR:
1079
- retExpr = null;
1080
- break;
1081
- default:
1082
- retExpr = expr(false);
1083
- hasReturnValue = true;
1084
- }
1085
- pn = nf.createReturn(retExpr, lineno);
1086
-
1087
- // see if we need a strict mode warning
1088
- if (retExpr == null) {
1089
- if (functionEndFlags == Node.END_RETURNS_VALUE)
1090
- addStrictWarning("msg.return.inconsistent", "");
1091
-
1092
- functionEndFlags |= Node.END_RETURNS;
1093
- } else {
1094
- if (functionEndFlags == Node.END_RETURNS)
1095
- addStrictWarning("msg.return.inconsistent", "");
1096
-
1097
- functionEndFlags |= Node.END_RETURNS_VALUE;
1098
- }
1099
-
1100
- break;
1101
- }
1102
-
1103
- case Token.LC:
1104
- consumeToken();
1105
- if (statementLabel != null) {
1106
- decompiler.addToken(Token.LC);
1107
- }
1108
- pn = statements();
1109
- mustMatchToken(Token.RC, "msg.no.brace.block");
1110
- if (statementLabel != null) {
1111
- decompiler.addEOL(Token.RC);
1112
- }
1113
- return pn;
1114
-
1115
- case Token.ERROR:
1116
- // Fall thru, to have a node for error recovery to work on
1117
- case Token.SEMI:
1118
- consumeToken();
1119
- pn = nf.createLeaf(Token.EMPTY);
1120
- return pn;
1121
-
1122
- case Token.FUNCTION: {
1123
- consumeToken();
1124
- pn = function(FunctionNode.FUNCTION_EXPRESSION_STATEMENT);
1125
- return pn;
1126
- }
1127
-
1128
- case Token.DEFAULT :
1129
- consumeToken();
1130
- mustHaveXML();
1131
-
1132
- decompiler.addToken(Token.DEFAULT);
1133
- int nsLine = ts.getLineno();
1134
-
1135
- if (!(matchToken(Token.NAME)
1136
- && ts.getString().equals("xml")))
1137
- {
1138
- reportError("msg.bad.namespace");
1139
- }
1140
- decompiler.addName(" xml");
1141
-
1142
- if (!(matchToken(Token.NAME)
1143
- && ts.getString().equals("namespace")))
1144
- {
1145
- reportError("msg.bad.namespace");
1146
- }
1147
- decompiler.addName(" namespace");
1148
-
1149
- if (!matchToken(Token.ASSIGN)) {
1150
- reportError("msg.bad.namespace");
1151
- }
1152
- decompiler.addToken(Token.ASSIGN);
1153
-
1154
- Node expr = expr(false);
1155
- pn = nf.createDefaultNamespace(expr, nsLine);
1156
- break;
1157
-
1158
- case Token.NAME: {
1159
- int lineno = ts.getLineno();
1160
- String name = ts.getString();
1161
- setCheckForLabel();
1162
- pn = expr(false);
1163
- if (pn.getType() != Token.LABEL) {
1164
- pn = nf.createExprStatement(pn, lineno);
1165
- } else {
1166
- // Parsed the label: push back token should be
1167
- // colon that primaryExpr left untouched.
1168
- if (peekToken() != Token.COLON) Kit.codeBug();
1169
- consumeToken();
1170
- // depend on decompiling lookahead to guess that that
1171
- // last name was a label.
1172
- decompiler.addName(name);
1173
- decompiler.addEOL(Token.COLON);
1174
-
1175
- if (labelSet == null) {
1176
- labelSet = new Hashtable();
1177
- } else if (labelSet.containsKey(name)) {
1178
- reportError("msg.dup.label");
1179
- }
1180
-
1181
- boolean firstLabel;
1182
- if (statementLabel == null) {
1183
- firstLabel = true;
1184
- statementLabel = pn;
1185
- } else {
1186
- // Discard multiple label nodes and use only
1187
- // the first: it allows to simplify IRFactory
1188
- firstLabel = false;
1189
- }
1190
- labelSet.put(name, statementLabel);
1191
- try {
1192
- pn = statementHelper(statementLabel);
1193
- } finally {
1194
- labelSet.remove(name);
1195
- }
1196
- if (firstLabel) {
1197
- pn = nf.createLabeledStatement(statementLabel, pn);
1198
- }
1199
- return pn;
1200
- }
1201
- break;
1202
- }
1203
-
1204
- default: {
1205
- int lineno = ts.getLineno();
1206
- pn = expr(false);
1207
- pn = nf.createExprStatement(pn, lineno);
1208
- break;
1209
- }
1210
- }
1211
-
1212
- int ttFlagged = peekFlaggedToken();
1213
- switch (ttFlagged & CLEAR_TI_MASK) {
1214
- case Token.SEMI:
1215
- // Consume ';' as a part of expression
1216
- consumeToken();
1217
- break;
1218
- case Token.ERROR:
1219
- case Token.EOF:
1220
- case Token.RC:
1221
- // Autoinsert ;
1222
- break;
1223
- default:
1224
- if ((ttFlagged & TI_AFTER_EOL) == 0) {
1225
- // Report error if no EOL or autoinsert ; otherwise
1226
- reportError("msg.no.semi.stmt");
1227
- }
1228
- break;
1229
- }
1230
- decompiler.addEOL(Token.SEMI);
1231
-
1232
- return pn;
1233
- }
1234
-
1235
- /**
1236
- * Parse a 'var' or 'const' statement, or a 'var' init list in a for
1237
- * statement.
1238
- * @param context A token value: either VAR, CONST or FOR depending on
1239
- * context.
1240
- * @return The parsed statement
1241
- * @throws IOException
1242
- * @throws ParserException
1243
- */
1244
- private Node variables(int context)
1245
- throws IOException, ParserException
1246
- {
1247
- Node pn;
1248
- boolean first = true;
1249
-
1250
- if (context == Token.CONST){
1251
- pn = nf.createVariables(Token.CONST, ts.getLineno());
1252
- decompiler.addToken(Token.CONST);
1253
- } else {
1254
- pn = nf.createVariables(Token.VAR, ts.getLineno());
1255
- decompiler.addToken(Token.VAR);
1256
- }
1257
-
1258
- for (;;) {
1259
- Node name;
1260
- Node init;
1261
- mustMatchToken(Token.NAME, "msg.bad.var");
1262
- String s = ts.getString();
1263
-
1264
- if (!first)
1265
- decompiler.addToken(Token.COMMA);
1266
- first = false;
1267
-
1268
- decompiler.addName(s);
1269
-
1270
- if (context == Token.CONST) {
1271
- if (!currentScriptOrFn.addConst(s)) {
1272
- // We know it's already defined, since addConst passes if
1273
- // it's not defined at all. The addVar call just confirms
1274
- // what it is.
1275
- if (currentScriptOrFn.addVar(s) != ScriptOrFnNode.DUPLICATE_CONST)
1276
- addError("msg.var.redecl", s);
1277
- else
1278
- addError("msg.const.redecl", s);
1279
- }
1280
- } else {
1281
- int dupState = currentScriptOrFn.addVar(s);
1282
- if (dupState == ScriptOrFnNode.DUPLICATE_CONST)
1283
- addError("msg.const.redecl", s);
1284
- else if (dupState == ScriptOrFnNode.DUPLICATE_PARAMETER)
1285
- addStrictWarning("msg.var.hides.arg", s);
1286
- else if (dupState == ScriptOrFnNode.DUPLICATE_VAR)
1287
- addStrictWarning("msg.var.redecl", s);
1288
- }
1289
- name = nf.createName(s);
1290
-
1291
- // omitted check for argument hiding
1292
-
1293
- if (matchToken(Token.ASSIGN)) {
1294
- decompiler.addToken(Token.ASSIGN);
1295
-
1296
- init = assignExpr(context == Token.FOR);
1297
- nf.addChildToBack(name, init);
1298
- }
1299
- nf.addChildToBack(pn, name);
1300
- if (!matchToken(Token.COMMA))
1301
- break;
1302
- }
1303
- return pn;
1304
- }
1305
-
1306
- private Node expr(boolean inForInit)
1307
- throws IOException, ParserException
1308
- {
1309
- Node pn = assignExpr(inForInit);
1310
- while (matchToken(Token.COMMA)) {
1311
- decompiler.addToken(Token.COMMA);
1312
- if (compilerEnv.isStrictMode() && !pn.hasSideEffects())
1313
- addStrictWarning("msg.no.side.effects", "");
1314
- pn = nf.createBinary(Token.COMMA, pn, assignExpr(inForInit));
1315
- }
1316
- return pn;
1317
- }
1318
-
1319
- private Node assignExpr(boolean inForInit)
1320
- throws IOException, ParserException
1321
- {
1322
- Node pn = condExpr(inForInit);
1323
-
1324
- int tt = peekToken();
1325
- if (Token.FIRST_ASSIGN <= tt && tt <= Token.LAST_ASSIGN) {
1326
- consumeToken();
1327
- decompiler.addToken(tt);
1328
- pn = nf.createAssignment(tt, pn, assignExpr(inForInit));
1329
- }
1330
-
1331
- return pn;
1332
- }
1333
-
1334
- private Node condExpr(boolean inForInit)
1335
- throws IOException, ParserException
1336
- {
1337
- Node pn = orExpr(inForInit);
1338
-
1339
- if (matchToken(Token.HOOK)) {
1340
- decompiler.addToken(Token.HOOK);
1341
- Node ifTrue = assignExpr(false);
1342
- mustMatchToken(Token.COLON, "msg.no.colon.cond");
1343
- decompiler.addToken(Token.COLON);
1344
- Node ifFalse = assignExpr(inForInit);
1345
- return nf.createCondExpr(pn, ifTrue, ifFalse);
1346
- }
1347
-
1348
- return pn;
1349
- }
1350
-
1351
- private Node orExpr(boolean inForInit)
1352
- throws IOException, ParserException
1353
- {
1354
- Node pn = andExpr(inForInit);
1355
- if (matchToken(Token.OR)) {
1356
- decompiler.addToken(Token.OR);
1357
- pn = nf.createBinary(Token.OR, pn, orExpr(inForInit));
1358
- }
1359
-
1360
- return pn;
1361
- }
1362
-
1363
- private Node andExpr(boolean inForInit)
1364
- throws IOException, ParserException
1365
- {
1366
- Node pn = bitOrExpr(inForInit);
1367
- if (matchToken(Token.AND)) {
1368
- decompiler.addToken(Token.AND);
1369
- pn = nf.createBinary(Token.AND, pn, andExpr(inForInit));
1370
- }
1371
-
1372
- return pn;
1373
- }
1374
-
1375
- private Node bitOrExpr(boolean inForInit)
1376
- throws IOException, ParserException
1377
- {
1378
- Node pn = bitXorExpr(inForInit);
1379
- while (matchToken(Token.BITOR)) {
1380
- decompiler.addToken(Token.BITOR);
1381
- pn = nf.createBinary(Token.BITOR, pn, bitXorExpr(inForInit));
1382
- }
1383
- return pn;
1384
- }
1385
-
1386
- private Node bitXorExpr(boolean inForInit)
1387
- throws IOException, ParserException
1388
- {
1389
- Node pn = bitAndExpr(inForInit);
1390
- while (matchToken(Token.BITXOR)) {
1391
- decompiler.addToken(Token.BITXOR);
1392
- pn = nf.createBinary(Token.BITXOR, pn, bitAndExpr(inForInit));
1393
- }
1394
- return pn;
1395
- }
1396
-
1397
- private Node bitAndExpr(boolean inForInit)
1398
- throws IOException, ParserException
1399
- {
1400
- Node pn = eqExpr(inForInit);
1401
- while (matchToken(Token.BITAND)) {
1402
- decompiler.addToken(Token.BITAND);
1403
- pn = nf.createBinary(Token.BITAND, pn, eqExpr(inForInit));
1404
- }
1405
- return pn;
1406
- }
1407
-
1408
- private Node eqExpr(boolean inForInit)
1409
- throws IOException, ParserException
1410
- {
1411
- Node pn = relExpr(inForInit);
1412
- for (;;) {
1413
- int tt = peekToken();
1414
- switch (tt) {
1415
- case Token.EQ:
1416
- case Token.NE:
1417
- case Token.SHEQ:
1418
- case Token.SHNE:
1419
- consumeToken();
1420
- int decompilerToken = tt;
1421
- int parseToken = tt;
1422
- if (compilerEnv.getLanguageVersion() == Context.VERSION_1_2) {
1423
- // JavaScript 1.2 uses shallow equality for == and != .
1424
- // In addition, convert === and !== for decompiler into
1425
- // == and != since the decompiler is supposed to show
1426
- // canonical source and in 1.2 ===, !== are allowed
1427
- // only as an alias to ==, !=.
1428
- switch (tt) {
1429
- case Token.EQ:
1430
- parseToken = Token.SHEQ;
1431
- break;
1432
- case Token.NE:
1433
- parseToken = Token.SHNE;
1434
- break;
1435
- case Token.SHEQ:
1436
- decompilerToken = Token.EQ;
1437
- break;
1438
- case Token.SHNE:
1439
- decompilerToken = Token.NE;
1440
- break;
1441
- }
1442
- }
1443
- decompiler.addToken(decompilerToken);
1444
- pn = nf.createBinary(parseToken, pn, relExpr(inForInit));
1445
- continue;
1446
- }
1447
- break;
1448
- }
1449
- return pn;
1450
- }
1451
-
1452
- private Node relExpr(boolean inForInit)
1453
- throws IOException, ParserException
1454
- {
1455
- Node pn = shiftExpr();
1456
- for (;;) {
1457
- int tt = peekToken();
1458
- switch (tt) {
1459
- case Token.IN:
1460
- if (inForInit)
1461
- break;
1462
- // fall through
1463
- case Token.INSTANCEOF:
1464
- case Token.LE:
1465
- case Token.LT:
1466
- case Token.GE:
1467
- case Token.GT:
1468
- consumeToken();
1469
- decompiler.addToken(tt);
1470
- pn = nf.createBinary(tt, pn, shiftExpr());
1471
- continue;
1472
- }
1473
- break;
1474
- }
1475
- return pn;
1476
- }
1477
-
1478
- private Node shiftExpr()
1479
- throws IOException, ParserException
1480
- {
1481
- Node pn = addExpr();
1482
- for (;;) {
1483
- int tt = peekToken();
1484
- switch (tt) {
1485
- case Token.LSH:
1486
- case Token.URSH:
1487
- case Token.RSH:
1488
- consumeToken();
1489
- decompiler.addToken(tt);
1490
- pn = nf.createBinary(tt, pn, addExpr());
1491
- continue;
1492
- }
1493
- break;
1494
- }
1495
- return pn;
1496
- }
1497
-
1498
- private Node addExpr()
1499
- throws IOException, ParserException
1500
- {
1501
- Node pn = mulExpr();
1502
- for (;;) {
1503
- int tt = peekToken();
1504
- if (tt == Token.ADD || tt == Token.SUB) {
1505
- consumeToken();
1506
- decompiler.addToken(tt);
1507
- // flushNewLines
1508
- pn = nf.createBinary(tt, pn, mulExpr());
1509
- continue;
1510
- }
1511
- break;
1512
- }
1513
-
1514
- return pn;
1515
- }
1516
-
1517
- private Node mulExpr()
1518
- throws IOException, ParserException
1519
- {
1520
- Node pn = unaryExpr();
1521
- for (;;) {
1522
- int tt = peekToken();
1523
- switch (tt) {
1524
- case Token.MUL:
1525
- case Token.DIV:
1526
- case Token.MOD:
1527
- consumeToken();
1528
- decompiler.addToken(tt);
1529
- pn = nf.createBinary(tt, pn, unaryExpr());
1530
- continue;
1531
- }
1532
- break;
1533
- }
1534
-
1535
- return pn;
1536
- }
1537
-
1538
- private Node unaryExpr()
1539
- throws IOException, ParserException
1540
- {
1541
- int tt;
1542
-
1543
- tt = peekToken();
1544
-
1545
- switch(tt) {
1546
- case Token.VOID:
1547
- case Token.NOT:
1548
- case Token.BITNOT:
1549
- case Token.TYPEOF:
1550
- consumeToken();
1551
- decompiler.addToken(tt);
1552
- return nf.createUnary(tt, unaryExpr());
1553
-
1554
- case Token.ADD:
1555
- consumeToken();
1556
- // Convert to special POS token in decompiler and parse tree
1557
- decompiler.addToken(Token.POS);
1558
- return nf.createUnary(Token.POS, unaryExpr());
1559
-
1560
- case Token.SUB:
1561
- consumeToken();
1562
- // Convert to special NEG token in decompiler and parse tree
1563
- decompiler.addToken(Token.NEG);
1564
- return nf.createUnary(Token.NEG, unaryExpr());
1565
-
1566
- case Token.INC:
1567
- case Token.DEC:
1568
- consumeToken();
1569
- decompiler.addToken(tt);
1570
- return nf.createIncDec(tt, false, memberExpr(true));
1571
-
1572
- case Token.DELPROP:
1573
- consumeToken();
1574
- decompiler.addToken(Token.DELPROP);
1575
- return nf.createUnary(Token.DELPROP, unaryExpr());
1576
-
1577
- case Token.ERROR:
1578
- consumeToken();
1579
- break;
1580
-
1581
- // XML stream encountered in expression.
1582
- case Token.LT:
1583
- if (compilerEnv.isXmlAvailable()) {
1584
- consumeToken();
1585
- Node pn = xmlInitializer();
1586
- return memberExprTail(true, pn);
1587
- }
1588
- // Fall thru to the default handling of RELOP
1589
-
1590
- default:
1591
- Node pn = memberExpr(true);
1592
-
1593
- // Don't look across a newline boundary for a postfix incop.
1594
- tt = peekTokenOrEOL();
1595
- if (tt == Token.INC || tt == Token.DEC) {
1596
- consumeToken();
1597
- decompiler.addToken(tt);
1598
- return nf.createIncDec(tt, true, pn);
1599
- }
1600
- return pn;
1601
- }
1602
- return nf.createName("err"); // Only reached on error. Try to continue.
1603
-
1604
- }
1605
-
1606
- private Node xmlInitializer() throws IOException
1607
- {
1608
- int tt = ts.getFirstXMLToken();
1609
- if (tt != Token.XML && tt != Token.XMLEND) {
1610
- reportError("msg.syntax");
1611
- return null;
1612
- }
1613
-
1614
- /* Make a NEW node to append to. */
1615
- Node pnXML = nf.createLeaf(Token.NEW);
1616
-
1617
- String xml = ts.getString();
1618
- boolean fAnonymous = xml.trim().startsWith("<>");
1619
-
1620
- Node pn = nf.createName(fAnonymous ? "XMLList" : "XML");
1621
- nf.addChildToBack(pnXML, pn);
1622
-
1623
- pn = null;
1624
- Node expr;
1625
- for (;;tt = ts.getNextXMLToken()) {
1626
- switch (tt) {
1627
- case Token.XML:
1628
- xml = ts.getString();
1629
- decompiler.addName(xml);
1630
- mustMatchToken(Token.LC, "msg.syntax");
1631
- decompiler.addToken(Token.LC);
1632
- expr = (peekToken() == Token.RC)
1633
- ? nf.createString("")
1634
- : expr(false);
1635
- mustMatchToken(Token.RC, "msg.syntax");
1636
- decompiler.addToken(Token.RC);
1637
- if (pn == null) {
1638
- pn = nf.createString(xml);
1639
- } else {
1640
- pn = nf.createBinary(Token.ADD, pn, nf.createString(xml));
1641
- }
1642
- if (ts.isXMLAttribute()) {
1643
- /* Need to put the result in double quotes */
1644
- expr = nf.createUnary(Token.ESCXMLATTR, expr);
1645
- Node prepend = nf.createBinary(Token.ADD,
1646
- nf.createString("\""),
1647
- expr);
1648
- expr = nf.createBinary(Token.ADD,
1649
- prepend,
1650
- nf.createString("\""));
1651
- } else {
1652
- expr = nf.createUnary(Token.ESCXMLTEXT, expr);
1653
- }
1654
- pn = nf.createBinary(Token.ADD, pn, expr);
1655
- break;
1656
- case Token.XMLEND:
1657
- xml = ts.getString();
1658
- decompiler.addName(xml);
1659
- if (pn == null) {
1660
- pn = nf.createString(xml);
1661
- } else {
1662
- pn = nf.createBinary(Token.ADD, pn, nf.createString(xml));
1663
- }
1664
-
1665
- nf.addChildToBack(pnXML, pn);
1666
- return pnXML;
1667
- default:
1668
- reportError("msg.syntax");
1669
- return null;
1670
- }
1671
- }
1672
- }
1673
-
1674
- private void argumentList(Node listNode)
1675
- throws IOException, ParserException
1676
- {
1677
- boolean matched;
1678
- matched = matchToken(Token.RP);
1679
- if (!matched) {
1680
- boolean first = true;
1681
- do {
1682
- if (!first)
1683
- decompiler.addToken(Token.COMMA);
1684
- first = false;
1685
- nf.addChildToBack(listNode, assignExpr(false));
1686
- } while (matchToken(Token.COMMA));
1687
-
1688
- mustMatchToken(Token.RP, "msg.no.paren.arg");
1689
- }
1690
- decompiler.addToken(Token.RP);
1691
- }
1692
-
1693
- private Node memberExpr(boolean allowCallSyntax)
1694
- throws IOException, ParserException
1695
- {
1696
- int tt;
1697
-
1698
- Node pn;
1699
-
1700
- /* Check for new expressions. */
1701
- tt = peekToken();
1702
- if (tt == Token.NEW) {
1703
- /* Eat the NEW token. */
1704
- consumeToken();
1705
- decompiler.addToken(Token.NEW);
1706
-
1707
- /* Make a NEW node to append to. */
1708
- pn = nf.createCallOrNew(Token.NEW, memberExpr(false));
1709
-
1710
- if (matchToken(Token.LP)) {
1711
- decompiler.addToken(Token.LP);
1712
- /* Add the arguments to pn, if any are supplied. */
1713
- argumentList(pn);
1714
- }
1715
-
1716
- /* XXX there's a check in the C source against
1717
- * "too many constructor arguments" - how many
1718
- * do we claim to support?
1719
- */
1720
-
1721
- /* Experimental syntax: allow an object literal to follow a new expression,
1722
- * which will mean a kind of anonymous class built with the JavaAdapter.
1723
- * the object literal will be passed as an additional argument to the constructor.
1724
- */
1725
- tt = peekToken();
1726
- if (tt == Token.LC) {
1727
- nf.addChildToBack(pn, primaryExpr());
1728
- }
1729
- } else {
1730
- pn = primaryExpr();
1731
- }
1732
-
1733
- return memberExprTail(allowCallSyntax, pn);
1734
- }
1735
-
1736
- private Node memberExprTail(boolean allowCallSyntax, Node pn)
1737
- throws IOException, ParserException
1738
- {
1739
- tailLoop:
1740
- for (;;) {
1741
- int tt = peekToken();
1742
- switch (tt) {
1743
-
1744
- case Token.DOT:
1745
- case Token.DOTDOT:
1746
- {
1747
- int memberTypeFlags;
1748
- String s;
1749
-
1750
- consumeToken();
1751
- decompiler.addToken(tt);
1752
- memberTypeFlags = 0;
1753
- if (tt == Token.DOTDOT) {
1754
- mustHaveXML();
1755
- memberTypeFlags = Node.DESCENDANTS_FLAG;
1756
- }
1757
- if (!compilerEnv.isXmlAvailable()) {
1758
- mustMatchToken(Token.NAME, "msg.no.name.after.dot");
1759
- s = ts.getString();
1760
- decompiler.addName(s);
1761
- pn = nf.createPropertyGet(pn, null, s, memberTypeFlags);
1762
- break;
1763
- }
1764
-
1765
- tt = nextToken();
1766
- switch (tt) {
1767
- // handles: name, ns::name, ns::*, ns::[expr]
1768
- case Token.NAME:
1769
- s = ts.getString();
1770
- decompiler.addName(s);
1771
- pn = propertyName(pn, s, memberTypeFlags);
1772
- break;
1773
-
1774
- // handles: *, *::name, *::*, *::[expr]
1775
- case Token.MUL:
1776
- decompiler.addName("*");
1777
- pn = propertyName(pn, "*", memberTypeFlags);
1778
- break;
1779
-
1780
- // handles: '@attr', '@ns::attr', '@ns::*', '@ns::*',
1781
- // '@::attr', '@::*', '@*', '@*::attr', '@*::*'
1782
- case Token.XMLATTR:
1783
- decompiler.addToken(Token.XMLATTR);
1784
- pn = attributeAccess(pn, memberTypeFlags);
1785
- break;
1786
-
1787
- default:
1788
- reportError("msg.no.name.after.dot");
1789
- }
1790
- }
1791
- break;
1792
-
1793
- case Token.DOTQUERY:
1794
- consumeToken();
1795
- mustHaveXML();
1796
- decompiler.addToken(Token.DOTQUERY);
1797
- pn = nf.createDotQuery(pn, expr(false), ts.getLineno());
1798
- mustMatchToken(Token.RP, "msg.no.paren");
1799
- decompiler.addToken(Token.RP);
1800
- break;
1801
-
1802
- case Token.LB:
1803
- consumeToken();
1804
- decompiler.addToken(Token.LB);
1805
- pn = nf.createElementGet(pn, null, expr(false), 0);
1806
- mustMatchToken(Token.RB, "msg.no.bracket.index");
1807
- decompiler.addToken(Token.RB);
1808
- break;
1809
-
1810
- case Token.LP:
1811
- if (!allowCallSyntax) {
1812
- break tailLoop;
1813
- }
1814
- consumeToken();
1815
- decompiler.addToken(Token.LP);
1816
- pn = nf.createCallOrNew(Token.CALL, pn);
1817
- /* Add the arguments to pn, if any are supplied. */
1818
- argumentList(pn);
1819
- break;
1820
-
1821
- default:
1822
- break tailLoop;
1823
- }
1824
- }
1825
- return pn;
1826
- }
1827
-
1828
- /*
1829
- * Xml attribute expression:
1830
- * '@attr', '@ns::attr', '@ns::*', '@ns::*', '@*', '@*::attr', '@*::*'
1831
- */
1832
- private Node attributeAccess(Node pn, int memberTypeFlags)
1833
- throws IOException
1834
- {
1835
- memberTypeFlags |= Node.ATTRIBUTE_FLAG;
1836
- int tt = nextToken();
1837
-
1838
- switch (tt) {
1839
- // handles: @name, @ns::name, @ns::*, @ns::[expr]
1840
- case Token.NAME:
1841
- {
1842
- String s = ts.getString();
1843
- decompiler.addName(s);
1844
- pn = propertyName(pn, s, memberTypeFlags);
1845
- }
1846
- break;
1847
-
1848
- // handles: @*, @*::name, @*::*, @*::[expr]
1849
- case Token.MUL:
1850
- decompiler.addName("*");
1851
- pn = propertyName(pn, "*", memberTypeFlags);
1852
- break;
1853
-
1854
- // handles @[expr]
1855
- case Token.LB:
1856
- decompiler.addToken(Token.LB);
1857
- pn = nf.createElementGet(pn, null, expr(false), memberTypeFlags);
1858
- mustMatchToken(Token.RB, "msg.no.bracket.index");
1859
- decompiler.addToken(Token.RB);
1860
- break;
1861
-
1862
- default:
1863
- reportError("msg.no.name.after.xmlAttr");
1864
- pn = nf.createPropertyGet(pn, null, "?", memberTypeFlags);
1865
- break;
1866
- }
1867
-
1868
- return pn;
1869
- }
1870
-
1871
- /**
1872
- * Check if :: follows name in which case it becomes qualified name
1873
- */
1874
- private Node propertyName(Node pn, String name, int memberTypeFlags)
1875
- throws IOException, ParserException
1876
- {
1877
- String namespace = null;
1878
- if (matchToken(Token.COLONCOLON)) {
1879
- decompiler.addToken(Token.COLONCOLON);
1880
- namespace = name;
1881
-
1882
- int tt = nextToken();
1883
- switch (tt) {
1884
- // handles name::name
1885
- case Token.NAME:
1886
- name = ts.getString();
1887
- decompiler.addName(name);
1888
- break;
1889
-
1890
- // handles name::*
1891
- case Token.MUL:
1892
- decompiler.addName("*");
1893
- name = "*";
1894
- break;
1895
-
1896
- // handles name::[expr]
1897
- case Token.LB:
1898
- decompiler.addToken(Token.LB);
1899
- pn = nf.createElementGet(pn, namespace, expr(false),
1900
- memberTypeFlags);
1901
- mustMatchToken(Token.RB, "msg.no.bracket.index");
1902
- decompiler.addToken(Token.RB);
1903
- return pn;
1904
-
1905
- default:
1906
- reportError("msg.no.name.after.coloncolon");
1907
- name = "?";
1908
- }
1909
- }
1910
-
1911
- pn = nf.createPropertyGet(pn, namespace, name, memberTypeFlags);
1912
- return pn;
1913
- }
1914
-
1915
- private Node primaryExpr()
1916
- throws IOException, ParserException
1917
- {
1918
- Node pn;
1919
-
1920
- int ttFlagged = nextFlaggedToken();
1921
- int tt = ttFlagged & CLEAR_TI_MASK;
1922
-
1923
- switch(tt) {
1924
-
1925
- case Token.FUNCTION:
1926
- return function(FunctionNode.FUNCTION_EXPRESSION);
1927
-
1928
- case Token.LB: {
1929
- ObjArray elems = new ObjArray();
1930
- int skipCount = 0;
1931
- decompiler.addToken(Token.LB);
1932
- boolean after_lb_or_comma = true;
1933
- for (;;) {
1934
- tt = peekToken();
1935
-
1936
- if (tt == Token.COMMA) {
1937
- consumeToken();
1938
- decompiler.addToken(Token.COMMA);
1939
- if (!after_lb_or_comma) {
1940
- after_lb_or_comma = true;
1941
- } else {
1942
- elems.add(null);
1943
- ++skipCount;
1944
- }
1945
- } else if (tt == Token.RB) {
1946
- consumeToken();
1947
- decompiler.addToken(Token.RB);
1948
- break;
1949
- } else {
1950
- if (!after_lb_or_comma) {
1951
- reportError("msg.no.bracket.arg");
1952
- }
1953
- elems.add(assignExpr(false));
1954
- after_lb_or_comma = false;
1955
- }
1956
- }
1957
- return nf.createArrayLiteral(elems, skipCount);
1958
- }
1959
-
1960
- case Token.LC: {
1961
- ObjArray elems = new ObjArray();
1962
- decompiler.addToken(Token.LC);
1963
- if (!matchToken(Token.RC)) {
1964
-
1965
- boolean first = true;
1966
- commaloop:
1967
- do {
1968
- Object property;
1969
-
1970
- if (!first)
1971
- decompiler.addToken(Token.COMMA);
1972
- else
1973
- first = false;
1974
-
1975
- tt = peekToken();
1976
- switch(tt) {
1977
- case Token.NAME:
1978
- case Token.STRING:
1979
- consumeToken();
1980
- // map NAMEs to STRINGs in object literal context
1981
- // but tell the decompiler the proper type
1982
- String s = ts.getString();
1983
- if (tt == Token.NAME) {
1984
- if (s.equals("get") &&
1985
- peekToken() == Token.NAME) {
1986
- decompiler.addToken(Token.GET);
1987
- consumeToken();
1988
- s = ts.getString();
1989
- decompiler.addName(s);
1990
- property = ScriptRuntime.getIndexObject(s);
1991
- if (!getterSetterProperty(elems, property,
1992
- true))
1993
- break commaloop;
1994
- break;
1995
- } else if (s.equals("set") &&
1996
- peekToken() == Token.NAME) {
1997
- decompiler.addToken(Token.SET);
1998
- consumeToken();
1999
- s = ts.getString();
2000
- decompiler.addName(s);
2001
- property = ScriptRuntime.getIndexObject(s);
2002
- if (!getterSetterProperty(elems, property,
2003
- false))
2004
- break commaloop;
2005
- break;
2006
- }
2007
- decompiler.addName(s);
2008
- } else {
2009
- decompiler.addString(s);
2010
- }
2011
- property = ScriptRuntime.getIndexObject(s);
2012
- plainProperty(elems, property);
2013
- break;
2014
-
2015
- case Token.NUMBER:
2016
- consumeToken();
2017
- double n = ts.getNumber();
2018
- decompiler.addNumber(n);
2019
- property = ScriptRuntime.getIndexObject(n);
2020
- plainProperty(elems, property);
2021
- break;
2022
-
2023
- case Token.RC:
2024
- // trailing comma is OK.
2025
- break commaloop;
2026
- default:
2027
- reportError("msg.bad.prop");
2028
- break commaloop;
2029
- }
2030
- } while (matchToken(Token.COMMA));
2031
-
2032
- mustMatchToken(Token.RC, "msg.no.brace.prop");
2033
- }
2034
- decompiler.addToken(Token.RC);
2035
- return nf.createObjectLiteral(elems);
2036
- }
2037
-
2038
- case Token.LP:
2039
-
2040
- /* Brendan's IR-jsparse.c makes a new node tagged with
2041
- * TOK_LP here... I'm not sure I understand why. Isn't
2042
- * the grouping already implicit in the structure of the
2043
- * parse tree? also TOK_LP is already overloaded (I
2044
- * think) in the C IR as 'function call.' */
2045
- decompiler.addToken(Token.LP);
2046
- pn = expr(false);
2047
- pn.putProp(Node.PARENTHESIZED_PROP, Boolean.TRUE);
2048
- decompiler.addToken(Token.RP);
2049
- mustMatchToken(Token.RP, "msg.no.paren");
2050
- return pn;
2051
-
2052
- case Token.XMLATTR:
2053
- mustHaveXML();
2054
- decompiler.addToken(Token.XMLATTR);
2055
- pn = attributeAccess(null, 0);
2056
- return pn;
2057
-
2058
- case Token.NAME: {
2059
- String name = ts.getString();
2060
- if ((ttFlagged & TI_CHECK_LABEL) != 0) {
2061
- if (peekToken() == Token.COLON) {
2062
- // Do not consume colon, it is used as unwind indicator
2063
- // to return to statementHelper.
2064
- // XXX Better way?
2065
- return nf.createLabel(ts.getLineno());
2066
- }
2067
- }
2068
-
2069
- decompiler.addName(name);
2070
- if (compilerEnv.isXmlAvailable()) {
2071
- pn = propertyName(null, name, 0);
2072
- } else {
2073
- pn = nf.createName(name);
2074
- }
2075
- return pn;
2076
- }
2077
-
2078
- case Token.NUMBER: {
2079
- double n = ts.getNumber();
2080
- decompiler.addNumber(n);
2081
- return nf.createNumber(n);
2082
- }
2083
-
2084
- case Token.STRING: {
2085
- String s = ts.getString();
2086
- decompiler.addString(s);
2087
- return nf.createString(s);
2088
- }
2089
-
2090
- case Token.DIV:
2091
- case Token.ASSIGN_DIV: {
2092
- // Got / or /= which should be treated as regexp in fact
2093
- ts.readRegExp(tt);
2094
- String flags = ts.regExpFlags;
2095
- ts.regExpFlags = null;
2096
- String re = ts.getString();
2097
- decompiler.addRegexp(re, flags);
2098
- int index = currentScriptOrFn.addRegexp(re, flags);
2099
- return nf.createRegExp(index);
2100
- }
2101
-
2102
- case Token.NULL:
2103
- case Token.THIS:
2104
- case Token.FALSE:
2105
- case Token.TRUE:
2106
- decompiler.addToken(tt);
2107
- return nf.createLeaf(tt);
2108
-
2109
- case Token.RESERVED:
2110
- reportError("msg.reserved.id");
2111
- break;
2112
-
2113
- case Token.ERROR:
2114
- /* the scanner or one of its subroutines reported the error. */
2115
- break;
2116
-
2117
- case Token.EOF:
2118
- reportError("msg.unexpected.eof");
2119
- break;
2120
-
2121
- default:
2122
- reportError("msg.syntax");
2123
- break;
2124
- }
2125
- return null; // should never reach here
2126
- }
2127
-
2128
- private void plainProperty(ObjArray elems, Object property)
2129
- throws IOException {
2130
- mustMatchToken(Token.COLON, "msg.no.colon.prop");
2131
-
2132
- // OBJLIT is used as ':' in object literal for
2133
- // decompilation to solve spacing ambiguity.
2134
- decompiler.addToken(Token.OBJECTLIT);
2135
- elems.add(property);
2136
- elems.add(assignExpr(false));
2137
- }
2138
-
2139
- private boolean getterSetterProperty(ObjArray elems, Object property,
2140
- boolean isGetter) throws IOException {
2141
- Node f = function(FunctionNode.FUNCTION_EXPRESSION);
2142
- if (f.getType() != Token.FUNCTION) {
2143
- reportError("msg.bad.prop");
2144
- return false;
2145
- }
2146
- int fnIndex = f.getExistingIntProp(Node.FUNCTION_PROP);
2147
- FunctionNode fn = currentScriptOrFn.getFunctionNode(fnIndex);
2148
- if (fn.getFunctionName().length() != 0) {
2149
- reportError("msg.bad.prop");
2150
- return false;
2151
- }
2152
- elems.add(property);
2153
- if (isGetter) {
2154
- elems.add(nf.createUnary(Token.GET, f));
2155
- } else {
2156
- elems.add(nf.createUnary(Token.SET, f));
2157
- }
2158
- return true;
2159
- }
2160
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
lib/Diglin/yuicompressor-2.4.6/src/org/mozilla/javascript/Parser.java.orig DELETED
@@ -1,2159 +0,0 @@
1
- /* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2
- *
3
- * ***** BEGIN LICENSE BLOCK *****
4
- * Version: MPL 1.1/GPL 2.0
5
- *
6
- * The contents of this file are subject to the Mozilla Public License Version
7
- * 1.1 (the "License"); you may not use this file except in compliance with
8
- * the License. You may obtain a copy of the License at
9
- * http://www.mozilla.org/MPL/
10
- *
11
- * Software distributed under the License is distributed on an "AS IS" basis,
12
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13
- * for the specific language governing rights and limitations under the
14
- * License.
15
- *
16
- * The Original Code is Rhino code, released
17
- * May 6, 1999.
18
- *
19
- * The Initial Developer of the Original Code is
20
- * Netscape Communications Corporation.
21
- * Portions created by the Initial Developer are Copyright (C) 1997-1999
22
- * the Initial Developer. All Rights Reserved.
23
- *
24
- * Contributor(s):
25
- * Mike Ang
26
- * Igor Bukanov
27
- * Yuh-Ruey Chen
28
- * Ethan Hugg
29
- * Bob Jervis
30
- * Terry Lucas
31
- * Mike McCabe
32
- * Milen Nankov
33
- *
34
- * Alternatively, the contents of this file may be used under the terms of
35
- * the GNU General Public License Version 2 or later (the "GPL"), in which
36
- * case the provisions of the GPL are applicable instead of those above. If
37
- * you wish to allow use of your version of this file only under the terms of
38
- * the GPL and not to allow others to use your version of this file under the
39
- * MPL, indicate your decision by deleting the provisions above and replacing
40
- * them with the notice and other provisions required by the GPL. If you do
41
- * not delete the provisions above, a recipient may use your version of this
42
- * file under either the MPL or the GPL.
43
- *
44
- * ***** END LICENSE BLOCK ***** */
45
-
46
- package org.mozilla.javascript;
47
-
48
- import java.io.Reader;
49
- import java.io.IOException;
50
- import java.util.Hashtable;
51
-
52
- /**
53
- * This class implements the JavaScript parser.
54
- *
55
- * It is based on the C source files jsparse.c and jsparse.h
56
- * in the jsref package.
57
- *
58
- * @see TokenStream
59
- *
60
- * @author Mike McCabe
61
- * @author Brendan Eich
62
- */
63
-
64
- public class Parser
65
- {
66
- // TokenInformation flags : currentFlaggedToken stores them together
67
- // with token type
68
- final static int
69
- CLEAR_TI_MASK = 0xFFFF, // mask to clear token information bits
70
- TI_AFTER_EOL = 1 << 16, // first token of the source line
71
- TI_CHECK_LABEL = 1 << 17; // indicates to check for label
72
-
73
- CompilerEnvirons compilerEnv;
74
- private ErrorReporter errorReporter;
75
- private String sourceURI;
76
- boolean calledByCompileFunction;
77
-
78
- private TokenStream ts;
79
- private int currentFlaggedToken;
80
- private int syntaxErrorCount;
81
-
82
- private IRFactory nf;
83
-
84
- private int nestingOfFunction;
85
-
86
- private Decompiler decompiler;
87
- private String encodedSource;
88
-
89
- // The following are per function variables and should be saved/restored
90
- // during function parsing.
91
- // XXX Move to separated class?
92
- ScriptOrFnNode currentScriptOrFn;
93
- private int nestingOfWith;
94
- private Hashtable labelSet; // map of label names into nodes
95
- private ObjArray loopSet;
96
- private ObjArray loopAndSwitchSet;
97
- private boolean hasReturnValue;
98
- private int functionEndFlags;
99
- // end of per function variables
100
-
101
- // Exception to unwind
102
- private static class ParserException extends RuntimeException
103
- {
104
- static final long serialVersionUID = 5882582646773765630L;
105
- }
106
-
107
- public Parser(CompilerEnvirons compilerEnv, ErrorReporter errorReporter)
108
- {
109
- this.compilerEnv = compilerEnv;
110
- this.errorReporter = errorReporter;
111
- }
112
-
113
- protected Decompiler createDecompiler(CompilerEnvirons compilerEnv)
114
- {
115
- return new Decompiler();
116
- }
117
-
118
- void addStrictWarning(String messageId, String messageArg)
119
- {
120
- if (compilerEnv.isStrictMode())
121
- addWarning(messageId, messageArg);
122
- }
123
-
124
- void addWarning(String messageId, String messageArg)
125
- {
126
- String message = ScriptRuntime.getMessage1(messageId, messageArg);
127
- if (compilerEnv.reportWarningAsError()) {
128
- ++syntaxErrorCount;
129
- errorReporter.error(message, sourceURI, ts.getLineno(),
130
- ts.getLine(), ts.getOffset());
131
- } else
132
- errorReporter.warning(message, sourceURI, ts.getLineno(),
133
- ts.getLine(), ts.getOffset());
134
- }
135
-
136
- void addError(String messageId)
137
- {
138
- ++syntaxErrorCount;
139
- String message = ScriptRuntime.getMessage0(messageId);
140
- errorReporter.error(message, sourceURI, ts.getLineno(),
141
- ts.getLine(), ts.getOffset());
142
- }
143
-
144
- void addError(String messageId, String messageArg)
145
- {
146
- ++syntaxErrorCount;
147
- String message = ScriptRuntime.getMessage1(messageId, messageArg);
148
- errorReporter.error(message, sourceURI, ts.getLineno(),
149
- ts.getLine(), ts.getOffset());
150
- }
151
-
152
- RuntimeException reportError(String messageId)
153
- {
154
- addError(messageId);
155
-
156
- // Throw a ParserException exception to unwind the recursive descent
157
- // parse.
158
- throw new ParserException();
159
- }
160
-
161
- private int peekToken()
162
- throws IOException
163
- {
164
- int tt = currentFlaggedToken;
165
- if (tt == Token.EOF) {
166
- tt = ts.getToken();
167
- if (tt == Token.EOL) {
168
- do {
169
- tt = ts.getToken();
170
- } while (tt == Token.EOL);
171
- tt |= TI_AFTER_EOL;
172
- }
173
- currentFlaggedToken = tt;
174
- }
175
- return tt & CLEAR_TI_MASK;
176
- }
177
-
178
- private int peekFlaggedToken()
179
- throws IOException
180
- {
181
- peekToken();
182
- return currentFlaggedToken;
183
- }
184
-
185
- private void consumeToken()
186
- {
187
- currentFlaggedToken = Token.EOF;
188
- }
189
-
190
- private int nextToken()
191
- throws IOException
192
- {
193
- int tt = peekToken();
194
- consumeToken();
195
- return tt;
196
- }
197
-
198
- private int nextFlaggedToken()
199
- throws IOException
200
- {
201
- peekToken();
202
- int ttFlagged = currentFlaggedToken;
203
- consumeToken();
204
- return ttFlagged;
205
- }
206
-
207
- private boolean matchToken(int toMatch)
208
- throws IOException
209
- {
210
- int tt = peekToken();
211
- if (tt != toMatch) {
212
- return false;
213
- }
214
- consumeToken();
215
- return true;
216
- }
217
-
218
- private int peekTokenOrEOL()
219
- throws IOException
220
- {
221
- int tt = peekToken();
222
- // Check for last peeked token flags
223
- if ((currentFlaggedToken & TI_AFTER_EOL) != 0) {
224
- tt = Token.EOL;
225
- }
226
- return tt;
227
- }
228
-
229
- private void setCheckForLabel()
230
- {
231
- if ((currentFlaggedToken & CLEAR_TI_MASK) != Token.NAME)
232
- throw Kit.codeBug();
233
- currentFlaggedToken |= TI_CHECK_LABEL;
234
- }
235
-
236
- private void mustMatchToken(int toMatch, String messageId)
237
- throws IOException, ParserException
238
- {
239
- if (!matchToken(toMatch)) {
240
- reportError(messageId);
241
- }
242
- }
243
-
244
- private void mustHaveXML()
245
- {
246
- if (!compilerEnv.isXmlAvailable()) {
247
- reportError("msg.XML.not.available");
248
- }
249
- }
250
-
251
- public String getEncodedSource()
252
- {
253
- return encodedSource;
254
- }
255
-
256
- public boolean eof()
257
- {
258
- return ts.eof();
259
- }
260
-
261
- boolean insideFunction()
262
- {
263
- return nestingOfFunction != 0;
264
- }
265
-
266
- private Node enterLoop(Node loopLabel)
267
- {
268
- Node loop = nf.createLoopNode(loopLabel, ts.getLineno());
269
- if (loopSet == null) {
270
- loopSet = new ObjArray();
271
- if (loopAndSwitchSet == null) {
272
- loopAndSwitchSet = new ObjArray();
273
- }
274
- }
275
- loopSet.push(loop);
276
- loopAndSwitchSet.push(loop);
277
- return loop;
278
- }
279
-
280
- private void exitLoop()
281
- {
282
- loopSet.pop();
283
- loopAndSwitchSet.pop();
284
- }
285
-
286
- private Node enterSwitch(Node switchSelector, int lineno)
287
- {
288
- Node switchNode = nf.createSwitch(switchSelector, lineno);
289
- if (loopAndSwitchSet == null) {
290
- loopAndSwitchSet = new ObjArray();
291
- }
292
- loopAndSwitchSet.push(switchNode);
293
- return switchNode;
294
- }
295
-
296
- private void exitSwitch()
297
- {
298
- loopAndSwitchSet.pop();
299
- }
300
-
301
- /*
302
- * Build a parse tree from the given sourceString.
303
- *
304
- * @return an Object representing the parsed
305
- * program. If the parse fails, null will be returned. (The
306
- * parse failure will result in a call to the ErrorReporter from
307
- * CompilerEnvirons.)
308
- */
309
- public ScriptOrFnNode parse(String sourceString,
310
- String sourceURI, int lineno)
311
- {
312
- this.sourceURI = sourceURI;
313
- this.ts = new TokenStream(this, null, sourceString, lineno);
314
- try {
315
- return parse();
316
- } catch (IOException ex) {
317
- // Should never happen
318
- throw new IllegalStateException();
319
- }
320
- }
321
-
322
- /*
323
- * Build a parse tree from the given sourceString.
324
- *
325
- * @return an Object representing the parsed
326
- * program. If the parse fails, null will be returned. (The
327
- * parse failure will result in a call to the ErrorReporter from
328
- * CompilerEnvirons.)
329
- */
330
- public ScriptOrFnNode parse(Reader sourceReader,
331
- String sourceURI, int lineno)
332
- throws IOException
333
- {
334
- this.sourceURI = sourceURI;
335
- this.ts = new TokenStream(this, sourceReader, null, lineno);
336
- return parse();
337
- }
338
-
339
- private ScriptOrFnNode parse()
340
- throws IOException
341
- {
342
- this.decompiler = createDecompiler(compilerEnv);
343
- this.nf = new IRFactory(this);
344
- currentScriptOrFn = nf.createScript();
345
- int sourceStartOffset = decompiler.getCurrentOffset();
346
- this.encodedSource = null;
347
- decompiler.addToken(Token.SCRIPT);
348
-
349
- this.currentFlaggedToken = Token.EOF;
350
- this.syntaxErrorCount = 0;
351
-
352
- int baseLineno = ts.getLineno(); // line number where source starts
353
-
354
- /* so we have something to add nodes to until
355
- * we've collected all the source */
356
- Node pn = nf.createLeaf(Token.BLOCK);
357
-
358
- try {
359
- for (;;) {
360
- int tt = peekToken();
361
-
362
- if (tt <= Token.EOF) {
363
- break;
364
- }
365
-
366
- Node n;
367
- if (tt == Token.FUNCTION) {
368
- consumeToken();
369
- try {
370
- n = function(calledByCompileFunction
371
- ? FunctionNode.FUNCTION_EXPRESSION
372
- : FunctionNode.FUNCTION_STATEMENT);
373
- } catch (ParserException e) {
374
- break;
375
- }
376
- } else {
377
- n = statement();
378
- }
379
- nf.addChildToBack(pn, n);
380
- }
381
- } catch (StackOverflowError ex) {
382
- String msg = ScriptRuntime.getMessage0(
383
- "msg.too.deep.parser.recursion");
384
- throw Context.reportRuntimeError(msg, sourceURI,
385
- ts.getLineno(), null, 0);
386
- }
387
-
388
- if (this.syntaxErrorCount != 0) {
389
- String msg = String.valueOf(this.syntaxErrorCount);
390
- msg = ScriptRuntime.getMessage1("msg.got.syntax.errors", msg);
391
- throw errorReporter.runtimeError(msg, sourceURI, baseLineno,
392
- null, 0);
393
- }
394
-
395
- currentScriptOrFn.setSourceName(sourceURI);
396
- currentScriptOrFn.setBaseLineno(baseLineno);
397
- currentScriptOrFn.setEndLineno(ts.getLineno());
398
-
399
- int sourceEndOffset = decompiler.getCurrentOffset();
400
- currentScriptOrFn.setEncodedSourceBounds(sourceStartOffset,
401
- sourceEndOffset);
402
-
403
- nf.initScript(currentScriptOrFn, pn);
404
-
405
- if (compilerEnv.isGeneratingSource()) {
406
- encodedSource = decompiler.getEncodedSource();
407
- }
408
- this.decompiler = null; // It helps GC
409
-
410
- return currentScriptOrFn;
411
- }
412
-
413
- /*
414
- * The C version of this function takes an argument list,
415
- * which doesn't seem to be needed for tree generation...
416
- * it'd only be useful for checking argument hiding, which
417
- * I'm not doing anyway...
418
- */
419
- private Node parseFunctionBody()
420
- throws IOException
421
- {
422
- ++nestingOfFunction;
423
- Node pn = nf.createBlock(ts.getLineno());
424
- try {
425
- bodyLoop: for (;;) {
426
- Node n;
427
- int tt = peekToken();
428
- switch (tt) {
429
- case Token.ERROR:
430
- case Token.EOF:
431
- case Token.RC:
432
- break bodyLoop;
433
-
434
- case Token.FUNCTION:
435
- consumeToken();
436
- n = function(FunctionNode.FUNCTION_STATEMENT);
437
- break;
438
- default:
439
- n = statement();
440
- break;
441
- }
442
- nf.addChildToBack(pn, n);
443
- }
444
- } catch (ParserException e) {
445
- // Ignore it
446
- } finally {
447
- --nestingOfFunction;
448
- }
449
-
450
- return pn;
451
- }
452
-
453
- private Node function(int functionType)
454
- throws IOException, ParserException
455
- {
456
- int syntheticType = functionType;
457
- int baseLineno = ts.getLineno(); // line number where source starts
458
-
459
- int functionSourceStart = decompiler.markFunctionStart(functionType);
460
- String name;
461
- Node memberExprNode = null;
462
- if (matchToken(Token.NAME)) {
463
- name = ts.getString();
464
- decompiler.addName(name);
465
- if (!matchToken(Token.LP)) {
466
- if (compilerEnv.isAllowMemberExprAsFunctionName()) {
467
- // Extension to ECMA: if 'function <name>' does not follow
468
- // by '(', assume <name> starts memberExpr
469
- Node memberExprHead = nf.createName(name);
470
- name = "";
471
- memberExprNode = memberExprTail(false, memberExprHead);
472
- }
473
- mustMatchToken(Token.LP, "msg.no.paren.parms");
474
- }
475
- } else if (matchToken(Token.LP)) {
476
- // Anonymous function
477
- name = "";
478
- } else {
479
- name = "";
480
- if (compilerEnv.isAllowMemberExprAsFunctionName()) {
481
- // Note that memberExpr can not start with '(' like
482
- // in function (1+2).toString(), because 'function (' already
483
- // processed as anonymous function
484
- memberExprNode = memberExpr(false);
485
- }
486
- mustMatchToken(Token.LP, "msg.no.paren.parms");
487
- }
488
-
489
- if (memberExprNode != null) {
490
- syntheticType = FunctionNode.FUNCTION_EXPRESSION;
491
- }
492
-
493
- boolean nested = insideFunction();
494
-
495
- FunctionNode fnNode = nf.createFunction(name);
496
- if (nested || nestingOfWith > 0) {
497
- // 1. Nested functions are not affected by the dynamic scope flag
498
- // as dynamic scope is already a parent of their scope.
499
- // 2. Functions defined under the with statement also immune to
500
- // this setup, in which case dynamic scope is ignored in favor
501
- // of with object.
502
- fnNode.itsIgnoreDynamicScope = true;
503
- }
504
-
505
- int functionIndex = currentScriptOrFn.addFunction(fnNode);
506
-
507
- int functionSourceEnd;
508
-
509
- ScriptOrFnNode savedScriptOrFn = currentScriptOrFn;
510
- currentScriptOrFn = fnNode;
511
- int savedNestingOfWith = nestingOfWith;
512
- nestingOfWith = 0;
513
- Hashtable savedLabelSet = labelSet;
514
- labelSet = null;
515
- ObjArray savedLoopSet = loopSet;
516
- loopSet = null;
517
- ObjArray savedLoopAndSwitchSet = loopAndSwitchSet;
518
- loopAndSwitchSet = null;
519
- boolean savedHasReturnValue = hasReturnValue;
520
- int savedFunctionEndFlags = functionEndFlags;
521
-
522
- Node body;
523
- try {
524
- decompiler.addToken(Token.LP);
525
- if (!matchToken(Token.RP)) {
526
- boolean first = true;
527
- do {
528
- if (!first)
529
- decompiler.addToken(Token.COMMA);
530
- first = false;
531
- mustMatchToken(Token.NAME, "msg.no.parm");
532
- String s = ts.getString();
533
- if (fnNode.hasParamOrVar(s)) {
534
- addWarning("msg.dup.parms", s);
535
- }
536
- fnNode.addParam(s);
537
- decompiler.addName(s);
538
- } while (matchToken(Token.COMMA));
539
-
540
- mustMatchToken(Token.RP, "msg.no.paren.after.parms");
541
- }
542
- decompiler.addToken(Token.RP);
543
-
544
- mustMatchToken(Token.LC, "msg.no.brace.body");
545
- decompiler.addEOL(Token.LC);
546
- body = parseFunctionBody();
547
- mustMatchToken(Token.RC, "msg.no.brace.after.body");
548
-
549
- if (compilerEnv.isStrictMode() && !body.hasConsistentReturnUsage())
550
- {
551
- String msg = name.length() > 0 ? "msg.no.return.value"
552
- : "msg.anon.no.return.value";
553
- addStrictWarning(msg, name);
554
- }
555
-
556
- decompiler.addToken(Token.RC);
557
- functionSourceEnd = decompiler.markFunctionEnd(functionSourceStart);
558
- if (functionType != FunctionNode.FUNCTION_EXPRESSION) {
559
- // Add EOL only if function is not part of expression
560
- // since it gets SEMI + EOL from Statement in that case
561
- decompiler.addToken(Token.EOL);
562
- }
563
- }
564
- finally {
565
- hasReturnValue = savedHasReturnValue;
566
- functionEndFlags = savedFunctionEndFlags;
567
- loopAndSwitchSet = savedLoopAndSwitchSet;
568
- loopSet = savedLoopSet;
569
- labelSet = savedLabelSet;
570
- nestingOfWith = savedNestingOfWith;
571
- currentScriptOrFn = savedScriptOrFn;
572
- }
573
-
574
- fnNode.setEncodedSourceBounds(functionSourceStart, functionSourceEnd);
575
- fnNode.setSourceName(sourceURI);
576
- fnNode.setBaseLineno(baseLineno);
577
- fnNode.setEndLineno(ts.getLineno());
578
-
579
- if (name != null) {
580
- int index = currentScriptOrFn.getParamOrVarIndex(name);
581
- if (index >= 0 && index < currentScriptOrFn.getParamCount())
582
- addStrictWarning("msg.var.hides.arg", name);
583
- }
584
-
585
- Node pn = nf.initFunction(fnNode, functionIndex, body, syntheticType);
586
- if (memberExprNode != null) {
587
- pn = nf.createAssignment(Token.ASSIGN, memberExprNode, pn);
588
- if (functionType != FunctionNode.FUNCTION_EXPRESSION) {
589
- // XXX check JScript behavior: should it be createExprStatement?
590
- pn = nf.createExprStatementNoReturn(pn, baseLineno);
591
- }
592
- }
593
- return pn;
594
- }
595
-
596
- private Node statements()
597
- throws IOException
598
- {
599
- Node pn = nf.createBlock(ts.getLineno());
600
-
601
- int tt;
602
- while((tt = peekToken()) > Token.EOF && tt != Token.RC) {
603
- nf.addChildToBack(pn, statement());
604
- }
605
-
606
- return pn;
607
- }
608
-
609
- private Node condition()
610
- throws IOException, ParserException
611
- {
612
- mustMatchToken(Token.LP, "msg.no.paren.cond");
613
- decompiler.addToken(Token.LP);
614
- Node pn = expr(false);
615
- mustMatchToken(Token.RP, "msg.no.paren.after.cond");
616
- decompiler.addToken(Token.RP);
617
-
618
- // Report strict warning on code like "if (a = 7) ...". Suppress the
619
- // warning if the condition is parenthesized, like "if ((a = 7)) ...".
620
- if (pn.getProp(Node.PARENTHESIZED_PROP) == null &&
621
- (pn.getType() == Token.SETNAME || pn.getType() == Token.SETPROP ||
622
- pn.getType() == Token.SETELEM))
623
- {
624
- addStrictWarning("msg.equal.as.assign", "");
625
- }
626
- return pn;
627
- }
628
-
629
- // match a NAME; return null if no match.
630
- private Node matchJumpLabelName()
631
- throws IOException, ParserException
632
- {
633
- Node label = null;
634
-
635
- int tt = peekTokenOrEOL();
636
- if (tt == Token.NAME) {
637
- consumeToken();
638
- String name = ts.getString();
639
- decompiler.addName(name);
640
- if (labelSet != null) {
641
- label = (Node)labelSet.get(name);
642
- }
643
- if (label == null) {
644
- reportError("msg.undef.label");
645
- }
646
- }
647
-
648
- return label;
649
- }
650
-
651
- private Node statement()
652
- throws IOException
653
- {
654
- try {
655
- Node pn = statementHelper(null);
656
- if (pn != null) {
657
- if (compilerEnv.isStrictMode() && !pn.hasSideEffects())
658
- addStrictWarning("msg.no.side.effects", "");
659
- return pn;
660
- }
661
- } catch (ParserException e) { }
662
-
663
- // skip to end of statement
664
- int lineno = ts.getLineno();
665
- guessingStatementEnd: for (;;) {
666
- int tt = peekTokenOrEOL();
667
- consumeToken();
668
- switch (tt) {
669
- case Token.ERROR:
670
- case Token.EOF:
671
- case Token.EOL:
672
- case Token.SEMI:
673
- break guessingStatementEnd;
674
- }
675
- }
676
- return nf.createExprStatement(nf.createName("error"), lineno);
677
- }
678
-
679
- /**
680
- * Whether the "catch (e: e instanceof Exception) { ... }" syntax
681
- * is implemented.
682
- */
683
-
684
- private Node statementHelper(Node statementLabel)
685
- throws IOException, ParserException
686
- {
687
- Node pn = null;
688
-
689
- int tt;
690
-
691
- tt = peekToken();
692
-
693
- switch(tt) {
694
- case Token.IF: {
695
- consumeToken();
696
-
697
- decompiler.addToken(Token.IF);
698
- int lineno = ts.getLineno();
699
- Node cond = condition();
700
- decompiler.addEOL(Token.LC);
701
- Node ifTrue = statement();
702
- Node ifFalse = null;
703
- if (matchToken(Token.ELSE)) {
704
- decompiler.addToken(Token.RC);
705
- decompiler.addToken(Token.ELSE);
706
- decompiler.addEOL(Token.LC);
707
- ifFalse = statement();
708
- }
709
- decompiler.addEOL(Token.RC);
710
- pn = nf.createIf(cond, ifTrue, ifFalse, lineno);
711
- return pn;
712
- }
713
-
714
- case Token.SWITCH: {
715
- consumeToken();
716
-
717
- decompiler.addToken(Token.SWITCH);
718
- int lineno = ts.getLineno();
719
- mustMatchToken(Token.LP, "msg.no.paren.switch");
720
- decompiler.addToken(Token.LP);
721
- pn = enterSwitch(expr(false), lineno);
722
- try {
723
- mustMatchToken(Token.RP, "msg.no.paren.after.switch");
724
- decompiler.addToken(Token.RP);
725
- mustMatchToken(Token.LC, "msg.no.brace.switch");
726
- decompiler.addEOL(Token.LC);
727
-
728
- boolean hasDefault = false;
729
- switchLoop: for (;;) {
730
- tt = nextToken();
731
- Node caseExpression;
732
- switch (tt) {
733
- case Token.RC:
734
- break switchLoop;
735
-
736
- case Token.CASE:
737
- decompiler.addToken(Token.CASE);
738
- caseExpression = expr(false);
739
- mustMatchToken(Token.COLON, "msg.no.colon.case");
740
- decompiler.addEOL(Token.COLON);
741
- break;
742
-
743
- case Token.DEFAULT:
744
- if (hasDefault) {
745
- reportError("msg.double.switch.default");
746
- }
747
- decompiler.addToken(Token.DEFAULT);
748
- hasDefault = true;
749
- caseExpression = null;
750
- mustMatchToken(Token.COLON, "msg.no.colon.case");
751
- decompiler.addEOL(Token.COLON);
752
- break;
753
-
754
- default:
755
- reportError("msg.bad.switch");
756
- break switchLoop;
757
- }
758
-
759
- Node block = nf.createLeaf(Token.BLOCK);
760
- while ((tt = peekToken()) != Token.RC
761
- && tt != Token.CASE
762
- && tt != Token.DEFAULT
763
- && tt != Token.EOF)
764
- {
765
- nf.addChildToBack(block, statement());
766
- }
767
-
768
- // caseExpression == null => add default lable
769
- nf.addSwitchCase(pn, caseExpression, block);
770
- }
771
- decompiler.addEOL(Token.RC);
772
- nf.closeSwitch(pn);
773
- } finally {
774
- exitSwitch();
775
- }
776
- return pn;
777
- }
778
-
779
- case Token.WHILE: {
780
- consumeToken();
781
- decompiler.addToken(Token.WHILE);
782
-
783
- Node loop = enterLoop(statementLabel);
784
- try {
785
- Node cond = condition();
786
- decompiler.addEOL(Token.LC);
787
- Node body = statement();
788
- decompiler.addEOL(Token.RC);
789
- pn = nf.createWhile(loop, cond, body);
790
- } finally {
791
- exitLoop();
792
- }
793
- return pn;
794
- }
795
-
796
- case Token.DO: {
797
- consumeToken();
798
- decompiler.addToken(Token.DO);
799
- decompiler.addEOL(Token.LC);
800
-
801
- Node loop = enterLoop(statementLabel);
802
- try {
803
- Node body = statement();
804
- decompiler.addToken(Token.RC);
805
- mustMatchToken(Token.WHILE, "msg.no.while.do");
806
- decompiler.addToken(Token.WHILE);
807
- Node cond = condition();
808
- pn = nf.createDoWhile(loop, body, cond);
809
- } finally {
810
- exitLoop();
811
- }
812
- // Always auto-insert semicon to follow SpiderMonkey:
813
- // It is required by EMAScript but is ignored by the rest of
814
- // world, see bug 238945
815
- matchToken(Token.SEMI);
816
- decompiler.addEOL(Token.SEMI);
817
- return pn;
818
- }
819
-
820
- case Token.FOR: {
821
- consumeToken();
822
- boolean isForEach = false;
823
- decompiler.addToken(Token.FOR);
824
-
825
- Node loop = enterLoop(statementLabel);
826
- try {
827
-
828
- Node init; // Node init is also foo in 'foo in Object'
829
- Node cond; // Node cond is also object in 'foo in Object'
830
- Node incr = null; // to kill warning
831
- Node body;
832
-
833
- // See if this is a for each () instead of just a for ()
834
- if (matchToken(Token.NAME)) {
835
- decompiler.addName(ts.getString());
836
- if (ts.getString().equals("each")) {
837
- isForEach = true;
838
- } else {
839
- reportError("msg.no.paren.for");
840
- }
841
- }
842
-
843
- mustMatchToken(Token.LP, "msg.no.paren.for");
844
- decompiler.addToken(Token.LP);
845
- tt = peekToken();
846
- if (tt == Token.SEMI) {
847
- init = nf.createLeaf(Token.EMPTY);
848
- } else {
849
- if (tt == Token.VAR) {
850
- // set init to a var list or initial
851
- consumeToken(); // consume the 'var' token
852
- init = variables(Token.FOR);
853
- }
854
- else {
855
- init = expr(true);
856
- }
857
- }
858
-
859
- if (matchToken(Token.IN)) {
860
- decompiler.addToken(Token.IN);
861
- // 'cond' is the object over which we're iterating
862
- cond = expr(false);
863
- } else { // ordinary for loop
864
- mustMatchToken(Token.SEMI, "msg.no.semi.for");
865
- decompiler.addToken(Token.SEMI);
866
- if (peekToken() == Token.SEMI) {
867
- // no loop condition
868
- cond = nf.createLeaf(Token.EMPTY);
869
- } else {
870
- cond = expr(false);
871
- }
872
-
873
- mustMatchToken(Token.SEMI, "msg.no.semi.for.cond");
874
- decompiler.addToken(Token.SEMI);
875
- if (peekToken() == Token.RP) {
876
- incr = nf.createLeaf(Token.EMPTY);
877
- } else {
878
- incr = expr(false);
879
- }
880
- }
881
-
882
- mustMatchToken(Token.RP, "msg.no.paren.for.ctrl");
883
- decompiler.addToken(Token.RP);
884
- decompiler.addEOL(Token.LC);
885
- body = statement();
886
- decompiler.addEOL(Token.RC);
887
-
888
- if (incr == null) {
889
- // cond could be null if 'in obj' got eaten
890
- // by the init node.
891
- pn = nf.createForIn(loop, init, cond, body, isForEach);
892
- } else {
893
- pn = nf.createFor(loop, init, cond, incr, body);
894
- }
895
- } finally {
896
- exitLoop();
897
- }
898
- return pn;
899
- }
900
-
901
- case Token.TRY: {
902
- consumeToken();
903
- int lineno = ts.getLineno();
904
-
905
- Node tryblock;
906
- Node catchblocks = null;
907
- Node finallyblock = null;
908
-
909
- decompiler.addToken(Token.TRY);
910
- decompiler.addEOL(Token.LC);
911
- tryblock = statement();
912
- decompiler.addEOL(Token.RC);
913
-
914
- catchblocks = nf.createLeaf(Token.BLOCK);
915
-
916
- boolean sawDefaultCatch = false;
917
- int peek = peekToken();
918
- if (peek == Token.CATCH) {
919
- while (matchToken(Token.CATCH)) {
920
- if (sawDefaultCatch) {
921
- reportError("msg.catch.unreachable");
922
- }
923
- decompiler.addToken(Token.CATCH);
924
- mustMatchToken(Token.LP, "msg.no.paren.catch");
925
- decompiler.addToken(Token.LP);
926
-
927
- mustMatchToken(Token.NAME, "msg.bad.catchcond");
928
- String varName = ts.getString();
929
- decompiler.addName(varName);
930
-
931
- Node catchCond = null;
932
- if (matchToken(Token.IF)) {
933
- decompiler.addToken(Token.IF);
934
- catchCond = expr(false);
935
- } else {
936
- sawDefaultCatch = true;
937
- }
938
-
939
- mustMatchToken(Token.RP, "msg.bad.catchcond");
940
- decompiler.addToken(Token.RP);
941
- mustMatchToken(Token.LC, "msg.no.brace.catchblock");
942
- decompiler.addEOL(Token.LC);
943
-
944
- nf.addChildToBack(catchblocks,
945
- nf.createCatch(varName, catchCond,
946
- statements(),
947
- ts.getLineno()));
948
-
949
- mustMatchToken(Token.RC, "msg.no.brace.after.body");
950
- decompiler.addEOL(Token.RC);
951
- }
952
- } else if (peek != Token.FINALLY) {
953
- mustMatchToken(Token.FINALLY, "msg.try.no.catchfinally");
954
- }
955
-
956
- if (matchToken(Token.FINALLY)) {
957
- decompiler.addToken(Token.FINALLY);
958
- decompiler.addEOL(Token.LC);
959
- finallyblock = statement();
960
- decompiler.addEOL(Token.RC);
961
- }
962
-
963
- pn = nf.createTryCatchFinally(tryblock, catchblocks,
964
- finallyblock, lineno);
965
-
966
- return pn;
967
- }
968
-
969
- case Token.THROW: {
970
- consumeToken();
971
- if (peekTokenOrEOL() == Token.EOL) {
972
- // ECMAScript does not allow new lines before throw expression,
973
- // see bug 256617
974
- reportError("msg.bad.throw.eol");
975
- }
976
-
977
- int lineno = ts.getLineno();
978
- decompiler.addToken(Token.THROW);
979
- pn = nf.createThrow(expr(false), lineno);
980
- break;
981
- }
982
-
983
- case Token.BREAK: {
984
- consumeToken();
985
- int lineno = ts.getLineno();
986
-
987
- decompiler.addToken(Token.BREAK);
988
-
989
- // matchJumpLabelName only matches if there is one
990
- Node breakStatement = matchJumpLabelName();
991
- if (breakStatement == null) {
992
- if (loopAndSwitchSet == null || loopAndSwitchSet.size() == 0) {
993
- reportError("msg.bad.break");
994
- return null;
995
- }
996
- breakStatement = (Node)loopAndSwitchSet.peek();
997
- }
998
- pn = nf.createBreak(breakStatement, lineno);
999
- break;
1000
- }
1001
-
1002
- case Token.CONTINUE: {
1003
- consumeToken();
1004
- int lineno = ts.getLineno();
1005
-
1006
- decompiler.addToken(Token.CONTINUE);
1007
-
1008
- Node loop;
1009
- // matchJumpLabelName only matches if there is one
1010
- Node label = matchJumpLabelName();
1011
- if (label == null) {
1012
- if (loopSet == null || loopSet.size() == 0) {
1013
- reportError("msg.continue.outside");
1014
- return null;
1015
- }
1016
- loop = (Node)loopSet.peek();
1017
- } else {
1018
- loop = nf.getLabelLoop(label);
1019
- if (loop == null) {
1020
- reportError("msg.continue.nonloop");
1021
- return null;
1022
- }
1023
- }
1024
- pn = nf.createContinue(loop, lineno);
1025
- break;
1026
- }
1027
-
1028
- case Token.WITH: {
1029
- consumeToken();
1030
-
1031
- decompiler.addToken(Token.WITH);
1032
- int lineno = ts.getLineno();
1033
- mustMatchToken(Token.LP, "msg.no.paren.with");
1034
- decompiler.addToken(Token.LP);
1035
- Node obj = expr(false);
1036
- mustMatchToken(Token.RP, "msg.no.paren.after.with");
1037
- decompiler.addToken(Token.RP);
1038
- decompiler.addEOL(Token.LC);
1039
-
1040
- ++nestingOfWith;
1041
- Node body;
1042
- try {
1043
- body = statement();
1044
- } finally {
1045
- --nestingOfWith;
1046
- }
1047
-
1048
- decompiler.addEOL(Token.RC);
1049
-
1050
- pn = nf.createWith(obj, body, lineno);
1051
- return pn;
1052
- }
1053
-
1054
- case Token.CONST:
1055
- case Token.VAR: {
1056
- consumeToken();
1057
- pn = variables(tt);
1058
- break;
1059
- }
1060
-
1061
- case Token.RETURN: {
1062
- if (!insideFunction()) {
1063
- reportError("msg.bad.return");
1064
- }
1065
- consumeToken();
1066
- decompiler.addToken(Token.RETURN);
1067
- int lineno = ts.getLineno();
1068
-
1069
- Node retExpr;
1070
- /* This is ugly, but we don't want to require a semicolon. */
1071
- tt = peekTokenOrEOL();
1072
- switch (tt) {
1073
- case Token.SEMI:
1074
- case Token.RC:
1075
- case Token.EOF:
1076
- case Token.EOL:
1077
- case Token.ERROR:
1078
- retExpr = null;
1079
- break;
1080
- default:
1081
- retExpr = expr(false);
1082
- hasReturnValue = true;
1083
- }
1084
- pn = nf.createReturn(retExpr, lineno);
1085
-
1086
- // see if we need a strict mode warning
1087
- if (retExpr == null) {
1088
- if (functionEndFlags == Node.END_RETURNS_VALUE)
1089
- addStrictWarning("msg.return.inconsistent", "");
1090
-
1091
- functionEndFlags |= Node.END_RETURNS;
1092
- } else {
1093
- if (functionEndFlags == Node.END_RETURNS)
1094
- addStrictWarning("msg.return.inconsistent", "");
1095
-
1096
- functionEndFlags |= Node.END_RETURNS_VALUE;
1097
- }
1098
-
1099
- break;
1100
- }
1101
-
1102
- case Token.LC:
1103
- consumeToken();
1104
- if (statementLabel != null) {
1105
- decompiler.addToken(Token.LC);
1106
- }
1107
- pn = statements();
1108
- mustMatchToken(Token.RC, "msg.no.brace.block");
1109
- if (statementLabel != null) {
1110
- decompiler.addEOL(Token.RC);
1111
- }
1112
- return pn;
1113
-
1114
- case Token.ERROR:
1115
- // Fall thru, to have a node for error recovery to work on
1116
- case Token.SEMI:
1117
- consumeToken();
1118
- pn = nf.createLeaf(Token.EMPTY);
1119
- return pn;
1120
-
1121
- case Token.FUNCTION: {
1122
- consumeToken();
1123
- pn = function(FunctionNode.FUNCTION_EXPRESSION_STATEMENT);
1124
- return pn;
1125
- }
1126
-
1127
- case Token.DEFAULT :
1128
- consumeToken();
1129
- mustHaveXML();
1130
-
1131
- decompiler.addToken(Token.DEFAULT);
1132
- int nsLine = ts.getLineno();
1133
-
1134
- if (!(matchToken(Token.NAME)
1135
- && ts.getString().equals("xml")))
1136
- {
1137
- reportError("msg.bad.namespace");
1138
- }
1139
- decompiler.addName(" xml");
1140
-
1141
- if (!(matchToken(Token.NAME)
1142
- && ts.getString().equals("namespace")))
1143
- {
1144
- reportError("msg.bad.namespace");
1145
- }
1146
- decompiler.addName(" namespace");
1147
-
1148
- if (!matchToken(Token.ASSIGN)) {
1149
- reportError("msg.bad.namespace");
1150
- }
1151
- decompiler.addToken(Token.ASSIGN);
1152
-
1153
- Node expr = expr(false);
1154
- pn = nf.createDefaultNamespace(expr, nsLine);
1155
- break;
1156
-
1157
- case Token.NAME: {
1158
- int lineno = ts.getLineno();
1159
- String name = ts.getString();
1160
- setCheckForLabel();
1161
- pn = expr(false);
1162
- if (pn.getType() != Token.LABEL) {
1163
- pn = nf.createExprStatement(pn, lineno);
1164
- } else {
1165
- // Parsed the label: push back token should be
1166
- // colon that primaryExpr left untouched.
1167
- if (peekToken() != Token.COLON) Kit.codeBug();
1168
- consumeToken();
1169
- // depend on decompiling lookahead to guess that that
1170
- // last name was a label.
1171
- decompiler.addName(name);
1172
- decompiler.addEOL(Token.COLON);
1173
-
1174
- if (labelSet == null) {
1175
- labelSet = new Hashtable();
1176
- } else if (labelSet.containsKey(name)) {
1177
- reportError("msg.dup.label");
1178
- }
1179
-
1180
- boolean firstLabel;
1181
- if (statementLabel == null) {
1182
- firstLabel = true;
1183
- statementLabel = pn;
1184
- } else {
1185
- // Discard multiple label nodes and use only
1186
- // the first: it allows to simplify IRFactory
1187
- firstLabel = false;
1188
- }
1189
- labelSet.put(name, statementLabel);
1190
- try {
1191
- pn = statementHelper(statementLabel);
1192
- } finally {
1193
- labelSet.remove(name);
1194
- }
1195
- if (firstLabel) {
1196
- pn = nf.createLabeledStatement(statementLabel, pn);
1197
- }
1198
- return pn;
1199
- }
1200
- break;
1201
- }
1202
-
1203
- default: {
1204
- int lineno = ts.getLineno();
1205
- pn = expr(false);
1206
- pn = nf.createExprStatement(pn, lineno);
1207
- break;
1208
- }
1209
- }
1210
-
1211
- int ttFlagged = peekFlaggedToken();
1212
- switch (ttFlagged & CLEAR_TI_MASK) {
1213
- case Token.SEMI:
1214
- // Consume ';' as a part of expression
1215
- consumeToken();
1216
- break;
1217
- case Token.ERROR:
1218
- case Token.EOF:
1219
- case Token.RC:
1220
- // Autoinsert ;
1221
- break;
1222
- default:
1223
- if ((ttFlagged & TI_AFTER_EOL) == 0) {
1224
- // Report error if no EOL or autoinsert ; otherwise
1225
- reportError("msg.no.semi.stmt");
1226
- }
1227
- break;
1228
- }
1229
- decompiler.addEOL(Token.SEMI);
1230
-
1231
- return pn;
1232
- }
1233
-
1234
- /**
1235
- * Parse a 'var' or 'const' statement, or a 'var' init list in a for
1236
- * statement.
1237
- * @param context A token value: either VAR, CONST or FOR depending on
1238
- * context.
1239
- * @return The parsed statement
1240
- * @throws IOException
1241
- * @throws ParserException
1242
- */
1243
- private Node variables(int context)
1244
- throws IOException, ParserException
1245
- {
1246
- Node pn;
1247
- boolean first = true;
1248
-
1249
- if (context == Token.CONST){
1250
- pn = nf.createVariables(Token.CONST, ts.getLineno());
1251
- decompiler.addToken(Token.CONST);
1252
- } else {
1253
- pn = nf.createVariables(Token.VAR, ts.getLineno());
1254
- decompiler.addToken(Token.VAR);
1255
- }
1256
-
1257
- for (;;) {
1258
- Node name;
1259
- Node init;
1260
- mustMatchToken(Token.NAME, "msg.bad.var");
1261
- String s = ts.getString();
1262
-
1263
- if (!first)
1264
- decompiler.addToken(Token.COMMA);
1265
- first = false;
1266
-
1267
- decompiler.addName(s);
1268
-
1269
- if (context == Token.CONST) {
1270
- if (!currentScriptOrFn.addConst(s)) {
1271
- // We know it's already defined, since addConst passes if
1272
- // it's not defined at all. The addVar call just confirms
1273
- // what it is.
1274
- if (currentScriptOrFn.addVar(s) != ScriptOrFnNode.DUPLICATE_CONST)
1275
- addError("msg.var.redecl", s);
1276
- else
1277
- addError("msg.const.redecl", s);
1278
- }
1279
- } else {
1280
- int dupState = currentScriptOrFn.addVar(s);
1281
- if (dupState == ScriptOrFnNode.DUPLICATE_CONST)
1282
- addError("msg.const.redecl", s);
1283
- else if (dupState == ScriptOrFnNode.DUPLICATE_PARAMETER)
1284
- addStrictWarning("msg.var.hides.arg", s);
1285
- else if (dupState == ScriptOrFnNode.DUPLICATE_VAR)
1286
- addStrictWarning("msg.var.redecl", s);
1287
- }
1288
- name = nf.createName(s);
1289
-
1290
- // omitted check for argument hiding
1291
-
1292
- if (matchToken(Token.ASSIGN)) {
1293
- decompiler.addToken(Token.ASSIGN);
1294
-
1295
- init = assignExpr(context == Token.FOR);
1296
- nf.addChildToBack(name, init);
1297
- }
1298
- nf.addChildToBack(pn, name);
1299
- if (!matchToken(Token.COMMA))
1300
- break;
1301
- }
1302
- return pn;
1303
- }
1304
-
1305
- private Node expr(boolean inForInit)
1306
- throws IOException, ParserException
1307
- {
1308
- Node pn = assignExpr(inForInit);
1309
- while (matchToken(Token.COMMA)) {
1310
- decompiler.addToken(Token.COMMA);
1311
- if (compilerEnv.isStrictMode() && !pn.hasSideEffects())
1312
- addStrictWarning("msg.no.side.effects", "");
1313
- pn = nf.createBinary(Token.COMMA, pn, assignExpr(inForInit));
1314
- }
1315
- return pn;
1316
- }
1317
-
1318
- private Node assignExpr(boolean inForInit)
1319
- throws IOException, ParserException
1320
- {
1321
- Node pn = condExpr(inForInit);
1322
-
1323
- int tt = peekToken();
1324
- if (Token.FIRST_ASSIGN <= tt && tt <= Token.LAST_ASSIGN) {
1325
- consumeToken();
1326
- decompiler.addToken(tt);
1327
- pn = nf.createAssignment(tt, pn, assignExpr(inForInit));
1328
- }
1329
-
1330
- return pn;
1331
- }
1332
-
1333
- private Node condExpr(boolean inForInit)
1334
- throws IOException, ParserException
1335
- {
1336
- Node pn = orExpr(inForInit);
1337
-
1338
- if (matchToken(Token.HOOK)) {
1339
- decompiler.addToken(Token.HOOK);
1340
- Node ifTrue = assignExpr(false);
1341
- mustMatchToken(Token.COLON, "msg.no.colon.cond");
1342
- decompiler.addToken(Token.COLON);
1343
- Node ifFalse = assignExpr(inForInit);
1344
- return nf.createCondExpr(pn, ifTrue, ifFalse);
1345
- }
1346
-
1347
- return pn;
1348
- }
1349
-
1350
- private Node orExpr(boolean inForInit)
1351
- throws IOException, ParserException
1352
- {
1353
- Node pn = andExpr(inForInit);
1354
- if (matchToken(Token.OR)) {
1355
- decompiler.addToken(Token.OR);
1356
- pn = nf.createBinary(Token.OR, pn, orExpr(inForInit));
1357
- }
1358
-
1359
- return pn;
1360
- }
1361
-
1362
- private Node andExpr(boolean inForInit)
1363
- throws IOException, ParserException
1364
- {
1365
- Node pn = bitOrExpr(inForInit);
1366
- if (matchToken(Token.AND)) {
1367
- decompiler.addToken(Token.AND);
1368
- pn = nf.createBinary(Token.AND, pn, andExpr(inForInit));
1369
- }
1370
-
1371
- return pn;
1372
- }
1373
-
1374
- private Node bitOrExpr(boolean inForInit)
1375
- throws IOException, ParserException
1376
- {
1377
- Node pn = bitXorExpr(inForInit);
1378
- while (matchToken(Token.BITOR)) {
1379
- decompiler.addToken(Token.BITOR);
1380
- pn = nf.createBinary(Token.BITOR, pn, bitXorExpr(inForInit));
1381
- }
1382
- return pn;
1383
- }
1384
-
1385
- private Node bitXorExpr(boolean inForInit)
1386
- throws IOException, ParserException
1387
- {
1388
- Node pn = bitAndExpr(inForInit);
1389
- while (matchToken(Token.BITXOR)) {
1390
- decompiler.addToken(Token.BITXOR);
1391
- pn = nf.createBinary(Token.BITXOR, pn, bitAndExpr(inForInit));
1392
- }
1393
- return pn;
1394
- }
1395
-
1396
- private Node bitAndExpr(boolean inForInit)
1397
- throws IOException, ParserException
1398
- {
1399
- Node pn = eqExpr(inForInit);
1400
- while (matchToken(Token.BITAND)) {
1401
- decompiler.addToken(Token.BITAND);
1402
- pn = nf.createBinary(Token.BITAND, pn, eqExpr(inForInit));
1403
- }
1404
- return pn;
1405
- }
1406
-
1407
- private Node eqExpr(boolean inForInit)
1408
- throws IOException, ParserException
1409
- {
1410
- Node pn = relExpr(inForInit);
1411
- for (;;) {
1412
- int tt = peekToken();
1413
- switch (tt) {
1414
- case Token.EQ:
1415
- case Token.NE:
1416
- case Token.SHEQ:
1417
- case Token.SHNE:
1418
- consumeToken();
1419
- int decompilerToken = tt;
1420
- int parseToken = tt;
1421
- if (compilerEnv.getLanguageVersion() == Context.VERSION_1_2) {
1422
- // JavaScript 1.2 uses shallow equality for == and != .
1423
- // In addition, convert === and !== for decompiler into
1424
- // == and != since the decompiler is supposed to show
1425
- // canonical source and in 1.2 ===, !== are allowed
1426
- // only as an alias to ==, !=.
1427
- switch (tt) {
1428
- case Token.EQ:
1429
- parseToken = Token.SHEQ;
1430
- break;
1431
- case Token.NE:
1432
- parseToken = Token.SHNE;
1433
- break;
1434
- case Token.SHEQ:
1435
- decompilerToken = Token.EQ;
1436
- break;
1437
- case Token.SHNE:
1438
- decompilerToken = Token.NE;
1439
- break;
1440
- }
1441
- }
1442
- decompiler.addToken(decompilerToken);
1443
- pn = nf.createBinary(parseToken, pn, relExpr(inForInit));
1444
- continue;
1445
- }
1446
- break;
1447
- }
1448
- return pn;
1449
- }
1450
-
1451
- private Node relExpr(boolean inForInit)
1452
- throws IOException, ParserException
1453
- {
1454
- Node pn = shiftExpr();
1455
- for (;;) {
1456
- int tt = peekToken();
1457
- switch (tt) {
1458
- case Token.IN:
1459
- if (inForInit)
1460
- break;
1461
- // fall through
1462
- case Token.INSTANCEOF:
1463
- case Token.LE:
1464
- case Token.LT:
1465
- case Token.GE:
1466
- case Token.GT:
1467
- consumeToken();
1468
- decompiler.addToken(tt);
1469
- pn = nf.createBinary(tt, pn, shiftExpr());
1470
- continue;
1471
- }
1472
- break;
1473
- }
1474
- return pn;
1475
- }
1476
-
1477
- private Node shiftExpr()
1478
- throws IOException, ParserException
1479
- {
1480
- Node pn = addExpr();
1481
- for (;;) {
1482
- int tt = peekToken();
1483
- switch (tt) {
1484
- case Token.LSH:
1485
- case Token.URSH:
1486
- case Token.RSH:
1487
- consumeToken();
1488
- decompiler.addToken(tt);
1489
- pn = nf.createBinary(tt, pn, addExpr());
1490
- continue;
1491
- }
1492
- break;
1493
- }
1494
- return pn;
1495
- }
1496
-
1497
- private Node addExpr()
1498
- throws IOException, ParserException
1499
- {
1500
- Node pn = mulExpr();
1501
- for (;;) {
1502
- int tt = peekToken();
1503
- if (tt == Token.ADD || tt == Token.SUB) {
1504
- consumeToken();
1505
- decompiler.addToken(tt);
1506
- // flushNewLines
1507
- pn = nf.createBinary(tt, pn, mulExpr());
1508
- continue;
1509
- }
1510
- break;
1511
- }
1512
-
1513
- return pn;
1514
- }
1515
-
1516
- private Node mulExpr()
1517
- throws IOException, ParserException
1518
- {
1519
- Node pn = unaryExpr();
1520
- for (;;) {
1521
- int tt = peekToken();
1522
- switch (tt) {
1523
- case Token.MUL:
1524
- case Token.DIV:
1525
- case Token.MOD:
1526
- consumeToken();
1527
- decompiler.addToken(tt);
1528
- pn = nf.createBinary(tt, pn, unaryExpr());
1529
- continue;
1530
- }
1531
- break;
1532
- }
1533
-
1534
- return pn;
1535
- }
1536
-
1537
- private Node unaryExpr()
1538
- throws IOException, ParserException
1539
- {
1540
- int tt;
1541
-
1542
- tt = peekToken();
1543
-
1544
- switch(tt) {
1545
- case Token.VOID:
1546
- case Token.NOT:
1547
- case Token.BITNOT:
1548
- case Token.TYPEOF:
1549
- consumeToken();
1550
- decompiler.addToken(tt);
1551
- return nf.createUnary(tt, unaryExpr());
1552
-
1553
- case Token.ADD:
1554
- consumeToken();
1555
- // Convert to special POS token in decompiler and parse tree
1556
- decompiler.addToken(Token.POS);
1557
- return nf.createUnary(Token.POS, unaryExpr());
1558
-
1559
- case Token.SUB:
1560
- consumeToken();
1561
- // Convert to special NEG token in decompiler and parse tree
1562
- decompiler.addToken(Token.NEG);
1563
- return nf.createUnary(Token.NEG, unaryExpr());
1564
-
1565
- case Token.INC:
1566
- case Token.DEC:
1567
- consumeToken();
1568
- decompiler.addToken(tt);
1569
- return nf.createIncDec(tt, false, memberExpr(true));
1570
-
1571
- case Token.DELPROP:
1572
- consumeToken();
1573
- decompiler.addToken(Token.DELPROP);
1574
- return nf.createUnary(Token.DELPROP, unaryExpr());
1575
-
1576
- case Token.ERROR:
1577
- consumeToken();
1578
- break;
1579
-
1580
- // XML stream encountered in expression.
1581
- case Token.LT:
1582
- if (compilerEnv.isXmlAvailable()) {
1583
- consumeToken();
1584
- Node pn = xmlInitializer();
1585
- return memberExprTail(true, pn);
1586
- }
1587
- // Fall thru to the default handling of RELOP
1588
-
1589
- default:
1590
- Node pn = memberExpr(true);
1591
-
1592
- // Don't look across a newline boundary for a postfix incop.
1593
- tt = peekTokenOrEOL();
1594
- if (tt == Token.INC || tt == Token.DEC) {
1595
- consumeToken();
1596
- decompiler.addToken(tt);
1597
- return nf.createIncDec(tt, true, pn);
1598
- }
1599
- return pn;
1600
- }
1601
- return nf.createName("err"); // Only reached on error. Try to continue.
1602
-
1603
- }
1604
-
1605
- private Node xmlInitializer() throws IOException
1606
- {
1607
- int tt = ts.getFirstXMLToken();
1608
- if (tt != Token.XML && tt != Token.XMLEND) {
1609
- reportError("msg.syntax");
1610
- return null;
1611
- }
1612
-
1613
- /* Make a NEW node to append to. */
1614
- Node pnXML = nf.createLeaf(Token.NEW);
1615
-
1616
- String xml = ts.getString();
1617
- boolean fAnonymous = xml.trim().startsWith("<>");
1618
-
1619
- Node pn = nf.createName(fAnonymous ? "XMLList" : "XML");
1620
- nf.addChildToBack(pnXML, pn);
1621
-
1622
- pn = null;
1623
- Node expr;
1624
- for (;;tt = ts.getNextXMLToken()) {
1625
- switch (tt) {
1626
- case Token.XML:
1627
- xml = ts.getString();
1628
- decompiler.addName(xml);
1629
- mustMatchToken(Token.LC, "msg.syntax");
1630
- decompiler.addToken(Token.LC);
1631
- expr = (peekToken() == Token.RC)
1632
- ? nf.createString("")
1633
- : expr(false);
1634
- mustMatchToken(Token.RC, "msg.syntax");
1635
- decompiler.addToken(Token.RC);
1636
- if (pn == null) {
1637
- pn = nf.createString(xml);
1638
- } else {
1639
- pn = nf.createBinary(Token.ADD, pn, nf.createString(xml));
1640
- }
1641
- if (ts.isXMLAttribute()) {
1642
- /* Need to put the result in double quotes */
1643
- expr = nf.createUnary(Token.ESCXMLATTR, expr);
1644
- Node prepend = nf.createBinary(Token.ADD,
1645
- nf.createString("\""),
1646
- expr);
1647
- expr = nf.createBinary(Token.ADD,
1648
- prepend,
1649
- nf.createString("\""));
1650
- } else {
1651
- expr = nf.createUnary(Token.ESCXMLTEXT, expr);
1652
- }
1653
- pn = nf.createBinary(Token.ADD, pn, expr);
1654
- break;
1655
- case Token.XMLEND:
1656
- xml = ts.getString();
1657
- decompiler.addName(xml);
1658
- if (pn == null) {
1659
- pn = nf.createString(xml);
1660
- } else {
1661
- pn = nf.createBinary(Token.ADD, pn, nf.createString(xml));
1662
- }
1663
-
1664
- nf.addChildToBack(pnXML, pn);
1665
- return pnXML;
1666
- default:
1667
- reportError("msg.syntax");
1668
- return null;
1669
- }
1670
- }
1671
- }
1672
-
1673
- private void argumentList(Node listNode)
1674
- throws IOException, ParserException
1675
- {
1676
- boolean matched;
1677
- matched = matchToken(Token.RP);
1678
- if (!matched) {
1679
- boolean first = true;
1680
- do {
1681
- if (!first)
1682
- decompiler.addToken(Token.COMMA);
1683
- first = false;
1684
- nf.addChildToBack(listNode, assignExpr(false));
1685
- } while (matchToken(Token.COMMA));
1686
-
1687
- mustMatchToken(Token.RP, "msg.no.paren.arg");
1688
- }
1689
- decompiler.addToken(Token.RP);
1690
- }
1691
-
1692
- private Node memberExpr(boolean allowCallSyntax)
1693
- throws IOException, ParserException
1694
- {
1695
- int tt;
1696
-
1697
- Node pn;
1698
-
1699
- /* Check for new expressions. */
1700
- tt = peekToken();
1701
- if (tt == Token.NEW) {
1702
- /* Eat the NEW token. */
1703
- consumeToken();
1704
- decompiler.addToken(Token.NEW);
1705
-
1706
- /* Make a NEW node to append to. */
1707
- pn = nf.createCallOrNew(Token.NEW, memberExpr(false));
1708
-
1709
- if (matchToken(Token.LP)) {
1710
- decompiler.addToken(Token.LP);
1711
- /* Add the arguments to pn, if any are supplied. */
1712
- argumentList(pn);
1713
- }
1714
-
1715
- /* XXX there's a check in the C source against
1716
- * "too many constructor arguments" - how many
1717
- * do we claim to support?
1718
- */
1719
-
1720
- /* Experimental syntax: allow an object literal to follow a new expression,
1721
- * which will mean a kind of anonymous class built with the JavaAdapter.
1722
- * the object literal will be passed as an additional argument to the constructor.
1723
- */
1724
- tt = peekToken();
1725
- if (tt == Token.LC) {
1726
- nf.addChildToBack(pn, primaryExpr());
1727
- }
1728
- } else {
1729
- pn = primaryExpr();
1730
- }
1731
-
1732
- return memberExprTail(allowCallSyntax, pn);
1733
- }
1734
-
1735
- private Node memberExprTail(boolean allowCallSyntax, Node pn)
1736
- throws IOException, ParserException
1737
- {
1738
- tailLoop:
1739
- for (;;) {
1740
- int tt = peekToken();
1741
- switch (tt) {
1742
-
1743
- case Token.DOT:
1744
- case Token.DOTDOT:
1745
- {
1746
- int memberTypeFlags;
1747
- String s;
1748
-
1749
- consumeToken();
1750
- decompiler.addToken(tt);
1751
- memberTypeFlags = 0;
1752
- if (tt == Token.DOTDOT) {
1753
- mustHaveXML();
1754
- memberTypeFlags = Node.DESCENDANTS_FLAG;
1755
- }
1756
- if (!compilerEnv.isXmlAvailable()) {
1757
- mustMatchToken(Token.NAME, "msg.no.name.after.dot");
1758
- s = ts.getString();
1759
- decompiler.addName(s);
1760
- pn = nf.createPropertyGet(pn, null, s, memberTypeFlags);
1761
- break;
1762
- }
1763
-
1764
- tt = nextToken();
1765
- switch (tt) {
1766
- // handles: name, ns::name, ns::*, ns::[expr]
1767
- case Token.NAME:
1768
- s = ts.getString();
1769
- decompiler.addName(s);
1770
- pn = propertyName(pn, s, memberTypeFlags);
1771
- break;
1772
-
1773
- // handles: *, *::name, *::*, *::[expr]
1774
- case Token.MUL:
1775
- decompiler.addName("*");
1776
- pn = propertyName(pn, "*", memberTypeFlags);
1777
- break;
1778
-
1779
- // handles: '@attr', '@ns::attr', '@ns::*', '@ns::*',
1780
- // '@::attr', '@::*', '@*', '@*::attr', '@*::*'
1781
- case Token.XMLATTR:
1782
- decompiler.addToken(Token.XMLATTR);
1783
- pn = attributeAccess(pn, memberTypeFlags);
1784
- break;
1785
-
1786
- default:
1787
- reportError("msg.no.name.after.dot");
1788
- }
1789
- }
1790
- break;
1791
-
1792
- case Token.DOTQUERY:
1793
- consumeToken();
1794
- mustHaveXML();
1795
- decompiler.addToken(Token.DOTQUERY);
1796
- pn = nf.createDotQuery(pn, expr(false), ts.getLineno());
1797
- mustMatchToken(Token.RP, "msg.no.paren");
1798
- decompiler.addToken(Token.RP);
1799
- break;
1800
-
1801
- case Token.LB:
1802
- consumeToken();
1803
- decompiler.addToken(Token.LB);
1804
- pn = nf.createElementGet(pn, null, expr(false), 0);
1805
- mustMatchToken(Token.RB, "msg.no.bracket.index");
1806
- decompiler.addToken(Token.RB);
1807
- break;
1808
-
1809
- case Token.LP:
1810
- if (!allowCallSyntax) {
1811
- break tailLoop;
1812
- }
1813
- consumeToken();
1814
- decompiler.addToken(Token.LP);
1815
- pn = nf.createCallOrNew(Token.CALL, pn);
1816
- /* Add the arguments to pn, if any are supplied. */
1817
- argumentList(pn);
1818
- break;
1819
-
1820
- default:
1821
- break tailLoop;
1822
- }
1823
- }
1824
- return pn;
1825
- }
1826
-
1827
- /*
1828
- * Xml attribute expression:
1829
- * '@attr', '@ns::attr', '@ns::*', '@ns::*', '@*', '@*::attr', '@*::*'
1830
- */
1831
- private Node attributeAccess(Node pn, int memberTypeFlags)
1832
- throws IOException
1833
- {
1834
- memberTypeFlags |= Node.ATTRIBUTE_FLAG;
1835
- int tt = nextToken();
1836
-
1837
- switch (tt) {
1838
- // handles: @name, @ns::name, @ns::*, @ns::[expr]
1839
- case Token.NAME:
1840
- {
1841
- String s = ts.getString();
1842
- decompiler.addName(s);
1843
- pn = propertyName(pn, s, memberTypeFlags);
1844
- }
1845
- break;
1846
-
1847
- // handles: @*, @*::name, @*::*, @*::[expr]
1848
- case Token.MUL:
1849
- decompiler.addName("*");
1850
- pn = propertyName(pn, "*", memberTypeFlags);
1851
- break;
1852
-
1853
- // handles @[expr]
1854
- case Token.LB:
1855
- decompiler.addToken(Token.LB);
1856
- pn = nf.createElementGet(pn, null, expr(false), memberTypeFlags);
1857
- mustMatchToken(Token.RB, "msg.no.bracket.index");
1858
- decompiler.addToken(Token.RB);
1859
- break;
1860
-
1861
- default:
1862
- reportError("msg.no.name.after.xmlAttr");
1863
- pn = nf.createPropertyGet(pn, null, "?", memberTypeFlags);
1864
- break;
1865
- }
1866
-
1867
- return pn;
1868
- }
1869
-
1870
- /**
1871
- * Check if :: follows name in which case it becomes qualified name
1872
- */
1873
- private Node propertyName(Node pn, String name, int memberTypeFlags)
1874
- throws IOException, ParserException
1875
- {
1876
- String namespace = null;
1877
- if (matchToken(Token.COLONCOLON)) {
1878
- decompiler.addToken(Token.COLONCOLON);
1879
- namespace = name;
1880
-
1881
- int tt = nextToken();
1882
- switch (tt) {
1883
- // handles name::name
1884
- case Token.NAME:
1885
- name = ts.getString();
1886
- decompiler.addName(name);
1887
- break;
1888
-
1889
- // handles name::*
1890
- case Token.MUL:
1891
- decompiler.addName("*");
1892
- name = "*";
1893
- break;
1894
-
1895
- // handles name::[expr]
1896
- case Token.LB:
1897
- decompiler.addToken(Token.LB);
1898
- pn = nf.createElementGet(pn, namespace, expr(false),
1899
- memberTypeFlags);
1900
- mustMatchToken(Token.RB, "msg.no.bracket.index");
1901
- decompiler.addToken(Token.RB);
1902
- return pn;
1903
-
1904
- default:
1905
- reportError("msg.no.name.after.coloncolon");
1906
- name = "?";
1907
- }
1908
- }
1909
-
1910
- pn = nf.createPropertyGet(pn, namespace, name, memberTypeFlags);
1911
- return pn;
1912
- }
1913
-
1914
- private Node primaryExpr()
1915
- throws IOException, ParserException
1916
- {
1917
- Node pn;
1918
-
1919
- int ttFlagged = nextFlaggedToken();
1920
- int tt = ttFlagged & CLEAR_TI_MASK;
1921
-
1922
- switch(tt) {
1923
-
1924
- case Token.FUNCTION:
1925
- return function(FunctionNode.FUNCTION_EXPRESSION);
1926
-
1927
- case Token.LB: {
1928
- ObjArray elems = new ObjArray();
1929
- int skipCount = 0;
1930
- decompiler.addToken(Token.LB);
1931
- boolean after_lb_or_comma = true;
1932
- for (;;) {
1933
- tt = peekToken();
1934
-
1935
- if (tt == Token.COMMA) {
1936
- consumeToken();
1937
- decompiler.addToken(Token.COMMA);
1938
- if (!after_lb_or_comma) {
1939
- after_lb_or_comma = true;
1940
- } else {
1941
- elems.add(null);
1942
- ++skipCount;
1943
- }
1944
- } else if (tt == Token.RB) {
1945
- consumeToken();
1946
- decompiler.addToken(Token.RB);
1947
- break;
1948
- } else {
1949
- if (!after_lb_or_comma) {
1950
- reportError("msg.no.bracket.arg");
1951
- }
1952
- elems.add(assignExpr(false));
1953
- after_lb_or_comma = false;
1954
- }
1955
- }
1956
- return nf.createArrayLiteral(elems, skipCount);
1957
- }
1958
-
1959
- case Token.LC: {
1960
- ObjArray elems = new ObjArray();
1961
- decompiler.addToken(Token.LC);
1962
- if (!matchToken(Token.RC)) {
1963
-
1964
- boolean first = true;
1965
- commaloop:
1966
- do {
1967
- Object property;
1968
-
1969
- if (!first)
1970
- decompiler.addToken(Token.COMMA);
1971
- else
1972
- first = false;
1973
-
1974
- tt = peekToken();
1975
- switch(tt) {
1976
- case Token.NAME:
1977
- case Token.STRING:
1978
- consumeToken();
1979
- // map NAMEs to STRINGs in object literal context
1980
- // but tell the decompiler the proper type
1981
- String s = ts.getString();
1982
- if (tt == Token.NAME) {
1983
- if (s.equals("get") &&
1984
- peekToken() == Token.NAME) {
1985
- decompiler.addToken(Token.GET);
1986
- consumeToken();
1987
- s = ts.getString();
1988
- decompiler.addName(s);
1989
- property = ScriptRuntime.getIndexObject(s);
1990
- if (!getterSetterProperty(elems, property,
1991
- true))
1992
- break commaloop;
1993
- break;
1994
- } else if (s.equals("set") &&
1995
- peekToken() == Token.NAME) {
1996
- decompiler.addToken(Token.SET);
1997
- consumeToken();
1998
- s = ts.getString();
1999
- decompiler.addName(s);
2000
- property = ScriptRuntime.getIndexObject(s);
2001
- if (!getterSetterProperty(elems, property,
2002
- false))
2003
- break commaloop;
2004
- break;
2005
- }
2006
- decompiler.addName(s);
2007
- } else {
2008
- decompiler.addString(s);
2009
- }
2010
- property = ScriptRuntime.getIndexObject(s);
2011
- plainProperty(elems, property);
2012
- break;
2013
-
2014
- case Token.NUMBER:
2015
- consumeToken();
2016
- double n = ts.getNumber();
2017
- decompiler.addNumber(n);
2018
- property = ScriptRuntime.getIndexObject(n);
2019
- plainProperty(elems, property);
2020
- break;
2021
-
2022
- case Token.RC:
2023
- // trailing comma is OK.
2024
- break commaloop;
2025
- default:
2026
- reportError("msg.bad.prop");
2027
- break commaloop;
2028
- }
2029
- } while (matchToken(Token.COMMA));
2030
-
2031
- mustMatchToken(Token.RC, "msg.no.brace.prop");
2032
- }
2033
- decompiler.addToken(Token.RC);
2034
- return nf.createObjectLiteral(elems);
2035
- }
2036
-
2037
- case Token.LP:
2038
-
2039
- /* Brendan's IR-jsparse.c makes a new node tagged with
2040
- * TOK_LP here... I'm not sure I understand why. Isn't
2041
- * the grouping already implicit in the structure of the
2042
- * parse tree? also TOK_LP is already overloaded (I
2043
- * think) in the C IR as 'function call.' */
2044
- decompiler.addToken(Token.LP);
2045
- pn = expr(false);
2046
- pn.putProp(Node.PARENTHESIZED_PROP, Boolean.TRUE);
2047
- decompiler.addToken(Token.RP);
2048
- mustMatchToken(Token.RP, "msg.no.paren");
2049
- return pn;
2050
-
2051
- case Token.XMLATTR:
2052
- mustHaveXML();
2053
- decompiler.addToken(Token.XMLATTR);
2054
- pn = attributeAccess(null, 0);
2055
- return pn;
2056
-
2057
- case Token.NAME: {
2058
- String name = ts.getString();
2059
- if ((ttFlagged & TI_CHECK_LABEL) != 0) {
2060
- if (peekToken() == Token.COLON) {
2061
- // Do not consume colon, it is used as unwind indicator
2062
- // to return to statementHelper.
2063
- // XXX Better way?
2064
- return nf.createLabel(ts.getLineno());
2065
- }
2066
- }
2067
-
2068
- decompiler.addName(name);
2069
- if (compilerEnv.isXmlAvailable()) {
2070
- pn = propertyName(null, name, 0);
2071
- } else {
2072
- pn = nf.createName(name);
2073
- }
2074
- return pn;
2075
- }
2076
-
2077
- case Token.NUMBER: {
2078
- double n = ts.getNumber();
2079
- decompiler.addNumber(n);
2080
- return nf.createNumber(n);
2081
- }
2082
-
2083
- case Token.STRING: {
2084
- String s = ts.getString();
2085
- decompiler.addString(s);
2086
- return nf.createString(s);
2087
- }
2088
-
2089
- case Token.DIV:
2090
- case Token.ASSIGN_DIV: {
2091
- // Got / or /= which should be treated as regexp in fact
2092
- ts.readRegExp(tt);
2093
- String flags = ts.regExpFlags;
2094
- ts.regExpFlags = null;
2095
- String re = ts.getString();
2096
- decompiler.addRegexp(re, flags);
2097
- int index = currentScriptOrFn.addRegexp(re, flags);
2098
- return nf.createRegExp(index);
2099
- }
2100
-
2101
- case Token.NULL:
2102
- case Token.THIS:
2103
- case Token.FALSE:
2104
- case Token.TRUE:
2105
- decompiler.addToken(tt);
2106
- return nf.createLeaf(tt);
2107
-
2108
- case Token.RESERVED:
2109
- reportError("msg.reserved.id");
2110
- break;
2111
-
2112
- case Token.ERROR:
2113
- /* the scanner or one of its subroutines reported the error. */
2114
- break;
2115
-
2116
- case Token.EOF:
2117
- reportError("msg.unexpected.eof");
2118
- break;
2119
-
2120
- default:
2121
- reportError("msg.syntax");
2122
- break;
2123
- }
2124
- return null; // should never reach here
2125
- }
2126
-
2127
- private void plainProperty(ObjArray elems, Object property)
2128
- throws IOException {
2129
- mustMatchToken(Token.COLON, "msg.no.colon.prop");
2130
-
2131
- // OBJLIT is used as ':' in object literal for
2132
- // decompilation to solve spacing ambiguity.
2133
- decompiler.addToken(Token.OBJECTLIT);
2134
- elems.add(property);
2135
- elems.add(assignExpr(false));
2136
- }
2137
-
2138
- private boolean getterSetterProperty(ObjArray elems, Object property,
2139
- boolean isGetter) throws IOException {
2140
- Node f = function(FunctionNode.FUNCTION_EXPRESSION);
2141
- if (f.getType() != Token.FUNCTION) {
2142
- reportError("msg.bad.prop");
2143
- return false;
2144
- }
2145
- int fnIndex = f.getExistingIntProp(Node.FUNCTION_PROP);
2146
- FunctionNode fn = currentScriptOrFn.getFunctionNode(fnIndex);
2147
- if (fn.getFunctionName().length() != 0) {
2148
- reportError("msg.bad.prop");
2149
- return false;
2150
- }
2151
- elems.add(property);
2152
- if (isGetter) {
2153
- elems.add(nf.createUnary(Token.GET, f));
2154
- } else {
2155
- elems.add(nf.createUnary(Token.SET, f));
2156
- }
2157
- return true;
2158
- }
2159
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
lib/Diglin/yuicompressor-2.4.6/src/org/mozilla/javascript/Token.java DELETED
@@ -1,406 +0,0 @@
1
- /* ***** BEGIN LICENSE BLOCK *****
2
- *
3
- * Version: MPL 1.1
4
- *
5
- * The contents of this file are subject to the Mozilla Public License
6
- * Version 1.1 (the "License"); you may not use this file except in
7
- * compliance with the License. You may obtain a copy of the License
8
- * at http://www.mozilla.org/MPL/
9
- *
10
- * Software distributed under the License is distributed on an "AS IS"
11
- * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.
12
- * See the License for the specific language governing rights and
13
- * limitations under the License.
14
- *
15
- * The Original Code is org/mozilla/javascript/Token.java,
16
- * a component of the Rhino Library ( http://www.mozilla.org/rhino/ )
17
- * This file is a modification of the Original Code developed
18
- * for YUI Compressor.
19
- *
20
- * The Initial Developer of the Original Code is Mozilla Foundation
21
- *
22
- * Copyright (c) 2009 Mozilla Foundation. All Rights Reserved.
23
- *
24
- * Contributor(s): Yahoo! Inc. 2009
25
- *
26
- * ***** END LICENSE BLOCK ***** */
27
-
28
- package org.mozilla.javascript;
29
-
30
- /**
31
- * This class implements the JavaScript scanner.
32
- *
33
- * It is based on the C source files jsscan.c and jsscan.h
34
- * in the jsref package.
35
- *
36
- * @see org.mozilla.javascript.Parser
37
- *
38
- * @author Mike McCabe
39
- * @author Brendan Eich
40
- */
41
-
42
- public class Token
43
- {
44
-
45
- // debug flags
46
- public static final boolean printTrees = false;
47
- static final boolean printICode = false;
48
- static final boolean printNames = printTrees || printICode;
49
-
50
- /**
51
- * Token types. These values correspond to JSTokenType values in
52
- * jsscan.c.
53
- */
54
-
55
- public final static int
56
- // start enum
57
- ERROR = -1, // well-known as the only code < EOF
58
- EOF = 0, // end of file token - (not EOF_CHAR)
59
- EOL = 1, // end of line
60
-
61
- // Interpreter reuses the following as bytecodes
62
- FIRST_BYTECODE_TOKEN = 2,
63
-
64
- ENTERWITH = 2,
65
- LEAVEWITH = 3,
66
- RETURN = 4,
67
- GOTO = 5,
68
- IFEQ = 6,
69
- IFNE = 7,
70
- SETNAME = 8,
71
- BITOR = 9,
72
- BITXOR = 10,
73
- BITAND = 11,
74
- EQ = 12,
75
- NE = 13,
76
- LT = 14,
77
- LE = 15,
78
- GT = 16,
79
- GE = 17,
80
- LSH = 18,
81
- RSH = 19,
82
- URSH = 20,
83
- ADD = 21,
84
- SUB = 22,
85
- MUL = 23,
86
- DIV = 24,
87
- MOD = 25,
88
- NOT = 26,
89
- BITNOT = 27,
90
- POS = 28,
91
- NEG = 29,
92
- NEW = 30,
93
- DELPROP = 31,
94
- TYPEOF = 32,
95
- GETPROP = 33,
96
- SETPROP = 34,
97
- GETELEM = 35,
98
- SETELEM = 36,
99
- CALL = 37,
100
- NAME = 38,
101
- NUMBER = 39,
102
- STRING = 40,
103
- NULL = 41,
104
- THIS = 42,
105
- FALSE = 43,
106
- TRUE = 44,
107
- SHEQ = 45, // shallow equality (===)
108
- SHNE = 46, // shallow inequality (!==)
109
- REGEXP = 47,
110
- BINDNAME = 48,
111
- THROW = 49,
112
- RETHROW = 50, // rethrow caught execetion: catch (e if ) use it
113
- IN = 51,
114
- INSTANCEOF = 52,
115
- LOCAL_LOAD = 53,
116
- GETVAR = 54,
117
- SETVAR = 55,
118
- CATCH_SCOPE = 56,
119
- ENUM_INIT_KEYS = 57,
120
- ENUM_INIT_VALUES = 58,
121
- ENUM_NEXT = 59,
122
- ENUM_ID = 60,
123
- THISFN = 61,
124
- RETURN_RESULT = 62, // to return prevoisly stored return result
125
- ARRAYLIT = 63, // array literal
126
- OBJECTLIT = 64, // object literal
127
- GET_REF = 65, // *reference
128
- SET_REF = 66, // *reference = something
129
- DEL_REF = 67, // delete reference
130
- REF_CALL = 68, // f(args) = something or f(args)++
131
- REF_SPECIAL = 69, // reference for special properties like __proto
132
-
133
- // For XML support:
134
- DEFAULTNAMESPACE = 70, // default xml namespace =
135
- ESCXMLATTR = 71,
136
- ESCXMLTEXT = 72,
137
- REF_MEMBER = 73, // Reference for x.@y, x..y etc.
138
- REF_NS_MEMBER = 74, // Reference for x.ns::y, x..ns::y etc.
139
- REF_NAME = 75, // Reference for @y, @[y] etc.
140
- REF_NS_NAME = 76; // Reference for ns::y, @ns::y@[y] etc.
141
-
142
- // End of interpreter bytecodes
143
- public final static int
144
- LAST_BYTECODE_TOKEN = REF_NS_NAME,
145
-
146
- TRY = 77,
147
- SEMI = 78, // semicolon
148
- LB = 79, // left and right brackets
149
- RB = 80,
150
- LC = 81, // left and right curlies (braces)
151
- RC = 82,
152
- LP = 83, // left and right parentheses
153
- RP = 84,
154
- COMMA = 85, // comma operator
155
-
156
- ASSIGN = 86, // simple assignment (=)
157
- ASSIGN_BITOR = 87, // |=
158
- ASSIGN_BITXOR = 88, // ^=
159
- ASSIGN_BITAND = 89, // |=
160
- ASSIGN_LSH = 90, // <<=
161
- ASSIGN_RSH = 91, // >>=
162
- ASSIGN_URSH = 92, // >>>=
163
- ASSIGN_ADD = 93, // +=
164
- ASSIGN_SUB = 94, // -=
165
- ASSIGN_MUL = 95, // *=
166
- ASSIGN_DIV = 96, // /=
167
- ASSIGN_MOD = 97; // %=
168
-
169
- public final static int
170
- FIRST_ASSIGN = ASSIGN,
171
- LAST_ASSIGN = ASSIGN_MOD,
172
-
173
- HOOK = 98, // conditional (?:)
174
- COLON = 99,
175
- OR = 100, // logical or (||)
176
- AND = 101, // logical and (&&)
177
- INC = 102, // increment/decrement (++ --)
178
- DEC = 103,
179
- DOT = 104, // member operator (.)
180
- FUNCTION = 105, // function keyword
181
- EXPORT = 106, // export keyword
182
- IMPORT = 107, // import keyword
183
- IF = 108, // if keyword
184
- ELSE = 109, // else keyword
185
- SWITCH = 110, // switch keyword
186
- CASE = 111, // case keyword
187
- DEFAULT = 112, // default keyword
188
- WHILE = 113, // while keyword
189
- DO = 114, // do keyword
190
- FOR = 115, // for keyword
191
- BREAK = 116, // break keyword
192
- CONTINUE = 117, // continue keyword
193
- VAR = 118, // var keyword
194
- WITH = 119, // with keyword
195
- CATCH = 120, // catch keyword
196
- FINALLY = 121, // finally keyword
197
- VOID = 122, // void keyword
198
- RESERVED = 123, // reserved keywords
199
-
200
- EMPTY = 124,
201
-
202
- /* types used for the parse tree - these never get returned
203
- * by the scanner.
204
- */
205
-
206
- BLOCK = 125, // statement block
207
- LABEL = 126, // label
208
- TARGET = 127,
209
- LOOP = 128,
210
- EXPR_VOID = 129, // expression statement in functions
211
- EXPR_RESULT = 130, // expression statement in scripts
212
- JSR = 131,
213
- SCRIPT = 132, // top-level node for entire script
214
- TYPEOFNAME = 133, // for typeof(simple-name)
215
- USE_STACK = 134,
216
- SETPROP_OP = 135, // x.y op= something
217
- SETELEM_OP = 136, // x[y] op= something
218
- LOCAL_BLOCK = 137,
219
- SET_REF_OP = 138, // *reference op= something
220
-
221
- // For XML support:
222
- DOTDOT = 139, // member operator (..)
223
- COLONCOLON = 140, // namespace::name
224
- XML = 141, // XML type
225
- DOTQUERY = 142, // .() -- e.g., x.emps.emp.(name == "terry")
226
- XMLATTR = 143, // @
227
- XMLEND = 144,
228
-
229
- // Optimizer-only-tokens
230
- TO_OBJECT = 145,
231
- TO_DOUBLE = 146,
232
-
233
- GET = 147, // JS 1.5 get pseudo keyword
234
- SET = 148, // JS 1.5 set pseudo keyword
235
- CONST = 149,
236
- SETCONST = 150,
237
- SETCONSTVAR = 151,
238
-
239
- CONDCOMMENT = 152, // JScript conditional comment
240
- KEEPCOMMENT = 153, // /*! ... */ comment
241
-
242
- LAST_TOKEN = 154;
243
-
244
- public static String name(int token)
245
- {
246
- if (!printNames) {
247
- return String.valueOf(token);
248
- }
249
- switch (token) {
250
- case ERROR: return "ERROR";
251
- case EOF: return "EOF";
252
- case EOL: return "EOL";
253
- case ENTERWITH: return "ENTERWITH";
254
- case LEAVEWITH: return "LEAVEWITH";
255
- case RETURN: return "RETURN";
256
- case GOTO: return "GOTO";
257
- case IFEQ: return "IFEQ";
258
- case IFNE: return "IFNE";
259
- case SETNAME: return "SETNAME";
260
- case BITOR: return "BITOR";
261
- case BITXOR: return "BITXOR";
262
- case BITAND: return "BITAND";
263
- case EQ: return "EQ";
264
- case NE: return "NE";
265
- case LT: return "LT";
266
- case LE: return "LE";
267
- case GT: return "GT";
268
- case GE: return "GE";
269
- case LSH: return "LSH";
270
- case RSH: return "RSH";
271
- case URSH: return "URSH";
272
- case ADD: return "ADD";
273
- case SUB: return "SUB";
274
- case MUL: return "MUL";
275
- case DIV: return "DIV";
276
- case MOD: return "MOD";
277
- case NOT: return "NOT";
278
- case BITNOT: return "BITNOT";
279
- case POS: return "POS";
280
- case NEG: return "NEG";
281
- case NEW: return "NEW";
282
- case DELPROP: return "DELPROP";
283
- case TYPEOF: return "TYPEOF";
284
- case GETPROP: return "GETPROP";
285
- case SETPROP: return "SETPROP";
286
- case GETELEM: return "GETELEM";
287
- case SETELEM: return "SETELEM";
288
- case CALL: return "CALL";
289
- case NAME: return "NAME";
290
- case NUMBER: return "NUMBER";
291
- case STRING: return "STRING";
292
- case NULL: return "NULL";
293
- case THIS: return "THIS";
294
- case FALSE: return "FALSE";
295
- case TRUE: return "TRUE";
296
- case SHEQ: return "SHEQ";
297
- case SHNE: return "SHNE";
298
- case REGEXP: return "OBJECT";
299
- case BINDNAME: return "BINDNAME";
300
- case THROW: return "THROW";
301
- case RETHROW: return "RETHROW";
302
- case IN: return "IN";
303
- case INSTANCEOF: return "INSTANCEOF";
304
- case LOCAL_LOAD: return "LOCAL_LOAD";
305
- case GETVAR: return "GETVAR";
306
- case SETVAR: return "SETVAR";
307
- case CATCH_SCOPE: return "CATCH_SCOPE";
308
- case ENUM_INIT_KEYS: return "ENUM_INIT_KEYS";
309
- case ENUM_INIT_VALUES: return "ENUM_INIT_VALUES";
310
- case ENUM_NEXT: return "ENUM_NEXT";
311
- case ENUM_ID: return "ENUM_ID";
312
- case THISFN: return "THISFN";
313
- case RETURN_RESULT: return "RETURN_RESULT";
314
- case ARRAYLIT: return "ARRAYLIT";
315
- case OBJECTLIT: return "OBJECTLIT";
316
- case GET_REF: return "GET_REF";
317
- case SET_REF: return "SET_REF";
318
- case DEL_REF: return "DEL_REF";
319
- case REF_CALL: return "REF_CALL";
320
- case REF_SPECIAL: return "REF_SPECIAL";
321
- case DEFAULTNAMESPACE:return "DEFAULTNAMESPACE";
322
- case ESCXMLTEXT: return "ESCXMLTEXT";
323
- case ESCXMLATTR: return "ESCXMLATTR";
324
- case REF_MEMBER: return "REF_MEMBER";
325
- case REF_NS_MEMBER: return "REF_NS_MEMBER";
326
- case REF_NAME: return "REF_NAME";
327
- case REF_NS_NAME: return "REF_NS_NAME";
328
- case TRY: return "TRY";
329
- case SEMI: return "SEMI";
330
- case LB: return "LB";
331
- case RB: return "RB";
332
- case LC: return "LC";
333
- case RC: return "RC";
334
- case LP: return "LP";
335
- case RP: return "RP";
336
- case COMMA: return "COMMA";
337
- case ASSIGN: return "ASSIGN";
338
- case ASSIGN_BITOR: return "ASSIGN_BITOR";
339
- case ASSIGN_BITXOR: return "ASSIGN_BITXOR";
340
- case ASSIGN_BITAND: return "ASSIGN_BITAND";
341
- case ASSIGN_LSH: return "ASSIGN_LSH";
342
- case ASSIGN_RSH: return "ASSIGN_RSH";
343
- case ASSIGN_URSH: return "ASSIGN_URSH";
344
- case ASSIGN_ADD: return "ASSIGN_ADD";
345
- case ASSIGN_SUB: return "ASSIGN_SUB";
346
- case ASSIGN_MUL: return "ASSIGN_MUL";
347
- case ASSIGN_DIV: return "ASSIGN_DIV";
348
- case ASSIGN_MOD: return "ASSIGN_MOD";
349
- case HOOK: return "HOOK";
350
- case COLON: return "COLON";
351
- case OR: return "OR";
352
- case AND: return "AND";
353
- case INC: return "INC";
354
- case DEC: return "DEC";
355
- case DOT: return "DOT";
356
- case FUNCTION: return "FUNCTION";
357
- case EXPORT: return "EXPORT";
358
- case IMPORT: return "IMPORT";
359
- case IF: return "IF";
360
- case ELSE: return "ELSE";
361
- case SWITCH: return "SWITCH";
362
- case CASE: return "CASE";
363
- case DEFAULT: return "DEFAULT";
364
- case WHILE: return "WHILE";
365
- case DO: return "DO";
366
- case FOR: return "FOR";
367
- case BREAK: return "BREAK";
368
- case CONTINUE: return "CONTINUE";
369
- case VAR: return "VAR";
370
- case WITH: return "WITH";
371
- case CATCH: return "CATCH";
372
- case FINALLY: return "FINALLY";
373
- case RESERVED: return "RESERVED";
374
- case EMPTY: return "EMPTY";
375
- case BLOCK: return "BLOCK";
376
- case LABEL: return "LABEL";
377
- case TARGET: return "TARGET";
378
- case LOOP: return "LOOP";
379
- case EXPR_VOID: return "EXPR_VOID";
380
- case EXPR_RESULT: return "EXPR_RESULT";
381
- case JSR: return "JSR";
382
- case SCRIPT: return "SCRIPT";
383
- case TYPEOFNAME: return "TYPEOFNAME";
384
- case USE_STACK: return "USE_STACK";
385
- case SETPROP_OP: return "SETPROP_OP";
386
- case SETELEM_OP: return "SETELEM_OP";
387
- case LOCAL_BLOCK: return "LOCAL_BLOCK";
388
- case SET_REF_OP: return "SET_REF_OP";
389
- case DOTDOT: return "DOTDOT";
390
- case COLONCOLON: return "COLONCOLON";
391
- case XML: return "XML";
392
- case DOTQUERY: return "DOTQUERY";
393
- case XMLATTR: return "XMLATTR";
394
- case XMLEND: return "XMLEND";
395
- case TO_OBJECT: return "TO_OBJECT";
396
- case TO_DOUBLE: return "TO_DOUBLE";
397
- case GET: return "GET";
398
- case SET: return "SET";
399
- case CONST: return "CONST";
400
- case SETCONST: return "SETCONST";
401
- }
402
-
403
- // Token without name
404
- throw new IllegalStateException(String.valueOf(token));
405
- }
406
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
lib/Diglin/yuicompressor-2.4.6/src/org/mozilla/javascript/Token.java.orig DELETED
@@ -1,417 +0,0 @@
1
- /* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2
- *
3
- * ***** BEGIN LICENSE BLOCK *****
4
- * Version: MPL 1.1/GPL 2.0
5
- *
6
- * The contents of this file are subject to the Mozilla Public License Version
7
- * 1.1 (the "License"); you may not use this file except in compliance with
8
- * the License. You may obtain a copy of the License at
9
- * http://www.mozilla.org/MPL/
10
- *
11
- * Software distributed under the License is distributed on an "AS IS" basis,
12
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13
- * for the specific language governing rights and limitations under the
14
- * License.
15
- *
16
- * The Original Code is Rhino code, released
17
- * May 6, 1999.
18
- *
19
- * The Initial Developer of the Original Code is
20
- * Netscape Communications Corporation.
21
- * Portions created by the Initial Developer are Copyright (C) 1997-1999
22
- * the Initial Developer. All Rights Reserved.
23
- *
24
- * Contributor(s):
25
- * Roger Lawrence
26
- * Mike McCabe
27
- * Igor Bukanov
28
- * Bob Jervis
29
- * Milen Nankov
30
- *
31
- * Alternatively, the contents of this file may be used under the terms of
32
- * the GNU General Public License Version 2 or later (the "GPL"), in which
33
- * case the provisions of the GPL are applicable instead of those above. If
34
- * you wish to allow use of your version of this file only under the terms of
35
- * the GPL and not to allow others to use your version of this file under the
36
- * MPL, indicate your decision by deleting the provisions above and replacing
37
- * them with the notice and other provisions required by the GPL. If you do
38
- * not delete the provisions above, a recipient may use your version of this
39
- * file under either the MPL or the GPL.
40
- *
41
- * ***** END LICENSE BLOCK ***** */
42
-
43
- package org.mozilla.javascript;
44
-
45
- /**
46
- * This class implements the JavaScript scanner.
47
- *
48
- * It is based on the C source files jsscan.c and jsscan.h
49
- * in the jsref package.
50
- *
51
- * @see org.mozilla.javascript.Parser
52
- *
53
- * @author Mike McCabe
54
- * @author Brendan Eich
55
- */
56
-
57
- public class Token
58
- {
59
-
60
- // debug flags
61
- public static final boolean printTrees = false;
62
- static final boolean printICode = false;
63
- static final boolean printNames = printTrees || printICode;
64
-
65
- /**
66
- * Token types. These values correspond to JSTokenType values in
67
- * jsscan.c.
68
- */
69
-
70
- public final static int
71
- // start enum
72
- ERROR = -1, // well-known as the only code < EOF
73
- EOF = 0, // end of file token - (not EOF_CHAR)
74
- EOL = 1, // end of line
75
-
76
- // Interpreter reuses the following as bytecodes
77
- FIRST_BYTECODE_TOKEN = 2,
78
-
79
- ENTERWITH = 2,
80
- LEAVEWITH = 3,
81
- RETURN = 4,
82
- GOTO = 5,
83
- IFEQ = 6,
84
- IFNE = 7,
85
- SETNAME = 8,
86
- BITOR = 9,
87
- BITXOR = 10,
88
- BITAND = 11,
89
- EQ = 12,
90
- NE = 13,
91
- LT = 14,
92
- LE = 15,
93
- GT = 16,
94
- GE = 17,
95
- LSH = 18,
96
- RSH = 19,
97
- URSH = 20,
98
- ADD = 21,
99
- SUB = 22,
100
- MUL = 23,
101
- DIV = 24,
102
- MOD = 25,
103
- NOT = 26,
104
- BITNOT = 27,
105
- POS = 28,
106
- NEG = 29,
107
- NEW = 30,
108
- DELPROP = 31,
109
- TYPEOF = 32,
110
- GETPROP = 33,
111
- SETPROP = 34,
112
- GETELEM = 35,
113
- SETELEM = 36,
114
- CALL = 37,
115
- NAME = 38,
116
- NUMBER = 39,
117
- STRING = 40,
118
- NULL = 41,
119
- THIS = 42,
120
- FALSE = 43,
121
- TRUE = 44,
122
- SHEQ = 45, // shallow equality (===)
123
- SHNE = 46, // shallow inequality (!==)
124
- REGEXP = 47,
125
- BINDNAME = 48,
126
- THROW = 49,
127
- RETHROW = 50, // rethrow caught execetion: catch (e if ) use it
128
- IN = 51,
129
- INSTANCEOF = 52,
130
- LOCAL_LOAD = 53,
131
- GETVAR = 54,
132
- SETVAR = 55,
133
- CATCH_SCOPE = 56,
134
- ENUM_INIT_KEYS = 57,
135
- ENUM_INIT_VALUES = 58,
136
- ENUM_NEXT = 59,
137
- ENUM_ID = 60,
138
- THISFN = 61,
139
- RETURN_RESULT = 62, // to return prevoisly stored return result
140
- ARRAYLIT = 63, // array literal
141
- OBJECTLIT = 64, // object literal
142
- GET_REF = 65, // *reference
143
- SET_REF = 66, // *reference = something
144
- DEL_REF = 67, // delete reference
145
- REF_CALL = 68, // f(args) = something or f(args)++
146
- REF_SPECIAL = 69, // reference for special properties like __proto
147
-
148
- // For XML support:
149
- DEFAULTNAMESPACE = 70, // default xml namespace =
150
- ESCXMLATTR = 71,
151
- ESCXMLTEXT = 72,
152
- REF_MEMBER = 73, // Reference for x.@y, x..y etc.
153
- REF_NS_MEMBER = 74, // Reference for x.ns::y, x..ns::y etc.
154
- REF_NAME = 75, // Reference for @y, @[y] etc.
155
- REF_NS_NAME = 76; // Reference for ns::y, @ns::y@[y] etc.
156
-
157
- // End of interpreter bytecodes
158
- public final static int
159
- LAST_BYTECODE_TOKEN = REF_NS_NAME,
160
-
161
- TRY = 77,
162
- SEMI = 78, // semicolon
163
- LB = 79, // left and right brackets
164
- RB = 80,
165
- LC = 81, // left and right curlies (braces)
166
- RC = 82,
167
- LP = 83, // left and right parentheses
168
- RP = 84,
169
- COMMA = 85, // comma operator
170
-
171
- ASSIGN = 86, // simple assignment (=)
172
- ASSIGN_BITOR = 87, // |=
173
- ASSIGN_BITXOR = 88, // ^=
174
- ASSIGN_BITAND = 89, // |=
175
- ASSIGN_LSH = 90, // <<=
176
- ASSIGN_RSH = 91, // >>=
177
- ASSIGN_URSH = 92, // >>>=
178
- ASSIGN_ADD = 93, // +=
179
- ASSIGN_SUB = 94, // -=
180
- ASSIGN_MUL = 95, // *=
181
- ASSIGN_DIV = 96, // /=
182
- ASSIGN_MOD = 97; // %=
183
-
184
- public final static int
185
- FIRST_ASSIGN = ASSIGN,
186
- LAST_ASSIGN = ASSIGN_MOD,
187
-
188
- HOOK = 98, // conditional (?:)
189
- COLON = 99,
190
- OR = 100, // logical or (||)
191
- AND = 101, // logical and (&&)
192
- INC = 102, // increment/decrement (++ --)
193
- DEC = 103,
194
- DOT = 104, // member operator (.)
195
- FUNCTION = 105, // function keyword
196
- EXPORT = 106, // export keyword
197
- IMPORT = 107, // import keyword
198
- IF = 108, // if keyword
199
- ELSE = 109, // else keyword
200
- SWITCH = 110, // switch keyword
201
- CASE = 111, // case keyword
202
- DEFAULT = 112, // default keyword
203
- WHILE = 113, // while keyword
204
- DO = 114, // do keyword
205
- FOR = 115, // for keyword
206
- BREAK = 116, // break keyword
207
- CONTINUE = 117, // continue keyword
208
- VAR = 118, // var keyword
209
- WITH = 119, // with keyword
210
- CATCH = 120, // catch keyword
211
- FINALLY = 121, // finally keyword
212
- VOID = 122, // void keyword
213
- RESERVED = 123, // reserved keywords
214
-
215
- EMPTY = 124,
216
-
217
- /* types used for the parse tree - these never get returned
218
- * by the scanner.
219
- */
220
-
221
- BLOCK = 125, // statement block
222
- LABEL = 126, // label
223
- TARGET = 127,
224
- LOOP = 128,
225
- EXPR_VOID = 129, // expression statement in functions
226
- EXPR_RESULT = 130, // expression statement in scripts
227
- JSR = 131,
228
- SCRIPT = 132, // top-level node for entire script
229
- TYPEOFNAME = 133, // for typeof(simple-name)
230
- USE_STACK = 134,
231
- SETPROP_OP = 135, // x.y op= something
232
- SETELEM_OP = 136, // x[y] op= something
233
- LOCAL_BLOCK = 137,
234
- SET_REF_OP = 138, // *reference op= something
235
-
236
- // For XML support:
237
- DOTDOT = 139, // member operator (..)
238
- COLONCOLON = 140, // namespace::name
239
- XML = 141, // XML type
240
- DOTQUERY = 142, // .() -- e.g., x.emps.emp.(name == "terry")
241
- XMLATTR = 143, // @
242
- XMLEND = 144,
243
-
244
- // Optimizer-only-tokens
245
- TO_OBJECT = 145,
246
- TO_DOUBLE = 146,
247
-
248
- GET = 147, // JS 1.5 get pseudo keyword
249
- SET = 148, // JS 1.5 set pseudo keyword
250
- CONST = 149,
251
- SETCONST = 150,
252
- SETCONSTVAR = 151,
253
- LAST_TOKEN = 152;
254
-
255
- public static String name(int token)
256
- {
257
- if (!printNames) {
258
- return String.valueOf(token);
259
- }
260
- switch (token) {
261
- case ERROR: return "ERROR";
262
- case EOF: return "EOF";
263
- case EOL: return "EOL";
264
- case ENTERWITH: return "ENTERWITH";
265
- case LEAVEWITH: return "LEAVEWITH";
266
- case RETURN: return "RETURN";
267
- case GOTO: return "GOTO";
268
- case IFEQ: return "IFEQ";
269
- case IFNE: return "IFNE";
270
- case SETNAME: return "SETNAME";
271
- case BITOR: return "BITOR";
272
- case BITXOR: return "BITXOR";
273
- case BITAND: return "BITAND";
274
- case EQ: return "EQ";
275
- case NE: return "NE";
276
- case LT: return "LT";
277
- case LE: return "LE";
278
- case GT: return "GT";
279
- case GE: return "GE";
280
- case LSH: return "LSH";
281
- case RSH: return "RSH";
282
- case URSH: return "URSH";
283
- case ADD: return "ADD";
284
- case SUB: return "SUB";
285
- case MUL: return "MUL";
286
- case DIV: return "DIV";
287
- case MOD: return "MOD";
288
- case NOT: return "NOT";
289
- case BITNOT: return "BITNOT";
290
- case POS: return "POS";
291
- case NEG: return "NEG";
292
- case NEW: return "NEW";
293
- case DELPROP: return "DELPROP";
294
- case TYPEOF: return "TYPEOF";
295
- case GETPROP: return "GETPROP";
296
- case SETPROP: return "SETPROP";
297
- case GETELEM: return "GETELEM";
298
- case SETELEM: return "SETELEM";
299
- case CALL: return "CALL";
300
- case NAME: return "NAME";
301
- case NUMBER: return "NUMBER";
302
- case STRING: return "STRING";
303
- case NULL: return "NULL";
304
- case THIS: return "THIS";
305
- case FALSE: return "FALSE";
306
- case TRUE: return "TRUE";
307
- case SHEQ: return "SHEQ";
308
- case SHNE: return "SHNE";
309
- case REGEXP: return "OBJECT";
310
- case BINDNAME: return "BINDNAME";
311
- case THROW: return "THROW";
312
- case RETHROW: return "RETHROW";
313
- case IN: return "IN";
314
- case INSTANCEOF: return "INSTANCEOF";
315
- case LOCAL_LOAD: return "LOCAL_LOAD";
316
- case GETVAR: return "GETVAR";
317
- case SETVAR: return "SETVAR";
318
- case CATCH_SCOPE: return "CATCH_SCOPE";
319
- case ENUM_INIT_KEYS: return "ENUM_INIT_KEYS";
320
- case ENUM_INIT_VALUES: return "ENUM_INIT_VALUES";
321
- case ENUM_NEXT: return "ENUM_NEXT";
322
- case ENUM_ID: return "ENUM_ID";
323
- case THISFN: return "THISFN";
324
- case RETURN_RESULT: return "RETURN_RESULT";
325
- case ARRAYLIT: return "ARRAYLIT";
326
- case OBJECTLIT: return "OBJECTLIT";
327
- case GET_REF: return "GET_REF";
328
- case SET_REF: return "SET_REF";
329
- case DEL_REF: return "DEL_REF";
330
- case REF_CALL: return "REF_CALL";
331
- case REF_SPECIAL: return "REF_SPECIAL";
332
- case DEFAULTNAMESPACE:return "DEFAULTNAMESPACE";
333
- case ESCXMLTEXT: return "ESCXMLTEXT";
334
- case ESCXMLATTR: return "ESCXMLATTR";
335
- case REF_MEMBER: return "REF_MEMBER";
336
- case REF_NS_MEMBER: return "REF_NS_MEMBER";
337
- case REF_NAME: return "REF_NAME";
338
- case REF_NS_NAME: return "REF_NS_NAME";
339
- case TRY: return "TRY";
340
- case SEMI: return "SEMI";
341
- case LB: return "LB";
342
- case RB: return "RB";
343
- case LC: return "LC";
344
- case RC: return "RC";
345
- case LP: return "LP";
346
- case RP: return "RP";
347
- case COMMA: return "COMMA";
348
- case ASSIGN: return "ASSIGN";
349
- case ASSIGN_BITOR: return "ASSIGN_BITOR";
350
- case ASSIGN_BITXOR: return "ASSIGN_BITXOR";
351
- case ASSIGN_BITAND: return "ASSIGN_BITAND";
352
- case ASSIGN_LSH: return "ASSIGN_LSH";
353
- case ASSIGN_RSH: return "ASSIGN_RSH";
354
- case ASSIGN_URSH: return "ASSIGN_URSH";
355
- case ASSIGN_ADD: return "ASSIGN_ADD";
356
- case ASSIGN_SUB: return "ASSIGN_SUB";
357
- case ASSIGN_MUL: return "ASSIGN_MUL";
358
- case ASSIGN_DIV: return "ASSIGN_DIV";
359
- case ASSIGN_MOD: return "ASSIGN_MOD";
360
- case HOOK: return "HOOK";
361
- case COLON: return "COLON";
362
- case OR: return "OR";
363
- case AND: return "AND";
364
- case INC: return "INC";
365
- case DEC: return "DEC";
366
- case DOT: return "DOT";
367
- case FUNCTION: return "FUNCTION";
368
- case EXPORT: return "EXPORT";
369
- case IMPORT: return "IMPORT";
370
- case IF: return "IF";
371
- case ELSE: return "ELSE";
372
- case SWITCH: return "SWITCH";
373
- case CASE: return "CASE";
374
- case DEFAULT: return "DEFAULT";
375
- case WHILE: return "WHILE";
376
- case DO: return "DO";
377
- case FOR: return "FOR";
378
- case BREAK: return "BREAK";
379
- case CONTINUE: return "CONTINUE";
380
- case VAR: return "VAR";
381
- case WITH: return "WITH";
382
- case CATCH: return "CATCH";
383
- case FINALLY: return "FINALLY";
384
- case RESERVED: return "RESERVED";
385
- case EMPTY: return "EMPTY";
386
- case BLOCK: return "BLOCK";
387
- case LABEL: return "LABEL";
388
- case TARGET: return "TARGET";
389
- case LOOP: return "LOOP";
390
- case EXPR_VOID: return "EXPR_VOID";
391
- case EXPR_RESULT: return "EXPR_RESULT";
392
- case JSR: return "JSR";
393
- case SCRIPT: return "SCRIPT";
394
- case TYPEOFNAME: return "TYPEOFNAME";
395
- case USE_STACK: return "USE_STACK";
396
- case SETPROP_OP: return "SETPROP_OP";
397
- case SETELEM_OP: return "SETELEM_OP";
398
- case LOCAL_BLOCK: return "LOCAL_BLOCK";
399
- case SET_REF_OP: return "SET_REF_OP";
400
- case DOTDOT: return "DOTDOT";
401
- case COLONCOLON: return "COLONCOLON";
402
- case XML: return "XML";
403
- case DOTQUERY: return "DOTQUERY";
404
- case XMLATTR: return "XMLATTR";
405
- case XMLEND: return "XMLEND";
406
- case TO_OBJECT: return "TO_OBJECT";
407
- case TO_DOUBLE: return "TO_DOUBLE";
408
- case GET: return "GET";
409
- case SET: return "SET";
410
- case CONST: return "CONST";
411
- case SETCONST: return "SETCONST";
412
- }
413
-
414
- // Token without name
415
- throw new IllegalStateException(String.valueOf(token));
416
- }
417
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
lib/Diglin/yuicompressor-2.4.6/src/org/mozilla/javascript/TokenStream.java DELETED
@@ -1,1365 +0,0 @@
1
- /* ***** BEGIN LICENSE BLOCK *****
2
- *
3
- * Version: MPL 1.1
4
- *
5
- * The contents of this file are subject to the Mozilla Public License
6
- * Version 1.1 (the "License"); you may not use this file except in
7
- * compliance with the License. You may obtain a copy of the License
8
- * at http://www.mozilla.org/MPL/
9
- *
10
- * Software distributed under the License is distributed on an "AS IS"
11
- * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.
12
- * See the License for the specific language governing rights and
13
- * limitations under the License.
14
- *
15
- * The Original Code is org/mozilla/javascript/TokenStream.java,
16
- * a component of the Rhino Library ( http://www.mozilla.org/rhino/ )
17
- * This file is a modification of the Original Code developed
18
- * for YUI Compressor.
19
- *
20
- * The Initial Developer of the Original Code is Mozilla Foundation
21
- *
22
- * Copyright (c) 2009 Mozilla Foundation. All Rights Reserved.
23
- *
24
- * Contributor(s): Yahoo! Inc. 2009
25
- *
26
- * ***** END LICENSE BLOCK ***** */
27
-
28
- package org.mozilla.javascript;
29
-
30
- import java.io.*;
31
-
32
- /**
33
- * This class implements the JavaScript scanner.
34
- *
35
- * It is based on the C source files jsscan.c and jsscan.h
36
- * in the jsref package.
37
- *
38
- * @see org.mozilla.javascript.Parser
39
- *
40
- * @author Mike McCabe
41
- * @author Brendan Eich
42
- */
43
-
44
- class TokenStream
45
- {
46
- /*
47
- * For chars - because we need something out-of-range
48
- * to check. (And checking EOF by exception is annoying.)
49
- * Note distinction from EOF token type!
50
- */
51
- private final static int
52
- EOF_CHAR = -1;
53
-
54
- TokenStream(Parser parser, Reader sourceReader, String sourceString,
55
- int lineno)
56
- {
57
- this.parser = parser;
58
- this.lineno = lineno;
59
- if (sourceReader != null) {
60
- if (sourceString != null) Kit.codeBug();
61
- this.sourceReader = sourceReader;
62
- this.sourceBuffer = new char[512];
63
- this.sourceEnd = 0;
64
- } else {
65
- if (sourceString == null) Kit.codeBug();
66
- this.sourceString = sourceString;
67
- this.sourceEnd = sourceString.length();
68
- }
69
- this.sourceCursor = 0;
70
- }
71
-
72
- /* This function uses the cached op, string and number fields in
73
- * TokenStream; if getToken has been called since the passed token
74
- * was scanned, the op or string printed may be incorrect.
75
- */
76
- String tokenToString(int token)
77
- {
78
- if (Token.printTrees) {
79
- String name = Token.name(token);
80
-
81
- switch (token) {
82
- case Token.STRING:
83
- case Token.REGEXP:
84
- case Token.NAME:
85
- return name + " `" + this.string + "'";
86
-
87
- case Token.NUMBER:
88
- return "NUMBER " + this.number;
89
- }
90
-
91
- return name;
92
- }
93
- return "";
94
- }
95
-
96
- static boolean isKeyword(String s)
97
- {
98
- return Token.EOF != stringToKeyword(s);
99
- }
100
-
101
- private static int stringToKeyword(String name)
102
- {
103
- // #string_id_map#
104
- // The following assumes that Token.EOF == 0
105
- final int
106
- Id_break = Token.BREAK,
107
- Id_case = Token.CASE,
108
- Id_continue = Token.CONTINUE,
109
- Id_default = Token.DEFAULT,
110
- Id_delete = Token.DELPROP,
111
- Id_do = Token.DO,
112
- Id_else = Token.ELSE,
113
- Id_export = Token.EXPORT,
114
- Id_false = Token.FALSE,
115
- Id_for = Token.FOR,
116
- Id_function = Token.FUNCTION,
117
- Id_if = Token.IF,
118
- Id_in = Token.IN,
119
- Id_new = Token.NEW,
120
- Id_null = Token.NULL,
121
- Id_return = Token.RETURN,
122
- Id_switch = Token.SWITCH,
123
- Id_this = Token.THIS,
124
- Id_true = Token.TRUE,
125
- Id_typeof = Token.TYPEOF,
126
- Id_var = Token.VAR,
127
- Id_void = Token.VOID,
128
- Id_while = Token.WHILE,
129
- Id_with = Token.WITH,
130
-
131
- // the following are #ifdef RESERVE_JAVA_KEYWORDS in jsscan.c
132
- Id_abstract = Token.RESERVED,
133
- Id_boolean = Token.RESERVED,
134
- Id_byte = Token.RESERVED,
135
- Id_catch = Token.CATCH,
136
- Id_char = Token.RESERVED,
137
- Id_class = Token.RESERVED,
138
- Id_const = Token.CONST,
139
- Id_debugger = Token.RESERVED,
140
- Id_double = Token.RESERVED,
141
- Id_enum = Token.RESERVED,
142
- Id_extends = Token.RESERVED,
143
- Id_final = Token.RESERVED,
144
- Id_finally = Token.FINALLY,
145
- Id_float = Token.RESERVED,
146
- Id_goto = Token.RESERVED,
147
- Id_implements = Token.RESERVED,
148
- Id_import = Token.IMPORT,
149
- Id_instanceof = Token.INSTANCEOF,
150
- Id_int = Token.RESERVED,
151
- Id_interface = Token.RESERVED,
152
- Id_long = Token.RESERVED,
153
- Id_native = Token.RESERVED,
154
- Id_package = Token.RESERVED,
155
- Id_private = Token.RESERVED,
156
- Id_protected = Token.RESERVED,
157
- Id_public = Token.RESERVED,
158
- Id_short = Token.RESERVED,
159
- Id_static = Token.RESERVED,
160
- Id_super = Token.RESERVED,
161
- Id_synchronized = Token.RESERVED,
162
- Id_throw = Token.THROW,
163
- Id_throws = Token.RESERVED,
164
- Id_transient = Token.RESERVED,
165
- Id_try = Token.TRY,
166
- Id_volatile = Token.RESERVED;
167
-
168
- int id;
169
- String s = name;
170
- // #generated# Last update: 2001-06-01 17:45:01 CEST
171
- L0: { id = 0; String X = null; int c;
172
- L: switch (s.length()) {
173
- case 2: c=s.charAt(1);
174
- if (c=='f') { if (s.charAt(0)=='i') {id=Id_if; break L0;} }
175
- else if (c=='n') { if (s.charAt(0)=='i') {id=Id_in; break L0;} }
176
- else if (c=='o') { if (s.charAt(0)=='d') {id=Id_do; break L0;} }
177
- break L;
178
- case 3: switch (s.charAt(0)) {
179
- case 'f': if (s.charAt(2)=='r' && s.charAt(1)=='o') {id=Id_for; break L0;} break L;
180
- case 'i': if (s.charAt(2)=='t' && s.charAt(1)=='n') {id=Id_int; break L0;} break L;
181
- case 'n': if (s.charAt(2)=='w' && s.charAt(1)=='e') {id=Id_new; break L0;} break L;
182
- case 't': if (s.charAt(2)=='y' && s.charAt(1)=='r') {id=Id_try; break L0;} break L;
183
- case 'v': if (s.charAt(2)=='r' && s.charAt(1)=='a') {id=Id_var; break L0;} break L;
184
- } break L;
185
- case 4: switch (s.charAt(0)) {
186
- case 'b': X="byte";id=Id_byte; break L;
187
- case 'c': c=s.charAt(3);
188
- if (c=='e') { if (s.charAt(2)=='s' && s.charAt(1)=='a') {id=Id_case; break L0;} }
189
- else if (c=='r') { if (s.charAt(2)=='a' && s.charAt(1)=='h') {id=Id_char; break L0;} }
190
- break L;
191
- case 'e': c=s.charAt(3);
192
- if (c=='e') { if (s.charAt(2)=='s' && s.charAt(1)=='l') {id=Id_else; break L0;} }
193
- else if (c=='m') { if (s.charAt(2)=='u' && s.charAt(1)=='n') {id=Id_enum; break L0;} }
194
- break L;
195
- case 'g': X="goto";id=Id_goto; break L;
196
- case 'l': X="long";id=Id_long; break L;
197
- case 'n': X="null";id=Id_null; break L;
198
- case 't': c=s.charAt(3);
199
- if (c=='e') { if (s.charAt(2)=='u' && s.charAt(1)=='r') {id=Id_true; break L0;} }
200
- else if (c=='s') { if (s.charAt(2)=='i' && s.charAt(1)=='h') {id=Id_this; break L0;} }
201
- break L;
202
- case 'v': X="void";id=Id_void; break L;
203
- case 'w': X="with";id=Id_with; break L;
204
- } break L;
205
- case 5: switch (s.charAt(2)) {
206
- case 'a': X="class";id=Id_class; break L;
207
- case 'e': X="break";id=Id_break; break L;
208
- case 'i': X="while";id=Id_while; break L;
209
- case 'l': X="false";id=Id_false; break L;
210
- case 'n': c=s.charAt(0);
211
- if (c=='c') { X="const";id=Id_const; }
212
- else if (c=='f') { X="final";id=Id_final; }
213
- break L;
214
- case 'o': c=s.charAt(0);
215
- if (c=='f') { X="float";id=Id_float; }
216
- else if (c=='s') { X="short";id=Id_short; }
217
- break L;
218
- case 'p': X="super";id=Id_super; break L;
219
- case 'r': X="throw";id=Id_throw; break L;
220
- case 't': X="catch";id=Id_catch; break L;
221
- } break L;
222
- case 6: switch (s.charAt(1)) {
223
- case 'a': X="native";id=Id_native; break L;
224
- case 'e': c=s.charAt(0);
225
- if (c=='d') { X="delete";id=Id_delete; }
226
- else if (c=='r') { X="return";id=Id_return; }
227
- break L;
228
- case 'h': X="throws";id=Id_throws; break L;
229
- case 'm': X="import";id=Id_import; break L;
230
- case 'o': X="double";id=Id_double; break L;
231
- case 't': X="static";id=Id_static; break L;
232
- case 'u': X="public";id=Id_public; break L;
233
- case 'w': X="switch";id=Id_switch; break L;
234
- case 'x': X="export";id=Id_export; break L;
235
- case 'y': X="typeof";id=Id_typeof; break L;
236
- } break L;
237
- case 7: switch (s.charAt(1)) {
238
- case 'a': X="package";id=Id_package; break L;
239
- case 'e': X="default";id=Id_default; break L;
240
- case 'i': X="finally";id=Id_finally; break L;
241
- case 'o': X="boolean";id=Id_boolean; break L;
242
- case 'r': X="private";id=Id_private; break L;
243
- case 'x': X="extends";id=Id_extends; break L;
244
- } break L;
245
- case 8: switch (s.charAt(0)) {
246
- case 'a': X="abstract";id=Id_abstract; break L;
247
- case 'c': X="continue";id=Id_continue; break L;
248
- case 'd': X="debugger";id=Id_debugger; break L;
249
- case 'f': X="function";id=Id_function; break L;
250
- case 'v': X="volatile";id=Id_volatile; break L;
251
- } break L;
252
- case 9: c=s.charAt(0);
253
- if (c=='i') { X="interface";id=Id_interface; }
254
- else if (c=='p') { X="protected";id=Id_protected; }
255
- else if (c=='t') { X="transient";id=Id_transient; }
256
- break L;
257
- case 10: c=s.charAt(1);
258
- if (c=='m') { X="implements";id=Id_implements; }
259
- else if (c=='n') { X="instanceof";id=Id_instanceof; }
260
- break L;
261
- case 12: X="synchronized";id=Id_synchronized; break L;
262
- }
263
- if (X!=null && X!=s && !X.equals(s)) id = 0;
264
- }
265
- // #/generated#
266
- // #/string_id_map#
267
- if (id == 0) { return Token.EOF; }
268
- return id & 0xff;
269
- }
270
-
271
- final int getLineno() { return lineno; }
272
-
273
- final String getString() { return string; }
274
-
275
- final double getNumber() { return number; }
276
-
277
- final boolean eof() { return hitEOF; }
278
-
279
- final int getToken() throws IOException
280
- {
281
- int c;
282
-
283
- retry:
284
- for (;;) {
285
- // Eat whitespace, possibly sensitive to newlines.
286
- for (;;) {
287
- c = getChar();
288
- if (c == EOF_CHAR) {
289
- return Token.EOF;
290
- } else if (c == '\n') {
291
- dirtyLine = false;
292
- return Token.EOL;
293
- } else if (!isJSSpace(c)) {
294
- if (c != '-') {
295
- dirtyLine = true;
296
- }
297
- break;
298
- }
299
- }
300
-
301
- if (c == '@') return Token.XMLATTR;
302
-
303
- // identifier/keyword/instanceof?
304
- // watch out for starting with a <backslash>
305
- boolean identifierStart;
306
- boolean isUnicodeEscapeStart = false;
307
- if (c == '\\') {
308
- c = getChar();
309
- if (c == 'u') {
310
- identifierStart = true;
311
- isUnicodeEscapeStart = true;
312
- stringBufferTop = 0;
313
- } else {
314
- identifierStart = false;
315
- ungetChar(c);
316
- c = '\\';
317
- }
318
- } else {
319
- identifierStart = Character.isJavaIdentifierStart((char)c);
320
- if (identifierStart) {
321
- stringBufferTop = 0;
322
- addToString(c);
323
- }
324
- }
325
-
326
- if (identifierStart) {
327
- boolean containsEscape = isUnicodeEscapeStart;
328
- for (;;) {
329
- if (isUnicodeEscapeStart) {
330
- // strictly speaking we should probably push-back
331
- // all the bad characters if the <backslash>uXXXX
332
- // sequence is malformed. But since there isn't a
333
- // correct context(is there?) for a bad Unicode
334
- // escape sequence in an identifier, we can report
335
- // an error here.
336
- int escapeVal = 0;
337
- for (int i = 0; i != 4; ++i) {
338
- c = getChar();
339
- escapeVal = Kit.xDigitToInt(c, escapeVal);
340
- // Next check takes care about c < 0 and bad escape
341
- if (escapeVal < 0) { break; }
342
- }
343
- if (escapeVal < 0) {
344
- parser.addError("msg.invalid.escape");
345
- return Token.ERROR;
346
- }
347
- addToString(escapeVal);
348
- isUnicodeEscapeStart = false;
349
- } else {
350
- c = getChar();
351
- if (c == '\\') {
352
- c = getChar();
353
- if (c == 'u') {
354
- isUnicodeEscapeStart = true;
355
- containsEscape = true;
356
- } else {
357
- parser.addError("msg.illegal.character");
358
- return Token.ERROR;
359
- }
360
- } else {
361
- if (c == EOF_CHAR
362
- || !Character.isJavaIdentifierPart((char)c))
363
- {
364
- break;
365
- }
366
- addToString(c);
367
- }
368
- }
369
- }
370
- ungetChar(c);
371
-
372
- String str = getStringFromBuffer();
373
- if (!containsEscape) {
374
- // OPT we shouldn't have to make a string (object!) to
375
- // check if it's a keyword.
376
-
377
- // Return the corresponding token if it's a keyword
378
- int result = stringToKeyword(str);
379
- if (result != Token.EOF) {
380
- if (result != Token.RESERVED) {
381
- return result;
382
- } else if (!parser.compilerEnv.
383
- isReservedKeywordAsIdentifier())
384
- {
385
- return result;
386
- } else {
387
- // If implementation permits to use future reserved
388
- // keywords in violation with the EcmaScript,
389
- // treat it as name but issue warning
390
- parser.addWarning("msg.reserved.keyword", str);
391
- }
392
- }
393
- }
394
- this.string = (String)allStrings.intern(str);
395
- return Token.NAME;
396
- }
397
-
398
- // is it a number?
399
- if (isDigit(c) || (c == '.' && isDigit(peekChar()))) {
400
-
401
- stringBufferTop = 0;
402
- int base = 10;
403
-
404
- if (c == '0') {
405
- c = getChar();
406
- if (c == 'x' || c == 'X') {
407
- base = 16;
408
- c = getChar();
409
- } else if (isDigit(c)) {
410
- base = 8;
411
- } else {
412
- addToString('0');
413
- }
414
- }
415
-
416
- if (base == 16) {
417
- while (0 <= Kit.xDigitToInt(c, 0)) {
418
- addToString(c);
419
- c = getChar();
420
- }
421
- } else {
422
- while ('0' <= c && c <= '9') {
423
- /*
424
- * We permit 08 and 09 as decimal numbers, which
425
- * makes our behavior a superset of the ECMA
426
- * numeric grammar. We might not always be so
427
- * permissive, so we warn about it.
428
- */
429
- if (base == 8 && c >= '8') {
430
- parser.addWarning("msg.bad.octal.literal",
431
- c == '8' ? "8" : "9");
432
- base = 10;
433
- }
434
- addToString(c);
435
- c = getChar();
436
- }
437
- }
438
-
439
- boolean isInteger = true;
440
-
441
- if (base == 10 && (c == '.' || c == 'e' || c == 'E')) {
442
- isInteger = false;
443
- if (c == '.') {
444
- do {
445
- addToString(c);
446
- c = getChar();
447
- } while (isDigit(c));
448
- }
449
- if (c == 'e' || c == 'E') {
450
- addToString(c);
451
- c = getChar();
452
- if (c == '+' || c == '-') {
453
- addToString(c);
454
- c = getChar();
455
- }
456
- if (!isDigit(c)) {
457
- parser.addError("msg.missing.exponent");
458
- return Token.ERROR;
459
- }
460
- do {
461
- addToString(c);
462
- c = getChar();
463
- } while (isDigit(c));
464
- }
465
- }
466
- ungetChar(c);
467
- String numString = getStringFromBuffer();
468
-
469
- double dval;
470
- if (base == 10 && !isInteger) {
471
- try {
472
- // Use Java conversion to number from string...
473
- dval = Double.valueOf(numString).doubleValue();
474
- }
475
- catch (NumberFormatException ex) {
476
- parser.addError("msg.caught.nfe");
477
- return Token.ERROR;
478
- }
479
- } else {
480
- dval = ScriptRuntime.stringToNumber(numString, 0, base);
481
- }
482
-
483
- this.number = dval;
484
- return Token.NUMBER;
485
- }
486
-
487
- // is it a string?
488
- if (c == '"' || c == '\'') {
489
- // We attempt to accumulate a string the fast way, by
490
- // building it directly out of the reader. But if there
491
- // are any escaped characters in the string, we revert to
492
- // building it out of a StringBuffer.
493
-
494
- int quoteChar = c;
495
- stringBufferTop = 0;
496
-
497
- c = getChar();
498
- while (c != quoteChar) {
499
- if (c == '\n' || c == EOF_CHAR) {
500
- ungetChar(c);
501
- parser.addError("msg.unterminated.string.lit");
502
- return Token.ERROR;
503
- }
504
-
505
- if (c == '\\') {
506
- // We've hit an escaped character
507
-
508
- c = getChar();
509
-
510
- switch (c) {
511
-
512
- case '\\': // backslash
513
- case 'b': // backspace
514
- case 'f': // form feed
515
- case 'n': // line feed
516
- case 'r': // carriage return
517
- case 't': // horizontal tab
518
- case 'v': // vertical tab
519
- case 'd': // octal sequence
520
- case 'u': // unicode sequence
521
- case 'x': // hexadecimal sequence
522
- // Only keep the '\' character for those
523
- // characters that need to be escaped...
524
- // Don't escape quoting characters...
525
- addToString('\\');
526
- addToString(c);
527
- break;
528
-
529
- case '\n':
530
- // Remove line terminator after escape
531
- break;
532
-
533
- default:
534
- if (isDigit(c)) {
535
- // Octal representation of a character.
536
- // Preserve the escaping (see Y! bug #1637286)
537
- addToString('\\');
538
- }
539
- addToString(c);
540
- break;
541
- }
542
-
543
- } else {
544
-
545
- addToString(c);
546
- }
547
-
548
- c = getChar();
549
- }
550
-
551
- String str = getStringFromBuffer();
552
- this.string = (String)allStrings.intern(str);
553
- return Token.STRING;
554
- }
555
-
556
- switch (c) {
557
- case ';': return Token.SEMI;
558
- case '[': return Token.LB;
559
- case ']': return Token.RB;
560
- case '{': return Token.LC;
561
- case '}': return Token.RC;
562
- case '(': return Token.LP;
563
- case ')': return Token.RP;
564
- case ',': return Token.COMMA;
565
- case '?': return Token.HOOK;
566
- case ':':
567
- if (matchChar(':')) {
568
- return Token.COLONCOLON;
569
- } else {
570
- return Token.COLON;
571
- }
572
- case '.':
573
- if (matchChar('.')) {
574
- return Token.DOTDOT;
575
- } else if (matchChar('(')) {
576
- return Token.DOTQUERY;
577
- } else {
578
- return Token.DOT;
579
- }
580
-
581
- case '|':
582
- if (matchChar('|')) {
583
- return Token.OR;
584
- } else if (matchChar('=')) {
585
- return Token.ASSIGN_BITOR;
586
- } else {
587
- return Token.BITOR;
588
- }
589
-
590
- case '^':
591
- if (matchChar('=')) {
592
- return Token.ASSIGN_BITXOR;
593
- } else {
594
- return Token.BITXOR;
595
- }
596
-
597
- case '&':
598
- if (matchChar('&')) {
599
- return Token.AND;
600
- } else if (matchChar('=')) {
601
- return Token.ASSIGN_BITAND;
602
- } else {
603
- return Token.BITAND;
604
- }
605
-
606
- case '=':
607
- if (matchChar('=')) {
608
- if (matchChar('='))
609
- return Token.SHEQ;
610
- else
611
- return Token.EQ;
612
- } else {
613
- return Token.ASSIGN;
614
- }
615
-
616
- case '!':
617
- if (matchChar('=')) {
618
- if (matchChar('='))
619
- return Token.SHNE;
620
- else
621
- return Token.NE;
622
- } else {
623
- return Token.NOT;
624
- }
625
-
626
- case '<':
627
- /* NB:treat HTML begin-comment as comment-till-eol */
628
- if (matchChar('!')) {
629
- if (matchChar('-')) {
630
- if (matchChar('-')) {
631
- skipLine();
632
- continue retry;
633
- }
634
- ungetChar('-');
635
- }
636
- ungetChar('!');
637
- }
638
- if (matchChar('<')) {
639
- if (matchChar('=')) {
640
- return Token.ASSIGN_LSH;
641
- } else {
642
- return Token.LSH;
643
- }
644
- } else {
645
- if (matchChar('=')) {
646
- return Token.LE;
647
- } else {
648
- return Token.LT;
649
- }
650
- }
651
-
652
- case '>':
653
- if (matchChar('>')) {
654
- if (matchChar('>')) {
655
- if (matchChar('=')) {
656
- return Token.ASSIGN_URSH;
657
- } else {
658
- return Token.URSH;
659
- }
660
- } else {
661
- if (matchChar('=')) {
662
- return Token.ASSIGN_RSH;
663
- } else {
664
- return Token.RSH;
665
- }
666
- }
667
- } else {
668
- if (matchChar('=')) {
669
- return Token.GE;
670
- } else {
671
- return Token.GT;
672
- }
673
- }
674
-
675
- case '*':
676
- if (matchChar('=')) {
677
- return Token.ASSIGN_MUL;
678
- } else {
679
- return Token.MUL;
680
- }
681
-
682
- case '/':
683
- // is it a // comment?
684
- if (matchChar('/')) {
685
- skipLine();
686
- continue retry;
687
- }
688
- if (matchChar('*')) {
689
- boolean lookForSlash = false;
690
- StringBuffer sb = new StringBuffer();
691
- for (;;) {
692
- c = getChar();
693
- if (c == EOF_CHAR) {
694
- parser.addError("msg.unterminated.comment");
695
- return Token.ERROR;
696
- }
697
- sb.append((char) c);
698
- if (c == '*') {
699
- lookForSlash = true;
700
- } else if (c == '/') {
701
- if (lookForSlash) {
702
- sb.delete(sb.length()-2, sb.length());
703
- String s1 = sb.toString();
704
- String s2 = s1.trim();
705
- if (s1.startsWith("!")) {
706
- // Remove the leading '!' ** EDIT actually don't remove it:
707
- // http://yuilibrary.com/projects/yuicompressor/ticket/2528008
708
- // this.string = s1.substring(1);
709
- this.string = s1;
710
- return Token.KEEPCOMMENT;
711
- } else if (s2.startsWith("@cc_on") ||
712
- s2.startsWith("@if") ||
713
- s2.startsWith("@elif") ||
714
- s2.startsWith("@else") ||
715
- s2.startsWith("@end")) {
716
- this.string = s1;
717
- return Token.CONDCOMMENT;
718
- } else {
719
- continue retry;
720
- }
721
- }
722
- } else {
723
- lookForSlash = false;
724
- }
725
- }
726
- }
727
-
728
- if (matchChar('=')) {
729
- return Token.ASSIGN_DIV;
730
- } else {
731
- return Token.DIV;
732
- }
733
-
734
- case '%':
735
- if (matchChar('=')) {
736
- return Token.ASSIGN_MOD;
737
- } else {
738
- return Token.MOD;
739
- }
740
-
741
- case '~':
742
- return Token.BITNOT;
743
-
744
- case '+':
745
- if (matchChar('=')) {
746
- return Token.ASSIGN_ADD;
747
- } else if (matchChar('+')) {
748
- return Token.INC;
749
- } else {
750
- return Token.ADD;
751
- }
752
-
753
- case '-':
754
- if (matchChar('=')) {
755
- c = Token.ASSIGN_SUB;
756
- } else if (matchChar('-')) {
757
- if (!dirtyLine) {
758
- // treat HTML end-comment after possible whitespace
759
- // after line start as comment-utill-eol
760
- if (matchChar('>')) {
761
- skipLine();
762
- continue retry;
763
- }
764
- }
765
- c = Token.DEC;
766
- } else {
767
- c = Token.SUB;
768
- }
769
- dirtyLine = true;
770
- return c;
771
-
772
- default:
773
- parser.addError("msg.illegal.character");
774
- return Token.ERROR;
775
- }
776
- }
777
- }
778
-
779
- private static boolean isAlpha(int c)
780
- {
781
- // Use 'Z' < 'a'
782
- if (c <= 'Z') {
783
- return 'A' <= c;
784
- } else {
785
- return 'a' <= c && c <= 'z';
786
- }
787
- }
788
-
789
- static boolean isDigit(int c)
790
- {
791
- return '0' <= c && c <= '9';
792
- }
793
-
794
- /* As defined in ECMA. jsscan.c uses C isspace() (which allows
795
- * \v, I think.) note that code in getChar() implicitly accepts
796
- * '\r' == \u000D as well.
797
- */
798
- static boolean isJSSpace(int c)
799
- {
800
- if (c <= 127) {
801
- return c == 0x20 || c == 0x9 || c == 0xC || c == 0xB;
802
- } else {
803
- return c == 0xA0
804
- || Character.getType((char)c) == Character.SPACE_SEPARATOR;
805
- }
806
- }
807
-
808
- private static boolean isJSFormatChar(int c)
809
- {
810
- return c > 127 && Character.getType((char)c) == Character.FORMAT;
811
- }
812
-
813
- /**
814
- * Parser calls the method when it gets / or /= in literal context.
815
- */
816
- void readRegExp(int startToken)
817
- throws IOException
818
- {
819
- stringBufferTop = 0;
820
- if (startToken == Token.ASSIGN_DIV) {
821
- // Miss-scanned /=
822
- addToString('=');
823
- } else {
824
- if (startToken != Token.DIV) Kit.codeBug();
825
- }
826
-
827
- int c;
828
- boolean inClass = false;
829
- while ((c = getChar()) != '/' || inClass) {
830
- if (c == '\n' || c == EOF_CHAR) {
831
- ungetChar(c);
832
- throw parser.reportError("msg.unterminated.re.lit");
833
- }
834
- if (c == '\\') {
835
- addToString(c);
836
- c = getChar();
837
- } else if (c == '[') {
838
- inClass = true;
839
- } else if (c == ']') {
840
- inClass = false;
841
- }
842
-
843
- addToString(c);
844
- }
845
- int reEnd = stringBufferTop;
846
-
847
- while (true) {
848
- if (matchChar('g'))
849
- addToString('g');
850
- else if (matchChar('i'))
851
- addToString('i');
852
- else if (matchChar('m'))
853
- addToString('m');
854
- else
855
- break;
856
- }
857
-
858
- if (isAlpha(peekChar())) {
859
- throw parser.reportError("msg.invalid.re.flag");
860
- }
861
-
862
- this.string = new String(stringBuffer, 0, reEnd);
863
- this.regExpFlags = new String(stringBuffer, reEnd,
864
- stringBufferTop - reEnd);
865
- }
866
-
867
- boolean isXMLAttribute()
868
- {
869
- return xmlIsAttribute;
870
- }
871
-
872
- int getFirstXMLToken() throws IOException
873
- {
874
- xmlOpenTagsCount = 0;
875
- xmlIsAttribute = false;
876
- xmlIsTagContent = false;
877
- ungetChar('<');
878
- return getNextXMLToken();
879
- }
880
-
881
- int getNextXMLToken() throws IOException
882
- {
883
- stringBufferTop = 0; // remember the XML
884
-
885
- for (int c = getChar(); c != EOF_CHAR; c = getChar()) {
886
- if (xmlIsTagContent) {
887
- switch (c) {
888
- case '>':
889
- addToString(c);
890
- xmlIsTagContent = false;
891
- xmlIsAttribute = false;
892
- break;
893
- case '/':
894
- addToString(c);
895
- if (peekChar() == '>') {
896
- c = getChar();
897
- addToString(c);
898
- xmlIsTagContent = false;
899
- xmlOpenTagsCount--;
900
- }
901
- break;
902
- case '{':
903
- ungetChar(c);
904
- this.string = getStringFromBuffer();
905
- return Token.XML;
906
- case '\'':
907
- case '"':
908
- addToString(c);
909
- if (!readQuotedString(c)) return Token.ERROR;
910
- break;
911
- case '=':
912
- addToString(c);
913
- xmlIsAttribute = true;
914
- break;
915
- case ' ':
916
- case '\t':
917
- case '\r':
918
- case '\n':
919
- addToString(c);
920
- break;
921
- default:
922
- addToString(c);
923
- xmlIsAttribute = false;
924
- break;
925
- }
926
-
927
- if (!xmlIsTagContent && xmlOpenTagsCount == 0) {
928
- this.string = getStringFromBuffer();
929
- return Token.XMLEND;
930
- }
931
- } else {
932
- switch (c) {
933
- case '<':
934
- addToString(c);
935
- c = peekChar();
936
- switch (c) {
937
- case '!':
938
- c = getChar(); // Skip !
939
- addToString(c);
940
- c = peekChar();
941
- switch (c) {
942
- case '-':
943
- c = getChar(); // Skip -
944
- addToString(c);
945
- c = getChar();
946
- if (c == '-') {
947
- addToString(c);
948
- if(!readXmlComment()) return Token.ERROR;
949
- } else {
950
- // throw away the string in progress
951
- stringBufferTop = 0;
952
- this.string = null;
953
- parser.addError("msg.XML.bad.form");
954
- return Token.ERROR;
955
- }
956
- break;
957
- case '[':
958
- c = getChar(); // Skip [
959
- addToString(c);
960
- if (getChar() == 'C' &&
961
- getChar() == 'D' &&
962
- getChar() == 'A' &&
963
- getChar() == 'T' &&
964
- getChar() == 'A' &&
965
- getChar() == '[')
966
- {
967
- addToString('C');
968
- addToString('D');
969
- addToString('A');
970
- addToString('T');
971
- addToString('A');
972
- addToString('[');
973
- if (!readCDATA()) return Token.ERROR;
974
-
975
- } else {
976
- // throw away the string in progress
977
- stringBufferTop = 0;
978
- this.string = null;
979
- parser.addError("msg.XML.bad.form");
980
- return Token.ERROR;
981
- }
982
- break;
983
- default:
984
- if(!readEntity()) return Token.ERROR;
985
- break;
986
- }
987
- break;
988
- case '?':
989
- c = getChar(); // Skip ?
990
- addToString(c);
991
- if (!readPI()) return Token.ERROR;
992
- break;
993
- case '/':
994
- // End tag
995
- c = getChar(); // Skip /
996
- addToString(c);
997
- if (xmlOpenTagsCount == 0) {
998
- // throw away the string in progress
999
- stringBufferTop = 0;
1000
- this.string = null;
1001
- parser.addError("msg.XML.bad.form");
1002
- return Token.ERROR;
1003
- }
1004
- xmlIsTagContent = true;
1005
- xmlOpenTagsCount--;
1006
- break;
1007
- default:
1008
- // Start tag
1009
- xmlIsTagContent = true;
1010
- xmlOpenTagsCount++;
1011
- break;
1012
- }
1013
- break;
1014
- case '{':
1015
- ungetChar(c);
1016
- this.string = getStringFromBuffer();
1017
- return Token.XML;
1018
- default:
1019
- addToString(c);
1020
- break;
1021
- }
1022
- }
1023
- }
1024
-
1025
- stringBufferTop = 0; // throw away the string in progress
1026
- this.string = null;
1027
- parser.addError("msg.XML.bad.form");
1028
- return Token.ERROR;
1029
- }
1030
-
1031
- /**
1032
- *
1033
- */
1034
- private boolean readQuotedString(int quote) throws IOException
1035
- {
1036
- for (int c = getChar(); c != EOF_CHAR; c = getChar()) {
1037
- addToString(c);
1038
- if (c == quote) return true;
1039
- }
1040
-
1041
- stringBufferTop = 0; // throw away the string in progress
1042
- this.string = null;
1043
- parser.addError("msg.XML.bad.form");
1044
- return false;
1045
- }
1046
-
1047
- /**
1048
- *
1049
- */
1050
- private boolean readXmlComment() throws IOException
1051
- {
1052
- for (int c = getChar(); c != EOF_CHAR;) {
1053
- addToString(c);
1054
- if (c == '-' && peekChar() == '-') {
1055
- c = getChar();
1056
- addToString(c);
1057
- if (peekChar() == '>') {
1058
- c = getChar(); // Skip >
1059
- addToString(c);
1060
- return true;
1061
- } else {
1062
- continue;
1063
- }
1064
- }
1065
- c = getChar();
1066
- }
1067
-
1068
- stringBufferTop = 0; // throw away the string in progress
1069
- this.string = null;
1070
- parser.addError("msg.XML.bad.form");
1071
- return false;
1072
- }
1073
-
1074
- /**
1075
- *
1076
- */
1077
- private boolean readCDATA() throws IOException
1078
- {
1079
- for (int c = getChar(); c != EOF_CHAR;) {
1080
- addToString(c);
1081
- if (c == ']' && peekChar() == ']') {
1082
- c = getChar();
1083
- addToString(c);
1084
- if (peekChar() == '>') {
1085
- c = getChar(); // Skip >
1086
- addToString(c);
1087
- return true;
1088
- } else {
1089
- continue;
1090
- }
1091
- }
1092
- c = getChar();
1093
- }
1094
-
1095
- stringBufferTop = 0; // throw away the string in progress
1096
- this.string = null;
1097
- parser.addError("msg.XML.bad.form");
1098
- return false;
1099
- }
1100
-
1101
- /**
1102
- *
1103
- */
1104
- private boolean readEntity() throws IOException
1105
- {
1106
- int declTags = 1;
1107
- for (int c = getChar(); c != EOF_CHAR; c = getChar()) {
1108
- addToString(c);
1109
- switch (c) {
1110
- case '<':
1111
- declTags++;
1112
- break;
1113
- case '>':
1114
- declTags--;
1115
- if (declTags == 0) return true;
1116
- break;
1117
- }
1118
- }
1119
-
1120
- stringBufferTop = 0; // throw away the string in progress
1121
- this.string = null;
1122
- parser.addError("msg.XML.bad.form");
1123
- return false;
1124
- }
1125
-
1126
- /**
1127
- *
1128
- */
1129
- private boolean readPI() throws IOException
1130
- {
1131
- for (int c = getChar(); c != EOF_CHAR; c = getChar()) {
1132
- addToString(c);
1133
- if (c == '?' && peekChar() == '>') {
1134
- c = getChar(); // Skip >
1135
- addToString(c);
1136
- return true;
1137
- }
1138
- }
1139
-
1140
- stringBufferTop = 0; // throw away the string in progress
1141
- this.string = null;
1142
- parser.addError("msg.XML.bad.form");
1143
- return false;
1144
- }
1145
-
1146
- private String getStringFromBuffer()
1147
- {
1148
- return new String(stringBuffer, 0, stringBufferTop);
1149
- }
1150
-
1151
- private void addToString(int c)
1152
- {
1153
- int N = stringBufferTop;
1154
- if (N == stringBuffer.length) {
1155
- char[] tmp = new char[stringBuffer.length * 2];
1156
- System.arraycopy(stringBuffer, 0, tmp, 0, N);
1157
- stringBuffer = tmp;
1158
- }
1159
- stringBuffer[N] = (char)c;
1160
- stringBufferTop = N + 1;
1161
- }
1162
-
1163
- private void ungetChar(int c)
1164
- {
1165
- // can not unread past across line boundary
1166
- if (ungetCursor != 0 && ungetBuffer[ungetCursor - 1] == '\n')
1167
- Kit.codeBug();
1168
- ungetBuffer[ungetCursor++] = c;
1169
- }
1170
-
1171
- private boolean matchChar(int test) throws IOException
1172
- {
1173
- int c = getChar();
1174
- if (c == test) {
1175
- return true;
1176
- } else {
1177
- ungetChar(c);
1178
- return false;
1179
- }
1180
- }
1181
-
1182
- private int peekChar() throws IOException
1183
- {
1184
- int c = getChar();
1185
- ungetChar(c);
1186
- return c;
1187
- }
1188
-
1189
- private int getChar() throws IOException
1190
- {
1191
- if (ungetCursor != 0) {
1192
- return ungetBuffer[--ungetCursor];
1193
- }
1194
-
1195
- for(;;) {
1196
- int c;
1197
- if (sourceString != null) {
1198
- if (sourceCursor == sourceEnd) {
1199
- hitEOF = true;
1200
- return EOF_CHAR;
1201
- }
1202
- c = sourceString.charAt(sourceCursor++);
1203
- } else {
1204
- if (sourceCursor == sourceEnd) {
1205
- if (!fillSourceBuffer()) {
1206
- hitEOF = true;
1207
- return EOF_CHAR;
1208
- }
1209
- }
1210
- c = sourceBuffer[sourceCursor++];
1211
- }
1212
-
1213
- if (lineEndChar >= 0) {
1214
- if (lineEndChar == '\r' && c == '\n') {
1215
- lineEndChar = '\n';
1216
- continue;
1217
- }
1218
- lineEndChar = -1;
1219
- lineStart = sourceCursor - 1;
1220
- lineno++;
1221
- }
1222
-
1223
- if (c <= 127) {
1224
- if (c == '\n' || c == '\r') {
1225
- lineEndChar = c;
1226
- c = '\n';
1227
- }
1228
- } else {
1229
- if (isJSFormatChar(c)) {
1230
- continue;
1231
- }
1232
- if (ScriptRuntime.isJSLineTerminator(c)) {
1233
- lineEndChar = c;
1234
- c = '\n';
1235
- }
1236
- }
1237
- return c;
1238
- }
1239
- }
1240
-
1241
- private void skipLine() throws IOException
1242
- {
1243
- // skip to end of line
1244
- int c;
1245
- while ((c = getChar()) != EOF_CHAR && c != '\n') { }
1246
- ungetChar(c);
1247
- }
1248
-
1249
- final int getOffset()
1250
- {
1251
- int n = sourceCursor - lineStart;
1252
- if (lineEndChar >= 0) { --n; }
1253
- return n;
1254
- }
1255
-
1256
- final String getLine()
1257
- {
1258
- if (sourceString != null) {
1259
- // String case
1260
- int lineEnd = sourceCursor;
1261
- if (lineEndChar >= 0) {
1262
- --lineEnd;
1263
- } else {
1264
- for (; lineEnd != sourceEnd; ++lineEnd) {
1265
- int c = sourceString.charAt(lineEnd);
1266
- if (ScriptRuntime.isJSLineTerminator(c)) {
1267
- break;
1268
- }
1269
- }
1270
- }
1271
- return sourceString.substring(lineStart, lineEnd);
1272
- } else {
1273
- // Reader case
1274
- int lineLength = sourceCursor - lineStart;
1275
- if (lineEndChar >= 0) {
1276
- --lineLength;
1277
- } else {
1278
- // Read until the end of line
1279
- for (;; ++lineLength) {
1280
- int i = lineStart + lineLength;
1281
- if (i == sourceEnd) {
1282
- try {
1283
- if (!fillSourceBuffer()) { break; }
1284
- } catch (IOException ioe) {
1285
- // ignore it, we're already displaying an error...
1286
- break;
1287
- }
1288
- // i recalculuation as fillSourceBuffer can move saved
1289
- // line buffer and change lineStart
1290
- i = lineStart + lineLength;
1291
- }
1292
- int c = sourceBuffer[i];
1293
- if (ScriptRuntime.isJSLineTerminator(c)) {
1294
- break;
1295
- }
1296
- }
1297
- }
1298
- return new String(sourceBuffer, lineStart, lineLength);
1299
- }
1300
- }
1301
-
1302
- private boolean fillSourceBuffer() throws IOException
1303
- {
1304
- if (sourceString != null) Kit.codeBug();
1305
- if (sourceEnd == sourceBuffer.length) {
1306
- if (lineStart != 0) {
1307
- System.arraycopy(sourceBuffer, lineStart, sourceBuffer, 0,
1308
- sourceEnd - lineStart);
1309
- sourceEnd -= lineStart;
1310
- sourceCursor -= lineStart;
1311
- lineStart = 0;
1312
- } else {
1313
- char[] tmp = new char[sourceBuffer.length * 2];
1314
- System.arraycopy(sourceBuffer, 0, tmp, 0, sourceEnd);
1315
- sourceBuffer = tmp;
1316
- }
1317
- }
1318
- int n = sourceReader.read(sourceBuffer, sourceEnd,
1319
- sourceBuffer.length - sourceEnd);
1320
- if (n < 0) {
1321
- return false;
1322
- }
1323
- sourceEnd += n;
1324
- return true;
1325
- }
1326
-
1327
- // stuff other than whitespace since start of line
1328
- private boolean dirtyLine;
1329
-
1330
- String regExpFlags;
1331
-
1332
- // Set this to an inital non-null value so that the Parser has
1333
- // something to retrieve even if an error has occured and no
1334
- // string is found. Fosters one class of error, but saves lots of
1335
- // code.
1336
- private String string = "";
1337
- private double number;
1338
-
1339
- private char[] stringBuffer = new char[128];
1340
- private int stringBufferTop;
1341
- private ObjToIntMap allStrings = new ObjToIntMap(50);
1342
-
1343
- // Room to backtrace from to < on failed match of the last - in <!--
1344
- private final int[] ungetBuffer = new int[3];
1345
- private int ungetCursor;
1346
-
1347
- private boolean hitEOF = false;
1348
-
1349
- private int lineStart = 0;
1350
- private int lineno;
1351
- private int lineEndChar = -1;
1352
-
1353
- private String sourceString;
1354
- private Reader sourceReader;
1355
- private char[] sourceBuffer;
1356
- private int sourceEnd;
1357
- private int sourceCursor;
1358
-
1359
- // for xml tokenizer
1360
- private boolean xmlIsAttribute;
1361
- private boolean xmlIsTagContent;
1362
- private int xmlOpenTagsCount;
1363
-
1364
- private Parser parser;
1365
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
lib/Diglin/yuicompressor-2.4.6/src/org/mozilla/javascript/TokenStream.java.orig DELETED
@@ -1,1398 +0,0 @@
1
- /* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2
- *
3
- * ***** BEGIN LICENSE BLOCK *****
4
- * Version: MPL 1.1/GPL 2.0
5
- *
6
- * The contents of this file are subject to the Mozilla Public License Version
7
- * 1.1 (the "License"); you may not use this file except in compliance with
8
- * the License. You may obtain a copy of the License at
9
- * http://www.mozilla.org/MPL/
10
- *
11
- * Software distributed under the License is distributed on an "AS IS" basis,
12
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13
- * for the specific language governing rights and limitations under the
14
- * License.
15
- *
16
- * The Original Code is Rhino code, released
17
- * May 6, 1999.
18
- *
19
- * The Initial Developer of the Original Code is
20
- * Netscape Communications Corporation.
21
- * Portions created by the Initial Developer are Copyright (C) 1997-1999
22
- * the Initial Developer. All Rights Reserved.
23
- *
24
- * Contributor(s):
25
- * Roger Lawrence
26
- * Mike McCabe
27
- * Igor Bukanov
28
- * Ethan Hugg
29
- * Bob Jervis
30
- * Terry Lucas
31
- * Milen Nankov
32
- *
33
- * Alternatively, the contents of this file may be used under the terms of
34
- * the GNU General Public License Version 2 or later (the "GPL"), in which
35
- * case the provisions of the GPL are applicable instead of those above. If
36
- * you wish to allow use of your version of this file only under the terms of
37
- * the GPL and not to allow others to use your version of this file under the
38
- * MPL, indicate your decision by deleting the provisions above and replacing
39
- * them with the notice and other provisions required by the GPL. If you do
40
- * not delete the provisions above, a recipient may use your version of this
41
- * file under either the MPL or the GPL.
42
- *
43
- * ***** END LICENSE BLOCK ***** */
44
-
45
- package org.mozilla.javascript;
46
-
47
- import java.io.*;
48
-
49
- /**
50
- * This class implements the JavaScript scanner.
51
- *
52
- * It is based on the C source files jsscan.c and jsscan.h
53
- * in the jsref package.
54
- *
55
- * @see org.mozilla.javascript.Parser
56
- *
57
- * @author Mike McCabe
58
- * @author Brendan Eich
59
- */
60
-
61
- class TokenStream
62
- {
63
- /*
64
- * For chars - because we need something out-of-range
65
- * to check. (And checking EOF by exception is annoying.)
66
- * Note distinction from EOF token type!
67
- */
68
- private final static int
69
- EOF_CHAR = -1;
70
-
71
- TokenStream(Parser parser, Reader sourceReader, String sourceString,
72
- int lineno)
73
- {
74
- this.parser = parser;
75
- this.lineno = lineno;
76
- if (sourceReader != null) {
77
- if (sourceString != null) Kit.codeBug();
78
- this.sourceReader = sourceReader;
79
- this.sourceBuffer = new char[512];
80
- this.sourceEnd = 0;
81
- } else {
82
- if (sourceString == null) Kit.codeBug();
83
- this.sourceString = sourceString;
84
- this.sourceEnd = sourceString.length();
85
- }
86
- this.sourceCursor = 0;
87
- }
88
-
89
- /* This function uses the cached op, string and number fields in
90
- * TokenStream; if getToken has been called since the passed token
91
- * was scanned, the op or string printed may be incorrect.
92
- */
93
- String tokenToString(int token)
94
- {
95
- if (Token.printTrees) {
96
- String name = Token.name(token);
97
-
98
- switch (token) {
99
- case Token.STRING:
100
- case Token.REGEXP:
101
- case Token.NAME:
102
- return name + " `" + this.string + "'";
103
-
104
- case Token.NUMBER:
105
- return "NUMBER " + this.number;
106
- }
107
-
108
- return name;
109
- }
110
- return "";
111
- }
112
-
113
- static boolean isKeyword(String s)
114
- {
115
- return Token.EOF != stringToKeyword(s);
116
- }
117
-
118
- private static int stringToKeyword(String name)
119
- {
120
- // #string_id_map#
121
- // The following assumes that Token.EOF == 0
122
- final int
123
- Id_break = Token.BREAK,
124
- Id_case = Token.CASE,
125
- Id_continue = Token.CONTINUE,
126
- Id_default = Token.DEFAULT,
127
- Id_delete = Token.DELPROP,
128
- Id_do = Token.DO,
129
- Id_else = Token.ELSE,
130
- Id_export = Token.EXPORT,
131
- Id_false = Token.FALSE,
132
- Id_for = Token.FOR,
133
- Id_function = Token.FUNCTION,
134
- Id_if = Token.IF,
135
- Id_in = Token.IN,
136
- Id_new = Token.NEW,
137
- Id_null = Token.NULL,
138
- Id_return = Token.RETURN,
139
- Id_switch = Token.SWITCH,
140
- Id_this = Token.THIS,
141
- Id_true = Token.TRUE,
142
- Id_typeof = Token.TYPEOF,
143
- Id_var = Token.VAR,
144
- Id_void = Token.VOID,
145
- Id_while = Token.WHILE,
146
- Id_with = Token.WITH,
147
-
148
- // the following are #ifdef RESERVE_JAVA_KEYWORDS in jsscan.c
149
- Id_abstract = Token.RESERVED,
150
- Id_boolean = Token.RESERVED,
151
- Id_byte = Token.RESERVED,
152
- Id_catch = Token.CATCH,
153
- Id_char = Token.RESERVED,
154
- Id_class = Token.RESERVED,
155
- Id_const = Token.CONST,
156
- Id_debugger = Token.RESERVED,
157
- Id_double = Token.RESERVED,
158
- Id_enum = Token.RESERVED,
159
- Id_extends = Token.RESERVED,
160
- Id_final = Token.RESERVED,
161
- Id_finally = Token.FINALLY,
162
- Id_float = Token.RESERVED,
163
- Id_goto = Token.RESERVED,
164
- Id_implements = Token.RESERVED,
165
- Id_import = Token.IMPORT,
166
- Id_instanceof = Token.INSTANCEOF,
167
- Id_int = Token.RESERVED,
168
- Id_interface = Token.RESERVED,
169
- Id_long = Token.RESERVED,
170
- Id_native = Token.RESERVED,
171
- Id_package = Token.RESERVED,
172
- Id_private = Token.RESERVED,
173
- Id_protected = Token.RESERVED,
174
- Id_public = Token.RESERVED,
175
- Id_short = Token.RESERVED,
176
- Id_static = Token.RESERVED,
177
- Id_super = Token.RESERVED,
178
- Id_synchronized = Token.RESERVED,
179
- Id_throw = Token.THROW,
180
- Id_throws = Token.RESERVED,
181
- Id_transient = Token.RESERVED,
182
- Id_try = Token.TRY,
183
- Id_volatile = Token.RESERVED;
184
-
185
- int id;
186
- String s = name;
187
- // #generated# Last update: 2001-06-01 17:45:01 CEST
188
- L0: { id = 0; String X = null; int c;
189
- L: switch (s.length()) {
190
- case 2: c=s.charAt(1);
191
- if (c=='f') { if (s.charAt(0)=='i') {id=Id_if; break L0;} }
192
- else if (c=='n') { if (s.charAt(0)=='i') {id=Id_in; break L0;} }
193
- else if (c=='o') { if (s.charAt(0)=='d') {id=Id_do; break L0;} }
194
- break L;
195
- case 3: switch (s.charAt(0)) {
196
- case 'f': if (s.charAt(2)=='r' && s.charAt(1)=='o') {id=Id_for; break L0;} break L;
197
- case 'i': if (s.charAt(2)=='t' && s.charAt(1)=='n') {id=Id_int; break L0;} break L;
198
- case 'n': if (s.charAt(2)=='w' && s.charAt(1)=='e') {id=Id_new; break L0;} break L;
199
- case 't': if (s.charAt(2)=='y' && s.charAt(1)=='r') {id=Id_try; break L0;} break L;
200
- case 'v': if (s.charAt(2)=='r' && s.charAt(1)=='a') {id=Id_var; break L0;} break L;
201
- } break L;
202
- case 4: switch (s.charAt(0)) {
203
- case 'b': X="byte";id=Id_byte; break L;
204
- case 'c': c=s.charAt(3);
205
- if (c=='e') { if (s.charAt(2)=='s' && s.charAt(1)=='a') {id=Id_case; break L0;} }
206
- else if (c=='r') { if (s.charAt(2)=='a' && s.charAt(1)=='h') {id=Id_char; break L0;} }
207
- break L;
208
- case 'e': c=s.charAt(3);
209
- if (c=='e') { if (s.charAt(2)=='s' && s.charAt(1)=='l') {id=Id_else; break L0;} }
210
- else if (c=='m') { if (s.charAt(2)=='u' && s.charAt(1)=='n') {id=Id_enum; break L0;} }
211
- break L;
212
- case 'g': X="goto";id=Id_goto; break L;
213
- case 'l': X="long";id=Id_long; break L;
214
- case 'n': X="null";id=Id_null; break L;
215
- case 't': c=s.charAt(3);
216
- if (c=='e') { if (s.charAt(2)=='u' && s.charAt(1)=='r') {id=Id_true; break L0;} }
217
- else if (c=='s') { if (s.charAt(2)=='i' && s.charAt(1)=='h') {id=Id_this; break L0;} }
218
- break L;
219
- case 'v': X="void";id=Id_void; break L;
220
- case 'w': X="with";id=Id_with; break L;
221
- } break L;
222
- case 5: switch (s.charAt(2)) {
223
- case 'a': X="class";id=Id_class; break L;
224
- case 'e': X="break";id=Id_break; break L;
225
- case 'i': X="while";id=Id_while; break L;
226
- case 'l': X="false";id=Id_false; break L;
227
- case 'n': c=s.charAt(0);
228
- if (c=='c') { X="const";id=Id_const; }
229
- else if (c=='f') { X="final";id=Id_final; }
230
- break L;
231
- case 'o': c=s.charAt(0);
232
- if (c=='f') { X="float";id=Id_float; }
233
- else if (c=='s') { X="short";id=Id_short; }
234
- break L;
235
- case 'p': X="super";id=Id_super; break L;
236
- case 'r': X="throw";id=Id_throw; break L;
237
- case 't': X="catch";id=Id_catch; break L;
238
- } break L;
239
- case 6: switch (s.charAt(1)) {
240
- case 'a': X="native";id=Id_native; break L;
241
- case 'e': c=s.charAt(0);
242
- if (c=='d') { X="delete";id=Id_delete; }
243
- else if (c=='r') { X="return";id=Id_return; }
244
- break L;
245
- case 'h': X="throws";id=Id_throws; break L;
246
- case 'm': X="import";id=Id_import; break L;
247
- case 'o': X="double";id=Id_double; break L;
248
- case 't': X="static";id=Id_static; break L;
249
- case 'u': X="public";id=Id_public; break L;
250
- case 'w': X="switch";id=Id_switch; break L;
251
- case 'x': X="export";id=Id_export; break L;
252
- case 'y': X="typeof";id=Id_typeof; break L;
253
- } break L;
254
- case 7: switch (s.charAt(1)) {
255
- case 'a': X="package";id=Id_package; break L;
256
- case 'e': X="default";id=Id_default; break L;
257
- case 'i': X="finally";id=Id_finally; break L;
258
- case 'o': X="boolean";id=Id_boolean; break L;
259
- case 'r': X="private";id=Id_private; break L;
260
- case 'x': X="extends";id=Id_extends; break L;
261
- } break L;
262
- case 8: switch (s.charAt(0)) {
263
- case 'a': X="abstract";id=Id_abstract; break L;
264
- case 'c': X="continue";id=Id_continue; break L;
265
- case 'd': X="debugger";id=Id_debugger; break L;
266
- case 'f': X="function";id=Id_function; break L;
267
- case 'v': X="volatile";id=Id_volatile; break L;
268
- } break L;
269
- case 9: c=s.charAt(0);
270
- if (c=='i') { X="interface";id=Id_interface; }
271
- else if (c=='p') { X="protected";id=Id_protected; }
272
- else if (c=='t') { X="transient";id=Id_transient; }
273
- break L;
274
- case 10: c=s.charAt(1);
275
- if (c=='m') { X="implements";id=Id_implements; }
276
- else if (c=='n') { X="instanceof";id=Id_instanceof; }
277
- break L;
278
- case 12: X="synchronized";id=Id_synchronized; break L;
279
- }
280
- if (X!=null && X!=s && !X.equals(s)) id = 0;
281
- }
282
- // #/generated#
283
- // #/string_id_map#
284
- if (id == 0) { return Token.EOF; }
285
- return id & 0xff;
286
- }
287
-
288
- final int getLineno() { return lineno; }
289
-
290
- final String getString() { return string; }
291
-
292
- final double getNumber() { return number; }
293
-
294
- final boolean eof() { return hitEOF; }
295
-
296
- final int getToken() throws IOException
297
- {
298
- int c;
299
-
300
- retry:
301
- for (;;) {
302
- // Eat whitespace, possibly sensitive to newlines.
303
- for (;;) {
304
- c = getChar();
305
- if (c == EOF_CHAR) {
306
- return Token.EOF;
307
- } else if (c == '\n') {
308
- dirtyLine = false;
309
- return Token.EOL;
310
- } else if (!isJSSpace(c)) {
311
- if (c != '-') {
312
- dirtyLine = true;
313
- }
314
- break;
315
- }
316
- }
317
-
318
- if (c == '@') return Token.XMLATTR;
319
-
320
- // identifier/keyword/instanceof?
321
- // watch out for starting with a <backslash>
322
- boolean identifierStart;
323
- boolean isUnicodeEscapeStart = false;
324
- if (c == '\\') {
325
- c = getChar();
326
- if (c == 'u') {
327
- identifierStart = true;
328
- isUnicodeEscapeStart = true;
329
- stringBufferTop = 0;
330
- } else {
331
- identifierStart = false;
332
- ungetChar(c);
333
- c = '\\';
334
- }
335
- } else {
336
- identifierStart = Character.isJavaIdentifierStart((char)c);
337
- if (identifierStart) {
338
- stringBufferTop = 0;
339
- addToString(c);
340
- }
341
- }
342
-
343
- if (identifierStart) {
344
- boolean containsEscape = isUnicodeEscapeStart;
345
- for (;;) {
346
- if (isUnicodeEscapeStart) {
347
- // strictly speaking we should probably push-back
348
- // all the bad characters if the <backslash>uXXXX
349
- // sequence is malformed. But since there isn't a
350
- // correct context(is there?) for a bad Unicode
351
- // escape sequence in an identifier, we can report
352
- // an error here.
353
- int escapeVal = 0;
354
- for (int i = 0; i != 4; ++i) {
355
- c = getChar();
356
- escapeVal = Kit.xDigitToInt(c, escapeVal);
357
- // Next check takes care about c < 0 and bad escape
358
- if (escapeVal < 0) { break; }
359
- }
360
- if (escapeVal < 0) {
361
- parser.addError("msg.invalid.escape");
362
- return Token.ERROR;
363
- }
364
- addToString(escapeVal);
365
- isUnicodeEscapeStart = false;
366
- } else {
367
- c = getChar();
368
- if (c == '\\') {
369
- c = getChar();
370
- if (c == 'u') {
371
- isUnicodeEscapeStart = true;
372
- containsEscape = true;
373
- } else {
374
- parser.addError("msg.illegal.character");
375
- return Token.ERROR;
376
- }
377
- } else {
378
- if (c == EOF_CHAR
379
- || !Character.isJavaIdentifierPart((char)c))
380
- {
381
- break;
382
- }
383
- addToString(c);
384
- }
385
- }
386
- }
387
- ungetChar(c);
388
-
389
- String str = getStringFromBuffer();
390
- if (!containsEscape) {
391
- // OPT we shouldn't have to make a string (object!) to
392
- // check if it's a keyword.
393
-
394
- // Return the corresponding token if it's a keyword
395
- int result = stringToKeyword(str);
396
- if (result != Token.EOF) {
397
- if (result != Token.RESERVED) {
398
- return result;
399
- } else if (!parser.compilerEnv.
400
- isReservedKeywordAsIdentifier())
401
- {
402
- return result;
403
- } else {
404
- // If implementation permits to use future reserved
405
- // keywords in violation with the EcmaScript,
406
- // treat it as name but issue warning
407
- parser.addWarning("msg.reserved.keyword", str);
408
- }
409
- }
410
- }
411
- this.string = (String)allStrings.intern(str);
412
- return Token.NAME;
413
- }
414
-
415
- // is it a number?
416
- if (isDigit(c) || (c == '.' && isDigit(peekChar()))) {
417
-
418
- stringBufferTop = 0;
419
- int base = 10;
420
-
421
- if (c == '0') {
422
- c = getChar();
423
- if (c == 'x' || c == 'X') {
424
- base = 16;
425
- c = getChar();
426
- } else if (isDigit(c)) {
427
- base = 8;
428
- } else {
429
- addToString('0');
430
- }
431
- }
432
-
433
- if (base == 16) {
434
- while (0 <= Kit.xDigitToInt(c, 0)) {
435
- addToString(c);
436
- c = getChar();
437
- }
438
- } else {
439
- while ('0' <= c && c <= '9') {
440
- /*
441
- * We permit 08 and 09 as decimal numbers, which
442
- * makes our behavior a superset of the ECMA
443
- * numeric grammar. We might not always be so
444
- * permissive, so we warn about it.
445
- */
446
- if (base == 8 && c >= '8') {
447
- parser.addWarning("msg.bad.octal.literal",
448
- c == '8' ? "8" : "9");
449
- base = 10;
450
- }
451
- addToString(c);
452
- c = getChar();
453
- }
454
- }
455
-
456
- boolean isInteger = true;
457
-
458
- if (base == 10 && (c == '.' || c == 'e' || c == 'E')) {
459
- isInteger = false;
460
- if (c == '.') {
461
- do {
462
- addToString(c);
463
- c = getChar();
464
- } while (isDigit(c));
465
- }
466
- if (c == 'e' || c == 'E') {
467
- addToString(c);
468
- c = getChar();
469
- if (c == '+' || c == '-') {
470
- addToString(c);
471
- c = getChar();
472
- }
473
- if (!isDigit(c)) {
474
- parser.addError("msg.missing.exponent");
475
- return Token.ERROR;
476
- }
477
- do {
478
- addToString(c);
479
- c = getChar();
480
- } while (isDigit(c));
481
- }
482
- }
483
- ungetChar(c);
484
- String numString = getStringFromBuffer();
485
-
486
- double dval;
487
- if (base == 10 && !isInteger) {
488
- try {
489
- // Use Java conversion to number from string...
490
- dval = Double.valueOf(numString).doubleValue();
491
- }
492
- catch (NumberFormatException ex) {
493
- parser.addError("msg.caught.nfe");
494
- return Token.ERROR;
495
- }
496
- } else {
497
- dval = ScriptRuntime.stringToNumber(numString, 0, base);
498
- }
499
-
500
- this.number = dval;
501
- return Token.NUMBER;
502
- }
503
-
504
- // is it a string?
505
- if (c == '"' || c == '\'') {
506
- // We attempt to accumulate a string the fast way, by
507
- // building it directly out of the reader. But if there
508
- // are any escaped characters in the string, we revert to
509
- // building it out of a StringBuffer.
510
-
511
- int quoteChar = c;
512
- stringBufferTop = 0;
513
-
514
- c = getChar();
515
- strLoop: while (c != quoteChar) {
516
- if (c == '\n' || c == EOF_CHAR) {
517
- ungetChar(c);
518
- parser.addError("msg.unterminated.string.lit");
519
- return Token.ERROR;
520
- }
521
-
522
- if (c == '\\') {
523
- // We've hit an escaped character
524
- int escapeVal;
525
-
526
- c = getChar();
527
- switch (c) {
528
- case 'b': c = '\b'; break;
529
- case 'f': c = '\f'; break;
530
- case 'n': c = '\n'; break;
531
- case 'r': c = '\r'; break;
532
- case 't': c = '\t'; break;
533
-
534
- // \v a late addition to the ECMA spec,
535
- // it is not in Java, so use 0xb
536
- case 'v': c = 0xb; break;
537
-
538
- case 'u':
539
- // Get 4 hex digits; if the u escape is not
540
- // followed by 4 hex digits, use 'u' + the
541
- // literal character sequence that follows.
542
- int escapeStart = stringBufferTop;
543
- addToString('u');
544
- escapeVal = 0;
545
- for (int i = 0; i != 4; ++i) {
546
- c = getChar();
547
- escapeVal = Kit.xDigitToInt(c, escapeVal);
548
- if (escapeVal < 0) {
549
- continue strLoop;
550
- }
551
- addToString(c);
552
- }
553
- // prepare for replace of stored 'u' sequence
554
- // by escape value
555
- stringBufferTop = escapeStart;
556
- c = escapeVal;
557
- break;
558
- case 'x':
559
- // Get 2 hex digits, defaulting to 'x'+literal
560
- // sequence, as above.
561
- c = getChar();
562
- escapeVal = Kit.xDigitToInt(c, 0);
563
- if (escapeVal < 0) {
564
- addToString('x');
565
- continue strLoop;
566
- } else {
567
- int c1 = c;
568
- c = getChar();
569
- escapeVal = Kit.xDigitToInt(c, escapeVal);
570
- if (escapeVal < 0) {
571
- addToString('x');
572
- addToString(c1);
573
- continue strLoop;
574
- } else {
575
- // got 2 hex digits
576
- c = escapeVal;
577
- }
578
- }
579
- break;
580
-
581
- case '\n':
582
- // Remove line terminator after escape to follow
583
- // SpiderMonkey and C/C++
584
- c = getChar();
585
- continue strLoop;
586
-
587
- default:
588
- if ('0' <= c && c < '8') {
589
- int val = c - '0';
590
- c = getChar();
591
- if ('0' <= c && c < '8') {
592
- val = 8 * val + c - '0';
593
- c = getChar();
594
- if ('0' <= c && c < '8' && val <= 037) {
595
- // c is 3rd char of octal sequence only
596
- // if the resulting val <= 0377
597
- val = 8 * val + c - '0';
598
- c = getChar();
599
- }
600
- }
601
- ungetChar(c);
602
- c = val;
603
- }
604
- }
605
- }
606
- addToString(c);
607
- c = getChar();
608
- }
609
-
610
- String str = getStringFromBuffer();
611
- this.string = (String)allStrings.intern(str);
612
- return Token.STRING;
613
- }
614
-
615
- switch (c) {
616
- case ';': return Token.SEMI;
617
- case '[': return Token.LB;
618
- case ']': return Token.RB;
619
- case '{': return Token.LC;
620
- case '}': return Token.RC;
621
- case '(': return Token.LP;
622
- case ')': return Token.RP;
623
- case ',': return Token.COMMA;
624
- case '?': return Token.HOOK;
625
- case ':':
626
- if (matchChar(':')) {
627
- return Token.COLONCOLON;
628
- } else {
629
- return Token.COLON;
630
- }
631
- case '.':
632
- if (matchChar('.')) {
633
- return Token.DOTDOT;
634
- } else if (matchChar('(')) {
635
- return Token.DOTQUERY;
636
- } else {
637
- return Token.DOT;
638
- }
639
-
640
- case '|':
641
- if (matchChar('|')) {
642
- return Token.OR;
643
- } else if (matchChar('=')) {
644
- return Token.ASSIGN_BITOR;
645
- } else {
646
- return Token.BITOR;
647
- }
648
-
649
- case '^':
650
- if (matchChar('=')) {
651
- return Token.ASSIGN_BITXOR;
652
- } else {
653
- return Token.BITXOR;
654
- }
655
-
656
- case '&':
657
- if (matchChar('&')) {
658
- return Token.AND;
659
- } else if (matchChar('=')) {
660
- return Token.ASSIGN_BITAND;
661
- } else {
662
- return Token.BITAND;
663
- }
664
-
665
- case '=':
666
- if (matchChar('=')) {
667
- if (matchChar('='))
668
- return Token.SHEQ;
669
- else
670
- return Token.EQ;
671
- } else {
672
- return Token.ASSIGN;
673
- }
674
-
675
- case '!':
676
- if (matchChar('=')) {
677
- if (matchChar('='))
678
- return Token.SHNE;
679
- else
680
- return Token.NE;
681
- } else {
682
- return Token.NOT;
683
- }
684
-
685
- case '<':
686
- /* NB:treat HTML begin-comment as comment-till-eol */
687
- if (matchChar('!')) {
688
- if (matchChar('-')) {
689
- if (matchChar('-')) {
690
- skipLine();
691
- continue retry;
692
- }
693
- ungetChar('-');
694
- }
695
- ungetChar('!');
696
- }
697
- if (matchChar('<')) {
698
- if (matchChar('=')) {
699
- return Token.ASSIGN_LSH;
700
- } else {
701
- return Token.LSH;
702
- }
703
- } else {
704
- if (matchChar('=')) {
705
- return Token.LE;
706
- } else {
707
- return Token.LT;
708
- }
709
- }
710
-
711
- case '>':
712
- if (matchChar('>')) {
713
- if (matchChar('>')) {
714
- if (matchChar('=')) {
715
- return Token.ASSIGN_URSH;
716
- } else {
717
- return Token.URSH;
718
- }
719
- } else {
720
- if (matchChar('=')) {
721
- return Token.ASSIGN_RSH;
722
- } else {
723
- return Token.RSH;
724
- }
725
- }
726
- } else {
727
- if (matchChar('=')) {
728
- return Token.GE;
729
- } else {
730
- return Token.GT;
731
- }
732
- }
733
-
734
- case '*':
735
- if (matchChar('=')) {
736
- return Token.ASSIGN_MUL;
737
- } else {
738
- return Token.MUL;
739
- }
740
-
741
- case '/':
742
- // is it a // comment?
743
- if (matchChar('/')) {
744
- skipLine();
745
- continue retry;
746
- }
747
- if (matchChar('*')) {
748
- boolean lookForSlash = false;
749
- for (;;) {
750
- c = getChar();
751
- if (c == EOF_CHAR) {
752
- parser.addError("msg.unterminated.comment");
753
- return Token.ERROR;
754
- } else if (c == '*') {
755
- lookForSlash = true;
756
- } else if (c == '/') {
757
- if (lookForSlash) {
758
- continue retry;
759
- }
760
- } else {
761
- lookForSlash = false;
762
- }
763
- }
764
- }
765
-
766
- if (matchChar('=')) {
767
- return Token.ASSIGN_DIV;
768
- } else {
769
- return Token.DIV;
770
- }
771
-
772
- case '%':
773
- if (matchChar('=')) {
774
- return Token.ASSIGN_MOD;
775
- } else {
776
- return Token.MOD;
777
- }
778
-
779
- case '~':
780
- return Token.BITNOT;
781
-
782
- case '+':
783
- if (matchChar('=')) {
784
- return Token.ASSIGN_ADD;
785
- } else if (matchChar('+')) {
786
- return Token.INC;
787
- } else {
788
- return Token.ADD;
789
- }
790
-
791
- case '-':
792
- if (matchChar('=')) {
793
- c = Token.ASSIGN_SUB;
794
- } else if (matchChar('-')) {
795
- if (!dirtyLine) {
796
- // treat HTML end-comment after possible whitespace
797
- // after line start as comment-utill-eol
798
- if (matchChar('>')) {
799
- skipLine();
800
- continue retry;
801
- }
802
- }
803
- c = Token.DEC;
804
- } else {
805
- c = Token.SUB;
806
- }
807
- dirtyLine = true;
808
- return c;
809
-
810
- default:
811
- parser.addError("msg.illegal.character");
812
- return Token.ERROR;
813
- }
814
- }
815
- }
816
-
817
- private static boolean isAlpha(int c)
818
- {
819
- // Use 'Z' < 'a'
820
- if (c <= 'Z') {
821
- return 'A' <= c;
822
- } else {
823
- return 'a' <= c && c <= 'z';
824
- }
825
- }
826
-
827
- static boolean isDigit(int c)
828
- {
829
- return '0' <= c && c <= '9';
830
- }
831
-
832
- /* As defined in ECMA. jsscan.c uses C isspace() (which allows
833
- * \v, I think.) note that code in getChar() implicitly accepts
834
- * '\r' == \u000D as well.
835
- */
836
- static boolean isJSSpace(int c)
837
- {
838
- if (c <= 127) {
839
- return c == 0x20 || c == 0x9 || c == 0xC || c == 0xB;
840
- } else {
841
- return c == 0xA0
842
- || Character.getType((char)c) == Character.SPACE_SEPARATOR;
843
- }
844
- }
845
-
846
- private static boolean isJSFormatChar(int c)
847
- {
848
- return c > 127 && Character.getType((char)c) == Character.FORMAT;
849
- }
850
-
851
- /**
852
- * Parser calls the method when it gets / or /= in literal context.
853
- */
854
- void readRegExp(int startToken)
855
- throws IOException
856
- {
857
- stringBufferTop = 0;
858
- if (startToken == Token.ASSIGN_DIV) {
859
- // Miss-scanned /=
860
- addToString('=');
861
- } else {
862
- if (startToken != Token.DIV) Kit.codeBug();
863
- }
864
-
865
- int c;
866
- while ((c = getChar()) != '/') {
867
- if (c == '\n' || c == EOF_CHAR) {
868
- ungetChar(c);
869
- throw parser.reportError("msg.unterminated.re.lit");
870
- }
871
- if (c == '\\') {
872
- addToString(c);
873
- c = getChar();
874
- }
875
-
876
- addToString(c);
877
- }
878
- int reEnd = stringBufferTop;
879
-
880
- while (true) {
881
- if (matchChar('g'))
882
- addToString('g');
883
- else if (matchChar('i'))
884
- addToString('i');
885
- else if (matchChar('m'))
886
- addToString('m');
887
- else
888
- break;
889
- }
890
-
891
- if (isAlpha(peekChar())) {
892
- throw parser.reportError("msg.invalid.re.flag");
893
- }
894
-
895
- this.string = new String(stringBuffer, 0, reEnd);
896
- this.regExpFlags = new String(stringBuffer, reEnd,
897
- stringBufferTop - reEnd);
898
- }
899
-
900
- boolean isXMLAttribute()
901
- {
902
- return xmlIsAttribute;
903
- }
904
-
905
- int getFirstXMLToken() throws IOException
906
- {
907
- xmlOpenTagsCount = 0;
908
- xmlIsAttribute = false;
909
- xmlIsTagContent = false;
910
- ungetChar('<');
911
- return getNextXMLToken();
912
- }
913
-
914
- int getNextXMLToken() throws IOException
915
- {
916
- stringBufferTop = 0; // remember the XML
917
-
918
- for (int c = getChar(); c != EOF_CHAR; c = getChar()) {
919
- if (xmlIsTagContent) {
920
- switch (c) {
921
- case '>':
922
- addToString(c);
923
- xmlIsTagContent = false;
924
- xmlIsAttribute = false;
925
- break;
926
- case '/':
927
- addToString(c);
928
- if (peekChar() == '>') {
929
- c = getChar();
930
- addToString(c);
931
- xmlIsTagContent = false;
932
- xmlOpenTagsCount--;
933
- }
934
- break;
935
- case '{':
936
- ungetChar(c);
937
- this.string = getStringFromBuffer();
938
- return Token.XML;
939
- case '\'':
940
- case '"':
941
- addToString(c);
942
- if (!readQuotedString(c)) return Token.ERROR;
943
- break;
944
- case '=':
945
- addToString(c);
946
- xmlIsAttribute = true;
947
- break;
948
- case ' ':
949
- case '\t':
950
- case '\r':
951
- case '\n':
952
- addToString(c);
953
- break;
954
- default:
955
- addToString(c);
956
- xmlIsAttribute = false;
957
- break;
958
- }
959
-
960
- if (!xmlIsTagContent && xmlOpenTagsCount == 0) {
961
- this.string = getStringFromBuffer();
962
- return Token.XMLEND;
963
- }
964
- } else {
965
- switch (c) {
966
- case '<':
967
- addToString(c);
968
- c = peekChar();
969
- switch (c) {
970
- case '!':
971
- c = getChar(); // Skip !
972
- addToString(c);
973
- c = peekChar();
974
- switch (c) {
975
- case '-':
976
- c = getChar(); // Skip -
977
- addToString(c);
978
- c = getChar();
979
- if (c == '-') {
980
- addToString(c);
981
- if(!readXmlComment()) return Token.ERROR;
982
- } else {
983
- // throw away the string in progress
984
- stringBufferTop = 0;
985
- this.string = null;
986
- parser.addError("msg.XML.bad.form");
987
- return Token.ERROR;
988
- }
989
- break;
990
- case '[':
991
- c = getChar(); // Skip [
992
- addToString(c);
993
- if (getChar() == 'C' &&
994
- getChar() == 'D' &&
995
- getChar() == 'A' &&
996
- getChar() == 'T' &&
997
- getChar() == 'A' &&
998
- getChar() == '[')
999
- {
1000
- addToString('C');
1001
- addToString('D');
1002
- addToString('A');
1003
- addToString('T');
1004
- addToString('A');
1005
- addToString('[');
1006
- if (!readCDATA()) return Token.ERROR;
1007
-
1008
- } else {
1009
- // throw away the string in progress
1010
- stringBufferTop = 0;
1011
- this.string = null;
1012
- parser.addError("msg.XML.bad.form");
1013
- return Token.ERROR;
1014
- }
1015
- break;
1016
- default:
1017
- if(!readEntity()) return Token.ERROR;
1018
- break;
1019
- }
1020
- break;
1021
- case '?':
1022
- c = getChar(); // Skip ?
1023
- addToString(c);
1024
- if (!readPI()) return Token.ERROR;
1025
- break;
1026
- case '/':
1027
- // End tag
1028
- c = getChar(); // Skip /
1029
- addToString(c);
1030
- if (xmlOpenTagsCount == 0) {
1031
- // throw away the string in progress
1032
- stringBufferTop = 0;
1033
- this.string = null;
1034
- parser.addError("msg.XML.bad.form");
1035
- return Token.ERROR;
1036
- }
1037
- xmlIsTagContent = true;
1038
- xmlOpenTagsCount--;
1039
- break;
1040
- default:
1041
- // Start tag
1042
- xmlIsTagContent = true;
1043
- xmlOpenTagsCount++;
1044
- break;
1045
- }
1046
- break;
1047
- case '{':
1048
- ungetChar(c);
1049
- this.string = getStringFromBuffer();
1050
- return Token.XML;
1051
- default:
1052
- addToString(c);
1053
- break;
1054
- }
1055
- }
1056
- }
1057
-
1058
- stringBufferTop = 0; // throw away the string in progress
1059
- this.string = null;
1060
- parser.addError("msg.XML.bad.form");
1061
- return Token.ERROR;
1062
- }
1063
-
1064
- /**
1065
- *
1066
- */
1067
- private boolean readQuotedString(int quote) throws IOException
1068
- {
1069
- for (int c = getChar(); c != EOF_CHAR; c = getChar()) {
1070
- addToString(c);
1071
- if (c == quote) return true;
1072
- }
1073
-
1074
- stringBufferTop = 0; // throw away the string in progress
1075
- this.string = null;
1076
- parser.addError("msg.XML.bad.form");
1077
- return false;
1078
- }
1079
-
1080
- /**
1081
- *
1082
- */
1083
- private boolean readXmlComment() throws IOException
1084
- {
1085
- for (int c = getChar(); c != EOF_CHAR;) {
1086
- addToString(c);
1087
- if (c == '-' && peekChar() == '-') {
1088
- c = getChar();
1089
- addToString(c);
1090
- if (peekChar() == '>') {
1091
- c = getChar(); // Skip >
1092
- addToString(c);
1093
- return true;
1094
- } else {
1095
- continue;
1096
- }
1097
- }
1098
- c = getChar();
1099
- }
1100
-
1101
- stringBufferTop = 0; // throw away the string in progress
1102
- this.string = null;
1103
- parser.addError("msg.XML.bad.form");
1104
- return false;
1105
- }
1106
-
1107
- /**
1108
- *
1109
- */
1110
- private boolean readCDATA() throws IOException
1111
- {
1112
- for (int c = getChar(); c != EOF_CHAR;) {
1113
- addToString(c);
1114
- if (c == ']' && peekChar() == ']') {
1115
- c = getChar();
1116
- addToString(c);
1117
- if (peekChar() == '>') {
1118
- c = getChar(); // Skip >
1119
- addToString(c);
1120
- return true;
1121
- } else {
1122
- continue;
1123
- }
1124
- }
1125
- c = getChar();
1126
- }
1127
-
1128
- stringBufferTop = 0; // throw away the string in progress
1129
- this.string = null;
1130
- parser.addError("msg.XML.bad.form");
1131
- return false;
1132
- }
1133
-
1134
- /**
1135
- *
1136
- */
1137
- private boolean readEntity() throws IOException
1138
- {
1139
- int declTags = 1;
1140
- for (int c = getChar(); c != EOF_CHAR; c = getChar()) {
1141
- addToString(c);
1142
- switch (c) {
1143
- case '<':
1144
- declTags++;
1145
- break;
1146
- case '>':
1147
- declTags--;
1148
- if (declTags == 0) return true;
1149
- break;
1150
- }
1151
- }
1152
-
1153
- stringBufferTop = 0; // throw away the string in progress
1154
- this.string = null;
1155
- parser.addError("msg.XML.bad.form");
1156
- return false;
1157
- }
1158
-
1159
- /**
1160
- *
1161
- */
1162
- private boolean readPI() throws IOException
1163
- {
1164
- for (int c = getChar(); c != EOF_CHAR; c = getChar()) {
1165
- addToString(c);
1166
- if (c == '?' && peekChar() == '>') {
1167
- c = getChar(); // Skip >
1168
- addToString(c);
1169
- return true;
1170
- }
1171
- }
1172
-
1173
- stringBufferTop = 0; // throw away the string in progress
1174
- this.string = null;
1175
- parser.addError("msg.XML.bad.form");
1176
- return false;
1177
- }
1178
-
1179
- private String getStringFromBuffer()
1180
- {
1181
- return new String(stringBuffer, 0, stringBufferTop);
1182
- }
1183
-
1184
- private void addToString(int c)
1185
- {
1186
- int N = stringBufferTop;
1187
- if (N == stringBuffer.length) {
1188
- char[] tmp = new char[stringBuffer.length * 2];
1189
- System.arraycopy(stringBuffer, 0, tmp, 0, N);
1190
- stringBuffer = tmp;
1191
- }
1192
- stringBuffer[N] = (char)c;
1193
- stringBufferTop = N + 1;
1194
- }
1195
-
1196
- private void ungetChar(int c)
1197
- {
1198
- // can not unread past across line boundary
1199
- if (ungetCursor != 0 && ungetBuffer[ungetCursor - 1] == '\n')
1200
- Kit.codeBug();
1201
- ungetBuffer[ungetCursor++] = c;
1202
- }
1203
-
1204
- private boolean matchChar(int test) throws IOException
1205
- {
1206
- int c = getChar();
1207
- if (c == test) {
1208
- return true;
1209
- } else {
1210
- ungetChar(c);
1211
- return false;
1212
- }
1213
- }
1214
-
1215
- private int peekChar() throws IOException
1216
- {
1217
- int c = getChar();
1218
- ungetChar(c);
1219
- return c;
1220
- }
1221
-
1222
- private int getChar() throws IOException
1223
- {
1224
- if (ungetCursor != 0) {
1225
- return ungetBuffer[--ungetCursor];
1226
- }
1227
-
1228
- for(;;) {
1229
- int c;
1230
- if (sourceString != null) {
1231
- if (sourceCursor == sourceEnd) {
1232
- hitEOF = true;
1233
- return EOF_CHAR;
1234
- }
1235
- c = sourceString.charAt(sourceCursor++);
1236
- } else {
1237
- if (sourceCursor == sourceEnd) {
1238
- if (!fillSourceBuffer()) {
1239
- hitEOF = true;
1240
- return EOF_CHAR;
1241
- }
1242
- }
1243
- c = sourceBuffer[sourceCursor++];
1244
- }
1245
-
1246
- if (lineEndChar >= 0) {
1247
- if (lineEndChar == '\r' && c == '\n') {
1248
- lineEndChar = '\n';
1249
- continue;
1250
- }
1251
- lineEndChar = -1;
1252
- lineStart = sourceCursor - 1;
1253
- lineno++;
1254
- }
1255
-
1256
- if (c <= 127) {
1257
- if (c == '\n' || c == '\r') {
1258
- lineEndChar = c;
1259
- c = '\n';
1260
- }
1261
- } else {
1262
- if (isJSFormatChar(c)) {
1263
- continue;
1264
- }
1265
- if (ScriptRuntime.isJSLineTerminator(c)) {
1266
- lineEndChar = c;
1267
- c = '\n';
1268
- }
1269
- }
1270
- return c;
1271
- }
1272
- }
1273
-
1274
- private void skipLine() throws IOException
1275
- {
1276
- // skip to end of line
1277
- int c;
1278
- while ((c = getChar()) != EOF_CHAR && c != '\n') { }
1279
- ungetChar(c);
1280
- }
1281
-
1282
- final int getOffset()
1283
- {
1284
- int n = sourceCursor - lineStart;
1285
- if (lineEndChar >= 0) { --n; }
1286
- return n;
1287
- }
1288
-
1289
- final String getLine()
1290
- {
1291
- if (sourceString != null) {
1292
- // String case
1293
- int lineEnd = sourceCursor;
1294
- if (lineEndChar >= 0) {
1295
- --lineEnd;
1296
- } else {
1297
- for (; lineEnd != sourceEnd; ++lineEnd) {
1298
- int c = sourceString.charAt(lineEnd);
1299
- if (ScriptRuntime.isJSLineTerminator(c)) {
1300
- break;
1301
- }
1302
- }
1303
- }
1304
- return sourceString.substring(lineStart, lineEnd);
1305
- } else {
1306
- // Reader case
1307
- int lineLength = sourceCursor - lineStart;
1308
- if (lineEndChar >= 0) {
1309
- --lineLength;
1310
- } else {
1311
- // Read until the end of line
1312
- for (;; ++lineLength) {
1313
- int i = lineStart + lineLength;
1314
- if (i == sourceEnd) {
1315
- try {
1316
- if (!fillSourceBuffer()) { break; }
1317
- } catch (IOException ioe) {
1318
- // ignore it, we're already displaying an error...
1319
- break;
1320
- }
1321
- // i recalculuation as fillSourceBuffer can move saved
1322
- // line buffer and change lineStart
1323
- i = lineStart + lineLength;
1324
- }
1325
- int c = sourceBuffer[i];
1326
- if (ScriptRuntime.isJSLineTerminator(c)) {
1327
- break;
1328
- }
1329
- }
1330
- }
1331
- return new String(sourceBuffer, lineStart, lineLength);
1332
- }
1333
- }
1334
-
1335
- private boolean fillSourceBuffer() throws IOException
1336
- {
1337
- if (sourceString != null) Kit.codeBug();
1338
- if (sourceEnd == sourceBuffer.length) {
1339
- if (lineStart != 0) {
1340
- System.arraycopy(sourceBuffer, lineStart, sourceBuffer, 0,
1341
- sourceEnd - lineStart);
1342
- sourceEnd -= lineStart;
1343
- sourceCursor -= lineStart;
1344
- lineStart = 0;
1345
- } else {
1346
- char[] tmp = new char[sourceBuffer.length * 2];
1347
- System.arraycopy(sourceBuffer, 0, tmp, 0, sourceEnd);
1348
- sourceBuffer = tmp;
1349
- }
1350
- }
1351
- int n = sourceReader.read(sourceBuffer, sourceEnd,
1352
- sourceBuffer.length - sourceEnd);
1353
- if (n < 0) {
1354
- return false;
1355
- }
1356
- sourceEnd += n;
1357
- return true;
1358
- }
1359
-
1360
- // stuff other than whitespace since start of line
1361
- private boolean dirtyLine;
1362
-
1363
- String regExpFlags;
1364
-
1365
- // Set this to an inital non-null value so that the Parser has
1366
- // something to retrieve even if an error has occured and no
1367
- // string is found. Fosters one class of error, but saves lots of
1368
- // code.
1369
- private String string = "";
1370
- private double number;
1371
-
1372
- private char[] stringBuffer = new char[128];
1373
- private int stringBufferTop;
1374
- private ObjToIntMap allStrings = new ObjToIntMap(50);
1375
-
1376
- // Room to backtrace from to < on failed match of the last - in <!--
1377
- private final int[] ungetBuffer = new int[3];
1378
- private int ungetCursor;
1379
-
1380
- private boolean hitEOF = false;
1381
-
1382
- private int lineStart = 0;
1383
- private int lineno;
1384
- private int lineEndChar = -1;
1385
-
1386
- private String sourceString;
1387
- private Reader sourceReader;
1388
- private char[] sourceBuffer;
1389
- private int sourceEnd;
1390
- private int sourceCursor;
1391
-
1392
- // for xml tokenizer
1393
- private boolean xmlIsAttribute;
1394
- private boolean xmlIsTagContent;
1395
- private int xmlOpenTagsCount;
1396
-
1397
- private Parser parser;
1398
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
lib/Diglin/yuicompressor-2.4.6/tests/README DELETED
@@ -1,6 +0,0 @@
1
- To add a test:
2
-
3
- 1. Create a "blah.css" or "blah.js" file.
4
- 2. Create a "blah.css.min" or "blah.js.min" file, containing the expected minified output.
5
-
6
- That's all!
 
 
 
 
 
 
lib/Diglin/yuicompressor-2.4.6/tests/_munge.js DELETED
@@ -1,8 +0,0 @@
1
- (function() {
2
- var w = window;
3
-
4
- w.hello = function(a, abc) {
5
- "a:nomunge";
6
- w.alert("Hello, " + a);
7
- };
8
- })();
 
 
 
 
 
 
 
 
lib/Diglin/yuicompressor-2.4.6/tests/_munge.js.min DELETED
@@ -1 +0,0 @@
1
- (function(){var a=window;a.hello=function(a,b){a.alert("Hello, "+a)}})();
 
lib/Diglin/yuicompressor-2.4.6/tests/_string_combo.js DELETED
@@ -1,5 +0,0 @@
1
- function test(){
2
- var a = "a" +
3
- "b" +
4
- "c";
5
- }
 
 
 
 
 
lib/Diglin/yuicompressor-2.4.6/tests/_string_combo.js.min DELETED
@@ -1 +0,0 @@
1
- function test(){var b="abc"};
 
lib/Diglin/yuicompressor-2.4.6/tests/_syntax_error.js DELETED
@@ -1,73 +0,0 @@
1
-
2
- window.$ = $telerik.$;
3
- $(document).ready(function() {
4
- movePageElements();
5
-
6
- var text = $('textarea').val();
7
-
8
- if (text != "")
9
- $('textarea').attr("style", "display: block;");
10
- else
11
- $('textarea').attr("style", "display: none;");
12
-
13
- //cleanup
14
- text = null;
15
- });
16
-
17
- function movePageElements() {
18
- var num = null;
19
- var pagenum = $(".pagecontrolscontainer");
20
- if (pagenum.length > 0) {
21
- var num = pagenum.attr("pagenumber");
22
- if ((num > 5) && (num < 28)) {
23
- var x = $('div#commentbutton');
24
- $("div.buttonContainer").prepend(x);
25
- }
26
- else {
27
- $('div#commentbutton').attr("style", "display: none;");
28
- }
29
- }
30
-
31
- //Add in dropshadowing
32
- if ((num > 5) && (num < 28)) {
33
- var top = $('.dropshadow-top');
34
- var middle = $('#dropshadow');
35
- var bottom = $('.dropshadow-bottom');
36
- $('#page').prepend(top);
37
- $('#topcontainer').after(middle);
38
- middle.append($('#topcontainer'));
39
- middle.after(bottom);
40
- }
41
-
42
- //cleanup
43
- num = null;
44
- pagenum = null;
45
- top = null;
46
- middle = null;
47
- bottom=null;
48
- }
49
-
50
- function expandCollapseDiv(id) {
51
- $telerik.$(id).slideToggle("slow");
52
- }
53
-
54
- function expandCollapseHelp() {
55
- $('.helpitems').slideToggle("slow");
56
-
57
- //Add in dropshadowing
58
- if ($('#helpcontainer').length) {
59
- $('#help-dropshadow-bot').insertAfter('#helpcontainer');
60
- $('#help-dropshadow-bot').removeAttr("style");
61
- }
62
- }
63
-
64
- function expandCollapseComments() {
65
- var style = $('textarea').attr("style");
66
- if (style == "display: none;")
67
- $('textarea').fadeIn().focus();
68
- else
69
- $('textarea').fadeOut();
70
-
71
- //cleanup
72
- style = null;
73
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
lib/Diglin/yuicompressor-2.4.6/tests/_syntax_error.js.min DELETED
@@ -1 +0,0 @@
1
- window.$=$telerik.$;$(document).ready(function(){movePageElements();var a=$("textarea").val();if(a!=""){$("textarea").attr("style","display: block;")}else{$("textarea").attr("style","display: none;")}a=null});function movePageElements(){var e=null;var b=$(".pagecontrolscontainer");if(b.length>0){var e=b.attr("pagenumber");if((e>5)&&(e<28)){var a=$("div#commentbutton");$("div.buttonContainer").prepend(a)}else{$("div#commentbutton").attr("style","display: none;")}}if((e>5)&&(e<28)){var f=$(".dropshadow-top");var d=$("#dropshadow");var c=$(".dropshadow-bottom");$("#page").prepend(f);$("#topcontainer").after(d);d.append($("#topcontainer"));d.after(c)}e=null;b=null;f=null;d=null;c=null}function expandCollapseDiv(a){$telerik.$(a).slideToggle("slow")}function expandCollapseHelp(){$(".helpitems").slideToggle("slow");if($("#helpcontainer").length){$("#help-dropshadow-bot").insertAfter("#helpcontainer");$("#help-dropshadow-bot").removeAttr("style")}}function expandCollapseComments(){var a=$("textarea").attr("style");if(a=="display: none;"){$("textarea").fadeIn().focus()}else{$("textarea").fadeOut()}a=null};
 
lib/Diglin/yuicompressor-2.4.6/tests/background-position.css DELETED
@@ -1,2 +0,0 @@
1
- a {background-position: 0 0 0 0;}
2
- b {BACKGROUND-POSITION: 0 0;}
 
 
lib/Diglin/yuicompressor-2.4.6/tests/background-position.css.min DELETED
@@ -1 +0,0 @@
1
- a{background-position:0 0}b{background-position:0 0}
 
lib/Diglin/yuicompressor-2.4.6/tests/border-none.css DELETED
@@ -1,5 +0,0 @@
1
- a {
2
- border: none;
3
- }
4
- b {BACKGROUND:none}
5
- s {border-top: none;}
 
 
 
 
 
lib/Diglin/yuicompressor-2.4.6/tests/border-none.css.min DELETED
@@ -1 +0,0 @@
1
- a{border:0}b{background:0}s{border-top:0}
 
lib/Diglin/yuicompressor-2.4.6/tests/box-model-hack.css DELETED
@@ -1,9 +0,0 @@
1
- #elem {
2
- width: 100px;
3
- voice-family: "\"}\"";
4
- voice-family:inherit;
5
- width: 200px;
6
- }
7
- html>body #elem {
8
- width: 200px;
9
- }
 
 
 
 
 
 
 
 
 
lib/Diglin/yuicompressor-2.4.6/tests/box-model-hack.css.min DELETED
@@ -1 +0,0 @@
1
- #elem{width:100px;voice-family:"\"}\"";voice-family:inherit;width:200px}html>body #elem{width:200px}
 
lib/Diglin/yuicompressor-2.4.6/tests/bug2527974.css DELETED
@@ -1,10 +0,0 @@
1
- /* this file contains no css, it exists purely to put the revision number into the
2
- combined css before uploading it to SiteManager. The exclaimation at the start
3
- of the comment informs yuicompressor not to strip the comment out */
4
-
5
- /*! $LastChangedRevision: 81 $ $LastChangedDate: 2009-05-27 17:41:02 +0100 (Wed, 27 May 2009) $ */
6
-
7
- body {
8
- yo: cats;
9
- }
10
- ul[id$=foo] label:hover {yo: yo;}
 
 
 
 
 
 
 
 
 
 
lib/Diglin/yuicompressor-2.4.6/tests/bug2527974.css.min DELETED
@@ -1 +0,0 @@
1
- /*! $LastChangedRevision: 81 $ $LastChangedDate: 2009-05-27 17:41:02 +0100 (Wed, 27 May 2009) $ */body{yo:cats}ul[id$=foo] label:hover{yo:yo}
 
lib/Diglin/yuicompressor-2.4.6/tests/bug2527991.css DELETED
@@ -1,19 +0,0 @@
1
- @media screen and/*!YUI-Compresser */(-webkit-min-device-pixel-ratio:0) {
2
- a{
3
- b: 1;
4
- }
5
- }
6
-
7
-
8
- @media screen and/*! */ /*! */(-webkit-min-device-pixel-ratio:0) {
9
- a{
10
- b: 1;
11
- }
12
- }
13
-
14
-
15
- @media -webkit-min-device-pixel-ratio:0 {
16
- a{
17
- b: 1;
18
- }
19
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
lib/Diglin/yuicompressor-2.4.6/tests/bug2527991.css.min DELETED
@@ -1 +0,0 @@
1
- @media screen and/*!YUI-Compresser */(-webkit-min-device-pixel-ratio:0){a{b:1}}@media screen and/*! *//*! */(-webkit-min-device-pixel-ratio:0){a{b:1}}@media -webkit-min-device-pixel-ratio:0{a{b:1}}
 
lib/Diglin/yuicompressor-2.4.6/tests/bug2527998.css DELETED
@@ -1,4 +0,0 @@
1
- /*! special */
2
- body {
3
-
4
- }
 
 
 
 
lib/Diglin/yuicompressor-2.4.6/tests/bug2527998.css.min DELETED
@@ -1 +0,0 @@
1
- /*! special */
 
lib/Diglin/yuicompressor-2.4.6/tests/bug2528034.css DELETED
@@ -1,5 +0,0 @@
1
- a[href$="/test/"] span:first-child { b:1; }
2
- a[href$="/test/"] span:first-child { }
3
-
4
-
5
-
 
 
 
 
 
lib/Diglin/yuicompressor-2.4.6/tests/bug2528034.css.min DELETED
@@ -1 +0,0 @@
1
- a[href$="/test/"] span:first-child{b:1}
 
lib/Diglin/yuicompressor-2.4.6/tests/charset-media.css DELETED
@@ -1,9 +0,0 @@
1
- /* re: 2495387 */
2
- @charset 'utf-8';
3
- @media all {
4
- body {
5
- }
6
- body {
7
- background-color: gold;
8
- }
9
- }
 
 
 
 
 
 
 
 
 
lib/Diglin/yuicompressor-2.4.6/tests/charset-media.css.min DELETED
@@ -1 +0,0 @@
1
- @charset 'utf-8';@media all{body{background-color:gold}}
 
lib/Diglin/yuicompressor-2.4.6/tests/color.css DELETED
@@ -1,7 +0,0 @@
1
- .color {
2
- me: rgb(123, 123, 123);
3
- impressed: #ffeedd;
4
- filter: chroma(color="#FFFFFF");
5
- background: none repeat scroll 0 0 rgb(255, 0,0);
6
- alpha: rgba(1, 2, 3, 4);
7
- }
 
 
 
 
 
 
 
lib/Diglin/yuicompressor-2.4.6/tests/color.css.min DELETED
@@ -1 +0,0 @@
1
- .color{me:#7b7b7b;impressed:#fed;filter:chroma(color="#FFFFFF");background:none repeat scroll 0 0 #f00;alpha:rgba(1,2,3,4)}
 
lib/Diglin/yuicompressor-2.4.6/tests/comment.css DELETED
@@ -1,3 +0,0 @@
1
- html >/**/ body p {
2
- color: blue;
3
- }
 
 
 
lib/Diglin/yuicompressor-2.4.6/tests/comment.css.min DELETED
@@ -1 +0,0 @@
1
- html>/**/body p{color:blue}
 
lib/Diglin/yuicompressor-2.4.6/tests/concat-charset.css DELETED
@@ -1,15 +0,0 @@
1
- /* This is invalid CSS, but frequently happens as a result of concatenation. */
2
- @charset "utf-8";
3
- #foo {
4
- border-width:1px;
5
- }
6
- /*
7
- Note that this is erroneous!
8
- The actual CSS file can only have a single charset.
9
- However, this is the job of the author/application.
10
- The compressor should not get involved.
11
- */
12
- @charset "another one";
13
- #bar {
14
- border-width:10px;
15
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
lib/Diglin/yuicompressor-2.4.6/tests/concat-charset.css.min DELETED
@@ -1 +0,0 @@
1
- @charset "utf-8";#foo{border-width:1px}#bar{border-width:10px}
 
lib/Diglin/yuicompressor-2.4.6/tests/decimals.css DELETED
@@ -1,3 +0,0 @@
1
- ::selection {
2
- margin: 0.6px 0.333pt 1.2em 8.8cm;
3
- }
 
 
 
lib/Diglin/yuicompressor-2.4.6/tests/decimals.css.min DELETED
@@ -1 +0,0 @@
1
- ::selection{margin:.6px .333pt 1.2em 8.8cm}
 
lib/Diglin/yuicompressor-2.4.6/tests/dollar-header.css DELETED
@@ -1,7 +0,0 @@
1
- /*!
2
- $Header: /temp/dirname/filename.css 3 2/02/08 3:37p JSmith $
3
- */
4
-
5
- foo {
6
- bar: baz
7
- }
 
 
 
 
 
 
 
lib/Diglin/yuicompressor-2.4.6/tests/dollar-header.css.min DELETED
@@ -1,3 +0,0 @@
1
- /*!
2
- $Header: /temp/dirname/filename.css 3 2/02/08 3:37p JSmith $
3
- */foo{bar:baz}
 
 
 
lib/Diglin/yuicompressor-2.4.6/tests/float.js DELETED
@@ -1,2 +0,0 @@
1
- obj.css({"float": "left"});
2
- obj.css({cssFloat:"left"});
 
 
lib/Diglin/yuicompressor-2.4.6/tests/float.js.min DELETED
@@ -1 +0,0 @@
1
- obj.css({"float":"left"});obj.css({cssFloat:"left"});
 
lib/Diglin/yuicompressor-2.4.6/tests/font-face.css DELETED
@@ -1,6 +0,0 @@
1
- @font-face {
2
- font-family: 'gzipper';
3
- src: url(yanone.eot);
4
- src: local('gzipper'),
5
- url(yanone.ttf) format('truetype');
6
- }
 
 
 
 
 
 
lib/Diglin/yuicompressor-2.4.6/tests/font-face.css.min DELETED
@@ -1 +0,0 @@
1
- @font-face{font-family:'gzipper';src:url(yanone.eot);src:local('gzipper'),url(yanone.ttf) format('truetype')}
 
lib/Diglin/yuicompressor-2.4.6/tests/ie5mac.css DELETED
@@ -1,5 +0,0 @@
1
- /* Ignore the next rule in IE mac \*/
2
- .selector {
3
- color: khaki;
4
- }
5
- /* Stop ignoring in IE mac */
 
 
 
 
 
lib/Diglin/yuicompressor-2.4.6/tests/ie5mac.css.min DELETED
@@ -1 +0,0 @@
1
- /*\*/.selector{color:khaki}/**/
 
lib/Diglin/yuicompressor-2.4.6/tests/media-empty-class.css DELETED
@@ -1,16 +0,0 @@
1
- /*! preserved */
2
- emptiness {}
3
-
4
- @import "another.css";
5
- /* I'm empty - delete me */
6
- empty { ;}
7
-
8
- @media print {
9
- .noprint { display: none; }
10
- }
11
-
12
- @media screen {
13
- /* this rule should be removed, not simply minified.*/
14
- .breakme {}
15
- .printonly { display: none; }
16
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
lib/Diglin/yuicompressor-2.4.6/tests/media-empty-class.css.min DELETED
@@ -1 +0,0 @@
1
- /*! preserved */@import "another.css";@media print{.noprint{display:none}}@media screen{.printonly{display:none}}
 
lib/Diglin/yuicompressor-2.4.6/tests/media-multi.css DELETED
@@ -1,3 +0,0 @@
1
- @media only all and (max-width:50em), only all and (max-device-width:800px), only all and (max-width:780px) {
2
- some-css : here
3
- }
 
 
 
lib/Diglin/yuicompressor-2.4.6/tests/media-multi.css.min DELETED
@@ -1 +0,0 @@
1
- @media only all and (max-width:50em),only all and (max-device-width:800px),only all and (max-width:780px){some-css:here}
 
lib/Diglin/yuicompressor-2.4.6/tests/media-test.css DELETED
@@ -1,3 +0,0 @@
1
- @media screen and (-webkit-min-device-pixel-ratio:0) {
2
- some-css : here
3
- }
 
 
 
lib/Diglin/yuicompressor-2.4.6/tests/media-test.css.min DELETED
@@ -1 +0,0 @@
1
- @media screen and (-webkit-min-device-pixel-ratio:0){some-css:here}
 
lib/Diglin/yuicompressor-2.4.6/tests/opacity-filter.css DELETED
@@ -1,14 +0,0 @@
1
- /* example from https://developer.mozilla.org/en/CSS/opacity */
2
- pre { /* make the box translucent (80% opaque) */
3
- border: solid red;
4
- opacity: 0.8; /* Firefox, Safari(WebKit), Opera */
5
- -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=80)"; /* IE 8 */
6
- filter: PROGID:DXImageTransform.Microsoft.Alpha(Opacity=80); /* IE 4-7 */
7
- zoom: 1; /* set "zoom", "width" or "height" to trigger "hasLayout" in IE 7 and lower */
8
- }
9
-
10
- /** and again */
11
- code {
12
- -ms-filter: "PROGID:DXImageTransform.Microsoft.Alpha(Opacity=80)"; /* IE 8 */
13
- filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=80); /* IE 4-7 */
14
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
lib/Diglin/yuicompressor-2.4.6/tests/opacity-filter.css.min DELETED
@@ -1 +0,0 @@
1
- pre{border:solid red;opacity:.8;-ms-filter:"alpha(opacity=80)";filter:alpha(opacity=80);zoom:1}code{-ms-filter:"alpha(opacity=80)";filter:alpha(opacity=80)}
 
lib/Diglin/yuicompressor-2.4.6/tests/preserve-new-line.css DELETED
@@ -1,6 +0,0 @@
1
- #sel-o {
2
- content: "on\"ce upon \
3
- a time";
4
- content: 'once upon \
5
- a ti\'me';
6
- }
 
 
 
 
 
 
lib/Diglin/yuicompressor-2.4.6/tests/preserve-new-line.css.min DELETED
@@ -1,3 +0,0 @@
1
- #sel-o{content:"on\"ce upon \
2
- a time";content:'once upon \
3
- a ti\'me'}
 
 
 
lib/Diglin/yuicompressor-2.4.6/tests/preserve-strings.css DELETED
@@ -1,7 +0,0 @@
1
- /* preserving strings */
2
- .sele {
3
- content: "\"keep \" me";
4
- something: '\\\' . . ';
5
- else: 'empty{}';
6
- content: "/* test */"; /* <---- this is not a comment, should be be kept */
7
- }
 
 
 
 
 
 
 
lib/Diglin/yuicompressor-2.4.6/tests/preserve-strings.css.min DELETED
@@ -1 +0,0 @@
1
- .sele{content:"\"keep \" me";something:'\\\' . . ';else:'empty{}';content:"/* test */"}
 
lib/Diglin/yuicompressor-2.4.6/tests/pseudo-first.css DELETED
@@ -1,16 +0,0 @@
1
- /*
2
- because of IE6 first-letter and first-line
3
- must be followed by a space
4
- http://reference.sitepoint.com/css/pseudoelement-firstletter
5
- Thanks: P.Sorokin comment at http://www.phpied.com/cssmin-js/
6
- */
7
- p:first-letter{
8
- buh: hum;
9
- }
10
- p:first-line{
11
- baa: 1;
12
- }
13
-
14
- p:first-line,a,p:first-letter,b{
15
- color: red;
16
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
lib/Diglin/yuicompressor-2.4.6/tests/pseudo-first.css.min DELETED
@@ -1 +0,0 @@
1
- p:first-letter {buh:hum}p:first-line {baa:1}p:first-line ,a,p:first-letter ,b{color:red}
 
lib/Diglin/yuicompressor-2.4.6/tests/pseudo.css DELETED
@@ -1,4 +0,0 @@
1
- p :link {
2
- ba:zinga;;;
3
- foo: bar;;;
4
- }
 
 
 
 
lib/Diglin/yuicompressor-2.4.6/tests/pseudo.css.min DELETED
@@ -1 +0,0 @@
1
- p :link{ba:zinga;foo:bar}
 
lib/Diglin/yuicompressor-2.4.6/tests/special-comments.css DELETED
@@ -1,13 +0,0 @@
1
- /*!************88****
2
- Preserving comments
3
- as they are
4
- ********************
5
- Keep the initial !
6
- *******************/
7
- #yo {
8
- ma: "ma";
9
- }
10
- /*!
11
- I said
12
- pre-
13
- serve! */
 
 
 
 
 
 
 
 
 
 
 
 
 
lib/Diglin/yuicompressor-2.4.6/tests/special-comments.css.min DELETED
@@ -1,9 +0,0 @@
1
- /*!************88****
2
- Preserving comments
3
- as they are
4
- ********************
5
- Keep the initial !
6
- *******************/#yo{ma:"ma"}/*!
7
- I said
8
- pre-
9
- serve! */
 
 
 
 
 
 
 
 
 
lib/Diglin/yuicompressor-2.4.6/tests/star-underscore-hacks.css DELETED
@@ -1,5 +0,0 @@
1
- #elementarr {
2
- width: 1px;
3
- *width: 3pt;
4
- _width: 2em;
5
- }
 
 
 
 
 
lib/Diglin/yuicompressor-2.4.6/tests/star-underscore-hacks.css.min DELETED
@@ -1 +0,0 @@
1
- #elementarr{width:1px;*width:3pt;_width:2em}
 
lib/Diglin/yuicompressor-2.4.6/tests/string-in-comment.css DELETED
@@ -1,8 +0,0 @@
1
- /* te " st */
2
- a{a:1}
3
- /*!"preserve" me*/
4
- b{content: "/**/"}
5
- /* quite " quote ' \' \" */
6
- /* ie mac \*/
7
- c {c : 3}
8
- /* end hiding */
 
 
 
 
 
 
 
 
lib/Diglin/yuicompressor-2.4.6/tests/string-in-comment.css.min DELETED
@@ -1 +0,0 @@
1
- a{a:1}/*!"preserve" me*/b{content:"/**/"}/*\*/c{c:3}/**/
 
lib/Diglin/yuicompressor-2.4.6/tests/suite.rhino DELETED
@@ -1,3 +0,0 @@
1
- input = readFile(arguments[0]);
2
- load("../ports/js/cssmin.js");
3
- print(YAHOO.compressor.cssmin(input));
 
 
 
lib/Diglin/yuicompressor-2.4.6/tests/suite.sh DELETED
@@ -1,62 +0,0 @@
1
- #!/usr/bin/env bash
2
-
3
- cd $(dirname $0)
4
-
5
- # Get the jar to use.
6
- jar="$(ls ../build/*.jar | sort | tail -n1)"
7
- echo "jar: $jar"
8
-
9
- runtest () {
10
- testfile="$1"
11
- expected=${testfile/\.FAIL/}.min
12
- expected="$(
13
- cat $expected
14
- )"
15
- filetype="$(
16
- echo $testfile | egrep -o '(cs|j)s'
17
- )"
18
-
19
- if [ "$2" == "cssminjs" ]; then
20
- actual="$(
21
- java -jar ../lib/rhino-1.6R7.jar suite.rhino $testfile
22
- )"
23
-
24
- else
25
- actual="$(
26
- java -jar $jar --type $filetype $testfile
27
- )"
28
- fi
29
-
30
- if [ "$expected" == "$actual" ]; then
31
- echo "Passed: $testfile" > /dev/stderr
32
- else
33
- (
34
- echo "Test failed: $testfile"
35
- echo ""
36
- echo "Expected:"
37
- echo "$expected"
38
- echo ""
39
- echo "Actual:"
40
- echo "$actual"
41
- ) > /dev/stderr
42
- return 1
43
- fi
44
- }
45
-
46
-
47
- ls *.FAIL | while read failtest; do
48
- echo "Failing test: " $failtest > /dev/stderr
49
- runtest $failtest && echo "Test passed, please remove the '.FAIL' from the filename"
50
- done
51
-
52
- ls *.{css,js} | while read testfile; do
53
- runtest $testfile || exit 1
54
- done
55
-
56
- echo
57
- echo "now testing the JS port of CSSMIN..."
58
- ls *.css | while read testfile; do
59
- runtest $testfile "cssminjs" || exit 1
60
- done
61
-
62
- exit 0
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
lib/Diglin/yuicompressor-2.4.6/tests/webkit-transform.css DELETED
@@ -1,2 +0,0 @@
1
- c {-webkit-transform-origin: 0 0;}
2
- d {-MOZ-TRANSFORM-ORIGIN: 0 0 }
 
 
lib/Diglin/yuicompressor-2.4.6/tests/webkit-transform.css.min DELETED
@@ -1 +0,0 @@
1
- c{-webkit-transform-origin:0 0}d{-moz-transform-origin:0 0}
 
lib/Diglin/yuicompressor-2.4.6/tests/zeros.css DELETED
@@ -1,6 +0,0 @@
1
- a {
2
- margin: 0px 0pt 0em 0%;
3
- _padding-top: 0ex;
4
- background-position: 0 0;
5
- padding: 0in 0cm 0mm 0pc
6
- }
 
 
 
 
 
 
lib/Diglin/yuicompressor-2.4.6/tests/zeros.css.min DELETED
@@ -1 +0,0 @@
1
- a{margin:0;_padding-top:0;background-position:0 0;padding:0}
 
lib/Diglin/yuicompressor/.DS_Store ADDED
Binary file
lib/Diglin/{yuicompressor-2.4.6/build/yuicompressor-2.4.6.jar → yuicompressor/yuicompressor-2.4.7.jar} RENAMED
Binary file
lib/Diglin/{yuicompressor-2.4.6/lib/rhino-1.6R7.jar → yuicompressor/yuicompressor.jar} RENAMED
Binary file
package.xml CHANGED
@@ -1,7 +1,7 @@
1
  <?xml version="1.0"?>
2
  <package>
3
  <name>Diglin_UIOptimization</name>
4
- <version>1.3.0</version>
5
  <stability>stable</stability>
6
  <license uri="http://www.opensource.org/licenses/osl-3.0.php">OSL v3.0</license>
7
  <channel>community</channel>
@@ -44,7 +44,9 @@ Inspired by the module from Yoast, this feature allows you to create canonical u
44
  - An assistant will be available soon&#xD;
45
  - Follow the instruction in the configuration page&#xD;
46
  - In case of Access Denied in the backend: clear your cache, logout/login. In case, it still doesn't work, save again the user role in System &gt; Permissions &gt; Roles.</description>
47
- <notes>- Version 1.3.0: improve canonical url generation, improve some configuration parameters, remove the option JS Packer because incompatible with Magento&#xD;
 
 
48
  - Version 1.2.0: improve compatibility with compilation feature of Magento, add a js/css flush button directly in the configuration page&#xD;
49
  - Version 1.1.0: rewrite some classes of the minify libraries to respect PHP 5 and prevent some errors, change the module name, make it compatible with compilation feature of Magento, add canonical url feature for SEO&#xD;
50
  - Version 1.0.10: fix type for css files stored in /js/ folder&#xD;
@@ -53,9 +55,9 @@ Inspired by the module from Yoast, this feature allows you to create canonical u
53
  - Version 1.0.2: add cron task to allow to update compressed/minified js/css files periodically&#xD;
54
  - Version 1.0.1: fix a missing config element class, this class seems to exists only since 1.4.1 or more</notes>
55
  <authors><author><name>diglin</name><user>auto-converted</user><email>sly@diglin.com</email></author></authors>
56
- <date>2012-01-15</date>
57
- <time>17:08:26</time>
58
- <contents><target name="magecommunity"><dir name="Diglin"><dir name="UIOptimization"><dir name="Block"><dir name="Adminhtml"><dir name="Config"><dir name="Source"><file name="Heading.php" hash="d15c30ac285cdff33a2ab32eb59cb564"/><file name="Hint.php" hash="01e1ea4a67c60e6ef987b5800c9723aa"/></dir></dir></dir><dir name="Optimize"><file name="Head.php" hash="3afe236f07364a8241a444863788558d"/></dir><file name="W3Ccssvalidator.php" hash="43f2e40257bc6d729f55ff86f892ffd9"/><file name="W3Chtmlvalidator.php" hash="3bb405092f65ce69f1de065074e938ef"/></dir><dir name="Helper"><file name="Data.php" hash="0a636bc27bdcb38796021b158ade7dbe"/></dir><dir name="Model"><dir name="Config"><dir name="Source"><file name="Caseproperties.php" hash="71ecf181882b3ba86f34e9b13688b818"/><file name="Charset.php" hash="ed5b2d44ac015ad7a2e47e5256fcf326"/><file name="Csslevel.php" hash="a4c463268772612d76fa8cb01d48b394"/><file name="Csstypeminify.php" hash="ac3a3407105923255c212aabfdb7839e"/><file name="Doctype.php" hash="25f7b13fa0fb7eca9325c91fa84f1f66"/><file name="Jstypeminify.php" hash="e56cf7fc3ab95320d786972355b5176f"/><file name="Language.php" hash="2824c01f7014bc9c2a01bba519bf0d70"/><file name="Mergeselectors.php" hash="70e30f4f5e303b045838991184841409"/><file name="Optishorthand.php" hash="a66d0a74e0e659ddabc26d12fe30333a"/><file name="Profile.php" hash="4e4245d513a11ea2e48648d15f048952"/><file name="Template.php" hash="512a4faca68c7bb11b75ced04ec3fd23"/><file name="Usermedium.php" hash="53748dbbb513cf47e0a5ff6aa1f45947"/><file name="Warning.php" hash="375871ff5f28fb6c0679b7b935df638e"/></dir></dir><dir name="Overwrite"><dir name="Design"><file name="Package.php" hash="9026106a0a9a5b00a95b3c36249d71a7"/></dir></dir><file name="Observer.php" hash="3b5ccbf0aef2289fe9d0d054d760478f"/></dir><dir name="etc"><file name="adminhtml.xml" hash="cde46a100bc94df35ce1fc8896e87514"/><file name="config.xml" hash="7f97187cec7f3d9c9e0c9c91e54b7018"/><file name="system.xml" hash="9acbc1244d4eb9568f611a3d625b7cca"/></dir></dir></dir></target><target name="magelib"><dir name="Diglin"><dir name="Csstidy"><file name="Core.php" hash="820e39515baba186803453eaf735bb5d"/><file name="Optimise.php" hash="3694084e725ba252b623492d0d09a67d"/><file name="Print.php" hash="203c86314418bc2b70fcb8beccafea3b"/><file name="README" hash="3a3e2ddf61de1689e042291b821262b0"/><file name="data.inc.php" hash="516492aeb1c37bb2a869863d9f2a21a1"/></dir><dir name="HTTP"><dir name="Request2"><dir name="Adapter"><file name="Curl.php" hash="e7a010aee80ee8dcfe73b5efc0890726"/><file name="Mock.php" hash="d33b4f9fdebdfad58034f4fe028a111c"/><file name="Socket.php" hash="ced36e7a1a3ed7a3adad46518c1954c2"/></dir><dir name="Observer"><file name="Log.php" hash="9aefde329905d25619d16f525bee9c6d"/></dir><file name="Adapter.php" hash="9f90535b4b7bff4a7052f767579b0ff1"/><file name="Exception.php" hash="ce7b316eaedcd5928a57e74725539fa6"/><file name="MultipartBody.php" hash="7073427f223db55059eca79cac36bbc1"/><file name="Response.php" hash="bdbcb96eadd6549d916f95acf45a0268"/></dir><file name="ConditionalGet.php" hash="5fb451fba76286fa28323f53f1870daf"/><file name="Encoder.php" hash="37a2b8e6bcb2908162e2881be93040a6"/><file name="Request2.php" hash="73fec75564cceac997605763812f061f"/></dir><dir name="Io"><file name="File.php" hash="d1b4545aeac7030d6991cf9310194b37"/></dir><dir name="Minify"><dir name="CSS"><file name="Compressor.php" hash="7382e9fe1dc08eef2b06fa016ed2dde8"/><file name="UriRewriter.php" hash="0585d4c22e773319b1616caa04ee253d"/></dir><dir name="Cache"><file name="APC.php" hash="6cab72f5c2a8cbe72f0751e7fdb35299"/><file name="File.php" hash="a0b06218ace157a91e8581481207554e"/><file name="Memcache.php" hash="92b3b852552e54fee0746beaeecfd920"/></dir><dir name="Controller"><file name="Base.php" hash="93d54ee900c594dae559a20d020d6eaa"/><file name="Files.php" hash="510d15562a7b77eafb3d366dea9cfcc9"/><file name="Groups.php" hash="cbf4869e3d9f99d56b9581f8477e78a3"/><file name="MinApp.php" hash="15a18fbc0cc30664e08ea880f4538215"/><file name="Page.php" hash="650d9edc5cfddd92027e6b7b257568f9"/><file name="Version1.php" hash="9a8fbce1285b08047393442e556adf89"/></dir><file name="Build.php" hash="78fe924cecb08a507f6c8fde9090dca5"/><file name="CSS.php" hash="128ff0cb67f075f175a51d0f9aac7469"/><file name="CommentPreserver.php" hash="efab6711d7ec10b046a58826dc314d21"/><file name="HTML.php" hash="ef58c0cf87dbec2f0301330062781b27"/><file name="ImportProcessor.php" hash="29379d4088d36d706ebaca5c7649ed27"/><file name="Lines.php" hash="ca9d9d718035dfb400c77568c9692f7c"/><file name="Logger.php" hash="b92325836feb2e64992ff931dd9b7454"/><file name="Packer.php" hash="ddc1e068af1043089764c80eaded7d81"/><file name="Source.php" hash="d9cbdc2851722a509157ab469b681b22"/><file name="YUICompressor.php" hash="4b73c98c6b650f54a96a264f3e0f0c8d"/></dir><dir name="Net"><file name="URL2.php" hash="65e54166dcf0994507459d0ad5b97a2c"/></dir><dir name="Services"><dir name="W3C"><dir name="CSSValidator"><file name="Error.php" hash="41cfd8ca38ef335ce03e75802c57ab81"/><file name="Message.php" hash="9d83bc04fdf945dc51d9974d6f626cfc"/><file name="Response.php" hash="7ae2b76ba7fdf008d06818596628f05f"/><file name="Warning.php" hash="3b654f71af352d5be419ef968323968f"/></dir><dir name="HTMLValidator"><file name="Error.php" hash="39139614730155f1cb70f8e35997cf09"/><file name="Exception.php" hash="133012d58d41064e2712ca93fee77ca4"/><file name="Message.php" hash="dcbdb982c3308598b8c2cd69caf591ff"/><file name="Response.php" hash="b263217ee5da08f275a77357d08efcf9"/><file name="Warning.php" hash="1f5f024525ead59be6adf39f78e93615"/></dir><file name="CSSValidator.php" hash="ae14a24c658a28adf2f4cbf3e2af17f8"/><file name="HTMLValidator.php" hash="75ac95c991d238fe10a2d4e54c6d2a07"/></dir></dir><dir name="Solar"><file name="Dir.php" hash="e71fa00999543f6c14960fffc7fe4f59"/></dir><dir name="yuicompressor-2.4.6"><dir name="build"><file name="yuicompressor-2.4.6.jar" hash="5980f34fce5868e93b174b23c329621f"/></dir><dir name="doc"><file name="CHANGELOG" hash="b6d3100c68ad7036035e6e71fb206750"/><file name="README" hash="aa4ae25f7cfb788a812695a05be0e138"/></dir><dir name="lib"><file name="jargs-1.0.jar" hash="6f3f1d7e5551b3a2c4f79a7a84304b7a"/><file name="rhino-1.6R7.jar" hash="4995caee1cf36af248f15df2b8ef4341"/></dir><dir name="ports"><dir name="js"><file name="cssmin.js" hash="04309be589d746e48e795205cf429b39"/></dir></dir><dir name="src"><dir name="com"><dir name="yahoo"><dir name="platform"><dir name="yui"><dir name="compressor"><file name="Bootstrap.java" hash="75e756e228a5c49974b807d02489cd13"/><file name="CssCompressor.java" hash="078bdea7f6d2f63af247229bc556673a"/><file name="JarClassLoader.java" hash="0bf8ae8b53566978478366a633827619"/><file name="JavaScriptCompressor.java" hash="7256d1f34ba3d01c8c3c525ffe16356c"/><file name="JavaScriptIdentifier.java" hash="49057621077a57034de36ff7d007fdc9"/><file name="JavaScriptToken.java" hash="370ac3982265e40052abe16ba4334219"/><file name="ScriptOrFnScope.java" hash="ed4f8de953c9ffd8ea281ae3eae0ee66"/><file name="YUICompressor.java" hash="19b36089bf5bf63011ec3f4ac758cfaf"/></dir></dir></dir></dir></dir><dir name="org"><dir name="mozilla"><dir name="javascript"><file name="Decompiler.java" hash="327ed36ff8c1f651571c3ce520be426e"/><file name="Decompiler.java.orig" hash="698d9ebaee2581d256d099a758b4071f"/><file name="Parser.java" hash="767abd69b48339d77c59184084158332"/><file name="Parser.java.orig" hash="7a699bb6a92d111912ae500e5cd38624"/><file name="Token.java" hash="e6f0f5ad85ec89b2cc2f0d1871d69f5b"/><file name="Token.java.orig" hash="fc29a8318923baf0fd901273c8fe3508"/><file name="TokenStream.java" hash="d13d1324cd82df8cdb776bf92803b631"/><file name="TokenStream.java.orig" hash="285c3df98b9c1ce89baa8869c99787fa"/></dir></dir></dir></dir><dir name="tests"><file name="README" hash="00759ebfaf6aa49096400113b8c979a9"/><file name="_munge.js" hash="f6aa2d7851acf77c9df23e9a4d008e65"/><file name="_munge.js.min" hash="a588cc04f58e03d4a160be09d4dfa9d3"/><file name="_string_combo.js" hash="eb8be931688b025dc19a4c0885215fdb"/><file name="_string_combo.js.min" hash="c31894fd93ce7fd39e0168e75043a975"/><file name="_syntax_error.js" hash="3ebfa7b74df65615a4cd8a84b2ba6557"/><file name="_syntax_error.js.min" hash="b6698b06b38258d3d3f70bc858c05ca9"/><file name="background-position.css" hash="41c8b60b980a8246420bedce9ad80f43"/><file name="background-position.css.min" hash="ab3083bbee5683a1b9e87f42d818f000"/><file name="border-none.css" hash="1f3f4f1d6a7e415f77cb3dd714273d4a"/><file name="border-none.css.min" hash="47d8f811087637a248d77b0e037e8c41"/><file name="box-model-hack.css" hash="9fea0ae9c85059e542d49ee5aa13555d"/><file name="box-model-hack.css.min" hash="8c0c7e93f069f4f86f675456922da775"/><file name="bug2527974.css" hash="36aac1fa682abc108c44ba5b78397b1f"/><file name="bug2527974.css.min" hash="05673cd175e6264c8dc7f7b8b1f1a4d6"/><file name="bug2527991.css" hash="7c9220e8b99c8482899998fd6824a827"/><file name="bug2527991.css.min" hash="b53f98777ad46666a6f1c7e49b15ab1c"/><file name="bug2527998.css" hash="79bc1cf4241d58092235d26cd8fd9a62"/><file name="bug2527998.css.min" hash="5b4eda9ed8f90a6c32284dbfc7c8ce30"/><file name="bug2528034.css" hash="d0a0c66851f1ce3650773c28ed1a87df"/><file name="bug2528034.css.min" hash="71a3bf1c4645dc8dbf8e770c32ee413a"/><file name="charset-media.css" hash="f5ce419dd15eb06acb42a6425efcc975"/><file name="charset-media.css.min" hash="1b97812c7a17d3eb53d761d254abf009"/><file name="color.css" hash="94783ce86f1a601a4fff5b7263012bab"/><file name="color.css.min" hash="3ffe7fd90cd053c808d701d1c8f40dac"/><file name="comment.css" hash="3a4ce0684608a07c97659eeef2f92c58"/><file name="comment.css.min" hash="25cc12f8db4af65032ab4db90951aa1b"/><file name="concat-charset.css" hash="50918cdb23e0fc6b496e805cf7680633"/><file name="concat-charset.css.min" hash="8567ed0beff3e83703d779f272951190"/><file name="decimals.css" hash="772c0211281af00de6ddca046ee3b376"/><file name="decimals.css.min" hash="e19cddee318f726350122581545215eb"/><file name="dollar-header.css" hash="aa8cc12a339a39146348f8e40d10269d"/><file name="dollar-header.css.min" hash="8c5436316574d9979f8a15ef73df1cca"/><file name="float.js" hash="628ee48be01710e3b424de663ee43387"/><file name="float.js.min" hash="27f8e451c22fb14c72d6fd5c6c3c030c"/><file name="font-face.css" hash="64501f813f2dac84e4e7a4af7add6b78"/><file name="font-face.css.min" hash="15d780bc4ba1c184881df880ad518c92"/><file name="ie5mac.css" hash="cce400f1ac3343f3e6bdf4cc8363aa0a"/><file name="ie5mac.css.min" hash="42e48b72ab79e34318ef5bb77ac0a611"/><file name="media-empty-class.css" hash="43d6b4cd603b301cf26bce376731843d"/><file name="media-empty-class.css.min" hash="b18b4b03ecd9b1bddbf23ef6a2f3b3ec"/><file name="media-multi.css" hash="4afa8bd30f96cc16a39b66eccfd0564d"/><file name="media-multi.css.min" hash="c104f19539c02a2922d91e3ad674080e"/><file name="media-test.css" hash="7dd3ab665ecc12f2bc4a45c006a99d55"/><file name="media-test.css.min" hash="35a05a55ad6a53d29a0127474977f738"/><file name="opacity-filter.css" hash="86d9df366af891c976ddda3522c0f940"/><file name="opacity-filter.css.min" hash="8bb3ec1ce452af5d16c64448bc8ac991"/><file name="preserve-new-line.css" hash="59529cee6c1368827bf1434c23c7d016"/><file name="preserve-new-line.css.min" hash="1337ad47f52d8b254c8f95f850430b6b"/><file name="preserve-strings.css" hash="1cc55ab8e7b566536f0fb96fa72cde3a"/><file name="preserve-strings.css.min" hash="0c564c025e5751c9b5f288a69552e2d1"/><file name="pseudo-first.css" hash="0b4a5a3b122ae327a53bebcb85669e34"/><file name="pseudo-first.css.min" hash="2a70774e971508d4f3162ccbc0e63445"/><file name="pseudo.css" hash="04345371998f4d01a7f45af52f88e61e"/><file name="pseudo.css.min" hash="51edc5f27abe8e14a57f11fd1b259c80"/><file name="special-comments.css" hash="b4c7acf039941b6b70b9ba5cc81b0fb8"/><file name="special-comments.css.min" hash="58916583c0dfac38c9d2daf71570c928"/><file name="star-underscore-hacks.css" hash="9ca59a789c3d81864d2cc99d7b43be8e"/><file name="star-underscore-hacks.css.min" hash="3cf8e4d1c60f5ec6cfdd7e754266021f"/><file name="string-in-comment.css" hash="90e90ae74f54f342552386da8276e578"/><file name="string-in-comment.css.min" hash="7df7e0b83884c7d9ab011ac04d97e4e1"/><file name="suite.rhino" hash="7b7721318c085d75ee46247ef52f119f"/><file name="suite.sh" hash="098286a327303a0cc23b90030a53d8c7"/><file name="webkit-transform.css" hash="4161a87a9732b3c89f7a88f1218801fa"/><file name="webkit-transform.css.min" hash="a673f8b4ac44e7ef939707d14244fb13"/><file name="zeros.css" hash="411b5c4b147adf4f5ae32cfbf04c4806"/><file name="zeros.css.min" hash="77cb7dbe3fc6e6a80906f69552d38801"/></dir><file name="LICENSE.TXT" hash="3613da48ce3df42e8878ee166242fd4f"/><file name="ant.properties" hash="ecbeb47b1702bde96874d085b9bf0955"/><file name="build.xml" hash="107ca508b743ed2ba27d0f5b7087b8b0"/></dir><file name="FirePHP.php" hash="0c1dce00e352b76ad76b36fc0a4d6fc7"/><file name="JSMin.php" hash="f6a43fd592beddde0736e19eb71d0cb0"/><file name="JSMinPlus.php" hash="99303433243e08149dd9c5082e22cf31"/><file name="JavaScriptPacker.php" hash="87ad3bd2bf41c3dbd4f9108a13ce3f45"/><file name="Minify.php" hash="e26f89ec7d5890875ed1de40875f46fa"/><file name="ParseMaster.php" hash="70988c48e5a68c8d3109d50542cfcde0"/></dir></target><target name="mageskin"><dir name="frontend"><dir name="default"><dir name="default"><dir name="css"><file name="w3c-validator.css" hash="ec35256d2c26b55084099d447fc15f37"/></dir></dir></dir></dir></target><target name="magedesign"><dir name="frontend"><dir name="default"><dir name="default"><dir name="layout"><file name="uioptimization.xml" hash="0db614f8736ab73850e64fec19163adb"/></dir><dir name="template"><dir name="uioptimization"><file name="canonicalurl.phtml" hash="4feb2a4801db037648479ce9a0fd6dbe"/><file name="w3ccssvalidator.phtml" hash="df20893c83302cac5485da4de78ba89c"/><file name="w3chtmlvalidator.phtml" hash="662d5d642f31b5fe2853cf8721b9e093"/></dir></dir></dir></dir></dir></target><target name="mageetc"><dir name="modules"><file name="Diglin_UIOptimization.xml" hash="df03af601856cd1869a114147b8eb6cc"/></dir></target></contents>
59
  <compatible/>
60
  <dependencies/>
61
  </package>
1
  <?xml version="1.0"?>
2
  <package>
3
  <name>Diglin_UIOptimization</name>
4
+ <version>1.4.0</version>
5
  <stability>stable</stability>
6
  <license uri="http://www.opensource.org/licenses/osl-3.0.php">OSL v3.0</license>
7
  <channel>community</channel>
44
  - An assistant will be available soon&#xD;
45
  - Follow the instruction in the configuration page&#xD;
46
  - In case of Access Denied in the backend: clear your cache, logout/login. In case, it still doesn't work, save again the user role in System &gt; Permissions &gt; Roles.</description>
47
+ <notes>- Version 1.4.0: Move themes files to the folder app/design/frontend/base/default, update yuicompressor to version 2.4.7, generate css/js file per store and not globally&#xD;
48
+ - Version 1.3.1: fix Paypal donation button&#xD;
49
+ - Version 1.3.0: improve canonical url generation, improve some configuration parameters, remove the option JS Packer because incompatible with Magento&#xD;
50
  - Version 1.2.0: improve compatibility with compilation feature of Magento, add a js/css flush button directly in the configuration page&#xD;
51
  - Version 1.1.0: rewrite some classes of the minify libraries to respect PHP 5 and prevent some errors, change the module name, make it compatible with compilation feature of Magento, add canonical url feature for SEO&#xD;
52
  - Version 1.0.10: fix type for css files stored in /js/ folder&#xD;
55
  - Version 1.0.2: add cron task to allow to update compressed/minified js/css files periodically&#xD;
56
  - Version 1.0.1: fix a missing config element class, this class seems to exists only since 1.4.1 or more</notes>
57
  <authors><author><name>diglin</name><user>auto-converted</user><email>sly@diglin.com</email></author></authors>
58
+ <date>2013-01-02</date>
59
+ <time>21:03:51</time>
60
+ <contents><target name="magecommunity"><dir name="Diglin"><dir name="UIOptimization"><dir name="Block"><dir name="Adminhtml"><dir name="Config"><dir name="Source"><file name="Heading.php" hash="d15c30ac285cdff33a2ab32eb59cb564"/><file name="Hint.php" hash="aa26cc47900487fde4e747f413fa7aef"/></dir></dir></dir><dir name="Optimize"><file name="Head.php" hash="066b19559f082283f89334bf69c2d6c8"/></dir><file name="W3Ccssvalidator.php" hash="43f2e40257bc6d729f55ff86f892ffd9"/><file name="W3Chtmlvalidator.php" hash="3bb405092f65ce69f1de065074e938ef"/></dir><dir name="Helper"><file name="Data.php" hash="abf185647c5b74cc0cd03e8f1217d7bb"/></dir><dir name="Model"><dir name="Config"><dir name="Source"><file name="Caseproperties.php" hash="71ecf181882b3ba86f34e9b13688b818"/><file name="Charset.php" hash="ed5b2d44ac015ad7a2e47e5256fcf326"/><file name="Csslevel.php" hash="a4c463268772612d76fa8cb01d48b394"/><file name="Csstypeminify.php" hash="ac3a3407105923255c212aabfdb7839e"/><file name="Doctype.php" hash="25f7b13fa0fb7eca9325c91fa84f1f66"/><file name="Jstypeminify.php" hash="e56cf7fc3ab95320d786972355b5176f"/><file name="Language.php" hash="2824c01f7014bc9c2a01bba519bf0d70"/><file name="Mergeselectors.php" hash="70e30f4f5e303b045838991184841409"/><file name="Optishorthand.php" hash="a66d0a74e0e659ddabc26d12fe30333a"/><file name="Profile.php" hash="4e4245d513a11ea2e48648d15f048952"/><file name="Template.php" hash="512a4faca68c7bb11b75ced04ec3fd23"/><file name="Usermedium.php" hash="53748dbbb513cf47e0a5ff6aa1f45947"/><file name="Warning.php" hash="375871ff5f28fb6c0679b7b935df638e"/></dir></dir><dir name="Overwrite"><dir name="Design"><file name="Package.php" hash="9026106a0a9a5b00a95b3c36249d71a7"/></dir></dir><file name="Observer.php" hash="3b5ccbf0aef2289fe9d0d054d760478f"/></dir><dir name="etc"><file name="adminhtml.xml" hash="cde46a100bc94df35ce1fc8896e87514"/><file name="config.xml" hash="03bfe35e6446a1b319d7d0d02c307500"/><file name="system.xml" hash="9acbc1244d4eb9568f611a3d625b7cca"/></dir></dir></dir></target><target name="magelib"><dir name="Diglin"><dir name="Csstidy"><file name="Core.php" hash="820e39515baba186803453eaf735bb5d"/><file name="Optimise.php" hash="3694084e725ba252b623492d0d09a67d"/><file name="Print.php" hash="203c86314418bc2b70fcb8beccafea3b"/><file name="README" hash="3a3e2ddf61de1689e042291b821262b0"/><file name="data.inc.php" hash="516492aeb1c37bb2a869863d9f2a21a1"/></dir><dir name="HTTP"><dir name="Request2"><dir name="Adapter"><file name="Curl.php" hash="e7a010aee80ee8dcfe73b5efc0890726"/><file name="Mock.php" hash="d33b4f9fdebdfad58034f4fe028a111c"/><file name="Socket.php" hash="ced36e7a1a3ed7a3adad46518c1954c2"/></dir><dir name="Observer"><file name="Log.php" hash="9aefde329905d25619d16f525bee9c6d"/></dir><file name="Adapter.php" hash="9f90535b4b7bff4a7052f767579b0ff1"/><file name="Exception.php" hash="ce7b316eaedcd5928a57e74725539fa6"/><file name="MultipartBody.php" hash="7073427f223db55059eca79cac36bbc1"/><file name="Response.php" hash="bdbcb96eadd6549d916f95acf45a0268"/></dir><file name="ConditionalGet.php" hash="5fb451fba76286fa28323f53f1870daf"/><file name="Encoder.php" hash="37a2b8e6bcb2908162e2881be93040a6"/><file name="Request2.php" hash="73fec75564cceac997605763812f061f"/></dir><dir name="Io"><file name="File.php" hash="d1b4545aeac7030d6991cf9310194b37"/></dir><dir name="Minify"><dir name="CSS"><file name="Compressor.php" hash="7382e9fe1dc08eef2b06fa016ed2dde8"/><file name="UriRewriter.php" hash="0585d4c22e773319b1616caa04ee253d"/></dir><dir name="Cache"><file name="APC.php" hash="6cab72f5c2a8cbe72f0751e7fdb35299"/><file name="File.php" hash="a0b06218ace157a91e8581481207554e"/><file name="Memcache.php" hash="92b3b852552e54fee0746beaeecfd920"/></dir><dir name="Controller"><file name="Base.php" hash="93d54ee900c594dae559a20d020d6eaa"/><file name="Files.php" hash="510d15562a7b77eafb3d366dea9cfcc9"/><file name="Groups.php" hash="cbf4869e3d9f99d56b9581f8477e78a3"/><file name="MinApp.php" hash="15a18fbc0cc30664e08ea880f4538215"/><file name="Page.php" hash="650d9edc5cfddd92027e6b7b257568f9"/><file name="Version1.php" hash="9a8fbce1285b08047393442e556adf89"/></dir><file name="Build.php" hash="78fe924cecb08a507f6c8fde9090dca5"/><file name="CSS.php" hash="128ff0cb67f075f175a51d0f9aac7469"/><file name="CommentPreserver.php" hash="efab6711d7ec10b046a58826dc314d21"/><file name="HTML.php" hash="ef58c0cf87dbec2f0301330062781b27"/><file name="ImportProcessor.php" hash="29379d4088d36d706ebaca5c7649ed27"/><file name="Lines.php" hash="ca9d9d718035dfb400c77568c9692f7c"/><file name="Logger.php" hash="b92325836feb2e64992ff931dd9b7454"/><file name="Packer.php" hash="ddc1e068af1043089764c80eaded7d81"/><file name="Source.php" hash="d9cbdc2851722a509157ab469b681b22"/><file name="YUICompressor.php" hash="4b73c98c6b650f54a96a264f3e0f0c8d"/></dir><dir name="Net"><file name="URL2.php" hash="65e54166dcf0994507459d0ad5b97a2c"/></dir><dir name="Services"><dir name="W3C"><dir name="CSSValidator"><file name="Error.php" hash="41cfd8ca38ef335ce03e75802c57ab81"/><file name="Message.php" hash="9d83bc04fdf945dc51d9974d6f626cfc"/><file name="Response.php" hash="7ae2b76ba7fdf008d06818596628f05f"/><file name="Warning.php" hash="3b654f71af352d5be419ef968323968f"/></dir><dir name="HTMLValidator"><file name="Error.php" hash="39139614730155f1cb70f8e35997cf09"/><file name="Exception.php" hash="133012d58d41064e2712ca93fee77ca4"/><file name="Message.php" hash="dcbdb982c3308598b8c2cd69caf591ff"/><file name="Response.php" hash="b263217ee5da08f275a77357d08efcf9"/><file name="Warning.php" hash="1f5f024525ead59be6adf39f78e93615"/></dir><file name="CSSValidator.php" hash="ae14a24c658a28adf2f4cbf3e2af17f8"/><file name="HTMLValidator.php" hash="75ac95c991d238fe10a2d4e54c6d2a07"/></dir></dir><dir name="Solar"><file name="Dir.php" hash="e71fa00999543f6c14960fffc7fe4f59"/></dir><dir name="yuicompressor"><file name="yuicompressor-2.4.7.jar" hash="a64311cb39d119805b41d547c8dd039d"/><file name="yuicompressor.jar" hash="a64311cb39d119805b41d547c8dd039d"/><file name=".DS_Store" hash="194577a7e20bdcc7afbb718f502c134c"/></dir><file name="FirePHP.php" hash="0c1dce00e352b76ad76b36fc0a4d6fc7"/><file name="JSMin.php" hash="f6a43fd592beddde0736e19eb71d0cb0"/><file name="JSMinPlus.php" hash="99303433243e08149dd9c5082e22cf31"/><file name="JavaScriptPacker.php" hash="87ad3bd2bf41c3dbd4f9108a13ce3f45"/><file name="Minify.php" hash="e26f89ec7d5890875ed1de40875f46fa"/><file name="ParseMaster.php" hash="70988c48e5a68c8d3109d50542cfcde0"/><file name=".DS_Store" hash="194577a7e20bdcc7afbb718f502c134c"/></dir></target><target name="mageskin"><dir name="frontend"><dir name="base"><dir name="default"><dir name="css"><file name="w3c-validator.css" hash="ec35256d2c26b55084099d447fc15f37"/></dir></dir></dir></dir></target><target name="magedesign"><dir name="frontend"><dir name="base"><dir name="default"><dir name="layout"><file name="uioptimization.xml" hash="0db614f8736ab73850e64fec19163adb"/></dir><dir name="template"><dir name="uioptimization"><file name="canonicalurl.phtml" hash="50b14f2d39febd53232da5f1091c5b98"/><file name="w3ccssvalidator.phtml" hash="df20893c83302cac5485da4de78ba89c"/><file name="w3chtmlvalidator.phtml" hash="662d5d642f31b5fe2853cf8721b9e093"/></dir></dir></dir></dir></dir></target><target name="mageetc"><dir name="modules"><file name="Diglin_UIOptimization.xml" hash="df03af601856cd1869a114147b8eb6cc"/></dir></target></contents>
61
  <compatible/>
62
  <dependencies/>
63
  </package>
skin/frontend/{default → base}/default/css/w3c-validator.css RENAMED
File without changes