diff -pruN 20130227+dfsg1-14/debian/changelog 20130227+rhino-1/debian/changelog
--- 20130227+dfsg1-14/debian/changelog	2023-05-20 15:13:17.000000000 +0000
+++ 20130227+rhino-1/debian/changelog	2023-05-25 14:51:03.000000000 +0000
@@ -1,3 +1,18 @@
+closure-compiler (20130227+rhino-1) unstable; urgency=medium
+
+  * QA upload.
+  * Revert to last compatible rhino version because the latest one in Debian is
+    not compatible with this 10! year old version of closure-compiler.
+   - Embed rhino 1.7.7.2 source package into src:closure-compiler.
+   - Build librhino-java from source. Update build_xml.patch and use the local
+     binary package instead of the system library.
+   - Drop build-dependency on librhino-java.
+   - Drop fix-librhino-java-FTBFS.patch.
+   - Update debian/copyright and document the rhino licenses.
+   (Closes: #1036249)
+
+ -- Markus Koschany <apo@debian.org>  Thu, 25 May 2023 16:51:03 +0200
+
 closure-compiler (20130227+dfsg1-14) unstable; urgency=medium
 
   * QA upload.
diff -pruN 20130227+dfsg1-14/debian/control 20130227+rhino-1/debian/control
--- 20130227+dfsg1-14/debian/control	2023-05-20 15:13:17.000000000 +0000
+++ 20130227+rhino-1/debian/control	2023-05-25 14:51:03.000000000 +0000
@@ -12,7 +12,6 @@ Build-Depends:
     libargs4j-java,
     libguava-java (>= 15.0),
     libjsr305-java,
-    librhino-java (>= 1.7.14-2~),
     ant,
     libjarjar-java,
     protobuf-compiler,
diff -pruN 20130227+dfsg1-14/debian/copyright 20130227+rhino-1/debian/copyright
--- 20130227+dfsg1-14/debian/copyright	2023-05-20 15:13:17.000000000 +0000
+++ 20130227+rhino-1/debian/copyright	2023-05-25 14:51:03.000000000 +0000
@@ -40,6 +40,443 @@ Files: debian/*
 Copyright: 2013, Thomas Koch <thomas@koch.ro>
 License: Apache-2.0
 
+Files: rhino/*
+Copyright: 1999-2015, Mozilla
+License: MPL-2.0
+
+Files: rhino/src/org/mozilla/javascript/v8dtoa/*
+Copyright: 2010, the V8 project authors
+License: BSD-3-clause-google
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are
+ met:
+     * Redistributions of source code must retain the above copyright
+       notice, this list of conditions and the following disclaimer.
+     * Redistributions in binary form must reproduce the above
+       copyright notice, this list of conditions and the following
+       disclaimer in the documentation and/or other materials provided
+       with the distribution.
+     * Neither the name of Google Inc. nor the names of its
+       contributors may be used to endorse or promote products derived
+       from this software without specific prior written permission.
+ .
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Files: rhino/toolsrc/org/mozilla/javascript/tools/debugger/treetable/*
+Copyright: 1997-1998 Sun Microsystems, Inc
+License: BSD-3-clause-sun
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+ .
+   - Redistributions of source code must retain the above copyright
+     notice, this list of conditions and the following disclaimer.
+ .
+   - Redistributions in binary form must reproduce the above copyright
+     notice, this list of conditions and the following disclaimer in the
+     documentation and/or other materials provided with the distribution.
+ .
+   - Neither the name of Sun Microsystems nor the names of its
+     contributors may be used to endorse or promote products derived
+     from this software without specific prior written permission.
+ .
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+License: MPL-2.0
+ Mozilla Public License Version 2.0
+ ==================================
+ .
+ 1. Definitions
+ --------------
+ .
+ 1.1. "Contributor"
+     means each individual or legal entity that creates, contributes to
+     the creation of, or owns Covered Software.
+ .
+ 1.2. "Contributor Version"
+     means the combination of the Contributions of others (if any) used
+     by a Contributor and that particular Contributor's Contribution.
+ .
+ 1.3. "Contribution"
+     means Covered Software of a particular Contributor.
+ .
+ 1.4. "Covered Software"
+     means Source Code Form to which the initial Contributor has attached
+     the notice in Exhibit A, the Executable Form of such Source Code
+     Form, and Modifications of such Source Code Form, in each case
+     including portions thereof.
+ .
+ 1.5. "Incompatible With Secondary Licenses"
+     means
+ .
+     (a) that the initial Contributor has attached the notice described
+         in Exhibit B to the Covered Software; or
+ .
+     (b) that the Covered Software was made available under the terms of
+         version 1.1 or earlier of the License, but not also under the
+         terms of a Secondary License.
+ .
+ 1.6. "Executable Form"
+     means any form of the work other than Source Code Form.
+ .
+ 1.7. "Larger Work"
+     means a work that combines Covered Software with other material, in
+     a separate file or files, that is not Covered Software.
+ .
+ 1.8. "License"
+     means this document.
+ .
+ 1.9. "Licensable"
+     means having the right to grant, to the maximum extent possible,
+     whether at the time of the initial grant or subsequently, any and
+     all of the rights conveyed by this License.
+ .
+ 1.10. "Modifications"
+     means any of the following:
+ .
+     (a) any file in Source Code Form that results from an addition to,
+         deletion from, or modification of the contents of Covered
+         Software; or
+ .
+     (b) any new file in Source Code Form that contains any Covered
+         Software.
+ .
+ 1.11. "Patent Claims" of a Contributor
+     means any patent claim(s), including without limitation, method,
+     process, and apparatus claims, in any patent Licensable by such
+     Contributor that would be infringed, but for the grant of the
+     License, by the making, using, selling, offering for sale, having
+     made, import, or transfer of either its Contributions or its
+     Contributor Version.
+ .
+ 1.12. "Secondary License"
+     means either the GNU General Public License, Version 2.0, the GNU
+     Lesser General Public License, Version 2.1, the GNU Affero General
+     Public License, Version 3.0, or any later versions of those
+     licenses.
+ .
+ 1.13. "Source Code Form"
+     means the form of the work preferred for making modifications.
+ .
+ 1.14. "You" (or "Your")
+     means an individual or a legal entity exercising rights under this
+     License. For legal entities, "You" includes any entity that
+     controls, is controlled by, or is under common control with You. For
+     purposes of this definition, "control" means (a) the power, direct
+     or indirect, to cause the direction or management of such entity,
+     whether by contract or otherwise, or (b) ownership of more than
+     fifty percent (50%) of the outstanding shares or beneficial
+     ownership of such entity.
+ .
+ 2. License Grants and Conditions
+ --------------------------------
+ .
+ 2.1. Grants
+ .
+ Each Contributor hereby grants You a world-wide, royalty-free,
+ non-exclusive license:
+ .
+ (a) under intellectual property rights (other than patent or trademark)
+     Licensable by such Contributor to use, reproduce, make available,
+     modify, display, perform, distribute, and otherwise exploit its
+     Contributions, either on an unmodified basis, with Modifications, or
+     as part of a Larger Work; and
+ .
+ (b) under Patent Claims of such Contributor to make, use, sell, offer
+     for sale, have made, import, and otherwise transfer either its
+     Contributions or its Contributor Version.
+ .
+ 2.2. Effective Date
+ .
+ The licenses granted in Section 2.1 with respect to any Contribution
+ become effective for each Contribution on the date the Contributor first
+ distributes such Contribution.
+ .
+ 2.3. Limitations on Grant Scope
+ .
+ The licenses granted in this Section 2 are the only rights granted under
+ this License. No additional rights or licenses will be implied from the
+ distribution or licensing of Covered Software under this License.
+ Notwithstanding Section 2.1(b) above, no patent license is granted by a
+ Contributor:
+ .
+ (a) for any code that a Contributor has removed from Covered Software;
+     or
+ .
+ (b) for infringements caused by: (i) Your and any other third party's
+     modifications of Covered Software, or (ii) the combination of its
+     Contributions with other software (except as part of its Contributor
+     Version); or
+ .
+ (c) under Patent Claims infringed by Covered Software in the absence of
+     its Contributions.
+ .
+ This License does not grant any rights in the trademarks, service marks,
+ or logos of any Contributor (except as may be necessary to comply with
+ the notice requirements in Section 3.4).
+ .
+ 2.4. Subsequent Licenses
+ .
+ No Contributor makes additional grants as a result of Your choice to
+ distribute the Covered Software under a subsequent version of this
+ License (see Section 10.2) or under the terms of a Secondary License (if
+ permitted under the terms of Section 3.3).
+ .
+ 2.5. Representation
+ .
+ Each Contributor represents that the Contributor believes its
+ Contributions are its original creation(s) or it has sufficient rights
+ to grant the rights to its Contributions conveyed by this License.
+ .
+ 2.6. Fair Use
+ .
+ This License is not intended to limit any rights You have under
+ applicable copyright doctrines of fair use, fair dealing, or other
+ equivalents.
+ .
+ 2.7. Conditions
+ .
+ Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted
+ in Section 2.1.
+ .
+ 3. Responsibilities
+ -------------------
+ .
+ 3.1. Distribution of Source Form
+ .
+ All distribution of Covered Software in Source Code Form, including any
+ Modifications that You create or to which You contribute, must be under
+ the terms of this License. You must inform recipients that the Source
+ Code Form of the Covered Software is governed by the terms of this
+ License, and how they can obtain a copy of this License. You may not
+ attempt to alter or restrict the recipients' rights in the Source Code
+ Form.
+ .
+ 3.2. Distribution of Executable Form
+ .
+ If You distribute Covered Software in Executable Form then:
+ .
+ (a) such Covered Software must also be made available in Source Code
+     Form, as described in Section 3.1, and You must inform recipients of
+     the Executable Form how they can obtain a copy of such Source Code
+     Form by reasonable means in a timely manner, at a charge no more
+     than the cost of distribution to the recipient; and
+ .
+ (b) You may distribute such Executable Form under the terms of this
+     License, or sublicense it under different terms, provided that the
+     license for the Executable Form does not attempt to limit or alter
+     the recipients' rights in the Source Code Form under this License.
+ .
+ 3.3. Distribution of a Larger Work
+ .
+ You may create and distribute a Larger Work under terms of Your choice,
+ provided that You also comply with the requirements of this License for
+ the Covered Software. If the Larger Work is a combination of Covered
+ Software with a work governed by one or more Secondary Licenses, and the
+ Covered Software is not Incompatible With Secondary Licenses, this
+ License permits You to additionally distribute such Covered Software
+ under the terms of such Secondary License(s), so that the recipient of
+ the Larger Work may, at their option, further distribute the Covered
+ Software under the terms of either this License or such Secondary
+ License(s).
+ .
+ 3.4. Notices
+ .
+ You may not remove or alter the substance of any license notices
+ (including copyright notices, patent notices, disclaimers of warranty,
+ or limitations of liability) contained within the Source Code Form of
+ the Covered Software, except that You may alter any license notices to
+ the extent required to remedy known factual inaccuracies.
+ .
+ 3.5. Application of Additional Terms
+ .
+ You may choose to offer, and to charge a fee for, warranty, support,
+ indemnity or liability obligations to one or more recipients of Covered
+ Software. However, You may do so only on Your own behalf, and not on
+ behalf of any Contributor. You must make it absolutely clear that any
+ such warranty, support, indemnity, or liability obligation is offered by
+ You alone, and You hereby agree to indemnify every Contributor for any
+ liability incurred by such Contributor as a result of warranty, support,
+ indemnity or liability terms You offer. You may include additional
+ disclaimers of warranty and limitations of liability specific to any
+ jurisdiction.
+ .
+ 4. Inability to Comply Due to Statute or Regulation
+ ---------------------------------------------------
+ .
+ If it is impossible for You to comply with any of the terms of this
+ License with respect to some or all of the Covered Software due to
+ statute, judicial order, or regulation then You must: (a) comply with
+ the terms of this License to the maximum extent possible; and (b)
+ describe the limitations and the code they affect. Such description must
+ be placed in a text file included with all distributions of the Covered
+ Software under this License. Except to the extent prohibited by statute
+ or regulation, such description must be sufficiently detailed for a
+ recipient of ordinary skill to be able to understand it.
+ .
+ 5. Termination
+ --------------
+ .
+ 5.1. The rights granted under this License will terminate automatically
+ if You fail to comply with any of its terms. However, if You become
+ compliant, then the rights granted under this License from a particular
+ Contributor are reinstated (a) provisionally, unless and until such
+ Contributor explicitly and finally terminates Your grants, and (b) on an
+ ongoing basis, if such Contributor fails to notify You of the
+ non-compliance by some reasonable means prior to 60 days after You have
+ come back into compliance. Moreover, Your grants from a particular
+ Contributor are reinstated on an ongoing basis if such Contributor
+ notifies You of the non-compliance by some reasonable means, this is the
+ first time You have received notice of non-compliance with this License
+ from such Contributor, and You become compliant prior to 30 days after
+ Your receipt of the notice.
+ .
+ 5.2. If You initiate litigation against any entity by asserting a patent
+ infringement claim (excluding declaratory judgment actions,
+ counter-claims, and cross-claims) alleging that a Contributor Version
+ directly or indirectly infringes any patent, then the rights granted to
+ You by any and all Contributors for the Covered Software under Section
+ 2.1 of this License shall terminate.
+ .
+ 5.3. In the event of termination under Sections 5.1 or 5.2 above, all
+ end user license agreements (excluding distributors and resellers) which
+ have been validly granted by You or Your distributors under this License
+ prior to termination shall survive termination.
+ .
+ ************************************************************************
+ *                                                                      *
+ *  6. Disclaimer of Warranty                                           *
+ *  -------------------------                                           *
+ *                                                                      *
+ *  Covered Software is provided under this License on an "as is"       *
+ *  basis, without warranty of any kind, either expressed, implied, or  *
+ *  statutory, including, without limitation, warranties that the       *
+ *  Covered Software is free of defects, merchantable, fit for a        *
+ *  particular purpose or non-infringing. The entire risk as to the     *
+ *  quality and performance of the Covered Software is with You.        *
+ *  Should any Covered Software prove defective in any respect, You     *
+ *  (not any Contributor) assume the cost of any necessary servicing,   *
+ *  repair, or correction. This disclaimer of warranty constitutes an   *
+ *  essential part of this License. No use of any Covered Software is   *
+ *  authorized under this License except under this disclaimer.         *
+ *                                                                      *
+ ************************************************************************
+ .
+ ************************************************************************
+ *                                                                      *
+ *  7. Limitation of Liability                                          *
+ *  --------------------------                                          *
+ *                                                                      *
+ *  Under no circumstances and under no legal theory, whether tort      *
+ *  (including negligence), contract, or otherwise, shall any           *
+ *  Contributor, or anyone who distributes Covered Software as          *
+ *  permitted above, be liable to You for any direct, indirect,         *
+ *  special, incidental, or consequential damages of any character      *
+ *  including, without limitation, damages for lost profits, loss of    *
+ *  goodwill, work stoppage, computer failure or malfunction, or any    *
+ *  and all other commercial damages or losses, even if such party      *
+ *  shall have been informed of the possibility of such damages. This   *
+ *  limitation of liability shall not apply to liability for death or   *
+ *  personal injury resulting from such party's negligence to the       *
+ *  extent applicable law prohibits such limitation. Some               *
+ *  jurisdictions do not allow the exclusion or limitation of           *
+ *  incidental or consequential damages, so this exclusion and          *
+ *  limitation may not apply to You.                                    *
+ *                                                                      *
+ ************************************************************************
+ .
+ 8. Litigation
+ -------------
+ .
+ Any litigation relating to this License may be brought only in the
+ courts of a jurisdiction where the defendant maintains its principal
+ place of business and such litigation shall be governed by laws of that
+ jurisdiction, without reference to its conflict-of-law provisions.
+ Nothing in this Section shall prevent a party's ability to bring
+ cross-claims or counter-claims.
+ .
+ 9. Miscellaneous
+ ----------------
+ .
+ This License represents the complete agreement concerning the subject
+ matter hereof. If any provision of this License is held to be
+ unenforceable, such provision shall be reformed only to the extent
+ necessary to make it enforceable. Any law or regulation which provides
+ that the language of a contract shall be construed against the drafter
+ shall not be used to construe this License against a Contributor.
+ .
+ 10. Versions of the License
+ ---------------------------
+ .
+ 10.1. New Versions
+ .
+ Mozilla Foundation is the license steward. Except as provided in Section
+ 10.3, no one other than the license steward has the right to modify or
+ publish new versions of this License. Each version will be given a
+ distinguishing version number.
+ .
+ 10.2. Effect of New Versions
+ .
+ You may distribute the Covered Software under the terms of the version
+ of the License under which You originally received the Covered Software,
+ or under the terms of any subsequent version published by the license
+ steward.
+ .
+ 10.3. Modified Versions
+ .
+ If you create software not governed by this License, and you want to
+ create a new license for such software, you may create and use a
+ modified version of this License if you rename the license and remove
+ any references to the name of the license steward (except to note that
+ such modified license differs from this License).
+ .
+ 10.4. Distributing Source Code Form that is Incompatible With Secondary
+ Licenses
+ .
+ If You choose to distribute Source Code Form that is Incompatible With
+ Secondary Licenses under the terms of this version of the License, the
+ notice described in Exhibit B of this License must be attached.
+ .
+ Exhibit A - Source Code Form License Notice
+ -------------------------------------------
+ .
+   This Source Code Form is subject to the terms of the Mozilla Public
+   License, v. 2.0. If a copy of the MPL was not distributed with this
+   file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ .
+ If it is not possible or desirable to put the notice in a particular
+ file, then You may include the notice in a location (such as a LICENSE
+ file in a relevant directory) where a recipient would be likely to look
+ for such a notice.
+ .
+ You may add additional accurate notices of copyright ownership.
+ .
+ Exhibit B - "Incompatible With Secondary Licenses" Notice
+ ---------------------------------------------------------
+ .
+   This Source Code Form is "Incompatible With Secondary Licenses", as
+ defined by the Mozilla Public License, v. 2.0.
+
 License: GPL-2.0
   On Debian GNU/Linux system you can find the complete text of the
   GPL-2.0 license in '/usr/share/common-licenses/GPL-2'
diff -pruN 20130227+dfsg1-14/debian/patches/build_xml.patch 20130227+rhino-1/debian/patches/build_xml.patch
--- 20130227+dfsg1-14/debian/patches/build_xml.patch	2023-05-20 15:13:17.000000000 +0000
+++ 20130227+rhino-1/debian/patches/build_xml.patch	2023-05-25 14:51:03.000000000 +0000
@@ -48,7 +48,7 @@ Forwarded: not-needed
 +             classpath="${lib.dir}/jarjar.jar"/>
      <jarjar destfile="${buildlib.dir}/rhino.jar" update="true">
 -      <zipfileset src="${buildlib.dir}/rhino1_7R5pre/js.jar"/>
-+      <zipfileset src="${lib.dir}/js.jar"/>
++      <zipfileset src="rhino/build/rhino1.7.7.2/js.jar"/>
        <rule pattern="org.mozilla.javascript.**"
              result="com.google.javascript.rhino.head.@1"/>
      </jarjar>
diff -pruN 20130227+dfsg1-14/debian/patches/fix-librhino-java-FTBFS.patch 20130227+rhino-1/debian/patches/fix-librhino-java-FTBFS.patch
--- 20130227+dfsg1-14/debian/patches/fix-librhino-java-FTBFS.patch	2023-05-20 15:13:17.000000000 +0000
+++ 20130227+rhino-1/debian/patches/fix-librhino-java-FTBFS.patch	1970-01-01 00:00:00.000000000 +0000
@@ -1,65 +0,0 @@
-From: Markus Koschany <apo@debian.org>
-Date: Tue, 14 Feb 2023 00:06:12 +0100
-Subject: fix librhino-java FTBFS
-
-Fix FTBFS with rhino 1.7.14.
-
-Forwarded: not-needed
----
- src/com/google/javascript/jscomp/parsing/IRFactory.java          | 4 ++--
- src/com/google/javascript/jscomp/parsing/TypeSafeDispatcher.java | 6 +++---
- 2 files changed, 5 insertions(+), 5 deletions(-)
-
-diff --git a/src/com/google/javascript/jscomp/parsing/IRFactory.java b/src/com/google/javascript/jscomp/parsing/IRFactory.java
-index 361f31d..0e34a4d 100644
---- a/src/com/google/javascript/jscomp/parsing/IRFactory.java
-+++ b/src/com/google/javascript/jscomp/parsing/IRFactory.java
-@@ -65,7 +65,7 @@ import com.google.javascript.rhino.head.ast.SwitchCase;
- import com.google.javascript.rhino.head.ast.SwitchStatement;
- import com.google.javascript.rhino.head.ast.ThrowStatement;
- import com.google.javascript.rhino.head.ast.TryStatement;
--import com.google.javascript.rhino.head.ast.UnaryExpression;
-+import com.google.javascript.rhino.head.ast.UpdateExpression;
- import com.google.javascript.rhino.head.ast.VariableDeclaration;
- import com.google.javascript.rhino.head.ast.VariableInitializer;
- import com.google.javascript.rhino.head.ast.WhileLoop;
-@@ -1145,7 +1145,7 @@ class IRFactory {
-     }
- 
-     @Override
--    Node processUnaryExpression(UnaryExpression exprNode) {
-+    Node processUpdateExpression(UpdateExpression exprNode) {
-       int type = transformTokenType(exprNode.getType());
-       Node operand = transform(exprNode.getOperand());
-       if (type == Token.NEG && operand.isNumber()) {
-diff --git a/src/com/google/javascript/jscomp/parsing/TypeSafeDispatcher.java b/src/com/google/javascript/jscomp/parsing/TypeSafeDispatcher.java
-index 95aaacd..fc6ace3 100644
---- a/src/com/google/javascript/jscomp/parsing/TypeSafeDispatcher.java
-+++ b/src/com/google/javascript/jscomp/parsing/TypeSafeDispatcher.java
-@@ -55,7 +55,7 @@ import com.google.javascript.rhino.head.ast.SwitchCase;
- import com.google.javascript.rhino.head.ast.SwitchStatement;
- import com.google.javascript.rhino.head.ast.ThrowStatement;
- import com.google.javascript.rhino.head.ast.TryStatement;
--import com.google.javascript.rhino.head.ast.UnaryExpression;
-+import com.google.javascript.rhino.head.ast.UpdateExpression;
- import com.google.javascript.rhino.head.ast.VariableDeclaration;
- import com.google.javascript.rhino.head.ast.VariableInitializer;
- import com.google.javascript.rhino.head.ast.WhileLoop;
-@@ -109,7 +109,7 @@ abstract class TypeSafeDispatcher<T> {
-   abstract T processSwitchStatement(SwitchStatement statementNode);
-   abstract T processThrowStatement(ThrowStatement statementNode);
-   abstract T processTryStatement(TryStatement statementNode);
--  abstract T processUnaryExpression(UnaryExpression exprNode);
-+  abstract T processUpdateExpression(UpdateExpression exprNode);
-   abstract T processVariableDeclaration(VariableDeclaration declarationNode);
-   abstract T processVariableInitializer(VariableInitializer initializerNode);
-   abstract T processWhileLoop(WhileLoop loopNode);
-@@ -168,7 +168,7 @@ abstract class TypeSafeDispatcher<T> {
-       case Token.POS:
-       case Token.TYPEOF:
-       case Token.VOID:
--        return processUnaryExpression((UnaryExpression) node);
-+        return processUpdateExpression((UpdateExpression) node);
-       case Token.BLOCK:
-         if (node instanceof Block) {
-           return processBlock((Block) node);
diff -pruN 20130227+dfsg1-14/debian/patches/series 20130227+rhino-1/debian/patches/series
--- 20130227+dfsg1-14/debian/patches/series	2023-05-20 15:13:17.000000000 +0000
+++ 20130227+rhino-1/debian/patches/series	2023-05-25 14:51:03.000000000 +0000
@@ -3,4 +3,3 @@ remove_tests_depending_on_caja.patch
 guava-compatibility.patch
 ftbfs-commandlinerunner.patch
 ignore-maven-ant-tasks.patch
-fix-librhino-java-FTBFS.patch
diff -pruN 20130227+dfsg1-14/debian/rules 20130227+rhino-1/debian/rules
--- 20130227+dfsg1-14/debian/rules	2023-05-20 15:13:17.000000000 +0000
+++ 20130227+rhino-1/debian/rules	2023-05-25 14:51:03.000000000 +0000
@@ -9,6 +9,7 @@ CP = "/usr/share/java/closure-compiler.j
 	dh $@ --with maven_repo_helper
 
 override_dh_auto_build:
+	cd rhino && dpkg-source --before-build . && debian/rules
 	ant -propertyfile debian/ant.properties jar-nodeps javadoc
 	
 	# update the manifest
diff -pruN 20130227+dfsg1-14/rhino/.gitattributes 20130227+rhino-1/rhino/.gitattributes
--- 20130227+dfsg1-14/rhino/.gitattributes	1970-01-01 00:00:00.000000000 +0000
+++ 20130227+rhino-1/rhino/.gitattributes	2023-05-25 14:24:50.000000000 +0000
@@ -0,0 +1,31 @@
+# Set default behavior, in case users don't have core.autocrlf set.
+* text=auto
+
+.classpath text
+.project text
+*.html text
+*.htm text
+*.java text
+*.js text
+*.jsp text
+*.php text
+*.properties text
+*.sh text
+*.xml text
+*.md text
+*.bat text
+*.gradle text
+*.pl text
+*.mk text
+*.tests text
+*.doctest text
+gradlew text
+manifest text
+LIST text
+
+*.bmp binary
+*.gif binary
+*.jar binary
+*.jpg binary
+*.jpeg binary
+*.png binary
diff -pruN 20130227+dfsg1-14/rhino/.gitignore 20130227+rhino-1/rhino/.gitignore
--- 20130227+dfsg1-14/rhino/.gitignore	1970-01-01 00:00:00.000000000 +0000
+++ 20130227+rhino-1/rhino/.gitignore	2023-05-25 14:24:50.000000000 +0000
@@ -0,0 +1,24 @@
+# os specific
+.DS_Store
+
+# build directories
+build/
+lib/
+buildGradle
+
+# artifacts
+*.zip
+
+*.iml
+.idea/
+out/
+target/
+.gradle
+
+
+*~
+
+# eclipse
+.classpath
+.project
+test262
diff -pruN 20130227+dfsg1-14/rhino/.gitmodules 20130227+rhino-1/rhino/.gitmodules
--- 20130227+dfsg1-14/rhino/.gitmodules	1970-01-01 00:00:00.000000000 +0000
+++ 20130227+rhino-1/rhino/.gitmodules	2023-05-25 14:24:50.000000000 +0000
@@ -0,0 +1,3 @@
+[submodule "test262"]
+	path = test262
+	url = https://github.com/tc39/test262.git
diff -pruN 20130227+dfsg1-14/rhino/.travis.yml 20130227+rhino-1/rhino/.travis.yml
--- 20130227+dfsg1-14/rhino/.travis.yml	1970-01-01 00:00:00.000000000 +0000
+++ 20130227+rhino-1/rhino/.travis.yml	2023-05-25 14:24:50.000000000 +0000
@@ -0,0 +1,13 @@
+language: java
+dist: trusty
+jdk: 
+  - openjdk8
+# Took this stuff from the travis docs:
+before_cache:
+  - rm -f $HOME/.gradle/caches/modules-2/modules-2.lock
+  - rm -f $HOME/.gradle/caches/*/plugin-resolution/
+cache:
+  directories:
+    - $HOME/.gradle/caches
+    - $HOME/.gradle/wrapper
+
diff -pruN 20130227+dfsg1-14/rhino/LICENSE.txt 20130227+rhino-1/rhino/LICENSE.txt
--- 20130227+dfsg1-14/rhino/LICENSE.txt	1970-01-01 00:00:00.000000000 +0000
+++ 20130227+rhino-1/rhino/LICENSE.txt	2023-05-25 14:24:50.000000000 +0000
@@ -0,0 +1,375 @@
+The majority of Rhino is licensed under the MPL 2.0:
+
+Mozilla Public License Version 2.0
+==================================
+
+1. Definitions
+--------------
+
+1.1. "Contributor"
+    means each individual or legal entity that creates, contributes to
+    the creation of, or owns Covered Software.
+
+1.2. "Contributor Version"
+    means the combination of the Contributions of others (if any) used
+    by a Contributor and that particular Contributor's Contribution.
+
+1.3. "Contribution"
+    means Covered Software of a particular Contributor.
+
+1.4. "Covered Software"
+    means Source Code Form to which the initial Contributor has attached
+    the notice in Exhibit A, the Executable Form of such Source Code
+    Form, and Modifications of such Source Code Form, in each case
+    including portions thereof.
+
+1.5. "Incompatible With Secondary Licenses"
+    means
+
+    (a) that the initial Contributor has attached the notice described
+        in Exhibit B to the Covered Software; or
+
+    (b) that the Covered Software was made available under the terms of
+        version 1.1 or earlier of the License, but not also under the
+        terms of a Secondary License.
+
+1.6. "Executable Form"
+    means any form of the work other than Source Code Form.
+
+1.7. "Larger Work"
+    means a work that combines Covered Software with other material, in 
+    a separate file or files, that is not Covered Software.
+
+1.8. "License"
+    means this document.
+
+1.9. "Licensable"
+    means having the right to grant, to the maximum extent possible,
+    whether at the time of the initial grant or subsequently, any and
+    all of the rights conveyed by this License.
+
+1.10. "Modifications"
+    means any of the following:
+
+    (a) any file in Source Code Form that results from an addition to,
+        deletion from, or modification of the contents of Covered
+        Software; or
+
+    (b) any new file in Source Code Form that contains any Covered
+        Software.
+
+1.11. "Patent Claims" of a Contributor
+    means any patent claim(s), including without limitation, method,
+    process, and apparatus claims, in any patent Licensable by such
+    Contributor that would be infringed, but for the grant of the
+    License, by the making, using, selling, offering for sale, having
+    made, import, or transfer of either its Contributions or its
+    Contributor Version.
+
+1.12. "Secondary License"
+    means either the GNU General Public License, Version 2.0, the GNU
+    Lesser General Public License, Version 2.1, the GNU Affero General
+    Public License, Version 3.0, or any later versions of those
+    licenses.
+
+1.13. "Source Code Form"
+    means the form of the work preferred for making modifications.
+
+1.14. "You" (or "Your")
+    means an individual or a legal entity exercising rights under this
+    License. For legal entities, "You" includes any entity that
+    controls, is controlled by, or is under common control with You. For
+    purposes of this definition, "control" means (a) the power, direct
+    or indirect, to cause the direction or management of such entity,
+    whether by contract or otherwise, or (b) ownership of more than
+    fifty percent (50%) of the outstanding shares or beneficial
+    ownership of such entity.
+
+2. License Grants and Conditions
+--------------------------------
+
+2.1. Grants
+
+Each Contributor hereby grants You a world-wide, royalty-free,
+non-exclusive license:
+
+(a) under intellectual property rights (other than patent or trademark)
+    Licensable by such Contributor to use, reproduce, make available,
+    modify, display, perform, distribute, and otherwise exploit its
+    Contributions, either on an unmodified basis, with Modifications, or
+    as part of a Larger Work; and
+
+(b) under Patent Claims of such Contributor to make, use, sell, offer
+    for sale, have made, import, and otherwise transfer either its
+    Contributions or its Contributor Version.
+
+2.2. Effective Date
+
+The licenses granted in Section 2.1 with respect to any Contribution
+become effective for each Contribution on the date the Contributor first
+distributes such Contribution.
+
+2.3. Limitations on Grant Scope
+
+The licenses granted in this Section 2 are the only rights granted under
+this License. No additional rights or licenses will be implied from the
+distribution or licensing of Covered Software under this License.
+Notwithstanding Section 2.1(b) above, no patent license is granted by a
+Contributor:
+
+(a) for any code that a Contributor has removed from Covered Software;
+    or
+
+(b) for infringements caused by: (i) Your and any other third party's
+    modifications of Covered Software, or (ii) the combination of its
+    Contributions with other software (except as part of its Contributor
+    Version); or
+
+(c) under Patent Claims infringed by Covered Software in the absence of
+    its Contributions.
+
+This License does not grant any rights in the trademarks, service marks,
+or logos of any Contributor (except as may be necessary to comply with
+the notice requirements in Section 3.4).
+
+2.4. Subsequent Licenses
+
+No Contributor makes additional grants as a result of Your choice to
+distribute the Covered Software under a subsequent version of this
+License (see Section 10.2) or under the terms of a Secondary License (if
+permitted under the terms of Section 3.3).
+
+2.5. Representation
+
+Each Contributor represents that the Contributor believes its
+Contributions are its original creation(s) or it has sufficient rights
+to grant the rights to its Contributions conveyed by this License.
+
+2.6. Fair Use
+
+This License is not intended to limit any rights You have under
+applicable copyright doctrines of fair use, fair dealing, or other
+equivalents.
+
+2.7. Conditions
+
+Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted
+in Section 2.1.
+
+3. Responsibilities
+-------------------
+
+3.1. Distribution of Source Form
+
+All distribution of Covered Software in Source Code Form, including any
+Modifications that You create or to which You contribute, must be under
+the terms of this License. You must inform recipients that the Source
+Code Form of the Covered Software is governed by the terms of this
+License, and how they can obtain a copy of this License. You may not
+attempt to alter or restrict the recipients' rights in the Source Code
+Form.
+
+3.2. Distribution of Executable Form
+
+If You distribute Covered Software in Executable Form then:
+
+(a) such Covered Software must also be made available in Source Code
+    Form, as described in Section 3.1, and You must inform recipients of
+    the Executable Form how they can obtain a copy of such Source Code
+    Form by reasonable means in a timely manner, at a charge no more
+    than the cost of distribution to the recipient; and
+
+(b) You may distribute such Executable Form under the terms of this
+    License, or sublicense it under different terms, provided that the
+    license for the Executable Form does not attempt to limit or alter
+    the recipients' rights in the Source Code Form under this License.
+
+3.3. Distribution of a Larger Work
+
+You may create and distribute a Larger Work under terms of Your choice,
+provided that You also comply with the requirements of this License for
+the Covered Software. If the Larger Work is a combination of Covered
+Software with a work governed by one or more Secondary Licenses, and the
+Covered Software is not Incompatible With Secondary Licenses, this
+License permits You to additionally distribute such Covered Software
+under the terms of such Secondary License(s), so that the recipient of
+the Larger Work may, at their option, further distribute the Covered
+Software under the terms of either this License or such Secondary
+License(s).
+
+3.4. Notices
+
+You may not remove or alter the substance of any license notices
+(including copyright notices, patent notices, disclaimers of warranty,
+or limitations of liability) contained within the Source Code Form of
+the Covered Software, except that You may alter any license notices to
+the extent required to remedy known factual inaccuracies.
+
+3.5. Application of Additional Terms
+
+You may choose to offer, and to charge a fee for, warranty, support,
+indemnity or liability obligations to one or more recipients of Covered
+Software. However, You may do so only on Your own behalf, and not on
+behalf of any Contributor. You must make it absolutely clear that any
+such warranty, support, indemnity, or liability obligation is offered by
+You alone, and You hereby agree to indemnify every Contributor for any
+liability incurred by such Contributor as a result of warranty, support,
+indemnity or liability terms You offer. You may include additional
+disclaimers of warranty and limitations of liability specific to any
+jurisdiction.
+
+4. Inability to Comply Due to Statute or Regulation
+---------------------------------------------------
+
+If it is impossible for You to comply with any of the terms of this
+License with respect to some or all of the Covered Software due to
+statute, judicial order, or regulation then You must: (a) comply with
+the terms of this License to the maximum extent possible; and (b)
+describe the limitations and the code they affect. Such description must
+be placed in a text file included with all distributions of the Covered
+Software under this License. Except to the extent prohibited by statute
+or regulation, such description must be sufficiently detailed for a
+recipient of ordinary skill to be able to understand it.
+
+5. Termination
+--------------
+
+5.1. The rights granted under this License will terminate automatically
+if You fail to comply with any of its terms. However, if You become
+compliant, then the rights granted under this License from a particular
+Contributor are reinstated (a) provisionally, unless and until such
+Contributor explicitly and finally terminates Your grants, and (b) on an
+ongoing basis, if such Contributor fails to notify You of the
+non-compliance by some reasonable means prior to 60 days after You have
+come back into compliance. Moreover, Your grants from a particular
+Contributor are reinstated on an ongoing basis if such Contributor
+notifies You of the non-compliance by some reasonable means, this is the
+first time You have received notice of non-compliance with this License
+from such Contributor, and You become compliant prior to 30 days after
+Your receipt of the notice.
+
+5.2. If You initiate litigation against any entity by asserting a patent
+infringement claim (excluding declaratory judgment actions,
+counter-claims, and cross-claims) alleging that a Contributor Version
+directly or indirectly infringes any patent, then the rights granted to
+You by any and all Contributors for the Covered Software under Section
+2.1 of this License shall terminate.
+
+5.3. In the event of termination under Sections 5.1 or 5.2 above, all
+end user license agreements (excluding distributors and resellers) which
+have been validly granted by You or Your distributors under this License
+prior to termination shall survive termination.
+
+************************************************************************
+*                                                                      *
+*  6. Disclaimer of Warranty                                           *
+*  -------------------------                                           *
+*                                                                      *
+*  Covered Software is provided under this License on an "as is"       *
+*  basis, without warranty of any kind, either expressed, implied, or  *
+*  statutory, including, without limitation, warranties that the       *
+*  Covered Software is free of defects, merchantable, fit for a        *
+*  particular purpose or non-infringing. The entire risk as to the     *
+*  quality and performance of the Covered Software is with You.        *
+*  Should any Covered Software prove defective in any respect, You     *
+*  (not any Contributor) assume the cost of any necessary servicing,   *
+*  repair, or correction. This disclaimer of warranty constitutes an   *
+*  essential part of this License. No use of any Covered Software is   *
+*  authorized under this License except under this disclaimer.         *
+*                                                                      *
+************************************************************************
+
+************************************************************************
+*                                                                      *
+*  7. Limitation of Liability                                          *
+*  --------------------------                                          *
+*                                                                      *
+*  Under no circumstances and under no legal theory, whether tort      *
+*  (including negligence), contract, or otherwise, shall any           *
+*  Contributor, or anyone who distributes Covered Software as          *
+*  permitted above, be liable to You for any direct, indirect,         *
+*  special, incidental, or consequential damages of any character      *
+*  including, without limitation, damages for lost profits, loss of    *
+*  goodwill, work stoppage, computer failure or malfunction, or any    *
+*  and all other commercial damages or losses, even if such party      *
+*  shall have been informed of the possibility of such damages. This   *
+*  limitation of liability shall not apply to liability for death or   *
+*  personal injury resulting from such party's negligence to the       *
+*  extent applicable law prohibits such limitation. Some               *
+*  jurisdictions do not allow the exclusion or limitation of           *
+*  incidental or consequential damages, so this exclusion and          *
+*  limitation may not apply to You.                                    *
+*                                                                      *
+************************************************************************
+
+8. Litigation
+-------------
+
+Any litigation relating to this License may be brought only in the
+courts of a jurisdiction where the defendant maintains its principal
+place of business and such litigation shall be governed by laws of that
+jurisdiction, without reference to its conflict-of-law provisions.
+Nothing in this Section shall prevent a party's ability to bring
+cross-claims or counter-claims.
+
+9. Miscellaneous
+----------------
+
+This License represents the complete agreement concerning the subject
+matter hereof. If any provision of this License is held to be
+unenforceable, such provision shall be reformed only to the extent
+necessary to make it enforceable. Any law or regulation which provides
+that the language of a contract shall be construed against the drafter
+shall not be used to construe this License against a Contributor.
+
+10. Versions of the License
+---------------------------
+
+10.1. New Versions
+
+Mozilla Foundation is the license steward. Except as provided in Section
+10.3, no one other than the license steward has the right to modify or
+publish new versions of this License. Each version will be given a
+distinguishing version number.
+
+10.2. Effect of New Versions
+
+You may distribute the Covered Software under the terms of the version
+of the License under which You originally received the Covered Software,
+or under the terms of any subsequent version published by the license
+steward.
+
+10.3. Modified Versions
+
+If you create software not governed by this License, and you want to
+create a new license for such software, you may create and use a
+modified version of this License if you rename the license and remove
+any references to the name of the license steward (except to note that
+such modified license differs from this License).
+
+10.4. Distributing Source Code Form that is Incompatible With Secondary
+Licenses
+
+If You choose to distribute Source Code Form that is Incompatible With
+Secondary Licenses under the terms of this version of the License, the
+notice described in Exhibit B of this License must be attached.
+
+Exhibit A - Source Code Form License Notice
+-------------------------------------------
+
+  This Source Code Form is subject to the terms of the Mozilla Public
+  License, v. 2.0. If a copy of the MPL was not distributed with this
+  file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+If it is not possible or desirable to put the notice in a particular
+file, then You may include the notice in a location (such as a LICENSE
+file in a relevant directory) where a recipient would be likely to look
+for such a notice.
+
+You may add additional accurate notices of copyright ownership.
+
+Exhibit B - "Incompatible With Secondary Licenses" Notice
+---------------------------------------------------------
+
+  This Source Code Form is "Incompatible With Secondary Licenses", as
+  defined by the Mozilla Public License, v. 2.0.
diff -pruN 20130227+dfsg1-14/rhino/NOTICE.txt 20130227+rhino-1/rhino/NOTICE.txt
--- 20130227+dfsg1-14/rhino/NOTICE.txt	1970-01-01 00:00:00.000000000 +0000
+++ 20130227+rhino-1/rhino/NOTICE.txt	2023-05-25 14:24:50.000000000 +0000
@@ -0,0 +1,35 @@
+Rhino is licensed subject to the terms of the Mozilla Public License, v. 2.0.
+See "License.txt" for the text of the license.
+
+Rhino contains the following additional software:
+
+----
+
+Portions of the floating-point conversion code, and portions of the test suite
+come from the Google V8 JavaScript engine and are subject to the following:
+
+Copyright 2010-2015 the V8 project authors. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+    * Neither the name of Google Inc. nor the names of its
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
\ No newline at end of file
diff -pruN 20130227+dfsg1-14/rhino/README.md 20130227+rhino-1/rhino/README.md
--- 20130227+dfsg1-14/rhino/README.md	1970-01-01 00:00:00.000000000 +0000
+++ 20130227+rhino-1/rhino/README.md	2023-05-25 14:24:50.000000000 +0000
@@ -0,0 +1,101 @@
+# Rhino: JavaScript in Java
+
+![Rhino](https://developer.mozilla.org/@api/deki/files/832/=Rhino.jpg)
+
+Rhino is an implementation of JavaScript in Java.
+
+## License
+
+Rhino is licensed under the [MPL 2.0](./LICENSE.txt).
+
+## Releases
+
+<table>
+<tr><td><a href="https://github.com/mozilla/rhino/releases/tag/Rhino1_7R5_RELEASE">Rhino 1.7R5</a></td><td>January 29, 2015</td></tr>
+<tr><td><a href="https://github.com/mozilla/rhino/releases/tag/Rhino1_7_6_RELEASE">Rhino 1.7.6</a></td><td>April 15, 2015</td></tr>
+<tr><td><a href="https://github.com/mozilla/rhino/releases/tag/Rhino1_7_7_RELEASE">Rhino 1.7.7</a></td><td>June 17, 2015</td></tr>
+<tr><td><a href="https://github.com/mozilla/rhino/releases/tag/Rhino1_7_7_1_RELEASE">Rhino 1.7.7.1</a></td><td>February 2, 2016</td></tr>
+<tr><td><a href="https://github.com/mozilla/rhino/releases/tag/Rhino1_7_7_2_RELEASE">Rhino 1.7.7.2</a></td><td>August 24, 2017</td></tr>
+</table>
+
+[Release Notes](./RELEASE-NOTES.md) for recent releases.
+
+[Compatability table](http://mozilla.github.io/rhino/compat/engines.html) which shows which advanced JavaScript
+features from ES5, 6, and 7 are implemented in Rhino.
+
+## Documentation
+
+Information for script builders and embedders:
+
+[https://developer.mozilla.org/en-US/docs/Rhino_documentation](https://developer.mozilla.org/en-US/docs/Rhino_documentation)
+
+JavaDoc for all the APIs:
+
+[http://mozilla.github.io/rhino/javadoc/index.html](http://mozilla.github.io/rhino/javadoc/index.html)
+
+More resources if you get stuck:
+
+[https://developer.mozilla.org/en-US/docs/Mozilla/Projects/Rhino/Community](https://developer.mozilla.org/en-US/docs/Mozilla/Projects/Rhino/Community)
+
+## Building
+
+### How to Build
+
+Rhino builds with `Gradle`. Here are some useful tasks:
+```
+./gradlew jar
+```
+Build and create `Rhino` jar in the `build/libs` directory.
+```
+./gradlew test
+```
+Build and run all the tests.
+```
+./gradlew testBenchmark
+```
+Build and run benchmark tests.
+
+## Releasing and publishing new version
+
+1. Ensure all tests are passing
+2. Remove `-SNAPSHOT` from version in `gradle.properties` in project root folder
+3. Create file `gradle.properties` in `$HOME/.gradle` folder with following properties. Populate them with maven repo credentials and repo location.
+```
+mavenUser=
+mavenPassword=
+mavenSnapshotRepo=
+mavenReleaseRepo=
+```
+
+4. Run `Gradle` task to publish artifacts to Maven Central.
+```
+./gradlew publish
+```
+5. Increase version and add `-SNAPSHOT` to it in `gradle.properties` in project root folder.
+6. Push `gradle.properties` to `GitHub`
+   
+## Running
+
+Rhino can run as a stand-alone interpreter from the command line:
+```
+java -jar buildGradle/libs/rhino-1.7.7.2.jar
+Rhino 1.7.7.2 2017 08 24
+js> print('Hello, World!');
+Hello, World!
+js>
+```
+You can also embed it, as most people do. See below for more docs.
+
+## Issues
+
+Most issues are managed on GitHub:
+
+[https://github.com/mozilla/rhino/issues](https://github.com/mozilla/rhino/issues)
+
+## More Help
+
+The Google group is the best place to go with questions:
+
+[https://groups.google.com/forum/#!forum/mozilla-rhino](https://groups.google.com/forum/#!forum/mozilla-rhino)
+
+
diff -pruN 20130227+dfsg1-14/rhino/RELEASE-NOTES.md 20130227+rhino-1/rhino/RELEASE-NOTES.md
--- 20130227+dfsg1-14/rhino/RELEASE-NOTES.md	1970-01-01 00:00:00.000000000 +0000
+++ 20130227+rhino-1/rhino/RELEASE-NOTES.md	2023-05-25 14:24:50.000000000 +0000
@@ -0,0 +1,367 @@
+# Rhino 1.7.7.2
+## February 1, 2016
+
+This release contains fixes for a few important bugs that have caught Rhino users out in the
+field.
+
+* Do not throw a Java exception from array.prototype.sort() no matter how weird the user-supplied
+comparator function is. This is a major difference between JavaScript and Java and has caused
+us to avoid using "Arrays.sort" on JavaScript arrays.
+* Fix incorrect offsets in the "DataView" class.
+
+It also includes several other fixes:
+
+* Always append a column number to V8-style stack traces. (Unfortunately it is always "0".)
+* Support Object.is and Object.assign.
+* Make the Symbol implementation match the spec (for VERSION_ES6 and up only).
+* Avoid throwing internal Java exceptions for certain native objects in "toJSON".
+* Allow subclassing of ContinuationPending.
+* For VERSION_ES6 and up, sort properties in the spec-defined order (int property names
+first).
+* Fix stack overflow in string concatenation.
+* Improve performance of ConsString.toString
+
+The next release is likely to be 1.7.8.
+
+# Rhino 1.7.7.1
+## February 1, 2016
+
+This release fixes a few critical bugs that were affecting code in the field:
+
+* Improve String.prototype.repeat to work more efficiently and to not overflow
+* Fix CallSite.isNative() and isTopLevel() so that they do not throw fatal errors
+* Replace the implementation of the "YearFromTime" internal method for the Date class to avoid large CPU loops
+
+Specific Changes:
+
+*     Formatting issue with SourceReader.
+*     Fix CallSite.isNative() and isTopLevel() to not throw.
+*     Make String.prototype.repeat not overflow for large values, and change code style a bit.
+*     Add tests from 1.7.7.
+*     Add Gradle code from 1.7.7.
+*     Replace YearFromTime with code from jsdate.cpp to avoid long CPU loops.
+
+# Rhino 1.7.7
+## June 17, 2015
+
+Major changes in this release:
+
+[Release 1.7.7](https://github.com/mozilla/rhino/issues?q=milestone%3A%22Release+1.7.7%22+is%3Aclosed)
+
+Specific changes:
+
+* [Issue 202](https://github.com/mozilla/rhino/issues/202) Initial support for ECMA Script 6 "method definitions".
+* [Issue 201](https://github.com/mozilla/rhino/issues/201) Make sure that all native Error instances can be converted
+to JSON.
+* [Issue 184](https://github.com/mozilla/rhino/issues/184) Fix compile encoding errors.
+* [Issue 178](https://github.com/mozilla/rhino/issues/178) Support build using Gradle (build using Ant is still
+supported but will be removed in a future release.)
+* [Issue 176](https://github.com/mozilla/rhino/issues/176) Add ScriptRuntime.throwCustomError to make it easier
+to re-throw Java exceptions
+* [Issue 166](https://github.com/mozilla/rhino/issues/166) Support many ES6 additions to the Math class.
+* [Issue 165](https://github.com/mozilla/rhino/issues/165) Support many ES6 additions to the Number class.
+* [Issue 163](https://github.com/mozilla/rhino/issues/163) Support ES6 additions to the String class.
+
+Thanks to everyone who contributed!
+
+Ahmed Ashour (3):
+*     Add .gitattributes for End-Of-Line automatic handling
+*     Remove extra space
+*     Update .gitignore for eclipse generated files.
+
+Evgeny Shepelyuk (45):
+*     Implementing possibility of writing  JS tests code inside JUnit Test.
+*     + gradle wrapper     + sources and test compilation     + jar building
+*     + More JUnit style for Gradle compatibility     - disabled test removed
+*     + running tests
+*     + benchmark test changes for Gradle compaibility     + run benchmark from Gradle     + publishing artifacts from Gradle
+*     + benchmark test changes for Gradle compaibility     + run benchmark from Gradle     + publishing artifacts from Gradle
+*     + publishing artifacts to maven compatible repositories
+*     + releasing with Gradle
+*     + releasing with Gradle
+*     + releasing with Gradle
+*     + releasing with Gradle
+*     [Gradle Release Plugin] - new version commit:  '1.7.8'.
+*     + releasing with Gradle
+*     + releasing with Gradle
+*     + releasing with Gradle
+*     [Gradle Release Plugin] - pre tag commit:  '1.7.8'.
+*     Revert "+ publishing artifacts to maven compatible repositories"
+*     rollback gradle release
+*     + properly populating manifest     + exclude unnecesary files from jar
+*     + adding license to jar
+*     + build will not fail when maven credentials are not defined
+*     + getting rhino display version from MANIFEST
+*     * modifying README with Gradle details
+*     Update README.md
+*     Improving reporting of MozillaSuiteTest tests
+*     Improving reporting of MozillaSuiteTest tests
+*     + initial implementation of String.prototype.includes
+*     + initial implementation of String.prototype.includes
+*     + initial implementation of String.prototype.includes
+*     + initial implementation of String.prototype.startsWith
+*     + initial implementation of String.prototype.startsWith
+*     + initial implementation of String.prototype.endsWith
+*     + initial implementation of String.prototype.endsWith
+*     + initial implementation of String.prototype.endsWith
+*     + implementation of String.prototype.normalize
+*     + implementation of String.prototype.normalize
+*     + implementation of String.prototype.normalize
+*     + implementation of String.prototype.repeat
+*     + implementation of String.prototype.repeat
+*     + implementation of String.prototype.codePointAt
+*     + implementation of String.prototype.codePointAt
+*     * fixing tests after implementation of ES6 string methods     + implementing RequireObjectCoercible from ECMA spec
+*     * fixing tests after implementation of ES6 string methods     + implementing RequireObjectCoercible from ECMA spec
+*     * fixing tests after implementation of ES6 string methods     + implementing RequireObjectCoercible from ECMA spec
+*     Better exception reporting
+
+Gregory Brail (16):
+*     Update for new development iteration.
+*     Read manifest URLs in a loop until we find the right one when trying     to determine the implementation version.
+*     Permissions fix.
+*     Fix potential NPE in ComplianceTest.
+*     Re-run IDMap on NativeString.
+*     Merge branch 'issue_176_2' of https://github.com/raimi/rhino into raimi-issue_176_2
+*     Merge branch 'master' of https://github.com/asashour/rhino into asashour-master
+*     Add .gitattributes.
+*     Re-arrange "global variables" regression tests for fewer spurious failures     under Gradle.
+*     Don't make "javaException" and "rhinoException" on the NativeError     object enumerable, because they cannot be converted to JSON.
+*     Fix file name for V8 benchmark results.
+*     Add some ES6 methods to Math and Number.
+*     "BigO" regression test exhibits different and inconsistent behavior     on Java 8. So fix it.
+*     Fix a bug in Math.hypot().
+*     Added a constant for ECMAScript 6 language level:     Context.VERSION_ES6.
+*     Add "readline" and "write" to console.
+
+Raimund Jacob (5):
+*     Allow throwing arbitrary objects from java world
+*     176: Adjust javadoc to reality.
+*     Emacs, sorry
+*     Issue176: Test infrastructure
+*     176: Actually Working Tests
+
+sainaen (1):
+*     Print exception message in case of JavaScriptException in ScriptTestsBase
+
+tntim96 (1):
+*     Fix Test compile encoding error 'unmappable character for encoding ASCII' - https://github.com/mozilla/rhino/issues/184
+
+uchida_t (5):
+*     set capacity for StringBuilder in String#repeat
+*     Implement ES6 MethodDefinition
+*     `set` and `get` is valid method name.
+*     NumericLiteral/StringLiteral is valid method name.
+
+# Rhino 1.7.6
+## April 15, 2015
+
+Merged many of the outstanding pull requests in the GitHub repo.
+
+High-level changes include the following:
+
+* Many compatibility fixes for Date, Array, String, and others (André Bargull)
+* Array.find() and findIndex() (Evgeny Shepelyuk)
+* String.trimLeft() and trimRight() (Travis Ennis)
+* AST and "toSource" fixes (tntim96)
+* Support for V8 Error extensions, including Error.captureStackTrace (Greg Brail)
+* Support for typed arrays (Greg Brail)
+* Support for attaching "external data" as the indexed properties of any object (Greg Brail)
+
+André Bargull (60):
+*     NativeDate: Date.length and Date.UTC.length is 7
+*     NativeDate: Fix bug 732779 (Date.prototype.setXXX functions don't evaluate all parameters)
+*     NativeDate: Date.prototype.toJSON uses [[GET]] to obtain the "toISOString" property
+*     add js_toISOString method to format date values in ISO-8601 Extended Format with expanded year representation if necessary
+*     NativeDate: Update Date.parse to support simplified ISO 8601 Extended Format [15.9.1.15]
+*     Fix indentation in NativeDate.java
+*     NativeError: Error.prototype.name and Error.prototype.message are not enumerable
+*     NativeError: 15.11.2.1 and 15.11.4.4 updates
+*     Arguments: arguments object should not have its own 'constructor' property, instead it inherits 'constructor' through its prototype
+*     Arguments: 'callee', 'caller' and 'length' properties can be redefined for the arguments object
+*     BaseFunction: Function.prototype.toString arity is 0
+*     BaseFunction: The 'prototype' property on function instances can be redefined
+*     BaseFunction: The 'arguments' property can be redefined for function instances
+*     NativeArray: Check [[Extensible]] flag for dense-array case in [[Put]]
+*     NativeArray: Remove (invalid) round-trips to ScriptRuntime when getting/setting elements
+*     NativeArray: Follow spec more closely for Array.isArray and Array.prototype.concat
+*     NativeArray: Array.prototype.{indexOf, lastIndexOf} bug fixes
+*     NativeArray: Array.prototype.sort bug fixes (bug 728286)
+*     NativeArray: Multiple changes to ensure specification algorithms are followed more closely
+*     TopLevel,NativeGlobal,ScriptRuntime: Add cache for native error objects
+*     NativeNumber: Handle case when precision is Infinity for Number.prototype.{toFixed,toExponential,toPrecision}
+*     NativeObject: Object.prototype.toLocaleString uses [[Get]] to retrieve 'toString' property
+*     NativeObject: Handle undefined arguments in Object.prototype.{hasOwnProperty,propertyIsEnumerable}
+*     NativeString: String.prototype.replace arity is 2 instead of 1
+*     NativeString: Handle undefined arguments in String.prototype.slice
+*     ScriptRuntime: Fix range check to follow spec in numberToString()
+*     ScriptRuntime: Set-up proto and parent-scope for TypeErrorThrower function
+*     ScriptableObject: Object.defineProperties needs to make sure to call [[Get]] exactly once for each property entry
+*     NativeRegExp: Handle undefined arguments in compile and exec
+*     NativeRegExp: Report error if a RegExp flag is used more than once
+*     NativeRegExp: RegExp.prototype.compile arity is 2
+*     NativeRegExp: RegExp.prototype.lastIndex is lazily evaluated and may be set to non-writable as well
+*     NativeRegExpCtor: arity of RegExp constructor is 2
+*     NativeRegExpCtor: RegExp.prototype.{multiline,star,input,underscore} properties can be re-defined
+*     RegExpImpl: Multiple changes for String.prototype.{match,search,replace,split}
+*     Remove obsolete test case js1_2/function/regexparg-2-n.js
+*     update test case doctests/arguments.doctest now that the arguments object inherits the 'constructor' property through its prototype
+*     NativeRegExp: Make octal escape sequences match web reality
+*     RegExpImpl: String.prototype.split with separator=undefined no longer treated as separator='undefined'
+*     Fix indentation
+*     Context: remove duplicate code in Context#newObject()
+*     Context: Use StackTraceElement API to traverse stack-trace
+*     NativeArray: address review comment from hns
+*     Updated tests files per instructions in o.m.j.tests.MozillaSuiteTest
+*     Patch for Bug 783797 ("Function calls across multiple global scopes are not handled properly")
+*     Silence warnings in ClassFileWriter
+*     Add missing @Deprecated annotations
+*     Add missing @Override annotations
+*     Add missing generic type info to deprecatedsrc/
+*     Add missing generic type info to toolsrc/
+*     Add missing generic type info to testsrc/
+*     Add missing generic type info to src/
+*     Fix invalid JavaDoc links
+*     Replace StringBuffer with StringBuilder if possible
+*     Address review comments from hns
+*     Generators save and later restore the current stack when processing the 'yield' operation. Our current implementation for restoring the stack unfortunately confuses the Java classfile verifier, so at class load time a VerifierError is thrown. This happens because the verifier can no longer ensure that the proper types are placed on the stack, since the stack-state is saved in a simple Object[]. Re-ordering a few operations is only necessary so the verifier will again accept the generated class. But this is only done for generators because it creates slightly less efficient code compared to the standard case.
+*     Add doctest and update comments with proper bug number
+*     Patch for Bug 782363 ("Increment/Decrement alters const variables")
+*     Patch for Bug 780458 ("Math.IEEEremainder makes ToInt32 slow for non-integer values") (V8):
+*     Patch for Bug 789277 ("JSC: "missing ; after statement" message prints out for the line after the problem one")
+
+C. Scott Ananian (1):
+*     Don't swallow empty lines in doctest; split lines on Mac/Windows/Unix.
+
+Edison (2):
+*     Add working directory support to "runCommand"
+*     Add working directory support to "runCommand"
+
+Elliott Baron (1):
+*     Add manpage for Rhino shell.
+
+Evgeny Shepelyuk (2):
+*     find and findIndex initial impl
+*     Improving test framework     + one JUnit class = one JS suite     + reporting JS stacktrace on error     + load function is available in JS     + separate file for JS assertions
+
+Gregory Brail (31):
+*     Update versions for next iteration.
+*     Update README for release notes.
+*     Change benchmark output so we can "plot" it in Maven.
+*     Fix code cleanup fix that broke the Java 6 build.
+*     Fix benchmark output file format again.
+*     Re-run ID map on NativeString.
+*     Manually add .gitignore additions from @sghill.
+*     Added a bit more to the README including content from @shirishp
+*     Add a NOTICE with the V8 copyright message.
+*     Move anba's new DoubleConversion code into the package with the     rest of the code derived from V8.
+*     Remove retrotranslator code to generate 1.4-compatible bytecode.     Switch bytecode generation to Java 6.
+*     Remove code and build artifacts pointing to the "old E4X" implementation,     based on XML Beans.
+*     Remove unused XML beans-based E4X implementation.
+*     One last vestige of XML Beans.
+*     Re-generate ID map on NativeArray.
+*     Initial checkin of typed arrays and tests from V8.     Fix bad capitalization.
+*     Fix some integer encoding and add more test cases.
+*     Switch typed array tests to use Evgeny's framework for running them.     Make them work only with version 1.8.
+*     Make typed arrays only appear in 1.8.
+*     Add List implementation for all native arrays.
+*     Add "Error" to the set of standard Error constructors     that could go down the new code path to create an error.
+*     Complete List implementation for typed arrays.     Write typed array unit tests for the List implementation.
+*     Do not double-initialize Error.
+*     Make loading of typed array classes lazy.     Rename Java classes so that the names are more consistent.
+*     Support for V8-style stack trace support:       Error.prepareStackTrace       Error.captureStackTrace       Error.stackTraceLimit     And "V8" format stack traces.
+*     Improve efficiency of NativeError via pre-cached Method objects     and reduced number of default fields.
+*     Make "stack" non-enumerable until generated.
+*     Add "setExternalArrayData" to ScriptableObject to allow array data     to be stored outside the core object.
+*     Set default version in shell to "180".
+*     Add method to both get and set external array data.
+*     Add "initSafeStandardObjects" to create standard objects with     no Java class access whatsoever.
+
+Ievgenii.Shepeliuk (2):
+*     `findIndex' implementation
+*     more V8 compatibility
+
+Raymond Auge (1):
+*     rhino exits the JVM even when run as a subshell of another java shell - bug-835147
+
+Travis Ennis (2):
+*     Added the Javascript 1.8 String methods trimLeft and trim Right.
+*     Added the Javascript 1.8 String methods trimLeft and trimRight.
+
+sainaen (1):
+*     Add 'LanguageVersion' annotation. Make 1.8 default version for 'ScriptsTestsBase'
+
+sghill (1):
+*     removing old .cvsignore files
+
+tntim96 (5):
+*     'undefined' pattern should be treated as empty string in RegExp constructor     http://www.ecma-international.org/ecma-262/5.1/#sec-15.10.4.1     https://sourceforge.net/p/htmlunit/bugs/1599/
+*     Bug 798642. AST 'toSource' on getter/setter mistakenly adding 'function' keyword     https://bugzilla.mozilla.org/show_bug.cgi?id=798642
+*     Bug 800616. Fix AST 'toSource' for Octal and Hexadecimal literals     https://bugzilla.mozilla.org/show_bug.cgi?id=800616
+*     Fix AST empty switch to source
+*     Fix compile encoding error 'unmappable character for encoding ASCII'
+
+# Rhino 1.7R5
+## January 29, 2015
+
+André Bargull (24):
+
+*     Add missing license header to DefineClassMapInheritance.java
+*     Remove invalid UTF-8 encoded unicode replacement characters (EF BF BD)
+*     Add missing entries
+*     Bug 772011: Decompiler does not add curly brackets for labelled statements
+*     Add fix for bug-772833 (comment copied over from Parser::condExpr1 in frontend/Parser.cpp)
+*     Fix bug 686806:     - trailing commas aren't allowed in object/array literals per JSON spec     - avoid using Integer.parseInt() to parse unicode escape sequences since parseInt() also accepts non-ASCII digits     - also avoid using Character.isDigit() in readNumber() for the very same reason     - readString() always created a StringBuilder instance to collect the input data, obviously this is actually only necessary when the input contains escaped characters. Therefore I've changed readString() to take the same approach as used in jsonparser.cpp     - the JSON number specification is stricter than Double.parseDouble(), for example Double.parseDouble() accepts the input string '10.'. To ensure only valid JSON number literals are passed to Double.parseDouble(), readNumber() was refactored to perform the necessary input validation.
+*     Patch for bug 774083.
+*     Patch for Bug 688023:
+*     Fix broken test cases which relied on the old (and erroneous) toSource() output
+*     Patch bug 685403
+*     Patch for bug 637811:
+*     Fix bug 773573: Search for first curly bracket after closing parentheses to take account of object destructuring parameters
+*     Simple doctest for bug 773573
+*     Array.prototype.sort performed an unchecked cast from long to int without any overflow checks, this may result in a negative length which then throws a NegativeArraySizeException in Java, cf. js1_5/Array/regress-157652.js . A similar problem was found in NativeJSON, so I've handled that as well
+*     Add explicit cast to int to ensure previous behaviour is retained
+*     Calls must not be special-calls and reference-calls at the same time, cf. js1_5/Regress/regress-319391.js for a test case
+*     Enable js1_5/Regress/regress-319391.js for MozillaSuiteTest
+*     Patch for Bug 728286
+*     Add test case
+*     Patch for Bug 778549
+*     Add missing overflow detection when processing RegExp character class pattern
+*     Patch for Bug 780147:
+*     Patch for Bug 608235 ("Incorrect error message for undefined[undefined]")
+*     Patch for Bug 784358 ("Defining const variable within eval() throws redeclaration error")
+
+Evgeny Shepelyuk (1):
+
+*     fix xmlbeans url
+
+Gregory Brail (10):
+
+*     Add JUnit-based benchmarks that we can automate in Jenkins.
+*     Extract zipped-up tests into a directory and check them in that way.
+*     Extracted the stuff that was formerly in testsrc/tests.tar.gz.
+*     Add XML output for EMMA coverage reports.
+*     Fix character encoding tests to work on Mac.
+*     Add output to benchmarks that can work with the Jenkins     "Measurement Plots" plugin. This replaces the former output from the     "SunSpider" and "V8" benchmarks.
+*     Add files for Maven deployment.
+*     README update.
+*     Update README for other tests.
+*     Fix E4X test 13.4.4.24 which was failing on Java 8 due to different     HashMap iteration ordering.
+
+Hannes Wallnoefer (8):
+
+*     Unwrap Synchronizer in BaseFunction.toSource().
+*     Override ScriptableObject.isEmpty in NativeArray
+*     Reduce concurrency level / memory footprint in concurrent class cache hash maps
+*     Return null for unhandled JavaAdapter methods
+*     Make JavaAdapter work with abstract base classes and protected constructors
+*     Change build version to 1_7R5pre
+*     Extract code to create JS error from Java exception into separate ScriptRuntime method
+*     Reduce invocation magic in ShellConsole JLine support classes
+
+Kyle Cronin (2):
+
+*     Patch for Bug 827538
+*     Patch for Bug 738388
+
+<!--- Start with " git shortlog --no-merges Rhino1_7R4_RELEASE.. | sed 's/^ /*/'" -->
diff -pruN 20130227+dfsg1-14/rhino/apiClasses.properties 20130227+rhino-1/rhino/apiClasses.properties
--- 20130227+dfsg1-14/rhino/apiClasses.properties	1970-01-01 00:00:00.000000000 +0000
+++ 20130227+rhino-1/rhino/apiClasses.properties	2023-05-25 14:24:50.000000000 +0000
@@ -0,0 +1,36 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+apiClasses=\
+	src/org/mozilla/javascript/Callable.java,\
+	src/org/mozilla/javascript/ClassCache.java,\
+	src/org/mozilla/javascript/ClassShutter.java,\
+	src/org/mozilla/javascript/CompilerEnvirons.java,\
+	src/org/mozilla/javascript/ContinuationPending.java,\
+	src/org/mozilla/javascript/Context.java,\
+	src/org/mozilla/javascript/ContextAction.java,\
+	src/org/mozilla/javascript/ContextFactory.java,\
+	src/org/mozilla/javascript/GeneratedClassLoader.java,\
+	src/org/mozilla/javascript/EcmaError.java,\
+	src/org/mozilla/javascript/ErrorReporter.java,\
+	src/org/mozilla/javascript/EvaluatorException.java,\
+	src/org/mozilla/javascript/Function.java,\
+	src/org/mozilla/javascript/FunctionObject.java,\
+	src/org/mozilla/javascript/GeneratedClassLoader.java,\
+	src/org/mozilla/javascript/ImporterTopLevel.java,\
+	src/org/mozilla/javascript/JavaScriptException.java,\
+	src/org/mozilla/javascript/RefCallable.java,\
+	src/org/mozilla/javascript/RhinoException.java,\
+	src/org/mozilla/javascript/Script.java,\
+	src/org/mozilla/javascript/Scriptable.java,\
+	src/org/mozilla/javascript/ScriptableObject.java,\
+	src/org/mozilla/javascript/SecurityController.java,\
+	src/org/mozilla/javascript/WrapFactory.java,\
+	src/org/mozilla/javascript/WrappedException.java,\
+	src/org/mozilla/javascript/Wrapper.java,\
+	src/org/mozilla/javascript/Synchronizer.java,\
+	src/org/mozilla/javascript/optimizer/ClassCompiler.java,\
+	src/org/mozilla/javascript/debug/DebuggableScript.java,\
+	src/org/mozilla/javascript/serialize/ScriptableInputStream.java,\
+	src/org/mozilla/javascript/serialize/ScriptableOutputStream.java
diff -pruN 20130227+dfsg1-14/rhino/build-date 20130227+rhino-1/rhino/build-date
--- 20130227+dfsg1-14/rhino/build-date	1970-01-01 00:00:00.000000000 +0000
+++ 20130227+rhino-1/rhino/build-date	2023-05-25 14:24:50.000000000 +0000
@@ -0,0 +1 @@
+This version was built on @datestamp@.
diff -pruN 20130227+dfsg1-14/rhino/build.gradle 20130227+rhino-1/rhino/build.gradle
--- 20130227+dfsg1-14/rhino/build.gradle	1970-01-01 00:00:00.000000000 +0000
+++ 20130227+rhino-1/rhino/build.gradle	2023-05-25 14:24:50.000000000 +0000
@@ -0,0 +1,249 @@
+apply plugin: 'java'
+apply plugin: 'idea'
+apply plugin: 'maven-publish'
+apply plugin: 'jacoco'
+apply plugin: 'distribution'
+apply plugin: 'checkstyle'
+
+sourceCompatibility = 1.6
+targetCompatibility = 1.6
+
+tasks.withType(JavaCompile) { options.encoding = "UTF-8" }
+
+task wrapper(type: Wrapper) {
+    gradleVersion = '2.3'
+}
+
+repositories {
+    mavenCentral()
+}
+
+sourceSets {
+    main {
+        java {
+            srcDirs 'src', 'toolsrc', 'xmlimplsrc'
+        }
+        resources {
+            srcDirs 'src', 'toolsrc'
+            exclude "build.xml"
+            exclude "manifest"
+        }
+    }
+
+    test {
+        java {
+            srcDirs "testsrc", 'examples'
+            exclude 'tests/**'
+        }
+        resources {
+            srcDirs "testsrc"
+        }
+    }
+}
+
+dependencies {
+    testCompile "junit:junit:4.12"
+    testCompile "org.yaml:snakeyaml:1.15"
+    testCompile "net.trajano.caliper:caliper:1.2.1"
+}
+
+if (JavaVersion.current().isJava8Compatible()) {
+    allprojects {
+        tasks.withType(Javadoc) {
+            options.addStringOption('Xdoclint:none', '-quiet')
+        }
+    }
+}
+
+test {
+    exclude "**/benchmarks/**"
+    systemProperty 'java.awt.headless', 'true'
+    systemProperty 'mozilla.js.tests', 'testsrc/tests'
+    systemProperty 'mozilla.js.tests.timeout', 60000
+    systemProperty 'user.language', 'en'
+    systemProperty 'user.country', 'US'
+    systemProperty 'user.timezone', 'America/Los_Angeles'
+    systemProperty 'file.encoding', 'UTF-8'
+    maxHeapSize = "256m"
+    testLogging.showStandardStreams = true
+}
+
+task sunSpiderBenchmark(type: JavaExec) {
+    main "com.google.caliper.runner.CaliperMain"
+    systemProperty 'rhino.benchmark.report', "${buildDir.absolutePath}"
+    args "-Cresults.upload.class=org.mozilla.javascript.benchmarks.ResultPlotter", "-i", "runtime", "org.mozilla.javascript.benchmarks.CaliperSpiderBenchmark.Spider"
+    classpath sourceSets.test.runtimeClasspath
+}
+
+task testBenchmark(type: Test) {
+    jacoco {
+        enabled = false
+    }
+    include "**/benchmarks/V8Benchmark*"
+    systemProperty 'rhino.benchmark.report', "${buildDir.absolutePath}"
+    systemProperty 'file.encoding', 'UTF-8'
+    workingDir = file("testsrc/benchmarks")
+    maxHeapSize = "256m"
+    testLogging.showStandardStreams = true
+    forkEvery = 1
+}
+testBenchmark.dependsOn sunSpiderBenchmark
+
+task microBenchmark(type: JavaExec) {
+    main "com.google.caliper.runner.CaliperMain"
+    args "-i", "runtime", "org.mozilla.javascript.benchmarks.CaliperObjectBenchmark.FieldAccess", "-DstringKeys=100,1000", "-DintKeys=0,10,1000"
+    classpath sourceSets.test.runtimeClasspath
+}
+
+
+
+idea {
+    module {
+        excludeDirs += file('testsrc/tests/src')
+        excludeDirs += file('buildGradle')
+        excludeDirs += file('build')
+        excludeDirs += file('.idea')
+        excludeDirs += file('lib')
+    }
+}
+
+jar {
+    from "LICENSE.txt"
+    manifest {
+        attributes(
+            "Manifest-Version": "1.0",
+            "Main-Class": "org.mozilla.javascript.tools.shell.Main",
+            "Implementation-Version": project.version,
+            "Implementation-Title":  "Mozilla Rhino",
+            "Implementation-Vendor": "Mozilla Foundation",
+            "Implementation-URL": "http://www.mozilla.org/rhino",
+            "Built-Date": new Date().format("yyyy-MM-dd"),
+            "Built-Time": new Date().format("HH:mm:ss")
+        )
+    }
+}
+
+task sourceJar(type: Jar) {
+    from sourceSets.main.allJava
+}
+
+task rhinoJavadoc(type: Javadoc) {
+    source = sourceSets.main.allJava
+    if (JavaVersion.current().isJava8Compatible()) {
+        options.addStringOption('Xdoclint:none', '-quiet')
+    }
+}
+
+task rhinoJavadocJar(type: Jar, dependsOn: rhinoJavadoc) {
+    from rhinoJavadoc.destinationDir
+}
+
+publishing {
+    publications {
+        rhino(MavenPublication) {
+            groupId 'org.mozilla'
+            artifactId 'rhino'
+
+            pom.withXml {
+                def root = asNode()
+
+                root.appendNode('description', """
+    Rhino is an open-source implementation of JavaScript written entirely in Java.
+    It is typically embedded into Java applications to provide scripting to end users.
+""")
+                root.appendNode("url", "https://developer.mozilla.org/en/Rhino")
+
+                def p = root.appendNode("parent")
+                p.appendNode("groupId", "org.sonatype.oss")
+                p.appendNode("artifactId", "oss-parent")
+                p.appendNode("version", "7")
+
+                def l = root.appendNode("licenses").appendNode("license")
+                l.appendNode("name", "Mozilla Public License, Version 2.0")
+                l.appendNode("url", "http://www.mozilla.org/MPL/2.0/index.txt")
+
+                def scm = root.appendNode("scm")
+                scm.appendNode("connection", "scm:git:git@github.com:mozilla/rhino.git")
+                scm.appendNode("developerConnection", "scm:git:git@github.com:mozilla/rhino.git")
+                scm.appendNode("url", "git@github.com:mozilla/rhino.git")
+
+                def o = root.appendNode("organization")
+                o.appendNode("name", "The Mozilla Foundation")
+                o.appendNode("url", "http://www.mozilla.org")
+
+            }
+            from components.java
+            artifact sourceJar {
+                classifier "sources"
+            }
+            artifact rhinoJavadocJar {
+                classifier "javadoc"
+            }
+        }
+    }
+
+    if (project.hasProperty("mavenPassword")) {
+        repositories {
+            maven {
+                credentials {
+                    username mavenUser
+                    password mavenPassword
+                }
+                if (project.version.endsWith('-SNAPSHOT')) {
+                    url mavenSnapshotRepo
+                } else {
+                    url mavenReleaseRepo
+                }
+            }
+        }
+    }
+}
+
+jacoco {
+    toolVersion = "0.7.4.201502262128"
+}
+
+jacocoTestReport.dependsOn test
+jacocoTestReport {
+    reports {
+        html.destination "${buildDir}/jacocoHtml"
+    }
+}
+
+checkstyle {
+    configFile = file("${projectDir}/checkstyle.xml")
+    sourceSets = [project.sourceSets.main]
+}
+
+distributions {
+    main {
+        contents {
+            from(sourceSets.main.java) {
+                exclude 'man'
+                into 'rhino' + project.version + '/src'
+            }
+            from(sourceSets.main.resources) {
+                exclude '**/*.java'
+                into 'rhino' + project.version + '/src'
+            }
+            from(javadoc.destinationDir) {
+                into 'rhino' + project.version + '/docs'
+            }
+            from(jar.outputs.files) {
+                into 'rhino' + project.version + '/lib'
+            }
+            from(sourceSets.main.allSource) {
+                include 'man/*.1'
+                into 'rhino' + project.version
+            }
+            from(file(".")) {
+                include '*.txt', '*.md', 'build.gradle', 'build.properties', 'gradle.properties',
+                        'gradle/**', 'gradlew'
+                into 'rhino' + project.version 
+            }
+            into "/"
+        }
+    }
+}
+
+distZip.dependsOn javadoc, jar
diff -pruN 20130227+dfsg1-14/rhino/build.properties 20130227+rhino-1/rhino/build.properties
--- 20130227+dfsg1-14/rhino/build.properties	1970-01-01 00:00:00.000000000 +0000
+++ 20130227+rhino-1/rhino/build.properties	2023-05-25 14:24:50.000000000 +0000
@@ -0,0 +1,26 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+name: rhino
+Name: Rhino
+version: 1.7.7.2
+# See Context#getImplementationVersion() for format of this!
+implementation.version: Rhino 1.7.7.2 ${implementation.date}
+
+build.dir: build
+rhino.jar: js.jar
+small-rhino.jar: smalljs.jar
+dist.name: rhino${version}
+dist.dir: ${build.dir}/${dist.name}
+
+# compilation destionation
+classes: ${build.dir}/classes
+
+# compilation settings
+debug: on
+target-jvm: 1.6
+source-level: 1.6
+
+# jar generation settings
+jar-compression: true
diff -pruN 20130227+dfsg1-14/rhino/build.xml 20130227+rhino-1/rhino/build.xml
--- 20130227+dfsg1-14/rhino/build.xml	1970-01-01 00:00:00.000000000 +0000
+++ 20130227+rhino-1/rhino/build.xml	2023-05-25 14:24:50.000000000 +0000
@@ -0,0 +1,335 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- This Source Code Form is subject to the terms of the Mozilla Public
+   - License, v. 2.0. If a copy of the MPL was not distributed with this
+   - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
+
+
+<!--
+    Build file for Rhino using Ant (see http://jakarta.apache.org/ant/index.html)
+    Requires Ant version 1.2 or later
+
+    Compilation currently requires JDK 1.5 or later. Can cross-compile to
+    support JDK 1.4.
+-->
+
+<project name="Rhino" default="help" basedir=".">
+
+  <target name="properties">
+    <!-- Allow user to override default settings from build.properties -->
+    <property file="build.local.properties" />
+    <tstamp>
+      <!-- Specify date part of Context#getImplementationVersion() -->
+      <format property="implementation.date" pattern="yyyy MM dd"/>
+    </tstamp>
+    <property file="build.properties"/>
+
+    <property name="dist.file" value="rhino${version}.zip"/>
+    <property name="dist.source-only-zip" value="rhino${version}-sources.zip"/>
+
+    <property file="apiClasses.properties"/>
+    <property name="xmlimplsrc-build-file"
+              location="xmlimplsrc/build.xml"/>
+
+    <available property="xmlimplsrc-present?"
+               file="${xmlimplsrc-build-file}" />
+
+  </target>
+
+  <target name="init" depends="properties">
+    <mkdir dir="${build.dir}"/>
+    <mkdir dir="${classes}"/>
+    <mkdir dir="${dist.dir}"/>
+  </target>
+
+  <target name="compile" depends="init">
+    <ant antfile="src/build.xml" target="compile"/>
+    <ant antfile="toolsrc/build.xml" target="compile"/>
+    <antcall target="xmlimplsrc-compile" />
+  </target>
+
+  <target name="compile-all" depends="compile"/>
+
+  <target name="graph" depends="init">
+    <ant antfile="src/build.xml" target="graph"/>
+  </target> 
+
+  <target name="shell" depends="compile">
+    <ant antfile="src/build.xml" target="shell"/>
+  </target> 
+
+  <target name="copy-source" depends="init">
+    <ant antfile="src/build.xml" target="copy-source"/>
+    <ant antfile="toolsrc/build.xml" target="copy-source"/>
+    <ant antfile="testsrc/build.xml" target="copy-source"/>
+    <antcall target="xmlimplsrc-copy-source" />
+    <copy todir="${dist.dir}" file="build.xml"/>
+    <copy todir="${dist.dir}" file="build.properties"/>
+    <copy todir="${dist.dir}" file="apiClasses.properties"/>
+    <copy todir="${dist.dir}" file="LICENSE.txt"/>
+  </target>
+
+  <target name="xmlimplsrc-compile" if="xmlimplsrc-present?">
+    <echo>Calling ${xmlimplsrc-build-file}</echo>
+    <!-- Ignore compilation errors under JDK less then 1.4 -->
+    <property name="xmlimpl.compile.failonerror" value="no"/>
+    <ant antfile="${xmlimplsrc-build-file}" target="compile"/>
+  </target>
+
+  <target name="xmlimplsrc-copy-source" if="xmlimplsrc-present?">
+    <echo>Calling ${xmlimplsrc-build-file}</echo>
+    <ant antfile="${xmlimplsrc-build-file}" target="copy-source"/>
+  </target>
+
+  <target name="jar" depends="compile-all">
+    <copy todir="${classes}" file="LICENSE.txt"/>
+    <property name="jarfile" location="${dist.dir}/${rhino.jar}"/>
+    <jar jarfile="${jarfile}"
+         basedir="${classes}"
+         manifest="src/manifest"
+         compress="${jar-compression}"
+     />
+  </target>
+
+  <target name="console" depends="jar">
+    <property name="jarfile" location="${dist.dir}/${rhino.jar}"/>
+    <java jar="${jarfile}"
+          fork="true">
+      <arg line="-version 170"/>
+    </java>
+  </target>
+
+  <target name="smalljar" depends="compile">
+    <property name="smalljarfile" location="${dist.dir}/${small-rhino.jar}"/>
+    <jar basedir="${classes}" destfile="${smalljarfile}"
+         compress="${jar-compression}">
+      <include name="org/mozilla/javascript/*.class"/>
+
+      <include name="org/mozilla/javascript/debug/*.class"/>
+      <include name="org/mozilla/javascript/resources/*.properties"/>
+      <include name="org/mozilla/javascript/xml/*.class"/>
+      <include name="org/mozilla/javascript/continuations/*.class"/>
+      <include name="org/mozilla/javascript/jdk13/*.class"/>
+      <include name="org/mozilla/javascript/ast/*.class"/>
+      <include name="org/mozilla/javascript/json/*.class"/>
+      <include name="org/mozilla/javascript/annotations/*.class"/>
+      <include name="org/mozilla/javascript/v8dtoa/*.class"/>
+
+      <!-- exclude classes that uses class generation library -->
+      <exclude name="org/mozilla/javascript/JavaAdapter*.class"/>
+
+      <include name="org/mozilla/javascript/regexp/*.class"
+               unless="no-regexp"/>
+    </jar>
+  </target>
+
+  <target name="copy-examples" depends="init">
+    <mkdir dir="${dist.dir}/examples"/>
+    <copy todir="${dist.dir}/examples">
+      <fileset dir="examples" includes="**/*.java,**/*.js,**/*.html" />
+    </copy>
+  </target>
+
+  <target name="copy-misc" depends="init">
+    <filter token="datestamp" value="${TODAY}"/>
+    <copy todir="${dist.dir}" filtering="yes">
+      <fileset dir=".">
+        <patternset>
+          <include name="build-date"/>
+        </patternset>
+      </fileset>
+    </copy>
+  </target>
+
+  <target name="copy-all" depends="copy-source,copy-examples,copy-misc">
+  </target>
+
+  <target name="javadoc" depends="init">
+    <mkdir dir="${dist.dir}/javadoc"/>
+    <javadoc sourcefiles="${apiClasses}"
+             sourcepath="src"
+             destdir="${dist.dir}/javadoc"
+             version="true"
+             author="true"
+             windowtitle="${Name}" />
+    <zip destfile="${dist.dir}/javadoc.zip" basedir="${dist.dir}/javadoc"/>
+  </target>
+
+  <target name="dev-javadoc" depends="init">
+    <mkdir dir="${dist.dir}/javadoc"/>
+    <javadoc sourcepath="src"
+             destdir="${dist.dir}/javadoc"
+             version="true"
+             package="true"
+             author="true"
+             windowtitle="${Name}">
+       <fileset
+         dir="."
+         includes="**/*.java"
+         excludes="**/testsrc/**/*.java"
+       />
+    </javadoc>
+  </target>
+
+  <!--
+    Compiles and tests all sources and then creates the distribution file
+  -->
+  <target name="all" depends="deepclean,compile-all,junit-all,dist">
+  </target>
+
+  <target name="dist" depends="deepclean,jar,copy-all,javadoc">
+    <delete file="${dist.file}" />
+    <zip destfile="${dist.file}">
+      <fileset dir="${build.dir}" includes="${dist.name}/**"/>
+    </zip>
+  </target>
+
+  <target name="source-zip" depends="copy-source,copy-examples,javadoc">
+    <delete file="${dist.source-only-zip}" />
+    <zip destfile="${dist.source-only-zip}">
+      <zipfileset prefix="${dist.name}" dir="${dist.dir}">
+        <include name="*src/**"/>
+        <include name="build.xml"/>
+        <include name="*.properties"/>
+        <include name="examples/**"/>
+      </zipfileset>
+    </zip>
+  </target>
+
+  <target name="compile-debugger">
+    <ant antfile="toolsrc/build.xml" target="compile-debugger"/>
+  </target>
+
+  <target name="clean" depends="properties">
+    <delete quiet="true" file="${dist.dir}/${rhino.jar}"/>
+    <delete quiet="true" file="${dist.dir}/${small-rhino.jar}"/>
+    <delete quiet="true" dir="${build.dir}"/>
+  </target>
+
+  <target name="deepclean" depends="properties">
+    <delete quiet="true" dir="${build.dir}"/>
+    <delete quiet="true" file="${dist.file}"/>
+    <delete quiet="true" file="${dist.source-only-zip}"/>
+  </target>
+
+  <!--
+    The next two targets run the JavaScript Test Library tests.  Note that these tests are quite extensive and take a long time
+    to run.  They are not documented in the 'help' target for now.
+  -->
+
+  <!--
+    Run the tests using JUnit.  Beware that if you are using Ant from the command-line, there are some difficulties you may
+    encounter setting this up correctly; see http://ant.apache.org/faq.html#delegating-classloader
+
+    IDEs that use Ant as the build system probably handle this fine.
+  -->
+  <target name="junit-all" depends="compile">
+    <ant antfile="testsrc/build.xml" target="junit-coveragereport"/>
+  </target>
+  <target name="junit" depends="compile">
+    <ant antfile="testsrc/build.xml" target="junit"/>
+  </target>
+
+   <target name="junit-benchmarks" depends="compile">
+    <ant antfile="testsrc/build.xml" target="junit-benchmarks"/>
+  </target>
+
+  <!--
+  Run the tests using the Java port of jsdriver.pl.  Note that running this port
+  from the command-line may be more useful running this Ant target, as running
+  from the command line allows configuration options, such as running with a
+  non-default optimization level, or running only a subset of the tests.
+  -->
+  <target name="jsdriver-run" depends="compile">
+      <ant antfile="testsrc/build.xml" target="jsdriver" />
+  </target>
+
+  <!--
+    Compile the JsDriver test driver.
+  -->
+  <target name="jsdriver" depends="compile">
+      <ant antfile="testsrc/build.xml" target="clean" />
+      <ant antfile="testsrc/build.xml" target="compile" />
+  </target>
+
+  <target name="benchmark-v8-opt-1" depends="jar">
+    <property name="jarfile" location="${dist.dir}/${rhino.jar}"/>
+    <java jar="${jarfile}" dir="testsrc/benchmarks/v8-benchmarks-v5" fork="true">
+      <jvmarg value="-server"/>
+      <arg line="-opt -1 run.js"/>
+    </java>
+  </target>
+
+  <target name="benchmark-v8-opt0" depends="jar">
+    <property name="jarfile" location="${dist.dir}/${rhino.jar}"/>
+    <java jar="${jarfile}" dir="testsrc/benchmarks/v8-benchmarks-v5" fork="true">
+      <jvmarg value="-server"/>
+      <arg line="-opt 0 run.js"/>
+    </java>
+  </target>
+
+  <target name="benchmark-v8-opt9" depends="jar">
+    <property name="jarfile" location="${dist.dir}/${rhino.jar}"/>
+    <java jar="${jarfile}" dir="testsrc/benchmarks/v8-benchmarks-v5" fork="true">
+      <jvmarg value="-server"/>
+      <arg line="-opt 9 run.js"/>
+    </java>
+  </target>
+
+  <target name="benchmark-sunspider-opt-1" depends="jar">
+    <property name="jarfile" location="${dist.dir}/${rhino.jar}"/>
+    <java jar="${jarfile}" dir="testsrc/benchmarks/sunspider-0.9.1" fork="true">
+      <jvmarg value="-server"/>
+      <arg line="-opt -1 run.js"/>
+    </java>
+  </target>
+
+  <target name="benchmark-sunspider-opt0" depends="jar">
+    <property name="jarfile" location="${dist.dir}/${rhino.jar}"/>
+    <java jar="${jarfile}" dir="testsrc/benchmarks/sunspider-0.9.1" fork="true">
+      <jvmarg value="-server"/>
+      <arg line="-opt 0 run.js"/>
+    </java>
+  </target>
+
+  <target name="benchmark-sunspider-opt9" depends="jar">
+    <property name="jarfile" location="${dist.dir}/${rhino.jar}"/>
+    <java jar="${jarfile}" dir="testsrc/benchmarks/sunspider-0.9.1" fork="true">
+      <jvmarg value="-server"/>
+      <arg line="-opt 9 run.js"/>
+    </java>
+  </target>
+
+  <target name="help" depends="properties">
+<echo>The following targets are available with this build file:
+
+ clean       remove all compiled classes and copied property files
+
+ compile     compile classes and copy all property files
+             into ${classes} directory
+             excluding deprecated code
+
+ compile-all compile all classes and copy all property files
+             into ${classes} directory
+             including deprecated code
+
+ deepclean   remove all generated files and directories
+
+ dist        create ${dist.file} with full Rhino distribution
+
+ help        print this help
+
+ jar         create ${rhino.jar} in ${dist.dir}
+
+ smalljar    create ${small-rhino.jar} in ${dist.dir} with
+             minimalist set of Rhino classes. See footprint.html
+             from the doc directory for details.
+
+ javadoc     generate Rhino API documentation
+             in ${dist.dir}/javadoc
+
+ source-zip  create ${dist.source-only-zip} with all Rhino
+             source files necessary to recreate ${dist.file}
+</echo>
+  </target>
+
+</project>
diff -pruN 20130227+dfsg1-14/rhino/checkstyle.xml 20130227+rhino-1/rhino/checkstyle.xml
--- 20130227+dfsg1-14/rhino/checkstyle.xml	1970-01-01 00:00:00.000000000 +0000
+++ 20130227+rhino-1/rhino/checkstyle.xml	2023-05-25 14:24:50.000000000 +0000
@@ -0,0 +1,195 @@
+<?xml version="1.0"?>
+<!DOCTYPE module PUBLIC
+          "-//Puppy Crawl//DTD Check Configuration 1.3//EN"
+          "http://checkstyle.sourceforge.net/dtds/configuration_1_3.dtd">
+
+<!--
+
+  Checkstyle configuration that checks the sun coding conventions from:
+
+    - the Java Language Specification at
+      http://java.sun.com/docs/books/jls/second_edition/html/index.html
+
+    - the Sun Code Conventions at http://java.sun.com/docs/codeconv/
+
+    - the Javadoc guidelines at
+      http://java.sun.com/j2se/javadoc/writingdoccomments/index.html
+
+    - the JDK Api documentation http://java.sun.com/j2se/docs/api/index.html
+
+    - some best practices
+
+  Checkstyle is very configurable. Be sure to read the documentation at
+  http://checkstyle.sf.net (or in your downloaded distribution).
+
+  Most Checks are configurable, be sure to consult the documentation.
+
+  To completely disable a check, just comment it out or delete it from the file.
+
+  Finally, it is worth reading the documentation.
+
+-->
+
+<module name="Checker">
+    <!--
+        If you set the basedir property below, then all reported file
+        names will be relative to the specified directory. See
+        http://checkstyle.sourceforge.net/5.x/config.html#Checker
+
+        <property name="basedir" value="${basedir}"/>
+    -->
+
+    <!-- <property name="fileExtensions" value="java, properties, xml"/> -->
+
+    <!-- Checks that a package-info.java file exists for each package.     -->
+    <!-- See http://checkstyle.sf.net/config_javadoc.html#JavadocPackage -->
+    <!-- <module name="JavadocPackage"/>-->
+
+    <!-- Checks whether files end with a new line.                        -->
+    <!-- See http://checkstyle.sf.net/config_misc.html#NewlineAtEndOfFile -->
+    <!-- <module name="NewlineAtEndOfFile"/> -->
+
+    <!-- Checks that property files contain the same keys.         -->
+    <!-- See http://checkstyle.sf.net/config_misc.html#Translation -->
+    <!-- <module name="Translation"/> -->
+
+    <!-- Checks for Size Violations.                    -->
+    <!-- See http://checkstyle.sf.net/config_sizes.html -->
+    <!--<module name="FileLength"/>-->
+
+    <!-- Checks for whitespace                               -->
+    <!-- See http://checkstyle.sf.net/config_whitespace.html -->
+    <module name="FileTabCharacter"/>
+
+    <!-- Miscellaneous other checks.                   -->
+    <!-- See http://checkstyle.sf.net/config_misc.html -->
+    <!--
+    <module name="RegexpSingleline">
+       <property name="format" value="\s+$"/>
+       <property name="minimum" value="0"/>
+       <property name="maximum" value="0"/>
+       <property name="message" value="Line has trailing spaces."/>
+    </module>
+    -->
+
+    <!-- Checks for Headers                                -->
+    <!-- See http://checkstyle.sf.net/config_header.html   -->
+    <!-- <module name="Header"> -->
+    <!--   <property name="headerFile" value="${checkstyle.header.file}"/> -->
+    <!--   <property name="fileExtensions" value="java"/> -->
+    <!-- </module> -->
+
+    <module name="TreeWalker">
+
+        <!-- Checks for Javadoc comments.                     -->
+        <!-- See http://checkstyle.sf.net/config_javadoc.html -->
+        <!--
+        <module name="JavadocMethod"/>
+        <module name="JavadocType"/>
+        <module name="JavadocVariable"/>
+        <module name="JavadocStyle"/>
+        -->
+
+        <!-- Checks for Naming Conventions.                  -->
+        <!-- See http://checkstyle.sf.net/config_naming.html -->
+        <!--
+        <module name="ConstantName"/>
+        <module name="LocalFinalVariableName"/>
+        <module name="LocalVariableName"/>
+        <module name="MemberName"/>
+        <module name="MethodName"/>
+        <module name="PackageName"/>
+        <module name="ParameterName"/>
+        <module name="StaticVariableName"/>
+        <module name="TypeName"/>
+        -->
+
+        <!-- Checks for imports                              -->
+        <!-- See http://checkstyle.sf.net/config_import.html -->
+        <!-- Unfortunately there's a lot of code to change with star imports... -->
+        <!-- <module name="AvoidStarImport"/> -->
+        <module name="IllegalImport"/>
+        <!-- defaults to sun.* packages -->
+        <module name="RedundantImport"/>
+        <module name="UnusedImports">
+            <property name="processJavadoc" value="true"/>
+        </module>
+        <!-- Checks for Size Violations.                    -->
+        <!-- See http://checkstyle.sf.net/config_sizes.html -->
+        <!--
+        <module name="LineLength"/>
+        <module name="MethodLength"/>
+        <module name="ParameterNumber"/>
+        -->
+
+        <!-- Checks for whitespace                               -->
+        <!-- See http://checkstyle.sf.net/config_whitespace.html -->
+        <!--
+        <module name="EmptyForIteratorPad"/>
+        <module name="GenericWhitespace"/>
+        <module name="MethodParamPad"/>
+        <module name="NoWhitespaceAfter"/>
+        <module name="NoWhitespaceBefore"/>
+        <module name="OperatorWrap"/>
+        <module name="ParenPad"/>
+        <module name="TypecastParenPad"/>
+        <module name="WhitespaceAfter"/>
+        <module name="WhitespaceAround"/>
+        -->
+
+        <!-- Modifier Checks                                    -->
+        <!-- See http://checkstyle.sf.net/config_modifiers.html -->
+        <!--
+        <module name="ModifierOrder"/>
+        <module name="RedundantModifier"/>
+        -->
+
+        <!-- Checks for blocks. You know, those {}'s         -->
+        <!-- See http://checkstyle.sf.net/config_blocks.html -->
+        <!--
+        <module name="AvoidNestedBlocks"/>
+        <module name="EmptyBlock"/>
+        <module name="LeftCurly"/>
+        <module name="NeedBraces"/>
+        <module name="RightCurly"/>
+        -->
+
+        <!-- Checks for common coding problems               -->
+        <!-- See http://checkstyle.sf.net/config_coding.html -->
+        <!-- <module name="AvoidInlineConditionals"/> -->
+        <module name="CovariantEquals"/>
+        <module name="EmptyStatement"/>
+        <module name="EqualsHashCode"/>
+        <module name="FallThrough"/>
+        <!-- <module name="HiddenField"/> -->
+        <module name="IllegalInstantiation"/>
+        <module name="NoClone"/>
+        <module name="NoFinalizer"/>
+        <!-- <module name="InnerAssignment"/> -->
+        <module name="SimplifyBooleanExpression"/>
+        <module name="SimplifyBooleanReturn"/>
+        <module name="StringLiteralEquality"/>
+        <module name="SuperClone"/>
+
+        <!-- Checks for class design                         -->
+        <!-- See http://checkstyle.sf.net/config_design.html -->
+        <!--
+        <module name="DesignForExtension"/>
+        <module name="FinalClass"/>
+        <module name="HideUtilityClassConstructor"/>
+        <module name="InterfaceIsType"/>
+        <module name="VisibilityModifier"/>
+        -->
+
+        <!-- Miscellaneous other checks.                   -->
+        <!-- See http://checkstyle.sf.net/config_misc.html -->
+        <!-- -->
+        <!-- <module name="ArrayTypeStyle"/> -->
+        <!-- <module name="FinalParameters"/> -->
+        <!-- <module name="TodoComment"/> -->
+        <module name="UpperEll"/>
+        <!-- -->
+
+    </module>
+
+</module>
diff -pruN 20130227+dfsg1-14/rhino/debian/bin/rhino 20130227+rhino-1/rhino/debian/bin/rhino
--- 20130227+dfsg1-14/rhino/debian/bin/rhino	1970-01-01 00:00:00.000000000 +0000
+++ 20130227+rhino-1/rhino/debian/bin/rhino	2023-05-25 14:27:27.000000000 +0000
@@ -0,0 +1,18 @@
+#!/bin/sh
+
+JAVA_CMD="/usr/bin/java"
+JAVA_OPTS=""
+JAVA_CLASSPATH="/usr/share/java/js.jar:/usr/share/java/jline.jar"
+JAVA_MAIN="org.mozilla.javascript.tools.shell.Main"
+
+## 
+## Remove bootclasspath overriding for OpenJDK since
+## it now use a mangled version of Rhino (in sun.org.mozilla.rhino package)
+##
+## References:
+## <https://bugs.launchpad.net/ubuntu/+source/openjdk-6/+bug/255149>
+## <http://icedtea.classpath.org/bugzilla/show_bug.cgi?id=179>
+## <http://www.openoffice.org/issues/show_bug.cgi?id=91641>
+##
+
+$JAVA_CMD $JAVA_OPTS -classpath $JAVA_CLASSPATH $JAVA_MAIN "$@"
diff -pruN 20130227+dfsg1-14/rhino/debian/bin/rhino-debugger 20130227+rhino-1/rhino/debian/bin/rhino-debugger
--- 20130227+dfsg1-14/rhino/debian/bin/rhino-debugger	1970-01-01 00:00:00.000000000 +0000
+++ 20130227+rhino-1/rhino/debian/bin/rhino-debugger	2023-05-25 14:27:27.000000000 +0000
@@ -0,0 +1,8 @@
+#!/bin/sh
+
+JAVA_CMD="/usr/bin/java"
+JAVA_OPTS=""
+JAVA_CLASSPATH="/usr/share/java/js.jar"
+JAVA_MAIN="org.mozilla.javascript.tools.debugger.Main"
+
+$JAVA_CMD $JAVA_OPTS -classpath $JAVA_CLASSPATH $JAVA_MAIN "$@"
diff -pruN 20130227+dfsg1-14/rhino/debian/bin/rhino-jsc 20130227+rhino-1/rhino/debian/bin/rhino-jsc
--- 20130227+dfsg1-14/rhino/debian/bin/rhino-jsc	1970-01-01 00:00:00.000000000 +0000
+++ 20130227+rhino-1/rhino/debian/bin/rhino-jsc	2023-05-25 14:27:27.000000000 +0000
@@ -0,0 +1,9 @@
+#!/bin/sh
+
+JAVA_CMD="/usr/bin/java"
+JAVA_OPTS=""
+JAVA_CLASSPATH="/usr/share/java/js.jar"
+JAVA_MAIN="org.mozilla.javascript.tools.jsc.Main"
+
+$JAVA_CMD $JAVA_OPTS -classpath $JAVA_CLASSPATH $JAVA_MAIN "$@"
+
diff -pruN 20130227+dfsg1-14/rhino/debian/changelog 20130227+rhino-1/rhino/debian/changelog
--- 20130227+dfsg1-14/rhino/debian/changelog	1970-01-01 00:00:00.000000000 +0000
+++ 20130227+rhino-1/rhino/debian/changelog	2023-05-25 14:27:27.000000000 +0000
@@ -0,0 +1,405 @@
+rhino (1.7.7.2-3) unstable; urgency=medium
+
+  * Team upload.
+  * Backported the JSR 223 script engine to use Rhino as a replacement
+    for Nashorn with OpenJDK 17
+  * Standards-Version updated to 4.5.1
+  * Switch to debhelper level 13
+
+ -- Emmanuel Bourg <ebourg@apache.org>  Mon, 08 Feb 2021 11:39:29 +0100
+
+rhino (1.7.7.2-2) UNRELEASED; urgency=medium
+
+  * Team upload.
+  * Add patch to install JAR as 1.7.7.2 (not 1.7.7.1)
+
+ -- tony mancill <tmancill@debian.org>  Wed, 25 Nov 2020 12:02:51 -0800
+
+rhino (1.7.7.2-1) unstable; urgency=medium
+
+  * Team upload.
+  * New upstream release
+    - Refreshed the patches
+  * Removed Damien Raude-Morvan from the uploaders (Closes: #889449)
+  * Track the releases > 1.7.7.1
+  * Standards-Version updated to 4.5.0
+  * Use salsa.debian.org Vcs-* URLs
+
+ -- Emmanuel Bourg <ebourg@apache.org>  Thu, 03 Sep 2020 13:59:51 +0200
+
+rhino (1.7.7.1-1) unstable; urgency=medium
+
+  * Team upload.
+  * New upstream release
+    - Refreshed the patches
+    - Removed 04_bug_798642_800616.diff (fixed upstream)
+    - Removed the build dependency on libxmlbeans-java
+    - Require a Java 6 runtime or higher
+    - Use the pom from the upstream sources to install the Maven artifacts,
+      and relocate the old coordinates rhino:js to org.mozilla:rhino
+    - Reintroduced some removed classes and methods to preserve the backward
+      compatibility and fix build failures in reverse dependencies.
+    - Fixed a bug in Context.getImplementationVersion() when the project
+      is built with Ant
+  * Removed the transitional package rhino-doc
+  * Updated the man pages (Closes: #792243)
+  * Build with the DH sequencer instead of CDBS
+  * Simplified the usage syntax displayed with the --help option
+  * Removed the out of tree debugger classes (merged upstream)
+  * Ignore the Lintian warnings on the test files (false positives)
+  * Install the upstream changelog
+  * Standards-Version updated to 3.9.8
+  * Switch to debhelper level 10
+  * Use secure Vcs-* URLs
+  * Track and download the new releases from GitHub
+  * Converted debian/copyright to the Copyright Format 1.0
+  * Removed the unused Lintian overrides
+
+ -- Emmanuel Bourg <ebourg@apache.org>  Fri, 20 Jan 2017 11:04:18 +0100
+
+rhino (1.7R4-4) unstable; urgency=medium
+
+  * Add a symlink /usr/share/java/rhino.jar which points to js.jar
+
+ -- Sylvestre Ledru <sylvestre@debian.org>  Tue, 03 Jun 2014 13:19:15 +0200
+
+rhino (1.7R4-3) unstable; urgency=medium
+
+  * Team upload
+  * Apply pull request https://github.com/mozilla/rhino/pull/138 to get
+    798642 and 800616 bug fixed. Necessary for jscover package
+  * Update the uploader list (Closes: #741281)
+  * d/control: Bump Standards-Version to 3.9.5 (no changes needed).
+
+ -- Sylvestre Ledru <sylvestre@debian.org>  Mon, 02 Jun 2014 18:06:04 +0200
+
+rhino (1.7R4-2) unstable; urgency=low
+
+  * Upload to unstable.
+   - closure-compiler FTBFS will be fixed.
+
+ -- Damien Raude-Morvan <drazzib@debian.org>  Sat, 17 Aug 2013 11:55:09 +0200
+
+rhino (1.7R4-1) experimental; urgency=low
+
+  [ Thomas Koch ]
+  * New upstream version (Closes: #699352, #661277, #630341).
+  * Switched packaging to Git
+
+  [ Damien Raude-Morvan ]
+  * d/copyright: Update license to MPL 2.0.
+  * d/control: Bump Standards-Version to 3.9.4 (no changes needed).
+  * Add lintian overrides for
+    'copyright-should-refer-to-common-license-file-for-gpl'.
+
+ -- Damien Raude-Morvan <drazzib@debian.org>  Sat, 16 Feb 2013 22:46:55 +0100
+
+rhino (1.7R3-5) unstable; urgency=low
+
+  [ Giovanni Mascellani ]
+  * Making getSourcePositionFromStack public (used by geogebra).
+    Closes: #659619.
+
+  [ Damien Raude-Morvan ]
+  * Upload to unstable.
+  * Remove Michael Koch from Uploaders (Closes: #654130).
+  * d/control: Wrap-and-sort
+
+ -- Damien Raude-Morvan <drazzib@debian.org>  Mon, 13 Feb 2012 23:52:51 +0100
+
+rhino (1.7R3-4) unstable; urgency=low
+
+  * Add OSGi metadata to jar manifest
+  * Add javahelper to Build-Depends:
+  * Add Jakub Adam to Uploaders:
+
+ -- Jakub Adam <jakub.adam@ktknet.cz>  Wed, 23 Nov 2011 10:21:50 +0100
+
+rhino (1.7R3-3) unstable; urgency=low
+
+  * Since OpenJDK{6,7} now use a mangled version of Rhino
+    (in "sun.org.mozilla.rhino" package), there is no need to override
+    bootclasspath :
+    - Fix "Incorrect classpath prevents running on AMD64" (Closes: #649131)
+    - Fix "js: Error occurred during initialization ov VM" (Closes: #649281)
+
+ -- Damien Raude-Morvan <drazzib@debian.org>  Sun, 20 Nov 2011 12:15:19 +0100
+
+rhino (1.7R3-2) unstable; urgency=low
+
+  * Upload to unstable.
+
+ -- Damien Raude-Morvan <drazzib@debian.org>  Sun, 12 Jun 2011 21:56:54 +0200
+
+rhino (1.7R3-1) experimental; urgency=low
+
+  * New upstream release:
+    - Upstream changelog <https://developer.mozilla.org/en/New_in_Rhino_1.7R3>
+    - Refresh all patches.
+  * Bump Standards-Version to 3.9.2 (no changes needed).
+  * d/rules: replace "rm debian/tmp" by mh_clean call.
+
+ -- Damien Raude-Morvan <drazzib@debian.org>  Wed, 25 May 2011 23:43:56 +0200
+
+rhino (1.7R3~pre-2) experimental; urgency=low
+
+  * Fix parsing of command line arguments by using quotes.
+    Thanks to Chris Lamb and Chris West for bugreport and patch
+    (Closes: #609965).
+  * Update rhino packaging to follow latest Debian Java Policy:
+    - move javadoc to a librhino-java-doc package.
+    - make rhino-doc package an empty transitional package.
+    - move jar/pom to a librhino-java package (which doesn't depends
+      on any java runtime).
+    - keep rhino interpreter in his own rhino package with a depends
+      on java5-runtime.
+
+ -- Damien Raude-Morvan <drazzib@debian.org>  Sat, 12 Mar 2011 02:08:43 +0100
+
+rhino (1.7R3~pre-1) experimental; urgency=low
+
+  * New upstream snapshot of 1.7R3:
+    - Needed by OpenJDK7 >= b126
+    - d/patches/*: Refresh all patches
+    - d/rules: Force version installed by mh_* tools
+  * Bump Standards-Version to 3.9.1 (no changes needed)
+  * Switch to 3.0 (quilt) source format
+
+ -- Damien Raude-Morvan <drazzib@debian.org>  Mon, 24 Jan 2011 19:49:04 +0100
+
+rhino (1.7R2-4) unstable; urgency=low
+
+  * Enable E4X support:
+    - Build-Depends on libxmlbeans-java
+    - Set JAR location in debian/ant.properties
+    - Should fix (Closes: #567847) and (LP: #304702)
+  * Bump Standards-Version to 3.8.4 (no changes needed)
+  * Fix small typo in rhino-jsc manpage
+  * Fix debian/copyright: don't use symlink to license
+
+ -- Damien Raude-Morvan <drazzib@debian.org>  Sat, 06 Feb 2010 21:19:47 +0100
+
+rhino (1.7R2-3) unstable; urgency=low
+
+  * Maven POMs:
+    - debian/control: add a Build-Depends on maven-repo-helper
+    - debian/rules: use mh_installpoms and mh_installjar
+      to install the POM and the jar to the Maven repository
+    - debian/pom.xml: Debian pom.xml file as upstream doesn't provide one
+    - debian/rules: new get-orig-pom to update debian/pom.xml at new upstream
+      release.
+  * Bump debhelper version to >= 7
+  * debian/rhino.1: Describe more precisly optimization levels and add missing
+    level '-1'. Thanks to Marcus Better for notifying (Closes: #558086)
+  * Remove Arnaud Vandyck from Uploaders
+  * Add description to debian/patches/*.diff
+
+ -- Damien Raude-Morvan <drazzib@debian.org>  Sat, 12 Dec 2009 15:18:24 +0100
+
+rhino (1.7R2-2) unstable; urgency=low
+
+  * Switch to Quilt patch system:
+    - Refresh all patches
+    - Add B-D on quilt
+    - Include patchsys-quilt.mk in debian/rules
+  * Bump Standards-Version to 3.8.3:
+    - Add a README.source to describe patch system
+  * Add a manpage for rhino-debugger script
+  * Build-Depends on default-jdk instead of default-jdk-builddep
+    because we don't build a native GCJ package
+  * Move api documentation to /usr/share/doc/rhino/api/
+  * debian/control: Improve rhino-doc package long description
+  * debian/copyright: Add missing BSD licence (3 clauses) for files under
+    toolsrc/org/mozilla/javascript/tools/debugger/treetable
+  * Update my email address
+
+ -- Damien Raude-Morvan <drazzib@debian.org>  Fri, 02 Oct 2009 22:23:46 +0200
+
+rhino (1.7R2-1) unstable; urgency=low
+
+  [ Marcus Better ]
+  * Updated package descriptions.
+
+  [ Matthias Klose ]
+  * (Build-)depend on default-jre-headless/-jdk.
+  * Drop alternate dependencies on java2-runtime-headless and
+    java2-runtime-headless. The binary package is currently built to
+    require a java5 runtime.
+
+  [ Damien Raude-Morvan ]
+  * New upstream release.
+    - new 02_exclude-jdk15 patch to exclude already compiled classes
+      for jdk15 rebuild: gcj doesn't handle compiling classes already
+      on its classpath
+    - new "rhino-debugger" launcher for Rhino Debugger Swing UI
+    - update "rhino" launcher to exclude OpenJDK bundled rhino (Closes: #512498)
+  * debian/{postinst,prerm }: scripts should take care of errors,
+    add set -e before any instruction
+  * debian/rules: add new get-orig-source target using uscan
+  * debian/control:
+    - Build-Depends on specialized default-jdk-builddep instead of
+    default-jdk
+    - Bump Standards-Version to 3.8.1: Wrap Uploaders field
+    - add Depends on ${misc:Depends}
+
+ -- Damien Raude-Morvan <drazzib@drazzib.com>  Mon, 13 Apr 2009 02:40:15 +0200
+
+rhino (1.7R2~pre-2) experimental; urgency=low
+
+  * Really include the debugger. Closes: #474046. 
+
+ -- Michael Koch <konqueror@gmx.de>  Sat, 05 Apr 2008 15:03:43 +0200
+
+rhino (1.7R2~pre-1) experimental; urgency=low
+
+  * New upstream release.
+  * Upload to experimental.
+  * Enable build of debugger. Closes: #474046.
+
+ -- Michael Koch <konqueror@gmx.de>  Fri, 04 Apr 2008 10:32:47 +0200
+
+rhino (1.7R1-1) unstable; urgency=low
+
+  * New upstream release.
+
+ -- Michael Koch <konqueror@gmx.de>  Sat, 22 Mar 2008 13:49:49 +0100
+
+rhino (1.7R1~RC3-1) experimental; urgency=low
+
+  * New upstream version.
+  * Fixed hyphen in rhino-jsc manpage.
+  * Updated watch file to handle upstream RC versions.
+  * Updated Standards-Version to 3.7.3.
+
+ -- Michael Koch <konqueror@gmx.de>  Tue, 19 Feb 2008 11:17:45 +0100
+
+rhino (1.6.R7-2) unstable; urgency=low
+
+  * Fixed bashism in debian/rules. Closes: #453766.
+  * Fixed names of Homepage, Vcs-Svn and Vcs-Browser fields.
+  * Added myself to Uploaders.
+
+ -- Michael Koch <konqueror@gmx.de>  Sat, 01 Dec 2007 11:56:31 +0100
+
+rhino (1.6.R7-1) unstable; urgency=low
+
+  * New upstream version.
+
+ -- Marcus Better <marcus@better.se>  Thu, 11 Oct 2007 15:50:42 +0200
+
+rhino (1.6.R5-3) unstable; urgency=low
+
+  * Removed Wolfgang Baer from Uploaders and added myself.
+  * Fixed FTBFS: java.net.ConnectException: Connection refused.
+    Was trying to download xmlbeans Jar, which is not allowed. As
+    this Jar is not (yet) in Debian, rhino has been built with XML
+    implementation disabled.
+    A bug in 1.6.R5-2 meant that it was still trying to download the
+    "treetable" source. This has been fixed in debian/rules by copying the
+    sample source code into the "downloaded" directory (the sample source code
+    had to be modified).
+    (Closes: #424466)
+  * Moved "-doc" package to doc section.
+
+ -- Paul Cager <paul-debian@home.paulcager.org>  Sun, 15 Jul 2007 00:32:12 +0100
+
+rhino (1.6.R5-2) unstable; urgency=low
+
+  * added java classes from a tutorial from Sun (BSD license as mentionned
+    in #409629), thanks to Roktas, Filipe Lautert and Bruno Harbulot for
+    filing bug, giving infos and proposed a patch (even if it's not
+    used). I've just removed the 02-dont_build-toolsrc.patch. I added the
+    classes examples if needed but it seems not to be the case (closes:
+    #409629).
+
+ -- Arnaud Vandyck <avdyk@debian.org>  Fri, 11 May 2007 14:07:21 +0200
+
+rhino (1.6.R5-1) unstable; urgency=low
+
+  * New upstream maintenance release.
+
+ -- Matthias Klose <doko@debian.org>  Sat,  3 Feb 2007 16:46:28 +0100
+
+rhino (1.6R2-3) unstable; urgency=low
+
+  * debian/patches/02-dont_build-toolsrc.patch: added. Don't build toolsrc
+    and xmlimplsrc because they use Sun classes to build. If you want to
+    build them, just remove the file (closes: #395525).
+
+ -- Arnaud Vandyck <avdyk@debian.org>  Mon,  6 Nov 2006 12:54:28 +0100
+
+rhino (1.6R2-2) unstable; urgency=low
+
+  * Changed the dependency from kaffe to java-gcj-compat.
+
+ -- Arnaud Vandyck <avdyk@debian.org>  Sun,  5 Nov 2006 17:45:52 +0100
+
+rhino (1.6R2-1) unstable; urgency=low
+
+  * New upstream (closes: #350971).
+  * Removed Takashi Okamoto <tora@debian.org> from uploaders (closes:
+    #352992)
+  * Updated Standards-Version to 3.7.2: moved debhelper and cdbs to
+    Build-Depends.
+  * Build with java-gcj-compat.
+  * debian/copyright: updated the download url.
+  * debian/watch: new file.
+
+ -- Arnaud Vandyck <avdyk@debian.org>  Mon, 17 Jul 2006 14:50:36 +0200
+
+rhino (1.5.R5-5) unstable; urgency=low
+
+  * Removed explicit usage of jikes build compiler property
+    for kaffe jikes -> ecj transition  
+
+ -- Wolfgang Baer <WBaer@gmx.de>  Fri,  6 Jan 2006 18:54:28 +0100
+
+rhino (1.5.R5-4) unstable; urgency=low
+
+  * libant1.6-java to ant transition
+  * Removed dependency on java-common
+  * Added suggests to rhino-doc and other way round
+  * Registered documentation with doc-base
+  * Fixed lintian warning in postinst and added override
+    for false positive lintian warning
+  * Standards-Version 3.6.2 (no changes)
+
+ -- Wolfgang Baer <WBaer@gmx.de>  Sat, 24 Sep 2005 23:31:36 +0200
+
+rhino (1.5.R5-3) unstable; urgency=low
+  
+  * Added java2-runtime to runtime choices
+  * Removed build.xml workaround patch which is no longer
+    needed with the current kaffe in sarge/unstable
+
+ -- Wolfgang Baer <WBaer@gmx.de>  Wed, 13 Apr 2005 19:30:40 +0200
+
+rhino (1.5.R5-2) unstable; urgency=low
+  
+  * Closes: #283651: alternative without a manpage
+  * upload to main: uses kaffe,jikes to build
+  * provide JavaScript compiler as rhino-jsc with manpage
+  * Arnaud Vandyck <avdyk@debian.org> did sponsor this package. As a
+    member of pkg-java Alioth's project, I added Wolfgang as uploaders
+
+ -- Wolfgang Baer <WBaer@gmx.de>  Sat, 12 Feb 2005 11:56:06 +0000
+
+rhino (1.5.R5-1) unstable; urgency=low
+
+  * New upstream release
+  * changed the build system to cdbs
+
+ -- Arnaud Vandyck <avdyk@debian.org>  Sun, 21 Nov 2004 14:29:34 +0100
+
+rhino (1.5.R2-2) unstable; urgency=low
+
+  * Add alternative for /usr/bin/js. The patch is provided by Brian 
+    Bassett. (Closes:#122669)
+
+ -- Takashi Okamoto <tora@debian.org>  Sat,  8 Dec 2001 10:45:06 +0900
+
+rhino (1.5.R2-1) unstable; urgency=low
+
+  * Initial Release.
+
+ -- Takashi Okamoto <tora@debian.org>  Fri, 16 Nov 2001 23:51:38 +0900
diff -pruN 20130227+dfsg1-14/rhino/debian/clean 20130227+rhino-1/rhino/debian/clean
--- 20130227+dfsg1-14/rhino/debian/clean	1970-01-01 00:00:00.000000000 +0000
+++ 20130227+rhino-1/rhino/debian/clean	2023-05-25 14:27:27.000000000 +0000
@@ -0,0 +1 @@
+build/
diff -pruN 20130227+dfsg1-14/rhino/debian/control 20130227+rhino-1/rhino/debian/control
--- 20130227+dfsg1-14/rhino/debian/control	1970-01-01 00:00:00.000000000 +0000
+++ 20130227+rhino-1/rhino/debian/control	2023-05-25 14:27:27.000000000 +0000
@@ -0,0 +1,60 @@
+Source: rhino
+Section: interpreters
+Priority: optional
+Maintainer: Debian Java Maintainers <pkg-java-maintainers@lists.alioth.debian.org>
+Uploaders:
+ Marcus Better <marcus@better.se>,
+ Jakub Adam <jakub.adam@ktknet.cz>
+Build-Depends:
+ ant,
+ debhelper-compat (= 13),
+ default-jdk,
+ javahelper,
+ maven-repo-helper
+Standards-Version: 4.5.1
+Vcs-Git: https://salsa.debian.org/java-team/rhino.git
+Vcs-Browser: https://salsa.debian.org/java-team/rhino
+Homepage: http://www.mozilla.org/rhino/
+
+Package: rhino
+Architecture: all
+Depends:
+ default-jre-headless (>= 1:1.6) | java6-runtime-headless,
+ libjline-java,
+ librhino-java (= ${source:Version}),
+ ${misc:Depends}
+Suggests: librhino-java-doc
+Description: JavaScript engine written in Java
+ Rhino is an implementation of the JavaScript language written
+ entirely in Java. It is typically embedded into Java applications to
+ provide scripting to end users.
+
+Package: librhino-java
+Section: java
+Architecture: all
+Replaces: rhino (<< 1.7R3~pre-2)
+Conflicts: rhino (<< 1.7R3~pre-2)
+Depends: ${misc:Depends}
+Suggests: rhino
+Description: Libraries for rhino Java Script Engine
+ Rhino is an implementation of the JavaScript language written
+ entirely in Java. It is typically embedded into Java applications to
+ provide scripting to end users.
+ .
+ This package contains only Java library and no interpreter. For
+ Rhino interpreter, you install rhino package.
+
+Package: librhino-java-doc
+Section: doc
+Architecture: all
+Replaces: rhino-doc (<< 1.7R3~pre-2)
+Conflicts: rhino-doc (<< 1.7R3~pre-2)
+Depends: ${misc:Depends}
+Suggests: rhino
+Description: Documentation for rhino Java Script Engine
+ Rhino is an implementation of the JavaScript language written
+ entirely in Java. It is typically embedded into Java applications to
+ provide scripting to end users.
+ .
+ This is the documentation, including API JavaDoc, for the Rhino
+ JavaScript engine.
diff -pruN 20130227+dfsg1-14/rhino/debian/copyright 20130227+rhino-1/rhino/debian/copyright
--- 20130227+dfsg1-14/rhino/debian/copyright	1970-01-01 00:00:00.000000000 +0000
+++ 20130227+rhino-1/rhino/debian/copyright	2023-05-25 14:27:27.000000000 +0000
@@ -0,0 +1,456 @@
+Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
+Upstream-Name: Rhino
+Source: https://github.com/mozilla/rhino
+Files-Excluded: gradlew*
+                gradle/wrapper
+
+Files: *
+Copyright: 1999-2015, Mozilla
+License: MPL-2.0
+
+Files: src/org/mozilla/javascript/v8dtoa/*
+Copyright: 2010, the V8 project authors
+License: BSD-3-clause-google
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are
+ met:
+     * Redistributions of source code must retain the above copyright
+       notice, this list of conditions and the following disclaimer.
+     * Redistributions in binary form must reproduce the above
+       copyright notice, this list of conditions and the following
+       disclaimer in the documentation and/or other materials provided
+       with the distribution.
+     * Neither the name of Google Inc. nor the names of its
+       contributors may be used to endorse or promote products derived
+       from this software without specific prior written permission.
+ .
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Files: toolsrc/org/mozilla/javascript/tools/debugger/treetable/*
+Copyright: 1997-1998 Sun Microsystems, Inc
+License: BSD-3-clause-sun
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+ .
+   - Redistributions of source code must retain the above copyright
+     notice, this list of conditions and the following disclaimer.
+ .
+   - Redistributions in binary form must reproduce the above copyright
+     notice, this list of conditions and the following disclaimer in the
+     documentation and/or other materials provided with the distribution.
+ .
+   - Neither the name of Sun Microsystems nor the names of its
+     contributors may be used to endorse or promote products derived
+     from this software without specific prior written permission.
+ .
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Files: debian/*
+Copyright: 2001, Takashi Okamoto <tora@debian.org>
+           2004-2007, Arnaud Vandyck <avdyk@debian.org>
+           2005-2006, Wolfgang Baer <WBaer@gmx.de>
+           2007-2009, Matthias Klose <doko@debian.org>
+           2007, Paul Cager <paul-debian@home.paulcager.org>
+           2007-2009, Marcus Better <marcus@better.se>
+           2007-2008, Michael Koch <konqueror@gmx.de>
+           2009-2013, Damien Raude-Morvan <drazzib@debian.org>
+           2011, Jakub Adam <jakub.adam@ktknet.cz>
+           2014, Sylvestre Ledru <sylvestre@debian.org>
+           2017, Emmanuel Bourg <ebourg@apache.org>
+License: MPL-2.0
+
+License: MPL-2.0
+ Mozilla Public License Version 2.0
+ ==================================
+ .
+ 1. Definitions
+ --------------
+ .
+ 1.1. "Contributor"
+     means each individual or legal entity that creates, contributes to
+     the creation of, or owns Covered Software.
+ .
+ 1.2. "Contributor Version"
+     means the combination of the Contributions of others (if any) used
+     by a Contributor and that particular Contributor's Contribution.
+ .
+ 1.3. "Contribution"
+     means Covered Software of a particular Contributor.
+ .
+ 1.4. "Covered Software"
+     means Source Code Form to which the initial Contributor has attached
+     the notice in Exhibit A, the Executable Form of such Source Code
+     Form, and Modifications of such Source Code Form, in each case
+     including portions thereof.
+ .
+ 1.5. "Incompatible With Secondary Licenses"
+     means
+ .
+     (a) that the initial Contributor has attached the notice described
+         in Exhibit B to the Covered Software; or
+ .
+     (b) that the Covered Software was made available under the terms of
+         version 1.1 or earlier of the License, but not also under the
+         terms of a Secondary License.
+ .
+ 1.6. "Executable Form"
+     means any form of the work other than Source Code Form.
+ .
+ 1.7. "Larger Work"
+     means a work that combines Covered Software with other material, in
+     a separate file or files, that is not Covered Software.
+ .
+ 1.8. "License"
+     means this document.
+ .
+ 1.9. "Licensable"
+     means having the right to grant, to the maximum extent possible,
+     whether at the time of the initial grant or subsequently, any and
+     all of the rights conveyed by this License.
+ .
+ 1.10. "Modifications"
+     means any of the following:
+ .
+     (a) any file in Source Code Form that results from an addition to,
+         deletion from, or modification of the contents of Covered
+         Software; or
+ .
+     (b) any new file in Source Code Form that contains any Covered
+         Software.
+ .
+ 1.11. "Patent Claims" of a Contributor
+     means any patent claim(s), including without limitation, method,
+     process, and apparatus claims, in any patent Licensable by such
+     Contributor that would be infringed, but for the grant of the
+     License, by the making, using, selling, offering for sale, having
+     made, import, or transfer of either its Contributions or its
+     Contributor Version.
+ .
+ 1.12. "Secondary License"
+     means either the GNU General Public License, Version 2.0, the GNU
+     Lesser General Public License, Version 2.1, the GNU Affero General
+     Public License, Version 3.0, or any later versions of those
+     licenses.
+ .
+ 1.13. "Source Code Form"
+     means the form of the work preferred for making modifications.
+ .
+ 1.14. "You" (or "Your")
+     means an individual or a legal entity exercising rights under this
+     License. For legal entities, "You" includes any entity that
+     controls, is controlled by, or is under common control with You. For
+     purposes of this definition, "control" means (a) the power, direct
+     or indirect, to cause the direction or management of such entity,
+     whether by contract or otherwise, or (b) ownership of more than
+     fifty percent (50%) of the outstanding shares or beneficial
+     ownership of such entity.
+ .
+ 2. License Grants and Conditions
+ --------------------------------
+ .
+ 2.1. Grants
+ .
+ Each Contributor hereby grants You a world-wide, royalty-free,
+ non-exclusive license:
+ .
+ (a) under intellectual property rights (other than patent or trademark)
+     Licensable by such Contributor to use, reproduce, make available,
+     modify, display, perform, distribute, and otherwise exploit its
+     Contributions, either on an unmodified basis, with Modifications, or
+     as part of a Larger Work; and
+ .
+ (b) under Patent Claims of such Contributor to make, use, sell, offer
+     for sale, have made, import, and otherwise transfer either its
+     Contributions or its Contributor Version.
+ .
+ 2.2. Effective Date
+ .
+ The licenses granted in Section 2.1 with respect to any Contribution
+ become effective for each Contribution on the date the Contributor first
+ distributes such Contribution.
+ .
+ 2.3. Limitations on Grant Scope
+ .
+ The licenses granted in this Section 2 are the only rights granted under
+ this License. No additional rights or licenses will be implied from the
+ distribution or licensing of Covered Software under this License.
+ Notwithstanding Section 2.1(b) above, no patent license is granted by a
+ Contributor:
+ .
+ (a) for any code that a Contributor has removed from Covered Software;
+     or
+ .
+ (b) for infringements caused by: (i) Your and any other third party's
+     modifications of Covered Software, or (ii) the combination of its
+     Contributions with other software (except as part of its Contributor
+     Version); or
+ .
+ (c) under Patent Claims infringed by Covered Software in the absence of
+     its Contributions.
+ .
+ This License does not grant any rights in the trademarks, service marks,
+ or logos of any Contributor (except as may be necessary to comply with
+ the notice requirements in Section 3.4).
+ .
+ 2.4. Subsequent Licenses
+ .
+ No Contributor makes additional grants as a result of Your choice to
+ distribute the Covered Software under a subsequent version of this
+ License (see Section 10.2) or under the terms of a Secondary License (if
+ permitted under the terms of Section 3.3).
+ .
+ 2.5. Representation
+ .
+ Each Contributor represents that the Contributor believes its
+ Contributions are its original creation(s) or it has sufficient rights
+ to grant the rights to its Contributions conveyed by this License.
+ .
+ 2.6. Fair Use
+ .
+ This License is not intended to limit any rights You have under
+ applicable copyright doctrines of fair use, fair dealing, or other
+ equivalents.
+ .
+ 2.7. Conditions
+ .
+ Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted
+ in Section 2.1.
+ .
+ 3. Responsibilities
+ -------------------
+ .
+ 3.1. Distribution of Source Form
+ .
+ All distribution of Covered Software in Source Code Form, including any
+ Modifications that You create or to which You contribute, must be under
+ the terms of this License. You must inform recipients that the Source
+ Code Form of the Covered Software is governed by the terms of this
+ License, and how they can obtain a copy of this License. You may not
+ attempt to alter or restrict the recipients' rights in the Source Code
+ Form.
+ .
+ 3.2. Distribution of Executable Form
+ .
+ If You distribute Covered Software in Executable Form then:
+ .
+ (a) such Covered Software must also be made available in Source Code
+     Form, as described in Section 3.1, and You must inform recipients of
+     the Executable Form how they can obtain a copy of such Source Code
+     Form by reasonable means in a timely manner, at a charge no more
+     than the cost of distribution to the recipient; and
+ .
+ (b) You may distribute such Executable Form under the terms of this
+     License, or sublicense it under different terms, provided that the
+     license for the Executable Form does not attempt to limit or alter
+     the recipients' rights in the Source Code Form under this License.
+ .
+ 3.3. Distribution of a Larger Work
+ .
+ You may create and distribute a Larger Work under terms of Your choice,
+ provided that You also comply with the requirements of this License for
+ the Covered Software. If the Larger Work is a combination of Covered
+ Software with a work governed by one or more Secondary Licenses, and the
+ Covered Software is not Incompatible With Secondary Licenses, this
+ License permits You to additionally distribute such Covered Software
+ under the terms of such Secondary License(s), so that the recipient of
+ the Larger Work may, at their option, further distribute the Covered
+ Software under the terms of either this License or such Secondary
+ License(s).
+ .
+ 3.4. Notices
+ .
+ You may not remove or alter the substance of any license notices
+ (including copyright notices, patent notices, disclaimers of warranty,
+ or limitations of liability) contained within the Source Code Form of
+ the Covered Software, except that You may alter any license notices to
+ the extent required to remedy known factual inaccuracies.
+ .
+ 3.5. Application of Additional Terms
+ .
+ You may choose to offer, and to charge a fee for, warranty, support,
+ indemnity or liability obligations to one or more recipients of Covered
+ Software. However, You may do so only on Your own behalf, and not on
+ behalf of any Contributor. You must make it absolutely clear that any
+ such warranty, support, indemnity, or liability obligation is offered by
+ You alone, and You hereby agree to indemnify every Contributor for any
+ liability incurred by such Contributor as a result of warranty, support,
+ indemnity or liability terms You offer. You may include additional
+ disclaimers of warranty and limitations of liability specific to any
+ jurisdiction.
+ .
+ 4. Inability to Comply Due to Statute or Regulation
+ ---------------------------------------------------
+ .
+ If it is impossible for You to comply with any of the terms of this
+ License with respect to some or all of the Covered Software due to
+ statute, judicial order, or regulation then You must: (a) comply with
+ the terms of this License to the maximum extent possible; and (b)
+ describe the limitations and the code they affect. Such description must
+ be placed in a text file included with all distributions of the Covered
+ Software under this License. Except to the extent prohibited by statute
+ or regulation, such description must be sufficiently detailed for a
+ recipient of ordinary skill to be able to understand it.
+ .
+ 5. Termination
+ --------------
+ .
+ 5.1. The rights granted under this License will terminate automatically
+ if You fail to comply with any of its terms. However, if You become
+ compliant, then the rights granted under this License from a particular
+ Contributor are reinstated (a) provisionally, unless and until such
+ Contributor explicitly and finally terminates Your grants, and (b) on an
+ ongoing basis, if such Contributor fails to notify You of the
+ non-compliance by some reasonable means prior to 60 days after You have
+ come back into compliance. Moreover, Your grants from a particular
+ Contributor are reinstated on an ongoing basis if such Contributor
+ notifies You of the non-compliance by some reasonable means, this is the
+ first time You have received notice of non-compliance with this License
+ from such Contributor, and You become compliant prior to 30 days after
+ Your receipt of the notice.
+ .
+ 5.2. If You initiate litigation against any entity by asserting a patent
+ infringement claim (excluding declaratory judgment actions,
+ counter-claims, and cross-claims) alleging that a Contributor Version
+ directly or indirectly infringes any patent, then the rights granted to
+ You by any and all Contributors for the Covered Software under Section
+ 2.1 of this License shall terminate.
+ .
+ 5.3. In the event of termination under Sections 5.1 or 5.2 above, all
+ end user license agreements (excluding distributors and resellers) which
+ have been validly granted by You or Your distributors under this License
+ prior to termination shall survive termination.
+ .
+ ************************************************************************
+ *                                                                      *
+ *  6. Disclaimer of Warranty                                           *
+ *  -------------------------                                           *
+ *                                                                      *
+ *  Covered Software is provided under this License on an "as is"       *
+ *  basis, without warranty of any kind, either expressed, implied, or  *
+ *  statutory, including, without limitation, warranties that the       *
+ *  Covered Software is free of defects, merchantable, fit for a        *
+ *  particular purpose or non-infringing. The entire risk as to the     *
+ *  quality and performance of the Covered Software is with You.        *
+ *  Should any Covered Software prove defective in any respect, You     *
+ *  (not any Contributor) assume the cost of any necessary servicing,   *
+ *  repair, or correction. This disclaimer of warranty constitutes an   *
+ *  essential part of this License. No use of any Covered Software is   *
+ *  authorized under this License except under this disclaimer.         *
+ *                                                                      *
+ ************************************************************************
+ .
+ ************************************************************************
+ *                                                                      *
+ *  7. Limitation of Liability                                          *
+ *  --------------------------                                          *
+ *                                                                      *
+ *  Under no circumstances and under no legal theory, whether tort      *
+ *  (including negligence), contract, or otherwise, shall any           *
+ *  Contributor, or anyone who distributes Covered Software as          *
+ *  permitted above, be liable to You for any direct, indirect,         *
+ *  special, incidental, or consequential damages of any character      *
+ *  including, without limitation, damages for lost profits, loss of    *
+ *  goodwill, work stoppage, computer failure or malfunction, or any    *
+ *  and all other commercial damages or losses, even if such party      *
+ *  shall have been informed of the possibility of such damages. This   *
+ *  limitation of liability shall not apply to liability for death or   *
+ *  personal injury resulting from such party's negligence to the       *
+ *  extent applicable law prohibits such limitation. Some               *
+ *  jurisdictions do not allow the exclusion or limitation of           *
+ *  incidental or consequential damages, so this exclusion and          *
+ *  limitation may not apply to You.                                    *
+ *                                                                      *
+ ************************************************************************
+ .
+ 8. Litigation
+ -------------
+ .
+ Any litigation relating to this License may be brought only in the
+ courts of a jurisdiction where the defendant maintains its principal
+ place of business and such litigation shall be governed by laws of that
+ jurisdiction, without reference to its conflict-of-law provisions.
+ Nothing in this Section shall prevent a party's ability to bring
+ cross-claims or counter-claims.
+ .
+ 9. Miscellaneous
+ ----------------
+ .
+ This License represents the complete agreement concerning the subject
+ matter hereof. If any provision of this License is held to be
+ unenforceable, such provision shall be reformed only to the extent
+ necessary to make it enforceable. Any law or regulation which provides
+ that the language of a contract shall be construed against the drafter
+ shall not be used to construe this License against a Contributor.
+ .
+ 10. Versions of the License
+ ---------------------------
+ .
+ 10.1. New Versions
+ .
+ Mozilla Foundation is the license steward. Except as provided in Section
+ 10.3, no one other than the license steward has the right to modify or
+ publish new versions of this License. Each version will be given a
+ distinguishing version number.
+ .
+ 10.2. Effect of New Versions
+ .
+ You may distribute the Covered Software under the terms of the version
+ of the License under which You originally received the Covered Software,
+ or under the terms of any subsequent version published by the license
+ steward.
+ .
+ 10.3. Modified Versions
+ .
+ If you create software not governed by this License, and you want to
+ create a new license for such software, you may create and use a
+ modified version of this License if you rename the license and remove
+ any references to the name of the license steward (except to note that
+ such modified license differs from this License).
+ .
+ 10.4. Distributing Source Code Form that is Incompatible With Secondary
+ Licenses
+ .
+ If You choose to distribute Source Code Form that is Incompatible With
+ Secondary Licenses under the terms of this version of the License, the
+ notice described in Exhibit B of this License must be attached.
+ .
+ Exhibit A - Source Code Form License Notice
+ -------------------------------------------
+ .
+   This Source Code Form is subject to the terms of the Mozilla Public
+   License, v. 2.0. If a copy of the MPL was not distributed with this
+   file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ .
+ If it is not possible or desirable to put the notice in a particular
+ file, then You may include the notice in a location (such as a LICENSE
+ file in a relevant directory) where a recipient would be likely to look
+ for such a notice.
+ .
+ You may add additional accurate notices of copyright ownership.
+ .
+ Exhibit B - "Incompatible With Secondary Licenses" Notice
+ ---------------------------------------------------------
+ .
+   This Source Code Form is "Incompatible With Secondary Licenses", as
+ defined by the Mozilla Public License, v. 2.0.
diff -pruN 20130227+dfsg1-14/rhino/debian/librhino-java-doc.doc-base 20130227+rhino-1/rhino/debian/librhino-java-doc.doc-base
--- 20130227+dfsg1-14/rhino/debian/librhino-java-doc.doc-base	1970-01-01 00:00:00.000000000 +0000
+++ 20130227+rhino-1/rhino/debian/librhino-java-doc.doc-base	2023-05-25 14:27:27.000000000 +0000
@@ -0,0 +1,10 @@
+Document: rhino-doc1
+Title: API JavaDoc for Rhino
+Author: The Mozilla Rhino Developers
+Abstract: This is the API JavaDoc of Rhino, a JavaScript 
+ engine written in Java.
+Section: Programming
+
+Format: HTML
+Index: /usr/share/doc/rhino/api/index.html
+Files: /usr/share/doc/rhino/api/*.html
diff -pruN 20130227+dfsg1-14/rhino/debian/librhino-java-doc.examples 20130227+rhino-1/rhino/debian/librhino-java-doc.examples
--- 20130227+dfsg1-14/rhino/debian/librhino-java-doc.examples	1970-01-01 00:00:00.000000000 +0000
+++ 20130227+rhino-1/rhino/debian/librhino-java-doc.examples	2023-05-25 14:27:27.000000000 +0000
@@ -0,0 +1 @@
+examples/*
diff -pruN 20130227+dfsg1-14/rhino/debian/librhino-java.links 20130227+rhino-1/rhino/debian/librhino-java.links
--- 20130227+dfsg1-14/rhino/debian/librhino-java.links	1970-01-01 00:00:00.000000000 +0000
+++ 20130227+rhino-1/rhino/debian/librhino-java.links	2023-05-25 14:27:27.000000000 +0000
@@ -0,0 +1 @@
+usr/share/java/js.jar usr/share/java/rhino.jar
diff -pruN 20130227+dfsg1-14/rhino/debian/librhino-java.manifest 20130227+rhino-1/rhino/debian/librhino-java.manifest
--- 20130227+dfsg1-14/rhino/debian/librhino-java.manifest	1970-01-01 00:00:00.000000000 +0000
+++ 20130227+rhino-1/rhino/debian/librhino-java.manifest	2023-05-25 14:27:27.000000000 +0000
@@ -0,0 +1,7 @@
+usr/share/java/js.jar:
+ Bundle-ManifestVersion: 2
+ Bundle-Name: Rhino Javascript interpreter
+ Bundle-Vendor: Mozilla Foundation
+ Bundle-Version: 1.7
+ Bundle-SymbolicName: org.mozilla.javascript
+ Export-Package: org.mozilla.javascript;version="1.7",org.mozilla.javascript.annotations;version="1.7",org.mozilla.javascript.ast;version="1.7",org.mozilla.javascript;version="1.7",org.mozilla.javascript.commonjs.module;version="1.7",org.mozilla.javascript.commonjs.module.provider;version="1.7",org.mozilla.javascript.debug;version="1.7",org.mozilla.javascript.jdk13;version="1.7",org.mozilla.javascript.json;version="1.7",org.mozilla.javascript.optimizer;version="1.7",org.mozilla.javascript.regexp;version="1.7",org.mozilla.javascript.serialize;version="1.7",org.mozilla.javascript.tools;version="1.7",org.mozilla.javascript.tools.debugger;version="1.7",org.mozilla.javascript.tools.debugger.downloaded;version="1.7",org.mozilla.javascript.tools.debugger.treetable;version="1.7",org.mozilla.javascript.tools.idswitch;version="1.7",org.mozilla.javascript.tools.jsc;version="1.7",org.mozilla.javascript.tools.shell;version="1.7",org.mozilla.javascript.xml;version="1.7",org.mozilla.javascript.xmlimpl;version="1.7",org.mozilla.classfile;version="1.7"
diff -pruN 20130227+dfsg1-14/rhino/debian/patches/03_public_getSourcePositionFromStack.patch 20130227+rhino-1/rhino/debian/patches/03_public_getSourcePositionFromStack.patch
--- 20130227+dfsg1-14/rhino/debian/patches/03_public_getSourcePositionFromStack.patch	1970-01-01 00:00:00.000000000 +0000
+++ 20130227+rhino-1/rhino/debian/patches/03_public_getSourcePositionFromStack.patch	2023-05-25 14:27:27.000000000 +0000
@@ -0,0 +1,18 @@
+From: Giovanni Mascellani <gio@debian.org>
+Subject: Make getSourcePositionFromStack() pulic
+Forwarded: no
+Last-Update: 2011-12-08
+
+This is needed by package geogebra.
+
+--- a/src/org/mozilla/javascript/Context.java
++++ b/src/org/mozilla/javascript/Context.java
+@@ -2592,7 +2592,7 @@
+         return (Evaluator)Kit.newInstanceOrNull(interpreterClass);
+     }
+ 
+-    static String getSourcePositionFromStack(int[] linep)
++    public static String getSourcePositionFromStack(int[] linep)
+     {
+         Context cx = getCurrentContext();
+         if (cx == null)
diff -pruN 20130227+dfsg1-14/rhino/debian/patches/05_modify-usage.patch 20130227+rhino-1/rhino/debian/patches/05_modify-usage.patch
--- 20130227+dfsg1-14/rhino/debian/patches/05_modify-usage.patch	1970-01-01 00:00:00.000000000 +0000
+++ 20130227+rhino-1/rhino/debian/patches/05_modify-usage.patch	2023-05-25 14:27:27.000000000 +0000
@@ -0,0 +1,23 @@
+Description: Simplify the usage syntax displayed with the --help option
+Author: Emmanuel Bourg <ebourg@apache.org>
+Forwarded: not-needed
+--- a/toolsrc/org/mozilla/javascript/tools/resources/Messages.properties
++++ b/toolsrc/org/mozilla/javascript/tools/resources/Messages.properties
+@@ -28,7 +28,7 @@
+     Invalid option "{0}"
+ 
+ msg.shell.usage =\
+-    Usage: java {0} [options...] [files]\n\
++    Usage: rhino [options...] [files]\n\
+     Valid options are:\n\
+     \    -?, -help          Displays help messages.\n\
+     \    -w                 Enable warnings.\n\
+@@ -110,7 +110,7 @@
+     For more information, try java {0} -h
+ 
+ msg.jsc.usage =\
+-Usage: java {0} [OPTION]... SOURCE...\n\
++Usage: rhino-jsc [OPTION]... SOURCE...\n\
+ Valid options are: \n\
+ \  -version VERSION   Use the specified language version.\n\
+ \                       VERSION should be one of 100|110|120|130|140|150|160|170.\n\
diff -pruN 20130227+dfsg1-14/rhino/debian/patches/06_preserve-backward-compatibility.patch 20130227+rhino-1/rhino/debian/patches/06_preserve-backward-compatibility.patch
--- 20130227+dfsg1-14/rhino/debian/patches/06_preserve-backward-compatibility.patch	1970-01-01 00:00:00.000000000 +0000
+++ 20130227+rhino-1/rhino/debian/patches/06_preserve-backward-compatibility.patch	2023-05-25 14:27:27.000000000 +0000
@@ -0,0 +1,172 @@
+Description: Reintroduces removed classes and methods to preserve the backward compatibility.
+ * Commit 9144b81 renamed isGetter/Setter methods, this breaks closure-compiler
+ * Commit 71468c9 removed deprecated exceptions still used by htmlunit/2.8-2
+Author: Emmanuel Bourg <ebourg@apache.org>
+Forwarded: not-needed
+--- a/src/org/mozilla/javascript/ast/ObjectProperty.java
++++ b/src/org/mozilla/javascript/ast/ObjectProperty.java
+@@ -69,6 +69,10 @@
+         type = Token.GET;
+     }
+ 
++    public void setIsGetter() {
++        setIsGetterMethod();
++    }
++
+     /**
+      * Returns true if this is a getter function.
+      */
+@@ -76,6 +80,10 @@
+         return type == Token.GET;
+     }
+ 
++    public boolean isGetter() {
++        return isGetterMethod();
++    }
++
+     /**
+      * Marks this node as a "setter" property.
+      */
+@@ -83,6 +91,10 @@
+         type = Token.SET;
+     }
+ 
++    public void setIsSetter() {
++        setIsSetterMethod();
++    }
++
+     /**
+      * Returns true if this is a setter function.
+      */
+@@ -90,6 +102,10 @@
+         return type == Token.SET;
+     }
+ 
++    public boolean isSetter() {
++        return isSetterMethod();
++    }
++
+     public void setIsNormalMethod() {
+         type = Token.METHOD;
+     }
+--- a/src/org/mozilla/javascript/ast/FunctionNode.java
++++ b/src/org/mozilla/javascript/ast/FunctionNode.java
+@@ -330,14 +330,26 @@
+         return functionForm == Form.GETTER || functionForm == Form.SETTER || functionForm == Form.METHOD;
+     }
+ 
++    public boolean isGetterOrSetter() {
++        return functionForm == Form.GETTER || functionForm == Form.SETTER;
++    }
++
+     public boolean isGetterMethod() {
+         return functionForm == Form.GETTER;
+     }
+ 
++    public boolean isGetter() {
++        return isGetterMethod();
++    }
++
+     public boolean isSetterMethod() {
+         return functionForm == Form.SETTER;
+     }
+ 
++    public boolean isSetter() {
++        return isSetterMethod();
++    }
++
+     public boolean isNormalMethod() {
+         return functionForm == Form.METHOD;
+     }
+@@ -346,10 +358,18 @@
+         functionForm = Form.GETTER;
+     }
+ 
++    public void setFunctionIsGetter() {
++        setFunctionIsGetterMethod();
++    }
++
+     public void setFunctionIsSetterMethod() {
+         functionForm = Form.SETTER;
+     }
+ 
++    public void setFunctionIsSetter() {
++        setFunctionIsSetterMethod();
++    }
++
+     public void setFunctionIsNormalMethod() {
+         functionForm = Form.METHOD;
+     }
+--- /dev/null
++++ b/src/org/mozilla/javascript/ClassDefinitionException.java
+@@ -0,0 +1,22 @@
++
++/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
++ *
++ * This Source Code Form is subject to the terms of the Mozilla Public
++ * License, v. 2.0. If a copy of the MPL was not distributed with this
++ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
++// API class
++
++package org.mozilla.javascript;
++
++/**
++ * @deprecated The exception is no longer thrown by Rhino runtime as
++ * {@link EvaluatorException} is used instead.
++ */
++public class ClassDefinitionException extends RuntimeException
++{
++    static final long serialVersionUID = -5637830967241712746L;
++
++    public ClassDefinitionException(String detail) {
++        super(detail);
++    }
++}
+--- /dev/null
++++ b/src/org/mozilla/javascript/NotAFunctionException.java
+@@ -0,0 +1,20 @@
++
++/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
++ *
++ * This Source Code Form is subject to the terms of the Mozilla Public
++ * License, v. 2.0. If a copy of the MPL was not distributed with this
++ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
++// API class
++
++package org.mozilla.javascript;
++
++/**
++ * @deprecated The exception is no longer thrown by Rhino runtime as
++ * {@link EvaluatorException} is used instead.
++ */
++public class NotAFunctionException extends RuntimeException
++{
++    static final long serialVersionUID = 6461524852170711724L;
++
++    public NotAFunctionException() { }
++}
+--- /dev/null
++++ b/src/org/mozilla/javascript/PropertyException.java
+@@ -0,0 +1,22 @@
++/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
++ *
++ * This Source Code Form is subject to the terms of the Mozilla Public
++ * License, v. 2.0. If a copy of the MPL was not distributed with this
++ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
++
++// API class
++
++package org.mozilla.javascript;
++
++/**
++ * @deprecated This exception is no longer thrown by Rhino runtime.
++ */
++public class PropertyException extends RuntimeException
++{
++    static final long serialVersionUID = -8221564865490676219L;
++
++    public PropertyException(String detail) {
++        super(detail);
++    }
++
++}
diff -pruN 20130227+dfsg1-14/rhino/debian/patches/07_fix-context-implementation-version.patch 20130227+rhino-1/rhino/debian/patches/07_fix-context-implementation-version.patch
--- 20130227+dfsg1-14/rhino/debian/patches/07_fix-context-implementation-version.patch	1970-01-01 00:00:00.000000000 +0000
+++ 20130227+rhino-1/rhino/debian/patches/07_fix-context-implementation-version.patch	2023-05-25 14:27:27.000000000 +0000
@@ -0,0 +1,18 @@
+Description: Fixes the logic to extract the implementation version from the manifest
+ (only when the project is built with Ant, with Gradle the manifest is ok).
+Author: Emmanuel Bourg <ebourg@apache.org>
+Forwarded: https://github.com/mozilla/rhino/commit/f575445cbe5e245#commitcomment-20551124
+--- a/src/org/mozilla/javascript/Context.java
++++ b/src/org/mozilla/javascript/Context.java
+@@ -729,9 +729,9 @@
+                     is = metaUrl.openStream();
+                     Manifest mf = new Manifest(is);
+                     Attributes attrs = mf.getMainAttributes();
+-                    if ("Mozilla Rhino".equals(attrs.getValue("Implementation-Title"))) {
++                    if (attrs.getValue("Implementation-Title") != null && attrs.getValue("Implementation-Title").startsWith("Mozilla Rhino")) {
+                         implementationVersion =
+-                            "Rhino " + attrs.getValue("Implementation-Version") + " " + attrs.getValue("Built-Date").replaceAll("-", " ");
++                            "Rhino " + attrs.getValue("Implementation-Version");
+                         return implementationVersion;
+                     }
+                 } catch (IOException e) {
diff -pruN 20130227+dfsg1-14/rhino/debian/patches/08_fix-jar-version-number.patch 20130227+rhino-1/rhino/debian/patches/08_fix-jar-version-number.patch
--- 20130227+dfsg1-14/rhino/debian/patches/08_fix-jar-version-number.patch	1970-01-01 00:00:00.000000000 +0000
+++ 20130227+rhino-1/rhino/debian/patches/08_fix-jar-version-number.patch	2023-05-25 14:27:27.000000000 +0000
@@ -0,0 +1,14 @@
+Description: update POM to match upstream version
+Author: tony mancill <tmancill@debian.org>
+
+--- a/maven/maven-pom.xml
++++ b/maven/maven-pom.xml
+@@ -12,7 +12,7 @@
+   <groupId>org.mozilla</groupId>
+   <artifactId>rhino</artifactId>
+   <name>Mozilla Rhino</name>
+-  <version>1.7.7.1</version>
++  <version>1.7.7.2</version>
+ 
+   <packaging>jar</packaging>
+   <description>
diff -pruN 20130227+dfsg1-14/rhino/debian/patches/script-engine.patch 20130227+rhino-1/rhino/debian/patches/script-engine.patch
--- 20130227+dfsg1-14/rhino/debian/patches/script-engine.patch	1970-01-01 00:00:00.000000000 +0000
+++ 20130227+rhino-1/rhino/debian/patches/script-engine.patch	2023-05-25 14:27:27.000000000 +0000
@@ -0,0 +1,1303 @@
+From f195514ffee1b759ba088883732e77b026b3a694 Mon Sep 17 00:00:00 2001
+From: Gregory Brail <gregbrail@google.com>
+Date: Fri, 5 Jun 2020 14:38:28 -0700
+Subject: [PATCH] Implement standard Java ScriptEngine
+
+This is not based on the now-removed JDK code but instead does a
+few things in a more modern way. See the comments for supported
+parameters (you can set language and optimization level via
+properties) and built-in functions (only print is supported right now.)
+
+This is built into a separate JAR called "rhino-engine" because
+otherwise, including it in any Java 8 JDK would break scripts that
+are expecting to see Nashorn instead.
+---
+ .circleci/config.yml                          |   2 +-
+ build.gradle                                  |  86 ++++-
+ .../services/javax.script.ScriptEngineFactory |   1 +
+ .../javascript/engine/BindingsObject.java     |  60 +++
+ .../mozilla/javascript/engine/Builtins.java   |  59 +++
+ .../engine/RhinoCompiledScript.java           |  33 ++
+ .../engine/RhinoInvocationHandler.java        |  25 ++
+ .../javascript/engine/RhinoScriptEngine.java  | 363 ++++++++++++++++++
+ .../engine/RhinoScriptEngineFactory.java      | 140 +++++++
+ .../tests/scriptengine/BuiltinsTest.java      |  54 +++
+ .../tests/scriptengine/FactoryTest.java       |  56 +++
+ .../tests/scriptengine/InvocableTest.java     | 158 ++++++++
+ .../tests/scriptengine/ScriptEngineTest.java  | 276 +++++++++++++
+ 13 files changed, 1305 insertions(+), 8 deletions(-)
+ create mode 100644 src/META-INF/services/javax.script.ScriptEngineFactory
+ create mode 100644 src/org/mozilla/javascript/engine/BindingsObject.java
+ create mode 100644 src/org/mozilla/javascript/engine/Builtins.java
+ create mode 100644 src/org/mozilla/javascript/engine/RhinoCompiledScript.java
+ create mode 100644 src/org/mozilla/javascript/engine/RhinoInvocationHandler.java
+ create mode 100644 src/org/mozilla/javascript/engine/RhinoScriptEngine.java
+ create mode 100644 src/org/mozilla/javascript/engine/RhinoScriptEngineFactory.java
+ create mode 100644 testsrc/org/mozilla/javascript/tests/scriptengine/BuiltinsTest.java
+ create mode 100644 testsrc/org/mozilla/javascript/tests/scriptengine/FactoryTest.java
+ create mode 100644 testsrc/org/mozilla/javascript/tests/scriptengine/InvocableTest.java
+ create mode 100644 testsrc/org/mozilla/javascript/tests/scriptengine/ScriptEngineTest.java
+
+--- /dev/null
++++ b/src/META-INF/services/javax.script.ScriptEngineFactory
+@@ -0,0 +1 @@
++org.mozilla.javascript.engine.RhinoScriptEngineFactory
+--- /dev/null
++++ b/src/org/mozilla/javascript/engine/BindingsObject.java
+@@ -0,0 +1,60 @@
++/* This Source Code Form is subject to the terms of the Mozilla Public
++ * License, v. 2.0. If a copy of the MPL was not distributed with this
++ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
++
++package org.mozilla.javascript.engine;
++
++import org.mozilla.javascript.Context;
++import org.mozilla.javascript.Scriptable;
++import org.mozilla.javascript.ScriptableObject;
++import javax.script.Bindings;
++
++/**
++ * This class makes the Bindings object into a Scriptable. That way, we can query and modify
++ * the contents of the Bindings on demand.
++ */
++public class BindingsObject
++  extends ScriptableObject {
++  private final Bindings bindings;
++
++  BindingsObject(Bindings bindings) {
++    if (bindings == null) {
++      throw new IllegalArgumentException("Bindings must not be null");
++    }
++    this.bindings = bindings;
++  }
++
++  @Override
++  public String getClassName() {
++    return "BindingsObject";
++  }
++
++  @Override
++  public Object get(String name, Scriptable start) {
++    Object ret = bindings.get(name);
++    if (ret == null) {
++      return Scriptable.NOT_FOUND;
++    }
++    return Context.jsToJava(ret, Object.class);
++  }
++
++  @Override
++  public void put(String name, Scriptable start, Object value) {
++    bindings.put(name, Context.javaToJS(value, start));
++  }
++
++  @Override
++  public void delete(String name) {
++    bindings.remove(name);
++  }
++
++  @Override
++  public boolean has(String name, Scriptable start) {
++    return bindings.containsKey(name);
++  }
++
++  @Override
++  public Object[] getIds() {
++    return bindings.keySet().toArray();
++  }
++}
+--- /dev/null
++++ b/src/org/mozilla/javascript/engine/Builtins.java
+@@ -0,0 +1,59 @@
++/* This Source Code Form is subject to the terms of the Mozilla Public
++ * License, v. 2.0. If a copy of the MPL was not distributed with this
++ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
++
++package org.mozilla.javascript.engine;
++
++import java.io.IOException;
++import java.io.OutputStreamWriter;
++import java.io.Writer;
++import javax.script.ScriptContext;
++import org.mozilla.javascript.Context;
++import org.mozilla.javascript.Function;
++import org.mozilla.javascript.ScriptRuntime;
++import org.mozilla.javascript.Scriptable;
++import org.mozilla.javascript.ScriptableObject;
++
++/**
++ * <p>
++ * This class defines the following built-in functions for the RhinoScriptEngine.
++ * </p>
++ * <ul>
++ * <li>print(arg, arg, ...): Write each argument, concatenated to the ScriptEngine's
++ * "standard output" as a string.</li>
++ * </ul>
++ */
++public class Builtins {
++
++  static final Object BUILTIN_KEY = new Object();
++
++  private Writer stdout;
++
++  void register(Context cx, ScriptableObject scope, ScriptContext sc) {
++    if (sc.getWriter() == null) {
++      stdout = new OutputStreamWriter(System.out);
++    } else {
++      stdout = sc.getWriter();
++    }
++
++    scope.defineFunctionProperties(new String[]{"print"},
++        Builtins.class,
++        ScriptableObject.PERMANENT | ScriptableObject.DONTENUM);
++  }
++
++  public static void print(Context cx, Scriptable thisObj, Object[] args, Function f)
++      throws IOException {
++    Builtins self = getSelf(thisObj);
++    for (Object arg : args) {
++      self.stdout.write(ScriptRuntime.toString(arg));
++    }
++    self.stdout.write('\n');
++  }
++
++  private static Builtins getSelf(Scriptable scope) {
++    // Since this class is invoked as a set of anonymous functions, "this"
++    // in JavaScript does not point to "this" in Java. We set a key on the
++    // top-level scope to address this.
++    return (Builtins) ScriptableObject.getTopScopeValue(scope, BUILTIN_KEY);
++  }
++}
+--- /dev/null
++++ b/src/org/mozilla/javascript/engine/RhinoCompiledScript.java
+@@ -0,0 +1,33 @@
++/* This Source Code Form is subject to the terms of the Mozilla Public
++ * License, v. 2.0. If a copy of the MPL was not distributed with this
++ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
++
++package org.mozilla.javascript.engine;
++
++import javax.script.CompiledScript;
++import javax.script.ScriptContext;
++import javax.script.ScriptEngine;
++import javax.script.ScriptException;
++import org.mozilla.javascript.Script;
++
++public class RhinoCompiledScript
++  extends CompiledScript {
++
++  private final RhinoScriptEngine engine;
++  private final Script script;
++
++  RhinoCompiledScript(RhinoScriptEngine engine, Script script) {
++    this.engine = engine;
++    this.script = script;
++  }
++
++  @Override
++  public Object eval(ScriptContext context) throws ScriptException {
++    return engine.eval(script, context);
++  }
++
++  @Override
++  public ScriptEngine getEngine() {
++    return engine;
++  }
++}
+--- /dev/null
++++ b/src/org/mozilla/javascript/engine/RhinoInvocationHandler.java
+@@ -0,0 +1,25 @@
++/* This Source Code Form is subject to the terms of the Mozilla Public
++ * License, v. 2.0. If a copy of the MPL was not distributed with this
++ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
++
++package org.mozilla.javascript.engine;
++
++import java.lang.reflect.InvocationHandler;
++import java.lang.reflect.Method;
++
++public class RhinoInvocationHandler
++    implements InvocationHandler {
++
++  private final Object thiz;
++  private final RhinoScriptEngine engine;
++
++  RhinoInvocationHandler(RhinoScriptEngine engine, Object thiz) {
++    this.engine = engine;
++    this.thiz = thiz;
++  }
++
++  @Override
++  public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
++    return engine.invokeMethodRaw(thiz, method.getName(), method.getReturnType(), args);
++  }
++}
+--- /dev/null
++++ b/src/org/mozilla/javascript/engine/RhinoScriptEngine.java
+@@ -0,0 +1,355 @@
++/* This Source Code Form is subject to the terms of the Mozilla Public
++ * License, v. 2.0. If a copy of the MPL was not distributed with this
++ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
++
++package org.mozilla.javascript.engine;
++
++import java.io.IOException;
++import java.io.Reader;
++import java.lang.reflect.Method;
++import java.lang.reflect.Proxy;
++import javax.script.AbstractScriptEngine;
++import javax.script.Bindings;
++import javax.script.Compilable;
++import javax.script.CompiledScript;
++import javax.script.Invocable;
++import javax.script.ScriptContext;
++import javax.script.ScriptEngine;
++import javax.script.ScriptEngineFactory;
++import javax.script.ScriptException;
++import javax.script.SimpleBindings;
++import org.mozilla.javascript.Callable;
++import org.mozilla.javascript.Context;
++import org.mozilla.javascript.ContextFactory;
++import org.mozilla.javascript.RhinoException;
++import org.mozilla.javascript.Script;
++import org.mozilla.javascript.Scriptable;
++import org.mozilla.javascript.ScriptableObject;
++
++/**
++ * <p>
++ * This is the implementation of the standard ScriptEngine interface for Rhino.
++ * </p>
++ * <p>
++ * An instance of the Rhino ScriptEngine is fully self-contained. Bindings at the GLOBAL_SCOPE may
++ * be set, but there is nothing special about them -- if both global and ENGINE_SCOPE bindings are
++ * set then the "engine" bindings override the global ones.
++ * </p>
++ * <p>
++ * The Rhino engine is not thread safe. Rhino does no synchronization of ScriptEngine instances and
++ * no synchronization of Bindings instances. It is up to the caller to ensure that the ScriptEngine
++ * and all its Bindings are used by a single thread at a time.
++ * </p>
++ * <p>
++ * The Rhino script engine includes some top-level built-in functions. See the Builtins class for
++ * more documentation.
++ * </p>
++ * <p>
++ * The engine supports a few configuration parameters that may be set at the "engine scope". Both
++ * are numbers that may be set to a String or Number object.
++ * </p>
++ * <ul>
++ * <li>javax.script.language_version: The version of the JavaScript language supported,
++ * which is an integer defined in the Context class. The default is the latest "ES6"
++ * version, defined as 200.</li>
++ * <li>org.mozilla.javascript.optimization_level: The level of optimization Rhino performs
++ * on the generated bytecode. Default is 9, which is the most. Set to -1 to use interpreted
++ * mode.</li>
++ * </ul>
++ */
++public class RhinoScriptEngine
++    extends AbstractScriptEngine
++    implements Compilable, Invocable {
++
++  /**
++   * Reserved key for the Rhino optimization level. Default is "9," for optimized and compiled code.
++   * Set this to "-1" to run Rhino in interpreted mode -- this is much much slower but the only
++   * option on platforms like Android that don't support class files.
++   */
++  public static final String OPTIMIZATION_LEVEL = "org.mozilla.javascript.optimization_level";
++
++  static final int DEFAULT_LANGUAGE_VERSION = Context.VERSION_ES6;
++  private static final int DEFAULT_OPT = 9;
++  private static final boolean DEFAULT_DEBUG = true;
++  private static final String DEFAULT_FILENAME = "eval";
++
++  private static final CtxFactory ctxFactory = new CtxFactory();
++
++  private final RhinoScriptEngineFactory factory;
++  private final Builtins builtins;
++  private ScriptableObject topLevelScope = null;
++
++  RhinoScriptEngine(RhinoScriptEngineFactory factory) {
++    this.factory = factory;
++    this.builtins = new Builtins();
++  }
++
++  private Scriptable initScope(Context cx, ScriptContext sc) throws ScriptException {
++    configureContext(cx);
++
++    if (topLevelScope == null) {
++      topLevelScope = cx.initStandardObjects();
++      // We need to stash this away so that the built in functions can find
++      // this engine's specific stuff that they need to work.
++      topLevelScope.associateValue(Builtins.BUILTIN_KEY, builtins);
++      builtins.register(cx, topLevelScope, sc);
++    }
++
++    Scriptable engineScope = new BindingsObject(
++        sc.getBindings(ScriptContext.ENGINE_SCOPE));
++    engineScope.setParentScope(null);
++    engineScope.setPrototype(topLevelScope);
++
++    if (sc.getBindings(ScriptContext.GLOBAL_SCOPE) != null) {
++      Scriptable globalScope = new BindingsObject(
++          sc.getBindings(ScriptContext.GLOBAL_SCOPE));
++      globalScope.setParentScope(null);
++      globalScope.setPrototype(topLevelScope);
++      engineScope.setPrototype(globalScope);
++    }
++
++    return engineScope;
++  }
++
++  @Override
++  public Object eval(String script, ScriptContext context) throws ScriptException {
++    Context cx = ctxFactory.enterContext();
++    try {
++      Scriptable scope = initScope(cx, context);
++      Object ret = cx.evaluateString(scope, script, getFilename(), 0, null);
++      return Context.jsToJava(ret, Object.class);
++    } catch (RhinoException re) {
++      throw new ScriptException(re.getMessage(), re.sourceName(), re.lineNumber(),
++          re.columnNumber());
++    } finally {
++      Context.exit();
++    }
++  }
++
++  @Override
++  public Object eval(Reader reader, ScriptContext context) throws ScriptException {
++    Context cx = ctxFactory.enterContext();
++    try {
++      Scriptable scope = initScope(cx, context);
++      Object ret = cx.evaluateReader(scope, reader, getFilename(), 0, null);
++      return Context.jsToJava(ret, Object.class);
++    } catch (RhinoException re) {
++      throw new ScriptException(re.getMessage(), re.sourceName(), re.lineNumber(),
++          re.columnNumber());
++    } catch (IOException ioe) {
++      throw new ScriptException(ioe);
++    } finally {
++      Context.exit();
++    }
++  }
++
++  @Override
++  public CompiledScript compile(String script) throws ScriptException {
++    Context cx = ctxFactory.enterContext();
++    try {
++      configureContext(cx);
++      Script s =
++          cx.compileString(script, getFilename(), 1, null);
++      return new RhinoCompiledScript(this, s);
++    } catch (RhinoException re) {
++      throw new ScriptException(re.getMessage(), re.sourceName(), re.lineNumber(),
++          re.columnNumber());
++    } finally {
++      Context.exit();
++    }
++  }
++
++  @Override
++  public CompiledScript compile(Reader script) throws ScriptException {
++    Context cx = ctxFactory.enterContext();
++    try {
++      configureContext(cx);
++      Script s =
++          cx.compileReader(script, getFilename(), 1, null);
++      return new RhinoCompiledScript(this, s);
++    } catch (RhinoException re) {
++      throw new ScriptException(re.getMessage(), re.sourceName(), re.lineNumber(),
++          re.columnNumber());
++    } catch (IOException ioe) {
++      throw new ScriptException(ioe);
++    } finally {
++      Context.exit();
++    }
++  }
++
++  Object eval(Script script, ScriptContext sc) throws ScriptException {
++    Context cx = ctxFactory.enterContext();
++    try {
++      Scriptable scope = initScope(cx, sc);
++      Object ret = script.exec(cx, scope);
++      return Context.jsToJava(ret, Object.class);
++    } catch (RhinoException re) {
++      throw new ScriptException(re.getMessage(), re.sourceName(), re.lineNumber(),
++          re.columnNumber());
++    } finally {
++      Context.exit();
++    }
++  }
++
++  @Override
++  public Object invokeFunction(String name, Object... args)
++      throws ScriptException, NoSuchMethodException {
++    return invokeMethod(null, name, args);
++  }
++
++  @Override
++  public Object invokeMethod(Object thiz, String name, Object... args)
++      throws ScriptException, NoSuchMethodException {
++    return invokeMethodRaw(thiz, name, Object.class, args);
++  }
++
++  Object invokeMethodRaw(Object thiz, String name, Class<?> returnType, Object... args)
++      throws ScriptException, NoSuchMethodException {
++    Context cx = ctxFactory.enterContext();
++    try {
++      Scriptable scope = initScope(cx, context);
++
++      Scriptable localThis;
++      if (thiz == null) {
++        localThis = scope;
++      } else {
++        localThis = Context.toObject(thiz, scope);
++      }
++
++      Object f = ScriptableObject.getProperty(localThis, name);
++      if (f == Scriptable.NOT_FOUND) {
++        throw new NoSuchMethodException(name);
++      }
++      if (!(f instanceof Callable)) {
++        throw new ScriptException("\"" + name + "\" is not a function");
++      }
++      Callable func = (Callable) f;
++
++      if (args != null) {
++        for (int i = 0; i < args.length; i++) {
++          args[i] = Context.javaToJS(args[i], scope);
++        }
++      }
++
++      Object ret = func.call(cx, scope, localThis, args);
++      if (returnType == Void.TYPE) {
++        return null;
++      }
++      return Context.jsToJava(ret, returnType);
++
++    } catch (RhinoException re) {
++      throw new ScriptException(re.getMessage(), re.sourceName(), re.lineNumber(),
++          re.columnNumber());
++    } finally {
++      Context.exit();
++    }
++  }
++
++  @Override
++  public <T> T getInterface(Class<T> clasz) {
++    if ((clasz == null) || !clasz.isInterface()) {
++      throw new IllegalArgumentException("Not an interface");
++    }
++    Context cx = ctxFactory.enterContext();
++    try {
++      Scriptable scope = initScope(cx, context);
++      if (methodsMissing(scope, clasz)) {
++        return null;
++      }
++    } catch (ScriptException se) {
++      return null;
++    } finally {
++      Context.exit();
++    }
++    return (T) Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),
++        new Class<?>[]{clasz}, new RhinoInvocationHandler(this, null));
++  }
++
++  @Override
++  public <T> T getInterface(Object thiz, Class<T> clasz) {
++    if ((clasz == null) || !clasz.isInterface()) {
++      throw new IllegalArgumentException("Not an interface");
++    }
++    Context cx = ctxFactory.enterContext();
++    try {
++      Scriptable scope = initScope(cx, context);
++      Scriptable thisObj = Context.toObject(thiz, scope);
++      if (methodsMissing(thisObj, clasz)) {
++        return null;
++      }
++    } catch (ScriptException se) {
++      return null;
++    } finally {
++      Context.exit();
++    }
++    return (T) Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),
++        new Class<?>[]{clasz}, new RhinoInvocationHandler(this, thiz));
++  }
++
++  @Override
++  public Bindings createBindings() {
++    return new SimpleBindings();
++  }
++
++  @Override
++  public ScriptEngineFactory getFactory() {
++    return factory;
++  }
++
++  private void configureContext(Context cx) throws ScriptException {
++    Object lv = get(ScriptEngine.LANGUAGE_VERSION);
++    if (lv != null) {
++      cx.setLanguageVersion(parseInteger(lv));
++    }
++    Object ol = get(OPTIMIZATION_LEVEL);
++    if (ol != null) {
++      cx.setOptimizationLevel(parseInteger(ol));
++    }
++  }
++
++  private int parseInteger(Object v) throws ScriptException {
++    if (v instanceof String) {
++      try {
++        return Integer.parseInt((String) v);
++      } catch (NumberFormatException nfe) {
++        throw new ScriptException("Invalid number " + v);
++      }
++    } else if (v instanceof Integer) {
++      return (Integer) v;
++    } else {
++      throw new ScriptException("Value must be a string or number");
++    }
++  }
++
++  private String getFilename() {
++    Object fn = get(ScriptEngine.FILENAME);
++    if (fn instanceof String) {
++      return (String) fn;
++    }
++    return DEFAULT_FILENAME;
++  }
++
++  private boolean methodsMissing(Scriptable scope, Class<?> clasz) {
++    for (Method m : clasz.getMethods()) {
++      if (m.getDeclaringClass() == Object.class) {
++        continue;
++      }
++      Object methodObj = ScriptableObject.getProperty(scope, m.getName());
++      if (!(methodObj instanceof Callable)) {
++        return true;
++      }
++    }
++    return false;
++  }
++
++  private static final class CtxFactory
++      extends ContextFactory {
++
++    @Override
++    protected void onContextCreated(Context cx) {
++      cx.setLanguageVersion(Context.VERSION_ES6);
++      cx.setOptimizationLevel(DEFAULT_OPT);
++      cx.setGeneratingDebug(DEFAULT_DEBUG);
++    }
++  }
++}
+--- /dev/null
++++ b/src/org/mozilla/javascript/engine/RhinoScriptEngineFactory.java
+@@ -0,0 +1,140 @@
++/* This Source Code Form is subject to the terms of the Mozilla Public
++ * License, v. 2.0. If a copy of the MPL was not distributed with this
++ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
++
++package org.mozilla.javascript.engine;
++
++import java.util.Arrays;
++import java.util.Collections;
++import java.util.List;
++import javax.script.ScriptEngine;
++import javax.script.ScriptEngineFactory;
++import org.mozilla.javascript.Context;
++
++/**
++ * <p>
++ * This is an implementation of the standard Java "ScriptEngine" for Rhino. If the Rhino engine
++ * (typically in the form of the "rhino-engine" JAR) is in the classpath, then this script
++ * engine will be activated.
++ * </p>
++ * <p>
++ * See the list of constants in this class for the list of language names, file extensions, and
++ * MIME types that this engine supports. This list is essentially the same as the list supported
++ * in the Nashorn script engine that was included in Java 8.
++ * </p>
++ * <p>
++ * Since this engine and Nashorn support the same language and file extensions, then unless
++ * you are sure you are running in an environment that has Nashorn, the best way to get this
++ * engine is to call ScriptEngine.getEngineByName("rhino") to ask for Rhino directly.
++ * </p>
++ */
++public class RhinoScriptEngineFactory
++  implements ScriptEngineFactory {
++
++  public static final String NAME = "rhino";
++  public static final String LANGUAGE = "javascript";
++  public static final List<String> NAMES =
++      Arrays.asList("rhino", "Rhino", "javascript", "JavaScript");
++  public static final List<String> EXTENSIONS =
++      Collections.singletonList("js");
++  public static final List<String> MIME_TYPES =
++      Arrays.asList("application/javascript", "application/ecmascript",
++          "text/javascript", "text/ecmascript");
++  public static final String LANGUAGE_VERSION =
++      String.valueOf(RhinoScriptEngine.DEFAULT_LANGUAGE_VERSION);
++
++  @Override
++  public String getEngineName() {
++    return NAME;
++  }
++
++  @Override
++  public String getEngineVersion() {
++    Context cx = Context.enter();
++    try {
++      String v = cx.getImplementationVersion();
++      return (v == null ? "unknown" : v);
++    } finally {
++      Context.exit();
++    }
++  }
++
++  @Override
++  public List<String> getExtensions() {
++    return EXTENSIONS;
++  }
++
++  @Override
++  public List<String> getMimeTypes() {
++    return MIME_TYPES;
++  }
++
++  @Override
++  public List<String> getNames() {
++    return NAMES;
++  }
++
++  @Override
++  public String getLanguageName() {
++    return LANGUAGE;
++  }
++
++  @Override
++  public String getLanguageVersion() {
++    return LANGUAGE_VERSION;
++  }
++
++  @Override
++  public Object getParameter(String key) {
++    switch (key) {
++      case ScriptEngine.ENGINE:
++        return getEngineName();
++      case ScriptEngine.ENGINE_VERSION:
++        return getEngineVersion();
++      case ScriptEngine.LANGUAGE:
++        return getLanguageName();
++      case ScriptEngine.LANGUAGE_VERSION:
++        return getLanguageVersion();
++      case ScriptEngine.NAME:
++        return NAME;
++      case "THREADING":
++        // Engines are explicitly not thread-safe
++        return null;
++      default:
++        return null;
++    }
++  }
++
++  @Override
++  public String getMethodCallSyntax(String obj, String m, String... args) {
++    StringBuilder sb = new StringBuilder();
++    sb.append(obj).append('.').append(m).append('(');
++    for (int i = 0; i < args.length; i++) {
++      if (i > 0) {
++        sb.append(',');
++      }
++      sb.append(args[i]);
++    }
++    sb.append(");");
++    return sb.toString();
++  }
++
++  @Override
++  public String getOutputStatement(String toDisplay) {
++    return "print('" + toDisplay + "');";
++  }
++
++  @Override
++  public String getProgram(String... statements) {
++    StringBuilder sb = new StringBuilder();
++    for (String stmt : statements) {
++      sb.append(stmt).append(";\n");
++    }
++    return sb.toString();
++  }
++
++  @Override
++  public ScriptEngine getScriptEngine() {
++    return new RhinoScriptEngine(this);
++  }
++}
+--- /dev/null
++++ b/testsrc/org/mozilla/javascript/tests/scriptengine/BuiltinsTest.java
+@@ -0,0 +1,54 @@
++package org.mozilla.javascript.tests.scriptengine;
++
++import java.io.StringWriter;
++import javax.script.ScriptContext;
++import javax.script.ScriptEngine;
++import javax.script.ScriptEngineManager;
++import javax.script.ScriptException;
++import javax.script.SimpleScriptContext;
++import org.junit.Before;
++import org.junit.BeforeClass;
++import org.junit.Test;
++import org.mozilla.javascript.engine.RhinoScriptEngineFactory;
++
++import static org.junit.Assert.*;
++
++public class BuiltinsTest {
++
++  private static ScriptEngineManager manager;
++
++  private ScriptEngine engine;
++
++  @BeforeClass
++  public static void init() {
++    manager = new ScriptEngineManager();
++    manager.registerEngineName("rhino", new RhinoScriptEngineFactory());
++  }
++
++  @Before
++  public void setup() {
++    engine = manager.getEngineByName("rhino");
++  }
++
++  @Test
++  public void testPrintStdout() throws ScriptException {
++    engine.eval("print('Hello, World!');");
++  }
++
++  @Test
++  public void testPrintWriter() throws ScriptException {
++    StringWriter sw = new StringWriter();
++    ScriptContext sc = new SimpleScriptContext();
++    sc.setWriter(sw);
++    engine.eval("print('one', 2, true);", sc);
++    assertEquals(sw.toString(), "one2true\n");
++  }
++
++  @Test
++  public void testPrintWriterGeneric() throws ScriptException {
++    StringWriter sw = new StringWriter();
++    engine.getContext().setWriter(sw);
++    engine.eval(engine.getFactory().getOutputStatement("Display This!"));
++    assertEquals(sw.toString(), "Display This!\n");
++  }
++}
+--- /dev/null
++++ b/testsrc/org/mozilla/javascript/tests/scriptengine/FactoryTest.java
+@@ -0,0 +1,56 @@
++package org.mozilla.javascript.tests.scriptengine;
++
++import javax.script.ScriptEngine;
++import javax.script.ScriptEngineFactory;
++import javax.script.ScriptEngineManager;
++import org.junit.Test;
++import org.mozilla.javascript.engine.RhinoScriptEngine;
++import org.mozilla.javascript.engine.RhinoScriptEngineFactory;
++
++import static org.junit.Assert.*;
++
++/*
++ * A series of tests that depend on us having our engine registered with the
++ * ScriptEngineManager by default.
++ */
++public class FactoryTest {
++
++  @Test
++  public void findRhinoFactory() {
++    ScriptEngineManager manager = new ScriptEngineManager();
++    for (ScriptEngineFactory factory : manager.getEngineFactories()) {
++      if (factory instanceof RhinoScriptEngineFactory) {
++        assertEquals("rhino", factory.getEngineName());
++        assertEquals("rhino", factory.getParameter(ScriptEngine.ENGINE));
++        assertEquals("rhino", factory.getParameter(ScriptEngine.NAME));
++        // This could be "unknown" if we're not running from a regular JAR
++        assertFalse(factory.getEngineVersion().isEmpty());
++        assertEquals("javascript", factory.getLanguageName());
++        assertEquals("javascript", factory.getParameter(ScriptEngine.LANGUAGE));
++        assertEquals("200", factory.getLanguageVersion());
++        assertEquals("200", factory.getParameter(ScriptEngine.LANGUAGE_VERSION));
++        assertNull(factory.getParameter("THREADING"));
++        assertTrue(factory.getExtensions().contains("js"));
++        assertTrue(factory.getMimeTypes().contains("application/javascript"));
++        assertTrue(factory.getMimeTypes().contains("application/ecmascript"));
++        assertTrue(factory.getMimeTypes().contains("text/javascript"));
++        assertTrue(factory.getMimeTypes().contains("text/ecmascript"));
++        assertTrue(factory.getNames().contains("rhino"));
++        assertTrue(factory.getNames().contains("Rhino"));
++        assertTrue(factory.getNames().contains("javascript"));
++        assertTrue(factory.getNames().contains("JavaScript"));
++        return;
++      }
++    }
++    fail("Expected to find Rhino script engine");
++  }
++
++  @Test
++  public void testRhinoFactory() {
++    // This will always uniquely return our engine.
++    // In Java 8, other ways to find it may return Nashorn.
++    ScriptEngine engine = new ScriptEngineManager().getEngineByName("rhino");
++    assertTrue(engine instanceof RhinoScriptEngine);
++
++  }
++}
+--- /dev/null
++++ b/testsrc/org/mozilla/javascript/tests/scriptengine/InvocableTest.java
+@@ -0,0 +1,158 @@
++package org.mozilla.javascript.tests.scriptengine;
++
++import java.io.FileNotFoundException;
++import java.io.FileReader;
++import javax.script.Invocable;
++import javax.script.ScriptEngine;
++import javax.script.ScriptEngineManager;
++import javax.script.ScriptException;
++import org.junit.Before;
++import org.junit.BeforeClass;
++import org.junit.Test;
++import org.mozilla.javascript.engine.RhinoScriptEngineFactory;
++
++import static org.junit.Assert.*;
++
++public class InvocableTest {
++
++  private static ScriptEngineManager manager;
++
++  private ScriptEngine engine;
++  private Invocable iEngine;
++
++  @BeforeClass
++  public static void init() {
++    manager = new ScriptEngineManager();
++    manager.registerEngineName("rhino", new RhinoScriptEngineFactory());
++  }
++
++  @Before
++  public void setup() {
++    engine = manager.getEngineByName("rhino");
++    iEngine = (Invocable) engine;
++  }
++
++  @Test
++  public void invokeFunctionTest() throws ScriptException, NoSuchMethodException {
++    engine.eval("function foo(a, b) { return a + b; }");
++    Object result = iEngine.invokeFunction("foo", 2, 2);
++    assertEquals(result, 4L);
++  }
++
++  @Test
++  public void invokeScriptFunctionTest() throws ScriptException, NoSuchMethodException {
++    Object scriptObj = engine.eval("let o = {};\n"
++        + "o.test = function(x) { return x + 2; }\n"
++        + "o;");
++    assertEquals(4L, iEngine.invokeMethod(scriptObj, "test", 2));
++  }
++
++  @Test
++  public void invokeGenericFunctionTest() throws ScriptException, NoSuchMethodException {
++    engine.eval("let o = {};\n"
++        + "o.test = function(x) { return x + 2; }\n");
++    Object result = engine.eval(engine.getFactory().getMethodCallSyntax("o", "test", "1"));
++    assertEquals(3L, result);
++  }
++
++  @Test
++  public void invokeGenericFunctionTest2() throws ScriptException, NoSuchMethodException {
++    engine.eval("let o = {};\n"
++        + "o.test = function(x, y) { return x + y; }\n");
++    Object result = engine.eval(engine.getFactory().getMethodCallSyntax("o", "test", "1", "7"));
++    assertEquals(8L, result);
++  }
++
++  @Test
++  public void invokeMethodTest()
++      throws ScriptException, NoSuchMethodException, FileNotFoundException {
++    engine.eval(new FileReader("testsrc/assert.js"));
++    engine.eval("function FooObj() { this.x = 0; }\n"
++        + "FooObj.prototype.set = function(a, b) { this.x = a + b; }");
++    engine.eval("let f = new FooObj();\n"
++        + "assertEquals(f.x, 0);\n"
++        + "f.set(2, 2);\n"
++        + "assertEquals(f.x, 4);");
++
++    Object fooObj = engine.eval("let y = new FooObj(); y");
++    assertNotNull(fooObj);
++    iEngine.invokeMethod(fooObj, "set", 3, 3);
++    Object result = engine.eval("y.x");
++    assertEquals(result, 6L);
++  }
++
++  @Test
++  public void interfaceFunctionTest()
++      throws ScriptException, FileNotFoundException {
++    engine.eval(new FileReader("testsrc/assert.js"));
++    engine.eval("var foo = 'initialized';\n"
++        + "function setFoo(v) { foo = v; }\n"
++        + "function getFoo() { return foo; }\n"
++        + "function addItUp(a, b) { return a + b; }");
++    I tester = iEngine.getInterface(I.class);
++    assertEquals(tester.getFoo(), "initialized");
++    tester.setFoo("tested");
++    assertEquals(tester.getFoo(), "tested");
++    assertEquals(tester.addItUp(100, 1), 101);
++  }
++
++  @Test
++  public void interfaceMethodTest()
++      throws ScriptException, FileNotFoundException {
++    engine.eval(new FileReader("testsrc/assert.js"));
++    Object foo = engine.eval("function Foo() { this.foo = 'initialized' }\n"
++        + "Foo.prototype.setFoo = function(v) { this.foo = v; };\n"
++        + "Foo.prototype.getFoo = function() { return this.foo; };\n"
++        + "Foo.prototype.addItUp = function(a, b) { return a + b; };\n"
++        + "new Foo();");
++    I tester = iEngine.getInterface(foo, I.class);
++    assertEquals(tester.getFoo(), "initialized");
++    tester.setFoo("tested");
++    assertEquals(tester.getFoo(), "tested");
++    assertEquals(tester.addItUp(100, 1), 101);
++  }
++
++  @Test
++  public void interfaceFunctionMissingTest() {
++    I tester = iEngine.getInterface(I.class);
++    assertNull(tester);
++  }
++
++  @Test
++  public void interfaceMethodMissingTest()
++      throws ScriptException {
++    // Functions defined, but not on the right object
++    Object foo = engine.eval("var foo = 'initialized';\n"
++        + "function setFoo(v) { foo = v; }\n"
++        + "function getFoo() { return foo; }\n"
++        + "function addItUp(a, b) { return a + b; }\n"
++        + "function Foo() {}\n"
++        + "new Foo();");
++    I tester = iEngine.getInterface(foo, I.class);
++    assertNull(tester);
++  }
++
++  @Test
++  public void invokeNotFoundTest() {
++    assertThrows(NoSuchMethodException.class, () -> {
++      iEngine.invokeFunction("foo", 2, 2);
++    });
++  }
++
++  @Test
++  public void invokeNotFunctionTest() {
++    assertThrows(ScriptException.class, () -> {
++      engine.eval("foo = 'bar';");
++      iEngine.invokeFunction("foo", 2, 2);
++    });
++  }
++
++  interface I {
++
++    void setFoo(String v);
++
++    String getFoo();
++
++    int addItUp(int a, int b);
++  }
++}
+--- /dev/null
++++ b/testsrc/org/mozilla/javascript/tests/scriptengine/ScriptEngineTest.java
+@@ -0,0 +1,276 @@
++package org.mozilla.javascript.tests.scriptengine;
++
++import java.io.File;
++import java.io.FileReader;
++import java.io.IOException;
++import java.io.StringReader;
++import javax.script.Bindings;
++import javax.script.Compilable;
++import javax.script.CompiledScript;
++import javax.script.ScriptContext;
++import javax.script.ScriptEngine;
++import javax.script.ScriptEngineFactory;
++import javax.script.ScriptEngineManager;
++import javax.script.ScriptException;
++import javax.script.SimpleBindings;
++import javax.script.SimpleScriptContext;
++import org.junit.Before;
++import org.junit.BeforeClass;
++import org.junit.Test;
++import org.mozilla.javascript.engine.RhinoScriptEngine;
++import org.mozilla.javascript.engine.RhinoScriptEngineFactory;
++
++import static org.junit.Assert.*;
++
++public class ScriptEngineTest {
++
++  private static ScriptEngineManager manager;
++  private ScriptEngine engine;
++  private Compilable cEngine;
++
++  @BeforeClass
++  public static void initManager() {
++    manager = new ScriptEngineManager();
++    manager.registerEngineName("rhino", new RhinoScriptEngineFactory());
++  }
++
++  @Before
++  public void init() {
++    engine = manager.getEngineByName("rhino");
++    cEngine = (Compilable) engine;
++  }
++
++  @Test
++  public void testHello() throws ScriptException {
++    Object result = engine.eval("'Hello, World!';");
++    assertEquals(result, "Hello, World!");
++  }
++
++  @Test
++  public void testHelloInterpreted() throws ScriptException {
++    engine.put(RhinoScriptEngine.OPTIMIZATION_LEVEL, -1);
++    Object result = engine.eval("'Hello, World!';");
++    assertEquals(result, "Hello, World!");
++  }
++
++
++  @Test
++  public void testHelloReader() throws ScriptException {
++    String src = "1 + 1;";
++    StringReader sr = new StringReader(src);
++    Object result = engine.eval(sr);
++    assertEquals(result, 2L);
++  }
++
++  @Test
++  public void testGenericStatements() throws ScriptException {
++    Object result = engine.eval(engine.getFactory().getProgram(
++        "let x = 1;",
++        "let y = 2",
++        "x + y"
++    ));
++    assertEquals(3L, result);
++  }
++
++  @Test
++  public void testThrows() {
++    assertThrows(ScriptException.class, () -> {
++      engine.eval("throw 'This is an error'");
++    });
++  }
++
++  @Test
++  public void testEngineBindings() throws IOException, ScriptException {
++    engine.put("string", "Hello");
++    engine.put("integer", 123);
++    engine.put("a", "a");
++    engine.put("b", "b");
++    engine.put("c", "c");
++
++    // Ensure that stuff we just stuck in bindings made it to a global
++    engine.eval(new FileReader("testsrc/assert.js"));
++    engine.eval("assertEquals(string, 'Hello');\n"
++        + "assertEquals(integer, 123);\n"
++        + "string = 'Goodbye';\n"
++        + "assertEquals(string, 'Goodbye');");
++    assertEquals(engine.get("string"), "Goodbye");
++
++    // Make sure we can delete
++    engine.getBindings(ScriptContext.ENGINE_SCOPE).remove("string");
++    // This will throw because string is undefined
++    assertThrows(ScriptException.class, () -> {
++      engine.eval("let failing = string + '123';");
++    });
++  }
++
++  @Test
++  public void testEngineScope() throws IOException, ScriptException {
++    engine.put("string", "Hello");
++    engine.put("integer", 123);
++    engine.eval(new FileReader("testsrc/assert.js"));
++    engine.eval("assertEquals(string, 'Hello');"
++        + "assertEquals(integer, 123);");
++
++    // Additional things added to the context but old stuff still there
++    engine.put("second", true);
++    engine.put("integer", 99);
++    engine.eval("assertEquals(string, 'Hello');"
++        + "assertEquals(integer, 99);"
++        + "assertTrue(second);");
++  }
++
++  @Test
++  public void testScopedBindings() throws IOException, ScriptException {
++    ScriptContext sc = new SimpleScriptContext();
++
++    // We treat engine and global scope the same -- if the user actually
++    // uses both, then engine scope overrides global scope.
++    Bindings eb = new SimpleBindings();
++    sc.setBindings(eb, ScriptContext.ENGINE_SCOPE);
++    eb.put("engine", Boolean.TRUE);
++    eb.put("level", 2);
++
++    Bindings gb = new SimpleBindings();
++    sc.setBindings(gb, ScriptContext.GLOBAL_SCOPE);
++    gb.put("global", Boolean.TRUE);
++    gb.put("level", 0);
++
++    engine.eval(new FileReader("testsrc/assert.js"), sc);
++    engine.eval("assertTrue(engine);"
++        + "assertTrue(global);"
++        + "assertEquals(level, 2);", sc);
++  }
++
++  @Test
++  public void testReservedBindings() throws ScriptException {
++    engine.put(ScriptEngine.ENGINE, "engine");
++    engine.put(ScriptEngine.ENGINE_VERSION, "123");
++    engine.put(ScriptEngine.LANGUAGE, "foo");
++    engine.put(ScriptEngine.NAME, "nothing");
++
++    // Can't actually test for those invalid property names -- but
++    // at least they didn't break the script.
++    assertEquals(engine.eval("'success'"), "success");
++  }
++
++  @Test
++  public void testCompiled() throws ScriptException, IOException {
++    CompiledScript asserts =
++        cEngine.compile(new FileReader("testsrc/assert.js"));
++    CompiledScript tests =
++        cEngine.compile("assertEquals(compiled, true);");
++
++    // Fails because asserts have not been loaded
++    assertThrows(ScriptException.class, tests::eval);
++
++    asserts.eval();
++    // Fails because value has not been set
++    assertThrows(ScriptException.class, tests::eval);
++
++    engine.put("compiled", Boolean.TRUE);
++    tests.eval();
++  }
++
++  @Test
++  public void testCompiled2() throws ScriptException, IOException {
++    CompiledScript asserts =
++        cEngine.compile(new FileReader("testsrc/assert.js"));
++    CompiledScript init =
++        cEngine.compile("value = 0;");
++    CompiledScript tests =
++        cEngine.compile("assertEquals(value, expectedValue);"
++            + "value += 1;");
++
++    asserts.eval();
++    init.eval();
++    for (int i = 0; i <= 10; i++) {
++      engine.put("expectedValue", i);
++      tests.eval();
++    }
++  }
++
++  @Test
++  public void testCompiledThrows() throws ScriptException {
++    engine.put(ScriptEngine.FILENAME, "throws1.js");
++    CompiledScript throw1 = cEngine.compile("throw 'one';");
++    engine.put(ScriptEngine.FILENAME, "throws2.js");
++    CompiledScript throw2 = cEngine.compile("throw 'two';");
++
++    try {
++      throw1.eval();
++      fail("Expected a throw");
++    } catch (ScriptException se) {
++      assertTrue(se.getMessage().startsWith("one"));
++      assertEquals("throws1.js", se.getFileName());
++      assertEquals(1, se.getLineNumber());
++    }
++
++    try {
++      throw2.eval();
++      fail("Expected a throw");
++    } catch (ScriptException se) {
++      assertTrue(se.getMessage().startsWith("two"));
++      assertEquals("throws2.js", se.getFileName());
++      assertEquals(1, se.getLineNumber());
++    }
++  }
++
++  @Test
++  public void testCantCompile() {
++    assertThrows(ScriptException.class, () -> {
++      cEngine.compile("This is not JavaScript at all!");
++    });
++  }
++
++  @Test
++  public void testLanguageVersion() throws ScriptException {
++    // Default language version is modernish
++    ScriptEngine newEngine = manager.getEngineByName("rhino");
++    assertEquals(newEngine.eval("Symbol() == Symbol()"), Boolean.FALSE);
++
++    // Older language versions
++    ScriptEngine oldEngine = manager.getEngineByName("rhino");
++    oldEngine.put(ScriptEngine.LANGUAGE_VERSION, 120);
++    assertThrows(ScriptException.class, () -> {
++      oldEngine.eval("Symbol() == Symbol()");
++    });
++
++    // The same with a string
++    ScriptEngine olderEngine = manager.getEngineByName("rhino");
++    olderEngine.put(ScriptEngine.LANGUAGE_VERSION, "100");
++    assertThrows(ScriptException.class, () -> {
++      olderEngine.eval("Symbol() == Symbol()");
++    });
++  }
++
++  @Test
++  public void testBadLanguageVersion() {
++    assertThrows(ScriptException.class, () -> {
++      engine.put(ScriptEngine.LANGUAGE_VERSION, "Not a number");
++      engine.eval("print('Hi!');");
++    });
++    assertThrows(ScriptException.class, () -> {
++      engine.put(ScriptEngine.LANGUAGE_VERSION, 3.14);
++      engine.eval("print('Hi!');");
++    });
++  }
++
++  @Test
++  public void testFilename() {
++    engine.put(ScriptEngine.FILENAME, "test.js");
++    try {
++      engine.eval("throw 'This is an exception';");
++    } catch (ScriptException se) {
++      assertEquals(se.getFileName(), "test.js");
++    }
++  }
++
++  @Test
++  public void testJavaObject() throws ScriptException {
++    File f = new File("testsrc/assert.js");
++    String absVal = f.getAbsolutePath();
++    engine.put("file", f);
++    Object result = engine.eval("file.getAbsolutePath();");
++    assertEquals(absVal, result);
++  }
++}
+--- a/build.xml
++++ b/build.xml
+@@ -87,7 +87,9 @@
+          basedir="${classes}"
+          manifest="src/manifest"
+          compress="${jar-compression}"
+-     />
++    >
++      <fileset dir="src" includes="META-INF/**"/>
++    </jar>
+   </target>
+ 
+   <target name="console" depends="jar">
diff -pruN 20130227+dfsg1-14/rhino/debian/patches/series 20130227+rhino-1/rhino/debian/patches/series
--- 20130227+dfsg1-14/rhino/debian/patches/series	1970-01-01 00:00:00.000000000 +0000
+++ 20130227+rhino-1/rhino/debian/patches/series	2023-05-25 14:27:27.000000000 +0000
@@ -0,0 +1,7 @@
+03_public_getSourcePositionFromStack.patch
+05_modify-usage.patch
+06_preserve-backward-compatibility.patch
+07_fix-context-implementation-version.patch
+08_fix-jar-version-number.patch
+script-engine.patch
+
diff -pruN 20130227+dfsg1-14/rhino/debian/rhino-debugger.1 20130227+rhino-1/rhino/debian/rhino-debugger.1
--- 20130227+dfsg1-14/rhino/debian/rhino-debugger.1	1970-01-01 00:00:00.000000000 +0000
+++ 20130227+rhino-1/rhino/debian/rhino-debugger.1	2023-05-25 14:27:27.000000000 +0000
@@ -0,0 +1,82 @@
+.\"                                      Hey, EMACS: -*- nroff -*-
+.\" First parameter, NAME, should be all caps
+.\" Second parameter, SECTION, should be 1-8, maybe w/ subsection
+.\" other parameters are allowed: see man(7), man(1)
+.TH RHINO-DEBUGGER 1
+.\" Please adjust this date whenever revising the manpage.
+.\"
+.\" Some roff macros, for reference:
+.\" .nh        disable hyphenation
+.\" .hy        enable hyphenation
+.\" .ad l      left justify
+.\" .ad b      justify to both left and right margins
+.\" .nf        disable filling
+.\" .fi        enable filling
+.\" .br        insert line break
+.\" .sp <n>    insert n+1 empty lines
+.\" for manpage-specific macros, see man(7)
+.SH NAME
+
+rhino-debugger \- invokes the rhino JavaScript debugger GUI
+
+.SH SYNOPSIS
+.B rhino-debugger
+.I [options]
+.I script_filename_or_url
+.I [script_arguments]
+
+.SH DESCRIPTION
+
+This manual page documents briefly the
+.B rhino-debugger
+command.
+This manual page was written for the Debian distribution because the original
+program does not have a manual page. It is written according to the html documentation.
+.PP
+\fBrhino-debugger\fP is a start script for the rhino JavaScript debugger.
+The Rhino JavaScript debugger is a GUI that allows debugging of interpreted
+JavaScript scripts run in Rhino. Note that this debugger will not work with
+JavaScript scripts run in the mozilla browser since Rhino is not the engine
+used in such environments.
+
+.SH OPTIONS
+
+.IP -w
+Enable warnings.
+.IP -version\ \fIversionNumber\fP
+Specifies the language version to compile with. The string versionNumber must be one of 100, 110, 120, 130, 140, 150, 160, 170, 180 or 200. See JavaScript Language Versions for more information on language$
+.IP -opt,\ -O\ \fIoptLevel\fP
+Optimizes at level optLevel, which must be an integer between -1 and 9. -1 means Interpretive mode is always used. 0 means no optimizations whereas 9 means all optimizations are performed.
+.IP -f\ \fIscript_filename_or_url\fP
+Reads script_filename_or_url content and execute it as a JavaScript script.
+.IP -e\ \fIscript_source\fP
+Executes script_source as a JavaScript script.
+.IP -modules\ \fIuri\fP
+Add a single path or URL element to the CommonJS module search path. (implies -require)
+.IP -require
+Enable CommonJS module support.
+.IP -sandbox
+Enable CommonJS sandbox mode. (implies -require)
+.IP -debug
+Generate debug code.
+.IP -strict
+Enable strict mode.
+.IP -fatal-warnings
+Treat warnings as errors.
+.IP -encoding\ \fIcharset\fP
+Use specified character encoding as default when reading scripts.
+
+.SH EXAMPLE
+
+Example debugging the NervousText.js applet written in JavaScript. The example is provided in the librhino-java-doc package.
+
+$ rhino-debugger NervousText.js
+
+.SH SEE ALSO
+
+The online documentation under https://developer.mozilla.org/en-US/docs/Mozilla/Projects/Rhino/Debugger
+
+.SH AUTHOR
+
+This manual page was written by Damien Raude-Morvan <drazzib@debian.org>,
+for the Debian project (but may be used by others).
diff -pruN 20130227+dfsg1-14/rhino/debian/rhino-jsc.1 20130227+rhino-1/rhino/debian/rhino-jsc.1
--- 20130227+dfsg1-14/rhino/debian/rhino-jsc.1	1970-01-01 00:00:00.000000000 +0000
+++ 20130227+rhino-1/rhino/debian/rhino-jsc.1	2023-05-25 14:27:27.000000000 +0000
@@ -0,0 +1,80 @@
+.\"                                      Hey, EMACS: -*- nroff -*-
+.\" First parameter, NAME, should be all caps
+.\" Second parameter, SECTION, should be 1-8, maybe w/ subsection
+.\" other parameters are allowed: see man(7), man(1)
+.TH RHINO-JSC 1
+.\" Please adjust this date whenever revising the manpage.
+.\"
+.\" Some roff macros, for reference:
+.\" .nh        disable hyphenation
+.\" .hy        enable hyphenation
+.\" .ad l      left justify
+.\" .ad b      justify to both left and right margins
+.\" .nf        disable filling
+.\" .fi        enable filling
+.\" .br        insert line break
+.\" .sp <n>    insert n+1 empty lines
+.\" for manpage-specific macros, see man(7)
+.SH NAME
+
+rhino-jsc \- invokes the rhino JavaScript compiler
+
+.SH SYNOPSIS
+
+.B rhino-jsc
+.I [options]
+.I file1.js
+.I [file2.js\&.\&.\&.]
+
+.SH DESCRIPTION
+
+This manual page documents briefly the
+.B rhino-jsc
+command.
+This manual page was written for the Debian distribution because the original
+program does not have a manual page. It is written according to the html documentation.
+.PP
+\fBrhino-jsc\fP is a start script for the rhino JavaScript compiler. The JavaScript compiler translates JavaScript source into Java class files. The resulting Java class files can then be loaded and executed at another time, providing a convenient method for transferring JavaScript, and for avoiding translation cost.
+Note that the top-level functions available to the shell (such as print) are not available to compiled scripts when they are run outside the shell.
+
+.SH OPTIONS
+
+.IP -version\ \fIversionNumber\fP
+Specifies the language version to compile with. The string versionNumber must be one of 100, 110, 120, 130, 140, 150, 160 or 170. See JavaScript Language Versions for more information on language versions.
+.IP -opt,\ -O\ \fIoptLevel\fP
+Optimizes at level optLevel, which must be an integer between 0 and 9.
+.IP -debug,\ -g
+Specifies that debug information should be generated. May not be combined with optimization at an optLevel greater than zero.
+.IP -nosource
+Does not save the source in the class file. Functions and scripts compiled this way cannot be decompiled. This option can be used to avoid distributing source or simply to save space in the resulting class file.
+.IP -o\ \fIoutputFile\fP
+Writes the class file to the given file (which should end in .class). The string outputFile must be a writable filename.
+.IP -package\ \fIpackageName\fP
+Specifies the package to generate the class into. The string packageName must be composed of valid identifier characters optionally separated by periods.
+.IP -d\ \fIoutputDirectory\fP
+Uses outputDirectory as destination directory for generated classes. If omitted, it defaults to parent directory of the source file.
+.IP -encoding\ \fIcharset\fP
+Sets the character encoding of the source files.
+.IP -extends\ \fIjava_class_name\fP
+Specifies that a java class extending the Java class java_class_name should be generated from the incoming JavaScript source file. Each global function in the source file is made a method of the generated class, overriding any methods in the base class by the same name.
+.IP -implements\ \fIjava_intf_name\fP
+Specifies that a java class implementing the Java interface java_intf_name should be generated from the incoming JavaScript source file. Each global function in the source file is made a method of the generated class, implementing any methods in the interface by the same name.
+.IP -main-method-class\ \fIclassName\fP
+Specifies the class name used for main method implementation. The class must have a method matching public static void main(Script sc, String[] args).
+.IP -observe-instruction-count
+Generates code that contains callbacks to accumulate counts of executed instructions. Code compiled with this flag can be monitored using Context.setInstructionObserverThreshold.
+
+.SH EXAMPLE
+
+Example compiling the NervousText.js applet written in JavaScript. The example is provided in the librhino-java-doc package.
+
+$ rhino-jsc \-extends java.applet.Applet \-implements java.lang.Runnable NervousText.js
+
+.SH SEE ALSO
+
+The online documentation under https://developer.mozilla.org/en-US/docs/Mozilla/Projects/Rhino/JavaScript_Compiler
+
+.SH AUTHOR
+
+This manual page was written by Wolfgang Baer <WBaer@gmx.de>,
+for the Debian project (but may be used by others).
diff -pruN 20130227+dfsg1-14/rhino/debian/rhino.1 20130227+rhino-1/rhino/debian/rhino.1
--- 20130227+dfsg1-14/rhino/debian/rhino.1	1970-01-01 00:00:00.000000000 +0000
+++ 20130227+rhino-1/rhino/debian/rhino.1	2023-05-25 14:27:27.000000000 +0000
@@ -0,0 +1,112 @@
+.\"                                      Hey, EMACS: -*- nroff -*-
+.\" First parameter, NAME, should be all caps
+.\" Second parameter, SECTION, should be 1-8, maybe w/ subsection
+.\" other parameters are allowed: see man(7), man(1)
+.TH RHINO 1
+.\" Please adjust this date whenever revising the manpage.
+.\"
+.\" Some roff macros, for reference:
+.\" .nh        disable hyphenation
+.\" .hy        enable hyphenation
+.\" .ad l      left justify
+.\" .ad b      justify to both left and right margins
+.\" .nf        disable filling
+.\" .fi        enable filling
+.\" .br        insert line break
+.\" .sp <n>    insert n+1 empty lines
+.\" for manpage-specific macros, see man(7)
+.SH NAME
+
+rhino \- invokes the JavaScript shell for running scripts in batch mode or interactive
+
+.SH SYNOPSIS
+
+.B rhino
+.I [options]
+.I script_filename_or_url
+.I [script_arguments]
+
+.SH DESCRIPTION
+
+This manual page documents briefly the
+.B rhino
+command.
+This manual page was written for the Debian distribution because the original
+program does not have a manual page. It is written according to the html documentation.
+.PP
+.\" TeX users may be more comfortable with the \fB<whatever>\fP and
+.\" \fI<whatever>\fP escape sequences to invode bold face and italics,
+.\" respectively.
+\fBrhino\fP is a start script for the rhino JavaScript shell which provides a simple way
+to run scripts in batch mode or an interactive environment for exploratory programming.
+
+.SH OPTIONS
+
+.IP -w
+Enable warnings.
+.IP -version\ \fIversionNumber\fP
+Specifies the language version to compile with. The string versionNumber must be one of 100, 110, 120, 130, 140, 150, 160, 170, 180 or 200. See JavaScript Language Versions for more information on language versions.
+.IP -opt,\ -O\ \fIoptLevel\fP
+Optimizes at level optLevel, which must be an integer between -1 and 9. -1 means Interpretive mode is always used. 0 means no optimizations whereas 9 means all optimizations are performed.
+.IP -f\ \fIscript_filename_or_url\fP
+Reads script_filename_or_url content and execute it as a JavaScript script.
+.IP -e\ \fIscript_source\fP
+Executes script_source as a JavaScript script.
+.IP -modules\ \fIuri\fP
+Add a single path or URL element to the CommonJS module search path. (implies -require)
+.IP -require
+Enable CommonJS module support.
+.IP -sandbox
+Enable CommonJS sandbox mode. (implies -require)
+.IP -debug
+Generate debug code.
+.IP -strict
+Enable strict mode.
+.IP -fatal-warnings
+Treat warnings as errors.
+.IP -encoding\ \fIcharset\fP
+Use specified character encoding as default when reading scripts.
+
+.SH PREDEFINED PROPERTIES
+
+Scripts executing in the shell have access to some additional properties of the top-level object.
+
+.IP arguments
+The arguments object is an array containing the strings of all the arguments given at the command line when the shell was invoked.
+.IP help()
+Executing the help function will print usage and help messages.
+.IP defineClass(\fIclassName\fP)
+Define an extension using the Java class named with the string argument className. Uses ScriptableObject.defineClass() to define the extension.
+.IP deserialize(\fIfilename\fP)
+Restore from the specified file an object previously written by a call to serialize.
+.IP load(\fI[filename,\&.\&.\&.]\fP)
+Load JavaScript source files named by string arguments. If multiple arguments are given, each file is read in and executed in turn.
+.IP loadClass(\fIclassName\fP)
+Load and execute the class named by the string argument className. The class must be a class that implements the Script interface, as will any script compiled by jsc.
+.IP print(\fI[expr\&.\&.\&.]\fP)
+Evaluate and print expressions. Evaluates each expression, converts the result to a string, and prints it.
+.IP readFile(\fIpath[,characterCoding]\fP)
+Read given file and convert its bytes to a string using the specified character coding or default character coding if explicit coding argument is not given.
+.IP readUrl(\fIurl[,characterCoding]\fP)
+Open an input connection to the given string url, read all its bytes and convert them to a string using the specified character coding or default character coding if explicit coding argument is not given.
+.IP runCommand(\fIcommandName,[arg,\&.\&.\&.][options]\fP)
+Execute the specified command with the given argument and options as a separate process and return the exit status of the process. For details, see JavaDoc for org.mozilla.javascript.tools.shell.Global#runCommand.
+.IP serialize(\fIobject,filename\fP)
+Serialize the given object to the specified file.
+.IP spawn(\fIfunctionOrScript\fP)
+Run the given function or script in a different thread.
+.IP sync(\fIfunction\fP)
+creates a synchronized function (in the sense of a Java synchronized method) from an existing function. The new function synchronizes on the this object of its invocation.
+.IP quit()
+Quit shell. The shell will also quit in interactive mode if an end-of-file character is typed at the prompt.
+.IP version(\fI[number]\fP)
+Get or set JavaScript version number. If no argument is supplied, the current version number is returned. If an argument is supplied, it is expected to be one of 100, 110, 120, 130, or 140 to indicate JavaScript version 1.0, 1.1, 1.2, 1.3, or 1.4 respectively.
+
+.SH SEE ALSO
+
+The online documentation under https://developer.mozilla.org/en-US/docs/Mozilla/Projects/Rhino/Shell
+
+.SH AUTHOR
+
+This manual page was written by Wolfgang Baer <WBaer@gmx.de>,
+for the Debian project (but may be used by others).
diff -pruN 20130227+dfsg1-14/rhino/debian/rhino.install 20130227+rhino-1/rhino/debian/rhino.install
--- 20130227+dfsg1-14/rhino/debian/rhino.install	1970-01-01 00:00:00.000000000 +0000
+++ 20130227+rhino-1/rhino/debian/rhino.install	2023-05-25 14:27:27.000000000 +0000
@@ -0,0 +1 @@
+debian/bin/*					usr/bin
diff -pruN 20130227+dfsg1-14/rhino/debian/rhino.manpages 20130227+rhino-1/rhino/debian/rhino.manpages
--- 20130227+dfsg1-14/rhino/debian/rhino.manpages	1970-01-01 00:00:00.000000000 +0000
+++ 20130227+rhino-1/rhino/debian/rhino.manpages	2023-05-25 14:27:27.000000000 +0000
@@ -0,0 +1,3 @@
+debian/rhino-debugger.1
+debian/rhino-jsc.1
+debian/rhino.1
diff -pruN 20130227+dfsg1-14/rhino/debian/rhino.postinst 20130227+rhino-1/rhino/debian/rhino.postinst
--- 20130227+dfsg1-14/rhino/debian/rhino.postinst	1970-01-01 00:00:00.000000000 +0000
+++ 20130227+rhino-1/rhino/debian/rhino.postinst	2023-05-25 14:27:27.000000000 +0000
@@ -0,0 +1,9 @@
+#!/bin/bash
+set -e
+
+if [ "$1" = "configure" -o "$1" = "abort-upgrade" ]; then
+  update-alternatives --install /usr/bin/js js /usr/bin/rhino 100 \
+                      --slave /usr/share/man/man1/js.1.gz js.1.gz /usr/share/man/man1/rhino.1.gz
+fi
+
+#DEBHELPER#
diff -pruN 20130227+dfsg1-14/rhino/debian/rhino.prerm 20130227+rhino-1/rhino/debian/rhino.prerm
--- 20130227+dfsg1-14/rhino/debian/rhino.prerm	1970-01-01 00:00:00.000000000 +0000
+++ 20130227+rhino-1/rhino/debian/rhino.prerm	2023-05-25 14:27:27.000000000 +0000
@@ -0,0 +1,8 @@
+#!/bin/sh
+set -e
+
+if [ "$1" = "remove" ]; then
+  update-alternatives --remove js /usr/bin/rhino
+fi
+
+#DEBHELPER#
diff -pruN 20130227+dfsg1-14/rhino/debian/rules 20130227+rhino-1/rhino/debian/rules
--- 20130227+dfsg1-14/rhino/debian/rules	1970-01-01 00:00:00.000000000 +0000
+++ 20130227+rhino-1/rhino/debian/rules	2023-05-25 14:27:27.000000000 +0000
@@ -0,0 +1,23 @@
+#!/usr/bin/make -f
+
+VERSION  = $(shell dpkg-parsechangelog --show-field Version | sed -rne 's/([^-]+).*/\1/p')
+BUILDDIR = build/rhino$(VERSION)
+
+%:
+	dh $@ --with javahelper --with maven-repo-helper
+
+override_dh_auto_build:
+	dh_auto_build -- jar javadoc -Dsource-level=7 -Dtarget-jvm=7
+
+override_dh_installchangelogs:
+	dh_installchangelogs -- RELEASE-NOTES.md
+
+override_mh_install:
+	mh_installpom -plibrhino-java maven/maven-pom.xml --no-parent --relocate=rhino:js
+	mh_installjar -plibrhino-java -l maven/maven-pom.xml --usj-name=js $(BUILDDIR)/js.jar
+
+override_dh_install:
+	dh_install
+
+	mv $(BUILDDIR)/javadoc $(BUILDDIR)/api
+	dh_install -plibrhino-java-doc $(BUILDDIR)/api /usr/share/doc/rhino/
diff -pruN 20130227+dfsg1-14/rhino/debian/source/format 20130227+rhino-1/rhino/debian/source/format
--- 20130227+dfsg1-14/rhino/debian/source/format	1970-01-01 00:00:00.000000000 +0000
+++ 20130227+rhino-1/rhino/debian/source/format	2023-05-25 14:27:27.000000000 +0000
@@ -0,0 +1 @@
+3.0 (quilt)
diff -pruN 20130227+dfsg1-14/rhino/debian/source/lintian-overrides 20130227+rhino-1/rhino/debian/source/lintian-overrides
--- 20130227+dfsg1-14/rhino/debian/source/lintian-overrides	1970-01-01 00:00:00.000000000 +0000
+++ 20130227+rhino-1/rhino/debian/source/lintian-overrides	2023-05-25 14:27:27.000000000 +0000
@@ -0,0 +1,4 @@
+# The tests contain non obfuscated JS files with really long lines
+rhino source: source-contains-prebuilt-javascript-object testsrc/*
+rhino source: source-is-missing testsrc/*
+rhino source: insane-line-length-in-source-file testsrc/*
diff -pruN 20130227+dfsg1-14/rhino/debian/watch 20130227+rhino-1/rhino/debian/watch
--- 20130227+dfsg1-14/rhino/debian/watch	1970-01-01 00:00:00.000000000 +0000
+++ 20130227+rhino-1/rhino/debian/watch	2023-05-25 14:27:27.000000000 +0000
@@ -0,0 +1,3 @@
+version=4
+opts=mode=git,compression=xz,uversionmangle=s/-RC/~RC/;s/pre/~pre/;s/_/./g;s/14R/1.4R/;s/140R/1.4.0R/;s/150R/1.5.0R/ \
+https://github.com/mozilla/rhino refs/tags/Rhino([\d_.R]+)_(?:RELEASE|Release)
diff -pruN 20130227+dfsg1-14/rhino/examples/Control.java 20130227+rhino-1/rhino/examples/Control.java
--- 20130227+dfsg1-14/rhino/examples/Control.java	1970-01-01 00:00:00.000000000 +0000
+++ 20130227+rhino-1/rhino/examples/Control.java	2023-05-25 14:24:50.000000000 +0000
@@ -0,0 +1,69 @@
+/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+import org.mozilla.javascript.*;
+
+/**
+ * Example of controlling the JavaScript execution engine.
+ *
+ * We evaluate a script and then manipulate the result.
+ *
+ */
+public class Control {
+
+    /**
+     * 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 main(String[] args)
+    {
+        Context cx = Context.enter();
+        try {
+            // Set version to JavaScript1.2 so that we get object-literal style
+            // printing instead of "[object Object]"
+            cx.setLanguageVersion(Context.VERSION_1_2);
+
+            // Initialize the standard objects (Object, Function, etc.)
+            // This must be done before scripts can be executed.
+            Scriptable scope = cx.initStandardObjects();
+
+            // Now we can evaluate a script. Let's create a new object
+            // using the object literal notation.
+            Object result = cx.evaluateString(scope, "obj = {a:1, b:['x','y']}",
+                                              "MySource", 1, null);
+
+            Scriptable obj = (Scriptable) scope.get("obj", scope);
+
+            // Should print "obj == result" (Since the result of an assignment
+            // expression is the value that was assigned)
+            System.out.println("obj " + (obj == result ? "==" : "!=") +
+                               " result");
+
+            // Should print "obj.a == 1"
+            System.out.println("obj.a == " + obj.get("a", obj));
+
+            Scriptable b = (Scriptable) obj.get("b", obj);
+
+            // Should print "obj.b[0] == x"
+            System.out.println("obj.b[0] == " + b.get(0, b));
+
+            // Should print "obj.b[1] == y"
+            System.out.println("obj.b[1] == " + b.get(1, b));
+
+            // Should print {a:1, b:["x", "y"]}
+            Function fn = (Function) ScriptableObject.getProperty(obj, "toString");
+            System.out.println(fn.call(cx, scope, obj, new Object[0]));
+        } finally {
+            Context.exit();
+        }
+    }
+
+}
+
diff -pruN 20130227+dfsg1-14/rhino/examples/Counter.java 20130227+rhino-1/rhino/examples/Counter.java
--- 20130227+dfsg1-14/rhino/examples/Counter.java	1970-01-01 00:00:00.000000000 +0000
+++ 20130227+rhino-1/rhino/examples/Counter.java	2023-05-25 14:24:50.000000000 +0000
@@ -0,0 +1,36 @@
+/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+import org.mozilla.javascript.*;
+import org.mozilla.javascript.annotations.JSFunction;
+import org.mozilla.javascript.annotations.JSConstructor;
+import org.mozilla.javascript.annotations.JSGetter;
+
+public class Counter extends ScriptableObject {
+    private static final long serialVersionUID = 438270592527335642L;
+
+    // The zero-argument constructor used by Rhino runtime to create instances
+    public Counter() { }
+
+    // @JSConstructor annotation defines the JavaScript constructor
+    @JSConstructor
+    public Counter(int a) { count = a; }
+
+    // The class name is defined by the getClassName method
+    @Override
+    public String getClassName() { return "Counter"; }
+
+    // The method getCount defines the count property.
+    @JSGetter
+    public int getCount() { return count++; }
+
+    // Methods can be defined the @JSFunction annotation.
+    // Here we define resetCount for JavaScript.
+    @JSFunction
+    public void resetCount() { count = 0; }
+
+    private int count;
+}
diff -pruN 20130227+dfsg1-14/rhino/examples/CounterTest.java 20130227+rhino-1/rhino/examples/CounterTest.java
--- 20130227+dfsg1-14/rhino/examples/CounterTest.java	1970-01-01 00:00:00.000000000 +0000
+++ 20130227+rhino-1/rhino/examples/CounterTest.java	2023-05-25 14:24:50.000000000 +0000
@@ -0,0 +1,50 @@
+/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+import org.mozilla.javascript.*;
+
+/**
+ * An example illustrating how to create a JavaScript object and retrieve
+ * properties and call methods.
+ * <p>
+ * Output should be:
+ * <pre>
+ * count = 0
+ * count = 1
+ * resetCount
+ * count = 0
+ * </pre>
+ */
+public class CounterTest {
+
+    public static void main(String[] args) throws Exception
+    {
+        Context cx = Context.enter();
+        try {
+            Scriptable scope = cx.initStandardObjects();
+            ScriptableObject.defineClass(scope, Counter.class);
+
+            Scriptable testCounter = cx.newObject(scope, "Counter");
+
+            Object count = ScriptableObject.getProperty(testCounter, "count");
+            System.out.println("count = " + count);
+
+            count = ScriptableObject.getProperty(testCounter, "count");
+            System.out.println("count = " + count);
+
+            ScriptableObject.callMethod(testCounter,
+                                        "resetCount",
+                                        new Object[0]);
+            System.out.println("resetCount");
+
+            count = ScriptableObject.getProperty(testCounter, "count");
+            System.out.println("count = " + count);
+        } finally {
+            Context.exit();
+        }
+    }
+
+}
diff -pruN 20130227+dfsg1-14/rhino/examples/DynamicScopes.java 20130227+rhino-1/rhino/examples/DynamicScopes.java
--- 20130227+dfsg1-14/rhino/examples/DynamicScopes.java	1970-01-01 00:00:00.000000000 +0000
+++ 20130227+rhino-1/rhino/examples/DynamicScopes.java	2023-05-25 14:24:50.000000000 +0000
@@ -0,0 +1,173 @@
+/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+import org.mozilla.javascript.*;
+
+/**
+ * Example of controlling the JavaScript with multiple scopes and threads.
+ */
+public class DynamicScopes {
+
+    static boolean useDynamicScope;
+
+    static class MyFactory extends ContextFactory
+    {
+        @Override
+        protected boolean hasFeature(Context cx, int featureIndex)
+        {
+            if (featureIndex == Context.FEATURE_DYNAMIC_SCOPE) {
+                return useDynamicScope;
+            }
+            return super.hasFeature(cx, featureIndex);
+        }
+    }
+
+    static {
+        ContextFactory.initGlobal(new MyFactory());
+    }
+
+
+    /**
+     * Main entry point.
+     *
+     * Set up the shared scope and then spawn new threads that execute
+     * relative to that shared scope. Try to run functions with and
+     * without dynamic scope to see the effect.
+     *
+     * The expected output is
+     * <pre>
+     * sharedScope
+     * nested:sharedScope
+     * sharedScope
+     * nested:sharedScope
+     * sharedScope
+     * nested:sharedScope
+     * thread0
+     * nested:thread0
+     * thread1
+     * nested:thread1
+     * thread2
+     * nested:thread2
+     * </pre>
+     * The final three lines may be permuted in any order depending on
+     * thread scheduling.
+     */
+    public static void main(String[] args)
+    {
+        Context cx = Context.enter();
+        try {
+            // Precompile source only once
+            String source = ""
+                            +"var x = 'sharedScope';\n"
+                            +"function f() { return x; }\n"
+                            // Dynamic scope works with nested function too
+                            +"function initClosure(prefix) {\n"
+                            +"    return function test() { return prefix+x; }\n"
+                            +"}\n"
+                            +"var closure = initClosure('nested:');\n"
+                            +"";
+            Script script = cx.compileString(source, "sharedScript", 1, null);
+
+            useDynamicScope = false;
+            runScripts(cx, script);
+            useDynamicScope = true;
+            runScripts(cx, script);
+        } finally {
+            Context.exit();
+        }
+    }
+
+    static void runScripts(Context cx, Script script)
+    {
+        // Initialize the standard objects (Object, Function, etc.)
+        // This must be done before scripts can be executed. The call
+        // returns a new scope that we will share.
+        ScriptableObject sharedScope = cx.initStandardObjects(null, true);
+
+        // Now we can execute the precompiled script against the scope
+        // to define x variable and f function in the shared scope.
+        script.exec(cx, sharedScope);
+
+        // Now we spawn some threads that execute a script that calls the
+        // function 'f'. The scope chain looks like this:
+        // <pre>
+        //            ------------------                ------------------
+        //           | per-thread scope | -prototype-> |   shared scope   |
+        //            ------------------                ------------------
+        //                    ^
+        //                    |
+        //               parentScope
+        //                    |
+        //            ------------------
+        //           | f's activation   |
+        //            ------------------
+        // </pre>
+        // Both the shared scope and the per-thread scope have variables 'x'
+        // defined in them. If 'f' is compiled with dynamic scope enabled,
+        // the 'x' from the per-thread scope will be used. Otherwise, the 'x'
+        // from the shared scope will be used. The 'x' defined in 'g' (which
+        // calls 'f') should not be seen by 'f'.
+        final int threadCount = 3;
+        Thread[] t = new Thread[threadCount];
+        for (int i=0; i < threadCount; i++) {
+            String source2 = ""
+                +"function g() { var x = 'local'; return f(); }\n"
+                +"java.lang.System.out.println(g());\n"
+                +"function g2() { var x = 'local'; return closure(); }\n"
+                +"java.lang.System.out.println(g2());\n"
+                +"";
+            t[i] = new Thread(new PerThread(sharedScope, source2,
+                                            "thread" + i));
+        }
+        for (int i=0; i < threadCount; i++)
+            t[i].start();
+        // Don't return in this thread until all the spawned threads have
+        // completed.
+        for (int i=0; i < threadCount; i++) {
+            try {
+                t[i].join();
+            } catch (InterruptedException e) {
+            }
+        }
+    }
+
+    static class PerThread implements Runnable {
+
+        PerThread(Scriptable sharedScope, String source, String x) {
+            this.sharedScope = sharedScope;
+            this.source = source;
+            this.x = x;
+        }
+
+        public void run() {
+            // We need a new Context for this thread.
+            Context cx = Context.enter();
+            try {
+                // We can share the scope.
+                Scriptable threadScope = cx.newObject(sharedScope);
+                threadScope.setPrototype(sharedScope);
+
+                // We want "threadScope" to be a new top-level
+                // scope, so set its parent scope to null. This
+                // means that any variables created by assignments
+                // will be properties of "threadScope".
+                threadScope.setParentScope(null);
+
+                // Create a JavaScript property of the thread scope named
+                // 'x' and save a value for it.
+                threadScope.put("x", threadScope, x);
+                cx.evaluateString(threadScope, source, "threadScript", 1, null);
+            } finally {
+                Context.exit();
+            }
+        }
+        private Scriptable sharedScope;
+        private String source;
+        private String x;
+    }
+
+}
+
diff -pruN 20130227+dfsg1-14/rhino/examples/E4X/e4x_example.js 20130227+rhino-1/rhino/examples/E4X/e4x_example.js
--- 20130227+dfsg1-14/rhino/examples/E4X/e4x_example.js	1970-01-01 00:00:00.000000000 +0000
+++ 20130227+rhino-1/rhino/examples/E4X/e4x_example.js	2023-05-25 14:24:50.000000000 +0000
@@ -0,0 +1,191 @@
+/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+print("----------------------------------------");
+
+// Use the XML constructor to parse an string into an XML object
+var John = "<employee><name>John</name><age>25</age></employee>";
+var Sue ="<employee><name>Sue</name><age>32</age></employee>";
+var tagName = "employees";
+var employees = new XML("<" + tagName +">" + John + Sue + "</" + tagName +">");
+print("The employees XML object constructed from a string is:\n" + employees);
+
+print("----------------------------------------");
+
+// Use an XML literal to create an XML object
+var order = <order>
+   <customer>
+      <firstname>John</firstname>
+      <lastname>Doe</lastname>
+   </customer>
+   <item>
+      <description>Big Screen Television</description>
+      <price>1299.99</price>
+      <quantity>1</quantity>
+   </item>
+</order>
+
+// Construct the full customer name
+var name = order.customer.firstname + " " + order.customer.lastname;
+
+// Calculate the total price
+var total = order.item.price * order.item.quantity;
+
+print("The order XML object constructed using a literal is:\n" + order);
+print("The total price of " + name + "'s order is " + total);
+
+print("----------------------------------------");
+
+// construct a new XML object using expando and super-expando properties
+var order = <order/>;
+order.customer.name = "Fred Jones";
+order.customer.address.street = "123 Long Lang";
+order.customer.address.city = "Underwood";
+order.customer.address.state = "CA";
+order.item[0] = "";
+order.item[0].description = "Small Rodents";
+order.item[0].quantity = 10;
+order.item[0].price = 6.95;
+
+print("The order custructed using expandos and super-expandos is:\n" + order);
+
+// append a new item to the order
+order.item += <item><description>Catapult</description><price>139.95</price></item>;
+
+print("----------------------------------------");
+
+print("The order after appending a new item is:\n" + order);
+
+print("----------------------------------------");
+
+// dynamically construct an XML element using embedded expressions
+var tagname = "name";
+var attributename = "id";
+var attributevalue = 5;
+var content = "Fred";
+
+var x = <{tagname} {attributename}={attributevalue}>{content}</{tagname}>;
+
+print("The dynamically computed element value is:\n" + x.toXMLString());
+
+print("----------------------------------------");
+
+// Create a SOAP message
+var message = <soap:Envelope
+      xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
+      soap:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
+   <soap:Body>
+      <m:GetLastTradePrice xmlns:m="http://mycompany.com/stocks">
+         <symbol>DIS</symbol>
+      </m:GetLastTradePrice>
+   </soap:Body>
+</soap:Envelope>
+
+// declare the SOAP and stocks namespaces
+var soap = new Namespace("http://schemas.xmlsoap.org/soap/envelope/");
+var stock = new Namespace ("http://mycompany.com/stocks");
+
+// extract the soap encoding style and body from the soap message
+var encodingStyle = message.@soap::encodingStyle;
+
+print("The encoding style of the soap message is specified by:\n" + encodingStyle);
+
+// change the stock symbol
+message.soap::Body.stock::GetLastTradePrice.symbol = "MYCO";
+
+var body = message.soap::Body;
+
+print("The body of the soap message is:\n" + body);
+
+print("----------------------------------------");
+
+// create an manipulate an XML object using the default xml namespace
+
+default xml namespace = "http://default.namespace.com";
+var x = <x/>;
+x.a = "one";
+x.b = "two";
+x.c = <c xmlns="http://some.other.namespace.com">three</c>;
+
+print("XML object constructed using the default xml namespace:\n" + x);
+
+default xml namespace="";
+
+print("----------------------------------------");
+
+var order = <order id = "123456" timestamp="Mon Mar 10 2003 16:03:25 GMT-0800 (PST)">
+   <customer>
+      <firstname>John</firstname>
+      <lastname>Doe</lastname>
+   </customer>
+   <item id="3456">
+      <description>Big Screen Television</description>
+      <price>1299.99</price>
+      <quantity>1</quantity>
+   </item>
+   <item id = "56789">
+      <description>DVD Player</description>
+      <price>399.99</price>
+      <quantity>1</quantity>
+   </item>
+</order>;
+
+
+// get the customer element from the orderprint("The customer is:\n" + order.customer);
+
+// get the id attribute from the order
+print("The order id is:" + order.@id);
+
+// get all the child elements from the order element
+print("The children of the order are:\n" + order.*); 
+
+// get the list of all item descriptions
+print("The order descriptions are:\n" + order.item.description); 
+
+
+// get second item by numeric index
+print("The second item is:\n" + order.item[1]);
+
+// get the list of all child elements in all item elements
+print("The children of the items are:\n" + order.item.*);
+
+// get the second child element from the order by index
+print("The second child of the order is:\n" + order.*[1]);
+
+// calculate the total price of the order
+var totalprice = 0;
+for each (i in order.item) {
+	totalprice += i.price * i.quantity;
+}
+print("The total price of the order is: " + totalprice);
+
+print("----------------------------------------");
+
+var e = <employees>
+   <employee id="1"><name>Joe</name><age>20</age></employee>
+   <employee id="2"><name>Sue</name><age>30</age></employee>
+</employees>;
+
+// get all the names in e
+print("All the employee names are:\n" + e..name);
+
+// employees with name Joe
+print("The employee named Joe is:\n" + e.employee.(name == "Joe"));
+
+// employees with id's 1 & 2
+print("Employees with ids 1 & 2:\n" + e.employee.(@id == 1 || @id == 2)); 
+
+// name of employee with id 1
+print("Name of the the employee with ID=1: " + e.employee.(@id == 1).name);
+
+print("----------------------------------------");
+
+
+
+
+
+
+
diff -pruN 20130227+dfsg1-14/rhino/examples/File.java 20130227+rhino-1/rhino/examples/File.java
--- 20130227+dfsg1-14/rhino/examples/File.java	1970-01-01 00:00:00.000000000 +0000
+++ 20130227+rhino-1/rhino/examples/File.java	2023-05-25 14:24:50.000000000 +0000
@@ -0,0 +1,336 @@
+/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+import org.mozilla.javascript.*;
+import org.mozilla.javascript.annotations.JSConstructor;
+import org.mozilla.javascript.annotations.JSFunction;
+import org.mozilla.javascript.annotations.JSGetter;
+
+import java.io.*;
+import java.util.List;
+import java.util.ArrayList;
+
+/**
+ * Define a simple JavaScript File object.
+ *
+ * This isn't intended to be any sort of definitive attempt at a
+ * standard File object for JavaScript, but instead is an example
+ * of a more involved definition of a host object.
+ *
+ * Example of use of the File object:
+ * <pre>
+ * js> defineClass("File")
+ * js> file = new File("myfile.txt");
+ * [object File]
+ * js> file.writeLine("one");                       <i>only now is file actually opened</i>
+ * js> file.writeLine("two");
+ * js> file.writeLine("thr", "ee");
+ * js> file.close();                                <i>must close file before we can reopen for reading</i>
+ * js> var a = file.readLines();                    <i>creates and fills an array with the contents of the file</i>
+ * js> a;
+ * one,two,three
+ * js>
+ * </pre>
+ *
+ *
+ * File errors or end-of-file signaled by thrown Java exceptions will
+ * be wrapped as JavaScript exceptions when called from JavaScript,
+ * and may be caught within JavaScript.
+ *
+ * @author Norris Boyd
+ */
+public class File extends ScriptableObject {
+
+    /**
+     *
+     */
+    private static final long serialVersionUID = 2549960399774237828L;
+    /**
+     * The zero-parameter constructor.
+     *
+     * When Context.defineClass is called with this class, it will
+     * construct File.prototype using this constructor.
+     */
+    public File() {
+    }
+
+    /**
+     * The Java method defining the JavaScript File constructor.
+     *
+     * If the constructor has one or more arguments, and the
+     * first argument is not undefined, the argument is converted
+     * to a string as used as the filename.<p>
+     *
+     * Otherwise System.in or System.out is assumed as appropriate
+     * to the use.
+     */
+    @JSConstructor
+    public static Scriptable jsConstructor(Context cx, Object[] args,
+                                           Function ctorObj,
+                                           boolean inNewExpr)
+    {
+        File result = new File();
+        if (args.length == 0 || args[0] == Context.getUndefinedValue()) {
+            result.name = "";
+            result.file = null;
+        } else {
+            result.name = Context.toString(args[0]);
+            result.file = new java.io.File(result.name);
+        }
+        return result;
+    }
+
+    /**
+     * Returns the name of this JavaScript class, "File".
+     */
+    @Override
+    public String getClassName() {
+        return "File";
+    }
+
+    /**
+     * Get the name of the file.
+     *
+     * Used to define the "name" property.
+     */
+    @JSGetter
+    public String getName() {
+        return name;
+    }
+
+    /**
+     * Read the remaining lines in the file and return them in an array.
+     *
+     * Implements a JavaScript function.<p>
+     *
+     * This is a good example of creating a new array and setting
+     * elements in that array.
+     *
+     * @exception IOException if an error occurred while accessing the file
+     *            associated with this object
+     */
+    @JSFunction
+    public Object readLines()
+        throws IOException
+    {
+        List<String> list = new ArrayList<String>();
+        String s;
+        while ((s = readLine()) != null) {
+            list.add(s);
+        }
+        String[] lines = list.toArray(new String[list.size()]);
+        Scriptable scope = ScriptableObject.getTopLevelScope(this);
+        Context cx = Context.getCurrentContext();
+        return cx.newObject(scope, "Array", lines);
+    }
+
+    /**
+     * Read a line.
+     *
+     * Implements a JavaScript function.
+     * @exception IOException if an error occurred while accessing the file
+     *            associated with this object, or EOFException if the object
+     *            reached the end of the file
+     */
+    @JSFunction
+    public String readLine() throws IOException {
+        return getReader().readLine();
+    }
+
+    /**
+     * Read a character.
+     *
+     * @exception IOException if an error occurred while accessing the file
+     *            associated with this object, or EOFException if the object
+     *            reached the end of the file
+     */
+    @JSFunction
+    public String readChar() throws IOException {
+        int i = getReader().read();
+        if (i == -1)
+            return null;
+        char[] charArray = { (char) i };
+        return new String(charArray);
+    }
+
+    /**
+     * Write strings.
+     *
+     * Implements a JavaScript function. <p>
+     *
+     * This function takes a variable number of arguments, converts
+     * each argument to a string, and writes that string to the file.
+     * @exception IOException if an error occurred while accessing the file
+     *            associated with this object
+     */
+    @JSFunction
+    public static void write(Context cx, Scriptable thisObj,
+                                        Object[] args, Function funObj)
+        throws IOException
+    {
+        write0(thisObj, args, false);
+    }
+
+    /**
+     * Write strings and a newline.
+     *
+     * Implements a JavaScript function.
+     * @exception IOException if an error occurred while accessing the file
+     *            associated with this object
+     *
+     */
+    @JSFunction
+    public static void writeLine(Context cx, Scriptable thisObj,
+                                            Object[] args, Function funObj)
+        throws IOException
+    {
+        write0(thisObj, args, true);
+    }
+
+    @JSGetter
+    public int getLineNumber()
+        throws FileNotFoundException
+    {
+        return getReader().getLineNumber();
+    }
+
+    /**
+     * Close the file. It may be reopened.
+     *
+     * Implements a JavaScript function.
+     * @exception IOException if an error occurred while accessing the file
+     *            associated with this object
+     */
+    @JSFunction
+    public void close() throws IOException {
+        if (reader != null) {
+            reader.close();
+            reader = null;
+        } else if (writer != null) {
+            writer.close();
+            writer = null;
+        }
+    }
+
+    /**
+     * Finalizer.
+     *
+     * Close the file when this object is collected.
+     */
+    @Override
+    protected void finalize() {
+        try {
+            close();
+        }
+        catch (IOException e) {
+        }
+    }
+
+    /**
+     * Get the Java reader.
+     */
+    @JSFunction("getReader")
+    public Object getJSReader() {
+        if (reader == null)
+            return null;
+        // Here we use toObject() to "wrap" the BufferedReader object
+        // in a Scriptable object so that it can be manipulated by
+        // JavaScript.
+        Scriptable parent = ScriptableObject.getTopLevelScope(this);
+        return Context.javaToJS(reader, parent);
+    }
+
+    /**
+     * Get the Java writer.
+     *
+     * @see File#getReader
+     *
+     */
+    @JSFunction
+    public Object getWriter() {
+        if (writer == null)
+            return null;
+        Scriptable parent = ScriptableObject.getTopLevelScope(this);
+        return Context.javaToJS(writer, parent);
+    }
+
+    /**
+     * Get the reader, checking that we're not already writing this file.
+     */
+    private LineNumberReader getReader() throws FileNotFoundException {
+        if (writer != null) {
+            throw Context.reportRuntimeError("already writing file \""
+                                             + name
+                                             + "\"");
+        }
+        if (reader == null)
+            reader = new LineNumberReader(file == null
+                                        ? new InputStreamReader(System.in)
+                                        : new FileReader(file));
+        return reader;
+    }
+
+    /**
+     * Perform the guts of write and writeLine.
+     *
+     * Since the two functions differ only in whether they write a
+     * newline character, move the code into a common subroutine.
+     *
+     */
+    private static void write0(Scriptable thisObj, Object[] args, boolean eol)
+        throws IOException
+    {
+        File thisFile = checkInstance(thisObj);
+        if (thisFile.reader != null) {
+            throw Context.reportRuntimeError("already writing file \""
+                                             + thisFile.name
+                                             + "\"");
+        }
+        if (thisFile.writer == null)
+            thisFile.writer = new BufferedWriter(
+                thisFile.file == null ? new OutputStreamWriter(System.out)
+                                      : new FileWriter(thisFile.file));
+        for (int i=0; i < args.length; i++) {
+            String s = Context.toString(args[i]);
+            thisFile.writer.write(s, 0, s.length());
+        }
+        if (eol)
+            thisFile.writer.newLine();
+    }
+
+    /**
+     * Perform the instanceof check and return the downcasted File object.
+     *
+     * This is necessary since methods may reside in the File.prototype
+     * object and scripts can dynamically alter prototype chains. For example:
+     * <pre>
+     * js> defineClass("File");
+     * js> o = {};
+     * [object Object]
+     * js> o.__proto__ = File.prototype;
+     * [object File]
+     * js> o.write("hi");
+     * js: called on incompatible object
+     * </pre>
+     * The runtime will take care of such checks when non-static Java methods
+     * are defined as JavaScript functions.
+     */
+    private static File checkInstance(Scriptable obj) {
+        if (obj == null || !(obj instanceof File)) {
+            throw Context.reportRuntimeError("called on incompatible object");
+        }
+        return (File) obj;
+    }
+
+    /**
+     * Some private data for this class.
+     */
+    private String name;
+    private java.io.File file;  // may be null, meaning to use System.out or .in
+    private LineNumberReader reader;
+    private BufferedWriter writer;
+}
+
diff -pruN 20130227+dfsg1-14/rhino/examples/Foo.java 20130227+rhino-1/rhino/examples/Foo.java
--- 20130227+dfsg1-14/rhino/examples/Foo.java	1970-01-01 00:00:00.000000000 +0000
+++ 20130227+rhino-1/rhino/examples/Foo.java	2023-05-25 14:24:50.000000000 +0000
@@ -0,0 +1,145 @@
+/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+import org.mozilla.javascript.*;
+import org.mozilla.javascript.annotations.JSFunction;
+import org.mozilla.javascript.annotations.JSGetter;
+
+/**
+ * An example host object class.
+ *
+ * Here's a shell session showing the Foo object in action:
+ * <pre>
+ * js> defineClass("Foo")
+ * js> foo = new Foo();         <i>A constructor call, see <a href="#Foo">Foo</a> below.</i>
+ * [object Foo]                 <i>The "Foo" here comes from <a href"#getClassName">getClassName</a>.</i>
+ * js> foo.counter;             <i>The counter property is defined by the <code>defineProperty</code></i>
+ * 0                            <i>call below and implemented by the <a href="#getCounter">getCounter</a></i>
+ * js> foo.counter;             <i>method below.</i>
+ * 1
+ * js> foo.counter;
+ * 2
+ * js> foo.resetCounter();      <i>Results in a call to <a href="#resetCounter">resetCounter</a>.</i>
+ * js> foo.counter;             <i>Now the counter has been reset.</i>
+ * 0
+ * js> foo.counter;
+ * 1
+ * js> bar = new Foo(37);       <i>Create a new instance.</i>
+ * [object Foo]
+ * js> bar.counter;             <i>This instance's counter is distinct from</i>
+ * 37                           <i>the other instance's counter.</i>
+ * js> foo.varargs(3, "hi");    <i>Calls <a href="#varargs">varargs</a>.</i>
+ * this = [object Foo]; args = [3, hi]
+ * js> foo[7] = 34;             <i>Since we extended ScriptableObject, we get</i>
+ * 34                           <i>all the behavior of a JavaScript object</i>
+ * js> foo.a = 23;              <i>for free.</i>
+ * 23
+ * js> foo.a + foo[7];
+ * 57
+ * js>
+ * </pre>
+ *
+ * @see org.mozilla.javascript.Context
+ * @see org.mozilla.javascript.Scriptable
+ * @see org.mozilla.javascript.ScriptableObject
+ *
+ * @author Norris Boyd
+ */
+
+public class Foo extends ScriptableObject {
+    private static final long serialVersionUID = -3833489808933339159L;
+
+    /**
+     * The zero-parameter constructor.
+     *
+     * When Context.defineClass is called with this class, it will
+     * construct Foo.prototype using this constructor.
+     */
+    public Foo() {
+    }
+
+    /**
+     * The Java method defining the JavaScript Foo constructor.
+     *
+     * Takes an initial value for the counter property.
+     * Note that in the example Shell session above, we didn't
+     * supply a argument to the Foo constructor. This means that
+     * the Undefined value is used as the value of the argument,
+     * and when the argument is converted to an integer, Undefined
+     * becomes 0.
+     */
+    public Foo(int counterStart) {
+        counter = counterStart;
+    }
+
+    /**
+     * Returns the name of this JavaScript class, "Foo".
+     */
+    @Override
+    public String getClassName() {
+        return "Foo";
+    }
+
+    /**
+     * The Java method defining the JavaScript resetCounter function.
+     *
+     * Resets the counter to 0.
+     */
+    @JSFunction
+    public void resetCounter() {
+        counter = 0;
+    }
+
+    /**
+     * The Java method implementing the getter for the counter property.
+     * <p>
+     * If "setCounter" had been defined in this class, the runtime would
+     * call the setter when the property is assigned to.
+     */
+    @JSGetter
+    public int getCounter() {
+        return counter++;
+    }
+
+    /**
+     * An example of a variable-arguments method.
+     *
+     * All variable arguments methods must have the same number and
+     * types of parameters, and must be static. <p>
+     * @param cx the Context of the current thread
+     * @param thisObj the JavaScript 'this' value.
+     * @param args the array of arguments for this call
+     * @param funObj the function object of the invoked JavaScript function
+     *               This value is useful to compute a scope using
+     *               Context.getTopLevelScope().
+     * @return computes the string values and types of 'this' and
+     * of each of the supplied arguments and returns them in a string.
+     *
+     * @see org.mozilla.javascript.ScriptableObject#getTopLevelScope
+     */
+    @JSFunction
+    public static Object varargs(Context cx, Scriptable thisObj,
+                                            Object[] args, Function funObj)
+    {
+        StringBuilder buf = new StringBuilder();
+        buf.append("this = ");
+        buf.append(Context.toString(thisObj));
+        buf.append("; args = [");
+        for (int i=0; i < args.length; i++) {
+            buf.append(Context.toString(args[i]));
+            if (i+1 != args.length)
+                buf.append(", ");
+        }
+        buf.append("]");
+        return buf.toString();
+    }
+
+    /**
+     * A piece of private data for this class.
+     */
+    private int counter;
+}
+
diff -pruN 20130227+dfsg1-14/rhino/examples/Matrix.java 20130227+rhino-1/rhino/examples/Matrix.java
--- 20130227+dfsg1-14/rhino/examples/Matrix.java	1970-01-01 00:00:00.000000000 +0000
+++ 20130227+rhino-1/rhino/examples/Matrix.java	2023-05-25 14:24:50.000000000 +0000
@@ -0,0 +1,249 @@
+/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+import org.mozilla.javascript.*;
+import java.util.List;
+import java.util.ArrayList;
+
+/**
+ * Matrix: An example host object class that implements the Scriptable interface.
+ *
+ * Built-in JavaScript arrays don't handle multiple dimensions gracefully: the
+ * script writer must create every array in an array of arrays. The Matrix class
+ * takes care of that by automatically allocating arrays for every index that
+ * is accessed. What's more, the Matrix constructor takes a integer argument
+ * that specifies the dimension of the Matrix. If m is a Matrix with dimension 3,
+ * then m[0] will be a Matrix with dimension 1, and m[0][0] will be an Array.
+ *
+ * Here's a shell session showing the Matrix object in action:
+ * <pre>
+ * js> defineClass("Matrix")
+ * js> var m = new Matrix(2); // A constructor call, see "Matrix(int dimension)"
+ * js> m                      // Object.toString will call "Matrix.getClassName()"
+ * [object Matrix]
+ * js> m[0][0] = 3;
+ * 3
+ * js> uneval(m[0]);          // an array was created automatically!
+ * [3]
+ * js> uneval(m[1]);          // array is created even if we don't set a value
+ * []
+ * js> m.dim;                 // we can access the "dim" property
+ * 2
+ * js> m.dim = 3;
+ * 3
+ * js> m.dim;                 // but not modify the "dim" property
+ * 2
+ * </pre>
+ *
+ * @see org.mozilla.javascript.Context
+ * @see org.mozilla.javascript.Scriptable
+ *
+ * @author Norris Boyd
+ */
+public class Matrix implements Scriptable {
+
+    /**
+     * The zero-parameter constructor.
+     *
+     * When ScriptableObject.defineClass is called with this class, it will
+     * construct Matrix.prototype using this constructor.
+     */
+    public Matrix() {
+    }
+
+    /**
+     * The Java constructor, also used to define the JavaScript constructor.
+     */
+    public Matrix(int dimension) {
+        if (dimension <= 0) {
+            throw Context.reportRuntimeError(
+                  "Dimension of Matrix must be greater than zero");
+        }
+        dim = dimension;
+        list = new ArrayList<Object>();
+    }
+
+    /**
+     * Returns the name of this JavaScript class, "Matrix".
+     */
+    public String getClassName() {
+        return "Matrix";
+    }
+
+    /**
+     * Defines the "dim" property by returning true if name is
+     * equal to "dim".
+     * <p>
+     * Defines no other properties, i.e., returns false for
+     * all other names.
+     *
+     * @param name the name of the property
+     * @param start the object where lookup began
+     */
+    public boolean has(String name, Scriptable start) {
+        return name.equals("dim");
+    }
+
+    /**
+     * Defines all numeric properties by returning true.
+     *
+     * @param index the index of the property
+     * @param start the object where lookup began
+     */
+    public boolean has(int index, Scriptable start) {
+        return true;
+    }
+
+    /**
+     * Get the named property.
+     * <p>
+     * Handles the "dim" property and returns NOT_FOUND for all
+     * other names.
+     * @param name the property name
+     * @param start the object where the lookup began
+     */
+    public Object get(String name, Scriptable start) {
+        if (name.equals("dim"))
+            return new Integer(dim);
+
+        return NOT_FOUND;
+    }
+
+    /**
+     * Get the indexed property.
+     * <p>
+     * Look up the element in the associated list and return
+     * it if it exists. If it doesn't exist, create it.<p>
+     * @param index the index of the integral property
+     * @param start the object where the lookup began
+     */
+    public Object get(int index, Scriptable start) {
+        while (index >= list.size()) {
+            list.add(null);
+        }
+        Object result = list.get(index);
+        if (result != null)
+            return result;
+        if (dim > 2) {
+            Matrix m = new Matrix(dim-1);
+            m.setParentScope(getParentScope());
+            m.setPrototype(getPrototype());
+            result = m;
+        } else {
+            Context cx = Context.getCurrentContext();
+            Scriptable scope = ScriptableObject.getTopLevelScope(start);
+            result = cx.newArray(scope, 0);
+        }
+        list.set(index, result);
+        return result;
+    }
+
+    /**
+     * Set a named property.
+     *
+     * We do nothing here, so all properties are effectively read-only.
+     */
+    public void put(String name, Scriptable start, Object value) {
+    }
+
+    /**
+     * Set an indexed property.
+     *
+     * We do nothing here, so all properties are effectively read-only.
+     */
+    public void put(int index, Scriptable start, Object value) {
+    }
+
+    /**
+     * Remove a named property.
+     *
+     * This method shouldn't even be called since we define all properties
+     * as PERMANENT.
+     */
+    public void delete(String id) {
+    }
+
+    /**
+     * Remove an indexed property.
+     *
+     * This method shouldn't even be called since we define all properties
+     * as PERMANENT.
+     */
+    public void delete(int index) {
+    }
+
+    /**
+     * Get prototype.
+     */
+    public Scriptable getPrototype() {
+        return prototype;
+    }
+
+    /**
+     * Set prototype.
+     */
+    public void setPrototype(Scriptable prototype) {
+        this.prototype = prototype;
+    }
+
+    /**
+     * Get parent.
+     */
+    public Scriptable getParentScope() {
+        return parent;
+    }
+
+    /**
+     * Set parent.
+     */
+    public void setParentScope(Scriptable parent) {
+        this.parent = parent;
+    }
+
+    /**
+     * Get properties.
+     *
+     * We return an empty array since we define all properties to be DONTENUM.
+     */
+    public Object[] getIds() {
+        return new Object[0];
+    }
+
+    /**
+     * Default value.
+     *
+     * Use the convenience method from Context that takes care of calling
+     * toString, etc.
+     */
+    public Object getDefaultValue(Class<?> typeHint) {
+        return "[object Matrix]";
+    }
+
+    /**
+     * instanceof operator.
+     *
+     * We mimick the normal JavaScript instanceof semantics, returning
+     * true if <code>this</code> appears in <code>value</code>'s prototype
+     * chain.
+     */
+    public boolean hasInstance(Scriptable value) {
+        Scriptable proto = value.getPrototype();
+        while (proto != null) {
+            if (proto.equals(this))
+                return true;
+            proto = proto.getPrototype();
+        }
+
+        return false;
+    }
+
+    /**
+     * Some private data for this class.
+     */
+    private int dim;
+    private List<Object> list;
+    private Scriptable prototype, parent;
+}
diff -pruN 20130227+dfsg1-14/rhino/examples/NervousText.html 20130227+rhino-1/rhino/examples/NervousText.html
--- 20130227+dfsg1-14/rhino/examples/NervousText.html	1970-01-01 00:00:00.000000000 +0000
+++ 20130227+rhino-1/rhino/examples/NervousText.html	2023-05-25 14:24:50.000000000 +0000
@@ -0,0 +1,23 @@
+<!-- This Source Code Form is subject to the terms of the Mozilla Public
+   - License, v. 2.0. If a copy of the MPL was not distributed with this
+   - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
+
+<html>
+<body>
+This is the NervousText applet in javascript:
+<applet archive="js.jar" code=NervousText width=200 height=50 >
+</applet>
+
+<hr>
+The test assumes that applet code is generated with:
+<pre>
+java -classpath js.jar org.mozilla.javascript.tools.jsc.Main \
+  -extends java.applet.Applet \
+  -implements java.lang.Runnable \
+  NervousText.js
+</pre>
+and the resulting 2 classes, NervousText.class extending java.applet.Applet and implementing java.lang.Runnable and NervousText1.class which represents compiled JavaScript code, are placed in the same directory as NervousText.html.
+<p>
+The test also assumes that js.jar from Rhino distribution is available in the same directory.
+</body>
+</html>
diff -pruN 20130227+dfsg1-14/rhino/examples/NervousText.js 20130227+rhino-1/rhino/examples/NervousText.js
--- 20130227+dfsg1-14/rhino/examples/NervousText.js	1970-01-01 00:00:00.000000000 +0000
+++ 20130227+rhino-1/rhino/examples/NervousText.js	2023-05-25 14:24:50.000000000 +0000
@@ -0,0 +1,79 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// The Java "NervousText" example ported to JavaScript.
+// Compile using java org.mozilla.javascript.tools.jsc.Main -extends java.applet.Applet -implements java.lang.Runnable NervousText.js
+/*
+Adapted from Java code by
+    Daniel Wyszynski
+    Center for Applied Large-Scale Computing (CALC)
+    04-12-95
+
+    Test of text animation.
+
+    kwalrath: Changed string; added thread suspension. 5-9-95
+*/
+var Font = java.awt.Font;
+var Thread = java.lang.Thread;
+var separated;
+var s = null;
+var killme = null;
+var i;
+var x_coord = 0, y_coord = 0;
+var num;
+var speed=35;
+var counter =0;
+var threadSuspended = false; //added by kwalrath
+
+function init() {
+        this.resize(150,50);
+        this.setFont(new Font("TimesRoman",Font.BOLD,36));
+        s = this.getParameter("text");
+        if (s == null) {
+            s = "Rhino";
+        }
+        separated = s.split('');
+}
+
+function start() {
+        if(killme == null)
+        {
+        killme = new java.lang.Thread(java.lang.Runnable(this));
+        killme.start();
+        }
+}
+
+function stop() {
+        killme = null;
+}
+
+function run() {
+        while (killme != null) {
+        try {Thread.sleep(100);} catch (e){}
+            this.repaint();
+        }
+        killme = null;
+}
+
+function paint(g) {
+        for(i=0;i<separated.length;i++)
+        {
+        x_coord = Math.random()*10+15*i;
+        y_coord = Math.random()*10+36;
+        g.drawChars(separated, i,1,x_coord,y_coord);
+        }
+}
+
+/* Added by kwalrath. */
+function mouseDown(evt, x, y) {
+        if (threadSuspended) {
+            killme.resume();
+        }
+        else {
+            killme.suspend();
+        }
+        threadSuspended = !threadSuspended;
+    return true;
+}
+
diff -pruN 20130227+dfsg1-14/rhino/examples/PrimitiveWrapFactory.java 20130227+rhino-1/rhino/examples/PrimitiveWrapFactory.java
--- 20130227+dfsg1-14/rhino/examples/PrimitiveWrapFactory.java	1970-01-01 00:00:00.000000000 +0000
+++ 20130227+rhino-1/rhino/examples/PrimitiveWrapFactory.java	2023-05-25 14:24:50.000000000 +0000
@@ -0,0 +1,40 @@
+/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+import org.mozilla.javascript.*;
+
+/**
+ * An example WrapFactory that can be used to avoid wrapping of Java types
+ * that can be converted to ECMA primitive values.
+ * So java.lang.String is mapped to ECMA string, all java.lang.Numbers are
+ * mapped to ECMA numbers, and java.lang.Booleans are mapped to ECMA booleans
+ * instead of being wrapped as objects. Additionally java.lang.Character is
+ * converted to ECMA string with length 1.
+ * Other types have the default behavior.
+ * <p>
+ * Note that calling "new java.lang.String('foo')" in JavaScript with this
+ * wrap factory enabled will still produce a wrapped Java object since the
+ * WrapFactory.wrapNewObject method is not overridden.
+ * <p>
+ * The PrimitiveWrapFactory is enabled on a Context by calling setWrapFactory
+ * on that context.
+ */
+public class PrimitiveWrapFactory extends WrapFactory {
+  @Override
+  public Object wrap(Context cx, Scriptable scope, Object obj,
+                     Class<?> staticType)
+  {
+    if (obj instanceof String || obj instanceof Number ||
+        obj instanceof Boolean)
+    {
+      return obj;
+    } else if (obj instanceof Character) {
+      char[] a = { ((Character)obj).charValue() };
+      return new String(a);
+    }
+    return super.wrap(cx, scope, obj, staticType);
+  }
+}
diff -pruN 20130227+dfsg1-14/rhino/examples/RunScript.java 20130227+rhino-1/rhino/examples/RunScript.java
--- 20130227+dfsg1-14/rhino/examples/RunScript.java	1970-01-01 00:00:00.000000000 +0000
+++ 20130227+rhino-1/rhino/examples/RunScript.java	2023-05-25 14:24:50.000000000 +0000
@@ -0,0 +1,47 @@
+/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+import org.mozilla.javascript.*;
+
+/**
+ * RunScript: simplest example of controlling execution of Rhino.
+ *
+ * Collects its arguments from the command line, executes the
+ * script, and prints the result.
+ *
+ * @author Norris Boyd
+ */
+public class RunScript {
+    public static void main(String args[])
+    {
+        // Creates and enters a Context. The Context stores information
+        // about the execution environment of a script.
+        Context cx = Context.enter();
+        try {
+            // Initialize the standard objects (Object, Function, etc.)
+            // This must be done before scripts can be executed. Returns
+            // a scope object that we use in later calls.
+            Scriptable scope = cx.initStandardObjects();
+
+            // Collect the arguments into a single string.
+            String s = "";
+            for (int i=0; i < args.length; i++) {
+                s += args[i];
+            }
+
+            // Now evaluate the string we've colected.
+            Object result = cx.evaluateString(scope, s, "<cmd>", 1, null);
+
+            // Convert the result to a string and print it.
+            System.err.println(Context.toString(result));
+
+        } finally {
+            // Exit from the context.
+            Context.exit();
+        }
+    }
+}
+
diff -pruN 20130227+dfsg1-14/rhino/examples/RunScript2.java 20130227+rhino-1/rhino/examples/RunScript2.java
--- 20130227+dfsg1-14/rhino/examples/RunScript2.java	1970-01-01 00:00:00.000000000 +0000
+++ 20130227+rhino-1/rhino/examples/RunScript2.java	2023-05-25 14:24:50.000000000 +0000
@@ -0,0 +1,38 @@
+/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+import org.mozilla.javascript.*;
+
+/**
+ * RunScript2: Like RunScript, but reflects the System.out into JavaScript.
+ *
+ * @author Norris Boyd
+ */
+public class RunScript2 {
+    public static void main(String args[])
+    {
+        Context cx = Context.enter();
+        try {
+            Scriptable scope = cx.initStandardObjects();
+
+            // Add a global variable "out" that is a JavaScript reflection
+            // of System.out
+            Object jsOut = Context.javaToJS(System.out, scope);
+            ScriptableObject.putProperty(scope, "out", jsOut);
+
+            String s = "";
+            for (int i=0; i < args.length; i++) {
+                s += args[i];
+            }
+            Object result = cx.evaluateString(scope, s, "<cmd>", 1, null);
+            System.err.println(Context.toString(result));
+        } finally {
+            Context.exit();
+        }
+    }
+
+}
+
diff -pruN 20130227+dfsg1-14/rhino/examples/RunScript3.java 20130227+rhino-1/rhino/examples/RunScript3.java
--- 20130227+dfsg1-14/rhino/examples/RunScript3.java	1970-01-01 00:00:00.000000000 +0000
+++ 20130227+rhino-1/rhino/examples/RunScript3.java	2023-05-25 14:24:50.000000000 +0000
@@ -0,0 +1,57 @@
+/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+import org.mozilla.javascript.*;
+
+/**
+ * RunScript3: Example of using JavaScript objects
+ *
+ * Collects its arguments from the command line, executes the
+ * script, and then ...
+ *
+ * @author Norris Boyd
+ */
+public class RunScript3 {
+    public static void main(String args[])
+    {
+        Context cx = Context.enter();
+        try {
+            Scriptable scope = cx.initStandardObjects();
+
+            // Collect the arguments into a single string.
+            String s = "";
+            for (int i=0; i < args.length; i++) {
+                s += args[i];
+            }
+
+            // Now evaluate the string we've collected. We'll ignore the result.
+            cx.evaluateString(scope, s, "<cmd>", 1, null);
+
+            // Print the value of variable "x"
+            Object x = scope.get("x", scope);
+            if (x == Scriptable.NOT_FOUND) {
+                System.out.println("x is not defined.");
+            } else {
+                System.out.println("x = " + Context.toString(x));
+            }
+
+            // Call function "f('my arg')" and print its result.
+            Object fObj = scope.get("f", scope);
+            if (!(fObj instanceof Function)) {
+                System.out.println("f is undefined or not a function.");
+            } else {
+                Object functionArgs[] = { "my arg" };
+                Function f = (Function)fObj;
+                Object result = f.call(cx, scope, scope, functionArgs);
+                String report = "f('my args') = " + Context.toString(result);
+                System.out.println(report);
+            }
+        } finally {
+            Context.exit();
+        }
+    }
+}
+
diff -pruN 20130227+dfsg1-14/rhino/examples/RunScript4.java 20130227+rhino-1/rhino/examples/RunScript4.java
--- 20130227+dfsg1-14/rhino/examples/RunScript4.java	1970-01-01 00:00:00.000000000 +0000
+++ 20130227+rhino-1/rhino/examples/RunScript4.java	2023-05-25 14:24:50.000000000 +0000
@@ -0,0 +1,47 @@
+/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+import org.mozilla.javascript.*;
+
+/**
+ * RunScript4: Execute scripts in an environment that includes the
+ *             example Counter class.
+ *
+ * @author Norris Boyd
+ */
+public class RunScript4 {
+    public static void main(String args[])
+        throws Exception
+    {
+        Context cx = Context.enter();
+        try {
+            Scriptable scope = cx.initStandardObjects();
+
+            // Use the Counter class to define a Counter constructor
+            // and prototype in JavaScript.
+            ScriptableObject.defineClass(scope, Counter.class);
+
+            // Create an instance of Counter and assign it to
+            // the top-level variable "myCounter". This is
+            // equivalent to the JavaScript code
+            //    myCounter = new Counter(7);
+            Object[] arg = { new Integer(7) };
+            Scriptable myCounter = cx.newObject(scope, "Counter", arg);
+            scope.put("myCounter", scope, myCounter);
+
+            String s = "";
+            for (int i=0; i < args.length; i++) {
+                s += args[i];
+            }
+            Object result = cx.evaluateString(scope, s, "<cmd>", 1, null);
+            System.err.println(Context.toString(result));
+        } finally {
+            Context.exit();
+        }
+    }
+
+}
+
diff -pruN 20130227+dfsg1-14/rhino/examples/Shell.java 20130227+rhino-1/rhino/examples/Shell.java
--- 20130227+dfsg1-14/rhino/examples/Shell.java	1970-01-01 00:00:00.000000000 +0000
+++ 20130227+rhino-1/rhino/examples/Shell.java	2023-05-25 14:24:50.000000000 +0000
@@ -0,0 +1,317 @@
+/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+import org.mozilla.javascript.*;
+import java.io.*;
+
+/**
+ * The shell program.
+ *
+ * Can execute scripts interactively or in batch mode at the command line.
+ * An example of controlling the JavaScript engine.
+ *
+ * @author Norris Boyd
+ */
+public class Shell extends ScriptableObject
+{
+    private static final long serialVersionUID = -5638074146250193112L;
+
+    @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 main(String args[]) {
+        // Associate a new Context with this thread
+        Context cx = Context.enter();
+        try {
+            // Initialize the standard objects (Object, Function, etc.)
+            // This must be done before scripts can be executed.
+            Shell shell = new Shell();
+            cx.initStandardObjects(shell);
+
+            // Define some global functions particular to the shell. Note
+            // that these functions are not part of ECMA.
+            String[] names = { "print", "quit", "version", "load", "help" };
+            shell.defineFunctionProperties(names, Shell.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(shell, array);
+            shell.defineProperty("arguments", argsObj,
+                                 ScriptableObject.DONTENUM);
+
+            shell.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 shell. ");
+        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 shell.
+     *
+     * This only affects the interactive mode.
+     *
+     * This method is defined as a JavaScript function.
+     */
+    public void quit()
+    {
+        quitting = true;
+    }
+
+    /**
+     * 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)
+    {
+        Shell shell = (Shell)getTopLevelScope(thisObj);
+        for (int i = 0; i < args.length; i++) {
+            shell.processSource(cx, Context.toString(args[i]));
+        }
+    }
+
+
+    /**
+     * 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;
+}
+
diff -pruN 20130227+dfsg1-14/rhino/examples/SwingApplication.js 20130227+rhino-1/rhino/examples/SwingApplication.js
--- 20130227+dfsg1-14/rhino/examples/SwingApplication.js	1970-01-01 00:00:00.000000000 +0000
+++ 20130227+rhino-1/rhino/examples/SwingApplication.js	2023-05-25 14:24:50.000000000 +0000
@@ -0,0 +1,81 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/*
+ * SwingApplication.js - a translation into JavaScript of
+ * SwingApplication.java, a java.sun.com Swing example.
+ *
+ * @author Roger E Critchlow, Jr.
+ */
+
+var swingNames = JavaImporter();
+
+swingNames.importPackage(Packages.javax.swing);
+swingNames.importPackage(Packages.java.awt);
+swingNames.importPackage(Packages.java.awt.event);
+
+function createComponents() 
+{
+    with (swingNames) {
+        var labelPrefix = "Number of button clicks: ";
+        var numClicks = 0;
+        var label = new JLabel(labelPrefix + numClicks);
+        var button = new JButton("I'm a Swing button!");
+        button.mnemonic = KeyEvent.VK_I;
+        // Since Rhino 1.5R5 JS functions can be passed to Java method if
+        // corresponding argument type is Java interface with single method
+        // or all its methods have the same number of arguments and the
+        // corresponding arguments has the same type. See also comments for
+        // frame.addWindowListener bellow
+        button.addActionListener(function() {
+            numClicks += 1;
+            label.setText(labelPrefix + numClicks);
+        });
+        label.setLabelFor(button);
+
+        /*
+         * An easy way to put space between a top-level container
+         * and its contents is to put the contents in a JPanel
+         * that has an "empty" border.
+         */
+        var pane = new JPanel();
+        pane.border = BorderFactory.createEmptyBorder(30, //top
+                                                      30, //left
+                                                      10, //bottom
+                                                      30); //right
+        pane.setLayout(new GridLayout(0, 1));
+        pane.add(button);
+        pane.add(label);
+
+        return pane;
+    }
+}
+
+with (swingNames) {
+    try {
+	UIManager.
+            setLookAndFeel(UIManager.getCrossPlatformLookAndFeelClassName());
+    } catch (e) { }
+
+    //Create the top-level container and add contents to it.
+    var frame = new swingNames.JFrame("SwingApplication");
+    frame.getContentPane().add(createComponents(), BorderLayout.CENTER);
+
+    // Pass JS function as implementation of WindowListener. It is allowed since 
+    // all methods in WindowListener have the same signature. To distinguish 
+    // between methods Rhino passes to JS function the name of corresponding 
+    // method as the last argument  
+    frame.addWindowListener(function(event, methodName) {
+	if (methodName == "windowClosing") {     
+            java.lang.System.exit(0);
+	}
+    });
+
+    //Finish setting up the frame, and show it.
+    frame.pack();
+    frame.setVisible(true);
+}
+
+
+
diff -pruN 20130227+dfsg1-14/rhino/examples/checkParam.js 20130227+rhino-1/rhino/examples/checkParam.js
--- 20130227+dfsg1-14/rhino/examples/checkParam.js	1970-01-01 00:00:00.000000000 +0000
+++ 20130227+rhino-1/rhino/examples/checkParam.js	2023-05-25 14:24:50.000000000 +0000
@@ -0,0 +1,105 @@
+/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/**
+ * checkParam.js
+ *
+ * The files given as arguments on the command line are assumed to be
+ * Java source code files. This program checks to see that the @param
+ * tags in the documentation comments match with the parameters for
+ * the associated Java methods.
+ * <p>
+ * Any errors found are reported.
+ *
+ */
+defineClass("File")
+
+// Return true if "str" ends with "suffix".
+function stringEndsWith(str, suffix) {
+	return str.substring(str.length - suffix.length) == suffix;
+}
+
+/**
+ * Perform processing once the end of a documentation comment is seen.
+ *
+ * Look for a parameter list following the end of the comment and
+ * collect the parameters and compare to the @param entries.
+ * Report any discrepancies.
+ * @param f the current file
+ * @param a an array of parameters from @param comments
+ * @param line the string containing the comment end (in case the
+ *        parameters are on the same line)
+ */
+function processCommentEnd(f, a, line) {
+	while (line != null && !line.match(/\(/))
+		line = f.readLine();
+	while (line != null && !line.match(/\)/))
+		line += f.readLine();
+	if (line === null)
+		return;
+	var m = line.match(/\(([^\)]+)\)/);
+	var args = m ? m[1].split(",") : [];
+	if (a.length != args.length) {
+		print('"' + f.name +
+		      '"; line ' + f.lineNumber +
+		      ' mismatch: had a different number' +
+		      ' of @param entries and parameters.');
+	} else {
+		for (var i=0; i < a.length; i++) {
+			if (!stringEndsWith(args[i], a[i])) {
+				print('"' + f.name +
+				      '"; line ' + f.lineNumber +
+				      ' mismatch: had "' + a[i] +
+				      '" and "' + args[i] + '".');
+				break;
+			}
+		}
+	}
+}
+
+/**
+ * Process the given file, looking for mismatched @param lists and
+ * parameter lists.
+ * @param f the file to process
+ */
+function processFile(f) {
+	var line;
+	var m;
+	var i = 0;
+	var a = [];
+      outer:
+	while ((line = f.readLine()) != null) {
+		if (line.match(/@param/)) {
+			while (m = line.match(/@param[ 	]+([^ 	]+)/)) {
+				a[i++] = m[1];
+				line = f.readLine();
+				if (line == null)
+					break outer;
+			}
+		}
+		if (i != 0 && line.match(/\*\//)) {
+			processCommentEnd(f, a, line);
+			i = 0;
+			a = [];
+		}
+	}
+	if (i != 0) {
+		print('"' + f.name +
+		      '"; line ' + f.lineNumber +
+		      ' missing parameters at end of file.');
+	}
+}
+
+// main script: process each file in arguments list
+
+for (var i=0; i < arguments.length; i++) {
+	var filename = String(arguments[i]);
+	print("Checking " + filename + "...");
+	var f = new File(filename);
+	processFile(f);
+}
+print("done.");
+
diff -pruN 20130227+dfsg1-14/rhino/examples/enum.js 20130227+rhino-1/rhino/examples/enum.js
--- 20130227+dfsg1-14/rhino/examples/enum.js	1970-01-01 00:00:00.000000000 +0000
+++ 20130227+rhino-1/rhino/examples/enum.js	2023-05-25 14:24:50.000000000 +0000
@@ -0,0 +1,37 @@
+/* -*- tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *      
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/*
+Implementing the interface java.util.Enumeration passing the object
+with JavaScript implementation directly to the constructor.
+This is a shorthand for JavaAdapter constructor:
+
+elements = new JavaAdapter(java.util.Enumeration, {
+        index: 0, 
+        elements: array,
+	hasMoreElements: function ...
+        nextElement: function ...
+		});
+ */
+
+// an array to enumerate.
+var array = [0, 1, 2];
+
+// create an array enumeration.
+var elements = new java.util.Enumeration({
+        index: 0,
+        elements: array,
+        hasMoreElements: function() {
+                return (this.index < this.elements.length);
+	},      
+        nextElement: function() {
+                return this.elements[this.index++];
+	}
+    });
+
+// now print out the array by enumerating through the Enumeration
+while (elements.hasMoreElements())
+	print(elements.nextElement());
diff -pruN 20130227+dfsg1-14/rhino/examples/jsdoc.js 20130227+rhino-1/rhino/examples/jsdoc.js
--- 20130227+dfsg1-14/rhino/examples/jsdoc.js	1970-01-01 00:00:00.000000000 +0000
+++ 20130227+rhino-1/rhino/examples/jsdoc.js	2023-05-25 14:24:50.000000000 +0000
@@ -0,0 +1,523 @@
+/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/**
+ * Process a JavaScript source file and process special comments
+ * to produce an HTML file of documentation, similar to javadoc.
+ * @author Norris Boyd
+ * @see rhinotip.jar
+ * @lastmodified xx
+ * @version 1.2 Roland Pennings: Allow multiple files for a function.
+ * @version 1.3 Roland Pennings: Removes ../.. from the input directory name
+ */
+defineClass("File")
+
+var functionDocArray = [];
+var inputDirName = "";
+var indexFileArray = [];
+var indexFile = "";
+var indexFileName = "index_files";
+var indexFunctionArray = [];
+var indexFunction = "";
+var indexFunctionName = "index_functions";
+var FileList = [];
+var DirList = [];
+var outputdir = null;
+var debug = 0;
+
+
+
+/**
+ * Process JavaScript source file <code>f</code>, writing jsdoc to
+ * file <code>out</code>.
+ * @param f input file
+ * @param fname name of the input file (without the path)
+ * @param inputdir directory of the input file
+ * @param out output file
+ */
+function processFile(f, fname, inputdir, out) {
+	var s;
+	var firstLine = true;
+	indexFileArray[fname] = "";
+
+    // write the header of the output file
+	out.writeLine('<HTML><HEADER><TITLE>' + fname + '</TITLE><BODY>');
+	if (inputdir != null) {
+	  outstr = '<a name=\"_top_\"></a><pre><a href=\"' + indexFile + '\">Index Files</a> ';
+	  outstr += '<a href=\"' + indexFunction + '\">Index Functions</a></pre><hr>';
+      out.writeLine(outstr);
+	}
+
+    // process the input file
+	var comment = "";
+	while ((s = f.readLine()) != null) {
+      var m = s.match(/\/\*\*(.*)/);
+	  if (m != null) {
+		  // Found a comment start.
+		  s = "*" + m[1];
+		  do {
+			m = s.match(/(.*)\*\//);
+			if (m != null) {
+			  // Found end of comment.
+			  comment += m[1];
+			  break;
+			}
+			// Strip leading whitespace and "*".
+			comment += s.replace(/^\s*\*/, "");
+			s = f.readLine();
+		  } while (s != null);
+
+    	  if (debug)
+          print("Found comment " + comment);
+
+		  if (firstLine) {
+			// We have a comment for the whole file.
+			out.writeLine('<H1>File ' + fname + '</H1>');
+			out.writeLine(processComment(comment,firstLine,fname));
+			out.writeLine('<HR>');
+			firstLine = false;
+			comment = "";
+			continue;
+		  }
+	  }
+	  // match the beginning of the function
+	  // NB we also match functions without a comment!
+	  // if we have two comments one after another only the last one will be taken
+	  m = s.match(/^\s*function\s+((\w+)|(\w+)(\s+))\(([^)]*)\)/);
+	  if (m != null)
+	  {
+			// Found a function start
+			var htmlText = processFunction(m[1], m[5], comment); // sjm changed from 2nd to 5th arg
+
+			// Save the text in a global variable, so we
+			// can write out a table of contents first.
+			functionDocArray[functionDocArray.length] = {name:m[1], text:htmlText};
+
+			// Store the function also in the indexFunctionArray
+			// so we can have a separate file with the function table of contents
+			if (indexFunctionArray[m[1]]) {
+				//  print("ERROR: function: " + m[1] + " is defined more than once!");
+				// Allow multiple files for a function
+				with (indexFunctionArray[m[1]]) {
+					filename = filename + "|" + fname;
+					// print("filename = " + filename);
+				}
+			}
+			else {
+				indexFunctionArray[m[1]] = {filename:fname};
+			}
+			//reset comment
+			comment = "";
+		}
+		// match a method being bound to a prototype
+	  m = s.match(/^\s*(\w*)\.prototype\.(\w*)\s*=\s*function\s*\(([^)]*)\)/);
+	  if (m != null)
+	  {
+			// Found a method being bound to a prototype.
+			var htmlText = processPrototypeMethod(m[1], m[2], m[3], comment);
+
+			// Save the text in a global variable, so we
+			// can write out a table of contents first.
+			functionDocArray[functionDocArray.length] = {name:m[1]+".prototype."+m[2], text:htmlText};
+
+			// Store the function also in the indexFunctionArray
+			// so we can have a separate file with the function table of contents
+			if (indexFunctionArray[m[1]]) {
+				//  print("ERROR: function: " + m[1] + " is defined more than once!");
+				// Allow multiple files for a function
+				with (indexFunctionArray[m[1]]) {
+					filename = filename + "|" + fname;
+					// print("filename = " + filename);
+				}
+			}
+			else {
+				indexFunctionArray[m[1]] = {filename:fname};
+			}
+			//reset comment
+			comment = "";
+		}
+
+
+		firstLine = false;
+	}
+
+	// Write table of contents.
+	for (var i=0; i < functionDocArray.length; i++) {
+		with (functionDocArray[i]) {
+			out.writeLine('function <A HREF=#' + name +
+				      '>' + name + '</A><BR>');
+		}
+	}
+	out.writeLine('<HR>');
+
+	// Now write the saved function documentation.
+	for (i=0; i < functionDocArray.length; i++) {
+		with (functionDocArray[i]) {
+			out.writeLine('<A NAME=' + name + '>');
+			out.writeLine(text);
+		}
+	}
+	out.writeLine('</BODY></HTML>');
+
+	// Now clean up the doc array
+	functionDocArray = [];
+}
+
+/**
+ * Process function and associated comment.
+ * @param name the name of the function
+ * @param args the args of the function as a single string
+ * @param comment the text of the comment
+ * @return a string for the HTML text of the documentation
+ */
+function processFunction(name, args, comment) {
+   if (debug)
+    print("Processing " + name + " " + args + " " + comment);
+	return "<H2>Function " + name + "</H2>" +
+		"<PRE>" +
+		"function " + name + "(" + args + ")" +
+		"</PRE>" +
+		processComment(comment,0,name) +
+		"<P><BR><BR>";
+}
+
+/**
+ * Process a method being bound to a prototype.
+ * @param proto the name of the prototype
+ * @param name the name of the function
+ * @param args the args of the function as a single string
+ * @param comment the text of the comment
+ * @return a string for the HTML text of the documentation
+ */
+function processPrototypeMethod(proto, name, args, comment) {
+   if (debug)
+    print("Processing " + proto + ".prototype." + name + " " + args + " " + comment);
+	return "<H2> Method " + proto + ".prototype." + name + "</H2>" +
+		"<PRE>" +
+		proto + ".prototype." + name + " = function(" + args + ")" +
+		"</PRE>" +
+		processComment(comment,0,name) +
+		"<P><BR><BR>";
+}
+
+
+/**
+ * Process comment.
+ * @param comment the text of the comment
+ * @param firstLine shows if comment is at the beginning of the file
+ * @param fname name of the file (without path)
+ * @return a string for the HTML text of the documentation
+ */
+function processComment(comment,firstLine,fname) {
+	var tags = {};
+	// Use the "lambda" form of regular expression replace,
+	// where the replacement object is a function rather
+	// than a string. The function is called with the
+	// matched text and any parenthetical matches as
+	// arguments, and the result of the function used as the
+	// replacement text.
+	// Here we use the function to build up the "tags" object,
+	// which has a property for each "@" tag that is the name
+	// of the tag, and whose value is an array of the
+	// text following that tag.
+	comment = comment.replace(/@(\w+)\s+([^@]*)/g,
+				  function (s, name, text) {
+					var a = tags[name] || [];
+					a.push(text);
+					tags[name] = a;
+					return "";
+				  });
+
+	// if we have a comment at the beginning of a file
+	// store the comment for the index file
+	if (firstLine) {
+	  indexFileArray[fname] = comment;
+	}
+
+	var out = comment + '<P>';
+	if (tags["param"]) {
+		// Create a table of parameters and their descriptions.
+		var array = tags["param"];
+		var params = "";
+		for (var i=0; i < array.length; i++) {
+			var m = array[i].match(/(\w+)\s+(.*)/);
+			params += '<TR><TD><I>'+m[1]+'</I></TD>' +
+			          '<TD>'+m[2]+'</TD></TR>';
+		}
+		out += '<TABLE WIDTH="90%" BORDER=1>';
+		out += '<TR BGCOLOR=0xdddddddd>';
+		out += '<TD><B>Parameter</B></TD>';
+		out += '<TD><B>Description</B></TD></TR>';
+		out += params;
+		out += '</TABLE><P>';
+	}
+	if (tags["return"]) {
+		out += "<DT><B>Returns:</B><DD>";
+		out += tags["return"][0] + "</DL><P>";
+	}
+	if (tags["author"]) {
+		// List the authors together, separated by commas.
+		out += '<DT><B>Author:</B><DD>';
+		var array = tags["author"];
+		for (var i=0; i < array.length; i++) {
+			out += array[i];
+			if (i+1 < array.length)
+				out += ", ";
+		}
+		out += '</DL><P>';
+	}
+	if (tags["version"]) {
+	    // Show the version.
+	    out += '<DT><B>Version:</B><DD>';
+	    var array = tags["version"];
+	    for (var i=0; i < array.length; i++) {
+		   out += array[i];
+		   if (i+1 < array.length)
+			   out += "<BR><DD>";
+		}
+		out += '</DL><P>';
+	}
+	if (tags["see"]) {
+	    // List the see modules together, separated by <BR>.
+	    out += '<DT><B>Dependencies:</B><DD>';
+	    var array = tags["see"];
+	    for (var i=0; i < array.length; i++) {
+		   out += array[i];
+		   if (i+1 < array.length)
+			   out += "<BR><DD>";
+		}
+		out += '</DL><P>';
+	}
+	if (tags["lastmodified"]) {
+	    // Shows a last modified description with client-side js.
+	    out += '<DT><B>Last modified:</B><DD>';
+		out += '<script><!--\n';
+		out += 'document.writeln(document.lastModified);\n';
+		out += '// ---></script>\n';
+		out += '</DL><P>';
+	}
+
+	// additional tags can be added here (i.e., "if (tags["see"])...")
+	return out;
+}
+
+/**
+ * Create an html output file
+ * @param outputdir directory to put the file
+ * @param htmlfile name of the file
+*/
+function CreateOutputFile(outputdir,htmlfile)
+{
+  if (outputdir==null)
+  {
+    var outname = htmlfile;
+  }
+  else
+  {
+    var separator = Packages.java.io.File.separator;
+    var outname = outputdir + separator + htmlfile.substring(htmlfile.lastIndexOf(separator),htmlfile.length);
+  }
+  print("output file: " + outname);
+  return new File(outname);
+}
+
+/**
+ * Process a javascript file. Puts the generated HTML file in the outdir
+ * @param filename name of the javascript file
+ * @inputdir input directory of the file (default null)
+ */
+function processJSFile(filename,inputdir)
+{
+  if (debug) print("filename = " + filename + " inputdir = " + inputdir);
+
+  if (!filename.match(/\.js$/)) {
+	print("Expected filename to end in '.js'; had instead " +
+	  filename + ". I don't treat the file.");
+  } else {
+    if (inputdir==null)
+	{
+	  var inname = filename;
+    }
+	else
+	{
+      var separator = Packages.java.io.File.separator;
+      var inname = inputdir + separator + filename;
+    }
+    print("Processing file " + inname);
+
+	var f = new File(inname);
+
+    // create the output file
+    var htmlfile = filename.replace(/\.js$/, ".html");
+
+	var out = CreateOutputFile(outputdir,htmlfile);
+
+    processFile(f, filename, inputdir, out);
+	out.close();
+  }
+}
+
+/**
+ * Generate index files containing links to the processed javascript files
+ * and the generated functions
+ */
+function GenerateIndex(dirname)
+{
+  // construct the files index file
+  var out = CreateOutputFile(outputdir,indexFile);
+
+  // write the beginning of the file
+  out.writeLine('<HTML><HEADER><TITLE>File Index - directory: ' + dirname + '</TITLE><BODY>');
+  out.writeLine('<H1>File Index - directory: ' + dirname + '</H1>\n');
+  out.writeLine('<TABLE WIDTH="90%" BORDER=1>');
+  out.writeLine('<TR BGCOLOR=0xdddddddd>');
+  out.writeLine('<TD><B>File</B></TD>');
+  out.writeLine('<TD><B>Description</B></TD></TR>');
+
+  var separator = Packages.java.io.File.separator;
+
+  // sort the index file array
+  var SortedFileArray = [];
+  for (var fname in indexFileArray)
+    SortedFileArray.push(fname);
+  SortedFileArray.sort();
+
+  for (var i=0; i < SortedFileArray.length; i++) {
+    var fname = SortedFileArray[i];
+  	var htmlfile = fname.replace(/\.js$/, ".html");
+    out.writeLine('<TR><TD><A HREF=\"' + htmlfile + '\">' + fname + '</A></TD></TD><TD>');
+	if (indexFileArray[fname])
+	  out.writeLine(indexFileArray[fname]);
+	else
+	  out.writeLine('No comments');
+	out.writeLine('</TD></TR>\n');
+  }
+  out.writeLine('</TABLE></BODY></HTML>');
+  out.close();
+
+  // construct the functions index file
+  var out = CreateOutputFile(outputdir,indexFunction);
+
+  // write the beginning of the file
+  out.writeLine('<HTML><HEADER><TITLE>Function Index - directory: ' + dirname + '</TITLE><BODY>');
+  out.writeLine('<H1>Function Index - directory: ' + dirname + '</H1>\n');
+  out.writeLine('<TABLE WIDTH="90%" BORDER=1>');
+  out.writeLine('<TR BGCOLOR=0xdddddddd>');
+  out.writeLine('<TD><B>Function</B></TD>');
+  out.writeLine('<TD><B>Files</B></TD></TR>');
+
+  // sort the function array
+  var SortedFunctionArray = [];
+  for (var functionname in indexFunctionArray)
+    SortedFunctionArray.push(functionname);
+  SortedFunctionArray.sort();
+
+  for (var j=0; j < SortedFunctionArray.length; j++) {
+    var funcname = SortedFunctionArray[j];
+    with (indexFunctionArray[funcname]) {
+	 var outstr = '<TR><TD>' + funcname + '</TD><TD>';
+	 var filelst = filename.split("|");
+	 for (var i in filelst) {
+	   var htmlfile = filelst[i].replace(/\.js$/, ".html");
+	   outstr += '<A HREF=\"' + htmlfile + '#' + funcname + '\">' + filelst[i] + '</A>&nbsp;';
+	 }
+	 outstr += '</TD></TR>';
+	 out.writeLine(outstr);
+    }
+  }
+  out.writeLine('</TABLE></BODY></HTML>');
+  out.close();
+}
+
+
+/**
+ * prints the options for JSDoc
+*/
+function PrintOptions()
+{
+  print("You can use the following options:\n");
+  print("-d: specify an output directory for the generated html files\n");
+  print("-i: processes all files in an input directory (you can specify several directories)\n");
+  quit();
+}
+
+
+// Main Script
+// first read the arguments
+if (! arguments)
+  PrintOptions();
+
+for (var i=0; i < arguments.length; i++) {
+  if (debug) print("argument: + \'" + arguments[i] + "\'");
+  if (arguments[i].match(/^\-/)) {
+   if (String(arguments[i])=="-d"){
+    // output directory for the generated html files
+
+    outputdir = String(arguments[i+1]);
+	if (debug) print("outputdir: + \'" + outputdir + "\'");
+
+    i++;
+   }
+   else if (String(arguments[i])=="-i"){
+    // process all files in an input directory
+
+    DirList.push(String(arguments[i+1]));
+if (debug) print("inputdir: + \'" + arguments[i+1] + "\'");
+     i++;
+   }
+   else {
+    print("Unknown option: " + arguments[i] + "\n");
+	PrintOptions();
+   }
+  }
+  else
+  {
+    // we have a single file
+	if (debug) print("file: + \'" + arguments[i] + "\'");
+
+	FileList.push(String(arguments[i]));
+  }
+}
+
+// first handle the single files
+for (var i in FileList)
+  processJSFile(FileList[i],null);
+
+// then handle the input directories
+for (var j in DirList) {
+  var inputdir = String(DirList[j]);
+
+  print("Process input directory: " + inputdir);
+
+  // clean up index arrays
+  var indexFileArray = [];
+  var indexFunctionArray = [];
+
+  // for the directory name get rid of ../../ or ..\..\
+  inputDirName = inputdir.replace(/\.\.\/|\.\.\\/g,"");
+
+  indexFile = indexFileName + "_" + inputDirName + ".html";
+  indexFunction = indexFunctionName + "_" + inputDirName + ".html";
+
+print("indexFile = " + indexFile);
+print("indexFunction = " + indexFunction);
+
+  // read the files in the directory
+  var DirFile = new java.io.File(inputdir);
+  var lst = DirFile.list();
+  var separator = Packages.java.io.File.separator;
+
+  for (var i=0; i < lst.length; i++)
+  {
+    processJSFile(String(lst[i]),inputdir);
+  }
+
+  // generate the index files for the input directory
+  GenerateIndex(inputDirName);
+}
+
+
+
diff -pruN 20130227+dfsg1-14/rhino/examples/liveConnect.js 20130227+rhino-1/rhino/examples/liveConnect.js
--- 20130227+dfsg1-14/rhino/examples/liveConnect.js	1970-01-01 00:00:00.000000000 +0000
+++ 20130227+rhino-1/rhino/examples/liveConnect.js	2023-05-25 14:24:50.000000000 +0000
@@ -0,0 +1,25 @@
+/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/**
+ * liveConnect.js: a simple demonstration of JavaScript-to-Java connectivity
+ */
+
+// Create a new StringBuffer. Note that the class name must be fully qualified
+// by its package. Packages other than "java" must start with "Packages", i.e.,
+// "Packages.javax.servlet...".
+var sb = new java.lang.StringBuffer();
+
+// Now add some stuff to the buffer.
+sb.append("hi, mom");
+sb.append(3);	// this will add "3.0" to the buffer since all JS numbers
+		// are doubles by default
+sb.append(true);
+
+// Now print it out. (The toString() method of sb is automatically called
+// to convert the buffer to a string.)
+// Should print "hi, mom3.0true".
+print(sb);
diff -pruN 20130227+dfsg1-14/rhino/examples/unique.js 20130227+rhino-1/rhino/examples/unique.js
--- 20130227+dfsg1-14/rhino/examples/unique.js	1970-01-01 00:00:00.000000000 +0000
+++ 20130227+rhino-1/rhino/examples/unique.js	2023-05-25 14:24:50.000000000 +0000
@@ -0,0 +1,24 @@
+/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// unique.js: read the contents of a file and print out the unique lines
+
+defineClass("File")
+
+// "arguments[0]" refers to the first argument at the command line to the
+// script, if present. If not present, "arguments[0]" will be undefined,
+// which will cause f to read from System.in.
+var f = new File(arguments[0]);
+var o = {}
+var line;
+while ((line = f.readLine()) != null) {
+	// Use JavaScript objects' inherent nature as an associative
+	// array to provide uniqueness
+	o[line] = true;
+}
+for (i in o) {
+	print(i);
+}
diff -pruN 20130227+dfsg1-14/rhino/gradle.properties 20130227+rhino-1/rhino/gradle.properties
--- 20130227+dfsg1-14/rhino/gradle.properties	1970-01-01 00:00:00.000000000 +0000
+++ 20130227+rhino-1/rhino/gradle.properties	2023-05-25 14:24:50.000000000 +0000
@@ -0,0 +1,7 @@
+#Sun, 26 Apr 2015 10:43:55 +0300
+rootProject.name=rhino
+group=org.mozilla
+version=1.7.7.2
+buildDir=buildGradle
+mavenSnapshotRepo=https://oss.sonatype.org/content/repositories/snapshots
+mavenReleaseRepo=https://oss.sonatype.org/service/local/staging/deploy/maven
diff -pruN 20130227+dfsg1-14/rhino/man/rhino.1 20130227+rhino-1/rhino/man/rhino.1
--- 20130227+dfsg1-14/rhino/man/rhino.1	1970-01-01 00:00:00.000000000 +0000
+++ 20130227+rhino-1/rhino/man/rhino.1	2023-05-25 14:24:50.000000000 +0000
@@ -0,0 +1,91 @@
+.\"                                      Hey, EMACS: -*- nroff -*-
+.\" First parameter, NAME, should be all caps
+.\" Second parameter, SECTION, should be 1-8, maybe w/ subsection
+.\" other parameters are allowed: see man(7), man(1)
+.TH RHINO 1 "February  12, 2005"
+.\" Please adjust this date whenever revising the manpage.
+.\"
+.\" Some roff macros, for reference:
+.\" .nh        disable hyphenation
+.\" .hy        enable hyphenation
+.\" .ad l      left justify
+.\" .ad b      justify to both left and right margins
+.\" .nf        disable filling
+.\" .fi        enable filling
+.\" .br        insert line break
+.\" .sp <n>    insert n+1 empty lines
+.\" for manpage-specific macros, see man(7)
+.SH NAME
+rhino \- invokes the JavaScript shell for running scripts in batch mode or interactive
+
+.SH SYNOPSIS
+.B rhino
+.I [options]
+.I script_filename_or_url
+.I [script_arguments]
+
+.SH DESCRIPTION
+This manual page documents briefly the
+.B rhino
+command.
+.PP
+.\" TeX users may be more comfortable with the \fB<whatever>\fP and
+.\" \fI<whatever>\fP escape sequences to invode bold face and italics, 
+.\" respectively.
+\fBrhino\fP is a start script for the rhino JavaScript shell which provides a simple way 
+to run scripts in batch mode or an interactive environment for exploratory programming.
+
+.SH OPTIONS
+
+.IP -e\ \fIscript_source\fP
+Executes script_source as a JavaScript script.
+.IP -f\ \fIscript_filename_or_url\fP
+Reads script_filename_or_url content and execute it as a JavaScript script.
+.IP -opt,\ -O\ \fIoptLevel\fP
+Optimizes at level optLevel, which must be an integer between 0 and 9. 
+.IP -version\ \fIversionNumber\fP
+Specifies the language version to compile with. The string versionNumber must be one of 100, 110, 120, 130, or 140. See JavaScript Language Versions for more information on language versions. 
+
+.SH PREDEFINED PROPERTIES
+
+Scripts executing in the shell have access to some additional properties of the top-level object.
+
+.IP arguments
+The arguments object is an array containing the strings of all the arguments given at the command line when the shell was invoked.
+.IP help()
+Executing the help function will print usage and help messages.
+.IP defineClass(\fIclassName\fP)
+Define an extension using the Java class named with the string argument className. Uses ScriptableObject.defineClass() to define the extension.
+.IP deserialize(\fIfilename\fP)
+Restore from the specified file an object previously written by a call to serialize.
+.IP load(\fI[filename,\&.\&.\&.]\fP)
+Load JavaScript source files named by string arguments. If multiple arguments are given, each file is read in and executed in turn.
+.IP loadClass(\fIclassName\fP)
+Load and execute the class named by the string argument className. The class must be a class that implements the Script interface, as will any script compiled by jsc.
+.IP print(\fI[expr\&.\&.\&.]\fP)
+Evaluate and print expressions. Evaluates each expression, converts the result to a string, and prints it.
+.IP readFile(\fIpath[,characterCoding]\fP)
+Read given file and convert its bytes to a string using the specified character coding or default character coding if explicit coding argument is not given.
+.IP readUrl(\fIurl[,characterCoding]\fP)
+Open an input connection to the given string url, read all its bytes and convert them to a string using the specified character coding or default character coding if explicit coding argument is not given.
+.IP runCommand(\fIcommandName,[arg,\&.\&.\&.][options]\fP)
+Execute the specified command with the given argument and options as a separate process and return the exit status of the process. For details, see JavaDoc for org.mozilla.javascript.tools.shell.Global#runCommand.
+.IP serialize(\fIobject,filename\fP)
+Serialize the given object to the specified file.
+.IP spawn(\fIfunctionOrScript\fP)
+Run the given function or script in a different thread.
+.IP sync(\fIfunction\fP)
+creates a synchronized function (in the sense of a Java synchronized method) from an existing function. The new function synchronizes on the this object of its invocation.
+.IP quit()
+Quit shell. The shell will also quit in interactive mode if an end-of-file character is typed at the prompt.
+.IP version(\fI[number]\fP)
+Get or set JavaScript version number. If no argument is supplied, the current version number is returned. If an argument is supplied, it is expected to be one of 100, 110, 120, 130, or 140 to indicate JavaScript version 1.0, 1.1, 1.2, 1.3, or 1.4 respectively.
+
+.SH SEE ALSO
+The online documentation under
+.UR http://www.mozilla.org/rhino/shell.html
+.I http://www.mozilla.org/rhino/shell.html
+.UE
+
+.SH AUTHOR
+This manual page was written by Wolfgang Baer <WBaer@gmx.de>.
diff -pruN 20130227+dfsg1-14/rhino/maven/maven-pom.xml 20130227+rhino-1/rhino/maven/maven-pom.xml
--- 20130227+dfsg1-14/rhino/maven/maven-pom.xml	1970-01-01 00:00:00.000000000 +0000
+++ 20130227+rhino-1/rhino/maven/maven-pom.xml	2023-05-25 14:24:50.000000000 +0000
@@ -0,0 +1,41 @@
+<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
+         xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+    <groupId>org.sonatype.oss</groupId>
+    <artifactId>oss-parent</artifactId>
+    <version>7</version>
+  </parent>
+
+  <groupId>org.mozilla</groupId>
+  <artifactId>rhino</artifactId>
+  <name>Mozilla Rhino</name>
+  <version>1.7.7.1</version>
+
+  <packaging>jar</packaging>
+  <description>
+      Rhino is an open-source implementation of JavaScript written entirely in Java. It is typically
+      embedded into Java applications to provide scripting to end users.
+  </description>
+  <url>https://developer.mozilla.org/en/Rhino</url>
+
+  <licenses>
+    <license>
+      <name>Mozilla Public License, Version 2.0</name>
+      <url>http://www.mozilla.org/MPL/2.0/index.txt</url>
+    </license>
+  </licenses>
+
+  <scm>
+    <connection>scm:git:git@github.com:mozilla/rhino.git</connection>
+    <developerConnection>scm:git:git@github.com:mozilla/rhino.git</developerConnection>
+    <url>git@github.com:mozilla/rhino.git</url>
+  </scm>
+
+  <organization>
+    <name>The Mozilla Foundation</name>
+    <url>http://www.mozilla.org</url>
+  </organization>
+</project>
diff -pruN 20130227+dfsg1-14/rhino/maven/maven-snapshot-deploy.sh 20130227+rhino-1/rhino/maven/maven-snapshot-deploy.sh
--- 20130227+dfsg1-14/rhino/maven/maven-snapshot-deploy.sh	1970-01-01 00:00:00.000000000 +0000
+++ 20130227+rhino-1/rhino/maven/maven-snapshot-deploy.sh	2023-05-25 14:24:50.000000000 +0000
@@ -0,0 +1,15 @@
+#!/bin/sh
+
+deployFile=`ls ../buildGradle/libs/rhino*.jar`
+
+if [ ! -f $deployFile ]
+then
+  echo "File cannot be found in $deployFile"
+  exit 2
+fi
+
+mvn deploy:deploy-file \
+  -Dfile=${deployFile} \
+  -DpomFile=maven-pom.xml \
+  -DrepositoryId=sonatype-nexus-snapshots \
+  -Durl=https://oss.sonatype.org/content/repositories/snapshots/
diff -pruN 20130227+dfsg1-14/rhino/maven/maven-staging-deploy.sh 20130227+rhino-1/rhino/maven/maven-staging-deploy.sh
--- 20130227+dfsg1-14/rhino/maven/maven-staging-deploy.sh	1970-01-01 00:00:00.000000000 +0000
+++ 20130227+rhino-1/rhino/maven/maven-staging-deploy.sh	2023-05-25 14:24:50.000000000 +0000
@@ -0,0 +1,51 @@
+#!/bin/sh
+
+vers=`egrep '^version:' ../build.properties | awk '{print $2}'`
+
+echo "Deploying ${vers}"
+
+pom=maven-pom.xml
+jsjar=../buildGradle/libs/rhino-${vers}.jar
+echo "Installing ${jsjar}"
+srczip=../buildGradle/libs/rhino-${vers}-sources.jar
+echo "Sources are ${srczip}"
+doczip=../buildGradle/libs/rhino-${vers}-javadoc.jar
+echo "Javadoc is ${doczip}"
+
+if [ ! -f $jsjar ]
+then
+  echo "Missing js.jar"
+  exit 1
+fi
+
+if [ ! -f $srczip ]
+then
+  echo "Missing rhino-${vers}-sources.zip. Run \"ant source-zip\"."
+  exit 2
+fi
+
+if [ ! -f $doczip ]
+then
+  echo "Missing javadoc.zip. Run \"ant javadoc\"."
+  exit 3
+fi
+
+mvn gpg:sign-and-deploy-file \
+  -Dfile=${jsjar} \
+  -DpomFile=${pom} \
+  -DrepositoryId=sonatype-nexus-staging \
+  -Durl=https://oss.sonatype.org/service/local/staging/deploy/maven2/ 
+
+mvn gpg:sign-and-deploy-file \
+  -Dfile=${srczip} \
+  -DpomFile=${pom} \
+  -DrepositoryId=sonatype-nexus-staging \
+  -Durl=https://oss.sonatype.org/service/local/staging/deploy/maven2/  \
+  -Dclassifier=sources
+
+mvn gpg:sign-and-deploy-file \
+  -Dfile=${doczip} \
+  -DpomFile=${pom} \
+  -DrepositoryId=sonatype-nexus-staging \
+  -Durl=https://oss.sonatype.org/service/local/staging/deploy/maven2/  \
+  -Dclassifier=javadoc
diff -pruN 20130227+dfsg1-14/rhino/release-steps.txt 20130227+rhino-1/rhino/release-steps.txt
--- 20130227+dfsg1-14/rhino/release-steps.txt	1970-01-01 00:00:00.000000000 +0000
+++ 20130227+rhino-1/rhino/release-steps.txt	2023-05-25 14:24:50.000000000 +0000
@@ -0,0 +1,37 @@
+Update version in:
+	src/manifest
+	build.properties
+	gradle.properties
+	maven/maven-pom.xml
+
+Paste release notes into RELEASE_NOTES.md:
+	git shortlog LAST_TAG.. | sed 's/^ /*/'
+
+Paste release info into README.md
+	Copy README into gh-pages
+	Extract build/*/javadoc.zip to gh-pages/javadoc
+
+Re-run compat-table "engine.js"
+	Copy HTML to gh-pages/compat
+
+./gradlew publishToMavenLocal distZip 
+cd maven
+./maven-staging-deploy.sh
+
+Go to oss.sonatype.org
+	Find "org.mozilla" staging repo, close, release, and drop.
+
+git tag for new release
+
+Update release in GitHub
+	Paste release notes, upload "rhinoXXX.zip" and "js.jar"
+
+Update to new snapshot version in:
+	src/manifest
+	build.properties
+	gradle.properties
+	maven/maven-pom.xml
+
+Update the Homebrew formula. Submit a PR for:
+	Homebrew/homebrew
+		Library/Formula/rhino.rb
diff -pruN 20130227+dfsg1-14/rhino/src/build.xml 20130227+rhino-1/rhino/src/build.xml
--- 20130227+dfsg1-14/rhino/src/build.xml	1970-01-01 00:00:00.000000000 +0000
+++ 20130227+rhino-1/rhino/src/build.xml	2023-05-25 14:24:50.000000000 +0000
@@ -0,0 +1,76 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- This Source Code Form is subject to the terms of the Mozilla Public
+   - License, v. 2.0. If a copy of the MPL was not distributed with this
+   - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
+
+
+<!--
+Build file for Rhino using Ant (see http://jakarta.apache.org/ant/index.html)
+Requires Ant version 1.2
+-->
+<project name="src" default="compile" basedir="..">
+
+  <property file="build.properties"/>
+
+  <available property="jdk15"
+             classname="java.lang.reflect.ParameterizedType" />
+
+  <target name="compile" depends="compile-most,compile-jdk15">
+  </target>
+
+  <target name="shell" depends="compile">
+    <java classname="org.mozilla.javascript.tools.shell.Main"
+          classpath="${classes}"
+          fork="true">
+      <arg line="-version 170"/>
+    </java>
+  </target>
+
+  <target name="compile-most">
+    <javac srcdir="src"
+           destdir="${classes}"
+           includes="org/**/*.java"
+           excludes="org/**/jdk15/*.java"
+           deprecation="on"
+           debug="${debug}"
+           includeAntRuntime="false"
+           encoding="UTF-8"
+           target="${target-jvm}"
+           source="${source-level}" />
+    <copy todir="${classes}">
+      <fileset dir="src" includes="org/**/*.properties" />
+      <filterset>
+      <filter token="IMPLEMENTATION.VERSION"
+              value="${implementation.version}"/>
+      </filterset>
+    </copy>
+  </target>
+
+  <target name="compile-jdk15" if="jdk15">
+    <javac srcdir="src"
+           destdir="${classes}"
+           includes="org/**/jdk15/*.java"
+           deprecation="on"
+           debug="${debug}"
+           includeAntRuntime="false"
+           encoding="UTF-8"
+           target="${target-jvm}"
+           source="${source-level}" />
+  </target>
+
+  <target name="copy-source">
+    <mkdir dir="${dist.dir}/src"/>
+    <copy todir="${dist.dir}/src">
+      <fileset dir="src"
+               includes="**/*.java,**/*.properties,**/*.xml,manifest"/>
+    </copy>
+  </target>
+
+  <target name="clean">
+    <delete includeEmptyDirs="true">
+      <fileset dir="${classes}"
+               excludes="org/mozilla/javascript/tools/**"/>
+    </delete>
+  </target>
+
+</project>
diff -pruN 20130227+dfsg1-14/rhino/src/manifest 20130227+rhino-1/rhino/src/manifest
--- 20130227+dfsg1-14/rhino/src/manifest	1970-01-01 00:00:00.000000000 +0000
+++ 20130227+rhino-1/rhino/src/manifest	2023-05-25 14:24:50.000000000 +0000
@@ -0,0 +1,6 @@
+Manifest-Version: 1.0
+Main-Class: org.mozilla.javascript.tools.shell.Main
+Implementation-Version: 1.7.7.2
+Implementation-Title: Mozilla Rhino 1.7.7.2
+Implementation-Vendor: Mozilla Foundation
+Implementation-URL: http://www.mozilla.org/rhino
diff -pruN 20130227+dfsg1-14/rhino/src/org/mozilla/classfile/ByteCode.java 20130227+rhino-1/rhino/src/org/mozilla/classfile/ByteCode.java
--- 20130227+dfsg1-14/rhino/src/org/mozilla/classfile/ByteCode.java	1970-01-01 00:00:00.000000000 +0000
+++ 20130227+rhino-1/rhino/src/org/mozilla/classfile/ByteCode.java	2023-05-25 14:24:50.000000000 +0000
@@ -0,0 +1,242 @@
+/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+package org.mozilla.classfile;
+
+/**
+ * This class provides opcode values expected by the JVM in Java class files.
+ *
+ * It also provides tables for internal use by the ClassFileWriter.
+ *
+ * @author Roger Lawrence
+ */
+public class ByteCode {
+
+    /**
+     * The byte opcodes defined by the Java Virtual Machine.
+     */
+    public static final int
+        NOP = 0x00,
+        ACONST_NULL = 0x01,
+        ICONST_M1 = 0x02,
+        ICONST_0 = 0x03,
+        ICONST_1 = 0x04,
+        ICONST_2 = 0x05,
+        ICONST_3 = 0x06,
+        ICONST_4 = 0x07,
+        ICONST_5 = 0x08,
+        LCONST_0 = 0x09,
+        LCONST_1 = 0x0A,
+        FCONST_0 = 0x0B,
+        FCONST_1 = 0x0C,
+        FCONST_2 = 0x0D,
+        DCONST_0 = 0x0E,
+        DCONST_1 = 0x0F,
+        BIPUSH = 0x10,
+        SIPUSH = 0x11,
+        LDC = 0x12,
+        LDC_W = 0x13,
+        LDC2_W = 0x14,
+        ILOAD = 0x15,
+        LLOAD = 0x16,
+        FLOAD = 0x17,
+        DLOAD = 0x18,
+        ALOAD = 0x19,
+        ILOAD_0 = 0x1A,
+        ILOAD_1 = 0x1B,
+        ILOAD_2 = 0x1C,
+        ILOAD_3 = 0x1D,
+        LLOAD_0 = 0x1E,
+        LLOAD_1 = 0x1F,
+        LLOAD_2 = 0x20,
+        LLOAD_3 = 0x21,
+        FLOAD_0 = 0x22,
+        FLOAD_1 = 0x23,
+        FLOAD_2 = 0x24,
+        FLOAD_3 = 0x25,
+        DLOAD_0 = 0x26,
+        DLOAD_1 = 0x27,
+        DLOAD_2 = 0x28,
+        DLOAD_3 = 0x29,
+        ALOAD_0 = 0x2A,
+        ALOAD_1 = 0x2B,
+        ALOAD_2 = 0x2C,
+        ALOAD_3 = 0x2D,
+        IALOAD = 0x2E,
+        LALOAD = 0x2F,
+        FALOAD = 0x30,
+        DALOAD = 0x31,
+        AALOAD = 0x32,
+        BALOAD = 0x33,
+        CALOAD = 0x34,
+        SALOAD = 0x35,
+        ISTORE = 0x36,
+        LSTORE = 0x37,
+        FSTORE = 0x38,
+        DSTORE = 0x39,
+        ASTORE = 0x3A,
+        ISTORE_0 = 0x3B,
+        ISTORE_1 = 0x3C,
+        ISTORE_2 = 0x3D,
+        ISTORE_3 = 0x3E,
+        LSTORE_0 = 0x3F,
+        LSTORE_1 = 0x40,
+        LSTORE_2 = 0x41,
+        LSTORE_3 = 0x42,
+        FSTORE_0 = 0x43,
+        FSTORE_1 = 0x44,
+        FSTORE_2 = 0x45,
+        FSTORE_3 = 0x46,
+        DSTORE_0 = 0x47,
+        DSTORE_1 = 0x48,
+        DSTORE_2 = 0x49,
+        DSTORE_3 = 0x4A,
+        ASTORE_0 = 0x4B,
+        ASTORE_1 = 0x4C,
+        ASTORE_2 = 0x4D,
+        ASTORE_3 = 0x4E,
+        IASTORE = 0x4F,
+        LASTORE = 0x50,
+        FASTORE = 0x51,
+        DASTORE = 0x52,
+        AASTORE = 0x53,
+        BASTORE = 0x54,
+        CASTORE = 0x55,
+        SASTORE = 0x56,
+        POP = 0x57,
+        POP2 = 0x58,
+        DUP = 0x59,
+        DUP_X1 = 0x5A,
+        DUP_X2 = 0x5B,
+        DUP2 = 0x5C,
+        DUP2_X1 = 0x5D,
+        DUP2_X2 = 0x5E,
+        SWAP = 0x5F,
+        IADD = 0x60,
+        LADD = 0x61,
+        FADD = 0x62,
+        DADD = 0x63,
+        ISUB = 0x64,
+        LSUB = 0x65,
+        FSUB = 0x66,
+        DSUB = 0x67,
+        IMUL = 0x68,
+        LMUL = 0x69,
+        FMUL = 0x6A,
+        DMUL = 0x6B,
+        IDIV = 0x6C,
+        LDIV = 0x6D,
+        FDIV = 0x6E,
+        DDIV = 0x6F,
+        IREM = 0x70,
+        LREM = 0x71,
+        FREM = 0x72,
+        DREM = 0x73,
+        INEG = 0x74,
+        LNEG = 0x75,
+        FNEG = 0x76,
+        DNEG = 0x77,
+        ISHL = 0x78,
+        LSHL = 0x79,
+        ISHR = 0x7A,
+        LSHR = 0x7B,
+        IUSHR = 0x7C,
+        LUSHR = 0x7D,
+        IAND = 0x7E,
+        LAND = 0x7F,
+        IOR = 0x80,
+        LOR = 0x81,
+        IXOR = 0x82,
+        LXOR = 0x83,
+        IINC = 0x84,
+        I2L = 0x85,
+        I2F = 0x86,
+        I2D = 0x87,
+        L2I = 0x88,
+        L2F = 0x89,
+        L2D = 0x8A,
+        F2I = 0x8B,
+        F2L = 0x8C,
+        F2D = 0x8D,
+        D2I = 0x8E,
+        D2L = 0x8F,
+        D2F = 0x90,
+        I2B = 0x91,
+        I2C = 0x92,
+        I2S = 0x93,
+        LCMP = 0x94,
+        FCMPL = 0x95,
+        FCMPG = 0x96,
+        DCMPL = 0x97,
+        DCMPG = 0x98,
+        IFEQ = 0x99,
+        IFNE = 0x9A,
+        IFLT = 0x9B,
+        IFGE = 0x9C,
+        IFGT = 0x9D,
+        IFLE = 0x9E,
+        IF_ICMPEQ = 0x9F,
+        IF_ICMPNE = 0xA0,
+        IF_ICMPLT = 0xA1,
+        IF_ICMPGE = 0xA2,
+        IF_ICMPGT = 0xA3,
+        IF_ICMPLE = 0xA4,
+        IF_ACMPEQ = 0xA5,
+        IF_ACMPNE = 0xA6,
+        GOTO = 0xA7,
+        JSR = 0xA8,
+        RET = 0xA9,
+        TABLESWITCH = 0xAA,
+        LOOKUPSWITCH = 0xAB,
+        IRETURN = 0xAC,
+        LRETURN = 0xAD,
+        FRETURN = 0xAE,
+        DRETURN = 0xAF,
+        ARETURN = 0xB0,
+        RETURN = 0xB1,
+        GETSTATIC = 0xB2,
+        PUTSTATIC = 0xB3,
+        GETFIELD = 0xB4,
+        PUTFIELD = 0xB5,
+        INVOKEVIRTUAL = 0xB6,
+        INVOKESPECIAL = 0xB7,
+        INVOKESTATIC = 0xB8,
+        INVOKEINTERFACE = 0xB9,
+        NEW = 0xBB,
+        NEWARRAY = 0xBC,
+        ANEWARRAY = 0xBD,
+        ARRAYLENGTH = 0xBE,
+        ATHROW = 0xBF,
+        CHECKCAST = 0xC0,
+        INSTANCEOF = 0xC1,
+        MONITORENTER = 0xC2,
+        MONITOREXIT = 0xC3,
+        WIDE = 0xC4,
+        MULTIANEWARRAY = 0xC5,
+        IFNULL = 0xC6,
+        IFNONNULL = 0xC7,
+        GOTO_W = 0xC8,
+        JSR_W = 0xC9,
+        BREAKPOINT = 0xCA,
+
+        IMPDEP1 = 0xFE,
+        IMPDEP2 = 0xFF;
+
+        /**
+         * Types for the NEWARRAY opcode.
+         */
+        public static final byte
+            T_BOOLEAN = 4,
+            T_CHAR = 5,
+            T_FLOAT = 6,
+            T_DOUBLE = 7,
+            T_BYTE = 8,
+            T_SHORT = 9,
+            T_INT = 10,
+            T_LONG = 11;
+
+
+}
diff -pruN 20130227+dfsg1-14/rhino/src/org/mozilla/classfile/ClassFileWriter.java 20130227+rhino-1/rhino/src/org/mozilla/classfile/ClassFileWriter.java
--- 20130227+dfsg1-14/rhino/src/org/mozilla/classfile/ClassFileWriter.java	1970-01-01 00:00:00.000000000 +0000
+++ 20130227+rhino-1/rhino/src/org/mozilla/classfile/ClassFileWriter.java	2023-05-25 14:24:50.000000000 +0000
@@ -0,0 +1,5198 @@
+/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+package org.mozilla.classfile;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import org.mozilla.javascript.ObjToIntMap;
+import org.mozilla.javascript.ObjArray;
+import org.mozilla.javascript.UintMap;
+
+import java.util.Arrays;
+
+/**
+ * ClassFileWriter
+ *
+ * A ClassFileWriter is used to write a Java class file. Methods are
+ * provided to create fields and methods, and within methods to write
+ * Java bytecodes.
+ *
+ * @author Roger Lawrence
+ */
+public class ClassFileWriter {
+
+    /**
+     * Thrown for cases where the error in generating the class file is
+     * due to a program size constraints rather than a likely bug in the
+     * compiler.
+     */
+    public static class ClassFileFormatException extends RuntimeException {
+
+        private static final long serialVersionUID = 1263998431033790599L;
+
+        ClassFileFormatException(String message) {
+            super(message);
+        }
+    }
+
+    /**
+     * Construct a ClassFileWriter for a class.
+     *
+     * @param className the name of the class to write, including
+     *        full package qualification.
+     * @param superClassName the name of the superclass of the class
+     *        to write, including full package qualification.
+     * @param sourceFileName the name of the source file to use for
+     *        producing debug information, or null if debug information
+     *        is not desired
+     */
+    public ClassFileWriter(String className, String superClassName,
+                           String sourceFileName)
+    {
+        generatedClassName = className;
+        itsConstantPool = new ConstantPool(this);
+        itsThisClassIndex = itsConstantPool.addClass(className);
+        itsSuperClassIndex = itsConstantPool.addClass(superClassName);
+        if (sourceFileName != null)
+            itsSourceFileNameIndex = itsConstantPool.addUtf8(sourceFileName);
+        // All "new" implementations are supposed to output ACC_SUPER as a
+        // class flag. This is specified in the first JVM spec, so it should
+        // be old enough that it's okay to always set it.
+        itsFlags = ACC_PUBLIC | ACC_SUPER;
+    }
+
+    public final String getClassName()
+    {
+        return generatedClassName;
+    }
+
+    /**
+     * Add an interface implemented by this class.
+     *
+     * This method may be called multiple times for classes that
+     * implement multiple interfaces.
+     *
+     * @param interfaceName a name of an interface implemented
+     *        by the class being written, including full package
+     *        qualification.
+     */
+    public void addInterface(String interfaceName) {
+        short interfaceIndex = itsConstantPool.addClass(interfaceName);
+        itsInterfaces.add(Short.valueOf(interfaceIndex));
+    }
+
+    public static final short
+        ACC_PUBLIC = 0x0001,
+        ACC_PRIVATE = 0x0002,
+        ACC_PROTECTED = 0x0004,
+        ACC_STATIC = 0x0008,
+        ACC_FINAL = 0x0010,
+        ACC_SUPER = 0x0020,
+        ACC_SYNCHRONIZED = 0x0020,
+        ACC_VOLATILE = 0x0040,
+        ACC_TRANSIENT = 0x0080,
+        ACC_NATIVE = 0x0100,
+        ACC_ABSTRACT = 0x0400;
+
+    /**
+     * Set the class's flags.
+     *
+     * Flags must be a set of the following flags, bitwise or'd
+     * together:
+     *      ACC_PUBLIC
+     *      ACC_PRIVATE
+     *      ACC_PROTECTED
+     *      ACC_FINAL
+     *      ACC_ABSTRACT
+     * TODO: check that this is the appropriate set
+     * @param flags the set of class flags to set
+     */
+    public void setFlags(short flags) {
+        itsFlags = flags;
+    }
+
+    static String getSlashedForm(String name)
+    {
+        return name.replace('.', '/');
+    }
+
+    /**
+     * Convert Java class name in dot notation into
+     * "Lname-with-dots-replaced-by-slashes;" form suitable for use as
+     * JVM type signatures.
+     */
+    public static String classNameToSignature(String name)
+    {
+        int nameLength = name.length();
+        int colonPos = 1 + nameLength;
+        char[] buf = new char[colonPos + 1];
+        buf[0] = 'L';
+        buf[colonPos] = ';';
+        name.getChars(0, nameLength, buf, 1);
+        for (int i = 1; i != colonPos; ++i) {
+            if (buf[i] == '.') {
+                buf[i] = '/';
+            }
+        }
+        return new String(buf, 0, colonPos + 1);
+    }
+
+    /**
+     * Add a field to the class.
+     *
+     * @param fieldName the name of the field
+     * @param type the type of the field using ...
+     * @param flags the attributes of the field, such as ACC_PUBLIC, etc.
+     *        bitwise or'd together
+     */
+    public void addField(String fieldName, String type, short flags) {
+        short fieldNameIndex = itsConstantPool.addUtf8(fieldName);
+        short typeIndex = itsConstantPool.addUtf8(type);
+        itsFields.add(new ClassFileField(fieldNameIndex, typeIndex, flags));
+    }
+
+    /**
+     * Add a field to the class.
+     *
+     * @param fieldName the name of the field
+     * @param type the type of the field using ...
+     * @param flags the attributes of the field, such as ACC_PUBLIC, etc.
+     *        bitwise or'd together
+     * @param value an initial integral value
+     */
+    public void addField(String fieldName, String type, short flags,
+                         int value)
+    {
+        short fieldNameIndex = itsConstantPool.addUtf8(fieldName);
+        short typeIndex = itsConstantPool.addUtf8(type);
+        ClassFileField field = new ClassFileField(fieldNameIndex, typeIndex,
+                                                  flags);
+        field.setAttributes(itsConstantPool.addUtf8("ConstantValue"),
+                            (short)0,
+                            (short)0,
+                            itsConstantPool.addConstant(value));
+        itsFields.add(field);
+    }
+
+    /**
+     * Add a field to the class.
+     *
+     * @param fieldName the name of the field
+     * @param type the type of the field using ...
+     * @param flags the attributes of the field, such as ACC_PUBLIC, etc.
+     *        bitwise or'd together
+     * @param value an initial long value
+     */
+    public void addField(String fieldName, String type, short flags,
+                         long value)
+    {
+        short fieldNameIndex = itsConstantPool.addUtf8(fieldName);
+        short typeIndex = itsConstantPool.addUtf8(type);
+        ClassFileField field = new ClassFileField(fieldNameIndex, typeIndex,
+                                                  flags);
+        field.setAttributes(itsConstantPool.addUtf8("ConstantValue"),
+                            (short)0,
+                            (short)2,
+                            itsConstantPool.addConstant(value));
+        itsFields.add(field);
+    }
+
+    /**
+     * Add a field to the class.
+     *
+     * @param fieldName the name of the field
+     * @param type the type of the field using ...
+     * @param flags the attributes of the field, such as ACC_PUBLIC, etc.
+     *        bitwise or'd together
+     * @param value an initial double value
+     */
+    public void addField(String fieldName, String type, short flags,
+                         double value)
+    {
+        short fieldNameIndex = itsConstantPool.addUtf8(fieldName);
+        short typeIndex = itsConstantPool.addUtf8(type);
+        ClassFileField field = new ClassFileField(fieldNameIndex, typeIndex,
+                                                  flags);
+        field.setAttributes(itsConstantPool.addUtf8("ConstantValue"),
+                            (short)0,
+                            (short)2,
+                            itsConstantPool.addConstant(value));
+        itsFields.add(field);
+    }
+
+    /**
+     * Add Information about java variable to use when generating the local
+     * variable table.
+     *
+     * @param name variable name.
+     * @param type variable type as bytecode descriptor string.
+     * @param startPC the starting bytecode PC where this variable is live,
+     *                 or -1 if it does not have a Java register.
+     * @param register the Java register number of variable
+     *                 or -1 if it does not have a Java register.
+     */
+    public void addVariableDescriptor(String name, String type, int startPC, int register)
+    {
+        int nameIndex = itsConstantPool.addUtf8(name);
+        int descriptorIndex = itsConstantPool.addUtf8(type);
+        int [] chunk = { nameIndex, descriptorIndex, startPC, register };
+        if (itsVarDescriptors == null) {
+            itsVarDescriptors = new ObjArray();
+        }
+        itsVarDescriptors.add(chunk);
+    }
+
+    /**
+     * Add a method and begin adding code.
+     *
+     * This method must be called before other methods for adding code,
+     * exception tables, etc. can be invoked.
+     *
+     * @param methodName the name of the method
+     * @param type a string representing the type
+     * @param flags the attributes of the field, such as ACC_PUBLIC, etc.
+     *        bitwise or'd together
+     */
+    public void startMethod(String methodName, String type, short flags) {
+        short methodNameIndex = itsConstantPool.addUtf8(methodName);
+        short typeIndex = itsConstantPool.addUtf8(type);
+        itsCurrentMethod = new ClassFileMethod(methodName, methodNameIndex,
+                                               type, typeIndex, flags);
+        itsJumpFroms = new UintMap();
+        itsMethods.add(itsCurrentMethod);
+        addSuperBlockStart(0);
+    }
+
+    /**
+     * Complete generation of the method.
+     *
+     * After this method is called, no more code can be added to the
+     * method begun with <code>startMethod</code>.
+     *
+     * @param maxLocals the maximum number of local variable slots
+     *        (a.k.a. Java registers) used by the method
+     */
+    public void stopMethod(short maxLocals) {
+        if (itsCurrentMethod == null)
+            throw new IllegalStateException("No method to stop");
+
+        fixLabelGotos();
+
+        itsMaxLocals = maxLocals;
+
+        StackMapTable stackMap = null;
+        if (GenerateStackMap) {
+            finalizeSuperBlockStarts();
+            stackMap = new StackMapTable();
+            stackMap.generate();
+        }
+
+        int lineNumberTableLength = 0;
+        if (itsLineNumberTable != null) {
+            // 6 bytes for the attribute header
+            // 2 bytes for the line number count
+            // 4 bytes for each entry
+            lineNumberTableLength = 6 + 2 + (itsLineNumberTableTop * 4);
+        }
+
+        int variableTableLength = 0;
+        if (itsVarDescriptors != null) {
+            // 6 bytes for the attribute header
+            // 2 bytes for the variable count
+            // 10 bytes for each entry
+            variableTableLength = 6 + 2 + (itsVarDescriptors.size() * 10);
+        }
+
+        int stackMapTableLength = 0;
+        if (stackMap != null) {
+            int stackMapWriteSize = stackMap.computeWriteSize();
+            if (stackMapWriteSize > 0) {
+                stackMapTableLength = 6 + stackMapWriteSize;
+            }
+        }
+
+        int attrLength = 2 +                    // attribute_name_index
+                         4 +                    // attribute_length
+                         2 +                    // max_stack
+                         2 +                    // max_locals
+                         4 +                    // code_length
+                         itsCodeBufferTop +
+                         2 +                    // exception_table_length
+                         (itsExceptionTableTop * 8) +
+                         2 +                    // attributes_count
+                         lineNumberTableLength +
+                         variableTableLength +
+                         stackMapTableLength;
+
+        if (attrLength > 65536) {
+            // See http://java.sun.com/docs/books/jvms/second_edition/html/ClassFile.doc.html,
+            // section 4.10, "The amount of code per non-native, non-abstract
+            // method is limited to 65536 bytes...
+            throw new ClassFileFormatException(
+                "generated bytecode for method exceeds 64K limit.");
+        }
+        byte[] codeAttribute = new byte[attrLength];
+        int index = 0;
+        int codeAttrIndex = itsConstantPool.addUtf8("Code");
+        index = putInt16(codeAttrIndex, codeAttribute, index);
+        attrLength -= 6;                 // discount the attribute header
+        index = putInt32(attrLength, codeAttribute, index);
+        index = putInt16(itsMaxStack, codeAttribute, index);
+        index = putInt16(itsMaxLocals, codeAttribute, index);
+        index = putInt32(itsCodeBufferTop, codeAttribute, index);
+        System.arraycopy(itsCodeBuffer, 0, codeAttribute, index,
+                         itsCodeBufferTop);
+        index += itsCodeBufferTop;
+
+        if (itsExceptionTableTop > 0) {
+            index = putInt16(itsExceptionTableTop, codeAttribute, index);
+            for (int i = 0; i < itsExceptionTableTop; i++) {
+                ExceptionTableEntry ete = itsExceptionTable[i];
+                short startPC = (short)getLabelPC(ete.itsStartLabel);
+                short endPC = (short)getLabelPC(ete.itsEndLabel);
+                short handlerPC = (short)getLabelPC(ete.itsHandlerLabel);
+                short catchType = ete.itsCatchType;
+                if (startPC == -1)
+                    throw new IllegalStateException("start label not defined");
+                if (endPC == -1)
+                    throw new IllegalStateException("end label not defined");
+                if (handlerPC == -1)
+                    throw new IllegalStateException(
+                        "handler label not defined");
+
+                index = putInt16(startPC, codeAttribute, index);
+                index = putInt16(endPC, codeAttribute, index);
+                index = putInt16(handlerPC, codeAttribute, index);
+                index = putInt16(catchType, codeAttribute, index);
+            }
+        }
+        else {
+            // write 0 as exception table length
+            index = putInt16(0, codeAttribute, index);
+        }
+
+        int attributeCount = 0;
+        if (itsLineNumberTable != null)
+            attributeCount++;
+        if (itsVarDescriptors != null)
+            attributeCount++;
+        if (stackMapTableLength > 0) {
+            attributeCount++;
+        }
+        index = putInt16(attributeCount, codeAttribute, index);
+
+        if (itsLineNumberTable != null) {
+            int lineNumberTableAttrIndex
+                    = itsConstantPool.addUtf8("LineNumberTable");
+            index = putInt16(lineNumberTableAttrIndex, codeAttribute, index);
+            int tableAttrLength = 2 + (itsLineNumberTableTop * 4);
+            index = putInt32(tableAttrLength, codeAttribute, index);
+            index = putInt16(itsLineNumberTableTop, codeAttribute, index);
+            for (int i = 0; i < itsLineNumberTableTop; i++) {
+                index = putInt32(itsLineNumberTable[i], codeAttribute, index);
+            }
+        }
+
+        if (itsVarDescriptors != null) {
+            int variableTableAttrIndex
+                    = itsConstantPool.addUtf8("LocalVariableTable");
+            index = putInt16(variableTableAttrIndex, codeAttribute, index);
+            int varCount = itsVarDescriptors.size();
+            int tableAttrLength = 2 + (varCount * 10);
+            index = putInt32(tableAttrLength, codeAttribute, index);
+            index = putInt16(varCount, codeAttribute, index);
+            for (int i = 0; i < varCount; i++) {
+                int[] chunk = (int[])itsVarDescriptors.get(i);
+                int nameIndex       = chunk[0];
+                int descriptorIndex = chunk[1];
+                int startPC         = chunk[2];
+                int register        = chunk[3];
+                int length = itsCodeBufferTop - startPC;
+
+                index = putInt16(startPC, codeAttribute, index);
+                index = putInt16(length, codeAttribute, index);
+                index = putInt16(nameIndex, codeAttribute, index);
+                index = putInt16(descriptorIndex, codeAttribute, index);
+                index = putInt16(register, codeAttribute, index);
+            }
+        }
+
+        if (stackMapTableLength > 0) {
+            int stackMapTableAttrIndex =
+                    itsConstantPool.addUtf8("StackMapTable");
+            int start = index;
+            index = putInt16(stackMapTableAttrIndex, codeAttribute, index);
+            index = stackMap.write(codeAttribute, index);
+        }
+
+        itsCurrentMethod.setCodeAttribute(codeAttribute);
+
+        itsExceptionTable = null;
+        itsExceptionTableTop = 0;
+        itsLineNumberTableTop = 0;
+        itsCodeBufferTop = 0;
+        itsCurrentMethod = null;
+        itsMaxStack = 0;
+        itsStackTop = 0;
+        itsLabelTableTop = 0;
+        itsFixupTableTop = 0;
+        itsVarDescriptors = null;
+        itsSuperBlockStarts = null;
+        itsSuperBlockStartsTop = 0;
+        itsJumpFroms = null;
+    }
+
+    /**
+     * Add the single-byte opcode to the current method.
+     *
+     * @param theOpCode the opcode of the bytecode
+     */
+    public void add(int theOpCode) {
+        if (opcodeCount(theOpCode) != 0)
+            throw new IllegalArgumentException("Unexpected operands");
+        int newStack = itsStackTop + stackChange(theOpCode);
+        if (newStack < 0 || Short.MAX_VALUE < newStack) badStack(newStack);
+        if (DEBUGCODE)
+            System.out.println("Add " + bytecodeStr(theOpCode));
+        addToCodeBuffer(theOpCode);
+        itsStackTop = (short)newStack;
+        if (newStack > itsMaxStack) itsMaxStack = (short)newStack;
+        if (DEBUGSTACK) {
+            System.out.println("After "+bytecodeStr(theOpCode)
+                               +" stack = "+itsStackTop);
+        }
+        if (theOpCode == ByteCode.ATHROW) {
+            addSuperBlockStart(itsCodeBufferTop);
+        }
+    }
+
+    /**
+     * Add a single-operand opcode to the current method.
+     *
+     * @param theOpCode the opcode of the bytecode
+     * @param theOperand the operand of the bytecode
+     */
+    public void add(int theOpCode, int theOperand) {
+        if (DEBUGCODE) {
+            System.out.println("Add "+bytecodeStr(theOpCode)
+                               +", "+Integer.toHexString(theOperand));
+        }
+        int newStack = itsStackTop + stackChange(theOpCode);
+        if (newStack < 0 || Short.MAX_VALUE < newStack) badStack(newStack);
+
+        switch (theOpCode) {
+            case ByteCode.GOTO :
+                // This is necessary because dead code is seemingly being
+                // generated and Sun's verifier is expecting type state to be
+                // placed even at dead blocks of code.
+                addSuperBlockStart(itsCodeBufferTop + 3);
+                // fallthru...
+            case ByteCode.IFEQ :
+            case ByteCode.IFNE :
+            case ByteCode.IFLT :
+            case ByteCode.IFGE :
+            case ByteCode.IFGT :
+            case ByteCode.IFLE :
+            case ByteCode.IF_ICMPEQ :
+            case ByteCode.IF_ICMPNE :
+            case ByteCode.IF_ICMPLT :
+            case ByteCode.IF_ICMPGE :
+            case ByteCode.IF_ICMPGT :
+            case ByteCode.IF_ICMPLE :
+            case ByteCode.IF_ACMPEQ :
+            case ByteCode.IF_ACMPNE :
+            case ByteCode.JSR :
+            case ByteCode.IFNULL :
+            case ByteCode.IFNONNULL : {
+                    if ((theOperand & 0x80000000) != 0x80000000) {
+                        if ((theOperand < 0) || (theOperand > 65535))
+                            throw new IllegalArgumentException(
+                                "Bad label for branch");
+                    }
+                    int branchPC = itsCodeBufferTop;
+                    addToCodeBuffer(theOpCode);
+                    if ((theOperand & 0x80000000) != 0x80000000) {
+                            // hard displacement
+                        addToCodeInt16(theOperand);
+                        int target = theOperand + branchPC;
+                        addSuperBlockStart(target);
+                        itsJumpFroms.put(target, branchPC);
+                    }
+                    else {  // a label
+                        int targetPC = getLabelPC(theOperand);
+                        if (DEBUGLABELS) {
+                            int theLabel = theOperand & 0x7FFFFFFF;
+                            System.out.println("Fixing branch to " +
+                                               theLabel + " at " + targetPC +
+                                               " from " + branchPC);
+                        }
+                        if (targetPC != -1) {
+                            int offset = targetPC - branchPC;
+                            addToCodeInt16(offset);
+                            addSuperBlockStart(targetPC);
+                            itsJumpFroms.put(targetPC, branchPC);
+                        }
+                        else {
+                            addLabelFixup(theOperand, branchPC + 1);
+                            addToCodeInt16(0);
+                        }
+                    }
+                }
+                break;
+
+            case ByteCode.BIPUSH :
+                if ((byte)theOperand != theOperand)
+                    throw new IllegalArgumentException("out of range byte");
+                addToCodeBuffer(theOpCode);
+                addToCodeBuffer((byte)theOperand);
+                break;
+
+            case ByteCode.SIPUSH :
+                if ((short)theOperand != theOperand)
+                    throw new IllegalArgumentException("out of range short");
+                addToCodeBuffer(theOpCode);
+                   addToCodeInt16(theOperand);
+                break;
+
+            case ByteCode.NEWARRAY :
+                if (!(0 <= theOperand && theOperand < 256))
+                    throw new IllegalArgumentException("out of range index");
+                addToCodeBuffer(theOpCode);
+                addToCodeBuffer(theOperand);
+                break;
+
+            case ByteCode.GETFIELD :
+            case ByteCode.PUTFIELD :
+                if (!(0 <= theOperand && theOperand < 65536))
+                    throw new IllegalArgumentException("out of range field");
+                addToCodeBuffer(theOpCode);
+                addToCodeInt16(theOperand);
+                break;
+
+            case ByteCode.LDC :
+            case ByteCode.LDC_W :
+            case ByteCode.LDC2_W :
+                if (!(0 <= theOperand && theOperand < 65536))
+                    throw new IllegalArgumentException("out of range index");
+                if (theOperand >= 256
+                    || theOpCode == ByteCode.LDC_W
+                    || theOpCode == ByteCode.LDC2_W)
+                {
+                    if (theOpCode == ByteCode.LDC) {
+                        addToCodeBuffer(ByteCode.LDC_W);
+                    } else {
+                        addToCodeBuffer(theOpCode);
+                    }
+                    addToCodeInt16(theOperand);
+                } else {
+                    addToCodeBuffer(theOpCode);
+                    addToCodeBuffer(theOperand);
+                }
+                break;
+
+            case ByteCode.RET :
+            case ByteCode.ILOAD :
+            case ByteCode.LLOAD :
+            case ByteCode.FLOAD :
+            case ByteCode.DLOAD :
+            case ByteCode.ALOAD :
+            case ByteCode.ISTORE :
+            case ByteCode.LSTORE :
+            case ByteCode.FSTORE :
+            case ByteCode.DSTORE :
+            case ByteCode.ASTORE :
+                if (!(0 <= theOperand && theOperand < 65536))
+                    throw new ClassFileFormatException("out of range variable");
+                if (theOperand >= 256) {
+                    addToCodeBuffer(ByteCode.WIDE);
+                    addToCodeBuffer(theOpCode);
+                    addToCodeInt16(theOperand);
+                }
+                else {
+                    addToCodeBuffer(theOpCode);
+                    addToCodeBuffer(theOperand);
+                }
+                break;
+
+            default :
+                throw new IllegalArgumentException(
+                    "Unexpected opcode for 1 operand");
+        }
+
+        itsStackTop = (short)newStack;
+        if (newStack > itsMaxStack) itsMaxStack = (short)newStack;
+        if (DEBUGSTACK) {
+            System.out.println("After "+bytecodeStr(theOpCode)
+                               +" stack = "+itsStackTop);
+        }
+    }
+
+    /**
+     * Generate the load constant bytecode for the given integer.
+     *
+     * @param k the constant
+     */
+    public void addLoadConstant(int k) {
+        switch (k) {
+            case 0: add(ByteCode.ICONST_0); break;
+            case 1: add(ByteCode.ICONST_1); break;
+            case 2: add(ByteCode.ICONST_2); break;
+            case 3: add(ByteCode.ICONST_3); break;
+            case 4: add(ByteCode.ICONST_4); break;
+            case 5: add(ByteCode.ICONST_5); break;
+            default:
+                add(ByteCode.LDC, itsConstantPool.addConstant(k));
+                break;
+        }
+    }
+
+    /**
+     * Generate the load constant bytecode for the given long.
+     *
+     * @param k the constant
+     */
+    public void addLoadConstant(long k) {
+        add(ByteCode.LDC2_W, itsConstantPool.addConstant(k));
+    }
+
+    /**
+     * Generate the load constant bytecode for the given float.
+     *
+     * @param k the constant
+     */
+    public void addLoadConstant(float k) {
+        add(ByteCode.LDC, itsConstantPool.addConstant(k));
+    }
+
+    /**
+     * Generate the load constant bytecode for the given double.
+     *
+     * @param k the constant
+     */
+    public void addLoadConstant(double k) {
+        add(ByteCode.LDC2_W, itsConstantPool.addConstant(k));
+    }
+
+    /**
+     * Generate the load constant bytecode for the given string.
+     *
+     * @param k the constant
+     */
+    public void addLoadConstant(String k) {
+        add(ByteCode.LDC, itsConstantPool.addConstant(k));
+    }
+
+    /**
+     * Add the given two-operand bytecode to the current method.
+     *
+     * @param theOpCode the opcode of the bytecode
+     * @param theOperand1 the first operand of the bytecode
+     * @param theOperand2 the second operand of the bytecode
+     */
+    public void add(int theOpCode, int theOperand1, int theOperand2) {
+        if (DEBUGCODE) {
+            System.out.println("Add "+bytecodeStr(theOpCode)
+                               +", "+Integer.toHexString(theOperand1)
+                               +", "+Integer.toHexString(theOperand2));
+        }
+        int newStack = itsStackTop + stackChange(theOpCode);
+        if (newStack < 0 || Short.MAX_VALUE < newStack) badStack(newStack);
+
+        if (theOpCode == ByteCode.IINC) {
+            if (!(0 <= theOperand1 && theOperand1 < 65536))
+                throw new ClassFileFormatException("out of range variable");
+            if (!(0 <= theOperand2 && theOperand2 < 65536))
+                throw new ClassFileFormatException("out of range increment");
+
+            if (theOperand1 > 255 || theOperand2 < -128 || theOperand2 > 127) {
+                addToCodeBuffer(ByteCode.WIDE);
+                addToCodeBuffer(ByteCode.IINC);
+                addToCodeInt16(theOperand1);
+                addToCodeInt16(theOperand2);
+            }
+            else {
+                addToCodeBuffer(ByteCode.IINC);
+                addToCodeBuffer(theOperand1);
+                addToCodeBuffer(theOperand2);
+            }
+        }
+        else if (theOpCode == ByteCode.MULTIANEWARRAY) {
+            if (!(0 <= theOperand1 && theOperand1 < 65536))
+                throw new IllegalArgumentException("out of range index");
+            if (!(0 <= theOperand2 && theOperand2 < 256))
+                throw new IllegalArgumentException("out of range dimensions");
+
+            addToCodeBuffer(ByteCode.MULTIANEWARRAY);
+            addToCodeInt16(theOperand1);
+            addToCodeBuffer(theOperand2);
+        }
+        else {
+            throw new IllegalArgumentException(
+                "Unexpected opcode for 2 operands");
+        }
+        itsStackTop = (short)newStack;
+        if (newStack > itsMaxStack) itsMaxStack = (short)newStack;
+        if (DEBUGSTACK) {
+            System.out.println("After "+bytecodeStr(theOpCode)
+                               +" stack = "+itsStackTop);
+        }
+
+    }
+
+    public void add(int theOpCode, String className) {
+        if (DEBUGCODE) {
+            System.out.println("Add "+bytecodeStr(theOpCode)
+                               +", "+className);
+        }
+        int newStack = itsStackTop + stackChange(theOpCode);
+        if (newStack < 0 || Short.MAX_VALUE < newStack) badStack(newStack);
+        switch (theOpCode) {
+            case ByteCode.NEW :
+            case ByteCode.ANEWARRAY :
+            case ByteCode.CHECKCAST :
+            case ByteCode.INSTANCEOF : {
+                short classIndex = itsConstantPool.addClass(className);
+                addToCodeBuffer(theOpCode);
+                addToCodeInt16(classIndex);
+            }
+            break;
+
+            default :
+                throw new IllegalArgumentException(
+                    "bad opcode for class reference");
+        }
+        itsStackTop = (short)newStack;
+        if (newStack > itsMaxStack) itsMaxStack = (short)newStack;
+        if (DEBUGSTACK) {
+            System.out.println("After "+bytecodeStr(theOpCode)
+                               +" stack = "+itsStackTop);
+        }
+    }
+
+
+    public void add(int theOpCode, String className, String fieldName,
+                    String fieldType)
+    {
+        if (DEBUGCODE) {
+            System.out.println("Add "+bytecodeStr(theOpCode)
+                               +", "+className+", "+fieldName+", "+fieldType);
+        }
+        int newStack = itsStackTop + stackChange(theOpCode);
+        char fieldTypeChar = fieldType.charAt(0);
+        int fieldSize = (fieldTypeChar == 'J' || fieldTypeChar == 'D')
+                        ? 2 : 1;
+        switch (theOpCode) {
+            case ByteCode.GETFIELD :
+            case ByteCode.GETSTATIC :
+                newStack += fieldSize;
+                break;
+            case ByteCode.PUTSTATIC :
+            case ByteCode.PUTFIELD :
+                newStack -= fieldSize;
+                break;
+            default :
+                throw new IllegalArgumentException(
+                    "bad opcode for field reference");
+        }
+        if (newStack < 0 || Short.MAX_VALUE < newStack) badStack(newStack);
+        short fieldRefIndex = itsConstantPool.addFieldRef(className,
+                                             fieldName, fieldType);
+        addToCodeBuffer(theOpCode);
+        addToCodeInt16(fieldRefIndex);
+
+        itsStackTop = (short)newStack;
+        if (newStack > itsMaxStack) itsMaxStack = (short)newStack;
+        if (DEBUGSTACK) {
+            System.out.println("After "+bytecodeStr(theOpCode)
+                               +" stack = "+itsStackTop);
+        }
+    }
+
+    public void addInvoke(int theOpCode, String className, String methodName,
+                          String methodType)
+    {
+        if (DEBUGCODE) {
+            System.out.println("Add "+bytecodeStr(theOpCode)
+                               +", "+className+", "+methodName+", "
+                               +methodType);
+        }
+        int parameterInfo = sizeOfParameters(methodType);
+        int parameterCount = parameterInfo >>> 16;
+        int stackDiff = (short)parameterInfo;
+
+        int newStack = itsStackTop + stackDiff;
+        newStack += stackChange(theOpCode);     // adjusts for 'this'
+        if (newStack < 0 || Short.MAX_VALUE < newStack) badStack(newStack);
+
+        switch (theOpCode) {
+            case ByteCode.INVOKEVIRTUAL :
+            case ByteCode.INVOKESPECIAL :
+            case ByteCode.INVOKESTATIC :
+            case ByteCode.INVOKEINTERFACE : {
+                    addToCodeBuffer(theOpCode);
+                    if (theOpCode == ByteCode.INVOKEINTERFACE) {
+                        short ifMethodRefIndex
+                                    = itsConstantPool.addInterfaceMethodRef(
+                                               className, methodName,
+                                               methodType);
+                        addToCodeInt16(ifMethodRefIndex);
+                        addToCodeBuffer(parameterCount + 1);
+                        addToCodeBuffer(0);
+                    }
+                    else {
+                        short methodRefIndex = itsConstantPool.addMethodRef(
+                                               className, methodName,
+                                               methodType);
+                        addToCodeInt16(methodRefIndex);
+                    }
+                }
+                break;
+
+            default :
+                throw new IllegalArgumentException(
+                    "bad opcode for method reference");
+        }
+        itsStackTop = (short)newStack;
+        if (newStack > itsMaxStack) itsMaxStack = (short)newStack;
+        if (DEBUGSTACK) {
+            System.out.println("After "+bytecodeStr(theOpCode)
+                               +" stack = "+itsStackTop);
+        }
+    }
+
+    /**
+     * Generate code to load the given integer on stack.
+     *
+     * @param k the constant
+     */
+    public void addPush(int k)
+    {
+        if ((byte)k == k) {
+            if (k == -1) {
+                add(ByteCode.ICONST_M1);
+            } else if (0 <= k && k <= 5) {
+                add((byte)(ByteCode.ICONST_0 + k));
+            } else {
+                add(ByteCode.BIPUSH, (byte)k);
+            }
+        } else if ((short)k == k) {
+            add(ByteCode.SIPUSH, (short)k);
+        } else {
+            addLoadConstant(k);
+        }
+    }
+
+    public void addPush(boolean k)
+    {
+        add(k ? ByteCode.ICONST_1 : ByteCode.ICONST_0);
+    }
+
+    /**
+     * Generate code to load the given long on stack.
+     *
+     * @param k the constant
+     */
+    public void addPush(long k)
+    {
+        int ik = (int)k;
+        if (ik == k) {
+            addPush(ik);
+            add(ByteCode.I2L);
+        } else {
+            addLoadConstant(k);
+        }
+    }
+
+    /**
+     * Generate code to load the given double on stack.
+     *
+     * @param k the constant
+     */
+    public void addPush(double k)
+    {
+        if (k == 0.0) {
+            // zero
+            add(ByteCode.DCONST_0);
+            if (1.0 / k < 0) {
+                // Negative zero
+                add(ByteCode.DNEG);
+            }
+        } else if (k == 1.0 || k == -1.0) {
+            add(ByteCode.DCONST_1);
+            if (k < 0) {
+                add(ByteCode.DNEG);
+            }
+        } else {
+            addLoadConstant(k);
+        }
+    }
+
+    /**
+     * Generate the code to leave on stack the given string even if the
+     * string encoding exeeds the class file limit for single string constant
+     *
+     * @param k the constant
+     */
+    public void addPush(String k) {
+        int length = k.length();
+        int limit = itsConstantPool.getUtfEncodingLimit(k, 0, length);
+        if (limit == length) {
+            addLoadConstant(k);
+            return;
+        }
+        // Split string into picies fitting the UTF limit and generate code for
+        // StringBuilder sb = new StringBuilder(length);
+        // sb.append(loadConstant(piece_1));
+        // ...
+        // sb.append(loadConstant(piece_N));
+        // sb.toString();
+        final String SB = "java/lang/StringBuilder";
+        add(ByteCode.NEW, SB);
+        add(ByteCode.DUP);
+        addPush(length);
+        addInvoke(ByteCode.INVOKESPECIAL, SB, "<init>", "(I)V");
+        int cursor = 0;
+        for (;;) {
+            add(ByteCode.DUP);
+            String s = k.substring(cursor, limit);
+            addLoadConstant(s);
+            addInvoke(ByteCode.INVOKEVIRTUAL, SB, "append",
+                      "(Ljava/lang/String;)Ljava/lang/StringBuilder;");
+            add(ByteCode.POP);
+            if (limit == length) {
+                break;
+            }
+            cursor = limit;
+            limit = itsConstantPool.getUtfEncodingLimit(k, limit, length);
+        }
+        addInvoke(ByteCode.INVOKEVIRTUAL, SB, "toString",
+                  "()Ljava/lang/String;");
+    }
+
+    /**
+     * Check if k fits limit on string constant size imposed by class file
+     * format.
+     *
+     * @param k the string constant
+     */
+    public boolean isUnderStringSizeLimit(String k)
+    {
+        return itsConstantPool.isUnderUtfEncodingLimit(k);
+    }
+
+    /**
+     * Store integer from stack top into the given local.
+     *
+     * @param local number of local register
+     */
+    public void addIStore(int local)
+    {
+        xop(ByteCode.ISTORE_0, ByteCode.ISTORE, local);
+    }
+
+    /**
+     * Store long from stack top into the given local.
+     *
+     * @param local number of local register
+     */
+    public void addLStore(int local)
+    {
+        xop(ByteCode.LSTORE_0, ByteCode.LSTORE, local);
+    }
+
+    /**
+     * Store float from stack top into the given local.
+     *
+     * @param local number of local register
+     */
+    public void addFStore(int local)
+    {
+        xop(ByteCode.FSTORE_0, ByteCode.FSTORE, local);
+    }
+
+    /**
+     * Store double from stack top into the given local.
+     *
+     * @param local number of local register
+     */
+    public void addDStore(int local)
+    {
+        xop(ByteCode.DSTORE_0, ByteCode.DSTORE, local);
+    }
+
+    /**
+     * Store object from stack top into the given local.
+     *
+     * @param local number of local register
+     */
+    public void addAStore(int local)
+    {
+        xop(ByteCode.ASTORE_0, ByteCode.ASTORE, local);
+    }
+
+    /**
+     * Load integer from the given local into stack.
+     *
+     * @param local number of local register
+     */
+    public void addILoad(int local)
+    {
+        xop(ByteCode.ILOAD_0, ByteCode.ILOAD, local);
+    }
+
+    /**
+     * Load long from the given local into stack.
+     *
+     * @param local number of local register
+     */
+    public void addLLoad(int local)
+    {
+        xop(ByteCode.LLOAD_0, ByteCode.LLOAD, local);
+    }
+
+    /**
+     * Load float from the given local into stack.
+     *
+     * @param local number of local register
+     */
+    public void addFLoad(int local)
+    {
+        xop(ByteCode.FLOAD_0, ByteCode.FLOAD, local);
+    }
+
+    /**
+     * Load double from the given local into stack.
+     *
+     * @param local number of local register
+     */
+    public void addDLoad(int local)
+    {
+        xop(ByteCode.DLOAD_0, ByteCode.DLOAD, local);
+    }
+
+    /**
+     * Load object from the given local into stack.
+     *
+     * @param local number of local register
+     */
+    public void addALoad(int local)
+    {
+        xop(ByteCode.ALOAD_0, ByteCode.ALOAD, local);
+    }
+
+    /**
+     * Load "this" into stack.
+     */
+    public void addLoadThis()
+    {
+        add(ByteCode.ALOAD_0);
+    }
+
+    private void xop(int shortOp, int op, int local)
+    {
+        switch (local) {
+          case 0:
+            add(shortOp);
+            break;
+          case 1:
+            add(shortOp + 1);
+            break;
+          case 2:
+            add(shortOp + 2);
+            break;
+          case 3:
+            add(shortOp + 3);
+            break;
+          default:
+            add(op, local);
+        }
+    }
+
+    public int addTableSwitch(int low, int high)
+    {
+        if (DEBUGCODE) {
+            System.out.println("Add "+bytecodeStr(ByteCode.TABLESWITCH)
+                               +" "+low+" "+high);
+        }
+        if (low > high)
+            throw new ClassFileFormatException("Bad bounds: "+low+' '+ high);
+
+        int newStack = itsStackTop + stackChange(ByteCode.TABLESWITCH);
+        if (newStack < 0 || Short.MAX_VALUE < newStack) badStack(newStack);
+
+        int entryCount = high - low + 1;
+        int padSize = 3 & ~itsCodeBufferTop; // == 3 - itsCodeBufferTop % 4
+
+        int N = addReservedCodeSpace(1 + padSize + 4 * (1 + 2 + entryCount));
+        int switchStart = N;
+        itsCodeBuffer[N++] = (byte)ByteCode.TABLESWITCH;
+        while (padSize != 0) {
+            itsCodeBuffer[N++] = 0;
+            --padSize;
+        }
+        N += 4; // skip default offset
+        N = putInt32(low, itsCodeBuffer, N);
+        putInt32(high, itsCodeBuffer, N);
+
+        itsStackTop = (short)newStack;
+        if (newStack > itsMaxStack) itsMaxStack = (short)newStack;
+        if (DEBUGSTACK) {
+            System.out.println("After "+bytecodeStr(ByteCode.TABLESWITCH)
+                               +" stack = "+itsStackTop);
+        }
+
+        return switchStart;
+    }
+
+    public final void markTableSwitchDefault(int switchStart)
+    {
+        addSuperBlockStart(itsCodeBufferTop);
+        itsJumpFroms.put(itsCodeBufferTop, switchStart);
+        setTableSwitchJump(switchStart, -1, itsCodeBufferTop);
+    }
+
+    public final void markTableSwitchCase(int switchStart, int caseIndex)
+    {
+        addSuperBlockStart(itsCodeBufferTop);
+        itsJumpFroms.put(itsCodeBufferTop, switchStart);
+        setTableSwitchJump(switchStart, caseIndex, itsCodeBufferTop);
+    }
+
+    public final void markTableSwitchCase(int switchStart, int caseIndex,
+                                          int stackTop)
+    {
+        if (!(0 <= stackTop && stackTop <= itsMaxStack))
+            throw new IllegalArgumentException("Bad stack index: "+stackTop);
+        itsStackTop = (short)stackTop;
+        addSuperBlockStart(itsCodeBufferTop);
+        itsJumpFroms.put(itsCodeBufferTop, switchStart);
+        setTableSwitchJump(switchStart, caseIndex, itsCodeBufferTop);
+    }
+
+    /**
+     * Set a jump case for a tableswitch instruction. The jump target should
+     * be marked as a super block start for stack map generation.
+     */
+    public void setTableSwitchJump(int switchStart, int caseIndex,
+                                   int jumpTarget)
+    {
+        if (!(0 <= jumpTarget && jumpTarget <= itsCodeBufferTop))
+            throw new IllegalArgumentException("Bad jump target: "+jumpTarget);
+        if (!(caseIndex >= -1))
+            throw new IllegalArgumentException("Bad case index: "+caseIndex);
+
+        int padSize = 3 & ~switchStart; // == 3 - switchStart % 4
+        int caseOffset;
+        if (caseIndex < 0) {
+            // default label
+            caseOffset = switchStart + 1 + padSize;
+        } else {
+            caseOffset = switchStart + 1 + padSize + 4 * (3 + caseIndex);
+        }
+        if (!(0 <= switchStart
+              && switchStart <= itsCodeBufferTop - 4 * 4 - padSize - 1))
+        {
+            throw new IllegalArgumentException(
+                switchStart+" is outside a possible range of tableswitch"
+                +" in already generated code");
+        }
+        if ((0xFF & itsCodeBuffer[switchStart]) != ByteCode.TABLESWITCH) {
+            throw new IllegalArgumentException(
+                switchStart+" is not offset of tableswitch statement");
+        }
+        if (!(0 <= caseOffset && caseOffset + 4 <= itsCodeBufferTop)) {
+            // caseIndex >= -1 does not guarantee that caseOffset >= 0 due
+            // to a possible overflow.
+            throw new ClassFileFormatException(
+                "Too big case index: "+caseIndex);
+        }
+        // ALERT: perhaps check against case bounds?
+        putInt32(jumpTarget - switchStart, itsCodeBuffer, caseOffset);
+    }
+
+    public int acquireLabel()
+    {
+        int top = itsLabelTableTop;
+        if (itsLabelTable == null || top == itsLabelTable.length) {
+            if (itsLabelTable == null) {
+                itsLabelTable = new int[MIN_LABEL_TABLE_SIZE];
+            }else {
+                int[] tmp = new int[itsLabelTable.length * 2];
+                System.arraycopy(itsLabelTable, 0, tmp, 0, top);
+                itsLabelTable = tmp;
+            }
+        }
+        itsLabelTableTop = top + 1;
+        itsLabelTable[top] = -1;
+        return top | 0x80000000;
+    }
+
+    public void markLabel(int label)
+    {
+        if (!(label < 0))
+            throw new IllegalArgumentException("Bad label, no biscuit");
+
+        label &= 0x7FFFFFFF;
+        if (label > itsLabelTableTop)
+            throw new IllegalArgumentException("Bad label");
+
+        if (itsLabelTable[label] != -1) {
+            throw new IllegalStateException("Can only mark label once");
+        }
+
+        itsLabelTable[label] = itsCodeBufferTop;
+    }
+
+    public void markLabel(int label, short stackTop)
+    {
+        markLabel(label);
+        itsStackTop = stackTop;
+    }
+
+    public void markHandler(int theLabel) {
+        itsStackTop = 1;
+        markLabel(theLabel);
+    }
+
+    public int getLabelPC(int label)
+    {
+        if (!(label < 0))
+            throw new IllegalArgumentException("Bad label, no biscuit");
+        label &= 0x7FFFFFFF;
+        if (!(label < itsLabelTableTop))
+            throw new IllegalArgumentException("Bad label");
+        return itsLabelTable[label];
+    }
+
+    private void addLabelFixup(int label, int fixupSite)
+    {
+        if (!(label < 0))
+            throw new IllegalArgumentException("Bad label, no biscuit");
+        label &= 0x7FFFFFFF;
+        if (!(label < itsLabelTableTop))
+            throw new IllegalArgumentException("Bad label");
+        int top = itsFixupTableTop;
+        if (itsFixupTable == null || top == itsFixupTable.length) {
+            if (itsFixupTable == null) {
+                itsFixupTable = new long[MIN_FIXUP_TABLE_SIZE];
+            }else {
+                long[] tmp = new long[itsFixupTable.length * 2];
+                System.arraycopy(itsFixupTable, 0, tmp, 0, top);
+                itsFixupTable = tmp;
+            }
+        }
+        itsFixupTableTop = top + 1;
+        itsFixupTable[top] = ((long)label << 32) | fixupSite;
+    }
+
+    private  void fixLabelGotos()
+    {
+        byte[] codeBuffer = itsCodeBuffer;
+        for (int i = 0; i < itsFixupTableTop; i++) {
+            long fixup = itsFixupTable[i];
+            int label = (int)(fixup >> 32);
+            int fixupSite = (int)fixup;
+            int pc = itsLabelTable[label];
+            if (pc == -1) {
+                // Unlocated label
+                throw new RuntimeException();
+            }
+            // -1 to get delta from instruction start
+            addSuperBlockStart(pc);
+            itsJumpFroms.put(pc, fixupSite - 1);
+            int offset = pc - (fixupSite - 1);
+            if ((short)offset != offset) {
+                throw new ClassFileFormatException
+                    ("Program too complex: too big jump offset");
+            }
+            codeBuffer[fixupSite] = (byte)(offset >> 8);
+            codeBuffer[fixupSite + 1] = (byte)offset;
+        }
+        itsFixupTableTop = 0;
+    }
+
+    /**
+     * Get the current offset into the code of the current method.
+     *
+     * @return an integer representing the offset
+     */
+    public int getCurrentCodeOffset() {
+        return itsCodeBufferTop;
+    }
+
+    public short getStackTop() {
+        return itsStackTop;
+    }
+
+    public void setStackTop(short n) {
+        itsStackTop = n;
+    }
+
+    public void adjustStackTop(int delta) {
+        int newStack = itsStackTop + delta;
+        if (newStack < 0 || Short.MAX_VALUE < newStack) badStack(newStack);
+        itsStackTop = (short)newStack;
+        if (newStack > itsMaxStack) itsMaxStack = (short)newStack;
+        if (DEBUGSTACK) {
+            System.out.println("After "+"adjustStackTop("+delta+")"
+                               +" stack = "+itsStackTop);
+        }
+    }
+
+    private void addToCodeBuffer(int b)
+    {
+        int N = addReservedCodeSpace(1);
+        itsCodeBuffer[N] = (byte)b;
+    }
+
+    private void addToCodeInt16(int value)
+    {
+        int N = addReservedCodeSpace(2);
+        putInt16(value, itsCodeBuffer, N);
+    }
+
+    private int addReservedCodeSpace(int size)
+    {
+        if (itsCurrentMethod == null)
+            throw new IllegalArgumentException("No method to add to");
+        int oldTop = itsCodeBufferTop;
+        int newTop = oldTop + size;
+        if (newTop > itsCodeBuffer.length) {
+            int newSize = itsCodeBuffer.length * 2;
+            if (newTop > newSize) { newSize = newTop; }
+            byte[] tmp = new byte[newSize];
+            System.arraycopy(itsCodeBuffer, 0, tmp, 0, oldTop);
+            itsCodeBuffer = tmp;
+        }
+        itsCodeBufferTop = newTop;
+        return oldTop;
+    }
+
+    public void addExceptionHandler(int startLabel, int endLabel,
+                                    int handlerLabel, String catchClassName)
+    {
+        if ((startLabel & 0x80000000) != 0x80000000)
+            throw new IllegalArgumentException("Bad startLabel");
+        if ((endLabel & 0x80000000) != 0x80000000)
+            throw new IllegalArgumentException("Bad endLabel");
+        if ((handlerLabel & 0x80000000) != 0x80000000)
+            throw new IllegalArgumentException("Bad handlerLabel");
+
+        /*
+         * If catchClassName is null, use 0 for the catch_type_index; which
+         * means catch everything.  (Even when the verifier has let you throw
+         * something other than a Throwable.)
+         */
+        short catch_type_index = (catchClassName == null)
+                                 ? 0
+                                 : itsConstantPool.addClass(catchClassName);
+        ExceptionTableEntry newEntry = new ExceptionTableEntry(
+                                           startLabel,
+                                           endLabel,
+                                           handlerLabel,
+                                           catch_type_index);
+        int N = itsExceptionTableTop;
+        if (N == 0) {
+            itsExceptionTable = new ExceptionTableEntry[ExceptionTableSize];
+        } else if (N == itsExceptionTable.length) {
+            ExceptionTableEntry[] tmp = new ExceptionTableEntry[N * 2];
+            System.arraycopy(itsExceptionTable, 0, tmp, 0, N);
+            itsExceptionTable = tmp;
+        }
+        itsExceptionTable[N] = newEntry;
+        itsExceptionTableTop = N + 1;
+
+    }
+
+    public void addLineNumberEntry(short lineNumber) {
+        if (itsCurrentMethod == null)
+            throw new IllegalArgumentException("No method to stop");
+        int N = itsLineNumberTableTop;
+        if (N == 0) {
+            itsLineNumberTable = new int[LineNumberTableSize];
+        } else if (N == itsLineNumberTable.length) {
+            int[] tmp = new int[N * 2];
+            System.arraycopy(itsLineNumberTable, 0, tmp, 0, N);
+            itsLineNumberTable = tmp;
+        }
+        itsLineNumberTable[N] = (itsCodeBufferTop << 16) + lineNumber;
+        itsLineNumberTableTop = N + 1;
+    }
+
+    /**
+     * A stack map table is a code attribute introduced in Java 6 that
+     * gives type information at key points in the method body (namely, at
+     * the beginning of each super block after the first). Each frame of a
+     * stack map table contains the state of local variable and operand stack
+     * for a given super block.
+     */
+    final class StackMapTable {
+        StackMapTable() {
+            superBlocks = null;
+            locals = stack = null;
+            workList = null;
+            rawStackMap = null;
+            localsTop = 0;
+            stackTop = 0;
+            workListTop = 0;
+            rawStackMapTop = 0;
+            wide = false;
+        }
+
+        void generate() {
+            superBlocks = new SuperBlock[itsSuperBlockStartsTop];
+            int[] initialLocals = createInitialLocals();
+
+            for (int i = 0; i < itsSuperBlockStartsTop; i++) {
+                int start = itsSuperBlockStarts[i];
+                int end;
+                if (i == itsSuperBlockStartsTop - 1) {
+                    end = itsCodeBufferTop;
+                } else {
+                    end = itsSuperBlockStarts[i + 1];
+                }
+                superBlocks[i] = new SuperBlock(i, start, end, initialLocals);
+            }
+
+            if (DEBUGSTACKMAP) {
+                System.out.println("super blocks: ");
+                for (int i = 0;
+                     i < superBlocks.length && superBlocks[i] != null; i++) {
+                    System.out.println("sb " + i + ": [" +
+                                       superBlocks[i].getStart() + ", " +
+                                       superBlocks[i].getEnd() + ")");
+                }
+            }
+
+            superBlockDeps = getSuperBlockDependencies();
+
+            verify();
+
+            if (DEBUGSTACKMAP) {
+                System.out.println("type information:");
+                for (int i = 0; i < superBlocks.length; i++) {
+                    SuperBlock sb = superBlocks[i];
+                    System.out.println("sb " + i + ":");
+                    TypeInfo.print(sb.getLocals(), sb.getStack(),
+                                   itsConstantPool);
+                }
+            }
+        }
+
+        private SuperBlock getSuperBlockFromOffset(int offset) {
+            for (int i = 0; i < superBlocks.length; i++) {
+                SuperBlock sb = superBlocks[i];
+                if (sb == null) {
+                    break;
+                } else if (offset >= sb.getStart() && offset < sb.getEnd()) {
+                    return sb;
+                }
+            }
+            throw new IllegalArgumentException("bad offset: " + offset);
+        }
+
+        /**
+         * Determine whether or not an opcode is an actual end to a super
+         * block. This includes any returns or unconditional jumps.
+         */
+        private boolean isSuperBlockEnd(int opcode) {
+            switch (opcode) {
+                case ByteCode.ARETURN:
+                case ByteCode.FRETURN:
+                case ByteCode.IRETURN:
+                case ByteCode.LRETURN:
+                case ByteCode.RETURN:
+                case ByteCode.ATHROW:
+                case ByteCode.GOTO:
+                case ByteCode.GOTO_W:
+                case ByteCode.TABLESWITCH:
+                case ByteCode.LOOKUPSWITCH:
+                    return true;
+                default:
+                    return false;
+            }
+        }
+
+        /**
+         * Calculate partial dependencies for super blocks.
+         *
+         * This is used as a workaround for dead code that is generated. Only
+         * one dependency per super block is given.
+         */
+        private SuperBlock[] getSuperBlockDependencies() {
+            SuperBlock[] deps = new SuperBlock[superBlocks.length];
+
+            for (int i = 0; i < itsExceptionTableTop; i++) {
+                ExceptionTableEntry ete = itsExceptionTable[i];
+                short startPC = (short) getLabelPC(ete.itsStartLabel);
+                short handlerPC = (short) getLabelPC(ete.itsHandlerLabel);
+                SuperBlock handlerSB = getSuperBlockFromOffset(handlerPC);
+                SuperBlock dep = getSuperBlockFromOffset(startPC);
+                deps[handlerSB.getIndex()] = dep;
+            }
+            int[] targetPCs = itsJumpFroms.getKeys();
+            for (int i = 0; i < targetPCs.length; i++) {
+                int targetPC = targetPCs[i];
+                int branchPC = itsJumpFroms.getInt(targetPC, -1);
+                SuperBlock branchSB = getSuperBlockFromOffset(branchPC);
+                SuperBlock targetSB = getSuperBlockFromOffset(targetPC);
+                deps[targetSB.getIndex()] = branchSB;
+            }
+
+            return deps;
+        }
+
+        /**
+         * Get the target super block of a branch instruction.
+         *
+         * @param bci the index of the branch instruction in the code buffer
+         */
+        private SuperBlock getBranchTarget(int bci) {
+            int target;
+            if ((itsCodeBuffer[bci] & 0xFF) == ByteCode.GOTO_W) {
+                target = bci + getOperand(bci + 1, 4);
+            } else {
+                target = bci + (short) getOperand(bci + 1, 2);
+            }
+            return getSuperBlockFromOffset(target);
+        }
+
+        /**
+         * Determine whether or not an opcode is a conditional or unconditional
+         * jump.
+         */
+        private boolean isBranch(int opcode) {
+            switch (opcode) {
+                case ByteCode.GOTO:
+                case ByteCode.GOTO_W:
+                case ByteCode.IFEQ:
+                case ByteCode.IFGE:
+                case ByteCode.IFGT:
+                case ByteCode.IFLE:
+                case ByteCode.IFLT:
+                case ByteCode.IFNE:
+                case ByteCode.IFNONNULL:
+                case ByteCode.IFNULL:
+                case ByteCode.IF_ACMPEQ:
+                case ByteCode.IF_ACMPNE:
+                case ByteCode.IF_ICMPEQ:
+                case ByteCode.IF_ICMPGE:
+                case ByteCode.IF_ICMPGT:
+                case ByteCode.IF_ICMPLE:
+                case ByteCode.IF_ICMPLT:
+                case ByteCode.IF_ICMPNE:
+                    return true;
+                default:
+                    return false;
+            }
+        }
+
+        private int getOperand(int offset) {
+            return getOperand(offset, 1);
+        }
+
+        /**
+         * Extract a logical operand from the byte code.
+         *
+         * This is used, for example, to get branch offsets.
+         */
+        private int getOperand(int start, int size) {
+            int result = 0;
+            if (size > 4) {
+                throw new IllegalArgumentException("bad operand size");
+            }
+            for (int i = 0; i < size; i++) {
+                result = (result << 8) | (itsCodeBuffer[start + i] & 0xFF);
+            }
+            return result;
+        }
+
+        /**
+         * Calculate initial local variable and op stack types for each super
+         * block in the method.
+         */
+        private void verify() {
+            int[] initialLocals = createInitialLocals();
+            superBlocks[0].merge(initialLocals, initialLocals.length,
+                                 new int[0], 0, itsConstantPool);
+
+            // Start from the top of the method and queue up block dependencies
+            // as they come along.
+            workList = new SuperBlock[] { superBlocks[0] };
+            workListTop = 1;
+            executeWorkList();
+
+            // Replace dead code with no-ops.
+            for (int i = 0; i < superBlocks.length; i++) {
+                SuperBlock sb = superBlocks[i];
+                if (!sb.isInitialized()) {
+                    killSuperBlock(sb);
+                }
+            }
+            executeWorkList();
+        }
+
+        /**
+         * Replace the contents of a super block with no-ops.
+         *
+         * The above description is not strictly true; the last instruction is
+         * an athrow instruction. This technique is borrowed from ASM's
+         * developer guide: http://asm.ow2.org/doc/developer-guide.html#deadcode
+         *
+         * The proposed algorithm fills a block with nop, ending it with an
+         * athrow. The stack map generated would be empty locals with an
+         * exception on the stack. In theory, it shouldn't matter what the
+         * locals are, as long as the stack has an exception for the athrow bit.
+         * However, it turns out that if the code being modified falls into an
+         * exception handler, it causes problems. Therefore, if it does, then
+         * we steal the locals from the exception block.
+         *
+         * If the block itself is an exception handler, we remove it from the
+         * exception table to simplify block dependencies.
+         */
+        private void killSuperBlock(SuperBlock sb) {
+            int[] locals = new int[0];
+            int[] stack = new int[] { TypeInfo.OBJECT("java/lang/Throwable",
+                                                      itsConstantPool) };
+
+            // If the super block is handled by any exception handler, use its
+            // locals as the killed block's locals. Ignore uninitialized
+            // handlers, because they will also be killed and removed from the
+            // exception table.
+            for (int i = 0; i < itsExceptionTableTop; i++) {
+                ExceptionTableEntry ete = itsExceptionTable[i];
+                int eteStart = getLabelPC(ete.itsStartLabel);
+                int eteEnd = getLabelPC(ete.itsEndLabel);
+                int handlerPC = getLabelPC(ete.itsHandlerLabel);
+                SuperBlock handlerSB = getSuperBlockFromOffset(handlerPC);
+                if ((sb.getStart() > eteStart && sb.getStart() < eteEnd) ||
+                    (eteStart > sb.getStart() && eteStart < sb.getEnd()) &&
+                    handlerSB.isInitialized()) {
+                    locals = handlerSB.getLocals();
+                    break;
+                }
+            }
+
+            // Remove any exception table entry whose handler is the killed
+            // block. This removes block dependencies to make stack maps for
+            // dead blocks easier to create.
+            for (int i = 0; i < itsExceptionTableTop; i++) {
+                ExceptionTableEntry ete = itsExceptionTable[i];
+                int eteStart = getLabelPC(ete.itsStartLabel);
+                if (eteStart == sb.getStart()) {
+                    for (int j = i + 1; j < itsExceptionTableTop; j++) {
+                        itsExceptionTable[j - 1] = itsExceptionTable[j];
+                    }
+                    itsExceptionTableTop--;
+                    i--;
+                }
+            }
+
+            sb.merge(locals, locals.length, stack, stack.length,
+                     itsConstantPool);
+
+            int end = sb.getEnd() - 1;
+            itsCodeBuffer[end] = (byte) ByteCode.ATHROW;
+            for (int bci = sb.getStart(); bci < end; bci++) {
+                itsCodeBuffer[bci] = (byte) ByteCode.NOP;
+            }
+        }
+
+        private void executeWorkList() {
+            while (workListTop > 0) {
+                SuperBlock work = workList[--workListTop];
+                work.setInQueue(false);
+                locals = work.getLocals();
+                stack = work.getStack();
+                localsTop = locals.length;
+                stackTop = stack.length;
+                executeBlock(work);
+            }
+        }
+
+        /**
+         * Simulate the local variable and op stack for a super block.
+         */
+        private void executeBlock(SuperBlock work) {
+            int bc = 0;
+            int next = 0;
+
+            if (DEBUGSTACKMAP) {
+                System.out.println("working on sb " + work.getIndex());
+                System.out.println("initial type state:");
+                TypeInfo.print(locals, localsTop, stack, stackTop,
+                               itsConstantPool);
+            }
+
+            for (int bci = work.getStart(); bci < work.getEnd(); bci += next) {
+                bc = itsCodeBuffer[bci] & 0xFF;
+                next = execute(bci);
+
+                // If we have a branch to some super block, we need to merge
+                // the current state of the local table and op stack with what's
+                // currently stored as the initial state of the super block. If
+                // something actually changed, we need to add it to the work
+                // list.
+                if (isBranch(bc)) {
+                    SuperBlock targetSB = getBranchTarget(bci);
+                    if (DEBUGSTACKMAP) {
+                        System.out.println("sb " + work.getIndex() +
+                                           " points to sb " +
+                                           targetSB.getIndex() +
+                                           " (offset " + bci + " -> " +
+                                           targetSB.getStart() + ")");
+                        System.out.println("type state at " + bci + ":");
+                        TypeInfo.print(locals, localsTop, stack, stackTop,
+                                       itsConstantPool);
+                    }
+                    flowInto(targetSB);
+                    if (DEBUGSTACKMAP) {
+                        System.out.println("type state of " + targetSB +
+                                           " after merge:");
+                        TypeInfo.print(targetSB.getLocals(),
+                                       targetSB.getStack(), itsConstantPool);
+                    }
+                } else if (bc == ByteCode.TABLESWITCH) {
+                    int switchStart = bci + 1 + (3 & ~bci); // 3 - bci % 4
+                    int defaultOffset = getOperand(switchStart, 4);
+                    SuperBlock targetSB =
+                            getSuperBlockFromOffset(bci + defaultOffset);
+                    if (DEBUGSTACK) {
+                        System.out.println("merging sb " + work.getIndex() +
+                                           " with sb " + targetSB.getIndex());
+                    }
+                    flowInto(targetSB);
+                    int low = getOperand(switchStart + 4, 4);
+                    int high = getOperand(switchStart + 8, 4);
+                    int numCases = high - low + 1;
+                    int caseBase = switchStart + 12;
+                    for (int i = 0; i < numCases; i++) {
+                        int label = bci + getOperand(caseBase + 4 * i, 4);
+                        targetSB = getSuperBlockFromOffset(label);
+                        if (DEBUGSTACKMAP) {
+                            System.out.println("merging sb " +
+                                               work.getIndex() + " with sb " +
+                                               targetSB.getIndex());
+                        }
+                        flowInto(targetSB);
+                    }
+                }
+
+                for (int i = 0; i < itsExceptionTableTop; i++) {
+                    ExceptionTableEntry ete = itsExceptionTable[i];
+                    short startPC = (short) getLabelPC(ete.itsStartLabel);
+                    short endPC = (short) getLabelPC(ete.itsEndLabel);
+                    if (bci < startPC || bci >= endPC) {
+                        continue;
+                    }
+                    short handlerPC =
+                            (short) getLabelPC(ete.itsHandlerLabel);
+                    SuperBlock sb = getSuperBlockFromOffset(handlerPC);
+                    int exceptionType;
+
+                    if (ete.itsCatchType == 0) {
+                        exceptionType = TypeInfo.OBJECT(
+                            itsConstantPool.addClass("java/lang/Throwable"));
+                    } else {
+                        exceptionType = TypeInfo.OBJECT(ete.itsCatchType);
+                    }
+                    sb.merge(locals, localsTop, new int[] { exceptionType }, 1,
+                             itsConstantPool);
+                    addToWorkList(sb);
+                }
+            }
+
+            if (DEBUGSTACKMAP) {
+                System.out.println("end of sb " + work.getIndex() + ":");
+                TypeInfo.print(locals, localsTop, stack, stackTop,
+                               itsConstantPool);
+            }
+
+            // Check the last instruction to see if it is a true end of a
+            // super block (ie., if the instruction is a return). If it
+            // isn't, we need to continue processing the next chunk.
+            if (!isSuperBlockEnd(bc)) {
+                int nextIndex = work.getIndex() + 1;
+                if (nextIndex < superBlocks.length) {
+                    if (DEBUGSTACKMAP) {
+                        System.out.println("continuing from sb " +
+                                           work.getIndex() + " into sb " +
+                                           nextIndex);
+                    }
+                    flowInto(superBlocks[nextIndex]);
+                }
+            }
+        }
+
+        /**
+         * Perform a merge of type state and add the super block to the work
+         * list if the merge changed anything.
+         */
+        private void flowInto(SuperBlock sb) {
+            if (sb.merge(locals, localsTop, stack, stackTop, itsConstantPool)) {
+                addToWorkList(sb);
+            }
+        }
+
+        private void addToWorkList(SuperBlock sb) {
+            if (!sb.isInQueue()) {
+                sb.setInQueue(true);
+                sb.setInitialized(true);
+                if (workListTop == workList.length) {
+                    SuperBlock[] tmp = new SuperBlock[workListTop * 2];
+                    System.arraycopy(workList, 0, tmp, 0, workListTop);
+                    workList = tmp;
+                }
+                workList[workListTop++] = sb;
+            }
+        }
+
+        /**
+         * Execute a single byte code instruction.
+         *
+         * @param bci the index of the byte code instruction to execute
+         * @return the length of the byte code instruction
+         */
+        private int execute(int bci) {
+            int bc = itsCodeBuffer[bci] & 0xFF;
+            int type, type2, index;
+            int length = 0;
+            long lType, lType2;
+            String className;
+
+            switch (bc) {
+                case ByteCode.NOP:
+                case ByteCode.IINC:
+                case ByteCode.GOTO:
+                case ByteCode.GOTO_W:
+                    // No change
+                    break;
+                case ByteCode.CHECKCAST:
+                    pop();
+                    push(TypeInfo.OBJECT(getOperand(bci + 1, 2)));
+                    break;
+                case ByteCode.IASTORE: // pop; pop; pop
+                case ByteCode.LASTORE:
+                case ByteCode.FASTORE:
+                case ByteCode.DASTORE:
+                case ByteCode.AASTORE:
+                case ByteCode.BASTORE:
+                case ByteCode.CASTORE:
+                case ByteCode.SASTORE:
+                    pop();
+                    // fallthru
+                case ByteCode.PUTFIELD: // pop; pop
+                case ByteCode.IF_ICMPEQ:
+                case ByteCode.IF_ICMPNE:
+                case ByteCode.IF_ICMPLT:
+                case ByteCode.IF_ICMPGE:
+                case ByteCode.IF_ICMPGT:
+                case ByteCode.IF_ICMPLE:
+                case ByteCode.IF_ACMPEQ:
+                case ByteCode.IF_ACMPNE:
+                    pop();
+                    // fallthru
+                case ByteCode.IFEQ: // pop
+                case ByteCode.IFNE:
+                case ByteCode.IFLT:
+                case ByteCode.IFGE:
+                case ByteCode.IFGT:
+                case ByteCode.IFLE:
+                case ByteCode.IFNULL:
+                case ByteCode.IFNONNULL:
+                case ByteCode.POP:
+                case ByteCode.MONITORENTER:
+                case ByteCode.MONITOREXIT:
+                case ByteCode.PUTSTATIC:
+                    pop();
+                    break;
+                case ByteCode.POP2:
+                    pop2();
+                    break;
+                case ByteCode.ACONST_NULL:
+                    push(TypeInfo.NULL);
+                    break;
+                case ByteCode.IALOAD: // pop; pop; push(INTEGER)
+                case ByteCode.BALOAD:
+                case ByteCode.CALOAD:
+                case ByteCode.SALOAD:
+                case ByteCode.IADD:
+                case ByteCode.ISUB:
+                case ByteCode.IMUL:
+                case ByteCode.IDIV:
+                case ByteCode.IREM:
+                case ByteCode.ISHL:
+                case ByteCode.ISHR:
+                case ByteCode.IUSHR:
+                case ByteCode.IAND:
+                case ByteCode.IOR:
+                case ByteCode.IXOR:
+                case ByteCode.LCMP:
+                case ByteCode.FCMPL:
+                case ByteCode.FCMPG:
+                case ByteCode.DCMPL:
+                case ByteCode.DCMPG:
+                    pop();
+                    // fallthru
+                case ByteCode.INEG: // pop; push(INTEGER)
+                case ByteCode.L2I:
+                case ByteCode.F2I:
+                case ByteCode.D2I:
+                case ByteCode.I2B:
+                case ByteCode.I2C:
+                case ByteCode.I2S:
+                case ByteCode.ARRAYLENGTH:
+                case ByteCode.INSTANCEOF:
+                    pop();
+                    // fallthru
+                case ByteCode.ICONST_M1: // push(INTEGER)
+                case ByteCode.ICONST_0:
+                case ByteCode.ICONST_1:
+                case ByteCode.ICONST_2:
+                case ByteCode.ICONST_3:
+                case ByteCode.ICONST_4:
+                case ByteCode.ICONST_5:
+                case ByteCode.ILOAD:
+                case ByteCode.ILOAD_0:
+                case ByteCode.ILOAD_1:
+                case ByteCode.ILOAD_2:
+                case ByteCode.ILOAD_3:
+                case ByteCode.BIPUSH:
+                case ByteCode.SIPUSH:
+                    push(TypeInfo.INTEGER);
+                    break;
+                case ByteCode.LALOAD: // pop; pop; push(LONG)
+                case ByteCode.LADD:
+                case ByteCode.LSUB:
+                case ByteCode.LMUL:
+                case ByteCode.LDIV:
+                case ByteCode.LREM:
+                case ByteCode.LSHL:
+                case ByteCode.LSHR:
+                case ByteCode.LUSHR:
+                case ByteCode.LAND:
+                case ByteCode.LOR:
+                case ByteCode.LXOR:
+                    pop();
+                    // fallthru
+                case ByteCode.LNEG: // pop; push(LONG)
+                case ByteCode.I2L:
+                case ByteCode.F2L:
+                case ByteCode.D2L:
+                    pop();
+                    // fallthru
+                case ByteCode.LCONST_0: // push(LONG)
+                case ByteCode.LCONST_1:
+                case ByteCode.LLOAD:
+                case ByteCode.LLOAD_0:
+                case ByteCode.LLOAD_1:
+                case ByteCode.LLOAD_2:
+                case ByteCode.LLOAD_3:
+                    push(TypeInfo.LONG);
+                    break;
+                case ByteCode.FALOAD: // pop; pop; push(FLOAT)
+                case ByteCode.FADD:
+                case ByteCode.FSUB:
+                case ByteCode.FMUL:
+                case ByteCode.FDIV:
+                case ByteCode.FREM:
+                    pop();
+                    // fallthru
+                case ByteCode.FNEG: // pop; push(FLOAT)
+                case ByteCode.I2F:
+                case ByteCode.L2F:
+                case ByteCode.D2F:
+                    pop();
+                    // fallthru
+                case ByteCode.FCONST_0: // push(FLOAT)
+                case ByteCode.FCONST_1:
+                case ByteCode.FCONST_2:
+                case ByteCode.FLOAD:
+                case ByteCode.FLOAD_0:
+                case ByteCode.FLOAD_1:
+                case ByteCode.FLOAD_2:
+                case ByteCode.FLOAD_3:
+                    push(TypeInfo.FLOAT);
+                    break;
+                case ByteCode.DALOAD: // pop; pop; push(DOUBLE)
+                case ByteCode.DADD:
+                case ByteCode.DSUB:
+                case ByteCode.DMUL:
+                case ByteCode.DDIV:
+                case ByteCode.DREM:
+                    pop();
+                    // fallthru
+                case ByteCode.DNEG: // pop; push(DOUBLE)
+                case ByteCode.I2D:
+                case ByteCode.L2D:
+                case ByteCode.F2D:
+                    pop();
+                    // fallthru
+                case ByteCode.DCONST_0: // push(DOUBLE)
+                case ByteCode.DCONST_1:
+                case ByteCode.DLOAD:
+                case ByteCode.DLOAD_0:
+                case ByteCode.DLOAD_1:
+                case ByteCode.DLOAD_2:
+                case ByteCode.DLOAD_3:
+                    push(TypeInfo.DOUBLE);
+                    break;
+                case ByteCode.ISTORE:
+                    executeStore(getOperand(bci + 1, wide ? 2 : 1), TypeInfo.INTEGER);
+                    break;
+                case ByteCode.ISTORE_0:
+                case ByteCode.ISTORE_1:
+                case ByteCode.ISTORE_2:
+                case ByteCode.ISTORE_3:
+                    executeStore(bc - ByteCode.ISTORE_0, TypeInfo.INTEGER);
+                    break;
+                case ByteCode.LSTORE:
+                    executeStore(getOperand(bci + 1, wide ? 2 : 1), TypeInfo.LONG);
+                    break;
+                case ByteCode.LSTORE_0:
+                case ByteCode.LSTORE_1:
+                case ByteCode.LSTORE_2:
+                case ByteCode.LSTORE_3:
+                    executeStore(bc - ByteCode.LSTORE_0, TypeInfo.LONG);
+                    break;
+                case ByteCode.FSTORE:
+                    executeStore(getOperand(bci + 1, wide ? 2 : 1), TypeInfo.FLOAT);
+                    break;
+                case ByteCode.FSTORE_0:
+                case ByteCode.FSTORE_1:
+                case ByteCode.FSTORE_2:
+                case ByteCode.FSTORE_3:
+                    executeStore(bc - ByteCode.FSTORE_0, TypeInfo.FLOAT);
+                    break;
+                case ByteCode.DSTORE:
+                    executeStore(getOperand(bci + 1, wide ? 2 : 1), TypeInfo.DOUBLE);
+                    break;
+                case ByteCode.DSTORE_0:
+                case ByteCode.DSTORE_1:
+                case ByteCode.DSTORE_2:
+                case ByteCode.DSTORE_3:
+                    executeStore(bc - ByteCode.DSTORE_0, TypeInfo.DOUBLE);
+                    break;
+                case ByteCode.ALOAD:
+                    executeALoad(getOperand(bci + 1, wide ? 2 : 1));
+                    break;
+                case ByteCode.ALOAD_0:
+                case ByteCode.ALOAD_1:
+                case ByteCode.ALOAD_2:
+                case ByteCode.ALOAD_3:
+                    executeALoad(bc - ByteCode.ALOAD_0);
+                    break;
+                case ByteCode.ASTORE:
+                    executeAStore(getOperand(bci + 1, wide ? 2 : 1));
+                    break;
+                case ByteCode.ASTORE_0:
+                case ByteCode.ASTORE_1:
+                case ByteCode.ASTORE_2:
+                case ByteCode.ASTORE_3:
+                    executeAStore(bc - ByteCode.ASTORE_0);
+                    break;
+                case ByteCode.IRETURN:
+                case ByteCode.LRETURN:
+                case ByteCode.FRETURN:
+                case ByteCode.DRETURN:
+                case ByteCode.ARETURN:
+                case ByteCode.RETURN:
+                    clearStack();
+                    break;
+                case ByteCode.ATHROW:
+                    type = pop();
+                    clearStack();
+                    push(type);
+                    break;
+                case ByteCode.SWAP:
+                    type = pop();
+                    type2 = pop();
+                    push(type);
+                    push(type2);
+                    break;
+                case ByteCode.LDC:
+                case ByteCode.LDC_W:
+                case ByteCode.LDC2_W:
+                    if (bc == ByteCode.LDC) {
+                        index = getOperand(bci + 1);
+                    } else {
+                        index = getOperand(bci + 1, 2);
+                    }
+                    byte constType = itsConstantPool.getConstantType(index);
+                    switch (constType) {
+                        case ConstantPool.CONSTANT_Double:
+                            push(TypeInfo.DOUBLE);
+                            break;
+                        case ConstantPool.CONSTANT_Float:
+                            push(TypeInfo.FLOAT);
+                            break;
+                        case ConstantPool.CONSTANT_Long:
+                            push(TypeInfo.LONG);
+                            break;
+                        case ConstantPool.CONSTANT_Integer:
+                            push(TypeInfo.INTEGER);
+                            break;
+                        case ConstantPool.CONSTANT_String:
+                            push(TypeInfo.OBJECT("java/lang/String",
+                                                 itsConstantPool));
+                            break;
+                        default:
+                            throw new IllegalArgumentException(
+                                "bad const type " + constType);
+                    }
+                    break;
+                case ByteCode.NEW:
+                    push(TypeInfo.UNINITIALIZED_VARIABLE(bci));
+                    break;
+                case ByteCode.NEWARRAY:
+                    pop();
+                    char componentType =
+                            arrayTypeToName(itsCodeBuffer[bci + 1]);
+                    index = itsConstantPool.addClass("[" + componentType);
+                    push(TypeInfo.OBJECT((short) index));
+                    break;
+                case ByteCode.ANEWARRAY:
+                    index = getOperand(bci + 1, 2);
+                    className = (String) itsConstantPool.getConstantData(index);
+                    pop();
+                    push(TypeInfo.OBJECT("[L" + className + ';',
+                                         itsConstantPool));
+                    break;
+                case ByteCode.INVOKEVIRTUAL:
+                case ByteCode.INVOKESPECIAL:
+                case ByteCode.INVOKESTATIC:
+                case ByteCode.INVOKEINTERFACE:
+                    index = getOperand(bci + 1, 2);
+                    FieldOrMethodRef m = (FieldOrMethodRef)
+                            itsConstantPool.getConstantData(index);
+                    String methodType = m.getType();
+                    String methodName = m.getName();
+                    int parameterCount = sizeOfParameters(methodType) >>> 16;
+                    for (int i = 0; i < parameterCount; i++) {
+                        pop();
+                    }
+                    if (bc != ByteCode.INVOKESTATIC) {
+                        int instType = pop();
+                        int tag = TypeInfo.getTag(instType);
+                        if (tag == TypeInfo.UNINITIALIZED_VARIABLE(0) ||
+                            tag == TypeInfo.UNINITIALIZED_THIS) {
+                            if ("<init>".equals(methodName)) {
+                                int newType =
+                                        TypeInfo.OBJECT(itsThisClassIndex);
+                                initializeTypeInfo(instType, newType);
+                            } else {
+                                throw new IllegalStateException("bad instance");
+                            }
+                        }
+                    }
+                    int rParen = methodType.indexOf(')');
+                    String returnType = methodType.substring(rParen + 1);
+                    returnType = descriptorToInternalName(returnType);
+                    if (!returnType.equals("V")) {
+                        push(TypeInfo.fromType(returnType, itsConstantPool));
+                    }
+                    break;
+                case ByteCode.GETFIELD:
+                    pop();
+                    // fallthru
+                case ByteCode.GETSTATIC:
+                    index = getOperand(bci + 1, 2);
+                    FieldOrMethodRef f = (FieldOrMethodRef)
+                            itsConstantPool.getConstantData(index);
+                    String fieldType = descriptorToInternalName(f.getType());
+                    push(TypeInfo.fromType(fieldType, itsConstantPool));
+                    break;
+                case ByteCode.DUP:
+                    type = pop();
+                    push(type);
+                    push(type);
+                    break;
+                case ByteCode.DUP_X1:
+                    type = pop();
+                    type2 = pop();
+                    push(type);
+                    push(type2);
+                    push(type);
+                    break;
+                case ByteCode.DUP_X2:
+                    type = pop();
+                    lType = pop2();
+                    push(type);
+                    push2(lType);
+                    push(type);
+                    break;
+                case ByteCode.DUP2:
+                    lType = pop2();
+                    push2(lType);
+                    push2(lType);
+                    break;
+                case ByteCode.DUP2_X1:
+                    lType = pop2();
+                    type = pop();
+                    push2(lType);
+                    push(type);
+                    push2(lType);
+                    break;
+                case ByteCode.DUP2_X2:
+                    lType = pop2();
+                    lType2 = pop2();
+                    push2(lType);
+                    push2(lType2);
+                    push2(lType);
+                    break;
+                case ByteCode.TABLESWITCH:
+                    int switchStart = bci + 1 + (3 & ~bci);
+                    int low = getOperand(switchStart + 4, 4);
+                    int high = getOperand(switchStart + 8, 4);
+                    length = 4 * (high - low + 4) + switchStart - bci;
+                    pop();
+                    break;
+                case ByteCode.AALOAD:
+                    pop();
+                    int typeIndex = pop() >>> 8;
+                    className =
+                            (String) itsConstantPool.getConstantData(typeIndex);
+                    String arrayType = className;
+                    if (arrayType.charAt(0) != '[') {
+                        throw new IllegalStateException("bad array type");
+                    }
+                    String elementDesc = arrayType.substring(1);
+                    String elementType = descriptorToInternalName(elementDesc);
+                    typeIndex = itsConstantPool.addClass(elementType);
+                    push(TypeInfo.OBJECT(typeIndex));
+                    break;
+                case ByteCode.WIDE:
+                    // Alters behaviour of next instruction
+                    wide = true;
+                    break;
+                case ByteCode.MULTIANEWARRAY:
+                case ByteCode.LOOKUPSWITCH:
+                    // Currently not used in any part of Rhino, so ignore it
+                case ByteCode.JSR: // TODO: JSR is deprecated
+                case ByteCode.RET:
+                case ByteCode.JSR_W:
+                default:
+                    throw new IllegalArgumentException("bad opcode: " + bc);
+            }
+
+            if (length == 0) {
+                length = opcodeLength(bc, wide);
+            }
+            if (wide && bc != ByteCode.WIDE) {
+                wide = false;
+            }
+            return length;
+        }
+
+        private void executeALoad(int localIndex) {
+            int type = getLocal(localIndex);
+            int tag = TypeInfo.getTag(type);
+            if (tag == TypeInfo.OBJECT_TAG ||
+                tag == TypeInfo.UNINITIALIZED_THIS ||
+                tag == TypeInfo.UNINITIALIZED_VAR_TAG ||
+                tag == TypeInfo.NULL) {
+                push(type);
+            } else {
+                throw new IllegalStateException("bad local variable type: " +
+                                                type + " at index: " +
+                                                localIndex);
+            }
+        }
+
+        private void executeAStore(int localIndex) {
+            setLocal(localIndex, pop());
+        }
+
+        private void executeStore(int localIndex, int typeInfo) {
+            pop();
+            setLocal(localIndex, typeInfo);
+        }
+
+        /**
+         * Change an UNINITIALIZED_OBJECT or UNINITIALIZED_THIS to the proper
+         * type of the object. This occurs when the proper constructor is
+         * invoked.
+         */
+        private void initializeTypeInfo(int prevType, int newType) {
+            initializeTypeInfo(prevType, newType, locals, localsTop);
+            initializeTypeInfo(prevType, newType, stack, stackTop);
+        }
+
+        private void initializeTypeInfo(int prevType, int newType, int[] data,
+                                        int dataTop) {
+            for (int i = 0; i < dataTop; i++) {
+                if (data[i] == prevType) {
+                    data[i] = newType;
+                }
+            }
+        }
+
+        private int getLocal(int localIndex) {
+            if (localIndex < localsTop) {
+                return locals[localIndex];
+            } else {
+                return TypeInfo.TOP;
+            }
+        }
+
+        private void setLocal(int localIndex, int typeInfo) {
+            if (localIndex >= localsTop) {
+                int[] tmp = new int[localIndex + 1];
+                System.arraycopy(locals, 0, tmp, 0, localsTop);
+                locals = tmp;
+                localsTop = localIndex + 1;
+            }
+            locals[localIndex] = typeInfo;
+        }
+
+        private void push(int typeInfo) {
+            if (stackTop == stack.length) {
+                int[] tmp = new int[Math.max(stackTop * 2, 4)];
+                System.arraycopy(stack, 0, tmp, 0, stackTop);
+                stack = tmp;
+            }
+            stack[stackTop++] = typeInfo;
+        }
+
+        private int pop() {
+            return stack[--stackTop];
+        }
+
+        /**
+         * Push two words onto the op stack.
+         *
+         * This is only meant to be used as a complement to pop2(), and both
+         * methods are helpers for the more complex DUP operations.
+         */
+        private void push2(long typeInfo) {
+            push((int) (typeInfo & 0xFFFFFF));
+            typeInfo >>>= 32;
+            if (typeInfo != 0) {
+                push((int) (typeInfo & 0xFFFFFF));
+            }
+        }
+
+        /**
+         * Pop two words from the op stack.
+         *
+         * If the top of the stack is a DOUBLE or LONG, then the bottom 32 bits
+         * reflects the appropriate type and the top 32 bits are 0. Otherwise,
+         * the top 32 bits are the first word on the stack and the lower 32
+         * bits are the second word on the stack.
+         */
+        private long pop2() {
+            long type = pop();
+            if (TypeInfo.isTwoWords((int) type)) {
+                return type;
+            } else {
+                return type << 32 | (pop() & 0xFFFFFF);
+            }
+        }
+
+        private void clearStack() {
+            stackTop = 0;
+        }
+
+        /**
+         * Compute the output size of the stack map table.
+         *
+         * Because this would share much in common with actual writing of the
+         * stack map table, we instead just write the stack map table to a
+         * buffer and return the size from it. The buffer is later used in
+         * the actual writing of bytecode.
+         */
+        int computeWriteSize() {
+            // Allocate a buffer that can handle the worst case size of the
+            // stack map to prevent lots of reallocations.
+            int writeSize = getWorstCaseWriteSize();
+            rawStackMap = new byte[writeSize];
+            computeRawStackMap();
+            return rawStackMapTop + 2;
+        }
+
+        int write(byte[] data, int offset) {
+            offset = putInt32(rawStackMapTop + 2, data, offset);
+            offset = putInt16(superBlocks.length - 1, data, offset);
+            System.arraycopy(rawStackMap, 0, data, offset, rawStackMapTop);
+            return offset + rawStackMapTop;
+        }
+
+        /**
+         * Compute a space-optimal stack map table.
+         */
+        private void computeRawStackMap() {
+            SuperBlock prev = superBlocks[0];
+            int[] prevLocals = prev.getTrimmedLocals();
+            int prevOffset = -1;
+            for (int i = 1; i < superBlocks.length; i++) {
+                SuperBlock current = superBlocks[i];
+                int[] currentLocals = current.getTrimmedLocals();
+                int[] currentStack = current.getStack();
+                int offsetDelta = current.getStart() - prevOffset - 1;
+
+                if (currentStack.length == 0) {
+                    int last = prevLocals.length > currentLocals.length ?
+                            currentLocals.length : prevLocals.length;
+                    int delta = Math.abs(prevLocals.length -
+                                         currentLocals.length);
+                    int j;
+                    // Compare locals until one is different or the end of a
+                    // local variable array is reached
+                    for (j = 0; j < last; j++) {
+                        if (prevLocals[j] != currentLocals[j]) {
+                            break;
+                        }
+                    }
+                    if (j == currentLocals.length && delta == 0) {
+                        // All of the compared locals are equal and the local
+                        // arrays are of equal size
+                        writeSameFrame(currentLocals, offsetDelta);
+                    } else if (j == currentLocals.length && delta <= 3) {
+                        // All of the compared locals are equal and the current
+                        // frame has less locals than the previous frame
+                        writeChopFrame(delta, offsetDelta);
+                    } else if (j == prevLocals.length && delta <= 3) {
+                        // All of the compared locals are equal and the current
+                        // frame has more locals than the previous frame
+                        writeAppendFrame(currentLocals, delta, offsetDelta);
+                    } else {
+                        // Not all locals were compared were equal, so a full
+                        // frame is necessary
+                        writeFullFrame(currentLocals, currentStack,
+                                       offsetDelta);
+                    }
+                } else if (currentStack.length == 1) {
+                    if (Arrays.equals(prevLocals, currentLocals)) {
+                       writeSameLocalsOneStackItemFrame(currentLocals,
+                                                        currentStack,
+                                                        offsetDelta);
+                    } else {
+                        // Output a full frame, since no other frame types have
+                        // one operand stack item.
+                        writeFullFrame(currentLocals, currentStack,
+                                       offsetDelta);
+                    }
+                } else {
+                    // Any stack map frame that has more than one operand stack
+                    // item has to be a full frame. All other frame types have
+                    // at most one item on the stack.
+                    writeFullFrame(currentLocals, currentStack, offsetDelta);
+                }
+
+                prev = current;
+                prevLocals = currentLocals;
+                prevOffset = current.getStart();
+            }
+        }
+
+        /**
+         * Get the worst case write size of the stack map table.
+         *
+         * This computes how much full frames would take, if each full frame
+         * contained the maximum number of locals and stack operands, and each
+         * verification type was 3 bytes.
+         */
+        private int getWorstCaseWriteSize() {
+            return (superBlocks.length - 1) * (7 + itsMaxLocals * 3 +
+                                               itsMaxStack * 3);
+        }
+
+        private void writeSameFrame(int[] locals, int offsetDelta) {
+            if (offsetDelta <= 63) {
+                // Output a same_frame frame. Despite the name,
+                // the operand stack may differ, but the current
+                // operand stack must be empty.
+                rawStackMap[rawStackMapTop++] = (byte) offsetDelta;
+            } else {
+                // Output a same_frame_extended frame. Similar to
+                // the above, except with a larger offset delta.
+                rawStackMap[rawStackMapTop++] = (byte) 251;
+                rawStackMapTop = putInt16(offsetDelta, rawStackMap,
+                                          rawStackMapTop);
+            }
+        }
+
+        private void writeSameLocalsOneStackItemFrame(int[] locals,
+                                                      int[] stack,
+                                                      int offsetDelta) {
+            if (offsetDelta <= 63) {
+                // Output a same_locals_1_stack_item frame. Similar
+                // to same_frame, only with one item on the operand
+                // stack instead of zero.
+                rawStackMap[rawStackMapTop++] = (byte) (64 + offsetDelta);
+            } else {
+                // Output a same_locals_1_stack_item_extended frame.
+                // Similar to same_frame_extended, only with one
+                // item on the operand stack instead of zero.
+                rawStackMap[rawStackMapTop++] = (byte) 247;
+                rawStackMapTop = putInt16(offsetDelta, rawStackMap,
+                                          rawStackMapTop);
+            }
+            writeType(stack[0]);
+        }
+
+        private void writeFullFrame(int[] locals, int[] stack,
+                                    int offsetDelta) {
+            rawStackMap[rawStackMapTop++] = (byte) 255;
+            rawStackMapTop = putInt16(offsetDelta, rawStackMap, rawStackMapTop);
+            rawStackMapTop = putInt16(locals.length, rawStackMap,
+                                      rawStackMapTop);
+            rawStackMapTop = writeTypes(locals);
+            rawStackMapTop = putInt16(stack.length, rawStackMap,
+                                      rawStackMapTop);
+            rawStackMapTop = writeTypes(stack);
+        }
+
+        private void writeAppendFrame(int[] locals, int localsDelta,
+                                      int offsetDelta) {
+            int start = locals.length - localsDelta;
+            rawStackMap[rawStackMapTop++] = (byte) (251 + localsDelta);
+            rawStackMapTop = putInt16(offsetDelta, rawStackMap, rawStackMapTop);
+            rawStackMapTop = writeTypes(locals, start);
+        }
+
+        private void writeChopFrame(int localsDelta, int offsetDelta) {
+            rawStackMap[rawStackMapTop++] = (byte) (251 - localsDelta);
+            rawStackMapTop = putInt16(offsetDelta, rawStackMap, rawStackMapTop);
+        }
+
+        private int writeTypes(int[] types) {
+            return writeTypes(types, 0);
+        }
+
+        private int writeTypes(int[] types, int start) {
+            int startOffset = rawStackMapTop;
+            for (int i = start; i < types.length; i++) {
+                rawStackMapTop = writeType(types[i]);
+            }
+            return rawStackMapTop;
+        }
+
+        private int writeType(int type) {
+            int tag = type & 0xFF;
+            rawStackMap[rawStackMapTop++] = (byte) tag;
+            if (tag == TypeInfo.OBJECT_TAG ||
+                tag == TypeInfo.UNINITIALIZED_VAR_TAG) {
+                rawStackMapTop = putInt16(type >>> 8, rawStackMap,
+                                          rawStackMapTop);
+            }
+            return rawStackMapTop;
+        }
+
+        // Intermediate operand stack and local variable state. During
+        // execution of a block, these are initialized to copies of the initial
+        // block type state and are modified by the actual stack/local
+        // emulation.
+        private int[] locals;
+        private int localsTop;
+        private int[] stack;
+        private int stackTop;
+
+        private SuperBlock[] workList;
+        private int workListTop;
+
+        private SuperBlock[] superBlocks;
+        private SuperBlock[] superBlockDeps;
+
+        private byte[] rawStackMap;
+        private int rawStackMapTop;
+
+        private boolean wide;
+
+        static final boolean DEBUGSTACKMAP = false;
+    }
+
+    /**
+     * Convert a newarray operand into an internal type.
+     */
+    private static char arrayTypeToName(int type) {
+        switch (type) {
+            case ByteCode.T_BOOLEAN:
+                return 'Z';
+            case ByteCode.T_CHAR:
+                return 'C';
+            case ByteCode.T_FLOAT:
+                return 'F';
+            case ByteCode.T_DOUBLE:
+                return 'D';
+            case ByteCode.T_BYTE:
+                return 'B';
+            case ByteCode.T_SHORT:
+                return 'S';
+            case ByteCode.T_INT:
+                return 'I';
+            case ByteCode.T_LONG:
+                return 'J';
+            default:
+                throw new IllegalArgumentException("bad operand");
+        }
+    }
+
+    /**
+     * Convert a class descriptor into an internal name.
+     *
+     * For example, descriptor Ljava/lang/Object; becomes java/lang/Object.
+     */
+    private static String classDescriptorToInternalName(String descriptor) {
+        return descriptor.substring(1, descriptor.length() - 1);
+    }
+
+    /**
+     * Convert a non-method type descriptor into an internal type.
+     *
+     * @param descriptor the simple type descriptor to convert
+     */
+    private static String descriptorToInternalName(String descriptor) {
+        switch (descriptor.charAt(0)) {
+            case 'B':
+            case 'C':
+            case 'D':
+            case 'F':
+            case 'I':
+            case 'J':
+            case 'S':
+            case 'Z':
+            case 'V':
+            case '[':
+                return descriptor;
+            case 'L':
+                return classDescriptorToInternalName(descriptor);
+            default:
+                throw new IllegalArgumentException("bad descriptor:" +
+                                                   descriptor);
+        }
+    }
+
+    /**
+     * Compute the initial local variable array for the current method.
+     *
+     * Creates an array of the size of the method's max locals, regardless of
+     * the number of parameters in the method.
+     */
+    private int[] createInitialLocals() {
+        int[] initialLocals = new int[itsMaxLocals];
+        int localsTop = 0;
+        // Instance methods require the first local variable in the array
+        // to be "this". However, if the method being created is a
+        // constructor, aka the method is <init>, then the type of "this"
+        // should be StackMapTable.UNINITIALIZED_THIS
+        if ((itsCurrentMethod.getFlags() & ACC_STATIC) == 0) {
+            if ("<init>".equals(itsCurrentMethod.getName())) {
+                initialLocals[localsTop++] = TypeInfo.UNINITIALIZED_THIS;
+            } else {
+                initialLocals[localsTop++] = TypeInfo.OBJECT(itsThisClassIndex);
+            }
+        }
+
+        // No error checking should be necessary, sizeOfParameters does this
+        String type = itsCurrentMethod.getType();
+        int lParenIndex = type.indexOf('(');
+        int rParenIndex = type.indexOf(')');
+        if (lParenIndex != 0 || rParenIndex < 0) {
+            throw new IllegalArgumentException("bad method type");
+        }
+        int start = lParenIndex + 1;
+        StringBuilder paramType = new StringBuilder();
+        while (start < rParenIndex) {
+            switch (type.charAt(start)) {
+                case 'B':
+                case 'C':
+                case 'D':
+                case 'F':
+                case 'I':
+                case 'J':
+                case 'S':
+                case 'Z':
+                    paramType.append(type.charAt(start));
+                    ++start;
+                    break;
+                case 'L':
+                    int end = type.indexOf(';', start) + 1;
+                    String name = type.substring(start, end);
+                    paramType.append(name);
+                    start = end;
+                    break;
+                case '[':
+                    paramType.append('[');
+                    ++start;
+                    continue;
+            }
+            String internalType =
+                    descriptorToInternalName(paramType.toString());
+            int typeInfo = TypeInfo.fromType(internalType, itsConstantPool);
+            initialLocals[localsTop++] = typeInfo;
+            if (TypeInfo.isTwoWords(typeInfo)) {
+                localsTop++;
+            }
+            paramType.setLength(0);
+        }
+        return initialLocals;
+    }
+
+    /**
+     * Write the class file to the OutputStream.
+     *
+     * @param oStream the stream to write to
+     * @throws IOException if writing to the stream produces an exception
+     */
+    public void write(OutputStream oStream)
+        throws IOException
+    {
+        byte[] array = toByteArray();
+        oStream.write(array);
+    }
+
+    private int getWriteSize()
+    {
+        int size = 0;
+
+        if (itsSourceFileNameIndex != 0) {
+            itsConstantPool.addUtf8("SourceFile");
+        }
+
+        size += 8; //writeLong(FileHeaderConstant);
+        size += itsConstantPool.getWriteSize();
+        size += 2; //writeShort(itsFlags);
+        size += 2; //writeShort(itsThisClassIndex);
+        size += 2; //writeShort(itsSuperClassIndex);
+        size += 2; //writeShort(itsInterfaces.size());
+        size += 2 * itsInterfaces.size();
+
+        size += 2; //writeShort(itsFields.size());
+        for (int i = 0; i < itsFields.size(); i++) {
+            size += ((ClassFileField)(itsFields.get(i))).getWriteSize();
+        }
+
+        size += 2; //writeShort(itsMethods.size());
+        for (int i = 0; i < itsMethods.size(); i++) {
+            size += ((ClassFileMethod)(itsMethods.get(i))).getWriteSize();
+        }
+
+        if (itsSourceFileNameIndex != 0) {
+            size += 2; //writeShort(1);  attributes count
+            size += 2; //writeShort(sourceFileAttributeNameIndex);
+            size += 4; //writeInt(2);
+            size += 2; //writeShort(itsSourceFileNameIndex);
+        }else {
+            size += 2; //out.writeShort(0);  no attributes
+        }
+
+        return size;
+    }
+
+    /**
+     * Get the class file as array of bytesto the OutputStream.
+     */
+    public byte[] toByteArray()
+    {
+        int dataSize = getWriteSize();
+        byte[] data = new byte[dataSize];
+        int offset = 0;
+
+        short sourceFileAttributeNameIndex = 0;
+        if (itsSourceFileNameIndex != 0) {
+            sourceFileAttributeNameIndex = itsConstantPool.addUtf8(
+                                               "SourceFile");
+        }
+
+        offset = putInt32(FileHeaderConstant, data, offset);
+        offset = putInt16(MinorVersion, data, offset);
+        offset = putInt16(MajorVersion, data, offset);
+        offset = itsConstantPool.write(data, offset);
+        offset = putInt16(itsFlags, data, offset);
+        offset = putInt16(itsThisClassIndex, data, offset);
+        offset = putInt16(itsSuperClassIndex, data, offset);
+        offset = putInt16(itsInterfaces.size(), data, offset);
+        for (int i = 0; i < itsInterfaces.size(); i++) {
+            int interfaceIndex = ((Short)(itsInterfaces.get(i))).shortValue();
+            offset = putInt16(interfaceIndex, data, offset);
+        }
+        offset = putInt16(itsFields.size(), data, offset);
+        for (int i = 0; i < itsFields.size(); i++) {
+            ClassFileField field = (ClassFileField)itsFields.get(i);
+            offset = field.write(data, offset);
+        }
+        offset = putInt16(itsMethods.size(), data, offset);
+        for (int i = 0; i < itsMethods.size(); i++) {
+            ClassFileMethod method = (ClassFileMethod)itsMethods.get(i);
+            offset = method.write(data, offset);
+        }
+        if (itsSourceFileNameIndex != 0) {
+            offset = putInt16(1, data, offset); // attributes count
+            offset = putInt16(sourceFileAttributeNameIndex, data, offset);
+            offset = putInt32(2, data, offset);
+            offset = putInt16(itsSourceFileNameIndex, data, offset);
+        } else {
+            offset = putInt16(0, data, offset); // no attributes
+        }
+
+        if (offset != dataSize) {
+            // Check getWriteSize is consistent with write!
+            throw new RuntimeException();
+        }
+
+        return data;
+    }
+
+    static int putInt64(long value, byte[] array, int offset)
+    {
+        offset = putInt32((int)(value >>> 32), array, offset);
+        return putInt32((int)value, array, offset);
+    }
+
+    private static void badStack(int value)
+    {
+        String s;
+        if (value < 0) { s = "Stack underflow: "+value; }
+        else { s = "Too big stack: "+value; }
+        throw new IllegalStateException(s);
+    }
+
+    /*
+        Really weird. Returns an int with # parameters in hi 16 bits, and
+        stack difference removal of parameters from stack and pushing the
+        result (it does not take into account removal of this in case of
+        non-static methods).
+        If Java really supported references we wouldn't have to be this
+        perverted.
+    */
+    private static int sizeOfParameters(String pString)
+    {
+        int length = pString.length();
+        int rightParenthesis = pString.lastIndexOf(')');
+        if (3 <= length /* minimal signature takes at least 3 chars: ()V */
+            && pString.charAt(0) == '('
+            && 1 <= rightParenthesis && rightParenthesis + 1 < length)
+        {
+            boolean ok = true;
+            int index = 1;
+            int stackDiff = 0;
+            int count = 0;
+        stringLoop:
+            while (index != rightParenthesis) {
+                switch (pString.charAt(index)) {
+                    default:
+                        ok = false;
+                        break stringLoop;
+                    case 'J' :
+                    case 'D' :
+                        --stackDiff;
+                        // fallthru
+                    case 'B' :
+                    case 'S' :
+                    case 'C' :
+                    case 'I' :
+                    case 'Z' :
+                    case 'F' :
+                        --stackDiff;
+                        ++count;
+                        ++index;
+                        continue;
+                    case '[' :
+                        ++index;
+                        int c = pString.charAt(index);
+                        while (c == '[') {
+                            ++index;
+                            c = pString.charAt(index);
+                        }
+                        switch (c) {
+                            default:
+                                ok = false;
+                                break stringLoop;
+                            case 'J' :
+                            case 'D' :
+                            case 'B' :
+                            case 'S' :
+                            case 'C' :
+                            case 'I' :
+                            case 'Z' :
+                            case 'F' :
+                                --stackDiff;
+                                ++count;
+                                ++index;
+                                continue;
+                            case 'L':
+                                // fallthru
+                        }
+                          // fallthru
+                    case 'L' : {
+                        --stackDiff;
+                        ++count;
+                        ++index;
+                        int semicolon = pString.indexOf(';',  index);
+                        if (!(index + 1 <= semicolon
+                            && semicolon < rightParenthesis))
+                        {
+                            ok = false;
+                            break stringLoop;
+                        }
+                        index = semicolon + 1;
+                        continue;
+                    }
+                }
+            }
+            if (ok) {
+                switch (pString.charAt(rightParenthesis + 1)) {
+                    default:
+                        ok = false;
+                        break;
+                    case 'J' :
+                    case 'D' :
+                        ++stackDiff;
+                        // fallthru
+                    case 'B' :
+                    case 'S' :
+                    case 'C' :
+                    case 'I' :
+                    case 'Z' :
+                    case 'F' :
+                    case 'L' :
+                    case '[' :
+                        ++stackDiff;
+                        // fallthru
+                    case 'V' :
+                        break;
+                }
+                if (ok) {
+                    return ((count << 16) | (0xFFFF & stackDiff));
+                }
+            }
+        }
+        throw new IllegalArgumentException(
+            "Bad parameter signature: "+pString);
+    }
+
+    static int putInt16(int value, byte[] array, int offset)
+    {
+        array[offset + 0] = (byte)(value >>> 8);
+        array[offset + 1] = (byte)value;
+        return offset + 2;
+    }
+
+    static int putInt32(int value, byte[] array, int offset)
+    {
+        array[offset + 0] = (byte)(value >>> 24);
+        array[offset + 1] = (byte)(value >>> 16);
+        array[offset + 2] = (byte)(value >>> 8);
+        array[offset + 3] = (byte)value;
+        return offset + 4;
+    }
+
+    /**
+     * Size of a bytecode instruction, counting the opcode and its operands.
+     *
+     * This is different from opcodeCount, since opcodeCount counts logical
+     * operands.
+     */
+    static int opcodeLength(int opcode, boolean wide) {
+        switch (opcode) {
+            case ByteCode.AALOAD:
+            case ByteCode.AASTORE:
+            case ByteCode.ACONST_NULL:
+            case ByteCode.ALOAD_0:
+            case ByteCode.ALOAD_1:
+            case ByteCode.ALOAD_2:
+            case ByteCode.ALOAD_3:
+            case ByteCode.ARETURN:
+            case ByteCode.ARRAYLENGTH:
+            case ByteCode.ASTORE_0:
+            case ByteCode.ASTORE_1:
+            case ByteCode.ASTORE_2:
+            case ByteCode.ASTORE_3:
+            case ByteCode.ATHROW:
+            case ByteCode.BALOAD:
+            case ByteCode.BASTORE:
+            case ByteCode.BREAKPOINT:
+            case ByteCode.CALOAD:
+            case ByteCode.CASTORE:
+            case ByteCode.D2F:
+            case ByteCode.D2I:
+            case ByteCode.D2L:
+            case ByteCode.DADD:
+            case ByteCode.DALOAD:
+            case ByteCode.DASTORE:
+            case ByteCode.DCMPG:
+            case ByteCode.DCMPL:
+            case ByteCode.DCONST_0:
+            case ByteCode.DCONST_1:
+            case ByteCode.DDIV:
+            case ByteCode.DLOAD_0:
+            case ByteCode.DLOAD_1:
+            case ByteCode.DLOAD_2:
+            case ByteCode.DLOAD_3:
+            case ByteCode.DMUL:
+            case ByteCode.DNEG:
+            case ByteCode.DREM:
+            case ByteCode.DRETURN:
+            case ByteCode.DSTORE_0:
+            case ByteCode.DSTORE_1:
+            case ByteCode.DSTORE_2:
+            case ByteCode.DSTORE_3:
+            case ByteCode.DSUB:
+            case ByteCode.DUP:
+            case ByteCode.DUP2:
+            case ByteCode.DUP2_X1:
+            case ByteCode.DUP2_X2:
+            case ByteCode.DUP_X1:
+            case ByteCode.DUP_X2:
+            case ByteCode.F2D:
+            case ByteCode.F2I:
+            case ByteCode.F2L:
+            case ByteCode.FADD:
+            case ByteCode.FALOAD:
+            case ByteCode.FASTORE:
+            case ByteCode.FCMPG:
+            case ByteCode.FCMPL:
+            case ByteCode.FCONST_0:
+            case ByteCode.FCONST_1:
+            case ByteCode.FCONST_2:
+            case ByteCode.FDIV:
+            case ByteCode.FLOAD_0:
+            case ByteCode.FLOAD_1:
+            case ByteCode.FLOAD_2:
+            case ByteCode.FLOAD_3:
+            case ByteCode.FMUL:
+            case ByteCode.FNEG:
+            case ByteCode.FREM:
+            case ByteCode.FRETURN:
+            case ByteCode.FSTORE_0:
+            case ByteCode.FSTORE_1:
+            case ByteCode.FSTORE_2:
+            case ByteCode.FSTORE_3:
+            case ByteCode.FSUB:
+            case ByteCode.I2B:
+            case ByteCode.I2C:
+            case ByteCode.I2D:
+            case ByteCode.I2F:
+            case ByteCode.I2L:
+            case ByteCode.I2S:
+            case ByteCode.IADD:
+            case ByteCode.IALOAD:
+            case ByteCode.IAND:
+            case ByteCode.IASTORE:
+            case ByteCode.ICONST_0:
+            case ByteCode.ICONST_1:
+            case ByteCode.ICONST_2:
+            case ByteCode.ICONST_3:
+            case ByteCode.ICONST_4:
+            case ByteCode.ICONST_5:
+            case ByteCode.ICONST_M1:
+            case ByteCode.IDIV:
+            case ByteCode.ILOAD_0:
+            case ByteCode.ILOAD_1:
+            case ByteCode.ILOAD_2:
+            case ByteCode.ILOAD_3:
+            case ByteCode.IMPDEP1:
+            case ByteCode.IMPDEP2:
+            case ByteCode.IMUL:
+            case ByteCode.INEG:
+            case ByteCode.IOR:
+            case ByteCode.IREM:
+            case ByteCode.IRETURN:
+            case ByteCode.ISHL:
+            case ByteCode.ISHR:
+            case ByteCode.ISTORE_0:
+            case ByteCode.ISTORE_1:
+            case ByteCode.ISTORE_2:
+            case ByteCode.ISTORE_3:
+            case ByteCode.ISUB:
+            case ByteCode.IUSHR:
+            case ByteCode.IXOR:
+            case ByteCode.L2D:
+            case ByteCode.L2F:
+            case ByteCode.L2I:
+            case ByteCode.LADD:
+            case ByteCode.LALOAD:
+            case ByteCode.LAND:
+            case ByteCode.LASTORE:
+            case ByteCode.LCMP:
+            case ByteCode.LCONST_0:
+            case ByteCode.LCONST_1:
+            case ByteCode.LDIV:
+            case ByteCode.LLOAD_0:
+            case ByteCode.LLOAD_1:
+            case ByteCode.LLOAD_2:
+            case ByteCode.LLOAD_3:
+            case ByteCode.LMUL:
+            case ByteCode.LNEG:
+            case ByteCode.LOR:
+            case ByteCode.LREM:
+            case ByteCode.LRETURN:
+            case ByteCode.LSHL:
+            case ByteCode.LSHR:
+            case ByteCode.LSTORE_0:
+            case ByteCode.LSTORE_1:
+            case ByteCode.LSTORE_2:
+            case ByteCode.LSTORE_3:
+            case ByteCode.LSUB:
+            case ByteCode.LUSHR:
+            case ByteCode.LXOR:
+            case ByteCode.MONITORENTER:
+            case ByteCode.MONITOREXIT:
+            case ByteCode.NOP:
+            case ByteCode.POP:
+            case ByteCode.POP2:
+            case ByteCode.RETURN:
+            case ByteCode.SALOAD:
+            case ByteCode.SASTORE:
+            case ByteCode.SWAP:
+            case ByteCode.WIDE:
+                return 1;
+            case ByteCode.BIPUSH:
+            case ByteCode.LDC:
+            case ByteCode.NEWARRAY:
+                return 2;
+            case ByteCode.ALOAD:
+            case ByteCode.ASTORE:
+            case ByteCode.DLOAD:
+            case ByteCode.DSTORE:
+            case ByteCode.FLOAD:
+            case ByteCode.FSTORE:
+            case ByteCode.ILOAD:
+            case ByteCode.ISTORE:
+            case ByteCode.LLOAD:
+            case ByteCode.LSTORE:
+            case ByteCode.RET:
+                return wide ? 3 : 2;
+
+            case ByteCode.ANEWARRAY:
+            case ByteCode.CHECKCAST:
+            case ByteCode.GETFIELD:
+            case ByteCode.GETSTATIC:
+            case ByteCode.GOTO:
+            case ByteCode.IFEQ:
+            case ByteCode.IFGE:
+            case ByteCode.IFGT:
+            case ByteCode.IFLE:
+            case ByteCode.IFLT:
+            case ByteCode.IFNE:
+            case ByteCode.IFNONNULL:
+            case ByteCode.IFNULL:
+            case ByteCode.IF_ACMPEQ:
+            case ByteCode.IF_ACMPNE:
+            case ByteCode.IF_ICMPEQ:
+            case ByteCode.IF_ICMPGE:
+            case ByteCode.IF_ICMPGT:
+            case ByteCode.IF_ICMPLE:
+            case ByteCode.IF_ICMPLT:
+            case ByteCode.IF_ICMPNE:
+            case ByteCode.INSTANCEOF:
+            case ByteCode.INVOKESPECIAL:
+            case ByteCode.INVOKESTATIC:
+            case ByteCode.INVOKEVIRTUAL:
+            case ByteCode.JSR:
+            case ByteCode.LDC_W:
+            case ByteCode.LDC2_W:
+            case ByteCode.NEW:
+            case ByteCode.PUTFIELD:
+            case ByteCode.PUTSTATIC:
+            case ByteCode.SIPUSH:
+                return 3;
+
+            case ByteCode.IINC:
+                return wide ? 5 : 3;
+
+            case ByteCode.MULTIANEWARRAY:
+                return 4;
+
+            case ByteCode.GOTO_W:
+            case ByteCode.INVOKEINTERFACE:
+            case ByteCode.JSR_W:
+                return 5;
+
+            /*
+            case ByteCode.LOOKUPSWITCH:
+            case ByteCode.TABLESWITCH:
+                return -1;
+            */
+        }
+        throw new IllegalArgumentException("Bad opcode: " + opcode);
+    }
+
+    /**
+     * Number of operands accompanying the opcode.
+     */
+    static int opcodeCount(int opcode)
+    {
+        switch (opcode) {
+            case ByteCode.AALOAD:
+            case ByteCode.AASTORE:
+            case ByteCode.ACONST_NULL:
+            case ByteCode.ALOAD_0:
+            case ByteCode.ALOAD_1:
+            case ByteCode.ALOAD_2:
+            case ByteCode.ALOAD_3:
+            case ByteCode.ARETURN:
+            case ByteCode.ARRAYLENGTH:
+            case ByteCode.ASTORE_0:
+            case ByteCode.ASTORE_1:
+            case ByteCode.ASTORE_2:
+            case ByteCode.ASTORE_3:
+            case ByteCode.ATHROW:
+            case ByteCode.BALOAD:
+            case ByteCode.BASTORE:
+            case ByteCode.BREAKPOINT:
+            case ByteCode.CALOAD:
+            case ByteCode.CASTORE:
+            case ByteCode.D2F:
+            case ByteCode.D2I:
+            case ByteCode.D2L:
+            case ByteCode.DADD:
+            case ByteCode.DALOAD:
+            case ByteCode.DASTORE:
+            case ByteCode.DCMPG:
+            case ByteCode.DCMPL:
+            case ByteCode.DCONST_0:
+            case ByteCode.DCONST_1:
+            case ByteCode.DDIV:
+            case ByteCode.DLOAD_0:
+            case ByteCode.DLOAD_1:
+            case ByteCode.DLOAD_2:
+            case ByteCode.DLOAD_3:
+            case ByteCode.DMUL:
+            case ByteCode.DNEG:
+            case ByteCode.DREM:
+            case ByteCode.DRETURN:
+            case ByteCode.DSTORE_0:
+            case ByteCode.DSTORE_1:
+            case ByteCode.DSTORE_2:
+            case ByteCode.DSTORE_3:
+            case ByteCode.DSUB:
+            case ByteCode.DUP:
+            case ByteCode.DUP2:
+            case ByteCode.DUP2_X1:
+            case ByteCode.DUP2_X2:
+            case ByteCode.DUP_X1:
+            case ByteCode.DUP_X2:
+            case ByteCode.F2D:
+            case ByteCode.F2I:
+            case ByteCode.F2L:
+            case ByteCode.FADD:
+            case ByteCode.FALOAD:
+            case ByteCode.FASTORE:
+            case ByteCode.FCMPG:
+            case ByteCode.FCMPL:
+            case ByteCode.FCONST_0:
+            case ByteCode.FCONST_1:
+            case ByteCode.FCONST_2:
+            case ByteCode.FDIV:
+            case ByteCode.FLOAD_0:
+            case ByteCode.FLOAD_1:
+            case ByteCode.FLOAD_2:
+            case ByteCode.FLOAD_3:
+            case ByteCode.FMUL:
+            case ByteCode.FNEG:
+            case ByteCode.FREM:
+            case ByteCode.FRETURN:
+            case ByteCode.FSTORE_0:
+            case ByteCode.FSTORE_1:
+            case ByteCode.FSTORE_2:
+            case ByteCode.FSTORE_3:
+            case ByteCode.FSUB:
+            case ByteCode.I2B:
+            case ByteCode.I2C:
+            case ByteCode.I2D:
+            case ByteCode.I2F:
+            case ByteCode.I2L:
+            case ByteCode.I2S:
+            case ByteCode.IADD:
+            case ByteCode.IALOAD:
+            case ByteCode.IAND:
+            case ByteCode.IASTORE:
+            case ByteCode.ICONST_0:
+            case ByteCode.ICONST_1:
+            case ByteCode.ICONST_2:
+            case ByteCode.ICONST_3:
+            case ByteCode.ICONST_4:
+            case ByteCode.ICONST_5:
+            case ByteCode.ICONST_M1:
+            case ByteCode.IDIV:
+            case ByteCode.ILOAD_0:
+            case ByteCode.ILOAD_1:
+            case ByteCode.ILOAD_2:
+            case ByteCode.ILOAD_3:
+            case ByteCode.IMPDEP1:
+            case ByteCode.IMPDEP2:
+            case ByteCode.IMUL:
+            case ByteCode.INEG:
+            case ByteCode.IOR:
+            case ByteCode.IREM:
+            case ByteCode.IRETURN:
+            case ByteCode.ISHL:
+            case ByteCode.ISHR:
+            case ByteCode.ISTORE_0:
+            case ByteCode.ISTORE_1:
+            case ByteCode.ISTORE_2:
+            case ByteCode.ISTORE_3:
+            case ByteCode.ISUB:
+            case ByteCode.IUSHR:
+            case ByteCode.IXOR:
+            case ByteCode.L2D:
+            case ByteCode.L2F:
+            case ByteCode.L2I:
+            case ByteCode.LADD:
+            case ByteCode.LALOAD:
+            case ByteCode.LAND:
+            case ByteCode.LASTORE:
+            case ByteCode.LCMP:
+            case ByteCode.LCONST_0:
+            case ByteCode.LCONST_1:
+            case ByteCode.LDIV:
+            case ByteCode.LLOAD_0:
+            case ByteCode.LLOAD_1:
+            case ByteCode.LLOAD_2:
+            case ByteCode.LLOAD_3:
+            case ByteCode.LMUL:
+            case ByteCode.LNEG:
+            case ByteCode.LOR:
+            case ByteCode.LREM:
+            case ByteCode.LRETURN:
+            case ByteCode.LSHL:
+            case ByteCode.LSHR:
+            case ByteCode.LSTORE_0:
+            case ByteCode.LSTORE_1:
+            case ByteCode.LSTORE_2:
+            case ByteCode.LSTORE_3:
+            case ByteCode.LSUB:
+            case ByteCode.LUSHR:
+            case ByteCode.LXOR:
+            case ByteCode.MONITORENTER:
+            case ByteCode.MONITOREXIT:
+            case ByteCode.NOP:
+            case ByteCode.POP:
+            case ByteCode.POP2:
+            case ByteCode.RETURN:
+            case ByteCode.SALOAD:
+            case ByteCode.SASTORE:
+            case ByteCode.SWAP:
+            case ByteCode.WIDE:
+                return 0;
+            case ByteCode.ALOAD:
+            case ByteCode.ANEWARRAY:
+            case ByteCode.ASTORE:
+            case ByteCode.BIPUSH:
+            case ByteCode.CHECKCAST:
+            case ByteCode.DLOAD:
+            case ByteCode.DSTORE:
+            case ByteCode.FLOAD:
+            case ByteCode.FSTORE:
+            case ByteCode.GETFIELD:
+            case ByteCode.GETSTATIC:
+            case ByteCode.GOTO:
+            case ByteCode.GOTO_W:
+            case ByteCode.IFEQ:
+            case ByteCode.IFGE:
+            case ByteCode.IFGT:
+            case ByteCode.IFLE:
+            case ByteCode.IFLT:
+            case ByteCode.IFNE:
+            case ByteCode.IFNONNULL:
+            case ByteCode.IFNULL:
+            case ByteCode.IF_ACMPEQ:
+            case ByteCode.IF_ACMPNE:
+            case ByteCode.IF_ICMPEQ:
+            case ByteCode.IF_ICMPGE:
+            case ByteCode.IF_ICMPGT:
+            case ByteCode.IF_ICMPLE:
+            case ByteCode.IF_ICMPLT:
+            case ByteCode.IF_ICMPNE:
+            case ByteCode.ILOAD:
+            case ByteCode.INSTANCEOF:
+            case ByteCode.INVOKEINTERFACE:
+            case ByteCode.INVOKESPECIAL:
+            case ByteCode.INVOKESTATIC:
+            case ByteCode.INVOKEVIRTUAL:
+            case ByteCode.ISTORE:
+            case ByteCode.JSR:
+            case ByteCode.JSR_W:
+            case ByteCode.LDC:
+            case ByteCode.LDC2_W:
+            case ByteCode.LDC_W:
+            case ByteCode.LLOAD:
+            case ByteCode.LSTORE:
+            case ByteCode.NEW:
+            case ByteCode.NEWARRAY:
+            case ByteCode.PUTFIELD:
+            case ByteCode.PUTSTATIC:
+            case ByteCode.RET:
+            case ByteCode.SIPUSH:
+                return 1;
+
+            case ByteCode.IINC:
+            case ByteCode.MULTIANEWARRAY:
+                return 2;
+
+            case ByteCode.LOOKUPSWITCH:
+            case ByteCode.TABLESWITCH:
+                return -1;
+        }
+        throw new IllegalArgumentException("Bad opcode: "+opcode);
+    }
+
+    /**
+     *  The effect on the operand stack of a given opcode.
+     */
+    static int stackChange(int opcode)
+    {
+        // For INVOKE... accounts only for popping this (unless static),
+        // ignoring parameters and return type
+        switch (opcode) {
+            case ByteCode.DASTORE:
+            case ByteCode.LASTORE:
+                return -4;
+
+            case ByteCode.AASTORE:
+            case ByteCode.BASTORE:
+            case ByteCode.CASTORE:
+            case ByteCode.DCMPG:
+            case ByteCode.DCMPL:
+            case ByteCode.FASTORE:
+            case ByteCode.IASTORE:
+            case ByteCode.LCMP:
+            case ByteCode.SASTORE:
+                return -3;
+
+            case ByteCode.DADD:
+            case ByteCode.DDIV:
+            case ByteCode.DMUL:
+            case ByteCode.DREM:
+            case ByteCode.DRETURN:
+            case ByteCode.DSTORE:
+            case ByteCode.DSTORE_0:
+            case ByteCode.DSTORE_1:
+            case ByteCode.DSTORE_2:
+            case ByteCode.DSTORE_3:
+            case ByteCode.DSUB:
+            case ByteCode.IF_ACMPEQ:
+            case ByteCode.IF_ACMPNE:
+            case ByteCode.IF_ICMPEQ:
+            case ByteCode.IF_ICMPGE:
+            case ByteCode.IF_ICMPGT:
+            case ByteCode.IF_ICMPLE:
+            case ByteCode.IF_ICMPLT:
+            case ByteCode.IF_ICMPNE:
+            case ByteCode.LADD:
+            case ByteCode.LAND:
+            case ByteCode.LDIV:
+            case ByteCode.LMUL:
+            case ByteCode.LOR:
+            case ByteCode.LREM:
+            case ByteCode.LRETURN:
+            case ByteCode.LSTORE:
+            case ByteCode.LSTORE_0:
+            case ByteCode.LSTORE_1:
+            case ByteCode.LSTORE_2:
+            case ByteCode.LSTORE_3:
+            case ByteCode.LSUB:
+            case ByteCode.LXOR:
+            case ByteCode.POP2:
+                return -2;
+
+            case ByteCode.AALOAD:
+            case ByteCode.ARETURN:
+            case ByteCode.ASTORE:
+            case ByteCode.ASTORE_0:
+            case ByteCode.ASTORE_1:
+            case ByteCode.ASTORE_2:
+            case ByteCode.ASTORE_3:
+            case ByteCode.ATHROW:
+            case ByteCode.BALOAD:
+            case ByteCode.CALOAD:
+            case ByteCode.D2F:
+            case ByteCode.D2I:
+            case ByteCode.FADD:
+            case ByteCode.FALOAD:
+            case ByteCode.FCMPG:
+            case ByteCode.FCMPL:
+            case ByteCode.FDIV:
+            case ByteCode.FMUL:
+            case ByteCode.FREM:
+            case ByteCode.FRETURN:
+            case ByteCode.FSTORE:
+            case ByteCode.FSTORE_0:
+            case ByteCode.FSTORE_1:
+            case ByteCode.FSTORE_2:
+            case ByteCode.FSTORE_3:
+            case ByteCode.FSUB:
+            case ByteCode.GETFIELD:
+            case ByteCode.IADD:
+            case ByteCode.IALOAD:
+            case ByteCode.IAND:
+            case ByteCode.IDIV:
+            case ByteCode.IFEQ:
+            case ByteCode.IFGE:
+            case ByteCode.IFGT:
+            case ByteCode.IFLE:
+            case ByteCode.IFLT:
+            case ByteCode.IFNE:
+            case ByteCode.IFNONNULL:
+            case ByteCode.IFNULL:
+            case ByteCode.IMUL:
+            case ByteCode.INVOKEINTERFACE:       //
+            case ByteCode.INVOKESPECIAL:         // but needs to account for
+            case ByteCode.INVOKEVIRTUAL:         // pops 'this' (unless static)
+            case ByteCode.IOR:
+            case ByteCode.IREM:
+            case ByteCode.IRETURN:
+            case ByteCode.ISHL:
+            case ByteCode.ISHR:
+            case ByteCode.ISTORE:
+            case ByteCode.ISTORE_0:
+            case ByteCode.ISTORE_1:
+            case ByteCode.ISTORE_2:
+            case ByteCode.ISTORE_3:
+            case ByteCode.ISUB:
+            case ByteCode.IUSHR:
+            case ByteCode.IXOR:
+            case ByteCode.L2F:
+            case ByteCode.L2I:
+            case ByteCode.LOOKUPSWITCH:
+            case ByteCode.LSHL:
+            case ByteCode.LSHR:
+            case ByteCode.LUSHR:
+            case ByteCode.MONITORENTER:
+            case ByteCode.MONITOREXIT:
+            case ByteCode.POP:
+            case ByteCode.PUTFIELD:
+            case ByteCode.SALOAD:
+            case ByteCode.TABLESWITCH:
+                return -1;
+
+            case ByteCode.ANEWARRAY:
+            case ByteCode.ARRAYLENGTH:
+            case ByteCode.BREAKPOINT:
+            case ByteCode.CHECKCAST:
+            case ByteCode.D2L:
+            case ByteCode.DALOAD:
+            case ByteCode.DNEG:
+            case ByteCode.F2I:
+            case ByteCode.FNEG:
+            case ByteCode.GETSTATIC:
+            case ByteCode.GOTO:
+            case ByteCode.GOTO_W:
+            case ByteCode.I2B:
+            case ByteCode.I2C:
+            case ByteCode.I2F:
+            case ByteCode.I2S:
+            case ByteCode.IINC:
+            case ByteCode.IMPDEP1:
+            case ByteCode.IMPDEP2:
+            case ByteCode.INEG:
+            case ByteCode.INSTANCEOF:
+            case ByteCode.INVOKESTATIC:
+            case ByteCode.L2D:
+            case ByteCode.LALOAD:
+            case ByteCode.LNEG:
+            case ByteCode.NEWARRAY:
+            case ByteCode.NOP:
+            case ByteCode.PUTSTATIC:
+            case ByteCode.RET:
+            case ByteCode.RETURN:
+            case ByteCode.SWAP:
+            case ByteCode.WIDE:
+                return 0;
+
+            case ByteCode.ACONST_NULL:
+            case ByteCode.ALOAD:
+            case ByteCode.ALOAD_0:
+            case ByteCode.ALOAD_1:
+            case ByteCode.ALOAD_2:
+            case ByteCode.ALOAD_3:
+            case ByteCode.BIPUSH:
+            case ByteCode.DUP:
+            case ByteCode.DUP_X1:
+            case ByteCode.DUP_X2:
+            case ByteCode.F2D:
+            case ByteCode.F2L:
+            case ByteCode.FCONST_0:
+            case ByteCode.FCONST_1:
+            case ByteCode.FCONST_2:
+            case ByteCode.FLOAD:
+            case ByteCode.FLOAD_0:
+            case ByteCode.FLOAD_1:
+            case ByteCode.FLOAD_2:
+            case ByteCode.FLOAD_3:
+            case ByteCode.I2D:
+            case ByteCode.I2L:
+            case ByteCode.ICONST_0:
+            case ByteCode.ICONST_1:
+            case ByteCode.ICONST_2:
+            case ByteCode.ICONST_3:
+            case ByteCode.ICONST_4:
+            case ByteCode.ICONST_5:
+            case ByteCode.ICONST_M1:
+            case ByteCode.ILOAD:
+            case ByteCode.ILOAD_0:
+            case ByteCode.ILOAD_1:
+            case ByteCode.ILOAD_2:
+            case ByteCode.ILOAD_3:
+            case ByteCode.JSR:
+            case ByteCode.JSR_W:
+            case ByteCode.LDC:
+            case ByteCode.LDC_W:
+            case ByteCode.MULTIANEWARRAY:
+            case ByteCode.NEW:
+            case ByteCode.SIPUSH:
+                return 1;
+
+            case ByteCode.DCONST_0:
+            case ByteCode.DCONST_1:
+            case ByteCode.DLOAD:
+            case ByteCode.DLOAD_0:
+            case ByteCode.DLOAD_1:
+            case ByteCode.DLOAD_2:
+            case ByteCode.DLOAD_3:
+            case ByteCode.DUP2:
+            case ByteCode.DUP2_X1:
+            case ByteCode.DUP2_X2:
+            case ByteCode.LCONST_0:
+            case ByteCode.LCONST_1:
+            case ByteCode.LDC2_W:
+            case ByteCode.LLOAD:
+            case ByteCode.LLOAD_0:
+            case ByteCode.LLOAD_1:
+            case ByteCode.LLOAD_2:
+            case ByteCode.LLOAD_3:
+                return 2;
+        }
+        throw new IllegalArgumentException("Bad opcode: "+opcode);
+    }
+
+        /*
+         * Number of bytes of operands generated after the opcode.
+         * Not in use currently.
+         */
+/*
+    int extra(int opcode)
+    {
+        switch (opcode) {
+            case ByteCode.AALOAD:
+            case ByteCode.AASTORE:
+            case ByteCode.ACONST_NULL:
+            case ByteCode.ALOAD_0:
+            case ByteCode.ALOAD_1:
+            case ByteCode.ALOAD_2:
+            case ByteCode.ALOAD_3:
+            case ByteCode.ARETURN:
+            case ByteCode.ARRAYLENGTH:
+            case ByteCode.ASTORE_0:
+            case ByteCode.ASTORE_1:
+            case ByteCode.ASTORE_2:
+            case ByteCode.ASTORE_3:
+            case ByteCode.ATHROW:
+            case ByteCode.BALOAD:
+            case ByteCode.BASTORE:
+            case ByteCode.BREAKPOINT:
+            case ByteCode.CALOAD:
+            case ByteCode.CASTORE:
+            case ByteCode.D2F:
+            case ByteCode.D2I:
+            case ByteCode.D2L:
+            case ByteCode.DADD:
+            case ByteCode.DALOAD:
+            case ByteCode.DASTORE:
+            case ByteCode.DCMPG:
+            case ByteCode.DCMPL:
+            case ByteCode.DCONST_0:
+            case ByteCode.DCONST_1:
+            case ByteCode.DDIV:
+            case ByteCode.DLOAD_0:
+            case ByteCode.DLOAD_1:
+            case ByteCode.DLOAD_2:
+            case ByteCode.DLOAD_3:
+            case ByteCode.DMUL:
+            case ByteCode.DNEG:
+            case ByteCode.DREM:
+            case ByteCode.DRETURN:
+            case ByteCode.DSTORE_0:
+            case ByteCode.DSTORE_1:
+            case ByteCode.DSTORE_2:
+            case ByteCode.DSTORE_3:
+            case ByteCode.DSUB:
+            case ByteCode.DUP2:
+            case ByteCode.DUP2_X1:
+            case ByteCode.DUP2_X2:
+            case ByteCode.DUP:
+            case ByteCode.DUP_X1:
+            case ByteCode.DUP_X2:
+            case ByteCode.F2D:
+            case ByteCode.F2I:
+            case ByteCode.F2L:
+            case ByteCode.FADD:
+            case ByteCode.FALOAD:
+            case ByteCode.FASTORE:
+            case ByteCode.FCMPG:
+            case ByteCode.FCMPL:
+            case ByteCode.FCONST_0:
+            case ByteCode.FCONST_1:
+            case ByteCode.FCONST_2:
+            case ByteCode.FDIV:
+            case ByteCode.FLOAD_0:
+            case ByteCode.FLOAD_1:
+            case ByteCode.FLOAD_2:
+            case ByteCode.FLOAD_3:
+            case ByteCode.FMUL:
+            case ByteCode.FNEG:
+            case ByteCode.FREM:
+            case ByteCode.FRETURN:
+            case ByteCode.FSTORE_0:
+            case ByteCode.FSTORE_1:
+            case ByteCode.FSTORE_2:
+            case ByteCode.FSTORE_3:
+            case ByteCode.FSUB:
+            case ByteCode.I2B:
+            case ByteCode.I2C:
+            case ByteCode.I2D:
+            case ByteCode.I2F:
+            case ByteCode.I2L:
+            case ByteCode.I2S:
+            case ByteCode.IADD:
+            case ByteCode.IALOAD:
+            case ByteCode.IAND:
+            case ByteCode.IASTORE:
+            case ByteCode.ICONST_0:
+            case ByteCode.ICONST_1:
+            case ByteCode.ICONST_2:
+            case ByteCode.ICONST_3:
+            case ByteCode.ICONST_4:
+            case ByteCode.ICONST_5:
+            case ByteCode.ICONST_M1:
+            case ByteCode.IDIV:
+            case ByteCode.ILOAD_0:
+            case ByteCode.ILOAD_1:
+            case ByteCode.ILOAD_2:
+            case ByteCode.ILOAD_3:
+            case ByteCode.IMPDEP1:
+            case ByteCode.IMPDEP2:
+            case ByteCode.IMUL:
+            case ByteCode.INEG:
+            case ByteCode.IOR:
+            case ByteCode.IREM:
+            case ByteCode.IRETURN:
+            case ByteCode.ISHL:
+            case ByteCode.ISHR:
+            case ByteCode.ISTORE_0:
+            case ByteCode.ISTORE_1:
+            case ByteCode.ISTORE_2:
+            case ByteCode.ISTORE_3:
+            case ByteCode.ISUB:
+            case ByteCode.IUSHR:
+            case ByteCode.IXOR:
+            case ByteCode.L2D:
+            case ByteCode.L2F:
+            case ByteCode.L2I:
+            case ByteCode.LADD:
+            case ByteCode.LALOAD:
+            case ByteCode.LAND:
+            case ByteCode.LASTORE:
+            case ByteCode.LCMP:
+            case ByteCode.LCONST_0:
+            case ByteCode.LCONST_1:
+            case ByteCode.LDIV:
+            case ByteCode.LLOAD_0:
+            case ByteCode.LLOAD_1:
+            case ByteCode.LLOAD_2:
+            case ByteCode.LLOAD_3:
+            case ByteCode.LMUL:
+            case ByteCode.LNEG:
+            case ByteCode.LOR:
+            case ByteCode.LREM:
+            case ByteCode.LRETURN:
+            case ByteCode.LSHL:
+            case ByteCode.LSHR:
+            case ByteCode.LSTORE_0:
+            case ByteCode.LSTORE_1:
+            case ByteCode.LSTORE_2:
+            case ByteCode.LSTORE_3:
+            case ByteCode.LSUB:
+            case ByteCode.LUSHR:
+            case ByteCode.LXOR:
+            case ByteCode.MONITORENTER:
+            case ByteCode.MONITOREXIT:
+            case ByteCode.NOP:
+            case ByteCode.POP2:
+            case ByteCode.POP:
+            case ByteCode.RETURN:
+            case ByteCode.SALOAD:
+            case ByteCode.SASTORE:
+            case ByteCode.SWAP:
+            case ByteCode.WIDE:
+                return 0;
+
+            case ByteCode.ALOAD:
+            case ByteCode.ASTORE:
+            case ByteCode.BIPUSH:
+            case ByteCode.DLOAD:
+            case ByteCode.DSTORE:
+            case ByteCode.FLOAD:
+            case ByteCode.FSTORE:
+            case ByteCode.ILOAD:
+            case ByteCode.ISTORE:
+            case ByteCode.LDC:
+            case ByteCode.LLOAD:
+            case ByteCode.LSTORE:
+            case ByteCode.NEWARRAY:
+            case ByteCode.RET:
+                return 1;
+
+            case ByteCode.ANEWARRAY:
+            case ByteCode.CHECKCAST:
+            case ByteCode.GETFIELD:
+            case ByteCode.GETSTATIC:
+            case ByteCode.GOTO:
+            case ByteCode.IFEQ:
+            case ByteCode.IFGE:
+            case ByteCode.IFGT:
+            case ByteCode.IFLE:
+            case ByteCode.IFLT:
+            case ByteCode.IFNE:
+            case ByteCode.IFNONNULL:
+            case ByteCode.IFNULL:
+            case ByteCode.IF_ACMPEQ:
+            case ByteCode.IF_ACMPNE:
+            case ByteCode.IF_ICMPEQ:
+            case ByteCode.IF_ICMPGE:
+            case ByteCode.IF_ICMPGT:
+            case ByteCode.IF_ICMPLE:
+            case ByteCode.IF_ICMPLT:
+            case ByteCode.IF_ICMPNE:
+            case ByteCode.IINC:
+            case ByteCode.INSTANCEOF:
+            case ByteCode.INVOKEINTERFACE:
+            case ByteCode.INVOKESPECIAL:
+            case ByteCode.INVOKESTATIC:
+            case ByteCode.INVOKEVIRTUAL:
+            case ByteCode.JSR:
+            case ByteCode.LDC2_W:
+            case ByteCode.LDC_W:
+            case ByteCode.NEW:
+            case ByteCode.PUTFIELD:
+            case ByteCode.PUTSTATIC:
+            case ByteCode.SIPUSH:
+                return 2;
+
+            case ByteCode.MULTIANEWARRAY:
+                return 3;
+
+            case ByteCode.GOTO_W:
+            case ByteCode.JSR_W:
+                return 4;
+
+            case ByteCode.LOOKUPSWITCH:    // depends on alignment
+            case ByteCode.TABLESWITCH: // depends on alignment
+                return -1;
+        }
+        throw new IllegalArgumentException("Bad opcode: "+opcode);
+    }
+*/
+
+    @SuppressWarnings("unused")
+    private static String bytecodeStr(int code)
+    {
+        if (DEBUGSTACK || DEBUGCODE) {
+            switch (code) {
+                case ByteCode.NOP:              return "nop";
+                case ByteCode.ACONST_NULL:      return "aconst_null";
+                case ByteCode.ICONST_M1:        return "iconst_m1";
+                case ByteCode.ICONST_0:         return "iconst_0";
+                case ByteCode.ICONST_1:         return "iconst_1";
+                case ByteCode.ICONST_2:         return "iconst_2";
+                case ByteCode.ICONST_3:         return "iconst_3";
+                case ByteCode.ICONST_4:         return "iconst_4";
+                case ByteCode.ICONST_5:         return "iconst_5";
+                case ByteCode.LCONST_0:         return "lconst_0";
+                case ByteCode.LCONST_1:         return "lconst_1";
+                case ByteCode.FCONST_0:         return "fconst_0";
+                case ByteCode.FCONST_1:         return "fconst_1";
+                case ByteCode.FCONST_2:         return "fconst_2";
+                case ByteCode.DCONST_0:         return "dconst_0";
+                case ByteCode.DCONST_1:         return "dconst_1";
+                case ByteCode.BIPUSH:           return "bipush";
+                case ByteCode.SIPUSH:           return "sipush";
+                case ByteCode.LDC:              return "ldc";
+                case ByteCode.LDC_W:            return "ldc_w";
+                case ByteCode.LDC2_W:           return "ldc2_w";
+                case ByteCode.ILOAD:            return "iload";
+                case ByteCode.LLOAD:            return "lload";
+                case ByteCode.FLOAD:            return "fload";
+                case ByteCode.DLOAD:            return "dload";
+                case ByteCode.ALOAD:            return "aload";
+                case ByteCode.ILOAD_0:          return "iload_0";
+                case ByteCode.ILOAD_1:          return "iload_1";
+                case ByteCode.ILOAD_2:          return "iload_2";
+                case ByteCode.ILOAD_3:          return "iload_3";
+                case ByteCode.LLOAD_0:          return "lload_0";
+                case ByteCode.LLOAD_1:          return "lload_1";
+                case ByteCode.LLOAD_2:          return "lload_2";
+                case ByteCode.LLOAD_3:          return "lload_3";
+                case ByteCode.FLOAD_0:          return "fload_0";
+                case ByteCode.FLOAD_1:          return "fload_1";
+                case ByteCode.FLOAD_2:          return "fload_2";
+                case ByteCode.FLOAD_3:          return "fload_3";
+                case ByteCode.DLOAD_0:          return "dload_0";
+                case ByteCode.DLOAD_1:          return "dload_1";
+                case ByteCode.DLOAD_2:          return "dload_2";
+                case ByteCode.DLOAD_3:          return "dload_3";
+                case ByteCode.ALOAD_0:          return "aload_0";
+                case ByteCode.ALOAD_1:          return "aload_1";
+                case ByteCode.ALOAD_2:          return "aload_2";
+                case ByteCode.ALOAD_3:          return "aload_3";
+                case ByteCode.IALOAD:           return "iaload";
+                case ByteCode.LALOAD:           return "laload";
+                case ByteCode.FALOAD:           return "faload";
+                case ByteCode.DALOAD:           return "daload";
+                case ByteCode.AALOAD:           return "aaload";
+                case ByteCode.BALOAD:           return "baload";
+                case ByteCode.CALOAD:           return "caload";
+                case ByteCode.SALOAD:           return "saload";
+                case ByteCode.ISTORE:           return "istore";
+                case ByteCode.LSTORE:           return "lstore";
+                case ByteCode.FSTORE:           return "fstore";
+                case ByteCode.DSTORE:           return "dstore";
+                case ByteCode.ASTORE:           return "astore";
+                case ByteCode.ISTORE_0:         return "istore_0";
+                case ByteCode.ISTORE_1:         return "istore_1";
+                case ByteCode.ISTORE_2:         return "istore_2";
+                case ByteCode.ISTORE_3:         return "istore_3";
+                case ByteCode.LSTORE_0:         return "lstore_0";
+                case ByteCode.LSTORE_1:         return "lstore_1";
+                case ByteCode.LSTORE_2:         return "lstore_2";
+                case ByteCode.LSTORE_3:         return "lstore_3";
+                case ByteCode.FSTORE_0:         return "fstore_0";
+                case ByteCode.FSTORE_1:         return "fstore_1";
+                case ByteCode.FSTORE_2:         return "fstore_2";
+                case ByteCode.FSTORE_3:         return "fstore_3";
+                case ByteCode.DSTORE_0:         return "dstore_0";
+                case ByteCode.DSTORE_1:         return "dstore_1";
+                case ByteCode.DSTORE_2:         return "dstore_2";
+                case ByteCode.DSTORE_3:         return "dstore_3";
+                case ByteCode.ASTORE_0:         return "astore_0";
+                case ByteCode.ASTORE_1:         return "astore_1";
+                case ByteCode.ASTORE_2:         return "astore_2";
+                case ByteCode.ASTORE_3:         return "astore_3";
+                case ByteCode.IASTORE:          return "iastore";
+                case ByteCode.LASTORE:          return "lastore";
+                case ByteCode.FASTORE:          return "fastore";
+                case ByteCode.DASTORE:          return "dastore";
+                case ByteCode.AASTORE:          return "aastore";
+                case ByteCode.BASTORE:          return "bastore";
+                case ByteCode.CASTORE:          return "castore";
+                case ByteCode.SASTORE:          return "sastore";
+                case ByteCode.POP:              return "pop";
+                case ByteCode.POP2:             return "pop2";
+                case ByteCode.DUP:              return "dup";
+                case ByteCode.DUP_X1:           return "dup_x1";
+                case ByteCode.DUP_X2:           return "dup_x2";
+                case ByteCode.DUP2:             return "dup2";
+                case ByteCode.DUP2_X1:          return "dup2_x1";
+                case ByteCode.DUP2_X2:          return "dup2_x2";
+                case ByteCode.SWAP:             return "swap";
+                case ByteCode.IADD:             return "iadd";
+                case ByteCode.LADD:             return "ladd";
+                case ByteCode.FADD:             return "fadd";
+                case ByteCode.DADD:             return "dadd";
+                case ByteCode.ISUB:             return "isub";
+                case ByteCode.LSUB:             return "lsub";
+                case ByteCode.FSUB:             return "fsub";
+                case ByteCode.DSUB:             return "dsub";
+                case ByteCode.IMUL:             return "imul";
+                case ByteCode.LMUL:             return "lmul";
+                case ByteCode.FMUL:             return "fmul";
+                case ByteCode.DMUL:             return "dmul";
+                case ByteCode.IDIV:             return "idiv";
+                case ByteCode.LDIV:             return "ldiv";
+                case ByteCode.FDIV:             return "fdiv";
+                case ByteCode.DDIV:             return "ddiv";
+                case ByteCode.IREM:             return "irem";
+                case ByteCode.LREM:             return "lrem";
+                case ByteCode.FREM:             return "frem";
+                case ByteCode.DREM:             return "drem";
+                case ByteCode.INEG:             return "ineg";
+                case ByteCode.LNEG:             return "lneg";
+                case ByteCode.FNEG:             return "fneg";
+                case ByteCode.DNEG:             return "dneg";
+                case ByteCode.ISHL:             return "ishl";
+                case ByteCode.LSHL:             return "lshl";
+                case ByteCode.ISHR:             return "ishr";
+                case ByteCode.LSHR:             return "lshr";
+                case ByteCode.IUSHR:            return "iushr";
+                case ByteCode.LUSHR:            return "lushr";
+                case ByteCode.IAND:             return "iand";
+                case ByteCode.LAND:             return "land";
+                case ByteCode.IOR:              return "ior";
+                case ByteCode.LOR:              return "lor";
+                case ByteCode.IXOR:             return "ixor";
+                case ByteCode.LXOR:             return "lxor";
+                case ByteCode.IINC:             return "iinc";
+                case ByteCode.I2L:              return "i2l";
+                case ByteCode.I2F:              return "i2f";
+                case ByteCode.I2D:              return "i2d";
+                case ByteCode.L2I:              return "l2i";
+                case ByteCode.L2F:              return "l2f";
+                case ByteCode.L2D:              return "l2d";
+                case ByteCode.F2I:              return "f2i";
+                case ByteCode.F2L:              return "f2l";
+                case ByteCode.F2D:              return "f2d";
+                case ByteCode.D2I:              return "d2i";
+                case ByteCode.D2L:              return "d2l";
+                case ByteCode.D2F:              return "d2f";
+                case ByteCode.I2B:              return "i2b";
+                case ByteCode.I2C:              return "i2c";
+                case ByteCode.I2S:              return "i2s";
+                case ByteCode.LCMP:             return "lcmp";
+                case ByteCode.FCMPL:            return "fcmpl";
+                case ByteCode.FCMPG:            return "fcmpg";
+                case ByteCode.DCMPL:            return "dcmpl";
+                case ByteCode.DCMPG:            return "dcmpg";
+                case ByteCode.IFEQ:             return "ifeq";
+                case ByteCode.IFNE:             return "ifne";
+                case ByteCode.IFLT:             return "iflt";
+                case ByteCode.IFGE:             return "ifge";
+                case ByteCode.IFGT:             return "ifgt";
+                case ByteCode.IFLE:             return "ifle";
+                case ByteCode.IF_ICMPEQ:        return "if_icmpeq";
+                case ByteCode.IF_ICMPNE:        return "if_icmpne";
+                case ByteCode.IF_ICMPLT:        return "if_icmplt";
+                case ByteCode.IF_ICMPGE:        return "if_icmpge";
+                case ByteCode.IF_ICMPGT:        return "if_icmpgt";
+                case ByteCode.IF_ICMPLE:        return "if_icmple";
+                case ByteCode.IF_ACMPEQ:        return "if_acmpeq";
+                case ByteCode.IF_ACMPNE:        return "if_acmpne";
+                case ByteCode.GOTO:             return "goto";
+                case ByteCode.JSR:              return "jsr";
+                case ByteCode.RET:              return "ret";
+                case ByteCode.TABLESWITCH:      return "tableswitch";
+                case ByteCode.LOOKUPSWITCH:     return "lookupswitch";
+                case ByteCode.IRETURN:          return "ireturn";
+                case ByteCode.LRETURN:          return "lreturn";
+                case ByteCode.FRETURN:          return "freturn";
+                case ByteCode.DRETURN:          return "dreturn";
+                case ByteCode.ARETURN:          return "areturn";
+                case ByteCode.RETURN:           return "return";
+                case ByteCode.GETSTATIC:        return "getstatic";
+                case ByteCode.PUTSTATIC:        return "putstatic";
+                case ByteCode.GETFIELD:         return "getfield";
+                case ByteCode.PUTFIELD:         return "putfield";
+                case ByteCode.INVOKEVIRTUAL:    return "invokevirtual";
+                case ByteCode.INVOKESPECIAL:    return "invokespecial";
+                case ByteCode.INVOKESTATIC:     return "invokestatic";
+                case ByteCode.INVOKEINTERFACE:  return "invokeinterface";
+                case ByteCode.NEW:              return "new";
+                case ByteCode.NEWARRAY:         return "newarray";
+                case ByteCode.ANEWARRAY:        return "anewarray";
+                case ByteCode.ARRAYLENGTH:      return "arraylength";
+                case ByteCode.ATHROW:           return "athrow";
+                case ByteCode.CHECKCAST:        return "checkcast";
+                case ByteCode.INSTANCEOF:       return "instanceof";
+                case ByteCode.MONITORENTER:     return "monitorenter";
+                case ByteCode.MONITOREXIT:      return "monitorexit";
+                case ByteCode.WIDE:             return "wide";
+                case ByteCode.MULTIANEWARRAY:   return "multianewarray";
+                case ByteCode.IFNULL:           return "ifnull";
+                case ByteCode.IFNONNULL:        return "ifnonnull";
+                case ByteCode.GOTO_W:           return "goto_w";
+                case ByteCode.JSR_W:            return "jsr_w";
+                case ByteCode.BREAKPOINT:       return "breakpoint";
+
+                case ByteCode.IMPDEP1:          return "impdep1";
+                case ByteCode.IMPDEP2:          return "impdep2";
+            }
+        }
+        return "";
+    }
+
+    final char[] getCharBuffer(int minimalSize)
+    {
+        if (minimalSize > tmpCharBuffer.length) {
+            int newSize = tmpCharBuffer.length * 2;
+            if (minimalSize > newSize) { newSize = minimalSize; }
+            tmpCharBuffer = new char[newSize];
+        }
+        return tmpCharBuffer;
+    }
+
+    /**
+     * Add a pc as the start of super block.
+     *
+     * A pc is the beginning of a super block if:
+     * - pc == 0
+     * - it is the target of a branch instruction
+     * - it is the beginning of an exception handler
+     * - it is directly after an unconditional jump
+     */
+    private void addSuperBlockStart(int pc) {
+        if (GenerateStackMap) {
+            if (itsSuperBlockStarts == null) {
+                itsSuperBlockStarts = new int[SuperBlockStartsSize];
+            } else if (itsSuperBlockStarts.length == itsSuperBlockStartsTop) {
+                int[] tmp = new int[itsSuperBlockStartsTop * 2];
+                System.arraycopy(itsSuperBlockStarts, 0, tmp, 0,
+                                 itsSuperBlockStartsTop);
+                itsSuperBlockStarts = tmp;
+            }
+            itsSuperBlockStarts[itsSuperBlockStartsTop++] = pc;
+        }
+    }
+
+    /**
+     * Sort the list of recorded super block starts and remove duplicates.
+     *
+     * Also adds exception handling blocks as block starts, since there is no
+     * explicit control flow to these. Used for stack map table generation.
+     */
+    private void finalizeSuperBlockStarts() {
+        if (GenerateStackMap) {
+            for (int i = 0; i < itsExceptionTableTop; i++) {
+                ExceptionTableEntry ete = itsExceptionTable[i];
+                short handlerPC = (short) getLabelPC(ete.itsHandlerLabel);
+                addSuperBlockStart(handlerPC);
+            }
+            Arrays.sort(itsSuperBlockStarts, 0, itsSuperBlockStartsTop);
+            int prev = itsSuperBlockStarts[0];
+            int copyTo = 1;
+            for (int i = 1; i < itsSuperBlockStartsTop; i++) {
+                int curr = itsSuperBlockStarts[i];
+                if (prev != curr) {
+                    if (copyTo != i) {
+                        itsSuperBlockStarts[copyTo] = curr;
+                    }
+                    copyTo++;
+                    prev = curr;
+                }
+            }
+            itsSuperBlockStartsTop = copyTo;
+            if (itsSuperBlockStarts[copyTo - 1] == itsCodeBufferTop) {
+                itsSuperBlockStartsTop--;
+            }
+        }
+    }
+
+    private int[] itsSuperBlockStarts = null;
+    private int itsSuperBlockStartsTop = 0;
+    private static final int SuperBlockStartsSize = 4;
+
+    // Used to find blocks of code with no dependencies (aka dead code).
+    // Necessary for generating type information for dead code, which is
+    // expected by the Sun verifier. It is only necessary to store a single
+    // jump source to determine if a block is reachable or not.
+    private UintMap itsJumpFroms = null;
+
+    private static final int LineNumberTableSize = 16;
+    private static final int ExceptionTableSize = 4;
+
+    private static final int MajorVersion;
+    private static final int MinorVersion;
+    private static final boolean GenerateStackMap;
+
+    static {
+        // Figure out which classfile version should be generated. This assumes
+        // that the runtime used to compile the JavaScript files is the same as
+        // the one used to run them. This is important because there are cases
+        // when bytecode is generated at runtime, where it is not easy to pass
+        // along what version is necessary. Instead, we grab the version numbers
+        // from the bytecode of this class and use that.
+        //
+        // Based on the version numbers we scrape, we can also determine what
+        // bytecode features we need. For example, Java 6 bytecode (classfile
+        // version 50) should have stack maps generated.
+        InputStream is = null;
+        int major = 48, minor = 0;
+        try {
+            is = ClassFileWriter.class.getResourceAsStream("ClassFileWriter.class");
+            if (is == null) {
+                is = ClassLoader.getSystemResourceAsStream(
+                    "org/mozilla/classfile/ClassFileWriter.class");
+            }
+            byte[] header = new byte[8];
+            // read loop is required since JDK7 will only provide 2 bytes
+            // on the first read() - see bug #630111
+            int read = 0;
+            while (read < 8) {
+                int c = is.read(header, read, 8 - read);
+                if (c < 0) throw new IOException();
+                read += c;
+            }
+            minor = (header[4] << 8) | (header[5] & 0xff);
+            major = (header[6] << 8) | (header[7] & 0xff);
+        } catch (Exception e) {
+            // Unable to get class file, use default bytecode version
+        } finally {
+            MinorVersion = minor;
+            MajorVersion = major;
+            GenerateStackMap = major >= 50;
+            if (is != null) {
+                try {
+                    is.close();
+                } catch (IOException e) {
+                }
+            }
+        }
+    }
+
+    private final static int FileHeaderConstant = 0xCAFEBABE;
+    // Set DEBUG flags to true to get better checking and progress info.
+    private static final boolean DEBUGSTACK = false;
+    private static final boolean DEBUGLABELS = false;
+    private static final boolean DEBUGCODE = false;
+
+    private String generatedClassName;
+
+    private ExceptionTableEntry itsExceptionTable[];
+    private int itsExceptionTableTop;
+
+    private int itsLineNumberTable[];   // pack start_pc & line_number together
+    private int itsLineNumberTableTop;
+
+    private byte[] itsCodeBuffer = new byte[256];
+    private int itsCodeBufferTop;
+
+    private ConstantPool itsConstantPool;
+
+    private ClassFileMethod itsCurrentMethod;
+    private short itsStackTop;
+
+    private short itsMaxStack;
+    private short itsMaxLocals;
+
+    private ObjArray itsMethods = new ObjArray();
+    private ObjArray itsFields = new ObjArray();
+    private ObjArray itsInterfaces = new ObjArray();
+
+    private short itsFlags;
+    private short itsThisClassIndex;
+    private short itsSuperClassIndex;
+    private short itsSourceFileNameIndex;
+
+    private static final int MIN_LABEL_TABLE_SIZE = 32;
+    private int[] itsLabelTable;
+    private int itsLabelTableTop;
+
+// itsFixupTable[i] = (label_index << 32) | fixup_site
+    private static final int MIN_FIXUP_TABLE_SIZE = 40;
+    private long[] itsFixupTable;
+    private int itsFixupTableTop;
+    private ObjArray itsVarDescriptors;
+
+    private char[] tmpCharBuffer = new char[64];
+}
+
+final class ExceptionTableEntry
+{
+
+    ExceptionTableEntry(int startLabel, int endLabel,
+                        int handlerLabel, short catchType)
+    {
+        itsStartLabel = startLabel;
+        itsEndLabel = endLabel;
+        itsHandlerLabel = handlerLabel;
+        itsCatchType = catchType;
+    }
+
+    int itsStartLabel;
+    int itsEndLabel;
+    int itsHandlerLabel;
+    short itsCatchType;
+}
+
+final class ClassFileField
+{
+
+    ClassFileField(short nameIndex, short typeIndex, short flags)
+    {
+        itsNameIndex = nameIndex;
+        itsTypeIndex = typeIndex;
+        itsFlags = flags;
+        itsHasAttributes = false;
+    }
+
+    void setAttributes(short attr1, short attr2, short attr3, int index)
+    {
+        itsHasAttributes = true;
+        itsAttr1 = attr1;
+        itsAttr2 = attr2;
+        itsAttr3 = attr3;
+        itsIndex = index;
+    }
+
+    int write(byte[] data, int offset)
+    {
+        offset = ClassFileWriter.putInt16(itsFlags, data, offset);
+        offset = ClassFileWriter.putInt16(itsNameIndex, data, offset);
+        offset = ClassFileWriter.putInt16(itsTypeIndex, data, offset);
+        if (!itsHasAttributes) {
+            // write 0 attributes
+            offset = ClassFileWriter.putInt16(0, data, offset);
+        } else {
+            offset = ClassFileWriter.putInt16(1, data, offset);
+            offset = ClassFileWriter.putInt16(itsAttr1, data, offset);
+            offset = ClassFileWriter.putInt16(itsAttr2, data, offset);
+            offset = ClassFileWriter.putInt16(itsAttr3, data, offset);
+            offset = ClassFileWriter.putInt16(itsIndex, data, offset);
+        }
+        return offset;
+    }
+
+    int getWriteSize()
+    {
+        int size = 2 * 3;
+        if (!itsHasAttributes) {
+            size += 2;
+        } else {
+            size += 2 + 2 * 4;
+        }
+        return size;
+    }
+
+    private short itsNameIndex;
+    private short itsTypeIndex;
+    private short itsFlags;
+    private boolean itsHasAttributes;
+    private short itsAttr1, itsAttr2, itsAttr3;
+    private int itsIndex;
+}
+
+final class ClassFileMethod
+{
+
+    ClassFileMethod(String name, short nameIndex, String type, short typeIndex,
+                    short flags)
+    {
+        itsName = name;
+        itsNameIndex = nameIndex;
+        itsType = type;
+        itsTypeIndex = typeIndex;
+        itsFlags = flags;
+    }
+
+    void setCodeAttribute(byte codeAttribute[])
+    {
+        itsCodeAttribute = codeAttribute;
+    }
+
+    int write(byte[] data, int offset)
+    {
+        offset = ClassFileWriter.putInt16(itsFlags, data, offset);
+        offset = ClassFileWriter.putInt16(itsNameIndex, data, offset);
+        offset = ClassFileWriter.putInt16(itsTypeIndex, data, offset);
+        // Code attribute only
+        offset = ClassFileWriter.putInt16(1, data, offset);
+        System.arraycopy(itsCodeAttribute, 0, data, offset,
+                         itsCodeAttribute.length);
+        offset += itsCodeAttribute.length;
+        return offset;
+    }
+
+    int getWriteSize()
+    {
+        return 2 * 4 + itsCodeAttribute.length;
+    }
+
+    String getName()
+    {
+        return itsName;
+    }
+
+    String getType()
+    {
+        return itsType;
+    }
+
+    short getFlags()
+    {
+        return itsFlags;
+    }
+
+    private String itsName;
+    private String itsType;
+    private short itsNameIndex;
+    private short itsTypeIndex;
+    private short itsFlags;
+    private byte[] itsCodeAttribute;
+
+}
+
+final class ConstantPool
+{
+
+    ConstantPool(ClassFileWriter cfw)
+    {
+        this.cfw = cfw;
+        itsTopIndex = 1;       // the zero'th entry is reserved
+        itsPool = new byte[ConstantPoolSize];
+        itsTop = 0;
+    }
+
+    private static final int ConstantPoolSize = 256;
+    static final byte
+        CONSTANT_Class = 7,
+        CONSTANT_Fieldref = 9,
+        CONSTANT_Methodref = 10,
+        CONSTANT_InterfaceMethodref = 11,
+        CONSTANT_String = 8,
+        CONSTANT_Integer = 3,
+        CONSTANT_Float = 4,
+        CONSTANT_Long = 5,
+        CONSTANT_Double = 6,
+        CONSTANT_NameAndType = 12,
+        CONSTANT_Utf8 = 1;
+
+    int write(byte[] data, int offset)
+    {
+        offset = ClassFileWriter.putInt16((short)itsTopIndex, data, offset);
+        System.arraycopy(itsPool, 0, data, offset, itsTop);
+        offset += itsTop;
+        return offset;
+    }
+
+    int getWriteSize()
+    {
+        return 2 + itsTop;
+    }
+
+    int addConstant(int k)
+    {
+        ensure(5);
+        itsPool[itsTop++] = CONSTANT_Integer;
+        itsTop = ClassFileWriter.putInt32(k, itsPool, itsTop);
+        itsPoolTypes.put(itsTopIndex, CONSTANT_Integer);
+        return (short)(itsTopIndex++);
+    }
+
+    int addConstant(long k)
+    {
+        ensure(9);
+        itsPool[itsTop++] = CONSTANT_Long;
+        itsTop = ClassFileWriter.putInt64(k, itsPool, itsTop);
+        int index = itsTopIndex;
+        itsTopIndex += 2;
+        itsPoolTypes.put(index, CONSTANT_Long);
+        return index;
+    }
+
+    int addConstant(float k)
+    {
+        ensure(5);
+        itsPool[itsTop++] = CONSTANT_Float;
+        int bits = Float.floatToIntBits(k);
+        itsTop = ClassFileWriter.putInt32(bits, itsPool, itsTop);
+        itsPoolTypes.put(itsTopIndex, CONSTANT_Float);
+        return itsTopIndex++;
+    }
+
+    int addConstant(double k)
+    {
+        ensure(9);
+        itsPool[itsTop++] = CONSTANT_Double;
+        long bits = Double.doubleToLongBits(k);
+        itsTop = ClassFileWriter.putInt64(bits, itsPool, itsTop);
+        int index = itsTopIndex;
+        itsTopIndex += 2;
+        itsPoolTypes.put(index, CONSTANT_Double);
+        return index;
+    }
+
+    int addConstant(String k)
+    {
+        int utf8Index = 0xFFFF & addUtf8(k);
+        int theIndex = itsStringConstHash.getInt(utf8Index, -1);
+        if (theIndex == -1) {
+            theIndex = itsTopIndex++;
+            ensure(3);
+            itsPool[itsTop++] = CONSTANT_String;
+            itsTop = ClassFileWriter.putInt16(utf8Index, itsPool, itsTop);
+            itsStringConstHash.put(utf8Index, theIndex);
+        }
+        itsPoolTypes.put(theIndex, CONSTANT_String);
+        return theIndex;
+    }
+
+    boolean isUnderUtfEncodingLimit(String s)
+    {
+        int strLen = s.length();
+        if (strLen * 3 <= MAX_UTF_ENCODING_SIZE) {
+            return true;
+        } else if (strLen > MAX_UTF_ENCODING_SIZE) {
+            return false;
+        }
+        return strLen == getUtfEncodingLimit(s, 0, strLen);
+    }
+
+    /**
+     * Get maximum i such that <tt>start <= i <= end</tt> and
+     * <tt>s.substring(start, i)</tt> fits JVM UTF string encoding limit.
+     */
+    int getUtfEncodingLimit(String s, int start, int end)
+    {
+        if ((end - start) * 3 <= MAX_UTF_ENCODING_SIZE) {
+            return end;
+        }
+        int limit = MAX_UTF_ENCODING_SIZE;
+        for (int i = start; i != end; i++) {
+            int c = s.charAt(i);
+            if (0 != c && c <= 0x7F) {
+                --limit;
+            } else if (c < 0x7FF) {
+                limit -= 2;
+            } else {
+                limit -= 3;
+            }
+            if (limit < 0) {
+                return i;
+            }
+        }
+        return end;
+    }
+
+    short addUtf8(String k)
+    {
+        int theIndex = itsUtf8Hash.get(k, -1);
+        if (theIndex == -1) {
+            int strLen = k.length();
+            boolean tooBigString;
+            if (strLen > MAX_UTF_ENCODING_SIZE) {
+                tooBigString = true;
+            } else {
+                tooBigString = false;
+                // Ask for worst case scenario buffer when each char takes 3
+                // bytes
+                ensure(1 + 2 + strLen * 3);
+                int top = itsTop;
+
+                itsPool[top++] = CONSTANT_Utf8;
+                top += 2; // skip length
+
+                char[] chars = cfw.getCharBuffer(strLen);
+                k.getChars(0, strLen, chars, 0);
+
+                for (int i = 0; i != strLen; i++) {
+                    int c = chars[i];
+                    if (c != 0 && c <= 0x7F) {
+                        itsPool[top++] = (byte)c;
+                    } else if (c > 0x7FF) {
+                        itsPool[top++] = (byte)(0xE0 | (c >> 12));
+                        itsPool[top++] = (byte)(0x80 | ((c >> 6) & 0x3F));
+                        itsPool[top++] = (byte)(0x80 | (c & 0x3F));
+                    } else {
+                        itsPool[top++] = (byte)(0xC0 | (c >> 6));
+                        itsPool[top++] = (byte)(0x80 | (c & 0x3F));
+                    }
+                }
+
+                int utfLen = top - (itsTop + 1 + 2);
+                if (utfLen > MAX_UTF_ENCODING_SIZE) {
+                    tooBigString = true;
+                } else {
+                    // Write back length
+                    itsPool[itsTop + 1] = (byte)(utfLen >>> 8);
+                    itsPool[itsTop + 2] = (byte)utfLen;
+
+                    itsTop = top;
+                    theIndex = itsTopIndex++;
+                    itsUtf8Hash.put(k, theIndex);
+                }
+            }
+            if (tooBigString) {
+                throw new IllegalArgumentException("Too big string");
+            }
+        }
+        setConstantData(theIndex, k);
+        itsPoolTypes.put(theIndex, CONSTANT_Utf8);
+        return (short)theIndex;
+    }
+
+    private short addNameAndType(String name, String type)
+    {
+        short nameIndex = addUtf8(name);
+        short typeIndex = addUtf8(type);
+        ensure(5);
+        itsPool[itsTop++] = CONSTANT_NameAndType;
+        itsTop = ClassFileWriter.putInt16(nameIndex, itsPool, itsTop);
+        itsTop = ClassFileWriter.putInt16(typeIndex, itsPool, itsTop);
+        itsPoolTypes.put(itsTopIndex, CONSTANT_NameAndType);
+        return (short)(itsTopIndex++);
+    }
+
+    short addClass(String className)
+    {
+        int theIndex = itsClassHash.get(className, -1);
+        if (theIndex == -1) {
+            String slashed = className;
+            if (className.indexOf('.') > 0) {
+                slashed = ClassFileWriter.getSlashedForm(className);
+                theIndex = itsClassHash.get(slashed, -1);
+                if (theIndex != -1) {
+                    itsClassHash.put(className, theIndex);
+                }
+            }
+            if (theIndex == -1) {
+                int utf8Index = addUtf8(slashed);
+                ensure(3);
+                itsPool[itsTop++] = CONSTANT_Class;
+                itsTop = ClassFileWriter.putInt16(utf8Index, itsPool, itsTop);
+                theIndex = itsTopIndex++;
+                itsClassHash.put(slashed, theIndex);
+                if (className != slashed) {
+                    itsClassHash.put(className, theIndex);
+                }
+            }
+        }
+        setConstantData(theIndex, className);
+        itsPoolTypes.put(theIndex, CONSTANT_Class);
+        return (short)theIndex;
+    }
+
+    short addFieldRef(String className, String fieldName, String fieldType)
+    {
+        FieldOrMethodRef ref = new FieldOrMethodRef(className, fieldName,
+                                                    fieldType);
+
+        int theIndex = itsFieldRefHash.get(ref, -1);
+        if (theIndex == -1) {
+            short ntIndex = addNameAndType(fieldName, fieldType);
+            short classIndex = addClass(className);
+            ensure(5);
+            itsPool[itsTop++] = CONSTANT_Fieldref;
+            itsTop = ClassFileWriter.putInt16(classIndex, itsPool, itsTop);
+            itsTop = ClassFileWriter.putInt16(ntIndex, itsPool, itsTop);
+            theIndex = itsTopIndex++;
+            itsFieldRefHash.put(ref, theIndex);
+        }
+        setConstantData(theIndex, ref);
+        itsPoolTypes.put(theIndex, CONSTANT_Fieldref);
+        return (short)theIndex;
+    }
+
+    short addMethodRef(String className, String methodName,
+                       String methodType)
+    {
+        FieldOrMethodRef ref = new FieldOrMethodRef(className, methodName,
+                                                    methodType);
+
+        int theIndex = itsMethodRefHash.get(ref, -1);
+        if (theIndex == -1) {
+            short ntIndex = addNameAndType(methodName, methodType);
+            short classIndex = addClass(className);
+            ensure(5);
+            itsPool[itsTop++] = CONSTANT_Methodref;
+            itsTop = ClassFileWriter.putInt16(classIndex, itsPool, itsTop);
+            itsTop = ClassFileWriter.putInt16(ntIndex, itsPool, itsTop);
+            theIndex = itsTopIndex++;
+            itsMethodRefHash.put(ref, theIndex);
+        }
+        setConstantData(theIndex, ref);
+        itsPoolTypes.put(theIndex, CONSTANT_Methodref);
+        return (short)theIndex;
+    }
+
+    short addInterfaceMethodRef(String className,
+                                String methodName, String methodType)
+    {
+        short ntIndex = addNameAndType(methodName, methodType);
+        short classIndex = addClass(className);
+        ensure(5);
+        itsPool[itsTop++] = CONSTANT_InterfaceMethodref;
+        itsTop = ClassFileWriter.putInt16(classIndex, itsPool, itsTop);
+        itsTop = ClassFileWriter.putInt16(ntIndex, itsPool, itsTop);
+        FieldOrMethodRef r = new FieldOrMethodRef(className, methodName,
+                                                  methodType);
+        setConstantData(itsTopIndex, r);
+        itsPoolTypes.put(itsTopIndex, CONSTANT_InterfaceMethodref);
+        return (short)(itsTopIndex++);
+    }
+
+    Object getConstantData(int index)
+    {
+        return itsConstantData.getObject(index);
+    }
+
+    void setConstantData(int index, Object data)
+    {
+        itsConstantData.put(index, data);
+    }
+
+    byte getConstantType(int index)
+    {
+        return (byte) itsPoolTypes.getInt(index, 0);
+    }
+
+    void ensure(int howMuch)
+    {
+        if (itsTop + howMuch > itsPool.length) {
+            int newCapacity = itsPool.length * 2;
+            if (itsTop + howMuch > newCapacity) {
+                newCapacity = itsTop + howMuch;
+            }
+            byte[] tmp = new byte[newCapacity];
+            System.arraycopy(itsPool, 0, tmp, 0, itsTop);
+            itsPool = tmp;
+        }
+    }
+
+    private ClassFileWriter cfw;
+
+    private static final int MAX_UTF_ENCODING_SIZE = 65535;
+
+    private UintMap itsStringConstHash = new UintMap();
+    private ObjToIntMap itsUtf8Hash = new ObjToIntMap();
+    private ObjToIntMap itsFieldRefHash = new ObjToIntMap();
+    private ObjToIntMap itsMethodRefHash = new ObjToIntMap();
+    private ObjToIntMap itsClassHash = new ObjToIntMap();
+
+    private int itsTop;
+    private int itsTopIndex;
+    private UintMap itsConstantData = new UintMap();
+    private UintMap itsPoolTypes = new UintMap();
+    private byte itsPool[];
+}
+
+final class FieldOrMethodRef
+{
+    FieldOrMethodRef(String className, String name, String type)
+    {
+        this.className = className;
+        this.name = name;
+        this.type = type;
+    }
+
+    public String getClassName()
+    {
+        return className;
+    }
+
+    public String getName()
+    {
+        return name;
+    }
+
+    public String getType()
+    {
+        return type;
+    }
+
+    @Override
+    public boolean equals(Object obj)
+    {
+        if (!(obj instanceof FieldOrMethodRef)) { return false; }
+        FieldOrMethodRef x = (FieldOrMethodRef)obj;
+        return className.equals(x.className)
+            && name.equals(x.name)
+            && type.equals(x.type);
+    }
+
+    @Override
+    public int hashCode()
+    {
+        if (hashCode == -1) {
+            int h1 = className.hashCode();
+            int h2 = name.hashCode();
+            int h3 = type.hashCode();
+            hashCode = h1 ^ h2 ^ h3;
+        }
+        return hashCode;
+    }
+
+    private String className;
+    private String name;
+    private String type;
+    private int hashCode = -1;
+}
+
+/**
+ * A super block is defined as a contiguous chunk of code with a single entry
+ * point and multiple exit points (therefore ending in an unconditional jump
+ * or the end of the method). This is used to emulate OpenJDK's compiler, which
+ * outputs stack map frames at the start of every super block except the method
+ * start.
+ */
+final class SuperBlock {
+    SuperBlock(int index, int start, int end, int[] initialLocals) {
+        this.index = index;
+        this.start = start;
+        this.end = end;
+        locals = new int[initialLocals.length];
+        System.arraycopy(initialLocals, 0, locals, 0, initialLocals.length);
+        stack = new int[0];
+        isInitialized = false;
+        isInQueue = false;
+    }
+
+    int getIndex() {
+        return index;
+    }
+
+    int[] getLocals() {
+        int[] copy = new int[locals.length];
+        System.arraycopy(locals, 0, copy, 0, locals.length);
+        return copy;
+    }
+
+    /**
+     * Get a copy of the super block's locals without any trailing TOP types.
+     *
+     * This is useful for actual writing stack maps; during the computation of
+     * stack map types, all local arrays have the same size; the max locals for
+     * the method. In addition, DOUBLE and LONG types have trailing TOP types
+     * because they occupy two words. For writing purposes, these are not
+     * useful.
+     */
+    int[] getTrimmedLocals() {
+        int last = locals.length - 1;
+        // Exclude all of the trailing TOPs not bound to a DOUBLE/LONG
+        while (last >= 0 && locals[last] == TypeInfo.TOP &&
+               !TypeInfo.isTwoWords(locals[last - 1])) {
+            last--;
+        }
+        last++;
+        // Exclude trailing TOPs following a DOUBLE/LONG
+        int size = last;
+        for (int i = 0; i < last; i++) {
+            if (TypeInfo.isTwoWords(locals[i])) {
+                size--;
+            }
+        }
+        int[] copy = new int[size];
+        for (int i = 0, j = 0; i < size; i++, j++) {
+            copy[i] = locals[j];
+            if (TypeInfo.isTwoWords(locals[j])) {
+                j++;
+            }
+        }
+        return copy;
+    }
+
+    int[] getStack() {
+        int[] copy = new int[stack.length];
+        System.arraycopy(stack, 0, copy, 0, stack.length);
+        return copy;
+    }
+
+    boolean merge(int[] locals, int localsTop, int[] stack, int stackTop,
+                  ConstantPool pool) {
+        if (!isInitialized) {
+            System.arraycopy(locals, 0, this.locals, 0, localsTop);
+            this.stack = new int[stackTop];
+            System.arraycopy(stack, 0, this.stack, 0, stackTop);
+            isInitialized = true;
+            return true;
+        } else if (this.locals.length == localsTop &&
+                   this.stack.length == stackTop) {
+            boolean localsChanged = mergeState(this.locals, locals, localsTop,
+                                               pool);
+            boolean stackChanged = mergeState(this.stack, stack, stackTop,
+                                              pool);
+            return localsChanged || stackChanged;
+        } else {
+            if (ClassFileWriter.StackMapTable.DEBUGSTACKMAP) {
+                System.out.println("bad merge");
+                System.out.println("current type state:");
+                TypeInfo.print(this.locals, this.stack, pool);
+                System.out.println("incoming type state:");
+                TypeInfo.print(locals, localsTop, stack, stackTop, pool);
+            }
+            throw new IllegalArgumentException("bad merge attempt");
+        }
+    }
+
+    /**
+     * Merge an operand stack or local variable array with incoming state.
+     *
+     * They are treated the same way; by this point, it should already be
+     * ensured that the array sizes are the same, which is the only additional
+     * constraint that is imposed on merging operand stacks (the local variable
+     * array is always the same size).
+     */
+    private boolean mergeState(int[] current, int[] incoming, int size,
+                               ConstantPool pool) {
+        boolean changed = false;
+        for (int i = 0; i < size; i++) {
+            int currentType = current[i];
+
+            current[i] = TypeInfo.merge(current[i], incoming[i], pool);
+            if (currentType != current[i]) {
+                changed = true;
+            }
+        }
+        return changed;
+    }
+
+    int getStart() {
+        return start;
+    }
+
+    int getEnd() {
+        return end;
+    }
+
+    @Override
+    public String toString() {
+        return "sb " + index;
+    }
+
+    boolean isInitialized() {
+        return isInitialized;
+    }
+
+    void setInitialized(boolean b) {
+        isInitialized = b;
+    }
+
+    boolean isInQueue() {
+        return isInQueue;
+    }
+
+    void setInQueue(boolean b) {
+        isInQueue = b;
+    }
+
+    private int index;
+    private int start;
+    private int end;
+    private int[] locals;
+    private int[] stack;
+    private boolean isInitialized;
+    private boolean isInQueue;
+}
+
+/**
+ * Helper class for internal representations of type information. In most
+ * cases, type information can be represented by a constant, but in some
+ * cases, a payload is included. Despite the payload coming after the type
+ * tag in the output, we store it in bits 8-23 for uniformity; the tag is
+ * always in bits 0-7.
+ */
+final class TypeInfo {
+    private TypeInfo() { }
+
+    static final int TOP = 0;
+    static final int INTEGER = 1;
+    static final int FLOAT = 2;
+    static final int DOUBLE = 3;
+    static final int LONG = 4;
+    static final int NULL = 5;
+    static final int UNINITIALIZED_THIS = 6;
+    static final int OBJECT_TAG = 7;
+    static final int UNINITIALIZED_VAR_TAG = 8;
+
+    static final int OBJECT(int constantPoolIndex) {
+        return ((constantPoolIndex & 0xFFFF) << 8) | OBJECT_TAG;
+    }
+
+    static final int OBJECT(String type, ConstantPool pool) {
+        return OBJECT(pool.addClass(type));
+    }
+
+    static final int UNINITIALIZED_VARIABLE(int bytecodeOffset) {
+        return ((bytecodeOffset & 0xFFFF) << 8) | UNINITIALIZED_VAR_TAG;
+    }
+
+    static final int getTag(int typeInfo) {
+        return typeInfo & 0xFF;
+    }
+
+    static final int getPayload(int typeInfo) {
+        return typeInfo >>> 8;
+    }
+
+    /**
+     * Treat the result of getPayload as a constant pool index and fetch the
+     * corresponding String mapped to it.
+     *
+     * Only works on OBJECT types.
+     */
+    static final String getPayloadAsType(int typeInfo, ConstantPool pool) {
+        if (getTag(typeInfo) == OBJECT_TAG) {
+            return (String) pool.getConstantData(getPayload(typeInfo));
+        }
+        throw new IllegalArgumentException("expecting object type");
+    }
+
+    /**
+     * Create type information from an internal type.
+     */
+    static final int fromType(String type, ConstantPool pool) {
+        if (type.length() == 1) {
+            switch (type.charAt(0)) {
+                case 'B': // sbyte
+                case 'C': // unicode char
+                case 'S': // short
+                case 'Z': // boolean
+                case 'I': // all of the above are verified as integers
+                    return INTEGER;
+                case 'D':
+                    return DOUBLE;
+                case 'F':
+                    return FLOAT;
+                case 'J':
+                    return LONG;
+                default:
+                    throw new IllegalArgumentException("bad type");
+            }
+        }
+        return TypeInfo.OBJECT(type, pool);
+    }
+
+    static boolean isTwoWords(int type) {
+        return type == DOUBLE || type == LONG;
+    }
+
+    /**
+     * Merge two verification types.
+     *
+     * In most cases, the verification types must be the same. For example,
+     * INTEGER and DOUBLE cannot be merged and an exception will be thrown.
+     * The basic rules are:
+     *
+     * - If the types are equal, simply return one.
+     * - If either type is TOP, return TOP.
+     * - If either type is NULL, return the other type.
+     * - If both types are objects, find the lowest common ancestor in the
+     *   class hierarchy.
+     *
+     * This method uses reflection to traverse the class hierarchy. Therefore,
+     * it is assumed that the current class being generated is never the target
+     * of a full object-object merge, which would need to load the current
+     * class reflectively.
+     */
+    static int merge(int current, int incoming, ConstantPool pool) {
+        int currentTag = getTag(current);
+        int incomingTag = getTag(incoming);
+        boolean currentIsObject = currentTag == TypeInfo.OBJECT_TAG;
+        boolean incomingIsObject = incomingTag == TypeInfo.OBJECT_TAG;
+
+        if (current == incoming || (currentIsObject && incoming == NULL)) {
+            return current;
+        } else if (currentTag == TypeInfo.TOP ||
+            incomingTag == TypeInfo.TOP) {
+            return TypeInfo.TOP;
+        } else if (current == NULL && incomingIsObject) {
+            return incoming;
+        } else if (currentIsObject && incomingIsObject) {
+            String currentName = getPayloadAsType(current, pool);
+            String incomingName = getPayloadAsType(incoming, pool);
+            // The class file always has the class and super names in the same
+            // spot. The constant order is: class_data, class_name, super_data,
+            // super_name.
+            String currentlyGeneratedName = (String) pool.getConstantData(2);
+            String currentlyGeneratedSuperName =
+                    (String) pool.getConstantData(4);
+
+            // If any of the merged types are the class that's currently being
+            // generated, automatically start at the super class instead. At
+            // this point, we already know the classes are different, so we
+            // don't need to handle that case.
+            if (currentName.equals(currentlyGeneratedName)) {
+                currentName = currentlyGeneratedSuperName;
+            }
+            if (incomingName.equals(currentlyGeneratedName)) {
+                incomingName = currentlyGeneratedSuperName;
+            }
+
+            Class<?> currentClass = getClassFromInternalName(currentName);
+            Class<?> incomingClass = getClassFromInternalName(incomingName);
+
+            if (currentClass.isAssignableFrom(incomingClass)) {
+                return current;
+            } else if (incomingClass.isAssignableFrom(currentClass)) {
+                return incoming;
+            } else if (incomingClass.isInterface() ||
+                       currentClass.isInterface()) {
+                // For verification purposes, Sun specifies that interfaces are
+                // subtypes of Object. Therefore, we know that the merge result
+                // involving interfaces where one is not assignable to the
+                // other results in Object.
+                return OBJECT("java/lang/Object", pool);
+            } else {
+                Class<?> commonClass = incomingClass.getSuperclass();
+                while (commonClass != null) {
+                    if (commonClass.isAssignableFrom(currentClass)) {
+                        String name = commonClass.getName();
+                        name = ClassFileWriter.getSlashedForm(name);
+                        return OBJECT(name, pool);
+                    }
+                    commonClass = commonClass.getSuperclass();
+                }
+            }
+        }
+        throw new IllegalArgumentException("bad merge attempt between " +
+                                           toString(current, pool) + " and " +
+                                           toString(incoming, pool));
+    }
+
+    static String toString(int type, ConstantPool pool) {
+        int tag = getTag(type);
+        switch (tag) {
+            case TypeInfo.TOP:
+                return "top";
+            case TypeInfo.INTEGER:
+                return "int";
+            case TypeInfo.FLOAT:
+                return "float";
+            case TypeInfo.DOUBLE:
+                return "double";
+            case TypeInfo.LONG:
+                return "long";
+            case TypeInfo.NULL:
+                return "null";
+            case TypeInfo.UNINITIALIZED_THIS:
+                return "uninitialized_this";
+            default:
+                if (tag == TypeInfo.OBJECT_TAG) {
+                    return getPayloadAsType(type, pool);
+                } else if (tag == TypeInfo.UNINITIALIZED_VAR_TAG) {
+                    return "uninitialized";
+                } else {
+                    throw new IllegalArgumentException("bad type");
+                }
+        }
+    }
+
+    /**
+     * Take an internal name and return a java.lang.Class instance that
+     * represents it.
+     *
+     * For example, given "java/lang/Object", returns the equivalent of
+     * Class.forName("java.lang.Object"), but also handles exceptions.
+     */
+    static Class<?> getClassFromInternalName(String internalName) {
+        try {
+            return Class.forName(internalName.replace('/', '.'));
+        } catch (ClassNotFoundException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    static String toString(int[] types, ConstantPool pool) {
+        return toString(types, types.length, pool);
+    }
+
+    static String toString(int[] types, int typesTop, ConstantPool pool) {
+        StringBuilder sb = new StringBuilder();
+        sb.append("[");
+        for (int i = 0; i < typesTop; i++) {
+            if (i > 0) {
+                sb.append(", ");
+            }
+            sb.append(toString(types[i], pool));
+        }
+        sb.append("]");
+        return sb.toString();
+    }
+
+    static void print(int[] locals, int[] stack, ConstantPool pool) {
+        print(locals, locals.length, stack, stack.length, pool);
+    }
+
+    static void print(int[] locals, int localsTop, int[] stack, int stackTop,
+                       ConstantPool pool) {
+        System.out.print("locals: ");
+        System.out.println(toString(locals, localsTop, pool));
+        System.out.print("stack: ");
+        System.out.println(toString(stack, stackTop, pool));
+        System.out.println();
+    }
+}
diff -pruN 20130227+dfsg1-14/rhino/src/org/mozilla/javascript/Arguments.java 20130227+rhino-1/rhino/src/org/mozilla/javascript/Arguments.java
--- 20130227+dfsg1-14/rhino/src/org/mozilla/javascript/Arguments.java	1970-01-01 00:00:00.000000000 +0000
+++ 20130227+rhino-1/rhino/src/org/mozilla/javascript/Arguments.java	2023-05-25 14:24:50.000000000 +0000
@@ -0,0 +1,451 @@
+/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+package org.mozilla.javascript;
+
+/**
+ * This class implements the "arguments" object.
+ *
+ * See ECMA 10.1.8
+ *
+ * @see org.mozilla.javascript.NativeCall
+ * @author Norris Boyd
+ */
+final class Arguments extends IdScriptableObject
+{
+    static final long serialVersionUID = 4275508002492040609L;
+
+    private static final String FTAG = "Arguments";
+
+    public Arguments(NativeCall activation)
+    {
+        this.activation = activation;
+
+        Scriptable parent = activation.getParentScope();
+        setParentScope(parent);
+        setPrototype(ScriptableObject.getObjectPrototype(parent));
+
+        args = activation.originalArgs;
+        lengthObj = Integer.valueOf(args.length);
+
+        NativeFunction f = activation.function;
+        calleeObj = f;
+
+        int version = f.getLanguageVersion();
+        if (version <= Context.VERSION_1_3
+            && version != Context.VERSION_DEFAULT)
+        {
+            callerObj = null;
+        } else {
+            callerObj = NOT_FOUND;
+        }
+
+        defineProperty(SymbolKey.ITERATOR, iteratorMethod, ScriptableObject.DONTENUM);
+    }
+
+    @Override
+    public String getClassName()
+    {
+        return FTAG;
+    }
+
+    private Object arg(int index) {
+      if (index < 0 || args.length <= index) return NOT_FOUND;
+      return args[index];
+    }
+
+    // the following helper methods assume that 0 < index < args.length
+
+    private void putIntoActivation(int index, Object value) {
+        String argName = activation.function.getParamOrVarName(index);
+        activation.put(argName, activation, value);
+    }
+
+    private Object getFromActivation(int index) {
+        String argName = activation.function.getParamOrVarName(index);
+        return activation.get(argName, activation);
+    }
+
+    private void replaceArg(int index, Object value) {
+      if (sharedWithActivation(index)) {
+        putIntoActivation(index, value);
+      }
+      synchronized (this) {
+        if (args == activation.originalArgs) {
+          args = args.clone();
+        }
+        args[index] = value;
+      }
+    }
+
+    private void removeArg(int index) {
+      synchronized (this) {
+        if (args[index] != NOT_FOUND) {
+          if (args == activation.originalArgs) {
+            args = args.clone();
+          }
+          args[index] = NOT_FOUND;
+        }
+      }
+    }
+
+    // end helpers
+
+    @Override
+    public boolean has(int index, Scriptable start)
+    {
+        if (arg(index) != NOT_FOUND) {
+          return true;
+        }
+        return super.has(index, start);
+    }
+
+    @Override
+    public Object get(int index, Scriptable start)
+    {
+      final Object value = arg(index);
+      if (value == NOT_FOUND) {
+        return super.get(index, start);
+      } else {
+        if (sharedWithActivation(index)) {
+          return getFromActivation(index);
+        } else {
+          return value;
+        }
+      }
+    }
+
+    private boolean sharedWithActivation(int index)
+    {
+        Context cx = Context.getContext();
+        if (cx.isStrictMode()) {
+            return false;
+        }
+        NativeFunction f = activation.function;
+        int definedCount = f.getParamCount();
+        if (index < definedCount) {
+            // Check if argument is not hidden by later argument with the same
+            // name as hidden arguments are not shared with activation
+            if (index < definedCount - 1) {
+                String argName = f.getParamOrVarName(index);
+                for (int i = index + 1; i < definedCount; i++) {
+                    if (argName.equals(f.getParamOrVarName(i))) {
+                        return false;
+                    }
+                }
+            }
+            return true;
+        }
+        return false;
+    }
+
+    @Override
+    public void put(int index, Scriptable start, Object value)
+    {
+        if (arg(index) == NOT_FOUND) {
+          super.put(index, start, value);
+        } else {
+          replaceArg(index, value);
+        }
+    }
+
+    @Override
+    public void put(String name, Scriptable start, Object value)
+    {
+        super.put(name, start, value);
+    }
+
+    @Override
+    public void delete(int index)
+    {
+        if (0 <= index && index < args.length) {
+          removeArg(index);
+        }
+        super.delete(index);
+    }
+
+// #string_id_map#
+
+    private static final int
+        Id_callee           = 1,
+        Id_length           = 2,
+        Id_caller           = 3,
+
+        MAX_INSTANCE_ID     = Id_caller;
+
+    @Override
+    protected int getMaxInstanceId()
+    {
+        return MAX_INSTANCE_ID;
+    }
+
+    @Override
+    protected int findInstanceIdInfo(String s)
+    {
+        int id;
+// #generated# Last update: 2010-01-06 05:48:21 ARST
+        L0: { id = 0; String X = null; int c;
+            int s_length = s.length();
+            if (s_length==6) {
+                c=s.charAt(5);
+                if (c=='e') { X="callee";id=Id_callee; }
+                else if (c=='h') { X="length";id=Id_length; }
+                else if (c=='r') { X="caller";id=Id_caller; }
+            }
+            if (X!=null && X!=s && !X.equals(s)) id = 0;
+            break L0;
+        }
+// #/generated#
+        Context cx = Context.getContext();
+        if (cx.isStrictMode()) {
+            if (id == Id_callee || id == Id_caller) {
+                return super.findInstanceIdInfo(s);
+            }
+        }
+
+
+        if (id == 0) return super.findInstanceIdInfo(s);
+
+        int attr;
+        switch (id) {
+          case Id_callee:
+            attr = calleeAttr;
+            break;
+          case Id_caller:
+            attr = callerAttr;
+            break;
+          case Id_length:
+            attr = lengthAttr;
+            break;
+          default: throw new IllegalStateException();
+        }
+        return instanceIdInfo(attr, id);
+    }
+
+// #/string_id_map#
+
+    @Override
+    protected String getInstanceIdName(int id)
+    {
+        switch (id) {
+            case Id_callee: return "callee";
+            case Id_length: return "length";
+            case Id_caller: return "caller";
+        }
+        return null;
+    }
+
+    @Override
+    protected Object getInstanceIdValue(int id)
+    {
+        switch (id) {
+            case Id_callee: return calleeObj;
+            case Id_length: return lengthObj;
+            case Id_caller: {
+                Object value = callerObj;
+                if (value == UniqueTag.NULL_VALUE) { value = null; }
+                else if (value == null) {
+                    NativeCall caller = activation.parentActivationCall;
+                    if (caller != null) {
+                        value = caller.get("arguments", caller);
+                    }
+                }
+                return value;
+            }
+        }
+        return super.getInstanceIdValue(id);
+    }
+
+    @Override
+    protected void setInstanceIdValue(int id, Object value)
+    {
+        switch (id) {
+            case Id_callee: calleeObj = value; return;
+            case Id_length: lengthObj = value; return;
+            case Id_caller:
+                callerObj = (value != null) ? value : UniqueTag.NULL_VALUE;
+                return;
+        }
+        super.setInstanceIdValue(id, value);
+    }
+
+    @Override
+    protected void setInstanceIdAttributes(int id, int attr)
+    {
+        switch (id) {
+            case Id_callee: calleeAttr = attr; return;
+            case Id_length: lengthAttr = attr; return;
+            case Id_caller: callerAttr = attr; return;
+        }
+        super.setInstanceIdAttributes(id, attr);
+    }
+
+    @Override
+    Object[] getIds(boolean getNonEnumerable, boolean getSymbols)
+    {
+        Object[] ids = super.getIds(getNonEnumerable, getSymbols);
+        if (args.length != 0) {
+            boolean[] present = new boolean[args.length];
+            int extraCount = args.length;
+            for (int i = 0; i != ids.length; ++i) {
+                Object id = ids[i];
+                if (id instanceof Integer) {
+                    int index = ((Integer)id).intValue();
+                    if (0 <= index && index < args.length) {
+                        if (!present[index]) {
+                            present[index] = true;
+                            extraCount--;
+                        }
+                    }
+                }
+            }
+            if (!getNonEnumerable) { // avoid adding args which were redefined to non-enumerable
+              for (int i = 0; i < present.length; i++) {
+                if (!present[i] && super.has(i, this)) {
+                  present[i] = true;
+                  extraCount--;
+                }
+              }
+            }
+            if (extraCount != 0) {
+                Object[] tmp = new Object[extraCount + ids.length];
+                System.arraycopy(ids, 0, tmp, extraCount, ids.length);
+                ids = tmp;
+                int offset = 0;
+                for (int i = 0; i != args.length; ++i) {
+                    if (present == null || !present[i]) {
+                        ids[offset] = Integer.valueOf(i);
+                        ++offset;
+                    }
+                }
+                if (offset != extraCount) Kit.codeBug();
+            }
+        }
+        return ids;
+    }
+
+    @Override
+    protected ScriptableObject getOwnPropertyDescriptor(Context cx, Object id) {
+        if (id instanceof Scriptable) {
+           return super.getOwnPropertyDescriptor(cx, id);
+        }
+      double d = ScriptRuntime.toNumber(id);
+      int index = (int) d;
+      if (d != index) {
+        return super.getOwnPropertyDescriptor(cx, id);
+      }
+      Object value = arg(index);
+      if (value == NOT_FOUND) {
+        return super.getOwnPropertyDescriptor(cx, id);
+      }
+      if (sharedWithActivation(index)) {
+        value = getFromActivation(index);
+      }
+      if (super.has(index, this)) { // the descriptor has been redefined
+        ScriptableObject desc = super.getOwnPropertyDescriptor(cx, id);
+        desc.put("value", desc, value);
+        return desc;
+      } else {
+        Scriptable scope = getParentScope();
+        if (scope == null) scope = this;
+        return buildDataDescriptor(scope, value, EMPTY);
+      }
+    }
+
+    @Override
+    protected void defineOwnProperty(Context cx, Object id,
+                                     ScriptableObject desc,
+                                     boolean checkValid) {
+      super.defineOwnProperty(cx, id, desc, checkValid);
+
+      double d = ScriptRuntime.toNumber(id);
+      int index = (int) d;
+      if (d != index) return;
+
+      Object value = arg(index);
+      if (value == NOT_FOUND) return;
+
+      if (isAccessorDescriptor(desc)) {
+        removeArg(index);
+        return;
+      }
+
+      Object newValue = getProperty(desc, "value");
+      if (newValue == NOT_FOUND) return;
+
+      replaceArg(index, newValue);
+
+      if (isFalse(getProperty(desc, "writable"))) {
+        removeArg(index);
+      }
+    }
+
+    // ECMAScript2015
+    // 9.4.4.6 CreateUnmappedArgumentsObject(argumentsList)
+    //   8. Perform DefinePropertyOrThrow(obj, "caller", PropertyDescriptor {[[Get]]: %ThrowTypeError%,
+    //      [[Set]]: %ThrowTypeError%, [[Enumerable]]: false, [[Configurable]]: false}).
+    //   9. Perform DefinePropertyOrThrow(obj, "callee", PropertyDescriptor {[[Get]]: %ThrowTypeError%,
+    //      [[Set]]: %ThrowTypeError%, [[Enumerable]]: false, [[Configurable]]: false}).
+    void defineAttributesForStrictMode() {
+        Context cx = Context.getContext();
+        if (!cx.isStrictMode()) {
+            return;
+        }
+        setGetterOrSetter("caller", 0, new ThrowTypeError("caller"), true);
+        setGetterOrSetter("caller", 0, new ThrowTypeError("caller"), false);
+        setGetterOrSetter("callee", 0, new ThrowTypeError("callee"), true);
+        setGetterOrSetter("callee", 0, new ThrowTypeError("callee"), false);
+        setAttributes("caller", DONTENUM | PERMANENT);
+        setAttributes("callee", DONTENUM | PERMANENT);
+        callerObj = null;
+        calleeObj = null;
+    }
+
+    private static BaseFunction iteratorMethod = new BaseFunction() {
+        @Override
+        public Object call(Context cx, Scriptable scope, Scriptable thisObj,
+                           Object[] args) {
+            // TODO : call %ArrayProto_values%
+            // 9.4.4.6 CreateUnmappedArgumentsObject(argumentsList)
+            //  1. Perform DefinePropertyOrThrow(obj, @@iterator, PropertyDescriptor {[[Value]]:%ArrayProto_values%,
+            //     [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: true}).
+            return new NativeArrayIterator(scope, thisObj);
+        }
+    };
+
+    private static class ThrowTypeError extends BaseFunction {
+        private String propertyName;
+
+        ThrowTypeError(String propertyName) {
+            this.propertyName = propertyName;
+        }
+
+        @Override
+        public Object call(Context cx, Scriptable scope, Scriptable thisObj, Object[] args) {
+            throw ScriptRuntime.typeError1("msg.arguments.not.access.strict", propertyName);
+        }
+    }
+
+// Fields to hold caller, callee and length properties,
+// where NOT_FOUND value tags deleted properties.
+// In addition if callerObj == NULL_VALUE, it tags null for scripts, as
+// initial callerObj == null means access to caller arguments available
+// only in JS <= 1.3 scripts
+    private Object callerObj;
+    private Object calleeObj;
+    private Object lengthObj;
+
+    private int callerAttr = DONTENUM;
+    private int calleeAttr = DONTENUM;
+    private int lengthAttr = DONTENUM;
+
+    private NativeCall activation;
+
+// Initially args holds activation.getOriginalArgs(), but any modification
+// of its elements triggers creation of a copy. If its element holds NOT_FOUND,
+// it indicates deleted index, in which case super class is queried.
+    private Object[] args;
+}
diff -pruN 20130227+dfsg1-14/rhino/src/org/mozilla/javascript/ArrowFunction.java 20130227+rhino-1/rhino/src/org/mozilla/javascript/ArrowFunction.java
--- 20130227+dfsg1-14/rhino/src/org/mozilla/javascript/ArrowFunction.java	1970-01-01 00:00:00.000000000 +0000
+++ 20130227+rhino-1/rhino/src/org/mozilla/javascript/ArrowFunction.java	2023-05-25 14:24:50.000000000 +0000
@@ -0,0 +1,75 @@
+/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+package org.mozilla.javascript;
+
+/**
+ * The class for  Arrow Function Definitions
+ * EcmaScript 6 Rev 14, March 8, 2013 Draft spec , 13.2
+ */
+public class ArrowFunction extends BaseFunction {
+    
+    static final long serialVersionUID = -7377989503697220633L;
+    
+    private final Callable targetFunction;
+    private final Scriptable boundThis;
+
+    public ArrowFunction(Context cx, Scriptable scope, Callable targetFunction, Scriptable boundThis)
+    {
+        this.targetFunction = targetFunction;
+        this.boundThis = boundThis;
+
+        ScriptRuntime.setFunctionProtoAndParent(this, scope);
+
+        Function thrower = ScriptRuntime.typeErrorThrower();
+        NativeObject throwing = new NativeObject();
+        throwing.put("get", throwing, thrower);
+        throwing.put("set", throwing, thrower);
+        throwing.put("enumerable", throwing, false);
+        throwing.put("configurable", throwing, false);
+        throwing.preventExtensions();
+
+        this.defineOwnProperty(cx, "caller", throwing, false);
+        this.defineOwnProperty(cx, "arguments", throwing, false);
+    }
+
+    @Override
+    public Object call(Context cx, Scriptable scope, Scriptable thisObj, Object[] args)
+    {
+        Scriptable callThis = boundThis != null ? boundThis : ScriptRuntime.getTopCallScope(cx);
+        return targetFunction.call(cx, scope, callThis, args);
+    }
+
+    @Override
+    public Scriptable construct(Context cx, Scriptable scope, Object[] args) {
+        throw ScriptRuntime.typeError1("msg.not.ctor", decompile(0, 0));
+    }
+
+    @Override
+    public boolean hasInstance(Scriptable instance) {
+        if (targetFunction instanceof Function) {
+            return ((Function) targetFunction).hasInstance(instance);
+        }
+        throw ScriptRuntime.typeError0("msg.not.ctor");
+    }
+
+    @Override
+    public int getLength() {
+        if (targetFunction instanceof BaseFunction) {
+            return ((BaseFunction) targetFunction).getLength();
+        }
+        return 0;
+    }
+
+    @Override
+    String decompile(int indent, int flags)
+    {
+        if (targetFunction instanceof BaseFunction) {
+            return ((BaseFunction)targetFunction).decompile(indent, flags);
+        }
+        return super.decompile(indent, flags);
+    }
+}
diff -pruN 20130227+dfsg1-14/rhino/src/org/mozilla/javascript/BaseFunction.java 20130227+rhino-1/rhino/src/org/mozilla/javascript/BaseFunction.java
--- 20130227+dfsg1-14/rhino/src/org/mozilla/javascript/BaseFunction.java	1970-01-01 00:00:00.000000000 +0000
+++ 20130227+rhino-1/rhino/src/org/mozilla/javascript/BaseFunction.java	2023-05-25 14:24:50.000000000 +0000
@@ -0,0 +1,609 @@
+/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+package org.mozilla.javascript;
+
+/**
+ * The base class for Function objects
+ * See ECMA 15.3.
+ * @author Norris Boyd
+ */
+public class BaseFunction extends IdScriptableObject implements Function
+{
+
+    static final long serialVersionUID = 5311394446546053859L;
+
+    private static final Object FUNCTION_TAG = "Function";
+
+    static void init(Scriptable scope, boolean sealed)
+    {
+        BaseFunction obj = new BaseFunction();
+        // Function.prototype attributes: see ECMA 15.3.3.1
+        obj.prototypePropertyAttributes = DONTENUM | READONLY | PERMANENT;
+        obj.exportAsJSClass(MAX_PROTOTYPE_ID, scope, sealed);
+    }
+
+    public BaseFunction()
+    {
+    }
+
+    public BaseFunction(Scriptable scope, Scriptable prototype)
+    {
+        super(scope, prototype);
+    }
+
+    @Override
+    public String getClassName() {
+        return "Function";
+    }
+
+    /**
+     * Gets the value returned by calling the typeof operator on this object.
+     * @see org.mozilla.javascript.ScriptableObject#getTypeOf()
+     * @return "function" or "undefined" if {@link #avoidObjectDetection()} returns <code>true</code>
+     */
+    @Override
+    public String getTypeOf()
+    {
+        return avoidObjectDetection() ? "undefined" : "function";
+    }
+
+    /**
+     * Implements the instanceof operator for JavaScript Function objects.
+     * <p>
+     * <code>
+     * foo = new Foo();<br>
+     * foo instanceof Foo;  // true<br>
+     * </code>
+     *
+     * @param instance The value that appeared on the LHS of the instanceof
+     *              operator
+     * @return true if the "prototype" property of "this" appears in
+     *              value's prototype chain
+     *
+     */
+    @Override
+    public boolean hasInstance(Scriptable instance)
+    {
+        Object protoProp = ScriptableObject.getProperty(this, "prototype");
+        if (protoProp instanceof Scriptable) {
+            return ScriptRuntime.jsDelegatesTo(instance, (Scriptable)protoProp);
+        }
+        throw ScriptRuntime.typeError1("msg.instanceof.bad.prototype",
+                                       getFunctionName());
+    }
+
+// #string_id_map#
+
+    private static final int
+        Id_length       = 1,
+        Id_arity        = 2,
+        Id_name         = 3,
+        Id_prototype    = 4,
+        Id_arguments    = 5,
+
+        MAX_INSTANCE_ID = 5;
+
+    @Override
+    protected int getMaxInstanceId()
+    {
+        return MAX_INSTANCE_ID;
+    }
+
+    @Override
+    protected int findInstanceIdInfo(String s)
+    {
+        int id;
+// #generated# Last update: 2007-05-09 08:15:15 EDT
+        L0: { id = 0; String X = null; int c;
+            L: switch (s.length()) {
+            case 4: X="name";id=Id_name; break L;
+            case 5: X="arity";id=Id_arity; break L;
+            case 6: X="length";id=Id_length; break L;
+            case 9: c=s.charAt(0);
+                if (c=='a') { X="arguments";id=Id_arguments; }
+                else if (c=='p') { X="prototype";id=Id_prototype; }
+                break L;
+            }
+            if (X!=null && X!=s && !X.equals(s)) id = 0;
+            break L0;
+        }
+// #/generated#
+// #/string_id_map#
+
+        if (id == 0) return super.findInstanceIdInfo(s);
+
+        int attr;
+        switch (id) {
+          case Id_length:
+          case Id_arity:
+          case Id_name:
+            attr = DONTENUM | READONLY | PERMANENT;
+            break;
+          case Id_prototype:
+            // some functions such as built-ins don't have a prototype property
+            if (!hasPrototypeProperty()) {
+                return 0;
+            }
+            attr = prototypePropertyAttributes;
+            break;
+          case Id_arguments:
+            attr = argumentsAttributes;
+            break;
+          default: throw new IllegalStateException();
+        }
+        return instanceIdInfo(attr, id);
+    }
+
+    @Override
+    protected String getInstanceIdName(int id)
+    {
+        switch (id) {
+            case Id_length:       return "length";
+            case Id_arity:        return "arity";
+            case Id_name:         return "name";
+            case Id_prototype:    return "prototype";
+            case Id_arguments:    return "arguments";
+        }
+        return super.getInstanceIdName(id);
+    }
+
+    @Override
+    protected Object getInstanceIdValue(int id)
+    {
+        switch (id) {
+          case Id_length:    return ScriptRuntime.wrapInt(getLength());
+          case Id_arity:     return ScriptRuntime.wrapInt(getArity());
+          case Id_name:      return getFunctionName();
+          case Id_prototype: return getPrototypeProperty();
+          case Id_arguments: return getArguments();
+        }
+        return super.getInstanceIdValue(id);
+    }
+
+    @Override
+    protected void setInstanceIdValue(int id, Object value)
+    {
+        switch (id) {
+            case Id_prototype:
+                if ((prototypePropertyAttributes & READONLY) == 0) {
+                    prototypeProperty = (value != null)
+                                        ? value : UniqueTag.NULL_VALUE;
+                }
+                return;
+            case Id_arguments:
+                if (value == NOT_FOUND) {
+                    // This should not be called since "arguments" is PERMANENT
+                    Kit.codeBug();
+                }
+                if (defaultHas("arguments")) {
+                    defaultPut("arguments", value);
+                } else if ((argumentsAttributes & READONLY) == 0) {
+                    argumentsObj = value;
+                }
+                return;
+            case Id_name:
+            case Id_arity:
+            case Id_length:
+                return;
+        }
+        super.setInstanceIdValue(id, value);
+    }
+
+    @Override
+    protected void setInstanceIdAttributes(int id, int attr)
+    {
+        switch (id) {
+            case Id_prototype:
+                prototypePropertyAttributes = attr;
+                return;
+            case Id_arguments:
+                argumentsAttributes = attr;
+                return;
+        }
+        super.setInstanceIdAttributes(id, attr);
+    }
+
+    @Override
+    protected void fillConstructorProperties(IdFunctionObject ctor)
+    {
+        // Fix up bootstrapping problem: getPrototype of the IdFunctionObject
+        // can not return Function.prototype because Function object is not
+        // yet defined.
+        ctor.setPrototype(this);
+        super.fillConstructorProperties(ctor);
+    }
+
+    @Override
+    protected void initPrototypeId(int id)
+    {
+        String s;
+        int arity;
+        switch (id) {
+          case Id_constructor: arity=1; s="constructor"; break;
+          case Id_toString:    arity=0; s="toString";    break;
+          case Id_toSource:    arity=1; s="toSource";    break;
+          case Id_apply:       arity=2; s="apply";       break;
+          case Id_call:        arity=1; s="call";        break;
+          case Id_bind:        arity=1; s="bind";        break;
+          default: throw new IllegalArgumentException(String.valueOf(id));
+        }
+        initPrototypeMethod(FUNCTION_TAG, id, s, arity);
+    }
+
+    static boolean isApply(IdFunctionObject f) {
+        return f.hasTag(FUNCTION_TAG) && f.methodId() == Id_apply;
+    }
+
+    static boolean isApplyOrCall(IdFunctionObject f) {
+        if(f.hasTag(FUNCTION_TAG)) {
+            switch(f.methodId()) {
+                case Id_apply:
+                case Id_call:
+                    return true;
+            }
+        }
+        return false;
+    }
+
+    @Override
+    public Object execIdCall(IdFunctionObject f, Context cx, Scriptable scope,
+                             Scriptable thisObj, Object[] args)
+    {
+        if (!f.hasTag(FUNCTION_TAG)) {
+            return super.execIdCall(f, cx, scope, thisObj, args);
+        }
+        int id = f.methodId();
+        switch (id) {
+          case Id_constructor:
+            return jsConstructor(cx, scope, args);
+
+          case Id_toString: {
+            BaseFunction realf = realFunction(thisObj, f);
+            int indent = ScriptRuntime.toInt32(args, 0);
+            return realf.decompile(indent, 0);
+          }
+
+          case Id_toSource: {
+            BaseFunction realf = realFunction(thisObj, f);
+            int indent = 0;
+            int flags = Decompiler.TO_SOURCE_FLAG;
+            if (args.length != 0) {
+                indent = ScriptRuntime.toInt32(args[0]);
+                if (indent >= 0) {
+                    flags = 0;
+                } else {
+                    indent = 0;
+                }
+            }
+            return realf.decompile(indent, flags);
+          }
+
+          case Id_apply:
+          case Id_call:
+            return ScriptRuntime.applyOrCall(id == Id_apply,
+                                             cx, scope, thisObj, args);
+
+          case Id_bind:
+            if ( !(thisObj instanceof Callable) ) {
+              throw ScriptRuntime.notFunctionError(thisObj);
+            }
+            Callable targetFunction = (Callable) thisObj;
+            int argc = args.length;
+            final Scriptable boundThis;
+            final Object[] boundArgs;
+            if (argc > 0) {
+              boundThis = ScriptRuntime.toObjectOrNull(cx, args[0], scope);
+              boundArgs = new Object[argc-1];
+              System.arraycopy(args, 1, boundArgs, 0, argc-1);
+            } else {
+              boundThis = null;
+              boundArgs = ScriptRuntime.emptyArgs;
+            }
+            return new BoundFunction(cx, scope, targetFunction, boundThis, boundArgs);
+        }
+        throw new IllegalArgumentException(String.valueOf(id));
+    }
+
+    private BaseFunction realFunction(Scriptable thisObj, IdFunctionObject f)
+    {
+        Object x = thisObj.getDefaultValue(ScriptRuntime.FunctionClass);
+        if (x instanceof Delegator) {
+            x = ((Delegator)x).getDelegee();
+        }
+        if (x instanceof BaseFunction) {
+            return (BaseFunction)x;
+        }
+        throw ScriptRuntime.typeError1("msg.incompat.call",
+                                       f.getFunctionName());
+    }
+
+    /**
+     * Make value as DontEnum, DontDelete, ReadOnly
+     * prototype property of this Function object
+     */
+    public void setImmunePrototypeProperty(Object value)
+    {
+        if ((prototypePropertyAttributes & READONLY) != 0) {
+            throw new IllegalStateException();
+        }
+        prototypeProperty = (value != null) ? value : UniqueTag.NULL_VALUE;
+        prototypePropertyAttributes = DONTENUM | PERMANENT | READONLY;
+    }
+
+    protected Scriptable getClassPrototype()
+    {
+        Object protoVal = getPrototypeProperty();
+        if (protoVal instanceof Scriptable) {
+            return (Scriptable) protoVal;
+        }
+        return ScriptableObject.getObjectPrototype(this);
+    }
+
+    /**
+     * Should be overridden.
+     */
+    public Object call(Context cx, Scriptable scope, Scriptable thisObj,
+                       Object[] args)
+    {
+        return Undefined.instance;
+    }
+
+    public Scriptable construct(Context cx, Scriptable scope, Object[] args)
+    {
+        Scriptable result = createObject(cx, scope);
+        if (result != null) {
+            Object val = call(cx, scope, result, args);
+            if (val instanceof Scriptable) {
+                result = (Scriptable)val;
+            }
+        } else {
+            Object val = call(cx, scope, null, args);
+            if (!(val instanceof Scriptable)) {
+                // It is program error not to return Scriptable from
+                // the call method if createObject returns null.
+                throw new IllegalStateException(
+                    "Bad implementaion of call as constructor, name="
+                    +getFunctionName()+" in "+getClass().getName());
+            }
+            result = (Scriptable)val;
+            if (result.getPrototype() == null) {
+                Scriptable proto = getClassPrototype();
+                if (result != proto) {
+                    result.setPrototype(proto);
+                }
+            }
+            if (result.getParentScope() == null) {
+                Scriptable parent = getParentScope();
+                if (result != parent) {
+                    result.setParentScope(parent);
+                }
+            }
+        }
+        return result;
+    }
+
+    /**
+     * Creates new script object.
+     * The default implementation of {@link #construct} uses the method to
+     * to get the value for <tt>thisObj</tt> argument when invoking
+     * {@link #call}.
+     * The methos is allowed to return <tt>null</tt> to indicate that
+     * {@link #call} will create a new object itself. In this case
+     * {@link #construct} will set scope and prototype on the result
+     * {@link #call} unless they are already set.
+     */
+    public Scriptable createObject(Context cx, Scriptable scope)
+    {
+        Scriptable newInstance = new NativeObject();
+        newInstance.setPrototype(getClassPrototype());
+        newInstance.setParentScope(getParentScope());
+        return newInstance;
+    }
+
+    /**
+     * Decompile the source information associated with this js
+     * function/script back into a string.
+     *
+     * @param indent How much to indent the decompiled result.
+     *
+     * @param flags Flags specifying format of decompilation output.
+     */
+    String decompile(int indent, int flags)
+    {
+        StringBuilder sb = new StringBuilder();
+        boolean justbody = (0 != (flags & Decompiler.ONLY_BODY_FLAG));
+        if (!justbody) {
+            sb.append("function ");
+            sb.append(getFunctionName());
+            sb.append("() {\n\t");
+        }
+        sb.append("[native code, arity=");
+        sb.append(getArity());
+        sb.append("]\n");
+        if (!justbody) {
+            sb.append("}\n");
+        }
+        return sb.toString();
+    }
+
+    public int getArity() { return 0; }
+
+    public int getLength() { return 0; }
+
+    public String getFunctionName() {
+        return "";
+    }
+
+    protected boolean hasPrototypeProperty() {
+        return prototypeProperty != null || this instanceof NativeFunction;
+    }
+
+    protected Object getPrototypeProperty() {
+        Object result = prototypeProperty;
+        if (result == null) {
+            // only create default prototype on native JavaScript functions,
+            // not on built-in functions, java methods, host objects etc.
+            if (this instanceof NativeFunction) {
+                result = setupDefaultPrototype();
+            } else {
+                result = Undefined.instance;
+            }
+        } else if (result == UniqueTag.NULL_VALUE) {
+            result = null;
+        }
+        return result;
+    }
+
+    private synchronized Object setupDefaultPrototype() {
+        if (prototypeProperty != null) {
+            return prototypeProperty;
+        }
+        NativeObject obj = new NativeObject();
+        final int attr = ScriptableObject.DONTENUM;
+        obj.defineProperty("constructor", this, attr);
+        // put the prototype property into the object now, then in the
+        // wacky case of a user defining a function Object(), we don't
+        // get an infinite loop trying to find the prototype.
+        prototypeProperty = obj;
+        Scriptable proto = getObjectPrototype(this);
+        if (proto != obj) {
+            // not the one we just made, it must remain grounded
+            obj.setPrototype(proto);
+        }
+        return obj;
+    }
+
+    private Object getArguments()
+    {
+      // <Function name>.arguments is deprecated, so we use a slow
+      // way of getting it that doesn't add to the invocation cost.
+      // TODO: add warning, error based on version
+      Object value = defaultHas("arguments") ? defaultGet("arguments") : argumentsObj;
+      if (value != NOT_FOUND) {
+          // Should after changing <Function name>.arguments its
+          // activation still be available during Function call?
+          // This code assumes it should not:
+          // defaultGet("arguments") != NOT_FOUND
+          // means assigned arguments
+          return value;
+      }
+      Context cx = Context.getContext();
+      NativeCall activation = ScriptRuntime.findFunctionActivation(cx, this);
+      return (activation == null)
+             ? null
+             : activation.get("arguments", activation);
+    }
+
+    private static Object jsConstructor(Context cx, Scriptable scope,
+                                        Object[] args)
+    {
+        int arglen = args.length;
+        StringBuilder sourceBuf = new StringBuilder();
+
+        sourceBuf.append("function ");
+        /* version != 1.2 Function constructor behavior -
+         * print 'anonymous' as the function name if the
+         * version (under which the function was compiled) is
+         * less than 1.2... or if it's greater than 1.2, because
+         * we need to be closer to ECMA.
+         */
+        if (cx.getLanguageVersion() != Context.VERSION_1_2) {
+            sourceBuf.append("anonymous");
+        }
+        sourceBuf.append('(');
+
+        // Append arguments as coma separated strings
+        for (int i = 0; i < arglen - 1; i++) {
+            if (i > 0) {
+                sourceBuf.append(',');
+            }
+            sourceBuf.append(ScriptRuntime.toString(args[i]));
+        }
+        sourceBuf.append(") {");
+        if (arglen != 0) {
+            // append function body
+            String funBody = ScriptRuntime.toString(args[arglen - 1]);
+            sourceBuf.append(funBody);
+        }
+        sourceBuf.append("\n}");
+        String source = sourceBuf.toString();
+
+        int[] linep = new int[1];
+        String filename = Context.getSourcePositionFromStack(linep);
+        if (filename == null) {
+            filename = "<eval'ed string>";
+            linep[0] = 1;
+        }
+
+        String sourceURI = ScriptRuntime.
+            makeUrlForGeneratedScript(false, filename, linep[0]);
+
+        Scriptable global = ScriptableObject.getTopLevelScope(scope);
+
+        ErrorReporter reporter;
+        reporter = DefaultErrorReporter.forEval(cx.getErrorReporter());
+
+        Evaluator evaluator = Context.createInterpreter();
+        if (evaluator == null) {
+            throw new JavaScriptException("Interpreter not present",
+                    filename, linep[0]);
+        }
+
+        // Compile with explicit interpreter instance to force interpreter
+        // mode.
+        return cx.compileFunction(global, source, evaluator, reporter,
+                                  sourceURI, 1, null);
+    }
+
+    @Override
+    protected int findPrototypeId(String s)
+    {
+        int id;
+// #string_id_map#
+// #generated# Last update: 2009-07-24 16:00:52 EST
+        L0: { id = 0; String X = null; int c;
+            L: switch (s.length()) {
+            case 4: c=s.charAt(0);
+                if (c=='b') { X="bind";id=Id_bind; }
+                else if (c=='c') { X="call";id=Id_call; }
+                break L;
+            case 5: X="apply";id=Id_apply; break L;
+            case 8: c=s.charAt(3);
+                if (c=='o') { X="toSource";id=Id_toSource; }
+                else if (c=='t') { X="toString";id=Id_toString; }
+                break L;
+            case 11: X="constructor";id=Id_constructor; break L;
+            }
+            if (X!=null && X!=s && !X.equals(s)) id = 0;
+            break L0;
+        }
+// #/generated#
+        return id;
+    }
+
+    private static final int
+        Id_constructor    = 1,
+        Id_toString       = 2,
+        Id_toSource       = 3,
+        Id_apply          = 4,
+        Id_call           = 5,
+        Id_bind           = 6,
+
+        MAX_PROTOTYPE_ID  = Id_bind;
+
+// #/string_id_map#
+
+    private Object prototypeProperty;
+    private Object argumentsObj = NOT_FOUND;
+
+    // For function object instances, attributes are
+    //  {configurable:false, enumerable:false};
+    // see ECMA 15.3.5.2
+    private int prototypePropertyAttributes = PERMANENT|DONTENUM;
+    private int argumentsAttributes = PERMANENT|DONTENUM;
+}
+
diff -pruN 20130227+dfsg1-14/rhino/src/org/mozilla/javascript/BoundFunction.java 20130227+rhino-1/rhino/src/org/mozilla/javascript/BoundFunction.java
--- 20130227+dfsg1-14/rhino/src/org/mozilla/javascript/BoundFunction.java	1970-01-01 00:00:00.000000000 +0000
+++ 20130227+rhino-1/rhino/src/org/mozilla/javascript/BoundFunction.java	2023-05-25 14:24:50.000000000 +0000
@@ -0,0 +1,83 @@
+/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+package org.mozilla.javascript;
+
+/**
+ * The class for results of the Function.bind operation
+ * EcmaScript 5 spec, 15.3.4.5
+ * @author Raphael Speyer
+ */
+public class BoundFunction extends BaseFunction {
+    
+  static final long serialVersionUID = 2118137342826470729L;
+    
+  private final Callable targetFunction;
+  private final Scriptable boundThis;
+  private final Object[] boundArgs;
+  private final int length;
+
+  public BoundFunction(Context cx, Scriptable scope, Callable targetFunction, Scriptable boundThis,
+                       Object[] boundArgs)
+  {
+    this.targetFunction = targetFunction;
+    this.boundThis = boundThis;
+    this.boundArgs = boundArgs;
+    if (targetFunction instanceof BaseFunction) {
+      length = Math.max(0, ((BaseFunction) targetFunction).getLength() - boundArgs.length);
+    } else {
+      length = 0;
+    }
+
+    ScriptRuntime.setFunctionProtoAndParent(this, scope);
+
+    Function thrower = ScriptRuntime.typeErrorThrower(cx);
+    NativeObject throwing = new NativeObject();
+    throwing.put("get", throwing, thrower);
+    throwing.put("set", throwing, thrower);
+    throwing.put("enumerable", throwing, false);
+    throwing.put("configurable", throwing, false);
+    throwing.preventExtensions();
+
+    this.defineOwnProperty(cx, "caller", throwing, false);
+    this.defineOwnProperty(cx, "arguments", throwing, false);
+  }
+
+  @Override
+  public Object call(Context cx, Scriptable scope, Scriptable thisObj, Object[] extraArgs)
+  {
+    Scriptable callThis = boundThis != null ? boundThis : ScriptRuntime.getTopCallScope(cx);
+    return targetFunction.call(cx, scope, callThis, concat(boundArgs, extraArgs));
+  }
+
+  @Override
+  public Scriptable construct(Context cx, Scriptable scope, Object[] extraArgs) {
+    if (targetFunction instanceof Function) {
+      return ((Function) targetFunction).construct(cx, scope, concat(boundArgs, extraArgs));
+    }
+    throw ScriptRuntime.typeError0("msg.not.ctor");
+  }
+
+  @Override
+  public boolean hasInstance(Scriptable instance) {
+    if (targetFunction instanceof Function) {
+      return ((Function) targetFunction).hasInstance(instance);
+    }
+    throw ScriptRuntime.typeError0("msg.not.ctor");
+  }
+
+  @Override
+  public int getLength() {
+    return length;
+  }
+
+  private Object[] concat(Object[] first, Object[] second) {
+    Object[] args = new Object[first.length + second.length];
+    System.arraycopy(first, 0, args, 0, first.length);
+    System.arraycopy(second, 0, args, first.length, second.length);
+    return args;
+  }
+}
diff -pruN 20130227+dfsg1-14/rhino/src/org/mozilla/javascript/Callable.java 20130227+rhino-1/rhino/src/org/mozilla/javascript/Callable.java
--- 20130227+dfsg1-14/rhino/src/org/mozilla/javascript/Callable.java	1970-01-01 00:00:00.000000000 +0000
+++ 20130227+rhino-1/rhino/src/org/mozilla/javascript/Callable.java	2023-05-25 14:24:50.000000000 +0000
@@ -0,0 +1,27 @@
+/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+package org.mozilla.javascript;
+
+/**
+ * Generic notion of callable object that can execute some script-related code
+ * upon request with specified values for script scope and this objects.
+ */
+public interface Callable
+{
+    /**
+     * Perform the call.
+     *
+     * @param cx the current Context for this thread
+     * @param scope the scope to use to resolve properties.
+     * @param thisObj the JavaScript <code>this</code> object
+     * @param args the array of arguments
+     * @return the result of the call
+     */
+    public Object call(Context cx, Scriptable scope, Scriptable thisObj,
+                       Object[] args);
+}
+
diff -pruN 20130227+dfsg1-14/rhino/src/org/mozilla/javascript/ClassCache.java 20130227+rhino-1/rhino/src/org/mozilla/javascript/ClassCache.java
--- 20130227+dfsg1-14/rhino/src/org/mozilla/javascript/ClassCache.java	1970-01-01 00:00:00.000000000 +0000
+++ 20130227+rhino-1/rhino/src/org/mozilla/javascript/ClassCache.java	2023-05-25 14:24:50.000000000 +0000
@@ -0,0 +1,200 @@
+/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+package org.mozilla.javascript;
+
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.io.Serializable;
+
+/**
+ * Cache of generated classes and data structures to access Java runtime
+ * from JavaScript.
+ *
+ * @author Igor Bukanov
+ *
+ * @since Rhino 1.5 Release 5
+ */
+public class ClassCache implements Serializable
+{
+    private static final long serialVersionUID = -8866246036237312215L;
+    private static final Object AKEY = "ClassCache";
+    private volatile boolean cachingIsEnabled = true;
+    private transient Map<Class<?>,JavaMembers> classTable;
+    private transient Map<JavaAdapter.JavaAdapterSignature,Class<?>> classAdapterCache;
+    private transient Map<Class<?>,Object> interfaceAdapterCache;
+    private int generatedClassSerial;
+    private Scriptable associatedScope;
+
+    /**
+     * Search for ClassCache object in the given scope.
+     * The method first calls
+     * {@link ScriptableObject#getTopLevelScope(Scriptable scope)}
+     * to get the top most scope and then tries to locate associated
+     * ClassCache object in the prototype chain of the top scope.
+     *
+     * @param scope scope to search for ClassCache object.
+     * @return previously associated ClassCache object or a new instance of
+     *         ClassCache if no ClassCache object was found.
+     *
+     * @see #associate(ScriptableObject topScope)
+     */
+    public static ClassCache get(Scriptable scope)
+    {
+        ClassCache cache = (ClassCache)
+                ScriptableObject.getTopScopeValue(scope, AKEY);
+        if (cache == null) {
+            throw new RuntimeException("Can't find top level scope for " +
+                    "ClassCache.get");
+        }
+        return cache;
+    }
+
+    /**
+     * Associate ClassCache object with the given top-level scope.
+     * The ClassCache object can only be associated with the given scope once.
+     *
+     * @param topScope scope to associate this ClassCache object with.
+     * @return true if no previous ClassCache objects were embedded into
+     *         the scope and this ClassCache were successfully associated
+     *         or false otherwise.
+     *
+     * @see #get(Scriptable scope)
+     */
+    public boolean associate(ScriptableObject topScope)
+    {
+        if (topScope.getParentScope() != null) {
+            // Can only associate cache with top level scope
+            throw new IllegalArgumentException();
+        }
+        if (this == topScope.associateValue(AKEY, this)) {
+            associatedScope = topScope;
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * Empty caches of generated Java classes and Java reflection information.
+     */
+    public synchronized void clearCaches()
+    {
+        classTable = null;
+        classAdapterCache = null;
+        interfaceAdapterCache = null;
+    }
+
+    /**
+     * Check if generated Java classes and Java reflection information
+     * is cached.
+     */
+    public final boolean isCachingEnabled()
+    {
+        return cachingIsEnabled;
+    }
+
+     /**
+     * Set whether to cache some values.
+     * <p>
+     * By default, the engine will cache the results of
+     * <tt>Class.getMethods()</tt> and similar calls.
+     * This can speed execution dramatically, but increases the memory
+     * footprint. Also, with caching enabled, references may be held to
+     * objects past the lifetime of any real usage.
+     * <p>
+     * If caching is enabled and this method is called with a
+     * <code>false</code> argument, the caches will be emptied.
+     * <p>
+     * Caching is enabled by default.
+     *
+     * @param enabled if true, caching is enabled
+     *
+     * @see #clearCaches()
+     */
+    public synchronized void setCachingEnabled(boolean enabled)
+    {
+        if (enabled == cachingIsEnabled)
+            return;
+        if (!enabled)
+            clearCaches();
+        cachingIsEnabled = enabled;
+    }
+
+    /**
+     * @return a map from classes to associated JavaMembers objects
+     */
+    Map<Class<?>,JavaMembers> getClassCacheMap() {
+        if (classTable == null) {
+            // Use 1 as concurrency level here and for other concurrent hash maps
+            // as we don't expect high levels of sustained concurrent writes.
+            classTable = new ConcurrentHashMap<Class<?>,JavaMembers>(16, 0.75f, 1);
+        }
+        return classTable;
+    }
+
+    Map<JavaAdapter.JavaAdapterSignature,Class<?>> getInterfaceAdapterCacheMap()
+    {
+        if (classAdapterCache == null) {
+            classAdapterCache = new ConcurrentHashMap<JavaAdapter.JavaAdapterSignature,Class<?>>(16, 0.75f, 1);
+        }
+        return classAdapterCache;
+    }
+
+    /**
+     * @deprecated
+     * The method always returns false.
+     * @see #setInvokerOptimizationEnabled(boolean enabled)
+     */
+    @Deprecated
+    public boolean isInvokerOptimizationEnabled()
+    {
+        return false;
+    }
+
+    /**
+     * @deprecated
+     * The method does nothing.
+     * Invoker optimization is no longer used by Rhino.
+     * On modern JDK like 1.4 or 1.5 the disadvantages of the optimization
+     * like increased memory usage or longer initialization time overweight
+     * small speed increase that can be gained using generated proxy class
+     * to replace reflection.
+     */
+    @Deprecated
+    public synchronized void setInvokerOptimizationEnabled(boolean enabled)
+    {
+    }
+
+    /**
+     * Internal engine method to return serial number for generated classes
+     * to ensure name uniqueness.
+     */
+    public final synchronized int newClassSerialNumber()
+    {
+        return ++generatedClassSerial;
+    }
+
+    Object getInterfaceAdapter(Class<?> cl)
+    {
+        return interfaceAdapterCache == null
+                    ? null
+                    : interfaceAdapterCache.get(cl);
+    }
+
+    synchronized void cacheInterfaceAdapter(Class<?> cl, Object iadapter)
+    {
+        if (cachingIsEnabled) {
+            if (interfaceAdapterCache == null) {
+                interfaceAdapterCache = new ConcurrentHashMap<Class<?>,Object>(16, 0.75f, 1);
+            }
+            interfaceAdapterCache.put(cl, iadapter);
+        }
+    }
+
+    Scriptable getAssociatedScope() {
+        return associatedScope;
+    }
+}
diff -pruN 20130227+dfsg1-14/rhino/src/org/mozilla/javascript/ClassShutter.java 20130227+rhino-1/rhino/src/org/mozilla/javascript/ClassShutter.java
--- 20130227+dfsg1-14/rhino/src/org/mozilla/javascript/ClassShutter.java	1970-01-01 00:00:00.000000000 +0000
+++ 20130227+rhino-1/rhino/src/org/mozilla/javascript/ClassShutter.java	2023-05-25 14:24:50.000000000 +0000
@@ -0,0 +1,56 @@
+/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// API class
+
+package org.mozilla.javascript;
+
+/**
+Embeddings that wish to filter Java classes that are visible to scripts
+through the LiveConnect, should implement this interface.
+
+@see Context#setClassShutter(ClassShutter)
+@since 1.5 Release 4
+@author Norris Boyd
+*/
+
+ public interface ClassShutter {
+
+    /**
+     * Return true iff the Java class with the given name should be exposed
+     * to scripts.
+     * <p>
+     * An embedding may filter which Java classes are exposed through
+     * LiveConnect to JavaScript scripts.
+     * <p>
+     * Due to the fact that there is no package reflection in Java,
+     * this method will also be called with package names. There
+     * is no way for Rhino to tell if "Packages.a.b" is a package name
+     * or a class that doesn't exist. What Rhino does is attempt
+     * to load each segment of "Packages.a.b.c": It first attempts to
+     * load class "a", then attempts to load class "a.b", then
+     * finally attempts to load class "a.b.c". On a Rhino installation
+     * without any ClassShutter set, and without any of the
+     * above classes, the expression "Packages.a.b.c" will result in
+     * a [JavaPackage a.b.c] and not an error.
+     * <p>
+     * With ClassShutter supplied, Rhino will first call
+     * visibleToScripts before attempting to look up the class name. If
+     * visibleToScripts returns false, the class name lookup is not
+     * performed and subsequent Rhino execution assumes the class is
+     * not present. So for "java.lang.System.out.println" the lookup
+     * of "java.lang.System" is skipped and thus Rhino assumes that
+     * "java.lang.System" doesn't exist. So then for "java.lang.System.out",
+     * Rhino attempts to load the class "java.lang.System.out" because
+     * it assumes that "java.lang.System" is a package name.
+     * <p>
+     * @param fullClassName the full name of the class (including the package
+     *                      name, with '.' as a delimiter). For example the
+     *                      standard string class is "java.lang.String"
+     * @return whether or not to reveal this class to scripts
+     */
+    public boolean visibleToScripts(String fullClassName);
+}
diff -pruN 20130227+dfsg1-14/rhino/src/org/mozilla/javascript/CodeGenerator.java 20130227+rhino-1/rhino/src/org/mozilla/javascript/CodeGenerator.java
--- 20130227+dfsg1-14/rhino/src/org/mozilla/javascript/CodeGenerator.java	1970-01-01 00:00:00.000000000 +0000
+++ 20130227+rhino-1/rhino/src/org/mozilla/javascript/CodeGenerator.java	2023-05-25 14:24:50.000000000 +0000
@@ -0,0 +1,1478 @@
+/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+package org.mozilla.javascript;
+
+import org.mozilla.javascript.ast.ScriptNode;
+import org.mozilla.javascript.ast.Jump;
+import org.mozilla.javascript.ast.FunctionNode;
+
+/**
+ * Generates bytecode for the Interpreter.
+ */
+class CodeGenerator extends Icode {
+
+    private static final int MIN_LABEL_TABLE_SIZE = 32;
+    private static final int MIN_FIXUP_TABLE_SIZE = 40;
+
+    private CompilerEnvirons compilerEnv;
+
+    private boolean itsInFunctionFlag;
+    private boolean itsInTryFlag;
+
+    private InterpreterData itsData;
+
+    private ScriptNode scriptOrFn;
+    private int iCodeTop;
+    private int stackDepth;
+    private int lineNumber;
+    private int doubleTableTop;
+
+    private ObjToIntMap strings = new ObjToIntMap(20);
+    private int localTop;
+    private int[] labelTable;
+    private int labelTableTop;
+
+    // fixupTable[i] = (label_index << 32) | fixup_site
+    private long[] fixupTable;
+    private int fixupTableTop;
+    private ObjArray literalIds = new ObjArray();
+
+    private int exceptionTableTop;
+
+    // ECF_ or Expression Context Flags constants: for now only TAIL
+    private static final int ECF_TAIL = 1 << 0;
+
+    public InterpreterData compile(CompilerEnvirons compilerEnv,
+                                   ScriptNode tree,
+                                   String encodedSource,
+                                   boolean returnFunction)
+    {
+        this.compilerEnv = compilerEnv;
+
+        if (Token.printTrees) {
+            System.out.println("before transform:");
+            System.out.println(tree.toStringTree(tree));
+        }
+
+        new NodeTransformer().transform(tree);
+
+        if (Token.printTrees) {
+            System.out.println("after transform:");
+            System.out.println(tree.toStringTree(tree));
+        }
+
+        if (returnFunction) {
+            scriptOrFn = tree.getFunctionNode(0);
+        } else {
+            scriptOrFn = tree;
+        }
+
+        itsData = new InterpreterData(compilerEnv.getLanguageVersion(),
+                                      scriptOrFn.getSourceName(),
+                                      encodedSource,
+                                      scriptOrFn.isInStrictMode());
+        itsData.topLevel = true;
+
+        if (returnFunction) {
+            generateFunctionICode();
+        } else {
+            generateICodeFromTree(scriptOrFn);
+        }
+        return itsData;
+    }
+
+    private void generateFunctionICode()
+    {
+        itsInFunctionFlag = true;
+
+        FunctionNode theFunction = (FunctionNode)scriptOrFn;
+
+        itsData.itsFunctionType = theFunction.getFunctionType();
+        itsData.itsNeedsActivation = theFunction.requiresActivation();
+        if (theFunction.getFunctionName() != null) {
+            itsData.itsName = theFunction.getName();
+        }
+        if (theFunction.isGenerator()) {
+          addIcode(Icode_GENERATOR);
+          addUint16(theFunction.getBaseLineno() & 0xFFFF);
+        }
+        if (theFunction.isInStrictMode()) {
+            itsData.isStrict = true;
+        }
+
+        generateICodeFromTree(theFunction.getLastChild());
+    }
+
+    private void generateICodeFromTree(Node tree)
+    {
+        generateNestedFunctions();
+
+        generateRegExpLiterals();
+
+        visitStatement(tree, 0);
+        fixLabelGotos();
+        // add RETURN_RESULT only to scripts as function always ends with RETURN
+        if (itsData.itsFunctionType == 0) {
+            addToken(Token.RETURN_RESULT);
+        }
+
+        if (itsData.itsICode.length != iCodeTop) {
+            // Make itsData.itsICode length exactly iCodeTop to save memory
+            // and catch bugs with jumps beyond icode as early as possible
+            byte[] tmp = new byte[iCodeTop];
+            System.arraycopy(itsData.itsICode, 0, tmp, 0, iCodeTop);
+            itsData.itsICode = tmp;
+        }
+        if (strings.size() == 0) {
+            itsData.itsStringTable = null;
+        } else {
+            itsData.itsStringTable = new String[strings.size()];
+            ObjToIntMap.Iterator iter = strings.newIterator();
+            for (iter.start(); !iter.done(); iter.next()) {
+                String str = (String)iter.getKey();
+                int index = iter.getValue();
+                if (itsData.itsStringTable[index] != null) Kit.codeBug();
+                itsData.itsStringTable[index] = str;
+            }
+        }
+        if (doubleTableTop == 0) {
+            itsData.itsDoubleTable = null;
+        } else if (itsData.itsDoubleTable.length != doubleTableTop) {
+            double[] tmp = new double[doubleTableTop];
+            System.arraycopy(itsData.itsDoubleTable, 0, tmp, 0,
+                             doubleTableTop);
+            itsData.itsDoubleTable = tmp;
+        }
+        if (exceptionTableTop != 0
+            && itsData.itsExceptionTable.length != exceptionTableTop)
+        {
+            int[] tmp = new int[exceptionTableTop];
+            System.arraycopy(itsData.itsExceptionTable, 0, tmp, 0,
+                             exceptionTableTop);
+            itsData.itsExceptionTable = tmp;
+        }
+
+        itsData.itsMaxVars = scriptOrFn.getParamAndVarCount();
+        // itsMaxFrameArray: interpret method needs this amount for its
+        // stack and sDbl arrays
+        itsData.itsMaxFrameArray = itsData.itsMaxVars
+                                   + itsData.itsMaxLocals
+                                   + itsData.itsMaxStack;
+
+        itsData.argNames = scriptOrFn.getParamAndVarNames();
+        itsData.argIsConst = scriptOrFn.getParamAndVarConst();
+        itsData.argCount = scriptOrFn.getParamCount();
+
+        itsData.encodedSourceStart = scriptOrFn.getEncodedSourceStart();
+        itsData.encodedSourceEnd = scriptOrFn.getEncodedSourceEnd();
+
+        if (literalIds.size() != 0) {
+            itsData.literalIds = literalIds.toArray();
+        }
+
+        if (Token.printICode) Interpreter.dumpICode(itsData);
+    }
+
+    private void generateNestedFunctions()
+    {
+        int functionCount = scriptOrFn.getFunctionCount();
+        if (functionCount == 0) return;
+
+        InterpreterData[] array = new InterpreterData[functionCount];
+        for (int i = 0; i != functionCount; i++) {
+            FunctionNode fn = scriptOrFn.getFunctionNode(i);
+            CodeGenerator gen = new CodeGenerator();
+            gen.compilerEnv = compilerEnv;
+            gen.scriptOrFn = fn;
+            gen.itsData = new InterpreterData(itsData);
+            gen.generateFunctionICode();
+            array[i] = gen.itsData;
+        }
+        itsData.itsNestedFunctions = array;
+    }
+
+    private void generateRegExpLiterals()
+    {
+        int N = scriptOrFn.getRegexpCount();
+        if (N == 0) return;
+
+        Context cx = Context.getContext();
+        RegExpProxy rep = ScriptRuntime.checkRegExpProxy(cx);
+        Object[] array = new Object[N];
+        for (int i = 0; i != N; i++) {
+            String string = scriptOrFn.getRegexpString(i);
+            String flags = scriptOrFn.getRegexpFlags(i);
+            array[i] = rep.compileRegExp(cx, string, flags);
+        }
+        itsData.itsRegExpLiterals = array;
+    }
+
+    private void updateLineNumber(Node node)
+    {
+        int lineno = node.getLineno();
+        if (lineno != lineNumber && lineno >= 0) {
+            if (itsData.firstLinePC < 0) {
+                itsData.firstLinePC = lineno;
+            }
+            lineNumber = lineno;
+            addIcode(Icode_LINE);
+            addUint16(lineno & 0xFFFF);
+        }
+    }
+
+    private RuntimeException badTree(Node node)
+    {
+        throw new RuntimeException(node.toString());
+    }
+
+    private void visitStatement(Node node, int initialStackDepth)
+    {
+        int type = node.getType();
+        Node child = node.getFirstChild();
+        switch (type) {
+
+          case Token.FUNCTION:
+            {
+                int fnIndex = node.getExistingIntProp(Node.FUNCTION_PROP);
+                int fnType = scriptOrFn.getFunctionNode(fnIndex).
+                                 getFunctionType();
+                // Only function expressions or function expression
+                // statements need closure code creating new function
+                // object on stack as function statements are initialized
+                // at script/function start.
+                // In addition, function expressions can not be present here
+                // at statement level, they must only be present as expressions.
+                if (fnType == FunctionNode.FUNCTION_EXPRESSION_STATEMENT) {
+                    addIndexOp(Icode_CLOSURE_STMT, fnIndex);
+                } else {
+                    if (fnType != FunctionNode.FUNCTION_STATEMENT) {
+                        throw Kit.codeBug();
+                    }
+                }
+                // For function statements or function expression statements
+                // in scripts, we need to ensure that the result of the script
+                // is the function if it is the last statement in the script.
+                // For example, eval("function () {}") should return a
+                // function, not undefined.
+                if (!itsInFunctionFlag) {
+                    addIndexOp(Icode_CLOSURE_EXPR, fnIndex);
+                    stackChange(1);
+                    addIcode(Icode_POP_RESULT);
+                    stackChange(-1);
+                }
+            }
+            break;
+
+          case Token.LABEL:
+          case Token.LOOP:
+          case Token.BLOCK:
+          case Token.EMPTY:
+          case Token.WITH:
+            updateLineNumber(node);
+            // fallthru
+          case Token.SCRIPT:
+            while (child != null) {
+                visitStatement(child, initialStackDepth);
+                child = child.getNext();
+            }
+            break;
+
+          case Token.ENTERWITH:
+            visitExpression(child, 0);
+            addToken(Token.ENTERWITH);
+            stackChange(-1);
+            break;
+
+          case Token.LEAVEWITH:
+            addToken(Token.LEAVEWITH);
+            break;
+
+          case Token.LOCAL_BLOCK:
+            {
+                int local = allocLocal();
+                node.putIntProp(Node.LOCAL_PROP, local);
+                updateLineNumber(node);
+                while (child != null) {
+                    visitStatement(child, initialStackDepth);
+                    child = child.getNext();
+                }
+                addIndexOp(Icode_LOCAL_CLEAR, local);
+                releaseLocal(local);
+            }
+            break;
+
+          case Token.DEBUGGER:
+            addIcode(Icode_DEBUGGER);
+            break;
+
+          case Token.SWITCH:
+            updateLineNumber(node);
+            // See comments in IRFactory.createSwitch() for description
+            // of SWITCH node
+            {
+                visitExpression(child, 0);
+                for (Jump caseNode = (Jump)child.getNext();
+                     caseNode != null;
+                     caseNode = (Jump)caseNode.getNext())
+                {
+                    if (caseNode.getType() != Token.CASE)
+                        throw badTree(caseNode);
+                    Node test = caseNode.getFirstChild();
+                    addIcode(Icode_DUP);
+                    stackChange(1);
+                    visitExpression(test, 0);
+                    addToken(Token.SHEQ);
+                    stackChange(-1);
+                    // If true, Icode_IFEQ_POP will jump and remove case
+                    // value from stack
+                    addGoto(caseNode.target, Icode_IFEQ_POP);
+                    stackChange(-1);
+                }
+                addIcode(Icode_POP);
+                stackChange(-1);
+            }
+            break;
+
+          case Token.TARGET:
+            markTargetLabel(node);
+            break;
+
+          case Token.IFEQ :
+          case Token.IFNE :
+            {
+                Node target = ((Jump)node).target;
+                visitExpression(child, 0);
+                addGoto(target, type);
+                stackChange(-1);
+            }
+            break;
+
+          case Token.GOTO:
+            {
+                Node target = ((Jump)node).target;
+                addGoto(target, type);
+            }
+            break;
+
+          case Token.JSR:
+            {
+                Node target = ((Jump)node).target;
+                addGoto(target, Icode_GOSUB);
+            }
+            break;
+
+          case Token.FINALLY:
+            {
+                // Account for incomming GOTOSUB address
+                stackChange(1);
+                int finallyRegister = getLocalBlockRef(node);
+                addIndexOp(Icode_STARTSUB, finallyRegister);
+                stackChange(-1);
+                while (child != null) {
+                    visitStatement(child, initialStackDepth);
+                    child = child.getNext();
+                }
+                addIndexOp(Icode_RETSUB, finallyRegister);
+            }
+            break;
+
+          case Token.EXPR_VOID:
+          case Token.EXPR_RESULT:
+            updateLineNumber(node);
+            visitExpression(child, 0);
+            addIcode((type == Token.EXPR_VOID) ? Icode_POP : Icode_POP_RESULT);
+            stackChange(-1);
+            break;
+
+          case Token.TRY:
+            {
+                Jump tryNode = (Jump)node;
+                int exceptionObjectLocal = getLocalBlockRef(tryNode);
+                int scopeLocal = allocLocal();
+
+                addIndexOp(Icode_SCOPE_SAVE, scopeLocal);
+
+                int tryStart = iCodeTop;
+                boolean savedFlag = itsInTryFlag;
+                itsInTryFlag = true;
+                while (child != null) {
+                    visitStatement(child, initialStackDepth);
+                    child = child.getNext();
+                }
+                itsInTryFlag = savedFlag;
+
+                Node catchTarget = tryNode.target;
+                if (catchTarget != null) {
+                    int catchStartPC
+                        = labelTable[getTargetLabel(catchTarget)];
+                    addExceptionHandler(
+                        tryStart, catchStartPC, catchStartPC,
+                        false, exceptionObjectLocal, scopeLocal);
+                }
+                Node finallyTarget = tryNode.getFinally();
+                if (finallyTarget != null) {
+                    int finallyStartPC
+                        = labelTable[getTargetLabel(finallyTarget)];
+                    addExceptionHandler(
+                        tryStart, finallyStartPC, finallyStartPC,
+                        true, exceptionObjectLocal, scopeLocal);
+                }
+
+                addIndexOp(Icode_LOCAL_CLEAR, scopeLocal);
+                releaseLocal(scopeLocal);
+            }
+            break;
+
+          case Token.CATCH_SCOPE:
+            {
+                int localIndex = getLocalBlockRef(node);
+                int scopeIndex = node.getExistingIntProp(Node.CATCH_SCOPE_PROP);
+                String name = child.getString();
+                child = child.getNext();
+                visitExpression(child, 0); // load expression object
+                addStringPrefix(name);
+                addIndexPrefix(localIndex);
+                addToken(Token.CATCH_SCOPE);
+                addUint8(scopeIndex != 0 ? 1 : 0);
+                stackChange(-1);
+            }
+            break;
+
+          case Token.THROW:
+            updateLineNumber(node);
+            visitExpression(child, 0);
+            addToken(Token.THROW);
+            addUint16(lineNumber & 0xFFFF);
+            stackChange(-1);
+            break;
+
+          case Token.RETHROW:
+            updateLineNumber(node);
+            addIndexOp(Token.RETHROW, getLocalBlockRef(node));
+            break;
+
+          case Token.RETURN:
+            updateLineNumber(node);
+            if (node.getIntProp(Node.GENERATOR_END_PROP, 0) != 0) {
+                // We're in a generator, so change RETURN to GENERATOR_END
+                addIcode(Icode_GENERATOR_END);
+                addUint16(lineNumber & 0xFFFF);
+            } else if (child != null) {
+                visitExpression(child, ECF_TAIL);
+                addToken(Token.RETURN);
+                stackChange(-1);
+            } else {
+                addIcode(Icode_RETUNDEF);
+            }
+            break;
+
+          case Token.RETURN_RESULT:
+            updateLineNumber(node);
+            addToken(Token.RETURN_RESULT);
+            break;
+
+          case Token.ENUM_INIT_KEYS:
+          case Token.ENUM_INIT_VALUES:
+          case Token.ENUM_INIT_ARRAY:
+          case Token.ENUM_INIT_VALUES_IN_ORDER:
+            visitExpression(child, 0);
+            addIndexOp(type, getLocalBlockRef(node));
+            stackChange(-1);
+            break;
+
+          case Icode_GENERATOR:
+            break;
+
+          default:
+            throw badTree(node);
+        }
+
+        if (stackDepth != initialStackDepth) {
+            throw Kit.codeBug();
+        }
+    }
+
+    private void visitExpression(Node node, int contextFlags)
+    {
+        int type = node.getType();
+        Node child = node.getFirstChild();
+        int savedStackDepth = stackDepth;
+        switch (type) {
+
+          case Token.FUNCTION:
+            {
+                int fnIndex = node.getExistingIntProp(Node.FUNCTION_PROP);
+                FunctionNode fn = scriptOrFn.getFunctionNode(fnIndex);
+                // See comments in visitStatement for Token.FUNCTION case
+                if (fn.getFunctionType() != FunctionNode.FUNCTION_EXPRESSION &&
+                    fn.getFunctionType() != FunctionNode.ARROW_FUNCTION) {
+                    throw Kit.codeBug();
+                }
+                addIndexOp(Icode_CLOSURE_EXPR, fnIndex);
+                stackChange(1);
+            }
+            break;
+
+          case Token.LOCAL_LOAD:
+            {
+                int localIndex = getLocalBlockRef(node);
+                addIndexOp(Token.LOCAL_LOAD, localIndex);
+                stackChange(1);
+            }
+            break;
+
+          case Token.COMMA:
+            {
+                Node lastChild = node.getLastChild();
+                while (child != lastChild) {
+                    visitExpression(child, 0);
+                    addIcode(Icode_POP);
+                    stackChange(-1);
+                    child = child.getNext();
+                }
+                // Preserve tail context flag if any
+                visitExpression(child, contextFlags & ECF_TAIL);
+            }
+            break;
+
+          case Token.USE_STACK:
+            // Indicates that stack was modified externally,
+            // like placed catch object
+            stackChange(1);
+            break;
+
+          case Token.REF_CALL:
+          case Token.CALL:
+          case Token.NEW:
+            {
+                if (type == Token.NEW) {
+                    visitExpression(child, 0);
+                } else {
+                    generateCallFunAndThis(child);
+                }
+                int argCount = 0;
+                while ((child = child.getNext()) != null) {
+                    visitExpression(child, 0);
+                    ++argCount;
+                }
+                int callType = node.getIntProp(Node.SPECIALCALL_PROP,
+                                               Node.NON_SPECIALCALL);
+                if (type != Token.REF_CALL && callType != Node.NON_SPECIALCALL) {
+                    // embed line number and source filename
+                    addIndexOp(Icode_CALLSPECIAL, argCount);
+                    addUint8(callType);
+                    addUint8(type == Token.NEW ? 1 : 0);
+                    addUint16(lineNumber & 0xFFFF);
+                } else {
+                    // Only use the tail call optimization if we're not in a try
+                    // or we're not generating debug info (since the
+                    // optimization will confuse the debugger)
+                    if (type == Token.CALL && (contextFlags & ECF_TAIL) != 0 &&
+                        !compilerEnv.isGenerateDebugInfo() && !itsInTryFlag)
+                    {
+                        type = Icode_TAIL_CALL;
+                    }
+                    addIndexOp(type, argCount);
+                }
+                // adjust stack
+                if (type == Token.NEW) {
+                    // new: f, args -> result
+                    stackChange(-argCount);
+                } else {
+                    // call: f, thisObj, args -> result
+                    // ref_call: f, thisObj, args -> ref
+                    stackChange(-1 - argCount);
+                }
+                if (argCount > itsData.itsMaxCalleeArgs) {
+                    itsData.itsMaxCalleeArgs = argCount;
+                }
+            }
+            break;
+
+          case Token.AND:
+          case Token.OR:
+            {
+                visitExpression(child, 0);
+                addIcode(Icode_DUP);
+                stackChange(1);
+                int afterSecondJumpStart = iCodeTop;
+                int jump = (type == Token.AND) ? Token.IFNE : Token.IFEQ;
+                addGotoOp(jump);
+                stackChange(-1);
+                addIcode(Icode_POP);
+                stackChange(-1);
+                child = child.getNext();
+                // Preserve tail context flag if any
+                visitExpression(child, contextFlags & ECF_TAIL);
+                resolveForwardGoto(afterSecondJumpStart);
+            }
+            break;
+
+          case Token.HOOK:
+            {
+                Node ifThen = child.getNext();
+                Node ifElse = ifThen.getNext();
+                visitExpression(child, 0);
+                int elseJumpStart = iCodeTop;
+                addGotoOp(Token.IFNE);
+                stackChange(-1);
+                // Preserve tail context flag if any
+                visitExpression(ifThen, contextFlags & ECF_TAIL);
+                int afterElseJumpStart = iCodeTop;
+                addGotoOp(Token.GOTO);
+                resolveForwardGoto(elseJumpStart);
+                stackDepth = savedStackDepth;
+                // Preserve tail context flag if any
+                visitExpression(ifElse, contextFlags & ECF_TAIL);
+                resolveForwardGoto(afterElseJumpStart);
+            }
+            break;
+
+          case Token.GETPROP:
+          case Token.GETPROPNOWARN:
+            visitExpression(child, 0);
+            child = child.getNext();
+            addStringOp(type, child.getString());
+            break;
+
+          case Token.DELPROP:
+            boolean isName = child.getType() == Token.BINDNAME;
+            visitExpression(child, 0);
+            child = child.getNext();
+            visitExpression(child, 0);
+            if (isName) {
+                // special handling for delete name
+                addIcode(Icode_DELNAME);
+            } else {
+                addToken(Token.DELPROP);
+            }
+            stackChange(-1);
+            break;
+
+          case Token.GETELEM:
+          case Token.BITAND:
+          case Token.BITOR:
+          case Token.BITXOR:
+          case Token.LSH:
+          case Token.RSH:
+          case Token.URSH:
+          case Token.ADD:
+          case Token.SUB:
+          case Token.MOD:
+          case Token.DIV:
+          case Token.MUL:
+          case Token.EQ:
+          case Token.NE:
+          case Token.SHEQ:
+          case Token.SHNE:
+          case Token.IN:
+          case Token.INSTANCEOF:
+          case Token.LE:
+          case Token.LT:
+          case Token.GE:
+          case Token.GT:
+            visitExpression(child, 0);
+            child = child.getNext();
+            visitExpression(child, 0);
+            addToken(type);
+            stackChange(-1);
+            break;
+
+          case Token.POS:
+          case Token.NEG:
+          case Token.NOT:
+          case Token.BITNOT:
+          case Token.TYPEOF:
+          case Token.VOID:
+            visitExpression(child, 0);
+            if (type == Token.VOID) {
+                addIcode(Icode_POP);
+                addIcode(Icode_UNDEF);
+            } else {
+                addToken(type);
+            }
+            break;
+
+          case Token.GET_REF:
+          case Token.DEL_REF:
+            visitExpression(child, 0);
+            addToken(type);
+            break;
+
+          case Token.SETPROP:
+          case Token.SETPROP_OP:
+            {
+                visitExpression(child, 0);
+                child = child.getNext();
+                String property = child.getString();
+                child = child.getNext();
+                if (type == Token.SETPROP_OP) {
+                    addIcode(Icode_DUP);
+                    stackChange(1);
+                    addStringOp(Token.GETPROP, property);
+                    // Compensate for the following USE_STACK
+                    stackChange(-1);
+                }
+                visitExpression(child, 0);
+                addStringOp(Token.SETPROP, property);
+                stackChange(-1);
+            }
+            break;
+
+          case Token.SETELEM:
+          case Token.SETELEM_OP:
+            visitExpression(child, 0);
+            child = child.getNext();
+            visitExpression(child, 0);
+            child = child.getNext();
+            if (type == Token.SETELEM_OP) {
+                addIcode(Icode_DUP2);
+                stackChange(2);
+                addToken(Token.GETELEM);
+                stackChange(-1);
+                // Compensate for the following USE_STACK
+                stackChange(-1);
+            }
+            visitExpression(child, 0);
+            addToken(Token.SETELEM);
+            stackChange(-2);
+            break;
+
+          case Token.SET_REF:
+          case Token.SET_REF_OP:
+            visitExpression(child, 0);
+            child = child.getNext();
+            if (type == Token.SET_REF_OP) {
+                addIcode(Icode_DUP);
+                stackChange(1);
+                addToken(Token.GET_REF);
+                // Compensate for the following USE_STACK
+                stackChange(-1);
+            }
+            visitExpression(child, 0);
+            addToken(Token.SET_REF);
+            stackChange(-1);
+            break;
+
+          case Token.STRICT_SETNAME:
+          case Token.SETNAME:
+            {
+                String name = child.getString();
+                visitExpression(child, 0);
+                child = child.getNext();
+                visitExpression(child, 0);
+                addStringOp(type, name);
+                stackChange(-1);
+            }
+            break;
+
+          case Token.SETCONST:
+            {
+                String name = child.getString();
+                visitExpression(child, 0);
+                child = child.getNext();
+                visitExpression(child, 0);
+                addStringOp(Icode_SETCONST, name);
+                stackChange(-1);
+            }
+            break;
+
+          case Token.TYPEOFNAME:
+            {
+                int index = -1;
+                // use typeofname if an activation frame exists
+                // since the vars all exist there instead of in jregs
+                if (itsInFunctionFlag && !itsData.itsNeedsActivation)
+                    index = scriptOrFn.getIndexForNameNode(node);
+                if (index == -1) {
+                    addStringOp(Icode_TYPEOFNAME, node.getString());
+                    stackChange(1);
+                } else {
+                    addVarOp(Token.GETVAR, index);
+                    stackChange(1);
+                    addToken(Token.TYPEOF);
+                }
+            }
+            break;
+
+          case Token.BINDNAME:
+          case Token.NAME:
+          case Token.STRING:
+            addStringOp(type, node.getString());
+            stackChange(1);
+            break;
+
+          case Token.INC:
+          case Token.DEC:
+            visitIncDec(node, child);
+            break;
+
+          case Token.NUMBER:
+            {
+                double num = node.getDouble();
+                int inum = (int)num;
+                if (inum == num) {
+                    if (inum == 0) {
+                        addIcode(Icode_ZERO);
+                        // Check for negative zero
+                        if (1.0 / num < 0.0) {
+                            addToken(Token.NEG);
+                        }
+                    } else if (inum == 1) {
+                        addIcode(Icode_ONE);
+                    } else if ((short)inum == inum) {
+                        addIcode(Icode_SHORTNUMBER);
+                        // write short as uin16 bit pattern
+                        addUint16(inum & 0xFFFF);
+                    } else {
+                        addIcode(Icode_INTNUMBER);
+                        addInt(inum);
+                    }
+                } else {
+                    int index = getDoubleIndex(num);
+                    addIndexOp(Token.NUMBER, index);
+                }
+                stackChange(1);
+            }
+            break;
+
+          case Token.GETVAR:
+            {
+                if (itsData.itsNeedsActivation) Kit.codeBug();
+                int index = scriptOrFn.getIndexForNameNode(node);
+                addVarOp(Token.GETVAR, index);
+                stackChange(1);
+            }
+            break;
+
+          case Token.SETVAR:
+            {
+                if (itsData.itsNeedsActivation) Kit.codeBug();
+                int index = scriptOrFn.getIndexForNameNode(child);
+                child = child.getNext();
+                visitExpression(child, 0);
+                addVarOp(Token.SETVAR, index);
+            }
+            break;
+
+          case Token.SETCONSTVAR:
+            {
+                if (itsData.itsNeedsActivation) Kit.codeBug();
+                int index = scriptOrFn.getIndexForNameNode(child);
+                child = child.getNext();
+                visitExpression(child, 0);
+                addVarOp(Token.SETCONSTVAR, index);
+            }
+            break;
+
+          case Token.NULL:
+          case Token.THIS:
+          case Token.THISFN:
+          case Token.FALSE:
+          case Token.TRUE:
+            addToken(type);
+            stackChange(1);
+            break;
+
+          case Token.ENUM_NEXT:
+          case Token.ENUM_ID:
+            addIndexOp(type, getLocalBlockRef(node));
+            stackChange(1);
+            break;
+
+          case Token.REGEXP:
+            {
+                int index = node.getExistingIntProp(Node.REGEXP_PROP);
+                addIndexOp(Token.REGEXP, index);
+                stackChange(1);
+            }
+            break;
+
+          case Token.ARRAYLIT:
+          case Token.OBJECTLIT:
+            visitLiteral(node, child);
+            break;
+
+          case Token.ARRAYCOMP:
+            visitArrayComprehension(node, child, child.getNext());
+            break;
+
+          case Token.REF_SPECIAL:
+            visitExpression(child, 0);
+            addStringOp(type, (String)node.getProp(Node.NAME_PROP));
+            break;
+
+          case Token.REF_MEMBER:
+          case Token.REF_NS_MEMBER:
+          case Token.REF_NAME:
+          case Token.REF_NS_NAME:
+            {
+                int memberTypeFlags = node.getIntProp(Node.MEMBER_TYPE_PROP, 0);
+                // generate possible target, possible namespace and member
+                int childCount = 0;
+                do {
+                    visitExpression(child, 0);
+                    ++childCount;
+                    child = child.getNext();
+                } while (child != null);
+                addIndexOp(type, memberTypeFlags);
+                stackChange(1 - childCount);
+            }
+            break;
+
+          case Token.DOTQUERY:
+            {
+                int queryPC;
+                updateLineNumber(node);
+                visitExpression(child, 0);
+                addIcode(Icode_ENTERDQ);
+                stackChange(-1);
+                queryPC = iCodeTop;
+                visitExpression(child.getNext(), 0);
+                addBackwardGoto(Icode_LEAVEDQ, queryPC);
+            }
+            break;
+
+          case Token.DEFAULTNAMESPACE :
+          case Token.ESCXMLATTR :
+          case Token.ESCXMLTEXT :
+            visitExpression(child, 0);
+            addToken(type);
+            break;
+
+          case Token.YIELD:
+            if (child != null) {
+                visitExpression(child, 0);
+            } else {
+                addIcode(Icode_UNDEF);
+                stackChange(1);
+            }
+            addToken(Token.YIELD);
+            addUint16(node.getLineno() & 0xFFFF);
+            break;
+
+          case Token.WITHEXPR: {
+            Node enterWith = node.getFirstChild();
+            Node with = enterWith.getNext();
+            visitExpression(enterWith.getFirstChild(), 0);
+            addToken(Token.ENTERWITH);
+            stackChange(-1);
+            visitExpression(with.getFirstChild(), 0);
+            addToken(Token.LEAVEWITH);
+            break;
+          }
+
+          default:
+            throw badTree(node);
+        }
+        if (savedStackDepth + 1 != stackDepth) {
+            Kit.codeBug();
+        }
+    }
+
+    private void generateCallFunAndThis(Node left)
+    {
+        // Generate code to place on stack function and thisObj
+        int type = left.getType();
+        switch (type) {
+          case Token.NAME: {
+            String name = left.getString();
+            // stack: ... -> ... function thisObj
+            addStringOp(Icode_NAME_AND_THIS, name);
+            stackChange(2);
+            break;
+          }
+          case Token.GETPROP:
+          case Token.GETELEM: {
+            Node target = left.getFirstChild();
+            visitExpression(target, 0);
+            Node id = target.getNext();
+            if (type == Token.GETPROP) {
+                String property = id.getString();
+                // stack: ... target -> ... function thisObj
+                addStringOp(Icode_PROP_AND_THIS, property);
+                stackChange(1);
+            } else {
+                visitExpression(id, 0);
+                // stack: ... target id -> ... function thisObj
+                addIcode(Icode_ELEM_AND_THIS);
+            }
+            break;
+          }
+          default:
+            // Including Token.GETVAR
+            visitExpression(left, 0);
+            // stack: ... value -> ... function thisObj
+            addIcode(Icode_VALUE_AND_THIS);
+            stackChange(1);
+            break;
+        }
+    }
+
+
+    private void visitIncDec(Node node, Node child)
+    {
+        int incrDecrMask = node.getExistingIntProp(Node.INCRDECR_PROP);
+        int childType = child.getType();
+        switch (childType) {
+          case Token.GETVAR : {
+            if (itsData.itsNeedsActivation) Kit.codeBug();
+            int i = scriptOrFn.getIndexForNameNode(child);
+            addVarOp(Icode_VAR_INC_DEC, i);
+            addUint8(incrDecrMask);
+            stackChange(1);
+            break;
+          }
+          case Token.NAME : {
+            String name = child.getString();
+            addStringOp(Icode_NAME_INC_DEC, name);
+            addUint8(incrDecrMask);
+            stackChange(1);
+            break;
+          }
+          case Token.GETPROP : {
+            Node object = child.getFirstChild();
+            visitExpression(object, 0);
+            String property = object.getNext().getString();
+            addStringOp(Icode_PROP_INC_DEC, property);
+            addUint8(incrDecrMask);
+            break;
+          }
+          case Token.GETELEM : {
+            Node object = child.getFirstChild();
+            visitExpression(object, 0);
+            Node index = object.getNext();
+            visitExpression(index, 0);
+            addIcode(Icode_ELEM_INC_DEC);
+            addUint8(incrDecrMask);
+            stackChange(-1);
+            break;
+          }
+          case Token.GET_REF : {
+            Node ref = child.getFirstChild();
+            visitExpression(ref, 0);
+            addIcode(Icode_REF_INC_DEC);
+            addUint8(incrDecrMask);
+            break;
+          }
+          default : {
+            throw badTree(node);
+          }
+        }
+    }
+
+    private void visitLiteral(Node node, Node child)
+    {
+        int type = node.getType();
+        int count;
+        Object[] propertyIds = null;
+        if (type == Token.ARRAYLIT) {
+            count = 0;
+            for (Node n = child; n != null; n = n.getNext()) {
+                ++count;
+            }
+        } else if (type == Token.OBJECTLIT) {
+            propertyIds = (Object[])node.getProp(Node.OBJECT_IDS_PROP);
+            count = propertyIds.length;
+        } else {
+            throw badTree(node);
+        }
+        addIndexOp(Icode_LITERAL_NEW, count);
+        stackChange(2);
+        while (child != null) {
+            int childType = child.getType();
+            if (childType == Token.GET) {
+                visitExpression(child.getFirstChild(), 0);
+                addIcode(Icode_LITERAL_GETTER);
+            } else if (childType == Token.SET) {
+                visitExpression(child.getFirstChild(), 0);
+                addIcode(Icode_LITERAL_SETTER);
+            } else if (childType == Token.METHOD) {
+                visitExpression(child.getFirstChild(), 0);
+                addIcode(Icode_LITERAL_SET);
+            } else {
+                visitExpression(child, 0);
+                addIcode(Icode_LITERAL_SET);
+            }
+            stackChange(-1);
+            child = child.getNext();
+        }
+        if (type == Token.ARRAYLIT) {
+            int[] skipIndexes = (int[])node.getProp(Node.SKIP_INDEXES_PROP);
+            if (skipIndexes == null) {
+                addToken(Token.ARRAYLIT);
+            } else {
+                int index = literalIds.size();
+                literalIds.add(skipIndexes);
+                addIndexOp(Icode_SPARE_ARRAYLIT, index);
+            }
+        } else {
+            int index = literalIds.size();
+            literalIds.add(propertyIds);
+            addIndexOp(Token.OBJECTLIT, index);
+        }
+        stackChange(-1);
+    }
+
+    private void visitArrayComprehension(Node node, Node initStmt, Node expr)
+    {
+        // A bit of a hack: array comprehensions are implemented using
+        // statement nodes for the iteration, yet they appear in an
+        // expression context. So we pass the current stack depth to
+        // visitStatement so it can check that the depth is not altered
+        // by statements.
+        visitStatement(initStmt, stackDepth);
+        visitExpression(expr, 0);
+    }
+
+    private int getLocalBlockRef(Node node)
+    {
+        Node localBlock = (Node)node.getProp(Node.LOCAL_BLOCK_PROP);
+        return localBlock.getExistingIntProp(Node.LOCAL_PROP);
+    }
+
+    private int getTargetLabel(Node target)
+    {
+        int label = target.labelId();
+        if (label != -1) {
+            return label;
+        }
+        label = labelTableTop;
+        if (labelTable == null || label == labelTable.length) {
+            if (labelTable == null) {
+                labelTable = new int[MIN_LABEL_TABLE_SIZE];
+            }else {
+                int[] tmp = new int[labelTable.length * 2];
+                System.arraycopy(labelTable, 0, tmp, 0, label);
+                labelTable = tmp;
+            }
+        }
+        labelTableTop = label + 1;
+        labelTable[label] = -1;
+
+        target.labelId(label);
+        return label;
+    }
+
+    private void markTargetLabel(Node target)
+    {
+        int label = getTargetLabel(target);
+        if (labelTable[label] != -1) {
+            // Can mark label only once
+            Kit.codeBug();
+        }
+        labelTable[label] = iCodeTop;
+    }
+
+    private void addGoto(Node target, int gotoOp)
+    {
+        int label = getTargetLabel(target);
+        if (!(label < labelTableTop)) Kit.codeBug();
+        int targetPC = labelTable[label];
+
+        if (targetPC != -1) {
+            addBackwardGoto(gotoOp, targetPC);
+        } else {
+            int gotoPC = iCodeTop;
+            addGotoOp(gotoOp);
+            int top = fixupTableTop;
+            if (fixupTable == null || top == fixupTable.length) {
+                if (fixupTable == null) {
+                    fixupTable = new long[MIN_FIXUP_TABLE_SIZE];
+                } else {
+                    long[] tmp = new long[fixupTable.length * 2];
+                    System.arraycopy(fixupTable, 0, tmp, 0, top);
+                    fixupTable = tmp;
+                }
+            }
+            fixupTableTop = top + 1;
+            fixupTable[top] = ((long)label << 32) | gotoPC;
+        }
+    }
+
+    private void fixLabelGotos()
+    {
+        for (int i = 0; i < fixupTableTop; i++) {
+            long fixup = fixupTable[i];
+            int label = (int)(fixup >> 32);
+            int jumpSource = (int)fixup;
+            int pc = labelTable[label];
+            if (pc == -1) {
+                // Unlocated label
+                throw Kit.codeBug();
+            }
+            resolveGoto(jumpSource, pc);
+        }
+        fixupTableTop = 0;
+    }
+
+    private void addBackwardGoto(int gotoOp, int jumpPC)
+    {
+        int fromPC = iCodeTop;
+        // Ensure that this is a jump backward
+        if (fromPC <= jumpPC) throw Kit.codeBug();
+        addGotoOp(gotoOp);
+        resolveGoto(fromPC, jumpPC);
+    }
+
+    private void resolveForwardGoto(int fromPC)
+    {
+        // Ensure that forward jump skips at least self bytecode
+        if (iCodeTop < fromPC + 3) throw Kit.codeBug();
+        resolveGoto(fromPC, iCodeTop);
+    }
+
+    private void resolveGoto(int fromPC, int jumpPC)
+    {
+        int offset = jumpPC - fromPC;
+        // Ensure that jumps do not overlap
+        if (0 <= offset && offset <= 2) throw Kit.codeBug();
+        int offsetSite = fromPC + 1;
+        if (offset != (short)offset) {
+            if (itsData.longJumps == null) {
+                itsData.longJumps = new UintMap();
+            }
+            itsData.longJumps.put(offsetSite, jumpPC);
+            offset = 0;
+        }
+        byte[] array = itsData.itsICode;
+        array[offsetSite] = (byte)(offset >> 8);
+        array[offsetSite + 1] = (byte)offset;
+    }
+
+    private void addToken(int token)
+    {
+        if (!Icode.validTokenCode(token)) throw Kit.codeBug();
+        addUint8(token);
+    }
+
+    private void addIcode(int icode)
+    {
+        if (!Icode.validIcode(icode)) throw Kit.codeBug();
+        // Write negative icode as uint8 bits
+        addUint8(icode & 0xFF);
+    }
+
+    private void addUint8(int value)
+    {
+        if ((value & ~0xFF) != 0) throw Kit.codeBug();
+        byte[] array = itsData.itsICode;
+        int top = iCodeTop;
+        if (top == array.length) {
+            array = increaseICodeCapacity(1);
+        }
+        array[top] = (byte)value;
+        iCodeTop = top + 1;
+    }
+
+    private void addUint16(int value)
+    {
+        if ((value & ~0xFFFF) != 0) throw Kit.codeBug();
+        byte[] array = itsData.itsICode;
+        int top = iCodeTop;
+        if (top + 2 > array.length) {
+            array = increaseICodeCapacity(2);
+        }
+        array[top] = (byte)(value >>> 8);
+        array[top + 1] = (byte)value;
+        iCodeTop = top + 2;
+    }
+
+    private void addInt(int i)
+    {
+        byte[] array = itsData.itsICode;
+        int top = iCodeTop;
+        if (top + 4 > array.length) {
+            array = increaseICodeCapacity(4);
+        }
+        array[top] = (byte)(i >>> 24);
+        array[top + 1] = (byte)(i >>> 16);
+        array[top + 2] = (byte)(i >>> 8);
+        array[top + 3] = (byte)i;
+        iCodeTop = top + 4;
+    }
+
+    private int getDoubleIndex(double num)
+    {
+        int index = doubleTableTop;
+        if (index == 0) {
+            itsData.itsDoubleTable = new double[64];
+        } else if (itsData.itsDoubleTable.length == index) {
+            double[] na = new double[index * 2];
+            System.arraycopy(itsData.itsDoubleTable, 0, na, 0, index);
+            itsData.itsDoubleTable = na;
+        }
+        itsData.itsDoubleTable[index] = num;
+        doubleTableTop = index + 1;
+        return index;
+    }
+
+    private void addGotoOp(int gotoOp)
+    {
+        byte[] array = itsData.itsICode;
+        int top = iCodeTop;
+        if (top + 3 > array.length) {
+            array = increaseICodeCapacity(3);
+        }
+        array[top] = (byte)gotoOp;
+        // Offset would written later
+        iCodeTop = top + 1 + 2;
+    }
+
+    private void addVarOp(int op, int varIndex)
+    {
+        switch (op) {
+          case Token.SETCONSTVAR:
+            if (varIndex < 128) {
+                addIcode(Icode_SETCONSTVAR1);
+                addUint8(varIndex);
+                return;
+            }
+            addIndexOp(Icode_SETCONSTVAR, varIndex);
+            return;
+          case Token.GETVAR:
+          case Token.SETVAR:
+            if (varIndex < 128) {
+                addIcode(op == Token.GETVAR ? Icode_GETVAR1 : Icode_SETVAR1);
+                addUint8(varIndex);
+                return;
+            }
+            // fallthrough
+          case Icode_VAR_INC_DEC:
+            addIndexOp(op, varIndex);
+            return;
+        }
+        throw Kit.codeBug();
+    }
+
+    private void addStringOp(int op, String str)
+    {
+        addStringPrefix(str);
+        if (Icode.validIcode(op)) {
+            addIcode(op);
+        } else {
+            addToken(op);
+        }
+    }
+
+    private void addIndexOp(int op, int index)
+    {
+        addIndexPrefix(index);
+        if (Icode.validIcode(op)) {
+            addIcode(op);
+        } else {
+            addToken(op);
+        }
+    }
+
+    private void addStringPrefix(String str)
+    {
+        int index = strings.get(str, -1);
+        if (index == -1) {
+            index = strings.size();
+            strings.put(str, index);
+        }
+        if (index < 4) {
+            addIcode(Icode_REG_STR_C0 - index);
+        } else if (index <= 0xFF) {
+            addIcode(Icode_REG_STR1);
+            addUint8(index);
+         } else if (index <= 0xFFFF) {
+            addIcode(Icode_REG_STR2);
+            addUint16(index);
+         } else {
+            addIcode(Icode_REG_STR4);
+            addInt(index);
+        }
+    }
+
+    private void addIndexPrefix(int index)
+    {
+        if (index < 0) Kit.codeBug();
+        if (index < 6) {
+            addIcode(Icode_REG_IND_C0 - index);
+        } else if (index <= 0xFF) {
+            addIcode(Icode_REG_IND1);
+            addUint8(index);
+         } else if (index <= 0xFFFF) {
+            addIcode(Icode_REG_IND2);
+            addUint16(index);
+         } else {
+            addIcode(Icode_REG_IND4);
+            addInt(index);
+        }
+    }
+
+    private void addExceptionHandler(int icodeStart, int icodeEnd,
+                                     int handlerStart, boolean isFinally,
+                                     int exceptionObjectLocal, int scopeLocal)
+    {
+        int top = exceptionTableTop;
+        int[] table = itsData.itsExceptionTable;
+        if (table == null) {
+            if (top != 0) Kit.codeBug();
+            table = new int[Interpreter.EXCEPTION_SLOT_SIZE * 2];
+            itsData.itsExceptionTable = table;
+        } else if (table.length == top) {
+            table = new int[table.length * 2];
+            System.arraycopy(itsData.itsExceptionTable, 0, table, 0, top);
+            itsData.itsExceptionTable = table;
+        }
+        table[top + Interpreter.EXCEPTION_TRY_START_SLOT]  = icodeStart;
+        table[top + Interpreter.EXCEPTION_TRY_END_SLOT]    = icodeEnd;
+        table[top + Interpreter.EXCEPTION_HANDLER_SLOT]    = handlerStart;
+        table[top + Interpreter.EXCEPTION_TYPE_SLOT]     = isFinally ? 1 : 0;
+        table[top + Interpreter.EXCEPTION_LOCAL_SLOT]    = exceptionObjectLocal;
+        table[top + Interpreter.EXCEPTION_SCOPE_SLOT]    = scopeLocal;
+
+        exceptionTableTop = top + Interpreter.EXCEPTION_SLOT_SIZE;
+    }
+
+    private byte[] increaseICodeCapacity(int extraSize)
+    {
+        int capacity = itsData.itsICode.length;
+        int top = iCodeTop;
+        if (top + extraSize <= capacity) throw Kit.codeBug();
+        capacity *= 2;
+        if (top + extraSize > capacity) {
+            capacity = top + extraSize;
+        }
+        byte[] array = new byte[capacity];
+        System.arraycopy(itsData.itsICode, 0, array, 0, top);
+        itsData.itsICode = array;
+        return array;
+    }
+
+    private void stackChange(int change)
+    {
+        if (change <= 0) {
+            stackDepth += change;
+        } else {
+            int newDepth = stackDepth + change;
+            if (newDepth > itsData.itsMaxStack) {
+                itsData.itsMaxStack = newDepth;
+            }
+            stackDepth = newDepth;
+        }
+    }
+
+    private int allocLocal()
+    {
+        int localSlot = localTop;
+        ++localTop;
+        if (localTop > itsData.itsMaxLocals) {
+            itsData.itsMaxLocals = localTop;
+        }
+        return localSlot;
+    }
+
+    private void releaseLocal(int localSlot)
+    {
+        --localTop;
+        if (localSlot != localTop) Kit.codeBug();
+    }
+}
diff -pruN 20130227+dfsg1-14/rhino/src/org/mozilla/javascript/CompilerEnvirons.java 20130227+rhino-1/rhino/src/org/mozilla/javascript/CompilerEnvirons.java
--- 20130227+dfsg1-14/rhino/src/org/mozilla/javascript/CompilerEnvirons.java	1970-01-01 00:00:00.000000000 +0000
+++ 20130227+rhino-1/rhino/src/org/mozilla/javascript/CompilerEnvirons.java	2023-05-25 14:24:50.000000000 +0000
@@ -0,0 +1,295 @@
+/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+package org.mozilla.javascript;
+
+import java.util.Set;
+
+import org.mozilla.javascript.ast.ErrorCollector;
+
+public class CompilerEnvirons
+{
+    public CompilerEnvirons()
+    {
+        errorReporter = DefaultErrorReporter.instance;
+        languageVersion = Context.VERSION_DEFAULT;
+        generateDebugInfo = true;
+        reservedKeywordAsIdentifier = true;
+        allowMemberExprAsFunctionName = false;
+        xmlAvailable = true;
+        optimizationLevel = 0;
+        generatingSource = true;
+        strictMode = false;
+        warningAsError = false;
+        generateObserverCount = false;
+        allowSharpComments = false;
+    }
+
+    public void initFromContext(Context cx)
+    {
+        setErrorReporter(cx.getErrorReporter());
+        languageVersion = cx.getLanguageVersion();
+        generateDebugInfo = (!cx.isGeneratingDebugChanged()
+                             || cx.isGeneratingDebug());
+        reservedKeywordAsIdentifier
+            = cx.hasFeature(Context.FEATURE_RESERVED_KEYWORD_AS_IDENTIFIER);
+        allowMemberExprAsFunctionName
+            = cx.hasFeature(Context.FEATURE_MEMBER_EXPR_AS_FUNCTION_NAME);
+        strictMode
+            = cx.hasFeature(Context.FEATURE_STRICT_MODE);
+        warningAsError = cx.hasFeature(Context.FEATURE_WARNING_AS_ERROR);
+        xmlAvailable
+            = cx.hasFeature(Context.FEATURE_E4X);
+
+        optimizationLevel = cx.getOptimizationLevel();
+
+        generatingSource = cx.isGeneratingSource();
+        activationNames = cx.activationNames;
+
+        // Observer code generation in compiled code :
+        generateObserverCount = cx.generateObserverCount;
+    }
+
+    public final ErrorReporter getErrorReporter()
+    {
+        return errorReporter;
+    }
+
+    public void setErrorReporter(ErrorReporter errorReporter)
+    {
+        if (errorReporter == null) throw new IllegalArgumentException();
+        this.errorReporter = errorReporter;
+    }
+
+    public final int getLanguageVersion()
+    {
+        return languageVersion;
+    }
+
+    public void setLanguageVersion(int languageVersion)
+    {
+        Context.checkLanguageVersion(languageVersion);
+        this.languageVersion = languageVersion;
+    }
+
+    public final boolean isGenerateDebugInfo()
+    {
+        return generateDebugInfo;
+    }
+
+    public void setGenerateDebugInfo(boolean flag)
+    {
+        this.generateDebugInfo = flag;
+    }
+
+    public final boolean isReservedKeywordAsIdentifier()
+    {
+        return reservedKeywordAsIdentifier;
+    }
+
+    public void setReservedKeywordAsIdentifier(boolean flag)
+    {
+        reservedKeywordAsIdentifier = flag;
+    }
+
+    /**
+     * Extension to ECMA: if 'function &lt;name&gt;' is not followed
+     * by '(', assume &lt;name&gt; starts a {@code memberExpr}
+     */
+    public final boolean isAllowMemberExprAsFunctionName()
+    {
+        return allowMemberExprAsFunctionName;
+    }
+
+    public void setAllowMemberExprAsFunctionName(boolean flag)
+    {
+        allowMemberExprAsFunctionName = flag;
+    }
+
+    public final boolean isXmlAvailable()
+    {
+        return xmlAvailable;
+    }
+
+    public void setXmlAvailable(boolean flag)
+    {
+        xmlAvailable = flag;
+    }
+
+    public final int getOptimizationLevel()
+    {
+        return optimizationLevel;
+    }
+
+    public void setOptimizationLevel(int level)
+    {
+        Context.checkOptimizationLevel(level);
+        this.optimizationLevel = level;
+    }
+
+    public final boolean isGeneratingSource()
+    {
+        return generatingSource;
+    }
+
+    public boolean getWarnTrailingComma() {
+        return warnTrailingComma;
+    }
+
+    public void setWarnTrailingComma(boolean warn) {
+        warnTrailingComma = warn;
+    }
+
+    public final boolean isStrictMode()
+    {
+        return strictMode;
+    }
+
+    public void setStrictMode(boolean strict)
+    {
+        strictMode = strict;
+    }
+
+    public final boolean reportWarningAsError()
+    {
+        return warningAsError;
+    }
+
+    /**
+     * Specify whether or not source information should be generated.
+     * <p>
+     * Without source information, evaluating the "toString" method
+     * on JavaScript functions produces only "[native code]" for
+     * the body of the function.
+     * Note that code generated without source is not fully ECMA
+     * conformant.
+     */
+    public void setGeneratingSource(boolean generatingSource)
+    {
+        this.generatingSource = generatingSource;
+    }
+
+    /**
+     * @return true iff code will be generated with callbacks to enable
+     * instruction thresholds
+     */
+    public boolean isGenerateObserverCount() {
+        return generateObserverCount;
+    }
+
+    /**
+     * Turn on or off generation of code with callbacks to
+     * track the count of executed instructions.
+     * Currently only affects JVM byte code generation: this slows down the
+     * generated code, but code generated without the callbacks will not
+     * be counted toward instruction thresholds. Rhino's interpretive
+     * mode does instruction counting without inserting callbacks, so
+     * there is no requirement to compile code differently.
+     * @param generateObserverCount if true, generated code will contain
+     * calls to accumulate an estimate of the instructions executed.
+     */
+    public void setGenerateObserverCount(boolean generateObserverCount) {
+        this.generateObserverCount = generateObserverCount;
+    }
+
+    public boolean isRecordingComments() {
+        return recordingComments;
+    }
+
+    public void setRecordingComments(boolean record) {
+        recordingComments = record;
+    }
+
+    public boolean isRecordingLocalJsDocComments() {
+        return recordingLocalJsDocComments;
+    }
+
+    public void setRecordingLocalJsDocComments(boolean record) {
+        recordingLocalJsDocComments = record;
+    }
+
+    /**
+     * Turn on or off full error recovery.  In this mode, parse errors do not
+     * throw an exception, and the parser attempts to build a full syntax tree
+     * from the input.  Useful for IDEs and other frontends.
+     */
+    public void setRecoverFromErrors(boolean recover) {
+        recoverFromErrors = recover;
+    }
+
+    public boolean recoverFromErrors() {
+        return recoverFromErrors;
+    }
+
+    /**
+     * Puts the parser in "IDE" mode.  This enables some slightly more expensive
+     * computations, such as figuring out helpful error bounds.
+     */
+    public void setIdeMode(boolean ide) {
+        ideMode = ide;
+    }
+
+    public boolean isIdeMode() {
+        return ideMode;
+    }
+
+    public Set<String> getActivationNames() {
+        return activationNames;
+    }
+
+    public void setActivationNames(Set<String> activationNames) {
+        this.activationNames = activationNames;
+    }
+
+    /**
+     * Mozilla sources use the C preprocessor.
+     */
+    public void setAllowSharpComments(boolean allow) {
+        allowSharpComments = allow;
+    }
+
+    public boolean getAllowSharpComments() {
+        return allowSharpComments;
+    }
+
+    /**
+     * Returns a {@code CompilerEnvirons} suitable for using Rhino
+     * in an IDE environment.  Most features are enabled by default.
+     * The {@link ErrorReporter} is set to an {@link ErrorCollector}.
+     */
+    public static CompilerEnvirons ideEnvirons() {
+        CompilerEnvirons env = new CompilerEnvirons();
+        env.setRecoverFromErrors(true);
+        env.setRecordingComments(true);
+        env.setStrictMode(true);
+        env.setWarnTrailingComma(true);
+        env.setLanguageVersion(170);
+        env.setReservedKeywordAsIdentifier(true);
+        env.setIdeMode(true);
+        env.setErrorReporter(new ErrorCollector());
+        return env;
+    }
+
+    private ErrorReporter errorReporter;
+
+    private int languageVersion;
+    private boolean generateDebugInfo;
+    private boolean reservedKeywordAsIdentifier;
+    private boolean allowMemberExprAsFunctionName;
+    private boolean xmlAvailable;
+    private int optimizationLevel;
+    private boolean generatingSource;
+    private boolean strictMode;
+    private boolean warningAsError;
+    private boolean generateObserverCount;
+    private boolean recordingComments;
+    private boolean recordingLocalJsDocComments;
+    private boolean recoverFromErrors;
+    private boolean warnTrailingComma;
+    private boolean ideMode;
+    private boolean allowSharpComments;
+    Set<String> activationNames;
+}
diff -pruN 20130227+dfsg1-14/rhino/src/org/mozilla/javascript/ConsString.java 20130227+rhino-1/rhino/src/org/mozilla/javascript/ConsString.java
--- 20130227+dfsg1-14/rhino/src/org/mozilla/javascript/ConsString.java	1970-01-01 00:00:00.000000000 +0000
+++ 20130227+rhino-1/rhino/src/org/mozilla/javascript/ConsString.java	2023-05-25 14:24:50.000000000 +0000
@@ -0,0 +1,96 @@
+/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+package org.mozilla.javascript;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+
+/**
+ * <p>This class represents a string composed of two components, each of which
+ * may be a <code>java.lang.String</code> or another ConsString.</p>
+ *
+ * <p>This string representation is optimized for concatenation using the "+"
+ * operator. Instead of immediately copying both components to a new character
+ * array, ConsString keeps references to the original components and only
+ * converts them to a String if either toString() is called or a certain depth
+ * level is reached.</p>
+ *
+ * <p>Note that instances of this class are only immutable if both parts are
+ * immutable, i.e. either Strings or ConsStrings that are ultimately composed
+ * of Strings.</p>
+ *
+ * <p>Both the name and the concept are borrowed from V8.</p>
+ */
+public class ConsString implements CharSequence, Serializable {
+
+    private static final long serialVersionUID = -8432806714471372570L;
+
+    private CharSequence s1, s2;
+    private final int length;
+    private int depth;
+
+    public ConsString(CharSequence str1, CharSequence str2) {
+        s1 = str1;
+        s2 = str2;
+        length = str1.length() + str2.length();
+        depth = 1;
+        if (str1 instanceof ConsString) {
+            depth += ((ConsString)str1).depth;
+        }
+        if (str2 instanceof ConsString) {
+            depth += ((ConsString)str2).depth;
+        }
+    }
+
+    // Replace with string representation when serializing
+    private Object writeReplace() {
+        return this.toString();
+    }
+    
+    @Override
+    public String toString() {
+        return depth == 0 ? (String)s1 : flatten();
+    }
+
+    private synchronized String flatten() {
+        if (depth > 0) {
+            StringBuilder b = new StringBuilder(length);
+            ArrayList<CharSequence> buffer = new ArrayList<CharSequence>();
+            buffer.add(s2);
+            buffer.add(s1);
+            while(!buffer.isEmpty()) {
+                CharSequence next = buffer.remove(buffer.size() - 1);
+                if (next instanceof ConsString) {
+                    ConsString casted = (ConsString) next;
+                    buffer.add(casted.s2);
+                    buffer.add(casted.s1);
+                } else {
+                    b.append(next);
+                }
+            }
+            s1 = b.toString();
+            s2 = "";
+            depth = 0;
+        }
+        return (String)s1;
+    }
+
+    public int length() {
+        return length;
+    }
+
+    public char charAt(int index) {
+        String str = depth == 0 ? (String)s1 : flatten();
+        return str.charAt(index);
+    }
+
+    public CharSequence subSequence(int start, int end) {
+        String str = depth == 0 ? (String)s1 : flatten();
+        return str.substring(start, end);
+    }
+
+}
diff -pruN 20130227+dfsg1-14/rhino/src/org/mozilla/javascript/ConstProperties.java 20130227+rhino-1/rhino/src/org/mozilla/javascript/ConstProperties.java
--- 20130227+dfsg1-14/rhino/src/org/mozilla/javascript/ConstProperties.java	1970-01-01 00:00:00.000000000 +0000
+++ 20130227+rhino-1/rhino/src/org/mozilla/javascript/ConstProperties.java	2023-05-25 14:24:50.000000000 +0000
@@ -0,0 +1,77 @@
+/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// API class
+
+package org.mozilla.javascript;
+
+public interface ConstProperties {
+    /**
+     * Sets a named const property in this object.
+     * <p>
+     * The property is specified by a string name
+     * as defined for <code>Scriptable.get</code>.
+     * <p>
+     * The possible values that may be passed in are as defined for
+     * <code>Scriptable.get</code>. A class that implements this method may choose
+     * to ignore calls to set certain properties, in which case those
+     * properties are effectively read-only.<p>
+     * For properties defined in a prototype chain,
+     * use <code>putProperty</code> in ScriptableObject. <p>
+     * Note that if a property <i>a</i> is defined in the prototype <i>p</i>
+     * of an object <i>o</i>, then evaluating <code>o.a = 23</code> will cause
+     * <code>set</code> to be called on the prototype <i>p</i> with
+     * <i>o</i> as the  <i>start</i> parameter.
+     * To preserve JavaScript semantics, it is the Scriptable
+     * object's responsibility to modify <i>o</i>. <p>
+     * This design allows properties to be defined in prototypes and implemented
+     * in terms of getters and setters of Java values without consuming slots
+     * in each instance.<p>
+     * <p>
+     * The values that may be set are limited to the following:
+     * <UL>
+     * <LI>java.lang.Boolean objects</LI>
+     * <LI>java.lang.String objects</LI>
+     * <LI>java.lang.Number objects</LI>
+     * <LI>org.mozilla.javascript.Scriptable objects</LI>
+     * <LI>null</LI>
+     * <LI>The value returned by Context.getUndefinedValue()</LI>
+     * </UL><p>
+     * Arbitrary Java objects may be wrapped in a Scriptable by first calling
+     * <code>Context.toObject</code>. This allows the property of a JavaScript
+     * object to contain an arbitrary Java object as a value.<p>
+     * Note that <code>has</code> will be called by the runtime first before
+     * <code>set</code> is called to determine in which object the
+     * property is defined.
+     * Note that this method is not expected to traverse the prototype chain,
+     * which is different from the ECMA [[Put]] operation.
+     * @param name the name of the property
+     * @param start the object whose property is being set
+     * @param value value to set the property to
+     * @see org.mozilla.javascript.Scriptable#has(String, Scriptable)
+     * @see org.mozilla.javascript.Scriptable#get(String, Scriptable)
+     * @see org.mozilla.javascript.ScriptableObject#putProperty(Scriptable, String, Object)
+     * @see org.mozilla.javascript.Context#toObject(Object, Scriptable)
+     */
+    public void putConst(String name, Scriptable start, Object value);
+
+    /**
+     * Reserves a definition spot for a const.  This will set up a definition
+     * of the const property, but set its value to undefined.  The semantics of
+     * the start parameter is the same as for putConst.
+     * @param name The name of the property.
+     * @param start The object whose property is being reserved.
+     */
+    public void defineConst(String name, Scriptable start);
+
+    /**
+     * Returns true if the named property is defined as a const on this object.
+     * @param name
+     * @return true if the named property is defined as a const, false
+     * otherwise.
+     */
+    public boolean isConst(String name);
+}
diff -pruN 20130227+dfsg1-14/rhino/src/org/mozilla/javascript/Context.java 20130227+rhino-1/rhino/src/org/mozilla/javascript/Context.java
--- 20130227+dfsg1-14/rhino/src/org/mozilla/javascript/Context.java	1970-01-01 00:00:00.000000000 +0000
+++ 20130227+rhino-1/rhino/src/org/mozilla/javascript/Context.java	2023-05-25 14:24:50.000000000 +0000
@@ -0,0 +1,2771 @@
+/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// API class
+
+package org.mozilla.javascript;
+
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.PrintWriter;
+import java.io.Reader;
+import java.io.StringWriter;
+import java.io.Writer;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.net.URL;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Set;
+import java.util.jar.Attributes;
+import java.util.jar.Manifest;
+
+import org.mozilla.javascript.ast.AstRoot;
+import org.mozilla.javascript.ast.ScriptNode;
+import org.mozilla.javascript.debug.DebuggableScript;
+import org.mozilla.javascript.debug.Debugger;
+import org.mozilla.javascript.xml.XMLLib;
+
+/**
+ * This class represents the runtime context of an executing script.
+ *
+ * Before executing a script, an instance of Context must be created
+ * and associated with the thread that will be executing the script.
+ * The Context will be used to store information about the executing
+ * of the script such as the call stack. Contexts are associated with
+ * the current thread  using the {@link #call(ContextAction)}
+ * or {@link #enter()} methods.<p>
+ *
+ * Different forms of script execution are supported. Scripts may be
+ * evaluated from the source directly, or first compiled and then later
+ * executed. Interactive execution is also supported.<p>
+ *
+ * Some aspects of script execution, such as type conversions and
+ * object creation, may be accessed directly through methods of
+ * Context.
+ *
+ * @see Scriptable
+ * @author Norris Boyd
+ * @author Brendan Eich
+ */
+
+public class Context
+{
+    /**
+     * Language versions.
+     *
+     * All integral values are reserved for future version numbers.
+     */
+
+    /**
+     * The unknown version.
+     */
+    public static final int VERSION_UNKNOWN =   -1;
+
+    /**
+     * The default version.
+     */
+    public static final int VERSION_DEFAULT =    0;
+
+    /**
+     * JavaScript 1.0
+     */
+    public static final int VERSION_1_0 =      100;
+
+    /**
+     * JavaScript 1.1
+     */
+    public static final int VERSION_1_1 =      110;
+
+    /**
+     * JavaScript 1.2
+     */
+    public static final int VERSION_1_2 =      120;
+
+    /**
+     * JavaScript 1.3
+     */
+    public static final int VERSION_1_3 =      130;
+
+    /**
+     * JavaScript 1.4
+     */
+    public static final int VERSION_1_4 =      140;
+
+    /**
+     * JavaScript 1.5
+     */
+    public static final int VERSION_1_5 =      150;
+
+    /**
+     * JavaScript 1.6
+     */
+    public static final int VERSION_1_6 =      160;
+
+    /**
+     * JavaScript 1.7
+     */
+    public static final int VERSION_1_7 =      170;
+
+    /**
+     * JavaScript 1.8
+     */
+    public static final int VERSION_1_8 =      180;
+
+    /**
+     * ECMAScript 6.
+     */
+    public static final int VERSION_ES6 =      200;
+
+    /**
+     * Controls behaviour of <tt>Date.prototype.getYear()</tt>.
+     * If <tt>hasFeature(FEATURE_NON_ECMA_GET_YEAR)</tt> returns true,
+     * Date.prototype.getYear subtructs 1900 only if 1900 <= date < 2000.
+     * The default behavior of {@link #hasFeature(int)} is always to subtruct
+     * 1900 as rquired by ECMAScript B.2.4.
+     */
+    public static final int FEATURE_NON_ECMA_GET_YEAR = 1;
+
+    /**
+     * Control if member expression as function name extension is available.
+     * If <tt>hasFeature(FEATURE_MEMBER_EXPR_AS_FUNCTION_NAME)</tt> returns
+     * true, allow <tt>function memberExpression(args) { body }</tt> to be
+     * syntax sugar for <tt>memberExpression = function(args) { body }</tt>,
+     * when memberExpression is not a simple identifier.
+     * See ECMAScript-262, section 11.2 for definition of memberExpression.
+     * By default {@link #hasFeature(int)} returns false.
+     */
+    public static final int FEATURE_MEMBER_EXPR_AS_FUNCTION_NAME = 2;
+
+    /**
+     * Control if reserved keywords are treated as identifiers.
+     * If <tt>hasFeature(RESERVED_KEYWORD_AS_IDENTIFIER)</tt> returns true,
+     * treat future reserved keyword (see  Ecma-262, section 7.5.3) as ordinary
+     * identifiers but warn about this usage.
+     *
+     * By default {@link #hasFeature(int)} returns false.
+     */
+    public static final int FEATURE_RESERVED_KEYWORD_AS_IDENTIFIER = 3;
+
+    /**
+     * Control if <tt>toString()</tt> should returns the same result
+     * as  <tt>toSource()</tt> when applied to objects and arrays.
+     * If <tt>hasFeature(FEATURE_TO_STRING_AS_SOURCE)</tt> returns true,
+     * calling <tt>toString()</tt> on JS objects gives the same result as
+     * calling <tt>toSource()</tt>. That is it returns JS source with code
+     * to create an object with all enumeratable fields of the original object
+     * instead of printing <tt>[object <i>result of
+     * {@link Scriptable#getClassName()}</i>]</tt>.
+     * <p>
+     * By default {@link #hasFeature(int)} returns true only if
+     * the current JS version is set to {@link #VERSION_1_2}.
+     */
+    public static final int FEATURE_TO_STRING_AS_SOURCE = 4;
+
+    /**
+     * Control if properties <tt>__proto__</tt> and <tt>__parent__</tt>
+     * are treated specially.
+     * If <tt>hasFeature(FEATURE_PARENT_PROTO_PROPERTIES)</tt> returns true,
+     * treat <tt>__parent__</tt> and <tt>__proto__</tt> as special properties.
+     * <p>
+     * The properties allow to query and set scope and prototype chains for the
+     * objects. The special meaning of the properties is available
+     * only when they are used as the right hand side of the dot operator.
+     * For example, while <tt>x.__proto__ = y</tt> changes the prototype
+     * chain of the object <tt>x</tt> to point to <tt>y</tt>,
+     * <tt>x["__proto__"] = y</tt> simply assigns a new value to the property
+     * <tt>__proto__</tt> in <tt>x</tt> even when the feature is on.
+     *
+     * By default {@link #hasFeature(int)} returns true.
+     */
+    public static final int FEATURE_PARENT_PROTO_PROPERTIES = 5;
+
+    /**
+     * @deprecated In previous releases, this name was given to
+     * FEATURE_PARENT_PROTO_PROPERTIES.
+     */
+    @Deprecated
+    public static final int FEATURE_PARENT_PROTO_PROPRTIES = 5;
+
+    /**
+     * Control if support for E4X(ECMAScript for XML) extension is available.
+     * If hasFeature(FEATURE_E4X) returns true, the XML syntax is available.
+     * <p>
+     * By default {@link #hasFeature(int)} returns true if
+     * the current JS version is set to {@link #VERSION_DEFAULT}
+     * or is at least {@link #VERSION_1_6}.
+     * @since 1.6 Release 1
+     */
+    public static final int FEATURE_E4X = 6;
+
+    /**
+     * Control if dynamic scope should be used for name access.
+     * If hasFeature(FEATURE_DYNAMIC_SCOPE) returns true, then the name lookup
+     * during name resolution will use the top scope of the script or function
+     * which is at the top of JS execution stack instead of the top scope of the
+     * script or function from the current stack frame if the top scope of
+     * the top stack frame contains the top scope of the current stack frame
+     * on its prototype chain.
+     * <p>
+     * This is useful to define shared scope containing functions that can
+     * be called from scripts and functions using private scopes.
+     * <p>
+     * By default {@link #hasFeature(int)} returns false.
+     * @since 1.6 Release 1
+     */
+    public static final int FEATURE_DYNAMIC_SCOPE = 7;
+
+    /**
+     * Control if strict variable mode is enabled.
+     * When the feature is on Rhino reports runtime errors if assignment
+     * to a global variable that does not exist is executed. When the feature
+     * is off such assignments create a new variable in the global scope as
+     * required by ECMA 262.
+     * <p>
+     * By default {@link #hasFeature(int)} returns false.
+     * @since 1.6 Release 1
+     */
+    public static final int FEATURE_STRICT_VARS = 8;
+
+    /**
+     * Control if strict eval mode is enabled.
+     * When the feature is on Rhino reports runtime errors if non-string
+     * argument is passed to the eval function. When the feature is off
+     * eval simply return non-string argument as is without performing any
+     * evaluation as required by ECMA 262.
+     * <p>
+     * By default {@link #hasFeature(int)} returns false.
+     * @since 1.6 Release 1
+     */
+    public static final int FEATURE_STRICT_EVAL = 9;
+
+    /**
+     * When the feature is on Rhino will add a "fileName" and "lineNumber"
+     * properties to Error objects automatically. When the feature is off, you
+     * have to explicitly pass them as the second and third argument to the
+     * Error constructor. Note that neither behavior is fully ECMA 262
+     * compliant (as 262 doesn't specify a three-arg constructor), but keeping
+     * the feature off results in Error objects that don't have
+     * additional non-ECMA properties when constructed using the ECMA-defined
+     * single-arg constructor and is thus desirable if a stricter ECMA
+     * compliance is desired, specifically adherence to the point 15.11.5. of
+     * the standard.
+     * <p>
+     * By default {@link #hasFeature(int)} returns false.
+     * @since 1.6 Release 6
+     */
+    public static final int FEATURE_LOCATION_INFORMATION_IN_ERROR = 10;
+
+    /**
+     * Controls whether JS 1.5 'strict mode' is enabled.
+     * When the feature is on, Rhino reports more than a dozen different
+     * warnings.  When the feature is off, these warnings are not generated.
+     * FEATURE_STRICT_MODE implies FEATURE_STRICT_VARS and FEATURE_STRICT_EVAL.
+     * <p>
+     * By default {@link #hasFeature(int)} returns false.
+     * @since 1.6 Release 6
+     */
+    public static final int FEATURE_STRICT_MODE = 11;
+
+    /**
+     * Controls whether a warning should be treated as an error.
+     * @since 1.6 Release 6
+     */
+    public static final int FEATURE_WARNING_AS_ERROR = 12;
+
+    /**
+     * Enables enhanced access to Java.
+     * Specifically, controls whether private and protected members can be
+     * accessed, and whether scripts can catch all Java exceptions.
+     * <p>
+     * Note that this feature should only be enabled for trusted scripts.
+     * <p>
+     * By default {@link #hasFeature(int)} returns false.
+     * @since 1.7 Release 1
+     */
+    public static final int FEATURE_ENHANCED_JAVA_ACCESS = 13;
+
+    /**
+     * Enables access to JavaScript features from ECMAscript 6 that are present in
+     * JavaScript engines that do not yet support version 6, such as V8.
+     * This includes support for typed arrays. Default is true.
+     * @since 1.7 Release 3
+     */
+    public static final int FEATURE_V8_EXTENSIONS = 14;
+
+    /**
+     * Defines how an undefined  "this" parameter is handled in certain calls. Previously Rhino
+     * would convert an undefined "this" to null, whereas recent specs call for it to be treated
+     * differently. Default is to be set if language version <= 1.7.
+     * @since 1.7.7
+     */
+    public static final int FEATURE_OLD_UNDEF_NULL_THIS = 15;
+
+    /**
+     * If set, then the order of property key enumeration will be first numeric keys in numeric order,
+     * followed by string keys in order of creation, and finally Symbol keys, as specified in ES6.
+     * Default is true for language version >= "ES6" and false otherwise.
+     * @since 1.7.8
+     */
+    public static final int FEATURE_ENUMERATE_IDS_FIRST = 16;
+
+    public static final String languageVersionProperty = "language version";
+    public static final String errorReporterProperty   = "error reporter";
+
+    /**
+     * Convenient value to use as zero-length array of objects.
+     */
+    public static final Object[] emptyArgs = ScriptRuntime.emptyArgs;
+
+    /**
+     * Creates a new Context. The context will be associated with the {@link
+     * ContextFactory#getGlobal() global context factory}.
+     *
+     * Note that the Context must be associated with a thread before
+     * it can be used to execute a script.
+     * @deprecated this constructor is deprecated because it creates a
+     * dependency on a static singleton context factory. Use
+     * {@link ContextFactory#enter()} or
+     * {@link ContextFactory#call(ContextAction)} instead. If you subclass
+     * this class, consider using {@link #Context(ContextFactory)} constructor
+     * instead in the subclasses' constructors.
+     */
+    @Deprecated
+    public Context()
+    {
+        this(ContextFactory.getGlobal());
+    }
+
+    /**
+     * Creates a new context. Provided as a preferred super constructor for
+     * subclasses in place of the deprecated default public constructor.
+     * @param factory the context factory associated with this context (most
+     * likely, the one that created the context). Can not be null. The context
+     * features are inherited from the factory, and the context will also
+     * otherwise use its factory's services.
+     * @throws IllegalArgumentException if factory parameter is null.
+     */
+    protected Context(ContextFactory factory)
+    {
+        if(factory == null) {
+            throw new IllegalArgumentException("factory == null");
+        }
+        this.factory = factory;
+        version = VERSION_DEFAULT;
+        optimizationLevel = codegenClass != null ? 0 : -1;
+        maximumInterpreterStackDepth = Integer.MAX_VALUE;
+    }
+
+    /**
+     * Get the current Context.
+     *
+     * The current Context is per-thread; this method looks up
+     * the Context associated with the current thread. <p>
+     *
+     * @return the Context associated with the current thread, or
+     *         null if no context is associated with the current
+     *         thread.
+     * @see ContextFactory#enterContext()
+     * @see ContextFactory#call(ContextAction)
+     */
+    public static Context getCurrentContext()
+    {
+        Object helper = VMBridge.instance.getThreadContextHelper();
+        return VMBridge.instance.getContext(helper);
+    }
+
+    /**
+     * Same as calling {@link ContextFactory#enterContext()} on the global
+     * ContextFactory instance.
+     * @return a Context associated with the current thread
+     * @see #getCurrentContext()
+     * @see #exit()
+     * @see #call(ContextAction)
+     */
+    public static Context enter()
+    {
+        return enter(null);
+    }
+
+    /**
+     * Get a Context associated with the current thread, using
+     * the given Context if need be.
+     * <p>
+     * The same as <code>enter()</code> except that <code>cx</code>
+     * is associated with the current thread and returned if
+     * the current thread has no associated context and <code>cx</code>
+     * is not associated with any other thread.
+     * @param cx a Context to associate with the thread if possible
+     * @return a Context associated with the current thread
+     * @deprecated use {@link ContextFactory#enterContext(Context)} instead as
+     * this method relies on usage of a static singleton "global" ContextFactory.
+     * @see ContextFactory#enterContext(Context)
+     * @see ContextFactory#call(ContextAction)
+     */
+    @Deprecated
+    public static Context enter(Context cx)
+    {
+        return enter(cx, ContextFactory.getGlobal());
+    }
+
+    static final Context enter(Context cx, ContextFactory factory)
+    {
+        Object helper = VMBridge.instance.getThreadContextHelper();
+        Context old = VMBridge.instance.getContext(helper);
+        if (old != null) {
+            cx = old;
+        } else {
+            if (cx == null) {
+                cx = factory.makeContext();
+                if (cx.enterCount != 0) {
+                    throw new IllegalStateException("factory.makeContext() returned Context instance already associated with some thread");
+                }
+                factory.onContextCreated(cx);
+                if (factory.isSealed() && !cx.isSealed()) {
+                    cx.seal(null);
+                }
+            } else {
+                if (cx.enterCount != 0) {
+                    throw new IllegalStateException("can not use Context instance already associated with some thread");
+                }
+            }
+            VMBridge.instance.setContext(helper, cx);
+        }
+        ++cx.enterCount;
+        return cx;
+     }
+
+    /**
+     * Exit a block of code requiring a Context.
+     *
+     * Calling <code>exit()</code> will remove the association between
+     * the current thread and a Context if the prior call to
+     * {@link ContextFactory#enterContext()} on this thread newly associated a
+     * Context with this thread. Once the current thread no longer has an
+     * associated Context, it cannot be used to execute JavaScript until it is
+     * again associated with a Context.
+     * @see ContextFactory#enterContext()
+     */
+    public static void exit()
+    {
+        Object helper = VMBridge.instance.getThreadContextHelper();
+        Context cx = VMBridge.instance.getContext(helper);
+        if (cx == null) {
+            throw new IllegalStateException(
+                "Calling Context.exit without previous Context.enter");
+        }
+        if (cx.enterCount < 1) Kit.codeBug();
+        if (--cx.enterCount == 0) {
+            VMBridge.instance.setContext(helper, null);
+            cx.factory.onContextReleased(cx);
+        }
+    }
+
+    /**
+     * Call {@link ContextAction#run(Context cx)}
+     * using the Context instance associated with the current thread.
+     * If no Context is associated with the thread, then
+     * <tt>ContextFactory.getGlobal().makeContext()</tt> will be called to
+     * construct new Context instance. The instance will be temporary
+     * associated with the thread during call to
+     * {@link ContextAction#run(Context)}.
+     * @deprecated use {@link ContextFactory#call(ContextAction)} instead as
+     * this method relies on usage of a static singleton "global"
+     * ContextFactory.
+     * @return The result of {@link ContextAction#run(Context)}.
+     */
+    @Deprecated
+    public static Object call(ContextAction action)
+    {
+        return call(ContextFactory.getGlobal(), action);
+    }
+
+    /**
+     * Call {@link
+     * Callable#call(Context cx, Scriptable scope, Scriptable thisObj,
+     *               Object[] args)}
+     * using the Context instance associated with the current thread.
+     * If no Context is associated with the thread, then
+     * {@link ContextFactory#makeContext()} will be called to construct
+     * new Context instance. The instance will be temporary associated
+     * with the thread during call to {@link ContextAction#run(Context)}.
+     * <p>
+     * It is allowed but not advisable to use null for <tt>factory</tt>
+     * argument in which case the global static singleton ContextFactory
+     * instance will be used to create new context instances.
+     * @see ContextFactory#call(ContextAction)
+     */
+    public static Object call(ContextFactory factory, final Callable callable,
+                              final Scriptable scope, final Scriptable thisObj,
+                              final Object[] args)
+    {
+        if(factory == null) {
+            factory = ContextFactory.getGlobal();
+        }
+        return call(factory, new ContextAction() {
+            public Object run(Context cx) {
+                return callable.call(cx, scope, thisObj, args);
+            }
+        });
+    }
+
+    /**
+     * The method implements {@link ContextFactory#call(ContextAction)} logic.
+     */
+    static Object call(ContextFactory factory, ContextAction action) {
+        Context cx = enter(null, factory);
+        try {
+            return action.run(cx);
+        }
+        finally {
+            exit();
+        }
+    }
+
+    /**
+     * @deprecated
+     * @see ContextFactory#addListener(org.mozilla.javascript.ContextFactory.Listener)
+     * @see ContextFactory#getGlobal()
+     */
+    @Deprecated
+    public static void addContextListener(ContextListener listener)
+    {
+        // Special workaround for the debugger
+        String DBG = "org.mozilla.javascript.tools.debugger.Main";
+        if (DBG.equals(listener.getClass().getName())) {
+            Class<?> cl = listener.getClass();
+            Class<?> factoryClass = Kit.classOrNull(
+                "org.mozilla.javascript.ContextFactory");
+            Class<?>[] sig = { factoryClass };
+            Object[] args = { ContextFactory.getGlobal() };
+            try {
+                Method m = cl.getMethod("attachTo", sig);
+                m.invoke(listener, args);
+            } catch (Exception ex) {
+                RuntimeException rex = new RuntimeException();
+                Kit.initCause(rex, ex);
+                throw rex;
+            }
+            return;
+        }
+
+        ContextFactory.getGlobal().addListener(listener);
+    }
+
+    /**
+     * @deprecated
+     * @see ContextFactory#removeListener(org.mozilla.javascript.ContextFactory.Listener)
+     * @see ContextFactory#getGlobal()
+     */
+    @Deprecated
+    public static void removeContextListener(ContextListener listener)
+    {
+        ContextFactory.getGlobal().addListener(listener);
+    }
+
+    /**
+     * Return {@link ContextFactory} instance used to create this Context.
+     */
+    public final ContextFactory getFactory()
+    {
+        return factory;
+    }
+
+    /**
+     * Checks if this is a sealed Context. A sealed Context instance does not
+     * allow to modify any of its properties and will throw an exception
+     * on any such attempt.
+     * @see #seal(Object sealKey)
+     */
+    public final boolean isSealed()
+    {
+        return sealed;
+    }
+
+    /**
+     * Seal this Context object so any attempt to modify any of its properties
+     * including calling {@link #enter()} and {@link #exit()} methods will
+     * throw an exception.
+     * <p>
+     * If <tt>sealKey</tt> is not null, calling
+     * {@link #unseal(Object sealKey)} with the same key unseals
+     * the object. If <tt>sealKey</tt> is null, unsealing is no longer possible.
+     *
+     * @see #isSealed()
+     * @see #unseal(Object)
+     */
+    public final void seal(Object sealKey)
+    {
+        if (sealed) onSealedMutation();
+        sealed = true;
+        this.sealKey = sealKey;
+    }
+
+    /**
+     * Unseal previously sealed Context object.
+     * The <tt>sealKey</tt> argument should not be null and should match
+     * <tt>sealKey</tt> suplied with the last call to
+     * {@link #seal(Object)} or an exception will be thrown.
+     *
+     * @see #isSealed()
+     * @see #seal(Object sealKey)
+     */
+    public final void unseal(Object sealKey)
+    {
+        if (sealKey == null) throw new IllegalArgumentException();
+        if (this.sealKey != sealKey) throw new IllegalArgumentException();
+        if (!sealed) throw new IllegalStateException();
+        sealed = false;
+        this.sealKey = null;
+    }
+
+    static void onSealedMutation()
+    {
+        throw new IllegalStateException();
+    }
+
+    /**
+     * Get the current language version.
+     * <p>
+     * The language version number affects JavaScript semantics as detailed
+     * in the overview documentation.
+     *
+     * @return an integer that is one of VERSION_1_0, VERSION_1_1, etc.
+     */
+    public final int getLanguageVersion()
+    {
+       return version;
+    }
+
+    /**
+     * Set the language version.
+     *
+     * <p>
+     * Setting the language version will affect functions and scripts compiled
+     * subsequently. See the overview documentation for version-specific
+     * behavior.
+     *
+     * @param version the version as specified by VERSION_1_0, VERSION_1_1, etc.
+     */
+    public void setLanguageVersion(int version)
+    {
+        if (sealed) onSealedMutation();
+        checkLanguageVersion(version);
+        Object listeners = propertyListeners;
+        if (listeners != null && version != this.version) {
+            firePropertyChangeImpl(listeners, languageVersionProperty,
+                               Integer.valueOf(this.version),
+                               Integer.valueOf(version));
+        }
+        this.version = version;
+    }
+
+    public static boolean isValidLanguageVersion(int version)
+    {
+        switch (version) {
+            case VERSION_DEFAULT:
+            case VERSION_1_0:
+            case VERSION_1_1:
+            case VERSION_1_2:
+            case VERSION_1_3:
+            case VERSION_1_4:
+            case VERSION_1_5:
+            case VERSION_1_6:
+            case VERSION_1_7:
+            case VERSION_1_8:
+            case VERSION_ES6:
+                return true;
+        }
+        return false;
+    }
+
+    public static void checkLanguageVersion(int version)
+    {
+        if (isValidLanguageVersion(version)) {
+            return;
+        }
+        throw new IllegalArgumentException("Bad language version: "+version);
+    }
+
+    /**
+     * Get the implementation version.
+     *
+     * <p>
+     * The implementation version is of the form
+     * <pre>
+     *    "<i>name langVer</i> <code>release</code> <i>relNum date</i>"
+     * </pre>
+     * where <i>name</i> is the name of the product, <i>langVer</i> is
+     * the language version, <i>relNum</i> is the release number, and
+     * <i>date</i> is the release date for that specific
+     * release in the form "yyyy mm dd".
+     *
+     * @return a string that encodes the product, language version, release
+     *         number, and date.
+     */
+    public final String getImplementationVersion()
+    {
+        if (implementationVersion == null) {
+            Enumeration<URL> urls;
+            try {
+                urls = Context.class.getClassLoader().getResources("META-INF/MANIFEST.MF");
+            } catch (IOException ioe) {
+                return null;
+            }
+
+            // There will be many manifests in the world -- enumerate all of them until we find the right one.
+            while (urls.hasMoreElements()) {
+                URL metaUrl = urls.nextElement();
+                InputStream is = null;
+                try {
+                    is = metaUrl.openStream();
+                    Manifest mf = new Manifest(is);
+                    Attributes attrs = mf.getMainAttributes();
+                    if ("Mozilla Rhino".equals(attrs.getValue("Implementation-Title"))) {
+                        implementationVersion =
+                            "Rhino " + attrs.getValue("Implementation-Version") + " " + attrs.getValue("Built-Date").replaceAll("-", " ");
+                        return implementationVersion;
+                    }
+                } catch (IOException e) {
+                    // Ignore this unlikely event
+                } finally {
+                    try {
+                        if (is != null) is.close();
+                    } catch (IOException e) {
+                        // Ignore this even unlikelier event
+                    }
+                }
+            }
+        }
+
+        return implementationVersion;
+    }
+
+    /**
+     * Get the current error reporter.
+     *
+     * @see org.mozilla.javascript.ErrorReporter
+     */
+    public final ErrorReporter getErrorReporter()
+    {
+        if (errorReporter == null) {
+            return DefaultErrorReporter.instance;
+        }
+        return errorReporter;
+    }
+
+    /**
+     * Change the current error reporter.
+     *
+     * @return the previous error reporter
+     * @see org.mozilla.javascript.ErrorReporter
+     */
+    public final ErrorReporter setErrorReporter(ErrorReporter reporter)
+    {
+        if (sealed) onSealedMutation();
+        if (reporter == null) throw new IllegalArgumentException();
+        ErrorReporter old = getErrorReporter();
+        if (reporter == old) {
+            return old;
+        }
+        Object listeners = propertyListeners;
+        if (listeners != null) {
+            firePropertyChangeImpl(listeners, errorReporterProperty,
+                                   old, reporter);
+        }
+        this.errorReporter = reporter;
+        return old;
+    }
+
+    /**
+     * Get the current locale.  Returns the default locale if none has
+     * been set.
+     *
+     * @see java.util.Locale
+     */
+
+    public final Locale getLocale()
+    {
+        if (locale == null)
+            locale = Locale.getDefault();
+        return locale;
+    }
+
+    /**
+     * Set the current locale.
+     *
+     * @see java.util.Locale
+     */
+    public final Locale setLocale(Locale loc)
+    {
+        if (sealed) onSealedMutation();
+        Locale result = locale;
+        locale = loc;
+        return result;
+    }
+
+    /**
+     * Register an object to receive notifications when a bound property
+     * has changed
+     * @see java.beans.PropertyChangeEvent
+     * @see #removePropertyChangeListener(java.beans.PropertyChangeListener)
+     * @param l the listener
+     */
+    public final void addPropertyChangeListener(PropertyChangeListener l)
+    {
+        if (sealed) onSealedMutation();
+        propertyListeners = Kit.addListener(propertyListeners, l);
+    }
+
+    /**
+     * Remove an object from the list of objects registered to receive
+     * notification of changes to a bounded property
+     * @see java.beans.PropertyChangeEvent
+     * @see #addPropertyChangeListener(java.beans.PropertyChangeListener)
+     * @param l the listener
+     */
+    public final void removePropertyChangeListener(PropertyChangeListener l)
+    {
+        if (sealed) onSealedMutation();
+        propertyListeners = Kit.removeListener(propertyListeners, l);
+    }
+
+    /**
+     * Notify any registered listeners that a bounded property has changed
+     * @see #addPropertyChangeListener(java.beans.PropertyChangeListener)
+     * @see #removePropertyChangeListener(java.beans.PropertyChangeListener)
+     * @see java.beans.PropertyChangeListener
+     * @see java.beans.PropertyChangeEvent
+     * @param  property  the bound property
+     * @param  oldValue  the old value
+     * @param  newValue   the new value
+     */
+    final void firePropertyChange(String property, Object oldValue,
+                                  Object newValue)
+    {
+        Object listeners = propertyListeners;
+        if (listeners != null) {
+            firePropertyChangeImpl(listeners, property, oldValue, newValue);
+        }
+    }
+
+    private void firePropertyChangeImpl(Object listeners, String property,
+                                        Object oldValue, Object newValue)
+    {
+        for (int i = 0; ; ++i) {
+            Object l = Kit.getListener(listeners, i);
+            if (l == null)
+                break;
+            if (l instanceof PropertyChangeListener) {
+                PropertyChangeListener pcl = (PropertyChangeListener)l;
+                pcl.propertyChange(new PropertyChangeEvent(
+                    this, property, oldValue, newValue));
+            }
+        }
+    }
+
+    /**
+     * Report a warning using the error reporter for the current thread.
+     *
+     * @param message the warning message to report
+     * @param sourceName a string describing the source, such as a filename
+     * @param lineno the starting line number
+     * @param lineSource the text of the line (may be null)
+     * @param lineOffset the offset into lineSource where problem was detected
+     * @see org.mozilla.javascript.ErrorReporter
+     */
+    public static void reportWarning(String message, String sourceName,
+                                     int lineno, String lineSource,
+                                     int lineOffset)
+    {
+        Context cx = Context.getContext();
+        if (cx.hasFeature(FEATURE_WARNING_AS_ERROR))
+            reportError(message, sourceName, lineno, lineSource, lineOffset);
+        else
+            cx.getErrorReporter().warning(message, sourceName, lineno,
+                                          lineSource, lineOffset);
+    }
+
+    /**
+     * Report a warning using the error reporter for the current thread.
+     *
+     * @param message the warning message to report
+     * @see org.mozilla.javascript.ErrorReporter
+     */
+    public static void reportWarning(String message)
+    {
+        int[] linep = { 0 };
+        String filename = getSourcePositionFromStack(linep);
+        Context.reportWarning(message, filename, linep[0], null, 0);
+    }
+
+    public static void reportWarning(String message, Throwable t)
+    {
+        int[] linep = { 0 };
+        String filename = getSourcePositionFromStack(linep);
+        Writer sw = new StringWriter();
+        PrintWriter pw = new PrintWriter(sw);
+        pw.println(message);
+        t.printStackTrace(pw);
+        pw.flush();
+        Context.reportWarning(sw.toString(), filename, linep[0], null, 0);
+    }
+
+    /**
+     * Report an error using the error reporter for the current thread.
+     *
+     * @param message the error message to report
+     * @param sourceName a string describing the source, such as a filename
+     * @param lineno the starting line number
+     * @param lineSource the text of the line (may be null)
+     * @param lineOffset the offset into lineSource where problem was detected
+     * @see org.mozilla.javascript.ErrorReporter
+     */
+    public static void reportError(String message, String sourceName,
+                                   int lineno, String lineSource,
+                                   int lineOffset)
+    {
+        Context cx = getCurrentContext();
+        if (cx != null) {
+            cx.getErrorReporter().error(message, sourceName, lineno,
+                                        lineSource, lineOffset);
+        } else {
+            throw new EvaluatorException(message, sourceName, lineno,
+                                         lineSource, lineOffset);
+        }
+    }
+
+    /**
+     * Report an error using the error reporter for the current thread.
+     *
+     * @param message the error message to report
+     * @see org.mozilla.javascript.ErrorReporter
+     */
+    public static void reportError(String message)
+    {
+        int[] linep = { 0 };
+        String filename = getSourcePositionFromStack(linep);
+        Context.reportError(message, filename, linep[0], null, 0);
+    }
+
+    /**
+     * Report a runtime error using the error reporter for the current thread.
+     *
+     * @param message the error message to report
+     * @param sourceName a string describing the source, such as a filename
+     * @param lineno the starting line number
+     * @param lineSource the text of the line (may be null)
+     * @param lineOffset the offset into lineSource where problem was detected
+     * @return a runtime exception that will be thrown to terminate the
+     *         execution of the script
+     * @see org.mozilla.javascript.ErrorReporter
+     */
+    public static EvaluatorException reportRuntimeError(String message,
+                                                        String sourceName,
+                                                        int lineno,
+                                                        String lineSource,
+                                                        int lineOffset)
+    {
+        Context cx = getCurrentContext();
+        if (cx != null) {
+            return cx.getErrorReporter().
+                            runtimeError(message, sourceName, lineno,
+                                         lineSource, lineOffset);
+        } else {
+            throw new EvaluatorException(message, sourceName, lineno,
+                                         lineSource, lineOffset);
+        }
+    }
+
+    static EvaluatorException reportRuntimeError0(String messageId)
+    {
+        String msg = ScriptRuntime.getMessage0(messageId);
+        return reportRuntimeError(msg);
+    }
+
+    static EvaluatorException reportRuntimeError1(String messageId,
+                                                  Object arg1)
+    {
+        String msg = ScriptRuntime.getMessage1(messageId, arg1);
+        return reportRuntimeError(msg);
+    }
+
+    static EvaluatorException reportRuntimeError2(String messageId,
+                                                  Object arg1, Object arg2)
+    {
+        String msg = ScriptRuntime.getMessage2(messageId, arg1, arg2);
+        return reportRuntimeError(msg);
+    }
+
+    static EvaluatorException reportRuntimeError3(String messageId,
+                                                  Object arg1, Object arg2,
+                                                  Object arg3)
+    {
+        String msg = ScriptRuntime.getMessage3(messageId, arg1, arg2, arg3);
+        return reportRuntimeError(msg);
+    }
+
+    static EvaluatorException reportRuntimeError4(String messageId,
+                                                  Object arg1, Object arg2,
+                                                  Object arg3, Object arg4)
+    {
+        String msg
+            = ScriptRuntime.getMessage4(messageId, arg1, arg2, arg3, arg4);
+        return reportRuntimeError(msg);
+    }
+
+    /**
+     * Report a runtime error using the error reporter for the current thread.
+     *
+     * @param message the error message to report
+     * @see org.mozilla.javascript.ErrorReporter
+     */
+    public static EvaluatorException reportRuntimeError(String message)
+    {
+        int[] linep = { 0 };
+        String filename = getSourcePositionFromStack(linep);
+        return Context.reportRuntimeError(message, filename, linep[0], null, 0);
+    }
+
+    /**
+     * Initialize the standard objects.
+     *
+     * Creates instances of the standard objects and their constructors
+     * (Object, String, Number, Date, etc.), setting up 'scope' to act
+     * as a global object as in ECMA 15.1.<p>
+     *
+     * This method must be called to initialize a scope before scripts
+     * can be evaluated in that scope.<p>
+     *
+     * This method does not affect the Context it is called upon.
+     *
+     * @return the initialized scope
+     */
+    public final ScriptableObject initStandardObjects()
+    {
+        return initStandardObjects(null, false);
+    }
+
+    /**
+     * Initialize the standard objects, leaving out those that offer access directly
+     * to Java classes. This sets up "scope" to have access to all the standard
+     * JavaScript classes, but does not create global objects for any top-level
+     * Java packages. In addition, the "Packages," "JavaAdapter," and
+     * "JavaImporter" classes, and the "getClass" function, are not
+     * initialized.
+     *
+     * The result of this function is a scope that may be safely used in a "sandbox"
+     * environment where it is not desirable to give access to Java code from JavaScript.
+     *
+     * Creates instances of the standard objects and their constructors
+     * (Object, String, Number, Date, etc.), setting up 'scope' to act
+     * as a global object as in ECMA 15.1.<p>
+     *
+     * This method must be called to initialize a scope before scripts
+     * can be evaluated in that scope.<p>
+     *
+     * This method does not affect the Context it is called upon.
+     *
+     * @return the initialized scope
+     */
+    public final ScriptableObject initSafeStandardObjects()
+    {
+        return initSafeStandardObjects(null, false);
+    }
+
+    /**
+     * Initialize the standard objects.
+     *
+     * Creates instances of the standard objects and their constructors
+     * (Object, String, Number, Date, etc.), setting up 'scope' to act
+     * as a global object as in ECMA 15.1.<p>
+     *
+     * This method must be called to initialize a scope before scripts
+     * can be evaluated in that scope.<p>
+     *
+     * This method does not affect the Context it is called upon.
+     *
+     * @param scope the scope to initialize, or null, in which case a new
+     *        object will be created to serve as the scope
+     * @return the initialized scope. The method returns the value of the scope
+     *         argument if it is not null or newly allocated scope object which
+     *         is an instance {@link ScriptableObject}.
+     */
+    public final Scriptable initStandardObjects(ScriptableObject scope)
+    {
+        return initStandardObjects(scope, false);
+    }
+
+    /**
+     * Initialize the standard objects, leaving out those that offer access directly
+     * to Java classes. This sets up "scope" to have access to all the standard
+     * JavaScript classes, but does not create global objects for any top-level
+     * Java packages. In addition, the "Packages," "JavaAdapter," and
+     * "JavaImporter" classes, and the "getClass" function, are not
+     * initialized.
+     *
+     * The result of this function is a scope that may be safely used in a "sandbox"
+     * environment where it is not desirable to give access to Java code from JavaScript.
+     *
+     * Creates instances of the standard objects and their constructors
+     * (Object, String, Number, Date, etc.), setting up 'scope' to act
+     * as a global object as in ECMA 15.1.<p>
+     *
+     * This method must be called to initialize a scope before scripts
+     * can be evaluated in that scope.<p>
+     *
+     * This method does not affect the Context it is called upon.
+     *
+     * @param scope the scope to initialize, or null, in which case a new
+     *        object will be created to serve as the scope
+     * @return the initialized scope. The method returns the value of the scope
+     *         argument if it is not null or newly allocated scope object which
+     *         is an instance {@link ScriptableObject}.
+     */
+    public final Scriptable initSafeStandardObjects(ScriptableObject scope)
+    {
+        return initSafeStandardObjects(scope, false);
+    }
+
+    /**
+     * Initialize the standard objects.
+     *
+     * Creates instances of the standard objects and their constructors
+     * (Object, String, Number, Date, etc.), setting up 'scope' to act
+     * as a global object as in ECMA 15.1.<p>
+     *
+     * This method must be called to initialize a scope before scripts
+     * can be evaluated in that scope.<p>
+     *
+     * This method does not affect the Context it is called upon.<p>
+     *
+     * This form of the method also allows for creating "sealed" standard
+     * objects. An object that is sealed cannot have properties added, changed,
+     * or removed. This is useful to create a "superglobal" that can be shared
+     * among several top-level objects. Note that sealing is not allowed in
+     * the current ECMA/ISO language specification, but is likely for
+     * the next version.
+     *
+     * @param scope the scope to initialize, or null, in which case a new
+     *        object will be created to serve as the scope
+     * @param sealed whether or not to create sealed standard objects that
+     *        cannot be modified.
+     * @return the initialized scope. The method returns the value of the scope
+     *         argument if it is not null or newly allocated scope object.
+     * @since 1.4R3
+     */
+    public ScriptableObject initStandardObjects(ScriptableObject scope,
+                                                boolean sealed)
+    {
+        return ScriptRuntime.initStandardObjects(this, scope, sealed);
+    }
+
+    /**
+     * Initialize the standard objects, leaving out those that offer access directly
+     * to Java classes. This sets up "scope" to have access to all the standard
+     * JavaScript classes, but does not create global objects for any top-level
+     * Java packages. In addition, the "Packages," "JavaAdapter," and
+     * "JavaImporter" classes, and the "getClass" function, are not
+     * initialized.
+     *
+     * The result of this function is a scope that may be safely used in a "sandbox"
+     * environment where it is not desirable to give access to Java code from JavaScript.
+     *
+     * Creates instances of the standard objects and their constructors
+     * (Object, String, Number, Date, etc.), setting up 'scope' to act
+     * as a global object as in ECMA 15.1.<p>
+     *
+     * This method must be called to initialize a scope before scripts
+     * can be evaluated in that scope.<p>
+     *
+     * This method does not affect the Context it is called upon.<p>
+     *
+     * This form of the method also allows for creating "sealed" standard
+     * objects. An object that is sealed cannot have properties added, changed,
+     * or removed. This is useful to create a "superglobal" that can be shared
+     * among several top-level objects. Note that sealing is not allowed in
+     * the current ECMA/ISO language specification, but is likely for
+     * the next version.
+     *
+     * @param scope the scope to initialize, or null, in which case a new
+     *        object will be created to serve as the scope
+     * @param sealed whether or not to create sealed standard objects that
+     *        cannot be modified.
+     * @return the initialized scope. The method returns the value of the scope
+     *         argument if it is not null or newly allocated scope object.
+     * @since 1.7.6
+     */
+    public ScriptableObject initSafeStandardObjects(ScriptableObject scope,
+                                                    boolean sealed)
+    {
+        return ScriptRuntime.initSafeStandardObjects(this, scope, sealed);
+    }
+
+    /**
+     * Get the singleton object that represents the JavaScript Undefined value.
+     */
+    public static Object getUndefinedValue()
+    {
+        return Undefined.instance;
+    }
+
+    /**
+     * Evaluate a JavaScript source string.
+     *
+     * The provided source name and line number are used for error messages
+     * and for producing debug information.
+     *
+     * @param scope the scope to execute in
+     * @param source the JavaScript source
+     * @param sourceName a string describing the source, such as a filename
+     * @param lineno the starting line number
+     * @param securityDomain an arbitrary object that specifies security
+     *        information about the origin or owner of the script. For
+     *        implementations that don't care about security, this value
+     *        may be null.
+     * @return the result of evaluating the string
+     * @see org.mozilla.javascript.SecurityController
+     */
+    public final Object evaluateString(Scriptable scope, String source,
+                                       String sourceName, int lineno,
+                                       Object securityDomain)
+    {
+        Script script = compileString(source, sourceName, lineno,
+                                      securityDomain);
+        if (script != null) {
+            return script.exec(this, scope);
+        } else {
+            return null;
+        }
+    }
+
+    /**
+     * Evaluate a reader as JavaScript source.
+     *
+     * All characters of the reader are consumed.
+     *
+     * @param scope the scope to execute in
+     * @param in the Reader to get JavaScript source from
+     * @param sourceName a string describing the source, such as a filename
+     * @param lineno the starting line number
+     * @param securityDomain an arbitrary object that specifies security
+     *        information about the origin or owner of the script. For
+     *        implementations that don't care about security, this value
+     *        may be null.
+     * @return the result of evaluating the source
+     *
+     * @exception IOException if an IOException was generated by the Reader
+     */
+    public final Object evaluateReader(Scriptable scope, Reader in,
+                                       String sourceName, int lineno,
+                                       Object securityDomain)
+        throws IOException
+    {
+        Script script = compileReader(scope, in, sourceName, lineno,
+                                      securityDomain);
+        if (script != null) {
+            return script.exec(this, scope);
+        } else {
+            return null;
+        }
+    }
+
+    /**
+     * Execute script that may pause execution by capturing a continuation.
+     * Caller must be prepared to catch a ContinuationPending exception
+     * and resume execution by calling
+     * {@link #resumeContinuation(Object, Scriptable, Object)}.
+     * @param script The script to execute. Script must have been compiled
+     *      with interpreted mode (optimization level -1)
+     * @param scope The scope to execute the script against
+     * @throws ContinuationPending if the script calls a function that results
+     *      in a call to {@link #captureContinuation()}
+     * @since 1.7 Release 2
+     */
+    public Object executeScriptWithContinuations(Script script,
+            Scriptable scope)
+        throws ContinuationPending
+    {
+        if (!(script instanceof InterpretedFunction) ||
+            !((InterpretedFunction)script).isScript())
+        {
+            // Can only be applied to scripts
+            throw new IllegalArgumentException("Script argument was not" +
+                    " a script or was not created by interpreted mode ");
+        }
+        return callFunctionWithContinuations((InterpretedFunction) script,
+                scope, ScriptRuntime.emptyArgs);
+    }
+
+    /**
+     * Call function that may pause execution by capturing a continuation.
+     * Caller must be prepared to catch a ContinuationPending exception
+     * and resume execution by calling
+     * {@link #resumeContinuation(Object, Scriptable, Object)}.
+     * @param function The function to call. The function must have been
+     *      compiled with interpreted mode (optimization level -1)
+     * @param scope The scope to execute the script against
+     * @param args The arguments for the function
+     * @throws ContinuationPending if the script calls a function that results
+     *      in a call to {@link #captureContinuation()}
+     * @since 1.7 Release 2
+     */
+    public Object callFunctionWithContinuations(Callable function,
+            Scriptable scope, Object[] args)
+        throws ContinuationPending
+    {
+        if (!(function instanceof InterpretedFunction)) {
+            // Can only be applied to scripts
+            throw new IllegalArgumentException("Function argument was not" +
+                    " created by interpreted mode ");
+        }
+        if (ScriptRuntime.hasTopCall(this)) {
+            throw new IllegalStateException("Cannot have any pending top " +
+                    "calls when executing a script with continuations");
+        }
+        // Annotate so we can check later to ensure no java code in
+        // intervening frames
+        isContinuationsTopCall = true;
+        return ScriptRuntime.doTopCall(function, this, scope, scope, args, isTopLevelStrict);
+    }
+
+    /**
+     * Capture a continuation from the current execution. The execution must
+     * have been started via a call to
+     * {@link #executeScriptWithContinuations(Script, Scriptable)} or
+     * {@link #callFunctionWithContinuations(Callable, Scriptable, Object[])}.
+     * This implies that the code calling
+     * this method must have been called as a function from the
+     * JavaScript script. Also, there cannot be any non-JavaScript code
+     * between the JavaScript frames (e.g., a call to eval()). The
+     * ContinuationPending exception returned must be thrown.
+     * @return A ContinuationPending exception that must be thrown
+     * @since 1.7 Release 2
+     */
+    public ContinuationPending captureContinuation() {
+        return new ContinuationPending(
+                Interpreter.captureContinuation(this));
+    }
+
+    /**
+     * Restarts execution of the JavaScript suspended at the call
+     * to {@link #captureContinuation()}. Execution of the code will resume
+     * with the functionResult as the result of the call that captured the
+     * continuation.
+     * Execution of the script will either conclude normally and the
+     * result returned, another continuation will be captured and
+     * thrown, or the script will terminate abnormally and throw an exception.
+     * @param continuation The value returned by
+     * {@link ContinuationPending#getContinuation()}
+     * @param functionResult This value will appear to the code being resumed
+     *      as the result of the function that captured the continuation
+     * @throws ContinuationPending if another continuation is captured before
+     *      the code terminates
+     * @since 1.7 Release 2
+     */
+    public Object resumeContinuation(Object continuation,
+            Scriptable scope, Object functionResult)
+            throws ContinuationPending
+    {
+        Object[] args = { functionResult };
+        return Interpreter.restartContinuation(
+                (org.mozilla.javascript.NativeContinuation) continuation,
+                this, scope, args);
+    }
+
+    /**
+     * Check whether a string is ready to be compiled.
+     * <p>
+     * stringIsCompilableUnit is intended to support interactive compilation of
+     * JavaScript.  If compiling the string would result in an error
+     * that might be fixed by appending more source, this method
+     * returns false.  In every other case, it returns true.
+     * <p>
+     * Interactive shells may accumulate source lines, using this
+     * method after each new line is appended to check whether the
+     * statement being entered is complete.
+     *
+     * @param source the source buffer to check
+     * @return whether the source is ready for compilation
+     * @since 1.4 Release 2
+     */
+    public final boolean stringIsCompilableUnit(String source) {
+        boolean errorseen = false;
+        CompilerEnvirons compilerEnv = new CompilerEnvirons();
+        compilerEnv.initFromContext(this);
+        // no source name or source text manager, because we're just
+        // going to throw away the result.
+        compilerEnv.setGeneratingSource(false);
+        Parser p = new Parser(compilerEnv, DefaultErrorReporter.instance);
+        try {
+            p.parse(source, null, 1);
+        } catch (EvaluatorException ee) {
+            errorseen = true;
+        }
+        // Return false only if an error occurred as a result of reading past
+        // the end of the file, i.e. if the source could be fixed by
+        // appending more source.
+        return !(errorseen && p.eof());
+    }
+
+    /**
+     * @deprecated
+     * @see #compileReader(Reader in, String sourceName, int lineno,
+     *                     Object securityDomain)
+     */
+    @Deprecated
+    public final Script compileReader(Scriptable scope, Reader in,
+                                      String sourceName, int lineno,
+                                      Object securityDomain)
+        throws IOException
+    {
+        return compileReader(in, sourceName, lineno, securityDomain);
+    }
+
+    /**
+     * Compiles the source in the given reader.
+     * <p>
+     * Returns a script that may later be executed.
+     * Will consume all the source in the reader.
+     *
+     * @param in the input reader
+     * @param sourceName a string describing the source, such as a filename
+     * @param lineno the starting line number for reporting errors
+     * @param securityDomain an arbitrary object that specifies security
+     *        information about the origin or owner of the script. For
+     *        implementations that don't care about security, this value
+     *        may be null.
+     * @return a script that may later be executed
+     * @exception IOException if an IOException was generated by the Reader
+     * @see org.mozilla.javascript.Script
+     */
+    public final Script compileReader(Reader in, String sourceName,
+                                      int lineno, Object securityDomain)
+        throws IOException
+    {
+        if (lineno < 0) {
+            // For compatibility IllegalArgumentException can not be thrown here
+            lineno = 0;
+        }
+        return (Script) compileImpl(null, in, null, sourceName, lineno,
+                                    securityDomain, false, null, null);
+    }
+
+    /**
+     * Compiles the source in the given string.
+     * <p>
+     * Returns a script that may later be executed.
+     *
+     * @param source the source string
+     * @param sourceName a string describing the source, such as a filename
+     * @param lineno the starting line number for reporting errors. Use
+     *        0 if the line number is unknown.
+     * @param securityDomain an arbitrary object that specifies security
+     *        information about the origin or owner of the script. For
+     *        implementations that don't care about security, this value
+     *        may be null.
+     * @return a script that may later be executed
+     * @see org.mozilla.javascript.Script
+     */
+    public final Script compileString(String source,
+                                      String sourceName, int lineno,
+                                      Object securityDomain)
+    {
+        if (lineno < 0) {
+            // For compatibility IllegalArgumentException can not be thrown here
+            lineno = 0;
+        }
+        return compileString(source, null, null, sourceName, lineno,
+                             securityDomain);
+    }
+
+    final Script compileString(String source,
+                               Evaluator compiler,
+                               ErrorReporter compilationErrorReporter,
+                               String sourceName, int lineno,
+                               Object securityDomain)
+    {
+        try {
+            return (Script) compileImpl(null, null, source, sourceName, lineno,
+                                        securityDomain, false,
+                                        compiler, compilationErrorReporter);
+        } catch (IOException ex) {
+            // Should not happen when dealing with source as string
+            throw new RuntimeException();
+        }
+    }
+
+    /**
+     * Compile a JavaScript function.
+     * <p>
+     * The function source must be a function definition as defined by
+     * ECMA (e.g., "function f(a) { return a; }").
+     *
+     * @param scope the scope to compile relative to
+     * @param source the function definition source
+     * @param sourceName a string describing the source, such as a filename
+     * @param lineno the starting line number
+     * @param securityDomain an arbitrary object that specifies security
+     *        information about the origin or owner of the script. For
+     *        implementations that don't care about security, this value
+     *        may be null.
+     * @return a Function that may later be called
+     * @see org.mozilla.javascript.Function
+     */
+    public final Function compileFunction(Scriptable scope, String source,
+                                          String sourceName, int lineno,
+                                          Object securityDomain)
+    {
+        return compileFunction(scope, source, null, null, sourceName, lineno,
+                               securityDomain);
+    }
+
+    final Function compileFunction(Scriptable scope, String source,
+                                   Evaluator compiler,
+                                   ErrorReporter compilationErrorReporter,
+                                   String sourceName, int lineno,
+                                   Object securityDomain)
+    {
+        try {
+            return (Function) compileImpl(scope, null, source, sourceName,
+                                          lineno, securityDomain, true,
+                                          compiler, compilationErrorReporter);
+        }
+        catch (IOException ioe) {
+            // Should never happen because we just made the reader
+            // from a String
+            throw new RuntimeException();
+        }
+    }
+
+    /**
+     * Decompile the script.
+     * <p>
+     * The canonical source of the script is returned.
+     *
+     * @param script the script to decompile
+     * @param indent the number of spaces to indent the result
+     * @return a string representing the script source
+     */
+    public final String decompileScript(Script script, int indent)
+    {
+        NativeFunction scriptImpl = (NativeFunction) script;
+        return scriptImpl.decompile(indent, 0);
+    }
+
+    /**
+     * Decompile a JavaScript Function.
+     * <p>
+     * Decompiles a previously compiled JavaScript function object to
+     * canonical source.
+     * <p>
+     * Returns function body of '[native code]' if no decompilation
+     * information is available.
+     *
+     * @param fun the JavaScript function to decompile
+     * @param indent the number of spaces to indent the result
+     * @return a string representing the function source
+     */
+    public final String decompileFunction(Function fun, int indent)
+    {
+        if (fun instanceof BaseFunction)
+            return ((BaseFunction)fun).decompile(indent, 0);
+        else
+            return "function " + fun.getClassName() +
+                   "() {\n\t[native code]\n}\n";
+    }
+
+    /**
+     * Decompile the body of a JavaScript Function.
+     * <p>
+     * Decompiles the body a previously compiled JavaScript Function
+     * object to canonical source, omitting the function header and
+     * trailing brace.
+     *
+     * Returns '[native code]' if no decompilation information is available.
+     *
+     * @param fun the JavaScript function to decompile
+     * @param indent the number of spaces to indent the result
+     * @return a string representing the function body source.
+     */
+    public final String decompileFunctionBody(Function fun, int indent)
+    {
+        if (fun instanceof BaseFunction) {
+            BaseFunction bf = (BaseFunction)fun;
+            return bf.decompile(indent, Decompiler.ONLY_BODY_FLAG);
+        }
+        // ALERT: not sure what the right response here is.
+        return "[native code]\n";
+    }
+
+    /**
+     * Create a new JavaScript object.
+     *
+     * Equivalent to evaluating "new Object()".
+     * @param scope the scope to search for the constructor and to evaluate
+     *              against
+     * @return the new object
+     */
+    public Scriptable newObject(Scriptable scope)
+    {
+        NativeObject result = new NativeObject();
+        ScriptRuntime.setBuiltinProtoAndParent(result, scope,
+                TopLevel.Builtins.Object);
+        return result;
+    }
+
+    /**
+     * Create a new JavaScript object by executing the named constructor.
+     *
+     * The call <code>newObject(scope, "Foo")</code> is equivalent to
+     * evaluating "new Foo()".
+     *
+     * @param scope the scope to search for the constructor and to evaluate against
+     * @param constructorName the name of the constructor to call
+     * @return the new object
+     */
+    public Scriptable newObject(Scriptable scope, String constructorName)
+    {
+        return newObject(scope, constructorName, ScriptRuntime.emptyArgs);
+    }
+
+    /**
+     * Creates a new JavaScript object by executing the named constructor.
+     *
+     * Searches <code>scope</code> for the named constructor, calls it with
+     * the given arguments, and returns the result.<p>
+     *
+     * The code
+     * <pre>
+     * Object[] args = { "a", "b" };
+     * newObject(scope, "Foo", args)</pre>
+     * is equivalent to evaluating "new Foo('a', 'b')", assuming that the Foo
+     * constructor has been defined in <code>scope</code>.
+     *
+     * @param scope The scope to search for the constructor and to evaluate
+     *              against
+     * @param constructorName the name of the constructor to call
+     * @param args the array of arguments for the constructor
+     * @return the new object
+     */
+    public Scriptable newObject(Scriptable scope, String constructorName,
+                                Object[] args)
+    {
+        return ScriptRuntime.newObject(this, scope, constructorName, args);
+    }
+
+    /**
+     * Create an array with a specified initial length.
+     * <p>
+     * @param scope the scope to create the object in
+     * @param length the initial length (JavaScript arrays may have
+     *               additional properties added dynamically).
+     * @return the new array object
+     */
+    public Scriptable newArray(Scriptable scope, int length)
+    {
+        NativeArray result = new NativeArray(length);
+        ScriptRuntime.setBuiltinProtoAndParent(result, scope,
+                TopLevel.Builtins.Array);
+        return result;
+    }
+
+    /**
+     * Create an array with a set of initial elements.
+     *
+     * @param scope the scope to create the object in.
+     * @param elements the initial elements. Each object in this array
+     *                 must be an acceptable JavaScript type and type
+     *                 of array should be exactly Object[], not
+     *                 SomeObjectSubclass[].
+     * @return the new array object.
+     */
+    public Scriptable newArray(Scriptable scope, Object[] elements)
+    {
+        if (elements.getClass().getComponentType() != ScriptRuntime.ObjectClass)
+            throw new IllegalArgumentException();
+        NativeArray result = new NativeArray(elements);
+        ScriptRuntime.setBuiltinProtoAndParent(result, scope,
+                TopLevel.Builtins.Array);
+        return result;
+    }
+
+    /**
+     * Get the elements of a JavaScript array.
+     * <p>
+     * If the object defines a length property convertible to double number,
+     * then the number is converted Uint32 value as defined in Ecma 9.6
+     * and Java array of that size is allocated.
+     * The array is initialized with the values obtained by
+     * calling get() on object for each value of i in [0,length-1]. If
+     * there is not a defined value for a property the Undefined value
+     * is used to initialize the corresponding element in the array. The
+     * Java array is then returned.
+     * If the object doesn't define a length property or it is not a number,
+     * empty array is returned.
+     * @param object the JavaScript array or array-like object
+     * @return a Java array of objects
+     * @since 1.4 release 2
+     */
+    public final Object[] getElements(Scriptable object)
+    {
+        return ScriptRuntime.getArrayElements(object);
+    }
+
+    /**
+     * Convert the value to a JavaScript boolean value.
+     * <p>
+     * See ECMA 9.2.
+     *
+     * @param value a JavaScript value
+     * @return the corresponding boolean value converted using
+     *         the ECMA rules
+     */
+    public static boolean toBoolean(Object value)
+    {
+        return ScriptRuntime.toBoolean(value);
+    }
+
+    /**
+     * Convert the value to a JavaScript Number value.
+     * <p>
+     * Returns a Java double for the JavaScript Number.
+     * <p>
+     * See ECMA 9.3.
+     *
+     * @param value a JavaScript value
+     * @return the corresponding double value converted using
+     *         the ECMA rules
+     */
+    public static double toNumber(Object value)
+    {
+        return ScriptRuntime.toNumber(value);
+    }
+
+    /**
+     * Convert the value to a JavaScript String value.
+     * <p>
+     * See ECMA 9.8.
+     * <p>
+     * @param value a JavaScript value
+     * @return the corresponding String value converted using
+     *         the ECMA rules
+     */
+    public static String toString(Object value)
+    {
+        return ScriptRuntime.toString(value);
+    }
+
+    /**
+     * Convert the value to an JavaScript object value.
+     * <p>
+     * Note that a scope must be provided to look up the constructors
+     * for Number, Boolean, and String.
+     * <p>
+     * See ECMA 9.9.
+     * <p>
+     * Additionally, arbitrary Java objects and classes will be
+     * wrapped in a Scriptable object with its Java fields and methods
+     * reflected as JavaScript properties of the object.
+     *
+     * @param value any Java object
+     * @param scope global scope containing constructors for Number,
+     *              Boolean, and String
+     * @return new JavaScript object
+     */
+    public static Scriptable toObject(Object value, Scriptable scope)
+    {
+        return ScriptRuntime.toObject(scope, value);
+    }
+
+    /**
+     * @deprecated
+     * @see #toObject(Object, Scriptable)
+     */
+    @Deprecated
+    public static Scriptable toObject(Object value, Scriptable scope,
+                                      Class<?> staticType)
+    {
+        return ScriptRuntime.toObject(scope, value);
+    }
+
+    /**
+     * Convenient method to convert java value to its closest representation
+     * in JavaScript.
+     * <p>
+     * If value is an instance of String, Number, Boolean, Function or
+     * Scriptable, it is returned as it and will be treated as the corresponding
+     * JavaScript type of string, number, boolean, function and object.
+     * <p>
+     * Note that for Number instances during any arithmetic operation in
+     * JavaScript the engine will always use the result of
+     * <tt>Number.doubleValue()</tt> resulting in a precision loss if
+     * the number can not fit into double.
+     * <p>
+     * If value is an instance of Character, it will be converted to string of
+     * length 1 and its JavaScript type will be string.
+     * <p>
+     * The rest of values will be wrapped as LiveConnect objects
+     * by calling {@link WrapFactory#wrap(Context cx, Scriptable scope,
+     * Object obj, Class staticType)} as in:
+     * <pre>
+     *    Context cx = Context.getCurrentContext();
+     *    return cx.getWrapFactory().wrap(cx, scope, value, null);
+     * </pre>
+     *
+     * @param value any Java object
+     * @param scope top scope object
+     * @return value suitable to pass to any API that takes JavaScript values.
+     */
+    public static Object javaToJS(Object value, Scriptable scope)
+    {
+        if (value instanceof String || value instanceof Number
+            || value instanceof Boolean || value instanceof Scriptable)
+        {
+            return value;
+        } else if (value instanceof Character) {
+            return String.valueOf(((Character)value).charValue());
+        } else {
+            Context cx = Context.getContext();
+            return cx.getWrapFactory().wrap(cx, scope, value, null);
+        }
+    }
+
+    /**
+     * Convert a JavaScript value into the desired type.
+     * Uses the semantics defined with LiveConnect3 and throws an
+     * Illegal argument exception if the conversion cannot be performed.
+     * @param value the JavaScript value to convert
+     * @param desiredType the Java type to convert to. Primitive Java
+     *        types are represented using the TYPE fields in the corresponding
+     *        wrapper class in java.lang.
+     * @return the converted value
+     * @throws EvaluatorException if the conversion cannot be performed
+     */
+    public static Object jsToJava(Object value, Class<?> desiredType)
+        throws EvaluatorException
+    {
+        return NativeJavaObject.coerceTypeImpl(desiredType, value);
+    }
+
+    /**
+     * @deprecated
+     * @see #jsToJava(Object, Class)
+     * @throws IllegalArgumentException if the conversion cannot be performed.
+     *         Note that {@link #jsToJava(Object, Class)} throws
+     *         {@link EvaluatorException} instead.
+     */
+    @Deprecated
+    public static Object toType(Object value, Class<?> desiredType)
+        throws IllegalArgumentException
+    {
+        try {
+            return jsToJava(value, desiredType);
+        } catch (EvaluatorException ex) {
+            IllegalArgumentException
+                ex2 = new IllegalArgumentException(ex.getMessage());
+            Kit.initCause(ex2, ex);
+            throw ex2;
+        }
+    }
+
+    /**
+     * Rethrow the exception wrapping it as the script runtime exception.
+     * Unless the exception is instance of {@link EcmaError} or
+     * {@link EvaluatorException} it will be wrapped as
+     * {@link WrappedException}, a subclass of {@link EvaluatorException}.
+     * The resulting exception object always contains
+     * source name and line number of script that triggered exception.
+     * <p>
+     * This method always throws an exception, its return value is provided
+     * only for convenience to allow a usage like:
+     * <pre>
+     * throw Context.throwAsScriptRuntimeEx(ex);
+     * </pre>
+     * to indicate that code after the method is unreachable.
+     * @throws EvaluatorException
+     * @throws EcmaError
+     */
+    public static RuntimeException throwAsScriptRuntimeEx(Throwable e)
+    {
+        while ((e instanceof InvocationTargetException)) {
+            e = ((InvocationTargetException) e).getTargetException();
+        }
+        // special handling of Error so scripts would not catch them
+        if (e instanceof Error) {
+            Context cx = getContext();
+            if (cx == null ||
+                !cx.hasFeature(Context.FEATURE_ENHANCED_JAVA_ACCESS))
+            {
+                throw (Error)e;
+            }
+        }
+        if (e instanceof RhinoException) {
+            throw (RhinoException)e;
+        }
+        throw new WrappedException(e);
+    }
+
+    /**
+     * Tell whether debug information is being generated.
+     * @since 1.3
+     */
+    public final boolean isGeneratingDebug()
+    {
+        return generatingDebug;
+    }
+
+    /**
+     * Specify whether or not debug information should be generated.
+     * <p>
+     * Setting the generation of debug information on will set the
+     * optimization level to zero.
+     * @since 1.3
+     */
+    public final void setGeneratingDebug(boolean generatingDebug)
+    {
+        if (sealed) onSealedMutation();
+        generatingDebugChanged = true;
+        if (generatingDebug && getOptimizationLevel() > 0)
+            setOptimizationLevel(0);
+        this.generatingDebug = generatingDebug;
+    }
+
+    /**
+     * Tell whether source information is being generated.
+     * @since 1.3
+     */
+    public final boolean isGeneratingSource()
+    {
+        return generatingSource;
+    }
+
+    /**
+     * Specify whether or not source information should be generated.
+     * <p>
+     * Without source information, evaluating the "toString" method
+     * on JavaScript functions produces only "[native code]" for
+     * the body of the function.
+     * Note that code generated without source is not fully ECMA
+     * conformant.
+     * @since 1.3
+     */
+    public final void setGeneratingSource(boolean generatingSource)
+    {
+        if (sealed) onSealedMutation();
+        this.generatingSource = generatingSource;
+    }
+
+    /**
+     * Get the current optimization level.
+     * <p>
+     * The optimization level is expressed as an integer between -1 and
+     * 9.
+     * @since 1.3
+     *
+     */
+    public final int getOptimizationLevel()
+    {
+        return optimizationLevel;
+    }
+
+    /**
+     * Set the current optimization level.
+     * <p>
+     * The optimization level is expected to be an integer between -1 and
+     * 9. Any negative values will be interpreted as -1, and any values
+     * greater than 9 will be interpreted as 9.
+     * An optimization level of -1 indicates that interpretive mode will
+     * always be used. Levels 0 through 9 indicate that class files may
+     * be generated. Higher optimization levels trade off compile time
+     * performance for runtime performance.
+     * The optimizer level can't be set greater than -1 if the optimizer
+     * package doesn't exist at run time.
+     * @param optimizationLevel an integer indicating the level of
+     *        optimization to perform
+     * @since 1.3
+     *
+     */
+    public final void setOptimizationLevel(int optimizationLevel)
+    {
+        if (sealed) onSealedMutation();
+        if (optimizationLevel == -2) {
+            // To be compatible with Cocoon fork
+            optimizationLevel = -1;
+        }
+        checkOptimizationLevel(optimizationLevel);
+        if (codegenClass == null)
+            optimizationLevel = -1;
+        this.optimizationLevel = optimizationLevel;
+    }
+
+    public static boolean isValidOptimizationLevel(int optimizationLevel)
+    {
+        return -1 <= optimizationLevel && optimizationLevel <= 9;
+    }
+
+    public static void checkOptimizationLevel(int optimizationLevel)
+    {
+        if (isValidOptimizationLevel(optimizationLevel)) {
+            return;
+        }
+        throw new IllegalArgumentException(
+            "Optimization level outside [-1..9]: "+optimizationLevel);
+    }
+
+    /**
+     * Returns the maximum stack depth (in terms of number of call frames)
+     * allowed in a single invocation of interpreter. If the set depth would be
+     * exceeded, the interpreter will throw an EvaluatorException in the script.
+     * Defaults to Integer.MAX_VALUE. The setting only has effect for
+     * interpreted functions (those compiled with optimization level set to -1).
+     * As the interpreter doesn't use the Java stack but rather manages its own
+     * stack in the heap memory, a runaway recursion in interpreted code would
+     * eventually consume all available memory and cause OutOfMemoryError
+     * instead of a StackOverflowError limited to only a single thread. This
+     * setting helps prevent such situations.
+     *
+     * @return The current maximum interpreter stack depth.
+     */
+    public final int getMaximumInterpreterStackDepth()
+    {
+        return maximumInterpreterStackDepth;
+    }
+
+    /**
+     * Sets the maximum stack depth (in terms of number of call frames)
+     * allowed in a single invocation of interpreter. If the set depth would be
+     * exceeded, the interpreter will throw an EvaluatorException in the script.
+     * Defaults to Integer.MAX_VALUE. The setting only has effect for
+     * interpreted functions (those compiled with optimization level set to -1).
+     * As the interpreter doesn't use the Java stack but rather manages its own
+     * stack in the heap memory, a runaway recursion in interpreted code would
+     * eventually consume all available memory and cause OutOfMemoryError
+     * instead of a StackOverflowError limited to only a single thread. This
+     * setting helps prevent such situations.
+     *
+     * @param max the new maximum interpreter stack depth
+     * @throws IllegalStateException if this context's optimization level is not
+     * -1
+     * @throws IllegalArgumentException if the new depth is not at least 1
+     */
+    public final void setMaximumInterpreterStackDepth(int max)
+    {
+        if(sealed) onSealedMutation();
+        if(optimizationLevel != -1) {
+            throw new IllegalStateException("Cannot set maximumInterpreterStackDepth when optimizationLevel != -1");
+        }
+        if(max < 1) {
+            throw new IllegalArgumentException("Cannot set maximumInterpreterStackDepth to less than 1");
+        }
+        maximumInterpreterStackDepth = max;
+    }
+
+    /**
+     * Set the security controller for this context.
+     * <p> SecurityController may only be set if it is currently null
+     * and {@link SecurityController#hasGlobal()} is <tt>false</tt>.
+     * Otherwise a SecurityException is thrown.
+     * @param controller a SecurityController object
+     * @throws SecurityException if there is already a SecurityController
+     *         object for this Context or globally installed.
+     * @see SecurityController#initGlobal(SecurityController controller)
+     * @see SecurityController#hasGlobal()
+     */
+    public final void setSecurityController(SecurityController controller)
+    {
+        if (sealed) onSealedMutation();
+        if (controller == null) throw new IllegalArgumentException();
+        if (securityController != null) {
+            throw new SecurityException("Can not overwrite existing SecurityController object");
+        }
+        if (SecurityController.hasGlobal()) {
+            throw new SecurityException("Can not overwrite existing global SecurityController object");
+        }
+        securityController = controller;
+    }
+
+    /**
+     * Set the LiveConnect access filter for this context.
+     * <p> {@link ClassShutter} may only be set if it is currently null.
+     * Otherwise a SecurityException is thrown.
+     * @param shutter a ClassShutter object
+     * @throws SecurityException if there is already a ClassShutter
+     *         object for this Context
+     */
+    public synchronized final void setClassShutter(ClassShutter shutter)
+    {
+        if (sealed) onSealedMutation();
+        if (shutter == null) throw new IllegalArgumentException();
+        if (hasClassShutter) {
+            throw new SecurityException("Cannot overwrite existing " +
+                                        "ClassShutter object");
+        }
+        classShutter = shutter;
+        hasClassShutter = true;
+    }
+
+    final synchronized ClassShutter getClassShutter()
+    {
+        return classShutter;
+    }
+
+    public interface ClassShutterSetter {
+        public void setClassShutter(ClassShutter shutter);
+        public ClassShutter getClassShutter();
+    }
+
+    public final synchronized ClassShutterSetter getClassShutterSetter() {
+        if (hasClassShutter)
+            return null;
+        hasClassShutter = true;
+        return new ClassShutterSetter() {
+            public void setClassShutter(ClassShutter shutter) {
+                classShutter = shutter;
+            }
+            public ClassShutter getClassShutter() {
+                return classShutter;
+            }
+        };
+    }
+
+    /**
+     * Get a value corresponding to a key.
+     * <p>
+     * Since the Context is associated with a thread it can be
+     * used to maintain values that can be later retrieved using
+     * the current thread.
+     * <p>
+     * Note that the values are maintained with the Context, so
+     * if the Context is disassociated from the thread the values
+     * cannot be retrieved. Also, if private data is to be maintained
+     * in this manner the key should be a java.lang.Object
+     * whose reference is not divulged to untrusted code.
+     * @param key the key used to lookup the value
+     * @return a value previously stored using putThreadLocal.
+     */
+    public final Object getThreadLocal(Object key)
+    {
+        if (threadLocalMap == null)
+            return null;
+        return threadLocalMap.get(key);
+    }
+
+    /**
+     * Put a value that can later be retrieved using a given key.
+     * <p>
+     * @param key the key used to index the value
+     * @param value the value to save
+     */
+    public synchronized final void putThreadLocal(Object key, Object value)
+    {
+        if (sealed) onSealedMutation();
+        if (threadLocalMap == null)
+            threadLocalMap = new HashMap<Object,Object>();
+        threadLocalMap.put(key, value);
+    }
+
+    /**
+     * Remove values from thread-local storage.
+     * @param key the key for the entry to remove.
+     * @since 1.5 release 2
+     */
+    public final void removeThreadLocal(Object key)
+    {
+        if (sealed) onSealedMutation();
+        if (threadLocalMap == null)
+            return;
+        threadLocalMap.remove(key);
+    }
+
+    /**
+     * @deprecated
+     * @see ClassCache#get(Scriptable)
+     * @see ClassCache#setCachingEnabled(boolean)
+     */
+    @Deprecated
+    public static void setCachingEnabled(boolean cachingEnabled)
+    {
+    }
+
+    /**
+     * Set a WrapFactory for this Context.
+     * <p>
+     * The WrapFactory allows custom object wrapping behavior for
+     * Java object manipulated with JavaScript.
+     * @see WrapFactory
+     * @since 1.5 Release 4
+     */
+    public final void setWrapFactory(WrapFactory wrapFactory)
+    {
+        if (sealed) onSealedMutation();
+        if (wrapFactory == null) throw new IllegalArgumentException();
+        this.wrapFactory = wrapFactory;
+    }
+
+    /**
+     * Return the current WrapFactory, or null if none is defined.
+     * @see WrapFactory
+     * @since 1.5 Release 4
+     */
+    public final WrapFactory getWrapFactory()
+    {
+        if (wrapFactory == null) {
+            wrapFactory = new WrapFactory();
+        }
+        return wrapFactory;
+    }
+
+    /**
+     * Return the current debugger.
+     * @return the debugger, or null if none is attached.
+     */
+    public final Debugger getDebugger()
+    {
+        return debugger;
+    }
+
+    /**
+     * Return the debugger context data associated with current context.
+     * @return the debugger data, or null if debugger is not attached
+     */
+    public final Object getDebuggerContextData()
+    {
+        return debuggerData;
+    }
+
+    /**
+     * Set the associated debugger.
+     * @param debugger the debugger to be used on callbacks from
+     * the engine.
+     * @param contextData arbitrary object that debugger can use to store
+     *        per Context data.
+     */
+    public final void setDebugger(Debugger debugger, Object contextData)
+    {
+        if (sealed) onSealedMutation();
+        this.debugger = debugger;
+        debuggerData = contextData;
+    }
+
+    /**
+     * Return DebuggableScript instance if any associated with the script.
+     * If callable supports DebuggableScript implementation, the method
+     * returns it. Otherwise null is returned.
+     */
+    public static DebuggableScript getDebuggableView(Script script)
+    {
+        if (script instanceof NativeFunction) {
+            return ((NativeFunction)script).getDebuggableView();
+        }
+        return null;
+    }
+
+    /**
+     * Controls certain aspects of script semantics.
+     * Should be overwritten to alter default behavior.
+     * <p>
+     * The default implementation calls
+     * {@link ContextFactory#hasFeature(Context cx, int featureIndex)}
+     * that allows to customize Context behavior without introducing
+     * Context subclasses.  {@link ContextFactory} documentation gives
+     * an example of hasFeature implementation.
+     *
+     * @param featureIndex feature index to check
+     * @return true if the <code>featureIndex</code> feature is turned on
+     * @see #FEATURE_NON_ECMA_GET_YEAR
+     * @see #FEATURE_MEMBER_EXPR_AS_FUNCTION_NAME
+     * @see #FEATURE_RESERVED_KEYWORD_AS_IDENTIFIER
+     * @see #FEATURE_TO_STRING_AS_SOURCE
+     * @see #FEATURE_PARENT_PROTO_PROPRTIES
+     * @see #FEATURE_E4X
+     * @see #FEATURE_DYNAMIC_SCOPE
+     * @see #FEATURE_STRICT_VARS
+     * @see #FEATURE_STRICT_EVAL
+     * @see #FEATURE_LOCATION_INFORMATION_IN_ERROR
+     * @see #FEATURE_STRICT_MODE
+     * @see #FEATURE_WARNING_AS_ERROR
+     * @see #FEATURE_ENHANCED_JAVA_ACCESS
+     */
+    public boolean hasFeature(int featureIndex)
+    {
+        ContextFactory f = getFactory();
+        return f.hasFeature(this, featureIndex);
+    }
+
+    /**
+     * Returns an object which specifies an E4X implementation to use within
+     * this <code>Context</code>. Note that the XMLLib.Factory interface should
+     * be considered experimental.
+     *
+     * The default implementation uses the implementation provided by this
+     * <code>Context</code>'s {@link ContextFactory}.
+     *
+     * @return An XMLLib.Factory. Should not return <code>null</code> if
+     *         {@link #FEATURE_E4X} is enabled. See {@link #hasFeature}.
+     */
+    public XMLLib.Factory getE4xImplementationFactory() {
+        return getFactory().getE4xImplementationFactory();
+    }
+
+    /**
+     * Get threshold of executed instructions counter that triggers call to
+     * <code>observeInstructionCount()</code>.
+     * When the threshold is zero, instruction counting is disabled,
+     * otherwise each time the run-time executes at least the threshold value
+     * of script instructions, <code>observeInstructionCount()</code> will
+     * be called.
+     */
+    public final int getInstructionObserverThreshold()
+    {
+        return instructionThreshold;
+    }
+
+    /**
+     * Set threshold of executed instructions counter that triggers call to
+     * <code>observeInstructionCount()</code>.
+     * When the threshold is zero, instruction counting is disabled,
+     * otherwise each time the run-time executes at least the threshold value
+     * of script instructions, <code>observeInstructionCount()</code> will
+     * be called.<p/>
+     * Note that the meaning of "instruction" is not guaranteed to be
+     * consistent between compiled and interpretive modes: executing a given
+     * script or function in the different modes will result in different
+     * instruction counts against the threshold.
+     * {@link #setGenerateObserverCount} is called with true if
+     * <code>threshold</code> is greater than zero, false otherwise.
+     * @param threshold The instruction threshold
+     */
+    public final void setInstructionObserverThreshold(int threshold)
+    {
+        if (sealed) onSealedMutation();
+        if (threshold < 0) throw new IllegalArgumentException();
+        instructionThreshold = threshold;
+        setGenerateObserverCount(threshold > 0);
+    }
+
+    /**
+     * Turn on or off generation of code with callbacks to
+     * track the count of executed instructions.
+     * Currently only affects JVM byte code generation: this slows down the
+     * generated code, but code generated without the callbacks will not
+     * be counted toward instruction thresholds. Rhino's interpretive
+     * mode does instruction counting without inserting callbacks, so
+     * there is no requirement to compile code differently.
+     * @param generateObserverCount if true, generated code will contain
+     * calls to accumulate an estimate of the instructions executed.
+     */
+    public void setGenerateObserverCount(boolean generateObserverCount) {
+        this.generateObserverCount = generateObserverCount;
+    }
+
+    /**
+     * Allow application to monitor counter of executed script instructions
+     * in Context subclasses.
+     * Run-time calls this when instruction counting is enabled and the counter
+     * reaches limit set by <code>setInstructionObserverThreshold()</code>.
+     * The method is useful to observe long running scripts and if necessary
+     * to terminate them.
+     * <p>
+     * The default implementation calls
+     * {@link ContextFactory#observeInstructionCount(Context cx,
+     *                                               int instructionCount)}
+     * that allows to customize Context behavior without introducing
+     * Context subclasses.
+     *
+     * @param instructionCount amount of script instruction executed since
+     * last call to <code>observeInstructionCount</code>
+     * @throws Error to terminate the script
+     * @see #setOptimizationLevel(int)
+     */
+    protected void observeInstructionCount(int instructionCount)
+    {
+        ContextFactory f = getFactory();
+        f.observeInstructionCount(this, instructionCount);
+    }
+
+    /**
+     * Create class loader for generated classes.
+     * The method calls {@link ContextFactory#createClassLoader(ClassLoader)}
+     * using the result of {@link #getFactory()}.
+     */
+    public GeneratedClassLoader createClassLoader(ClassLoader parent)
+    {
+        ContextFactory f = getFactory();
+        return f.createClassLoader(parent);
+    }
+
+    public final ClassLoader getApplicationClassLoader()
+    {
+        if (applicationClassLoader == null) {
+            ContextFactory f = getFactory();
+            ClassLoader loader = f.getApplicationClassLoader();
+            if (loader == null) {
+                ClassLoader threadLoader
+                    = VMBridge.instance.getCurrentThreadClassLoader();
+                if (threadLoader != null
+                    && Kit.testIfCanLoadRhinoClasses(threadLoader))
+                {
+                    // Thread.getContextClassLoader is not cached since
+                    // its caching prevents it from GC which may lead to
+                    // a memory leak and hides updates to
+                    // Thread.getContextClassLoader
+                    return threadLoader;
+                }
+                // Thread.getContextClassLoader can not load Rhino classes,
+                // try to use the loader of ContextFactory or Context
+                // subclasses.
+                Class<?> fClass = f.getClass();
+                if (fClass != ScriptRuntime.ContextFactoryClass) {
+                    loader = fClass.getClassLoader();
+                } else {
+                    loader = getClass().getClassLoader();
+                }
+            }
+            applicationClassLoader = loader;
+        }
+        return applicationClassLoader;
+    }
+
+    public final void setApplicationClassLoader(ClassLoader loader)
+    {
+        if (sealed) onSealedMutation();
+        if (loader == null) {
+            // restore default behaviour
+            applicationClassLoader = null;
+            return;
+        }
+        if (!Kit.testIfCanLoadRhinoClasses(loader)) {
+            throw new IllegalArgumentException(
+                "Loader can not resolve Rhino classes");
+        }
+        applicationClassLoader = loader;
+    }
+
+    /********** end of API **********/
+
+    /**
+     * Internal method that reports an error for missing calls to
+     * enter().
+     */
+    static Context getContext()
+    {
+        Context cx = getCurrentContext();
+        if (cx == null) {
+            throw new RuntimeException(
+                "No Context associated with current Thread");
+        }
+        return cx;
+    }
+
+    private Object compileImpl(Scriptable scope,
+                               Reader sourceReader, String sourceString,
+                               String sourceName, int lineno,
+                               Object securityDomain, boolean returnFunction,
+                               Evaluator compiler,
+                               ErrorReporter compilationErrorReporter)
+        throws IOException
+    {
+        if(sourceName == null) {
+            sourceName = "unnamed script";
+        }
+        if (securityDomain != null && getSecurityController() == null) {
+            throw new IllegalArgumentException(
+                "securityDomain should be null if setSecurityController() was never called");
+        }
+
+        // One of sourceReader or sourceString has to be null
+        if (!(sourceReader == null ^ sourceString == null)) Kit.codeBug();
+        // scope should be given if and only if compiling function
+        if (!(scope == null ^ returnFunction)) Kit.codeBug();
+
+        CompilerEnvirons compilerEnv = new CompilerEnvirons();
+        compilerEnv.initFromContext(this);
+        if (compilationErrorReporter == null) {
+            compilationErrorReporter = compilerEnv.getErrorReporter();
+        }
+
+        if (debugger != null) {
+            if (sourceReader != null) {
+                sourceString = Kit.readReader(sourceReader);
+                sourceReader = null;
+            }
+        }
+
+        Parser p = new Parser(compilerEnv, compilationErrorReporter);
+        if (returnFunction) {
+            p.calledByCompileFunction = true;
+        }
+        if (isStrictMode()) {
+            p.setDefaultUseStrictDirective(true);
+        }
+        AstRoot ast;
+        if (sourceString != null) {
+            ast = p.parse(sourceString, sourceName, lineno);
+        } else {
+            ast = p.parse(sourceReader, sourceName, lineno);
+        }
+        if (returnFunction) {
+            // parser no longer adds function to script node
+            if (!(ast.getFirstChild() != null
+                  && ast.getFirstChild().getType() == Token.FUNCTION))
+            {
+                // XXX: the check just looks for the first child
+                // and allows for more nodes after it for compatibility
+                // with sources like function() {};;;
+                throw new IllegalArgumentException(
+                    "compileFunction only accepts source with single JS function: "+sourceString);
+            }
+        }
+
+        IRFactory irf = new IRFactory(compilerEnv, compilationErrorReporter);
+        ScriptNode tree = irf.transformTree(ast);
+
+        // discard everything but the IR tree
+        p = null;
+        ast = null;
+        irf = null;
+
+        if (compiler == null) {
+            compiler = createCompiler();
+        }
+
+        Object bytecode = compiler.compile(compilerEnv,
+                                           tree, tree.getEncodedSource(),
+                                           returnFunction);
+        if (debugger != null) {
+            if (sourceString == null) Kit.codeBug();
+            if (bytecode instanceof DebuggableScript) {
+                DebuggableScript dscript = (DebuggableScript)bytecode;
+                notifyDebugger_r(this, dscript, sourceString);
+            } else {
+                throw new RuntimeException("NOT SUPPORTED");
+            }
+        }
+
+        Object result;
+        if (returnFunction) {
+            result = compiler.createFunctionObject(this, scope, bytecode, securityDomain);
+        } else {
+            result = compiler.createScriptObject(bytecode, securityDomain);
+        }
+
+        return result;
+    }
+
+    private static void notifyDebugger_r(Context cx, DebuggableScript dscript,
+                                         String debugSource)
+    {
+        cx.debugger.handleCompilationDone(cx, dscript, debugSource);
+        for (int i = 0; i != dscript.getFunctionCount(); ++i) {
+            notifyDebugger_r(cx, dscript.getFunction(i), debugSource);
+        }
+    }
+
+    private static Class<?> codegenClass = Kit.classOrNull(
+                             "org.mozilla.javascript.optimizer.Codegen");
+    private static Class<?> interpreterClass = Kit.classOrNull(
+                             "org.mozilla.javascript.Interpreter");
+
+    private Evaluator createCompiler()
+    {
+        Evaluator result = null;
+        if (optimizationLevel >= 0 && codegenClass != null) {
+            result = (Evaluator)Kit.newInstanceOrNull(codegenClass);
+        }
+        if (result == null) {
+            result = createInterpreter();
+        }
+        return result;
+    }
+
+    static Evaluator createInterpreter()
+    {
+        return (Evaluator)Kit.newInstanceOrNull(interpreterClass);
+    }
+
+    static String getSourcePositionFromStack(int[] linep)
+    {
+        Context cx = getCurrentContext();
+        if (cx == null)
+            return null;
+        if (cx.lastInterpreterFrame != null) {
+            Evaluator evaluator = createInterpreter();
+            if (evaluator != null)
+                return evaluator.getSourcePositionFromStack(cx, linep);
+        }
+        /**
+         * A bit of a hack, but the only way to get filename and line
+         * number from an enclosing frame.
+         */
+        StackTraceElement[] stackTrace = new Throwable().getStackTrace();
+        for (StackTraceElement st : stackTrace) {
+            String file = st.getFileName();
+            if (!(file == null || file.endsWith(".java"))) {
+                int line = st.getLineNumber();
+                if (line >= 0) {
+                    linep[0] = line;
+                    return file;
+                }
+            }
+        }
+
+        return null;
+    }
+
+    RegExpProxy getRegExpProxy()
+    {
+        if (regExpProxy == null) {
+            Class<?> cl = Kit.classOrNull(
+                          "org.mozilla.javascript.regexp.RegExpImpl");
+            if (cl != null) {
+                regExpProxy = (RegExpProxy)Kit.newInstanceOrNull(cl);
+            }
+        }
+        return regExpProxy;
+    }
+
+    final boolean isVersionECMA1()
+    {
+        return version == VERSION_DEFAULT || version >= VERSION_1_3;
+    }
+
+// The method must NOT be public or protected
+    SecurityController getSecurityController()
+    {
+        SecurityController global = SecurityController.global();
+        if (global != null) {
+            return global;
+        }
+        return securityController;
+    }
+
+    public final boolean isGeneratingDebugChanged()
+    {
+        return generatingDebugChanged;
+    }
+
+    /**
+     * Add a name to the list of names forcing the creation of real
+     * activation objects for functions.
+     *
+     * @param name the name of the object to add to the list
+     */
+    public void addActivationName(String name)
+    {
+        if (sealed) onSealedMutation();
+        if (activationNames == null)
+            activationNames = new HashSet<String>();
+        activationNames.add(name);
+    }
+
+    /**
+     * Check whether the name is in the list of names of objects
+     * forcing the creation of activation objects.
+     *
+     * @param name the name of the object to test
+     *
+     * @return true if an function activation object is needed.
+     */
+    public final boolean isActivationNeeded(String name)
+    {
+        return activationNames != null && activationNames.contains(name);
+    }
+
+    /**
+     * Remove a name from the list of names forcing the creation of real
+     * activation objects for functions.
+     *
+     * @param name the name of the object to remove from the list
+     */
+    public void removeActivationName(String name)
+    {
+        if (sealed) onSealedMutation();
+        if (activationNames != null)
+            activationNames.remove(name);
+    }
+
+    public final boolean isStrictMode() {
+        return isTopLevelStrict || (currentActivationCall != null && currentActivationCall.isStrict);
+    }
+
+    private static String implementationVersion;
+
+    private final ContextFactory factory;
+    private boolean sealed;
+    private Object sealKey;
+
+    Scriptable topCallScope;
+    boolean isContinuationsTopCall;
+    NativeCall currentActivationCall;
+    XMLLib cachedXMLLib;
+    BaseFunction typeErrorThrower;
+
+    // for Objects, Arrays to tag themselves as being printed out,
+    // so they don't print themselves out recursively.
+    // Use ObjToIntMap instead of java.util.HashSet for JDK 1.1 compatibility
+    ObjToIntMap iterating;
+
+    Object interpreterSecurityDomain;
+
+    int version;
+
+    private SecurityController securityController;
+    private boolean hasClassShutter;
+    private ClassShutter classShutter;
+    private ErrorReporter errorReporter;
+    RegExpProxy regExpProxy;
+    private Locale locale;
+    private boolean generatingDebug;
+    private boolean generatingDebugChanged;
+    private boolean generatingSource=true;
+    boolean useDynamicScope;
+    private int optimizationLevel;
+    private int maximumInterpreterStackDepth;
+    private WrapFactory wrapFactory;
+    Debugger debugger;
+    private Object debuggerData;
+    private int enterCount;
+    private Object propertyListeners;
+    private Map<Object,Object> threadLocalMap;
+    private ClassLoader applicationClassLoader;
+
+    /**
+     * This is the list of names of objects forcing the creation of
+     * function activation records.
+     */
+    Set<String> activationNames;
+
+    // For the interpreter to store the last frame for error reports etc.
+    Object lastInterpreterFrame;
+
+    // For the interpreter to store information about previous invocations
+    // interpreter invocations
+    ObjArray previousInterpreterInvocations;
+
+    // For instruction counting (interpreter only)
+    int instructionCount;
+    int instructionThreshold;
+
+    // It can be used to return the second index-like result from function
+    int scratchIndex;
+
+    // It can be used to return the second uint32 result from function
+    long scratchUint32;
+
+    // It can be used to return the second Scriptable result from function
+    Scriptable scratchScriptable;
+
+    // Generate an observer count on compiled code
+    public boolean generateObserverCount = false;
+
+    boolean isTopLevelStrict;
+}
diff -pruN 20130227+dfsg1-14/rhino/src/org/mozilla/javascript/ContextAction.java 20130227+rhino-1/rhino/src/org/mozilla/javascript/ContextAction.java
--- 20130227+dfsg1-14/rhino/src/org/mozilla/javascript/ContextAction.java	1970-01-01 00:00:00.000000000 +0000
+++ 20130227+rhino-1/rhino/src/org/mozilla/javascript/ContextAction.java	2023-05-25 14:24:50.000000000 +0000
@@ -0,0 +1,26 @@
+/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// API class
+
+package org.mozilla.javascript;
+
+/**
+ * Interface to represent arbitrary action that requires to have Context
+ * object associated with the current thread for its execution.
+ */
+public interface ContextAction
+{
+    /**
+     * Execute action using the supplied Context instance.
+     * When Rhino runtime calls the method, <tt>cx</tt> will be associated
+     * with the current thread as active context.
+     *
+     * @see ContextFactory#call(ContextAction)
+     */
+    public Object run(Context cx);
+}
+
diff -pruN 20130227+dfsg1-14/rhino/src/org/mozilla/javascript/ContextFactory.java 20130227+rhino-1/rhino/src/org/mozilla/javascript/ContextFactory.java
--- 20130227+dfsg1-14/rhino/src/org/mozilla/javascript/ContextFactory.java	1970-01-01 00:00:00.000000000 +0000
+++ 20130227+rhino-1/rhino/src/org/mozilla/javascript/ContextFactory.java	2023-05-25 14:24:50.000000000 +0000
@@ -0,0 +1,594 @@
+/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// API class
+
+package org.mozilla.javascript;
+
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+
+/**
+ * Factory class that Rhino runtime uses to create new {@link Context}
+ * instances.  A <code>ContextFactory</code> can also notify listeners
+ * about context creation and release.
+ * <p>
+ * When the Rhino runtime needs to create new {@link Context} instance during
+ * execution of {@link Context#enter()} or {@link Context}, it will call
+ * {@link #makeContext()} of the current global ContextFactory.
+ * See {@link #getGlobal()} and {@link #initGlobal(ContextFactory)}.
+ * <p>
+ * It is also possible to use explicit ContextFactory instances for Context
+ * creation. This is useful to have a set of independent Rhino runtime
+ * instances under single JVM. See {@link #call(ContextAction)}.
+ * <p>
+ * The following example demonstrates Context customization to terminate
+ * scripts running more then 10 seconds and to provide better compatibility
+ * with JavaScript code using MSIE-specific features.
+ * <pre>
+ * import org.mozilla.javascript.*;
+ *
+ * class MyFactory extends ContextFactory
+ * {
+ *
+ *     // Custom {@link Context} to store execution time.
+ *     private static class MyContext extends Context
+ *     {
+ *         long startTime;
+ *     }
+ *
+ *     static {
+ *         // Initialize GlobalFactory with custom factory
+ *         ContextFactory.initGlobal(new MyFactory());
+ *     }
+ *
+ *     // Override {@link #makeContext()}
+ *     protected Context makeContext()
+ *     {
+ *         MyContext cx = new MyContext();
+ *         // Make Rhino runtime to call observeInstructionCount
+ *         // each 10000 bytecode instructions
+ *         cx.setInstructionObserverThreshold(10000);
+ *         return cx;
+ *     }
+ *
+ *     // Override {@link #hasFeature(Context, int)}
+ *     public boolean hasFeature(Context cx, int featureIndex)
+ *     {
+ *         // Turn on maximum compatibility with MSIE scripts
+ *         switch (featureIndex) {
+ *             case {@link Context#FEATURE_NON_ECMA_GET_YEAR}:
+ *                 return true;
+ *
+ *             case {@link Context#FEATURE_MEMBER_EXPR_AS_FUNCTION_NAME}:
+ *                 return true;
+ *
+ *             case {@link Context#FEATURE_RESERVED_KEYWORD_AS_IDENTIFIER}:
+ *                 return true;
+ *
+ *             case {@link Context#FEATURE_PARENT_PROTO_PROPERTIES}:
+ *                 return false;
+ *         }
+ *         return super.hasFeature(cx, featureIndex);
+ *     }
+ *
+ *     // Override {@link #observeInstructionCount(Context, int)}
+ *     protected void observeInstructionCount(Context cx, int instructionCount)
+ *     {
+ *         MyContext mcx = (MyContext)cx;
+ *         long currentTime = System.currentTimeMillis();
+ *         if (currentTime - mcx.startTime > 10*1000) {
+ *             // More then 10 seconds from Context creation time:
+ *             // it is time to stop the script.
+ *             // Throw Error instance to ensure that script will never
+ *             // get control back through catch or finally.
+ *             throw new Error();
+ *         }
+ *     }
+ *
+ *     // Override {@link #doTopCall(Callable,
+                               Context, Scriptable,
+                               Scriptable, Object[])}
+ *     protected Object doTopCall(Callable callable,
+ *                                Context cx, Scriptable scope,
+ *                                Scriptable thisObj, Object[] args)
+ *     {
+ *         MyContext mcx = (MyContext)cx;
+ *         mcx.startTime = System.currentTimeMillis();
+ *
+ *         return super.doTopCall(callable, cx, scope, thisObj, args);
+ *     }
+ *
+ * }
+ *
+ * </pre>
+ */
+
+public class ContextFactory
+{
+    private static volatile boolean hasCustomGlobal;
+    private static ContextFactory global = new ContextFactory();
+
+    private volatile boolean sealed;
+
+    private final Object listenersLock = new Object();
+    private volatile Object listeners;
+    private boolean disabledListening;
+    private ClassLoader applicationClassLoader;
+
+    /**
+     * Listener of {@link Context} creation and release events.
+     */
+    public interface Listener
+    {
+        /**
+         * Notify about newly created {@link Context} object.
+         */
+        public void contextCreated(Context cx);
+
+        /**
+         * Notify that the specified {@link Context} instance is no longer
+         * associated with the current thread.
+         */
+        public void contextReleased(Context cx);
+    }
+
+    /**
+     * Get global ContextFactory.
+     *
+     * @see #hasExplicitGlobal()
+     * @see #initGlobal(ContextFactory)
+     */
+    public static ContextFactory getGlobal()
+    {
+        return global;
+    }
+
+    /**
+     * Check if global factory was set.
+     * Return true to indicate that {@link #initGlobal(ContextFactory)} was
+     * already called and false to indicate that the global factory was not
+     * explicitly set.
+     *
+     * @see #getGlobal()
+     * @see #initGlobal(ContextFactory)
+     */
+    public static boolean hasExplicitGlobal()
+    {
+        return hasCustomGlobal;
+    }
+
+    /**
+     * Set global ContextFactory.
+     * The method can only be called once.
+     *
+     * @see #getGlobal()
+     * @see #hasExplicitGlobal()
+     */
+    public synchronized static void initGlobal(ContextFactory factory)
+    {
+        if (factory == null) {
+            throw new IllegalArgumentException();
+        }
+        if (hasCustomGlobal) {
+            throw new IllegalStateException();
+        }
+        hasCustomGlobal = true;
+        global = factory;
+    }
+
+    public interface GlobalSetter {
+        public void setContextFactoryGlobal(ContextFactory factory);
+        public ContextFactory getContextFactoryGlobal();
+    }
+
+    public synchronized static GlobalSetter getGlobalSetter() {
+        if (hasCustomGlobal) {
+            throw new IllegalStateException();
+        }
+        hasCustomGlobal = true;
+        class GlobalSetterImpl implements GlobalSetter {
+            public void setContextFactoryGlobal(ContextFactory factory) {
+                global = factory == null ? new ContextFactory() : factory;
+            }
+            public ContextFactory getContextFactoryGlobal() {
+                return global;
+            }
+        }
+        return new GlobalSetterImpl();
+    }
+
+    /**
+     * Create new {@link Context} instance to be associated with the current
+     * thread.
+     * This is a callback method used by Rhino to create {@link Context}
+     * instance when it is necessary to associate one with the current
+     * execution thread. <tt>makeContext()</tt> is allowed to call
+     * {@link Context#seal(Object)} on the result to prevent
+     * {@link Context} changes by hostile scripts or applets.
+     */
+    protected Context makeContext()
+    {
+        return new Context(this);
+    }
+
+    /**
+     * Implementation of {@link Context#hasFeature(int featureIndex)}.
+     * This can be used to customize {@link Context} without introducing
+     * additional subclasses.
+     */
+    protected boolean hasFeature(Context cx, int featureIndex)
+    {
+        int version;
+        switch (featureIndex) {
+          case Context.FEATURE_NON_ECMA_GET_YEAR:
+           /*
+            * During the great date rewrite of 1.3, we tried to track the
+            * evolving ECMA standard, which then had a definition of
+            * getYear which always subtracted 1900.  Which we
+            * implemented, not realizing that it was incompatible with
+            * the old behavior...  now, rather than thrash the behavior
+            * yet again, we've decided to leave it with the - 1900
+            * behavior and point people to the getFullYear method.  But
+            * we try to protect existing scripts that have specified a
+            * version...
+            */
+            version = cx.getLanguageVersion();
+            return (version == Context.VERSION_1_0
+                    || version == Context.VERSION_1_1
+                    || version == Context.VERSION_1_2);
+
+          case Context.FEATURE_MEMBER_EXPR_AS_FUNCTION_NAME:
+            return false;
+
+          case Context.FEATURE_RESERVED_KEYWORD_AS_IDENTIFIER:
+            return true;
+
+          case Context.FEATURE_TO_STRING_AS_SOURCE:
+            version = cx.getLanguageVersion();
+            return version == Context.VERSION_1_2;
+
+          case Context.FEATURE_PARENT_PROTO_PROPERTIES:
+            return true;
+
+          case Context.FEATURE_E4X:
+            version = cx.getLanguageVersion();
+            return (version == Context.VERSION_DEFAULT
+                    || version >= Context.VERSION_1_6);
+
+          case Context.FEATURE_DYNAMIC_SCOPE:
+            return false;
+
+          case Context.FEATURE_STRICT_VARS:
+            return false;
+
+          case Context.FEATURE_STRICT_EVAL:
+            return false;
+
+          case Context.FEATURE_LOCATION_INFORMATION_IN_ERROR:
+            return false;
+
+          case Context.FEATURE_STRICT_MODE:
+            return false;
+
+          case Context.FEATURE_WARNING_AS_ERROR:
+            return false;
+
+          case Context.FEATURE_ENHANCED_JAVA_ACCESS:
+            return false;
+
+          case Context.FEATURE_V8_EXTENSIONS:
+            return true;
+
+          case Context.FEATURE_OLD_UNDEF_NULL_THIS:
+              return cx.getLanguageVersion() <= Context.VERSION_1_7;
+
+          case Context.FEATURE_ENUMERATE_IDS_FIRST:
+              return cx.getLanguageVersion() >= Context.VERSION_ES6;
+        }
+        // It is a bug to call the method with unknown featureIndex
+        throw new IllegalArgumentException(String.valueOf(featureIndex));
+    }
+
+    private boolean isDom3Present() {
+        Class<?> nodeClass = Kit.classOrNull("org.w3c.dom.Node");
+        if (nodeClass == null) return false;
+        // Check to see whether DOM3 is present; use a new method defined in
+        // DOM3 that is vital to our implementation
+        try {
+            nodeClass.getMethod("getUserData", new Class<?>[] { String.class });
+            return true;
+        } catch (NoSuchMethodException e) {
+            return false;
+        }
+    }
+
+    /**
+     * Provides a default
+     * {@link org.mozilla.javascript.xml.XMLLib.Factory XMLLib.Factory}
+     * to be used by the <code>Context</code> instances produced by this
+     * factory. See {@link Context#getE4xImplementationFactory} for details.
+     *
+     * May return null, in which case E4X functionality is not supported in
+     * Rhino.
+     *
+     * The default implementation now prefers the DOM3 E4X implementation.
+     */
+    protected org.mozilla.javascript.xml.XMLLib.Factory
+        getE4xImplementationFactory()
+    {
+        // Must provide default implementation, rather than abstract method,
+        // so that past implementors of ContextFactory do not fail at runtime
+        // upon invocation of this method.
+        // Note that the default implementation returns null if we
+        // neither have XMLBeans nor a DOM3 implementation present.
+
+        if (isDom3Present()) {
+            return org.mozilla.javascript.xml.XMLLib.Factory.create(
+                "org.mozilla.javascript.xmlimpl.XMLLibImpl"
+            );
+        } else {
+            return null;
+        }
+    }
+
+
+    /**
+     * Create class loader for generated classes.
+     * This method creates an instance of the default implementation
+     * of {@link GeneratedClassLoader}. Rhino uses this interface to load
+     * generated JVM classes when no {@link SecurityController}
+     * is installed.
+     * Application can override the method to provide custom class loading.
+     */
+    protected GeneratedClassLoader createClassLoader(final ClassLoader parent)
+    {
+        return AccessController.doPrivileged(new PrivilegedAction<DefiningClassLoader>() {
+            public DefiningClassLoader run(){
+                return new DefiningClassLoader(parent);
+            }
+        });
+    }
+
+    /**
+     * Get ClassLoader to use when searching for Java classes.
+     * Unless it was explicitly initialized with
+     * {@link #initApplicationClassLoader(ClassLoader)} the method returns
+     * null to indicate that Thread.getContextClassLoader() should be used.
+     */
+    public final ClassLoader getApplicationClassLoader()
+    {
+        return applicationClassLoader;
+    }
+
+    /**
+     * Set explicit class loader to use when searching for Java classes.
+     *
+     * @see #getApplicationClassLoader()
+     */
+    public final void initApplicationClassLoader(ClassLoader loader)
+    {
+        if (loader == null)
+            throw new IllegalArgumentException("loader is null");
+        if (!Kit.testIfCanLoadRhinoClasses(loader))
+            throw new IllegalArgumentException(
+                "Loader can not resolve Rhino classes");
+
+        if (this.applicationClassLoader != null)
+            throw new IllegalStateException(
+                "applicationClassLoader can only be set once");
+        checkNotSealed();
+
+        this.applicationClassLoader = loader;
+    }
+
+    /**
+     * Execute top call to script or function.
+     * When the runtime is about to execute a script or function that will
+     * create the first stack frame with scriptable code, it calls this method
+     * to perform the real call. In this way execution of any script
+     * happens inside this function.
+     */
+    protected Object doTopCall(Callable callable,
+                               Context cx, Scriptable scope,
+                               Scriptable thisObj, Object[] args)
+    {
+        Object result = callable.call(cx, scope, thisObj, args);
+        return result instanceof ConsString ? result.toString() : result;
+    }
+
+    /**
+     * Implementation of
+     * {@link Context#observeInstructionCount(int instructionCount)}.
+     * This can be used to customize {@link Context} without introducing
+     * additional subclasses.
+     */
+    protected void observeInstructionCount(Context cx, int instructionCount) {
+    }
+
+    protected void onContextCreated(Context cx)
+    {
+        Object listeners = this.listeners;
+        for (int i = 0; ; ++i) {
+            Listener l = (Listener)Kit.getListener(listeners, i);
+            if (l == null)
+                break;
+            l.contextCreated(cx);
+        }
+    }
+
+    protected void onContextReleased(Context cx)
+    {
+        Object listeners = this.listeners;
+        for (int i = 0; ; ++i) {
+            Listener l = (Listener)Kit.getListener(listeners, i);
+            if (l == null)
+                break;
+            l.contextReleased(cx);
+        }
+    }
+
+    public final void addListener(Listener listener)
+    {
+        checkNotSealed();
+        synchronized (listenersLock) {
+            if (disabledListening) {
+                throw new IllegalStateException();
+            }
+            listeners = Kit.addListener(listeners, listener);
+        }
+    }
+
+    public final void removeListener(Listener listener)
+    {
+        checkNotSealed();
+        synchronized (listenersLock) {
+            if (disabledListening) {
+                throw new IllegalStateException();
+            }
+            listeners = Kit.removeListener(listeners, listener);
+        }
+    }
+
+    /**
+     * The method is used only to implement
+     * Context.disableStaticContextListening()
+     */
+    final void disableContextListening()
+    {
+        checkNotSealed();
+        synchronized (listenersLock) {
+            disabledListening = true;
+            listeners = null;
+        }
+    }
+
+    /**
+     * Checks if this is a sealed ContextFactory.
+     * @see #seal()
+     */
+    public final boolean isSealed()
+    {
+        return sealed;
+    }
+
+    /**
+     * Seal this ContextFactory so any attempt to modify it like to add or
+     * remove its listeners will throw an exception.
+     * @see #isSealed()
+     */
+    public final void seal()
+    {
+        checkNotSealed();
+        sealed = true;
+    }
+
+    protected final void checkNotSealed()
+    {
+        if (sealed) throw new IllegalStateException();
+    }
+
+    /**
+     * Call {@link ContextAction#run(Context cx)}
+     * using the {@link Context} instance associated with the current thread.
+     * If no Context is associated with the thread, then
+     * {@link #makeContext()} will be called to construct
+     * new Context instance. The instance will be temporary associated
+     * with the thread during call to {@link ContextAction#run(Context)}.
+     *
+     * @see ContextFactory#call(ContextAction)
+     * @see Context#call(ContextFactory factory, Callable callable,
+     *                   Scriptable scope, Scriptable thisObj,
+     *                   Object[] args)
+     */
+    public final Object call(ContextAction action)
+    {
+        return Context.call(this, action);
+    }
+
+    /**
+     * Get a context associated with the current thread, creating one if need
+     * be. The Context stores the execution state of the JavaScript engine, so
+     * it is required that the context be entered before execution may begin.
+     * Once a thread has entered a Context, then getCurrentContext() may be
+     * called to find the context that is associated with the current thread.
+     * <p>
+     * Calling <code>enterContext()</code> will return either the Context
+     * currently associated with the thread, or will create a new context and
+     * associate it with the current thread. Each call to
+     * <code>enterContext()</code> must have a matching call to
+     * {@link Context#exit()}.
+     * <pre>
+     *      Context cx = contextFactory.enterContext();
+     *      try {
+     *          ...
+     *          cx.evaluateString(...);
+     *      } finally {
+     *          Context.exit();
+     *      }
+     * </pre>
+     * Instead of using <tt>enterContext()</tt>, <tt>exit()</tt> pair consider
+     * using {@link #call(ContextAction)} which guarantees proper association
+     * of Context instances with the current thread.
+     * With this method the above example becomes:
+     * <pre>
+     *      ContextFactory.call(new ContextAction() {
+     *          public Object run(Context cx) {
+     *              ...
+     *              cx.evaluateString(...);
+     *              return null;
+     *          }
+     *      });
+     * </pre>
+     * @return a Context associated with the current thread
+     * @see Context#getCurrentContext()
+     * @see Context#exit()
+     * @see #call(ContextAction)
+     */
+    public Context enterContext()
+    {
+        return enterContext(null);
+    }
+
+    /**
+     * @deprecated use {@link #enterContext()} instead
+     * @return a Context associated with the current thread
+     */
+    @Deprecated
+    public final Context enter()
+    {
+        return enterContext(null);
+    }
+
+    /**
+     * @deprecated Use {@link Context#exit()} instead.
+     */
+    @Deprecated
+    public final void exit()
+    {
+        Context.exit();
+    }
+
+    /**
+     * Get a Context associated with the current thread, using the given
+     * Context if need be.
+     * <p>
+     * The same as <code>enterContext()</code> except that <code>cx</code>
+     * is associated with the current thread and returned if the current thread
+     * has no associated context and <code>cx</code> is not associated with any
+     * other thread.
+     * @param cx a Context to associate with the thread if possible
+     * @return a Context associated with the current thread
+     * @see #enterContext()
+     * @see #call(ContextAction)
+     * @throws IllegalStateException if <code>cx</code> is already associated
+     * with a different thread
+     */
+    public final Context enterContext(Context cx)
+    {
+        return Context.enter(cx, this);
+    }
+}
\ No newline at end of file
diff -pruN 20130227+dfsg1-14/rhino/src/org/mozilla/javascript/ContextListener.java 20130227+rhino-1/rhino/src/org/mozilla/javascript/ContextListener.java
--- 20130227+dfsg1-14/rhino/src/org/mozilla/javascript/ContextListener.java	1970-01-01 00:00:00.000000000 +0000
+++ 20130227+rhino-1/rhino/src/org/mozilla/javascript/ContextListener.java	2023-05-25 14:24:50.000000000 +0000
@@ -0,0 +1,31 @@
+/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// API class
+
+package org.mozilla.javascript;
+
+/**
+ * @deprecated Embeddings that wish to customize newly created
+ * {@link Context} instances should implement
+ * {@link ContextFactory.Listener}.
+ */
+@Deprecated
+public interface ContextListener extends ContextFactory.Listener
+{
+
+    /**
+     * @deprecated Rhino runtime never calls the method.
+     */
+    @Deprecated
+    public void contextEntered(Context cx);
+
+    /**
+     * @deprecated Rhino runtime never calls the method.
+     */
+    @Deprecated
+    public void contextExited(Context cx);
+}
diff -pruN 20130227+dfsg1-14/rhino/src/org/mozilla/javascript/ContinuationPending.java 20130227+rhino-1/rhino/src/org/mozilla/javascript/ContinuationPending.java
--- 20130227+dfsg1-14/rhino/src/org/mozilla/javascript/ContinuationPending.java	1970-01-01 00:00:00.000000000 +0000
+++ 20130227+rhino-1/rhino/src/org/mozilla/javascript/ContinuationPending.java	2023-05-25 14:24:50.000000000 +0000
@@ -0,0 +1,76 @@
+/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+package org.mozilla.javascript;
+
+/**
+ * Exception thrown by
+ * {@link org.mozilla.javascript.Context#executeScriptWithContinuations(Script, Scriptable)}
+ * and {@link org.mozilla.javascript.Context#callFunctionWithContinuations(Callable, Scriptable, Object[])}
+ * when execution encounters a continuation captured by
+ * {@link org.mozilla.javascript.Context#captureContinuation()}.
+ * Exception will contain the captured state needed to restart the continuation
+ * with {@link org.mozilla.javascript.Context#resumeContinuation(Object, Scriptable, Object)}.
+ * @author Norris Boyd
+ */
+public class ContinuationPending extends RuntimeException {
+    private static final long serialVersionUID = 4956008116771118856L;
+    private NativeContinuation continuationState;
+    private Object applicationState;
+
+    /**
+     * Construct a ContinuationPending exception. Internal call only;
+     * users of the API should get continuations created on their behalf by
+     * calling {@link org.mozilla.javascript.Context#executeScriptWithContinuations(Script, Scriptable)}
+     * and {@link org.mozilla.javascript.Context#callFunctionWithContinuations(Callable, Scriptable, Object[])}
+     * Creating subclasses allowed.
+     * @param continuationState Internal Continuation object
+     */
+    protected ContinuationPending(NativeContinuation continuationState) {
+        this.continuationState = continuationState;
+    }
+
+    /**
+     * Get continuation object. The only
+     * use for this object is to be passed to
+     * {@link org.mozilla.javascript.Context#resumeContinuation(Object, Scriptable, Object)}.
+     * @return continuation object
+     */
+    public Object getContinuation() {
+        return continuationState;
+    }
+
+    /**
+     * Set continuation object. Allows subclasses to modify the internal state.
+     * @param continuation object
+     */
+    public void setContinuation(NativeContinuation continuation) {
+        this.continuationState = continuation;
+    }
+    
+    /**
+     * @return internal continuation state
+     */
+    NativeContinuation getContinuationState() {
+        return continuationState;
+    }
+
+    /**
+     * Store an arbitrary object that applications can use to associate
+     * their state with the continuation.
+     * @param applicationState arbitrary application state
+     */
+    public void setApplicationState(Object applicationState) {
+        this.applicationState = applicationState;
+    }
+
+    /**
+     * @return arbitrary application state
+     */
+    public Object getApplicationState() {
+        return applicationState;
+    }
+}
diff -pruN 20130227+dfsg1-14/rhino/src/org/mozilla/javascript/DToA.java 20130227+rhino-1/rhino/src/org/mozilla/javascript/DToA.java
--- 20130227+dfsg1-14/rhino/src/org/mozilla/javascript/DToA.java	1970-01-01 00:00:00.000000000 +0000
+++ 20130227+rhino-1/rhino/src/org/mozilla/javascript/DToA.java	2023-05-25 14:24:50.000000000 +0000
@@ -0,0 +1,1228 @@
+/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/****************************************************************
+  *
+  * The author of this software is David M. Gay.
+  *
+  * Copyright (c) 1991, 2000, 2001 by Lucent Technologies.
+  *
+  * Permission to use, copy, modify, and distribute this software for any
+  * purpose without fee is hereby granted, provided that this entire notice
+  * is included in all copies of any software which is or includes a copy
+  * or modification of this software and in all copies of the supporting
+  * documentation for such software.
+  *
+  * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
+  * WARRANTY.  IN PARTICULAR, NEITHER THE AUTHOR NOR LUCENT MAKES ANY
+  * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
+  * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
+  *
+  ***************************************************************/
+
+package org.mozilla.javascript;
+
+import java.math.BigInteger;
+
+class DToA {
+
+
+    private static char BASEDIGIT(int digit) {
+        return (char)((digit >= 10) ? 'a' - 10 + digit : '0' + digit);
+    }
+
+    static final int
+        DTOSTR_STANDARD = 0,              /* Either fixed or exponential format; round-trip */
+        DTOSTR_STANDARD_EXPONENTIAL = 1,  /* Always exponential format; round-trip */
+        DTOSTR_FIXED = 2,                 /* Round to <precision> digits after the decimal point; exponential if number is large */
+        DTOSTR_EXPONENTIAL = 3,           /* Always exponential format; <precision> significant digits */
+        DTOSTR_PRECISION = 4;             /* Either fixed or exponential format; <precision> significant digits */
+
+
+    private static final int Frac_mask = 0xfffff;
+    private static final int Exp_shift = 20;
+    private static final int Exp_msk1 = 0x100000;
+
+    private static final long Frac_maskL = 0xfffffffffffffL;
+    private static final int Exp_shiftL = 52;
+    private static final long Exp_msk1L = 0x10000000000000L;
+
+    private static final int Bias = 1023;
+    private static final int P = 53;
+
+    private static final int Exp_shift1 = 20;
+    private static final int Exp_mask  = 0x7ff00000;
+    private static final int Exp_mask_shifted = 0x7ff;
+    private static final int Bndry_mask  = 0xfffff;
+    private static final int Log2P = 1;
+
+    private static final int Sign_bit = 0x80000000;
+    private static final int Exp_11  = 0x3ff00000;
+    private static final int Ten_pmax = 22;
+    private static final int Quick_max = 14;
+    private static final int Bletch = 0x10;
+    private static final int Frac_mask1 = 0xfffff;
+    private static final int Int_max = 14;
+    private static final int n_bigtens = 5;
+
+
+    private static final double tens[] = {
+        1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9,
+        1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19,
+        1e20, 1e21, 1e22
+    };
+
+    private static final double bigtens[] = { 1e16, 1e32, 1e64, 1e128, 1e256 };
+
+    private static int lo0bits(int y)
+    {
+        int k;
+        int x = y;
+
+        if ((x & 7) != 0) {
+            if ((x & 1) != 0)
+                return 0;
+            if ((x & 2) != 0) {
+                return 1;
+            }
+            return 2;
+        }
+        k = 0;
+        if ((x & 0xffff) == 0) {
+            k = 16;
+            x >>>= 16;
+        }
+        if ((x & 0xff) == 0) {
+            k += 8;
+            x >>>= 8;
+        }
+        if ((x & 0xf) == 0) {
+            k += 4;
+            x >>>= 4;
+        }
+        if ((x & 0x3) == 0) {
+            k += 2;
+            x >>>= 2;
+        }
+        if ((x & 1) == 0) {
+            k++;
+            x >>>= 1;
+            if ((x & 1) == 0)
+                return 32;
+        }
+        return k;
+    }
+
+    /* Return the number (0 through 32) of most significant zero bits in x. */
+    private static int hi0bits(int x)
+    {
+        int k = 0;
+
+        if ((x & 0xffff0000) == 0) {
+            k = 16;
+            x <<= 16;
+        }
+        if ((x & 0xff000000) == 0) {
+            k += 8;
+            x <<= 8;
+        }
+        if ((x & 0xf0000000) == 0) {
+            k += 4;
+            x <<= 4;
+        }
+        if ((x & 0xc0000000) == 0) {
+            k += 2;
+            x <<= 2;
+        }
+        if ((x & 0x80000000) == 0) {
+            k++;
+            if ((x & 0x40000000) == 0)
+                return 32;
+        }
+        return k;
+    }
+
+    private static void stuffBits(byte bits[], int offset, int val)
+    {
+        bits[offset] = (byte)(val >> 24);
+        bits[offset + 1] = (byte)(val >> 16);
+        bits[offset + 2] = (byte)(val >> 8);
+        bits[offset + 3] = (byte)(val);
+    }
+
+    /* Convert d into the form b*2^e, where b is an odd integer.  b is the returned
+     * Bigint and e is the returned binary exponent.  Return the number of significant
+     * bits in b in bits.  d must be finite and nonzero. */
+    private static BigInteger d2b(double d, int[] e, int[] bits)
+    {
+        byte dbl_bits[];
+        int i, k, y, z, de;
+        long dBits = Double.doubleToLongBits(d);
+        int d0 = (int)(dBits >>> 32);
+        int d1 = (int)(dBits);
+
+        z = d0 & Frac_mask;
+        d0 &= 0x7fffffff;   /* clear sign bit, which we ignore */
+
+        if ((de = (d0 >>> Exp_shift)) != 0)
+            z |= Exp_msk1;
+
+        if ((y = d1) != 0) {
+            dbl_bits = new byte[8];
+            k = lo0bits(y);
+            y >>>= k;
+            if (k != 0) {
+                stuffBits(dbl_bits, 4, y | z << (32 - k));
+                z >>= k;
+            }
+            else
+                stuffBits(dbl_bits, 4, y);
+            stuffBits(dbl_bits, 0, z);
+            i = (z != 0) ? 2 : 1;
+        }
+        else {
+    //        JS_ASSERT(z);
+            dbl_bits = new byte[4];
+            k = lo0bits(z);
+            z >>>= k;
+            stuffBits(dbl_bits, 0, z);
+            k += 32;
+            i = 1;
+        }
+        if (de != 0) {
+            e[0] = de - Bias - (P-1) + k;
+            bits[0] = P - k;
+        }
+        else {
+            e[0] = de - Bias - (P-1) + 1 + k;
+            bits[0] = 32*i - hi0bits(z);
+        }
+        return new BigInteger(dbl_bits);
+    }
+
+    static String JS_dtobasestr(int base, double d)
+    {
+        if (!(2 <= base && base <= 36))
+            throw new IllegalArgumentException("Bad base: "+base);
+
+        /* Check for Infinity and NaN */
+        if (Double.isNaN(d)) {
+            return "NaN";
+        } else if (Double.isInfinite(d)) {
+            return (d > 0.0) ? "Infinity" : "-Infinity";
+        } else if (d == 0) {
+            // ALERT: should it distinguish -0.0 from +0.0 ?
+            return "0";
+        }
+
+        boolean negative;
+        if (d >= 0.0) {
+            negative = false;
+        } else {
+            negative = true;
+            d = -d;
+        }
+
+        /* Get the integer part of d including '-' sign. */
+        String intDigits;
+
+        double dfloor = Math.floor(d);
+        long lfloor = (long)dfloor;
+        if (lfloor == dfloor) {
+            // int part fits long
+            intDigits = Long.toString((negative) ? -lfloor : lfloor, base);
+        } else {
+            // BigInteger should be used
+            long floorBits = Double.doubleToLongBits(dfloor);
+            int exp = (int)(floorBits >> Exp_shiftL) & Exp_mask_shifted;
+            long mantissa;
+            if (exp == 0) {
+                mantissa = (floorBits & Frac_maskL) << 1;
+            } else {
+                mantissa = (floorBits & Frac_maskL) | Exp_msk1L;
+            }
+            if (negative) {
+                mantissa = -mantissa;
+            }
+            exp -= 1075;
+            BigInteger x = BigInteger.valueOf(mantissa);
+            if (exp > 0) {
+                x = x.shiftLeft(exp);
+            } else if (exp < 0) {
+                x = x.shiftRight(-exp);
+            }
+            intDigits = x.toString(base);
+        }
+
+        if (d == dfloor) {
+            // No fraction part
+            return intDigits;
+        } else {
+            /* We have a fraction. */
+
+            StringBuilder buffer;       /* The output string */
+            int digit;
+            double df;           /* The fractional part of d */
+            BigInteger b;
+
+            buffer = new StringBuilder();
+            buffer.append(intDigits).append('.');
+            df = d - dfloor;
+
+            long dBits = Double.doubleToLongBits(d);
+            int word0 = (int)(dBits >> 32);
+            int word1 = (int)(dBits);
+
+            int[] e = new int[1];
+            int[] bbits = new int[1];
+
+            b = d2b(df, e, bbits);
+//            JS_ASSERT(e < 0);
+            /* At this point df = b * 2^e.  e must be less than zero because 0 < df < 1. */
+
+            int s2 = -(word0 >>> Exp_shift1 & Exp_mask >> Exp_shift1);
+            if (s2 == 0)
+                s2 = -1;
+            s2 += Bias + P;
+            /* 1/2^s2 = (nextDouble(d) - d)/2 */
+//            JS_ASSERT(-s2 < e);
+            BigInteger mlo = BigInteger.valueOf(1);
+            BigInteger mhi = mlo;
+            if ((word1 == 0) && ((word0 & Bndry_mask) == 0)
+                && ((word0 & (Exp_mask & Exp_mask << 1)) != 0)) {
+                /* The special case.  Here we want to be within a quarter of the last input
+                   significant digit instead of one half of it when the output string's value is less than d.  */
+                s2 += Log2P;
+                mhi = BigInteger.valueOf(1<<Log2P);
+            }
+
+            b = b.shiftLeft(e[0] + s2);
+            BigInteger s = BigInteger.valueOf(1);
+            s = s.shiftLeft(s2);
+            /* At this point we have the following:
+             *   s = 2^s2;
+             *   1 > df = b/2^s2 > 0;
+             *   (d - prevDouble(d))/2 = mlo/2^s2;
+             *   (nextDouble(d) - d)/2 = mhi/2^s2. */
+            BigInteger bigBase = BigInteger.valueOf(base);
+
+            boolean done = false;
+            do {
+                b = b.multiply(bigBase);
+                BigInteger[] divResult = b.divideAndRemainder(s);
+                b = divResult[1];
+                digit = (char)(divResult[0].intValue());
+                if (mlo == mhi)
+                    mlo = mhi = mlo.multiply(bigBase);
+                else {
+                    mlo = mlo.multiply(bigBase);
+                    mhi = mhi.multiply(bigBase);
+                }
+
+                /* Do we yet have the shortest string that will round to d? */
+                int j = b.compareTo(mlo);
+                /* j is b/2^s2 compared with mlo/2^s2. */
+                BigInteger delta = s.subtract(mhi);
+                int j1 = (delta.signum() <= 0) ? 1 : b.compareTo(delta);
+                /* j1 is b/2^s2 compared with 1 - mhi/2^s2. */
+                if (j1 == 0 && ((word1 & 1) == 0)) {
+                    if (j > 0)
+                        digit++;
+                    done = true;
+                } else
+                if (j < 0 || (j == 0 && ((word1 & 1) == 0))) {
+                    if (j1 > 0) {
+                        /* Either dig or dig+1 would work here as the least significant digit.
+                           Use whichever would produce an output value closer to d. */
+                        b = b.shiftLeft(1);
+                        j1 = b.compareTo(s);
+                        if (j1 > 0) /* The even test (|| (j1 == 0 && (digit & 1))) is not here because it messes up odd base output
+                                     * such as 3.5 in base 3.  */
+                            digit++;
+                    }
+                    done = true;
+                } else if (j1 > 0) {
+                    digit++;
+                    done = true;
+                }
+//                JS_ASSERT(digit < (uint32)base);
+                buffer.append(BASEDIGIT(digit));
+            } while (!done);
+
+            return buffer.toString();
+        }
+
+    }
+
+    /* dtoa for IEEE arithmetic (dmg): convert double to ASCII string.
+     *
+     * Inspired by "How to Print Floating-Point Numbers Accurately" by
+     * Guy L. Steele, Jr. and Jon L. White [Proc. ACM SIGPLAN '90, pp. 92-101].
+     *
+     * Modifications:
+     *  1. Rather than iterating, we use a simple numeric overestimate
+     *     to determine k = floor(log10(d)).  We scale relevant
+     *     quantities using O(log2(k)) rather than O(k) multiplications.
+     *  2. For some modes > 2 (corresponding to ecvt and fcvt), we don't
+     *     try to generate digits strictly left to right.  Instead, we
+     *     compute with fewer bits and propagate the carry if necessary
+     *     when rounding the final digit up.  This is often faster.
+     *  3. Under the assumption that input will be rounded nearest,
+     *     mode 0 renders 1e23 as 1e23 rather than 9.999999999999999e22.
+     *     That is, we allow equality in stopping tests when the
+     *     round-nearest rule will give the same floating-point value
+     *     as would satisfaction of the stopping test with strict
+     *     inequality.
+     *  4. We remove common factors of powers of 2 from relevant
+     *     quantities.
+     *  5. When converting floating-point integers less than 1e16,
+     *     we use floating-point arithmetic rather than resorting
+     *     to multiple-precision integers.
+     *  6. When asked to produce fewer than 15 digits, we first try
+     *     to get by with floating-point arithmetic; we resort to
+     *     multiple-precision integer arithmetic only if we cannot
+     *     guarantee that the floating-point calculation has given
+     *     the correctly rounded result.  For k requested digits and
+     *     "uniformly" distributed input, the probability is
+     *     something like 10^(k-15) that we must resort to the Long
+     *     calculation.
+     */
+
+    static int word0(double d)
+    {
+        long dBits = Double.doubleToLongBits(d);
+        return (int)(dBits >> 32);
+    }
+
+    static double setWord0(double d, int i)
+    {
+        long dBits = Double.doubleToLongBits(d);
+        dBits = ((long)i << 32) | (dBits & 0x0FFFFFFFFL);
+        return Double.longBitsToDouble(dBits);
+    }
+
+    static int word1(double d)
+    {
+        long dBits = Double.doubleToLongBits(d);
+        return (int)(dBits);
+    }
+
+    /* Return b * 5^k.  k must be nonnegative. */
+    // XXXX the C version built a cache of these
+    static BigInteger pow5mult(BigInteger b, int k)
+    {
+        return b.multiply(BigInteger.valueOf(5).pow(k));
+    }
+
+    static boolean roundOff(StringBuilder buf)
+    {
+        int i = buf.length();
+        while (i != 0) {
+            --i;
+            char c = buf.charAt(i);
+            if (c != '9') {
+                buf.setCharAt(i, (char)(c + 1));
+                buf.setLength(i + 1);
+                return false;
+            }
+        }
+        buf.setLength(0);
+        return true;
+    }
+
+    /* Always emits at least one digit. */
+    /* If biasUp is set, then rounding in modes 2 and 3 will round away from zero
+     * when the number is exactly halfway between two representable values.  For example,
+     * rounding 2.5 to zero digits after the decimal point will return 3 and not 2.
+     * 2.49 will still round to 2, and 2.51 will still round to 3. */
+    /* bufsize should be at least 20 for modes 0 and 1.  For the other modes,
+     * bufsize should be two greater than the maximum number of output characters expected. */
+    static int
+    JS_dtoa(double d, int mode, boolean biasUp, int ndigits,
+                    boolean[] sign, StringBuilder buf)
+    {
+        /*  Arguments ndigits, decpt, sign are similar to those
+            of ecvt and fcvt; trailing zeros are suppressed from
+            the returned string.  If not null, *rve is set to point
+            to the end of the return value.  If d is +-Infinity or NaN,
+            then *decpt is set to 9999.
+
+            mode:
+            0 ==> shortest string that yields d when read in
+            and rounded to nearest.
+            1 ==> like 0, but with Steele & White stopping rule;
+            e.g. with IEEE P754 arithmetic , mode 0 gives
+            1e23 whereas mode 1 gives 9.999999999999999e22.
+            2 ==> max(1,ndigits) significant digits.  This gives a
+            return value similar to that of ecvt, except
+            that trailing zeros are suppressed.
+            3 ==> through ndigits past the decimal point.  This
+            gives a return value similar to that from fcvt,
+            except that trailing zeros are suppressed, and
+            ndigits can be negative.
+            4-9 should give the same return values as 2-3, i.e.,
+            4 <= mode <= 9 ==> same return as mode
+            2 + (mode & 1).  These modes are mainly for
+            debugging; often they run slower but sometimes
+            faster than modes 2-3.
+            4,5,8,9 ==> left-to-right digit generation.
+            6-9 ==> don't try fast floating-point estimate
+            (if applicable).
+
+            Values of mode other than 0-9 are treated as mode 0.
+
+            Sufficient space is allocated to the return value
+            to hold the suppressed trailing zeros.
+        */
+
+        int b2, b5, i, ieps, ilim, ilim0, ilim1,
+            j, j1, k, k0, m2, m5, s2, s5;
+        char dig;
+        long L;
+        long x;
+        BigInteger b, b1, delta, mlo, mhi, S;
+        int[] be = new int[1];
+        int[] bbits = new int[1];
+        double d2, ds, eps;
+        boolean spec_case, denorm, k_check, try_quick, leftright;
+
+        if ((word0(d) & Sign_bit) != 0) {
+            /* set sign for everything, including 0's and NaNs */
+            sign[0] = true;
+            // word0(d) &= ~Sign_bit;  /* clear sign bit */
+            d = setWord0(d, word0(d) & ~Sign_bit);
+        }
+        else
+            sign[0] = false;
+
+        if ((word0(d) & Exp_mask) == Exp_mask) {
+            /* Infinity or NaN */
+            buf.append(((word1(d) == 0) && ((word0(d) & Frac_mask) == 0)) ? "Infinity" : "NaN");
+            return 9999;
+        }
+        if (d == 0) {
+//          no_digits:
+            buf.setLength(0);
+            buf.append('0');        /* copy "0" to buffer */
+            return 1;
+        }
+
+        b = d2b(d, be, bbits);
+        if ((i = (word0(d) >>> Exp_shift1 & (Exp_mask>>Exp_shift1))) != 0) {
+            d2 = setWord0(d, (word0(d) & Frac_mask1) | Exp_11);
+            /* log(x)   ~=~ log(1.5) + (x-1.5)/1.5
+             * log10(x)  =  log(x) / log(10)
+             *      ~=~ log(1.5)/log(10) + (x-1.5)/(1.5*log(10))
+             * log10(d) = (i-Bias)*log(2)/log(10) + log10(d2)
+             *
+             * This suggests computing an approximation k to log10(d) by
+             *
+             * k = (i - Bias)*0.301029995663981
+             *  + ( (d2-1.5)*0.289529654602168 + 0.176091259055681 );
+             *
+             * We want k to be too large rather than too small.
+             * The error in the first-order Taylor series approximation
+             * is in our favor, so we just round up the constant enough
+             * to compensate for any error in the multiplication of
+             * (i - Bias) by 0.301029995663981; since |i - Bias| <= 1077,
+             * and 1077 * 0.30103 * 2^-52 ~=~ 7.2e-14,
+             * adding 1e-13 to the constant term more than suffices.
+             * Hence we adjust the constant term to 0.1760912590558.
+             * (We could get a more accurate k by invoking log10,
+             *  but this is probably not worthwhile.)
+             */
+            i -= Bias;
+            denorm = false;
+        }
+        else {
+            /* d is denormalized */
+            i = bbits[0] + be[0] + (Bias + (P-1) - 1);
+            x = (i > 32)
+                    ? ((long) word0(d)) << (64 - i) | word1(d) >>> (i - 32)
+                    : ((long) word1(d)) << (32 - i);
+//            d2 = x;
+//            word0(d2) -= 31*Exp_msk1; /* adjust exponent */
+            d2 = setWord0(x, word0(x) - 31*Exp_msk1);
+            i -= (Bias + (P-1) - 1) + 1;
+            denorm = true;
+        }
+        /* At this point d = f*2^i, where 1 <= f < 2.  d2 is an approximation of f. */
+        ds = (d2-1.5)*0.289529654602168 + 0.1760912590558 + i*0.301029995663981;
+        k = (int)ds;
+        if (ds < 0.0 && ds != k)
+            k--;    /* want k = floor(ds) */
+        k_check = true;
+        if (k >= 0 && k <= Ten_pmax) {
+            if (d < tens[k])
+                k--;
+            k_check = false;
+        }
+        /* At this point floor(log10(d)) <= k <= floor(log10(d))+1.
+           If k_check is zero, we're guaranteed that k = floor(log10(d)). */
+        j = bbits[0] - i - 1;
+        /* At this point d = b/2^j, where b is an odd integer. */
+        if (j >= 0) {
+            b2 = 0;
+            s2 = j;
+        }
+        else {
+            b2 = -j;
+            s2 = 0;
+        }
+        if (k >= 0) {
+            b5 = 0;
+            s5 = k;
+            s2 += k;
+        }
+        else {
+            b2 -= k;
+            b5 = -k;
+            s5 = 0;
+        }
+        /* At this point d/10^k = (b * 2^b2 * 5^b5) / (2^s2 * 5^s5), where b is an odd integer,
+           b2 >= 0, b5 >= 0, s2 >= 0, and s5 >= 0. */
+        if (mode < 0 || mode > 9)
+            mode = 0;
+        try_quick = true;
+        if (mode > 5) {
+            mode -= 4;
+            try_quick = false;
+        }
+        leftright = true;
+        ilim = ilim1 = 0;
+        switch(mode) {
+            case 0:
+            case 1:
+                ilim = ilim1 = -1;
+                i = 18;
+                ndigits = 0;
+                break;
+            case 2:
+                leftright = false;
+                /* fallthru */
+            case 4:
+                if (ndigits <= 0)
+                    ndigits = 1;
+                ilim = ilim1 = i = ndigits;
+                break;
+            case 3:
+                leftright = false;
+                /* fallthru */
+            case 5:
+                i = ndigits + k + 1;
+                ilim = i;
+                ilim1 = i - 1;
+                if (i <= 0)
+                    i = 1;
+        }
+        /* ilim is the maximum number of significant digits we want, based on k and ndigits. */
+        /* ilim1 is the maximum number of significant digits we want, based on k and ndigits,
+           when it turns out that k was computed too high by one. */
+
+        boolean fast_failed = false;
+        if (ilim >= 0 && ilim <= Quick_max && try_quick) {
+
+            /* Try to get by with floating-point arithmetic. */
+
+            i = 0;
+            d2 = d;
+            k0 = k;
+            ilim0 = ilim;
+            ieps = 2; /* conservative */
+            /* Divide d by 10^k, keeping track of the roundoff error and avoiding overflows. */
+            if (k > 0) {
+                ds = tens[k&0xf];
+                j = k >> 4;
+                if ((j & Bletch) != 0) {
+                    /* prevent overflows */
+                    j &= Bletch - 1;
+                    d /= bigtens[n_bigtens-1];
+                    ieps++;
+                }
+                for(; (j != 0); j >>= 1, i++)
+                    if ((j & 1) != 0) {
+                        ieps++;
+                        ds *= bigtens[i];
+                    }
+                d /= ds;
+            }
+            else if ((j1 = -k) != 0) {
+                d *= tens[j1 & 0xf];
+                for(j = j1 >> 4; (j != 0); j >>= 1, i++)
+                    if ((j & 1) != 0) {
+                        ieps++;
+                        d *= bigtens[i];
+                    }
+            }
+            /* Check that k was computed correctly. */
+            if (k_check && d < 1.0 && ilim > 0) {
+                if (ilim1 <= 0)
+                    fast_failed = true;
+                else {
+                    ilim = ilim1;
+                    k--;
+                    d *= 10.;
+                    ieps++;
+                }
+            }
+            /* eps bounds the cumulative error. */
+//            eps = ieps*d + 7.0;
+//            word0(eps) -= (P-1)*Exp_msk1;
+            eps = ieps*d + 7.0;
+            eps = setWord0(eps, word0(eps) - (P-1)*Exp_msk1);
+            if (ilim == 0) {
+                S = mhi = null;
+                d -= 5.0;
+                if (d > eps) {
+                    buf.append('1');
+                    k++;
+                    return k + 1;
+                }
+                if (d < -eps) {
+                    buf.setLength(0);
+                    buf.append('0');        /* copy "0" to buffer */
+                    return 1;
+                }
+                fast_failed = true;
+            }
+            if (!fast_failed) {
+                fast_failed = true;
+                if (leftright) {
+                    /* Use Steele & White method of only
+                     * generating digits needed.
+                     */
+                    eps = 0.5/tens[ilim-1] - eps;
+                    for(i = 0;;) {
+                        L = (long)d;
+                        d -= L;
+                        buf.append((char)('0' + L));
+                        if (d < eps) {
+                            return k + 1;
+                        }
+                        if (1.0 - d < eps) {
+//                            goto bump_up;
+                                char lastCh;
+                                while (true) {
+                                    lastCh = buf.charAt(buf.length() - 1);
+                                    buf.setLength(buf.length() - 1);
+                                    if (lastCh != '9') break;
+                                    if (buf.length() == 0) {
+                                        k++;
+                                        lastCh = '0';
+                                        break;
+                                    }
+                                }
+                                buf.append((char)(lastCh + 1));
+                                return k + 1;
+                        }
+                        if (++i >= ilim)
+                            break;
+                        eps *= 10.0;
+                        d *= 10.0;
+                    }
+                }
+                else {
+                    /* Generate ilim digits, then fix them up. */
+                    eps *= tens[ilim-1];
+                    for(i = 1;; i++, d *= 10.0) {
+                        L = (long)d;
+                        d -= L;
+                        buf.append((char)('0' + L));
+                        if (i == ilim) {
+                            if (d > 0.5 + eps) {
+//                                goto bump_up;
+                                char lastCh;
+                                while (true) {
+                                    lastCh = buf.charAt(buf.length() - 1);
+                                    buf.setLength(buf.length() - 1);
+                                    if (lastCh != '9') break;
+                                    if (buf.length() == 0) {
+                                        k++;
+                                        lastCh = '0';
+                                        break;
+                                    }
+                                }
+                                buf.append((char)(lastCh + 1));
+                                return k + 1;
+                            }
+                            else
+                                if (d < 0.5 - eps) {
+                                    stripTrailingZeroes(buf);
+//                                    while(*--s == '0') ;
+//                                    s++;
+                                    return k + 1;
+                                }
+                            break;
+                        }
+                    }
+                }
+            }
+            if (fast_failed) {
+                buf.setLength(0);
+                d = d2;
+                k = k0;
+                ilim = ilim0;
+            }
+        }
+
+        /* Do we have a "small" integer? */
+
+        if (be[0] >= 0 && k <= Int_max) {
+            /* Yes. */
+            ds = tens[k];
+            if (ndigits < 0 && ilim <= 0) {
+                S = mhi = null;
+                if (ilim < 0 || d < 5*ds || (!biasUp && d == 5*ds)) {
+                    buf.setLength(0);
+                    buf.append('0');        /* copy "0" to buffer */
+                    return 1;
+                }
+                buf.append('1');
+                k++;
+                return k + 1;
+            }
+            for(i = 1;; i++) {
+                L = (long) (d / ds);
+                d -= L*ds;
+                buf.append((char)('0' + L));
+                if (i == ilim) {
+                    d += d;
+                    if ((d > ds) || (d == ds && (((L & 1) != 0) || biasUp))) {
+//                    bump_up:
+//                        while(*--s == '9')
+//                            if (s == buf) {
+//                                k++;
+//                                *s = '0';
+//                                break;
+//                            }
+//                        ++*s++;
+                        char lastCh;
+                        while (true) {
+                            lastCh = buf.charAt(buf.length() - 1);
+                            buf.setLength(buf.length() - 1);
+                            if (lastCh != '9') break;
+                            if (buf.length() == 0) {
+                                k++;
+                                lastCh = '0';
+                                break;
+                            }
+                        }
+                        buf.append((char)(lastCh + 1));
+                    }
+                    break;
+                }
+                d *= 10.0;
+                if (d == 0)
+                    break;
+            }
+            return k + 1;
+        }
+
+        m2 = b2;
+        m5 = b5;
+        mhi = mlo = null;
+        if (leftright) {
+            if (mode < 2) {
+                i = (denorm) ? be[0] + (Bias + (P-1) - 1 + 1) : 1 + P - bbits[0];
+                /* i is 1 plus the number of trailing zero bits in d's significand. Thus,
+                   (2^m2 * 5^m5) / (2^(s2+i) * 5^s5) = (1/2 lsb of d)/10^k. */
+            }
+            else {
+                j = ilim - 1;
+                if (m5 >= j)
+                    m5 -= j;
+                else {
+                    s5 += j -= m5;
+                    b5 += j;
+                    m5 = 0;
+                }
+                if ((i = ilim) < 0) {
+                    m2 -= i;
+                    i = 0;
+                }
+                /* (2^m2 * 5^m5) / (2^(s2+i) * 5^s5) = (1/2 * 10^(1-ilim))/10^k. */
+            }
+            b2 += i;
+            s2 += i;
+            mhi = BigInteger.valueOf(1);
+            /* (mhi * 2^m2 * 5^m5) / (2^s2 * 5^s5) = one-half of last printed (when mode >= 2) or
+               input (when mode < 2) significant digit, divided by 10^k. */
+        }
+        /* We still have d/10^k = (b * 2^b2 * 5^b5) / (2^s2 * 5^s5).  Reduce common factors in
+           b2, m2, and s2 without changing the equalities. */
+        if (m2 > 0 && s2 > 0) {
+            i = (m2 < s2) ? m2 : s2;
+            b2 -= i;
+            m2 -= i;
+            s2 -= i;
+        }
+
+        /* Fold b5 into b and m5 into mhi. */
+        if (b5 > 0) {
+            if (leftright) {
+                if (m5 > 0) {
+                    mhi = pow5mult(mhi, m5);
+                    b1 = mhi.multiply(b);
+                    b = b1;
+                }
+                if ((j = b5 - m5) != 0)
+                    b = pow5mult(b, j);
+            }
+            else
+                b = pow5mult(b, b5);
+        }
+        /* Now we have d/10^k = (b * 2^b2) / (2^s2 * 5^s5) and
+           (mhi * 2^m2) / (2^s2 * 5^s5) = one-half of last printed or input significant digit, divided by 10^k. */
+
+        S = BigInteger.valueOf(1);
+        if (s5 > 0)
+            S = pow5mult(S, s5);
+        /* Now we have d/10^k = (b * 2^b2) / (S * 2^s2) and
+           (mhi * 2^m2) / (S * 2^s2) = one-half of last printed or input significant digit, divided by 10^k. */
+
+        /* Check for special case that d is a normalized power of 2. */
+        spec_case = false;
+        if (mode < 2) {
+            if ( (word1(d) == 0) && ((word0(d) & Bndry_mask) == 0)
+                && ((word0(d) & (Exp_mask & Exp_mask << 1)) != 0)
+                ) {
+                /* The special case.  Here we want to be within a quarter of the last input
+                   significant digit instead of one half of it when the decimal output string's value is less than d.  */
+                b2 += Log2P;
+                s2 += Log2P;
+                spec_case = true;
+            }
+        }
+
+        /* Arrange for convenient computation of quotients:
+         * shift left if necessary so divisor has 4 leading 0 bits.
+         *
+         * Perhaps we should just compute leading 28 bits of S once
+         * and for all and pass them and a shift to quorem, so it
+         * can do shifts and ors to compute the numerator for q.
+         */
+        byte [] S_bytes = S.toByteArray();
+        int S_hiWord = 0;
+        for (int idx = 0; idx < 4; idx++) {
+            S_hiWord = (S_hiWord << 8);
+            if (idx < S_bytes.length)
+                S_hiWord |= (S_bytes[idx] & 0xFF);
+        }
+        if ((i = (((s5 != 0) ? 32 - hi0bits(S_hiWord) : 1) + s2) & 0x1f) != 0)
+            i = 32 - i;
+        /* i is the number of leading zero bits in the most significant word of S*2^s2. */
+        if (i > 4) {
+            i -= 4;
+            b2 += i;
+            m2 += i;
+            s2 += i;
+        }
+        else if (i < 4) {
+            i += 28;
+            b2 += i;
+            m2 += i;
+            s2 += i;
+        }
+        /* Now S*2^s2 has exactly four leading zero bits in its most significant word. */
+        if (b2 > 0)
+            b = b.shiftLeft(b2);
+        if (s2 > 0)
+            S = S.shiftLeft(s2);
+        /* Now we have d/10^k = b/S and
+           (mhi * 2^m2) / S = maximum acceptable error, divided by 10^k. */
+        if (k_check) {
+            if (b.compareTo(S) < 0) {
+                k--;
+                b = b.multiply(BigInteger.valueOf(10));  /* we botched the k estimate */
+                if (leftright)
+                    mhi = mhi.multiply(BigInteger.valueOf(10));
+                ilim = ilim1;
+            }
+        }
+        /* At this point 1 <= d/10^k = b/S < 10. */
+
+        if (ilim <= 0 && mode > 2) {
+            /* We're doing fixed-mode output and d is less than the minimum nonzero output in this mode.
+               Output either zero or the minimum nonzero output depending on which is closer to d. */
+            if ((ilim < 0 )
+                    || ((i = b.compareTo(S = S.multiply(BigInteger.valueOf(5)))) < 0)
+                    || ((i == 0 && !biasUp))) {
+            /* Always emit at least one digit.  If the number appears to be zero
+               using the current mode, then emit one '0' digit and set decpt to 1. */
+            /*no_digits:
+                k = -1 - ndigits;
+                goto ret; */
+                buf.setLength(0);
+                buf.append('0');        /* copy "0" to buffer */
+                return 1;
+//                goto no_digits;
+            }
+//        one_digit:
+            buf.append('1');
+            k++;
+            return k + 1;
+        }
+        if (leftright) {
+            if (m2 > 0)
+                mhi = mhi.shiftLeft(m2);
+
+            /* Compute mlo -- check for special case
+             * that d is a normalized power of 2.
+             */
+
+            mlo = mhi;
+            if (spec_case) {
+                mhi = mlo;
+                mhi = mhi.shiftLeft(Log2P);
+            }
+            /* mlo/S = maximum acceptable error, divided by 10^k, if the output is less than d. */
+            /* mhi/S = maximum acceptable error, divided by 10^k, if the output is greater than d. */
+
+            for(i = 1;;i++) {
+                BigInteger[] divResult = b.divideAndRemainder(S);
+                b = divResult[1];
+                dig = (char)(divResult[0].intValue() + '0');
+                /* Do we yet have the shortest decimal string
+                 * that will round to d?
+                 */
+                j = b.compareTo(mlo);
+                /* j is b/S compared with mlo/S. */
+                delta = S.subtract(mhi);
+                j1 = (delta.signum() <= 0) ? 1 : b.compareTo(delta);
+                /* j1 is b/S compared with 1 - mhi/S. */
+                if ((j1 == 0) && (mode == 0) && ((word1(d) & 1) == 0)) {
+                    if (dig == '9') {
+                        buf.append('9');
+                        if (roundOff(buf)) {
+                            k++;
+                            buf.append('1');
+                        }
+                        return k + 1;
+//                        goto round_9_up;
+                    }
+                    if (j > 0)
+                        dig++;
+                    buf.append(dig);
+                    return k + 1;
+                }
+                if ((j < 0)
+                        || ((j == 0)
+                            && (mode == 0)
+                            && ((word1(d) & 1) == 0)
+                    )) {
+                    if (j1 > 0) {
+                        /* Either dig or dig+1 would work here as the least significant decimal digit.
+                           Use whichever would produce a decimal value closer to d. */
+                        b = b.shiftLeft(1);
+                        j1 = b.compareTo(S);
+                        if (((j1 > 0) || (j1 == 0 && (((dig & 1) == 1) || biasUp)))
+                            && (dig++ == '9')) {
+                                buf.append('9');
+                                if (roundOff(buf)) {
+                                    k++;
+                                    buf.append('1');
+                                }
+                                return k + 1;
+//                                goto round_9_up;
+                        }
+                    }
+                    buf.append(dig);
+                    return k + 1;
+                }
+                if (j1 > 0) {
+                    if (dig == '9') { /* possible if i == 1 */
+//                    round_9_up:
+//                        *s++ = '9';
+//                        goto roundoff;
+                        buf.append('9');
+                        if (roundOff(buf)) {
+                            k++;
+                            buf.append('1');
+                        }
+                        return k + 1;
+                    }
+                    buf.append((char)(dig + 1));
+                    return k + 1;
+                }
+                buf.append(dig);
+                if (i == ilim)
+                    break;
+                b = b.multiply(BigInteger.valueOf(10));
+                if (mlo == mhi)
+                    mlo = mhi = mhi.multiply(BigInteger.valueOf(10));
+                else {
+                    mlo = mlo.multiply(BigInteger.valueOf(10));
+                    mhi = mhi.multiply(BigInteger.valueOf(10));
+                }
+            }
+        }
+        else
+            for(i = 1;; i++) {
+//                (char)(dig = quorem(b,S) + '0');
+                BigInteger[] divResult = b.divideAndRemainder(S);
+                b = divResult[1];
+                dig = (char)(divResult[0].intValue() + '0');
+                buf.append(dig);
+                if (i >= ilim)
+                    break;
+                b = b.multiply(BigInteger.valueOf(10));
+            }
+
+        /* Round off last digit */
+
+        b = b.shiftLeft(1);
+        j = b.compareTo(S);
+        if ((j > 0) || (j == 0 && (((dig & 1) == 1) || biasUp))) {
+//        roundoff:
+//            while(*--s == '9')
+//                if (s == buf) {
+//                    k++;
+//                    *s++ = '1';
+//                    goto ret;
+//                }
+//            ++*s++;
+            if (roundOff(buf)) {
+                k++;
+                buf.append('1');
+                return k + 1;
+            }
+        }
+        else {
+            stripTrailingZeroes(buf);
+//            while(*--s == '0') ;
+//            s++;
+        }
+//      ret:
+//        Bfree(S);
+//        if (mhi) {
+//            if (mlo && mlo != mhi)
+//                Bfree(mlo);
+//            Bfree(mhi);
+//        }
+//      ret1:
+//        Bfree(b);
+//        JS_ASSERT(s < buf + bufsize);
+        return k + 1;
+    }
+
+    private static void
+    stripTrailingZeroes(StringBuilder buf)
+    {
+//      while(*--s == '0') ;
+//      s++;
+        int bl = buf.length();
+        while(bl-->0 && buf.charAt(bl) == '0') {
+          // empty
+        }
+        buf.setLength(bl + 1);
+    }
+
+    /* Mapping of JSDToStrMode -> JS_dtoa mode */
+    private static final int dtoaModes[] = {
+        0,   /* DTOSTR_STANDARD */
+        0,   /* DTOSTR_STANDARD_EXPONENTIAL, */
+        3,   /* DTOSTR_FIXED, */
+        2,   /* DTOSTR_EXPONENTIAL, */
+        2};  /* DTOSTR_PRECISION */
+
+    static void
+    JS_dtostr(StringBuilder buffer, int mode, int precision, double d)
+    {
+        int decPt;                                    /* Position of decimal point relative to first digit returned by JS_dtoa */
+        boolean[] sign = new boolean[1];            /* true if the sign bit was set in d */
+        int nDigits;                                /* Number of significand digits returned by JS_dtoa */
+
+//        JS_ASSERT(bufferSize >= (size_t)(mode <= DTOSTR_STANDARD_EXPONENTIAL ? DTOSTR_STANDARD_BUFFER_SIZE :
+//                DTOSTR_VARIABLE_BUFFER_SIZE(precision)));
+
+        if (mode == DTOSTR_FIXED && (d >= 1e21 || d <= -1e21))
+            mode = DTOSTR_STANDARD; /* Change mode here rather than below because the buffer may not be large enough to hold a large integer. */
+
+        decPt = JS_dtoa(d, dtoaModes[mode], mode >= DTOSTR_FIXED, precision, sign, buffer);
+        nDigits = buffer.length();
+
+        /* If Infinity, -Infinity, or NaN, return the string regardless of the mode. */
+        if (decPt != 9999) {
+            boolean exponentialNotation = false;
+            int minNDigits = 0;         /* Minimum number of significand digits required by mode and precision */
+            int p;
+
+            switch (mode) {
+                case DTOSTR_STANDARD:
+                    if (decPt < -5 || decPt > 21)
+                        exponentialNotation = true;
+                    else
+                        minNDigits = decPt;
+                    break;
+
+                case DTOSTR_FIXED:
+                    if (precision >= 0)
+                        minNDigits = decPt + precision;
+                    else
+                        minNDigits = decPt;
+                    break;
+
+                case DTOSTR_EXPONENTIAL:
+//                    JS_ASSERT(precision > 0);
+                    minNDigits = precision;
+                    /* fallthru */
+                case DTOSTR_STANDARD_EXPONENTIAL:
+                    exponentialNotation = true;
+                    break;
+
+                case DTOSTR_PRECISION:
+//                    JS_ASSERT(precision > 0);
+                    minNDigits = precision;
+                    if (decPt < -5 || decPt > precision)
+                        exponentialNotation = true;
+                    break;
+            }
+
+            /* If the number has fewer than minNDigits, pad it with zeros at the end */
+            if (nDigits < minNDigits) {
+                p = minNDigits;
+                nDigits = minNDigits;
+                do {
+                    buffer.append('0');
+                } while (buffer.length() != p);
+            }
+
+            if (exponentialNotation) {
+                /* Insert a decimal point if more than one significand digit */
+                if (nDigits != 1) {
+                    buffer.insert(1, '.');
+                }
+                buffer.append('e');
+                if ((decPt - 1) >= 0)
+                    buffer.append('+');
+                buffer.append(decPt - 1);
+//                JS_snprintf(numEnd, bufferSize - (numEnd - buffer), "e%+d", decPt-1);
+            } else if (decPt != nDigits) {
+                /* Some kind of a fraction in fixed notation */
+//                JS_ASSERT(decPt <= nDigits);
+                if (decPt > 0) {
+                    /* dd...dd . dd...dd */
+                    buffer.insert(decPt, '.');
+                } else {
+                    /* 0 . 00...00dd...dd */
+                    for (int i = 0; i < 1 - decPt; i++)
+                        buffer.insert(0, '0');
+                    buffer.insert(1, '.');
+                }
+            }
+        }
+
+        /* If negative and neither -0.0 nor NaN, output a leading '-'. */
+        if (sign[0] &&
+                !(word0(d) == Sign_bit && word1(d) == 0) &&
+                !((word0(d) & Exp_mask) == Exp_mask &&
+                  ((word1(d) != 0) || ((word0(d) & Frac_mask) != 0)))) {
+            buffer.insert(0, '-');
+        }
+    }
+
+}
+
diff -pruN 20130227+dfsg1-14/rhino/src/org/mozilla/javascript/Decompiler.java 20130227+rhino-1/rhino/src/org/mozilla/javascript/Decompiler.java
--- 20130227+dfsg1-14/rhino/src/org/mozilla/javascript/Decompiler.java	1970-01-01 00:00:00.000000000 +0000
+++ 20130227+rhino-1/rhino/src/org/mozilla/javascript/Decompiler.java	2023-05-25 14:24:50.000000000 +0000
@@ -0,0 +1,900 @@
+/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+package org.mozilla.javascript;
+
+import org.mozilla.javascript.ast.FunctionNode;
+
+/**
+ * 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();
+        if (functionType != FunctionNode.ARROW_FUNCTION) {
+            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 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();
+
+        StringBuilder result = new StringBuilder();
+        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:
+            case Token.METHOD:
+                if (source.charAt(i) == Token.GET) {
+                    result.append("get ");
+                } else if (source.charAt(i) == Token.SET) {
+                    result.append("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.LET:
+              result.append("let ");
+              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.YIELD:
+                result.append("yield ");
+                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;
+
+            case Token.DEBUGGER:
+                result.append("debugger;\n");
+                break;
+
+            case Token.ARROW:
+                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,
+                                         StringBuilder 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,
+                                         StringBuilder 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;
+
+}
diff -pruN 20130227+dfsg1-14/rhino/src/org/mozilla/javascript/DefaultErrorReporter.java 20130227+rhino-1/rhino/src/org/mozilla/javascript/DefaultErrorReporter.java
--- 20130227+dfsg1-14/rhino/src/org/mozilla/javascript/DefaultErrorReporter.java	1970-01-01 00:00:00.000000000 +0000
+++ 20130227+rhino-1/rhino/src/org/mozilla/javascript/DefaultErrorReporter.java	2023-05-25 14:24:50.000000000 +0000
@@ -0,0 +1,81 @@
+/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+package org.mozilla.javascript;
+
+/**
+ * This is the default error reporter for JavaScript.
+ *
+ * @author Norris Boyd
+ */
+class DefaultErrorReporter implements ErrorReporter
+{
+    static final DefaultErrorReporter instance = new DefaultErrorReporter();
+
+    private boolean forEval;
+    private ErrorReporter chainedReporter;
+
+    private DefaultErrorReporter() { }
+
+    static ErrorReporter forEval(ErrorReporter reporter)
+    {
+        DefaultErrorReporter r = new DefaultErrorReporter();
+        r.forEval = true;
+        r.chainedReporter = reporter;
+        return r;
+    }
+
+    public void warning(String message, String sourceURI, int line,
+                        String lineText, int lineOffset)
+    {
+        if (chainedReporter != null) {
+            chainedReporter.warning(
+                message, sourceURI, line, lineText, lineOffset);
+        } else {
+            // Do nothing
+        }
+    }
+
+    public void error(String message, String sourceURI, int line,
+                      String lineText, int lineOffset)
+    {
+        if (forEval) {
+            // Assume error message strings that start with "TypeError: "
+            // should become TypeError exceptions. A bit of a hack, but we
+            // don't want to change the ErrorReporter interface.
+            String error = "SyntaxError";
+            final String TYPE_ERROR_NAME = "TypeError";
+            final String DELIMETER = ": ";
+            final String prefix = TYPE_ERROR_NAME + DELIMETER;
+            if (message.startsWith(prefix)) {
+                error = TYPE_ERROR_NAME;
+                message = message.substring(prefix.length());
+            }
+            throw ScriptRuntime.constructError(error, message, sourceURI,
+                                               line, lineText, lineOffset);
+        }
+        if (chainedReporter != null) {
+            chainedReporter.error(
+                message, sourceURI, line, lineText, lineOffset);
+        } else {
+            throw runtimeError(
+                message, sourceURI, line, lineText, lineOffset);
+        }
+    }
+
+    public EvaluatorException runtimeError(String message, String sourceURI,
+                                           int line, String lineText,
+                                           int lineOffset)
+    {
+        if (chainedReporter != null) {
+            return chainedReporter.runtimeError(
+                message, sourceURI, line, lineText, lineOffset);
+        } else {
+            return new EvaluatorException(
+                message, sourceURI, line, lineText, lineOffset);
+        }
+    }
+}
diff -pruN 20130227+dfsg1-14/rhino/src/org/mozilla/javascript/DefiningClassLoader.java 20130227+rhino-1/rhino/src/org/mozilla/javascript/DefiningClassLoader.java
--- 20130227+dfsg1-14/rhino/src/org/mozilla/javascript/DefiningClassLoader.java	1970-01-01 00:00:00.000000000 +0000
+++ 20130227+rhino-1/rhino/src/org/mozilla/javascript/DefiningClassLoader.java	2023-05-25 14:24:50.000000000 +0000
@@ -0,0 +1,54 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+package org.mozilla.javascript;
+
+/**
+ * Load generated classes.
+ *
+ * @author Norris Boyd
+ */
+public class DefiningClassLoader extends ClassLoader
+    implements GeneratedClassLoader
+{
+    public DefiningClassLoader() {
+        this.parentLoader = getClass().getClassLoader();
+    }
+
+    public DefiningClassLoader(ClassLoader parentLoader) {
+        this.parentLoader = parentLoader;
+    }
+
+    public Class<?> defineClass(String name, byte[] data) {
+        // Use our own protection domain for the generated classes.
+        // TODO: we might want to use a separate protection domain for classes
+        // compiled from scripts, based on where the script was loaded from.
+        return super.defineClass(name, data, 0, data.length,
+                SecurityUtilities.getProtectionDomain(getClass()));
+    }
+
+    public void linkClass(Class<?> cl) {
+        resolveClass(cl);
+    }
+
+    @Override
+    public Class<?> loadClass(String name, boolean resolve)
+        throws ClassNotFoundException
+    {
+        Class<?> cl = findLoadedClass(name);
+        if (cl == null) {
+            if (parentLoader != null) {
+                cl = parentLoader.loadClass(name);
+            } else {
+                cl = findSystemClass(name);
+            }
+        }
+        if (resolve) {
+            resolveClass(cl);
+        }
+        return cl;
+    }
+
+    private final ClassLoader parentLoader;
+}
diff -pruN 20130227+dfsg1-14/rhino/src/org/mozilla/javascript/Delegator.java 20130227+rhino-1/rhino/src/org/mozilla/javascript/Delegator.java
--- 20130227+dfsg1-14/rhino/src/org/mozilla/javascript/Delegator.java	1970-01-01 00:00:00.000000000 +0000
+++ 20130227+rhino-1/rhino/src/org/mozilla/javascript/Delegator.java	2023-05-25 14:24:50.000000000 +0000
@@ -0,0 +1,235 @@
+/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// API class
+
+package org.mozilla.javascript;
+
+/**
+ * This is a helper class for implementing wrappers around Scriptable
+ * objects. It implements the Function interface and delegates all
+ * invocations to a delegee Scriptable object. The normal use of this
+ * class involves creating a sub-class and overriding one or more of
+ * the methods.
+ *
+ * A useful application is the implementation of interceptors,
+ * pre/post conditions, debugging.
+ *
+ * @see Function
+ * @see Scriptable
+ * @author Matthias Radestock
+ */
+
+public class Delegator implements Function {
+
+    protected Scriptable obj = null;
+
+    /**
+     * Create a Delegator prototype.
+     *
+     * This constructor should only be used for creating prototype
+     * objects of Delegator.
+     *
+     * @see org.mozilla.javascript.Delegator#construct
+     */
+    public Delegator() {
+    }
+
+    /**
+     * Create a new Delegator that forwards requests to a delegee
+     * Scriptable object.
+     *
+     * @param obj the delegee
+     * @see org.mozilla.javascript.Scriptable
+     */
+    public Delegator(Scriptable obj) {
+        this.obj = obj;
+    }
+
+    /**
+     * Crete new Delegator instance.
+     * The default implementation calls this.getClass().newInstance().
+     *
+     * @see #construct(Context cx, Scriptable scope, Object[] args)
+     */
+    protected Delegator newInstance()
+    {
+        try {
+            return this.getClass().newInstance();
+        } catch (Exception ex) {
+            throw Context.throwAsScriptRuntimeEx(ex);
+        }
+    }
+
+    /**
+     * Retrieve the delegee.
+     *
+     * @return the delegee
+     */
+    public Scriptable getDelegee() {
+        return obj;
+    }
+    /**
+     * Set the delegee.
+     *
+     * @param obj the delegee
+     * @see org.mozilla.javascript.Scriptable
+     */
+    public void setDelegee(Scriptable obj) {
+        this.obj = obj;
+    }
+    /**
+     * @see org.mozilla.javascript.Scriptable#getClassName
+     */
+    public String getClassName() {
+        return obj.getClassName();
+    }
+    /**
+     * @see org.mozilla.javascript.Scriptable#get(String, Scriptable)
+     */
+    public Object get(String name, Scriptable start) {
+        return obj.get(name,start);
+    }
+    /**
+     * @see org.mozilla.javascript.Scriptable#get(int, Scriptable)
+     */
+    public Object get(int index, Scriptable start) {
+        return obj.get(index,start);
+        }
+    /**
+     * @see org.mozilla.javascript.Scriptable#has(String, Scriptable)
+     */
+    public boolean has(String name, Scriptable start) {
+        return obj.has(name,start);
+        }
+    /**
+     * @see org.mozilla.javascript.Scriptable#has(int, Scriptable)
+     */
+    public boolean has(int index, Scriptable start) {
+        return obj.has(index,start);
+        }
+    /**
+     * @see org.mozilla.javascript.Scriptable#put(String, Scriptable, Object)
+     */
+    public void put(String name, Scriptable start, Object value) {
+        obj.put(name,start,value);
+    }
+    /**
+     * @see org.mozilla.javascript.Scriptable#put(int, Scriptable, Object)
+     */
+    public void put(int index, Scriptable start, Object value) {
+        obj.put(index,start,value);
+    }
+    /**
+     * @see org.mozilla.javascript.Scriptable#delete(String)
+     */
+    public void delete(String name) {
+        obj.delete(name);
+    }
+    /**
+     * @see org.mozilla.javascript.Scriptable#delete(int)
+     */
+    public void delete(int index) {
+        obj.delete(index);
+    }
+    /**
+     * @see org.mozilla.javascript.Scriptable#getPrototype
+     */
+    public Scriptable getPrototype() {
+        return obj.getPrototype();
+    }
+    /**
+     * @see org.mozilla.javascript.Scriptable#setPrototype
+     */
+    public void setPrototype(Scriptable prototype) {
+        obj.setPrototype(prototype);
+    }
+    /**
+     * @see org.mozilla.javascript.Scriptable#getParentScope
+     */
+    public Scriptable getParentScope() {
+        return obj.getParentScope();
+    }
+    /**
+     * @see org.mozilla.javascript.Scriptable#setParentScope
+     */
+    public void setParentScope(Scriptable parent) {
+        obj.setParentScope(parent);
+    }
+    /**
+     * @see org.mozilla.javascript.Scriptable#getIds
+     */
+    public Object[] getIds() {
+        return obj.getIds();
+    }
+    /**
+     * Note that this method does not get forwarded to the delegee if
+     * the <code>hint</code> parameter is null,
+     * <code>ScriptRuntime.ScriptableClass</code> or
+     * <code>ScriptRuntime.FunctionClass</code>. Instead the object
+     * itself is returned.
+     *
+     * @param hint the type hint
+     * @return the default value
+     *
+     * @see org.mozilla.javascript.Scriptable#getDefaultValue
+     */
+    public Object getDefaultValue(Class<?> hint) {
+        return (hint == null ||
+                hint == ScriptRuntime.ScriptableClass ||
+                hint == ScriptRuntime.FunctionClass) ?
+            this : obj.getDefaultValue(hint);
+    }
+    /**
+     * @see org.mozilla.javascript.Scriptable#hasInstance
+     */
+    public boolean hasInstance(Scriptable instance) {
+        return obj.hasInstance(instance);
+    }
+    /**
+     * @see org.mozilla.javascript.Function#call
+     */
+    public Object call(Context cx, Scriptable scope, Scriptable thisObj,
+                       Object[] args)
+    {
+        return ((Function)obj).call(cx,scope,thisObj,args);
+    }
+
+    /**
+     * Note that if the <code>delegee</code> is <code>null</code>,
+     * this method creates a new instance of the Delegator itself
+     * rathert than forwarding the call to the
+     * <code>delegee</code>. This permits the use of Delegator
+     * prototypes.
+     *
+     * @param cx the current Context for this thread
+     * @param scope an enclosing scope of the caller except
+     *              when the function is called from a closure.
+     * @param args the array of arguments
+     * @return the allocated object
+     *
+     * @see Function#construct(Context, Scriptable, Object[])
+     */
+    public Scriptable construct(Context cx, Scriptable scope, Object[] args)
+    {
+        if (obj == null) {
+            //this little trick allows us to declare prototype objects for
+            //Delegators
+            Delegator n = newInstance();
+            Scriptable delegee;
+            if (args.length == 0) {
+                delegee = new NativeObject();
+            } else {
+                delegee = ScriptRuntime.toObject(cx, scope, args[0]);
+            }
+            n.setDelegee(delegee);
+            return n;
+        }
+        else {
+            return ((Function)obj).construct(cx,scope,args);
+        }
+    }
+}
diff -pruN 20130227+dfsg1-14/rhino/src/org/mozilla/javascript/ES6Iterator.java 20130227+rhino-1/rhino/src/org/mozilla/javascript/ES6Iterator.java
--- 20130227+dfsg1-14/rhino/src/org/mozilla/javascript/ES6Iterator.java	1970-01-01 00:00:00.000000000 +0000
+++ 20130227+rhino-1/rhino/src/org/mozilla/javascript/ES6Iterator.java	2023-05-25 14:24:50.000000000 +0000
@@ -0,0 +1,138 @@
+/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+package org.mozilla.javascript;
+
+public abstract class ES6Iterator extends IdScriptableObject {
+
+    static void init(ScriptableObject scope, boolean sealed, IdScriptableObject prototype, String tag) {
+        if (scope != null) {
+            prototype.setParentScope(scope);
+            prototype.setPrototype(getObjectPrototype(scope));
+        }
+        prototype.activatePrototypeMap(MAX_PROTOTYPE_ID);
+        if (sealed) {
+            prototype.sealObject();
+        }
+
+        // Need to access Iterator prototype when constructing
+        // Iterator instances, but don't have a iterator constructor
+        // to use to find the prototype. Use the "associateValue"
+        // approach instead.
+        if (scope != null) {
+            scope.associateValue(tag, prototype);
+        }
+    }
+
+    protected boolean exhausted = false;
+
+    ES6Iterator() {}
+
+    ES6Iterator(Scriptable scope) {
+        // Set parent and prototype properties. Since we don't have a
+        // "Iterator" constructor in the top scope, we stash the
+        // prototype in the top scope's associated value.
+        Scriptable top = ScriptableObject.getTopLevelScope(scope);
+        this.setParentScope(top);
+        IdScriptableObject prototype = (IdScriptableObject)
+            ScriptableObject.getTopScopeValue(top, getTag());
+        setPrototype(prototype);
+    }
+
+    @Override
+    protected void initPrototypeId(int id)
+    {
+        switch (id) {
+            case Id_next:
+                initPrototypeMethod(getTag(), id, NEXT_METHOD, 0);
+                return;
+            case Id_iterator:
+                initPrototypeMethod(getTag(), id, SymbolKey.ITERATOR, "[Symbol.iterator]", 0);
+                return;
+            case Id_toStringTag:
+                initPrototypeValue(Id_toStringTag, SymbolKey.TO_STRING_TAG, getClassName(), DONTENUM | READONLY);
+                return;
+            default: throw new IllegalArgumentException(String.valueOf(id));
+        }
+    }
+
+    @Override
+    public Object execIdCall(IdFunctionObject f, Context cx, Scriptable scope,
+                             Scriptable thisObj, Object[] args)
+    {
+        if (!f.hasTag(getTag())) {
+            return super.execIdCall(f, cx, scope, thisObj, args);
+        }
+        int id = f.methodId();
+
+        if (!(thisObj instanceof ES6Iterator))
+            throw incompatibleCallError(f);
+
+        ES6Iterator iterator = (ES6Iterator) thisObj;
+
+        switch (id) {
+        case Id_next:
+            return iterator.next(cx, scope);
+        case Id_iterator:
+            return iterator;
+        default:
+            throw new IllegalArgumentException(String.valueOf(id));
+        }
+    }
+
+    @Override
+    protected int findPrototypeId(Symbol k) {
+        if (SymbolKey.ITERATOR.equals(k)) {
+            return Id_iterator;
+        } else if (SymbolKey.TO_STRING_TAG.equals(k)) {
+            return Id_toStringTag;
+        }
+        return 0;
+    }
+
+    @Override
+    protected int findPrototypeId(String s) {
+        if ("next".equals(s)) {
+            return Id_next;
+        }
+        return 0;
+    }
+
+    abstract protected boolean isDone(Context cx, Scriptable scope);
+
+    abstract protected Object nextValue(Context cx, Scriptable scope);
+
+    protected Object next(Context cx, Scriptable scope) {
+        Object value = Undefined.instance;
+        boolean done = isDone(cx, scope) || this.exhausted;
+        if (!done) {
+            value = nextValue(cx, scope);
+        } else {
+            this.exhausted = true;
+        }
+        return makeIteratorResult(cx, scope, done, value);
+    }
+
+    abstract protected String getTag();
+
+    // 25.1.1.3 The IteratorResult Interface
+    private Scriptable makeIteratorResult(Context cx, Scriptable scope, boolean done, Object value) {
+        Scriptable iteratorResult = cx.newObject(scope);
+        ScriptableObject.putProperty(iteratorResult, VALUE_PROPERTY, value);
+        ScriptableObject.putProperty(iteratorResult, DONE_PROPERTY, done);
+        return iteratorResult;
+    }
+
+    private static final int
+        Id_next             = 1,
+        Id_iterator         = 2,
+        Id_toStringTag      = 3,
+        MAX_PROTOTYPE_ID    = Id_toStringTag;
+
+    public static final String NEXT_METHOD = "next";
+    public static final String DONE_PROPERTY = "done";
+    public static final String VALUE_PROPERTY = "value";
+}
diff -pruN 20130227+dfsg1-14/rhino/src/org/mozilla/javascript/EcmaError.java 20130227+rhino-1/rhino/src/org/mozilla/javascript/EcmaError.java
--- 20130227+dfsg1-14/rhino/src/org/mozilla/javascript/EcmaError.java	1970-01-01 00:00:00.000000000 +0000
+++ 20130227+rhino-1/rhino/src/org/mozilla/javascript/EcmaError.java	2023-05-25 14:24:50.000000000 +0000
@@ -0,0 +1,135 @@
+/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// API class
+
+package org.mozilla.javascript;
+
+/**
+ * The class of exceptions raised by the engine as described in
+ * ECMA edition 3. See section 15.11.6 in particular.
+ */
+public class EcmaError extends RhinoException
+{
+    static final long serialVersionUID = -6261226256957286699L;
+
+    private String errorName;
+    private String errorMessage;
+
+    /**
+     * Create an exception with the specified detail message.
+     *
+     * Errors internal to the JavaScript engine will simply throw a
+     * RuntimeException.
+     *
+     * @param sourceName the name of the source responsible for the error
+     * @param lineNumber the line number of the source
+     * @param columnNumber the columnNumber of the source (may be zero if
+     *                     unknown)
+     * @param lineSource the source of the line containing the error (may be
+     *                   null if unknown)
+     */
+    EcmaError(String errorName, String errorMessage,
+              String sourceName, int lineNumber,
+              String lineSource, int columnNumber)
+    {
+        recordErrorOrigin(sourceName, lineNumber, lineSource, columnNumber);
+        this.errorName = errorName;
+        this.errorMessage = errorMessage;
+    }
+
+    /**
+     * @deprecated EcmaError error instances should not be constructed
+     *             explicitly since they are generated by the engine.
+     */
+    @Deprecated
+    public EcmaError(Scriptable nativeError, String sourceName,
+                     int lineNumber, int columnNumber, String lineSource)
+    {
+        this("InternalError", ScriptRuntime.toString(nativeError),
+             sourceName, lineNumber, lineSource, columnNumber);
+    }
+
+    @Override
+    public String details()
+    {
+        return errorName+": "+errorMessage;
+    }
+
+    /**
+     * Gets the name of the error.
+     *
+     * ECMA edition 3 defines the following
+     * errors: EvalError, RangeError, ReferenceError,
+     * SyntaxError, TypeError, and URIError. Additional error names
+     * may be added in the future.
+     *
+     * See ECMA edition 3, 15.11.7.9.
+     *
+     * @return the name of the error.
+     */
+    public String getName()
+    {
+        return errorName;
+    }
+
+    /**
+     * Gets the message corresponding to the error.
+     *
+     * See ECMA edition 3, 15.11.7.10.
+     *
+     * @return an implementation-defined string describing the error.
+     */
+    public String getErrorMessage()
+    {
+        return errorMessage;
+    }
+
+    /**
+     * @deprecated Use {@link RhinoException#sourceName()} from the super class.
+     */
+    @Deprecated
+    public String getSourceName()
+    {
+        return sourceName();
+    }
+
+    /**
+     * @deprecated Use {@link RhinoException#lineNumber()} from the super class.
+     */
+    @Deprecated
+    public int getLineNumber()
+    {
+        return lineNumber();
+    }
+
+    /**
+     * @deprecated
+     * Use {@link RhinoException#columnNumber()} from the super class.
+     */
+    @Deprecated
+    public int getColumnNumber() {
+        return columnNumber();
+    }
+
+    /**
+     * @deprecated Use {@link RhinoException#lineSource()} from the super class.
+     */
+    @Deprecated
+    public String getLineSource() {
+        return lineSource();
+    }
+
+    /**
+     * @deprecated
+     * Always returns <b>null</b>.
+     */
+    @Deprecated
+    public Scriptable getErrorObject()
+    {
+        return null;
+    }
+}
diff -pruN 20130227+dfsg1-14/rhino/src/org/mozilla/javascript/ErrorReporter.java 20130227+rhino-1/rhino/src/org/mozilla/javascript/ErrorReporter.java
--- 20130227+dfsg1-14/rhino/src/org/mozilla/javascript/ErrorReporter.java	1970-01-01 00:00:00.000000000 +0000
+++ 20130227+rhino-1/rhino/src/org/mozilla/javascript/ErrorReporter.java	2023-05-25 14:24:50.000000000 +0000
@@ -0,0 +1,74 @@
+/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// API class
+
+package org.mozilla.javascript;
+
+/**
+ * This is interface defines a protocol for the reporting of
+ * errors during JavaScript translation or execution.
+ *
+ * @author Norris Boyd
+ */
+
+public interface ErrorReporter {
+
+    /**
+     * Report a warning.
+     *
+     * The implementing class may choose to ignore the warning
+     * if it desires.
+     *
+     * @param message a String describing the warning
+     * @param sourceName a String describing the JavaScript source
+     * where the warning occured; typically a filename or URL
+     * @param line the line number associated with the warning
+     * @param lineSource the text of the line (may be null)
+     * @param lineOffset the offset into lineSource where problem was detected
+     */
+    void warning(String message, String sourceName, int line,
+                 String lineSource, int lineOffset);
+
+    /**
+     * Report an error.
+     *
+     * The implementing class is free to throw an exception if
+     * it desires.
+     *
+     * If execution has not yet begun, the JavaScript engine is
+     * free to find additional errors rather than terminating
+     * the translation. It will not execute a script that had
+     * errors, however.
+     *
+     * @param message a String describing the error
+     * @param sourceName a String describing the JavaScript source
+     * where the error occured; typically a filename or URL
+     * @param line the line number associated with the error
+     * @param lineSource the text of the line (may be null)
+     * @param lineOffset the offset into lineSource where problem was detected
+     */
+    void error(String message, String sourceName, int line,
+               String lineSource, int lineOffset);
+
+    /**
+     * Creates an EvaluatorException that may be thrown.
+     *
+     * runtimeErrors, unlike errors, will always terminate the
+     * current script.
+     *
+     * @param message a String describing the error
+     * @param sourceName a String describing the JavaScript source
+     * where the error occured; typically a filename or URL
+     * @param line the line number associated with the error
+     * @param lineSource the text of the line (may be null)
+     * @param lineOffset the offset into lineSource where problem was detected
+     * @return an EvaluatorException that will be thrown.
+     */
+    EvaluatorException runtimeError(String message, String sourceName,
+                                    int line, String lineSource,
+                                    int lineOffset);
+}
diff -pruN 20130227+dfsg1-14/rhino/src/org/mozilla/javascript/Evaluator.java 20130227+rhino-1/rhino/src/org/mozilla/javascript/Evaluator.java
--- 20130227+dfsg1-14/rhino/src/org/mozilla/javascript/Evaluator.java	1970-01-01 00:00:00.000000000 +0000
+++ 20130227+rhino-1/rhino/src/org/mozilla/javascript/Evaluator.java	2023-05-25 14:24:50.000000000 +0000
@@ -0,0 +1,96 @@
+/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+package org.mozilla.javascript;
+
+import org.mozilla.javascript.ast.ScriptNode;
+
+import java.util.List;
+
+/**
+ * Abstraction of evaluation, which can be implemented either by an
+ * interpreter or compiler.
+ */
+public interface Evaluator {
+
+    /**
+     * Compile the script or function from intermediate representation
+     * tree into an executable form.
+     *
+     * @param compilerEnv Compiler environment
+     * @param tree parse tree
+     * @param encodedSource encoding of the source code for decompilation
+     * @param returnFunction if true, compiling a function
+     * @return an opaque object that can be passed to either
+     *         createFunctionObject or createScriptObject, depending on the
+     *         value of returnFunction
+     */
+    public Object compile(CompilerEnvirons compilerEnv,
+                          ScriptNode tree,
+                          String encodedSource,
+                          boolean returnFunction);
+
+    /**
+     * Create a function object.
+     *
+     * @param cx Current context
+     * @param scope scope of the function
+     * @param bytecode opaque object returned by compile
+     * @param staticSecurityDomain security domain
+     * @return Function object that can be called
+     */
+    public Function createFunctionObject(Context cx, Scriptable scope,
+            Object bytecode, Object staticSecurityDomain);
+
+    /**
+     * Create a script object.
+     *
+     * @param bytecode opaque object returned by compile
+     * @param staticSecurityDomain security domain
+     * @return Script object that can be evaluated
+     */
+    public Script createScriptObject(Object bytecode,
+                                     Object staticSecurityDomain);
+
+    /**
+     * Capture stack information from the given exception.
+     * @param ex an exception thrown during execution
+     */
+    public void captureStackInfo(RhinoException ex);
+
+    /**
+     * Get the source position information by examining the stack.
+     * @param cx Context
+     * @param linep Array object of length >= 1; getSourcePositionFromStack
+     *              will assign the line number to linep[0].
+     * @return the name of the file or other source container
+     */
+    public String getSourcePositionFromStack(Context cx, int[] linep);
+
+    /**
+     * Given a native stack trace, patch it with script-specific source
+     * and line information
+     * @param ex exception
+     * @param nativeStackTrace the native stack trace
+     * @return patched stack trace
+     */
+    public String getPatchedStack(RhinoException ex,
+                                  String nativeStackTrace);
+
+    /**
+     * Get the script stack for the given exception
+     * @param ex exception from execution
+     * @return list of strings for the stack trace
+     */
+    public List<String> getScriptStack(RhinoException ex);
+
+    /**
+     * Mark the given script to indicate it was created by a call to
+     * eval() or to a Function constructor.
+     * @param script script to mark as from eval
+     */
+    public void setEvalScriptFlag(Script script);
+}
diff -pruN 20130227+dfsg1-14/rhino/src/org/mozilla/javascript/EvaluatorException.java 20130227+rhino-1/rhino/src/org/mozilla/javascript/EvaluatorException.java
--- 20130227+dfsg1-14/rhino/src/org/mozilla/javascript/EvaluatorException.java	1970-01-01 00:00:00.000000000 +0000
+++ 20130227+rhino-1/rhino/src/org/mozilla/javascript/EvaluatorException.java	2023-05-25 14:24:50.000000000 +0000
@@ -0,0 +1,95 @@
+/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+
+package org.mozilla.javascript;
+
+/**
+ * The class of exceptions thrown by the JavaScript engine.
+ */
+public class EvaluatorException extends RhinoException
+{
+    static final long serialVersionUID = -8743165779676009808L;
+
+    public EvaluatorException(String detail)
+    {
+        super(detail);
+    }
+
+    /**
+     * Create an exception with the specified detail message.
+     *
+     * Errors internal to the JavaScript engine will simply throw a
+     * RuntimeException.
+     *
+     * @param detail the error message
+     * @param sourceName the name of the source reponsible for the error
+     * @param lineNumber the line number of the source
+     */
+    public EvaluatorException(String detail, String sourceName,
+                              int lineNumber)
+    {
+        this(detail, sourceName, lineNumber, null, 0);
+    }
+
+    /**
+     * Create an exception with the specified detail message.
+     *
+     * Errors internal to the JavaScript engine will simply throw a
+     * RuntimeException.
+     *
+     * @param detail the error message
+     * @param sourceName the name of the source responsible for the error
+     * @param lineNumber the line number of the source
+     * @param columnNumber the columnNumber of the source (may be zero if
+     *                     unknown)
+     * @param lineSource the source of the line containing the error (may be
+     *                   null if unknown)
+     */
+    public EvaluatorException(String detail, String sourceName, int lineNumber,
+                              String lineSource, int columnNumber)
+    {
+        super(detail);
+        recordErrorOrigin(sourceName, lineNumber, lineSource, columnNumber);
+    }
+
+    /**
+     * @deprecated Use {@link RhinoException#sourceName()} from the super class.
+     */
+    @Deprecated
+    public String getSourceName()
+    {
+        return sourceName();
+    }
+
+    /**
+     * @deprecated Use {@link RhinoException#lineNumber()} from the super class.
+     */
+    @Deprecated
+    public int getLineNumber()
+    {
+        return lineNumber();
+    }
+
+    /**
+     * @deprecated Use {@link RhinoException#columnNumber()} from the super class.
+     */
+    @Deprecated
+    public int getColumnNumber()
+    {
+        return columnNumber();
+    }
+
+    /**
+     * @deprecated Use {@link RhinoException#lineSource()} from the super class.
+     */
+    @Deprecated
+    public String getLineSource()
+    {
+        return lineSource();
+    }
+
+}
diff -pruN 20130227+dfsg1-14/rhino/src/org/mozilla/javascript/ExternalArrayData.java 20130227+rhino-1/rhino/src/org/mozilla/javascript/ExternalArrayData.java
--- 20130227+dfsg1-14/rhino/src/org/mozilla/javascript/ExternalArrayData.java	1970-01-01 00:00:00.000000000 +0000
+++ 20130227+rhino-1/rhino/src/org/mozilla/javascript/ExternalArrayData.java	2023-05-25 14:24:50.000000000 +0000
@@ -0,0 +1,32 @@
+/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+package org.mozilla.javascript;
+
+/**
+ * Implement this interface in order to allow external data to be attached to a ScriptableObject.
+ */
+
+public interface ExternalArrayData
+{
+    /**
+     * Return the element at the specified index. The result must be a type that is valid in JavaScript:
+     * Number, String, or Scriptable. This method will not be called unless "index" is in
+     * range.
+     */
+    Object getArrayElement(int index);
+
+    /**
+     * Set the element at the specified index. This method will not be called unless "index" is in
+     * range. The method must check that "value" is a valid type, and convert it if necessary.
+     */
+    void setArrayElement(int index, Object value);
+
+    /**
+     * Return the length of the array.
+     */
+    int getArrayLength();
+}
diff -pruN 20130227+dfsg1-14/rhino/src/org/mozilla/javascript/Function.java 20130227+rhino-1/rhino/src/org/mozilla/javascript/Function.java
--- 20130227+dfsg1-14/rhino/src/org/mozilla/javascript/Function.java	1970-01-01 00:00:00.000000000 +0000
+++ 20130227+rhino-1/rhino/src/org/mozilla/javascript/Function.java	2023-05-25 14:24:50.000000000 +0000
@@ -0,0 +1,52 @@
+/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// API class
+
+package org.mozilla.javascript;
+
+/**
+ * This is interface that all functions in JavaScript must implement.
+ * The interface provides for calling functions and constructors.
+ *
+ * @see org.mozilla.javascript.Scriptable
+ * @author Norris Boyd
+ */
+
+public interface Function extends Scriptable, Callable
+{
+    /**
+     * Call the function.
+     *
+     * Note that the array of arguments is not guaranteed to have
+     * length greater than 0.
+     *
+     * @param cx the current Context for this thread
+     * @param scope the scope to execute the function relative to. This is
+     *              set to the value returned by getParentScope() except
+     *              when the function is called from a closure.
+     * @param thisObj the JavaScript <code>this</code> object
+     * @param args the array of arguments
+     * @return the result of the call
+     */
+    public Object call(Context cx, Scriptable scope, Scriptable thisObj,
+                       Object[] args);
+
+    /**
+     * Call the function as a constructor.
+     *
+     * This method is invoked by the runtime in order to satisfy a use
+     * of the JavaScript <code>new</code> operator.  This method is
+     * expected to create a new object and return it.
+     *
+     * @param cx the current Context for this thread
+     * @param scope an enclosing scope of the caller except
+     *              when the function is called from a closure.
+     * @param args the array of arguments
+     * @return the allocated object
+     */
+    public Scriptable construct(Context cx, Scriptable scope, Object[] args);
+}
diff -pruN 20130227+dfsg1-14/rhino/src/org/mozilla/javascript/FunctionObject.java 20130227+rhino-1/rhino/src/org/mozilla/javascript/FunctionObject.java
--- 20130227+dfsg1-14/rhino/src/org/mozilla/javascript/FunctionObject.java	1970-01-01 00:00:00.000000000 +0000
+++ 20130227+rhino-1/rhino/src/org/mozilla/javascript/FunctionObject.java	2023-05-25 14:24:50.000000000 +0000
@@ -0,0 +1,546 @@
+/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// API class
+
+package org.mozilla.javascript;
+
+import java.lang.reflect.*;
+import java.io.*;
+
+public class FunctionObject extends BaseFunction
+{
+    static final long serialVersionUID = -5332312783643935019L;
+
+    /**
+     * Create a JavaScript function object from a Java method.
+     *
+     * <p>The <code>member</code> argument must be either a java.lang.reflect.Method
+     * or a java.lang.reflect.Constructor and must match one of two forms.<p>
+     *
+     * The first form is a member with zero or more parameters
+     * of the following types: Object, String, boolean, Scriptable,
+     * int, or double. The Long type is not supported
+     * because the double representation of a long (which is the
+     * EMCA-mandated storage type for Numbers) may lose precision.
+     * If the member is a Method, the return value must be void or one
+     * of the types allowed for parameters.<p>
+     *
+     * The runtime will perform appropriate conversions based
+     * upon the type of the parameter. A parameter type of
+     * Object specifies that no conversions are to be done. A parameter
+     * of type String will use Context.toString to convert arguments.
+     * Similarly, parameters of type double, boolean, and Scriptable
+     * will cause Context.toNumber, Context.toBoolean, and
+     * Context.toObject, respectively, to be called.<p>
+     *
+     * If the method is not static, the Java 'this' value will
+     * correspond to the JavaScript 'this' value. Any attempt
+     * to call the function with a 'this' value that is not
+     * of the right Java type will result in an error.<p>
+     *
+     * The second form is the variable arguments (or "varargs")
+     * form. If the FunctionObject will be used as a constructor,
+     * the member must have the following parameters
+     * <pre>
+     *      (Context cx, Object[] args, Function ctorObj,
+     *       boolean inNewExpr)</pre>
+     * and if it is a Method, be static and return an Object result.<p>
+     *
+     * Otherwise, if the FunctionObject will <i>not</i> be used to define a
+     * constructor, the member must be a static Method with parameters
+     * <pre>
+     *      (Context cx, Scriptable thisObj, Object[] args,
+     *       Function funObj) </pre>
+     * and an Object result.<p>
+     *
+     * When the function varargs form is called as part of a function call,
+     * the <code>args</code> parameter contains the
+     * arguments, with <code>thisObj</code>
+     * set to the JavaScript 'this' value. <code>funObj</code>
+     * is the function object for the invoked function.<p>
+     *
+     * When the constructor varargs form is called or invoked while evaluating
+     * a <code>new</code> expression, <code>args</code> contains the
+     * arguments, <code>ctorObj</code> refers to this FunctionObject, and
+     * <code>inNewExpr</code> is true if and only if  a <code>new</code>
+     * expression caused the call. This supports defining a function that
+     * has different behavior when called as a constructor than when
+     * invoked as a normal function call. (For example, the Boolean
+     * constructor, when called as a function,
+     * will convert to boolean rather than creating a new object.)<p>
+     *
+     * @param name the name of the function
+     * @param methodOrConstructor a java.lang.reflect.Method or a java.lang.reflect.Constructor
+     *                            that defines the object
+     * @param scope enclosing scope of function
+     * @see org.mozilla.javascript.Scriptable
+     */
+    public FunctionObject(String name, Member methodOrConstructor,
+                          Scriptable scope)
+    {
+        if (methodOrConstructor instanceof Constructor) {
+            member = new MemberBox((Constructor<?>) methodOrConstructor);
+            isStatic = true; // well, doesn't take a 'this'
+        } else {
+            member = new MemberBox((Method) methodOrConstructor);
+            isStatic = member.isStatic();
+        }
+        String methodName = member.getName();
+        this.functionName = name;
+        Class<?>[] types = member.argTypes;
+        int arity = types.length;
+        if (arity == 4 && (types[1].isArray() || types[2].isArray())) {
+            // Either variable args or an error.
+            if (types[1].isArray()) {
+                if (!isStatic ||
+                    types[0] != ScriptRuntime.ContextClass ||
+                    types[1].getComponentType() != ScriptRuntime.ObjectClass ||
+                    types[2] != ScriptRuntime.FunctionClass ||
+                    types[3] != Boolean.TYPE)
+                {
+                    throw Context.reportRuntimeError1(
+                        "msg.varargs.ctor", methodName);
+                }
+                parmsLength = VARARGS_CTOR;
+            } else {
+                if (!isStatic ||
+                    types[0] != ScriptRuntime.ContextClass ||
+                    types[1] != ScriptRuntime.ScriptableClass ||
+                    types[2].getComponentType() != ScriptRuntime.ObjectClass ||
+                    types[3] != ScriptRuntime.FunctionClass)
+                {
+                    throw Context.reportRuntimeError1(
+                        "msg.varargs.fun", methodName);
+                }
+                parmsLength = VARARGS_METHOD;
+            }
+        } else {
+            parmsLength = arity;
+            if (arity > 0) {
+                typeTags = new byte[arity];
+                for (int i = 0; i != arity; ++i) {
+                    int tag = getTypeTag(types[i]);
+                    if (tag == JAVA_UNSUPPORTED_TYPE) {
+                        throw Context.reportRuntimeError2(
+                            "msg.bad.parms", types[i].getName(), methodName);
+                    }
+                    typeTags[i] = (byte)tag;
+                }
+            }
+        }
+
+        if (member.isMethod()) {
+            Method method = member.method();
+            Class<?> returnType = method.getReturnType();
+            if (returnType == Void.TYPE) {
+                hasVoidReturn = true;
+            } else {
+                returnTypeTag = getTypeTag(returnType);
+            }
+        } else {
+            Class<?> ctorType = member.getDeclaringClass();
+            if (!ScriptRuntime.ScriptableClass.isAssignableFrom(ctorType)) {
+                throw Context.reportRuntimeError1(
+                    "msg.bad.ctor.return", ctorType.getName());
+            }
+        }
+
+        ScriptRuntime.setFunctionProtoAndParent(this, scope);
+    }
+
+    /**
+     * @return One of <tt>JAVA_*_TYPE</tt> constants to indicate desired type
+     *         or {@link #JAVA_UNSUPPORTED_TYPE} if the convertion is not
+     *         possible
+     */
+    public static int getTypeTag(Class<?> type)
+    {
+        if (type == ScriptRuntime.StringClass)
+            return JAVA_STRING_TYPE;
+        if (type == ScriptRuntime.IntegerClass || type == Integer.TYPE)
+            return JAVA_INT_TYPE;
+        if (type == ScriptRuntime.BooleanClass || type == Boolean.TYPE)
+            return JAVA_BOOLEAN_TYPE;
+        if (type == ScriptRuntime.DoubleClass || type == Double.TYPE)
+            return JAVA_DOUBLE_TYPE;
+        if (ScriptRuntime.ScriptableClass.isAssignableFrom(type))
+            return JAVA_SCRIPTABLE_TYPE;
+        if (type == ScriptRuntime.ObjectClass)
+            return JAVA_OBJECT_TYPE;
+
+        // Note that the long type is not supported; see the javadoc for
+        // the constructor for this class
+
+        return JAVA_UNSUPPORTED_TYPE;
+    }
+
+    public static Object convertArg(Context cx, Scriptable scope,
+                                    Object arg, int typeTag)
+    {
+        switch (typeTag) {
+          case JAVA_STRING_TYPE:
+              if (arg instanceof String)
+                return arg;
+            return ScriptRuntime.toString(arg);
+          case JAVA_INT_TYPE:
+              if (arg instanceof Integer)
+                return arg;
+            return Integer.valueOf(ScriptRuntime.toInt32(arg));
+          case JAVA_BOOLEAN_TYPE:
+              if (arg instanceof Boolean)
+                return arg;
+            return ScriptRuntime.toBoolean(arg) ? Boolean.TRUE
+                                                : Boolean.FALSE;
+          case JAVA_DOUBLE_TYPE:
+            if (arg instanceof Double)
+                return arg;
+            return new Double(ScriptRuntime.toNumber(arg));
+          case JAVA_SCRIPTABLE_TYPE:
+              return ScriptRuntime.toObjectOrNull(cx, arg, scope);
+          case JAVA_OBJECT_TYPE:
+            return arg;
+          default:
+            throw new IllegalArgumentException();
+        }
+    }
+
+    /**
+     * Return the value defined by  the method used to construct the object
+     * (number of parameters of the method, or 1 if the method is a "varargs"
+     * form).
+     */
+    @Override
+    public int getArity() {
+        return parmsLength < 0 ? 1 : parmsLength;
+    }
+
+    /**
+     * Return the same value as {@link #getArity()}.
+     */
+    @Override
+    public int getLength() {
+        return getArity();
+    }
+
+    @Override
+    public String getFunctionName()
+    {
+        return (functionName == null) ? "" : functionName;
+    }
+
+    /**
+     * Get Java method or constructor this function represent.
+     */
+    public Member getMethodOrConstructor()
+    {
+        if (member.isMethod()) {
+            return member.method();
+        } else {
+            return member.ctor();
+        }
+    }
+
+    static Method findSingleMethod(Method[] methods, String name)
+    {
+        Method found = null;
+        for (int i = 0, N = methods.length; i != N; ++i) {
+            Method method = methods[i];
+            if (method != null && name.equals(method.getName())) {
+                if (found != null) {
+                    throw Context.reportRuntimeError2(
+                        "msg.no.overload", name,
+                        method.getDeclaringClass().getName());
+                }
+                found = method;
+            }
+        }
+        return found;
+    }
+
+    /**
+     * Returns all public methods declared by the specified class. This excludes
+     * inherited methods.
+     *
+     * @param clazz the class from which to pull public declared methods
+     * @return the public methods declared in the specified class
+     * @see Class#getDeclaredMethods()
+     */
+    static Method[] getMethodList(Class<?> clazz) {
+        Method[] methods = null;
+        try {
+            // getDeclaredMethods may be rejected by the security manager
+            // but getMethods is more expensive
+            if (!sawSecurityException)
+                methods = clazz.getDeclaredMethods();
+        } catch (SecurityException e) {
+            // If we get an exception once, give up on getDeclaredMethods
+            sawSecurityException = true;
+        }
+        if (methods == null) {
+            methods = clazz.getMethods();
+        }
+        int count = 0;
+        for (int i=0; i < methods.length; i++) {
+            if (sawSecurityException
+                ? methods[i].getDeclaringClass() != clazz
+                : !Modifier.isPublic(methods[i].getModifiers()))
+            {
+                methods[i] = null;
+            } else {
+                count++;
+            }
+        }
+        Method[] result = new Method[count];
+        int j=0;
+        for (int i=0; i < methods.length; i++) {
+            if (methods[i] != null)
+                result[j++] = methods[i];
+        }
+        return result;
+    }
+
+    /**
+     * Define this function as a JavaScript constructor.
+     * <p>
+     * Sets up the "prototype" and "constructor" properties. Also
+     * calls setParent and setPrototype with appropriate values.
+     * Then adds the function object as a property of the given scope, using
+     *      <code>prototype.getClassName()</code>
+     * as the name of the property.
+     *
+     * @param scope the scope in which to define the constructor (typically
+     *              the global object)
+     * @param prototype the prototype object
+     * @see org.mozilla.javascript.Scriptable#setParentScope
+     * @see org.mozilla.javascript.Scriptable#setPrototype
+     * @see org.mozilla.javascript.Scriptable#getClassName
+     */
+    public void addAsConstructor(Scriptable scope, Scriptable prototype)
+    {
+        initAsConstructor(scope, prototype);
+        defineProperty(scope, prototype.getClassName(),
+                       this, ScriptableObject.DONTENUM);
+    }
+
+    void initAsConstructor(Scriptable scope, Scriptable prototype)
+    {
+        ScriptRuntime.setFunctionProtoAndParent(this, scope);
+        setImmunePrototypeProperty(prototype);
+
+        prototype.setParentScope(this);
+
+        defineProperty(prototype, "constructor", this,
+                       ScriptableObject.DONTENUM  |
+                       ScriptableObject.PERMANENT |
+                       ScriptableObject.READONLY);
+        setParentScope(scope);
+    }
+
+    /**
+     * @deprecated Use {@link #getTypeTag(Class)}
+     * and {@link #convertArg(Context, Scriptable, Object, int)}
+     * for type conversion.
+     */
+    @Deprecated
+    public static Object convertArg(Context cx, Scriptable scope,
+                                    Object arg, Class<?> desired)
+    {
+        int tag = getTypeTag(desired);
+        if (tag == JAVA_UNSUPPORTED_TYPE) {
+            throw Context.reportRuntimeError1
+                ("msg.cant.convert", desired.getName());
+        }
+        return convertArg(cx, scope, arg, tag);
+    }
+
+    /**
+     * Performs conversions on argument types if needed and
+     * invokes the underlying Java method or constructor.
+     * <p>
+     * Implements Function.call.
+     *
+     * @see org.mozilla.javascript.Function#call(
+     *          Context, Scriptable, Scriptable, Object[])
+     */
+    @Override
+    public Object call(Context cx, Scriptable scope, Scriptable thisObj,
+                       Object[] args)
+    {
+        Object result;
+        boolean checkMethodResult = false;
+        int argsLength = args.length;
+
+        for (int i = 0; i < argsLength; i++) {
+            // flatten cons-strings before passing them as arguments
+            if (args[i] instanceof ConsString) {
+                args[i] = args[i].toString();
+            }
+        }
+
+        if (parmsLength < 0) {
+            if (parmsLength == VARARGS_METHOD) {
+                Object[] invokeArgs = { cx, thisObj, args, this };
+                result = member.invoke(null, invokeArgs);
+                checkMethodResult = true;
+            } else {
+                boolean inNewExpr = (thisObj == null);
+                Boolean b = inNewExpr ? Boolean.TRUE : Boolean.FALSE;
+                Object[] invokeArgs = { cx, args, this, b };
+                result = (member.isCtor())
+                         ? member.newInstance(invokeArgs)
+                         : member.invoke(null, invokeArgs);
+            }
+
+        } else {
+            if (!isStatic) {
+                Class<?> clazz = member.getDeclaringClass();
+                if (!clazz.isInstance(thisObj)) {
+                    boolean compatible = false;
+                    if (thisObj == scope) {
+                        Scriptable parentScope = getParentScope();
+                        if (scope != parentScope) {
+                            // Call with dynamic scope for standalone function,
+                            // use parentScope as thisObj
+                            compatible = clazz.isInstance(parentScope);
+                            if (compatible) {
+                                thisObj = parentScope;
+                            }
+                        }
+                    }
+                    if (!compatible) {
+                        // Couldn't find an object to call this on.
+                        throw ScriptRuntime.typeError1("msg.incompat.call",
+                                                       functionName);
+                    }
+                }
+            }
+
+            Object[] invokeArgs;
+            if (parmsLength == argsLength) {
+                // Do not allocate new argument array if java arguments are
+                // the same as the original js ones.
+                invokeArgs = args;
+                for (int i = 0; i != parmsLength; ++i) {
+                    Object arg = args[i];
+                    Object converted = convertArg(cx, scope, arg, typeTags[i]);
+                    if (arg != converted) {
+                        if (invokeArgs == args) {
+                            invokeArgs = args.clone();
+                        }
+                        invokeArgs[i] = converted;
+                    }
+                }
+            } else if (parmsLength == 0) {
+                invokeArgs = ScriptRuntime.emptyArgs;
+            } else {
+                invokeArgs = new Object[parmsLength];
+                for (int i = 0; i != parmsLength; ++i) {
+                    Object arg = (i < argsLength)
+                                 ? args[i]
+                                 : Undefined.instance;
+                    invokeArgs[i] = convertArg(cx, scope, arg, typeTags[i]);
+                }
+            }
+
+            if (member.isMethod()) {
+                result = member.invoke(thisObj, invokeArgs);
+                checkMethodResult = true;
+            } else {
+                result = member.newInstance(invokeArgs);
+            }
+
+        }
+
+        if (checkMethodResult) {
+            if (hasVoidReturn) {
+                result = Undefined.instance;
+            } else if (returnTypeTag == JAVA_UNSUPPORTED_TYPE) {
+                result = cx.getWrapFactory().wrap(cx, scope, result, null);
+            }
+            // XXX: the code assumes that if returnTypeTag == JAVA_OBJECT_TYPE
+            // then the Java method did a proper job of converting the
+            // result to JS primitive or Scriptable to avoid
+            // potentially costly Context.javaToJS call.
+        }
+
+        return result;
+    }
+
+    /**
+     * Return new {@link Scriptable} instance using the default
+     * constructor for the class of the underlying Java method.
+     * Return null to indicate that the call method should be used to create
+     * new objects.
+     */
+    @Override
+    public Scriptable createObject(Context cx, Scriptable scope) {
+        if (member.isCtor() || parmsLength == VARARGS_CTOR) {
+            return null;
+        }
+        Scriptable result;
+        try {
+            result = (Scriptable) member.getDeclaringClass().newInstance();
+        } catch (Exception ex) {
+            throw Context.throwAsScriptRuntimeEx(ex);
+        }
+
+        result.setPrototype(getClassPrototype());
+        result.setParentScope(getParentScope());
+        return result;
+    }
+
+    boolean isVarArgsMethod() {
+        return parmsLength == VARARGS_METHOD;
+    }
+
+    boolean isVarArgsConstructor() {
+        return parmsLength == VARARGS_CTOR;
+    }
+
+    private void readObject(ObjectInputStream in)
+        throws IOException, ClassNotFoundException
+    {
+        in.defaultReadObject();
+        if (parmsLength > 0) {
+            Class<?>[] types = member.argTypes;
+            typeTags = new byte[parmsLength];
+            for (int i = 0; i != parmsLength; ++i) {
+                typeTags[i] = (byte)getTypeTag(types[i]);
+            }
+        }
+        if (member.isMethod()) {
+            Method method = member.method();
+            Class<?> returnType = method.getReturnType();
+            if (returnType == Void.TYPE) {
+                hasVoidReturn = true;
+            } else {
+                returnTypeTag = getTypeTag(returnType);
+            }
+        }
+    }
+
+    private static final short VARARGS_METHOD = -1;
+    private static final short VARARGS_CTOR =   -2;
+
+    private static boolean sawSecurityException;
+
+    public static final int JAVA_UNSUPPORTED_TYPE = 0;
+    public static final int JAVA_STRING_TYPE      = 1;
+    public static final int JAVA_INT_TYPE         = 2;
+    public static final int JAVA_BOOLEAN_TYPE     = 3;
+    public static final int JAVA_DOUBLE_TYPE      = 4;
+    public static final int JAVA_SCRIPTABLE_TYPE  = 5;
+    public static final int JAVA_OBJECT_TYPE      = 6;
+
+    MemberBox member;
+    private String functionName;
+    private transient byte[] typeTags;
+    private int parmsLength;
+    private transient boolean hasVoidReturn;
+    private transient int returnTypeTag;
+    private boolean isStatic;
+}
diff -pruN 20130227+dfsg1-14/rhino/src/org/mozilla/javascript/GeneratedClassLoader.java 20130227+rhino-1/rhino/src/org/mozilla/javascript/GeneratedClassLoader.java
--- 20130227+dfsg1-14/rhino/src/org/mozilla/javascript/GeneratedClassLoader.java	1970-01-01 00:00:00.000000000 +0000
+++ 20130227+rhino-1/rhino/src/org/mozilla/javascript/GeneratedClassLoader.java	2023-05-25 14:24:50.000000000 +0000
@@ -0,0 +1,34 @@
+/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// API class
+
+package org.mozilla.javascript;
+
+/**
+ * Interface to define classes from generated byte code.
+ */
+public interface GeneratedClassLoader {
+
+    /**
+     * Define a new Java class.
+     * Classes created via this method should have the same class loader.
+     *
+     * @param name fully qualified class name
+     * @param data class byte code
+     * @return new class object
+     */
+    public Class<?> defineClass(String name, byte[] data);
+
+    /**
+     * Link the given class.
+     *
+     * @param cl Class instance returned from the previous call to
+     *        {@link #defineClass(String, byte[])}
+     * @see java.lang.ClassLoader
+     */
+    public void linkClass(Class<?> cl);
+}
diff -pruN 20130227+dfsg1-14/rhino/src/org/mozilla/javascript/IRFactory.java 20130227+rhino-1/rhino/src/org/mozilla/javascript/IRFactory.java
--- 20130227+dfsg1-14/rhino/src/org/mozilla/javascript/IRFactory.java	1970-01-01 00:00:00.000000000 +0000
+++ 20130227+rhino-1/rhino/src/org/mozilla/javascript/IRFactory.java	2023-05-25 14:24:50.000000000 +0000
@@ -0,0 +1,2462 @@
+/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+package org.mozilla.javascript;
+
+import org.mozilla.javascript.ast.ArrayComprehension;
+import org.mozilla.javascript.ast.ArrayComprehensionLoop;
+import org.mozilla.javascript.ast.ArrayLiteral;
+import org.mozilla.javascript.ast.Assignment;
+import org.mozilla.javascript.ast.AstNode;
+import org.mozilla.javascript.ast.AstRoot;
+import org.mozilla.javascript.ast.Block;
+import org.mozilla.javascript.ast.BreakStatement;
+import org.mozilla.javascript.ast.CatchClause;
+import org.mozilla.javascript.ast.ConditionalExpression;
+import org.mozilla.javascript.ast.ContinueStatement;
+import org.mozilla.javascript.ast.DestructuringForm;
+import org.mozilla.javascript.ast.DoLoop;
+import org.mozilla.javascript.ast.ElementGet;
+import org.mozilla.javascript.ast.EmptyExpression;
+import org.mozilla.javascript.ast.ExpressionStatement;
+import org.mozilla.javascript.ast.ForInLoop;
+import org.mozilla.javascript.ast.ForLoop;
+import org.mozilla.javascript.ast.FunctionCall;
+import org.mozilla.javascript.ast.FunctionNode;
+import org.mozilla.javascript.ast.GeneratorExpression;
+import org.mozilla.javascript.ast.GeneratorExpressionLoop;
+import org.mozilla.javascript.ast.IfStatement;
+import org.mozilla.javascript.ast.InfixExpression;
+import org.mozilla.javascript.ast.Jump;
+import org.mozilla.javascript.ast.Label;
+import org.mozilla.javascript.ast.LabeledStatement;
+import org.mozilla.javascript.ast.LetNode;
+import org.mozilla.javascript.ast.Loop;
+import org.mozilla.javascript.ast.Name;
+import org.mozilla.javascript.ast.NewExpression;
+import org.mozilla.javascript.ast.NumberLiteral;
+import org.mozilla.javascript.ast.ObjectLiteral;
+import org.mozilla.javascript.ast.ObjectProperty;
+import org.mozilla.javascript.ast.ParenthesizedExpression;
+import org.mozilla.javascript.ast.PropertyGet;
+import org.mozilla.javascript.ast.RegExpLiteral;
+import org.mozilla.javascript.ast.ReturnStatement;
+import org.mozilla.javascript.ast.Scope;
+import org.mozilla.javascript.ast.ScriptNode;
+import org.mozilla.javascript.ast.StringLiteral;
+import org.mozilla.javascript.ast.SwitchCase;
+import org.mozilla.javascript.ast.SwitchStatement;
+import org.mozilla.javascript.ast.Symbol;
+import org.mozilla.javascript.ast.ThrowStatement;
+import org.mozilla.javascript.ast.TryStatement;
+import org.mozilla.javascript.ast.UnaryExpression;
+import org.mozilla.javascript.ast.VariableDeclaration;
+import org.mozilla.javascript.ast.VariableInitializer;
+import org.mozilla.javascript.ast.WhileLoop;
+import org.mozilla.javascript.ast.WithStatement;
+import org.mozilla.javascript.ast.XmlDotQuery;
+import org.mozilla.javascript.ast.XmlElemRef;
+import org.mozilla.javascript.ast.XmlExpression;
+import org.mozilla.javascript.ast.XmlFragment;
+import org.mozilla.javascript.ast.XmlLiteral;
+import org.mozilla.javascript.ast.XmlMemberGet;
+import org.mozilla.javascript.ast.XmlPropRef;
+import org.mozilla.javascript.ast.XmlRef;
+import org.mozilla.javascript.ast.XmlString;
+import org.mozilla.javascript.ast.Yield;
+
+import java.util.List;
+import java.util.ArrayList;
+
+/**
+ * This class rewrites the parse tree into an IR suitable for codegen.
+ *
+ * @see Node
+ * @author Mike McCabe
+ * @author Norris Boyd
+ */
+public final class IRFactory extends Parser
+{
+    private static final int LOOP_DO_WHILE = 0;
+    private static final int LOOP_WHILE    = 1;
+    private static final int LOOP_FOR      = 2;
+
+    private static final int ALWAYS_TRUE_BOOLEAN = 1;
+    private static final int ALWAYS_FALSE_BOOLEAN = -1;
+
+    private Decompiler decompiler = new Decompiler();
+
+    public IRFactory() {
+        super();
+    }
+
+    public IRFactory(CompilerEnvirons env) {
+        this(env, env.getErrorReporter());
+    }
+
+    public IRFactory(CompilerEnvirons env, ErrorReporter errorReporter) {
+        super(env, errorReporter);
+    }
+
+    /**
+     * Transforms the tree into a lower-level IR suitable for codegen.
+     * Optionally generates the encoded source.
+     */
+    public ScriptNode transformTree(AstRoot root) {
+        currentScriptOrFn = root;
+        this.inUseStrictDirective = root.isInStrictMode();
+        int sourceStartOffset = decompiler.getCurrentOffset();
+
+        if (Token.printTrees) {
+            System.out.println("IRFactory.transformTree");
+            System.out.println(root.debugPrint());
+        }
+        ScriptNode script = (ScriptNode)transform(root);
+
+        int sourceEndOffset = decompiler.getCurrentOffset();
+        script.setEncodedSourceBounds(sourceStartOffset,
+                                      sourceEndOffset);
+
+        if (compilerEnv.isGeneratingSource()) {
+            script.setEncodedSource(decompiler.getEncodedSource());
+        }
+
+        decompiler = null;
+        return script;
+    }
+
+    // Might want to convert this to polymorphism - move transform*
+    // functions into the AstNode subclasses.  OTOH that would make
+    // IR transformation part of the public AST API - desirable?
+    // Another possibility:  create AstTransformer interface and adapter.
+    public Node transform(AstNode node) {
+        switch (node.getType()) {
+          case Token.ARRAYCOMP:
+              return transformArrayComp((ArrayComprehension)node);
+          case Token.ARRAYLIT:
+              return transformArrayLiteral((ArrayLiteral)node);
+          case Token.BLOCK:
+              return transformBlock(node);
+          case Token.BREAK:
+              return transformBreak((BreakStatement)node);
+          case Token.CALL:
+              return transformFunctionCall((FunctionCall)node);
+          case Token.CONTINUE:
+              return transformContinue((ContinueStatement)node);
+          case Token.DO:
+              return transformDoLoop((DoLoop)node);
+          case Token.EMPTY:
+              return node;
+          case Token.FOR:
+              if (node instanceof ForInLoop) {
+                  return transformForInLoop((ForInLoop)node);
+              } else {
+                  return transformForLoop((ForLoop)node);
+              }
+          case Token.FUNCTION:
+              return transformFunction((FunctionNode)node);
+          case Token.GENEXPR:
+              return transformGenExpr((GeneratorExpression)node);
+          case Token.GETELEM:
+              return transformElementGet((ElementGet)node);
+          case Token.GETPROP:
+              return transformPropertyGet((PropertyGet)node);
+          case Token.HOOK:
+              return transformCondExpr((ConditionalExpression)node);
+          case Token.IF:
+              return transformIf((IfStatement)node);
+
+          case Token.TRUE:
+          case Token.FALSE:
+          case Token.THIS:
+          case Token.NULL:
+          case Token.DEBUGGER:
+              return transformLiteral(node);
+
+          case Token.NAME:
+              return transformName((Name)node);
+          case Token.NUMBER:
+              return transformNumber((NumberLiteral)node);
+          case Token.NEW:
+              return transformNewExpr((NewExpression)node);
+          case Token.OBJECTLIT:
+              return transformObjectLiteral((ObjectLiteral)node);
+          case Token.REGEXP:
+              return transformRegExp((RegExpLiteral)node);
+          case Token.RETURN:
+              return transformReturn((ReturnStatement)node);
+          case Token.SCRIPT:
+              return transformScript((ScriptNode)node);
+          case Token.STRING:
+              return transformString((StringLiteral)node);
+          case Token.SWITCH:
+              return transformSwitch((SwitchStatement)node);
+          case Token.THROW:
+              return transformThrow((ThrowStatement)node);
+          case Token.TRY:
+              return transformTry((TryStatement)node);
+          case Token.WHILE:
+              return transformWhileLoop((WhileLoop)node);
+          case Token.WITH:
+              return transformWith((WithStatement)node);
+          case Token.YIELD:
+              return transformYield((Yield)node);
+          default:
+              if (node instanceof ExpressionStatement) {
+                  return transformExprStmt((ExpressionStatement)node);
+              }
+              if (node instanceof Assignment) {
+                  return transformAssignment((Assignment)node);
+              }
+              if (node instanceof UnaryExpression) {
+                  return transformUnary((UnaryExpression)node);
+              }
+              if (node instanceof XmlMemberGet) {
+                  return transformXmlMemberGet((XmlMemberGet)node);
+              }
+              if (node instanceof InfixExpression) {
+                  return transformInfix((InfixExpression)node);
+              }
+              if (node instanceof VariableDeclaration) {
+                  return transformVariables((VariableDeclaration)node);
+              }
+              if (node instanceof ParenthesizedExpression) {
+                  return transformParenExpr((ParenthesizedExpression)node);
+              }
+              if (node instanceof LabeledStatement) {
+                  return transformLabeledStatement((LabeledStatement)node);
+              }
+              if (node instanceof LetNode) {
+                  return transformLetNode((LetNode)node);
+              }
+              if (node instanceof XmlRef) {
+                  return transformXmlRef((XmlRef)node);
+              }
+              if (node instanceof XmlLiteral) {
+                  return transformXmlLiteral((XmlLiteral)node);
+              }
+              throw new IllegalArgumentException("Can't transform: " + node);
+        }
+    }
+
+    private Node transformArrayComp(ArrayComprehension node) {
+        // An array comprehension expression such as
+        //
+        //   [expr for (x in foo) for each ([y, z] in bar) if (cond)]
+        //
+        // is rewritten approximately as
+        //
+        // new Scope(ARRAYCOMP) {
+        //   new Node(BLOCK) {
+        //     let tmp1 = new Array;
+        //     for (let x in foo) {
+        //       for each (let tmp2 in bar) {
+        //         if (cond) {
+        //           tmp1.push([y, z] = tmp2, expr);
+        //         }
+        //       }
+        //     }
+        //   }
+        //   createName(tmp1)
+        // }
+
+        int lineno = node.getLineno();
+        Scope scopeNode = createScopeNode(Token.ARRAYCOMP, lineno);
+        String arrayName = currentScriptOrFn.getNextTempName();
+        pushScope(scopeNode);
+        try {
+            defineSymbol(Token.LET, arrayName, false);
+            Node block = new Node(Token.BLOCK, lineno);
+            Node newArray = createCallOrNew(Token.NEW, createName("Array"));
+            Node init = new Node(Token.EXPR_VOID,
+                                 createAssignment(Token.ASSIGN,
+                                                  createName(arrayName),
+                                                  newArray),
+                                 lineno);
+            block.addChildToBack(init);
+            block.addChildToBack(arrayCompTransformHelper(node, arrayName));
+            scopeNode.addChildToBack(block);
+            scopeNode.addChildToBack(createName(arrayName));
+            return scopeNode;
+        } finally {
+            popScope();
+        }
+    }
+
+    private Node arrayCompTransformHelper(ArrayComprehension node,
+                                          String arrayName) {
+        decompiler.addToken(Token.LB);
+        int lineno = node.getLineno();
+        Node expr = transform(node.getResult());
+
+        List<ArrayComprehensionLoop> loops = node.getLoops();
+        int numLoops = loops.size();
+
+        // Walk through loops, collecting and defining their iterator symbols.
+        Node[] iterators = new Node[numLoops];
+        Node[] iteratedObjs = new Node[numLoops];
+
+        for (int i = 0; i < numLoops; i++) {
+            ArrayComprehensionLoop acl = loops.get(i);
+            decompiler.addName(" ");
+            decompiler.addToken(Token.FOR);
+            if (acl.isForEach()) {
+                decompiler.addName("each ");
+            }
+            decompiler.addToken(Token.LP);
+
+            AstNode iter = acl.getIterator();
+            String name = null;
+            if (iter.getType() == Token.NAME) {
+                name = iter.getString();
+                decompiler.addName(name);
+            } else {
+                // destructuring assignment
+                decompile(iter);
+                name = currentScriptOrFn.getNextTempName();
+                defineSymbol(Token.LP, name, false);
+                expr = createBinary(Token.COMMA,
+                                    createAssignment(Token.ASSIGN,
+                                                     iter,
+                                                     createName(name)),
+                                    expr);
+            }
+            Node init = createName(name);
+            // Define as a let since we want the scope of the variable to
+            // be restricted to the array comprehension
+            defineSymbol(Token.LET, name, false);
+            iterators[i] = init;
+
+            if (acl.isForOf()) {
+                decompiler.addName("of ");
+            } else {
+                decompiler.addToken(Token.IN);
+            }
+            iteratedObjs[i] = transform(acl.getIteratedObject());
+            decompiler.addToken(Token.RP);
+        }
+
+        // generate code for tmpArray.push(body)
+        Node call = createCallOrNew(Token.CALL,
+                                    createPropertyGet(createName(arrayName),
+                                                      null,
+                                                      "push", 0));
+
+        Node body = new Node(Token.EXPR_VOID, call, lineno);
+
+        if (node.getFilter() != null) {
+            decompiler.addName(" ");
+            decompiler.addToken(Token.IF);
+            decompiler.addToken(Token.LP);
+            body = createIf(transform(node.getFilter()), body, null, lineno);
+            decompiler.addToken(Token.RP);
+        }
+
+        // Now walk loops in reverse to build up the body statement.
+        int pushed = 0;
+        try {
+            for (int i = numLoops-1; i >= 0; i--) {
+                ArrayComprehensionLoop acl = loops.get(i);
+                Scope loop = createLoopNode(null,  // no label
+                                            acl.getLineno());
+                pushScope(loop);
+                pushed++;
+                body = createForIn(Token.LET,
+                                   loop,
+                                   iterators[i],
+                                   iteratedObjs[i],
+                                   body,
+                                   acl.isForEach(),
+                                   acl.isForOf());
+            }
+        } finally {
+            for (int i = 0; i < pushed; i++) {
+                popScope();
+            }
+        }
+
+        decompiler.addToken(Token.RB);
+
+        // Now that we've accumulated any destructuring forms,
+        // add expr to the call node; it's pushed on each iteration.
+        call.addChildToBack(expr);
+        return body;
+    }
+
+    private Node transformArrayLiteral(ArrayLiteral node) {
+        if (node.isDestructuring()) {
+            return node;
+        }
+        decompiler.addToken(Token.LB);
+        List<AstNode> elems = node.getElements();
+        Node array = new Node(Token.ARRAYLIT);
+        List<Integer> skipIndexes = null;
+        for (int i = 0; i < elems.size(); ++i) {
+            AstNode elem = elems.get(i);
+            if (elem.getType() != Token.EMPTY) {
+                array.addChildToBack(transform(elem));
+            } else {
+                if (skipIndexes == null) {
+                    skipIndexes = new ArrayList<Integer>();
+                }
+                skipIndexes.add(i);
+            }
+            if (i < elems.size() - 1)
+                decompiler.addToken(Token.COMMA);
+        }
+        decompiler.addToken(Token.RB);
+        array.putIntProp(Node.DESTRUCTURING_ARRAY_LENGTH,
+                         node.getDestructuringLength());
+        if (skipIndexes != null) {
+            int[] skips = new int[skipIndexes.size()];
+            for (int i = 0; i < skipIndexes.size(); i++)
+                skips[i] = skipIndexes.get(i);
+            array.putProp(Node.SKIP_INDEXES_PROP, skips);
+        }
+        return array;
+    }
+
+    private Node transformAssignment(Assignment node) {
+        AstNode left = removeParens(node.getLeft());
+        Node target = null;
+        if (isDestructuring(left)) {
+            decompile(left);
+            target = left;
+        } else {
+            target = transform(left);
+        }
+        decompiler.addToken(node.getType());
+        return createAssignment(node.getType(),
+                                target,
+                                transform(node.getRight()));
+    }
+
+    private Node transformBlock(AstNode node) {
+        if (node instanceof Scope) {
+            pushScope((Scope)node);
+        }
+        try {
+            List<Node> kids = new ArrayList<Node>();
+            for (Node kid : node) {
+                kids.add(transform((AstNode)kid));
+            }
+            node.removeChildren();
+            for (Node kid : kids) {
+                node.addChildToBack(kid);
+            }
+            return node;
+        } finally {
+            if (node instanceof Scope) {
+                popScope();
+            }
+        }
+    }
+
+    private Node transformBreak(BreakStatement node) {
+        decompiler.addToken(Token.BREAK);
+        if (node.getBreakLabel() != null) {
+            decompiler.addName(node.getBreakLabel().getIdentifier());
+        }
+        decompiler.addEOL(Token.SEMI);
+        return node;
+    }
+
+    private Node transformCondExpr(ConditionalExpression node) {
+        Node test = transform(node.getTestExpression());
+        decompiler.addToken(Token.HOOK);
+        Node ifTrue = transform(node.getTrueExpression());
+        decompiler.addToken(Token.COLON);
+        Node ifFalse = transform(node.getFalseExpression());
+        return createCondExpr(test, ifTrue, ifFalse);
+    }
+
+    private Node transformContinue(ContinueStatement node) {
+        decompiler.addToken(Token.CONTINUE);
+        if (node.getLabel() != null) {
+            decompiler.addName(node.getLabel().getIdentifier());
+        }
+        decompiler.addEOL(Token.SEMI);
+        return node;
+    }
+
+    private Node transformDoLoop(DoLoop loop) {
+        loop.setType(Token.LOOP);
+        pushScope(loop);
+        try {
+            decompiler.addToken(Token.DO);
+            decompiler.addEOL(Token.LC);
+            Node body = transform(loop.getBody());
+            decompiler.addToken(Token.RC);
+            decompiler.addToken(Token.WHILE);
+            decompiler.addToken(Token.LP);
+            Node cond = transform(loop.getCondition());
+            decompiler.addToken(Token.RP);
+            decompiler.addEOL(Token.SEMI);
+            return createLoop(loop, LOOP_DO_WHILE,
+                              body, cond, null, null);
+        } finally {
+            popScope();
+        }
+    }
+
+    private Node transformElementGet(ElementGet node) {
+        // OPT: could optimize to createPropertyGet
+        // iff elem is string that can not be number
+        Node target = transform(node.getTarget());
+        decompiler.addToken(Token.LB);
+        Node element = transform(node.getElement());
+        decompiler.addToken(Token.RB);
+        return new Node(Token.GETELEM, target, element);
+    }
+
+    private Node transformExprStmt(ExpressionStatement node) {
+        Node expr = transform(node.getExpression());
+        decompiler.addEOL(Token.SEMI);
+        return new Node(node.getType(), expr, node.getLineno());
+    }
+
+    private Node transformForInLoop(ForInLoop loop) {
+        decompiler.addToken(Token.FOR);
+        if (loop.isForEach())
+            decompiler.addName("each ");
+        decompiler.addToken(Token.LP);
+
+        loop.setType(Token.LOOP);
+        pushScope(loop);
+        try {
+            int declType = -1;
+            AstNode iter = loop.getIterator();
+            if (iter instanceof VariableDeclaration) {
+                declType = ((VariableDeclaration)iter).getType();
+            }
+            Node lhs = transform(iter);
+            if (loop.isForOf()) {
+                decompiler.addName("of ");
+            } else {
+                decompiler.addToken(Token.IN);
+            }
+            Node obj = transform(loop.getIteratedObject());
+            decompiler.addToken(Token.RP);
+            decompiler.addEOL(Token.LC);
+            Node body = transform(loop.getBody());
+            decompiler.addEOL(Token.RC);
+            return createForIn(declType, loop, lhs, obj, body,
+                               loop.isForEach(), loop.isForOf());
+        } finally {
+            popScope();
+        }
+    }
+
+    private Node transformForLoop(ForLoop loop) {
+        decompiler.addToken(Token.FOR);
+        decompiler.addToken(Token.LP);
+        loop.setType(Token.LOOP);
+        // XXX: Can't use pushScope/popScope here since 'createFor' may split
+        // the scope
+        Scope savedScope = currentScope;
+        currentScope = loop;
+        try {
+            Node init = transform(loop.getInitializer());
+            decompiler.addToken(Token.SEMI);
+            Node test = transform(loop.getCondition());
+            decompiler.addToken(Token.SEMI);
+            Node incr = transform(loop.getIncrement());
+            decompiler.addToken(Token.RP);
+            decompiler.addEOL(Token.LC);
+            Node body = transform(loop.getBody());
+            decompiler.addEOL(Token.RC);
+            return createFor(loop, init, test, incr, body);
+        } finally {
+            currentScope = savedScope;
+        }
+    }
+
+    private Node transformFunction(FunctionNode fn) {
+        int functionType = fn.getFunctionType();
+        int start = decompiler.markFunctionStart(functionType);
+        Node mexpr = decompileFunctionHeader(fn);
+        int index = currentScriptOrFn.addFunction(fn);
+
+        PerFunctionVariables savedVars = new PerFunctionVariables(fn);
+        try {
+            // If we start needing to record much more codegen metadata during
+            // function parsing, we should lump it all into a helper class.
+            Node destructuring = (Node)fn.getProp(Node.DESTRUCTURING_PARAMS);
+            fn.removeProp(Node.DESTRUCTURING_PARAMS);
+
+            int lineno = fn.getBody().getLineno();
+            ++nestingOfFunction;  // only for body, not params
+            Node body = transform(fn.getBody());
+
+            if (!fn.isExpressionClosure()) {
+                decompiler.addToken(Token.RC);
+            }
+            fn.setEncodedSourceBounds(start, decompiler.markFunctionEnd(start));
+
+            if (functionType != FunctionNode.FUNCTION_EXPRESSION && !fn.isExpressionClosure()) {
+                // Add EOL only if function is not part of expression
+                // since it gets SEMI + EOL from Statement in that case
+                decompiler.addToken(Token.EOL);
+            }
+
+            if (destructuring != null) {
+                body.addChildToFront(new Node(Token.EXPR_VOID,
+                                              destructuring, lineno));
+            }
+
+            int syntheticType = fn.getFunctionType();
+            Node pn = initFunction(fn, index, body, syntheticType);
+            if (mexpr != null) {
+                pn = createAssignment(Token.ASSIGN, mexpr, pn);
+                if (syntheticType != FunctionNode.FUNCTION_EXPRESSION) {
+                    pn = createExprStatementNoReturn(pn, fn.getLineno());
+                }
+            }
+            return pn;
+
+        } finally {
+            --nestingOfFunction;
+            savedVars.restore();
+        }
+    }
+
+    private Node transformFunctionCall(FunctionCall node) {
+        Node call = createCallOrNew(Token.CALL, transform(node.getTarget()));
+        call.setLineno(node.getLineno());
+        decompiler.addToken(Token.LP);
+        List<AstNode> args = node.getArguments();
+        for (int i = 0; i < args.size(); i++) {
+            AstNode arg = args.get(i);
+            call.addChildToBack(transform(arg));
+            if (i < args.size() - 1) {
+                decompiler.addToken(Token.COMMA);
+            }
+        }
+        decompiler.addToken(Token.RP);
+        return call;
+    }
+    
+    private Node transformGenExpr(GeneratorExpression node) {
+        Node pn;
+        
+        FunctionNode fn = new FunctionNode();
+        fn.setSourceName(currentScriptOrFn.getNextTempName());
+        fn.setIsGenerator();
+        fn.setFunctionType(FunctionNode.FUNCTION_EXPRESSION);
+        fn.setRequiresActivation();
+      
+        int functionType = fn.getFunctionType();
+        int start = decompiler.markFunctionStart(functionType);
+        Node mexpr = decompileFunctionHeader(fn);
+        int index = currentScriptOrFn.addFunction(fn);
+
+        PerFunctionVariables savedVars = new PerFunctionVariables(fn);
+        try {
+            // If we start needing to record much more codegen metadata during
+            // function parsing, we should lump it all into a helper class.
+            Node destructuring = (Node)fn.getProp(Node.DESTRUCTURING_PARAMS);
+            fn.removeProp(Node.DESTRUCTURING_PARAMS);
+
+            int lineno = node.lineno;
+            ++nestingOfFunction;  // only for body, not params
+            Node body = genExprTransformHelper(node);
+
+            if (!fn.isExpressionClosure()) {
+                decompiler.addToken(Token.RC);
+            }
+            fn.setEncodedSourceBounds(start, decompiler.markFunctionEnd(start));
+
+            if (functionType != FunctionNode.FUNCTION_EXPRESSION && !fn.isExpressionClosure()) {
+                // Add EOL only if function is not part of expression
+                // since it gets SEMI + EOL from Statement in that case
+                decompiler.addToken(Token.EOL);
+            }
+
+            if (destructuring != null) {
+                body.addChildToFront(new Node(Token.EXPR_VOID,
+                                              destructuring, lineno));
+            }
+
+            int syntheticType = fn.getFunctionType();
+            pn = initFunction(fn, index, body, syntheticType);
+            if (mexpr != null) {
+                pn = createAssignment(Token.ASSIGN, mexpr, pn);
+                if (syntheticType != FunctionNode.FUNCTION_EXPRESSION) {
+                    pn = createExprStatementNoReturn(pn, fn.getLineno());
+                }
+            }
+        } finally {
+            --nestingOfFunction;
+            savedVars.restore();
+        }
+       
+        Node call = createCallOrNew(Token.CALL, pn);
+        call.setLineno(node.getLineno());
+        decompiler.addToken(Token.LP);
+        decompiler.addToken(Token.RP);
+        return call;
+    }
+    
+    private Node genExprTransformHelper(GeneratorExpression node) {
+        decompiler.addToken(Token.LP);
+        int lineno = node.getLineno();
+        Node expr = transform(node.getResult());
+
+        List<GeneratorExpressionLoop> loops = node.getLoops();
+        int numLoops = loops.size();
+
+        // Walk through loops, collecting and defining their iterator symbols.
+        Node[] iterators = new Node[numLoops];
+        Node[] iteratedObjs = new Node[numLoops];
+
+        for (int i = 0; i < numLoops; i++) {
+            GeneratorExpressionLoop acl = loops.get(i);
+            decompiler.addName(" ");
+            decompiler.addToken(Token.FOR);
+            decompiler.addToken(Token.LP);
+
+            AstNode iter = acl.getIterator();
+            String name = null;
+            if (iter.getType() == Token.NAME) {
+                name = iter.getString();
+                decompiler.addName(name);
+            } else {
+                // destructuring assignment
+                decompile(iter);
+                name = currentScriptOrFn.getNextTempName();
+                defineSymbol(Token.LP, name, false);
+                expr = createBinary(Token.COMMA,
+                                    createAssignment(Token.ASSIGN,
+                                                     iter,
+                                                     createName(name)),
+                                    expr);
+            }
+            Node init = createName(name);
+            // Define as a let since we want the scope of the variable to
+            // be restricted to the array comprehension
+            defineSymbol(Token.LET, name, false);
+            iterators[i] = init;
+
+            if (acl.isForOf()) {
+                decompiler.addName("of ");
+            } else {
+                decompiler.addToken(Token.IN);
+            }
+            iteratedObjs[i] = transform(acl.getIteratedObject());
+            decompiler.addToken(Token.RP);
+        }
+
+        // generate code for tmpArray.push(body)
+        Node yield = new Node(Token.YIELD, expr, node.getLineno());
+
+        Node body = new Node(Token.EXPR_VOID, yield, lineno);
+
+        if (node.getFilter() != null) {
+            decompiler.addName(" ");
+            decompiler.addToken(Token.IF);
+            decompiler.addToken(Token.LP);
+            body = createIf(transform(node.getFilter()), body, null, lineno);
+            decompiler.addToken(Token.RP);
+        }
+
+        // Now walk loops in reverse to build up the body statement.
+        int pushed = 0;
+        try {
+            for (int i = numLoops-1; i >= 0; i--) {
+                GeneratorExpressionLoop acl = loops.get(i);
+                Scope loop = createLoopNode(null,  // no label
+                                            acl.getLineno());
+                pushScope(loop);
+                pushed++;
+                body = createForIn(Token.LET,
+                                   loop,
+                                   iterators[i],
+                                   iteratedObjs[i],
+                                   body,
+                                   acl.isForEach(),
+                                   acl.isForOf());
+            }
+        } finally {
+            for (int i = 0; i < pushed; i++) {
+                popScope();
+            }
+        }
+
+        decompiler.addToken(Token.RP);
+
+        return body;
+    }
+
+    private Node transformIf(IfStatement n) {
+        decompiler.addToken(Token.IF);
+        decompiler.addToken(Token.LP);
+        Node cond = transform(n.getCondition());
+        decompiler.addToken(Token.RP);
+        decompiler.addEOL(Token.LC);
+        Node ifTrue = transform(n.getThenPart());
+        Node ifFalse = null;
+        if (n.getElsePart() != null) {
+            decompiler.addToken(Token.RC);
+            decompiler.addToken(Token.ELSE);
+            decompiler.addEOL(Token.LC);
+            ifFalse = transform(n.getElsePart());
+        }
+        decompiler.addEOL(Token.RC);
+        return createIf(cond, ifTrue, ifFalse, n.getLineno());
+    }
+
+    private Node transformInfix(InfixExpression node) {
+        Node left = transform(node.getLeft());
+        decompiler.addToken(node.getType());
+        Node right = transform(node.getRight());
+        if (node instanceof XmlDotQuery) {
+            decompiler.addToken(Token.RP);
+        }
+        return createBinary(node.getType(), left, right);
+    }
+
+    private Node transformLabeledStatement(LabeledStatement ls) {
+        Label label = ls.getFirstLabel();
+        List<Label> labels = ls.getLabels();
+        decompiler.addName(label.getName());
+        if (labels.size() > 1) {
+            // more than one label
+            for (Label lb : labels.subList(1, labels.size())) {
+                decompiler.addEOL(Token.COLON);
+                decompiler.addName(lb.getName());
+            }
+        }
+        if (ls.getStatement().getType() == Token.BLOCK) {
+            // reuse OBJECTLIT for ':' workaround, cf. transformObjectLiteral()
+            decompiler.addToken(Token.OBJECTLIT);
+            decompiler.addEOL(Token.LC);
+        } else {
+            decompiler.addEOL(Token.COLON);
+        }
+        Node statement = transform(ls.getStatement());
+        if (ls.getStatement().getType() == Token.BLOCK) {
+            decompiler.addEOL(Token.RC);
+        }
+
+        // Make a target and put it _after_ the statement node.  Add in the
+        // LABEL node, so breaks get the right target.
+        Node breakTarget = Node.newTarget();
+        Node block = new Node(Token.BLOCK, label, statement, breakTarget);
+        label.target = breakTarget;
+
+        return block;
+    }
+
+    private Node transformLetNode(LetNode node) {
+        pushScope(node);
+        try {
+            decompiler.addToken(Token.LET);
+            decompiler.addToken(Token.LP);
+            Node vars = transformVariableInitializers(node.getVariables());
+            decompiler.addToken(Token.RP);
+            node.addChildToBack(vars);
+            boolean letExpr = node.getType() == Token.LETEXPR;
+            if (node.getBody() != null) {
+                if (letExpr) {
+                    decompiler.addName(" ");
+                } else {
+                    decompiler.addEOL(Token.LC);
+                }
+                node.addChildToBack(transform(node.getBody()));
+                if (!letExpr) {
+                    decompiler.addEOL(Token.RC);
+                }
+            }
+            return node;
+        } finally {
+            popScope();
+        }
+    }
+
+    private Node transformLiteral(AstNode node) {
+        decompiler.addToken(node.getType());
+        return node;
+    }
+
+    private Node transformName(Name node) {
+        decompiler.addName(node.getIdentifier());
+        return node;
+    }
+
+    private Node transformNewExpr(NewExpression node) {
+        decompiler.addToken(Token.NEW);
+        Node nx = createCallOrNew(Token.NEW, transform(node.getTarget()));
+        nx.setLineno(node.getLineno());
+        List<AstNode> args = node.getArguments();
+        decompiler.addToken(Token.LP);
+        for (int i = 0; i < args.size(); i++) {
+            AstNode arg = args.get(i);
+            nx.addChildToBack(transform(arg));
+            if (i < args.size() - 1) {
+                decompiler.addToken(Token.COMMA);
+            }
+        }
+        decompiler.addToken(Token.RP);
+        if (node.getInitializer() != null) {
+            nx.addChildToBack(transformObjectLiteral(node.getInitializer()));
+        }
+        return nx;
+    }
+
+    private Node transformNumber(NumberLiteral node) {
+        decompiler.addNumber(node.getNumber());
+        return node;
+    }
+
+    private Node transformObjectLiteral(ObjectLiteral node) {
+        if (node.isDestructuring()) {
+            return node;
+        }
+        // createObjectLiteral rewrites its argument as object
+        // creation plus object property entries, so later compiler
+        // stages don't need to know about object literals.
+        decompiler.addToken(Token.LC);
+        List<ObjectProperty> elems = node.getElements();
+        Node object = new Node(Token.OBJECTLIT);
+        Object[] properties;
+        if (elems.isEmpty()) {
+            properties = ScriptRuntime.emptyArgs;
+        } else {
+            int size = elems.size(), i = 0;
+            properties = new Object[size];
+            for (ObjectProperty prop : elems) {
+                if (prop.isGetterMethod()) {
+                    decompiler.addToken(Token.GET);
+                } else if (prop.isSetterMethod()) {
+                    decompiler.addToken(Token.SET);
+                } else if (prop.isNormalMethod()) {
+                    decompiler.addToken(Token.METHOD);
+                }
+
+                properties[i++] = getPropKey(prop.getLeft());
+
+                // OBJECTLIT is used as ':' in object literal for
+                // decompilation to solve spacing ambiguity.
+                if (!(prop.isMethod())) {
+                    decompiler.addToken(Token.OBJECTLIT);
+                }
+
+                Node right = transform(prop.getRight());
+                if (prop.isGetterMethod()) {
+                    right = createUnary(Token.GET, right);
+                } else if (prop.isSetterMethod()) {
+                    right = createUnary(Token.SET, right);
+                } else if (prop.isNormalMethod()) {
+                    right = createUnary(Token.METHOD, right);
+                }
+                object.addChildToBack(right);
+
+                if (i < size) {
+                    decompiler.addToken(Token.COMMA);
+                }
+            }
+        }
+        decompiler.addToken(Token.RC);
+        object.putProp(Node.OBJECT_IDS_PROP, properties);
+        return object;
+    }
+
+    private Object getPropKey(Node id) {
+        Object key;
+        if (id instanceof Name) {
+            String s = ((Name)id).getIdentifier();
+            decompiler.addName(s);
+            key = ScriptRuntime.getIndexObject(s);
+        } else if (id instanceof StringLiteral) {
+            String s = ((StringLiteral)id).getValue();
+            decompiler.addString(s);
+            key = ScriptRuntime.getIndexObject(s);
+        } else if (id instanceof NumberLiteral) {
+            double n = ((NumberLiteral)id).getNumber();
+            decompiler.addNumber(n);
+            key = ScriptRuntime.getIndexObject(n);
+        } else {
+            throw Kit.codeBug();
+        }
+        return key;
+    }
+
+    private Node transformParenExpr(ParenthesizedExpression node) {
+        AstNode expr = node.getExpression();
+        decompiler.addToken(Token.LP);
+        int count = 1;
+        while (expr instanceof ParenthesizedExpression) {
+            decompiler.addToken(Token.LP);
+            count++;
+            expr = ((ParenthesizedExpression)expr).getExpression();
+        }
+        Node result = transform(expr);
+        for (int i = 0; i < count; i++) {
+            decompiler.addToken(Token.RP);
+        }
+        result.putProp(Node.PARENTHESIZED_PROP, Boolean.TRUE);
+        return result;
+    }
+
+    private Node transformPropertyGet(PropertyGet node) {
+        Node target = transform(node.getTarget());
+        String name = node.getProperty().getIdentifier();
+        decompiler.addToken(Token.DOT);
+        decompiler.addName(name);
+        return createPropertyGet(target, null, name, 0);
+    }
+
+    private Node transformRegExp(RegExpLiteral node) {
+        decompiler.addRegexp(node.getValue(), node.getFlags());
+        currentScriptOrFn.addRegExp(node);
+        return node;
+    }
+
+    private Node transformReturn(ReturnStatement node) {
+        boolean expClosure = Boolean.TRUE.equals(node.getProp(Node.EXPRESSION_CLOSURE_PROP));
+        boolean isArrow = Boolean.TRUE.equals(node.getProp(Node.ARROW_FUNCTION_PROP));
+        if (expClosure) {
+            if (!isArrow) {
+                decompiler.addName(" ");
+            }
+        } else {
+            decompiler.addToken(Token.RETURN);
+        }
+        AstNode rv = node.getReturnValue();
+        Node value = rv == null ? null : transform(rv);
+        if (!expClosure) decompiler.addEOL(Token.SEMI);
+        return rv == null
+            ? new Node(Token.RETURN, node.getLineno())
+            : new Node(Token.RETURN, value, node.getLineno());
+    }
+
+    private Node transformScript(ScriptNode node) {
+        decompiler.addToken(Token.SCRIPT);
+        if (currentScope != null) Kit.codeBug();
+        currentScope = node;
+        Node body = new Node(Token.BLOCK);
+        for (Node kid : node) {
+            body.addChildToBack(transform((AstNode)kid));
+        }
+        node.removeChildren();
+        Node children = body.getFirstChild();
+        if (children != null) {
+            node.addChildrenToBack(children);
+        }
+        return node;
+    }
+
+    private Node transformString(StringLiteral node) {
+        decompiler.addString(node.getValue());
+        return Node.newString(node.getValue());
+    }
+
+    private Node transformSwitch(SwitchStatement node) {
+        // The switch will be rewritten from:
+        //
+        // switch (expr) {
+        //   case test1: statements1;
+        //   ...
+        //   default: statementsDefault;
+        //   ...
+        //   case testN: statementsN;
+        // }
+        //
+        // to:
+        //
+        // {
+        //     switch (expr) {
+        //       case test1: goto label1;
+        //       ...
+        //       case testN: goto labelN;
+        //     }
+        //     goto labelDefault;
+        //   label1:
+        //     statements1;
+        //   ...
+        //   labelDefault:
+        //     statementsDefault;
+        //   ...
+        //   labelN:
+        //     statementsN;
+        //   breakLabel:
+        // }
+        //
+        // where inside switch each "break;" without label will be replaced
+        // by "goto breakLabel".
+        //
+        // If the original switch does not have the default label, then
+        // after the switch he transformed code would contain this goto:
+        //     goto breakLabel;
+        // instead of:
+        //     goto labelDefault;
+
+        decompiler.addToken(Token.SWITCH);
+        decompiler.addToken(Token.LP);
+        Node switchExpr = transform(node.getExpression());
+        decompiler.addToken(Token.RP);
+        node.addChildToBack(switchExpr);
+
+        Node block = new Node(Token.BLOCK, node, node.getLineno());
+        decompiler.addEOL(Token.LC);
+
+        for (SwitchCase sc : node.getCases()) {
+            AstNode expr = sc.getExpression();
+            Node caseExpr = null;
+
+            if (expr != null) {
+                decompiler.addToken(Token.CASE);
+                caseExpr = transform(expr);
+            } else {
+                decompiler.addToken(Token.DEFAULT);
+            }
+            decompiler.addEOL(Token.COLON);
+
+            List<AstNode> stmts = sc.getStatements();
+            Node body = new Block();
+            if (stmts != null) {
+                for (AstNode kid : stmts) {
+                    body.addChildToBack(transform(kid));
+                }
+            }
+            addSwitchCase(block, caseExpr, body);
+        }
+        decompiler.addEOL(Token.RC);
+        closeSwitch(block);
+        return block;
+    }
+
+    private Node transformThrow(ThrowStatement node) {
+        decompiler.addToken(Token.THROW);
+        Node value = transform(node.getExpression());
+        decompiler.addEOL(Token.SEMI);
+        return new Node(Token.THROW, value, node.getLineno());
+    }
+
+    private Node transformTry(TryStatement node) {
+        decompiler.addToken(Token.TRY);
+        decompiler.addEOL(Token.LC);
+        Node tryBlock = transform(node.getTryBlock());
+        decompiler.addEOL(Token.RC);
+
+        Node catchBlocks = new Block();
+        for (CatchClause cc : node.getCatchClauses()) {
+            decompiler.addToken(Token.CATCH);
+            decompiler.addToken(Token.LP);
+
+            String varName = cc.getVarName().getIdentifier();
+            decompiler.addName(varName);
+
+            Node catchCond = null;
+            AstNode ccc = cc.getCatchCondition();
+            if (ccc != null) {
+                decompiler.addName(" ");
+                decompiler.addToken(Token.IF);
+                catchCond = transform(ccc);
+            } else {
+                catchCond = new EmptyExpression();
+            }
+            decompiler.addToken(Token.RP);
+            decompiler.addEOL(Token.LC);
+
+            Node body = transform(cc.getBody());
+            decompiler.addEOL(Token.RC);
+
+            catchBlocks.addChildToBack(createCatch(varName, catchCond,
+                                                   body, cc.getLineno()));
+        }
+        Node finallyBlock = null;
+        if (node.getFinallyBlock() != null) {
+            decompiler.addToken(Token.FINALLY);
+            decompiler.addEOL(Token.LC);
+            finallyBlock = transform(node.getFinallyBlock());
+            decompiler.addEOL(Token.RC);
+        }
+        return createTryCatchFinally(tryBlock, catchBlocks,
+                                     finallyBlock, node.getLineno());
+    }
+
+    private Node transformUnary(UnaryExpression node) {
+        int type = node.getType();
+        if (type == Token.DEFAULTNAMESPACE) {
+            return transformDefaultXmlNamepace(node);
+        }
+        if (node.isPrefix()) {
+            decompiler.addToken(type);
+        }
+        Node child = transform(node.getOperand());
+        if (node.isPostfix()) {
+            decompiler.addToken(type);
+        }
+        if (type == Token.INC || type == Token.DEC) {
+            return createIncDec(type, node.isPostfix(), child);
+        }
+        return createUnary(type, child);
+    }
+
+    private Node transformVariables(VariableDeclaration node) {
+        decompiler.addToken(node.getType());
+        transformVariableInitializers(node);
+
+        // Might be most robust to have parser record whether it was
+        // a variable declaration statement, possibly as a node property.
+        AstNode parent = node.getParent();
+        if (!(parent instanceof Loop)
+            && !(parent instanceof LetNode)) {
+            decompiler.addEOL(Token.SEMI);
+        }
+        return node;
+    }
+
+    private Node transformVariableInitializers(VariableDeclaration node) {
+        List<VariableInitializer> vars = node.getVariables();
+        int size = vars.size(), i = 0;
+        for (VariableInitializer var : vars) {
+            AstNode target = var.getTarget();
+            AstNode init = var.getInitializer();
+
+            Node left = null;
+            if (var.isDestructuring()) {
+                decompile(target);  // decompile but don't transform
+                left = target;
+            } else {
+                left = transform(target);
+            }
+
+            Node right = null;
+            if (init != null) {
+                decompiler.addToken(Token.ASSIGN);
+                right = transform(init);
+            }
+
+            if (var.isDestructuring()) {
+                if (right == null) {  // TODO:  should this ever happen?
+                    node.addChildToBack(left);
+                } else {
+                    Node d = createDestructuringAssignment(node.getType(),
+                                                           left, right);
+                    node.addChildToBack(d);
+                }
+            } else {
+                if (right != null) {
+                    left.addChildToBack(right);
+                }
+                node.addChildToBack(left);
+            }
+            if (i++ < size-1) {
+                decompiler.addToken(Token.COMMA);
+            }
+        }
+        return node;
+    }
+
+    private Node transformWhileLoop(WhileLoop loop) {
+        decompiler.addToken(Token.WHILE);
+        loop.setType(Token.LOOP);
+        pushScope(loop);
+        try {
+            decompiler.addToken(Token.LP);
+            Node cond = transform(loop.getCondition());
+            decompiler.addToken(Token.RP);
+            decompiler.addEOL(Token.LC);
+            Node body = transform(loop.getBody());
+            decompiler.addEOL(Token.RC);
+            return createLoop(loop, LOOP_WHILE, body, cond, null, null);
+        } finally {
+            popScope();
+        }
+    }
+
+    private Node transformWith(WithStatement node) {
+        decompiler.addToken(Token.WITH);
+        decompiler.addToken(Token.LP);
+        Node expr = transform(node.getExpression());
+        decompiler.addToken(Token.RP);
+        decompiler.addEOL(Token.LC);
+        Node stmt = transform(node.getStatement());
+        decompiler.addEOL(Token.RC);
+        return createWith(expr, stmt, node.getLineno());
+    }
+
+    private Node transformYield(Yield node) {
+        decompiler.addToken(Token.YIELD);
+        Node kid = node.getValue() == null ? null : transform(node.getValue());
+        if (kid != null)
+            return new Node(Token.YIELD, kid, node.getLineno());
+        else
+            return new Node(Token.YIELD, node.getLineno());
+    }
+
+    private Node transformXmlLiteral(XmlLiteral node) {
+        // a literal like <foo>{bar}</foo> is rewritten as
+        //   new XML("<foo>" + bar + "</foo>");
+
+        Node pnXML = new Node(Token.NEW, node.getLineno());
+        List<XmlFragment> frags = node.getFragments();
+
+        XmlString first = (XmlString)frags.get(0);
+        boolean anon = first.getXml().trim().startsWith("<>");
+        pnXML.addChildToBack(createName(anon ? "XMLList" : "XML"));
+
+        Node pn = null;
+        for (XmlFragment frag : frags) {
+            if (frag instanceof XmlString) {
+                String xml = ((XmlString)frag).getXml();
+                decompiler.addName(xml);
+                if (pn == null) {
+                    pn = createString(xml);
+                } else {
+                    pn = createBinary(Token.ADD, pn, createString(xml));
+                }
+            } else {
+                XmlExpression xexpr = (XmlExpression)frag;
+                boolean isXmlAttr = xexpr.isXmlAttribute();
+                Node expr;
+                decompiler.addToken(Token.LC);
+                if (xexpr.getExpression() instanceof EmptyExpression) {
+                    expr = createString("");
+                } else {
+                    expr = transform(xexpr.getExpression());
+                }
+                decompiler.addToken(Token.RC);
+                if (isXmlAttr) {
+                    // Need to put the result in double quotes
+                    expr = createUnary(Token.ESCXMLATTR, expr);
+                    Node prepend = createBinary(Token.ADD,
+                                                createString("\""),
+                                                expr);
+                    expr = createBinary(Token.ADD,
+                                        prepend,
+                                        createString("\""));
+                } else {
+                    expr = createUnary(Token.ESCXMLTEXT, expr);
+                }
+                pn = createBinary(Token.ADD, pn, expr);
+            }
+        }
+
+        pnXML.addChildToBack(pn);
+        return pnXML;
+    }
+
+    private Node transformXmlMemberGet(XmlMemberGet node) {
+        XmlRef ref = node.getMemberRef();
+        Node pn = transform(node.getLeft());
+        int flags = ref.isAttributeAccess() ? Node.ATTRIBUTE_FLAG : 0;
+        if (node.getType() == Token.DOTDOT) {
+            flags |= Node.DESCENDANTS_FLAG;
+            decompiler.addToken(Token.DOTDOT);
+        } else {
+            decompiler.addToken(Token.DOT);
+        }
+        return transformXmlRef(pn, ref, flags);
+    }
+
+    // We get here if we weren't a child of a . or .. infix node
+    private Node transformXmlRef(XmlRef node) {
+        int memberTypeFlags = node.isAttributeAccess()
+            ? Node.ATTRIBUTE_FLAG : 0;
+        return transformXmlRef(null, node, memberTypeFlags);
+    }
+
+    private Node transformXmlRef(Node pn, XmlRef node, int memberTypeFlags) {
+        if ((memberTypeFlags & Node.ATTRIBUTE_FLAG) != 0)
+            decompiler.addToken(Token.XMLATTR);
+        Name namespace = node.getNamespace();
+        String ns = namespace != null ? namespace.getIdentifier() : null;
+        if (ns != null) {
+            decompiler.addName(ns);
+            decompiler.addToken(Token.COLONCOLON);
+        }
+        if (node instanceof XmlPropRef) {
+            String name = ((XmlPropRef)node).getPropName().getIdentifier();
+            decompiler.addName(name);
+            return createPropertyGet(pn, ns, name, memberTypeFlags);
+        } else {
+            decompiler.addToken(Token.LB);
+            Node expr = transform(((XmlElemRef)node).getExpression());
+            decompiler.addToken(Token.RB);
+            return createElementGet(pn, ns, expr, memberTypeFlags);
+        }
+    }
+
+    private Node transformDefaultXmlNamepace(UnaryExpression node) {
+        decompiler.addToken(Token.DEFAULT);
+        decompiler.addName(" xml");
+        decompiler.addName(" namespace");
+        decompiler.addToken(Token.ASSIGN);
+        Node child = transform(node.getOperand());
+        return createUnary(Token.DEFAULTNAMESPACE, child);
+    }
+
+    /**
+     * If caseExpression argument is null it indicates a default label.
+     */
+    private void addSwitchCase(Node switchBlock, Node caseExpression,
+                               Node statements)
+    {
+        if (switchBlock.getType() != Token.BLOCK) throw Kit.codeBug();
+        Jump switchNode = (Jump)switchBlock.getFirstChild();
+        if (switchNode.getType() != Token.SWITCH) throw Kit.codeBug();
+
+        Node gotoTarget = Node.newTarget();
+        if (caseExpression != null) {
+            Jump caseNode = new Jump(Token.CASE, caseExpression);
+            caseNode.target = gotoTarget;
+            switchNode.addChildToBack(caseNode);
+        } else {
+            switchNode.setDefault(gotoTarget);
+        }
+        switchBlock.addChildToBack(gotoTarget);
+        switchBlock.addChildToBack(statements);
+    }
+
+    private void closeSwitch(Node switchBlock)
+    {
+        if (switchBlock.getType() != Token.BLOCK) throw Kit.codeBug();
+        Jump switchNode = (Jump)switchBlock.getFirstChild();
+        if (switchNode.getType() != Token.SWITCH) throw Kit.codeBug();
+
+        Node switchBreakTarget = Node.newTarget();
+        // switchNode.target is only used by NodeTransformer
+        // to detect switch end
+        switchNode.target = switchBreakTarget;
+
+        Node defaultTarget = switchNode.getDefault();
+        if (defaultTarget == null) {
+            defaultTarget = switchBreakTarget;
+        }
+
+        switchBlock.addChildAfter(makeJump(Token.GOTO, defaultTarget),
+                                  switchNode);
+        switchBlock.addChildToBack(switchBreakTarget);
+    }
+
+    private Node createExprStatementNoReturn(Node expr, int lineno) {
+        return new Node(Token.EXPR_VOID, expr, lineno);
+    }
+
+    private Node createString(String string) {
+        return Node.newString(string);
+    }
+
+    /**
+     * Catch clause of try/catch/finally
+     * @param varName the name of the variable to bind to the exception
+     * @param catchCond the condition under which to catch the exception.
+     *                  May be null if no condition is given.
+     * @param stmts the statements in the catch clause
+     * @param lineno the starting line number of the catch clause
+     */
+    private Node createCatch(String varName, Node catchCond, Node stmts,
+                             int lineno) {
+        if (catchCond == null) {
+            catchCond = new Node(Token.EMPTY);
+        }
+        return new Node(Token.CATCH, createName(varName),
+                        catchCond, stmts, lineno);
+    }
+
+    private Node initFunction(FunctionNode fnNode, int functionIndex,
+                              Node statements, int functionType) {
+        fnNode.setFunctionType(functionType);
+        fnNode.addChildToBack(statements);
+
+        int functionCount = fnNode.getFunctionCount();
+        if (functionCount != 0) {
+            // Functions containing other functions require activation objects
+            fnNode.setRequiresActivation();
+        }
+
+        if (functionType == FunctionNode.FUNCTION_EXPRESSION) {
+            Name name = fnNode.getFunctionName();
+            if (name != null && name.length() != 0
+                    && fnNode.getSymbol(name.getIdentifier()) == null) {
+                // A function expression needs to have its name as a
+                // variable (if it isn't already allocated as a variable).
+                // See ECMA Ch. 13.  We add code to the beginning of the
+                // function to initialize a local variable of the
+                // function's name to the function value, but only if the
+                // function doesn't already define a formal parameter, var,
+                // or nested function with the same name.
+                fnNode.putSymbol(new Symbol(Token.FUNCTION, name.getIdentifier()));
+                Node setFn = new Node(Token.EXPR_VOID,
+                                 new Node(Token.SETNAME,
+                                          Node.newString(Token.BINDNAME,
+                                                         name.getIdentifier()),
+                                     new Node(Token.THISFN)));
+                statements.addChildrenToFront(setFn);
+            }
+        }
+
+        // Add return to end if needed.
+        Node lastStmt = statements.getLastChild();
+        if (lastStmt == null || lastStmt.getType() != Token.RETURN) {
+            statements.addChildToBack(new Node(Token.RETURN));
+        }
+
+        Node result = Node.newString(Token.FUNCTION, fnNode.getName());
+        result.putIntProp(Node.FUNCTION_PROP, functionIndex);
+        return result;
+    }
+
+    /**
+     * Create loop node. The code generator will later call
+     * createWhile|createDoWhile|createFor|createForIn
+     * to finish loop generation.
+     */
+    private Scope createLoopNode(Node loopLabel, int lineno) {
+        Scope result = createScopeNode(Token.LOOP, lineno);
+        if (loopLabel != null) {
+            ((Jump)loopLabel).setLoop(result);
+        }
+        return result;
+    }
+
+    private Node createFor(Scope loop, Node init,
+                           Node test, Node incr, Node body) {
+        if (init.getType() == Token.LET) {
+            // rewrite "for (let i=s; i < N; i++)..." as
+            // "let (i=s) { for (; i < N; i++)..." so that "s" is evaluated
+            // outside the scope of the for.
+            Scope let = Scope.splitScope(loop);
+            let.setType(Token.LET);
+            let.addChildrenToBack(init);
+            let.addChildToBack(createLoop(loop, LOOP_FOR, body, test,
+                new Node(Token.EMPTY), incr));
+            return let;
+        }
+        return createLoop(loop, LOOP_FOR, body, test, init, incr);
+    }
+
+    private Node createLoop(Jump loop, int loopType, Node body,
+                            Node cond, Node init, Node incr)
+    {
+        Node bodyTarget = Node.newTarget();
+        Node condTarget = Node.newTarget();
+        if (loopType == LOOP_FOR && cond.getType() == Token.EMPTY) {
+            cond = new Node(Token.TRUE);
+        }
+        Jump IFEQ = new Jump(Token.IFEQ, cond);
+        IFEQ.target = bodyTarget;
+        Node breakTarget = Node.newTarget();
+
+        loop.addChildToBack(bodyTarget);
+        loop.addChildrenToBack(body);
+        if (loopType == LOOP_WHILE || loopType == LOOP_FOR) {
+            // propagate lineno to condition
+            loop.addChildrenToBack(new Node(Token.EMPTY, loop.getLineno()));
+        }
+        loop.addChildToBack(condTarget);
+        loop.addChildToBack(IFEQ);
+        loop.addChildToBack(breakTarget);
+
+        loop.target = breakTarget;
+        Node continueTarget = condTarget;
+
+        if (loopType == LOOP_WHILE || loopType == LOOP_FOR) {
+            // Just add a GOTO to the condition in the do..while
+            loop.addChildToFront(makeJump(Token.GOTO, condTarget));
+
+            if (loopType == LOOP_FOR) {
+                int initType = init.getType();
+                if (initType != Token.EMPTY) {
+                    if (initType != Token.VAR && initType != Token.LET) {
+                        init = new Node(Token.EXPR_VOID, init);
+                    }
+                    loop.addChildToFront(init);
+                }
+                Node incrTarget = Node.newTarget();
+                loop.addChildAfter(incrTarget, body);
+                if (incr.getType() != Token.EMPTY) {
+                    incr = new Node(Token.EXPR_VOID, incr);
+                    loop.addChildAfter(incr, incrTarget);
+                }
+                continueTarget = incrTarget;
+            }
+        }
+
+        loop.setContinue(continueTarget);
+        return loop;
+    }
+
+    /**
+     * Generate IR for a for..in loop.
+     */
+    private Node createForIn(int declType, Node loop, Node lhs,
+                             Node obj, Node body, boolean isForEach, boolean isForOf)
+    {
+        int destructuring = -1;
+        int destructuringLen = 0;
+        Node lvalue;
+        int type = lhs.getType();
+        if (type == Token.VAR || type == Token.LET) {
+            Node kid = lhs.getLastChild();
+            int kidType = kid.getType();
+            if (kidType == Token.ARRAYLIT || kidType == Token.OBJECTLIT)
+            {
+                type = destructuring = kidType;
+                lvalue = kid;
+                destructuringLen = 0;
+                if (kid instanceof ArrayLiteral)
+                    destructuringLen = ((ArrayLiteral) kid).getDestructuringLength();
+            } else if (kidType == Token.NAME) {
+                lvalue = Node.newString(Token.NAME, kid.getString());
+            } else {
+                reportError("msg.bad.for.in.lhs");
+                return null;
+            }
+        } else if (type == Token.ARRAYLIT || type == Token.OBJECTLIT) {
+            destructuring = type;
+            lvalue = lhs;
+            destructuringLen = 0;
+            if (lhs instanceof ArrayLiteral)
+                destructuringLen = ((ArrayLiteral) lhs).getDestructuringLength();
+        } else {
+            lvalue = makeReference(lhs);
+            if (lvalue == null) {
+                reportError("msg.bad.for.in.lhs");
+                return null;
+            }
+        }
+
+        Node localBlock = new Node(Token.LOCAL_BLOCK);
+        int initType = isForEach ? Token.ENUM_INIT_VALUES
+                       : isForOf ? Token.ENUM_INIT_VALUES_IN_ORDER
+                                 : (destructuring != -1
+                                    ? Token.ENUM_INIT_ARRAY
+                                    : Token.ENUM_INIT_KEYS);
+        Node init = new Node(initType, obj);
+        init.putProp(Node.LOCAL_BLOCK_PROP, localBlock);
+        Node cond = new Node(Token.ENUM_NEXT);
+        cond.putProp(Node.LOCAL_BLOCK_PROP, localBlock);
+        Node id = new Node(Token.ENUM_ID);
+        id.putProp(Node.LOCAL_BLOCK_PROP, localBlock);
+
+        Node newBody = new Node(Token.BLOCK);
+        Node assign;
+        if (destructuring != -1) {
+            assign = createDestructuringAssignment(declType, lvalue, id);
+            if (!isForEach && !isForOf &&
+                (destructuring == Token.OBJECTLIT ||
+                 destructuringLen != 2))
+            {
+                // destructuring assignment is only allowed in for..each or
+                // with an array type of length 2 (to hold key and value)
+                reportError("msg.bad.for.in.destruct");
+            }
+        } else {
+            assign = simpleAssignment(lvalue, id);
+        }
+        newBody.addChildToBack(new Node(Token.EXPR_VOID, assign));
+        newBody.addChildToBack(body);
+
+        loop = createLoop((Jump)loop, LOOP_WHILE, newBody, cond, null, null);
+        loop.addChildToFront(init);
+        if (type == Token.VAR || type == Token.LET)
+            loop.addChildToFront(lhs);
+        localBlock.addChildToBack(loop);
+
+        return localBlock;
+    }
+
+    /**
+     * Try/Catch/Finally
+     *
+     * The IRFactory tries to express as much as possible in the tree;
+     * the responsibilities remaining for Codegen are to add the Java
+     * handlers: (Either (but not both) of TARGET and FINALLY might not
+     * be defined)
+     *
+     * - a catch handler for javascript exceptions that unwraps the
+     * exception onto the stack and GOTOes to the catch target
+     *
+     * - a finally handler
+     *
+     * ... and a goto to GOTO around these handlers.
+     */
+    private Node createTryCatchFinally(Node tryBlock, Node catchBlocks,
+                                       Node finallyBlock, int lineno)
+    {
+        boolean hasFinally = (finallyBlock != null)
+                             && (finallyBlock.getType() != Token.BLOCK
+                                 || finallyBlock.hasChildren());
+
+        // short circuit
+        if (tryBlock.getType() == Token.BLOCK && !tryBlock.hasChildren()
+            && !hasFinally)
+        {
+            return tryBlock;
+        }
+
+        boolean hasCatch = catchBlocks.hasChildren();
+
+        // short circuit
+        if (!hasFinally && !hasCatch)  {
+            // bc finally might be an empty block...
+            return tryBlock;
+        }
+
+        Node handlerBlock  = new Node(Token.LOCAL_BLOCK);
+        Jump pn = new Jump(Token.TRY, tryBlock, lineno);
+        pn.putProp(Node.LOCAL_BLOCK_PROP, handlerBlock);
+
+        if (hasCatch) {
+            // jump around catch code
+            Node endCatch = Node.newTarget();
+            pn.addChildToBack(makeJump(Token.GOTO, endCatch));
+
+            // make a TARGET for the catch that the tcf node knows about
+            Node catchTarget = Node.newTarget();
+            pn.target = catchTarget;
+            // mark it
+            pn.addChildToBack(catchTarget);
+
+            //
+            //  Given
+            //
+            //   try {
+            //       tryBlock;
+            //   } catch (e if condition1) {
+            //       something1;
+            //   ...
+            //
+            //   } catch (e if conditionN) {
+            //       somethingN;
+            //   } catch (e) {
+            //       somethingDefault;
+            //   }
+            //
+            //  rewrite as
+            //
+            //   try {
+            //       tryBlock;
+            //       goto after_catch:
+            //   } catch (x) {
+            //       with (newCatchScope(e, x)) {
+            //           if (condition1) {
+            //               something1;
+            //               goto after_catch;
+            //           }
+            //       }
+            //   ...
+            //       with (newCatchScope(e, x)) {
+            //           if (conditionN) {
+            //               somethingN;
+            //               goto after_catch;
+            //           }
+            //       }
+            //       with (newCatchScope(e, x)) {
+            //           somethingDefault;
+            //           goto after_catch;
+            //       }
+            //   }
+            // after_catch:
+            //
+            // If there is no default catch, then the last with block
+            // arround  "somethingDefault;" is replaced by "rethrow;"
+
+            // It is assumed that catch handler generation will store
+            // exeception object in handlerBlock register
+
+            // Block with local for exception scope objects
+            Node catchScopeBlock = new Node(Token.LOCAL_BLOCK);
+
+            // expects catchblocks children to be (cond block) pairs.
+            Node cb = catchBlocks.getFirstChild();
+            boolean hasDefault = false;
+            int scopeIndex = 0;
+            while (cb != null) {
+                int catchLineNo = cb.getLineno();
+
+                Node name = cb.getFirstChild();
+                Node cond = name.getNext();
+                Node catchStatement = cond.getNext();
+                cb.removeChild(name);
+                cb.removeChild(cond);
+                cb.removeChild(catchStatement);
+
+                // Add goto to the catch statement to jump out of catch
+                // but prefix it with LEAVEWITH since try..catch produces
+                // "with"code in order to limit the scope of the exception
+                // object.
+                catchStatement.addChildToBack(new Node(Token.LEAVEWITH));
+                catchStatement.addChildToBack(makeJump(Token.GOTO, endCatch));
+
+                // Create condition "if" when present
+                Node condStmt;
+                if (cond.getType() == Token.EMPTY) {
+                    condStmt = catchStatement;
+                    hasDefault = true;
+                } else {
+                    condStmt = createIf(cond, catchStatement, null,
+                                        catchLineNo);
+                }
+
+                // Generate code to create the scope object and store
+                // it in catchScopeBlock register
+                Node catchScope = new Node(Token.CATCH_SCOPE, name,
+                                           createUseLocal(handlerBlock));
+                catchScope.putProp(Node.LOCAL_BLOCK_PROP, catchScopeBlock);
+                catchScope.putIntProp(Node.CATCH_SCOPE_PROP, scopeIndex);
+                catchScopeBlock.addChildToBack(catchScope);
+
+                // Add with statement based on catch scope object
+                catchScopeBlock.addChildToBack(
+                    createWith(createUseLocal(catchScopeBlock), condStmt,
+                               catchLineNo));
+
+                // move to next cb
+                cb = cb.getNext();
+                ++scopeIndex;
+            }
+            pn.addChildToBack(catchScopeBlock);
+            if (!hasDefault) {
+                // Generate code to rethrow if no catch clause was executed
+                Node rethrow = new Node(Token.RETHROW);
+                rethrow.putProp(Node.LOCAL_BLOCK_PROP, handlerBlock);
+                pn.addChildToBack(rethrow);
+            }
+
+            pn.addChildToBack(endCatch);
+        }
+
+        if (hasFinally) {
+            Node finallyTarget = Node.newTarget();
+            pn.setFinally(finallyTarget);
+
+            // add jsr finally to the try block
+            pn.addChildToBack(makeJump(Token.JSR, finallyTarget));
+
+            // jump around finally code
+            Node finallyEnd = Node.newTarget();
+            pn.addChildToBack(makeJump(Token.GOTO, finallyEnd));
+
+            pn.addChildToBack(finallyTarget);
+            Node fBlock = new Node(Token.FINALLY, finallyBlock);
+            fBlock.putProp(Node.LOCAL_BLOCK_PROP, handlerBlock);
+            pn.addChildToBack(fBlock);
+
+            pn.addChildToBack(finallyEnd);
+        }
+        handlerBlock.addChildToBack(pn);
+        return handlerBlock;
+    }
+
+    private Node createWith(Node obj, Node body, int lineno) {
+        setRequiresActivation();
+        Node result = new Node(Token.BLOCK, lineno);
+        result.addChildToBack(new Node(Token.ENTERWITH, obj));
+        Node bodyNode = new Node(Token.WITH, body, lineno);
+        result.addChildrenToBack(bodyNode);
+        result.addChildToBack(new Node(Token.LEAVEWITH));
+        return result;
+    }
+
+    private Node createIf(Node cond, Node ifTrue, Node ifFalse, int lineno)
+    {
+        int condStatus = isAlwaysDefinedBoolean(cond);
+        if (condStatus == ALWAYS_TRUE_BOOLEAN) {
+            return ifTrue;
+        } else if (condStatus == ALWAYS_FALSE_BOOLEAN) {
+            if (ifFalse != null) {
+                return ifFalse;
+            }
+            // Replace if (false) xxx by empty block
+            return new Node(Token.BLOCK, lineno);
+        }
+
+        Node result = new Node(Token.BLOCK, lineno);
+        Node ifNotTarget = Node.newTarget();
+        Jump IFNE = new Jump(Token.IFNE, cond);
+        IFNE.target = ifNotTarget;
+
+        result.addChildToBack(IFNE);
+        result.addChildrenToBack(ifTrue);
+
+        if (ifFalse != null) {
+            Node endTarget = Node.newTarget();
+            result.addChildToBack(makeJump(Token.GOTO, endTarget));
+            result.addChildToBack(ifNotTarget);
+            result.addChildrenToBack(ifFalse);
+            result.addChildToBack(endTarget);
+        } else {
+            result.addChildToBack(ifNotTarget);
+        }
+
+        return result;
+    }
+
+    private Node createCondExpr(Node cond, Node ifTrue, Node ifFalse) {
+        int condStatus = isAlwaysDefinedBoolean(cond);
+        if (condStatus == ALWAYS_TRUE_BOOLEAN) {
+            return ifTrue;
+        } else if (condStatus == ALWAYS_FALSE_BOOLEAN) {
+            return ifFalse;
+        }
+        return new Node(Token.HOOK, cond, ifTrue, ifFalse);
+    }
+
+    private Node createUnary(int nodeType, Node child)
+    {
+        int childType = child.getType();
+        switch (nodeType) {
+          case Token.DELPROP: {
+            Node n;
+            if (childType == Token.NAME) {
+                // Transform Delete(Name "a")
+                //  to Delete(Bind("a"), String("a"))
+                child.setType(Token.BINDNAME);
+                Node left = child;
+                Node right = Node.newString(child.getString());
+                n = new Node(nodeType, left, right);
+            } else if (childType == Token.GETPROP ||
+                       childType == Token.GETELEM)
+            {
+                Node left = child.getFirstChild();
+                Node right = child.getLastChild();
+                child.removeChild(left);
+                child.removeChild(right);
+                n = new Node(nodeType, left, right);
+            } else if (childType == Token.GET_REF) {
+                Node ref = child.getFirstChild();
+                child.removeChild(ref);
+                n = new Node(Token.DEL_REF, ref);
+            } else {
+                // Always evaluate delete operand, see ES5 11.4.1 & bug #726121
+                n = new Node(nodeType, new Node(Token.TRUE), child);
+            }
+            return n;
+          }
+          case Token.TYPEOF:
+            if (childType == Token.NAME) {
+                child.setType(Token.TYPEOFNAME);
+                return child;
+            }
+            break;
+          case Token.BITNOT:
+            if (childType == Token.NUMBER) {
+                int value = ScriptRuntime.toInt32(child.getDouble());
+                child.setDouble(~value);
+                return child;
+            }
+            break;
+          case Token.NEG:
+            if (childType == Token.NUMBER) {
+                child.setDouble(-child.getDouble());
+                return child;
+            }
+            break;
+          case Token.NOT: {
+            int status = isAlwaysDefinedBoolean(child);
+            if (status != 0) {
+                int type;
+                if (status == ALWAYS_TRUE_BOOLEAN) {
+                    type = Token.FALSE;
+                } else {
+                    type = Token.TRUE;
+                }
+                if (childType == Token.TRUE || childType == Token.FALSE) {
+                    child.setType(type);
+                    return child;
+                }
+                return new Node(type);
+            }
+            break;
+          }
+        }
+        return new Node(nodeType, child);
+    }
+
+    private Node createCallOrNew(int nodeType, Node child) {
+        int type = Node.NON_SPECIALCALL;
+        if (child.getType() == Token.NAME) {
+            String name = child.getString();
+            if (name.equals("eval")) {
+                type = Node.SPECIALCALL_EVAL;
+            } else if (name.equals("With")) {
+                type = Node.SPECIALCALL_WITH;
+            }
+        } else if (child.getType() == Token.GETPROP) {
+            String name = child.getLastChild().getString();
+            if (name.equals("eval")) {
+                type = Node.SPECIALCALL_EVAL;
+            }
+        }
+        Node node = new Node(nodeType, child);
+        if (type != Node.NON_SPECIALCALL) {
+            // Calls to these functions require activation objects.
+            setRequiresActivation();
+            node.putIntProp(Node.SPECIALCALL_PROP, type);
+        }
+        return node;
+    }
+
+    private Node createIncDec(int nodeType, boolean post, Node child)
+    {
+        child = makeReference(child);
+        int childType = child.getType();
+
+        switch (childType) {
+          case Token.NAME:
+          case Token.GETPROP:
+          case Token.GETELEM:
+          case Token.GET_REF: {
+            Node n = new Node(nodeType, child);
+            int incrDecrMask = 0;
+            if (nodeType == Token.DEC) {
+                incrDecrMask |= Node.DECR_FLAG;
+            }
+            if (post) {
+                incrDecrMask |= Node.POST_FLAG;
+            }
+            n.putIntProp(Node.INCRDECR_PROP, incrDecrMask);
+            return n;
+          }
+        }
+        throw Kit.codeBug();
+    }
+
+    private Node createPropertyGet(Node target, String namespace, String name,
+                                   int memberTypeFlags)
+    {
+        if (namespace == null && memberTypeFlags == 0) {
+            if (target == null) {
+                return createName(name);
+            }
+            checkActivationName(name, Token.GETPROP);
+            if (ScriptRuntime.isSpecialProperty(name)) {
+                Node ref = new Node(Token.REF_SPECIAL, target);
+                ref.putProp(Node.NAME_PROP, name);
+                return new Node(Token.GET_REF, ref);
+            }
+            return new Node(Token.GETPROP, target, Node.newString(name));
+        }
+        Node elem = Node.newString(name);
+        memberTypeFlags |= Node.PROPERTY_FLAG;
+        return createMemberRefGet(target, namespace, elem, memberTypeFlags);
+    }
+
+    /**
+     * @param target the node before the LB
+     * @param namespace optional namespace
+     * @param elem the node in the brackets
+     * @param memberTypeFlags E4X flags
+     */
+    private Node createElementGet(Node target, String namespace, Node elem,
+                                  int memberTypeFlags)
+    {
+        // OPT: could optimize to createPropertyGet
+        // iff elem is string that can not be number
+        if (namespace == null && memberTypeFlags == 0) {
+            // stand-alone [aaa] as primary expression is array literal
+            // declaration and should not come here!
+            if (target == null) throw Kit.codeBug();
+            return new Node(Token.GETELEM, target, elem);
+        }
+        return createMemberRefGet(target, namespace, elem, memberTypeFlags);
+    }
+
+    private Node createMemberRefGet(Node target, String namespace, Node elem,
+                                    int memberTypeFlags)
+    {
+        Node nsNode = null;
+        if (namespace != null) {
+            // See 11.1.2 in ECMA 357
+            if (namespace.equals("*")) {
+                nsNode = new Node(Token.NULL);
+            } else {
+                nsNode = createName(namespace);
+            }
+        }
+        Node ref;
+        if (target == null) {
+            if (namespace == null) {
+                ref = new Node(Token.REF_NAME, elem);
+            } else {
+                ref = new Node(Token.REF_NS_NAME, nsNode, elem);
+            }
+        } else {
+            if (namespace == null) {
+                ref = new Node(Token.REF_MEMBER, target, elem);
+            } else {
+                ref = new Node(Token.REF_NS_MEMBER, target, nsNode, elem);
+            }
+        }
+        if (memberTypeFlags != 0) {
+            ref.putIntProp(Node.MEMBER_TYPE_PROP, memberTypeFlags);
+        }
+        return new Node(Token.GET_REF, ref);
+    }
+
+    private Node createBinary(int nodeType, Node left, Node right) {
+        switch (nodeType) {
+
+          case Token.ADD:
+            // numerical addition and string concatenation
+            if (left.type == Token.STRING) {
+                String s2;
+                if (right.type == Token.STRING) {
+                    s2 = right.getString();
+                } else if (right.type == Token.NUMBER) {
+                    s2 = ScriptRuntime.numberToString(right.getDouble(), 10);
+                } else {
+                    break;
+                }
+                String s1 = left.getString();
+                left.setString(s1.concat(s2));
+                return left;
+            } else if (left.type == Token.NUMBER) {
+                if (right.type == Token.NUMBER) {
+                    left.setDouble(left.getDouble() + right.getDouble());
+                    return left;
+                } else if (right.type == Token.STRING) {
+                    String s1, s2;
+                    s1 = ScriptRuntime.numberToString(left.getDouble(), 10);
+                    s2 = right.getString();
+                    right.setString(s1.concat(s2));
+                    return right;
+                }
+            }
+            // can't do anything if we don't know  both types - since
+            // 0 + object is supposed to call toString on the object and do
+            // string concantenation rather than addition
+            break;
+
+          case Token.SUB:
+            // numerical subtraction
+            if (left.type == Token.NUMBER) {
+                double ld = left.getDouble();
+                if (right.type == Token.NUMBER) {
+                    //both numbers
+                    left.setDouble(ld - right.getDouble());
+                    return left;
+                } else if (ld == 0.0) {
+                    // first 0: 0-x -> -x
+                    return new Node(Token.NEG, right);
+                }
+            } else if (right.type == Token.NUMBER) {
+                if (right.getDouble() == 0.0) {
+                    //second 0: x - 0 -> +x
+                    // can not make simply x because x - 0 must be number
+                    return new Node(Token.POS, left);
+                }
+            }
+            break;
+
+          case Token.MUL:
+            // numerical multiplication
+            if (left.type == Token.NUMBER) {
+                double ld = left.getDouble();
+                if (right.type == Token.NUMBER) {
+                    //both numbers
+                    left.setDouble(ld * right.getDouble());
+                    return left;
+                } else if (ld == 1.0) {
+                    // first 1: 1 *  x -> +x
+                    return new Node(Token.POS, right);
+                }
+            } else if (right.type == Token.NUMBER) {
+                if (right.getDouble() == 1.0) {
+                    //second 1: x * 1 -> +x
+                    // can not make simply x because x - 0 must be number
+                    return new Node(Token.POS, left);
+                }
+            }
+            // can't do x*0: Infinity * 0 gives NaN, not 0
+            break;
+
+          case Token.DIV:
+            // number division
+            if (right.type == Token.NUMBER) {
+                double rd = right.getDouble();
+                if (left.type == Token.NUMBER) {
+                    // both constants -- just divide, trust Java to handle x/0
+                    left.setDouble(left.getDouble() / rd);
+                    return left;
+               } else if (rd == 1.0) {
+                    // second 1: x/1 -> +x
+                    // not simply x to force number convertion
+                    return new Node(Token.POS, left);
+                }
+            }
+            break;
+
+          case Token.AND: {
+            // Since x && y gives x, not false, when Boolean(x) is false,
+            // and y, not Boolean(y), when Boolean(x) is true, x && y
+            // can only be simplified if x is defined. See bug 309957.
+
+            int leftStatus = isAlwaysDefinedBoolean(left);
+            if (leftStatus == ALWAYS_FALSE_BOOLEAN) {
+                // if the first one is false, just return it
+                return left;
+            } else if (leftStatus == ALWAYS_TRUE_BOOLEAN) {
+                // if first is true, set to second
+                return right;
+            }
+            break;
+          }
+
+          case Token.OR: {
+            // Since x || y gives x, not true, when Boolean(x) is true,
+            // and y, not Boolean(y), when Boolean(x) is false, x || y
+            // can only be simplified if x is defined. See bug 309957.
+
+            int leftStatus = isAlwaysDefinedBoolean(left);
+            if (leftStatus == ALWAYS_TRUE_BOOLEAN) {
+                // if the first one is true, just return it
+                return left;
+            } else if (leftStatus == ALWAYS_FALSE_BOOLEAN) {
+                // if first is false, set to second
+                return right;
+            }
+            break;
+          }
+        }
+
+        return new Node(nodeType, left, right);
+    }
+
+    private Node createAssignment(int assignType, Node left, Node right)
+    {
+        Node ref = makeReference(left);
+        if (ref == null) {
+            if (left.getType() == Token.ARRAYLIT ||
+                left.getType() == Token.OBJECTLIT)
+            {
+                if (assignType != Token.ASSIGN) {
+                    reportError("msg.bad.destruct.op");
+                    return right;
+                }
+                return createDestructuringAssignment(-1, left, right);
+            }
+            reportError("msg.bad.assign.left");
+            return right;
+        }
+        left = ref;
+
+        int assignOp;
+        switch (assignType) {
+          case Token.ASSIGN:
+            return simpleAssignment(left, right);
+          case Token.ASSIGN_BITOR:  assignOp = Token.BITOR;  break;
+          case Token.ASSIGN_BITXOR: assignOp = Token.BITXOR; break;
+          case Token.ASSIGN_BITAND: assignOp = Token.BITAND; break;
+          case Token.ASSIGN_LSH:    assignOp = Token.LSH;    break;
+          case Token.ASSIGN_RSH:    assignOp = Token.RSH;    break;
+          case Token.ASSIGN_URSH:   assignOp = Token.URSH;   break;
+          case Token.ASSIGN_ADD:    assignOp = Token.ADD;    break;
+          case Token.ASSIGN_SUB:    assignOp = Token.SUB;    break;
+          case Token.ASSIGN_MUL:    assignOp = Token.MUL;    break;
+          case Token.ASSIGN_DIV:    assignOp = Token.DIV;    break;
+          case Token.ASSIGN_MOD:    assignOp = Token.MOD;    break;
+          default: throw Kit.codeBug();
+        }
+
+        int nodeType = left.getType();
+        switch (nodeType) {
+          case Token.NAME: {
+            Node op = new Node(assignOp, left, right);
+            Node lvalueLeft = Node.newString(Token.BINDNAME, left.getString());
+            return new Node(Token.SETNAME, lvalueLeft, op);
+          }
+          case Token.GETPROP:
+          case Token.GETELEM: {
+            Node obj = left.getFirstChild();
+            Node id = left.getLastChild();
+
+            int type = nodeType == Token.GETPROP
+                       ? Token.SETPROP_OP
+                       : Token.SETELEM_OP;
+
+            Node opLeft = new Node(Token.USE_STACK);
+            Node op = new Node(assignOp, opLeft, right);
+            return new Node(type, obj, id, op);
+          }
+          case Token.GET_REF: {
+            ref = left.getFirstChild();
+            checkMutableReference(ref);
+            Node opLeft = new Node(Token.USE_STACK);
+            Node op = new Node(assignOp, opLeft, right);
+            return new Node(Token.SET_REF_OP, ref, op);
+          }
+        }
+
+        throw Kit.codeBug();
+    }
+
+    private Node createUseLocal(Node localBlock) {
+        if (Token.LOCAL_BLOCK != localBlock.getType()) throw Kit.codeBug();
+        Node result = new Node(Token.LOCAL_LOAD);
+        result.putProp(Node.LOCAL_BLOCK_PROP, localBlock);
+        return result;
+    }
+
+    private Jump makeJump(int type, Node target) {
+        Jump n = new Jump(type);
+        n.target = target;
+        return n;
+    }
+
+    private Node makeReference(Node node) {
+        int type = node.getType();
+        switch (type) {
+          case Token.NAME:
+          case Token.GETPROP:
+          case Token.GETELEM:
+          case Token.GET_REF:
+            return node;
+          case Token.CALL:
+            node.setType(Token.REF_CALL);
+            return new Node(Token.GET_REF, node);
+        }
+        // Signal caller to report error
+        return null;
+    }
+
+    // Check if Node always mean true or false in boolean context
+    private static int isAlwaysDefinedBoolean(Node node) {
+        switch (node.getType()) {
+          case Token.FALSE:
+          case Token.NULL:
+            return ALWAYS_FALSE_BOOLEAN;
+          case Token.TRUE:
+            return ALWAYS_TRUE_BOOLEAN;
+          case Token.NUMBER: {
+            double num = node.getDouble();
+            if (num == num && num != 0.0) {
+                return ALWAYS_TRUE_BOOLEAN;
+            } else {
+                return ALWAYS_FALSE_BOOLEAN;
+            }
+          }
+        }
+        return 0;
+    }
+
+    // Check if node is the target of a destructuring bind.
+    boolean isDestructuring(Node n) {
+        return n instanceof DestructuringForm
+            && ((DestructuringForm)n).isDestructuring();
+    }
+
+    Node decompileFunctionHeader(FunctionNode fn) {
+        Node mexpr = null;
+        if (fn.getFunctionName() != null) {
+            decompiler.addName(fn.getName());
+        } else if (fn.getMemberExprNode() != null) {
+            mexpr = transform(fn.getMemberExprNode());
+        }
+        boolean isArrow = fn.getFunctionType() == FunctionNode.ARROW_FUNCTION;
+        boolean noParen = isArrow && fn.getLp() == -1;
+        if (!noParen) {
+            decompiler.addToken(Token.LP);
+        }
+        List<AstNode> params = fn.getParams();
+        for (int i = 0; i < params.size(); i++) {
+            decompile(params.get(i));
+            if (i < params.size() - 1) {
+                decompiler.addToken(Token.COMMA);
+            }
+        }
+        if (!noParen) {
+            decompiler.addToken(Token.RP);
+        }
+        if (isArrow) {
+            decompiler.addToken(Token.ARROW);
+        }
+        if (!fn.isExpressionClosure()) {
+            decompiler.addEOL(Token.LC);
+        }
+        return mexpr;
+    }
+
+    void decompile(AstNode node) {
+        switch (node.getType()) {
+          case Token.ARRAYLIT:
+              decompileArrayLiteral((ArrayLiteral)node);
+              break;
+          case Token.OBJECTLIT:
+              decompileObjectLiteral((ObjectLiteral)node);
+              break;
+          case Token.STRING:
+              decompiler.addString(((StringLiteral)node).getValue());
+              break;
+          case Token.NAME:
+              decompiler.addName(((Name)node).getIdentifier());
+              break;
+          case Token.NUMBER:
+              decompiler.addNumber(((NumberLiteral)node).getNumber());
+              break;
+          case Token.GETPROP:
+              decompilePropertyGet((PropertyGet)node);
+              break;
+          case Token.EMPTY:
+              break;
+          case Token.GETELEM:
+              decompileElementGet((ElementGet) node);
+              break;
+          case Token.THIS:
+              decompiler.addToken(node.getType());
+              break;
+          default:
+              Kit.codeBug("unexpected token: "
+                          + Token.typeToName(node.getType()));
+        }
+    }
+
+    // used for destructuring forms, since we don't transform() them
+    void decompileArrayLiteral(ArrayLiteral node) {
+        decompiler.addToken(Token.LB);
+        List<AstNode> elems = node.getElements();
+        int size = elems.size();
+        for (int i = 0; i < size; i++) {
+            AstNode elem = elems.get(i);
+            decompile(elem);
+            if (i < size - 1) {
+                decompiler.addToken(Token.COMMA);
+            }
+        }
+        decompiler.addToken(Token.RB);
+    }
+
+    // only used for destructuring forms
+    void decompileObjectLiteral(ObjectLiteral node) {
+        decompiler.addToken(Token.LC);
+        List<ObjectProperty> props = node.getElements();
+        int size = props.size();
+        for (int i = 0; i < size; i++) {
+            ObjectProperty prop = props.get(i);
+            boolean destructuringShorthand =
+                    Boolean.TRUE.equals(prop.getProp(Node.DESTRUCTURING_SHORTHAND));
+            decompile(prop.getLeft());
+            if (!destructuringShorthand) {
+                decompiler.addToken(Token.COLON);
+                decompile(prop.getRight());
+            }
+            if (i < size - 1) {
+                decompiler.addToken(Token.COMMA);
+            }
+        }
+        decompiler.addToken(Token.RC);
+    }
+
+    // only used for destructuring forms
+    void decompilePropertyGet(PropertyGet node) {
+        decompile(node.getTarget());
+        decompiler.addToken(Token.DOT);
+        decompile(node.getProperty());
+    }
+
+    // only used for destructuring forms
+    void decompileElementGet(ElementGet node) {
+        decompile(node.getTarget());
+        decompiler.addToken(Token.LB);
+        decompile(node.getElement());
+        decompiler.addToken(Token.RB);
+    }
+}
diff -pruN 20130227+dfsg1-14/rhino/src/org/mozilla/javascript/Icode.java 20130227+rhino-1/rhino/src/org/mozilla/javascript/Icode.java
--- 20130227+dfsg1-14/rhino/src/org/mozilla/javascript/Icode.java	1970-01-01 00:00:00.000000000 +0000
+++ 20130227+rhino-1/rhino/src/org/mozilla/javascript/Icode.java	2023-05-25 14:24:50.000000000 +0000
@@ -0,0 +1,241 @@
+/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+package org.mozilla.javascript;
+
+/**
+ * Additional interpreter-specific codes
+ */
+abstract class Icode {
+
+    static final int
+
+    // delete operator used on a name
+        Icode_DELNAME                    = 0,
+
+    // Stack: ... value1 -> ... value1 value1
+        Icode_DUP                       = -1,
+
+    // Stack: ... value2 value1 -> ... value2 value1 value2 value1
+        Icode_DUP2                      = -2,
+
+    // Stack: ... value2 value1 -> ... value1 value2
+        Icode_SWAP                      = -3,
+
+    // Stack: ... value1 -> ...
+        Icode_POP                       = -4,
+
+    // Store stack top into return register and then pop it
+        Icode_POP_RESULT                = -5,
+
+    // To jump conditionally and pop additional stack value
+        Icode_IFEQ_POP                  = -6,
+
+    // various types of ++/--
+        Icode_VAR_INC_DEC               = -7,
+        Icode_NAME_INC_DEC              = -8,
+        Icode_PROP_INC_DEC              = -9,
+        Icode_ELEM_INC_DEC              = -10,
+        Icode_REF_INC_DEC               = -11,
+
+    // load/save scope from/to local
+        Icode_SCOPE_LOAD                = -12,
+        Icode_SCOPE_SAVE                = -13,
+
+        Icode_TYPEOFNAME                = -14,
+
+    // helper for function calls
+        Icode_NAME_AND_THIS             = -15,
+        Icode_PROP_AND_THIS             = -16,
+        Icode_ELEM_AND_THIS             = -17,
+        Icode_VALUE_AND_THIS            = -18,
+
+    // Create closure object for nested functions
+        Icode_CLOSURE_EXPR              = -19,
+        Icode_CLOSURE_STMT              = -20,
+
+    // Special calls
+        Icode_CALLSPECIAL               = -21,
+
+    // To return undefined value
+        Icode_RETUNDEF                  = -22,
+
+    // Exception handling implementation
+        Icode_GOSUB                     = -23,
+        Icode_STARTSUB                  = -24,
+        Icode_RETSUB                    = -25,
+
+    // To indicating a line number change in icodes.
+        Icode_LINE                      = -26,
+
+    // To store shorts and ints inline
+        Icode_SHORTNUMBER               = -27,
+        Icode_INTNUMBER                 = -28,
+
+    // To create and populate array to hold values for [] and {} literals
+        Icode_LITERAL_NEW               = -29,
+        Icode_LITERAL_SET               = -30,
+
+    // Array literal with skipped index like [1,,2]
+        Icode_SPARE_ARRAYLIT            = -31,
+
+    // Load index register to prepare for the following index operation
+        Icode_REG_IND_C0                = -32,
+        Icode_REG_IND_C1                = -33,
+        Icode_REG_IND_C2                = -34,
+        Icode_REG_IND_C3                = -35,
+        Icode_REG_IND_C4                = -36,
+        Icode_REG_IND_C5                = -37,
+        Icode_REG_IND1                  = -38,
+        Icode_REG_IND2                  = -39,
+        Icode_REG_IND4                  = -40,
+
+    // Load string register to prepare for the following string operation
+        Icode_REG_STR_C0                = -41,
+        Icode_REG_STR_C1                = -42,
+        Icode_REG_STR_C2                = -43,
+        Icode_REG_STR_C3                = -44,
+        Icode_REG_STR1                  = -45,
+        Icode_REG_STR2                  = -46,
+        Icode_REG_STR4                  = -47,
+
+    // Version of getvar/setvar that read var index directly from bytecode
+        Icode_GETVAR1                   = -48,
+        Icode_SETVAR1                   = -49,
+
+    // Load undefined
+        Icode_UNDEF                     = -50,
+        Icode_ZERO                      = -51,
+        Icode_ONE                       = -52,
+
+    // entrance and exit from .()
+       Icode_ENTERDQ                    = -53,
+       Icode_LEAVEDQ                    = -54,
+
+       Icode_TAIL_CALL                  = -55,
+
+    // Clear local to allow GC its context
+       Icode_LOCAL_CLEAR                = -56,
+
+    // Literal get/set
+       Icode_LITERAL_GETTER             = -57,
+       Icode_LITERAL_SETTER             = -58,
+
+    // const
+       Icode_SETCONST                   = -59,
+       Icode_SETCONSTVAR                = -60,
+       Icode_SETCONSTVAR1               = -61,
+
+    // Generator opcodes (along with Token.YIELD)
+       Icode_GENERATOR                  = -62,
+       Icode_GENERATOR_END              = -63,
+
+       Icode_DEBUGGER                   = -64,
+
+       // Last icode
+        MIN_ICODE                       = -64;
+
+    static String bytecodeName(int bytecode)
+    {
+        if (!validBytecode(bytecode)) {
+            throw new IllegalArgumentException(String.valueOf(bytecode));
+        }
+
+        if (!Token.printICode) {
+            return String.valueOf(bytecode);
+        }
+
+        if (validTokenCode(bytecode)) {
+            return Token.name(bytecode);
+        }
+
+        switch (bytecode) {
+          case Icode_DUP:              return "DUP";
+          case Icode_DUP2:             return "DUP2";
+          case Icode_SWAP:             return "SWAP";
+          case Icode_POP:              return "POP";
+          case Icode_POP_RESULT:       return "POP_RESULT";
+          case Icode_IFEQ_POP:         return "IFEQ_POP";
+          case Icode_VAR_INC_DEC:      return "VAR_INC_DEC";
+          case Icode_NAME_INC_DEC:     return "NAME_INC_DEC";
+          case Icode_PROP_INC_DEC:     return "PROP_INC_DEC";
+          case Icode_ELEM_INC_DEC:     return "ELEM_INC_DEC";
+          case Icode_REF_INC_DEC:      return "REF_INC_DEC";
+          case Icode_SCOPE_LOAD:       return "SCOPE_LOAD";
+          case Icode_SCOPE_SAVE:       return "SCOPE_SAVE";
+          case Icode_TYPEOFNAME:       return "TYPEOFNAME";
+          case Icode_NAME_AND_THIS:    return "NAME_AND_THIS";
+          case Icode_PROP_AND_THIS:    return "PROP_AND_THIS";
+          case Icode_ELEM_AND_THIS:    return "ELEM_AND_THIS";
+          case Icode_VALUE_AND_THIS:   return "VALUE_AND_THIS";
+          case Icode_CLOSURE_EXPR:     return "CLOSURE_EXPR";
+          case Icode_CLOSURE_STMT:     return "CLOSURE_STMT";
+          case Icode_CALLSPECIAL:      return "CALLSPECIAL";
+          case Icode_RETUNDEF:         return "RETUNDEF";
+          case Icode_GOSUB:            return "GOSUB";
+          case Icode_STARTSUB:         return "STARTSUB";
+          case Icode_RETSUB:           return "RETSUB";
+          case Icode_LINE:             return "LINE";
+          case Icode_SHORTNUMBER:      return "SHORTNUMBER";
+          case Icode_INTNUMBER:        return "INTNUMBER";
+          case Icode_LITERAL_NEW:      return "LITERAL_NEW";
+          case Icode_LITERAL_SET:      return "LITERAL_SET";
+          case Icode_SPARE_ARRAYLIT:   return "SPARE_ARRAYLIT";
+          case Icode_REG_IND_C0:       return "REG_IND_C0";
+          case Icode_REG_IND_C1:       return "REG_IND_C1";
+          case Icode_REG_IND_C2:       return "REG_IND_C2";
+          case Icode_REG_IND_C3:       return "REG_IND_C3";
+          case Icode_REG_IND_C4:       return "REG_IND_C4";
+          case Icode_REG_IND_C5:       return "REG_IND_C5";
+          case Icode_REG_IND1:         return "LOAD_IND1";
+          case Icode_REG_IND2:         return "LOAD_IND2";
+          case Icode_REG_IND4:         return "LOAD_IND4";
+          case Icode_REG_STR_C0:       return "REG_STR_C0";
+          case Icode_REG_STR_C1:       return "REG_STR_C1";
+          case Icode_REG_STR_C2:       return "REG_STR_C2";
+          case Icode_REG_STR_C3:       return "REG_STR_C3";
+          case Icode_REG_STR1:         return "LOAD_STR1";
+          case Icode_REG_STR2:         return "LOAD_STR2";
+          case Icode_REG_STR4:         return "LOAD_STR4";
+          case Icode_GETVAR1:          return "GETVAR1";
+          case Icode_SETVAR1:          return "SETVAR1";
+          case Icode_UNDEF:            return "UNDEF";
+          case Icode_ZERO:             return "ZERO";
+          case Icode_ONE:              return "ONE";
+          case Icode_ENTERDQ:          return "ENTERDQ";
+          case Icode_LEAVEDQ:          return "LEAVEDQ";
+          case Icode_TAIL_CALL:        return "TAIL_CALL";
+          case Icode_LOCAL_CLEAR:      return "LOCAL_CLEAR";
+          case Icode_LITERAL_GETTER:   return "LITERAL_GETTER";
+          case Icode_LITERAL_SETTER:   return "LITERAL_SETTER";
+          case Icode_SETCONST:         return "SETCONST";
+          case Icode_SETCONSTVAR:      return "SETCONSTVAR";
+          case Icode_SETCONSTVAR1:     return "SETCONSTVAR1";
+          case Icode_GENERATOR:        return "GENERATOR";
+          case Icode_GENERATOR_END:    return "GENERATOR_END";
+          case Icode_DEBUGGER:         return "DEBUGGER";
+        }
+
+        // icode without name
+        throw new IllegalStateException(String.valueOf(bytecode));
+    }
+
+    static boolean validIcode(int icode)
+    {
+        return MIN_ICODE <= icode && icode <= 0;
+    }
+
+    static boolean validTokenCode(int token)
+    {
+        return Token.FIRST_BYTECODE_TOKEN <= token
+               && token <= Token.LAST_BYTECODE_TOKEN;
+    }
+
+    static boolean validBytecode(int bytecode)
+    {
+        return validIcode(bytecode) || validTokenCode(bytecode);
+    }
+}
diff -pruN 20130227+dfsg1-14/rhino/src/org/mozilla/javascript/IdFunctionCall.java 20130227+rhino-1/rhino/src/org/mozilla/javascript/IdFunctionCall.java
--- 20130227+dfsg1-14/rhino/src/org/mozilla/javascript/IdFunctionCall.java	1970-01-01 00:00:00.000000000 +0000
+++ 20130227+rhino-1/rhino/src/org/mozilla/javascript/IdFunctionCall.java	2023-05-25 14:24:50.000000000 +0000
@@ -0,0 +1,23 @@
+/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+package org.mozilla.javascript;
+
+/**
+ * Master for id-based functions that knows their properties and how to
+ * execute them.
+ */
+public interface IdFunctionCall
+{
+    /**
+     * 'thisObj' will be null if invoked as constructor, in which case
+     * instance of Scriptable should be returned
+     */
+    public Object execIdCall(IdFunctionObject f, Context cx, Scriptable scope,
+                             Scriptable thisObj, Object[] args);
+
+}
+
diff -pruN 20130227+dfsg1-14/rhino/src/org/mozilla/javascript/IdFunctionObject.java 20130227+rhino-1/rhino/src/org/mozilla/javascript/IdFunctionObject.java
--- 20130227+dfsg1-14/rhino/src/org/mozilla/javascript/IdFunctionObject.java	1970-01-01 00:00:00.000000000 +0000
+++ 20130227+rhino-1/rhino/src/org/mozilla/javascript/IdFunctionObject.java	2023-05-25 14:24:50.000000000 +0000
@@ -0,0 +1,168 @@
+/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// API class
+
+package org.mozilla.javascript;
+
+public class IdFunctionObject extends BaseFunction
+{
+
+    static final long serialVersionUID = -5332312783643935019L;
+
+    public IdFunctionObject(IdFunctionCall idcall, Object tag, int id, int arity)
+    {
+        if (arity < 0)
+            throw new IllegalArgumentException();
+
+        this.idcall = idcall;
+        this.tag = tag;
+        this.methodId = id;
+        this.arity = arity;
+        if (arity < 0) throw new IllegalArgumentException();
+    }
+
+    public IdFunctionObject(IdFunctionCall idcall, Object tag, int id,
+                            String name, int arity, Scriptable scope)
+    {
+        super(scope, null);
+
+        if (arity < 0)
+            throw new IllegalArgumentException();
+        if (name == null)
+            throw new IllegalArgumentException();
+
+        this.idcall = idcall;
+        this.tag = tag;
+        this.methodId = id;
+        this.arity = arity;
+        this.functionName = name;
+    }
+
+    public void initFunction(String name, Scriptable scope)
+    {
+        if (name == null) throw new IllegalArgumentException();
+        if (scope == null) throw new IllegalArgumentException();
+        this.functionName = name;
+        setParentScope(scope);
+    }
+
+    public final boolean hasTag(Object tag)
+    {
+        return tag == null ? this.tag == null : tag.equals(this.tag);
+    }
+
+    public Object getTag() {
+        return tag;
+    }
+
+    public final int methodId()
+    {
+        return methodId;
+    }
+
+    public final void markAsConstructor(Scriptable prototypeProperty)
+    {
+        useCallAsConstructor = true;
+        setImmunePrototypeProperty(prototypeProperty);
+    }
+
+    public final void addAsProperty(Scriptable target)
+    {
+        ScriptableObject.defineProperty(target, functionName, this,
+                                        ScriptableObject.DONTENUM);
+    }
+
+    public void exportAsScopeProperty()
+    {
+        addAsProperty(getParentScope());
+    }
+
+    @Override
+    public Scriptable getPrototype()
+    {
+        // Lazy initialization of prototype: for native functions this
+        // may not be called at all
+        Scriptable proto = super.getPrototype();
+        if (proto == null) {
+            proto = getFunctionPrototype(getParentScope());
+            setPrototype(proto);
+        }
+        return proto;
+    }
+
+    @Override
+    public Object call(Context cx, Scriptable scope, Scriptable thisObj,
+                       Object[] args)
+    {
+        return idcall.execIdCall(this, cx, scope, thisObj, args);
+    }
+
+    @Override
+    public Scriptable createObject(Context cx, Scriptable scope)
+    {
+        if (useCallAsConstructor) {
+            return null;
+        }
+        // Throw error if not explicitly coded to be used as constructor,
+        // to satisfy ECMAScript standard (see bugzilla 202019).
+        // To follow current (2003-05-01) SpiderMonkey behavior, change it to:
+        // return super.createObject(cx, scope);
+        throw ScriptRuntime.typeError1("msg.not.ctor", functionName);
+    }
+
+    @Override
+    String decompile(int indent, int flags)
+    {
+        StringBuilder sb = new StringBuilder();
+        boolean justbody = (0 != (flags & Decompiler.ONLY_BODY_FLAG));
+        if (!justbody) {
+            sb.append("function ");
+            sb.append(getFunctionName());
+            sb.append("() { ");
+        }
+        sb.append("[native code for ");
+        if (idcall instanceof Scriptable) {
+            Scriptable sobj = (Scriptable)idcall;
+            sb.append(sobj.getClassName());
+            sb.append('.');
+        }
+        sb.append(getFunctionName());
+        sb.append(", arity=");
+        sb.append(getArity());
+        sb.append(justbody ? "]\n" : "] }\n");
+        return sb.toString();
+    }
+
+    @Override
+    public int getArity()
+    {
+        return arity;
+    }
+
+    @Override
+    public int getLength() { return getArity(); }
+
+    @Override
+    public String getFunctionName()
+    {
+        return (functionName == null) ? "" : functionName;
+    }
+
+    public final RuntimeException unknown()
+    {
+        // It is program error to call id-like methods for unknown function
+        return new IllegalArgumentException(
+            "BAD FUNCTION ID="+methodId+" MASTER="+idcall);
+    }
+
+    private final IdFunctionCall idcall;
+    private final Object tag;
+    private final int methodId;
+    private int arity;
+    private boolean useCallAsConstructor;
+    private String functionName;
+}
diff -pruN 20130227+dfsg1-14/rhino/src/org/mozilla/javascript/IdFunctionObjectES6.java 20130227+rhino-1/rhino/src/org/mozilla/javascript/IdFunctionObjectES6.java
--- 20130227+dfsg1-14/rhino/src/org/mozilla/javascript/IdFunctionObjectES6.java	1970-01-01 00:00:00.000000000 +0000
+++ 20130227+rhino-1/rhino/src/org/mozilla/javascript/IdFunctionObjectES6.java	2023-05-25 14:24:50.000000000 +0000
@@ -0,0 +1,44 @@
+package org.mozilla.javascript;
+
+public class IdFunctionObjectES6 extends IdFunctionObject{
+
+    public IdFunctionObjectES6(IdFunctionCall idcall, Object tag, int id, String name, int arity, Scriptable scope) {
+        super(idcall, tag, id, name, arity, scope);
+    }
+
+    private static final int
+        Id_length       = 1,
+        Id_name         = 3;
+
+    private boolean myLength = true;
+    private boolean myName = true;
+
+    @Override
+    protected int findInstanceIdInfo(String s) {
+        if (s.equals("length")) return instanceIdInfo(READONLY | DONTENUM, Id_length);
+        else if (s.equals("name")) return instanceIdInfo(READONLY | DONTENUM, Id_name);
+        return super.findInstanceIdInfo(s);
+    }
+
+    @Override
+    protected Object getInstanceIdValue(int id) {
+        if (id == Id_length && !myLength) {
+            return NOT_FOUND;
+        } else if (id == Id_name && !myName) {
+            return NOT_FOUND;
+        }
+        return super.getInstanceIdValue(id);
+    }
+
+    @Override
+    protected void setInstanceIdValue(int id, Object value) {
+        if (id == Id_length && value == NOT_FOUND) {
+            this.myLength = false;
+            return;
+        } else if (id == Id_name && value == NOT_FOUND) {
+            this.myName = false;
+            return;
+        }
+        super.setInstanceIdValue(id, value);
+    }
+}
diff -pruN 20130227+dfsg1-14/rhino/src/org/mozilla/javascript/IdScriptableObject.java 20130227+rhino-1/rhino/src/org/mozilla/javascript/IdScriptableObject.java
--- 20130227+dfsg1-14/rhino/src/org/mozilla/javascript/IdScriptableObject.java	1970-01-01 00:00:00.000000000 +0000
+++ 20130227+rhino-1/rhino/src/org/mozilla/javascript/IdScriptableObject.java	2023-05-25 14:24:50.000000000 +0000
@@ -0,0 +1,1032 @@
+/* -*- Mode: java; tab-width: 4; indent-tabs-mode: 1; c-basic-offset: 4 -*-
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+package org.mozilla.javascript;
+
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
+
+/**
+Base class for native object implementation that uses IdFunctionObject to export its methods to script via <class-name>.prototype object.
+
+Any descendant should implement at least the following methods:
+    findInstanceIdInfo
+    getInstanceIdName
+    execIdCall
+    methodArity
+
+To define non-function properties, the descendant should override
+    getInstanceIdValue
+    setInstanceIdValue
+to get/set property value and provide its default attributes.
+
+
+To customize initialization of constructor and prototype objects, descendant
+may override scopeInit or fillConstructorProperties methods.
+
+*/
+public abstract class IdScriptableObject extends ScriptableObject
+    implements IdFunctionCall
+{
+    private transient PrototypeValues prototypeValues;
+
+    private static final class PrototypeValues implements Serializable
+    {
+        static final long serialVersionUID = 3038645279153854371L;
+
+        private static final int NAME_SLOT = 1;
+        private static final int SLOT_SPAN = 2;
+
+        private IdScriptableObject obj;
+        private int maxId;
+        private Object[] valueArray;
+        private short[] attributeArray;
+
+        // The following helps to avoid creation of valueArray during runtime
+        // initialization for common case of "constructor" property
+        int constructorId;
+        private IdFunctionObject constructor;
+        private short constructorAttrs;
+
+        PrototypeValues(IdScriptableObject obj, int maxId)
+        {
+            if (obj == null) throw new IllegalArgumentException();
+            if (maxId < 1) throw new IllegalArgumentException();
+            this.obj = obj;
+            this.maxId = maxId;
+        }
+
+        final int getMaxId()
+        {
+            return maxId;
+        }
+
+        final void initValue(int id, String name, Object value, int attributes)
+        {
+            if (!(1 <= id && id <= maxId))
+                throw new IllegalArgumentException();
+            if (name == null)
+                throw new IllegalArgumentException();
+            if (value == NOT_FOUND)
+                throw new IllegalArgumentException();
+            ScriptableObject.checkValidAttributes(attributes);
+            if (obj.findPrototypeId(name) != id)
+                throw new IllegalArgumentException(name);
+
+            if (id == constructorId) {
+                if (!(value instanceof IdFunctionObject)) {
+                    throw new IllegalArgumentException("consructor should be initialized with IdFunctionObject");
+                }
+                constructor = (IdFunctionObject)value;
+                constructorAttrs = (short)attributes;
+                return;
+            }
+
+            initSlot(id, name, value, attributes);
+        }
+
+        final void initValue(int id, Symbol key, Object value, int attributes)
+        {
+            if (!(1 <= id && id <= maxId))
+                throw new IllegalArgumentException();
+            if (key == null)
+                throw new IllegalArgumentException();
+            if (value == NOT_FOUND)
+                throw new IllegalArgumentException();
+            ScriptableObject.checkValidAttributes(attributes);
+            if (obj.findPrototypeId(key) != id)
+                throw new IllegalArgumentException(key.toString());
+
+            if (id == constructorId) {
+                if (!(value instanceof IdFunctionObject)) {
+                    throw new IllegalArgumentException("consructor should be initialized with IdFunctionObject");
+                }
+                constructor = (IdFunctionObject)value;
+                constructorAttrs = (short)attributes;
+                return;
+            }
+
+            initSlot(id, "", value, attributes);
+        }
+
+        private void initSlot(int id, String name, Object value,
+                              int attributes)
+        {
+            Object[] array = valueArray;
+            if (array == null)
+                throw new IllegalStateException();
+
+            if (value == null) {
+                value = UniqueTag.NULL_VALUE;
+            }
+            int index = (id - 1) * SLOT_SPAN;
+            synchronized (this) {
+                Object value2 = array[index];
+                if (value2 == null) {
+                    array[index] = value;
+                    array[index + NAME_SLOT] = name;
+                    attributeArray[id - 1] = (short)attributes;
+                } else {
+                    if (!name.equals(array[index + NAME_SLOT]))
+                         throw new IllegalStateException();
+                }
+            }
+        }
+
+        final IdFunctionObject createPrecachedConstructor()
+        {
+            if (constructorId != 0) throw new IllegalStateException();
+            constructorId = obj.findPrototypeId("constructor");
+            if (constructorId == 0) {
+                throw new IllegalStateException(
+                    "No id for constructor property");
+            }
+            obj.initPrototypeId(constructorId);
+            if (constructor == null) {
+                throw new IllegalStateException(
+                    obj.getClass().getName()+".initPrototypeId() did not "
+                    +"initialize id="+constructorId);
+            }
+            constructor.initFunction(obj.getClassName(),
+                                     ScriptableObject.getTopLevelScope(obj));
+            constructor.markAsConstructor(obj);
+            return constructor;
+        }
+
+        final int findId(String name)
+        {
+            return obj.findPrototypeId(name);
+        }
+
+        final int findId(Symbol key)
+        {
+            return obj.findPrototypeId(key);
+        }
+
+        final boolean has(int id)
+        {
+            Object[] array = valueArray;
+            if (array == null) {
+                // Not yet initialized, assume all exists
+                return true;
+            }
+            int valueSlot = (id  - 1) * SLOT_SPAN;
+            Object value = array[valueSlot];
+            if (value == null) {
+                // The particular entry has not been yet initialized
+                return true;
+            }
+            return value != NOT_FOUND;
+        }
+
+        final Object get(int id)
+        {
+            Object value = ensureId(id);
+            if (value == UniqueTag.NULL_VALUE) {
+                value = null;
+            }
+            return value;
+        }
+
+        final void set(int id, Scriptable start, Object value)
+        {
+            if (value == NOT_FOUND) throw new IllegalArgumentException();
+            ensureId(id);
+            int attr = attributeArray[id - 1];
+            if ((attr & READONLY) == 0) {
+                if (start == obj) {
+                    if (value == null) {
+                        value = UniqueTag.NULL_VALUE;
+                    }
+                    int valueSlot = (id  - 1) * SLOT_SPAN;
+                    synchronized (this) {
+                        valueArray[valueSlot] = value;
+                    }
+                }
+                else {
+                    int nameSlot = (id  - 1) * SLOT_SPAN + NAME_SLOT;
+                    String name = (String)valueArray[nameSlot];
+                    start.put(name, start, value);
+                }
+            }
+        }
+
+        final void delete(int id)
+        {
+            ensureId(id);
+            int attr = attributeArray[id - 1];
+            // non-configurable
+            if ((attr & PERMANENT) != 0) {
+                Context cx = Context.getContext();
+                if (cx.isStrictMode()) {
+                    int nameSlot = (id  - 1) * SLOT_SPAN + NAME_SLOT;
+                    String name = (String)valueArray[nameSlot];
+                    throw ScriptRuntime.typeError1("msg.delete.property.with.configurable.false", name);
+                }
+            } else {
+                int valueSlot = (id  - 1) * SLOT_SPAN;
+                synchronized (this) {
+                    valueArray[valueSlot] = NOT_FOUND;
+                    attributeArray[id - 1] = EMPTY;
+                }
+            }
+        }
+
+        final int getAttributes(int id)
+        {
+            ensureId(id);
+            return attributeArray[id - 1];
+        }
+
+        final void setAttributes(int id, int attributes)
+        {
+            ScriptableObject.checkValidAttributes(attributes);
+            ensureId(id);
+            synchronized (this) {
+                attributeArray[id - 1] = (short)attributes;
+            }
+        }
+
+        final Object[] getNames(boolean getAll, Object[] extraEntries)
+        {
+            Object[] names = null;
+            int count = 0;
+            for (int id = 1; id <= maxId; ++id) {
+                Object value = ensureId(id);
+                if (getAll || (attributeArray[id - 1] & DONTENUM) == 0) {
+                    if (value != NOT_FOUND) {
+                        int nameSlot = (id  - 1) * SLOT_SPAN + NAME_SLOT;
+                        String name = (String)valueArray[nameSlot];
+                        if (names == null) {
+                            names = new Object[maxId];
+                        }
+                        names[count++] = name;
+                    }
+                }
+            }
+            if (count == 0) {
+                return extraEntries;
+            } else if (extraEntries == null || extraEntries.length == 0) {
+                if (count != names.length) {
+                    Object[] tmp = new Object[count];
+                    System.arraycopy(names, 0, tmp, 0, count);
+                    names = tmp;
+                }
+                return names;
+            } else {
+                int extra = extraEntries.length;
+                Object[] tmp = new Object[extra + count];
+                System.arraycopy(extraEntries, 0, tmp, 0, extra);
+                System.arraycopy(names, 0, tmp, extra, count);
+                return tmp;
+            }
+        }
+
+        private Object ensureId(int id)
+        {
+            