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
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
- app/code/community/Diglin/UIOptimization/Block/Adminhtml/Config/Source/Hint.php +2 -3
- app/code/community/Diglin/UIOptimization/Block/Optimize/Head.php +3 -3
- app/code/community/Diglin/UIOptimization/Helper/Data.php +13 -12
- app/code/community/Diglin/UIOptimization/etc/config.xml +1 -1
- app/design/frontend/{default → base}/default/layout/uioptimization.xml +0 -0
- app/design/frontend/{default → base}/default/template/uioptimization/canonicalurl.phtml +23 -23
- app/design/frontend/{default → base}/default/template/uioptimization/w3ccssvalidator.phtml +0 -0
- app/design/frontend/{default → base}/default/template/uioptimization/w3chtmlvalidator.phtml +0 -0
- lib/Diglin/.DS_Store +0 -0
- lib/Diglin/yuicompressor-2.4.6/LICENSE.TXT +0 -54
- lib/Diglin/yuicompressor-2.4.6/ant.properties +0 -8
- lib/Diglin/yuicompressor-2.4.6/build.xml +0 -69
- lib/Diglin/yuicompressor-2.4.6/doc/CHANGELOG +0 -257
- lib/Diglin/yuicompressor-2.4.6/doc/README +0 -145
- lib/Diglin/yuicompressor-2.4.6/lib/jargs-1.0.jar +0 -0
- lib/Diglin/yuicompressor-2.4.6/ports/js/cssmin.js +0 -231
- lib/Diglin/yuicompressor-2.4.6/src/com/yahoo/platform/yui/compressor/Bootstrap.java +0 -23
- lib/Diglin/yuicompressor-2.4.6/src/com/yahoo/platform/yui/compressor/CssCompressor.java +0 -304
- lib/Diglin/yuicompressor-2.4.6/src/com/yahoo/platform/yui/compressor/JarClassLoader.java +0 -158
- lib/Diglin/yuicompressor-2.4.6/src/com/yahoo/platform/yui/compressor/JavaScriptCompressor.java +0 -1317
- lib/Diglin/yuicompressor-2.4.6/src/com/yahoo/platform/yui/compressor/JavaScriptIdentifier.java +0 -55
- lib/Diglin/yuicompressor-2.4.6/src/com/yahoo/platform/yui/compressor/JavaScriptToken.java +0 -28
- lib/Diglin/yuicompressor-2.4.6/src/com/yahoo/platform/yui/compressor/ScriptOrFnScope.java +0 -160
- lib/Diglin/yuicompressor-2.4.6/src/com/yahoo/platform/yui/compressor/YUICompressor.java +0 -255
- lib/Diglin/yuicompressor-2.4.6/src/org/mozilla/javascript/Decompiler.java +0 -908
- lib/Diglin/yuicompressor-2.4.6/src/org/mozilla/javascript/Decompiler.java.orig +0 -910
- lib/Diglin/yuicompressor-2.4.6/src/org/mozilla/javascript/Parser.java +0 -2160
- lib/Diglin/yuicompressor-2.4.6/src/org/mozilla/javascript/Parser.java.orig +0 -2159
- lib/Diglin/yuicompressor-2.4.6/src/org/mozilla/javascript/Token.java +0 -406
- lib/Diglin/yuicompressor-2.4.6/src/org/mozilla/javascript/Token.java.orig +0 -417
- lib/Diglin/yuicompressor-2.4.6/src/org/mozilla/javascript/TokenStream.java +0 -1365
- lib/Diglin/yuicompressor-2.4.6/src/org/mozilla/javascript/TokenStream.java.orig +0 -1398
- lib/Diglin/yuicompressor-2.4.6/tests/README +0 -6
- lib/Diglin/yuicompressor-2.4.6/tests/_munge.js +0 -8
- lib/Diglin/yuicompressor-2.4.6/tests/_munge.js.min +0 -1
- lib/Diglin/yuicompressor-2.4.6/tests/_string_combo.js +0 -5
- lib/Diglin/yuicompressor-2.4.6/tests/_string_combo.js.min +0 -1
- lib/Diglin/yuicompressor-2.4.6/tests/_syntax_error.js +0 -73
- lib/Diglin/yuicompressor-2.4.6/tests/_syntax_error.js.min +0 -1
- lib/Diglin/yuicompressor-2.4.6/tests/background-position.css +0 -2
- lib/Diglin/yuicompressor-2.4.6/tests/background-position.css.min +0 -1
- lib/Diglin/yuicompressor-2.4.6/tests/border-none.css +0 -5
- lib/Diglin/yuicompressor-2.4.6/tests/border-none.css.min +0 -1
- lib/Diglin/yuicompressor-2.4.6/tests/box-model-hack.css +0 -9
- lib/Diglin/yuicompressor-2.4.6/tests/box-model-hack.css.min +0 -1
- lib/Diglin/yuicompressor-2.4.6/tests/bug2527974.css +0 -10
- lib/Diglin/yuicompressor-2.4.6/tests/bug2527974.css.min +0 -1
- lib/Diglin/yuicompressor-2.4.6/tests/bug2527991.css +0 -19
- lib/Diglin/yuicompressor-2.4.6/tests/bug2527991.css.min +0 -1
- lib/Diglin/yuicompressor-2.4.6/tests/bug2527998.css +0 -4
- lib/Diglin/yuicompressor-2.4.6/tests/bug2527998.css.min +0 -1
- lib/Diglin/yuicompressor-2.4.6/tests/bug2528034.css +0 -5
- lib/Diglin/yuicompressor-2.4.6/tests/bug2528034.css.min +0 -1
- lib/Diglin/yuicompressor-2.4.6/tests/charset-media.css +0 -9
- lib/Diglin/yuicompressor-2.4.6/tests/charset-media.css.min +0 -1
- lib/Diglin/yuicompressor-2.4.6/tests/color.css +0 -7
- lib/Diglin/yuicompressor-2.4.6/tests/color.css.min +0 -1
- lib/Diglin/yuicompressor-2.4.6/tests/comment.css +0 -3
- lib/Diglin/yuicompressor-2.4.6/tests/comment.css.min +0 -1
- lib/Diglin/yuicompressor-2.4.6/tests/concat-charset.css +0 -15
- lib/Diglin/yuicompressor-2.4.6/tests/concat-charset.css.min +0 -1
- lib/Diglin/yuicompressor-2.4.6/tests/decimals.css +0 -3
- lib/Diglin/yuicompressor-2.4.6/tests/decimals.css.min +0 -1
- lib/Diglin/yuicompressor-2.4.6/tests/dollar-header.css +0 -7
- lib/Diglin/yuicompressor-2.4.6/tests/dollar-header.css.min +0 -3
- lib/Diglin/yuicompressor-2.4.6/tests/float.js +0 -2
- lib/Diglin/yuicompressor-2.4.6/tests/float.js.min +0 -1
- lib/Diglin/yuicompressor-2.4.6/tests/font-face.css +0 -6
- lib/Diglin/yuicompressor-2.4.6/tests/font-face.css.min +0 -1
- lib/Diglin/yuicompressor-2.4.6/tests/ie5mac.css +0 -5
- lib/Diglin/yuicompressor-2.4.6/tests/ie5mac.css.min +0 -1
- lib/Diglin/yuicompressor-2.4.6/tests/media-empty-class.css +0 -16
- lib/Diglin/yuicompressor-2.4.6/tests/media-empty-class.css.min +0 -1
- lib/Diglin/yuicompressor-2.4.6/tests/media-multi.css +0 -3
- lib/Diglin/yuicompressor-2.4.6/tests/media-multi.css.min +0 -1
- lib/Diglin/yuicompressor-2.4.6/tests/media-test.css +0 -3
- lib/Diglin/yuicompressor-2.4.6/tests/media-test.css.min +0 -1
- lib/Diglin/yuicompressor-2.4.6/tests/opacity-filter.css +0 -14
- lib/Diglin/yuicompressor-2.4.6/tests/opacity-filter.css.min +0 -1
- lib/Diglin/yuicompressor-2.4.6/tests/preserve-new-line.css +0 -6
- lib/Diglin/yuicompressor-2.4.6/tests/preserve-new-line.css.min +0 -3
- lib/Diglin/yuicompressor-2.4.6/tests/preserve-strings.css +0 -7
- lib/Diglin/yuicompressor-2.4.6/tests/preserve-strings.css.min +0 -1
- lib/Diglin/yuicompressor-2.4.6/tests/pseudo-first.css +0 -16
- lib/Diglin/yuicompressor-2.4.6/tests/pseudo-first.css.min +0 -1
- lib/Diglin/yuicompressor-2.4.6/tests/pseudo.css +0 -4
- lib/Diglin/yuicompressor-2.4.6/tests/pseudo.css.min +0 -1
- lib/Diglin/yuicompressor-2.4.6/tests/special-comments.css +0 -13
- lib/Diglin/yuicompressor-2.4.6/tests/special-comments.css.min +0 -9
- lib/Diglin/yuicompressor-2.4.6/tests/star-underscore-hacks.css +0 -5
- lib/Diglin/yuicompressor-2.4.6/tests/star-underscore-hacks.css.min +0 -1
- lib/Diglin/yuicompressor-2.4.6/tests/string-in-comment.css +0 -8
- lib/Diglin/yuicompressor-2.4.6/tests/string-in-comment.css.min +0 -1
- lib/Diglin/yuicompressor-2.4.6/tests/suite.rhino +0 -3
- lib/Diglin/yuicompressor-2.4.6/tests/suite.sh +0 -62
- lib/Diglin/yuicompressor-2.4.6/tests/webkit-transform.css +0 -2
- lib/Diglin/yuicompressor-2.4.6/tests/webkit-transform.css.min +0 -1
- lib/Diglin/yuicompressor-2.4.6/tests/zeros.css +0 -6
- lib/Diglin/yuicompressor-2.4.6/tests/zeros.css.min +0 -1
- lib/Diglin/yuicompressor/.DS_Store +0 -0
- lib/Diglin/{yuicompressor-2.4.6/build/yuicompressor-2.4.6.jar → yuicompressor/yuicompressor-2.4.7.jar} +0 -0
- lib/Diglin/{yuicompressor-2.4.6/lib/rhino-1.6R7.jar → yuicompressor/yuicompressor.jar} +0 -0
- package.xml +7 -5
- skin/frontend/{default → base}/default/css/w3c-validator.css +0 -0
@@ -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><
|
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 |
}
|
@@ -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
|
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
|
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 |
+
}
|
@@ -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)
|
@@ -2,7 +2,7 @@
|
|
2 |
<config>
|
3 |
<modules>
|
4 |
<Diglin_UIOptimization>
|
5 |
-
<version>1.
|
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 |
|
File without changes
|
@@ -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; ?>
|
File without changes
|
File without changes
|
Binary file
|
@@ -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 )
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@@ -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}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@@ -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>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@@ -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.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@@ -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.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Binary file
|
@@ -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 |
-
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@@ -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 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@@ -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 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@@ -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 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@@ -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 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@@ -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 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@@ -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 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@@ -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 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@@ -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 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@@ -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 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@@ -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 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@@ -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 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@@ -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 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@@ -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 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@@ -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 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@@ -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 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@@ -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 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@@ -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!
|
|
|
|
|
|
|
|
|
|
|
|
@@ -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 |
-
})();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@@ -1 +0,0 @@
|
|
1 |
-
(function(){var a=window;a.hello=function(a,b){a.alert("Hello, "+a)}})();
|
|
@@ -1,5 +0,0 @@
|
|
1 |
-
function test(){
|
2 |
-
var a = "a" +
|
3 |
-
"b" +
|
4 |
-
"c";
|
5 |
-
}
|
|
|
|
|
|
|
|
|
|
@@ -1 +0,0 @@
|
|
1 |
-
function test(){var b="abc"};
|
|
@@ -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 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@@ -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};
|
|
@@ -1,2 +0,0 @@
|
|
1 |
-
a {background-position: 0 0 0 0;}
|
2 |
-
b {BACKGROUND-POSITION: 0 0;}
|
|
|
|
@@ -1 +0,0 @@
|
|
1 |
-
a{background-position:0 0}b{background-position:0 0}
|
|
@@ -1,5 +0,0 @@
|
|
1 |
-
a {
|
2 |
-
border: none;
|
3 |
-
}
|
4 |
-
b {BACKGROUND:none}
|
5 |
-
s {border-top: none;}
|
|
|
|
|
|
|
|
|
|
@@ -1 +0,0 @@
|
|
1 |
-
a{border:0}b{background:0}s{border-top:0}
|
|
@@ -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 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@@ -1 +0,0 @@
|
|
1 |
-
#elem{width:100px;voice-family:"\"}\"";voice-family:inherit;width:200px}html>body #elem{width:200px}
|
|
@@ -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;}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@@ -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}
|
|
@@ -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 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@@ -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}}
|
|
@@ -1,4 +0,0 @@
|
|
1 |
-
/*! special */
|
2 |
-
body {
|
3 |
-
|
4 |
-
}
|
|
|
|
|
|
|
|
@@ -1 +0,0 @@
|
|
1 |
-
/*! special */
|
|
@@ -1,5 +0,0 @@
|
|
1 |
-
a[href$="/test/"] span:first-child { b:1; }
|
2 |
-
a[href$="/test/"] span:first-child { }
|
3 |
-
|
4 |
-
|
5 |
-
|
|
|
|
|
|
|
|
|
|
@@ -1 +0,0 @@
|
|
1 |
-
a[href$="/test/"] span:first-child{b:1}
|
|
@@ -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 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@@ -1 +0,0 @@
|
|
1 |
-
@charset 'utf-8';@media all{body{background-color:gold}}
|
|
@@ -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 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@@ -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)}
|
|
@@ -1,3 +0,0 @@
|
|
1 |
-
html >/**/ body p {
|
2 |
-
color: blue;
|
3 |
-
}
|
|
|
|
|
|
@@ -1 +0,0 @@
|
|
1 |
-
html>/**/body p{color:blue}
|
|
@@ -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 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@@ -1 +0,0 @@
|
|
1 |
-
@charset "utf-8";#foo{border-width:1px}#bar{border-width:10px}
|
|
@@ -1,3 +0,0 @@
|
|
1 |
-
::selection {
|
2 |
-
margin: 0.6px 0.333pt 1.2em 8.8cm;
|
3 |
-
}
|
|
|
|
|
|
@@ -1 +0,0 @@
|
|
1 |
-
::selection{margin:.6px .333pt 1.2em 8.8cm}
|
|
@@ -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 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@@ -1,3 +0,0 @@
|
|
1 |
-
/*!
|
2 |
-
$Header: /temp/dirname/filename.css 3 2/02/08 3:37p JSmith $
|
3 |
-
*/foo{bar:baz}
|
|
|
|
|
|
@@ -1,2 +0,0 @@
|
|
1 |
-
obj.css({"float": "left"});
|
2 |
-
obj.css({cssFloat:"left"});
|
|
|
|
@@ -1 +0,0 @@
|
|
1 |
-
obj.css({"float":"left"});obj.css({cssFloat:"left"});
|
|
@@ -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 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
@@ -1 +0,0 @@
|
|
1 |
-
@font-face{font-family:'gzipper';src:url(yanone.eot);src:local('gzipper'),url(yanone.ttf) format('truetype')}
|
|
@@ -1,5 +0,0 @@
|
|
1 |
-
/* Ignore the next rule in IE mac \*/
|
2 |
-
.selector {
|
3 |
-
color: khaki;
|
4 |
-
}
|
5 |
-
/* Stop ignoring in IE mac */
|
|
|
|
|
|
|
|
|
|
@@ -1 +0,0 @@
|
|
1 |
-
/*\*/.selector{color:khaki}/**/
|
|
@@ -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 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@@ -1 +0,0 @@
|
|
1 |
-
/*! preserved */@import "another.css";@media print{.noprint{display:none}}@media screen{.printonly{display:none}}
|
|
@@ -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 |
-
}
|
|
|
|
|
|
@@ -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}
|
|
@@ -1,3 +0,0 @@
|
|
1 |
-
@media screen and (-webkit-min-device-pixel-ratio:0) {
|
2 |
-
some-css : here
|
3 |
-
}
|
|
|
|
|
|
@@ -1 +0,0 @@
|
|
1 |
-
@media screen and (-webkit-min-device-pixel-ratio:0){some-css:here}
|
|
@@ -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 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@@ -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)}
|
|
@@ -1,6 +0,0 @@
|
|
1 |
-
#sel-o {
|
2 |
-
content: "on\"ce upon \
|
3 |
-
a time";
|
4 |
-
content: 'once upon \
|
5 |
-
a ti\'me';
|
6 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
@@ -1,3 +0,0 @@
|
|
1 |
-
#sel-o{content:"on\"ce upon \
|
2 |
-
a time";content:'once upon \
|
3 |
-
a ti\'me'}
|
|
|
|
|
|
@@ -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 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@@ -1 +0,0 @@
|
|
1 |
-
.sele{content:"\"keep \" me";something:'\\\' . . ';else:'empty{}';content:"/* test */"}
|
|
@@ -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 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@@ -1 +0,0 @@
|
|
1 |
-
p:first-letter {buh:hum}p:first-line {baa:1}p:first-line ,a,p:first-letter ,b{color:red}
|
|
@@ -1,4 +0,0 @@
|
|
1 |
-
p :link {
|
2 |
-
ba:zinga;;;
|
3 |
-
foo: bar;;;
|
4 |
-
}
|
|
|
|
|
|
|
|
@@ -1 +0,0 @@
|
|
1 |
-
p :link{ba:zinga;foo:bar}
|
|
@@ -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! */
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@@ -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! */
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@@ -1,5 +0,0 @@
|
|
1 |
-
#elementarr {
|
2 |
-
width: 1px;
|
3 |
-
*width: 3pt;
|
4 |
-
_width: 2em;
|
5 |
-
}
|
|
|
|
|
|
|
|
|
|
@@ -1 +0,0 @@
|
|
1 |
-
#elementarr{width:1px;*width:3pt;_width:2em}
|
|
@@ -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 */
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@@ -1 +0,0 @@
|
|
1 |
-
a{a:1}/*!"preserve" me*/b{content:"/**/"}/*\*/c{c:3}/**/
|
|
@@ -1,3 +0,0 @@
|
|
1 |
-
input = readFile(arguments[0]);
|
2 |
-
load("../ports/js/cssmin.js");
|
3 |
-
print(YAHOO.compressor.cssmin(input));
|
|
|
|
|
|
@@ -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
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@@ -1,2 +0,0 @@
|
|
1 |
-
c {-webkit-transform-origin: 0 0;}
|
2 |
-
d {-MOZ-TRANSFORM-ORIGIN: 0 0 }
|
|
|
|
@@ -1 +0,0 @@
|
|
1 |
-
c{-webkit-transform-origin:0 0}d{-moz-transform-origin:0 0}
|
|
@@ -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 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
@@ -1 +0,0 @@
|
|
1 |
-
a{margin:0;_padding-top:0;background-position:0 0;padding:0}
|
|
Binary file
|
Binary file
|
Binary file
|
@@ -1,7 +1,7 @@
|
|
1 |
<?xml version="1.0"?>
|
2 |
<package>
|
3 |
<name>Diglin_UIOptimization</name>
|
4 |
-
<version>1.
|
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
|
45 |
- Follow the instruction in the configuration page
|
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 > Permissions > Roles.</description>
|
47 |
-
<notes>- Version 1.
|
|
|
|
|
48 |
- Version 1.2.0: improve compatibility with compilation feature of Magento, add a js/css flush button directly in the configuration page
|
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
|
50 |
- Version 1.0.10: fix type for css files stored in /js/ folder
|
@@ -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
|
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>
|
57 |
-
<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
|
45 |
- Follow the instruction in the configuration page
|
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 > Permissions > 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
|
48 |
+
- Version 1.3.1: fix Paypal donation button
|
49 |
+
- Version 1.3.0: improve canonical url generation, improve some configuration parameters, remove the option JS Packer because incompatible with Magento
|
50 |
- Version 1.2.0: improve compatibility with compilation feature of Magento, add a js/css flush button directly in the configuration page
|
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
|
52 |
- Version 1.0.10: fix type for css files stored in /js/ folder
|
55 |
- Version 1.0.2: add cron task to allow to update compressed/minified js/css files periodically
|
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>
|
File without changes
|