[richfaces-svn-commits] JBoss Rich Faces SVN: r4755 - in trunk: cdk/maven-javascript-plugin and 30 other directories.

richfaces-svn-commits at lists.jboss.org richfaces-svn-commits at lists.jboss.org
Tue Dec 11 18:30:42 EST 2007


Author: alexsmirnov
Date: 2007-12-11 18:30:42 -0500 (Tue, 11 Dec 2007)
New Revision: 4755

Added:
   trunk/cdk/maven-javascript-plugin/
   trunk/cdk/maven-javascript-plugin/README-YUICompressor.txt
   trunk/cdk/maven-javascript-plugin/README-yuicompressor.txt
   trunk/cdk/maven-javascript-plugin/pom.xml
   trunk/cdk/maven-javascript-plugin/src/
   trunk/cdk/maven-javascript-plugin/src/changes/
   trunk/cdk/maven-javascript-plugin/src/changes/changes.xml
   trunk/cdk/maven-javascript-plugin/src/main/
   trunk/cdk/maven-javascript-plugin/src/main/java/
   trunk/cdk/maven-javascript-plugin/src/main/java/com/
   trunk/cdk/maven-javascript-plugin/src/main/java/com/yahoo/
   trunk/cdk/maven-javascript-plugin/src/main/java/com/yahoo/platform/
   trunk/cdk/maven-javascript-plugin/src/main/java/com/yahoo/platform/yui/
   trunk/cdk/maven-javascript-plugin/src/main/java/com/yahoo/platform/yui/compressor/
   trunk/cdk/maven-javascript-plugin/src/main/java/com/yahoo/platform/yui/compressor/CssCompressor.java
   trunk/cdk/maven-javascript-plugin/src/main/java/com/yahoo/platform/yui/compressor/JavaScriptCompressor.java
   trunk/cdk/maven-javascript-plugin/src/main/java/com/yahoo/platform/yui/compressor/JavaScriptErrorReporter.java
   trunk/cdk/maven-javascript-plugin/src/main/java/com/yahoo/platform/yui/compressor/JavaScriptIdentifier.java
   trunk/cdk/maven-javascript-plugin/src/main/java/com/yahoo/platform/yui/compressor/JavaScriptToken.java
   trunk/cdk/maven-javascript-plugin/src/main/java/com/yahoo/platform/yui/compressor/ScriptOrFnScope.java
   trunk/cdk/maven-javascript-plugin/src/main/java/net/
   trunk/cdk/maven-javascript-plugin/src/main/java/net/sf/
   trunk/cdk/maven-javascript-plugin/src/main/java/net/sf/alchim/
   trunk/cdk/maven-javascript-plugin/src/main/java/net/sf/alchim/mojo/
   trunk/cdk/maven-javascript-plugin/src/main/java/net/sf/alchim/mojo/yuicompressor/
   trunk/cdk/maven-javascript-plugin/src/main/java/net/sf/alchim/mojo/yuicompressor/Aggregation.java
   trunk/cdk/maven-javascript-plugin/src/main/java/net/sf/alchim/mojo/yuicompressor/BasicRhinoShell.java
   trunk/cdk/maven-javascript-plugin/src/main/java/net/sf/alchim/mojo/yuicompressor/ErrorReporter4Mojo.java
   trunk/cdk/maven-javascript-plugin/src/main/java/net/sf/alchim/mojo/yuicompressor/JSLintChecker.java
   trunk/cdk/maven-javascript-plugin/src/main/java/net/sf/alchim/mojo/yuicompressor/JSLintMojo.java
   trunk/cdk/maven-javascript-plugin/src/main/java/net/sf/alchim/mojo/yuicompressor/MojoSupport.java
   trunk/cdk/maven-javascript-plugin/src/main/java/net/sf/alchim/mojo/yuicompressor/SourceFile.java
   trunk/cdk/maven-javascript-plugin/src/main/java/net/sf/alchim/mojo/yuicompressor/YuiCompressorMojo.java
   trunk/cdk/maven-javascript-plugin/src/main/java/org/
   trunk/cdk/maven-javascript-plugin/src/main/java/org/mozilla/
   trunk/cdk/maven-javascript-plugin/src/main/java/org/mozilla/javascript/
   trunk/cdk/maven-javascript-plugin/src/main/java/org/mozilla/javascript/Decompiler.java
   trunk/cdk/maven-javascript-plugin/src/main/java/org/mozilla/javascript/Parser.java
   trunk/cdk/maven-javascript-plugin/src/main/java/org/mozilla/javascript/Token.java
   trunk/cdk/maven-javascript-plugin/src/main/java/org/mozilla/javascript/TokenStream.java
   trunk/cdk/maven-javascript-plugin/src/main/resources/
   trunk/cdk/maven-javascript-plugin/src/main/resources/jslint.js
   trunk/cdk/maven-javascript-plugin/src/test/
   trunk/cdk/maven-javascript-plugin/src/test/java/
   trunk/cdk/maven-javascript-plugin/src/test/java/net/
   trunk/cdk/maven-javascript-plugin/src/test/java/net/sf/
   trunk/cdk/maven-javascript-plugin/src/test/java/net/sf/alchim/
   trunk/cdk/maven-javascript-plugin/src/test/java/net/sf/alchim/mojo/
   trunk/cdk/maven-javascript-plugin/src/test/java/net/sf/alchim/mojo/yuicompressor/
   trunk/cdk/maven-javascript-plugin/src/test/java/net/sf/alchim/mojo/yuicompressor/AggregationTestCase.java
Modified:
   trunk/cdk/pom.xml
   trunk/extensions/portletbridge/portletbridge-impl/src/main/java/org/ajax4jsf/portlet/context/PortletContextImpl.java
   trunk/extensions/portletbridge/portletbridge-impl/src/main/java/org/ajax4jsf/portlet/context/PortletRenderContextImpl.java
   trunk/framework/impl/pom.xml
   trunk/framework/test/pom.xml
   trunk/samples/seamPortletEar/seamBookingPortlet/pom.xml
   trunk/samples/seamPortletEar/seamBookingPortlet/src/main/webapp/WEB-INF/portlet.xml
   trunk/samples/seamPortletEar/seamBookingPortlet/src/main/webapp/WEB-INF/seamBookingPortlet-object.xml
Log:
Import patched yuicompressor-maven-plugin into project, to aggregate and test JavaScripts.
Generate aggregatet scripts and styles.
Modify Seam Booking portlet to work with a refactored bridge.

Added: trunk/cdk/maven-javascript-plugin/README-YUICompressor.txt
===================================================================
--- trunk/cdk/maven-javascript-plugin/README-YUICompressor.txt	                        (rev 0)
+++ trunk/cdk/maven-javascript-plugin/README-YUICompressor.txt	2007-12-11 23:30:42 UTC (rev 4755)
@@ -0,0 +1,76 @@
+==============================================================================
+YUI Compressor
+==============================================================================
+
+NAME
+
+  YUI Compressor - The Yahoo! JavaScript and CSS Compressor
+
+SYNOPSIS
+
+  java -jar yuicompressor.jar
+      [-h, --help] [--line-break] [--nomunge]
+      [--warn] [--charset character-set]
+      [-o outfile] infile
+
+DESCRIPTION
+
+  The YUI Compressor is a JavaScript compressor which, in addition to removing
+  comments and white-spaces, obfuscates local variables using the smallest
+  possible variable name. This obfuscation is safe, even when using constructs
+  such as 'eval' or 'with' (although the compression is not optimal is those
+  cases) Compared to jsmin, the average savings is around 20%.
+
+  The YUI Compressor is also able to safely compress CSS files. The decision
+  on which compressor is being used is made on the file extension (js or css)
+
+GLOBAL OPTIONS
+
+  -h, --help
+      Prints help on how to use the YUI Compressor
+
+  --type js|css
+      The type of compressor (JavaScript or CSS) is chosen based on the
+      extension of the input file name (.js or .css) If the input file name
+      does not have an extension, or that extension is neither .js nor .css,
+      the type option MUST be specified.
+
+  --charset character-set
+      If a supported character set is specified, the YUI Compressor will use it
+      to read the input file. Otherwise, it will assume that the platform's
+      default character set is being used. The output file is encoded using
+      the same character set.
+
+  -o outfile
+      Place output in file outfile. If not specified, the YUI Compressor will
+      place the output in a file which name is made of the input file name,
+      the "-min" suffix and the "js" extension.
+
+JAVASCRIPT ONLY OPTIONS
+
+  --line-break
+      Adds a line feed character after each semi-colon character in the
+      output file (may help debugging with the MS Script debugger)
+
+  --nomunge
+      Minify only. Do not obfuscate local symbols.
+
+  --warn
+      Prints additional warnings such as duplicate variable declarations,
+      missing variable declaration, unrecommended practices, etc.
+
+NOTES
+
+  The YUI Compressor requires Java version >= 1.4.
+
+AUTHOR
+
+  The YUI Compressor was written and is maintained by:
+      Julien Lecomte <jlecomte at yahoo-inc.com>
+  The CSS portion is a port of Isaac Schlueter's cssmin utility.
+
+COPYRIGHT
+
+  Copyright (c) 2007, Yahoo! Inc. All rights reserved.
+  Code licensed under the BSD License:
+      http://developer.yahoo.net/yui/license.txt


Property changes on: trunk/cdk/maven-javascript-plugin/README-YUICompressor.txt
___________________________________________________________________
Name: svn:mime-type
   + text/plain

Added: trunk/cdk/maven-javascript-plugin/README-yuicompressor.txt
===================================================================
--- trunk/cdk/maven-javascript-plugin/README-yuicompressor.txt	                        (rev 0)
+++ trunk/cdk/maven-javascript-plugin/README-yuicompressor.txt	2007-12-11 23:30:42 UTC (rev 4755)
@@ -0,0 +1,100 @@
+==============================================================================
+YUI Compressor
+==============================================================================
+
+NAME
+
+  YUI Compressor - The Yahoo! JavaScript and CSS Compressor
+
+SYNOPSIS
+
+  Usage: java -jar yuicompressor-x.y.z.jar [options] [input file]
+
+  Global Options
+    -h, --help              Displays this information
+    --type <js|css>         Specifies the type of the input file
+    --charset <charset>     Read the input file using <charset>
+    --line-break <column>   Insert a line break after the specified column number
+    -o <file>               Place the output into <file>. Defaults to stdout.
+
+  JavaScript Options
+    --warn                  Display possible errors in the code
+    --nomunge               Minify only, do not obfuscate
+    --preserve-semi         Preserve all semicolons
+    --preserve-strings      Do not merge concatenated string literals
+
+DESCRIPTION
+
+  The YUI Compressor is a JavaScript compressor which, in addition to removing
+  comments and white-spaces, obfuscates local variables using the smallest
+  possible variable name. This obfuscation is safe, even when using constructs
+  such as 'eval' or 'with' (although the compression is not optimal is those
+  cases) Compared to jsmin, the average savings is around 20%.
+
+  The YUI Compressor is also able to safely compress CSS files. The decision
+  on which compressor is being used is made on the file extension (js or css)
+
+GLOBAL OPTIONS
+
+  -h, --help
+      Prints help on how to use the YUI Compressor
+
+  --line-break
+      Some source control tools don't like files containing lines longer than,
+      say 8000 characters. The linebreak option is used in that case to split
+      long lines after a specific column. It can also be used to make the code
+      more readable, easier to debug (especially with the MS Script Debugger)
+      Specify 0 to get a line break after each semi-colon in JavaScript, and
+      after each rule in CSS.
+
+  --type js|css
+      The type of compressor (JavaScript or CSS) is chosen based on the
+      extension of the input file name (.js or .css) This option is required
+      if no input file has been specified. Otherwise, this option is only
+      required if the input file extension is neither 'js' nor 'css'.
+
+  --charset character-set
+      If a supported character set is specified, the YUI Compressor will use it
+      to read the input file. Otherwise, it will assume that the platform's
+      default character set is being used. The output file is encoded using
+      the same character set.
+
+  -o outfile
+      Place output in file outfile. If not specified, the YUI Compressor will
+      default to the standard output, which you can redirect to a file.
+
+JAVASCRIPT ONLY OPTIONS
+
+  --nomunge
+      Minify only. Do not obfuscate local symbols.
+
+  --warn
+      Prints additional warnings such as duplicate variable declarations,
+      missing variable declaration, unrecommended practices, etc.
+
+  --preserve-semi
+      Preserve unnecessary semicolons (such as right before a '}') This option
+      is useful when compressed code has to be run through JSLint (which is the
+      case of YUI for example)
+
+  --preserve-strings
+      Use this option to specify that concatenated string literals should
+      never be merged.
+
+NOTES
+
+  + If no input file is specified, it defaults to stdin.
+
+  + The YUI Compressor requires Java version >= 1.4.
+
+AUTHOR
+
+  The YUI Compressor was written and is maintained by:
+      Julien Lecomte <jlecomte at yahoo-inc.com>
+  The CSS portion is a port of Isaac Schlueter's cssmin utility.
+
+COPYRIGHT
+
+  Copyright (c) 2007, Yahoo! Inc. All rights reserved.
+  Code licensed under the BSD License:
+      http://developer.yahoo.net/yui/license.txt


Property changes on: trunk/cdk/maven-javascript-plugin/README-yuicompressor.txt
___________________________________________________________________
Name: svn:mime-type
   + text/plain

Added: trunk/cdk/maven-javascript-plugin/pom.xml
===================================================================
--- trunk/cdk/maven-javascript-plugin/pom.xml	                        (rev 0)
+++ trunk/cdk/maven-javascript-plugin/pom.xml	2007-12-11 23:30:42 UTC (rev 4755)
@@ -0,0 +1,56 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+	<modelVersion>4.0.0</modelVersion>
+	<parent>
+		<artifactId>cdk</artifactId>
+		<groupId>org.richfaces</groupId>
+		<version>3.2.0-SNAPSHOT</version>
+	</parent>
+	<groupId>org.richfaces.cdk</groupId>
+	<artifactId>maven-javascript-plugin</artifactId>
+	<packaging>maven-plugin</packaging>
+	<name>YUI Compressor Maven Mojo</name>
+	<description>
+		To compress (Minify + Ofuscate) Javascript files and CSS files
+		(using YUI Compressor from Julien Lecomte) and/or to check
+		Javascript files with jslint.
+	</description>
+
+	<dependencies>
+		<dependency>
+			<groupId>rhino</groupId>
+			<artifactId>js</artifactId>
+			<version>1.6R7</version>
+		</dependency>
+		<dependency>
+			<groupId>org.apache.maven</groupId>
+			<artifactId>maven-plugin-api</artifactId>
+			<version>2.0.7</version>
+			<scope>provided</scope>
+		</dependency>
+		<dependency>
+			<groupId>org.apache.maven</groupId>
+			<artifactId>maven-project</artifactId>
+			<version>2.0.7</version>
+			<scope>provided</scope>
+		</dependency>
+	</dependencies>
+	<build>
+		<plugins></plugins>
+	</build>
+	<reporting>
+		<plugins>
+			<plugin>
+				<groupId>org.apache.maven.plugins</groupId>
+				<artifactId>maven-plugin-plugin</artifactId>
+			</plugin>
+		</plugins>
+	</reporting>
+
+	<properties>
+		<java.src.version>1.5</java.src.version>
+		<runtime.log>target/velocity.log</runtime.log>
+	</properties>
+
+</project>


Property changes on: trunk/cdk/maven-javascript-plugin/pom.xml
___________________________________________________________________
Name: svn:mime-type
   + text/plain
Name: svn:keywords
   + Date Revision Author

Added: trunk/cdk/maven-javascript-plugin/src/changes/changes.xml
===================================================================
--- trunk/cdk/maven-javascript-plugin/src/changes/changes.xml	                        (rev 0)
+++ trunk/cdk/maven-javascript-plugin/src/changes/changes.xml	2007-12-11 23:30:42 UTC (rev 4755)
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<document>
+  <properties>
+    <author email="dwayneb at users.sourceforge.net">David Bernard</author>
+  </properties>
+  <body>
+    <release version="TODO" description="Future">
+      <action dev="dwayneb" type="add">add support for offline mode (don't failed)</action>
+      <action dev="dwayneb" type="add">generate an xml report for integration with external tool (like QALab)</action>
+      <action dev="dwayneb" type="add">generate an html/xdoc report for integration with the site (like other static analyser : pmd, checkstyle,...)</action>
+      <action dev="dwayneb" type="add">more test</action>
+      <action dev="dwayneb" type="add">add option to stop maven processing if Spoon building failed (pre-compilation by JDTCompiler)</action>
+      <action dev="dwayneb" type="add">add logging information (about download,...)</action>
+    </release>
+    <release version="0.6.1" date="2007-06-27" description="spoon-1.3">
+      <action dev="dwayneb" type="update">move to spoon-1.3</action>
+    </release>
+    <release version="0.6" date="2007-06-14" description="testing">
+      <action dev="dwayneb" type="fix">keep annotation in the generated bytecode</action>
+      <action dev="dwayneb" type="update">enhance/fix support for using plugin for test phase with local spoonlet</action>
+      <action dev="dwayneb" type="add">add the goal 'test-recompile'</action>
+      <action dev="dwayneb" type="update">rename the goal 'test-run' to 'test-generate'</action>
+    </release>
+    <release version="0.5" date="2007-06-06" description="spoon-1.2">
+      <action dev="dwayneb" type="add">add option to stop maven processing if WARNING or ERROR are reported by Spoonlet(s)</action>
+      <action dev="dwayneb" type="fix">use maven logger for every report (include new from spoon-core-1.2)</action>
+      <action dev="dwayneb" type="update">change scm from subversion (svn) to mercurial (hg)</action>
+      <action dev="dwayneb" type="update">move to spoon-core-1.2.</action>
+      <action dev="dwayneb" type="fix">change the groupId from spoon.contrib to net.sf.alchim to follow Maven's convention</action>
+    </release>
+    <release version="0.4" description="launcher improvement">
+      <action dev="dwayneb" type="fix">support change in the api of spoon-1.1-SNAPSHOT.</action>
+      <action dev="dwayneb" type="fix">display classpath as debug message</action>
+      <action dev="dwayneb" type="add">add basic support SNAPSHOT (always downloaded)</action>
+      <action dev="dwayneb" type="add">add basic support for relocation of artifact's groupId (see http://maven.apache.org/guides/mini/guide-relocation.html)</action>
+    </release>
+    <release version="0.3" date="2006-12-03" description="Support spoon.cfg.xml">
+      <action dev="dwayneb" type="add">add support of "spoon.cfg.xml".</action>
+      <action dev="dwayneb" type="add">rename previous 'run' goal by 'generate' goal.</action>
+      <action dev="dwayneb" type="add">add 'recompile' goal.</action>
+      <action dev="dwayneb" type="fix">fix classloader and classpath issue when compile and run spoonlet.</action>
+    </release>
+    <release version="0.2" date="2006-11-23" description="First release">
+      <action dev="dwayneb" type="add">Publish the project on sourceforge (under alchim project)</action>
+    </release>
+  </body>
+</document>


Property changes on: trunk/cdk/maven-javascript-plugin/src/changes/changes.xml
___________________________________________________________________
Name: svn:executable
   + *
Name: svn:mime-type
   + text/plain
Name: svn:keywords
   + Date Revision Author

Added: trunk/cdk/maven-javascript-plugin/src/main/java/com/yahoo/platform/yui/compressor/CssCompressor.java
===================================================================
--- trunk/cdk/maven-javascript-plugin/src/main/java/com/yahoo/platform/yui/compressor/CssCompressor.java	                        (rev 0)
+++ trunk/cdk/maven-javascript-plugin/src/main/java/com/yahoo/platform/yui/compressor/CssCompressor.java	2007-12-11 23:30:42 UTC (rev 4755)
@@ -0,0 +1,157 @@
+/*
+ * YUI Compressor
+ * Author: Julien Lecomte <jlecomte at yahoo-inc.com>
+ * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
+ * Code licensed under the BSD License:
+ *     http://developer.yahoo.net/yui/license.txt
+ *
+ * This code is a port of Isaac Schlueter's cssmin utility.
+ */
+
+package com.yahoo.platform.yui.compressor;
+
+import java.io.IOException;
+import java.io.Reader;
+import java.io.Writer;
+import java.util.regex.Pattern;
+import java.util.regex.Matcher;
+
+public class CssCompressor {
+
+    private StringBuffer srcsb = new StringBuffer();
+
+    public CssCompressor(Reader in) throws IOException {
+        // Read the stream...
+        int c;
+        while ((c = in.read()) != -1) {
+            srcsb.append((char) c);
+        }
+    }
+
+    public void compress(Writer out, int linebreakpos)
+            throws IOException {
+
+        Pattern p;
+        Matcher m;
+        String css;
+        StringBuffer sb;
+        int startIndex, endIndex;
+
+        // Remove all comment blocks...
+        sb = new StringBuffer(srcsb.toString());
+        while ((startIndex = sb.indexOf("/*")) >= 0) {
+            endIndex = sb.indexOf("*/", startIndex + 2);
+            if (endIndex >= startIndex + 2)
+                sb.delete(startIndex, endIndex + 2);
+        }
+
+        css = sb.toString();
+
+        // Normalize all whitespace strings to single spaces. Easier to work with that way.
+        css = css.replaceAll("\\s+", " ");
+
+        // Remove the spaces before the things that should not have spaces before them.
+        // But, be careful not to turn "p :link {...}" into "p:link{...}"
+        // Swap out any pseudo-class colons with the token, and then swap back.
+        sb = new StringBuffer();
+        p = Pattern.compile("(^|\\})(([^\\{:])+:)+([^\\{]*\\{)");
+        m = p.matcher(css);
+        while (m.find()) {
+            String s = m.group();
+            s = s.replaceAll(":", "___PSEUDOCLASSCOLON___");
+            m.appendReplacement(sb, s);
+        }
+        m.appendTail(sb);
+        css = sb.toString();
+        css = css.replaceAll("\\s+([!{};:>+\\(\\)\\],])", "$1");
+        css = css.replaceAll("___PSEUDOCLASSCOLON___", ":");
+
+        // Remove the spaces after the things that should not have spaces after them.
+        css = css.replaceAll("([!{}:;>+\\(\\[,])\\s+", "$1");
+
+        // Add the semicolon where it's missing.
+        css = css.replaceAll("([^;\\}])}", "$1;}");
+
+        // Replace 0(px,em,%) with 0.
+        css = css.replaceAll("([\\s:])(0)(px|em|%|in|cm|mm|pc|pt|ex)", "$1$2");
+
+        // Replace 0 0 0 0; with 0.
+        css = css.replaceAll(":0 0 0 0;", ":0;");
+        css = css.replaceAll(":0 0 0;", ":0;");
+        css = css.replaceAll(":0 0;", ":0;");
+        // Replace background-position:0; with background-position:0 0;
+        css = css.replaceAll("background-position:0;", "background-position:0 0;");
+
+        // Replace 0.6 to .6, but only when preceded by : or a white-space
+        css = css.replaceAll("(:|\\s)0+\\.(\\d+)", "$1.$2");
+
+        // Shorten colors from rgb(51,102,153) to #336699
+        // This makes it more likely that it'll get further compressed in the next step.
+        p = Pattern.compile("rgb\\s*\\(\\s*([0-9,\\s]+)\\s*\\)");
+        m = p.matcher(css);
+        sb = new StringBuffer();
+        while (m.find()) {
+            String[] rgbcolors = m.group(1).split(",");
+            StringBuffer hexcolor = new StringBuffer("#");
+            for (int i = 0; i < rgbcolors.length; i++) {
+                int val = Integer.parseInt(rgbcolors[i]);
+                if (val < 16) {
+                    hexcolor.append("0");
+                }
+                hexcolor.append(Integer.toHexString(val));
+            }
+            m.appendReplacement(sb, hexcolor.toString());
+        }
+        m.appendTail(sb);
+        css = sb.toString();
+
+        // Shorten colors from #AABBCC to #ABC. Note that we want to make sure
+        // the color is not preceded by either ", " or =. Indeed, the property
+        //     filter: chroma(color="#FFFFFF");
+        // would become
+        //     filter: chroma(color="#FFF");
+        // which makes the filter break in IE.
+        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])");
+        m = p.matcher(css);
+        sb = new StringBuffer();
+        while (m.find()) {
+            // Test for AABBCC pattern
+            if (m.group(3).equalsIgnoreCase(m.group(4)) &&
+                    m.group(5).equalsIgnoreCase(m.group(6)) &&
+                    m.group(7).equalsIgnoreCase(m.group(8))) {
+                m.appendReplacement(sb, m.group(1) + m.group(2) + "#" + m.group(3) + m.group(5) + m.group(7));
+            } else {
+                m.appendReplacement(sb, m.group());
+            }
+        }
+        m.appendTail(sb);
+        css = sb.toString();
+
+        // Remove empty rules.
+        css = css.replaceAll("[^\\}]+\\{;\\}", "");
+
+        if (linebreakpos >= 0) {
+            // Some source control tools don't like it when files containing lines longer
+            // than, say 8000 characters, are checked in. The linebreak option is used in
+            // that case to split long lines after a specific column.
+            int i = 0;
+            int linestartpos = 0;
+            sb = new StringBuffer(css);
+            while (i < sb.length()) {
+                char c = sb.charAt(i++);
+                if (c == '}' && i - linestartpos > linebreakpos) {
+                    sb.insert(i, '\n');
+                    linestartpos = i;
+                }
+            }
+
+            css = sb.toString();
+        }
+
+        // Trim the final string (for any leading or trailing white spaces)
+        css = css.trim();
+
+        // Write the output...
+        out.write(css);
+    }
+}


Property changes on: trunk/cdk/maven-javascript-plugin/src/main/java/com/yahoo/platform/yui/compressor/CssCompressor.java
___________________________________________________________________
Name: svn:mime-type
   + text/plain
Name: svn:keywords
   + Date Revision Author

Added: trunk/cdk/maven-javascript-plugin/src/main/java/com/yahoo/platform/yui/compressor/JavaScriptCompressor.java
===================================================================
--- trunk/cdk/maven-javascript-plugin/src/main/java/com/yahoo/platform/yui/compressor/JavaScriptCompressor.java	                        (rev 0)
+++ trunk/cdk/maven-javascript-plugin/src/main/java/com/yahoo/platform/yui/compressor/JavaScriptCompressor.java	2007-12-11 23:30:42 UTC (rev 4755)
@@ -0,0 +1,1151 @@
+/*
+ * YUI Compressor
+ * Author: Julien Lecomte <jlecomte at yahoo-inc.com>
+ * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
+ * Code licensed under the BSD License:
+ *     http://developer.yahoo.net/yui/license.txt
+ */
+
+package com.yahoo.platform.yui.compressor;
+
+import org.mozilla.javascript.*;
+
+import java.io.IOException;
+import java.io.Reader;
+import java.io.Writer;
+import java.util.*;
+
+public class JavaScriptCompressor {
+
+    static final ArrayList ones;
+    static final ArrayList twos;
+    static final ArrayList threes;
+
+    static final Set builtin = new HashSet();
+    static final Map literals = new Hashtable();
+
+    static {
+
+        // This list contains all the 3 characters or less built-in global
+        // symbols available in a browser. Please add to this list if you
+        // see anything missing.
+        builtin.add("NaN");
+        builtin.add("top");
+
+        ones = new ArrayList();
+        for (char c = 'A'; c <= 'Z'; c++)
+            ones.add(Character.toString(c));
+        for (char c = 'a'; c <= 'z'; c++)
+            ones.add(Character.toString(c));
+
+        twos = new ArrayList();
+        for (int i = 0; i < ones.size(); i++) {
+            String one = (String) ones.get(i);
+            for (char c = 'A'; c <= 'Z'; c++)
+                twos.add(one + Character.toString(c));
+            for (char c = 'a'; c <= 'z'; c++)
+                twos.add(one + Character.toString(c));
+            for (char c = '0'; c <= '9'; c++)
+                twos.add(one + Character.toString(c));
+        }
+
+        // Remove two-letter JavaScript reserved words and built-in globals...
+        twos.remove("as");
+        twos.remove("is");
+        twos.remove("do");
+        twos.remove("if");
+        twos.remove("in");
+        twos.removeAll(builtin);
+
+        threes = new ArrayList();
+        for (int i = 0; i < twos.size(); i++) {
+            String two = (String) twos.get(i);
+            for (char c = 'A'; c <= 'Z'; c++)
+                threes.add(two + Character.toString(c));
+            for (char c = 'a'; c <= 'z'; c++)
+                threes.add(two + Character.toString(c));
+            for (char c = '0'; c <= '9'; c++)
+                threes.add(two + Character.toString(c));
+        }
+
+        // Remove three-letter JavaScript reserved words and built-in globals...
+        threes.remove("for");
+        threes.remove("int");
+        threes.remove("new");
+        threes.remove("try");
+        threes.remove("use");
+        threes.remove("var");
+        threes.removeAll(builtin);
+
+        // That's up to ((26+26)*(1+(26+26+10)))*(1+(26+26+10))-8
+        // (206,380 symbols per scope)
+
+        // The following list comes from org/mozilla/javascript/Decompiler.java...
+        literals.put(new Integer(Token.GET), "get ");
+        literals.put(new Integer(Token.SET), "set ");
+        literals.put(new Integer(Token.TRUE), "true");
+        literals.put(new Integer(Token.FALSE), "false");
+        literals.put(new Integer(Token.NULL), "null");
+        literals.put(new Integer(Token.THIS), "this");
+        literals.put(new Integer(Token.FUNCTION), "function ");
+        literals.put(new Integer(Token.COMMA), ",");
+        literals.put(new Integer(Token.LC), "{");
+        literals.put(new Integer(Token.RC), "}");
+        literals.put(new Integer(Token.LP), "(");
+        literals.put(new Integer(Token.RP), ")");
+        literals.put(new Integer(Token.LB), "[");
+        literals.put(new Integer(Token.RB), "]");
+        literals.put(new Integer(Token.DOT), ".");
+        literals.put(new Integer(Token.NEW), "new ");
+        literals.put(new Integer(Token.DELPROP), "delete ");
+        literals.put(new Integer(Token.IF), "if");
+        literals.put(new Integer(Token.ELSE), "else");
+        literals.put(new Integer(Token.FOR), "for");
+        literals.put(new Integer(Token.IN), " in ");
+        literals.put(new Integer(Token.WITH), "with");
+        literals.put(new Integer(Token.WHILE), "while");
+        literals.put(new Integer(Token.DO), "do");
+        literals.put(new Integer(Token.TRY), "try");
+        literals.put(new Integer(Token.CATCH), "catch");
+        literals.put(new Integer(Token.FINALLY), "finally");
+        literals.put(new Integer(Token.THROW), "throw ");
+        literals.put(new Integer(Token.SWITCH), "switch");
+        literals.put(new Integer(Token.BREAK), "break ");
+        literals.put(new Integer(Token.CONTINUE), "continue ");
+        literals.put(new Integer(Token.CASE), "case ");
+        literals.put(new Integer(Token.DEFAULT), "default");
+        literals.put(new Integer(Token.RETURN), "return ");
+        literals.put(new Integer(Token.VAR), "var ");
+        literals.put(new Integer(Token.SEMI), ";");
+        literals.put(new Integer(Token.ASSIGN), "=");
+        literals.put(new Integer(Token.ASSIGN_ADD), "+=");
+        literals.put(new Integer(Token.ASSIGN_SUB), "-=");
+        literals.put(new Integer(Token.ASSIGN_MUL), "*=");
+        literals.put(new Integer(Token.ASSIGN_DIV), "/=");
+        literals.put(new Integer(Token.ASSIGN_MOD), "%=");
+        literals.put(new Integer(Token.ASSIGN_BITOR), "|=");
+        literals.put(new Integer(Token.ASSIGN_BITXOR), "^=");
+        literals.put(new Integer(Token.ASSIGN_BITAND), "&=");
+        literals.put(new Integer(Token.ASSIGN_LSH), "<<=");
+        literals.put(new Integer(Token.ASSIGN_RSH), ">>=");
+        literals.put(new Integer(Token.ASSIGN_URSH), ">>>=");
+        literals.put(new Integer(Token.HOOK), "?");
+        literals.put(new Integer(Token.OBJECTLIT), ":");
+        literals.put(new Integer(Token.COLON), ":");
+        literals.put(new Integer(Token.OR), "||");
+        literals.put(new Integer(Token.AND), "&&");
+        literals.put(new Integer(Token.BITOR), "|");
+        literals.put(new Integer(Token.BITXOR), "^");
+        literals.put(new Integer(Token.BITAND), "&");
+        literals.put(new Integer(Token.SHEQ), "===");
+        literals.put(new Integer(Token.SHNE), "!==");
+        literals.put(new Integer(Token.EQ), "==");
+        literals.put(new Integer(Token.NE), "!=");
+        literals.put(new Integer(Token.LE), "<=");
+        literals.put(new Integer(Token.LT), "<");
+        literals.put(new Integer(Token.GE), ">=");
+        literals.put(new Integer(Token.GT), ">");
+        literals.put(new Integer(Token.INSTANCEOF), " instanceof ");
+        literals.put(new Integer(Token.LSH), "<<");
+        literals.put(new Integer(Token.RSH), ">>");
+        literals.put(new Integer(Token.URSH), ">>>");
+        literals.put(new Integer(Token.TYPEOF), "typeof ");
+        literals.put(new Integer(Token.VOID), "void ");
+        literals.put(new Integer(Token.CONST), "const ");
+        literals.put(new Integer(Token.NOT), "!");
+        literals.put(new Integer(Token.BITNOT), "~");
+        literals.put(new Integer(Token.POS), "+");
+        literals.put(new Integer(Token.NEG), "-");
+        literals.put(new Integer(Token.INC), "++");
+        literals.put(new Integer(Token.DEC), "--");
+        literals.put(new Integer(Token.ADD), "+");
+        literals.put(new Integer(Token.SUB), "-");
+        literals.put(new Integer(Token.MUL), "*");
+        literals.put(new Integer(Token.DIV), "/");
+        literals.put(new Integer(Token.MOD), "%");
+        literals.put(new Integer(Token.COLONCOLON), "::");
+        literals.put(new Integer(Token.DOTDOT), "..");
+        literals.put(new Integer(Token.DOTQUERY), ".(");
+        literals.put(new Integer(Token.XMLATTR), "@");
+    }
+
+    private static int countChar(String haystack, char needle) {
+        int idx = 0;
+        int count = 0;
+        int length = haystack.length();
+        while (idx < length) {
+            char c = haystack.charAt(idx++);
+            if (c == needle) {
+                count++;
+            }
+        }
+        return count;
+    }
+
+    private static int printSourceString(String source, int offset, StringBuffer sb) {
+        int length = source.charAt(offset);
+        ++offset;
+        if ((0x8000 & length) != 0) {
+            length = ((0x7FFF & length) << 16) | source.charAt(offset);
+            ++offset;
+        }
+        if (sb != null) {
+            String str = source.substring(offset, offset + length);
+            sb.append(str);
+        }
+        return offset + length;
+    }
+
+    private static int printSourceNumber(String source,
+            int offset, StringBuffer sb) {
+        double number = 0.0;
+        char type = source.charAt(offset);
+        ++offset;
+        if (type == 'S') {
+            if (sb != null) {
+                number = source.charAt(offset);
+            }
+            ++offset;
+        } else if (type == 'J' || type == 'D') {
+            if (sb != null) {
+                long lbits;
+                lbits = (long) source.charAt(offset) << 48;
+                lbits |= (long) source.charAt(offset + 1) << 32;
+                lbits |= (long) source.charAt(offset + 2) << 16;
+                lbits |= (long) source.charAt(offset + 3);
+                if (type == 'J') {
+                    number = lbits;
+                } else {
+                    number = Double.longBitsToDouble(lbits);
+                }
+            }
+            offset += 4;
+        } else {
+            // Bad source
+            throw new RuntimeException();
+        }
+        if (sb != null) {
+            sb.append(ScriptRuntime.numberToString(number, 10));
+        }
+        return offset;
+    }
+
+    private static ArrayList parse(Reader in, ErrorReporter reporter)
+            throws IOException, EvaluatorException {
+
+        CompilerEnvirons env = new CompilerEnvirons();
+        Parser parser = new Parser(env, reporter);
+        parser.parse(in, null, 1);
+        String source = parser.getEncodedSource();
+
+        int offset = 0;
+        int length = source.length();
+        ArrayList tokens = new ArrayList();
+        StringBuffer sb = new StringBuffer();
+
+        while (offset < length) {
+            int tt = source.charAt(offset++);
+            switch (tt) {
+
+                case Token.IECC:
+                case Token.NAME:
+                case Token.REGEXP:
+                case Token.STRING:
+                    sb.setLength(0);
+                    offset = printSourceString(source, offset, sb);
+                    tokens.add(new JavaScriptToken(tt, sb.toString()));
+                    break;
+
+                case Token.NUMBER:
+                    sb.setLength(0);
+                    offset = printSourceNumber(source, offset, sb);
+                    tokens.add(new JavaScriptToken(tt, sb.toString()));
+                    break;
+
+                default:
+                    String literal = (String) literals.get(new Integer(tt));
+                    if (literal != null) {
+                        tokens.add(new JavaScriptToken(tt, literal));
+                    }
+                    break;
+            }
+        }
+
+        return tokens;
+    }
+
+    private static ArrayList processStringLiterals(ArrayList tokens, boolean merge) {
+
+        String tv;
+        int i, length;
+        ArrayList result = new ArrayList();
+        JavaScriptToken token, prevToken, nextToken;
+
+        // Concatenate string literals that are being appended wherever
+        // it is safe to do so. Note that we take care of the case:
+        //     "a" + "b".toUpperCase()
+
+        for (i = 0, length = tokens.size(); i < length; i++) {
+            token = (JavaScriptToken) tokens.get(i);
+            switch (token.getType()) {
+
+                case Token.ADD:
+                    if (merge) {
+                        if (i > 0 && i < length) {
+                            prevToken = (JavaScriptToken) result.get(result.size() - 1);
+                            nextToken = (JavaScriptToken) tokens.get(i + 1);
+                            if (prevToken.getType() == Token.STRING && nextToken.getType() == Token.STRING &&
+                                    (i == length - 1 || ((JavaScriptToken) tokens.get(i + 2)).getType() != Token.DOT)) {
+                                result.set(result.size() - 1, new JavaScriptToken(Token.STRING,
+                                        prevToken.getValue() + nextToken.getValue()));
+                                i++; // not a good practice, but oh well...
+                                break;
+                            }
+                        }
+                    }
+
+                    /* FALLSTHROUGH */
+
+                default:
+                    result.add(token);
+                    break;
+            }
+        }
+
+        // Second pass...
+
+        for (i = 0, length = result.size(); i < length; i++) {
+            token = (JavaScriptToken) result.get(i);
+            if (token.getType() == Token.STRING) {
+                tv = token.getValue();
+
+                // Finally, add the quoting characters and escape the string. We use
+                // the quoting character that minimizes the amount of escaping to save
+                // a few additional bytes.
+
+                char quotechar;
+                int singleQuoteCount = countChar(tv, '\'');
+                int doubleQuoteCount = countChar(tv, '"');
+                if (doubleQuoteCount <= singleQuoteCount) {
+                    quotechar = '"';
+                } else {
+                    quotechar = '\'';
+                }
+
+                tv = quotechar + escapeString(tv, quotechar) + quotechar;
+
+                // String concatenation transforms the old script scheme:
+                //     '<scr'+'ipt ...><'+'/script>'
+                // into the following:
+                //     '<script ...></script>'
+                // which breaks if this code is embedded inside an HTML document.
+                // Since this is not the right way to do this, let's fix the code by
+                // transforming all "</script" into "<\/script"
+
+                if (tv.indexOf("</script") >= 0) {
+                    tv = tv.replaceAll("<\\/script", "<\\\\/script");
+                }
+
+                result.set(i, new JavaScriptToken(Token.STRING, tv));
+            }
+        }
+
+        return result;
+    }
+
+    // Add necessary escaping that was removed in Rhino's tokenizer.
+    private static String escapeString(String s, char quotechar) {
+
+        assert quotechar == '"' || quotechar == '\'';
+
+        if (s == null) {
+            return null;
+        }
+
+        StringBuffer sb = new StringBuffer();
+        for (int i = 0, L = s.length(); i < L; i++) {
+            int c = s.charAt(i);
+            if (c == quotechar) {
+                sb.append("\\");
+            }
+            sb.append((char) c);
+        }
+
+        return sb.toString();
+    }
+
+    private ErrorReporter logger;
+
+    private boolean munge;
+    private boolean warn;
+
+    private static final int BUILDING_SYMBOL_TREE = 1;
+    private static final int CHECKING_SYMBOL_TREE = 2;
+
+    private int mode;
+    private int offset;
+    private int braceNesting;
+    private ArrayList srctokens, tokens;
+    private Stack scopes = new Stack();
+    private ScriptOrFnScope globalScope = new ScriptOrFnScope(-1, null);
+    private Hashtable indexedScopes = new Hashtable();
+
+    public JavaScriptCompressor(Reader in, ErrorReporter reporter)
+            throws IOException, EvaluatorException {
+
+        this.logger = reporter;
+        this.srctokens = parse(in, reporter);
+    }
+
+    public void compress(Writer out, int linebreak, boolean munge, boolean warn,
+            boolean preserveAllSemiColons, boolean preserveStringLiterals)
+            throws IOException {
+
+        this.munge = munge;
+        this.warn = warn;
+
+        this.tokens = processStringLiterals(this.srctokens, !preserveStringLiterals);
+
+        buildSymbolTree();
+        mungeSymboltree();
+        StringBuffer sb = printSymbolTree(linebreak, preserveAllSemiColons);
+
+        out.write(sb.toString());
+    }
+
+    private ScriptOrFnScope getCurrentScope() {
+        return (ScriptOrFnScope) scopes.peek();
+    }
+
+    private void enterScope(ScriptOrFnScope scope) {
+        scopes.push(scope);
+    }
+
+    private void leaveCurrentScope() {
+        scopes.pop();
+    }
+
+    private JavaScriptToken consumeToken() {
+        return (JavaScriptToken) tokens.get(offset++);
+    }
+
+    private JavaScriptToken getToken(int delta) {
+        return (JavaScriptToken) tokens.get(offset + delta);
+    }
+
+    /*
+     * Returns the identifier for the specified symbol defined in
+     * the specified scope or in any scope above it. Returns null
+     * if this symbol does not have a corresponding identifier.
+     */
+    private JavaScriptIdentifier getIdentifier(String symbol, ScriptOrFnScope scope) {
+        JavaScriptIdentifier identifier;
+        while (scope != null) {
+            identifier = scope.getIdentifier(symbol);
+            if (identifier != null) {
+                return identifier;
+            }
+            scope = scope.getParentScope();
+        }
+        return null;
+    }
+
+    /*
+     * If either 'eval' or 'with' is used in a local scope, we must make
+     * sure that all containing local scopes don't get munged. Otherwise,
+     * the obfuscation would potentially introduce bugs.
+     */
+    private void protectScopeFromObfuscation(ScriptOrFnScope scope) {
+        assert scope != null;
+
+        if (scope == globalScope) {
+            // The global scope does not get obfuscated,
+            // so we don't need to worry about it...
+            return;
+        }
+
+        // Find the highest local scope containing the specified scope.
+        while (scope.getParentScope() != globalScope) {
+            scope = scope.getParentScope();
+        }
+
+        assert scope.getParentScope() == globalScope;
+        scope.preventMunging();
+    }
+
+    private String getDebugString(int max) {
+        assert max > 0;
+        StringBuffer result = new StringBuffer();
+        int start = Math.max(offset - max, 0);
+        int end = Math.min(offset + max, tokens.size());
+        for (int i = start; i < end; i++) {
+            JavaScriptToken token = (JavaScriptToken) tokens.get(i);
+            if (i == offset)
+                result.append(" ---> ");
+            result.append(token.getValue());
+            if (i == offset)
+                result.append(" <--- ");
+        }
+        return result.toString();
+    }
+
+    private void warn(String message, boolean showDebugString) {
+        if (warn) {
+            if (showDebugString) {
+                message = message + "\n" + getDebugString(10);
+            }
+            logger.warning(message, null, -1, null, -1);
+        }
+    }
+
+    private void parseFunctionDeclaration() {
+
+        String symbol;
+        JavaScriptToken token;
+        ScriptOrFnScope currentScope, fnScope;
+        JavaScriptIdentifier identifier;
+
+        currentScope = getCurrentScope();
+
+        token = consumeToken();
+        if (token.getType() == Token.NAME) {
+            if (mode == BUILDING_SYMBOL_TREE) {
+                // Get the name of the function and declare it in the current scope.
+                symbol = token.getValue();
+                if (currentScope.getIdentifier(symbol) != null) {
+                    warn("[WARNING] The function " + symbol + " has already been declared in the same scope...", true);
+                }
+                currentScope.declareIdentifier(symbol);
+            }
+            token = consumeToken();
+        }
+
+        assert token.getType() == Token.LP;
+        if (mode == BUILDING_SYMBOL_TREE) {
+            fnScope = new ScriptOrFnScope(braceNesting, currentScope);
+            indexedScopes.put(new Integer(offset), fnScope);
+        } else {
+            fnScope = (ScriptOrFnScope) indexedScopes.get(new Integer(offset));
+        }
+
+        // Parse function arguments.
+        int argpos = 0;
+        while ((token = consumeToken()).getType() != Token.RP) {
+            assert token.getType() == Token.NAME ||
+                    token.getType() == Token.COMMA;
+            if (token.getType() == Token.NAME && mode == BUILDING_SYMBOL_TREE) {
+                symbol = token.getValue();
+                identifier = fnScope.declareIdentifier(symbol);
+                if (symbol.equals("$super") && argpos == 0) {
+                    // Exception for Prototype 1.6...
+                    identifier.preventMunging();
+                }
+                argpos++;
+            }
+        }
+
+        token = consumeToken();
+        assert token.getType() == Token.LC;
+        braceNesting++;
+
+        token = getToken(0);
+        if (token.getType() == Token.STRING &&
+                getToken(1).getType() == Token.SEMI) {
+            // This is a hint. Hints are empty statements that look like
+            // "localvar1:nomunge, localvar2:nomunge"; They allow developers
+            // to prevent specific symbols from getting obfuscated (some heretic
+            // implementations, such as Prototype 1.6, require specific variable
+            // names, such as $super for example, in order to work appropriately.
+            // Note: right now, only "nomunge" is supported in the right hand side
+            // of a hint. However, in the future, the right hand side may contain
+            // other values.
+            consumeToken();
+            String hints = token.getValue();
+            // Remove the leading and trailing quotes...
+            hints = hints.substring(1, hints.length() - 1).trim();
+            StringTokenizer st1 = new StringTokenizer(hints, ",");
+            while (st1.hasMoreTokens()) {
+                String hint = st1.nextToken();
+                int idx = hint.indexOf(':');
+                if (idx <= 0 || idx >= hint.length() - 1) {
+                    if (mode == BUILDING_SYMBOL_TREE) {
+                        // No need to report the error twice, hence the test...
+                        warn("[WARNING] Invalid hint syntax: " + hint, true);
+                    }
+                    break;
+                }
+                String variableName = hint.substring(0, idx).trim();
+                String variableType = hint.substring(idx + 1).trim();
+                if (mode == BUILDING_SYMBOL_TREE) {
+                    fnScope.addHint(variableName, variableType);
+                } else if (mode == CHECKING_SYMBOL_TREE) {
+                    identifier = fnScope.getIdentifier(variableName);
+                    if (identifier != null) {
+                        if (variableType.equals("nomunge")) {
+                            identifier.preventMunging();
+                        } else {
+                            warn("[WARNING] Unsupported hint value: " + hint, true);
+                        }
+                    } else {
+                        warn("[WARNING] Hint refers to an unknown identifier: " + hint, true);
+                    }
+                }
+            }
+        }
+
+        parseScope(fnScope);
+    }
+
+    private void parseCatch() {
+
+        String symbol;
+        JavaScriptToken token;
+        ScriptOrFnScope currentScope;
+        JavaScriptIdentifier identifier;
+
+        token = getToken(-1);
+        assert token.getType() == Token.CATCH;
+        token = consumeToken();
+        assert token.getType() == Token.LP;
+        token = consumeToken();
+        assert token.getType() == Token.NAME;
+
+        symbol = token.getValue();
+        currentScope = getCurrentScope();
+
+        if (mode == BUILDING_SYMBOL_TREE) {
+            // We must declare the exception identifier in the containing function
+            // scope to avoid errors related to the obfuscation process. No need to
+            // display a warning if the symbol was already declared here...
+            currentScope.declareIdentifier(symbol);
+        } else {
+            identifier = getIdentifier(symbol, currentScope);
+            identifier.incrementRefcount();
+        }
+
+        token = consumeToken();
+        assert token.getType() == Token.RP;
+    }
+
+    private void parseExpression() {
+
+        // Parse the expression until we encounter a comma or a semi-colon
+        // in the same brace nesting, bracket nesting and paren nesting.
+        // Parse functions if any...
+
+        String symbol;
+        JavaScriptToken token;
+        ScriptOrFnScope currentScope;
+        JavaScriptIdentifier identifier;
+
+        int expressionBraceNesting = braceNesting;
+        int bracketNesting = 0;
+        int parensNesting = 0;
+
+        int length = tokens.size();
+
+        while (offset < length) {
+
+            token = consumeToken();
+            currentScope = getCurrentScope();
+
+            switch (token.getType()) {
+
+                case Token.SEMI:
+                case Token.COMMA:
+                    if (braceNesting == expressionBraceNesting &&
+                            bracketNesting == 0 &&
+                            parensNesting == 0) {
+                        return;
+                    }
+                    break;
+
+                case Token.FUNCTION:
+                    parseFunctionDeclaration();
+                    break;
+
+                case Token.LC:
+                    braceNesting++;
+                    break;
+
+                case Token.RC:
+                    braceNesting--;
+                    assert braceNesting >= expressionBraceNesting;
+                    break;
+
+                case Token.LB:
+                    bracketNesting++;
+                    break;
+
+                case Token.RB:
+                    bracketNesting--;
+                    break;
+
+                case Token.LP:
+                    parensNesting++;
+                    break;
+
+                case Token.RP:
+                    parensNesting--;
+                    break;
+
+                case Token.IECC:
+                    if (mode == BUILDING_SYMBOL_TREE) {
+                        protectScopeFromObfuscation(currentScope);
+                        warn("[WARNING] Using JScript conditional comments is not recommended..." + (munge ? "\n[INFO] Using JSCript conditional comments reduces the level of compression!" : ""), true);
+                    }
+                    break;
+
+                case Token.NAME:
+                    symbol = token.getValue();
+
+                    if (mode == BUILDING_SYMBOL_TREE) {
+
+                        if (symbol.equals("eval")) {
+
+                            protectScopeFromObfuscation(currentScope);
+                            warn("[WARNING] Using 'eval' is not recommended..." + (munge ? "\n[INFO] Using 'eval' reduces the level of compression!" : ""), true);
+
+                        }
+
+                    } else if (mode == CHECKING_SYMBOL_TREE) {
+
+                        if ((offset < 2 ||
+                                (getToken(-2).getType() != Token.DOT &&
+                                        getToken(-2).getType() != Token.GET &&
+                                        getToken(-2).getType() != Token.SET)) &&
+                                getToken(0).getType() != Token.OBJECTLIT) {
+
+                            identifier = getIdentifier(symbol, currentScope);
+
+                            if (identifier == null) {
+
+                                if (symbol.length() <= 3 && !builtin.contains(symbol)) {
+                                    // Here, we found an undeclared and un-namespaced symbol that is
+                                    // 3 characters or less in length. Declare it in the global scope.
+                                    // We don't need to declare longer symbols since they won't cause
+                                    // any conflict with other munged symbols.
+                                    globalScope.declareIdentifier(symbol);
+                                    warn("[WARNING] Found an undeclared symbol: " + symbol, true);
+                                }
+
+                            } else {
+
+                                identifier.incrementRefcount();
+                            }
+                        }
+                    }
+                    break;
+            }
+        }
+    }
+
+    private void parseScope(ScriptOrFnScope scope) {
+
+        String symbol;
+        JavaScriptToken token;
+        JavaScriptIdentifier identifier;
+
+        int length = tokens.size();
+
+        enterScope(scope);
+
+        while (offset < length) {
+
+            token = consumeToken();
+
+            switch (token.getType()) {
+
+                case Token.VAR:
+                case Token.CONST:
+
+                    // The var keyword is followed by at least one symbol name.
+                    // If several symbols follow, they are comma separated.
+                    for (; ;) {
+                        token = consumeToken();
+
+                        assert token.getType() == Token.NAME;
+
+                        if (mode == BUILDING_SYMBOL_TREE) {
+                            symbol = token.getValue();
+                            if (scope.getIdentifier(symbol) == null) {
+                                scope.declareIdentifier(symbol);
+                            } else {
+                                warn("[WARNING] The variable " + symbol + " has already been declared in the same scope...", true);
+                            }
+                        }
+
+                        token = getToken(0);
+
+                        assert token.getType() == Token.SEMI ||
+                                token.getType() == Token.ASSIGN ||
+                                token.getType() == Token.COMMA ||
+                                token.getType() == Token.IN;
+
+                        if (token.getType() == Token.IN) {
+                            break;
+                        } else {
+                            parseExpression();
+                            token = getToken(-1);
+                            if (token.getType() == Token.SEMI) {
+                                break;
+                            }
+                        }
+                    }
+                    break;
+
+                case Token.FUNCTION:
+                    parseFunctionDeclaration();
+                    break;
+
+                case Token.LC:
+                    braceNesting++;
+                    break;
+
+                case Token.RC:
+                    braceNesting--;
+                    assert braceNesting >= scope.getBraceNesting();
+                    if (braceNesting == scope.getBraceNesting()) {
+                        leaveCurrentScope();
+                        return;
+                    }
+                    break;
+
+                case Token.WITH:
+                    if (mode == BUILDING_SYMBOL_TREE) {
+                        // Inside a 'with' block, it is impossible to figure out
+                        // statically whether a symbol is a local variable or an
+                        // object member. As a consequence, the only thing we can
+                        // do is turn the obfuscation off for the highest scope
+                        // containing the 'with' block.
+                        protectScopeFromObfuscation(scope);
+                        warn("[WARNING] Using 'with' is not recommended" + (munge ? "(and it reduces the level of compression)" : ""), true);
+                    }
+                    break;
+
+                case Token.CATCH:
+                    parseCatch();
+                    break;
+
+                case Token.IECC:
+                    if (mode == BUILDING_SYMBOL_TREE) {
+                        protectScopeFromObfuscation(scope);
+                        warn("[WARNING] Using JScript conditional comments is not recommended..." + (munge ? "\n[INFO] Using JSCript conditional comments reduces the level of compression!" : ""), true);
+                    }
+                    break;
+
+                case Token.NAME:
+                    symbol = token.getValue();
+
+                    if (mode == BUILDING_SYMBOL_TREE) {
+
+                        if (symbol.equals("eval")) {
+
+                            protectScopeFromObfuscation(scope);
+                            warn("[WARNING] Using 'eval' is not recommended..." + (munge ? "\n[INFO] Using 'eval' reduces the level of compression!" : ""), true);
+
+                        }
+
+                    } else if (mode == CHECKING_SYMBOL_TREE) {
+
+                        if ((offset < 2 || getToken(-2).getType() != Token.DOT) &&
+                                getToken(0).getType() != Token.OBJECTLIT) {
+
+                            identifier = getIdentifier(symbol, scope);
+
+                            if (identifier == null) {
+
+                                if (symbol.length() <= 3 && !builtin.contains(symbol)) {
+                                    // Here, we found an undeclared and un-namespaced symbol that is
+                                    // 3 characters or less in length. Declare it in the global scope.
+                                    // We don't need to declare longer symbols since they won't cause
+                                    // any conflict with other munged symbols.
+                                    globalScope.declareIdentifier(symbol);
+                                    warn("[WARNING] Found an undeclared symbol: " + symbol, true);
+                                }
+
+                            } else {
+
+                                identifier.incrementRefcount();
+                            }
+                        }
+                    }
+                    break;
+            }
+        }
+    }
+
+    private void buildSymbolTree() {
+        offset = 0;
+        braceNesting = 0;
+        scopes.clear();
+        indexedScopes.clear();
+        indexedScopes.put(new Integer(0), globalScope);
+        mode = BUILDING_SYMBOL_TREE;
+        parseScope(globalScope);
+    }
+
+    private void mungeSymboltree() {
+
+        if (!munge) {
+            return;
+        }
+
+        // One problem with obfuscation resides in the use of undeclared
+        // and un-namespaced global symbols that are 3 characters or less
+        // in length. Here is an example:
+        //
+        //     var declaredGlobalVar;
+        //
+        //     function declaredGlobalFn() {
+        //         var localvar;
+        //         localvar = abc; // abc is an undeclared global symbol
+        //     }
+        //
+        // In the example above, there is a slim chance that localvar may be
+        // munged to 'abc', conflicting with the undeclared global symbol
+        // abc, creating a potential bug. The following code detects such
+        // global symbols. This must be done AFTER the entire file has been
+        // parsed, and BEFORE munging the symbol tree. Note that declaring
+        // extra symbols in the global scope won't hurt.
+        //
+        // Note: Since we go through all the tokens to do this, we also use
+        // the opportunity to count how many times each identifier is used.
+
+        offset = 0;
+        braceNesting = 0;
+        scopes.clear();
+        mode = CHECKING_SYMBOL_TREE;
+        parseScope(globalScope);
+        globalScope.munge();
+    }
+
+    private StringBuffer printSymbolTree(int linebreakpos, boolean preserveAllSemiColons)
+            throws IOException {
+
+        offset = 0;
+        braceNesting = 0;
+        scopes.clear();
+
+        String symbol;
+        JavaScriptToken token;
+        ScriptOrFnScope currentScope;
+        JavaScriptIdentifier identifier;
+
+        int length = tokens.size();
+        StringBuffer result = new StringBuffer();
+
+        int linestartpos = 0;
+
+        enterScope(globalScope);
+
+        while (offset < length) {
+
+            token = consumeToken();
+            symbol = token.getValue();
+            currentScope = getCurrentScope();
+
+            switch (token.getType()) {
+
+                case Token.NAME:
+
+                    if (offset >= 2 && getToken(-2).getType() == Token.DOT ||
+                            getToken(0).getType() == Token.OBJECTLIT) {
+
+                        result.append(symbol);
+
+                    } else {
+
+                        identifier = getIdentifier(symbol, currentScope);
+                        if (identifier != null) {
+                            if (identifier.getMungedValue() != null) {
+                                result.append(identifier.getMungedValue());
+                            } else {
+                                result.append(symbol);
+                            }
+                            if (currentScope != globalScope && identifier.getRefcount() == 0) {
+                                warn("[WARNING] The symbol " + symbol + " is declared but is apparently never used.\nThis code can probably be written in a more efficient way.", true);
+                            }
+                        } else {
+                            result.append(symbol);
+                        }
+                    }
+                    break;
+
+                case Token.REGEXP:
+                case Token.NUMBER:
+                case Token.STRING:
+                    result.append(symbol);
+                    break;
+
+                case Token.ADD:
+                case Token.SUB:
+                    result.append((String) literals.get(new Integer(token.getType())));
+                    if (offset < length) {
+                        token = getToken(0);
+                        if (token.getType() == Token.INC ||
+                                token.getType() == Token.DEC ||
+                                token.getType() == Token.ADD ||
+                                token.getType() == Token.DEC) {
+                            // Handle the case x +/- ++/-- y
+                            // We must keep a white space here. Otherwise, x +++ y would be
+                            // interpreted as x ++ + y by the compiler, which is a bug (due
+                            // to the implicit assignment being done on the wrong variable)
+                            result.append(" ");
+                        } else if (token.getType() == Token.POS && getToken(-1).getType() == Token.ADD ||
+                                token.getType() == Token.NEG && getToken(-1).getType() == Token.SUB) {
+                            // Handle the case x + + y and x - - y
+                            result.append(" ");
+                        }
+                    }
+                    break;
+
+                case Token.FUNCTION:
+                    result.append("function");
+                    token = consumeToken();
+                    if (token.getType() == Token.NAME) {
+                        result.append(" ");
+                        symbol = token.getValue();
+                        identifier = getIdentifier(symbol, currentScope);
+                        assert identifier != null;
+                        if (identifier.getMungedValue() != null) {
+                            result.append(identifier.getMungedValue());
+                        } else {
+                            result.append(symbol);
+                        }
+                        if (currentScope != globalScope && identifier.getRefcount() == 0) {
+                            warn("[WARNING] The symbol " + symbol + " is declared but is apparently never used.\nThis code can probably be written in a more efficient way.", true);
+                        }
+                        token = consumeToken();
+                    }
+                    assert token.getType() == Token.LP;
+                    result.append("(");
+                    currentScope = (ScriptOrFnScope) indexedScopes.get(new Integer(offset));
+                    enterScope(currentScope);
+                    while ((token = consumeToken()).getType() != Token.RP) {
+                        assert token.getType() == Token.NAME || token.getType() == Token.COMMA;
+                        if (token.getType() == Token.NAME) {
+                            symbol = token.getValue();
+                            identifier = getIdentifier(symbol, currentScope);
+                            assert identifier != null;
+                            if (identifier.getMungedValue() != null) {
+                                result.append(identifier.getMungedValue());
+                            } else {
+                                result.append(symbol);
+                            }
+                        } else if (token.getType() == Token.COMMA) {
+                            result.append(",");
+                        }
+                    }
+                    result.append(")");
+                    token = consumeToken();
+                    assert token.getType() == Token.LC;
+                    result.append("{");
+                    braceNesting++;
+                    token = getToken(0);
+                    if (token.getType() == Token.STRING) {
+                        // This is a hint. Skip it!
+                        consumeToken();
+                        token = getToken(0);
+                        assert token.getType() == Token.SEMI;
+                        consumeToken();
+                    }
+                    break;
+
+                case Token.RETURN:
+                    result.append("return");
+                    // No space needed after 'return' when followed
+                    // by '(', '[', '{', a string or a regexp.
+                    if (offset < length) {
+                        token = getToken(0);
+                        if (token.getType() != Token.LP &&
+                                token.getType() != Token.LB &&
+                                token.getType() != Token.LC &&
+                                token.getType() != Token.STRING &&
+                                token.getType() != Token.REGEXP) {
+                            result.append(" ");
+                        }
+                    }
+                    break;
+
+                case Token.CASE:
+                    result.append("case");
+                    // White-space needed after 'case' when not followed by a string.
+                    if (offset < length && getToken(0).getType() != Token.STRING) {
+                        result.append(" ");
+                    }
+                    break;
+
+                case Token.THROW:
+                    // White-space needed after 'throw' when not followed by a string.
+                    result.append("throw");
+                    if (offset < length && getToken(0).getType() != Token.STRING) {
+                        result.append(" ");
+                    }
+                    break;
+
+                case Token.BREAK:
+                    result.append("break");
+                    if (offset < length && getToken(0).getType() != Token.SEMI) {
+                        // If 'break' is not followed by a semi-colon, it must be
+                        // followed by a label, hence the need for a white space.
+                        result.append(" ");
+                    }
+                    break;
+
+                case Token.CONTINUE:
+                    result.append("continue");
+                    if (offset < length && getToken(0).getType() != Token.SEMI) {
+                        // If 'continue' is not followed by a semi-colon, it must be
+                        // followed by a label, hence the need for a white space.
+                        result.append(" ");
+                    }
+                    break;
+
+                case Token.LC:
+                    result.append("{");
+                    braceNesting++;
+                    break;
+
+                case Token.RC:
+                    result.append("}");
+                    braceNesting--;
+                    assert braceNesting >= currentScope.getBraceNesting();
+                    if (braceNesting == currentScope.getBraceNesting()) {
+                        leaveCurrentScope();
+                    }
+                    break;
+
+                case Token.SEMI:
+                    // No need to output a semi-colon if the next character is a right-curly...
+                    if (preserveAllSemiColons || offset < length && getToken(0).getType() != Token.RC)
+                        result.append(";");
+                    if (linebreakpos >= 0 && result.length() - linestartpos > linebreakpos) {
+                        // Some source control tools don't like it when files containing lines longer
+                        // than, say 8000 characters, are checked in. The linebreak option is used in
+                        // that case to split long lines after a specific column.
+                        result.append("\n");
+                        linestartpos = result.length();
+                    }
+                    break;
+
+                case Token.IECC:
+                    result.append("/*");
+                    result.append(symbol);
+                    result.append("*/");
+                    break;
+
+                default:
+                    String literal = (String) literals.get(new Integer(token.getType()));
+                    if (literal != null) {
+                        result.append(literal);
+                    } else {
+                        warn("[WARNING] This symbol cannot be printed: " + symbol, true);
+                    }
+                    break;
+            }
+        }
+
+        return result;
+    }
+}


Property changes on: trunk/cdk/maven-javascript-plugin/src/main/java/com/yahoo/platform/yui/compressor/JavaScriptCompressor.java
___________________________________________________________________
Name: svn:mime-type
   + text/plain
Name: svn:keywords
   + Date Revision Author

Added: trunk/cdk/maven-javascript-plugin/src/main/java/com/yahoo/platform/yui/compressor/JavaScriptErrorReporter.java
===================================================================
--- trunk/cdk/maven-javascript-plugin/src/main/java/com/yahoo/platform/yui/compressor/JavaScriptErrorReporter.java	                        (rev 0)
+++ trunk/cdk/maven-javascript-plugin/src/main/java/com/yahoo/platform/yui/compressor/JavaScriptErrorReporter.java	2007-12-11 23:30:42 UTC (rev 4755)
@@ -0,0 +1,56 @@
+/*
+ * YUI Compressor
+ * Author: Julien Lecomte <jlecomte at yahoo-inc.com>
+ * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
+ * Code licensed under the BSD License:
+ *     http://developer.yahoo.net/yui/license.txt
+ */
+
+package com.yahoo.platform.yui.compressor;
+
+import org.mozilla.javascript.ErrorReporter;
+import org.mozilla.javascript.EvaluatorException;
+
+import java.io.PrintStream;
+
+class JavaScriptErrorReporter implements ErrorReporter {
+
+    private boolean reportWarnings;
+    private PrintStream err;
+
+    JavaScriptErrorReporter(PrintStream err, boolean reportWarnings) {
+        this.err = err;
+        this.reportWarnings = reportWarnings;
+    }
+
+    public void warning(String message, String sourceName,
+            int line, String lineSource, int lineOffset) {
+        if (reportWarnings) {
+            reportMessage(message, sourceName, line, lineSource, lineOffset);
+        }
+    }
+
+    public EvaluatorException runtimeError(String message, String sourceName,
+            int line, String lineSource, int lineOffset) {
+        error(message, sourceName, line, lineSource, lineOffset);
+        return new EvaluatorException(message);
+    }
+
+    public void error(String message, String sourceName,
+            int line, String lineSource, int lineOffset) {
+        reportMessage(message, sourceName, line, lineSource, lineOffset);
+    }
+
+    private void reportMessage(String message, String sourceName,
+            int line, String lineSource, int lineOffset) {
+        if (line < 0) {
+            if (message.length() == 0) {
+                err.println("An unknown error occurred...");
+            } else {
+                err.println(message);
+            }
+        } else {
+            err.println(line + ':' + lineOffset + ':' + message);
+        }
+    }
+}


Property changes on: trunk/cdk/maven-javascript-plugin/src/main/java/com/yahoo/platform/yui/compressor/JavaScriptErrorReporter.java
___________________________________________________________________
Name: svn:mime-type
   + text/plain
Name: svn:keywords
   + Date Revision Author

Added: trunk/cdk/maven-javascript-plugin/src/main/java/com/yahoo/platform/yui/compressor/JavaScriptIdentifier.java
===================================================================
--- trunk/cdk/maven-javascript-plugin/src/main/java/com/yahoo/platform/yui/compressor/JavaScriptIdentifier.java	                        (rev 0)
+++ trunk/cdk/maven-javascript-plugin/src/main/java/com/yahoo/platform/yui/compressor/JavaScriptIdentifier.java	2007-12-11 23:30:42 UTC (rev 4755)
@@ -0,0 +1,55 @@
+/*
+ * YUI Compressor
+ * Author: Julien Lecomte <jlecomte at yahoo-inc.com>
+ * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
+ * Code licensed under the BSD License:
+ *     http://developer.yahoo.net/yui/license.txt
+ */
+
+package com.yahoo.platform.yui.compressor;
+
+import org.mozilla.javascript.Token;
+
+/**
+ * JavaScriptIdentifier represents a variable/function identifier.
+ */
+class JavaScriptIdentifier extends JavaScriptToken {
+
+    private int refcount = 0;
+    private String mungedValue;
+    private ScriptOrFnScope declaredScope;
+    private boolean markedForMunging = true;
+
+    JavaScriptIdentifier(String value, ScriptOrFnScope declaredScope) {
+        super(Token.NAME, value);
+        this.declaredScope = declaredScope;
+    }
+
+    ScriptOrFnScope getDeclaredScope() {
+        return declaredScope;
+    }
+
+    void setMungedValue(String value) {
+        mungedValue = value;
+    }
+
+    String getMungedValue() {
+        return mungedValue;
+    }
+
+    void preventMunging() {
+        markedForMunging = false;
+    }
+
+    boolean isMarkedForMunging() {
+        return markedForMunging;
+    }
+
+    void incrementRefcount() {
+        refcount++;
+    }
+
+    int getRefcount() {
+        return refcount;
+    }
+}


Property changes on: trunk/cdk/maven-javascript-plugin/src/main/java/com/yahoo/platform/yui/compressor/JavaScriptIdentifier.java
___________________________________________________________________
Name: svn:mime-type
   + text/plain
Name: svn:keywords
   + Date Revision Author

Added: trunk/cdk/maven-javascript-plugin/src/main/java/com/yahoo/platform/yui/compressor/JavaScriptToken.java
===================================================================
--- trunk/cdk/maven-javascript-plugin/src/main/java/com/yahoo/platform/yui/compressor/JavaScriptToken.java	                        (rev 0)
+++ trunk/cdk/maven-javascript-plugin/src/main/java/com/yahoo/platform/yui/compressor/JavaScriptToken.java	2007-12-11 23:30:42 UTC (rev 4755)
@@ -0,0 +1,28 @@
+/*
+ * YUI Compressor
+ * Author: Julien Lecomte <jlecomte at yahoo-inc.com>
+ * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
+ * Code licensed under the BSD License:
+ *     http://developer.yahoo.net/yui/license.txt
+ */
+
+package com.yahoo.platform.yui.compressor;
+
+public class JavaScriptToken {
+
+    private int type;
+    private String value;
+
+    JavaScriptToken(int type, String value) {
+        this.type = type;
+        this.value = value;
+    }
+
+    int getType() {
+        return type;
+    }
+
+    String getValue() {
+        return value;
+    }
+}


Property changes on: trunk/cdk/maven-javascript-plugin/src/main/java/com/yahoo/platform/yui/compressor/JavaScriptToken.java
___________________________________________________________________
Name: svn:mime-type
   + text/plain
Name: svn:keywords
   + Date Revision Author

Added: trunk/cdk/maven-javascript-plugin/src/main/java/com/yahoo/platform/yui/compressor/ScriptOrFnScope.java
===================================================================
--- trunk/cdk/maven-javascript-plugin/src/main/java/com/yahoo/platform/yui/compressor/ScriptOrFnScope.java	                        (rev 0)
+++ trunk/cdk/maven-javascript-plugin/src/main/java/com/yahoo/platform/yui/compressor/ScriptOrFnScope.java	2007-12-11 23:30:42 UTC (rev 4755)
@@ -0,0 +1,156 @@
+/*
+ * YUI Compressor
+ * Author: Julien Lecomte <jlecomte at yahoo-inc.com>
+ * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
+ * Code licensed under the BSD License:
+ *     http://developer.yahoo.net/yui/license.txt
+ */
+
+package com.yahoo.platform.yui.compressor;
+
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.Hashtable;
+
+class ScriptOrFnScope {
+
+    private int braceNesting;
+    private ScriptOrFnScope parentScope;
+    private ArrayList subScopes;
+    private Hashtable identifiers = new Hashtable();
+    private Hashtable hints = new Hashtable();
+    private boolean markedForMunging = true;
+
+    ScriptOrFnScope(int braceNesting, ScriptOrFnScope parentScope) {
+        this.braceNesting = braceNesting;
+        this.parentScope = parentScope;
+        this.subScopes = new ArrayList();
+        if (parentScope != null) {
+            parentScope.subScopes.add(this);
+        }
+    }
+
+    int getBraceNesting() {
+        return braceNesting;
+    }
+
+    ScriptOrFnScope getParentScope() {
+        return parentScope;
+    }
+
+    JavaScriptIdentifier declareIdentifier(String symbol) {
+        JavaScriptIdentifier identifier = (JavaScriptIdentifier) identifiers.get(symbol);
+        if (identifier == null) {
+            identifier = new JavaScriptIdentifier(symbol, this);
+            identifiers.put(symbol, identifier);
+        }
+        return identifier;
+    }
+
+    JavaScriptIdentifier getIdentifier(String symbol) {
+        return (JavaScriptIdentifier) identifiers.get(symbol);
+    }
+
+    void addHint(String variableName, String variableType) {
+        hints.put(variableName, variableType);
+    }
+
+    void preventMunging() {
+        if (parentScope != null) {
+            // The symbols in the global scope don't get munged,
+            // but the sub-scopes it contains do get munged.
+            markedForMunging = false;
+        }
+    }
+
+    private ArrayList getUsedSymbols() {
+        ArrayList result = new ArrayList();
+        Enumeration elements = identifiers.elements();
+        while (elements.hasMoreElements()) {
+            JavaScriptIdentifier identifier = (JavaScriptIdentifier) elements.nextElement();
+            String mungedValue = identifier.getMungedValue();
+            if (mungedValue == null) {
+                mungedValue = identifier.getValue();
+            }
+            result.add(mungedValue);
+        }
+        return result;
+    }
+
+    private ArrayList getAllUsedSymbols() {
+        ArrayList result = new ArrayList();
+        ScriptOrFnScope scope = this;
+        while (scope != null) {
+            result.addAll(scope.getUsedSymbols());
+            scope = scope.parentScope;
+        }
+        return result;
+    }
+
+    void munge() {
+
+        if (!markedForMunging) {
+            // Stop right here if this scope was flagged as unsafe for munging.
+            return;
+        }
+
+        int pickFromSet = 1;
+
+        // Do not munge symbols in the global scope!
+        if (parentScope != null) {
+
+            ArrayList freeSymbols = new ArrayList();
+
+            freeSymbols.addAll(JavaScriptCompressor.ones);
+            freeSymbols.removeAll(getAllUsedSymbols());
+            if (freeSymbols.size() == 0) {
+                pickFromSet = 2;
+                freeSymbols.addAll(JavaScriptCompressor.twos);
+                freeSymbols.removeAll(getAllUsedSymbols());
+            }
+            if (freeSymbols.size() == 0) {
+                pickFromSet = 3;
+                freeSymbols.addAll(JavaScriptCompressor.threes);
+                freeSymbols.removeAll(getAllUsedSymbols());
+            }
+            if (freeSymbols.size() == 0) {
+                System.err.println("The YUI Compressor ran out of symbols. Aborting...");
+                System.exit(1);
+            }
+
+            Enumeration elements = identifiers.elements();
+            while (elements.hasMoreElements()) {
+                if (freeSymbols.size() == 0) {
+                    pickFromSet++;
+                    if (pickFromSet == 2) {
+                        freeSymbols.addAll(JavaScriptCompressor.twos);
+                    } else if (pickFromSet == 3) {
+                        freeSymbols.addAll(JavaScriptCompressor.threes);
+                    } else {
+                        System.err.println("The YUI Compressor ran out of symbols. Aborting...");
+                        System.exit(1);
+                    }
+                    // It is essential to remove the symbols already used in
+                    // the containing scopes, or some of the variables declared
+                    // in the containing scopes will be redeclared, which can
+                    // lead to errors.
+                    freeSymbols.removeAll(getAllUsedSymbols());
+                }
+
+                String mungedValue;
+                JavaScriptIdentifier identifier = (JavaScriptIdentifier) elements.nextElement();
+                if (identifier.isMarkedForMunging()) {
+                    mungedValue = (String) freeSymbols.remove(0);
+                } else {
+                    mungedValue = identifier.getValue();
+                }
+                identifier.setMungedValue(mungedValue);
+            }
+        }
+
+        for (int i = 0; i < subScopes.size(); i++) {
+            ScriptOrFnScope scope = (ScriptOrFnScope) subScopes.get(i);
+            scope.munge();
+        }
+    }
+}


Property changes on: trunk/cdk/maven-javascript-plugin/src/main/java/com/yahoo/platform/yui/compressor/ScriptOrFnScope.java
___________________________________________________________________
Name: svn:mime-type
   + text/plain
Name: svn:keywords
   + Date Revision Author

Added: trunk/cdk/maven-javascript-plugin/src/main/java/net/sf/alchim/mojo/yuicompressor/Aggregation.java
===================================================================
--- trunk/cdk/maven-javascript-plugin/src/main/java/net/sf/alchim/mojo/yuicompressor/Aggregation.java	                        (rev 0)
+++ trunk/cdk/maven-javascript-plugin/src/main/java/net/sf/alchim/mojo/yuicompressor/Aggregation.java	2007-12-11 23:30:42 UTC (rev 4755)
@@ -0,0 +1,92 @@
+package net.sf.alchim.mojo.yuicompressor;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.codehaus.plexus.util.DirectoryScanner;
+import org.codehaus.plexus.util.IOUtil;
+
+public class Aggregation {
+    public File output;
+    public File sourceDirectory;
+    public String[] includes;
+    public String[] excludes;
+    public boolean removeIncluded = false;
+    public boolean insertNewLine = false;
+
+    public void run(File outputDirectory) throws Exception {
+    	if(null == sourceDirectory){
+    		sourceDirectory = outputDirectory;
+    	}
+        List<File> files = getIncludedFiles();
+        if (files.size() != 0) {
+            FileOutputStream out = new FileOutputStream(output);
+            try {
+                for (File file : files) {
+                    FileInputStream in = new FileInputStream(file);
+                    try {
+                        IOUtil.copy(in, out);
+                        if (insertNewLine) {
+                            out.write('\n');
+                        }
+                        if (removeIncluded) {
+                            file.delete();
+                        }
+                    } finally {
+                        IOUtil.close(in);
+                        in = null;
+                    }
+                }
+            } finally {
+                IOUtil.close(out);
+                out = null;
+            }
+        }
+    }
+
+    protected List<File> getIncludedFiles() throws Exception {
+        ArrayList<File> back = new ArrayList<File>();
+        if (includes != null) {
+            for (String include : includes) {
+                addInto(include, back);
+            }
+        }
+        return back;
+    }
+
+    private void addInto(String include, List<File> includedFiles) throws Exception {
+        if (include.indexOf('*') > -1) {
+            DirectoryScanner scanner = newScanner();
+            scanner.setIncludes(new String[] { include });
+            scanner.scan();
+            String[] rpaths = scanner.getIncludedFiles();
+            for (String rpath : rpaths) {
+                File file = new File(scanner.getBasedir(), rpath);
+                if (!includedFiles.contains(file)) {
+                    includedFiles.add(file);
+                }
+            }
+        } else {
+            File file = new File(include);
+            if (!file.isAbsolute()) {
+                file = new File(output.getParentFile(), include);
+            }
+            if (!includedFiles.contains(file)) {
+                includedFiles.add(file);
+            }
+        }
+    }
+
+    private DirectoryScanner newScanner() throws Exception {
+        DirectoryScanner scanner = new DirectoryScanner();
+        scanner.setBasedir(sourceDirectory);
+        if ((excludes != null) && (excludes.length != 0)) {
+            scanner.setExcludes(excludes);
+        }
+        scanner.addDefaultExcludes();
+        return scanner;
+    }
+}


Property changes on: trunk/cdk/maven-javascript-plugin/src/main/java/net/sf/alchim/mojo/yuicompressor/Aggregation.java
___________________________________________________________________
Name: svn:mime-type
   + text/plain
Name: svn:keywords
   + Date Revision Author

Added: trunk/cdk/maven-javascript-plugin/src/main/java/net/sf/alchim/mojo/yuicompressor/BasicRhinoShell.java
===================================================================
--- trunk/cdk/maven-javascript-plugin/src/main/java/net/sf/alchim/mojo/yuicompressor/BasicRhinoShell.java	                        (rev 0)
+++ trunk/cdk/maven-javascript-plugin/src/main/java/net/sf/alchim/mojo/yuicompressor/BasicRhinoShell.java	2007-12-11 23:30:42 UTC (rev 4755)
@@ -0,0 +1,354 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Rhino code, released
+ * May 6, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1997-1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * the GNU General Public License Version 2 or later (the "GPL"), in which
+ * case the provisions of the GPL are applicable instead of those above. If
+ * you wish to allow use of your version of this file only under the terms of
+ * the GPL and not to allow others to use your version of this file under the
+ * MPL, indicate your decision by deleting the provisions above and replacing
+ * them with the notice and other provisions required by the GPL. If you do
+ * not delete the provisions above, a recipient may use your version of this
+ * file under either the MPL or the GPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+package net.sf.alchim.mojo.yuicompressor;
+
+import java.io.BufferedReader;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+
+import org.codehaus.plexus.util.IOUtil;
+import org.mozilla.javascript.Context;
+import org.mozilla.javascript.ErrorReporter;
+import org.mozilla.javascript.EvaluatorException;
+import org.mozilla.javascript.Function;
+import org.mozilla.javascript.JavaScriptException;
+import org.mozilla.javascript.Scriptable;
+import org.mozilla.javascript.ScriptableObject;
+import org.mozilla.javascript.WrappedException;
+
+/**
+ * The BasicRhinoShell program.
+ *
+ * Can execute scripts interactively or in batch mode at the command line. An
+ * example of controlling the JavaScript engine.
+ *
+ * @author Norris Boyd
+ * @based http://lxr.mozilla.org/mozilla/source/js/rhino/examples/BasicRhinoShell.java
+ *        (2007-08-30)
+ */
+ at SuppressWarnings("serial")
+public class BasicRhinoShell extends ScriptableObject {
+
+    @Override
+    public String getClassName() {
+        return "global";
+    }
+
+    /**
+     * Main entry point.
+     *
+     * Process arguments as would a normal Java program. Also create a new
+     * Context and associate it with the current thread. Then set up the
+     * execution environment and begin to execute scripts.
+     */
+    public static void exec(String args[], ErrorReporter reporter) {
+        // Associate a new Context with this thread
+        Context cx = Context.enter();
+        cx.setErrorReporter(reporter);
+        try {
+            // Initialize the standard objects (Object, Function, etc.)
+            // This must be done before scripts can be executed.
+            BasicRhinoShell BasicRhinoShell = new BasicRhinoShell();
+            cx.initStandardObjects(BasicRhinoShell);
+
+            // Define some global functions particular to the BasicRhinoShell.
+            // Note
+            // that these functions are not part of ECMA.
+            String[] names = { "print", "quit", "version", "load", "help", "readFile" };
+            BasicRhinoShell.defineFunctionProperties(names, BasicRhinoShell.class, ScriptableObject.DONTENUM);
+
+            args = processOptions(cx, args);
+
+            // Set up "arguments" in the global scope to contain the command
+            // line arguments after the name of the script to execute
+            Object[] array;
+            if (args.length == 0) {
+                array = new Object[0];
+            } else {
+                int length = args.length - 1;
+                array = new Object[length];
+                System.arraycopy(args, 1, array, 0, length);
+            }
+            Scriptable argsObj = cx.newArray(BasicRhinoShell, array);
+            BasicRhinoShell.defineProperty("arguments", argsObj, ScriptableObject.DONTENUM);
+
+            BasicRhinoShell.processSource(cx, args.length == 0 ? null : args[0]);
+        } finally {
+            Context.exit();
+        }
+    }
+
+    /**
+     * Parse arguments.
+     */
+    public static String[] processOptions(Context cx, String args[]) {
+        for (int i = 0; i < args.length; i++) {
+            String arg = args[i];
+            if (!arg.startsWith("-")) {
+                String[] result = new String[args.length - i];
+                for (int j = i; j < args.length; j++) {
+                    result[j - i] = args[j];
+                }
+                return result;
+            }
+            if (arg.equals("-version")) {
+                if (++i == args.length) {
+                    usage(arg);
+                }
+                double d = Context.toNumber(args[i]);
+                if (d != d) {
+                    usage(arg);
+                }
+                cx.setLanguageVersion((int) d);
+                continue;
+            }
+            usage(arg);
+        }
+        return new String[0];
+    }
+
+    /**
+     * Print a usage message.
+     */
+    private static void usage(String s) {
+        p("Didn't understand \"" + s + "\".");
+        p("Valid arguments are:");
+        p("-version 100|110|120|130|140|150|160|170");
+        System.exit(1);
+    }
+
+    /**
+     * Print a help message.
+     *
+     * This method is defined as a JavaScript function.
+     */
+    public void help() {
+        p("");
+        p("Command                Description");
+        p("=======                ===========");
+        p("help()                 Display usage and help messages. ");
+        p("defineClass(className) Define an extension using the Java class");
+        p("                       named with the string argument. ");
+        p("                       Uses ScriptableObject.defineClass(). ");
+        p("load(['foo.js', ...])  Load JavaScript source files named by ");
+        p("                       string arguments. ");
+        p("loadClass(className)   Load a class named by a string argument.");
+        p("                       The class must be a script compiled to a");
+        p("                       class file. ");
+        p("print([expr ...])      Evaluate and print expressions. ");
+        p("quit()                 Quit the BasicRhinoShell. ");
+        p("version([number])      Get or set the JavaScript version number.");
+        p("");
+    }
+
+    /**
+     * Print the string values of its arguments.
+     *
+     * This method is defined as a JavaScript function. Note that its arguments
+     * are of the "varargs" form, which allows it to handle an arbitrary number
+     * of arguments supplied to the JavaScript function.
+     *
+     */
+    public static void print(Context cx, Scriptable thisObj, Object[] args, Function funObj) {
+        for (int i = 0; i < args.length; i++) {
+            if (i > 0) {
+                System.out.print(" ");
+            }
+
+            // Convert the arbitrary JavaScript value into a string form.
+            String s = Context.toString(args[i]);
+
+            System.out.print(s);
+        }
+        System.out.println();
+    }
+
+    /**
+     * Quit the BasicRhinoShell.
+     *
+     * This only affects the interactive mode.
+     *
+     * This method is defined as a JavaScript function.
+     */
+    public void quit() {
+        quitting = true;
+    }
+
+    /**
+     * This method is defined as a JavaScript function.
+     */
+    public String readFile(String path) {
+        try {
+            return IOUtil.toString(new FileInputStream(path));
+        } catch (RuntimeException exc) {
+            throw exc;
+        } catch (Exception exc) {
+            throw new RuntimeException("wrap: " + exc.getMessage(), exc);
+        }
+    }
+
+    /**
+     * Get and set the language version.
+     *
+     * This method is defined as a JavaScript function.
+     */
+    public static double version(Context cx, Scriptable thisObj, Object[] args, Function funObj) {
+        double result = cx.getLanguageVersion();
+        if (args.length > 0) {
+            double d = Context.toNumber(args[0]);
+            cx.setLanguageVersion((int) d);
+        }
+        return result;
+    }
+
+    /**
+     * Load and execute a set of JavaScript source files.
+     *
+     * This method is defined as a JavaScript function.
+     *
+     */
+    public static void load(Context cx, Scriptable thisObj, Object[] args, Function funObj) {
+        BasicRhinoShell BasicRhinoShell = (BasicRhinoShell) getTopLevelScope(thisObj);
+        for (Object element : args) {
+            BasicRhinoShell.processSource(cx, Context.toString(element));
+        }
+    }
+
+    /**
+     * Evaluate JavaScript source.
+     *
+     * @param cx the current context
+     * @param filename the name of the file to compile, or null for interactive
+     *            mode.
+     */
+    private void processSource(Context cx, String filename) {
+        if (filename == null) {
+            BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
+            String sourceName = "<stdin>";
+            int lineno = 1;
+            boolean hitEOF = false;
+            do {
+                int startline = lineno;
+                System.err.print("js> ");
+                System.err.flush();
+                try {
+                    String source = "";
+                    // Collect lines of source to compile.
+                    while (true) {
+                        String newline;
+                        newline = in.readLine();
+                        if (newline == null) {
+                            hitEOF = true;
+                            break;
+                        }
+                        source = source + newline + "\n";
+                        lineno++;
+                        // Continue collecting as long as more lines
+                        // are needed to complete the current
+                        // statement. stringIsCompilableUnit is also
+                        // true if the source statement will result in
+                        // any error other than one that might be
+                        // resolved by appending more source.
+                        if (cx.stringIsCompilableUnit(source)) {
+                            break;
+                        }
+                    }
+                    Object result = cx.evaluateString(this, source, sourceName, startline, null);
+                    if (result != Context.getUndefinedValue()) {
+                        System.err.println(Context.toString(result));
+                    }
+                } catch (WrappedException we) {
+                    // Some form of exception was caught by JavaScript and
+                    // propagated up.
+                    System.err.println(we.getWrappedException().toString());
+                    we.printStackTrace();
+                } catch (EvaluatorException ee) {
+                    // Some form of JavaScript error.
+                    System.err.println("js: " + ee.getMessage());
+                } catch (JavaScriptException jse) {
+                    // Some form of JavaScript error.
+                    System.err.println("js: " + jse.getMessage());
+                } catch (IOException ioe) {
+                    System.err.println(ioe.toString());
+                }
+                if (quitting) {
+                    // The user executed the quit() function.
+                    break;
+                }
+            } while (!hitEOF);
+            System.err.println();
+        } else {
+            FileReader in = null;
+            try {
+                in = new FileReader(filename);
+            } catch (FileNotFoundException ex) {
+                Context.reportError("Couldn't open file \"" + filename + "\".");
+                return;
+            }
+
+            try {
+                // Here we evalute the entire contents of the file as
+                // a script. Text is printed only if the print() function
+                // is called.
+                cx.evaluateReader(this, in, filename, 1, null);
+            } catch (WrappedException we) {
+                System.err.println(we.getWrappedException().toString());
+                we.printStackTrace();
+            } catch (EvaluatorException ee) {
+                System.err.println("js: " + ee.getMessage());
+            } catch (JavaScriptException jse) {
+                System.err.println("js: " + jse.getMessage());
+            } catch (IOException ioe) {
+                System.err.println(ioe.toString());
+            } finally {
+                try {
+                    in.close();
+                } catch (IOException ioe) {
+                    System.err.println(ioe.toString());
+                }
+            }
+        }
+    }
+
+    private static void p(String s) {
+        System.out.println(s);
+    }
+
+    private boolean quitting;
+}


Property changes on: trunk/cdk/maven-javascript-plugin/src/main/java/net/sf/alchim/mojo/yuicompressor/BasicRhinoShell.java
___________________________________________________________________
Name: svn:mime-type
   + text/plain
Name: svn:keywords
   + Date Revision Author

Added: trunk/cdk/maven-javascript-plugin/src/main/java/net/sf/alchim/mojo/yuicompressor/ErrorReporter4Mojo.java
===================================================================
--- trunk/cdk/maven-javascript-plugin/src/main/java/net/sf/alchim/mojo/yuicompressor/ErrorReporter4Mojo.java	                        (rev 0)
+++ trunk/cdk/maven-javascript-plugin/src/main/java/net/sf/alchim/mojo/yuicompressor/ErrorReporter4Mojo.java	2007-12-11 23:30:42 UTC (rev 4755)
@@ -0,0 +1,81 @@
+package net.sf.alchim.mojo.yuicompressor;
+
+import org.apache.maven.plugin.logging.Log;
+import org.mozilla.javascript.ErrorReporter;
+import org.mozilla.javascript.EvaluatorException;
+
+public class ErrorReporter4Mojo implements ErrorReporter {
+
+    private String defaultFilename_;
+    private boolean acceptWarn_;
+    private Log log_;
+    private int warningCnt_;
+    private int errorCnt_;
+
+    public ErrorReporter4Mojo(Log log, boolean jswarn) {
+        log_ = log;
+        acceptWarn_ = jswarn;
+    }
+
+    public void setDefaultFileName(String v) {
+        if (v.length() == 0) {
+            v = null;
+        }
+        defaultFilename_ = v;
+    }
+
+    public int getErrorCnt() {
+        return errorCnt_;
+    }
+
+    public int getWarningCnt() {
+        return warningCnt_;
+    }
+
+    public void error(String message, String sourceName, int line, String lineSource, int lineOffset) {
+        String fullMessage = newMessage(message, sourceName, line, lineSource, lineOffset);
+        log_.error(fullMessage);
+        errorCnt_++;
+    }
+
+    public EvaluatorException runtimeError(String message, String sourceName, int line, String lineSource, int lineOffset) {
+        error(message, sourceName, line, lineSource, lineOffset);
+        throw new EvaluatorException(message, sourceName, line, lineSource, lineOffset);
+    }
+
+    public void warning(String message, String sourceName, int line, String lineSource, int lineOffset) {
+        if (acceptWarn_) {
+            String fullMessage = newMessage(message, sourceName, line, lineSource, lineOffset);
+            log_.warn(fullMessage);
+            warningCnt_++;
+        }
+    }
+
+    private String newMessage(String message, String sourceName, int line, String lineSource, int lineOffset) {
+        StringBuilder back = new StringBuilder();
+        if ((sourceName == null) || (sourceName.length() == 0)) {
+            sourceName = defaultFilename_;
+        }
+        if (sourceName != null) {
+            back.append(sourceName)
+                .append(":line ")
+                .append(line)
+                .append(":column ")
+                .append(lineOffset)
+                .append(':')
+                ;
+        }
+        if ((message != null) && (message.length() != 0)) {
+            back.append(message);
+        } else {
+            back.append("unknown error");
+        }
+        if ((lineSource != null) && (lineSource.length() != 0)) {
+            back.append("\n\t")
+                .append(lineSource)
+                ;
+        }
+        return back.toString();
+    }
+
+}


Property changes on: trunk/cdk/maven-javascript-plugin/src/main/java/net/sf/alchim/mojo/yuicompressor/ErrorReporter4Mojo.java
___________________________________________________________________
Name: svn:mime-type
   + text/plain
Name: svn:keywords
   + Date Revision Author

Added: trunk/cdk/maven-javascript-plugin/src/main/java/net/sf/alchim/mojo/yuicompressor/JSLintChecker.java
===================================================================
--- trunk/cdk/maven-javascript-plugin/src/main/java/net/sf/alchim/mojo/yuicompressor/JSLintChecker.java	                        (rev 0)
+++ trunk/cdk/maven-javascript-plugin/src/main/java/net/sf/alchim/mojo/yuicompressor/JSLintChecker.java	2007-12-11 23:30:42 UTC (rev 4755)
@@ -0,0 +1,38 @@
+package net.sf.alchim.mojo.yuicompressor;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.InputStream;
+
+import org.codehaus.plexus.util.IOUtil;
+import org.mozilla.javascript.ErrorReporter;
+
+//TODO: use MojoErrorReporter
+class JSLintChecker {
+    private String jslintPath_;
+
+    public JSLintChecker() throws Exception {
+        FileOutputStream out = null;
+        InputStream in = null;
+        try {
+            File jslint = File.createTempFile("jslint", ".js");
+            in = getClass().getResourceAsStream("/jslint.js");
+            out = new FileOutputStream(jslint);
+            IOUtil.copy(in, out);
+            jslintPath_ = jslint.getAbsolutePath();
+        } finally {
+            IOUtil.close(in);
+            IOUtil.close(out);
+        }
+    }
+
+    public void check(File jsFile, ErrorReporter reporter) {
+        String[] args = new String[2];
+        args[0] = jslintPath_;
+        args[1] = jsFile.getAbsolutePath();
+        BasicRhinoShell.exec(args, reporter);
+        //if (Main.exec(args) != 0) {
+        //    reporter.warning("warnings during checking of :" + jsFile.getAbsolutePath(), null, -1, null, -1);
+        //}
+    }
+}


Property changes on: trunk/cdk/maven-javascript-plugin/src/main/java/net/sf/alchim/mojo/yuicompressor/JSLintChecker.java
___________________________________________________________________
Name: svn:mime-type
   + text/plain
Name: svn:keywords
   + Date Revision Author

Added: trunk/cdk/maven-javascript-plugin/src/main/java/net/sf/alchim/mojo/yuicompressor/JSLintMojo.java
===================================================================
--- trunk/cdk/maven-javascript-plugin/src/main/java/net/sf/alchim/mojo/yuicompressor/JSLintMojo.java	                        (rev 0)
+++ trunk/cdk/maven-javascript-plugin/src/main/java/net/sf/alchim/mojo/yuicompressor/JSLintMojo.java	2007-12-11 23:30:42 UTC (rev 4755)
@@ -0,0 +1,36 @@
+package net.sf.alchim.mojo.yuicompressor;
+
+
+/**
+ * Check JS files with jslint.
+ *
+ * @goal jslint
+ * @phase process-resources
+ *
+ * @author David Bernard
+ * @created 2007-08-29
+ */
+// @SuppressWarnings("unchecked")
+public class JSLintMojo extends MojoSupport {
+    private JSLintChecker jslint_;
+
+    @Override
+    protected String[] getDefaultIncludes() throws Exception {
+        return new String[] { "**/**.js" };
+    }
+
+    @Override
+    public void beforeProcess() throws Exception {
+        jslint_ = new JSLintChecker();
+    }
+
+    @Override
+    public void afterProcess() throws Exception {
+    }
+
+    @Override
+    protected void processFile(SourceFile src) throws Exception {
+        getLog().info("check file :" + src.toFile());
+        jslint_.check(src.toFile(), jsErrorReporter_);
+    }
+}


Property changes on: trunk/cdk/maven-javascript-plugin/src/main/java/net/sf/alchim/mojo/yuicompressor/JSLintMojo.java
___________________________________________________________________
Name: svn:mime-type
   + text/plain
Name: svn:keywords
   + Date Revision Author

Added: trunk/cdk/maven-javascript-plugin/src/main/java/net/sf/alchim/mojo/yuicompressor/MojoSupport.java
===================================================================
--- trunk/cdk/maven-javascript-plugin/src/main/java/net/sf/alchim/mojo/yuicompressor/MojoSupport.java	                        (rev 0)
+++ trunk/cdk/maven-javascript-plugin/src/main/java/net/sf/alchim/mojo/yuicompressor/MojoSupport.java	2007-12-11 23:30:42 UTC (rev 4755)
@@ -0,0 +1,184 @@
+package net.sf.alchim.mojo.yuicompressor;
+
+import java.io.File;
+import java.util.List;
+
+import org.apache.maven.model.Resource;
+import org.apache.maven.plugin.AbstractMojo;
+import org.apache.maven.plugin.MojoExecutionException;
+import org.apache.maven.plugin.MojoFailureException;
+import org.apache.maven.project.MavenProject;
+import org.codehaus.plexus.util.DirectoryScanner;
+
+/**
+ * Common class for mojos.
+ * 
+ * @author David Bernard
+ * @created 2007-08-29
+ */
+// @SuppressWarnings("unchecked")
+public abstract class MojoSupport extends AbstractMojo {
+	private static final String[] EMPTY_STRING_ARRAY = {};
+
+	/**
+	 * Javascript source directory. (result will be put to outputDirectory).
+	 * This allow project with "src/main/js" structure.
+	 * 
+	 * @parameter default-value="${project.build.sourceDirectory}/../js"
+	 */
+	private File sourceDirectory;
+
+	/**
+	 * Single directory for extra files to include in the WAR.
+	 * 
+	 * @parameter default-value="${basedir}/src/main/webapp"
+	 */
+	private File warSourceDirectory;
+
+	/**
+	 * The directory where the webapp is built.
+	 * 
+	 * @parameter default-value="${project.build.directory}/${project.build.finalName}"
+	 */
+	protected File webappDirectory;
+
+	/**
+	 * The output directory into which to copy the resources.
+	 * 
+	 * @parameter default-value="${project.build.outputDirectory}"
+	 */
+	protected File outputDirectory;
+
+	/**
+	 * The list of resources we want to transfer.
+	 * 
+	 * @parameter default-value="${project.resources}"
+	 */
+	private List<Resource> resources;
+
+	/**
+	 * list of additionnal excludes
+	 * 
+	 * @parameter
+	 */
+	private List<String> excludes;
+
+	/**
+	 * list of additionnal includes
+	 * 
+	 * @parameter
+	 */
+	private List<String> includes;
+
+	/**
+	 * @parameter expression="${project}"
+	 * @readonly
+	 * @required
+	 */
+	protected MavenProject project;
+
+	/**
+	 * [js only] Display possible errors in the code
+	 * 
+	 * @parameter expression="${maven.yuicompressor.jswarm}"
+	 *            default-value="true"
+	 */
+	protected boolean jswarn;
+
+	/**
+	 * define if plugin must stop/fail on warnings.
+	 * 
+	 * @parameter expression="${maven.yuicompressor.failOnWarning}"
+	 *            default-value="false"
+	 */
+	protected boolean failOnWarning;
+	protected ErrorReporter4Mojo jsErrorReporter_;
+
+	@SuppressWarnings("unchecked")
+	public void execute() throws MojoExecutionException, MojoFailureException {
+		try {
+			if (failOnWarning) {
+				jswarn = true;
+			}
+			jsErrorReporter_ = new ErrorReporter4Mojo(getLog(), jswarn);
+			beforeProcess();
+			processDir(sourceDirectory, outputDirectory, null, null,
+					true);
+			for (Resource resource : resources) {
+				File destRoot = outputDirectory;
+				if (resource.getTargetPath() != null) {
+					destRoot = new File(outputDirectory, resource
+							.getTargetPath());
+				}
+				processDir(new File(resource.getDirectory()), destRoot,
+						resource.getIncludes(), resource.getExcludes(), true);
+			}
+			processDir(warSourceDirectory, webappDirectory, null, null,
+					false);
+			afterProcess();
+			getLog().info(
+					String.format("nb warnings: %d, nb errors: %d",
+							jsErrorReporter_.getWarningCnt(), jsErrorReporter_
+									.getErrorCnt()));
+			if (failOnWarning && (jsErrorReporter_.getWarningCnt() > 0)) {
+				throw new MojoFailureException("warnings on "
+						+ this.getClass().getSimpleName()
+						+ "=> failure ! (see log)");
+			}
+		} catch (RuntimeException exc) {
+			throw exc;
+		} catch (MojoFailureException exc) {
+			throw exc;
+		} catch (MojoExecutionException exc) {
+			throw exc;
+		} catch (Exception exc) {
+			throw new MojoExecutionException("wrap: " + exc.getMessage(), exc);
+		}
+	}
+
+	protected abstract String[] getDefaultIncludes() throws Exception;
+
+	protected abstract void beforeProcess() throws Exception;
+
+	protected abstract void afterProcess() throws Exception;
+
+	protected void processDir(File srcRoot, File destRoot,
+			List<String> srcIncludes, List<String> srcExcludes,
+			boolean destAsSource) throws Exception {
+		if ((srcRoot == null) || (!srcRoot.exists())) {
+			return;
+		}
+		if (destRoot == null) {
+			throw new MojoFailureException("destination directory for "
+					+ srcRoot + " is null");
+		}
+		DirectoryScanner scanner = new DirectoryScanner();
+		scanner.setBasedir(srcRoot);
+		if ((srcIncludes != null) && !srcIncludes.isEmpty()) {
+			scanner.setIncludes(srcIncludes.toArray(EMPTY_STRING_ARRAY));
+		} 
+		if ((includes != null) && !includes.isEmpty()) {
+			scanner.setIncludes(includes.toArray(EMPTY_STRING_ARRAY));
+		} else {
+			scanner.setIncludes(getDefaultIncludes());
+		}
+		if ((srcExcludes != null) && !srcExcludes.isEmpty()) {
+			scanner.setExcludes(srcExcludes.toArray(EMPTY_STRING_ARRAY));
+		}
+		if ((excludes != null) && !excludes.isEmpty()) {
+			scanner.setExcludes(excludes.toArray(EMPTY_STRING_ARRAY));
+		}
+		scanner.addDefaultExcludes();
+		scanner.scan();
+		for (String name : scanner.getIncludedFiles()) {
+			SourceFile src = new SourceFile(srcRoot, destRoot, name,
+					destAsSource);
+			jsErrorReporter_.setDefaultFileName("..."
+					+ src.toFile().getAbsolutePath().substring(
+							project.getBasedir().getAbsolutePath().length()));
+			processFile(src);
+		}
+	}
+
+	protected abstract void processFile(SourceFile src) throws Exception;
+}


Property changes on: trunk/cdk/maven-javascript-plugin/src/main/java/net/sf/alchim/mojo/yuicompressor/MojoSupport.java
___________________________________________________________________
Name: svn:mime-type
   + text/plain
Name: svn:keywords
   + Date Revision Author

Added: trunk/cdk/maven-javascript-plugin/src/main/java/net/sf/alchim/mojo/yuicompressor/SourceFile.java
===================================================================
--- trunk/cdk/maven-javascript-plugin/src/main/java/net/sf/alchim/mojo/yuicompressor/SourceFile.java	                        (rev 0)
+++ trunk/cdk/maven-javascript-plugin/src/main/java/net/sf/alchim/mojo/yuicompressor/SourceFile.java	2007-12-11 23:30:42 UTC (rev 4755)
@@ -0,0 +1,45 @@
+package net.sf.alchim.mojo.yuicompressor;
+
+import java.io.File;
+
+public class SourceFile {
+
+    private File srcRoot_;
+    private File destRoot_;
+    private boolean destAsSource_;
+    private String rpath_;
+    private String extension_;
+
+    public SourceFile(File srcRoot, File destRoot, String name, boolean destAsSource) throws Exception {
+        srcRoot_ = srcRoot;
+        destRoot_ = destRoot;
+        destAsSource_ = destAsSource;
+        rpath_ = name;
+        int sep = rpath_.lastIndexOf('.');
+        if (sep>0) {
+            extension_ = rpath_.substring(sep);
+            rpath_ = rpath_.substring(0, sep);
+        } else {
+            extension_ = "";
+        }
+    }
+
+    public File toFile() {
+        String frpath = rpath_ + extension_;
+        if (destAsSource_) {
+            File defaultDest = new File(destRoot_, frpath);
+            if (defaultDest.exists() && defaultDest.canRead()) {
+                return defaultDest;
+            }
+        }
+        return new File(srcRoot_, frpath);
+    }
+
+    public File toDestFile(String suffix) {
+        return new File(destRoot_, rpath_ + suffix + extension_);
+    }
+
+    public String getExtension() {
+        return extension_;
+    }
+}


Property changes on: trunk/cdk/maven-javascript-plugin/src/main/java/net/sf/alchim/mojo/yuicompressor/SourceFile.java
___________________________________________________________________
Name: svn:mime-type
   + text/plain
Name: svn:keywords
   + Date Revision Author

Added: trunk/cdk/maven-javascript-plugin/src/main/java/net/sf/alchim/mojo/yuicompressor/YuiCompressorMojo.java
===================================================================
--- trunk/cdk/maven-javascript-plugin/src/main/java/net/sf/alchim/mojo/yuicompressor/YuiCompressorMojo.java	                        (rev 0)
+++ trunk/cdk/maven-javascript-plugin/src/main/java/net/sf/alchim/mojo/yuicompressor/YuiCompressorMojo.java	2007-12-11 23:30:42 UTC (rev 4755)
@@ -0,0 +1,229 @@
+package net.sf.alchim.mojo.yuicompressor;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStreamWriter;
+import java.util.zip.GZIPOutputStream;
+
+import org.apache.maven.plugin.MojoExecutionException;
+import org.codehaus.plexus.util.FileUtils;
+import org.codehaus.plexus.util.IOUtil;
+
+import com.yahoo.platform.yui.compressor.CssCompressor;
+import com.yahoo.platform.yui.compressor.JavaScriptCompressor;
+
+/**
+ * Apply compression on JS and CSS (using YUI Compressor).
+ *
+ * @goal compress
+ * @phase process-resources
+ *
+ * @author David Bernard
+ * @created 2007-08-28
+ */
+// @SuppressWarnings("unchecked")
+public class YuiCompressorMojo extends MojoSupport {
+
+    /**
+     * Read the input file using "encoding".
+     *
+     * @parameter expression="${file.encoding}" default-value="UTF-8"
+     */
+    private String encoding;
+
+    /**
+     * The output filename suffix.
+     *
+     * @parameter expression="${maven.yuicompressor.suffix}" default-value="-min"
+     */
+    private String suffix;
+
+    /**
+     * If no "suffix" must be add to output filename (maven's configuration manage empty suffix like default).
+     *
+     * @parameter expression="${maven.yuicompressor.nosuffix}" default-value="false"
+     */
+    private boolean nosuffix;
+
+    /**
+     * Insert line breaks in output after the specified column number.
+     *
+     * @parameter expression="${maven.yuicompressor.linebreakpos}" default-value="0"
+     */
+    private int linebreakpos;
+
+    /**
+     * [js only] Minify only, do not obfuscate.
+     *
+     * @parameter expression="${maven.yuicompressor.nomunge}" default-value="false"
+     */
+    private boolean nomunge;
+
+    /**
+     * [js only] Preserve unnecessary semicolons.
+     *
+     * @parameter expression="${maven.yuicompressor.preserveAllSemiColons}" default-value="false"
+     */
+    private boolean preserveAllSemiColons;
+
+    /**
+     * [js only] Preserve string (no optimization).
+     *
+     * @parameter expression="${maven.yuicompressor.preserveStringLiterals}" default-value="false"
+     */
+    private boolean preserveStringLiterals;
+
+    /**
+     * force the compression of every files,
+     * else if compressed file already exists and is younger than source file, nothing is done.
+     *
+     * @parameter expression="${maven.yuicompressor.force}" default-value="false"
+     */
+    private boolean force;
+
+    /**
+     * a list of aggregation/concatenation to do after processing,
+     * for example to create big js files that contain several small js files.
+     * Aggregation could be done on any type of file (js, css, ...).
+     *
+     * @parameter
+     */
+    private Aggregation[] aggregations;
+
+    /**
+     * request to create a gzipped version of the yuicompressed/aggregation files.
+     *
+     * @parameter expression="${maven.yuicompressor.gzip}" default-value="false"
+     */
+    private boolean gzip;
+
+    /**
+     * show statistics (compression ratio).
+     *
+     * @parameter expression="${maven.yuicompressor.statistics}" default-value="true"
+     */
+    private boolean statistics;
+
+    private long inSizeTotal_;
+    private long outSizeTotal_;
+
+    @Override
+    protected String[] getDefaultIncludes() throws Exception {
+        return new String[]{"**/*.css", "**/*.js"};
+    }
+
+    @Override
+    public void beforeProcess() throws Exception {
+        if (nosuffix) {
+            suffix = "";
+        }
+    }
+
+    @Override
+    protected void afterProcess() throws Exception {
+        if (statistics && (inSizeTotal_ > 0)) {
+            getLog().info(String.format("total input (%db) -> output (%db)[%d%%]", inSizeTotal_, outSizeTotal_, ((outSizeTotal_ * 100)/inSizeTotal_)));
+        }
+        if (aggregations != null) {
+            for(Aggregation aggregation : aggregations) {
+                getLog().info("generate aggregation : " + aggregation.output);
+                aggregation.run(outputDirectory);
+                File gzipped = gzipIfRequested(aggregation.output);
+                if (statistics) {
+                    if (gzipped != null) {
+                        getLog().info(String.format("%s (%db) -> %s (%db)[%d%%]", aggregation.output.getName(), aggregation.output.length(), gzipped.getName(), gzipped.length(), ratioOfSize(aggregation.output, gzipped)));
+                    } else if (aggregation.output.exists()){
+                        getLog().info(String.format("%s (%db)", aggregation.output.getName(), aggregation.output.length()));
+                    } else {
+                        getLog().warn(String.format("%s not created", aggregation.output.getName()));
+                    }
+                }
+            }
+        }
+    }
+
+
+    @Override
+    protected void processFile(SourceFile src) throws Exception {
+        if (getLog().isDebugEnabled()) {
+            getLog().debug("compress file :" + src.toFile()+ " to " + src.toDestFile(suffix));
+        }
+        File inFile = src.toFile();
+        File outFile = src.toDestFile(suffix);
+
+        getLog().debug("only compress if input file is youger than existing output file");
+        if (!force && outFile.exists() && (outFile.lastModified() > inFile.lastModified())) {
+            if (getLog().isInfoEnabled()) {
+                getLog().info("nothing to do, " + outFile + " is younger than original, use 'force' option or clean your target");
+            }
+            return;
+        }
+
+        InputStreamReader in = null;
+        OutputStreamWriter out = null;
+        try {
+            in = new InputStreamReader(new FileInputStream(inFile), encoding);
+            if (!outFile.getParentFile().exists() && !outFile.getParentFile().mkdirs()) {
+                throw new MojoExecutionException( "Cannot create resource output directory: " + outFile.getParentFile() );
+            }
+            getLog().debug("use a temporary outputfile (in case in == out)");
+            File outFileTmp = new File(outFile.getAbsolutePath() + ".tmp");
+            FileUtils.forceDelete(outFileTmp);
+
+            getLog().debug("start compression");
+            out = new OutputStreamWriter(new FileOutputStream(outFileTmp), encoding);
+            if (".js".equalsIgnoreCase(src.getExtension())) {
+                JavaScriptCompressor compressor = new JavaScriptCompressor(in, jsErrorReporter_);
+                compressor.compress(out, linebreakpos, !nomunge, jswarn, preserveAllSemiColons, preserveStringLiterals);
+            } else if (".css".equalsIgnoreCase(src.getExtension())) {
+                CssCompressor compressor = new CssCompressor(in);
+                compressor.compress(out, linebreakpos);
+            }
+            getLog().debug("end compression");
+            FileUtils.forceDelete(outFile);
+            FileUtils.rename(outFileTmp, outFile);
+        } finally {
+            IOUtil.close(in);
+            IOUtil.close(out);
+        }
+        File gzipped = gzipIfRequested(outFile);
+        if (statistics) {
+            inSizeTotal_ += inFile.length();
+            outSizeTotal_ += outFile.length();
+            getLog().info(String.format("%s (%db) -> %s (%db)[%d%%]", inFile.getName(), inFile.length(), outFile.getName(), outFile.length(), ratioOfSize(inFile, outFile)));
+            if (gzipped != null) {
+                getLog().info(String.format("%s (%db) -> %s (%db)[%d%%]", inFile.getName(), inFile.length(), gzipped.getName(), gzipped.length(), ratioOfSize(inFile, gzipped)));
+            }
+        }
+    }
+
+    protected File gzipIfRequested(File file) throws Exception {
+        if (!gzip || (file == null) || (!file.exists())) {
+            return null;
+        }
+        if (".gz".equalsIgnoreCase(FileUtils.getExtension(file.getName()))) {
+            return null;
+        }
+        File gzipped = new File(file.getAbsolutePath()+".gz");
+        getLog().debug(String.format("create gzip version : %s", gzipped.getName()));
+        GZIPOutputStream out = null;
+        FileInputStream in = null;
+        try {
+            out = new GZIPOutputStream(new FileOutputStream(gzipped));
+            in = new FileInputStream(file);
+            IOUtil.copy(in, out);
+        } finally {
+            IOUtil.close(in);
+            IOUtil.close(out);
+        }
+        return gzipped;
+    }
+
+    protected long ratioOfSize(File file100, File fileX) throws Exception {
+        long v100 = Math.max(file100.length(), 1);
+        long vX = Math.max(fileX.length(), 1);
+        return (vX * 100)/v100;
+    }
+}


Property changes on: trunk/cdk/maven-javascript-plugin/src/main/java/net/sf/alchim/mojo/yuicompressor/YuiCompressorMojo.java
___________________________________________________________________
Name: svn:mime-type
   + text/plain
Name: svn:keywords
   + Date Revision Author

Added: trunk/cdk/maven-javascript-plugin/src/main/java/org/mozilla/javascript/Decompiler.java
===================================================================
--- trunk/cdk/maven-javascript-plugin/src/main/java/org/mozilla/javascript/Decompiler.java	                        (rev 0)
+++ trunk/cdk/maven-javascript-plugin/src/main/java/org/mozilla/javascript/Decompiler.java	2007-12-11 23:30:42 UTC (rev 4755)
@@ -0,0 +1,916 @@
+/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Rhino code, released
+ * May 6, 1999.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1997-1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Mike Ang
+ *   Igor Bukanov
+ *   Bob Jervis
+ *   Mike McCabe
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * the GNU General Public License Version 2 or later (the "GPL"), in which
+ * case the provisions of the GPL are applicable instead of those above. If
+ * you wish to allow use of your version of this file only under the terms of
+ * the GPL and not to allow others to use your version of this file under the
+ * MPL, indicate your decision by deleting the provisions above and replacing
+ * them with the notice and other provisions required by the GPL. If you do
+ * not delete the provisions above, a recipient may use your version of this
+ * file under either the MPL or the GPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+package org.mozilla.javascript;
+
+/**
+ * The following class save decompilation information about the source.
+ * Source information is returned from the parser as a String
+ * associated with function nodes and with the toplevel script.  When
+ * saved in the constant pool of a class, this string will be UTF-8
+ * encoded, and token values will occupy a single byte.
+
+ * Source is saved (mostly) as token numbers.  The tokens saved pretty
+ * much correspond to the token stream of a 'canonical' representation
+ * of the input program, as directed by the parser.  (There were a few
+ * cases where tokens could have been left out where decompiler could
+ * easily reconstruct them, but I left them in for clarity).  (I also
+ * looked adding source collection to TokenStream instead, where I
+ * could have limited the changes to a few lines in getToken... but
+ * this wouldn't have saved any space in the resulting source
+ * representation, and would have meant that I'd have to duplicate
+ * parser logic in the decompiler to disambiguate situations where
+ * newlines are important.)  The function decompile expands the
+ * tokens back into their string representations, using simple
+ * lookahead to correct spacing and indentation.
+ *
+ * Assignments are saved as two-token pairs (Token.ASSIGN, op). Number tokens
+ * are stored inline, as a NUMBER token, a character representing the type, and
+ * either 1 or 4 characters representing the bit-encoding of the number.  String
+ * types NAME, STRING and OBJECT are currently stored as a token type,
+ * followed by a character giving the length of the string (assumed to
+ * be less than 2^16), followed by the characters of the string
+ * inlined into the source string.  Changing this to some reference to
+ * to the string in the compiled class' constant pool would probably
+ * save a lot of space... but would require some method of deriving
+ * the final constant pool entry from information available at parse
+ * time.
+ */
+public class Decompiler
+{
+    /**
+     * Flag to indicate that the decompilation should omit the
+     * function header and trailing brace.
+     */
+    public static final int ONLY_BODY_FLAG = 1 << 0;
+
+    /**
+     * Flag to indicate that the decompilation generates toSource result.
+     */
+    public static final int TO_SOURCE_FLAG = 1 << 1;
+
+    /**
+     * Decompilation property to specify initial ident value.
+     */
+    public static final int INITIAL_INDENT_PROP = 1;
+
+    /**
+     * Decompilation property to specify default identation offset.
+     */
+    public static final int INDENT_GAP_PROP = 2;
+
+    /**
+     * Decompilation property to specify identation offset for case labels.
+     */
+    public static final int CASE_GAP_PROP = 3;
+
+    // Marker to denote the last RC of function so it can be distinguished from
+    // the last RC of object literals in case of function expressions
+    private static final int FUNCTION_END = Token.LAST_TOKEN + 1;
+
+    String getEncodedSource()
+    {
+        return sourceToString(0);
+    }
+
+    int getCurrentOffset()
+    {
+        return sourceTop;
+    }
+
+    int markFunctionStart(int functionType)
+    {
+        int savedOffset = getCurrentOffset();
+        addToken(Token.FUNCTION);
+        append((char)functionType);
+        return savedOffset;
+    }
+
+    int markFunctionEnd(int functionStart)
+    {
+        int offset = getCurrentOffset();
+        append((char)FUNCTION_END);
+        return offset;
+    }
+
+    void addToken(int token)
+    {
+        if (!(0 <= token && token <= Token.LAST_TOKEN))
+            throw new IllegalArgumentException();
+
+        append((char)token);
+    }
+
+    void addEOL(int token)
+    {
+        if (!(0 <= token && token <= Token.LAST_TOKEN))
+            throw new IllegalArgumentException();
+
+        append((char)token);
+        append((char)Token.EOL);
+    }
+
+    void addName(String str)
+    {
+        addToken(Token.NAME);
+        appendString(str);
+    }
+
+    void addString(String str)
+    {
+        addToken(Token.STRING);
+        appendString(str);
+    }
+
+    void addRegexp(String regexp, String flags)
+    {
+        addToken(Token.REGEXP);
+        appendString('/' + regexp + '/' + flags);
+    }
+
+    void addJScriptConditionalComment(String str)
+    {
+        addToken(Token.IECC);
+        appendString(str);
+    }
+
+    void addNumber(double n)
+    {
+        addToken(Token.NUMBER);
+
+        /* encode the number in the source stream.
+         * Save as NUMBER type (char | char char char char)
+         * where type is
+         * 'D' - double, 'S' - short, 'J' - long.
+
+         * We need to retain float vs. integer type info to keep the
+         * behavior of liveconnect type-guessing the same after
+         * decompilation.  (Liveconnect tries to present 1.0 to Java
+         * as a float/double)
+         * OPT: This is no longer true. We could compress the format.
+
+         * This may not be the most space-efficient encoding;
+         * the chars created below may take up to 3 bytes in
+         * constant pool UTF-8 encoding, so a Double could take
+         * up to 12 bytes.
+         */
+
+        long lbits = (long)n;
+        if (lbits != n) {
+            // if it's floating point, save as a Double bit pattern.
+            // (12/15/97 our scanner only returns Double for f.p.)
+            lbits = Double.doubleToLongBits(n);
+            append('D');
+            append((char)(lbits >> 48));
+            append((char)(lbits >> 32));
+            append((char)(lbits >> 16));
+            append((char)lbits);
+        }
+        else {
+            // we can ignore negative values, bc they're already prefixed
+            // by NEG
+               if (lbits < 0) Kit.codeBug();
+
+            // will it fit in a char?
+            // this gives a short encoding for integer values up to 2^16.
+            if (lbits <= Character.MAX_VALUE) {
+                append('S');
+                append((char)lbits);
+            }
+            else { // Integral, but won't fit in a char. Store as a long.
+                append('J');
+                append((char)(lbits >> 48));
+                append((char)(lbits >> 32));
+                append((char)(lbits >> 16));
+                append((char)lbits);
+            }
+        }
+    }
+
+    private void appendString(String str)
+    {
+        int L = str.length();
+        int lengthEncodingSize = 1;
+        if (L >= 0x8000) {
+            lengthEncodingSize = 2;
+        }
+        int nextTop = sourceTop + lengthEncodingSize + L;
+        if (nextTop > sourceBuffer.length) {
+            increaseSourceCapacity(nextTop);
+        }
+        if (L >= 0x8000) {
+            // Use 2 chars to encode strings exceeding 32K, were the highest
+            // bit in the first char indicates presence of the next byte
+            sourceBuffer[sourceTop] = (char)(0x8000 | (L >>> 16));
+            ++sourceTop;
+        }
+        sourceBuffer[sourceTop] = (char)L;
+        ++sourceTop;
+        str.getChars(0, L, sourceBuffer, sourceTop);
+        sourceTop = nextTop;
+    }
+
+    private void append(char c)
+    {
+        if (sourceTop == sourceBuffer.length) {
+            increaseSourceCapacity(sourceTop + 1);
+        }
+        sourceBuffer[sourceTop] = c;
+        ++sourceTop;
+    }
+
+    private void increaseSourceCapacity(int minimalCapacity)
+    {
+        // Call this only when capacity increase is must
+        if (minimalCapacity <= sourceBuffer.length) Kit.codeBug();
+        int newCapacity = sourceBuffer.length * 2;
+        if (newCapacity < minimalCapacity) {
+            newCapacity = minimalCapacity;
+        }
+        char[] tmp = new char[newCapacity];
+        System.arraycopy(sourceBuffer, 0, tmp, 0, sourceTop);
+        sourceBuffer = tmp;
+    }
+
+    private String sourceToString(int offset)
+    {
+        if (offset < 0 || sourceTop < offset) Kit.codeBug();
+        return new String(sourceBuffer, offset, sourceTop - offset);
+    }
+
+    /**
+     * Decompile the source information associated with this js
+     * function/script back into a string.  For the most part, this
+     * just means translating tokens back to their string
+     * representations; there's a little bit of lookahead logic to
+     * decide the proper spacing/indentation.  Most of the work in
+     * mapping the original source to the prettyprinted decompiled
+     * version is done by the parser.
+     *
+     * @param source encoded source tree presentation
+     *
+     * @param flags flags to select output format
+     *
+     * @param properties indentation properties
+     *
+     */
+    public static String decompile(String source, int flags,
+                                   UintMap properties)
+    {
+        int length = source.length();
+        if (length == 0) { return ""; }
+
+        int indent = properties.getInt(INITIAL_INDENT_PROP, 0);
+        if (indent < 0) throw new IllegalArgumentException();
+        int indentGap = properties.getInt(INDENT_GAP_PROP, 4);
+        if (indentGap < 0) throw new IllegalArgumentException();
+        int caseGap = properties.getInt(CASE_GAP_PROP, 2);
+        if (caseGap < 0) throw new IllegalArgumentException();
+
+        StringBuffer result = new StringBuffer();
+        boolean justFunctionBody = (0 != (flags & Decompiler.ONLY_BODY_FLAG));
+        boolean toSource = (0 != (flags & Decompiler.TO_SOURCE_FLAG));
+
+        // Spew tokens in source, for debugging.
+        // as TYPE number char
+        if (printSource) {
+            System.err.println("length:" + length);
+            for (int i = 0; i < length; ++i) {
+                // Note that tokenToName will fail unless Context.printTrees
+                // is true.
+                String tokenname = null;
+                if (Token.printNames) {
+                    tokenname = Token.name(source.charAt(i));
+                }
+                if (tokenname == null) {
+                    tokenname = "---";
+                }
+                String pad = tokenname.length() > 7
+                    ? "\t"
+                    : "\t\t";
+                System.err.println
+                    (tokenname
+                     + pad + (int)source.charAt(i)
+                     + "\t'" + ScriptRuntime.escapeString
+                     (source.substring(i, i+1))
+                     + "'");
+            }
+            System.err.println();
+        }
+
+        int braceNesting = 0;
+        boolean afterFirstEOL = false;
+        int i = 0;
+        int topFunctionType;
+        if (source.charAt(i) == Token.SCRIPT) {
+            ++i;
+            topFunctionType = -1;
+        } else {
+            topFunctionType = source.charAt(i + 1);
+        }
+
+        if (!toSource) {
+            // add an initial newline to exactly match js.
+            result.append('\n');
+            for (int j = 0; j < indent; j++)
+                result.append(' ');
+        } else {
+            if (topFunctionType == FunctionNode.FUNCTION_EXPRESSION) {
+                result.append('(');
+            }
+        }
+
+        while (i < length) {
+            switch(source.charAt(i)) {
+            case Token.GET:
+            case Token.SET:
+                result.append(source.charAt(i) == Token.GET ? "get " : "set ");
+                ++i;
+                i = printSourceString(source, i + 1, false, result);
+                // Now increment one more to get past the FUNCTION token
+                ++i;
+                break;
+
+            case Token.NAME:
+            case Token.REGEXP:  // re-wrapped in '/'s in parser...
+                i = printSourceString(source, i + 1, false, result);
+                continue;
+
+            case Token.STRING:
+                i = printSourceString(source, i + 1, true, result);
+                continue;
+
+            case Token.NUMBER:
+                i = printSourceNumber(source, i + 1, result);
+                continue;
+
+            case Token.TRUE:
+                result.append("true");
+                break;
+
+            case Token.FALSE:
+                result.append("false");
+                break;
+
+            case Token.NULL:
+                result.append("null");
+                break;
+
+            case Token.THIS:
+                result.append("this");
+                break;
+
+            case Token.FUNCTION:
+                ++i; // skip function type
+                result.append("function ");
+                break;
+
+            case FUNCTION_END:
+                // Do nothing
+                break;
+
+            case Token.COMMA:
+                result.append(", ");
+                break;
+
+            case Token.LC:
+                ++braceNesting;
+                if (Token.EOL == getNext(source, length, i))
+                    indent += indentGap;
+                result.append('{');
+                break;
+
+            case Token.RC: {
+                --braceNesting;
+                /* don't print the closing RC if it closes the
+                 * toplevel function and we're called from
+                 * decompileFunctionBody.
+                 */
+                if (justFunctionBody && braceNesting == 0)
+                    break;
+
+                result.append('}');
+                switch (getNext(source, length, i)) {
+                    case Token.EOL:
+                    case FUNCTION_END:
+                        indent -= indentGap;
+                        break;
+                    case Token.WHILE:
+                    case Token.ELSE:
+                        indent -= indentGap;
+                        result.append(' ');
+                        break;
+                }
+                break;
+            }
+            case Token.LP:
+                result.append('(');
+                break;
+
+            case Token.RP:
+                result.append(')');
+                if (Token.LC == getNext(source, length, i))
+                    result.append(' ');
+                break;
+
+            case Token.LB:
+                result.append('[');
+                break;
+
+            case Token.RB:
+                result.append(']');
+                break;
+
+            case Token.EOL: {
+                if (toSource) break;
+                boolean newLine = true;
+                if (!afterFirstEOL) {
+                    afterFirstEOL = true;
+                    if (justFunctionBody) {
+                        /* throw away just added 'function name(...) {'
+                         * and restore the original indent
+                         */
+                        result.setLength(0);
+                        indent -= indentGap;
+                        newLine = false;
+                    }
+                }
+                if (newLine) {
+                    result.append('\n');
+                }
+
+                /* add indent if any tokens remain,
+                 * less setback if next token is
+                 * a label, case or default.
+                 */
+                if (i + 1 < length) {
+                    int less = 0;
+                    int nextToken = source.charAt(i + 1);
+                    if (nextToken == Token.CASE
+                        || nextToken == Token.DEFAULT)
+                    {
+                        less = indentGap - caseGap;
+                    } else if (nextToken == Token.RC) {
+                        less = indentGap;
+                    }
+
+                    /* elaborate check against label... skip past a
+                     * following inlined NAME and look for a COLON.
+                     */
+                    else if (nextToken == Token.NAME) {
+                        int afterName = getSourceStringEnd(source, i + 2);
+                        if (source.charAt(afterName) == Token.COLON)
+                            less = indentGap;
+                    }
+
+                    for (; less < indent; less++)
+                        result.append(' ');
+                }
+                break;
+            }
+            case Token.DOT:
+                result.append('.');
+                break;
+
+            case Token.NEW:
+                result.append("new ");
+                break;
+
+            case Token.DELPROP:
+                result.append("delete ");
+                break;
+
+            case Token.IF:
+                result.append("if ");
+                break;
+
+            case Token.ELSE:
+                result.append("else ");
+                break;
+
+            case Token.FOR:
+                result.append("for ");
+                break;
+
+            case Token.IN:
+                result.append(" in ");
+                break;
+
+            case Token.WITH:
+                result.append("with ");
+                break;
+
+            case Token.WHILE:
+                result.append("while ");
+                break;
+
+            case Token.DO:
+                result.append("do ");
+                break;
+
+            case Token.TRY:
+                result.append("try ");
+                break;
+
+            case Token.CATCH:
+                result.append("catch ");
+                break;
+
+            case Token.FINALLY:
+                result.append("finally ");
+                break;
+
+            case Token.THROW:
+                result.append("throw ");
+                break;
+
+            case Token.SWITCH:
+                result.append("switch ");
+                break;
+
+            case Token.BREAK:
+                result.append("break");
+                if (Token.NAME == getNext(source, length, i))
+                    result.append(' ');
+                break;
+
+            case Token.CONTINUE:
+                result.append("continue");
+                if (Token.NAME == getNext(source, length, i))
+                    result.append(' ');
+                break;
+
+            case Token.CASE:
+                result.append("case ");
+                break;
+
+            case Token.DEFAULT:
+                result.append("default");
+                break;
+
+            case Token.RETURN:
+                result.append("return");
+                if (Token.SEMI != getNext(source, length, i))
+                    result.append(' ');
+                break;
+
+            case Token.VAR:
+                result.append("var ");
+                break;
+
+            case Token.SEMI:
+                result.append(';');
+                if (Token.EOL != getNext(source, length, i)) {
+                    // separators in FOR
+                    result.append(' ');
+                }
+                break;
+
+            case Token.ASSIGN:
+                result.append(" = ");
+                break;
+
+            case Token.ASSIGN_ADD:
+                result.append(" += ");
+                break;
+
+            case Token.ASSIGN_SUB:
+                result.append(" -= ");
+                break;
+
+            case Token.ASSIGN_MUL:
+                result.append(" *= ");
+                break;
+
+            case Token.ASSIGN_DIV:
+                result.append(" /= ");
+                break;
+
+            case Token.ASSIGN_MOD:
+                result.append(" %= ");
+                break;
+
+            case Token.ASSIGN_BITOR:
+                result.append(" |= ");
+                break;
+
+            case Token.ASSIGN_BITXOR:
+                result.append(" ^= ");
+                break;
+
+            case Token.ASSIGN_BITAND:
+                result.append(" &= ");
+                break;
+
+            case Token.ASSIGN_LSH:
+                result.append(" <<= ");
+                break;
+
+            case Token.ASSIGN_RSH:
+                result.append(" >>= ");
+                break;
+
+            case Token.ASSIGN_URSH:
+                result.append(" >>>= ");
+                break;
+
+            case Token.HOOK:
+                result.append(" ? ");
+                break;
+
+            case Token.OBJECTLIT:
+                // pun OBJECTLIT to mean colon in objlit property
+                // initialization.
+                // This needs to be distinct from COLON in the general case
+                // to distinguish from the colon in a ternary... which needs
+                // different spacing.
+                result.append(':');
+                break;
+
+            case Token.COLON:
+                if (Token.EOL == getNext(source, length, i))
+                    // it's the end of a label
+                    result.append(':');
+                else
+                    // it's the middle part of a ternary
+                    result.append(" : ");
+                break;
+
+            case Token.OR:
+                result.append(" || ");
+                break;
+
+            case Token.AND:
+                result.append(" && ");
+                break;
+
+            case Token.BITOR:
+                result.append(" | ");
+                break;
+
+            case Token.BITXOR:
+                result.append(" ^ ");
+                break;
+
+            case Token.BITAND:
+                result.append(" & ");
+                break;
+
+            case Token.SHEQ:
+                result.append(" === ");
+                break;
+
+            case Token.SHNE:
+                result.append(" !== ");
+                break;
+
+            case Token.EQ:
+                result.append(" == ");
+                break;
+
+            case Token.NE:
+                result.append(" != ");
+                break;
+
+            case Token.LE:
+                result.append(" <= ");
+                break;
+
+            case Token.LT:
+                result.append(" < ");
+                break;
+
+            case Token.GE:
+                result.append(" >= ");
+                break;
+
+            case Token.GT:
+                result.append(" > ");
+                break;
+
+            case Token.INSTANCEOF:
+                result.append(" instanceof ");
+                break;
+
+            case Token.LSH:
+                result.append(" << ");
+                break;
+
+            case Token.RSH:
+                result.append(" >> ");
+                break;
+
+            case Token.URSH:
+                result.append(" >>> ");
+                break;
+
+            case Token.TYPEOF:
+                result.append("typeof ");
+                break;
+
+            case Token.VOID:
+                result.append("void ");
+                break;
+
+            case Token.CONST:
+                result.append("const ");
+                break;
+
+            case Token.NOT:
+                result.append('!');
+                break;
+
+            case Token.BITNOT:
+                result.append('~');
+                break;
+
+            case Token.POS:
+                result.append('+');
+                break;
+
+            case Token.NEG:
+                result.append('-');
+                break;
+
+            case Token.INC:
+                result.append("++");
+                break;
+
+            case Token.DEC:
+                result.append("--");
+                break;
+
+            case Token.ADD:
+                result.append(" + ");
+                break;
+
+            case Token.SUB:
+                result.append(" - ");
+                break;
+
+            case Token.MUL:
+                result.append(" * ");
+                break;
+
+            case Token.DIV:
+                result.append(" / ");
+                break;
+
+            case Token.MOD:
+                result.append(" % ");
+                break;
+
+            case Token.COLONCOLON:
+                result.append("::");
+                break;
+
+            case Token.DOTDOT:
+                result.append("..");
+                break;
+
+            case Token.DOTQUERY:
+                result.append(".(");
+                break;
+
+            case Token.XMLATTR:
+                result.append('@');
+                break;
+
+            default:
+                // If we don't know how to decompile it, raise an exception.
+                throw new RuntimeException("Token: " +
+                                               Token.name(source.charAt(i)));
+            }
+            ++i;
+        }
+
+        if (!toSource) {
+            // add that trailing newline if it's an outermost function.
+            if (!justFunctionBody)
+                result.append('\n');
+        } else {
+            if (topFunctionType == FunctionNode.FUNCTION_EXPRESSION) {
+                result.append(')');
+            }
+        }
+
+        return result.toString();
+    }
+
+    private static int getNext(String source, int length, int i)
+    {
+        return (i + 1 < length) ? source.charAt(i + 1) : Token.EOF;
+    }
+
+    private static int getSourceStringEnd(String source, int offset)
+    {
+        return printSourceString(source, offset, false, null);
+    }
+
+    private static int printSourceString(String source, int offset,
+                                         boolean asQuotedString,
+                                         StringBuffer sb)
+    {
+        int length = source.charAt(offset);
+        ++offset;
+        if ((0x8000 & length) != 0) {
+            length = ((0x7FFF & length) << 16) | source.charAt(offset);
+            ++offset;
+        }
+        if (sb != null) {
+            String str = source.substring(offset, offset + length);
+            if (!asQuotedString) {
+                sb.append(str);
+            } else {
+                sb.append('"');
+                sb.append(ScriptRuntime.escapeString(str));
+                sb.append('"');
+            }
+        }
+        return offset + length;
+    }
+
+    private static int printSourceNumber(String source, int offset,
+                                         StringBuffer sb)
+    {
+        double number = 0.0;
+        char type = source.charAt(offset);
+        ++offset;
+        if (type == 'S') {
+            if (sb != null) {
+                int ival = source.charAt(offset);
+                number = ival;
+            }
+            ++offset;
+        } else if (type == 'J' || type == 'D') {
+            if (sb != null) {
+                long lbits;
+                lbits = (long)source.charAt(offset) << 48;
+                lbits |= (long)source.charAt(offset + 1) << 32;
+                lbits |= (long)source.charAt(offset + 2) << 16;
+                lbits |= source.charAt(offset + 3);
+                if (type == 'J') {
+                    number = lbits;
+                } else {
+                    number = Double.longBitsToDouble(lbits);
+                }
+            }
+            offset += 4;
+        } else {
+            // Bad source
+            throw new RuntimeException();
+        }
+        if (sb != null) {
+            sb.append(ScriptRuntime.numberToString(number, 10));
+        }
+        return offset;
+    }
+
+    private char[] sourceBuffer = new char[128];
+
+// Per script/function source buffer top: parent source does not include a
+// nested functions source and uses function index as a reference instead.
+    private int sourceTop;
+
+// whether to do a debug print of the source information, when decompiling.
+    private static final boolean printSource = false;
+
+}


Property changes on: trunk/cdk/maven-javascript-plugin/src/main/java/org/mozilla/javascript/Decompiler.java
___________________________________________________________________
Name: svn:mime-type
   + text/plain
Name: svn:keywords
   + Date Revision Author

Added: trunk/cdk/maven-javascript-plugin/src/main/java/org/mozilla/javascript/Parser.java
===================================================================
--- trunk/cdk/maven-javascript-plugin/src/main/java/org/mozilla/javascript/Parser.java	                        (rev 0)
+++ trunk/cdk/maven-javascript-plugin/src/main/java/org/mozilla/javascript/Parser.java	2007-12-11 23:30:42 UTC (rev 4755)
@@ -0,0 +1,2170 @@
+/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Rhino code, released
+ * May 6, 1999.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1997-1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Mike Ang
+ *   Igor Bukanov
+ *   Yuh-Ruey Chen
+ *   Ethan Hugg
+ *   Bob Jervis
+ *   Terry Lucas
+ *   Mike McCabe
+ *   Milen Nankov
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * the GNU General Public License Version 2 or later (the "GPL"), in which
+ * case the provisions of the GPL are applicable instead of those above. If
+ * you wish to allow use of your version of this file only under the terms of
+ * the GPL and not to allow others to use your version of this file under the
+ * MPL, indicate your decision by deleting the provisions above and replacing
+ * them with the notice and other provisions required by the GPL. If you do
+ * not delete the provisions above, a recipient may use your version of this
+ * file under either the MPL or the GPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+package org.mozilla.javascript;
+
+import java.io.Reader;
+import java.io.IOException;
+import java.util.Hashtable;
+
+/**
+ * This class implements the JavaScript parser.
+ *
+ * It is based on the C source files jsparse.c and jsparse.h
+ * in the jsref package.
+ *
+ * @see TokenStream
+ *
+ * @author Mike McCabe
+ * @author Brendan Eich
+ */
+
+public class Parser
+{
+    // TokenInformation flags : currentFlaggedToken stores them together
+    // with token type
+    final static int
+        CLEAR_TI_MASK  = 0xFFFF,   // mask to clear token information bits
+        TI_AFTER_EOL   = 1 << 16,  // first token of the source line
+        TI_CHECK_LABEL = 1 << 17;  // indicates to check for label
+
+    CompilerEnvirons compilerEnv;
+    private ErrorReporter errorReporter;
+    private String sourceURI;
+    boolean calledByCompileFunction;
+
+    private TokenStream ts;
+    private int currentFlaggedToken;
+    private int syntaxErrorCount;
+
+    private IRFactory nf;
+
+    private int nestingOfFunction;
+
+    private Decompiler decompiler;
+    private String encodedSource;
+
+// The following are per function variables and should be saved/restored
+// during function parsing.
+// XXX Move to separated class?
+    ScriptOrFnNode currentScriptOrFn;
+    private int nestingOfWith;
+    private Hashtable labelSet; // map of label names into nodes
+    private ObjArray loopSet;
+    private ObjArray loopAndSwitchSet;
+    private boolean hasReturnValue;
+    private int functionEndFlags;
+// end of per function variables
+
+    // Exception to unwind
+    private static class ParserException extends RuntimeException
+    {
+        static final long serialVersionUID = 5882582646773765630L;
+    }
+
+    public Parser(CompilerEnvirons compilerEnv, ErrorReporter errorReporter)
+    {
+        this.compilerEnv = compilerEnv;
+        this.errorReporter = errorReporter;
+    }
+
+    protected Decompiler createDecompiler(CompilerEnvirons compilerEnv)
+    {
+        return new Decompiler();
+    }
+
+    void addStrictWarning(String messageId, String messageArg)
+    {
+        if (compilerEnv.isStrictMode())
+            addWarning(messageId, messageArg);
+    }
+
+    void addWarning(String messageId, String messageArg)
+    {
+        String message = ScriptRuntime.getMessage1(messageId, messageArg);
+        if (compilerEnv.reportWarningAsError()) {
+            ++syntaxErrorCount;
+            errorReporter.error(message, sourceURI, ts.getLineno(),
+                                ts.getLine(), ts.getOffset());
+        } else
+            errorReporter.warning(message, sourceURI, ts.getLineno(),
+                                  ts.getLine(), ts.getOffset());
+    }
+
+    void addError(String messageId)
+    {
+        ++syntaxErrorCount;
+        String message = ScriptRuntime.getMessage0(messageId);
+        errorReporter.error(message, sourceURI, ts.getLineno(),
+                            ts.getLine(), ts.getOffset());
+    }
+
+    void addError(String messageId, String messageArg)
+    {
+        ++syntaxErrorCount;
+        String message = ScriptRuntime.getMessage1(messageId, messageArg);
+        errorReporter.error(message, sourceURI, ts.getLineno(),
+                            ts.getLine(), ts.getOffset());
+    }
+
+    RuntimeException reportError(String messageId)
+    {
+        addError(messageId);
+
+        // Throw a ParserException exception to unwind the recursive descent
+        // parse.
+        throw new ParserException();
+    }
+
+    private int peekToken()
+        throws IOException
+    {
+        int tt = currentFlaggedToken;
+        if (tt == Token.EOF) {
+
+            while ((tt = ts.getToken()) == Token.IECC) {
+                /* Support for JScript conditional comments */
+                decompiler.addJScriptConditionalComment(ts.getString());
+            }
+
+            if (tt == Token.EOL) {
+                do {
+                    tt = ts.getToken();
+
+                    if (tt == Token.IECC) {
+                        /* Support for JScript conditional comments */
+                        decompiler.addJScriptConditionalComment(ts.getString());
+                    }
+
+                } while (tt == Token.EOL || tt == Token.IECC);
+                tt |= TI_AFTER_EOL;
+            }
+            currentFlaggedToken = tt;
+        }
+        return tt & CLEAR_TI_MASK;
+    }
+
+    private int peekFlaggedToken()
+        throws IOException
+    {
+        peekToken();
+        return currentFlaggedToken;
+    }
+
+    private void consumeToken()
+    {
+        currentFlaggedToken = Token.EOF;
+    }
+
+    private int nextToken()
+        throws IOException
+    {
+        int tt = peekToken();
+        consumeToken();
+        return tt;
+    }
+
+    private int nextFlaggedToken()
+        throws IOException
+    {
+        peekToken();
+        int ttFlagged = currentFlaggedToken;
+        consumeToken();
+        return ttFlagged;
+    }
+
+    private boolean matchToken(int toMatch)
+        throws IOException
+    {
+        int tt = peekToken();
+        if (tt != toMatch) {
+            return false;
+        }
+        consumeToken();
+        return true;
+    }
+
+    private int peekTokenOrEOL()
+        throws IOException
+    {
+        int tt = peekToken();
+        // Check for last peeked token flags
+        if ((currentFlaggedToken & TI_AFTER_EOL) != 0) {
+            tt = Token.EOL;
+        }
+        return tt;
+    }
+
+    private void setCheckForLabel()
+    {
+        if ((currentFlaggedToken & CLEAR_TI_MASK) != Token.NAME)
+            throw Kit.codeBug();
+        currentFlaggedToken |= TI_CHECK_LABEL;
+    }
+
+    private void mustMatchToken(int toMatch, String messageId)
+        throws IOException, ParserException
+    {
+        if (!matchToken(toMatch)) {
+            reportError(messageId);
+        }
+    }
+
+    private void mustHaveXML()
+    {
+        if (!compilerEnv.isXmlAvailable()) {
+            reportError("msg.XML.not.available");
+        }
+    }
+
+    public String getEncodedSource()
+    {
+        return encodedSource;
+    }
+
+    public boolean eof()
+    {
+        return ts.eof();
+    }
+
+    boolean insideFunction()
+    {
+        return nestingOfFunction != 0;
+    }
+
+    private Node enterLoop(Node loopLabel)
+    {
+        Node loop = nf.createLoopNode(loopLabel, ts.getLineno());
+        if (loopSet == null) {
+            loopSet = new ObjArray();
+            if (loopAndSwitchSet == null) {
+                loopAndSwitchSet = new ObjArray();
+            }
+        }
+        loopSet.push(loop);
+        loopAndSwitchSet.push(loop);
+        return loop;
+    }
+
+    private void exitLoop()
+    {
+        loopSet.pop();
+        loopAndSwitchSet.pop();
+    }
+
+    private Node enterSwitch(Node switchSelector, int lineno)
+    {
+        Node switchNode = nf.createSwitch(switchSelector, lineno);
+        if (loopAndSwitchSet == null) {
+            loopAndSwitchSet = new ObjArray();
+        }
+        loopAndSwitchSet.push(switchNode);
+        return switchNode;
+    }
+
+    private void exitSwitch()
+    {
+        loopAndSwitchSet.pop();
+    }
+
+    /*
+     * Build a parse tree from the given sourceString.
+     *
+     * @return an Object representing the parsed
+     * program.  If the parse fails, null will be returned.  (The
+     * parse failure will result in a call to the ErrorReporter from
+     * CompilerEnvirons.)
+     */
+    public ScriptOrFnNode parse(String sourceString,
+                                String sourceURI, int lineno)
+    {
+        this.sourceURI = sourceURI;
+        this.ts = new TokenStream(this, null, sourceString, lineno);
+        try {
+            return parse();
+        } catch (IOException ex) {
+            // Should never happen
+            throw new IllegalStateException();
+        }
+    }
+
+    /*
+     * Build a parse tree from the given sourceString.
+     *
+     * @return an Object representing the parsed
+     * program.  If the parse fails, null will be returned.  (The
+     * parse failure will result in a call to the ErrorReporter from
+     * CompilerEnvirons.)
+     */
+    public ScriptOrFnNode parse(Reader sourceReader,
+                                String sourceURI, int lineno)
+        throws IOException
+    {
+        this.sourceURI = sourceURI;
+        this.ts = new TokenStream(this, sourceReader, null, lineno);
+        return parse();
+    }
+
+    private ScriptOrFnNode parse()
+        throws IOException
+    {
+        this.decompiler = createDecompiler(compilerEnv);
+        this.nf = new IRFactory(this);
+        currentScriptOrFn = nf.createScript();
+        int sourceStartOffset = decompiler.getCurrentOffset();
+        this.encodedSource = null;
+        decompiler.addToken(Token.SCRIPT);
+
+        this.currentFlaggedToken = Token.EOF;
+        this.syntaxErrorCount = 0;
+
+        int baseLineno = ts.getLineno();  // line number where source starts
+
+        /* so we have something to add nodes to until
+         * we've collected all the source */
+        Node pn = nf.createLeaf(Token.BLOCK);
+
+        try {
+            for (;;) {
+                int tt = peekToken();
+
+                if (tt <= Token.EOF) {
+                    break;
+                }
+
+                Node n;
+                if (tt == Token.FUNCTION) {
+                    consumeToken();
+                    try {
+                        n = function(calledByCompileFunction
+                                     ? FunctionNode.FUNCTION_EXPRESSION
+                                     : FunctionNode.FUNCTION_STATEMENT);
+                    } catch (ParserException e) {
+                        break;
+                    }
+                } else {
+                    n = statement();
+                }
+                nf.addChildToBack(pn, n);
+            }
+        } catch (StackOverflowError ex) {
+            String msg = ScriptRuntime.getMessage0(
+                "msg.too.deep.parser.recursion");
+            throw Context.reportRuntimeError(msg, sourceURI,
+                                             ts.getLineno(), null, 0);
+        }
+
+        if (this.syntaxErrorCount != 0) {
+            String msg = String.valueOf(this.syntaxErrorCount);
+            msg = ScriptRuntime.getMessage1("msg.got.syntax.errors", msg);
+            throw errorReporter.runtimeError(msg, sourceURI, baseLineno,
+                                             null, 0);
+        }
+
+        currentScriptOrFn.setSourceName(sourceURI);
+        currentScriptOrFn.setBaseLineno(baseLineno);
+        currentScriptOrFn.setEndLineno(ts.getLineno());
+
+        int sourceEndOffset = decompiler.getCurrentOffset();
+        currentScriptOrFn.setEncodedSourceBounds(sourceStartOffset,
+                                                 sourceEndOffset);
+
+        nf.initScript(currentScriptOrFn, pn);
+
+        if (compilerEnv.isGeneratingSource()) {
+            encodedSource = decompiler.getEncodedSource();
+        }
+        this.decompiler = null; // It helps GC
+
+        return currentScriptOrFn;
+    }
+
+    /*
+     * The C version of this function takes an argument list,
+     * which doesn't seem to be needed for tree generation...
+     * it'd only be useful for checking argument hiding, which
+     * I'm not doing anyway...
+     */
+    private Node parseFunctionBody()
+        throws IOException
+    {
+        ++nestingOfFunction;
+        Node pn = nf.createBlock(ts.getLineno());
+        try {
+            bodyLoop: for (;;) {
+                Node n;
+                int tt = peekToken();
+                switch (tt) {
+                  case Token.ERROR:
+                  case Token.EOF:
+                  case Token.RC:
+                    break bodyLoop;
+
+                  case Token.FUNCTION:
+                    consumeToken();
+                    n = function(FunctionNode.FUNCTION_STATEMENT);
+                    break;
+                  default:
+                    n = statement();
+                    break;
+                }
+                nf.addChildToBack(pn, n);
+            }
+        } catch (ParserException e) {
+            // Ignore it
+        } finally {
+            --nestingOfFunction;
+        }
+
+        return pn;
+    }
+
+    private Node function(int functionType)
+        throws IOException, ParserException
+    {
+        int syntheticType = functionType;
+        int baseLineno = ts.getLineno();  // line number where source starts
+
+        int functionSourceStart = decompiler.markFunctionStart(functionType);
+        String name;
+        Node memberExprNode = null;
+        if (matchToken(Token.NAME)) {
+            name = ts.getString();
+            decompiler.addName(name);
+            if (!matchToken(Token.LP)) {
+                if (compilerEnv.isAllowMemberExprAsFunctionName()) {
+                    // Extension to ECMA: if 'function <name>' does not follow
+                    // by '(', assume <name> starts memberExpr
+                    Node memberExprHead = nf.createName(name);
+                    name = "";
+                    memberExprNode = memberExprTail(false, memberExprHead);
+                }
+                mustMatchToken(Token.LP, "msg.no.paren.parms");
+            }
+        } else if (matchToken(Token.LP)) {
+            // Anonymous function
+            name = "";
+        } else {
+            name = "";
+            if (compilerEnv.isAllowMemberExprAsFunctionName()) {
+                // Note that memberExpr can not start with '(' like
+                // in function (1+2).toString(), because 'function (' already
+                // processed as anonymous function
+                memberExprNode = memberExpr(false);
+            }
+            mustMatchToken(Token.LP, "msg.no.paren.parms");
+        }
+
+        if (memberExprNode != null) {
+            syntheticType = FunctionNode.FUNCTION_EXPRESSION;
+        }
+
+        boolean nested = insideFunction();
+
+        FunctionNode fnNode = nf.createFunction(name);
+        if (nested || nestingOfWith > 0) {
+            // 1. Nested functions are not affected by the dynamic scope flag
+            // as dynamic scope is already a parent of their scope.
+            // 2. Functions defined under the with statement also immune to
+            // this setup, in which case dynamic scope is ignored in favor
+            // of with object.
+            fnNode.itsIgnoreDynamicScope = true;
+        }
+
+        int functionIndex = currentScriptOrFn.addFunction(fnNode);
+
+        int functionSourceEnd;
+
+        ScriptOrFnNode savedScriptOrFn = currentScriptOrFn;
+        currentScriptOrFn = fnNode;
+        int savedNestingOfWith = nestingOfWith;
+        nestingOfWith = 0;
+        Hashtable savedLabelSet = labelSet;
+        labelSet = null;
+        ObjArray savedLoopSet = loopSet;
+        loopSet = null;
+        ObjArray savedLoopAndSwitchSet = loopAndSwitchSet;
+        loopAndSwitchSet = null;
+        boolean savedHasReturnValue = hasReturnValue;
+        int savedFunctionEndFlags = functionEndFlags;
+
+        Node body;
+        try {
+            decompiler.addToken(Token.LP);
+            if (!matchToken(Token.RP)) {
+                boolean first = true;
+                do {
+                    if (!first)
+                        decompiler.addToken(Token.COMMA);
+                    first = false;
+                    mustMatchToken(Token.NAME, "msg.no.parm");
+                    String s = ts.getString();
+                    if (fnNode.hasParamOrVar(s)) {
+                        addWarning("msg.dup.parms", s);
+                    }
+                    fnNode.addParam(s);
+                    decompiler.addName(s);
+                } while (matchToken(Token.COMMA));
+
+                mustMatchToken(Token.RP, "msg.no.paren.after.parms");
+            }
+            decompiler.addToken(Token.RP);
+
+            mustMatchToken(Token.LC, "msg.no.brace.body");
+            decompiler.addEOL(Token.LC);
+            body = parseFunctionBody();
+            mustMatchToken(Token.RC, "msg.no.brace.after.body");
+
+            if (compilerEnv.isStrictMode() && !body.hasConsistentReturnUsage())
+            {
+              String msg = name.length() > 0 ? "msg.no.return.value"
+                                             : "msg.anon.no.return.value";
+              addStrictWarning(msg, name);
+            }
+
+            decompiler.addToken(Token.RC);
+            functionSourceEnd = decompiler.markFunctionEnd(functionSourceStart);
+            if (functionType != FunctionNode.FUNCTION_EXPRESSION) {
+                // Add EOL only if function is not part of expression
+                // since it gets SEMI + EOL from Statement in that case
+                decompiler.addToken(Token.EOL);
+            }
+        }
+        finally {
+            hasReturnValue = savedHasReturnValue;
+            functionEndFlags = savedFunctionEndFlags;
+            loopAndSwitchSet = savedLoopAndSwitchSet;
+            loopSet = savedLoopSet;
+            labelSet = savedLabelSet;
+            nestingOfWith = savedNestingOfWith;
+            currentScriptOrFn = savedScriptOrFn;
+        }
+
+        fnNode.setEncodedSourceBounds(functionSourceStart, functionSourceEnd);
+        fnNode.setSourceName(sourceURI);
+        fnNode.setBaseLineno(baseLineno);
+        fnNode.setEndLineno(ts.getLineno());
+
+        if (name != null) {
+          int index = currentScriptOrFn.getParamOrVarIndex(name);
+          if (index >= 0 && index < currentScriptOrFn.getParamCount())
+            addStrictWarning("msg.var.hides.arg", name);
+        }
+
+        Node pn = nf.initFunction(fnNode, functionIndex, body, syntheticType);
+        if (memberExprNode != null) {
+            pn = nf.createAssignment(Token.ASSIGN, memberExprNode, pn);
+            if (functionType != FunctionNode.FUNCTION_EXPRESSION) {
+                // XXX check JScript behavior: should it be createExprStatement?
+                pn = nf.createExprStatementNoReturn(pn, baseLineno);
+            }
+        }
+        return pn;
+    }
+
+    private Node statements()
+        throws IOException
+    {
+        Node pn = nf.createBlock(ts.getLineno());
+
+        int tt;
+        while((tt = peekToken()) > Token.EOF && tt != Token.RC) {
+            nf.addChildToBack(pn, statement());
+        }
+
+        return pn;
+    }
+
+    private Node condition()
+        throws IOException, ParserException
+    {
+        mustMatchToken(Token.LP, "msg.no.paren.cond");
+        decompiler.addToken(Token.LP);
+        Node pn = expr(false);
+        mustMatchToken(Token.RP, "msg.no.paren.after.cond");
+        decompiler.addToken(Token.RP);
+
+        // Report strict warning on code like "if (a = 7) ...". Suppress the
+        // warning if the condition is parenthesized, like "if ((a = 7)) ...".
+        if (pn.getProp(Node.PARENTHESIZED_PROP) == null &&
+            (pn.getType() == Token.SETNAME || pn.getType() == Token.SETPROP ||
+             pn.getType() == Token.SETELEM))
+        {
+            addStrictWarning("msg.equal.as.assign", "");
+        }
+        return pn;
+    }
+
+    // match a NAME; return null if no match.
+    private Node matchJumpLabelName()
+        throws IOException, ParserException
+    {
+        Node label = null;
+
+        int tt = peekTokenOrEOL();
+        if (tt == Token.NAME) {
+            consumeToken();
+            String name = ts.getString();
+            decompiler.addName(name);
+            if (labelSet != null) {
+                label = (Node)labelSet.get(name);
+            }
+            if (label == null) {
+                reportError("msg.undef.label");
+            }
+        }
+
+        return label;
+    }
+
+    private Node statement()
+        throws IOException
+    {
+        try {
+            Node pn = statementHelper(null);
+            if (pn != null) {
+                if (compilerEnv.isStrictMode() && !pn.hasSideEffects())
+                    addStrictWarning("msg.no.side.effects", "");
+                return pn;
+            }
+        } catch (ParserException e) { }
+
+        // skip to end of statement
+        int lineno = ts.getLineno();
+        guessingStatementEnd: for (;;) {
+            int tt = peekTokenOrEOL();
+            consumeToken();
+            switch (tt) {
+              case Token.ERROR:
+              case Token.EOF:
+              case Token.EOL:
+              case Token.SEMI:
+                break guessingStatementEnd;
+            }
+        }
+        return nf.createExprStatement(nf.createName("error"), lineno);
+    }
+
+    /**
+     * Whether the "catch (e: e instanceof Exception) { ... }" syntax
+     * is implemented.
+     */
+
+    private Node statementHelper(Node statementLabel)
+        throws IOException, ParserException
+    {
+        Node pn = null;
+
+        int tt;
+
+        tt = peekToken();
+
+        switch(tt) {
+          case Token.IF: {
+            consumeToken();
+
+            decompiler.addToken(Token.IF);
+            int lineno = ts.getLineno();
+            Node cond = condition();
+            decompiler.addEOL(Token.LC);
+            Node ifTrue = statement();
+            Node ifFalse = null;
+            if (matchToken(Token.ELSE)) {
+                decompiler.addToken(Token.RC);
+                decompiler.addToken(Token.ELSE);
+                decompiler.addEOL(Token.LC);
+                ifFalse = statement();
+            }
+            decompiler.addEOL(Token.RC);
+            pn = nf.createIf(cond, ifTrue, ifFalse, lineno);
+            return pn;
+          }
+
+          case Token.SWITCH: {
+            consumeToken();
+
+            decompiler.addToken(Token.SWITCH);
+            int lineno = ts.getLineno();
+            mustMatchToken(Token.LP, "msg.no.paren.switch");
+            decompiler.addToken(Token.LP);
+            pn = enterSwitch(expr(false), lineno);
+            try {
+                mustMatchToken(Token.RP, "msg.no.paren.after.switch");
+                decompiler.addToken(Token.RP);
+                mustMatchToken(Token.LC, "msg.no.brace.switch");
+                decompiler.addEOL(Token.LC);
+
+                boolean hasDefault = false;
+                switchLoop: for (;;) {
+                    tt = nextToken();
+                    Node caseExpression;
+                    switch (tt) {
+                      case Token.RC:
+                        break switchLoop;
+
+                      case Token.CASE:
+                        decompiler.addToken(Token.CASE);
+                        caseExpression = expr(false);
+                        mustMatchToken(Token.COLON, "msg.no.colon.case");
+                        decompiler.addEOL(Token.COLON);
+                        break;
+
+                      case Token.DEFAULT:
+                        if (hasDefault) {
+                            reportError("msg.double.switch.default");
+                        }
+                        decompiler.addToken(Token.DEFAULT);
+                        hasDefault = true;
+                        caseExpression = null;
+                        mustMatchToken(Token.COLON, "msg.no.colon.case");
+                        decompiler.addEOL(Token.COLON);
+                        break;
+
+                      default:
+                        reportError("msg.bad.switch");
+                        break switchLoop;
+                    }
+
+                    Node block = nf.createLeaf(Token.BLOCK);
+                    while ((tt = peekToken()) != Token.RC
+                           && tt != Token.CASE
+                           && tt != Token.DEFAULT
+                           && tt != Token.EOF)
+                    {
+                        nf.addChildToBack(block, statement());
+                    }
+
+                    // caseExpression == null => add default lable
+                    nf.addSwitchCase(pn, caseExpression, block);
+                }
+                decompiler.addEOL(Token.RC);
+                nf.closeSwitch(pn);
+            } finally {
+                exitSwitch();
+            }
+            return pn;
+          }
+
+          case Token.WHILE: {
+            consumeToken();
+            decompiler.addToken(Token.WHILE);
+
+            Node loop = enterLoop(statementLabel);
+            try {
+                Node cond = condition();
+                decompiler.addEOL(Token.LC);
+                Node body = statement();
+                decompiler.addEOL(Token.RC);
+                pn = nf.createWhile(loop, cond, body);
+            } finally {
+                exitLoop();
+            }
+            return pn;
+          }
+
+          case Token.DO: {
+            consumeToken();
+            decompiler.addToken(Token.DO);
+            decompiler.addEOL(Token.LC);
+
+            Node loop = enterLoop(statementLabel);
+            try {
+                Node body = statement();
+                decompiler.addToken(Token.RC);
+                mustMatchToken(Token.WHILE, "msg.no.while.do");
+                decompiler.addToken(Token.WHILE);
+                Node cond = condition();
+                pn = nf.createDoWhile(loop, body, cond);
+            } finally {
+                exitLoop();
+            }
+            // Always auto-insert semicon to follow SpiderMonkey:
+            // It is required by EMAScript but is ignored by the rest of
+            // world, see bug 238945
+            matchToken(Token.SEMI);
+            decompiler.addEOL(Token.SEMI);
+            return pn;
+          }
+
+          case Token.FOR: {
+            consumeToken();
+            boolean isForEach = false;
+            decompiler.addToken(Token.FOR);
+
+            Node loop = enterLoop(statementLabel);
+            try {
+
+                Node init;  // Node init is also foo in 'foo in Object'
+                Node cond;  // Node cond is also object in 'foo in Object'
+                Node incr = null; // to kill warning
+                Node body;
+
+                // See if this is a for each () instead of just a for ()
+                if (matchToken(Token.NAME)) {
+                    decompiler.addName(ts.getString());
+                    if (ts.getString().equals("each")) {
+                        isForEach = true;
+                    } else {
+                        reportError("msg.no.paren.for");
+                    }
+                }
+
+                mustMatchToken(Token.LP, "msg.no.paren.for");
+                decompiler.addToken(Token.LP);
+                tt = peekToken();
+                if (tt == Token.SEMI) {
+                    init = nf.createLeaf(Token.EMPTY);
+                } else {
+                    if (tt == Token.VAR) {
+                        // set init to a var list or initial
+                        consumeToken();    // consume the 'var' token
+                        init = variables(Token.FOR);
+                    }
+                    else {
+                        init = expr(true);
+                    }
+                }
+
+                if (matchToken(Token.IN)) {
+                    decompiler.addToken(Token.IN);
+                    // 'cond' is the object over which we're iterating
+                    cond = expr(false);
+                } else {  // ordinary for loop
+                    mustMatchToken(Token.SEMI, "msg.no.semi.for");
+                    decompiler.addToken(Token.SEMI);
+                    if (peekToken() == Token.SEMI) {
+                        // no loop condition
+                        cond = nf.createLeaf(Token.EMPTY);
+                    } else {
+                        cond = expr(false);
+                    }
+
+                    mustMatchToken(Token.SEMI, "msg.no.semi.for.cond");
+                    decompiler.addToken(Token.SEMI);
+                    if (peekToken() == Token.RP) {
+                        incr = nf.createLeaf(Token.EMPTY);
+                    } else {
+                        incr = expr(false);
+                    }
+                }
+
+                mustMatchToken(Token.RP, "msg.no.paren.for.ctrl");
+                decompiler.addToken(Token.RP);
+                decompiler.addEOL(Token.LC);
+                body = statement();
+                decompiler.addEOL(Token.RC);
+
+                if (incr == null) {
+                    // cond could be null if 'in obj' got eaten
+                    // by the init node.
+                    pn = nf.createForIn(loop, init, cond, body, isForEach);
+                } else {
+                    pn = nf.createFor(loop, init, cond, incr, body);
+                }
+            } finally {
+                exitLoop();
+            }
+            return pn;
+          }
+
+          case Token.TRY: {
+            consumeToken();
+            int lineno = ts.getLineno();
+
+            Node tryblock;
+            Node catchblocks = null;
+            Node finallyblock = null;
+
+            decompiler.addToken(Token.TRY);
+            decompiler.addEOL(Token.LC);
+            tryblock = statement();
+            decompiler.addEOL(Token.RC);
+
+            catchblocks = nf.createLeaf(Token.BLOCK);
+
+            boolean sawDefaultCatch = false;
+            int peek = peekToken();
+            if (peek == Token.CATCH) {
+                while (matchToken(Token.CATCH)) {
+                    if (sawDefaultCatch) {
+                        reportError("msg.catch.unreachable");
+                    }
+                    decompiler.addToken(Token.CATCH);
+                    mustMatchToken(Token.LP, "msg.no.paren.catch");
+                    decompiler.addToken(Token.LP);
+
+                    mustMatchToken(Token.NAME, "msg.bad.catchcond");
+                    String varName = ts.getString();
+                    decompiler.addName(varName);
+
+                    Node catchCond = null;
+                    if (matchToken(Token.IF)) {
+                        decompiler.addToken(Token.IF);
+                        catchCond = expr(false);
+                    } else {
+                        sawDefaultCatch = true;
+                    }
+
+                    mustMatchToken(Token.RP, "msg.bad.catchcond");
+                    decompiler.addToken(Token.RP);
+                    mustMatchToken(Token.LC, "msg.no.brace.catchblock");
+                    decompiler.addEOL(Token.LC);
+
+                    nf.addChildToBack(catchblocks,
+                        nf.createCatch(varName, catchCond,
+                                       statements(),
+                                       ts.getLineno()));
+
+                    mustMatchToken(Token.RC, "msg.no.brace.after.body");
+                    decompiler.addEOL(Token.RC);
+                }
+            } else if (peek != Token.FINALLY) {
+                mustMatchToken(Token.FINALLY, "msg.try.no.catchfinally");
+            }
+
+            if (matchToken(Token.FINALLY)) {
+                decompiler.addToken(Token.FINALLY);
+                decompiler.addEOL(Token.LC);
+                finallyblock = statement();
+                decompiler.addEOL(Token.RC);
+            }
+
+            pn = nf.createTryCatchFinally(tryblock, catchblocks,
+                                          finallyblock, lineno);
+
+            return pn;
+          }
+
+          case Token.THROW: {
+            consumeToken();
+            if (peekTokenOrEOL() == Token.EOL) {
+                // ECMAScript does not allow new lines before throw expression,
+                // see bug 256617
+                reportError("msg.bad.throw.eol");
+            }
+
+            int lineno = ts.getLineno();
+            decompiler.addToken(Token.THROW);
+            pn = nf.createThrow(expr(false), lineno);
+            break;
+          }
+
+          case Token.BREAK: {
+            consumeToken();
+            int lineno = ts.getLineno();
+
+            decompiler.addToken(Token.BREAK);
+
+            // matchJumpLabelName only matches if there is one
+            Node breakStatement = matchJumpLabelName();
+            if (breakStatement == null) {
+                if (loopAndSwitchSet == null || loopAndSwitchSet.size() == 0) {
+                    reportError("msg.bad.break");
+                    return null;
+                }
+                breakStatement = (Node)loopAndSwitchSet.peek();
+            }
+            pn = nf.createBreak(breakStatement, lineno);
+            break;
+          }
+
+          case Token.CONTINUE: {
+            consumeToken();
+            int lineno = ts.getLineno();
+
+            decompiler.addToken(Token.CONTINUE);
+
+            Node loop;
+            // matchJumpLabelName only matches if there is one
+            Node label = matchJumpLabelName();
+            if (label == null) {
+                if (loopSet == null || loopSet.size() == 0) {
+                    reportError("msg.continue.outside");
+                    return null;
+                }
+                loop = (Node)loopSet.peek();
+            } else {
+                loop = nf.getLabelLoop(label);
+                if (loop == null) {
+                    reportError("msg.continue.nonloop");
+                    return null;
+                }
+            }
+            pn = nf.createContinue(loop, lineno);
+            break;
+          }
+
+          case Token.WITH: {
+            consumeToken();
+
+            decompiler.addToken(Token.WITH);
+            int lineno = ts.getLineno();
+            mustMatchToken(Token.LP, "msg.no.paren.with");
+            decompiler.addToken(Token.LP);
+            Node obj = expr(false);
+            mustMatchToken(Token.RP, "msg.no.paren.after.with");
+            decompiler.addToken(Token.RP);
+            decompiler.addEOL(Token.LC);
+
+            ++nestingOfWith;
+            Node body;
+            try {
+                body = statement();
+            } finally {
+                --nestingOfWith;
+            }
+
+            decompiler.addEOL(Token.RC);
+
+            pn = nf.createWith(obj, body, lineno);
+            return pn;
+          }
+
+          case Token.CONST:
+          case Token.VAR: {
+            consumeToken();
+            pn = variables(tt);
+            break;
+          }
+
+          case Token.RETURN: {
+            if (!insideFunction()) {
+                reportError("msg.bad.return");
+            }
+            consumeToken();
+            decompiler.addToken(Token.RETURN);
+            int lineno = ts.getLineno();
+
+            Node retExpr;
+            /* This is ugly, but we don't want to require a semicolon. */
+            tt = peekTokenOrEOL();
+            switch (tt) {
+              case Token.SEMI:
+              case Token.RC:
+              case Token.EOF:
+              case Token.EOL:
+              case Token.ERROR:
+                retExpr = null;
+                break;
+              default:
+                retExpr = expr(false);
+                hasReturnValue = true;
+            }
+            pn = nf.createReturn(retExpr, lineno);
+
+            // see if we need a strict mode warning
+            if (retExpr == null) {
+                if (functionEndFlags == Node.END_RETURNS_VALUE)
+                    addStrictWarning("msg.return.inconsistent", "");
+
+                functionEndFlags |= Node.END_RETURNS;
+            } else {
+                if (functionEndFlags == Node.END_RETURNS)
+                    addStrictWarning("msg.return.inconsistent", "");
+
+                functionEndFlags |= Node.END_RETURNS_VALUE;
+            }
+
+            break;
+          }
+
+          case Token.LC:
+            consumeToken();
+            if (statementLabel != null) {
+                decompiler.addToken(Token.LC);
+            }
+            pn = statements();
+            mustMatchToken(Token.RC, "msg.no.brace.block");
+            if (statementLabel != null) {
+                decompiler.addEOL(Token.RC);
+            }
+            return pn;
+
+          case Token.ERROR:
+            // Fall thru, to have a node for error recovery to work on
+          case Token.SEMI:
+            consumeToken();
+            pn = nf.createLeaf(Token.EMPTY);
+            return pn;
+
+          case Token.FUNCTION: {
+            consumeToken();
+            pn = function(FunctionNode.FUNCTION_EXPRESSION_STATEMENT);
+            return pn;
+          }
+
+          case Token.DEFAULT :
+            consumeToken();
+            mustHaveXML();
+
+            decompiler.addToken(Token.DEFAULT);
+            int nsLine = ts.getLineno();
+
+            if (!(matchToken(Token.NAME)
+                  && ts.getString().equals("xml")))
+            {
+                reportError("msg.bad.namespace");
+            }
+            decompiler.addName(" xml");
+
+            if (!(matchToken(Token.NAME)
+                  && ts.getString().equals("namespace")))
+            {
+                reportError("msg.bad.namespace");
+            }
+            decompiler.addName(" namespace");
+
+            if (!matchToken(Token.ASSIGN)) {
+                reportError("msg.bad.namespace");
+            }
+            decompiler.addToken(Token.ASSIGN);
+
+            Node expr = expr(false);
+            pn = nf.createDefaultNamespace(expr, nsLine);
+            break;
+
+          case Token.NAME: {
+            int lineno = ts.getLineno();
+            String name = ts.getString();
+            setCheckForLabel();
+            pn = expr(false);
+            if (pn.getType() != Token.LABEL) {
+                pn = nf.createExprStatement(pn, lineno);
+            } else {
+                // Parsed the label: push back token should be
+                // colon that primaryExpr left untouched.
+                if (peekToken() != Token.COLON) Kit.codeBug();
+                consumeToken();
+                // depend on decompiling lookahead to guess that that
+                // last name was a label.
+                decompiler.addName(name);
+                decompiler.addEOL(Token.COLON);
+
+                if (labelSet == null) {
+                    labelSet = new Hashtable();
+                } else if (labelSet.containsKey(name)) {
+                    reportError("msg.dup.label");
+                }
+
+                boolean firstLabel;
+                if (statementLabel == null) {
+                    firstLabel = true;
+                    statementLabel = pn;
+                } else {
+                    // Discard multiple label nodes and use only
+                    // the first: it allows to simplify IRFactory
+                    firstLabel = false;
+                }
+                labelSet.put(name, statementLabel);
+                try {
+                    pn = statementHelper(statementLabel);
+                } finally {
+                    labelSet.remove(name);
+                }
+                if (firstLabel) {
+                    pn = nf.createLabeledStatement(statementLabel, pn);
+                }
+                return pn;
+            }
+            break;
+          }
+
+          default: {
+            int lineno = ts.getLineno();
+            pn = expr(false);
+            pn = nf.createExprStatement(pn, lineno);
+            break;
+          }
+        }
+
+        int ttFlagged = peekFlaggedToken();
+        switch (ttFlagged & CLEAR_TI_MASK) {
+          case Token.SEMI:
+            // Consume ';' as a part of expression
+            consumeToken();
+            break;
+          case Token.ERROR:
+          case Token.EOF:
+          case Token.RC:
+            // Autoinsert ;
+            break;
+          default:
+            if ((ttFlagged & TI_AFTER_EOL) == 0) {
+                // Report error if no EOL or autoinsert ; otherwise
+                reportError("msg.no.semi.stmt");
+            }
+            break;
+        }
+        decompiler.addEOL(Token.SEMI);
+
+        return pn;
+    }
+
+    /**
+     * Parse a 'var' or 'const' statement, or a 'var' init list in a for
+     * statement.
+     * @param context A token value: either VAR, CONST or FOR depending on
+     * context.
+     * @return The parsed statement
+     * @throws IOException
+     * @throws ParserException
+     */
+    private Node variables(int context)
+        throws IOException, ParserException
+    {
+        Node pn;
+        boolean first = true;
+
+        if (context == Token.CONST){
+            pn = nf.createVariables(Token.CONST, ts.getLineno());
+            decompiler.addToken(Token.CONST);
+        } else {
+            pn = nf.createVariables(Token.VAR, ts.getLineno());
+            decompiler.addToken(Token.VAR);
+        }
+
+        for (;;) {
+            Node name;
+            Node init;
+            mustMatchToken(Token.NAME, "msg.bad.var");
+            String s = ts.getString();
+
+            if (!first)
+                decompiler.addToken(Token.COMMA);
+            first = false;
+
+            decompiler.addName(s);
+
+            if (context == Token.CONST) {
+                if (!currentScriptOrFn.addConst(s)) {
+                    // We know it's already defined, since addConst passes if
+                    // it's not defined at all.  The addVar call just confirms
+                    // what it is.
+                    if (currentScriptOrFn.addVar(s) != ScriptOrFnNode.DUPLICATE_CONST)
+                        addError("msg.var.redecl", s);
+                    else
+                        addError("msg.const.redecl", s);
+                }
+            } else {
+                int dupState = currentScriptOrFn.addVar(s);
+                if (dupState == ScriptOrFnNode.DUPLICATE_CONST)
+                    addError("msg.const.redecl", s);
+                else if (dupState == ScriptOrFnNode.DUPLICATE_PARAMETER)
+                    addStrictWarning("msg.var.hides.arg", s);
+                else if (dupState == ScriptOrFnNode.DUPLICATE_VAR)
+                    addStrictWarning("msg.var.redecl", s);
+            }
+            name = nf.createName(s);
+
+            // omitted check for argument hiding
+
+            if (matchToken(Token.ASSIGN)) {
+                decompiler.addToken(Token.ASSIGN);
+
+                init = assignExpr(context == Token.FOR);
+                nf.addChildToBack(name, init);
+            }
+            nf.addChildToBack(pn, name);
+            if (!matchToken(Token.COMMA))
+                break;
+        }
+        return pn;
+    }
+
+    private Node expr(boolean inForInit)
+        throws IOException, ParserException
+    {
+        Node pn = assignExpr(inForInit);
+        while (matchToken(Token.COMMA)) {
+            decompiler.addToken(Token.COMMA);
+            if (compilerEnv.isStrictMode() && !pn.hasSideEffects())
+                addStrictWarning("msg.no.side.effects", "");
+            pn = nf.createBinary(Token.COMMA, pn, assignExpr(inForInit));
+        }
+        return pn;
+    }
+
+    private Node assignExpr(boolean inForInit)
+        throws IOException, ParserException
+    {
+        Node pn = condExpr(inForInit);
+
+        int tt = peekToken();
+        if (Token.FIRST_ASSIGN <= tt && tt <= Token.LAST_ASSIGN) {
+            consumeToken();
+            decompiler.addToken(tt);
+            pn = nf.createAssignment(tt, pn, assignExpr(inForInit));
+        }
+
+        return pn;
+    }
+
+    private Node condExpr(boolean inForInit)
+        throws IOException, ParserException
+    {
+        Node pn = orExpr(inForInit);
+
+        if (matchToken(Token.HOOK)) {
+            decompiler.addToken(Token.HOOK);
+            Node ifTrue = assignExpr(false);
+            mustMatchToken(Token.COLON, "msg.no.colon.cond");
+            decompiler.addToken(Token.COLON);
+            Node ifFalse = assignExpr(inForInit);
+            return nf.createCondExpr(pn, ifTrue, ifFalse);
+        }
+
+        return pn;
+    }
+
+    private Node orExpr(boolean inForInit)
+        throws IOException, ParserException
+    {
+        Node pn = andExpr(inForInit);
+        if (matchToken(Token.OR)) {
+            decompiler.addToken(Token.OR);
+            pn = nf.createBinary(Token.OR, pn, orExpr(inForInit));
+        }
+
+        return pn;
+    }
+
+    private Node andExpr(boolean inForInit)
+        throws IOException, ParserException
+    {
+        Node pn = bitOrExpr(inForInit);
+        if (matchToken(Token.AND)) {
+            decompiler.addToken(Token.AND);
+            pn = nf.createBinary(Token.AND, pn, andExpr(inForInit));
+        }
+
+        return pn;
+    }
+
+    private Node bitOrExpr(boolean inForInit)
+        throws IOException, ParserException
+    {
+        Node pn = bitXorExpr(inForInit);
+        while (matchToken(Token.BITOR)) {
+            decompiler.addToken(Token.BITOR);
+            pn = nf.createBinary(Token.BITOR, pn, bitXorExpr(inForInit));
+        }
+        return pn;
+    }
+
+    private Node bitXorExpr(boolean inForInit)
+        throws IOException, ParserException
+    {
+        Node pn = bitAndExpr(inForInit);
+        while (matchToken(Token.BITXOR)) {
+            decompiler.addToken(Token.BITXOR);
+            pn = nf.createBinary(Token.BITXOR, pn, bitAndExpr(inForInit));
+        }
+        return pn;
+    }
+
+    private Node bitAndExpr(boolean inForInit)
+        throws IOException, ParserException
+    {
+        Node pn = eqExpr(inForInit);
+        while (matchToken(Token.BITAND)) {
+            decompiler.addToken(Token.BITAND);
+            pn = nf.createBinary(Token.BITAND, pn, eqExpr(inForInit));
+        }
+        return pn;
+    }
+
+    private Node eqExpr(boolean inForInit)
+        throws IOException, ParserException
+    {
+        Node pn = relExpr(inForInit);
+        for (;;) {
+            int tt = peekToken();
+            switch (tt) {
+              case Token.EQ:
+              case Token.NE:
+              case Token.SHEQ:
+              case Token.SHNE:
+                consumeToken();
+                int decompilerToken = tt;
+                int parseToken = tt;
+                if (compilerEnv.getLanguageVersion() == Context.VERSION_1_2) {
+                    // JavaScript 1.2 uses shallow equality for == and != .
+                    // In addition, convert === and !== for decompiler into
+                    // == and != since the decompiler is supposed to show
+                    // canonical source and in 1.2 ===, !== are allowed
+                    // only as an alias to ==, !=.
+                    switch (tt) {
+                      case Token.EQ:
+                        parseToken = Token.SHEQ;
+                        break;
+                      case Token.NE:
+                        parseToken = Token.SHNE;
+                        break;
+                      case Token.SHEQ:
+                        decompilerToken = Token.EQ;
+                        break;
+                      case Token.SHNE:
+                        decompilerToken = Token.NE;
+                        break;
+                    }
+                }
+                decompiler.addToken(decompilerToken);
+                pn = nf.createBinary(parseToken, pn, relExpr(inForInit));
+                continue;
+            }
+            break;
+        }
+        return pn;
+    }
+
+    private Node relExpr(boolean inForInit)
+        throws IOException, ParserException
+    {
+        Node pn = shiftExpr();
+        for (;;) {
+            int tt = peekToken();
+            switch (tt) {
+              case Token.IN:
+                if (inForInit)
+                    break;
+                // fall through
+              case Token.INSTANCEOF:
+              case Token.LE:
+              case Token.LT:
+              case Token.GE:
+              case Token.GT:
+                consumeToken();
+                decompiler.addToken(tt);
+                pn = nf.createBinary(tt, pn, shiftExpr());
+                continue;
+            }
+            break;
+        }
+        return pn;
+    }
+
+    private Node shiftExpr()
+        throws IOException, ParserException
+    {
+        Node pn = addExpr();
+        for (;;) {
+            int tt = peekToken();
+            switch (tt) {
+              case Token.LSH:
+              case Token.URSH:
+              case Token.RSH:
+                consumeToken();
+                decompiler.addToken(tt);
+                pn = nf.createBinary(tt, pn, addExpr());
+                continue;
+            }
+            break;
+        }
+        return pn;
+    }
+
+    private Node addExpr()
+        throws IOException, ParserException
+    {
+        Node pn = mulExpr();
+        for (;;) {
+            int tt = peekToken();
+            if (tt == Token.ADD || tt == Token.SUB) {
+                consumeToken();
+                decompiler.addToken(tt);
+                // flushNewLines
+                pn = nf.createBinary(tt, pn, mulExpr());
+                continue;
+            }
+            break;
+        }
+
+        return pn;
+    }
+
+    private Node mulExpr()
+        throws IOException, ParserException
+    {
+        Node pn = unaryExpr();
+        for (;;) {
+            int tt = peekToken();
+            switch (tt) {
+              case Token.MUL:
+              case Token.DIV:
+              case Token.MOD:
+                consumeToken();
+                decompiler.addToken(tt);
+                pn = nf.createBinary(tt, pn, unaryExpr());
+                continue;
+            }
+            break;
+        }
+
+        return pn;
+    }
+
+    private Node unaryExpr()
+        throws IOException, ParserException
+    {
+        int tt;
+
+        tt = peekToken();
+
+        switch(tt) {
+        case Token.VOID:
+        case Token.NOT:
+        case Token.BITNOT:
+        case Token.TYPEOF:
+            consumeToken();
+            decompiler.addToken(tt);
+            return nf.createUnary(tt, unaryExpr());
+
+        case Token.ADD:
+            consumeToken();
+            // Convert to special POS token in decompiler and parse tree
+            decompiler.addToken(Token.POS);
+            return nf.createUnary(Token.POS, unaryExpr());
+
+        case Token.SUB:
+            consumeToken();
+            // Convert to special NEG token in decompiler and parse tree
+            decompiler.addToken(Token.NEG);
+            return nf.createUnary(Token.NEG, unaryExpr());
+
+        case Token.INC:
+        case Token.DEC:
+            consumeToken();
+            decompiler.addToken(tt);
+            return nf.createIncDec(tt, false, memberExpr(true));
+
+        case Token.DELPROP:
+            consumeToken();
+            decompiler.addToken(Token.DELPROP);
+            return nf.createUnary(Token.DELPROP, unaryExpr());
+
+        case Token.ERROR:
+            consumeToken();
+            break;
+
+        // XML stream encountered in expression.
+        case Token.LT:
+            if (compilerEnv.isXmlAvailable()) {
+                consumeToken();
+                Node pn = xmlInitializer();
+                return memberExprTail(true, pn);
+            }
+            // Fall thru to the default handling of RELOP
+
+        default:
+            Node pn = memberExpr(true);
+
+            // Don't look across a newline boundary for a postfix incop.
+            tt = peekTokenOrEOL();
+            if (tt == Token.INC || tt == Token.DEC) {
+                consumeToken();
+                decompiler.addToken(tt);
+                return nf.createIncDec(tt, true, pn);
+            }
+            return pn;
+        }
+        return nf.createName("err"); // Only reached on error.  Try to continue.
+
+    }
+
+    private Node xmlInitializer() throws IOException
+    {
+        int tt = ts.getFirstXMLToken();
+        if (tt != Token.XML && tt != Token.XMLEND) {
+            reportError("msg.syntax");
+            return null;
+        }
+
+        /* Make a NEW node to append to. */
+        Node pnXML = nf.createLeaf(Token.NEW);
+
+        String xml = ts.getString();
+        boolean fAnonymous = xml.trim().startsWith("<>");
+
+        Node pn = nf.createName(fAnonymous ? "XMLList" : "XML");
+        nf.addChildToBack(pnXML, pn);
+
+        pn = null;
+        Node expr;
+        for (;;tt = ts.getNextXMLToken()) {
+            switch (tt) {
+            case Token.XML:
+                xml = ts.getString();
+                decompiler.addName(xml);
+                mustMatchToken(Token.LC, "msg.syntax");
+                decompiler.addToken(Token.LC);
+                expr = (peekToken() == Token.RC)
+                    ? nf.createString("")
+                    : expr(false);
+                mustMatchToken(Token.RC, "msg.syntax");
+                decompiler.addToken(Token.RC);
+                if (pn == null) {
+                    pn = nf.createString(xml);
+                } else {
+                    pn = nf.createBinary(Token.ADD, pn, nf.createString(xml));
+                }
+                if (ts.isXMLAttribute()) {
+                    /* Need to put the result in double quotes */
+                    expr = nf.createUnary(Token.ESCXMLATTR, expr);
+                    Node prepend = nf.createBinary(Token.ADD,
+                                                   nf.createString("\""),
+                                                   expr);
+                    expr = nf.createBinary(Token.ADD,
+                                           prepend,
+                                           nf.createString("\""));
+                } else {
+                    expr = nf.createUnary(Token.ESCXMLTEXT, expr);
+                }
+                pn = nf.createBinary(Token.ADD, pn, expr);
+                break;
+            case Token.XMLEND:
+                xml = ts.getString();
+                decompiler.addName(xml);
+                if (pn == null) {
+                    pn = nf.createString(xml);
+                } else {
+                    pn = nf.createBinary(Token.ADD, pn, nf.createString(xml));
+                }
+
+                nf.addChildToBack(pnXML, pn);
+                return pnXML;
+            default:
+                reportError("msg.syntax");
+                return null;
+            }
+        }
+    }
+
+    private void argumentList(Node listNode)
+        throws IOException, ParserException
+    {
+        boolean matched;
+        matched = matchToken(Token.RP);
+        if (!matched) {
+            boolean first = true;
+            do {
+                if (!first)
+                    decompiler.addToken(Token.COMMA);
+                first = false;
+                nf.addChildToBack(listNode, assignExpr(false));
+            } while (matchToken(Token.COMMA));
+
+            mustMatchToken(Token.RP, "msg.no.paren.arg");
+        }
+        decompiler.addToken(Token.RP);
+    }
+
+    private Node memberExpr(boolean allowCallSyntax)
+        throws IOException, ParserException
+    {
+        int tt;
+
+        Node pn;
+
+        /* Check for new expressions. */
+        tt = peekToken();
+        if (tt == Token.NEW) {
+            /* Eat the NEW token. */
+            consumeToken();
+            decompiler.addToken(Token.NEW);
+
+            /* Make a NEW node to append to. */
+            pn = nf.createCallOrNew(Token.NEW, memberExpr(false));
+
+            if (matchToken(Token.LP)) {
+                decompiler.addToken(Token.LP);
+                /* Add the arguments to pn, if any are supplied. */
+                argumentList(pn);
+            }
+
+            /* XXX there's a check in the C source against
+             * "too many constructor arguments" - how many
+             * do we claim to support?
+             */
+
+            /* Experimental syntax:  allow an object literal to follow a new expression,
+             * which will mean a kind of anonymous class built with the JavaAdapter.
+             * the object literal will be passed as an additional argument to the constructor.
+             */
+            tt = peekToken();
+            if (tt == Token.LC) {
+                nf.addChildToBack(pn, primaryExpr());
+            }
+        } else {
+            pn = primaryExpr();
+        }
+
+        return memberExprTail(allowCallSyntax, pn);
+    }
+
+    private Node memberExprTail(boolean allowCallSyntax, Node pn)
+        throws IOException, ParserException
+    {
+      tailLoop:
+        for (;;) {
+            int tt = peekToken();
+            switch (tt) {
+
+              case Token.DOT:
+              case Token.DOTDOT:
+                {
+                    int memberTypeFlags;
+                    String s;
+
+                    consumeToken();
+                    decompiler.addToken(tt);
+                    memberTypeFlags = 0;
+                    if (tt == Token.DOTDOT) {
+                        mustHaveXML();
+                        memberTypeFlags = Node.DESCENDANTS_FLAG;
+                    }
+                    if (!compilerEnv.isXmlAvailable()) {
+                        mustMatchToken(Token.NAME, "msg.no.name.after.dot");
+                        s = ts.getString();
+                        decompiler.addName(s);
+                        pn = nf.createPropertyGet(pn, null, s, memberTypeFlags);
+                        break;
+                    }
+
+                    tt = nextToken();
+                    switch (tt) {
+                      // handles: name, ns::name, ns::*, ns::[expr]
+                      case Token.NAME:
+                        s = ts.getString();
+                        decompiler.addName(s);
+                        pn = propertyName(pn, s, memberTypeFlags);
+                        break;
+
+                      // handles: *, *::name, *::*, *::[expr]
+                      case Token.MUL:
+                        decompiler.addName("*");
+                        pn = propertyName(pn, "*", memberTypeFlags);
+                        break;
+
+                      // handles: '@attr', '@ns::attr', '@ns::*', '@ns::*',
+                      //          '@::attr', '@::*', '@*', '@*::attr', '@*::*'
+                      case Token.XMLATTR:
+                        decompiler.addToken(Token.XMLATTR);
+                        pn = attributeAccess(pn, memberTypeFlags);
+                        break;
+
+                      default:
+                        reportError("msg.no.name.after.dot");
+                    }
+                }
+                break;
+
+              case Token.DOTQUERY:
+                consumeToken();
+                mustHaveXML();
+                decompiler.addToken(Token.DOTQUERY);
+                pn = nf.createDotQuery(pn, expr(false), ts.getLineno());
+                mustMatchToken(Token.RP, "msg.no.paren");
+                decompiler.addToken(Token.RP);
+                break;
+
+              case Token.LB:
+                consumeToken();
+                decompiler.addToken(Token.LB);
+                pn = nf.createElementGet(pn, null, expr(false), 0);
+                mustMatchToken(Token.RB, "msg.no.bracket.index");
+                decompiler.addToken(Token.RB);
+                break;
+
+              case Token.LP:
+                if (!allowCallSyntax) {
+                    break tailLoop;
+                }
+                consumeToken();
+                decompiler.addToken(Token.LP);
+                pn = nf.createCallOrNew(Token.CALL, pn);
+                /* Add the arguments to pn, if any are supplied. */
+                argumentList(pn);
+                break;
+
+              default:
+                break tailLoop;
+            }
+        }
+        return pn;
+    }
+
+    /*
+     * Xml attribute expression:
+     *   '@attr', '@ns::attr', '@ns::*', '@ns::*', '@*', '@*::attr', '@*::*'
+     */
+    private Node attributeAccess(Node pn, int memberTypeFlags)
+        throws IOException
+    {
+        memberTypeFlags |= Node.ATTRIBUTE_FLAG;
+        int tt = nextToken();
+
+        switch (tt) {
+          // handles: @name, @ns::name, @ns::*, @ns::[expr]
+          case Token.NAME:
+            {
+                String s = ts.getString();
+                decompiler.addName(s);
+                pn = propertyName(pn, s, memberTypeFlags);
+            }
+            break;
+
+          // handles: @*, @*::name, @*::*, @*::[expr]
+          case Token.MUL:
+            decompiler.addName("*");
+            pn = propertyName(pn, "*", memberTypeFlags);
+            break;
+
+          // handles @[expr]
+          case Token.LB:
+            decompiler.addToken(Token.LB);
+            pn = nf.createElementGet(pn, null, expr(false), memberTypeFlags);
+            mustMatchToken(Token.RB, "msg.no.bracket.index");
+            decompiler.addToken(Token.RB);
+            break;
+
+          default:
+            reportError("msg.no.name.after.xmlAttr");
+            pn = nf.createPropertyGet(pn, null, "?", memberTypeFlags);
+            break;
+        }
+
+        return pn;
+    }
+
+    /**
+     * Check if :: follows name in which case it becomes qualified name
+     */
+    private Node propertyName(Node pn, String name, int memberTypeFlags)
+        throws IOException, ParserException
+    {
+        String namespace = null;
+        if (matchToken(Token.COLONCOLON)) {
+            decompiler.addToken(Token.COLONCOLON);
+            namespace = name;
+
+            int tt = nextToken();
+            switch (tt) {
+              // handles name::name
+              case Token.NAME:
+                name = ts.getString();
+                decompiler.addName(name);
+                break;
+
+              // handles name::*
+              case Token.MUL:
+                decompiler.addName("*");
+                name = "*";
+                break;
+
+              // handles name::[expr]
+              case Token.LB:
+                decompiler.addToken(Token.LB);
+                pn = nf.createElementGet(pn, namespace, expr(false),
+                                         memberTypeFlags);
+                mustMatchToken(Token.RB, "msg.no.bracket.index");
+                decompiler.addToken(Token.RB);
+                return pn;
+
+              default:
+                reportError("msg.no.name.after.coloncolon");
+                name = "?";
+            }
+        }
+
+        pn = nf.createPropertyGet(pn, namespace, name, memberTypeFlags);
+        return pn;
+    }
+
+    private Node primaryExpr()
+        throws IOException, ParserException
+    {
+        Node pn;
+
+        int ttFlagged = nextFlaggedToken();
+        int tt = ttFlagged & CLEAR_TI_MASK;
+
+        switch(tt) {
+
+          case Token.FUNCTION:
+            return function(FunctionNode.FUNCTION_EXPRESSION);
+
+          case Token.LB: {
+            ObjArray elems = new ObjArray();
+            int skipCount = 0;
+            decompiler.addToken(Token.LB);
+            boolean after_lb_or_comma = true;
+            for (;;) {
+                tt = peekToken();
+
+                if (tt == Token.COMMA) {
+                    consumeToken();
+                    decompiler.addToken(Token.COMMA);
+                    if (!after_lb_or_comma) {
+                        after_lb_or_comma = true;
+                    } else {
+                        elems.add(null);
+                        ++skipCount;
+                    }
+                } else if (tt == Token.RB) {
+                    consumeToken();
+                    decompiler.addToken(Token.RB);
+                    break;
+                } else {
+                    if (!after_lb_or_comma) {
+                        reportError("msg.no.bracket.arg");
+                    }
+                    elems.add(assignExpr(false));
+                    after_lb_or_comma = false;
+                }
+            }
+            return nf.createArrayLiteral(elems, skipCount);
+          }
+
+          case Token.LC: {
+            ObjArray elems = new ObjArray();
+            decompiler.addToken(Token.LC);
+            if (!matchToken(Token.RC)) {
+
+                boolean first = true;
+            commaloop:
+                do {
+                    Object property;
+
+                    if (!first)
+                        decompiler.addToken(Token.COMMA);
+                    else
+                        first = false;
+
+                    tt = peekToken();
+                    switch(tt) {
+                      case Token.NAME:
+                      case Token.STRING:
+                        consumeToken();
+                        // map NAMEs to STRINGs in object literal context
+                        // but tell the decompiler the proper type
+                        String s = ts.getString();
+                        if (tt == Token.NAME) {
+                            if (s.equals("get") &&
+                                peekToken() == Token.NAME) {
+                                decompiler.addToken(Token.GET);
+                                consumeToken();
+                                s = ts.getString();
+                                decompiler.addName(s);
+                                property = ScriptRuntime.getIndexObject(s);
+                                if (!getterSetterProperty(elems, property,
+                                                          true))
+                                    break commaloop;
+                                break;
+                            } else if (s.equals("set") &&
+                                       peekToken() == Token.NAME) {
+                                decompiler.addToken(Token.SET);
+                                consumeToken();
+                                s = ts.getString();
+                                decompiler.addName(s);
+                                property = ScriptRuntime.getIndexObject(s);
+                                if (!getterSetterProperty(elems, property,
+                                                          false))
+                                    break commaloop;
+                                break;
+                            }
+                            decompiler.addName(s);
+                        } else {
+                            decompiler.addString(s);
+                        }
+                        property = ScriptRuntime.getIndexObject(s);
+                        plainProperty(elems, property);
+                        break;
+
+                      case Token.NUMBER:
+                        consumeToken();
+                        double n = ts.getNumber();
+                        decompiler.addNumber(n);
+                        property = ScriptRuntime.getIndexObject(n);
+                        plainProperty(elems, property);
+                        break;
+
+                      case Token.RC:
+                        // trailing comma is OK.
+                        break commaloop;
+                    default:
+                        reportError("msg.bad.prop");
+                        break commaloop;
+                    }
+                } while (matchToken(Token.COMMA));
+
+                mustMatchToken(Token.RC, "msg.no.brace.prop");
+            }
+            decompiler.addToken(Token.RC);
+            return nf.createObjectLiteral(elems);
+          }
+
+          case Token.LP:
+
+            /* Brendan's IR-jsparse.c makes a new node tagged with
+             * TOK_LP here... I'm not sure I understand why.  Isn't
+             * the grouping already implicit in the structure of the
+             * parse tree?  also TOK_LP is already overloaded (I
+             * think) in the C IR as 'function call.'  */
+            decompiler.addToken(Token.LP);
+            pn = expr(false);
+            pn.putProp(Node.PARENTHESIZED_PROP, Boolean.TRUE);
+            decompiler.addToken(Token.RP);
+            mustMatchToken(Token.RP, "msg.no.paren");
+            return pn;
+
+          case Token.XMLATTR:
+            mustHaveXML();
+            decompiler.addToken(Token.XMLATTR);
+            pn = attributeAccess(null, 0);
+            return pn;
+
+          case Token.NAME: {
+            String name = ts.getString();
+            if ((ttFlagged & TI_CHECK_LABEL) != 0) {
+                if (peekToken() == Token.COLON) {
+                    // Do not consume colon, it is used as unwind indicator
+                    // to return to statementHelper.
+                    // XXX Better way?
+                    return nf.createLabel(ts.getLineno());
+                }
+            }
+
+            decompiler.addName(name);
+            if (compilerEnv.isXmlAvailable()) {
+                pn = propertyName(null, name, 0);
+            } else {
+                pn = nf.createName(name);
+            }
+            return pn;
+          }
+
+          case Token.NUMBER: {
+            double n = ts.getNumber();
+            decompiler.addNumber(n);
+            return nf.createNumber(n);
+          }
+
+          case Token.STRING: {
+            String s = ts.getString();
+            decompiler.addString(s);
+            return nf.createString(s);
+          }
+
+          case Token.DIV:
+          case Token.ASSIGN_DIV: {
+            // Got / or /= which should be treated as regexp in fact
+            ts.readRegExp(tt);
+            String flags = ts.regExpFlags;
+            ts.regExpFlags = null;
+            String re = ts.getString();
+            decompiler.addRegexp(re, flags);
+            int index = currentScriptOrFn.addRegexp(re, flags);
+            return nf.createRegExp(index);
+          }
+
+          case Token.NULL:
+          case Token.THIS:
+          case Token.FALSE:
+          case Token.TRUE:
+            decompiler.addToken(tt);
+            return nf.createLeaf(tt);
+
+          case Token.RESERVED:
+            reportError("msg.reserved.id");
+            break;
+
+          case Token.ERROR:
+            /* the scanner or one of its subroutines reported the error. */
+            break;
+
+          case Token.EOF:
+            reportError("msg.unexpected.eof");
+            break;
+
+          default:
+            reportError("msg.syntax");
+            break;
+        }
+        return null;    // should never reach here
+    }
+
+    private void plainProperty(ObjArray elems, Object property)
+            throws IOException {
+        mustMatchToken(Token.COLON, "msg.no.colon.prop");
+
+        // OBJLIT is used as ':' in object literal for
+        // decompilation to solve spacing ambiguity.
+        decompiler.addToken(Token.OBJECTLIT);
+        elems.add(property);
+        elems.add(assignExpr(false));
+    }
+
+    private boolean getterSetterProperty(ObjArray elems, Object property,
+                                         boolean isGetter) throws IOException {
+        Node f = function(FunctionNode.FUNCTION_EXPRESSION);
+        if (f.getType() != Token.FUNCTION) {
+            reportError("msg.bad.prop");
+            return false;
+        }
+        int fnIndex = f.getExistingIntProp(Node.FUNCTION_PROP);
+        FunctionNode fn = currentScriptOrFn.getFunctionNode(fnIndex);
+        if (fn.getFunctionName().length() != 0) {
+            reportError("msg.bad.prop");
+            return false;
+        }
+        elems.add(property);
+        if (isGetter) {
+            elems.add(nf.createUnary(Token.GET, f));
+        } else {
+            elems.add(nf.createUnary(Token.SET, f));
+        }
+        return true;
+    }
+}


Property changes on: trunk/cdk/maven-javascript-plugin/src/main/java/org/mozilla/javascript/Parser.java
___________________________________________________________________
Name: svn:mime-type
   + text/plain
Name: svn:keywords
   + Date Revision Author

Added: trunk/cdk/maven-javascript-plugin/src/main/java/org/mozilla/javascript/Token.java
===================================================================
--- trunk/cdk/maven-javascript-plugin/src/main/java/org/mozilla/javascript/Token.java	                        (rev 0)
+++ trunk/cdk/maven-javascript-plugin/src/main/java/org/mozilla/javascript/Token.java	2007-12-11 23:30:42 UTC (rev 4755)
@@ -0,0 +1,420 @@
+/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Rhino code, released
+ * May 6, 1999.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1997-1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Roger Lawrence
+ *   Mike McCabe
+ *   Igor Bukanov
+ *   Bob Jervis
+ *   Milen Nankov
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * the GNU General Public License Version 2 or later (the "GPL"), in which
+ * case the provisions of the GPL are applicable instead of those above. If
+ * you wish to allow use of your version of this file only under the terms of
+ * the GPL and not to allow others to use your version of this file under the
+ * MPL, indicate your decision by deleting the provisions above and replacing
+ * them with the notice and other provisions required by the GPL. If you do
+ * not delete the provisions above, a recipient may use your version of this
+ * file under either the MPL or the GPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+package org.mozilla.javascript;
+
+/**
+ * This class implements the JavaScript scanner.
+ *
+ * It is based on the C source files jsscan.c and jsscan.h
+ * in the jsref package.
+ *
+ * @see org.mozilla.javascript.Parser
+ *
+ * @author Mike McCabe
+ * @author Brendan Eich
+ */
+
+public class Token
+{
+
+    // debug flags
+    public static final boolean printTrees = false;
+    static final boolean printICode = false;
+    static final boolean printNames = printTrees || printICode;
+
+    /**
+     * Token types.  These values correspond to JSTokenType values in
+     * jsscan.c.
+     */
+
+    public final static int
+    // start enum
+        ERROR          = -1, // well-known as the only code < EOF
+        EOF            = 0,  // end of file token - (not EOF_CHAR)
+        EOL            = 1,  // end of line
+
+        // Interpreter reuses the following as bytecodes
+        FIRST_BYTECODE_TOKEN    = 2,
+
+        ENTERWITH      = 2,
+        LEAVEWITH      = 3,
+        RETURN         = 4,
+        GOTO           = 5,
+        IFEQ           = 6,
+        IFNE           = 7,
+        SETNAME        = 8,
+        BITOR          = 9,
+        BITXOR         = 10,
+        BITAND         = 11,
+        EQ             = 12,
+        NE             = 13,
+        LT             = 14,
+        LE             = 15,
+        GT             = 16,
+        GE             = 17,
+        LSH            = 18,
+        RSH            = 19,
+        URSH           = 20,
+        ADD            = 21,
+        SUB            = 22,
+        MUL            = 23,
+        DIV            = 24,
+        MOD            = 25,
+        NOT            = 26,
+        BITNOT         = 27,
+        POS            = 28,
+        NEG            = 29,
+        NEW            = 30,
+        DELPROP        = 31,
+        TYPEOF         = 32,
+        GETPROP        = 33,
+        SETPROP        = 34,
+        GETELEM        = 35,
+        SETELEM        = 36,
+        CALL           = 37,
+        NAME           = 38,
+        NUMBER         = 39,
+        STRING         = 40,
+        NULL           = 41,
+        THIS           = 42,
+        FALSE          = 43,
+        TRUE           = 44,
+        SHEQ           = 45,   // shallow equality (===)
+        SHNE           = 46,   // shallow inequality (!==)
+        REGEXP         = 47,
+        BINDNAME       = 48,
+        THROW          = 49,
+        RETHROW        = 50, // rethrow caught execetion: catch (e if ) use it
+        IN             = 51,
+        INSTANCEOF     = 52,
+        LOCAL_LOAD     = 53,
+        GETVAR         = 54,
+        SETVAR         = 55,
+        CATCH_SCOPE    = 56,
+        ENUM_INIT_KEYS = 57,
+        ENUM_INIT_VALUES = 58,
+        ENUM_NEXT      = 59,
+        ENUM_ID        = 60,
+        THISFN         = 61,
+        RETURN_RESULT  = 62, // to return prevoisly stored return result
+        ARRAYLIT       = 63, // array literal
+        OBJECTLIT      = 64, // object literal
+        GET_REF        = 65, // *reference
+        SET_REF        = 66, // *reference    = something
+        DEL_REF        = 67, // delete reference
+        REF_CALL       = 68, // f(args)    = something or f(args)++
+        REF_SPECIAL    = 69, // reference for special properties like __proto
+
+        // For XML support:
+        DEFAULTNAMESPACE = 70, // default xml namespace =
+        ESCXMLATTR     = 71,
+        ESCXMLTEXT     = 72,
+        REF_MEMBER     = 73, // Reference for x. at y, x..y etc.
+        REF_NS_MEMBER  = 74, // Reference for x.ns::y, x..ns::y etc.
+        REF_NAME       = 75, // Reference for @y, @[y] etc.
+        REF_NS_NAME    = 76; // Reference for ns::y, @ns::y@[y] etc.
+
+        // End of interpreter bytecodes
+    public final static int
+        LAST_BYTECODE_TOKEN    = REF_NS_NAME,
+
+        TRY            = 77,
+        SEMI           = 78,  // semicolon
+        LB             = 79,  // left and right brackets
+        RB             = 80,
+        LC             = 81,  // left and right curlies (braces)
+        RC             = 82,
+        LP             = 83,  // left and right parentheses
+        RP             = 84,
+        COMMA          = 85,  // comma operator
+
+        ASSIGN         = 86,  // simple assignment  (=)
+        ASSIGN_BITOR   = 87,  // |=
+        ASSIGN_BITXOR  = 88,  // ^=
+        ASSIGN_BITAND  = 89,  // |=
+        ASSIGN_LSH     = 90,  // <<=
+        ASSIGN_RSH     = 91,  // >>=
+        ASSIGN_URSH    = 92,  // >>>=
+        ASSIGN_ADD     = 93,  // +=
+        ASSIGN_SUB     = 94,  // -=
+        ASSIGN_MUL     = 95,  // *=
+        ASSIGN_DIV     = 96,  // /=
+        ASSIGN_MOD     = 97;  // %=
+
+    public final static int
+        FIRST_ASSIGN   = ASSIGN,
+        LAST_ASSIGN    = ASSIGN_MOD,
+
+        HOOK           = 98, // conditional (?:)
+        COLON          = 99,
+        OR             = 100, // logical or (||)
+        AND            = 101, // logical and (&&)
+        INC            = 102, // increment/decrement (++ --)
+        DEC            = 103,
+        DOT            = 104, // member operator (.)
+        FUNCTION       = 105, // function keyword
+        EXPORT         = 106, // export keyword
+        IMPORT         = 107, // import keyword
+        IF             = 108, // if keyword
+        ELSE           = 109, // else keyword
+        SWITCH         = 110, // switch keyword
+        CASE           = 111, // case keyword
+        DEFAULT        = 112, // default keyword
+        WHILE          = 113, // while keyword
+        DO             = 114, // do keyword
+        FOR            = 115, // for keyword
+        BREAK          = 116, // break keyword
+        CONTINUE       = 117, // continue keyword
+        VAR            = 118, // var keyword
+        WITH           = 119, // with keyword
+        CATCH          = 120, // catch keyword
+        FINALLY        = 121, // finally keyword
+        VOID           = 122, // void keyword
+        RESERVED       = 123, // reserved keywords
+
+        EMPTY          = 124,
+
+        /* types used for the parse tree - these never get returned
+         * by the scanner.
+         */
+
+        BLOCK          = 125, // statement block
+        LABEL          = 126, // label
+        TARGET         = 127,
+        LOOP           = 128,
+        EXPR_VOID      = 129, // expression statement in functions
+        EXPR_RESULT    = 130, // expression statement in scripts
+        JSR            = 131,
+        SCRIPT         = 132, // top-level node for entire script
+        TYPEOFNAME     = 133, // for typeof(simple-name)
+        USE_STACK      = 134,
+        SETPROP_OP     = 135, // x.y op= something
+        SETELEM_OP     = 136, // x[y] op= something
+        LOCAL_BLOCK    = 137,
+        SET_REF_OP     = 138, // *reference op= something
+
+        // For XML support:
+        DOTDOT         = 139,  // member operator (..)
+        COLONCOLON     = 140,  // namespace::name
+        XML            = 141,  // XML type
+        DOTQUERY       = 142,  // .() -- e.g., x.emps.emp.(name == "terry")
+        XMLATTR        = 143,  // @
+        XMLEND         = 144,
+
+        // Optimizer-only-tokens
+        TO_OBJECT      = 145,
+        TO_DOUBLE      = 146,
+
+        GET            = 147,  // JS 1.5 get pseudo keyword
+        SET            = 148,  // JS 1.5 set pseudo keyword
+        CONST          = 149,
+        SETCONST       = 150,
+        SETCONSTVAR    = 151,
+
+        IECC           = 152, // Internet Explorer conditional comment
+
+        LAST_TOKEN     = 153;
+
+    public static String name(int token)
+    {
+        if (!printNames) {
+            return String.valueOf(token);
+        }
+        switch (token) {
+          case ERROR:           return "ERROR";
+          case EOF:             return "EOF";
+          case EOL:             return "EOL";
+          case ENTERWITH:       return "ENTERWITH";
+          case LEAVEWITH:       return "LEAVEWITH";
+          case RETURN:          return "RETURN";
+          case GOTO:            return "GOTO";
+          case IFEQ:            return "IFEQ";
+          case IFNE:            return "IFNE";
+          case SETNAME:         return "SETNAME";
+          case BITOR:           return "BITOR";
+          case BITXOR:          return "BITXOR";
+          case BITAND:          return "BITAND";
+          case EQ:              return "EQ";
+          case NE:              return "NE";
+          case LT:              return "LT";
+          case LE:              return "LE";
+          case GT:              return "GT";
+          case GE:              return "GE";
+          case LSH:             return "LSH";
+          case RSH:             return "RSH";
+          case URSH:            return "URSH";
+          case ADD:             return "ADD";
+          case SUB:             return "SUB";
+          case MUL:             return "MUL";
+          case DIV:             return "DIV";
+          case MOD:             return "MOD";
+          case NOT:             return "NOT";
+          case BITNOT:          return "BITNOT";
+          case POS:             return "POS";
+          case NEG:             return "NEG";
+          case NEW:             return "NEW";
+          case DELPROP:         return "DELPROP";
+          case TYPEOF:          return "TYPEOF";
+          case GETPROP:         return "GETPROP";
+          case SETPROP:         return "SETPROP";
+          case GETELEM:         return "GETELEM";
+          case SETELEM:         return "SETELEM";
+          case CALL:            return "CALL";
+          case NAME:            return "NAME";
+          case NUMBER:          return "NUMBER";
+          case STRING:          return "STRING";
+          case NULL:            return "NULL";
+          case THIS:            return "THIS";
+          case FALSE:           return "FALSE";
+          case TRUE:            return "TRUE";
+          case SHEQ:            return "SHEQ";
+          case SHNE:            return "SHNE";
+          case REGEXP:          return "OBJECT";
+          case BINDNAME:        return "BINDNAME";
+          case THROW:           return "THROW";
+          case RETHROW:         return "RETHROW";
+          case IN:              return "IN";
+          case INSTANCEOF:      return "INSTANCEOF";
+          case LOCAL_LOAD:      return "LOCAL_LOAD";
+          case GETVAR:          return "GETVAR";
+          case SETVAR:          return "SETVAR";
+          case CATCH_SCOPE:     return "CATCH_SCOPE";
+          case ENUM_INIT_KEYS:  return "ENUM_INIT_KEYS";
+          case ENUM_INIT_VALUES:  return "ENUM_INIT_VALUES";
+          case ENUM_NEXT:       return "ENUM_NEXT";
+          case ENUM_ID:         return "ENUM_ID";
+          case THISFN:          return "THISFN";
+          case RETURN_RESULT:   return "RETURN_RESULT";
+          case ARRAYLIT:        return "ARRAYLIT";
+          case OBJECTLIT:       return "OBJECTLIT";
+          case GET_REF:         return "GET_REF";
+          case SET_REF:         return "SET_REF";
+          case DEL_REF:         return "DEL_REF";
+          case REF_CALL:        return "REF_CALL";
+          case REF_SPECIAL:     return "REF_SPECIAL";
+          case DEFAULTNAMESPACE:return "DEFAULTNAMESPACE";
+          case ESCXMLTEXT:      return "ESCXMLTEXT";
+          case ESCXMLATTR:      return "ESCXMLATTR";
+          case REF_MEMBER:      return "REF_MEMBER";
+          case REF_NS_MEMBER:   return "REF_NS_MEMBER";
+          case REF_NAME:        return "REF_NAME";
+          case REF_NS_NAME:     return "REF_NS_NAME";
+          case TRY:             return "TRY";
+          case SEMI:            return "SEMI";
+          case LB:              return "LB";
+          case RB:              return "RB";
+          case LC:              return "LC";
+          case RC:              return "RC";
+          case LP:              return "LP";
+          case RP:              return "RP";
+          case COMMA:           return "COMMA";
+          case ASSIGN:          return "ASSIGN";
+          case ASSIGN_BITOR:    return "ASSIGN_BITOR";
+          case ASSIGN_BITXOR:   return "ASSIGN_BITXOR";
+          case ASSIGN_BITAND:   return "ASSIGN_BITAND";
+          case ASSIGN_LSH:      return "ASSIGN_LSH";
+          case ASSIGN_RSH:      return "ASSIGN_RSH";
+          case ASSIGN_URSH:     return "ASSIGN_URSH";
+          case ASSIGN_ADD:      return "ASSIGN_ADD";
+          case ASSIGN_SUB:      return "ASSIGN_SUB";
+          case ASSIGN_MUL:      return "ASSIGN_MUL";
+          case ASSIGN_DIV:      return "ASSIGN_DIV";
+          case ASSIGN_MOD:      return "ASSIGN_MOD";
+          case HOOK:            return "HOOK";
+          case COLON:           return "COLON";
+          case OR:              return "OR";
+          case AND:             return "AND";
+          case INC:             return "INC";
+          case DEC:             return "DEC";
+          case DOT:             return "DOT";
+          case FUNCTION:        return "FUNCTION";
+          case EXPORT:          return "EXPORT";
+          case IMPORT:          return "IMPORT";
+          case IF:              return "IF";
+          case ELSE:            return "ELSE";
+          case SWITCH:          return "SWITCH";
+          case CASE:            return "CASE";
+          case DEFAULT:         return "DEFAULT";
+          case WHILE:           return "WHILE";
+          case DO:              return "DO";
+          case FOR:             return "FOR";
+          case BREAK:           return "BREAK";
+          case CONTINUE:        return "CONTINUE";
+          case VAR:             return "VAR";
+          case WITH:            return "WITH";
+          case CATCH:           return "CATCH";
+          case FINALLY:         return "FINALLY";
+          case RESERVED:        return "RESERVED";
+          case EMPTY:           return "EMPTY";
+          case BLOCK:           return "BLOCK";
+          case LABEL:           return "LABEL";
+          case TARGET:          return "TARGET";
+          case LOOP:            return "LOOP";
+          case EXPR_VOID:       return "EXPR_VOID";
+          case EXPR_RESULT:     return "EXPR_RESULT";
+          case JSR:             return "JSR";
+          case SCRIPT:          return "SCRIPT";
+          case TYPEOFNAME:      return "TYPEOFNAME";
+          case USE_STACK:       return "USE_STACK";
+          case SETPROP_OP:      return "SETPROP_OP";
+          case SETELEM_OP:      return "SETELEM_OP";
+          case LOCAL_BLOCK:     return "LOCAL_BLOCK";
+          case SET_REF_OP:      return "SET_REF_OP";
+          case DOTDOT:          return "DOTDOT";
+          case COLONCOLON:      return "COLONCOLON";
+          case XML:             return "XML";
+          case DOTQUERY:        return "DOTQUERY";
+          case XMLATTR:         return "XMLATTR";
+          case XMLEND:          return "XMLEND";
+          case TO_OBJECT:       return "TO_OBJECT";
+          case TO_DOUBLE:       return "TO_DOUBLE";
+          case GET:             return "GET";
+          case SET:             return "SET";
+          case CONST:           return "CONST";
+          case SETCONST:        return "SETCONST";
+        }
+
+        // Token without name
+        throw new IllegalStateException(String.valueOf(token));
+    }
+}


Property changes on: trunk/cdk/maven-javascript-plugin/src/main/java/org/mozilla/javascript/Token.java
___________________________________________________________________
Name: svn:mime-type
   + text/plain
Name: svn:keywords
   + Date Revision Author

Added: trunk/cdk/maven-javascript-plugin/src/main/java/org/mozilla/javascript/TokenStream.java
===================================================================
--- trunk/cdk/maven-javascript-plugin/src/main/java/org/mozilla/javascript/TokenStream.java	                        (rev 0)
+++ trunk/cdk/maven-javascript-plugin/src/main/java/org/mozilla/javascript/TokenStream.java	2007-12-11 23:30:42 UTC (rev 4755)
@@ -0,0 +1,1359 @@
+/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Rhino code, released
+ * May 6, 1999.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1997-1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Roger Lawrence
+ *   Mike McCabe
+ *   Igor Bukanov
+ *   Ethan Hugg
+ *   Bob Jervis
+ *   Terry Lucas
+ *   Milen Nankov
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * the GNU General Public License Version 2 or later (the "GPL"), in which
+ * case the provisions of the GPL are applicable instead of those above. If
+ * you wish to allow use of your version of this file only under the terms of
+ * the GPL and not to allow others to use your version of this file under the
+ * MPL, indicate your decision by deleting the provisions above and replacing
+ * them with the notice and other provisions required by the GPL. If you do
+ * not delete the provisions above, a recipient may use your version of this
+ * file under either the MPL or the GPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+package org.mozilla.javascript;
+
+import java.io.*;
+
+/**
+ * This class implements the JavaScript scanner.
+ *
+ * It is based on the C source files jsscan.c and jsscan.h
+ * in the jsref package.
+ *
+ * @see org.mozilla.javascript.Parser
+ *
+ * @author Mike McCabe
+ * @author Brendan Eich
+ */
+
+class TokenStream
+{
+    /*
+     * For chars - because we need something out-of-range
+     * to check.  (And checking EOF by exception is annoying.)
+     * Note distinction from EOF token type!
+     */
+    private final static int
+        EOF_CHAR = -1;
+
+    TokenStream(Parser parser, Reader sourceReader, String sourceString,
+                int lineno)
+    {
+        this.parser = parser;
+        this.lineno = lineno;
+        if (sourceReader != null) {
+            if (sourceString != null) Kit.codeBug();
+            this.sourceReader = sourceReader;
+            this.sourceBuffer = new char[512];
+            this.sourceEnd = 0;
+        } else {
+            if (sourceString == null) Kit.codeBug();
+            this.sourceString = sourceString;
+            this.sourceEnd = sourceString.length();
+        }
+        this.sourceCursor = 0;
+    }
+
+    /* This function uses the cached op, string and number fields in
+     * TokenStream; if getToken has been called since the passed token
+     * was scanned, the op or string printed may be incorrect.
+     */
+    String tokenToString(int token)
+    {
+        if (Token.printTrees) {
+            String name = Token.name(token);
+
+            switch (token) {
+            case Token.STRING:
+            case Token.REGEXP:
+            case Token.NAME:
+                return name + " `" + this.string + "'";
+
+            case Token.NUMBER:
+                return "NUMBER " + this.number;
+            }
+
+            return name;
+        }
+        return "";
+    }
+
+    static boolean isKeyword(String s)
+    {
+        return Token.EOF != stringToKeyword(s);
+    }
+
+    private static int stringToKeyword(String name)
+    {
+// #string_id_map#
+// The following assumes that Token.EOF == 0
+        final int
+            Id_break         = Token.BREAK,
+            Id_case          = Token.CASE,
+            Id_continue      = Token.CONTINUE,
+            Id_default       = Token.DEFAULT,
+            Id_delete        = Token.DELPROP,
+            Id_do            = Token.DO,
+            Id_else          = Token.ELSE,
+            Id_export        = Token.EXPORT,
+            Id_false         = Token.FALSE,
+            Id_for           = Token.FOR,
+            Id_function      = Token.FUNCTION,
+            Id_if            = Token.IF,
+            Id_in            = Token.IN,
+            Id_new           = Token.NEW,
+            Id_null          = Token.NULL,
+            Id_return        = Token.RETURN,
+            Id_switch        = Token.SWITCH,
+            Id_this          = Token.THIS,
+            Id_true          = Token.TRUE,
+            Id_typeof        = Token.TYPEOF,
+            Id_var           = Token.VAR,
+            Id_void          = Token.VOID,
+            Id_while         = Token.WHILE,
+            Id_with          = Token.WITH,
+
+            // the following are #ifdef RESERVE_JAVA_KEYWORDS in jsscan.c
+            Id_abstract      = Token.RESERVED,
+            Id_boolean       = Token.RESERVED,
+            Id_byte          = Token.RESERVED,
+            Id_catch         = Token.CATCH,
+            Id_char          = Token.RESERVED,
+            Id_class         = Token.RESERVED,
+            Id_const         = Token.CONST,
+            Id_debugger      = Token.RESERVED,
+            Id_double        = Token.RESERVED,
+            Id_enum          = Token.RESERVED,
+            Id_extends       = Token.RESERVED,
+            Id_final         = Token.RESERVED,
+            Id_finally       = Token.FINALLY,
+            Id_float         = Token.RESERVED,
+            Id_goto          = Token.RESERVED,
+            Id_implements    = Token.RESERVED,
+            Id_import        = Token.IMPORT,
+            Id_instanceof    = Token.INSTANCEOF,
+            Id_int           = Token.RESERVED,
+            Id_interface     = Token.RESERVED,
+            Id_long          = Token.RESERVED,
+            Id_native        = Token.RESERVED,
+            Id_package       = Token.RESERVED,
+            Id_private       = Token.RESERVED,
+            Id_protected     = Token.RESERVED,
+            Id_public        = Token.RESERVED,
+            Id_short         = Token.RESERVED,
+            Id_static        = Token.RESERVED,
+            Id_super         = Token.RESERVED,
+            Id_synchronized  = Token.RESERVED,
+            Id_throw         = Token.THROW,
+            Id_throws        = Token.RESERVED,
+            Id_transient     = Token.RESERVED,
+            Id_try           = Token.TRY,
+            Id_volatile      = Token.RESERVED;
+
+        int id;
+        String s = name;
+// #generated# Last update: 2001-06-01 17:45:01 CEST
+        L0: { id = 0; String X = null; int c;
+            L: switch (s.length()) {
+            case 2: c=s.charAt(1);
+                if (c=='f') { if (s.charAt(0)=='i') {id=Id_if; break L0;} }
+                else if (c=='n') { if (s.charAt(0)=='i') {id=Id_in; break L0;} }
+                else if (c=='o') { if (s.charAt(0)=='d') {id=Id_do; break L0;} }
+                break L;
+            case 3: switch (s.charAt(0)) {
+                case 'f': if (s.charAt(2)=='r' && s.charAt(1)=='o') {id=Id_for; break L0;} break L;
+                case 'i': if (s.charAt(2)=='t' && s.charAt(1)=='n') {id=Id_int; break L0;} break L;
+                case 'n': if (s.charAt(2)=='w' && s.charAt(1)=='e') {id=Id_new; break L0;} break L;
+                case 't': if (s.charAt(2)=='y' && s.charAt(1)=='r') {id=Id_try; break L0;} break L;
+                case 'v': if (s.charAt(2)=='r' && s.charAt(1)=='a') {id=Id_var; break L0;} break L;
+                } break L;
+            case 4: switch (s.charAt(0)) {
+                case 'b': X="byte";id=Id_byte; break L;
+                case 'c': c=s.charAt(3);
+                    if (c=='e') { if (s.charAt(2)=='s' && s.charAt(1)=='a') {id=Id_case; break L0;} }
+                    else if (c=='r') { if (s.charAt(2)=='a' && s.charAt(1)=='h') {id=Id_char; break L0;} }
+                    break L;
+                case 'e': c=s.charAt(3);
+                    if (c=='e') { if (s.charAt(2)=='s' && s.charAt(1)=='l') {id=Id_else; break L0;} }
+                    else if (c=='m') { if (s.charAt(2)=='u' && s.charAt(1)=='n') {id=Id_enum; break L0;} }
+                    break L;
+                case 'g': X="goto";id=Id_goto; break L;
+                case 'l': X="long";id=Id_long; break L;
+                case 'n': X="null";id=Id_null; break L;
+                case 't': c=s.charAt(3);
+                    if (c=='e') { if (s.charAt(2)=='u' && s.charAt(1)=='r') {id=Id_true; break L0;} }
+                    else if (c=='s') { if (s.charAt(2)=='i' && s.charAt(1)=='h') {id=Id_this; break L0;} }
+                    break L;
+                case 'v': X="void";id=Id_void; break L;
+                case 'w': X="with";id=Id_with; break L;
+                } break L;
+            case 5: switch (s.charAt(2)) {
+                case 'a': X="class";id=Id_class; break L;
+                case 'e': X="break";id=Id_break; break L;
+                case 'i': X="while";id=Id_while; break L;
+                case 'l': X="false";id=Id_false; break L;
+                case 'n': c=s.charAt(0);
+                    if (c=='c') { X="const";id=Id_const; }
+                    else if (c=='f') { X="final";id=Id_final; }
+                    break L;
+                case 'o': c=s.charAt(0);
+                    if (c=='f') { X="float";id=Id_float; }
+                    else if (c=='s') { X="short";id=Id_short; }
+                    break L;
+                case 'p': X="super";id=Id_super; break L;
+                case 'r': X="throw";id=Id_throw; break L;
+                case 't': X="catch";id=Id_catch; break L;
+                } break L;
+            case 6: switch (s.charAt(1)) {
+                case 'a': X="native";id=Id_native; break L;
+                case 'e': c=s.charAt(0);
+                    if (c=='d') { X="delete";id=Id_delete; }
+                    else if (c=='r') { X="return";id=Id_return; }
+                    break L;
+                case 'h': X="throws";id=Id_throws; break L;
+                case 'm': X="import";id=Id_import; break L;
+                case 'o': X="double";id=Id_double; break L;
+                case 't': X="static";id=Id_static; break L;
+                case 'u': X="public";id=Id_public; break L;
+                case 'w': X="switch";id=Id_switch; break L;
+                case 'x': X="export";id=Id_export; break L;
+                case 'y': X="typeof";id=Id_typeof; break L;
+                } break L;
+            case 7: switch (s.charAt(1)) {
+                case 'a': X="package";id=Id_package; break L;
+                case 'e': X="default";id=Id_default; break L;
+                case 'i': X="finally";id=Id_finally; break L;
+                case 'o': X="boolean";id=Id_boolean; break L;
+                case 'r': X="private";id=Id_private; break L;
+                case 'x': X="extends";id=Id_extends; break L;
+                } break L;
+            case 8: switch (s.charAt(0)) {
+                case 'a': X="abstract";id=Id_abstract; break L;
+                case 'c': X="continue";id=Id_continue; break L;
+                case 'd': X="debugger";id=Id_debugger; break L;
+                case 'f': X="function";id=Id_function; break L;
+                case 'v': X="volatile";id=Id_volatile; break L;
+                } break L;
+            case 9: c=s.charAt(0);
+                if (c=='i') { X="interface";id=Id_interface; }
+                else if (c=='p') { X="protected";id=Id_protected; }
+                else if (c=='t') { X="transient";id=Id_transient; }
+                break L;
+            case 10: c=s.charAt(1);
+                if (c=='m') { X="implements";id=Id_implements; }
+                else if (c=='n') { X="instanceof";id=Id_instanceof; }
+                break L;
+            case 12: X="synchronized";id=Id_synchronized; break L;
+            }
+            if (X!=null && X!=s && !X.equals(s)) id = 0;
+        }
+// #/generated#
+// #/string_id_map#
+        if (id == 0) { return Token.EOF; }
+        return id & 0xff;
+    }
+
+    final int getLineno() { return lineno; }
+
+    final String getString() { return string; }
+
+    final double getNumber() { return number; }
+
+    final boolean eof() { return hitEOF; }
+
+    final int getToken() throws IOException
+    {
+        int c;
+
+    retry:
+        for (;;) {
+            // Eat whitespace, possibly sensitive to newlines.
+            for (;;) {
+                c = getChar();
+                if (c == EOF_CHAR) {
+                    return Token.EOF;
+                } else if (c == '\n') {
+                    dirtyLine = false;
+                    return Token.EOL;
+                } else if (!isJSSpace(c)) {
+                    if (c != '-') {
+                        dirtyLine = true;
+                    }
+                    break;
+                }
+            }
+
+            if (c == '@') return Token.XMLATTR;
+
+            // identifier/keyword/instanceof?
+            // watch out for starting with a <backslash>
+            boolean identifierStart;
+            boolean isUnicodeEscapeStart = false;
+            if (c == '\\') {
+                c = getChar();
+                if (c == 'u') {
+                    identifierStart = true;
+                    isUnicodeEscapeStart = true;
+                    stringBufferTop = 0;
+                } else {
+                    identifierStart = false;
+                    ungetChar(c);
+                    c = '\\';
+                }
+            } else {
+                identifierStart = Character.isJavaIdentifierStart((char)c);
+                if (identifierStart) {
+                    stringBufferTop = 0;
+                    addToString(c);
+                }
+            }
+
+            if (identifierStart) {
+                boolean containsEscape = isUnicodeEscapeStart;
+                for (;;) {
+                    if (isUnicodeEscapeStart) {
+                        // strictly speaking we should probably push-back
+                        // all the bad characters if the <backslash>uXXXX
+                        // sequence is malformed. But since there isn't a
+                        // correct context(is there?) for a bad Unicode
+                        // escape sequence in an identifier, we can report
+                        // an error here.
+                        int escapeVal = 0;
+                        for (int i = 0; i != 4; ++i) {
+                            c = getChar();
+                            escapeVal = Kit.xDigitToInt(c, escapeVal);
+                            // Next check takes care about c < 0 and bad escape
+                            if (escapeVal < 0) { break; }
+                        }
+                        if (escapeVal < 0) {
+                            parser.addError("msg.invalid.escape");
+                            return Token.ERROR;
+                        }
+                        addToString(escapeVal);
+                        isUnicodeEscapeStart = false;
+                    } else {
+                        c = getChar();
+                        if (c == '\\') {
+                            c = getChar();
+                            if (c == 'u') {
+                                isUnicodeEscapeStart = true;
+                                containsEscape = true;
+                            } else {
+                                parser.addError("msg.illegal.character");
+                                return Token.ERROR;
+                            }
+                        } else {
+                            if (c == EOF_CHAR
+                                || !Character.isJavaIdentifierPart((char)c))
+                            {
+                                break;
+                            }
+                            addToString(c);
+                        }
+                    }
+                }
+                ungetChar(c);
+
+                String str = getStringFromBuffer();
+                if (!containsEscape) {
+                    // OPT we shouldn't have to make a string (object!) to
+                    // check if it's a keyword.
+
+                    // Return the corresponding token if it's a keyword
+                    int result = stringToKeyword(str);
+                    if (result != Token.EOF) {
+                        if (result != Token.RESERVED) {
+                            return result;
+                        } else if (!parser.compilerEnv.
+                                        isReservedKeywordAsIdentifier())
+                        {
+                            return result;
+                        } else {
+                            // If implementation permits to use future reserved
+                            // keywords in violation with the EcmaScript,
+                            // treat it as name but issue warning
+                            parser.addWarning("msg.reserved.keyword", str);
+                        }
+                    }
+                }
+                this.string = (String)allStrings.intern(str);
+                return Token.NAME;
+            }
+
+            // is it a number?
+            if (isDigit(c) || (c == '.' && isDigit(peekChar()))) {
+
+                stringBufferTop = 0;
+                int base = 10;
+
+                if (c == '0') {
+                    c = getChar();
+                    if (c == 'x' || c == 'X') {
+                        base = 16;
+                        c = getChar();
+                    } else if (isDigit(c)) {
+                        base = 8;
+                    } else {
+                        addToString('0');
+                    }
+                }
+
+                if (base == 16) {
+                    while (0 <= Kit.xDigitToInt(c, 0)) {
+                        addToString(c);
+                        c = getChar();
+                    }
+                } else {
+                    while ('0' <= c && c <= '9') {
+                        /*
+                         * We permit 08 and 09 as decimal numbers, which
+                         * makes our behavior a superset of the ECMA
+                         * numeric grammar.  We might not always be so
+                         * permissive, so we warn about it.
+                         */
+                        if (base == 8 && c >= '8') {
+                            parser.addWarning("msg.bad.octal.literal",
+                                              c == '8' ? "8" : "9");
+                            base = 10;
+                        }
+                        addToString(c);
+                        c = getChar();
+                    }
+                }
+
+                boolean isInteger = true;
+
+                if (base == 10 && (c == '.' || c == 'e' || c == 'E')) {
+                    isInteger = false;
+                    if (c == '.') {
+                        do {
+                            addToString(c);
+                            c = getChar();
+                        } while (isDigit(c));
+                    }
+                    if (c == 'e' || c == 'E') {
+                        addToString(c);
+                        c = getChar();
+                        if (c == '+' || c == '-') {
+                            addToString(c);
+                            c = getChar();
+                        }
+                        if (!isDigit(c)) {
+                            parser.addError("msg.missing.exponent");
+                            return Token.ERROR;
+                        }
+                        do {
+                            addToString(c);
+                            c = getChar();
+                        } while (isDigit(c));
+                    }
+                }
+                ungetChar(c);
+                String numString = getStringFromBuffer();
+
+                double dval;
+                if (base == 10 && !isInteger) {
+                    try {
+                        // Use Java conversion to number from string...
+                        dval = Double.valueOf(numString).doubleValue();
+                    }
+                    catch (NumberFormatException ex) {
+                        parser.addError("msg.caught.nfe");
+                        return Token.ERROR;
+                    }
+                } else {
+                    dval = ScriptRuntime.stringToNumber(numString, 0, base);
+                }
+
+                this.number = dval;
+                return Token.NUMBER;
+            }
+
+            // is it a string?
+            if (c == '"' || c == '\'') {
+                // We attempt to accumulate a string the fast way, by
+                // building it directly out of the reader.  But if there
+                // are any escaped characters in the string, we revert to
+                // building it out of a StringBuffer.
+
+                int quoteChar = c;
+                stringBufferTop = 0;
+
+                c = getChar();
+                while (c != quoteChar) {
+                    if (c == '\n' || c == EOF_CHAR) {
+                        ungetChar(c);
+                        parser.addError("msg.unterminated.string.lit");
+                        return Token.ERROR;
+                    }
+
+                    if (c == '\\') {
+                        // We've hit an escaped character
+
+                        c = getChar();
+
+                        switch (c) {
+
+                            case '\\': // backslash
+                            case 'b':  // backspace
+                            case 'f':  // form feed
+                            case 'n':  // line feed
+                            case 'r':  // carriage return
+                            case 't':  // horizontal tab
+                            case 'v':  // vertical tab
+                            case 'd':  // octal sequence
+                            case 'u':  // unicode sequence
+                            case 'x':  // hexadecimal sequence
+
+                                // Only keep the '\' character for those
+                                // characters that need to be escaped...
+                                // Don't escape quoting characters...
+                                addToString('\\');
+                                break;
+
+                            case '\n':
+                                // Remove line terminator after escape
+                                c = getChar();
+                                break;
+                        }
+                    }
+
+                    addToString(c);
+                    c = getChar();
+                }
+
+                String str = getStringFromBuffer();
+                this.string = (String)allStrings.intern(str);
+                return Token.STRING;
+            }
+
+            switch (c) {
+            case ';': return Token.SEMI;
+            case '[': return Token.LB;
+            case ']': return Token.RB;
+            case '{': return Token.LC;
+            case '}': return Token.RC;
+            case '(': return Token.LP;
+            case ')': return Token.RP;
+            case ',': return Token.COMMA;
+            case '?': return Token.HOOK;
+            case ':':
+                if (matchChar(':')) {
+                    return Token.COLONCOLON;
+                } else {
+                    return Token.COLON;
+                }
+            case '.':
+                if (matchChar('.')) {
+                    return Token.DOTDOT;
+                } else if (matchChar('(')) {
+                    return Token.DOTQUERY;
+                } else {
+                    return Token.DOT;
+                }
+
+            case '|':
+                if (matchChar('|')) {
+                    return Token.OR;
+                } else if (matchChar('=')) {
+                    return Token.ASSIGN_BITOR;
+                } else {
+                    return Token.BITOR;
+                }
+
+            case '^':
+                if (matchChar('=')) {
+                    return Token.ASSIGN_BITXOR;
+                } else {
+                    return Token.BITXOR;
+                }
+
+            case '&':
+                if (matchChar('&')) {
+                    return Token.AND;
+                } else if (matchChar('=')) {
+                    return Token.ASSIGN_BITAND;
+                } else {
+                    return Token.BITAND;
+                }
+
+            case '=':
+                if (matchChar('=')) {
+                    if (matchChar('='))
+                        return Token.SHEQ;
+                    else
+                        return Token.EQ;
+                } else {
+                    return Token.ASSIGN;
+                }
+
+            case '!':
+                if (matchChar('=')) {
+                    if (matchChar('='))
+                        return Token.SHNE;
+                    else
+                        return Token.NE;
+                } else {
+                    return Token.NOT;
+                }
+
+            case '<':
+                /* NB:treat HTML begin-comment as comment-till-eol */
+                if (matchChar('!')) {
+                    if (matchChar('-')) {
+                        if (matchChar('-')) {
+                            skipLine();
+                            continue retry;
+                        }
+                        ungetChar('-');
+                    }
+                    ungetChar('!');
+                }
+                if (matchChar('<')) {
+                    if (matchChar('=')) {
+                        return Token.ASSIGN_LSH;
+                    } else {
+                        return Token.LSH;
+                    }
+                } else {
+                    if (matchChar('=')) {
+                        return Token.LE;
+                    } else {
+                        return Token.LT;
+                    }
+                }
+
+            case '>':
+                if (matchChar('>')) {
+                    if (matchChar('>')) {
+                        if (matchChar('=')) {
+                            return Token.ASSIGN_URSH;
+                        } else {
+                            return Token.URSH;
+                        }
+                    } else {
+                        if (matchChar('=')) {
+                            return Token.ASSIGN_RSH;
+                        } else {
+                            return Token.RSH;
+                        }
+                    }
+                } else {
+                    if (matchChar('=')) {
+                        return Token.GE;
+                    } else {
+                        return Token.GT;
+                    }
+                }
+
+            case '*':
+                if (matchChar('=')) {
+                    return Token.ASSIGN_MUL;
+                } else {
+                    return Token.MUL;
+                }
+
+            case '/':
+                // is it a // comment?
+                if (matchChar('/')) {
+                    skipLine();
+                    continue retry;
+                }
+                if (matchChar('*')) {
+                    boolean lookForSlash = false;
+                    StringBuffer sb = new StringBuffer();
+                    for (;;) {
+                        c = getChar();
+                        if (c == EOF_CHAR) {
+                            parser.addError("msg.unterminated.comment");
+                            return Token.ERROR;
+                        }
+                        sb.append((char) c);
+                        if (c == '*') {
+                            lookForSlash = true;
+                        } else if (c == '/') {
+                            if (lookForSlash) {
+                                sb.delete(sb.length()-2, sb.length());
+                                String s = sb.toString();
+                                if (s.startsWith("@cc_on") ||
+                                        s.startsWith("@if") ||
+                                        s.startsWith("@elif") ||
+                                        s.startsWith("@else") ||
+                                        s.startsWith("@end")) {
+                                    this.string = s;
+                                    return Token.IECC;
+                                } else {
+                                    continue retry;
+                                }
+                            }
+                        } else {
+                            lookForSlash = false;
+                        }
+                    }
+                }
+
+                if (matchChar('=')) {
+                    return Token.ASSIGN_DIV;
+                } else {
+                    return Token.DIV;
+                }
+
+            case '%':
+                if (matchChar('=')) {
+                    return Token.ASSIGN_MOD;
+                } else {
+                    return Token.MOD;
+                }
+
+            case '~':
+                return Token.BITNOT;
+
+            case '+':
+                if (matchChar('=')) {
+                    return Token.ASSIGN_ADD;
+                } else if (matchChar('+')) {
+                    return Token.INC;
+                } else {
+                    return Token.ADD;
+                }
+
+            case '-':
+                if (matchChar('=')) {
+                    c = Token.ASSIGN_SUB;
+                } else if (matchChar('-')) {
+                    if (!dirtyLine) {
+                        // treat HTML end-comment after possible whitespace
+                        // after line start as comment-utill-eol
+                        if (matchChar('>')) {
+                            skipLine();
+                            continue retry;
+                        }
+                    }
+                    c = Token.DEC;
+                } else {
+                    c = Token.SUB;
+                }
+                dirtyLine = true;
+                return c;
+
+            default:
+                parser.addError("msg.illegal.character");
+                return Token.ERROR;
+            }
+        }
+    }
+
+    private static boolean isAlpha(int c)
+    {
+        // Use 'Z' < 'a'
+        if (c <= 'Z') {
+            return 'A' <= c;
+        } else {
+            return 'a' <= c && c <= 'z';
+        }
+    }
+
+    static boolean isDigit(int c)
+    {
+        return '0' <= c && c <= '9';
+    }
+
+    /* As defined in ECMA.  jsscan.c uses C isspace() (which allows
+     * \v, I think.)  note that code in getChar() implicitly accepts
+     * '\r' == \u000D as well.
+     */
+    static boolean isJSSpace(int c)
+    {
+        if (c <= 127) {
+            return c == 0x20 || c == 0x9 || c == 0xC || c == 0xB;
+        } else {
+            return c == 0xA0
+                || Character.getType((char)c) == Character.SPACE_SEPARATOR;
+        }
+    }
+
+    private static boolean isJSFormatChar(int c)
+    {
+        return c > 127 && Character.getType((char)c) == Character.FORMAT;
+    }
+
+    /**
+     * Parser calls the method when it gets / or /= in literal context.
+     */
+    void readRegExp(int startToken)
+        throws IOException
+    {
+        stringBufferTop = 0;
+        if (startToken == Token.ASSIGN_DIV) {
+            // Miss-scanned /=
+            addToString('=');
+        } else {
+            if (startToken != Token.DIV) Kit.codeBug();
+        }
+
+        int c;
+        while ((c = getChar()) != '/') {
+            if (c == '\n' || c == EOF_CHAR) {
+                ungetChar(c);
+                throw parser.reportError("msg.unterminated.re.lit");
+            }
+            if (c == '\\') {
+                addToString(c);
+                c = getChar();
+            }
+
+            addToString(c);
+        }
+        int reEnd = stringBufferTop;
+
+        while (true) {
+            if (matchChar('g'))
+                addToString('g');
+            else if (matchChar('i'))
+                addToString('i');
+            else if (matchChar('m'))
+                addToString('m');
+            else
+                break;
+        }
+
+        if (isAlpha(peekChar())) {
+            throw parser.reportError("msg.invalid.re.flag");
+        }
+
+        this.string = new String(stringBuffer, 0, reEnd);
+        this.regExpFlags = new String(stringBuffer, reEnd,
+                                      stringBufferTop - reEnd);
+    }
+
+    boolean isXMLAttribute()
+    {
+        return xmlIsAttribute;
+    }
+
+    int getFirstXMLToken() throws IOException
+    {
+        xmlOpenTagsCount = 0;
+        xmlIsAttribute = false;
+        xmlIsTagContent = false;
+        ungetChar('<');
+        return getNextXMLToken();
+    }
+
+    int getNextXMLToken() throws IOException
+    {
+        stringBufferTop = 0; // remember the XML
+
+        for (int c = getChar(); c != EOF_CHAR; c = getChar()) {
+            if (xmlIsTagContent) {
+                switch (c) {
+                case '>':
+                    addToString(c);
+                    xmlIsTagContent = false;
+                    xmlIsAttribute = false;
+                    break;
+                case '/':
+                    addToString(c);
+                    if (peekChar() == '>') {
+                        c = getChar();
+                        addToString(c);
+                        xmlIsTagContent = false;
+                        xmlOpenTagsCount--;
+                    }
+                    break;
+                case '{':
+                    ungetChar(c);
+                    this.string = getStringFromBuffer();
+                    return Token.XML;
+                case '\'':
+                case '"':
+                    addToString(c);
+                    if (!readQuotedString(c)) return Token.ERROR;
+                    break;
+                case '=':
+                    addToString(c);
+                    xmlIsAttribute = true;
+                    break;
+                case ' ':
+                case '\t':
+                case '\r':
+                case '\n':
+                    addToString(c);
+                    break;
+                default:
+                    addToString(c);
+                    xmlIsAttribute = false;
+                    break;
+                }
+
+                if (!xmlIsTagContent && xmlOpenTagsCount == 0) {
+                    this.string = getStringFromBuffer();
+                    return Token.XMLEND;
+                }
+            } else {
+                switch (c) {
+                case '<':
+                    addToString(c);
+                    c = peekChar();
+                    switch (c) {
+                    case '!':
+                        c = getChar(); // Skip !
+                        addToString(c);
+                        c = peekChar();
+                        switch (c) {
+                        case '-':
+                            c = getChar(); // Skip -
+                            addToString(c);
+                            c = getChar();
+                            if (c == '-') {
+                                addToString(c);
+                                if(!readXmlComment()) return Token.ERROR;
+                            } else {
+                                // throw away the string in progress
+                                stringBufferTop = 0;
+                                this.string = null;
+                                parser.addError("msg.XML.bad.form");
+                                return Token.ERROR;
+                            }
+                            break;
+                        case '[':
+                            c = getChar(); // Skip [
+                            addToString(c);
+                            if (getChar() == 'C' &&
+                                getChar() == 'D' &&
+                                getChar() == 'A' &&
+                                getChar() == 'T' &&
+                                getChar() == 'A' &&
+                                getChar() == '[')
+                            {
+                                addToString('C');
+                                addToString('D');
+                                addToString('A');
+                                addToString('T');
+                                addToString('A');
+                                addToString('[');
+                                if (!readCDATA()) return Token.ERROR;
+
+                            } else {
+                                // throw away the string in progress
+                                stringBufferTop = 0;
+                                this.string = null;
+                                parser.addError("msg.XML.bad.form");
+                                return Token.ERROR;
+                            }
+                            break;
+                        default:
+                            if(!readEntity()) return Token.ERROR;
+                            break;
+                        }
+                        break;
+                    case '?':
+                        c = getChar(); // Skip ?
+                        addToString(c);
+                        if (!readPI()) return Token.ERROR;
+                        break;
+                    case '/':
+                        // End tag
+                        c = getChar(); // Skip /
+                        addToString(c);
+                        if (xmlOpenTagsCount == 0) {
+                            // throw away the string in progress
+                            stringBufferTop = 0;
+                            this.string = null;
+                            parser.addError("msg.XML.bad.form");
+                            return Token.ERROR;
+                        }
+                        xmlIsTagContent = true;
+                        xmlOpenTagsCount--;
+                        break;
+                    default:
+                        // Start tag
+                        xmlIsTagContent = true;
+                        xmlOpenTagsCount++;
+                        break;
+                    }
+                    break;
+                case '{':
+                    ungetChar(c);
+                    this.string = getStringFromBuffer();
+                    return Token.XML;
+                default:
+                    addToString(c);
+                    break;
+                }
+            }
+        }
+
+        stringBufferTop = 0; // throw away the string in progress
+        this.string = null;
+        parser.addError("msg.XML.bad.form");
+        return Token.ERROR;
+    }
+
+    /**
+     *
+     */
+    private boolean readQuotedString(int quote) throws IOException
+    {
+        for (int c = getChar(); c != EOF_CHAR; c = getChar()) {
+            addToString(c);
+            if (c == quote) return true;
+        }
+
+        stringBufferTop = 0; // throw away the string in progress
+        this.string = null;
+        parser.addError("msg.XML.bad.form");
+        return false;
+    }
+
+    /**
+     *
+     */
+    private boolean readXmlComment() throws IOException
+    {
+        for (int c = getChar(); c != EOF_CHAR;) {
+            addToString(c);
+            if (c == '-' && peekChar() == '-') {
+                c = getChar();
+                addToString(c);
+                if (peekChar() == '>') {
+                    c = getChar(); // Skip >
+                    addToString(c);
+                    return true;
+                } else {
+                    continue;
+                }
+            }
+            c = getChar();
+        }
+
+        stringBufferTop = 0; // throw away the string in progress
+        this.string = null;
+        parser.addError("msg.XML.bad.form");
+        return false;
+    }
+
+    /**
+     *
+     */
+    private boolean readCDATA() throws IOException
+    {
+        for (int c = getChar(); c != EOF_CHAR;) {
+            addToString(c);
+            if (c == ']' && peekChar() == ']') {
+                c = getChar();
+                addToString(c);
+                if (peekChar() == '>') {
+                    c = getChar(); // Skip >
+                    addToString(c);
+                    return true;
+                } else {
+                    continue;
+                }
+            }
+            c = getChar();
+        }
+
+        stringBufferTop = 0; // throw away the string in progress
+        this.string = null;
+        parser.addError("msg.XML.bad.form");
+        return false;
+    }
+
+    /**
+     *
+     */
+    private boolean readEntity() throws IOException
+    {
+        int declTags = 1;
+        for (int c = getChar(); c != EOF_CHAR; c = getChar()) {
+            addToString(c);
+            switch (c) {
+            case '<':
+                declTags++;
+                break;
+            case '>':
+                declTags--;
+                if (declTags == 0) return true;
+                break;
+            }
+        }
+
+        stringBufferTop = 0; // throw away the string in progress
+        this.string = null;
+        parser.addError("msg.XML.bad.form");
+        return false;
+    }
+
+    /**
+     *
+     */
+    private boolean readPI() throws IOException
+    {
+        for (int c = getChar(); c != EOF_CHAR; c = getChar()) {
+            addToString(c);
+            if (c == '?' && peekChar() == '>') {
+                c = getChar(); // Skip >
+                addToString(c);
+                return true;
+            }
+        }
+
+        stringBufferTop = 0; // throw away the string in progress
+        this.string = null;
+        parser.addError("msg.XML.bad.form");
+        return false;
+    }
+
+    private String getStringFromBuffer()
+    {
+        return new String(stringBuffer, 0, stringBufferTop);
+    }
+
+    private void addToString(int c)
+    {
+        int N = stringBufferTop;
+        if (N == stringBuffer.length) {
+            char[] tmp = new char[stringBuffer.length * 2];
+            System.arraycopy(stringBuffer, 0, tmp, 0, N);
+            stringBuffer = tmp;
+        }
+        stringBuffer[N] = (char)c;
+        stringBufferTop = N + 1;
+    }
+
+    private void ungetChar(int c)
+    {
+        // can not unread past across line boundary
+        if (ungetCursor != 0 && ungetBuffer[ungetCursor - 1] == '\n')
+            Kit.codeBug();
+        ungetBuffer[ungetCursor++] = c;
+    }
+
+    private boolean matchChar(int test) throws IOException
+    {
+        int c = getChar();
+        if (c == test) {
+            return true;
+        } else {
+            ungetChar(c);
+            return false;
+        }
+    }
+
+    private int peekChar() throws IOException
+    {
+        int c = getChar();
+        ungetChar(c);
+        return c;
+    }
+
+    private int getChar() throws IOException
+    {
+        if (ungetCursor != 0) {
+            return ungetBuffer[--ungetCursor];
+        }
+
+        for(;;) {
+            int c;
+            if (sourceString != null) {
+                if (sourceCursor == sourceEnd) {
+                    hitEOF = true;
+                    return EOF_CHAR;
+                }
+                c = sourceString.charAt(sourceCursor++);
+            } else {
+                if (sourceCursor == sourceEnd) {
+                    if (!fillSourceBuffer()) {
+                        hitEOF = true;
+                        return EOF_CHAR;
+                    }
+                }
+                c = sourceBuffer[sourceCursor++];
+            }
+
+            if (lineEndChar >= 0) {
+                if (lineEndChar == '\r' && c == '\n') {
+                    lineEndChar = '\n';
+                    continue;
+                }
+                lineEndChar = -1;
+                lineStart = sourceCursor - 1;
+                lineno++;
+            }
+
+            if (c <= 127) {
+                if (c == '\n' || c == '\r') {
+                    lineEndChar = c;
+                    c = '\n';
+                }
+            } else {
+                if (isJSFormatChar(c)) {
+                    continue;
+                }
+                if (ScriptRuntime.isJSLineTerminator(c)) {
+                    lineEndChar = c;
+                    c = '\n';
+                }
+            }
+            return c;
+        }
+    }
+
+    private void skipLine() throws IOException
+    {
+        // skip to end of line
+        int c;
+        while ((c = getChar()) != EOF_CHAR && c != '\n') { }
+        ungetChar(c);
+    }
+
+    final int getOffset()
+    {
+        int n = sourceCursor - lineStart;
+        if (lineEndChar >= 0) { --n; }
+        return n;
+    }
+
+    final String getLine()
+    {
+        if (sourceString != null) {
+            // String case
+            int lineEnd = sourceCursor;
+            if (lineEndChar >= 0) {
+                --lineEnd;
+            } else {
+                for (; lineEnd != sourceEnd; ++lineEnd) {
+                    int c = sourceString.charAt(lineEnd);
+                    if (ScriptRuntime.isJSLineTerminator(c)) {
+                        break;
+                    }
+                }
+            }
+            return sourceString.substring(lineStart, lineEnd);
+        } else {
+            // Reader case
+            int lineLength = sourceCursor - lineStart;
+            if (lineEndChar >= 0) {
+                --lineLength;
+            } else {
+                // Read until the end of line
+                for (;; ++lineLength) {
+                    int i = lineStart + lineLength;
+                    if (i == sourceEnd) {
+                        try {
+                            if (!fillSourceBuffer()) { break; }
+                        } catch (IOException ioe) {
+                            // ignore it, we're already displaying an error...
+                            break;
+                        }
+                        // i recalculuation as fillSourceBuffer can move saved
+                        // line buffer and change lineStart
+                        i = lineStart + lineLength;
+                    }
+                    int c = sourceBuffer[i];
+                    if (ScriptRuntime.isJSLineTerminator(c)) {
+                        break;
+                    }
+                }
+            }
+            return new String(sourceBuffer, lineStart, lineLength);
+        }
+    }
+
+    private boolean fillSourceBuffer() throws IOException
+    {
+        if (sourceString != null) Kit.codeBug();
+        if (sourceEnd == sourceBuffer.length) {
+            if (lineStart != 0) {
+                System.arraycopy(sourceBuffer, lineStart, sourceBuffer, 0,
+                                 sourceEnd - lineStart);
+                sourceEnd -= lineStart;
+                sourceCursor -= lineStart;
+                lineStart = 0;
+            } else {
+                char[] tmp = new char[sourceBuffer.length * 2];
+                System.arraycopy(sourceBuffer, 0, tmp, 0, sourceEnd);
+                sourceBuffer = tmp;
+            }
+        }
+        int n = sourceReader.read(sourceBuffer, sourceEnd,
+                                  sourceBuffer.length - sourceEnd);
+        if (n < 0) {
+            return false;
+        }
+        sourceEnd += n;
+        return true;
+    }
+
+    // stuff other than whitespace since start of line
+    private boolean dirtyLine;
+
+    String regExpFlags;
+
+    // Set this to an inital non-null value so that the Parser has
+    // something to retrieve even if an error has occured and no
+    // string is found.  Fosters one class of error, but saves lots of
+    // code.
+    private String string = "";
+    private double number;
+
+    private char[] stringBuffer = new char[128];
+    private int stringBufferTop;
+    private ObjToIntMap allStrings = new ObjToIntMap(50);
+
+    // Room to backtrace from to < on failed match of the last - in <!--
+    private final int[] ungetBuffer = new int[3];
+    private int ungetCursor;
+
+    private boolean hitEOF = false;
+
+    private int lineStart = 0;
+    private int lineno;
+    private int lineEndChar = -1;
+
+    private String sourceString;
+    private Reader sourceReader;
+    private char[] sourceBuffer;
+    private int sourceEnd;
+    private int sourceCursor;
+
+    // for xml tokenizer
+    private boolean xmlIsAttribute;
+    private boolean xmlIsTagContent;
+    private int xmlOpenTagsCount;
+
+    private Parser parser;
+}


Property changes on: trunk/cdk/maven-javascript-plugin/src/main/java/org/mozilla/javascript/TokenStream.java
___________________________________________________________________
Name: svn:mime-type
   + text/plain
Name: svn:keywords
   + Date Revision Author

Added: trunk/cdk/maven-javascript-plugin/src/main/resources/jslint.js
===================================================================
--- trunk/cdk/maven-javascript-plugin/src/main/resources/jslint.js	                        (rev 0)
+++ trunk/cdk/maven-javascript-plugin/src/main/resources/jslint.js	2007-12-11 23:30:42 UTC (rev 4755)
@@ -0,0 +1,295 @@
+// (C)2002 Douglas Crockford
+// www.JSLint.com
+// Rhino Edition
+
+var JSLINT;JSLINT=function(){var adsafe={activexobject:true,alert:true,back:true,body:true,close:true,confirm:true,cookie:true,constructor:true,createpopup:true,defaultstatus:true,defaultview:true,document:true,documentelement:true,domain:true,'eval':true,execScript:true,external:true,forms:true,forward:true,frameelement:true,fromcharcode:true,history:true,home:true,location:true,moveby:true,moveto:true,navigate:true,opener:true,parent:true,print:true,prompt:true,prototype:true,referrer:true,resizeby:true,resizeto:true,self:true,showhelp:true,showmodaldialog:true,status:true,stop:true,top:true,window:true,write:true,writeln:true,__proto__:true},allOptions={adsafe:true,bitwise:true,browser:true,cap:true,debug:true,eqeqeq:true,evil:true,fragment:true,laxbreak:true,nomen:true,passfail:true,plusplus:true,rhino:true,undef:true,white:true,widget:true},anonname,browser={alert:true,blur:true,clearInterval:true,clearTimeout:true,close:true,closed:true,confirm:true,console:true,Debug!
 :true,defaultStatus:true,document:true,event:true,focus:true,frames:true,getComputedStyle:true,history:true,Image:true,length:true,location:true,moveBy:true,moveTo:true,name:true,navigator:true,onblur:true,onerror:true,onfocus:true,onload:true,onresize:true,onunload:true,open:true,opener:true,opera:true,parent:true,print:true,prompt:true,resizeBy:true,resizeTo:true,screen:true,scroll:true,scrollBy:true,scrollTo:true,self:true,setInterval:true,setTimeout:true,status:true,top:true,window:true,XMLHttpRequest:true},escapes={'\b':'\\b','\t':'\\t','\n':'\\n','\f':'\\f','\r':'\\r','"':'\\"','\\':'\\\\'},funct,functions,globals,implied,inblock,indent,jsonmode,lines,lookahead,member,membersOnly,nexttoken,noreach,option,prereg,prevtoken,rhino={defineClass:true,deserialize:true,gc:true,help:true,load:true,loadClass:true,print:true,quit:true,readFile:true,readUrl:true,runCommand:true,seal:true,serialize:true,spawn:true,sync:true,toint32:true,version:true},scope,stack,standard={Array:tr!
 ue,Boolean:true,Date:true,decodeURI:true,decodeURIComponent:true,encod
eURI:true,encodeURIComponent:true,Error:true,escape:true,'eval':true,EvalError:true,Function:true,isFinite:true,isNaN:true,Math:true,Number:true,Object:true,parseInt:true,parseFloat:true,RangeError:true,ReferenceError:true,RegExp:true,String:true,SyntaxError:true,TypeError:true,unescape:true,URIError:true},syntax={},token,verb,warnings,widget={alert:true,appleScript:true,animator:true,appleScript:true,beep:true,bytesToUIString:true,Canvas:true,chooseColor:true,chooseFile:true,chooseFolder:true,convertPathToHFS:true,convertPathToPlatform:true,closeWidget:true,COM:true,CustomAnimation:true,escape:true,FadeAnimation:true,filesystem:true,focusWidget:true,form:true,Frame:true,HotKey:true,Image:true,include:true,isApplicationRunning:true,iTunes:true,konfabulatorVersion:true,log:true,MenuItem:true,MoveAnimation:true,openURL:true,play:true,Point:true,popupMenu:true,preferenceGroups:true,preferences:true,print:true,prompt:true,random:true,reloadWidget:true,resolvePath:true,resumeUpda!
 tes:true,RotateAnimation:true,runCommand:true,runCommandInBg:true,saveAs:true,savePreferences:true,screen:true,ScrollBar:true,showWidgetPreferences:true,sleep:true,speak:true,suppressUpdates:true,system:true,tellWidget:true,Text:true,TextArea:true,unescape:true,updateNow:true,URL:true,widget:true,Window:true,XMLDOM:true,XMLHttpRequest:true,yahooCheckLogin:true,yahooLogin:true,yahooLogout:true},wmode,xmode,xtype,tx=/^\s*([(){}[.,:;'"~]|\](\]>)?|\?>?|==?=?|\/(\*(global|extern|jslint|member|members)?|=|\/)?|\*[\/=]?|\+[+=]?|-[-=]?|%[=>]?|&[&=]?|\|[|=]?|>>?>?=?|<([\/=%\?]|\!(\[|--)?|<=?)?|\^=?|\!=?=?|[a-zA-Z_$][a-zA-Z0-9_$]*|[0-9]+([xX][0-9a-fA-F]+|\.[0-9]*)?([eE][+-]?[0-9]+)?)/,rx=/^(\\[^\x00-\x1f]|\[(\\[^\x00-\x1f]|[^\x00-\x1f\\\/])*\]|[^\x00-\x1f\\\/\[])+\/[gim]*/,lx=/\*\/|\/\*/,ix=/^([a-zA-Z_$][a-zA-Z0-9_$]*$)/,jx=/(javascript|jscript|ecmascript)\s*:/i;Object.prototype.begetObject=function(){function F(){}
+F.prototype=this;return new F();};Object.prototype.combine=function(o){var n;for(n in o){if(o.hasOwnProperty(n)){this[n]=o[n];}}};String.prototype.entityify=function(){return this.replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;');};String.prototype.isAlpha=function(){return(this>='a'&&this<='z\uffff')||(this>='A'&&this<='Z\uffff');};String.prototype.isDigit=function(){return(this>='0'&&this<='9');};String.prototype.supplant=function(o){return this.replace(/{([^{}]*)}/g,function(a,b){var r=o[b];return typeof r==='string'||typeof r==='number'?r:a;});};String.prototype.name=function(){if(ix.test(this)){return this;}
+if(/[&<"\\\x00-\x1f]/.test(this)){return'"'+this.replace(/[&<"\\\x00-\x1f]/g,function(a){var c=escapes[a];if(c){return c;}
+c=a.charCodeAt();return'\\u00'+
+Math.floor(c/16).toString(16)+
+(c%16).toString(16);})+'"';}
+return'"'+this+'"';};function populateGlobals(){if(option.rhino){globals.combine(rhino);}
+if(option.browser){globals.combine(browser);}
+if(option.widget){globals.combine(widget);}}
+function quit(m,l,ch){throw{name:'JSLintError',line:l,character:ch,message:m+" ("+Math.floor((l/lines.length)*100)+"% scanned)."};}
+function warning(m,t,a,b,c,d){var ch,l,w;t=t||nexttoken;if(t.id==='(end)'){t=token;}
+l=t.line||0;ch=t.from||0;w={id:'(error)',raw:m,evidence:lines[l]||'',line:l,character:ch,a:a,b:b,c:c,d:d};w.reason=m.supplant(w);JSLINT.errors.push(w);if(option.passfail){quit('Stopping. ',l,ch);}
+warnings+=1;if(warnings===50){quit("Too many errors.",l,ch);}
+return w;}
+function warningAt(m,l,ch,a,b,c,d){return warning(m,{line:l,from:ch},a,b,c,d);}
+function error(m,t,a,b,c,d){var w=warning(m,t,a,b,c,d);quit("Stopping, unable to continue.",w.line,w.character);}
+function errorAt(m,l,ch,a,b,c,d){return error(m,{line:l,from:ch},a,b,c,d);}
+var lex=function(){var character,from,line,s;function nextLine(){line+=1;if(line>=lines.length){return false;}
+character=0;s=lines[line];return true;}
+function it(type,value){var i,t;if(option.adsafe&&adsafe[value.toLowerCase()]===true){warning("Adsafe restricted word '{a}'.",{line:line,from:character},value);}
+if(type==='(punctuator)'||(type==='(identifier)'&&syntax.hasOwnProperty(value))){t=syntax[value];if(!t.id){t=syntax[type];}}else{t=syntax[type];}
+t=t.begetObject();if(type==='(string)'){if(/(javascript|jscript|ecmascript)\s*:/i.test(value)){warningAt("JavaScript URL.",line,from);}}
+t.value=value;t.line=line;t.character=character;t.from=from;i=t.id;prereg=i&&(('(,=:[!&|?{};'.indexOf(i.charAt(i.length-1))>=0)||i==='return');return t;}
+return{init:function(source){if(typeof source==='string'){lines=source.replace(/\r\n/g,'\n').replace(/\r/g,'\n').split('\n');}else{lines=source;}
+line=0;character=0;from=0;s=lines[0];},token:function(){var c,d,i,l,r,t;function match(x){var r=x.exec(s),r1;if(r){l=r[0].length;r1=r[1];c=r1.charAt(0);s=s.substr(l);character+=l;from=character-r1.length;return r1;}}
+function string(x){var c,j,r='';if(jsonmode&&x!=='"'){warningAt("Strings must use doublequote.",line,character);}
+if(xmode===x||xmode==='string'){return it('(punctuator)',x);}
+function esc(n){var i=parseInt(s.substr(j+1,n),16);j+=n;if(i>=32&&i<=127&&i!==34&&i!==92&&i!==39){warningAt("Unnecessary escapement.",line,character);}
+character+=n;c=String.fromCharCode(i);}
+for(j=0;j<s.length;j+=1){c=s.charAt(j);if(c===x){character+=1;s=s.substr(j+1);return it('(string)',r,x);}
+if(c<' '){if(c==='\n'||c==='\r'){break;}
+warningAt("Control character in string: {a}.",line,character+j,s.substring(0,j));}else if(c==='<'){if(s.charAt(j+1)==='/'&&xmode&&xmode!=='CDATA'){warningAt("Expected '<\\/' and instead saw '</'.",line,character);}}else if(c==='\\'){j+=1;character+=1;c=s.charAt(j);switch(c){case'\\':case'\'':case'"':case'/':break;case'b':c='\b';break;case'f':c='\f';break;case'n':c='\n';break;case'r':c='\r';break;case't':c='\t';break;case'u':esc(4);break;case'v':c='\v';break;case'x':if(jsonmode){warningAt("Avoid \\x-.",line,character);}
+esc(2);break;default:warningAt("Bad escapement.",line,character);}}
+r+=c;character+=1;}
+errorAt("Unclosed string.",line,from);}
+for(;;){if(!s){return it(nextLine()?'(endline)':'(end)','');}
+t=match(tx);if(!t){t='';c='';while(s&&s<'!'){s=s.substr(1);}
+if(s){errorAt("Unexpected '{a}'.",line,character,s.substr(0,1));}}
+if(c.isAlpha()||c==='_'||c==='$'){return it('(identifier)',t);}
+if(c.isDigit()){if(!isFinite(Number(t))){warningAt("Bad number '{a}'.",line,character,t);}
+if(s.substr(0,1).isAlpha()){warningAt("Missing space after '{a}'.",line,character,t);}
+if(c==='0'){d=t.substr(1,1);if(d.isDigit()){warningAt("Don't use extra leading zeros '{a}'.",line,character,t);}else if(jsonmode&&(d==='x'||d==='X')){warningAt("Avoid 0x-. '{a}'.",line,character,t);}}
+if(t.substr(t.length-1)==='.'){warningAt("A trailing decimal point can be confused with a dot '{a}'.",line,character,t);}
+return it('(number)',t);}
+switch(t){case'"':case"'":return string(t);case'//':s='';break;case'/*':for(;;){i=s.search(lx);if(i>=0){break;}
+if(!nextLine()){errorAt("Unclosed comment.",line,character);}}
+character+=i+2;if(s.substr(i,1)==='/'){errorAt("Nested comment.",line,character);}
+s=s.substr(i+2);break;case'/*extern':case'/*global':case'/*members':case'/*member':case'/*jslint':case'*/':return{value:t,type:'special',line:line,character:character,from:from};case'':break;case'/':if(prereg){r=rx.exec(s);if(r){c=r[0];l=c.length;character+=l;s=s.substr(l);return it('(regex)',c);}
+errorAt("Bad regular expression.",line,character);}
+return it('(punctuator)',t);default:return it('(punctuator)',t);}}},skip:function(p){var i,t=p;if(nexttoken.id){if(!t){t='';if(nexttoken.id.substr(0,1)==='<'){lookahead.push(nexttoken);return true;}}else if(nexttoken.id.indexOf(t)>=0){return true;}}
+token=nexttoken;nexttoken=syntax['(end)'];for(;;){i=s.indexOf(t||'<');if(i>=0){character+=i+t.length;s=s.substr(i+t.length);return true;}
+if(!nextLine()){break;}}
+return false;}};}();function addlabel(t,type){if(t==='hasOwnProperty'){error("'hasOwnProperty' is a really bad name.");}
+if(funct===true){scope[t]=true;}else{if(funct.hasOwnProperty(t)){warning(funct[t]===true?"'{a}' was used before it was defined.":"'{a}' is already defined.",nexttoken,t);}
+scope[t]=funct;funct[t]=type;}}
+function doOption(){var b,obj,filter,t,v;switch(nexttoken.value){case'*/':error("Unbegun comment.");break;case'/*extern':case'/*global':obj=globals;break;case'/*members':case'/*member':if(!membersOnly){membersOnly={};}
+obj=membersOnly;break;case'/*jslint':if(option.adsafe){error("Adsafe restriction.");}
+obj=option;filter=allOptions;}
+for(;;){t=lex.token();if(t.id===','){t=lex.token();}
+while(t.id==='(endline)'){t=lex.token();}
+if(t.type==='special'&&t.value==='*/'){break;}
+if(t.type!=='(string)'&&t.type!=='(identifier)'){error("Bad option.",t);}
+if(filter){if(filter[t.value]!==true){error("Bad option.",t);}
+v=lex.token();if(v.id!==':'){error("Expected '{a}' and instead saw '{b}'.",t,':',t.value);}
+v=lex.token();if(v.value==='true'){b=true;}else if(v.value==='false'){b=false;}else{error("Expected '{a}' and instead saw '{b}'.",t,'true',t.value);}}else{b=true;}
+obj[t.value]=b;}
+if(filter){populateGlobals();}}
+function peek(p){var i=p||0,j=0,t;while(j<=i){t=lookahead[j];if(!t){t=lookahead[j]=lex.token();}
+j+=1;}
+return t;}
+var badbreak={')':true,']':true,'++':true,'--':true};function advance(id,t){var l;switch(token.id){case'(number)':if(nexttoken.id==='.'){warning("A dot following a number can be confused with a decimal point.",token);}
+break;case'-':if(nexttoken.id==='-'||nexttoken.id==='--'){warning("Confusing minusses.");}
+break;case'+':if(nexttoken.id==='+'||nexttoken.id==='++'){warning("Confusing plusses.");}
+break;}
+if(token.type==='(string)'||token.identifier){anonname=token.value;}
+if(id&&nexttoken.id!==id){if(t){if(nexttoken.id==='(end)'){warning("Unmatched '{a}'.",t,t.id);}else{warning("Expected '{a}' to match '{b}' from line {c} and instead saw '{d}'.",nexttoken,id,t.id,t.line+1,nexttoken.value);}}else{warning("Expected '{a}' and instead saw '{b}'.",nexttoken,id,nexttoken.value);}}
+prevtoken=token;token=nexttoken;for(;;){nexttoken=lookahead.shift()||lex.token();if(nexttoken.type==='special'){doOption();}else{if(nexttoken.id==='<!['){if(xtype==='html'){error("Unexpected '{a}'.",nexttoken,'<![');}
+if(xmode==='script'){nexttoken=lex.token();if(nexttoken.value!=='CDATA'){error("Missing '{a}'.",nexttoken,'CDATA');}
+nexttoken=lex.token();if(nexttoken.id!=='['){error("Missing '{a}'.",nexttoken,'[');}
+xmode='CDATA';}else if(xmode==='xml'){lex.skip(']]>');}else{error("Unexpected '{a}'.",nexttoken,'<![');}}else if(nexttoken.id===']]>'){if(xmode==='CDATA'){xmode='script';}else{error("Unexpected '{a}'.",nexttoken,']]>');}}else if(nexttoken.id!=='(endline)'){break;}
+if(xmode==='"'||xmode==="'"){error("Missing '{a}'.",token,xmode);}
+l=!xmode&&!option.laxbreak&&(token.type==='(string)'||token.type==='(number)'||token.type==='(identifier)'||badbreak[token.id]);}}
+if(l){switch(nexttoken.id){case'{':case'}':case']':break;case')':switch(token.id){case')':case'}':case']':break;default:warning("Line breaking error '{a}'.",token,')');}
+break;default:warning("Line breaking error '{a}'.",token,token.value);}}
+if(xtype==='widget'&&xmode==='script'&&nexttoken.id){l=nexttoken.id.charAt(0);if(l==='<'||l==='&'){nexttoken.nud=nexttoken.led=null;nexttoken.lbp=0;nexttoken.reach=true;}}}
+function parse(rbp,initial){var left;var o;if(nexttoken.id==='(end)'){error("Unexpected early end of program.",token);}
+advance();if(initial){anonname='anonymous';verb=token.value;}
+if(initial&&token.fud){token.fud();}else{if(token.nud){o=token.exps;left=token.nud();}else{if(nexttoken.type==='(number)'&&token.id==='.'){warning("A leading decimal point can be confused with a dot: '.{a}'.",token,nexttoken.value);advance();return token;}else{error("Expected an identifier and instead saw '{a}'.",token,token.id);}}
+while(rbp<nexttoken.lbp){o=nexttoken.exps;advance();if(token.led){left=token.led(left);}else{error("Expected an operator and instead saw '{a}'.",token,token.id);}}
+if(initial&&!o){warning("Expected an assignment or function call and instead saw an expression.",token);}}
+if(!option.evil&&left&&left.value==='eval'){warning("eval is evil.",left);}
+return left;}
+function adjacent(left,right){left=left||token;right=right||nexttoken;if(option.white){if(left.character!==right.from){warning("Unexpected space after '{a}'.",nexttoken,left.value);}}}
+function nospace(left,right){left=left||token;right=right||nexttoken;if(option.white){if(left.line===right.line){adjacent(left,right);}}}
+function nonadjacent(left,right){left=left||token;right=right||nexttoken;if(option.white){if(left.character===right.from){warning("Missing space after '{a}'.",nexttoken,left.value);}}}
+function indentation(bias){var i;if(option.white&&nexttoken.id!=='(end)'){i=indent+(bias||0);if(nexttoken.from!==i){warning("Expected '{a}' to have an indentation of {b} instead of {c}.",nexttoken,nexttoken.value,i,nexttoken.from);}}}
+function symbol(s,p){return syntax[s]||(syntax[s]={id:s,lbp:p,value:s});}
+function delim(s){return symbol(s,0);}
+function stmt(s,f){var x=delim(s);x.identifier=x.reserved=true;x.fud=f;return x;}
+function blockstmt(s,f){var x=stmt(s,f);x.block=true;return x;}
+function reserveName(x){var c=x.id.charAt(0);if((c>='a'&&c<='z')||(c>='A'&&c<='Z')){x.identifier=x.reserved=true;}
+return x;}
+function prefix(s,f){var x=symbol(s,150);reserveName(x);x.nud=(typeof f==='function')?f:function(){if(option.plusplus&&(this.id==='++'||this.id==='--')){warning("Unexpected use of '{a}'.",this,this.id);}
+parse(150);return this;};return x;}
+function type(s,f){var x=delim(s);x.type=s;x.nud=f;return x;}
+function reserve(s,f){var x=type(s,f);x.identifier=x.reserved=true;return x;}
+function reservevar(s){return reserve(s,function(){return this;});}
+function infix(s,f,p){var x=symbol(s,p);reserveName(x);x.led=(typeof f==='function')?f:function(left){nonadjacent(prevtoken,token);nonadjacent(token,nexttoken);return[this.id,left,parse(p)];};return x;}
+function relation(s,f){var x=symbol(s,100);x.led=function(left){nonadjacent(prevtoken,token);nonadjacent(token,nexttoken);var right=parse(100);if((left&&left.id==='NaN')||(right&&right.id==='NaN')){warning("Use the isNaN function to compare with NaN.",this);}else if(f){f.apply(this,[left,right]);}
+return[this.id,left,right];};return x;}
+function isPoorRelation(node){return(node.type==='(number)'&&!+node.value)||(node.type==='(string)'&&!node.value)||node.type==='true'||node.type==='false'||node.type==='undefined'||node.type==='null';}
+function assignop(s,f){symbol(s,20).exps=true;return infix(s,function(left){nonadjacent(prevtoken,token);nonadjacent(token,nexttoken);if(left){if(left.id==='.'||left.id==='['||(left.identifier&&!left.reserved)){parse(19);return left;}
+if(left===syntax['function']){warning("Expected an identifier in an assignment and instead saw a function invocation.",token);}}
+error("Bad assignment.",this);},20);}
+function bitwise(s,f,p){var x=symbol(s,p);reserveName(x);x.led=(typeof f==='function')?f:function(left){if(option.bitwise){warning("Unexpected use of '{a}'.",this,this.id);}
+nonadjacent(prevtoken,token);nonadjacent(token,nexttoken);return[this.id,left,parse(p)];};return x;}
+function bitwiseassignop(s){symbol(s,20).exps=true;return infix(s,function(left){if(option.bitwise){warning("Unexpected use of '{a}'.",this,this.id);}
+nonadjacent(prevtoken,token);nonadjacent(token,nexttoken);if(left){if(left.id==='.'||left.id==='['||(left.identifier&&!left.reserved)){parse(19);return left;}
+if(left===syntax['function']){warning("Expected an identifier in an assignment, and instead saw a function invocation.",token);}}
+error("Bad assignment.",this);},20);}
+function suffix(s,f){var x=symbol(s,150);x.led=function(left){if(option.plusplus){warning("Unexpected use of '{a}'.",this,this.id);}
+return[f,left];};return x;}
+function optionalidentifier(){if(nexttoken.reserved){warning("Expected an identifier and instead saw '{a}' (a reserved word).",nexttoken,nexttoken.id);}
+if(nexttoken.identifier){if(option.nomen){if(nexttoken.value.charAt(0)==='_'||nexttoken.value.indexOf('$')>=0){warning("Unexpected characters in '{a}'.",nexttoken,nexttoken.value);}}
+advance();return token.value;}}
+function identifier(){var i=optionalidentifier();if(i){return i;}
+if(token.id==='function'&&nexttoken.id==='('){warning("Missing name in function statement.");}else{error("Expected an identifier and instead saw '{a}'.",nexttoken,nexttoken.value);}}
+function reachable(s){var i=0;var t;if(nexttoken.id!==';'||noreach){return;}
+for(;;){t=peek(i);if(t.reach){return;}
+if(t.id!=='(endline)'){if(t.id==='function'){warning("Inner functions should be listed at the top of the outer function.",t);break;}
+warning("Unreachable '{a}' after '{b}'.",t,t.value,s);break;}
+i+=1;}}
+function statement(){var i=indent,s=scope,t=nexttoken;if(t.id===';'){warning("Unnecessary semicolon.",t);advance(';');return;}
+if(t.identifier&&!t.reserved&&peek().id===':'){advance();advance(':');scope=s.begetObject();addlabel(t.value,'label');if(!nexttoken.labelled){warning("Label '{a}' on {b} statement.",nexttoken,t.value,nexttoken.value);}
+if(jx.test(t.value+':')){warning("Label '{a}' looks like a javascript url.",t,t.value);}
+nexttoken.label=t.value;t=nexttoken;}
+parse(0,true);if(!t.block){if(nexttoken.id!==';'){warningAt("Missing semicolon.",token.line,token.from+token.value.length);}else{adjacent(token,nexttoken);advance(';');nonadjacent(token,nexttoken);}}
+indent=i;scope=s;}
+function statements(){while(!nexttoken.reach&&nexttoken.id!=='(end)'){if(nexttoken.id===';'){warning("Unnecessary semicolon.");advance(';');}
+indentation();statement();}}
+function block(f){var b=inblock,s=scope;inblock=f;if(f){scope=scope.begetObject();}
+nonadjacent(token,nexttoken);var t=nexttoken;if(nexttoken.id==='{'){advance('{');if(nexttoken.id!=='}'||token.line!==nexttoken.line){indent+=4;if(!f&&nexttoken.from===indent+4){indent+=4;}
+statements();indent-=4;indentation();}
+advance('}',t);}else{warning("Expected '{a}' and instead saw '{b}'.",nexttoken,'{',nexttoken.value);noreach=true;statement();noreach=false;}
+verb=null;scope=s;inblock=b;}
+function idValue(){return this;}
+function countMember(m){if(membersOnly&&membersOnly[m]!==true){warning("Unexpected member '{a}'.",nexttoken,m);}
+if(typeof member[m]==='number'){member[m]+=1;}else{member[m]=1;}}
+var scriptstring={onblur:true,onchange:true,onclick:true,ondblclick:true,onfocus:true,onkeydown:true,onkeypress:true,onkeyup:true,onload:true,onmousedown:true,onmousemove:true,onmouseout:true,onmouseover:true,onmouseup:true,onreset:true,onselect:true,onsubmit:true,onunload:true};var xmltype={HTML:{doBegin:function(n){if(!option.cap){warning("HTML case error.");}
+xmltype.html.doBegin();}},html:{doBegin:function(n){xtype='html';xmltype.html.script=false;option.browser=true;populateGlobals();},doTagName:function(n,p){var i;var t=xmltype.html.tag[n];var x;if(!t){error("Unrecognized tag '<{a}>'.",nexttoken,n===n.toLowerCase()?n:n+' (capitalization error)');}
+x=t.parent;if(x){if(x.indexOf(' '+p+' ')<0){error("A '<{a}>' must be within '<{b}>'.",token,n,x);}}else{i=stack.length;do{if(i<=0){error("A '<{a}>' must be within '<{b}>'.",token,n,'body');}
+i-=1;}while(stack[i].name!=='body');}
+xmltype.html.script=n==='script';return t.empty;},doAttribute:function(n,a){if(n==='script'){if(a==='src'){xmltype.html.script=false;return'string';}else if(a==='language'){warning("The 'language' attribute is deprecated.",token);return false;}}
+if(a==='href'){return'href';}
+return scriptstring[a]&&'script';},doIt:function(n){return xmltype.html.script?'script':n!=='html'&&xmltype.html.tag[n].special&&'special';},tag:{a:{},abbr:{},acronym:{},address:{},applet:{},area:{empty:true,parent:' map '},b:{},base:{empty:true,parent:' head '},bdo:{},big:{},blockquote:{},body:{parent:' html noframes '},br:{empty:true},button:{},canvas:{parent:' body p div th td '},caption:{parent:' table '},center:{},cite:{},code:{},col:{empty:true,parent:' table colgroup '},colgroup:{parent:' table '},dd:{parent:' dl '},del:{},dfn:{},dir:{},div:{},dl:{},dt:{parent:' dl '},em:{},embed:{},fieldset:{},font:{},form:{},frame:{empty:true,parent:' frameset '},frameset:{parent:' html frameset '},h1:{},h2:{},h3:{},h4:{},h5:{},h6:{},head:{parent:' html '},html:{},hr:{empty:true},i:{},iframe:{},img:{empty:true},input:{empty:true},ins:{},kbd:{},label:{},legend:{parent:' fieldset '},li:{parent:' dir menu ol ul '},link:{empty:true,parent:' head '},map:{},menu:{},meta:{empty:true,paren!
 t:' head noscript '},noframes:{parent:' html body '},noscript:{parent:' applet blockquote body button center dd del div fieldset form frameset head html iframe ins li map noframes noscript object td th '},object:{},ol:{},optgroup:{parent:' select '},option:{parent:' optgroup select '},p:{},param:{empty:true,parent:' applet object '},pre:{},q:{},samp:{},script:{parent:' head body p div span abbr acronym address bdo blockquote cite code del dfn em ins kbd pre samp strong table tbody td th tr var '},select:{},small:{},span:{},strong:{},style:{parent:' head ',special:true},sub:{},sup:{},table:{},tbody:{parent:' table '},td:{parent:' tr '},textarea:{},tfoot:{parent:' table '},th:{parent:' tr '},thead:{parent:' table '},title:{parent:' head '},tr:{parent:' table tbody thead tfoot '},tt:{},u:{},ul:{},'var':{}}},widget:{doBegin:function(n){xtype='widget';option.widget=true;populateGlobals();},doTagName:function(n,p){var t=xmltype.widget.tag[n];if(!t){error("Unrecognized tag '<{a}>'!
 .",nexttoken,n);}
+var x=t.parent;if(x.indexOf(' '+p+' ')<0){error("A '<{a}>' must be within '<{b}>'.",token,n,x);}},doAttribute:function(n,a){var t=xmltype.widget.tag[a];if(!t){error("Unrecognized attribute '<{a} {b}>'.",nexttoken,n,a);}
+var x=t.parent;if(x.indexOf(' '+n+' ')<0){error("Attribute '{a}' does not belong in '<{b}>'.",nexttoken,a,n);}
+return t.script?'script':a==='name'&&n!=='setting'?'define':'string';},doIt:function(n){var x=xmltype.widget.tag[n];return x&&x.script&&'script';},tag:{"about-box":{parent:' widget '},"about-image":{parent:' about-box '},"about-text":{parent:' about-box '},"about-version":{parent:' about-box '},action:{parent:' widget ',script:true},alignment:{parent:' canvas frame image scrollbar text textarea window '},anchorStyle:{parent:' text '},author:{parent:' widget '},autoHide:{parent:' scrollbar '},beget:{parent:' canvas frame image scrollbar text window '},bgColor:{parent:' text textarea '},bgColour:{parent:' text textarea '},bgOpacity:{parent:' text textarea '},canvas:{parent:' frame window '},checked:{parent:' image menuItem '},clipRect:{parent:' image '},color:{parent:' about-text about-version shadow text textarea '},colorize:{parent:' image '},colour:{parent:' about-text about-version shadow text textarea '},columns:{parent:' textarea '},company:{parent:' widget '},contextMe!
 nuItems:{parent:' canvas frame image scrollbar text textarea window '},copyright:{parent:' widget '},data:{parent:' about-text about-version text textarea '},debug:{parent:' widget '},defaultValue:{parent:' preference '},defaultTracking:{parent:' widget '},description:{parent:' preference '},directory:{parent:' preference '},editable:{parent:' textarea '},enabled:{parent:' menuItem '},extension:{parent:' preference '},file:{parent:' action preference '},fillMode:{parent:' image '},font:{parent:' about-text about-version text textarea '},fontStyle:{parent:' textarea '},frame:{parent:' frame window '},group:{parent:' preference '},hAlign:{parent:' canvas frame image scrollbar text textarea '},handleLinks:{parent:' textArea '},height:{parent:' canvas frame image scrollbar text textarea window '},hidden:{parent:' preference '},hLineSize:{parent:' frame '},hOffset:{parent:' about-text about-version canvas frame image scrollbar shadow text textarea window '},hotkey:{parent:' widg!
 et '},hRegistrationPoint:{parent:' canvas frame image scrollbar text '
},hScrollBar:{parent:' frame '},hslAdjustment:{parent:' image '},hslTinting:{parent:' image '},icon:{parent:' preferenceGroup '},id:{parent:' canvas frame hotkey image preference text textarea timer scrollbar widget window '},image:{parent:' about-box frame window widget '},interval:{parent:' action timer '},key:{parent:' hotkey '},kind:{parent:' preference '},level:{parent:' window '},lines:{parent:' textarea '},loadingSrc:{parent:' image '},locked:{parent:' window '},max:{parent:' scrollbar '},maxLength:{parent:' preference '},menuItem:{parent:' contextMenuItems '},min:{parent:' scrollbar '},minimumVersion:{parent:' widget '},minLength:{parent:' preference '},missingSrc:{parent:' image '},modifier:{parent:' hotkey '},name:{parent:' canvas frame hotkey image preference preferenceGroup scrollbar setting text textarea timer widget window '},notSaved:{parent:' preference '},onClick:{parent:' canvas frame image scrollbar text textarea ',script:true},onContextMenu:{parent:' canv!
 as frame image scrollbar text textarea window ',script:true},onDragDrop:{parent:' canvas frame image scrollbar text textarea ',script:true},onDragEnter:{parent:' canvas frame image scrollbar text textarea ',script:true},onDragExit:{parent:' canvas frame image scrollbar text textarea ',script:true},onFirstDisplay:{parent:' window ',script:true},onGainFocus:{parent:' textarea window ',script:true},onKeyDown:{parent:' hotkey text textarea window ',script:true},onKeyPress:{parent:' textarea window ',script:true},onKeyUp:{parent:' hotkey text textarea window ',script:true},onImageLoaded:{parent:' image ',script:true},onLoseFocus:{parent:' textarea window ',script:true},onMouseDown:{parent:' canvas frame image scrollbar text textarea window ',script:true},onMouseDrag:{parent:' canvas frame image scrollbar text textArea window ',script:true},onMouseEnter:{parent:' canvas frame image scrollbar text textarea window ',script:true},onMouseExit:{parent:' canvas frame image scrollbar te!
 xt textarea window ',script:true},onMouseMove:{parent:' canvas frame i
mage scrollbar text textarea window ',script:true},onMouseUp:{parent:' canvas frame image scrollbar text textarea window ',script:true},onMouseWheel:{parent:' frame ',script:true},onMultiClick:{parent:' canvas frame image scrollbar text textarea window ',script:true},onSelect:{parent:' menuItem ',script:true},onTextInput:{parent:' window ',script:true},onTimerFired:{parent:' timer ',script:true},onValueChanged:{parent:' scrollbar ',script:true},opacity:{parent:' canvas frame image scrollbar shadow text textarea window '},option:{parent:' preference widget '},optionValue:{parent:' preference '},order:{parent:' preferenceGroup '},orientation:{parent:' scrollbar '},pageSize:{parent:' scrollbar '},preference:{parent:' widget '},preferenceGroup:{parent:' widget '},remoteAsync:{parent:' image '},requiredPlatform:{parent:' widget '},root:{parent:' window '},rotation:{parent:' canvas frame image scrollbar text '},scrollbar:{parent:' frame text textarea window '},scrolling:{parent:' !
 text '},scrollX:{parent:' frame '},scrollY:{parent:' frame '},secure:{parent:' preference textarea '},setting:{parent:' settings '},settings:{parent:' widget '},shadow:{parent:' about-text about-version text window '},size:{parent:' about-text about-version text textarea '},spellcheck:{parent:' textarea '},src:{parent:' image '},srcHeight:{parent:' image '},srcWidth:{parent:' image '},style:{parent:' about-text about-version canvas frame image preference scrollbar text textarea window '},subviews:{parent:' frame '},superview:{parent:' canvas frame image scrollbar text textarea '},text:{parent:' frame text textarea window '},textarea:{parent:' frame window '},timer:{parent:' widget '},thumbColor:{parent:' scrollbar textarea '},ticking:{parent:' timer '},ticks:{parent:' preference '},tickLabel:{parent:' preference '},tileOrigin:{parent:' image '},title:{parent:' menuItem preference preferenceGroup window '},tooltip:{parent:' frame image text textarea '},tracking:{parent:' can!
 vas image '},trigger:{parent:' action '},truncation:{parent:' text '},
type:{parent:' preference '},url:{parent:' about-box about-text about-version '},useFileIcon:{parent:' image '},vAlign:{parent:' canvas frame image scrollbar text textarea '},value:{parent:' preference scrollbar setting '},version:{parent:' widget '},visible:{parent:' canvas frame image scrollbar text textarea window '},vLineSize:{parent:' frame '},vOffset:{parent:' about-text about-version canvas frame image scrollbar shadow text textarea window '},vRegistrationPoint:{parent:' canvas frame image scrollbar text '},vScrollBar:{parent:' frame '},width:{parent:' canvas frame image scrollbar text textarea window '},window:{parent:' canvas frame image scrollbar text textarea widget '},wrap:{parent:' text '},zOrder:{parent:' canvas frame image scrollbar text textarea window '}}}};function xmlword(tag){var w=nexttoken.value;if(!nexttoken.identifier){if(nexttoken.id==='<'){if(tag){error("Expected '{a}' and instead saw '{b}'.",token,'&lt;','<');}else{error("Missing '{a}'.",token,'>')!
 ;}}else if(nexttoken.id==='(end)'){error("Bad structure.");}else{warning("Missing quote.",token);}}
+advance();while(nexttoken.id==='-'||nexttoken.id===':'){w+=nexttoken.id;advance();if(!nexttoken.identifier){error("Bad name '{a}'.",nexttoken,w+nexttoken.value);}
+w+=nexttoken.value;advance();}
+return w;}
+function closetag(n){return'</'+n+'>';}
+function xml(){var a,e,n,q,t;xmode='xml';stack=null;for(;;){switch(nexttoken.value){case'<':if(!stack){stack=[];}
+advance('<');t=nexttoken;n=xmlword(true);t.name=n;if(!xtype){if(xmltype[n]){xmltype[n].doBegin();n=xtype;e=false;}else{if(option.fragment){xmltype.html.doBegin();stack=[{name:'body'}];e=xmltype[xtype].doTagName(n,'body');}else{error("Unrecognized tag '<{a}>'.",nexttoken,n);}}}else{if(option.cap&&xtype==='html'){n=n.toLowerCase();}
+if(stack.length===0){error("What the hell is this?");}
+e=xmltype[xtype].doTagName(n,stack[stack.length-1].name);}
+t.type=n;for(;;){if(nexttoken.id==='/'){advance('/');e=true;break;}
+if(nexttoken.id&&nexttoken.id.substr(0,1)==='>'){break;}
+a=xmlword();switch(xmltype[xtype].doAttribute(n,a)){case'script':xmode='string';advance('=');q=nexttoken.id;if(q!=='"'&&q!=="'"){error("Missing quote.");}
+xmode=q;wmode=option.white;option.white=false;advance(q);statements();option.white=wmode;if(nexttoken.id!==q){error("Missing close quote on script attribute.");}
+xmode='xml';advance(q);break;case'value':advance('=');if(!nexttoken.identifier&&nexttoken.type!=='(string)'&&nexttoken.type!=='(number)'){error("Bad value '{a}'.",nexttoken,nexttoken.value);}
+advance();break;case'string':case'href':advance('=');if(nexttoken.type!=='(string)'){error("Bad value '{a}'.",nexttoken,nexttoken.value);}
+advance();break;case'define':advance('=');if(nexttoken.type!=='(string)'){error("Bad value '{a}'.",nexttoken,nexttoken.value);}
+addlabel(nexttoken.value,'var');advance();break;default:if(nexttoken.id==='='){advance('=');if(!nexttoken.identifier&&nexttoken.type!=='(string)'&&nexttoken.type!=='(number)'){}
+advance();}}}
+switch(xmltype[xtype].doIt(n)){case'script':xmode='script';advance('>');indent=nexttoken.from;statements();if(nexttoken.id!=='</'&&nexttoken.id!=='(end)'){warning("Unexpected '{a}'.",nexttoken,nexttoken.id);}
+xmode='xml';break;case'special':e=true;n=closetag(t.name);if(!lex.skip(n)){error("Missing '{a}'.",t,n);}
+break;default:lex.skip('>');}
+if(!e){stack.push(t);}
+break;case'</':advance('</');n=xmlword(true);t=stack.pop();if(!t){error("Unexpected '{a}'.",nexttoken,closetag(n));}
+if(t.name!==n){error("Expected '{a}' and instead saw '{b}'.",nexttoken,closetag(t.name),closetag(n));}
+if(nexttoken.id!=='>'){error("Missing '{a}'.",nexttoken,'>');}
+if(stack.length>0){lex.skip('>');}else{advance('>');}
+break;case'<!':for(;;){advance();if(nexttoken.id==='>'){break;}
+if(nexttoken.id==='<'||nexttoken.id==='(end)'){error("Missing '{a}'.",token,'>');}}
+lex.skip('>');break;case'<!--':lex.skip('-->');break;case'<%':lex.skip('%>');break;case'<?':for(;;){advance();if(nexttoken.id==='?>'){break;}
+if(nexttoken.id==='<?'||nexttoken.id==='<'||nexttoken.id==='>'||nexttoken.id==='(end)'){error("Missing '{a}'.",token,'?>');}}
+lex.skip('?>');break;case'<=':case'<<':case'<<=':error("Missing '{a}'.",nexttoken,'&lt;');break;case'(end)':return;}
+if(stack&&stack.length===0){return;}
+if(!lex.skip('')){t=stack.pop();if(t.value){error("Missing '{a}'.",t,closetag(t.name));}else{return;}}
+advance();}}
+type('(number)',idValue);type('(string)',idValue);syntax['(identifier)']={type:'(identifier)',lbp:0,identifier:true,nud:function(){var v=this.value,s=scope[v];if(s===funct){if(funct!==true){switch(funct[v]){case'unused':funct[v]='var';break;case'label':warning("'{a}' is a statement label.",token,v);break;}}}else if(funct===true){if(option.undef){warning("'{a}' is undefined.",token,v);}else{implied[v]=true;globals[v]=true;}}else{switch(funct[v]){case'closure':case'function':case'var':case'unused':warning("'{a}' used out of scope.",token,v);break;case'label':warning("'{a}' is a statement label.",token,v);break;case'outer':case true:break;default:if(s===true){funct[v]=true;}else if(typeof s!=='object'){if(option.undef){warning("'{a}' is undefined.",token,v);}else{implied[v]=true;globals[v]=true;funct[v]=true;}}else{switch(s[v]){case'function':case'var':case'unused':s[v]='closure';funct[v]='outer';break;case'closure':case'parameter':funct[v]='outer';break;case'label':warning("'!
 {a}' is a statement label.",token,v);}}}}
+return this;},led:function(){error("Expected an operator and instead saw '{a}'.",nexttoken,nexttoken.value);}};type('(regex)',function(){return[this.id,this.value,this.flags];});delim('(endline)');delim('(begin)');delim('(end)').reach=true;delim('</').reach=true;delim('<![').reach=true;delim('<%');delim('<?');delim('<!');delim('<!--');delim('%>');delim('?>');delim('(error)').reach=true;delim('}').reach=true;delim(')');delim(']');delim(']]>').reach=true;delim('"').reach=true;delim("'").reach=true;delim(';');delim(':').reach=true;delim(',');reserve('else');reserve('case').reach=true;reserve('catch');reserve('default').reach=true;reserve('finally');reservevar('arguments');reservevar('eval');reservevar('false');reservevar('Infinity');reservevar('NaN');reservevar('null');reservevar('this');reservevar('true');reservevar('undefined');assignop('=','assign',20);assignop('+=','assignadd',20);assignop('-=','assignsub',20);assignop('*=','assignmult',20);assignop('/=','assigndiv',20).nu!
 d=function(){error("A regular expression literal can be confused with '/='.");};assignop('%=','assignmod',20);bitwiseassignop('&=','assignbitand',20);bitwiseassignop('|=','assignbitor',20);bitwiseassignop('^=','assignbitxor',20);bitwiseassignop('<<=','assignshiftleft',20);bitwiseassignop('>>=','assignshiftright',20);bitwiseassignop('>>>=','assignshiftrightunsigned',20);infix('?',function(left){parse(10);advance(':');parse(10);},30);infix('||','or',40);infix('&&','and',50);bitwise('|','bitor',70);bitwise('^','bitxor',80);bitwise('&','bitand',90);relation('==',function(left,right){if(option.eqeqeq){warning("Expected '{a}' and instead saw '{b}'.",this,'===','==');}else if(isPoorRelation(left)){warning("Use '{a}' to compare with '{b}'.",this,'===',left.value);}else if(isPoorRelation(right)){warning("Use '{a}' to compare with '{b}'.",this,'===',right.value);}
+return['==',left,right];});relation('===');relation('!=',function(left,right){if(option.eqeqeq){warning("Expected '{a}' and instead saw '{b}'.",this,'!==','!=');}else if(isPoorRelation(left)){warning("Use '{a}' to compare with '{b}'.",this,'!==',left.value);}else if(isPoorRelation(right)){warning("Use '{a}' to compare with '{b}'.",this,'!==',right.value);}
+return['!=',left,right];});relation('!==');relation('<');relation('>');relation('<=');relation('>=');bitwise('<<','shiftleft',120);bitwise('>>','shiftright',120);bitwise('>>>','shiftrightunsigned',120);infix('in','in',120);infix('instanceof','instanceof',120);infix('+',function(left){nonadjacent(prevtoken,token);nonadjacent(token,nexttoken);var right=parse(130);if(left&&right&&left.id==='(string)'&&right.id==='(string)'){left.value+=right.value;left.character=right.character;if(option.adsafe&&adsafe[left.value.toLowerCase()]===true){warning("Adsafe restricted word '{a}'.",left,left.value);}
+if(jx.test(left.value)){warning("JavaScript URL.",left);}
+return left;}
+return[this.id,left,right];},130);prefix('+','num');infix('-','sub',130);prefix('-','neg');infix('*','mult',140);infix('/','div',140);infix('%','mod',140);suffix('++','postinc');prefix('++','preinc');syntax['++'].exps=true;suffix('--','postdec');prefix('--','predec');syntax['--'].exps=true;prefix('delete',function(){var p=parse(0);if(p.id!=='.'&&p.id!=='['){warning("Expected '{a}' and instead saw '{b}'.",nexttoken,'.',nexttoken.value);}}).exps=true;prefix('~',function(){if(option.bitwise){warning("Unexpected '{a}'.",this,'~');}
+parse(150);return this;});prefix('!','not');prefix('typeof','typeof');prefix('new',function(){var c=parse(155),i;if(c){if(c.identifier){c['new']=true;switch(c.value){case'Object':warning("Use the object literal notation {}.",token);break;case'Array':warning("Use the array literal notation [].",token);break;case'Number':case'String':case'Boolean':warning("Do not use the {a} function as a constructor.",token,c.value);break;case'Function':if(!option.evil){warning("The Function constructor is eval.");}
+break;default:if(c.id!=='function'){i=c.value.substr(0,1);if(i<'A'||i>'Z'){warning("A constructor name should start with an uppercase letter.",token);}}}}else{if(c.id!=='.'&&c.id!=='['&&c.id!=='('){warning("Bad constructor.",token);}}}else{warning("Weird construction. Delete 'new'.",this);}
+adjacent(token,nexttoken);if(nexttoken.id==='('){advance('(');nospace();if(nexttoken.id!==')'){for(;;){parse(10);if(nexttoken.id!==','){break;}
+advance(',');}}
+advance(')');nospace(prevtoken,token);}else{warning("Missing '()' invoking a constructor.");}
+return syntax['function'];});syntax['new'].exps=true;infix('.',function(left){adjacent(prevtoken,token);var m=identifier();if(typeof m==='string'){countMember(m);}
+if(!option.evil&&left&&left.value==='document'&&(m==='write'||m==='writeln')){warning("document.write can be a form of eval.",left);}
+this.left=left;this.right=m;return this;},160);infix('(',function(left){adjacent(prevtoken,token);nospace();var n=0;var p=[];if(left&&left.type==='(identifier)'){if(left.value.match(/^[A-Z](.*[a-z].*)?$/)){if(left.value!=='Number'&&left.value!=='String'&&left.value!=='Boolean'&&left.value!=='Date'){warning("Missing 'new' prefix when invoking a constructor.",left);}}}
+if(nexttoken.id!==')'){for(;;){p[p.length]=parse(10);n+=1;if(nexttoken.id!==','){break;}
+advance(',');nonadjacent(token,nexttoken);}}
+advance(')');nospace(prevtoken,token);if(typeof left==='object'){if(left.value==='parseInt'&&n===1){warning("Missing radix parameter.",left);}
+if(!option.evil){if(left.value==='eval'||left.value==='Function'){warning("eval is evil.",left);}else if(p[0]&&p[0].id==='(string)'&&(left.value==='setTimeout'||left.value==='setInterval')){warning("Implied eval is evil. Pass a function instead of a string.",left);}}
+if(!left.identifier&&left.id!=='.'&&left.id!=='['&&left.id!=='('){warning("Bad invocation.",left);}}
+return syntax['function'];},155).exps=true;prefix('(',function(){nospace();var v=parse(0);advance(')',this);nospace(prevtoken,token);return v;});infix('[',function(left){nospace();var e=parse(0),s;if(e&&e.type==='(string)'){countMember(e.value);if(ix.test(e.value)){s=syntax[e.value];if(!s||!s.reserved){warning("['{a}'] is better written in dot notation.",e,e.value);}}}
+advance(']',this);nospace(prevtoken,token);this.left=left;this.right=e;return this;},160);prefix('[',function(){if(nexttoken.id===']'){advance(']');return;}
+var b=token.line!==nexttoken.line;if(b){indent+=4;if(nexttoken.from===indent+4){indent+=4;}}
+for(;;){if(b&&token.line!==nexttoken.line){indentation();}
+parse(10);if(nexttoken.id===','){adjacent(token,nexttoken);advance(',');if(nexttoken.id===','||nexttoken.id===']'){warning("Extra comma.",token);}
+nonadjacent(token,nexttoken);}else{if(b){indent-=4;indentation();}
+advance(']',this);return;}}},160);(function(x){x.nud=function(){var i,s;if(nexttoken.id==='}'){advance('}');return;}
+var b=token.line!==nexttoken.line;if(b){indent+=4;if(nexttoken.from===indent+4){indent+=4;}}
+for(;;){if(b){indentation();}
+i=optionalidentifier(true);if(!i){if(nexttoken.id==='(string)'){i=nexttoken.value;if(ix.test(i)){s=syntax[i];}
+advance();}else if(nexttoken.id==='(number)'){i=nexttoken.value.toString();advance();}else{error("Expected '{a}' and instead saw '{b}'.",nexttoken,'}',nexttoken.value);}}
+countMember(i);advance(':');nonadjacent(token,nexttoken);parse(10);if(nexttoken.id===','){adjacent(token,nexttoken);advance(',');if(nexttoken.id===','||nexttoken.id==='}'){warning("Extra comma.",token);}
+nonadjacent(token,nexttoken);}else{if(b){indent-=4;indentation();}
+advance('}',this);return;}}};x.fud=function(){error("Expected to see a statement and instead saw a block.");};})(delim('{'));function varstatement(){for(;;){nonadjacent(token,nexttoken);addlabel(identifier(),'unused');if(nexttoken.id==='='){nonadjacent(token,nexttoken);advance('=');nonadjacent(token,nexttoken);if(peek(0).id==='='){error("Variable {a} was not declared correctly.",nexttoken,nexttoken.value);}
+parse(20);}
+if(nexttoken.id!==','){return;}
+adjacent(token,nexttoken);advance(',');nonadjacent(token,nexttoken);}}
+stmt('var',varstatement);stmt('new',function(){error("'new' should not be used as a statement.");});function functionparams(){var i,t=nexttoken,p=[];advance('(');nospace();if(nexttoken.id===')'){advance(')');nospace(prevtoken,token);return;}
+for(;;){i=identifier();p.push(i);addlabel(i,'parameter');if(nexttoken.id===','){advance(',');nonadjacent(token,nexttoken);}else{advance(')',t);nospace(prevtoken,token);return p.join(', ');}}}
+function doFunction(i){var s=scope;scope=s.begetObject();funct={'(name)':i||'"'+anonname+'"','(line)':nexttoken.line+1,'(context)':funct};functions.push(funct);if(i){addlabel(i,'function');}
+funct['(params)']=functionparams();block(false);scope=s;funct=funct['(context)'];}
+blockstmt('function',function(){if(inblock){warning("Function statements cannot be placed in blocks. Use a function expression or move the statement to the top of the outer function.",token);}
+var i=identifier();adjacent(token,nexttoken);addlabel(i,'unused');doFunction(i);if(nexttoken.id==='('&&nexttoken.line===token.line){error("Function statements are not invocable. Wrap the function expression in parens.");}});prefix('function',function(){var i=optionalidentifier();if(i){adjacent(token,nexttoken);}else{nonadjacent(token,nexttoken);}
+doFunction(i);});blockstmt('if',function(){var t=nexttoken;advance('(');nonadjacent(this,t);nospace();parse(20);if(nexttoken.id==='='){warning("Assignment in control part.");advance('=');parse(20);}
+advance(')',t);nospace(prevtoken,token);block(true);if(nexttoken.id==='else'){nonadjacent(token,nexttoken);advance('else');if(nexttoken.id==='if'||nexttoken.id==='switch'){statement();}else{block(true);}}});blockstmt('try',function(){var b,e;block(true);if(nexttoken.id==='catch'){advance('catch');nonadjacent(token,nexttoken);advance('(');e=nexttoken.value;if(nexttoken.type!=='(identifier)'){warning("Expected an identifier and instead saw '{a}'.",nexttoken,e);}else{addlabel(e,'unused');}
+advance();advance(')');block(false);b=true;}
+if(nexttoken.id==='finally'){advance('finally');block(false);return;}else if(!b){error("Expected '{a}' and instead saw '{b}'.",nexttoken,'catch',nexttoken.value);}});blockstmt('while',function(){var t=nexttoken;advance('(');nonadjacent(this,t);nospace();parse(20);if(nexttoken.id==='='){warning("Assignment in control part.");advance('=');parse(20);}
+advance(')',t);nospace(prevtoken,token);block(true);}).labelled=true;reserve('with');blockstmt('switch',function(){var t=nexttoken;var g=false;advance('(');nonadjacent(this,t);nospace();this.condition=parse(20);advance(')',t);nospace(prevtoken,token);nonadjacent(token,nexttoken);t=nexttoken;advance('{');nonadjacent(token,nexttoken);indent+=4;this.cases=[];for(;;){switch(nexttoken.id){case'case':switch(verb){case'break':case'case':case'continue':case'return':case'switch':case'throw':break;default:warning("Expected a 'break' statement before 'case'.",token);}
+indentation(-4);advance('case');this.cases.push(parse(20));g=true;advance(':');verb='case';break;case'default':switch(verb){case'break':case'continue':case'return':case'throw':break;default:warning("Expected a 'break' statement before 'default'.",token);}
+indentation(-4);advance('default');g=true;advance(':');break;case'}':indent-=4;indentation();advance('}',t);if(this.cases.length===1||this.condition.id==='true'||this.condition.id==='false'){warning("This 'switch' should be an 'if'.",this);}
+return;case'(end)':error("Missing '{a}'.",nexttoken,'}');return;default:if(g){switch(token.id){case',':error("Each value should have its own case label.");return;case':':statements();break;default:error("Missing ':' on a case clause.",token);}}else{error("Expected '{a}' and instead saw '{b}'.",nexttoken,'case',nexttoken.value);}}}}).labelled=true;stmt('debugger',function(){if(!option.debug){warning("All 'debugger' statements should be removed.");}});stmt('do',function(){block(true);advance('while');var t=nexttoken;nonadjacent(token,t);advance('(');nospace();parse(20);advance(')',t);nospace(prevtoken,token);}).labelled=true;blockstmt('for',function(){var t=nexttoken;advance('(');nonadjacent(this,t);nospace();if(peek(nexttoken.id==='var'?1:0).id==='in'){if(nexttoken.id==='var'){advance('var');addlabel(identifier(),'var');}else{advance();}
+advance('in');parse(20);advance(')',t);block(true);return;}else{if(nexttoken.id!==';'){if(nexttoken.id==='var'){advance('var');varstatement();}else{for(;;){parse(0);if(nexttoken.id!==','){break;}
+advance(',');}}}
+advance(';');if(nexttoken.id!==';'){parse(20);}
+advance(';');if(nexttoken.id===';'){error("Expected '{a}' and instead saw '{b}'.",nexttoken,')',';');}
+if(nexttoken.id!==')'){for(;;){parse(0);if(nexttoken.id!==','){break;}
+advance(',');}}
+advance(')',t);nospace(prevtoken,token);block(true);}}).labelled=true;function nolinebreak(t){if(t.line!==nexttoken.line){warning("Line breaking error '{a}'.",t,t.id);}}
+stmt('break',function(){var v=nexttoken.value;nolinebreak(this);if(nexttoken.id!==';'){if(funct===true){warning("Put '{a}' and the statement it labels in a function.",nexttoken,v);}else if(funct[v]!=='label'){warning("'{a}' is not a statement label.",nexttoken,v);}else if(scope[v]!==funct){warning("'{a}' is out of scope.",nexttoken,v);}
+advance();}
+reachable('break');});stmt('continue',function(){var v=nexttoken.value;nolinebreak(this);if(nexttoken.id!==';'){if(funct===true){warning("Put '{a}' and the statement it labels in a function.",nexttoken,v);}else if(funct[v]!=='label'){warning("'{a}' is not a statement label.",nexttoken,v);}else if(scope[v]!==funct){warning("'{a}' is out of scope.",nexttoken,v);}
+advance();}
+reachable('continue');});stmt('return',function(){nolinebreak(this);if(nexttoken.id!==';'&&!nexttoken.reach){nonadjacent(token,nexttoken);parse(20);}
+reachable('return');});stmt('throw',function(){nolinebreak(this);nonadjacent(token,nexttoken);parse(20);reachable('throw');});reserve('abstract');reserve('boolean');reserve('byte');reserve('char');reserve('class');reserve('const');reserve('double');reserve('enum');reserve('export');reserve('extends');reserve('final');reserve('float');reserve('goto');reserve('implements');reserve('import');reserve('int');reserve('interface');reserve('long');reserve('native');reserve('package');reserve('private');reserve('protected');reserve('public');reserve('short');reserve('static');reserve('super');reserve('synchronized');reserve('throws');reserve('transient');reserve('void');reserve('volatile');function jsonValue(){function jsonObject(){var t=nexttoken;advance('{');if(nexttoken.id!=='}'){for(;;){if(nexttoken.id==='(end)'){error("Missing '}' to match '{' from line {a}.",nexttoken,t.line+1);}else if(nexttoken.id==='}'){warning("Unexpected comma.",token);break;}else if(nexttoken.id===','){e!
 rror("Unexpected comma.",nexttoken);}else if(nexttoken.id!=='(string)'){warning("Expected a string and instead saw {a}.",nexttoken,nexttoken.value);}
+advance();advance(':');jsonValue();if(nexttoken.id!==','){break;}
+advance(',');}}
+advance('}');}
+function jsonArray(){var t=nexttoken;advance('[');if(nexttoken.id!==']'){for(;;){if(nexttoken.id==='(end)'){error("Missing ']' to match '[' from line {a}.",nexttoken,t.line+1);}else if(nexttoken.id===']'){warning("Unexpected comma.",token);break;}else if(nexttoken.id===','){error("Unexpected comma.",nexttoken);}
+jsonValue();if(nexttoken.id!==','){break;}
+advance(',');}}
+advance(']');}
+switch(nexttoken.id){case'{':jsonObject();break;case'[':jsonArray();break;case'true':case'false':case'null':case'(number)':case'(string)':advance();break;case'-':advance('-');if(token.character!==nexttoken.from){warning("Unexpected space after '-'.",token);}
+adjacent(token,nexttoken);advance('(number)');break;default:error("Expected a JSON value.",nexttoken);}}
+var itself=function(s,o){option=o||{};JSLINT.errors=[];globals=standard.begetObject();scope=globals.begetObject();funct=true;functions=[];xmode=false;xtype='';stack=null;member={};membersOnly=null;implied={};inblock=false;lookahead=[];indent=0;jsonmode=false;warnings=0;lex.init(s);prereg=true;prevtoken=token=nexttoken=syntax['(begin)'];populateGlobals();try{advance();if(nexttoken.value.charAt(0)==='<'){xml();}else if(nexttoken.id==='{'||nexttoken.id==='['){option.laxbreak=true;jsonmode=true;jsonValue();}else{statements();}
+advance('(end)');}catch(e){if(e){JSLINT.errors.push({reason:e.message,line:e.line||nexttoken.line,character:e.character||nexttoken.from},null);}}
+return JSLINT.errors.length===0;};itself.report=function(option){var a=[],c,e,f,i,k,l,m='',n,o=[],s,v,cl,va,un,ou,gl,la;function detail(h,s){if(s.length){o.push('<div><i>'+h+'</i> '+
+s.sort().join(', ')+'</div>');}}
+s=[];for(k in implied){if(implied.hasOwnProperty(k)){s.push(k);}}
+k=JSLINT.errors.length;if(k||s.length>0){o.push('<div id=errors><i>Error:</i>');if(s.length>0){o.push('<p><i>Implied global:</i> '+s.sort().join(', ')+'</p>');c=true;}
+for(i=0;i<k;i+=1){c=JSLINT.errors[i];if(c){e=c.evidence||'';o.push('<p>Problem at line '+(c.line+1)+' character '+(c.character+1)+': '+c.reason.entityify()+'</p><p class=evidence>'+
+(e&&(e.length>80?e.substring(0,77)+'...':e).entityify())+'</p>');}}
+o.push('</div>');if(!c){return o.join('');}}
+if(!option){o.push('<div id=functions>');s=[];for(k in scope){if(scope.hasOwnProperty(k)){s.push(k);}}
+if(s.length===0){o.push('<div><i>No new global variables introduced.</i></div>');}else{o.push('<div><i>Global</i> '+s.join(', ')+'</div>');}
+for(i=0;i<functions.length;i+=1){f=functions[i];cl=[];va=[];un=[];ou=[];gl=[];la=[];for(k in f){if(f.hasOwnProperty(k)){v=f[k];switch(v){case'closure':cl.push(k);break;case'var':va.push(k);break;case'unused':un.push(k);break;case'label':la.push(k);break;case'outer':ou.push(k);break;case true:if(k!=='(context)'){gl.push(k);}
+break;}}}
+o.push('<br><div class=function><i>'+f['(line)']+'</i> '+
+(f['(name)']||'')+'('+
+(f['(params)']||'')+')</div>');detail('Closure',cl);detail('Variable',va);detail('Unused',un);detail('Label',la);detail('Outer',ou);detail('Global',gl);}
+for(k in member){if(typeof member[k]==='number'){a.push(k);}}
+if(a.length){a=a.sort();m='<br><div class=function>/*members ';l=10;for(i=0;i<a.length;i+=1){k=a[i];n=k.name();if(l+n.length>72){o.push(m+'</div>');m='<div> ';l=1;}
+l+=n.length+2;if(member[k]===1){n='<i>'+n+'</i>';}
+if(i<a.length-1){n+=', ';}
+m+=n;}
+o.push(m+' */</div>');}
+o.push('</div>');}
+return o.join('');};return itself;}();(function(a){if(!a[0]){print("Usage: jslint.js file.js");quit(1);}
+var input=readFile(a[0]);if(!input){print("jslint: Couldn't open file '"+a[0]+"'.");quit(1);}
+if(!JSLINT(input,{rhino:true,passfail:false})){for(var i=0;i<JSLINT.errors.length;i+=1){var e=JSLINT.errors[i];if(e){print('Lint at line '+(e.line+1)+' character '+
+(e.character+1)+': '+e.reason);print((e.evidence||'').replace(/^\s*(\S*(\s+\S+)*)\s*$/,"$1"));print('');}}}else{print("jslint: No problems found in "+a[0]);quit();}})(arguments);
\ No newline at end of file

Added: trunk/cdk/maven-javascript-plugin/src/test/java/net/sf/alchim/mojo/yuicompressor/AggregationTestCase.java
===================================================================
--- trunk/cdk/maven-javascript-plugin/src/test/java/net/sf/alchim/mojo/yuicompressor/AggregationTestCase.java	                        (rev 0)
+++ trunk/cdk/maven-javascript-plugin/src/test/java/net/sf/alchim/mojo/yuicompressor/AggregationTestCase.java	2007-12-11 23:30:42 UTC (rev 4755)
@@ -0,0 +1,177 @@
+package net.sf.alchim.mojo.yuicompressor;
+
+import java.io.File;
+
+import junit.framework.TestCase;
+
+import org.codehaus.plexus.util.FileUtils;
+
+public class AggregationTestCase extends TestCase {
+    private File dir_;
+
+    @Override
+    protected void setUp() throws Exception {
+        dir_ = File.createTempFile(this.getClass().getName(), "-test");
+        dir_.delete();
+        dir_.mkdirs();
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        FileUtils.deleteDirectory(dir_);
+    }
+
+    public void test0to1() throws Exception {
+        Aggregation target = new Aggregation();
+        target.output = new File(dir_, "output.js");
+
+        assertFalse(target.output.exists());
+        target.run(dir_);
+        assertFalse(target.output.exists());
+
+        target.includes = new String[]{};
+        assertFalse(target.output.exists());
+        target.run(dir_);
+        assertFalse(target.output.exists());
+
+        target.includes = new String[]{"**/*.js"};
+        assertFalse(target.output.exists());
+        target.run(dir_);
+        assertFalse(target.output.exists());
+    }
+
+
+    public void test1to1() throws Exception {
+        File f1 = new File(dir_, "01.js");
+        FileUtils.fileWrite(f1.getAbsolutePath(), "1");
+        Aggregation target = new Aggregation();
+        target.output = new File(dir_, "output.js");
+        target.includes = new String[]{f1.getName()};
+
+        assertFalse(target.output.exists());
+        target.run(dir_);
+        assertTrue(target.output.exists());
+        assertEquals(FileUtils.fileRead(f1), FileUtils.fileRead(target.output));
+    }
+
+    public void test2to1() throws Exception {
+        File f1 = new File(dir_, "01.js");
+        FileUtils.fileWrite(f1.getAbsolutePath(), "1");
+
+        File f2 = new File(dir_, "02.js");
+        FileUtils.fileWrite(f2.getAbsolutePath(), "22\n22");
+
+        Aggregation target = new Aggregation();
+        target.output = new File(dir_, "output.js");
+
+        target.includes = new String[]{f1.getName(), f2.getName()};
+        assertFalse(target.output.exists());
+        target.run(dir_);
+        assertTrue(target.output.exists());
+        assertEquals(FileUtils.fileRead(f1) + FileUtils.fileRead(f2), FileUtils.fileRead(target.output));
+
+        target.output.delete();
+        target.includes = new String[]{"*.js"};
+        assertFalse(target.output.exists());
+        target.run(dir_);
+        assertTrue(target.output.exists());
+//        assertEquals(FileUtils.fileRead(f1) + FileUtils.fileRead(f2), FileUtils.fileRead(target.output));
+    }
+
+    public void testNoDuplicateAggregation() throws Exception {
+        File f1 = new File(dir_, "01.js");
+        FileUtils.fileWrite(f1.getAbsolutePath(), "1");
+
+        File f2 = new File(dir_, "02.js");
+        FileUtils.fileWrite(f2.getAbsolutePath(), "22\n22");
+
+        Aggregation target = new Aggregation();
+        target.output = new File(dir_, "output.js");
+
+        target.includes = new String[]{f1.getName(), f1.getName(), f2.getName()};
+        assertFalse(target.output.exists());
+        target.run(dir_);
+        assertTrue(target.output.exists());
+        assertEquals(FileUtils.fileRead(f1) + FileUtils.fileRead(f2), FileUtils.fileRead(target.output));
+
+        target.output.delete();
+        target.includes = new String[]{f1.getName(), "*.js"};
+        assertFalse(target.output.exists());
+        target.run(dir_);
+        assertTrue(target.output.exists());
+        assertEquals(FileUtils.fileRead(f1) + FileUtils.fileRead(f2), FileUtils.fileRead(target.output));
+    }
+
+    public void test2to1Order() throws Exception {
+        File f1 = new File(dir_, "01.js");
+        FileUtils.fileWrite(f1.getAbsolutePath(), "1");
+
+        File f2 = new File(dir_, "02.js");
+        FileUtils.fileWrite(f2.getAbsolutePath(), "2");
+
+        Aggregation target = new Aggregation();
+        target.output = new File(dir_, "output.js");
+
+        target.includes = new String[]{f2.getName(), f1.getName()};
+        assertFalse(target.output.exists());
+        target.run(dir_);
+        assertTrue(target.output.exists());
+        assertEquals(FileUtils.fileRead(f2) + FileUtils.fileRead(f1), FileUtils.fileRead(target.output));
+    }
+
+    public void test2to1WithNewLine() throws Exception {
+        File f1 = new File(dir_, "01.js");
+        FileUtils.fileWrite(f1.getAbsolutePath(), "1");
+
+        File f2 = new File(dir_, "02.js");
+        FileUtils.fileWrite(f2.getAbsolutePath(), "22\n22");
+
+        Aggregation target = new Aggregation();
+        target.output = new File(dir_, "output.js");
+        target.insertNewLine = true;
+        target.includes = new String[]{f1.getName(), f2.getName()};
+
+        assertFalse(target.output.exists());
+        target.run(dir_);
+        assertTrue(target.output.exists());
+        assertEquals(FileUtils.fileRead(f1) + "\n" + FileUtils.fileRead(f2) + "\n", FileUtils.fileRead(target.output));
+    }
+
+    public void testAbsolutePathFromInside() throws Exception {
+        File f1 = new File(dir_, "01.js");
+        FileUtils.fileWrite(f1.getAbsolutePath(), "1");
+
+        File f2 = new File(dir_, "02.js");
+        FileUtils.fileWrite(f2.getAbsolutePath(), "22\n22");
+
+        Aggregation target = new Aggregation();
+        target.output = new File(dir_, "output.js");
+
+        target.includes = new String[]{f1.getAbsolutePath(), f2.getName()};
+        assertFalse(target.output.exists());
+        target.run(dir_);
+        assertTrue(target.output.exists());
+        assertEquals(FileUtils.fileRead(f1) + FileUtils.fileRead(f2), FileUtils.fileRead(target.output));
+    }
+
+    public void testAbsolutePathFromOutside() throws Exception {
+        File f1 = File.createTempFile("test-01", ".js");
+        try {
+            FileUtils.fileWrite(f1.getAbsolutePath(), "1");
+
+            File f2 = new File(dir_, "02.js");
+            FileUtils.fileWrite(f2.getAbsolutePath(), "22\n22");
+
+            Aggregation target = new Aggregation();
+            target.output = new File(dir_, "output.js");
+
+            target.includes = new String[]{f1.getAbsolutePath(), f2.getName()};
+            assertFalse(target.output.exists());
+            target.run(dir_);
+            assertTrue(target.output.exists());
+            assertEquals(FileUtils.fileRead(f1) + FileUtils.fileRead(f2), FileUtils.fileRead(target.output));
+        } finally {
+            f1.delete();
+        }
+    }
+}


Property changes on: trunk/cdk/maven-javascript-plugin/src/test/java/net/sf/alchim/mojo/yuicompressor/AggregationTestCase.java
___________________________________________________________________
Name: svn:mime-type
   + text/plain
Name: svn:keywords
   + Date Revision Author

Modified: trunk/cdk/pom.xml
===================================================================
--- trunk/cdk/pom.xml	2007-12-11 23:02:12 UTC (rev 4754)
+++ trunk/cdk/pom.xml	2007-12-11 23:30:42 UTC (rev 4755)
@@ -27,9 +27,11 @@
 		</pluginManagement>
 	</build>
 	<modules>
+		<module>generator</module>
 		<module>maven-cdk-plugin</module>
-		<module>generator</module>
+		<module>maven-javascript-plugin</module>
 		<module>maven-archetype-jsf-component</module>
 		<module>maven-archetype-jsfwebapp</module>
+		
 	</modules>
 </project>
\ No newline at end of file

Modified: trunk/extensions/portletbridge/portletbridge-impl/src/main/java/org/ajax4jsf/portlet/context/PortletContextImpl.java
===================================================================
--- trunk/extensions/portletbridge/portletbridge-impl/src/main/java/org/ajax4jsf/portlet/context/PortletContextImpl.java	2007-12-11 23:02:12 UTC (rev 4754)
+++ trunk/extensions/portletbridge/portletbridge-impl/src/main/java/org/ajax4jsf/portlet/context/PortletContextImpl.java	2007-12-11 23:30:42 UTC (rev 4755)
@@ -31,6 +31,7 @@
 import javax.portlet.PortletSession;
 import javax.portlet.RenderRequest;
 import javax.portlet.RenderResponse;
+import javax.portlet.PortletURL;
 import javax.portlet.faces.Bridge;
 
 import org.ajax4jsf.webapp.WebXml;
@@ -235,8 +236,17 @@
 	 */
 	@Override
 	protected String createActionUrl(Map<String, String> parameters){
-		return "/ajax4jsfPortletBridge/actionUrl/do/nothitg";
-	}
+		RenderResponse renderResponse = (RenderResponse) getPortletResponse();
+		PortletURL portletURL = renderResponse.createActionURL();
+		portletURL.setParameter(AbstractExternalContext.NAMESPACE_PARAMETER,
+				renderResponse.getNamespace());
+		for (Iterator<Map.Entry<String, String>> param = parameters.entrySet()
+				.iterator(); param.hasNext();) {
+			Map.Entry<String, String> parameter = param.next();
+			portletURL.setParameter(parameter.getKey(), parameter.getValue());
+		}
+		return portletURL.toString();
+   }
 
 	public String encodeResourceURL(String url) {
 		return encodeURL(url);
@@ -247,7 +257,7 @@
 	 * @return
 	 */
 	protected String encodeURL(String url) {
-		return getPortletResponse().encodeURL(url);
+      return getPortletResponse().encodeURL(url);
 	}
 
 	public String getAuthType() {
@@ -307,11 +317,11 @@
 	}
 
 	public void redirect(String url) throws IOException {
-		if (null == url) {
+		if (null == url || url.length() < 0) {
 			throw new NullPointerException("Path to redirect is null");
 		}
 		PortalActionURL actionURL = new PortalActionURL(url);
-		if(url.startsWith("#") || (!actionURL.isInContext(getRequestContextPath())) || "true".equalsIgnoreCase(actionURL.getParameter(Bridge.DIRECT_LINK))){
+      if(url.startsWith("#") || (!actionURL.isInContext(getRequestContextPath())) || "true".equalsIgnoreCase(actionURL.getParameter(Bridge.DIRECT_LINK))){
 			((ActionResponse) getResponse()).sendRedirect(url);
 		}
 	}

Modified: trunk/extensions/portletbridge/portletbridge-impl/src/main/java/org/ajax4jsf/portlet/context/PortletRenderContextImpl.java
===================================================================
--- trunk/extensions/portletbridge/portletbridge-impl/src/main/java/org/ajax4jsf/portlet/context/PortletRenderContextImpl.java	2007-12-11 23:02:12 UTC (rev 4754)
+++ trunk/extensions/portletbridge/portletbridge-impl/src/main/java/org/ajax4jsf/portlet/context/PortletRenderContextImpl.java	2007-12-11 23:30:42 UTC (rev 4755)
@@ -91,9 +91,11 @@
 			throw new NullPointerException("Path to redirect is null");
 		}
 		PortalActionURL actionURL = new PortalActionURL(url);
-		if(!actionURL.isInContext(getRequestContextPath()) || "true".equalsIgnoreCase(actionURL.getParameter(Bridge.DIRECT_LINK))){
-			throw new IllegalStateException(
-			"Redirect to new url not at action phase");
+      if(!actionURL.isInContext(getRequestContextPath()) || "true".equalsIgnoreCase(actionURL.getParameter(Bridge.DIRECT_LINK))){
+			dispatch(url);
+
+//         throw new IllegalStateException(
+//			"Redirect to new url not at action phase");
 		}
 		// HACK - if page is in the context, just treat it as navigation case
 	}
@@ -109,14 +111,14 @@
 			Entry<String, String> parameter = param.next();
 			portletURL.setParameter(parameter.getKey(), parameter.getValue());
 		}
-		return portletURL.toString();
+      return portletURL.toString();
 	}
 
 	public void dispatch(String path) throws IOException {
 		if (null == path) {
 			throw new NullPointerException("Path to new view is null");
 		}
-		PortletRequestDispatcher dispatcher = getPortletContext()
+      PortletRequestDispatcher dispatcher = getPortletContext()
 				.getRequestDispatcher(path);
 		if (null == dispatcher) {
 			throw new IllegalStateException(

Modified: trunk/framework/impl/pom.xml
===================================================================
--- trunk/framework/impl/pom.xml	2007-12-11 23:02:12 UTC (rev 4754)
+++ trunk/framework/impl/pom.xml	2007-12-11 23:30:42 UTC (rev 4755)
@@ -64,30 +64,17 @@
 							</resourceRoot>
 						</configuration>
 					</execution>
-					<execution>
-						<id>framevork-javascript</id>
-						<phase>compile</phase>
-						<goals>
-							<goal>run</goal>
-						</goals>
-						<configuration>
-							<tasks>
-								<copy todir="target/classes/org/ajax4jsf" file="target/compressed/framework.pack.js"/>
-							</tasks>
-						</configuration>
-					</execution>
 				</executions>
 			</plugin>
 			      <plugin>
-        <groupId>net.sf.alchim</groupId>
-        <artifactId>yuicompressor-maven-plugin</artifactId>
+        <groupId>org.richfaces.cdk</groupId>
+        <artifactId>maven-javascript-plugin</artifactId>
+        <version>${project.version}</version>
         <executions> 
           <execution>
             <goals>
               <goal>compress</goal>
             </goals>
-          </execution>
-        </executions>        
         <configuration>
           <nosuffix>false</nosuffix>
           <outputDirectory>${project.build.directory}/compressed/</outputDirectory>
@@ -98,7 +85,7 @@
               -->
               <!-- insert new line after each concatenation (default: false) -->
               <insertNewLine>true</insertNewLine>
-              <output>${project.build.directory}/compressed/framework.pack.js</output>
+              <output>${project.build.outputDirectory}/org/ajax4jsf/framework.pack.js</output>
               <!-- files to include, path relative to output's directory or absolute path-->
               <includes>
                 <include>${project.build.directory}/compressed/org/ajax4jsf/javascript/scripts/prototype-min.js</include>
@@ -126,6 +113,25 @@
 			</resource>
 		</resources>
         </configuration>
+            
+          </execution>
+          <execution>
+            <id>jslint</id>
+            <goals>
+              <goal>jslint</goal>
+            </goals>
+            <phase>test</phase>
+        <configuration>
+		<includes><include>**/framework.pack.js</include></includes>
+		<resources>
+			<resource>
+				<directory>${project.build.outputDirectory}</directory>
+			</resource>
+		</resources>
+        </configuration>
+            
+          </execution>
+        </executions>        
       </plugin>
 		</plugins>
 	</build>

Modified: trunk/framework/test/pom.xml
===================================================================
--- trunk/framework/test/pom.xml	2007-12-11 23:02:12 UTC (rev 4754)
+++ trunk/framework/test/pom.xml	2007-12-11 23:30:42 UTC (rev 4755)
@@ -68,5 +68,10 @@
 			<version>2.2.1</version>
 			<optional>true</optional>
 		</dependency>
+		<dependency>
+			<groupId>rhino</groupId>
+			<artifactId>js</artifactId>
+			<version>1.6R7</version>
+		</dependency>
 	</dependencies>
 </project>
\ No newline at end of file

Modified: trunk/samples/seamPortletEar/seamBookingPortlet/pom.xml
===================================================================
--- trunk/samples/seamPortletEar/seamBookingPortlet/pom.xml	2007-12-11 23:02:12 UTC (rev 4754)
+++ trunk/samples/seamPortletEar/seamBookingPortlet/pom.xml	2007-12-11 23:30:42 UTC (rev 4755)
@@ -106,8 +106,8 @@
 			<scope>provided</scope>
 		</dependency>
 		<dependency>
-			<groupId>org.richfaces.extensions</groupId>
-			<artifactId>portlet</artifactId>
+			<groupId>org.richfaces.extensions.portletbridge</groupId>
+			<artifactId>portletbridge-api</artifactId>
 			<version>3.2.0-SNAPSHOT</version>
 			<exclusions>
 				<exclusion>
@@ -121,6 +121,21 @@
 			</exclusions>
 		</dependency>
 		<dependency>
+			<groupId>org.richfaces.extensions.portletbridge</groupId>
+			<artifactId>portletbridge-impl</artifactId>
+			<version>3.2.0-SNAPSHOT</version>
+			<exclusions>
+				<exclusion>
+					<groupId>javax.faces</groupId>
+					<artifactId>jsf-api</artifactId>
+				</exclusion>
+				<exclusion>
+					<groupId>javax.faces</groupId>
+					<artifactId>jsf-impl</artifactId>
+				</exclusion>
+			</exclusions>
+		</dependency>
+		<dependency>
 			<groupId>org.richfaces.ui</groupId>
 			<artifactId>richfaces-ui</artifactId>
 			<version>3.2.0-SNAPSHOT</version>

Modified: trunk/samples/seamPortletEar/seamBookingPortlet/src/main/webapp/WEB-INF/portlet.xml
===================================================================
--- trunk/samples/seamPortletEar/seamBookingPortlet/src/main/webapp/WEB-INF/portlet.xml	2007-12-11 23:02:12 UTC (rev 4754)
+++ trunk/samples/seamPortletEar/seamBookingPortlet/src/main/webapp/WEB-INF/portlet.xml	2007-12-11 23:30:42 UTC (rev 4755)
@@ -19,7 +19,7 @@
 -->
     <expiration-cache>-0</expiration-cache>
     <portlet-info>
-       <title>Ajax Portlet</title>
+       <title>Seam Booking Example Portlet</title>
     </portlet-info>
     <supports>
       <mime-type>text/html</mime-type>

Modified: trunk/samples/seamPortletEar/seamBookingPortlet/src/main/webapp/WEB-INF/seamBookingPortlet-object.xml
===================================================================
--- trunk/samples/seamPortletEar/seamBookingPortlet/src/main/webapp/WEB-INF/seamBookingPortlet-object.xml	2007-12-11 23:02:12 UTC (rev 4754)
+++ trunk/samples/seamPortletEar/seamBookingPortlet/src/main/webapp/WEB-INF/seamBookingPortlet-object.xml	2007-12-11 23:30:42 UTC (rev 4755)
@@ -35,7 +35,7 @@
       <if-exists>overwrite</if-exists>
       <parent-ref>default.default</parent-ref>
 	    <window>
-		    <window-name>otherAjaxportletWindow</window-name>
+		    <window-name>seamBookingPortletWindow</window-name>
 		    <instance-ref>SeamBookingPortletInstance</instance-ref>
 		    <default>true</default>
 		    <region>center</region>




More information about the richfaces-svn-commits mailing list