htmlunit-core-js-2.8/0000755000175000017500000000000011530107756014414 5ustar cavedoncavedonhtmlunit-core-js-2.8/MPL-1.1.html0000644000175000017500000006550610776624432016251 0ustar cavedoncavedon Mozilla Public License version 1.1

(Plain text version)

Mozilla Public License Version 1.1

1. Definitions.

1.0.1. "Commercial Use"
means distribution or otherwise making the Covered Code available to a third party.
1.1. "Contributor"
means each entity that creates or contributes to the creation of Modifications.
1.2. "Contributor Version"
means the combination of the Original Code, prior Modifications used by a Contributor, and the Modifications made by that particular Contributor.
1.3. "Covered Code"
means the Original Code or Modifications or the combination of the Original Code and Modifications, in each case including portions thereof.
1.4. "Electronic Distribution Mechanism"
means a mechanism generally accepted in the software development community for the electronic transfer of data.
1.5. "Executable"
means Covered Code in any form other than Source Code.
1.6. "Initial Developer"
means the individual or entity identified as the Initial Developer in the Source Code notice required by Exhibit A.
1.7. "Larger Work"
means a work which combines Covered Code or portions thereof with code not governed by the terms of this License.
1.8. "License"
means this document.
1.8.1. "Licensable"
means having the right to grant, to the maximum extent possible, whether at the time of the initial grant or subsequently acquired, any and all of the rights conveyed herein.
1.9. "Modifications"

means any addition to or deletion from the substance or structure of either the Original Code or any previous Modifications. When Covered Code is released as a series of files, a Modification is:

  1. Any addition to or deletion from the contents of a file containing Original Code or previous Modifications.
  2. Any new file that contains any part of the Original Code or previous Modifications.
1.10. "Original Code"
means Source Code of computer software code which is described in the Source Code notice required by Exhibit A as Original Code, and which, at the time of its release under this License is not already Covered Code governed by this License.
1.10.1. "Patent Claims"
means any patent claim(s), now owned or hereafter acquired, including without limitation, method, process, and apparatus claims, in any patent Licensable by grantor.
1.11. "Source Code"
means the preferred form of the Covered Code for making modifications to it, including all modules it contains, plus any associated interface definition files, scripts used to control compilation and installation of an Executable, or source code differential comparisons against either the Original Code or another well known, available Covered Code of the Contributor's choice. The Source Code can be in a compressed or archival form, provided the appropriate decompression or de-archiving software is widely available for no charge.
1.12. "You" (or "Your")
means an individual or a legal entity exercising rights under, and complying with all of the terms of, this License or a future version of this License issued under Section 6.1. For legal entities, "You" includes any entity which 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. Source Code License.

2.1. The Initial Developer Grant.

The Initial Developer hereby grants You a world-wide, royalty-free, non-exclusive license, subject to third party intellectual property claims:

  1. under intellectual property rights (other than patent or trademark) Licensable by Initial Developer to use, reproduce, modify, display, perform, sublicense and distribute the Original Code (or portions thereof) with or without Modifications, and/or as part of a Larger Work; and
  2. under Patents Claims infringed by the making, using or selling of Original Code, to make, have made, use, practice, sell, and offer for sale, and/or otherwise dispose of the Original Code (or portions thereof).
  3. the licenses granted in this Section 2.1 (a) and (b) are effective on the date Initial Developer first distributes Original Code under the terms of this License.
  4. Notwithstanding Section 2.1 (b) above, no patent license is granted: 1) for code that You delete from the Original Code; 2) separate from the Original Code; or 3) for infringements caused by: i) the modification of the Original Code or ii) the combination of the Original Code with other software or devices.

2.2. Contributor Grant.

Subject to third party intellectual property claims, each Contributor hereby grants You a world-wide, royalty-free, non-exclusive license

  1. under intellectual property rights (other than patent or trademark) Licensable by Contributor, to use, reproduce, modify, display, perform, sublicense and distribute the Modifications created by such Contributor (or portions thereof) either on an unmodified basis, with other Modifications, as Covered Code and/or as part of a Larger Work; and
  2. under Patent Claims infringed by the making, using, or selling of Modifications made by that Contributor either alone and/or in combination with its Contributor Version (or portions of such combination), to make, use, sell, offer for sale, have made, and/or otherwise dispose of: 1) Modifications made by that Contributor (or portions thereof); and 2) the combination of Modifications made by that Contributor with its Contributor Version (or portions of such combination).
  3. the licenses granted in Sections 2.2 (a) and 2.2 (b) are effective on the date Contributor first makes Commercial Use of the Covered Code.
  4. Notwithstanding Section 2.2 (b) above, no patent license is granted: 1) for any code that Contributor has deleted from the Contributor Version; 2) separate from the Contributor Version; 3) for infringements caused by: i) third party modifications of Contributor Version or ii) the combination of Modifications made by that Contributor with other software (except as part of the Contributor Version) or other devices; or 4) under Patent Claims infringed by Covered Code in the absence of Modifications made by that Contributor.

3. Distribution Obligations.

3.1. Application of License.

The Modifications which You create or to which You contribute are governed by the terms of this License, including without limitation Section 2.2. The Source Code version of Covered Code may be distributed only under the terms of this License or a future version of this License released under Section 6.1, and You must include a copy of this License with every copy of the Source Code You distribute. You may not offer or impose any terms on any Source Code version that alters or restricts the applicable version of this License or the recipients' rights hereunder. However, You may include an additional document offering the additional rights described in Section 3.5.

3.2. Availability of Source Code.

Any Modification which You create or to which You contribute must be made available in Source Code form under the terms of this License either on the same media as an Executable version or via an accepted Electronic Distribution Mechanism to anyone to whom you made an Executable version available; and if made available via Electronic Distribution Mechanism, must remain available for at least twelve (12) months after the date it initially became available, or at least six (6) months after a subsequent version of that particular Modification has been made available to such recipients. You are responsible for ensuring that the Source Code version remains available even if the Electronic Distribution Mechanism is maintained by a third party.

3.3. Description of Modifications.

You must cause all Covered Code to which You contribute to contain a file documenting the changes You made to create that Covered Code and the date of any change. You must include a prominent statement that the Modification is derived, directly or indirectly, from Original Code provided by the Initial Developer and including the name of the Initial Developer in (a) the Source Code, and (b) in any notice in an Executable version or related documentation in which You describe the origin or ownership of the Covered Code.

3.4. Intellectual Property Matters

(a) Third Party Claims

If Contributor has knowledge that a license under a third party's intellectual property rights is required to exercise the rights granted by such Contributor under Sections 2.1 or 2.2, Contributor must include a text file with the Source Code distribution titled "LEGAL" which describes the claim and the party making the claim in sufficient detail that a recipient will know whom to contact. If Contributor obtains such knowledge after the Modification is made available as described in Section 3.2, Contributor shall promptly modify the LEGAL file in all copies Contributor makes available thereafter and shall take other steps (such as notifying appropriate mailing lists or newsgroups) reasonably calculated to inform those who received the Covered Code that new knowledge has been obtained.

(b) Contributor APIs

If Contributor's Modifications include an application programming interface and Contributor has knowledge of patent licenses which are reasonably necessary to implement that API, Contributor must also include this information in the legal file.

(c) Representations.

Contributor represents that, except as disclosed pursuant to Section 3.4 (a) above, Contributor believes that Contributor's Modifications are Contributor's original creation(s) and/or Contributor has sufficient rights to grant the rights conveyed by this License.

3.5. Required Notices.

You must duplicate the notice in Exhibit A in each file of the Source Code. If it is not possible to put such notice in a particular Source Code file due to its structure, then You must include such notice in a location (such as a relevant directory) where a user would be likely to look for such a notice. If You created one or more Modification(s) You may add your name as a Contributor to the notice described in Exhibit A. You must also duplicate this License in any documentation for the Source Code where You describe recipients' rights or ownership rights relating to Covered Code. You may choose to offer, and to charge a fee for, warranty, support, indemnity or liability obligations to one or more recipients of Covered Code. However, You may do so only on Your own behalf, and not on behalf of the Initial Developer or any Contributor. You must make it absolutely clear than any such warranty, support, indemnity or liability obligation is offered by You alone, and You hereby agree to indemnify the Initial Developer and every Contributor for any liability incurred by the Initial Developer or such Contributor as a result of warranty, support, indemnity or liability terms You offer.

3.6. Distribution of Executable Versions.

You may distribute Covered Code in Executable form only if the requirements of Sections 3.1, 3.2, 3.3, 3.4 and 3.5 have been met for that Covered Code, and if You include a notice stating that the Source Code version of the Covered Code is available under the terms of this License, including a description of how and where You have fulfilled the obligations of Section 3.2. The notice must be conspicuously included in any notice in an Executable version, related documentation or collateral in which You describe recipients' rights relating to the Covered Code. You may distribute the Executable version of Covered Code or ownership rights under a license of Your choice, which may contain terms different from this License, provided that You are in compliance with the terms of this License and that the license for the Executable version does not attempt to limit or alter the recipient's rights in the Source Code version from the rights set forth in this License. If You distribute the Executable version under a different license You must make it absolutely clear that any terms which differ from this License are offered by You alone, not by the Initial Developer or any Contributor. You hereby agree to indemnify the Initial Developer and every Contributor for any liability incurred by the Initial Developer or such Contributor as a result of any such terms You offer.

3.7. Larger Works.

You may create a Larger Work by combining Covered Code with other code not governed by the terms of this License and distribute the Larger Work as a single product. In such a case, You must make sure the requirements of this License are fulfilled for the Covered Code.

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 Code 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 included in the legal file described in Section 3.4 and must be included with all distributions of the Source Code. 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. Application of this License.

This License applies to code to which the Initial Developer has attached the notice in Exhibit A and to related Covered Code.

6. Versions of the License.

6.1. New Versions

Netscape Communications Corporation ("Netscape") may publish revised and/or new versions of the License from time to time. Each version will be given a distinguishing version number.

6.2. Effect of New Versions

Once Covered Code has been published under a particular version of the License, You may always continue to use it under the terms of that version. You may also choose to use such Covered Code under the terms of any subsequent version of the License published by Netscape. No one other than Netscape has the right to modify the terms applicable to Covered Code created under this License.

6.3. Derivative Works

If You create or use a modified version of this License (which you may only do in order to apply it to code which is not already Covered Code governed by this License), You must (a) rename Your license so that the phrases "Mozilla", "MOZILLAPL", "MOZPL", "Netscape", "MPL", "NPL" or any confusingly similar phrase do not appear in your license (except to note that your license differs from this License) and (b) otherwise make it clear that Your version of the license contains terms which differ from the Mozilla Public License and Netscape Public License. (Filling in the name of the Initial Developer, Original Code or Contributor in the notice described in Exhibit A shall not of themselves be deemed to be modifications of this License.)

7. Disclaimer of warranty

Covered code is provided under this license on an "as is" basis, without warranty of any kind, either expressed or implied, including, without limitation, warranties that the covered code 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 code is with you. Should any covered code prove defective in any respect, you (not the initial developer or any other 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 code is authorized hereunder except under this disclaimer.

8. Termination

8.1. This License and the rights granted hereunder will terminate automatically if You fail to comply with terms herein and fail to cure such breach within 30 days of becoming aware of the breach. All sublicenses to the Covered Code which are properly granted shall survive any termination of this License. Provisions which, by their nature, must remain in effect beyond the termination of this License shall survive.

8.2. If You initiate litigation by asserting a patent infringement claim (excluding declatory judgment actions) against Initial Developer or a Contributor (the Initial Developer or Contributor against whom You file such action is referred to as "Participant") alleging that:

  1. such Participant's Contributor Version directly or indirectly infringes any patent, then any and all rights granted by such Participant to You under Sections 2.1 and/or 2.2 of this License shall, upon 60 days notice from Participant terminate prospectively, unless if within 60 days after receipt of notice You either: (i) agree in writing to pay Participant a mutually agreeable reasonable royalty for Your past and future use of Modifications made by such Participant, or (ii) withdraw Your litigation claim with respect to the Contributor Version against such Participant. If within 60 days of notice, a reasonable royalty and payment arrangement are not mutually agreed upon in writing by the parties or the litigation claim is not withdrawn, the rights granted by Participant to You under Sections 2.1 and/or 2.2 automatically terminate at the expiration of the 60 day notice period specified above.
  2. any software, hardware, or device, other than such Participant's Contributor Version, directly or indirectly infringes any patent, then any rights granted to You by such Participant under Sections 2.1(b) and 2.2(b) are revoked effective as of the date You first made, used, sold, distributed, or had made, Modifications made by that Participant.

8.3. If You assert a patent infringement claim against Participant alleging that such Participant's Contributor Version directly or indirectly infringes any patent where such claim is resolved (such as by license or settlement) prior to the initiation of patent infringement litigation, then the reasonable value of the licenses granted by such Participant under Sections 2.1 or 2.2 shall be taken into account in determining the amount or value of any payment or license.

8.4. In the event of termination under Sections 8.1 or 8.2 above, all end user license agreements (excluding distributors and resellers) which have been validly granted by You or any distributor hereunder prior to termination shall survive termination.

9. Limitation of liability

Under no circumstances and under no legal theory, whether tort (including negligence), contract, or otherwise, shall you, the initial developer, any other contributor, or any distributor of covered code, or any supplier of any of such parties, be liable to any person for any indirect, special, incidental, or consequential damages of any character including, without limitation, damages for 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.

10. U.S. government end users

The Covered Code is a "commercial item," as that term is defined in 48 C.F.R. 2.101 (Oct. 1995), consisting of "commercial computer software" and "commercial computer software documentation," as such terms are used in 48 C.F.R. 12.212 (Sept. 1995). Consistent with 48 C.F.R. 12.212 and 48 C.F.R. 227.7202-1 through 227.7202-4 (June 1995), all U.S. Government End Users acquire Covered Code with only those rights set forth herein.

11. Miscellaneous

This License represents the complete agreement concerning 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. This License shall be governed by California law provisions (except to the extent applicable law, if any, provides otherwise), excluding its conflict-of-law provisions. With respect to disputes in which at least one party is a citizen of, or an entity chartered or registered to do business in the United States of America, any litigation relating to this License shall be subject to the jurisdiction of the Federal Courts of the Northern District of California, with venue lying in Santa Clara County, California, with the losing party responsible for costs, including without limitation, court costs and reasonable attorneys' fees and expenses. The application of the United Nations Convention on Contracts for the International Sale of Goods is expressly excluded. Any law or regulation which provides that the language of a contract shall be construed against the drafter shall not apply to this License.

12. Responsibility for claims

As between Initial Developer and the Contributors, each party is responsible for claims and damages arising, directly or indirectly, out of its utilization of rights under this License and You agree to work with Initial Developer and Contributors to distribute such responsibility on an equitable basis. Nothing herein is intended or shall be deemed to constitute any admission of liability.

13. Multiple-licensed code

Initial Developer may designate portions of the Covered Code as "Multiple-Licensed". "Multiple-Licensed" means that the Initial Developer permits you to utilize portions of the Covered Code under Your choice of the MPL or the alternative licenses, if any, specified by the Initial Developer in the file described in Exhibit A.

Exhibit A - Mozilla Public License.

"The contents of this file are subject to the Mozilla Public License
Version 1.1 (the "License"); you may not use this file except in
compliance with the License. You may obtain a copy of the License at
http://www.mozilla.org/MPL/

Software distributed under the License is distributed on an "AS IS"
basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
License for the specific language governing rights and limitations
under the License.

The Original Code is ______________________________________.

The Initial Developer of the Original Code is ________________________.
Portions created by ______________________ are Copyright (C) ______
_______________________. All Rights Reserved.

Contributor(s): ______________________________________.

Alternatively, the contents of this file may be used under the terms
of the _____ license (the  "[___] License"), in which case the
provisions of [______] License are applicable instead of those
above. If you wish to allow use of your version of this file only
under the terms of the [____] License and not to allow others to use
your version of this file under the MPL, indicate your decision by
deleting the provisions above and replace them with the notice and
other provisions required by the [___] License. If you do not delete
the provisions above, a recipient may use your version of this file
under either the MPL or the [___] License."

NOTE: The text of this Exhibit A may differ slightly from the text of the notices in the Source Code files of the Original Code. You should use the text of this Exhibit A rather than the text found in the Original Code Source Code for Your Modifications. htmlunit-core-js-2.8/src/0000755000175000017500000000000011530107756015203 5ustar cavedoncavedonhtmlunit-core-js-2.8/src/net/0000755000175000017500000000000011530107756015771 5ustar cavedoncavedonhtmlunit-core-js-2.8/src/net/sourceforge/0000755000175000017500000000000011530107756020314 5ustar cavedoncavedonhtmlunit-core-js-2.8/src/net/sourceforge/htmlunit/0000755000175000017500000000000011530107756022160 5ustar cavedoncavedonhtmlunit-core-js-2.8/src/net/sourceforge/htmlunit/DecompileTest.java0000644000175000017500000000165611261070323025562 0ustar cavedoncavedonpackage net.sourceforge.htmlunit; import org.junit.Assert; import org.junit.Test; import org.mozilla.javascript.Context; import org.mozilla.javascript.ContextAction; import org.mozilla.javascript.Script; /** * Test for {@link Context#decompileScript(Script, int)}. * @author Marc Guillemot */ public class DecompileTest { /** * As of head of trunk on 30.09.09, decompile of "new Date()" returns "new Date" without parentheses. * @see Bug 519692 */ @Test public void newObject0Arg() { final String source = "var x = new Date().getTime();"; final ContextAction action = new ContextAction() { public Object run(final Context cx) { final Script script = cx.compileString(source, "my script", 0, null); Assert.assertEquals(source, cx.decompileScript(script, 4).trim()); return null; } }; Utils.runWithAllOptimizationLevels(action); } } htmlunit-core-js-2.8/src/net/sourceforge/htmlunit/PrimitiveTypeScopeResolutionTest.java0000644000175000017500000000502411111044312031533 0ustar cavedoncavedonpackage net.sourceforge.htmlunit; import net.sourceforge.htmlunit.Utils; import org.junit.Test; import org.junit.runner.RunWith; import org.mozilla.javascript.Context; import org.mozilla.javascript.ContextAction; import org.mozilla.javascript.Scriptable; import org.mozilla.javascript.ScriptableObject; /** * Unit tests for Bug 374918 - * String primitive prototype wrongly resolved when used with many top scopes * @author Marc Guillemot */ @RunWith(RhinoPatchedRunner.class) public class PrimitiveTypeScopeResolutionTest { /** */ @Test public void functionCall() { String str2 = "function f() { String.prototype.foo = function() { return 'from 2' }; \n" + "var s2 = 's2';\n" + "var s2Foo = s2.foo();\n" + "if (s2Foo != 'from 2') throw 's2 got: ' + s2Foo;\n" // fails + "}"; String str1 = "String.prototype.foo = function() { return 'from 1'}; scope2.f()"; testWithTwoScopes(str1, str2); } /** */ @Test public void propertyAccess() { String str2 = "function f() { String.prototype.foo = 'from 2'; \n" + "var s2 = 's2';\n" + "var s2Foo = s2.foo;\n" + "if (s2Foo != 'from 2') throw 's2 got: ' + s2Foo;\n" // fails + "}"; String str1 = "String.prototype.foo = 'from 1'; scope2.f()"; testWithTwoScopes(str1, str2); } private void testWithTwoScopes(final String scriptScope1, final String scriptScope2) { final ContextAction action = new ContextAction() { public Object run(final Context cx) { final Scriptable scope1 = cx.initStandardObjects(new MySimpleScriptableObject("scope1")); final Scriptable scope2 = cx.initStandardObjects(new MySimpleScriptableObject("scope2")); cx.evaluateString(scope2, scriptScope2, "source2", 1, null); scope1.put("scope2", scope1, scope2); return cx.evaluateString(scope1, scriptScope1, "source1", 1, null); } }; Utils.runWithAllOptimizationLevels(action); } /** * Simple utility allowing to better see the concerned scope while debugging */ static class MySimpleScriptableObject extends ScriptableObject { private String label_; MySimpleScriptableObject(String label) { label_ = label; } @Override public String getClassName() { return "MySimpleScriptableObject"; } @Override public String toString() { return label_; } }; } htmlunit-core-js-2.8/src/net/sourceforge/htmlunit/NumberTest.java0000644000175000017500000000112011327403546025105 0ustar cavedoncavedonpackage net.sourceforge.htmlunit; import org.junit.Test; /** * Unit tests for Bug 538172 - * Number.toString fails for 2.274341322658976E-309 * @author Marc Guillemot */ public class NumberTest { /** * @throws Exception if the test fails */ @Test public void test() throws Exception { final String script = "var n = 2.274341322658976E-309;\n" + "var s = '' + n;\n" + "if (s != '2.274341322658976e-309') throw 'got ' + s"; Utilities.executeScript(script); Utilities.executeScript("'' + 1"); } } htmlunit-core-js-2.8/src/net/sourceforge/htmlunit/RhinoPatchedRunner.java0000644000175000017500000000230510776651054026573 0ustar cavedoncavedonpackage net.sourceforge.htmlunit; import java.lang.reflect.Method; import org.junit.internal.runners.InitializationError; import org.junit.internal.runners.JUnit4ClassRunner; import org.junit.internal.runners.TestMethod; /** * Runs the unit test, expecting them to fail when run with unpatched Rhino version * (in fact when system property {@link #PROPERTY_RHINO} is set to {@link #PROPERTY_RHINO_VALUE_ORIGINAL}). * @author Marc Guillemot */ public class RhinoPatchedRunner extends JUnit4ClassRunner { private boolean runWithOriginalRhino; public static final String PROPERTY_RHINO = "rhino"; public static final String PROPERTY_RHINO_VALUE_ORIGINAL = "original"; public RhinoPatchedRunner(final Class klass) throws InitializationError { super(klass); runWithOriginalRhino = PROPERTY_RHINO_VALUE_ORIGINAL.equalsIgnoreCase(System.getProperty(PROPERTY_RHINO)); } @Override protected TestMethod wrapMethod(final Method method) { if (runWithOriginalRhino) { return new TestMethod(method, getTestClass()) { @Override protected Class getExpectedException() { return Throwable.class; } }; } else { return super.wrapMethod(method); } } } htmlunit-core-js-2.8/src/net/sourceforge/htmlunit/DelegatorAndHostObjectTest.java0000644000175000017500000000433111332527432030177 0ustar cavedoncavedonpackage net.sourceforge.htmlunit; import org.junit.Assert; import org.junit.Test; import org.mozilla.javascript.Context; import org.mozilla.javascript.ContextAction; import org.mozilla.javascript.Delegator; import org.mozilla.javascript.Scriptable; import org.mozilla.javascript.ScriptableObject; /** * Unit tests for Bug 539875 - * Delegator incompatible with host objects with functions. * * @author Daniel Gredler * @author Marc Guillemot */ public class DelegatorAndHostObjectTest { public static class MyHostObject extends ScriptableObject { private int x; @Override public String getClassName() { return getClass().getSimpleName(); } public Delegator jsFunction_createDelegator() { return new Delegator(this); } public int jsFunction_methodWithParam(final MyHostObject param) { return 123; } public int jsFunction_foo() { return 42; } public int jsGet_x() { return x; } public void jsSet_x(int x) { this.x = x; } } @Test public void delegatorAndHostObjectFunction() { testIt("new MyHostObject().createDelegator().foo()", 42); } @Test public void delegatorAndHostObjectGetterSetter() { testIt("var t = new MyHostObject().createDelegator(); t.x = 12; t.x;", 12); } @Test public void delegatorAsParameter() { testIt("var t = new MyHostObject().createDelegator(); t.methodWithParam(t);", 123); } @Test public void delegatorAnd__defineGetter__() { final String script = "var t = new MyHostObject().createDelegator();\n" + "t.__defineGetter__('foo', function(a) { return 'hello' });\n" + "t.foo;"; testIt(script, "hello"); } private void testIt(final String script, final Object expected) { final ContextAction action = new ContextAction() { public Object run(final Context cx) { try { Scriptable scope = cx.initStandardObjects(); ScriptableObject.defineClass(scope, MyHostObject.class); final Object o = cx.evaluateString(scope, script, "test_script", 1, null); Assert.assertEquals(expected, o); return o; } catch (final Exception e) { throw new RuntimeException(e); } } }; Utils.runWithAllOptimizationLevels(action); } } htmlunit-core-js-2.8/src/net/sourceforge/htmlunit/HostExceptionsTest.java0000644000175000017500000000631211261076053026640 0ustar cavedoncavedonpackage net.sourceforge.htmlunit; import org.junit.Assert; import org.junit.Test; import org.mozilla.javascript.Context; import org.mozilla.javascript.ContextAction; import org.mozilla.javascript.ContextFactory; import org.mozilla.javascript.Scriptable; import org.mozilla.javascript.ScriptableObject; /** * It can be useful to avoid that JavaScript catch block can catch internal exceptions in host objects. * Indeed it hides these exception and makes more difficult to find the root problems. * @see Rhino bug 519935 * @author Marc Guillemot */ public class HostExceptionsTest { /** * JS catch block should always catch JS exceptions */ @Test public void testCatchJSException() throws Exception { doTest("foo.willThrowJSException", true); doTest("foo.willThrowJSException", false); } /** * Per default JS catch block catch Java exception */ @Test public void testCatchJavaException() throws Exception { doTest("foo.willThrowJavaException", true); doTest("foo.throwJavaException()", true); } /** * If configured, JS catch block should not catch Java exception */ @Test public void testDontCatchJavaException_inGetter() throws Exception { try { doTest("foo.willThrowJavaException", false); Assert.fail("Should have throw!"); } catch(final Exception e) { Assert.assertSame(MyScriptable.javaException, e.getCause()); } } /** * If configured, JS catch block should not catch Java exception */ @Test public void testDontCatchJavaException_inFunction() throws Exception { try { doTest("foo.throwJavaException()", false); Assert.fail("Should have throw!"); } catch(final Exception e) { Assert.assertSame(MyScriptable.javaException, e.getCause()); } } private void doTest(final String jsExpression, final boolean contextFeatureJSCatchOn) throws Exception { final String script = "var foo = new MyScriptable(); try { " + jsExpression + "} catch(e) {}"; final ContextFactory myContextFactory = new ContextFactory() { protected boolean hasFeature(final Context cx, final int featureIndex) { if (Context.FEATURE_HTMLUNIT_JS_CATCH_JAVA_EXCEPTION == featureIndex) { return contextFeatureJSCatchOn; } return super.hasFeature(cx, featureIndex); }; }; final ContextAction action = new ContextAction() { public Object run(final Context cx) { final Scriptable scope = cx.initStandardObjects(); try { ScriptableObject.defineClass(scope, MyScriptable.class); } catch (final Exception e) { throw new RuntimeException(); } cx.evaluateString(scope, script, "test.js", 0, null); return null; } }; Utils.runWithAllOptimizationLevels(myContextFactory, action); } public static class MyScriptable extends ScriptableObject { static RuntimeException javaException = new NullPointerException(); @Override public String getClassName() { return "MyScriptable"; } public String jsGet_willThrowJavaException() { throw javaException; } public String jsGet_willThrowJSException() { throw Context.reportRuntimeError("this is a JS exception"); } public void jsFunction_throwJavaException() { throw javaException; } } } htmlunit-core-js-2.8/src/net/sourceforge/htmlunit/ContextMethodsTest.java0000644000175000017500000000360611154745020026632 0ustar cavedoncavedonpackage net.sourceforge.htmlunit; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import org.junit.Assert; import org.junit.Test; import org.mozilla.javascript.Context; import org.mozilla.javascript.ContextAction; import org.mozilla.javascript.ContextFactory; import org.mozilla.javascript.ErrorReporter; import org.mozilla.javascript.Evaluator; import org.mozilla.javascript.Script; import org.mozilla.javascript.Scriptable; /** * Unit tests for Bug 481152 - * Open Context class for extension * @author Marc Guillemot */ public class ContextMethodsTest { /** * When {@link Context#compileString(String, String, int, Object)} is protected and not final, * we can capture code passed to eval. * @throws Exception if the test fails */ @Test public void captureEvalScript() throws Exception { final List compiled = new ArrayList(); final ContextFactory cf = new ContextFactory() { @Override protected Context makeContext() { return new Context(this) { @Override protected Script compileString(String source, Evaluator compiler, ErrorReporter compilationErrorReporter, String sourceName, int lineno, Object securityDomain) { compiled.add(source); return super.compileString(source, compiler, compilationErrorReporter, sourceName, lineno, securityDomain); } }; } }; final String source = "eval('1 + 2')"; final ContextAction action = new ContextAction() { public Object run(Context cx) { final Scriptable scope = cx.initStandardObjects(); final Script script = cx.compileString(source, "", 1, (Object) null); return script.exec(cx, scope); }; }; cf.call(action); final String[] expected = { "eval('1 + 2')", "1 + 2" }; Assert.assertEquals(Arrays.asList(expected), compiled); } } htmlunit-core-js-2.8/src/net/sourceforge/htmlunit/ExceptionPropertiesTest.java0000644000175000017500000000551511343213760027677 0ustar cavedoncavedonpackage net.sourceforge.htmlunit; import org.junit.Assert; import org.junit.Test; import org.mozilla.javascript.Context; import org.mozilla.javascript.ContextAction; import org.mozilla.javascript.RhinoException; import org.mozilla.javascript.ScriptableObject; /** * Unit tests for bug 549604. * This tests verify the properties of a JS exception and ensures that they don't change with different optimization levels. * @author Marc Guillemot */ public class ExceptionPropertiesTest { final static String LS = System.getProperty("line.separator"); @Test public void scriptStackTrace() { testScriptStackTrace("null.method()", "\tat myScript.js:1" + LS); final String script = "function f() \n" + "{\n" + " null.method();\n" + "}\n" + "f();\n"; testScriptStackTrace(script, "\tat myScript.js:3 (f)" + LS + "\tat myScript.js:5" + LS); } private void testScriptStackTrace(final String script, final String expectedStackTrace) { testScriptStackTrace(script, expectedStackTrace, -1); testScriptStackTrace(script, expectedStackTrace, 0); testScriptStackTrace(script, expectedStackTrace, 1); } private void testScriptStackTrace(final String script, final String expectedStackTrace, final int optimizationLevel) { try { Utilities.executeScript(script, optimizationLevel); } catch (final RhinoException e) { Assert.assertEquals(expectedStackTrace, e.getScriptStackTrace()); } } @Test public void fileName() { testIt("try { null.method() } catch (e) { e.fileName }", "myScript.js"); testIt("try { null.property } catch (e) { e.fileName }", "myScript.js"); } @Test public void lineNumber() { testIt("try { null.method() } catch (e) { e.lineNumber }", 1); testIt("try {\n null.method() \n} catch (e) { e.lineNumber }", 2); testIt("\ntry \n{\n null.method() \n} catch (e) { e.lineNumber }", 4); testIt("function f() {\n null.method(); \n}\n try { f() } catch (e) { e.lineNumber }", 2); } @Test public void stack() { testIt("try { null.method() } catch (e) { e.stack }", "@myScript.js:1" + LS); final String expectedStack = "f()@myScript.js:2" + LS + "@myScript.js:4" + LS; testIt("function f() {\n null.method(); \n}\n try { f() } catch (e) { e.stack }", expectedStack); } private void testIt(final String script, final Object expected) { final ContextAction action = new ContextAction() { public Object run(final Context cx) { try { final ScriptableObject scope = cx.initStandardObjects(); final Object o = cx.evaluateString(scope, script, "myScript.js", 1, null); Assert.assertEquals(expected, o); return o; } catch (final RuntimeException e) { throw e; } catch (final Exception e) { throw new RuntimeException(e); } } }; Utils.runWithAllOptimizationLevels(action); } } htmlunit-core-js-2.8/src/net/sourceforge/htmlunit/ArrayConcatTest.java0000644000175000017500000000111111154745177026072 0ustar cavedoncavedonpackage net.sourceforge.htmlunit; import org.junit.Test; /** * Unit tests for Bug 477604 - * Array.concat causes ArrayIndexOutOfBoundException with non dense array * @author Marc Guillemot */ public class ArrayConcatTest { /** * @throws Exception if the test fails */ @Test public void concat() throws Exception { final String script = "var a = [1, 2, 3];\n" + "for (var i=10; i<20; ++i) a[i] = 't' + i;\n" + "var b = [1, 2, 3];\n" + "b.concat(a)"; Utilities.executeScript(script); } } htmlunit-core-js-2.8/src/net/sourceforge/htmlunit/Utilities.java0000644000175000017500000000220711343214034024765 0ustar cavedoncavedonpackage net.sourceforge.htmlunit; import org.mozilla.javascript.Context; import org.mozilla.javascript.ContextAction; import org.mozilla.javascript.ContextFactory; import org.mozilla.javascript.Scriptable; /** * Misc utilities. * @author Marc Guillemot */ public class Utilities { /** * Execute the provided script in a fresh context * @param script the script */ static void executeScript(final String script) { final ContextAction action = new ContextAction() { public Object run(Context cx) { final Scriptable scope = cx.initStandardObjects(); return cx.evaluateString(scope, script, "myScript.js", 1, null); } }; Utils.runWithAllOptimizationLevels(action); } /** * Execute the provided script in a fresh context * @param script the script */ static void executeScript(final String script, final int optimizationLevel) { final ContextAction action = new ContextAction() { public Object run(Context cx) { final Scriptable scope = cx.initStandardObjects(); return cx.evaluateString(scope, script, "myScript.js", 1, null); } }; Utils.runWithOptimizationLevel(action, optimizationLevel); } } htmlunit-core-js-2.8/src/net/sourceforge/htmlunit/StackTraceTest.java0000644000175000017500000000317511223107350025702 0ustar cavedoncavedonpackage net.sourceforge.htmlunit; import org.junit.Assert; import org.junit.Test; import org.mozilla.javascript.Context; import org.mozilla.javascript.ContextAction; import org.mozilla.javascript.JavaScriptException; import org.mozilla.javascript.Scriptable; /** * In certain cases stacktrace if lost in case of exception * https://bugzilla.mozilla.org/show_bug.cgi?id=376717 * @author Marc Guillemot */ public class StackTraceTest { /** * As of CVS head on May, 11. 2009, stacktrace information is lost when a call to some * native function has been made. */ @Test public void testFailureStackTrace() { final String source1 = "function f2() { throw 'hello'; }; f2();"; final String source2 = "function f2() { 'H'.toLowerCase(); throw 'hello'; }; f2();"; runWithExpectedStackTrace(source1, " at test.js (f2)\n\tat test.js\n"); // works runWithExpectedStackTrace(source2, " at test.js (f2)\n\tat test.js\n"); // fails } private void runWithExpectedStackTrace(final String _source, final String _expectedStackTrace) { final ContextAction action = new ContextAction() { public Object run(final Context cx) { final Scriptable scope = cx.initStandardObjects(); try { cx.evaluateString(scope, _source, "test.js", 0, null); } catch (final JavaScriptException e) { Assert.assertEquals(_expectedStackTrace, e.getScriptStackTrace()); return null; } throw new RuntimeException("Exception expected!"); } }; Utils.runWithOptimizationLevel(action, -1); } } htmlunit-core-js-2.8/src/net/sourceforge/htmlunit/WriteReadOnlyPropertyTest.java0000644000175000017500000000472411261073713030163 0ustar cavedoncavedonpackage net.sourceforge.htmlunit; import java.lang.reflect.Method; import org.junit.Assert; import org.junit.Test; import org.mozilla.javascript.Context; import org.mozilla.javascript.ContextAction; import org.mozilla.javascript.ContextFactory; import org.mozilla.javascript.EcmaError; import org.mozilla.javascript.ScriptableObject; /** * Test that read-only properties can be... set when needed. * This was the standard behavior in Rhino until 1.7R2 but has changed then. * It is needed to simulate IE as well as FF2 (but not FF3). * @see Rhino bug 519933 * @author Marc Guillemot */ public class WriteReadOnlyPropertyTest { /** * @throws Exception if the test fails */ @Test public void testWriteReadOnly_accepted() throws Exception { testWriteReadOnly(true); } /** * @throws Exception if the test fails */ @Test public void testWriteReadOnly_throws() throws Exception { try { testWriteReadOnly(false); Assert.fail(); } catch (EcmaError e) { Assert.assertTrue(e.getMessage(), e.getMessage().contains("Cannot set property myProp that has only a getter")); } } void testWriteReadOnly(final boolean acceptWriteReadOnly) throws Exception { final Method readMethod = Foo.class.getMethod("getMyProp", null); final Foo foo = new Foo("hello"); foo.defineProperty("myProp", null, readMethod, null, ScriptableObject.EMPTY); final String script = "foo.myProp = 123; foo.myProp"; final ContextAction action = new ContextAction() { public Object run(final Context cx) { final ScriptableObject top = cx.initStandardObjects(); ScriptableObject.putProperty(top, "foo", foo); System.out.println(cx.evaluateString(top, script, "script", 0, null)); return null; } }; final ContextFactory contextFactory = new ContextFactory() { @Override protected boolean hasFeature(final Context cx, final int featureIndex) { if (Context.FEATURE_HTMLUNIT_WRITE_READONLY_PROPERTIES == featureIndex) { return acceptWriteReadOnly; } return super.hasFeature(cx, featureIndex); } }; contextFactory.call(action); } /** * Simple utility allowing to better see the concerned scope while debugging */ static class Foo extends ScriptableObject { final String prop_; Foo(final String label) { prop_ = label; } @Override public String getClassName() { return "Foo"; } public String getMyProp() { return prop_; } }; } htmlunit-core-js-2.8/src/net/sourceforge/htmlunit/ArgumentsTest.java0000644000175000017500000000112311321335670025621 0ustar cavedoncavedonpackage net.sourceforge.htmlunit; import org.junit.Test; /** * String conversion of Arguments array used to be '[object Object]', * with EcmaScript 5 it is now '[object Arguments]' what is not good for HtmlUnit. * @author Marc Guillemot */ public class ArgumentsTest { /** * @throws Exception if the test fails */ @Test public void argumentstoString() throws Exception { final String script = "function f() {\n" + "var s = arguments.toString();" + "if ('[object Object]' != s)\n" + " throw 'got: ' + s;" + "}\n" + "f()"; Utilities.executeScript(script); } } htmlunit-core-js-2.8/src/net/sourceforge/htmlunit/UpperCaseHexTest.java0000644000175000017500000000106111075604241026210 0ustar cavedoncavedonpackage net.sourceforge.htmlunit; import org.junit.Test; /** * Test that encodeURIComponent uses upper case letters for hex encoding. * https://bugzilla.mozilla.org/show_bug.cgi?id=429121 * (now fixed in Rhino itself) * @author Marc Guillemot */ public class UpperCaseHexTest { /** * @throws Exception if the test fails */ @Test public void testUpperCaseHex() throws Exception { final String script = "var a = encodeURIComponent('$ a ;');\n" + "if (a != '%24%20a%20%3B') throw 'got: >' + a + '<'"; Utilities.executeScript(script); } } htmlunit-core-js-2.8/src/net/sourceforge/htmlunit/FunctionCaller.java0000644000175000017500000000224111311524415025722 0ustar cavedoncavedonpackage net.sourceforge.htmlunit; import org.junit.Test; import org.mozilla.javascript.Context; import org.mozilla.javascript.ContextAction; import org.mozilla.javascript.Scriptable; /** * Test for a basic implementation of caller property on functions. * Implementation is not yet good enough to propose a patch to Rhino. * @author Marc Guillemot */ public class FunctionCaller { /** * JS catch block should always catch JS exceptions */ @Test public void callee() throws Exception { final String script = "function f() {\n" + " var c = arguments.callee.caller;\n" + " if (c) throw 'got: ' + c;\n" + " if (g.caller) throw 'got: ' + c;\n" + " g();\n" + " if (g.caller) throw 'after g() got: ' + g.caller;\n" + "}\n" + "function g() {\n" + " var c = arguments.callee.caller;\n" + " if (c != f) throw 'got: ' + c;\n" + "}\n" + "f();\n"; final ContextAction action = new ContextAction() { public Object run(final Context cx) { final Scriptable scope = cx.initStandardObjects(); cx.evaluateString(scope, script, "test.js", 1, null); return null; } }; Utils.runWithOptimizationLevel(action, -1); } } htmlunit-core-js-2.8/src/net/sourceforge/htmlunit/PropertiesOrderTest.java0000644000175000017500000000134511075604454027017 0ustar cavedoncavedonpackage net.sourceforge.htmlunit; import org.junit.Test; /** * Test that Object properties are returned in the creation order. * (now fixed in Rhino itself) * @author Marc Guillemot */ public class PropertiesOrderTest { /** * Test for properties order as exposed in issues * https://bugzilla.mozilla.org/show_bug.cgi?id=419090 * and * https://bugzilla.mozilla.org/show_bug.cgi?id=383592 * @throws Exception if the test fails */ @Test public void testPropertiesOrder() throws Exception { final String script = "var o = {a: 1, b: 1, c: 1, d: 1};\n" + "var str = '';\n" + "for (var i in o) str += i + ' ';\n" + "if (str != 'a b c d ')\n" + " throw 'Got: ' + str"; Utilities.executeScript(script); } } htmlunit-core-js-2.8/src/net/sourceforge/htmlunit/Utils.java0000644000175000017500000000307011261076053024117 0ustar cavedoncavedonpackage net.sourceforge.htmlunit; import org.mozilla.javascript.Context; import org.mozilla.javascript.ContextAction; import org.mozilla.javascript.ContextFactory; /** * Misc utilities to make test code easier. * @author Marc Guillemot */ public class Utils { /** * Runs the action successively with all available optimization levels */ public static void runWithAllOptimizationLevels(final ContextAction action) { runWithOptimizationLevel(action, -1); runWithOptimizationLevel(action, 0); runWithOptimizationLevel(action, 1); } /** * Runs the action successively with all available optimization levels */ public static void runWithAllOptimizationLevels(final ContextFactory contextFactory, final ContextAction action) { runWithOptimizationLevel(contextFactory, action, -1); runWithOptimizationLevel(contextFactory, action, 0); runWithOptimizationLevel(contextFactory, action, 1); } /** * Runs the provided action at the given optimization level */ public static void runWithOptimizationLevel(final ContextAction action, final int optimizationLevel) { runWithOptimizationLevel(new ContextFactory(), action, optimizationLevel); } /** * Runs the provided action at the given optimization level */ public static void runWithOptimizationLevel(final ContextFactory contextFactory, final ContextAction action, final int optimizationLevel) { final Context cx = contextFactory.enterContext(); try { cx.setOptimizationLevel(optimizationLevel); action.run(cx); } finally { Context.exit(); } } } htmlunit-core-js-2.8/src/net/sourceforge/htmlunit/RegExpUnescapedSlashTest.java0000644000175000017500000000074411075604454027706 0ustar cavedoncavedonpackage net.sourceforge.htmlunit; import org.junit.Test; /** * Test that regexp like "[/]" are parsed correctly. * https://bugzilla.mozilla.org/show_bug.cgi?id=368019 * (now fixed in Rhino itself) * @author Marc Guillemot */ public class RegExpUnescapedSlashTest { /** * @throws Exception if the test fails */ @Test public void testUnescapedSlashInSquareBrackets() throws Exception { final String script = "var o = /[/]/;"; Utilities.executeScript(script); } } htmlunit-core-js-2.8/LICENSE.txt0000644000175000017500000000064310776653510016247 0ustar cavedoncavedonhtmlunit-core-js.jar is a modified version of Mozilla Rhino (http://www.mozilla.org/rhino/) which was initially developed by Netscape Communications Corporation. The changes to the source code are provided in the file rhinoDiff.txt (and can be generated by calling cvs diff in the rhino folder). This software is provided by the HtmlUnit team "as is" under the MPL 1.1 license, available at http://www.mozilla.org/MPLhtmlunit-core-js-2.8/lib/0000755000175000017500000000000011530107756015162 5ustar cavedoncavedonhtmlunit-core-js-2.8/rhino/0000755000175000017500000000000011530107756015533 5ustar cavedoncavedonhtmlunit-core-js-2.8/rhino/build.properties0000644000175000017500000000422111222460357020744 0ustar cavedoncavedon# ***** BEGIN LICENSE BLOCK ***** # Version: MPL 1.1/GPL 2.0 # # The contents of this file are subject to the Mozilla Public License Version # 1.1 (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # http://www.mozilla.org/MPL/ # # Software distributed under the License is distributed on an "AS IS" basis, # WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License # for the specific language governing rights and limitations under the # License. # # The Original Code is Rhino code, released # May 6, 1999. # # The Initial Developer of the Original Code is # Netscape Communications Corporation. # Portions created by the Initial Developer are Copyright (C) 1997-1999 # the Initial Developer. All Rights Reserved. # # Contributor(s): # Igor Bukanov # # Alternatively, the contents of this file may be used under the terms of # the GNU General Public License Version 2 or later (the "GPL"), in which # case the provisions of the GPL are applicable instead of those above. If # you wish to allow use of your version of this file only under the terms of # the GPL and not to allow others to use your version of this file under the # MPL, indicate your decision by deleting the provisions above and replacing # them with the notice and other provisions required by the GPL. If you do # not delete the provisions above, a recipient may use your version of this # file under either the MPL or the GPL. # # ***** END LICENSE BLOCK ***** name: rhino Name: Rhino version: 1_7R3pre # See Context#getImplementationVersion() for format of this! implementation.version: Rhino 1.7 release 3 PRERELEASE ${implementation.date} build.dir: build rhino.jar: js.jar small-rhino.jar: smalljs.jar rhino-14.jar: js-14.jar small-rhino-14.jar: smalljs-14.jar dist.name: rhino${version} dist.dir: ${build.dir}/${dist.name} # compilation destionation classes: ${build.dir}/classes # compilation settings debug: on target-jvm: 1.5 source-level: 1.5 # jar generation settings jar-compression: true # optional external packages xmlbeans: . xbean.jar: ${xmlbeans}/lib/xbean.jar jsr173.jar: ${xmlbeans}/lib/jsr173_1.0_api.jar htmlunit-core-js-2.8/rhino/src/0000755000175000017500000000000011530107756016322 5ustar cavedoncavedonhtmlunit-core-js-2.8/rhino/src/build.xml0000644000175000017500000000665311222455466020157 0ustar cavedoncavedon htmlunit-core-js-2.8/rhino/src/manifest0000644000175000017500000000035411321335670020051 0ustar cavedoncavedonManifest-Version: 1.0 Main-Class: org.mozilla.javascript.tools.shell.Main Implementation-Version: 1.7R2 Implementation-Title: Mozilla Rhino 1.7R2 Implementation-Vendor: Mozilla Foundation Implementation-URL: http://www.mozilla.org/rhinohtmlunit-core-js-2.8/rhino/src/org/0000755000175000017500000000000011530107756017111 5ustar cavedoncavedonhtmlunit-core-js-2.8/rhino/src/org/mozilla/0000755000175000017500000000000011530107756020560 5ustar cavedoncavedonhtmlunit-core-js-2.8/rhino/src/org/mozilla/javascript/0000755000175000017500000000000011530107756022726 5ustar cavedoncavedonhtmlunit-core-js-2.8/rhino/src/org/mozilla/javascript/NativeIterator.java0000644000175000017500000002277211222455466026545 0ustar cavedoncavedon/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- * * ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * Contributor(s): * Norris Boyd * * Alternatively, the contents of this file may be used under the terms of * the GNU General Public License Version 2 or later (the "GPL"), in which * case the provisions of the GPL are applicable instead of those above. If * you wish to allow use of your version of this file only under the terms of * the GPL and not to allow others to use your version of this file under the * MPL, indicate your decision by deleting the provisions above and replacing * them with the notice and other provisions required by the GPL. If you do * not delete the provisions above, a recipient may use your version of this * file under either the MPL or the GPL. * * ***** END LICENSE BLOCK ***** */ package org.mozilla.javascript; import java.util.Iterator; /** * This class implements iterator objects. See * http://developer.mozilla.org/en/docs/New_in_JavaScript_1.7#Iterators * * @author Norris Boyd */ public final class NativeIterator extends IdScriptableObject { private static final long serialVersionUID = -4136968203581667681L; private static final Object ITERATOR_TAG = "Iterator"; static void init(ScriptableObject scope, boolean sealed) { // Iterator NativeIterator iterator = new NativeIterator(); iterator.exportAsJSClass(MAX_PROTOTYPE_ID, scope, sealed); // Generator NativeGenerator.init(scope, sealed); // StopIteration NativeObject obj = new StopIteration(); obj.setPrototype(getObjectPrototype(scope)); obj.setParentScope(scope); if (sealed) { obj.sealObject(); } ScriptableObject.defineProperty(scope, STOP_ITERATION, obj, ScriptableObject.DONTENUM); // Use "associateValue" so that generators can continue to // throw StopIteration even if the property of the global // scope is replaced or deleted. scope.associateValue(ITERATOR_TAG, obj); } /** * Only for constructing the prototype object. */ private NativeIterator() { } private NativeIterator(Object objectIterator) { this.objectIterator = objectIterator; } /** * Get the value of the "StopIteration" object. Note that this value * is stored in the top-level scope using "associateValue" so the * value can still be found even if a script overwrites or deletes * the global "StopIteration" property. * @param scope a scope whose parent chain reaches a top-level scope * @return the StopIteration object */ public static Object getStopIterationObject(Scriptable scope) { Scriptable top = ScriptableObject.getTopLevelScope(scope); return ScriptableObject.getTopScopeValue(top, ITERATOR_TAG); } private static final String STOP_ITERATION = "StopIteration"; public static final String ITERATOR_PROPERTY_NAME = "__iterator__"; static class StopIteration extends NativeObject { private static final long serialVersionUID = 2485151085722377663L; @Override public String getClassName() { return STOP_ITERATION; } /* StopIteration has custom instanceof behavior since it * doesn't have a constructor. */ @Override public boolean hasInstance(Scriptable instance) { return instance instanceof StopIteration; } } @Override public String getClassName() { return "Iterator"; } @Override protected void initPrototypeId(int id) { String s; int arity; switch (id) { case Id_constructor: arity=2; s="constructor"; break; case Id_next: arity=0; s="next"; break; case Id___iterator__: arity=1; s=ITERATOR_PROPERTY_NAME; break; default: throw new IllegalArgumentException(String.valueOf(id)); } initPrototypeMethod(ITERATOR_TAG, id, s, arity); } @Override public Object execIdCall(IdFunctionObject f, Context cx, Scriptable scope, Scriptable thisObj, Object[] args) { if (!f.hasTag(ITERATOR_TAG)) { return super.execIdCall(f, cx, scope, thisObj, args); } int id = f.methodId(); if (id == Id_constructor) { return jsConstructor(cx, scope, thisObj, args); } if (!(thisObj instanceof NativeIterator)) throw incompatibleCallError(f); NativeIterator iterator = (NativeIterator) thisObj; switch (id) { case Id_next: return iterator.next(cx, scope); case Id___iterator__: /// XXX: what about argument? SpiderMonkey apparently ignores it return thisObj; default: throw new IllegalArgumentException(String.valueOf(id)); } } /* The JavaScript constructor */ private static Object jsConstructor(Context cx, Scriptable scope, Scriptable thisObj, Object[] args) { if (args.length == 0 || args[0] == null || args[0] == Undefined.instance) { throw ScriptRuntime.typeError1("msg.no.properties", ScriptRuntime.toString(args[0])); } Scriptable obj = ScriptRuntime.toObject(scope, args[0]); boolean keyOnly = args.length > 1 && ScriptRuntime.toBoolean(args[1]); if (thisObj != null) { // Called as a function. Convert to iterator if possible. // For objects that implement java.lang.Iterable or // java.util.Iterator, have JavaScript Iterator call the underlying // iteration methods Iterator iterator = VMBridge.instance.getJavaIterator(cx, scope, obj); if (iterator != null) { scope = ScriptableObject.getTopLevelScope(scope); return cx.getWrapFactory().wrap(cx, scope, new WrappedJavaIterator(iterator, scope), WrappedJavaIterator.class); } // Otherwise, just call the runtime routine Scriptable jsIterator = ScriptRuntime.toIterator(cx, scope, obj, keyOnly); if (jsIterator != null) { return jsIterator; } } // Otherwise, just set up to iterate over the properties of the object. // Do not call __iterator__ method. Object objectIterator = ScriptRuntime.enumInit(obj, cx, keyOnly ? ScriptRuntime.ENUMERATE_KEYS_NO_ITERATOR : ScriptRuntime.ENUMERATE_ARRAY_NO_ITERATOR); ScriptRuntime.setEnumNumbers(objectIterator, true); NativeIterator result = new NativeIterator(objectIterator); result.setPrototype(ScriptableObject.getClassPrototype(scope, result.getClassName())); result.setParentScope(scope); return result; } private Object next(Context cx, Scriptable scope) { Boolean b = ScriptRuntime.enumNext(this.objectIterator); if (!b.booleanValue()) { // Out of values. Throw StopIteration. throw new JavaScriptException( NativeIterator.getStopIterationObject(scope), null, 0); } return ScriptRuntime.enumId(this.objectIterator, cx); } static public class WrappedJavaIterator { WrappedJavaIterator(Iterator iterator, Scriptable scope) { this.iterator = iterator; this.scope = scope; } public Object next() { if (!iterator.hasNext()) { // Out of values. Throw StopIteration. throw new JavaScriptException( NativeIterator.getStopIterationObject(scope), null, 0); } return iterator.next(); } public Object __iterator__(boolean b) { return this; } private Iterator iterator; private Scriptable scope; } // #string_id_map# @Override protected int findPrototypeId(String s) { int id; // #generated# Last update: 2007-06-11 09:43:19 EDT L0: { id = 0; String X = null; int s_length = s.length(); if (s_length==4) { X="next";id=Id_next; } else if (s_length==11) { X="constructor";id=Id_constructor; } else if (s_length==12) { X="__iterator__";id=Id___iterator__; } if (X!=null && X!=s && !X.equals(s)) id = 0; break L0; } // #/generated# return id; } private static final int Id_constructor = 1, Id_next = 2, Id___iterator__ = 3, MAX_PROTOTYPE_ID = 3; // #/string_id_map# private Object objectIterator; } htmlunit-core-js-2.8/rhino/src/org/mozilla/javascript/jdk13/0000755000175000017500000000000011530107756023642 5ustar cavedoncavedonhtmlunit-core-js-2.8/rhino/src/org/mozilla/javascript/jdk13/VMBridge_jdk13.java0000644000175000017500000001341011111044312027116 0ustar cavedoncavedon/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- * * ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is Rhino code, released * May 6, 1999. * * The Initial Developer of the Original Code is * Netscape Communications Corporation. * Portions created by the Initial Developer are Copyright (C) 1997-2000 * the Initial Developer. All Rights Reserved. * * Contributor(s): * * Alternatively, the contents of this file may be used under the terms of * the GNU General Public License Version 2 or later (the "GPL"), in which * case the provisions of the GPL are applicable instead of those above. If * you wish to allow use of your version of this file only under the terms of * the GPL and not to allow others to use your version of this file under the * MPL, indicate your decision by deleting the provisions above and replacing * them with the notice and other provisions required by the GPL. If you do * not delete the provisions above, a recipient may use your version of this * file under either the MPL or the GPL. * * ***** END LICENSE BLOCK ***** */ package org.mozilla.javascript.jdk13; import java.lang.reflect.AccessibleObject; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationHandler; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Member; import java.lang.reflect.Proxy; import org.mozilla.javascript.*; public class VMBridge_jdk13 extends VMBridge { private ThreadLocal contextLocal = new ThreadLocal(); @Override protected Object getThreadContextHelper() { // To make subsequent batch calls to getContext/setContext faster // associate permanently one element array with contextLocal // so getContext/setContext would need just to read/write the first // array element. // Note that it is necessary to use Object[], not Context[] to allow // garbage collection of Rhino classes. For details see comments // by Attila Szegedi in // https://bugzilla.mozilla.org/show_bug.cgi?id=281067#c5 Object[] storage = contextLocal.get(); if (storage == null) { storage = new Object[1]; contextLocal.set(storage); } return storage; } @Override protected Context getContext(Object contextHelper) { Object[] storage = (Object[])contextHelper; return (Context)storage[0]; } @Override protected void setContext(Object contextHelper, Context cx) { Object[] storage = (Object[])contextHelper; storage[0] = cx; } @Override protected ClassLoader getCurrentThreadClassLoader() { return Thread.currentThread().getContextClassLoader(); } @Override protected boolean tryToMakeAccessible(Object accessibleObject) { if (!(accessibleObject instanceof AccessibleObject)) { return false; } AccessibleObject accessible = (AccessibleObject)accessibleObject; if (accessible.isAccessible()) { return true; } try { accessible.setAccessible(true); } catch (Exception ex) { } return accessible.isAccessible(); } @Override protected Object getInterfaceProxyHelper(ContextFactory cf, Class[] interfaces) { // XXX: How to handle interfaces array withclasses from different // class loaders? Using cf.getApplicationClassLoader() ? ClassLoader loader = interfaces[0].getClassLoader(); Class cl = Proxy.getProxyClass(loader, interfaces); Constructor c; try { c = cl.getConstructor(new Class[] { InvocationHandler.class }); } catch (NoSuchMethodException ex) { // Should not happen throw Kit.initCause(new IllegalStateException(), ex); } return c; } @Override protected Object newInterfaceProxy(Object proxyHelper, final ContextFactory cf, final InterfaceAdapter adapter, final Object target, final Scriptable topScope) { Constructor c = (Constructor)proxyHelper; InvocationHandler handler = new InvocationHandler() { public Object invoke(Object proxy, Method method, Object[] args) { return adapter.invoke(cf, target, topScope, method, args); } }; Object proxy; try { proxy = c.newInstance(new Object[] { handler }); } catch (InvocationTargetException ex) { throw Context.throwAsScriptRuntimeEx(ex); } catch (IllegalAccessException ex) { // Shouls not happen throw Kit.initCause(new IllegalStateException(), ex); } catch (InstantiationException ex) { // Shouls not happen throw Kit.initCause(new IllegalStateException(), ex); } return proxy; } @Override protected boolean isVarArgs(Member member) { return false; } } htmlunit-core-js-2.8/rhino/src/org/mozilla/javascript/ConstProperties.java0000644000175000017500000001152610776622373026751 0ustar cavedoncavedon/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- * * ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is Rhino code, released * May 6, 1999. * * The Initial Developer of the Original Code is * Netscape Communications Corporation. * Portions created by the Initial Developer are Copyright (C) 1997-1999 * the Initial Developer. All Rights Reserved. * * Contributor(s): * Bob Jervis * * Alternatively, the contents of this file may be used under the terms of * the GNU General Public License Version 2 or later (the "GPL"), in which * case the provisions of the GPL are applicable instead of those above. If * you wish to allow use of your version of this file only under the terms of * the GPL and not to allow others to use your version of this file under the * MPL, indicate your decision by deleting the provisions above and replacing * them with the notice and other provisions required by the GPL. If you do * not delete the provisions above, a recipient may use your version of this * file under either the MPL or the GPL. * * ***** END LICENSE BLOCK ***** */ // API class package org.mozilla.javascript; public interface ConstProperties { /** * Sets a named const property in this object. *

* The property is specified by a string name * as defined for Scriptable.get. *

* The possible values that may be passed in are as defined for * Scriptable.get. A class that implements this method may choose * to ignore calls to set certain properties, in which case those * properties are effectively read-only.

* For properties defined in a prototype chain, * use putProperty in ScriptableObject.

* Note that if a property a is defined in the prototype p * of an object o, then evaluating o.a = 23 will cause * set to be called on the prototype p with * o as the start parameter. * To preserve JavaScript semantics, it is the Scriptable * object's responsibility to modify o.

* 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.

*

* The values that may be set are limited to the following: *

* Arbitrary Java objects may be wrapped in a Scriptable by first calling * Context.toObject. This allows the property of a JavaScript * object to contain an arbitrary Java object as a value.

* Note that has will be called by the runtime first before * set 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); } htmlunit-core-js-2.8/rhino/src/org/mozilla/javascript/IdFunctionObject.java0000644000175000017500000001362010776622373026774 0ustar cavedoncavedon/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- * * ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is Rhino code, released * May 6, 1999. * * The Initial Developer of the Original Code is * Netscape Communications Corporation. * Portions created by the Initial Developer are Copyright (C) 1997-1999 * the Initial Developer. All Rights Reserved. * * Contributor(s): * Igor Bukanov * * Alternatively, the contents of this file may be used under the terms of * the GNU General Public License Version 2 or later (the "GPL"), in which * case the provisions of the GPL are applicable instead of those above. If * you wish to allow use of your version of this file only under the terms of * the GPL and not to allow others to use your version of this file under the * MPL, indicate your decision by deleting the provisions above and replacing * them with the notice and other provisions required by the GPL. If you do * not delete the provisions above, a recipient may use your version of this * file under either the MPL or the GPL. * * ***** END LICENSE BLOCK ***** */ // 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 this.tag == 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) { StringBuffer sb = new StringBuffer(); 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; } htmlunit-core-js-2.8/rhino/src/org/mozilla/javascript/NativeJavaConstructor.java0000644000175000017500000000552410776622373030105 0ustar cavedoncavedon/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- * * ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is Rhino code, released * May 6, 1999. * * The Initial Developer of the Original Code is * Netscape Communications Corporation. * Portions created by the Initial Developer are Copyright (C) 1997-1999 * the Initial Developer. All Rights Reserved. * * Contributor(s): * Norris Boyd * Frank Mitchell * Mike Shaver * * Alternatively, the contents of this file may be used under the terms of * the GNU General Public License Version 2 or later (the "GPL"), in which * case the provisions of the GPL are applicable instead of those above. If * you wish to allow use of your version of this file only under the terms of * the GPL and not to allow others to use your version of this file under the * MPL, indicate your decision by deleting the provisions above and replacing * them with the notice and other provisions required by the GPL. If you do * not delete the provisions above, a recipient may use your version of this * file under either the MPL or the GPL. * * ***** END LICENSE BLOCK ***** */ package org.mozilla.javascript; /** * This class reflects a single Java constructor into the JavaScript * environment. It satisfies a request for an overloaded constructor, * as introduced in LiveConnect 3. * All NativeJavaConstructors behave as JSRef `bound' methods, in that they * always construct the same NativeJavaClass regardless of any reparenting * that may occur. * * @author Frank Mitchell * @see NativeJavaMethod * @see NativeJavaPackage * @see NativeJavaClass */ public class NativeJavaConstructor extends BaseFunction { static final long serialVersionUID = -8149253217482668463L; MemberBox ctor; public NativeJavaConstructor(MemberBox ctor) { this.ctor = ctor; } @Override public Object call(Context cx, Scriptable scope, Scriptable thisObj, Object[] args) { return NativeJavaClass.constructSpecific(cx, scope, args, ctor); } @Override public String getFunctionName() { String sig = JavaMembers.liveConnectSignature(ctor.argTypes); return "".concat(sig); } @Override public String toString() { return "[JavaConstructor " + ctor.getName() + "]"; } } htmlunit-core-js-2.8/rhino/src/org/mozilla/javascript/TokenStream.java0000644000175000017500000015704111321335670026031 0ustar cavedoncavedon/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- * * ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is Rhino code, released * May 6, 1999. * * The Initial Developer of the Original Code is * Netscape Communications Corporation. * Portions created by the Initial Developer are Copyright (C) 1997-1999 * the Initial Developer. All Rights Reserved. * * Contributor(s): * Roger Lawrence * Mike McCabe * Igor Bukanov * Ethan Hugg * Bob Jervis * Terry Lucas * Milen Nankov * Steve Yegge * * Alternatively, the contents of this file may be used under the terms of * the GNU General Public License Version 2 or later (the "GPL"), in which * case the provisions of the GPL are applicable instead of those above. If * you wish to allow use of your version of this file only under the terms of * the GPL and not to allow others to use your version of this file under the * MPL, indicate your decision by deleting the provisions above and replacing * them with the notice and other provisions required by the GPL. If you do * not delete the provisions above, a recipient may use your version of this * file under either the MPL or the GPL. * * ***** END LICENSE BLOCK ***** */ package org.mozilla.javascript; import java.io.*; /** * This class implements the JavaScript scanner. * * It is based on the C source files jsscan.c and jsscan.h * in the jsref package. * * @see org.mozilla.javascript.Parser * * @author Mike McCabe * @author Brendan Eich */ class TokenStream { /* * For chars - because we need something out-of-range * to check. (And checking EOF by exception is annoying.) * Note distinction from EOF token type! */ private final static int EOF_CHAR = -1; private final static char BYTE_ORDER_MARK = '\uFEFF'; TokenStream(Parser parser, Reader sourceReader, String sourceString, int lineno) { this.parser = parser; this.lineno = lineno; if (sourceReader != null) { if (sourceString != null) Kit.codeBug(); this.sourceReader = sourceReader; this.sourceBuffer = new char[512]; this.sourceEnd = 0; } else { if (sourceString == null) Kit.codeBug(); this.sourceString = sourceString; this.sourceEnd = sourceString.length(); } this.sourceCursor = this.cursor = 0; } /* This function uses the cached op, string and number fields in * TokenStream; if getToken has been called since the passed token * was scanned, the op or string printed may be incorrect. */ String tokenToString(int token) { if (Token.printTrees) { String name = Token.name(token); switch (token) { case Token.STRING: case Token.REGEXP: case Token.NAME: return name + " `" + this.string + "'"; case Token.NUMBER: return "NUMBER " + this.number; } return name; } return ""; } static boolean isKeyword(String s) { return Token.EOF != stringToKeyword(s); } private static int stringToKeyword(String name) { // #string_id_map# // The following assumes that Token.EOF == 0 final int Id_break = Token.BREAK, Id_case = Token.CASE, Id_continue = Token.CONTINUE, Id_default = Token.DEFAULT, Id_delete = Token.DELPROP, Id_do = Token.DO, Id_else = Token.ELSE, Id_export = Token.RESERVED, Id_false = Token.FALSE, Id_for = Token.FOR, Id_function = Token.FUNCTION, Id_if = Token.IF, Id_in = Token.IN, Id_let = Token.LET, Id_new = Token.NEW, Id_null = Token.NULL, Id_return = Token.RETURN, Id_switch = Token.SWITCH, Id_this = Token.THIS, Id_true = Token.TRUE, Id_typeof = Token.TYPEOF, Id_var = Token.VAR, Id_void = Token.VOID, Id_while = Token.WHILE, Id_with = Token.WITH, Id_yield = Token.YIELD, // the following are #ifdef RESERVE_JAVA_KEYWORDS in jsscan.c Id_abstract = Token.RESERVED, Id_boolean = Token.RESERVED, Id_byte = Token.RESERVED, Id_catch = Token.CATCH, Id_char = Token.RESERVED, Id_class = Token.RESERVED, Id_const = Token.CONST, Id_debugger = Token.DEBUGGER, Id_double = Token.RESERVED, Id_enum = Token.RESERVED, Id_extends = Token.RESERVED, Id_final = Token.RESERVED, Id_finally = Token.FINALLY, Id_float = Token.RESERVED, Id_goto = Token.RESERVED, Id_implements = Token.RESERVED, Id_import = Token.RESERVED, Id_instanceof = Token.INSTANCEOF, Id_int = Token.RESERVED, Id_interface = Token.RESERVED, Id_long = Token.RESERVED, Id_native = Token.RESERVED, Id_package = Token.RESERVED, Id_private = Token.RESERVED, Id_protected = Token.RESERVED, Id_public = Token.RESERVED, Id_short = Token.RESERVED, Id_static = Token.RESERVED, Id_super = Token.RESERVED, Id_synchronized = Token.RESERVED, Id_throw = Token.THROW, Id_throws = Token.RESERVED, Id_transient = Token.RESERVED, Id_try = Token.TRY, Id_volatile = Token.RESERVED; int id; String s = name; // #generated# Last update: 2007-04-18 13:53:30 PDT L0: { id = 0; String X = null; int c; L: switch (s.length()) { case 2: c=s.charAt(1); if (c=='f') { if (s.charAt(0)=='i') {id=Id_if; break L0;} } else if (c=='n') { if (s.charAt(0)=='i') {id=Id_in; break L0;} } else if (c=='o') { if (s.charAt(0)=='d') {id=Id_do; break L0;} } break L; case 3: switch (s.charAt(0)) { case 'f': if (s.charAt(2)=='r' && s.charAt(1)=='o') {id=Id_for; break L0;} break L; case 'i': if (s.charAt(2)=='t' && s.charAt(1)=='n') {id=Id_int; break L0;} break L; case 'l': if (s.charAt(2)=='t' && s.charAt(1)=='e') {id=Id_let; break L0;} break L; case 'n': if (s.charAt(2)=='w' && s.charAt(1)=='e') {id=Id_new; break L0;} break L; case 't': if (s.charAt(2)=='y' && s.charAt(1)=='r') {id=Id_try; break L0;} break L; case 'v': if (s.charAt(2)=='r' && s.charAt(1)=='a') {id=Id_var; break L0;} break L; } break L; case 4: switch (s.charAt(0)) { case 'b': X="byte";id=Id_byte; break L; case 'c': c=s.charAt(3); if (c=='e') { if (s.charAt(2)=='s' && s.charAt(1)=='a') {id=Id_case; break L0;} } else if (c=='r') { if (s.charAt(2)=='a' && s.charAt(1)=='h') {id=Id_char; break L0;} } break L; case 'e': c=s.charAt(3); if (c=='e') { if (s.charAt(2)=='s' && s.charAt(1)=='l') {id=Id_else; break L0;} } else if (c=='m') { if (s.charAt(2)=='u' && s.charAt(1)=='n') {id=Id_enum; break L0;} } break L; case 'g': X="goto";id=Id_goto; break L; case 'l': X="long";id=Id_long; break L; case 'n': X="null";id=Id_null; break L; case 't': c=s.charAt(3); if (c=='e') { if (s.charAt(2)=='u' && s.charAt(1)=='r') {id=Id_true; break L0;} } else if (c=='s') { if (s.charAt(2)=='i' && s.charAt(1)=='h') {id=Id_this; break L0;} } break L; case 'v': X="void";id=Id_void; break L; case 'w': X="with";id=Id_with; break L; } break L; case 5: switch (s.charAt(2)) { case 'a': X="class";id=Id_class; break L; case 'e': c=s.charAt(0); if (c=='b') { X="break";id=Id_break; } else if (c=='y') { X="yield";id=Id_yield; } break L; case 'i': X="while";id=Id_while; break L; case 'l': X="false";id=Id_false; break L; case 'n': c=s.charAt(0); if (c=='c') { X="const";id=Id_const; } else if (c=='f') { X="final";id=Id_final; } break L; case 'o': c=s.charAt(0); if (c=='f') { X="float";id=Id_float; } else if (c=='s') { X="short";id=Id_short; } break L; case 'p': X="super";id=Id_super; break L; case 'r': X="throw";id=Id_throw; break L; case 't': X="catch";id=Id_catch; break L; } break L; case 6: switch (s.charAt(1)) { case 'a': X="native";id=Id_native; break L; case 'e': c=s.charAt(0); if (c=='d') { X="delete";id=Id_delete; } else if (c=='r') { X="return";id=Id_return; } break L; case 'h': X="throws";id=Id_throws; break L; case 'm': X="import";id=Id_import; break L; case 'o': X="double";id=Id_double; break L; case 't': X="static";id=Id_static; break L; case 'u': X="public";id=Id_public; break L; case 'w': X="switch";id=Id_switch; break L; case 'x': X="export";id=Id_export; break L; case 'y': X="typeof";id=Id_typeof; break L; } break L; case 7: switch (s.charAt(1)) { case 'a': X="package";id=Id_package; break L; case 'e': X="default";id=Id_default; break L; case 'i': X="finally";id=Id_finally; break L; case 'o': X="boolean";id=Id_boolean; break L; case 'r': X="private";id=Id_private; break L; case 'x': X="extends";id=Id_extends; break L; } break L; case 8: switch (s.charAt(0)) { case 'a': X="abstract";id=Id_abstract; break L; case 'c': X="continue";id=Id_continue; break L; case 'd': X="debugger";id=Id_debugger; break L; case 'f': X="function";id=Id_function; break L; case 'v': X="volatile";id=Id_volatile; break L; } break L; case 9: c=s.charAt(0); if (c=='i') { X="interface";id=Id_interface; } else if (c=='p') { X="protected";id=Id_protected; } else if (c=='t') { X="transient";id=Id_transient; } break L; case 10: c=s.charAt(1); if (c=='m') { X="implements";id=Id_implements; } else if (c=='n') { X="instanceof";id=Id_instanceof; } break L; case 12: X="synchronized";id=Id_synchronized; break L; } if (X!=null && X!=s && !X.equals(s)) id = 0; } // #/generated# // #/string_id_map# if (id == 0) { return Token.EOF; } return id & 0xff; } final String getSourceString() { return sourceString; } final int getLineno() { return lineno; } final String getString() { return string; } final char getQuoteChar() { return (char) quoteChar; } final double getNumber() { return number; } final boolean isNumberOctal() { return isOctal; } final boolean eof() { return hitEOF; } final int getToken() throws IOException { int c; retry: for (;;) { // Eat whitespace, possibly sensitive to newlines. for (;;) { c = getChar(); if (c == EOF_CHAR) { tokenBeg = cursor - 1; tokenEnd = cursor; return Token.EOF; } else if (c == '\n') { dirtyLine = false; tokenBeg = cursor - 1; tokenEnd = cursor; return Token.EOL; } else if (!isJSSpace(c)) { if (c != '-') { dirtyLine = true; } break; } } // Assume the token will be 1 char - fixed up below. tokenBeg = cursor - 1; tokenEnd = cursor; if (c == '@') return Token.XMLATTR; // identifier/keyword/instanceof? // watch out for starting with a boolean identifierStart; boolean isUnicodeEscapeStart = false; if (c == '\\') { c = getChar(); if (c == 'u') { identifierStart = true; isUnicodeEscapeStart = true; stringBufferTop = 0; } else { identifierStart = false; ungetChar(c); c = '\\'; } } else { identifierStart = Character.isJavaIdentifierStart((char)c); if (identifierStart) { stringBufferTop = 0; addToString(c); } } if (identifierStart) { boolean containsEscape = isUnicodeEscapeStart; for (;;) { if (isUnicodeEscapeStart) { // strictly speaking we should probably push-back // all the bad characters if the uXXXX // sequence is malformed. But since there isn't a // correct context(is there?) for a bad Unicode // escape sequence in an identifier, we can report // an error here. int escapeVal = 0; for (int i = 0; i != 4; ++i) { c = getChar(); escapeVal = Kit.xDigitToInt(c, escapeVal); // Next check takes care about c < 0 and bad escape if (escapeVal < 0) { break; } } if (escapeVal < 0) { parser.addError("msg.invalid.escape"); return Token.ERROR; } addToString(escapeVal); isUnicodeEscapeStart = false; } else { c = getChar(); if (c == '\\') { c = getChar(); if (c == 'u') { isUnicodeEscapeStart = true; containsEscape = true; } else { parser.addError("msg.illegal.character"); return Token.ERROR; } } else { if (c == EOF_CHAR || c == BYTE_ORDER_MARK || !Character.isJavaIdentifierPart((char)c)) { break; } addToString(c); } } } ungetChar(c); String str = getStringFromBuffer(); if (!containsEscape) { // OPT we shouldn't have to make a string (object!) to // check if it's a keyword. // Return the corresponding token if it's a keyword int result = stringToKeyword(str); if (result != Token.EOF) { if ((result == Token.LET || result == Token.YIELD) && parser.compilerEnv.getLanguageVersion() < Context.VERSION_1_7) { // LET and YIELD are tokens only in 1.7 and later string = result == Token.LET ? "let" : "yield"; result = Token.NAME; } if (result != Token.RESERVED) { return result; } else if (!parser.compilerEnv. isReservedKeywordAsIdentifier()) { return result; } } } this.string = (String)allStrings.intern(str); return Token.NAME; } // is it a number? if (isDigit(c) || (c == '.' && isDigit(peekChar()))) { isOctal = false; stringBufferTop = 0; int base = 10; if (c == '0') { c = getChar(); if (c == 'x' || c == 'X') { base = 16; c = getChar(); } else if (isDigit(c)) { base = 8; isOctal = true; } else { addToString('0'); } } if (base == 16) { while (0 <= Kit.xDigitToInt(c, 0)) { addToString(c); c = getChar(); } } else { while ('0' <= c && c <= '9') { /* * We permit 08 and 09 as decimal numbers, which * makes our behavior a superset of the ECMA * numeric grammar. We might not always be so * permissive, so we warn about it. */ if (base == 8 && c >= '8') { parser.addWarning("msg.bad.octal.literal", c == '8' ? "8" : "9"); base = 10; } addToString(c); c = getChar(); } } boolean isInteger = true; if (base == 10 && (c == '.' || c == 'e' || c == 'E')) { isInteger = false; if (c == '.') { do { addToString(c); c = getChar(); } while (isDigit(c)); } if (c == 'e' || c == 'E') { addToString(c); c = getChar(); if (c == '+' || c == '-') { addToString(c); c = getChar(); } if (!isDigit(c)) { parser.addError("msg.missing.exponent"); return Token.ERROR; } do { addToString(c); c = getChar(); } while (isDigit(c)); } } ungetChar(c); String numString = getStringFromBuffer(); this.string = numString; double dval; if (base == 10 && !isInteger) { try { // Use Java conversion to number from string... dval = Double.valueOf(numString).doubleValue(); } catch (NumberFormatException ex) { parser.addError("msg.caught.nfe"); return Token.ERROR; } } else { dval = ScriptRuntime.stringToNumber(numString, 0, base); } this.number = dval; return Token.NUMBER; } // is it a string? if (c == '"' || c == '\'') { // We attempt to accumulate a string the fast way, by // building it directly out of the reader. But if there // are any escaped characters in the string, we revert to // building it out of a StringBuffer. quoteChar = c; stringBufferTop = 0; c = getChar(); strLoop: while (c != quoteChar) { if (c == '\n' || c == EOF_CHAR) { ungetChar(c); tokenEnd = cursor; parser.addError("msg.unterminated.string.lit"); return Token.ERROR; } if (c == '\\') { // We've hit an escaped character int escapeVal; c = getChar(); switch (c) { case 'b': c = '\b'; break; case 'f': c = '\f'; break; case 'n': c = '\n'; break; case 'r': c = '\r'; break; case 't': c = '\t'; break; // \v a late addition to the ECMA spec, // it is not in Java, so use 0xb case 'v': c = 0xb; break; case 'u': // Get 4 hex digits; if the u escape is not // followed by 4 hex digits, use 'u' + the // literal character sequence that follows. int escapeStart = stringBufferTop; addToString('u'); escapeVal = 0; for (int i = 0; i != 4; ++i) { c = getChar(); escapeVal = Kit.xDigitToInt(c, escapeVal); if (escapeVal < 0) { continue strLoop; } addToString(c); } // prepare for replace of stored 'u' sequence // by escape value stringBufferTop = escapeStart; c = escapeVal; break; case 'x': // Get 2 hex digits, defaulting to 'x'+literal // sequence, as above. c = getChar(); escapeVal = Kit.xDigitToInt(c, 0); if (escapeVal < 0) { addToString('x'); continue strLoop; } else { int c1 = c; c = getChar(); escapeVal = Kit.xDigitToInt(c, escapeVal); if (escapeVal < 0) { addToString('x'); addToString(c1); continue strLoop; } else { // got 2 hex digits c = escapeVal; } } break; case '\n': // Remove line terminator after escape to follow // SpiderMonkey and C/C++ c = getChar(); continue strLoop; default: if ('0' <= c && c < '8') { int val = c - '0'; c = getChar(); if ('0' <= c && c < '8') { val = 8 * val + c - '0'; c = getChar(); if ('0' <= c && c < '8' && val <= 037) { // c is 3rd char of octal sequence only // if the resulting val <= 0377 val = 8 * val + c - '0'; c = getChar(); } } ungetChar(c); c = val; } } } addToString(c); c = getChar(); } String str = getStringFromBuffer(); this.string = (String)allStrings.intern(str); return Token.STRING; } switch (c) { case ';': return Token.SEMI; case '[': return Token.LB; case ']': return Token.RB; case '{': return Token.LC; case '}': return Token.RC; case '(': return Token.LP; case ')': return Token.RP; case ',': return Token.COMMA; case '?': return Token.HOOK; case ':': if (matchChar(':')) { return Token.COLONCOLON; } else { return Token.COLON; } case '.': if (matchChar('.')) { return Token.DOTDOT; } else if (matchChar('(')) { return Token.DOTQUERY; } else { return Token.DOT; } case '|': if (matchChar('|')) { return Token.OR; } else if (matchChar('=')) { return Token.ASSIGN_BITOR; } else { return Token.BITOR; } case '^': if (matchChar('=')) { return Token.ASSIGN_BITXOR; } else { return Token.BITXOR; } case '&': if (matchChar('&')) { return Token.AND; } else if (matchChar('=')) { return Token.ASSIGN_BITAND; } else { return Token.BITAND; } case '=': if (matchChar('=')) { if (matchChar('=')) { return Token.SHEQ; } else { return Token.EQ; } } else { return Token.ASSIGN; } case '!': if (matchChar('=')) { if (matchChar('=')) { return Token.SHNE; } else { return Token.NE; } } else { return Token.NOT; } case '<': /* NB:treat HTML begin-comment as comment-till-eol */ if (matchChar('!')) { if (matchChar('-')) { if (matchChar('-')) { skipLine(); continue retry; } ungetCharIgnoreLineEnd('-'); } ungetCharIgnoreLineEnd('!'); } if (matchChar('<')) { if (matchChar('=')) { return Token.ASSIGN_LSH; } else { return Token.LSH; } } else { if (matchChar('=')) { return Token.LE; } else { return Token.LT; } } case '>': if (matchChar('>')) { if (matchChar('>')) { if (matchChar('=')) { return Token.ASSIGN_URSH; } else { return Token.URSH; } } else { if (matchChar('=')) { return Token.ASSIGN_RSH; } else { return Token.RSH; } } } else { if (matchChar('=')) { return Token.GE; } else { return Token.GT; } } case '*': if (matchChar('=')) { return Token.ASSIGN_MUL; } else { return Token.MUL; } case '/': markCommentStart(); // is it a // comment? if (matchChar('/')) { tokenBeg = cursor - 2; skipLine(); commentType = Token.CommentType.LINE; return Token.COMMENT; } // is it a /* or /** comment? if (matchChar('*')) { boolean lookForSlash = false; tokenBeg = cursor - 2; if (matchChar('*')) { lookForSlash = true; commentType = Token.CommentType.JSDOC; } else { commentType = Token.CommentType.BLOCK_COMMENT; } for (;;) { c = getChar(); if (c == EOF_CHAR) { tokenEnd = cursor - 1; parser.addError("msg.unterminated.comment"); return Token.COMMENT; } else if (c == '*') { lookForSlash = true; } else if (c == '/') { if (lookForSlash) { tokenEnd = cursor; return Token.COMMENT; } } else { lookForSlash = false; tokenEnd = cursor; } } } if (matchChar('=')) { return Token.ASSIGN_DIV; } else { return Token.DIV; } case '%': if (matchChar('=')) { return Token.ASSIGN_MOD; } else { return Token.MOD; } case '~': return Token.BITNOT; case '+': if (matchChar('=')) { return Token.ASSIGN_ADD; } else if (matchChar('+')) { return Token.INC; } else { return Token.ADD; } case '-': if (matchChar('=')) { c = Token.ASSIGN_SUB; } else if (matchChar('-')) { if (!dirtyLine) { // treat HTML end-comment after possible whitespace // after line start as comment-until-eol if (matchChar('>')) { markCommentStart("--"); skipLine(); commentType = Token.CommentType.HTML; return Token.COMMENT; } } c = Token.DEC; } else { c = Token.SUB; } dirtyLine = true; return c; default: parser.addError("msg.illegal.character"); return Token.ERROR; } } } private static boolean isAlpha(int c) { // Use 'Z' < 'a' if (c <= 'Z') { return 'A' <= c; } else { return 'a' <= c && c <= 'z'; } } static boolean isDigit(int c) { return '0' <= c && c <= '9'; } /* As defined in ECMA. jsscan.c uses C isspace() (which allows * \v, I think.) note that code in getChar() implicitly accepts * '\r' == \u000D as well. */ static boolean isJSSpace(int c) { if (c <= 127) { return c == 0x20 || c == 0x9 || c == 0xC || c == 0xB; } else { return c == 0xA0 || c == BYTE_ORDER_MARK || Character.getType((char)c) == Character.SPACE_SEPARATOR; } } private static boolean isJSFormatChar(int c) { return c > 127 && Character.getType((char)c) == Character.FORMAT; } /** * Parser calls the method when it gets / or /= in literal context. */ void readRegExp(int startToken) throws IOException { int start = tokenBeg; stringBufferTop = 0; if (startToken == Token.ASSIGN_DIV) { // Miss-scanned /= addToString('='); } else { if (startToken != Token.DIV) Kit.codeBug(); } boolean inCharSet = false; // true if inside a '['..']' pair int c; while ((c = getChar()) != '/' || inCharSet) { if (c == '\n' || c == EOF_CHAR) { ungetChar(c); tokenEnd = cursor - 1; this.string = new String(stringBuffer, 0, stringBufferTop); parser.reportError("msg.unterminated.re.lit"); return; } if (c == '\\') { addToString(c); c = getChar(); } else if (c == '[') { inCharSet = true; } else if (c == ']') { inCharSet = false; } addToString(c); } int reEnd = stringBufferTop; while (true) { if (matchChar('g')) addToString('g'); else if (matchChar('i')) addToString('i'); else if (matchChar('m')) addToString('m'); else if (matchChar('y')) // FireFox 3 addToString('y'); else break; } tokenEnd = start + stringBufferTop + 2; // include slashes if (isAlpha(peekChar())) { parser.reportError("msg.invalid.re.flag"); } this.string = new String(stringBuffer, 0, reEnd); this.regExpFlags = new String(stringBuffer, reEnd, stringBufferTop - reEnd); } String readAndClearRegExpFlags() { String flags = this.regExpFlags; this.regExpFlags = null; return flags; } boolean isXMLAttribute() { return xmlIsAttribute; } int getFirstXMLToken() throws IOException { xmlOpenTagsCount = 0; xmlIsAttribute = false; xmlIsTagContent = false; if (!canUngetChar()) return Token.ERROR; ungetChar('<'); return getNextXMLToken(); } int getNextXMLToken() throws IOException { tokenBeg = cursor; stringBufferTop = 0; // remember the XML for (int c = getChar(); c != EOF_CHAR; c = getChar()) { if (xmlIsTagContent) { switch (c) { case '>': addToString(c); xmlIsTagContent = false; xmlIsAttribute = false; break; case '/': addToString(c); if (peekChar() == '>') { c = getChar(); addToString(c); xmlIsTagContent = false; xmlOpenTagsCount--; } break; case '{': ungetChar(c); this.string = getStringFromBuffer(); return Token.XML; case '\'': case '"': addToString(c); if (!readQuotedString(c)) return Token.ERROR; break; case '=': addToString(c); xmlIsAttribute = true; break; case ' ': case '\t': case '\r': case '\n': addToString(c); break; default: addToString(c); xmlIsAttribute = false; break; } if (!xmlIsTagContent && xmlOpenTagsCount == 0) { this.string = getStringFromBuffer(); return Token.XMLEND; } } else { switch (c) { case '<': addToString(c); c = peekChar(); switch (c) { case '!': c = getChar(); // Skip ! addToString(c); c = peekChar(); switch (c) { case '-': c = getChar(); // Skip - addToString(c); c = getChar(); if (c == '-') { addToString(c); if(!readXmlComment()) return Token.ERROR; } else { // throw away the string in progress stringBufferTop = 0; this.string = null; parser.addError("msg.XML.bad.form"); return Token.ERROR; } break; case '[': c = getChar(); // Skip [ addToString(c); if (getChar() == 'C' && getChar() == 'D' && getChar() == 'A' && getChar() == 'T' && getChar() == 'A' && getChar() == '[') { addToString('C'); addToString('D'); addToString('A'); addToString('T'); addToString('A'); addToString('['); if (!readCDATA()) return Token.ERROR; } else { // throw away the string in progress stringBufferTop = 0; this.string = null; parser.addError("msg.XML.bad.form"); return Token.ERROR; } break; default: if(!readEntity()) return Token.ERROR; break; } break; case '?': c = getChar(); // Skip ? addToString(c); if (!readPI()) return Token.ERROR; break; case '/': // End tag c = getChar(); // Skip / addToString(c); if (xmlOpenTagsCount == 0) { // throw away the string in progress stringBufferTop = 0; this.string = null; parser.addError("msg.XML.bad.form"); return Token.ERROR; } xmlIsTagContent = true; xmlOpenTagsCount--; break; default: // Start tag xmlIsTagContent = true; xmlOpenTagsCount++; break; } break; case '{': ungetChar(c); this.string = getStringFromBuffer(); return Token.XML; default: addToString(c); break; } } } tokenEnd = cursor; stringBufferTop = 0; // throw away the string in progress this.string = null; parser.addError("msg.XML.bad.form"); return Token.ERROR; } /** * */ private boolean readQuotedString(int quote) throws IOException { for (int c = getChar(); c != EOF_CHAR; c = getChar()) { addToString(c); if (c == quote) return true; } stringBufferTop = 0; // throw away the string in progress this.string = null; parser.addError("msg.XML.bad.form"); return false; } /** * */ private boolean readXmlComment() throws IOException { for (int c = getChar(); c != EOF_CHAR;) { addToString(c); if (c == '-' && peekChar() == '-') { c = getChar(); addToString(c); if (peekChar() == '>') { c = getChar(); // Skip > addToString(c); return true; } else { continue; } } c = getChar(); } stringBufferTop = 0; // throw away the string in progress this.string = null; parser.addError("msg.XML.bad.form"); return false; } /** * */ private boolean readCDATA() throws IOException { for (int c = getChar(); c != EOF_CHAR;) { addToString(c); if (c == ']' && peekChar() == ']') { c = getChar(); addToString(c); if (peekChar() == '>') { c = getChar(); // Skip > addToString(c); return true; } else { continue; } } c = getChar(); } stringBufferTop = 0; // throw away the string in progress this.string = null; parser.addError("msg.XML.bad.form"); return false; } /** * */ private boolean readEntity() throws IOException { int declTags = 1; for (int c = getChar(); c != EOF_CHAR; c = getChar()) { addToString(c); switch (c) { case '<': declTags++; break; case '>': declTags--; if (declTags == 0) return true; break; } } stringBufferTop = 0; // throw away the string in progress this.string = null; parser.addError("msg.XML.bad.form"); return false; } /** * */ private boolean readPI() throws IOException { for (int c = getChar(); c != EOF_CHAR; c = getChar()) { addToString(c); if (c == '?' && peekChar() == '>') { c = getChar(); // Skip > addToString(c); return true; } } stringBufferTop = 0; // throw away the string in progress this.string = null; parser.addError("msg.XML.bad.form"); return false; } private String getStringFromBuffer() { tokenEnd = cursor; return new String(stringBuffer, 0, stringBufferTop); } private void addToString(int c) { int N = stringBufferTop; if (N == stringBuffer.length) { char[] tmp = new char[stringBuffer.length * 2]; System.arraycopy(stringBuffer, 0, tmp, 0, N); stringBuffer = tmp; } stringBuffer[N] = (char)c; stringBufferTop = N + 1; } private boolean canUngetChar() { return ungetCursor == 0 || ungetBuffer[ungetCursor - 1] != '\n'; } private void ungetChar(int c) { // can not unread past across line boundary if (ungetCursor != 0 && ungetBuffer[ungetCursor - 1] == '\n') Kit.codeBug(); ungetBuffer[ungetCursor++] = c; cursor--; } private boolean matchChar(int test) throws IOException { int c = getCharIgnoreLineEnd(); if (c == test) { tokenEnd = cursor; return true; } else { ungetCharIgnoreLineEnd(c); return false; } } private int peekChar() throws IOException { int c = getChar(); ungetChar(c); return c; } private int getChar() throws IOException { if (ungetCursor != 0) { cursor++; return ungetBuffer[--ungetCursor]; } for(;;) { int c; if (sourceString != null) { if (sourceCursor == sourceEnd) { hitEOF = true; return EOF_CHAR; } cursor++; c = sourceString.charAt(sourceCursor++); } else { if (sourceCursor == sourceEnd) { if (!fillSourceBuffer()) { hitEOF = true; return EOF_CHAR; } } cursor++; c = sourceBuffer[sourceCursor++]; } if (lineEndChar >= 0) { if (lineEndChar == '\r' && c == '\n') { lineEndChar = '\n'; continue; } lineEndChar = -1; lineStart = sourceCursor - 1; lineno++; } if (c <= 127) { if (c == '\n' || c == '\r') { lineEndChar = c; c = '\n'; } } else { if (c == BYTE_ORDER_MARK) return c; // BOM is considered whitespace if (isJSFormatChar(c)) { continue; } if (ScriptRuntime.isJSLineTerminator(c)) { lineEndChar = c; c = '\n'; } } return c; } } private int getCharIgnoreLineEnd() throws IOException { if (ungetCursor != 0) { cursor++; return ungetBuffer[--ungetCursor]; } for(;;) { int c; if (sourceString != null) { if (sourceCursor == sourceEnd) { hitEOF = true; return EOF_CHAR; } cursor++; c = sourceString.charAt(sourceCursor++); } else { if (sourceCursor == sourceEnd) { if (!fillSourceBuffer()) { hitEOF = true; return EOF_CHAR; } } cursor++; c = sourceBuffer[sourceCursor++]; } if (c <= 127) { if (c == '\n' || c == '\r') { lineEndChar = c; c = '\n'; } } else { if (c == BYTE_ORDER_MARK) return c; // BOM is considered whitespace if (isJSFormatChar(c)) { continue; } if (ScriptRuntime.isJSLineTerminator(c)) { lineEndChar = c; c = '\n'; } } return c; } } private void ungetCharIgnoreLineEnd(int c) { ungetBuffer[ungetCursor++] = c; cursor--; } private void skipLine() throws IOException { // skip to end of line int c; while ((c = getChar()) != EOF_CHAR && c != '\n') { } ungetChar(c); tokenEnd = cursor; } /** * Returns the offset into the current line. */ final int getOffset() { int n = sourceCursor - lineStart; if (lineEndChar >= 0) { --n; } return n; } final String getLine() { if (sourceString != null) { // String case int lineEnd = sourceCursor; if (lineEndChar >= 0) { --lineEnd; } else { for (; lineEnd != sourceEnd; ++lineEnd) { int c = sourceString.charAt(lineEnd); if (ScriptRuntime.isJSLineTerminator(c)) { break; } } } return sourceString.substring(lineStart, lineEnd); } else { // Reader case int lineLength = sourceCursor - lineStart; if (lineEndChar >= 0) { --lineLength; } else { // Read until the end of line for (;; ++lineLength) { int i = lineStart + lineLength; if (i == sourceEnd) { try { if (!fillSourceBuffer()) { break; } } catch (IOException ioe) { // ignore it, we're already displaying an error... break; } // i recalculuation as fillSourceBuffer can move saved // line buffer and change lineStart i = lineStart + lineLength; } int c = sourceBuffer[i]; if (ScriptRuntime.isJSLineTerminator(c)) { break; } } } return new String(sourceBuffer, lineStart, lineLength); } } private boolean fillSourceBuffer() throws IOException { if (sourceString != null) Kit.codeBug(); if (sourceEnd == sourceBuffer.length) { if (lineStart != 0 && !isMarkingComment()) { System.arraycopy(sourceBuffer, lineStart, sourceBuffer, 0, sourceEnd - lineStart); sourceEnd -= lineStart; sourceCursor -= lineStart; lineStart = 0; } else { char[] tmp = new char[sourceBuffer.length * 2]; System.arraycopy(sourceBuffer, 0, tmp, 0, sourceEnd); sourceBuffer = tmp; } } int n = sourceReader.read(sourceBuffer, sourceEnd, sourceBuffer.length - sourceEnd); if (n < 0) { return false; } sourceEnd += n; return true; } /** * Return the current position of the scanner cursor. */ public int getCursor() { return cursor; } /** * Return the absolute source offset of the last scanned token. */ public int getTokenBeg() { return tokenBeg; } /** * Return the absolute source end-offset of the last scanned token. */ public int getTokenEnd() { return tokenEnd; } /** * Return tokenEnd - tokenBeg */ public int getTokenLength() { return tokenEnd - tokenBeg; } /** * Return the type of the last scanned comment. * @return type of last scanned comment, or 0 if none have been scanned. */ public Token.CommentType getCommentType() { return commentType; } private void markCommentStart() { markCommentStart(""); } private void markCommentStart(String prefix) { if (parser.compilerEnv.isRecordingComments() && sourceReader != null) { commentPrefix = prefix; commentCursor = sourceCursor - 1; } } private boolean isMarkingComment() { return commentCursor != -1; } final String getAndResetCurrentComment() { if (sourceString != null) { if (isMarkingComment()) Kit.codeBug(); return sourceString.substring(tokenBeg, tokenEnd); } else { if (!isMarkingComment()) Kit.codeBug(); StringBuilder comment = new StringBuilder(commentPrefix); comment.append(sourceBuffer, commentCursor, getTokenLength() - commentPrefix.length()); commentCursor = -1; return comment.toString(); } } // stuff other than whitespace since start of line private boolean dirtyLine; String regExpFlags; // Set this to an initial non-null value so that the Parser has // something to retrieve even if an error has occurred and no // string is found. Fosters one class of error, but saves lots of // code. private String string = ""; private double number; private boolean isOctal; // delimiter for last string literal scanned private int quoteChar; private char[] stringBuffer = new char[128]; private int stringBufferTop; private ObjToIntMap allStrings = new ObjToIntMap(50); // Room to backtrace from to < on failed match of the last - in 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(StringBuffer 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(); // Hack to fix Rhino bug 538172: 2.274341322658976E-309 -> F.774341322658976E-309 if (mode == DToA.DTOSTR_STANDARD && buffer.charAt(0) > '9') { final char c0 = buffer.charAt(0); final char c1 = buffer.charAt(1); final int sum = (c0 - 'A' + 10) + (c1 - '0'); buffer.replace(0, 1, Integer.toString(sum)); decPt++; } /* 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; /* Fall through */ 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, '-'); } } } htmlunit-core-js-2.8/rhino/src/org/mozilla/javascript/Node.java0000644000175000017500000012052711222455466024467 0ustar cavedoncavedon/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- * * ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is Rhino code, released * May 6, 1999. * * The Initial Developer of the Original Code is * Netscape Communications Corporation. * Portions created by the Initial Developer are Copyright (C) 1997-1999 * the Initial Developer. All Rights Reserved. * * Contributor(s): * Norris Boyd * Roshan James * Roger Lawrence * Mike McCabe * * Alternatively, the contents of this file may be used under the terms of * the GNU General Public License Version 2 or later (the "GPL"), in which * case the provisions of the GPL are applicable instead of those above. If * you wish to allow use of your version of this file only under the terms of * the GPL and not to allow others to use your version of this file under the * MPL, indicate your decision by deleting the provisions above and replacing * them with the notice and other provisions required by the GPL. If you do * not delete the provisions above, a recipient may use your version of this * file under either the MPL or the GPL. * * ***** END LICENSE BLOCK ***** */ package org.mozilla.javascript; import org.mozilla.javascript.ast.FunctionNode; import org.mozilla.javascript.ast.Jump; import org.mozilla.javascript.ast.Name; import org.mozilla.javascript.ast.NumberLiteral; import org.mozilla.javascript.ast.Scope; import org.mozilla.javascript.ast.ScriptNode; import java.util.Iterator; import java.util.NoSuchElementException; /** * This class implements the root of the intermediate representation. * * @author Norris Boyd * @author Mike McCabe */ public class Node implements Iterable { public static final int FUNCTION_PROP = 1, LOCAL_PROP = 2, LOCAL_BLOCK_PROP = 3, REGEXP_PROP = 4, CASEARRAY_PROP = 5, // the following properties are defined and manipulated by the // optimizer - // TARGETBLOCK_PROP - the block referenced by a branch node // VARIABLE_PROP - the variable referenced by a BIND or NAME node // ISNUMBER_PROP - this node generates code on Number children and // delivers a Number result (as opposed to Objects) // DIRECTCALL_PROP - this call node should emit code to test the function // object against the known class and call direct if it // matches. TARGETBLOCK_PROP = 6, VARIABLE_PROP = 7, ISNUMBER_PROP = 8, DIRECTCALL_PROP = 9, SPECIALCALL_PROP = 10, SKIP_INDEXES_PROP = 11, // array of skipped indexes of array literal OBJECT_IDS_PROP = 12, // array of properties for object literal INCRDECR_PROP = 13, // pre or post type of increment/decrement CATCH_SCOPE_PROP = 14, // index of catch scope block in catch LABEL_ID_PROP = 15, // label id: code generation uses it MEMBER_TYPE_PROP = 16, // type of element access operation NAME_PROP = 17, // property name CONTROL_BLOCK_PROP = 18, // flags a control block that can drop off PARENTHESIZED_PROP = 19, // expression is parenthesized GENERATOR_END_PROP = 20, DESTRUCTURING_ARRAY_LENGTH = 21, DESTRUCTURING_NAMES = 22, DESTRUCTURING_PARAMS = 23, JSDOC_PROP = 24, EXPRESSION_CLOSURE_PROP = 25, // JS 1.8 expression closure pseudo-return DESTRUCTURING_SHORTHAND = 26, // JS 1.8 destructuring shorthand LAST_PROP = 26; // values of ISNUMBER_PROP to specify // which of the children are Number types public static final int BOTH = 0, LEFT = 1, RIGHT = 2; public static final int // values for SPECIALCALL_PROP NON_SPECIALCALL = 0, SPECIALCALL_EVAL = 1, SPECIALCALL_WITH = 2; public static final int // flags for INCRDECR_PROP DECR_FLAG = 0x1, POST_FLAG = 0x2; public static final int // flags for MEMBER_TYPE_PROP PROPERTY_FLAG = 0x1, // property access: element is valid name ATTRIBUTE_FLAG = 0x2, // x.@y or x..@y DESCENDANTS_FLAG = 0x4; // x..y or x..@i private static class PropListItem { PropListItem next; int type; int intValue; Object objectValue; } public Node(int nodeType) { type = nodeType; } public Node(int nodeType, Node child) { type = nodeType; first = last = child; child.next = null; } public Node(int nodeType, Node left, Node right) { type = nodeType; first = left; last = right; left.next = right; right.next = null; } public Node(int nodeType, Node left, Node mid, Node right) { type = nodeType; first = left; last = right; left.next = mid; mid.next = right; right.next = null; } public Node(int nodeType, int line) { type = nodeType; lineno = line; } public Node(int nodeType, Node child, int line) { this(nodeType, child); lineno = line; } public Node(int nodeType, Node left, Node right, int line) { this(nodeType, left, right); lineno = line; } public Node(int nodeType, Node left, Node mid, Node right, int line) { this(nodeType, left, mid, right); lineno = line; } public static Node newNumber(double number) { NumberLiteral n = new NumberLiteral(); n.setNumber(number); return n; } public static Node newString(String str) { return newString(Token.STRING, str); } public static Node newString(int type, String str) { Name name = new Name(); name.setIdentifier(str); name.setType(type); return name; } public int getType() { return type; } /** * Sets the node type and returns this node. */ public Node setType(int type) { this.type = type; return this; } /** * Gets the JsDoc comment string attached to this node. * @return the comment string or {@code null} if no JsDoc is attached to * this node */ public String getJsDoc() { return (String) getProp(JSDOC_PROP); } /** * Sets the JsDoc comment string attached to this node. */ public void setJsDoc(String jsdoc) { putProp(JSDOC_PROP, jsdoc); } public boolean hasChildren() { return first != null; } public Node getFirstChild() { return first; } public Node getLastChild() { return last; } public Node getNext() { return next; } public Node getChildBefore(Node child) { if (child == first) return null; Node n = first; while (n.next != child) { n = n.next; if (n == null) throw new RuntimeException("node is not a child"); } return n; } public Node getLastSibling() { Node n = this; while (n.next != null) { n = n.next; } return n; } public void addChildToFront(Node child) { child.next = first; first = child; if (last == null) { last = child; } } public void addChildToBack(Node child) { child.next = null; if (last == null) { first = last = child; return; } last.next = child; last = child; } public void addChildrenToFront(Node children) { Node lastSib = children.getLastSibling(); lastSib.next = first; first = children; if (last == null) { last = lastSib; } } public void addChildrenToBack(Node children) { if (last != null) { last.next = children; } last = children.getLastSibling(); if (first == null) { first = children; } } /** * Add 'child' before 'node'. */ public void addChildBefore(Node newChild, Node node) { if (newChild.next != null) throw new RuntimeException( "newChild had siblings in addChildBefore"); if (first == node) { newChild.next = first; first = newChild; return; } Node prev = getChildBefore(node); addChildAfter(newChild, prev); } /** * Add 'child' after 'node'. */ public void addChildAfter(Node newChild, Node node) { if (newChild.next != null) throw new RuntimeException( "newChild had siblings in addChildAfter"); newChild.next = node.next; node.next = newChild; if (last == node) last = newChild; } public void removeChild(Node child) { Node prev = getChildBefore(child); if (prev == null) first = first.next; else prev.next = child.next; if (child == last) last = prev; child.next = null; } public void replaceChild(Node child, Node newChild) { newChild.next = child.next; if (child == first) { first = newChild; } else { Node prev = getChildBefore(child); prev.next = newChild; } if (child == last) last = newChild; child.next = null; } public void replaceChildAfter(Node prevChild, Node newChild) { Node child = prevChild.next; newChild.next = child.next; prevChild.next = newChild; if (child == last) last = newChild; child.next = null; } public void removeChildren() { first = last = null; } private static final Node NOT_SET = new Node(Token.ERROR); /** * Iterates over the children of this Node. Supports child removal. Not * thread-safe. If anyone changes the child list before the iterator * finishes, the results are undefined and probably bad. */ public class NodeIterator implements Iterator { private Node cursor; // points to node to be returned next private Node prev = NOT_SET; private Node prev2; private boolean removed = false; public NodeIterator() { cursor = Node.this.first; } public boolean hasNext() { return cursor != null; } public Node next() { if (cursor == null) { throw new NoSuchElementException(); } removed = false; prev2 = prev; prev = cursor; cursor = cursor.next; return prev; } public void remove() { if (prev == NOT_SET) { throw new IllegalStateException("next() has not been called"); } if (removed) { throw new IllegalStateException( "remove() already called for current element"); } if (prev == first) { first = prev.next; } else if (prev == last) { prev2.next = null; last = prev2; } else { prev2.next = cursor; } } } /** * Returns an {@link java.util.Iterator} over the node's children. */ public Iterator iterator() { return new NodeIterator(); } private static final String propToString(int propType) { if (Token.printTrees) { // If Context.printTrees is false, the compiler // can remove all these strings. switch (propType) { case FUNCTION_PROP: return "function"; case LOCAL_PROP: return "local"; case LOCAL_BLOCK_PROP: return "local_block"; case REGEXP_PROP: return "regexp"; case CASEARRAY_PROP: return "casearray"; case TARGETBLOCK_PROP: return "targetblock"; case VARIABLE_PROP: return "variable"; case ISNUMBER_PROP: return "isnumber"; case DIRECTCALL_PROP: return "directcall"; case SPECIALCALL_PROP: return "specialcall"; case SKIP_INDEXES_PROP: return "skip_indexes"; case OBJECT_IDS_PROP: return "object_ids_prop"; case INCRDECR_PROP: return "incrdecr_prop"; case CATCH_SCOPE_PROP: return "catch_scope_prop"; case LABEL_ID_PROP: return "label_id_prop"; case MEMBER_TYPE_PROP: return "member_type_prop"; case NAME_PROP: return "name_prop"; case CONTROL_BLOCK_PROP: return "control_block_prop"; case PARENTHESIZED_PROP: return "parenthesized_prop"; case GENERATOR_END_PROP: return "generator_end"; case DESTRUCTURING_ARRAY_LENGTH: return "destructuring_array_length"; case DESTRUCTURING_NAMES: return "destructuring_names"; case DESTRUCTURING_PARAMS: return "destructuring_params"; default: Kit.codeBug(); } } return null; } private PropListItem lookupProperty(int propType) { PropListItem x = propListHead; while (x != null && propType != x.type) { x = x.next; } return x; } private PropListItem ensureProperty(int propType) { PropListItem item = lookupProperty(propType); if (item == null) { item = new PropListItem(); item.type = propType; item.next = propListHead; propListHead = item; } return item; } public void removeProp(int propType) { PropListItem x = propListHead; if (x != null) { PropListItem prev = null; while (x.type != propType) { prev = x; x = x.next; if (x == null) { return; } } if (prev == null) { propListHead = x.next; } else { prev.next = x.next; } } } public Object getProp(int propType) { PropListItem item = lookupProperty(propType); if (item == null) { return null; } return item.objectValue; } public int getIntProp(int propType, int defaultValue) { PropListItem item = lookupProperty(propType); if (item == null) { return defaultValue; } return item.intValue; } public int getExistingIntProp(int propType) { PropListItem item = lookupProperty(propType); if (item == null) { Kit.codeBug(); } return item.intValue; } public void putProp(int propType, Object prop) { if (prop == null) { removeProp(propType); } else { PropListItem item = ensureProperty(propType); item.objectValue = prop; } } public void putIntProp(int propType, int prop) { PropListItem item = ensureProperty(propType); item.intValue = prop; } /** * Return the line number recorded for this node. * @return the line number */ public int getLineno() { return lineno; } public void setLineno(int lineno) { this.lineno = lineno; } /** Can only be called when getType() == Token.NUMBER */ public final double getDouble() { return ((NumberLiteral)this).getNumber(); } public final void setDouble(double number) { ((NumberLiteral)this).setNumber(number); } /** Can only be called when node has String context. */ public final String getString() { return ((Name)this).getIdentifier(); } /** Can only be called when node has String context. */ public final void setString(String s) { if (s == null) Kit.codeBug(); ((Name)this).setIdentifier(s); } /** Can only be called when node has String context. */ public Scope getScope() { return ((Name)this).getScope(); } /** Can only be called when node has String context. */ public void setScope(Scope s) { if (s == null) Kit.codeBug(); if (!(this instanceof Name)) { throw Kit.codeBug(); } ((Name)this).setScope(s); } public static Node newTarget() { return new Node(Token.TARGET); } public final int labelId() { if (type != Token.TARGET && type != Token.YIELD) Kit.codeBug(); return getIntProp(LABEL_ID_PROP, -1); } public void labelId(int labelId) { if (type != Token.TARGET && type != Token.YIELD) Kit.codeBug(); putIntProp(LABEL_ID_PROP, labelId); } /** * Does consistent-return analysis on the function body when strict mode is * enabled. * * function (x) { return (x+1) } * is ok, but * function (x) { if (x < 0) return (x+1); } * is not becuase the function can potentially return a value when the * condition is satisfied and if not, the function does not explicitly * return value. * * This extends to checking mismatches such as "return" and "return " * used in the same function. Warnings are not emitted if inconsistent * returns exist in code that can be statically shown to be unreachable. * Ex. *

function (x) { while (true) { ... if (..) { return value } ... } }
     * 
* emits no warning. However if the loop had a break statement, then a * warning would be emitted. * * The consistency analysis looks at control structures such as loops, ifs, * switch, try-catch-finally blocks, examines the reachable code paths and * warns the user about an inconsistent set of termination possibilities. * * Caveat: Since the parser flattens many control structures into almost * straight-line code with gotos, it makes such analysis hard. Hence this * analyser is written to taken advantage of patterns of code generated by * the parser (for loops, try blocks and such) and does not do a full * control flow analysis of the gotos and break/continue statements. * Future changes to the parser will affect this analysis. */ /** * These flags enumerate the possible ways a statement/function can * terminate. These flags are used by endCheck() and by the Parser to * detect inconsistent return usage. * * END_UNREACHED is reserved for code paths that are assumed to always be * able to execute (example: throw, continue) * * END_DROPS_OFF indicates if the statement can transfer control to the * next one. Statement such as return dont. A compound statement may have * some branch that drops off control to the next statement. * * END_RETURNS indicates that the statement can return (without arguments) * END_RETURNS_VALUE indicates that the statement can return a value. * * A compound statement such as * if (condition) { * return value; * } * Will be detected as (END_DROPS_OFF | END_RETURN_VALUE) by endCheck() */ public static final int END_UNREACHED = 0; public static final int END_DROPS_OFF = 1; public static final int END_RETURNS = 2; public static final int END_RETURNS_VALUE = 4; public static final int END_YIELDS = 8; /** * Checks that every return usage in a function body is consistent with the * requirements of strict-mode. * @return true if the function satisfies strict mode requirement. */ public boolean hasConsistentReturnUsage() { int n = endCheck(); return (n & END_RETURNS_VALUE) == 0 || (n & (END_DROPS_OFF|END_RETURNS|END_YIELDS)) == 0; } /** * Returns in the then and else blocks must be consistent with each other. * If there is no else block, then the return statement can fall through. * @return logical OR of END_* flags */ private int endCheckIf() { Node th, el; int rv = END_UNREACHED; th = next; el = ((Jump)this).target; rv = th.endCheck(); if (el != null) rv |= el.endCheck(); else rv |= END_DROPS_OFF; return rv; } /** * Consistency of return statements is checked between the case statements. * If there is no default, then the switch can fall through. If there is a * default,we check to see if all code paths in the default return or if * there is a code path that can fall through. * @return logical OR of END_* flags */ private int endCheckSwitch() { int rv = END_UNREACHED; // examine the cases // for (n = first.next; n != null; n = n.next) // { // if (n.type == Token.CASE) { // rv |= ((Jump)n).target.endCheck(); // } else // break; // } // // we don't care how the cases drop into each other // rv &= ~END_DROPS_OFF; // // examine the default // n = ((Jump)this).getDefault(); // if (n != null) // rv |= n.endCheck(); // else // rv |= END_DROPS_OFF; // // remove the switch block // rv |= getIntProp(CONTROL_BLOCK_PROP, END_UNREACHED); return rv; } /** * If the block has a finally, return consistency is checked in the * finally block. If all code paths in the finally returns, then the * returns in the try-catch blocks don't matter. If there is a code path * that does not return or if there is no finally block, the returns * of the try and catch blocks are checked for mismatch. * @return logical OR of END_* flags */ private int endCheckTry() { int rv = END_UNREACHED; // a TryStatement isn't a jump - needs rewriting // check the finally if it exists // n = ((Jump)this).getFinally(); // if(n != null) { // rv = n.next.first.endCheck(); // } else { // rv = END_DROPS_OFF; // } // // if the finally block always returns, then none of the returns // // in the try or catch blocks matter // if ((rv & END_DROPS_OFF) != 0) { // rv &= ~END_DROPS_OFF; // // examine the try block // rv |= first.endCheck(); // // check each catch block // n = ((Jump)this).target; // if (n != null) // { // // point to the first catch_scope // for (n = n.next.first; n != null; n = n.next.next) // { // // check the block of user code in the catch_scope // rv |= n.next.first.next.first.endCheck(); // } // } // } return rv; } /** * Return statement in the loop body must be consistent. The default * assumption for any kind of a loop is that it will eventually terminate. * The only exception is a loop with a constant true condition. Code that * follows such a loop is examined only if one can statically determine * that there is a break out of the loop. *
     *  for(<> ; <>; <>) {}
     *  for(<> in <> ) {}
     *  while(<>) { }
     *  do { } while(<>)
     * 
* @return logical OR of END_* flags */ private int endCheckLoop() { Node n; int rv = END_UNREACHED; // To find the loop body, we look at the second to last node of the // loop node, which should be the predicate that the loop should // satisfy. // The target of the predicate is the loop-body for all 4 kinds of // loops. for (n = first; n.next != last; n = n.next) { /* skip */ } if (n.type != Token.IFEQ) return END_DROPS_OFF; // The target's next is the loop body block rv = ((Jump)n).target.next.endCheck(); // check to see if the loop condition is true if (n.first.type == Token.TRUE) rv &= ~END_DROPS_OFF; // look for effect of breaks rv |= getIntProp(CONTROL_BLOCK_PROP, END_UNREACHED); return rv; } /** * A general block of code is examined statement by statement. If any * statement (even compound ones) returns in all branches, then subsequent * statements are not examined. * @return logical OR of END_* flags */ private int endCheckBlock() { Node n; int rv = END_DROPS_OFF; // check each statment and if the statement can continue onto the next // one, then check the next statement for (n=first; ((rv & END_DROPS_OFF) != 0) && n != null; n = n.next) { rv &= ~END_DROPS_OFF; rv |= n.endCheck(); } return rv; } /** * A labelled statement implies that there maybe a break to the label. The * function processes the labelled statement and then checks the * CONTROL_BLOCK_PROP property to see if there is ever a break to the * particular label. * @return logical OR of END_* flags */ private int endCheckLabel() { int rv = END_UNREACHED; rv = next.endCheck(); rv |= getIntProp(CONTROL_BLOCK_PROP, END_UNREACHED); return rv; } /** * When a break is encountered annotate the statement being broken * out of by setting its CONTROL_BLOCK_PROP property. * @return logical OR of END_* flags */ private int endCheckBreak() { Node n = ((Jump) this).getJumpStatement(); n.putIntProp(CONTROL_BLOCK_PROP, END_DROPS_OFF); return END_UNREACHED; } /** * endCheck() examines the body of a function, doing a basic reachability * analysis and returns a combination of flags END_* flags that indicate * how the function execution can terminate. These constitute only the * pessimistic set of termination conditions. It is possible that at * runtime certain code paths will never be actually taken. Hence this * analysis will flag errors in cases where there may not be errors. * @return logical OR of END_* flags */ private int endCheck() { switch(type) { case Token.BREAK: return endCheckBreak(); case Token.EXPR_VOID: if (this.first != null) return first.endCheck(); return END_DROPS_OFF; case Token.YIELD: return END_YIELDS; case Token.CONTINUE: case Token.THROW: return END_UNREACHED; case Token.RETURN: if (this.first != null) return END_RETURNS_VALUE; else return END_RETURNS; case Token.TARGET: if (next != null) return next.endCheck(); else return END_DROPS_OFF; case Token.LOOP: return endCheckLoop(); case Token.LOCAL_BLOCK: case Token.BLOCK: // there are several special kinds of blocks if (first == null) return END_DROPS_OFF; switch(first.type) { case Token.LABEL: return first.endCheckLabel(); case Token.IFNE: return first.endCheckIf(); case Token.SWITCH: return first.endCheckSwitch(); case Token.TRY: return first.endCheckTry(); default: return endCheckBlock(); } default: return END_DROPS_OFF; } } public boolean hasSideEffects() { switch (type) { case Token.EXPR_VOID: case Token.COMMA: if (last != null) return last.hasSideEffects(); else return true; case Token.HOOK: if (first == null || first.next == null || first.next.next == null) Kit.codeBug(); return first.next.hasSideEffects() && first.next.next.hasSideEffects(); case Token.AND: case Token.OR: if (first == null || last == null) Kit.codeBug(); return first.hasSideEffects() || last.hasSideEffects(); case Token.ERROR: // Avoid cascaded error messages case Token.EXPR_RESULT: case Token.ASSIGN: case Token.ASSIGN_ADD: case Token.ASSIGN_SUB: case Token.ASSIGN_MUL: case Token.ASSIGN_DIV: case Token.ASSIGN_MOD: case Token.ASSIGN_BITOR: case Token.ASSIGN_BITXOR: case Token.ASSIGN_BITAND: case Token.ASSIGN_LSH: case Token.ASSIGN_RSH: case Token.ASSIGN_URSH: case Token.ENTERWITH: case Token.LEAVEWITH: case Token.RETURN: case Token.GOTO: case Token.IFEQ: case Token.IFNE: case Token.NEW: case Token.DELPROP: case Token.SETNAME: case Token.SETPROP: case Token.SETELEM: case Token.CALL: case Token.THROW: case Token.RETHROW: case Token.SETVAR: case Token.CATCH_SCOPE: case Token.RETURN_RESULT: case Token.SET_REF: case Token.DEL_REF: case Token.REF_CALL: case Token.TRY: case Token.SEMI: case Token.INC: case Token.DEC: case Token.IF: case Token.ELSE: case Token.SWITCH: case Token.WHILE: case Token.DO: case Token.FOR: case Token.BREAK: case Token.CONTINUE: case Token.VAR: case Token.CONST: case Token.LET: case Token.LETEXPR: case Token.WITH: case Token.WITHEXPR: case Token.CATCH: case Token.FINALLY: case Token.BLOCK: case Token.LABEL: case Token.TARGET: case Token.LOOP: case Token.JSR: case Token.SETPROP_OP: case Token.SETELEM_OP: case Token.LOCAL_BLOCK: case Token.SET_REF_OP: case Token.YIELD: return true; default: return false; } } @Override public String toString() { if (Token.printTrees) { StringBuffer sb = new StringBuffer(); toString(new ObjToIntMap(), sb); return sb.toString(); } return String.valueOf(type); } private void toString(ObjToIntMap printIds, StringBuffer sb) { if (Token.printTrees) { sb.append(Token.name(type)); if (this instanceof Name) { sb.append(' '); sb.append(getString()); Scope scope = getScope(); if (scope != null) { sb.append("[scope: "); appendPrintId(scope, printIds, sb); sb.append("]"); } } else if (this instanceof Scope) { if (this instanceof ScriptNode) { ScriptNode sof = (ScriptNode)this; if (this instanceof FunctionNode) { FunctionNode fn = (FunctionNode)this; sb.append(' '); sb.append(fn.getName()); } sb.append(" [source name: "); sb.append(sof.getSourceName()); sb.append("] [encoded source length: "); sb.append(sof.getEncodedSourceEnd() - sof.getEncodedSourceStart()); sb.append("] [base line: "); sb.append(sof.getBaseLineno()); sb.append("] [end line: "); sb.append(sof.getEndLineno()); sb.append(']'); } if (((Scope)this).getSymbolTable() != null) { sb.append(" [scope "); appendPrintId(this, printIds, sb); sb.append(": "); Iterator iter = ((Scope) this).getSymbolTable().keySet().iterator(); while (iter.hasNext()) { sb.append(iter.next()); sb.append(" "); } sb.append("]"); } } else if (this instanceof Jump) { Jump jump = (Jump)this; if (type == Token.BREAK || type == Token.CONTINUE) { sb.append(" [label: "); appendPrintId(jump.getJumpStatement(), printIds, sb); sb.append(']'); } else if (type == Token.TRY) { Node catchNode = jump.target; Node finallyTarget = jump.getFinally(); if (catchNode != null) { sb.append(" [catch: "); appendPrintId(catchNode, printIds, sb); sb.append(']'); } if (finallyTarget != null) { sb.append(" [finally: "); appendPrintId(finallyTarget, printIds, sb); sb.append(']'); } } else if (type == Token.LABEL || type == Token.LOOP || type == Token.SWITCH) { sb.append(" [break: "); appendPrintId(jump.target, printIds, sb); sb.append(']'); if (type == Token.LOOP) { sb.append(" [continue: "); appendPrintId(jump.getContinue(), printIds, sb); sb.append(']'); } } else { sb.append(" [target: "); appendPrintId(jump.target, printIds, sb); sb.append(']'); } } else if (type == Token.NUMBER) { sb.append(' '); sb.append(getDouble()); } else if (type == Token.TARGET) { sb.append(' '); appendPrintId(this, printIds, sb); } if (lineno != -1) { sb.append(' '); sb.append(lineno); } for (PropListItem x = propListHead; x != null; x = x.next) { int type = x.type; sb.append(" ["); sb.append(propToString(type)); sb.append(": "); String value; switch (type) { case TARGETBLOCK_PROP : // can't add this as it recurses value = "target block property"; break; case LOCAL_BLOCK_PROP : // can't add this as it is dull value = "last local block"; break; case ISNUMBER_PROP: switch (x.intValue) { case BOTH: value = "both"; break; case RIGHT: value = "right"; break; case LEFT: value = "left"; break; default: throw Kit.codeBug(); } break; case SPECIALCALL_PROP: switch (x.intValue) { case SPECIALCALL_EVAL: value = "eval"; break; case SPECIALCALL_WITH: value = "with"; break; default: // NON_SPECIALCALL should not be stored throw Kit.codeBug(); } break; case OBJECT_IDS_PROP: { Object[] a = (Object[]) x.objectValue; value = "["; for (int i=0; i < a.length; i++) { value += a[i].toString(); if (i+1 < a.length) value += ", "; } value += "]"; break; } default : Object obj = x.objectValue; if (obj != null) { value = obj.toString(); } else { value = String.valueOf(x.intValue); } break; } sb.append(value); sb.append(']'); } } } public String toStringTree(ScriptNode treeTop) { if (Token.printTrees) { StringBuffer sb = new StringBuffer(); toStringTreeHelper(treeTop, this, null, 0, sb); return sb.toString(); } return null; } private static void toStringTreeHelper(ScriptNode treeTop, Node n, ObjToIntMap printIds, int level, StringBuffer sb) { if (Token.printTrees) { if (printIds == null) { printIds = new ObjToIntMap(); generatePrintIds(treeTop, printIds); } for (int i = 0; i != level; ++i) { sb.append(" "); } n.toString(printIds, sb); sb.append('\n'); for (Node cursor = n.getFirstChild(); cursor != null; cursor = cursor.getNext()) { if (cursor.getType() == Token.FUNCTION) { int fnIndex = cursor.getExistingIntProp(Node.FUNCTION_PROP); FunctionNode fn = treeTop.getFunctionNode(fnIndex); toStringTreeHelper(fn, fn, null, level + 1, sb); } else { toStringTreeHelper(treeTop, cursor, printIds, level+1, sb); } } } } private static void generatePrintIds(Node n, ObjToIntMap map) { if (Token.printTrees) { map.put(n, map.size()); for (Node cursor = n.getFirstChild(); cursor != null; cursor = cursor.getNext()) { generatePrintIds(cursor, map); } } } private static void appendPrintId(Node n, ObjToIntMap printIds, StringBuffer sb) { if (Token.printTrees) { if (n != null) { int id = printIds.get(n, -1); sb.append('#'); if (id != -1) { sb.append(id + 1); } else { sb.append(""); } } } } protected int type = Token.ERROR; // type of the node, e.g. Token.NAME protected Node next; // next sibling protected Node first; // first element of a linked list of children protected Node last; // last element of a linked list of children protected int lineno = -1; /** * Linked list of properties. Since vast majority of nodes would have * no more then 2 properties, linked list saves memory and provides * fast lookup. If this does not holds, propListHead can be replaced * by UintMap. */ protected PropListItem propListHead; } htmlunit-core-js-2.8/rhino/src/org/mozilla/javascript/Synchronizer.java0000644000175000017500000000562710776622373026310 0ustar cavedoncavedon/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- * * ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is Delegator.java, released * Sep 27, 2000. * * The Initial Developer of the Original Code is * Matthias Radestock. . * Portions created by the Initial Developer are Copyright (C) 2000 * the Initial Developer. All Rights Reserved. * * Contributor(s): * * Alternatively, the contents of this file may be used under the terms of * the GNU General Public License Version 2 or later (the "GPL"), in which * case the provisions of the GPL are applicable instead of those above. If * you wish to allow use of your version of this file only under the terms of * the GPL and not to allow others to use your version of this file under the * MPL, indicate your decision by deleting the provisions above and replacing * them with the notice and other provisions required by the GPL. If you do * not delete the provisions above, a recipient may use your version of this * file under either the MPL or the GPL. * * ***** END LICENSE BLOCK ***** */ // API class package org.mozilla.javascript; /** * This class provides support for implementing Java-style synchronized * methods in Javascript. * * Synchronized functions are created from ordinary Javascript * functions by the Synchronizer constructor, e.g. * new Packages.org.mozilla.javascript.Synchronizer(fun). * The resulting object is a function that establishes an exclusive * lock on the this object of its invocation. * * The Rhino shell provides a short-cut for the creation of * synchronized methods: sync(fun) has the same effect as * calling the above constructor. * * @see org.mozilla.javascript.Delegator * @author Matthias Radestock */ public class Synchronizer extends Delegator { /** * Create a new synchronized function from an existing one. * * @param obj the existing function */ public Synchronizer(Scriptable obj) { super(obj); } /** * @see org.mozilla.javascript.Function#call */ @Override public Object call(Context cx, Scriptable scope, Scriptable thisObj, Object[] args) { synchronized(thisObj instanceof Wrapper ? ((Wrapper)thisObj).unwrap() : thisObj) { return ((Function)obj).call(cx,scope,thisObj,args); } } } htmlunit-core-js-2.8/rhino/src/org/mozilla/javascript/jdk15/0000755000175000017500000000000011530107756023644 5ustar cavedoncavedonhtmlunit-core-js-2.8/rhino/src/org/mozilla/javascript/jdk15/VMBridge_jdk15.java0000644000175000017500000000675511111044312027140 0ustar cavedoncavedon/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- * * ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is Rhino code, released * May 6, 1999. * * The Initial Developer of the Original Code is * Netscape Communications Corporation. * Portions created by the Initial Developer are Copyright (C) 1997-2000 * the Initial Developer. All Rights Reserved. * * Contributor(s): * * Alternatively, the contents of this file may be used under the terms of * the GNU General Public License Version 2 or later (the "GPL"), in which * case the provisions of the GPL are applicable instead of those above. If * you wish to allow use of your version of this file only under the terms of * the GPL and not to allow others to use your version of this file under the * MPL, indicate your decision by deleting the provisions above and replacing * them with the notice and other provisions required by the GPL. If you do * not delete the provisions above, a recipient may use your version of this * file under either the MPL or the GPL. * * ***** END LICENSE BLOCK ***** */ package org.mozilla.javascript.jdk15; import java.lang.reflect.Member; import java.lang.reflect.Method; import java.lang.reflect.Constructor; import java.util.Iterator; import org.mozilla.javascript.*; public class VMBridge_jdk15 extends org.mozilla.javascript.jdk13.VMBridge_jdk13 { public VMBridge_jdk15() throws SecurityException, InstantiationException { try { // Just try and see if we can access the isVarArgs method. // We want to fail loading if the method does not exist // so that we can load a bridge to an older JDK instead. Method.class.getMethod("isVarArgs", (Class[]) null); } catch (NoSuchMethodException e) { // Throw a fitting exception that is handled by // org.mozilla.javascript.Kit.newInstanceOrNull: throw new InstantiationException(e.getMessage()); } } @Override public boolean isVarArgs(Member member) { if (member instanceof Method) return ((Method) member).isVarArgs(); else if (member instanceof Constructor) return ((Constructor) member).isVarArgs(); else return false; } /** * If "obj" is a java.util.Iterator or a java.lang.Iterable, return a * wrapping as a JavaScript Iterator. Otherwise, return null. * This method is in VMBridge since Iterable is a JDK 1.5 addition. */ @Override public Iterator getJavaIterator(Context cx, Scriptable scope, Object obj) { if (obj instanceof Wrapper) { Object unwrapped = ((Wrapper) obj).unwrap(); Iterator iterator = null; if (unwrapped instanceof Iterator) iterator = (Iterator) unwrapped; if (unwrapped instanceof Iterable) iterator = ((Iterable)unwrapped).iterator(); return iterator; } return null; } } htmlunit-core-js-2.8/rhino/src/org/mozilla/javascript/NativeJavaTopPackage.java0000644000175000017500000001560711222455466027573 0ustar cavedoncavedon/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- * * ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is Rhino code, released * May 6, 1999. * * The Initial Developer of the Original Code is * Netscape Communications Corporation. * Portions created by the Initial Developer are Copyright (C) 1997-1999 * the Initial Developer. All Rights Reserved. * * Contributor(s): * Norris Boyd * Frank Mitchell * Mike Shaver * * Alternatively, the contents of this file may be used under the terms of * the GNU General Public License Version 2 or later (the "GPL"), in which * case the provisions of the GPL are applicable instead of those above. If * you wish to allow use of your version of this file only under the terms of * the GPL and not to allow others to use your version of this file under the * MPL, indicate your decision by deleting the provisions above and replacing * them with the notice and other provisions required by the GPL. If you do * not delete the provisions above, a recipient may use your version of this * file under either the MPL or the GPL. * * ***** END LICENSE BLOCK ***** */ package org.mozilla.javascript; /** * This class reflects Java packages into the JavaScript environment. We * lazily reflect classes and subpackages, and use a caching/sharing * system to ensure that members reflected into one JavaPackage appear * in all other references to the same package (as with Packages.java.lang * and java.lang). * * @author Mike Shaver * @see NativeJavaArray * @see NativeJavaObject * @see NativeJavaClass */ public class NativeJavaTopPackage extends NativeJavaPackage implements Function, IdFunctionCall { static final long serialVersionUID = -1455787259477709999L; // we know these are packages so we can skip the class check // note that this is ok even if the package isn't present. private static final String[][] commonPackages = { {"java", "lang", "reflect"}, {"java", "io"}, {"java", "math"}, {"java", "net"}, {"java", "util", "zip"}, {"java", "text", "resources"}, {"java", "applet"}, {"javax", "swing"} }; NativeJavaTopPackage(ClassLoader loader) { super(true, "", loader); } public Object call(Context cx, Scriptable scope, Scriptable thisObj, Object[] args) { return construct(cx, scope, args); } public Scriptable construct(Context cx, Scriptable scope, Object[] args) { ClassLoader loader = null; if (args.length != 0) { Object arg = args[0]; if (arg instanceof Wrapper) { arg = ((Wrapper)arg).unwrap(); } if (arg instanceof ClassLoader) { loader = (ClassLoader)arg; } } if (loader == null) { Context.reportRuntimeError0("msg.not.classloader"); return null; } NativeJavaPackage pkg = new NativeJavaPackage(true, "", loader); ScriptRuntime.setObjectProtoAndParent(pkg, scope); return pkg; } public static void init(Context cx, Scriptable scope, boolean sealed) { ClassLoader loader = cx.getApplicationClassLoader(); final NativeJavaTopPackage top = new NativeJavaTopPackage(loader); top.setPrototype(getObjectPrototype(scope)); top.setParentScope(scope); for (int i = 0; i != commonPackages.length; i++) { NativeJavaPackage parent = top; for (int j = 0; j != commonPackages[i].length; j++) { parent = parent.forcePackage(commonPackages[i][j], scope); } } // getClass implementation IdFunctionObject getClass = new IdFunctionObject(top, FTAG, Id_getClass, "getClass", 1, scope); // We want to get a real alias, and not a distinct JavaPackage // with the same packageName, so that we share classes and top // that are underneath. String[] topNames = { "java", "javax", "org", "com", "edu", "net" }; NativeJavaPackage[] topPackages = new NativeJavaPackage[topNames.length]; for (int i=0; i < topNames.length; i++) { topPackages[i] = (NativeJavaPackage)top.get(topNames[i], top); } // It's safe to downcast here since initStandardObjects takes // a ScriptableObject. ScriptableObject global = (ScriptableObject) scope; if (sealed) { getClass.sealObject(); } getClass.exportAsScopeProperty(); global.defineProperty("Packages", top, ScriptableObject.DONTENUM); for (int i=0; i < topNames.length; i++) { global.defineProperty(topNames[i], topPackages[i], ScriptableObject.DONTENUM); } } public Object execIdCall(IdFunctionObject f, Context cx, Scriptable scope, Scriptable thisObj, Object[] args) { if (f.hasTag(FTAG)) { if (f.methodId() == Id_getClass) { return js_getClass(cx, scope, args); } } throw f.unknown(); } private Scriptable js_getClass(Context cx, Scriptable scope, Object[] args) { if (args.length > 0 && args[0] instanceof Wrapper) { Scriptable result = this; Class cl = ((Wrapper) args[0]).unwrap().getClass(); // Evaluate the class name by getting successive properties of // the string to find the appropriate NativeJavaClass object String name = cl.getName(); int offset = 0; for (;;) { int index = name.indexOf('.', offset); String propName = index == -1 ? name.substring(offset) : name.substring(offset, index); Object prop = result.get(propName, result); if (!(prop instanceof Scriptable)) break; // fall through to error result = (Scriptable) prop; if (index == -1) return result; offset = index+1; } } throw Context.reportRuntimeError0("msg.not.java.obj"); } private static final Object FTAG = "JavaTopPackage"; private static final int Id_getClass = 1; } htmlunit-core-js-2.8/rhino/src/org/mozilla/javascript/resources/0000755000175000017500000000000011530107756024740 5ustar cavedoncavedonhtmlunit-core-js-2.8/rhino/src/org/mozilla/javascript/resources/Messages.properties0000644000175000017500000005225611321335670030633 0ustar cavedoncavedon# # Default JavaScript messages file. # # ***** BEGIN LICENSE BLOCK ***** # Version: MPL 1.1/GPL 2.0 # # The contents of this file are subject to the Mozilla Public License Version # 1.1 (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # http://www.mozilla.org/MPL/ # # Software distributed under the License is distributed on an "AS IS" basis, # WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License # for the specific language governing rights and limitations under the # License. # # The Original Code is Rhino code, released # May 6, 1999. # # The Initial Developer of the Original Code is # Netscape Communications Corporation. # Portions created by the Initial Developer are Copyright (C) 1997-1999 # the Initial Developer. All Rights Reserved. # # Contributor(s): # Norris Boyd # Bob Jervis # # Alternatively, the contents of this file may be used under the terms of # the GNU General Public License Version 2 or later (the "GPL"), in which # case the provisions of the GPL are applicable instead of those above. If # you wish to allow use of your version of this file only under the terms of # the GPL and not to allow others to use your version of this file under the # MPL, indicate your decision by deleting the provisions above and replacing # them with the notice and other provisions required by the GPL. If you do # not delete the provisions above, a recipient may use your version of this # file under either the MPL or the GPL. # # ***** END LICENSE BLOCK ***** # This is replaced during jar assembly from property string # and should not be translated implementation.version = @IMPLEMENTATION.VERSION@ # # To add JavaScript error messages for a particular locale, create a # new Messages_[locale].properties file, where [locale] is the Java # string abbreviation for that locale. For example, JavaScript # messages for the Polish locale should be located in # Messages_pl.properties, and messages for the Italian Swiss locale # should be located in Messages_it_CH.properties. Message properties # files should be accessible through the classpath under # org.mozilla.javascript.resources # # See: # java.util.ResourceBundle # java.text.MessageFormat # # SomeJavaClassWhereUsed # Codegen msg.dup.parms =\ Duplicate parameter name "{0}". msg.too.big.jump =\ Program too complex: too big jump offset. msg.too.big.index =\ Program too complex: internal index exceeds 64K limit. msg.while.compiling.fn =\ Encountered code generation error while compiling function "{0}": {1} msg.while.compiling.script =\ Encountered code generation error while compiling script: {0} # Context msg.ctor.not.found =\ Constructor for "{0}" not found. msg.not.ctor =\ "{0}" is not a constructor. # FunctionObject msg.varargs.ctor =\ Method or constructor "{0}" must be static with the signature \ "(Context cx, Object[] args, Function ctorObj, boolean inNewExpr)" \ to define a variable arguments constructor. msg.varargs.fun =\ Method "{0}" must be static with the signature \ "(Context cx, Scriptable thisObj, Object[] args, Function funObj)" \ to define a variable arguments function. msg.incompat.call =\ Method "{0}" called on incompatible object. msg.bad.parms =\ Unsupported parameter type "{0}" in method "{1}". msg.bad.method.return =\ Unsupported return type "{0}" in method "{1}". msg.bad.ctor.return =\ Construction of objects of type "{0}" is not supported. msg.no.overload =\ Method "{0}" occurs multiple times in class "{1}". msg.method.not.found =\ Method "{0}" not found in "{1}". # IRFactory msg.bad.for.in.lhs =\ Invalid left-hand side of for..in loop. msg.mult.index =\ Only one variable allowed in for..in loop. msg.bad.for.in.destruct =\ Left hand side of for..in loop must be an array of length 2 to accept \ key/value pair. msg.cant.convert =\ Can''t convert to type "{0}". msg.bad.assign.left =\ Invalid assignment left-hand side. msg.bad.decr =\ Invalid decrement operand. msg.bad.incr =\ Invalid increment operand. msg.bad.yield =\ yield must be in a function. msg.yield.parenthesized =\ yield expression must be parenthesized. # NativeGlobal msg.cant.call.indirect =\ Function "{0}" must be called directly, and not by way of a \ function of another name. msg.eval.nonstring =\ Calling eval() with anything other than a primitive string value will \ simply return the value. Is this what you intended? msg.eval.nonstring.strict =\ Calling eval() with anything other than a primitive string value is not \ allowed in strict mode. msg.bad.destruct.op =\ Invalid destructuring assignment operator # NativeCall msg.only.from.new =\ "{0}" may only be invoked from a "new" expression. msg.deprec.ctor =\ The "{0}" constructor is deprecated. # NativeFunction msg.no.function.ref.found =\ no source found to decompile function reference {0} msg.arg.isnt.array =\ second argument to Function.prototype.apply must be an array # NativeGlobal msg.bad.esc.mask =\ invalid string escape mask # NativeJavaClass msg.cant.instantiate =\ error instantiating ({0}): class {1} is interface or abstract msg.bad.ctor.sig =\ Found constructor with wrong signature: \ {0} calling {1} with signature {2} msg.not.java.obj =\ Expected argument to getClass() to be a Java object. msg.no.java.ctor =\ Java constructor for "{0}" with arguments "{1}" not found. # NativeJavaMethod msg.method.ambiguous =\ The choice of Java method {0}.{1} matching JavaScript argument types ({2}) is ambiguous; \ candidate methods are: {3} msg.constructor.ambiguous =\ The choice of Java constructor {0} matching JavaScript argument types ({1}) is ambiguous; \ candidate constructors are: {2} # NativeJavaObject msg.conversion.not.allowed =\ Cannot convert {0} to {1} msg.no.empty.interface.conversion =\ Cannot convert {0} to interface {1} with no methods msg.no.function.interface.conversion =\ Cannot convert function {0} to interface since it contains methods with \ different signatures # NativeJavaPackage msg.not.classloader =\ Constructor for "Packages" expects argument of type java.lang.Classloader # NativeRegExp msg.bad.quant =\ Invalid quantifier {0} msg.overlarge.backref =\ Overly large back reference {0} msg.overlarge.min =\ Overly large minimum {0} msg.overlarge.max =\ Overly large maximum {0} msg.zero.quant =\ Zero quantifier {0} msg.max.lt.min =\ Maximum {0} less than minimum msg.unterm.quant =\ Unterminated quantifier {0} msg.unterm.paren =\ Unterminated parenthetical {0} msg.unterm.class =\ Unterminated character class {0} msg.bad.range =\ Invalid range in character class. msg.trail.backslash =\ Trailing \\ in regular expression. msg.re.unmatched.right.paren =\ unmatched ) in regular expression. msg.no.regexp =\ Regular expressions are not available. msg.bad.backref =\ back-reference exceeds number of capturing parentheses. msg.bad.regexp.compile =\ Only one argument may be specified if the first argument to \ RegExp.prototype.compile is a RegExp object. msg.arg.not.object =\ Expected argument of type object, but instead had type {0} # NativeDate msg.invalid.date =\ Date is invalid. msg.toisostring.must.return.primitive =\ toISOString must return a primitive value, but instead returned "{0}" # Parser msg.got.syntax.errors = \ Compilation produced {0} syntax errors. msg.var.redecl =\ TypeError: redeclaration of var {0}. msg.const.redecl =\ TypeError: redeclaration of const {0}. msg.let.redecl =\ TypeError: redeclaration of variable {0}. msg.parm.redecl =\ TypeError: redeclaration of formal parameter {0}. msg.fn.redecl =\ TypeError: redeclaration of function {0}. msg.let.decl.not.in.block =\ SyntaxError: let declaration not directly within block msg.bad.object.init =\ SyntaxError: invalid object initializer # NodeTransformer msg.dup.label =\ duplicated label msg.undef.label =\ undefined label msg.bad.break =\ unlabelled break must be inside loop or switch msg.continue.outside =\ continue must be inside loop msg.continue.nonloop =\ continue can only use labeles of iteration statements msg.bad.throw.eol =\ Line terminator is not allowed between the throw keyword and throw \ expression. msg.no.paren.parms =\ missing ( before function parameters. msg.no.parm =\ missing formal parameter msg.no.paren.after.parms =\ missing ) after formal parameters msg.no.brace.body =\ missing '{' before function body msg.no.brace.after.body =\ missing } after function body msg.no.paren.cond =\ missing ( before condition msg.no.paren.after.cond =\ missing ) after condition msg.no.semi.stmt =\ missing ; before statement msg.missing.semi =\ missing ; after statement msg.no.name.after.dot =\ missing name after . operator msg.no.name.after.coloncolon =\ missing name after :: operator msg.no.name.after.dotdot =\ missing name after .. operator msg.no.name.after.xmlAttr =\ missing name after .@ msg.no.bracket.index =\ missing ] in index expression msg.no.paren.switch =\ missing ( before switch expression msg.no.paren.after.switch =\ missing ) after switch expression msg.no.brace.switch =\ missing '{' before switch body msg.bad.switch =\ invalid switch statement msg.no.colon.case =\ missing : after case expression msg.double.switch.default =\ double default label in the switch statement msg.no.while.do =\ missing while after do-loop body msg.no.paren.for =\ missing ( after for msg.no.semi.for =\ missing ; after for-loop initializer msg.no.semi.for.cond =\ missing ; after for-loop condition msg.in.after.for.name =\ missing in after for msg.no.paren.for.ctrl =\ missing ) after for-loop control msg.no.paren.with =\ missing ( before with-statement object msg.no.paren.after.with =\ missing ) after with-statement object msg.no.with.strict =\ with statements not allowed in strict mode msg.no.paren.after.let =\ missing ( after let msg.no.paren.let =\ missing ) after variable list msg.no.curly.let =\ missing } after let statement msg.bad.return =\ invalid return msg.no.brace.block =\ missing } in compound statement msg.bad.label =\ invalid label msg.bad.var =\ missing variable name msg.bad.var.init =\ invalid variable initialization msg.no.colon.cond =\ missing : in conditional expression msg.no.paren.arg =\ missing ) after argument list msg.no.bracket.arg =\ missing ] after element list msg.bad.prop =\ invalid property id msg.no.colon.prop =\ missing : after property id msg.no.brace.prop =\ missing } after property list msg.no.paren =\ missing ) in parenthetical msg.reserved.id =\ identifier is a reserved word msg.no.paren.catch =\ missing ( before catch-block condition msg.bad.catchcond =\ invalid catch block condition msg.catch.unreachable =\ any catch clauses following an unqualified catch are unreachable msg.no.brace.try =\ missing '{' before try block msg.no.brace.catchblock =\ missing '{' before catch-block body msg.try.no.catchfinally =\ ''try'' without ''catch'' or ''finally'' msg.no.return.value =\ function {0} does not always return a value msg.anon.no.return.value =\ anonymous function does not always return a value msg.return.inconsistent =\ return statement is inconsistent with previous usage msg.generator.returns =\ TypeError: generator function {0} returns a value msg.anon.generator.returns =\ TypeError: anonymous generator function returns a value msg.syntax =\ syntax error msg.unexpected.eof =\ Unexpected end of file msg.XML.bad.form =\ illegally formed XML syntax msg.XML.not.available =\ XML runtime not available msg.too.deep.parser.recursion =\ Too deep recursion while parsing msg.too.many.constructor.args =\ Too many constructor arguments msg.too.many.function.args =\ Too many function arguments msg.no.side.effects =\ Code has no side effects msg.extra.trailing.semi =\ Extraneous trailing semicolon msg.extra.trailing.comma =\ Trailing comma is not legal in an ECMA-262 object initializer msg.trailing.array.comma =\ Trailing comma in array literal has different cross-browser behavior msg.equal.as.assign =\ Test for equality (==) mistyped as assignment (=)? msg.var.hides.arg =\ Variable {0} hides argument msg.destruct.assign.no.init =\ Missing = in destructuring declaration msg.no.octal.strict =\ Octal numbers prohibited in strict mode. msg.dup.obj.lit.prop.strict =\ Property "{0}" already defined in this object literal. msg.dup.param.strict =\ Parameter "{0}" already declared in this function. msg.bad.id.strict =\ "{0}" is not a valid identifier for this use in strict mode. # ScriptRuntime # is there a better message for this? # it's currently only used as a poison pill for caller, caller and arguments properties msg.op.not.allowed =\ This operation is not allowed. msg.no.properties =\ {0} has no properties. msg.invalid.iterator =\ Invalid iterator value msg.iterator.primitive =\ __iterator__ returned a primitive value msg.assn.create.strict =\ Assignment to undeclared variable {0} msg.ref.undefined.prop =\ Reference to undefined property "{0}" msg.prop.not.found =\ Property {0} not found. msg.set.prop.no.setter =\ Cannot set property {0} that has only a getter. msg.invalid.type =\ Invalid JavaScript value of type {0} msg.primitive.expected =\ Primitive type expected (had {0} instead) msg.namespace.expected =\ Namespace object expected to left of :: (found {0} instead) msg.null.to.object =\ Cannot convert null to an object. msg.undef.to.object =\ Cannot convert undefined to an object. msg.cyclic.value =\ Cyclic {0} value not allowed. msg.is.not.defined =\ "{0}" is not defined. msg.undef.prop.read =\ Cannot read property "{1}" from {0} msg.undef.prop.write =\ Cannot set property "{1}" of {0} to "{2}" msg.undef.prop.delete =\ Cannot delete property "{1}" of {0} msg.undef.method.call =\ Cannot call method "{1}" of {0} msg.undef.with =\ Cannot apply "with" to {0} msg.isnt.function =\ {0} is not a function, it is {1}. msg.isnt.function.in =\ Cannot call property {0} in object {1}. It is not a function, it is "{2}". msg.function.not.found =\ Cannot find function {0}. msg.function.not.found.in =\ Cannot find function {0} in object {1}. msg.isnt.xml.object =\ {0} is not an xml object. msg.no.ref.to.get =\ {0} is not a reference to read reference value. msg.no.ref.to.set =\ {0} is not a reference to set reference value to {1}. msg.no.ref.from.function =\ Function {0} can not be used as the left-hand side of assignment \ or as an operand of ++ or -- operator. msg.bad.default.value =\ Object''s getDefaultValue() method returned an object. msg.instanceof.not.object = \ Can''t use instanceof on a non-object. msg.instanceof.bad.prototype = \ ''prototype'' property of {0} is not an object. msg.bad.radix = \ illegal radix {0}. # ScriptableObject msg.default.value =\ Cannot find default value for object. msg.zero.arg.ctor =\ Cannot load class "{0}" which has no zero-parameter constructor. duplicate.defineClass.name =\ Invalid method "{0}": name "{1}" is already in use. msg.ctor.multiple.parms =\ Can''t define constructor or class {0} since more than one \ constructor has multiple parameters. msg.extend.scriptable =\ {0} must extend ScriptableObject in order to define property {1}. msg.bad.getter.parms =\ In order to define a property, getter {0} must have zero parameters \ or a single ScriptableObject parameter. msg.obj.getter.parms =\ Expected static or delegated getter {0} to take a ScriptableObject parameter. msg.getter.static =\ Getter and setter must both be static or neither be static. msg.setter.return =\ Setter must have void return type: {0} msg.setter2.parms =\ Two-parameter setter must take a ScriptableObject as its first parameter. msg.setter1.parms =\ Expected single parameter setter for {0} msg.setter2.expected =\ Expected static or delegated setter {0} to take two parameters. msg.setter.parms =\ Expected either one or two parameters for setter. msg.setter.bad.type =\ Unsupported parameter type "{0}" in setter "{1}". msg.add.sealed =\ Cannot add a property to a sealed object: {0}. msg.remove.sealed =\ Cannot remove a property from a sealed object: {0}. msg.modify.sealed =\ Cannot modify a property of a sealed object: {0}. msg.modify.readonly =\ Cannot modify readonly property: {0}. msg.both.data.and.accessor.desc =\ Cannot be both a data and an accessor descriptor. msg.change.configurable.false.to.true =\ Cannot change the configurable attribute of "{0}" from false to true. msg.change.enumerable.with.configurable.false =\ Cannot change the enumerable attribute of "{0}" because configurable is false. msg.change.writable.false.to.true.with.configurable.false =\ Cannot change the writable attribute of "{0}" from false to true because configurable is false. msg.change.value.with.writable.false =\ Cannot change the value of attribute "{0}" because writable is false. msg.change.getter.with.configurable.false =\ Cannot change the get attribute of "{0}" because configurable is false. msg.change.setter.with.configurable.false =\ Cannot change the set attribute of "{0}" because configurable is false. msg.change.property.data.to.accessor.with.configurable.false =\ Cannot change "{0}" from a data property to an accessor property because configurable is false. msg.change.property.accessor.to.data.with.configurable.false =\ Cannot change "{0}" from an accessor property to a data property because configurable is false. msg.not.extensible =\ Cannot add properties to this object because extensible is false. # TokenStream msg.missing.exponent =\ missing exponent msg.caught.nfe =\ number format error msg.unterminated.string.lit =\ unterminated string literal msg.unterminated.comment =\ unterminated comment msg.unterminated.re.lit =\ unterminated regular expression literal msg.invalid.re.flag =\ invalid flag after regular expression msg.no.re.input.for =\ no input for {0} msg.illegal.character =\ illegal character msg.invalid.escape =\ invalid Unicode escape sequence msg.bad.namespace =\ not a valid default namespace statement. \ Syntax is: default xml namespace = EXPRESSION; # TokensStream warnings msg.bad.octal.literal =\ illegal octal literal digit {0}; interpreting it as a decimal digit msg.reserved.keyword =\ illegal usage of future reserved keyword {0}; interpreting it as ordinary identifier # LiveConnect errors msg.java.internal.field.type =\ Internal error: type conversion of {0} to assign to {1} on {2} failed. msg.java.conversion.implicit_method =\ Can''t find converter method "{0}" on class {1}. msg.java.method.assign =\ Java method "{0}" cannot be assigned to. msg.java.internal.private =\ Internal error: attempt to access private/protected field "{0}". msg.java.no_such_method =\ Can''t find method {0}. msg.script.is.not.constructor =\ Script objects are not constructors. msg.nonjava.method =\ Java method "{0}" was invoked with {1} as "this" value that can not be converted to Java type {2}. msg.java.member.not.found =\ Java class "{0}" has no public instance field or method named "{1}". msg.java.array.index.out.of.bounds =\ Array index {0} is out of bounds [0..{1}]. msg.java.array.member.not.found =\ Java arrays have no public instance fields or methods named "{0}". msg.pkg.int =\ Java package names may not be numbers. msg.access.prohibited =\ Access to Java class "{0}" is prohibited. # ImporterTopLevel msg.ambig.import =\ Ambiguous import: "{0}" and and "{1}". msg.not.pkg =\ Function importPackage must be called with a package; had "{0}" instead. msg.not.class =\ Function importClass must be called with a class; had "{0}" instead. msg.not.class.not.pkg =\ "{0}" is neither a class nor a package. msg.prop.defined =\ Cannot import "{0}" since a property by that name is already defined. #JavaAdapter msg.adapter.zero.args =\ JavaAdapter requires at least one argument. msg.not.java.class.arg = \ Argument {0} is not Java class: {1}. #JavaAdapter msg.only.one.super = \ Only one class may be extended by a JavaAdapter. Had {0} and {1}. # Arrays msg.arraylength.bad =\ Inappropriate array length. # Arrays msg.arraylength.too.big =\ Array length {0} exceeds supported capacity limit. msg.empty.array.reduce =\ Reduce of empty array with no initial value # URI msg.bad.uri =\ Malformed URI sequence. # Number msg.bad.precision =\ Precision {0} out of range. # NativeGenerator msg.send.newborn =\ Attempt to send value to newborn generator msg.already.exec.gen =\ Already executing generator msg.StopIteration.invalid =\ StopIteration may not be changed to an arbitrary object. # Interpreter msg.yield.closing =\ Yield from closing generator htmlunit-core-js-2.8/rhino/src/org/mozilla/javascript/resources/Messages_fr.properties0000644000175000017500000003524510776622373031335 0ustar cavedoncavedon# # French JavaScript messages file. # # ***** BEGIN LICENSE BLOCK ***** # Version: MPL 1.1/GPL 2.0 # # The contents of this file are subject to the Mozilla Public License Version # 1.1 (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # http://www.mozilla.org/MPL/ # # Software distributed under the License is distributed on an "AS IS" basis, # WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License # for the specific language governing rights and limitations under the # License. # # The Original Code is Aviva Inc. code, released # March 5, 2004. # # The Initial Developer of the Original Code is # Aviva Inc. # Portions created by the Initial Developer are Copyright (C) 2004 # the Initial Developer. All Rights Reserved. # # Contributor(s): # Eugene Aresteanu # # Alternatively, the contents of this file may be used under the terms of # the GNU General Public License Version 2 or later (the "GPL"), in which # case the provisions of the GPL are applicable instead of those above. If # you wish to allow use of your version of this file only under the terms of # the GPL and not to allow others to use your version of this file under the # MPL, indicate your decision by deleting the provisions above and replacing # them with the notice and other provisions required by the GPL. If you do # not delete the provisions above, a recipient may use your version of this # file under either the MPL or the GPL. # # ***** END LICENSE BLOCK ***** msg.dup.parms =\ Le nom de param\u00E8tre "{0}" existe d\u00E9j\u00E0. msg.too.big.jump =\ Programme trop complexe : d\u00E9calage de saut trop important msg.too.big.index =\ Programme trop complexe : l''indice interne d\u00E9passe la limite de 64 ko msg.ctor.not.found =\ Le constructeur de "{0}" est introuvable msg.not.ctor =\ {0} n''est pas un constructeur msg.varargs.ctor =\ La m\u00E9thode ou le constructeur "{0}" doit \u00EAtre statique avec la signature "(Context cx, arguments Object[], Function ctorObj, boolean inNewExpr)" pour d\u00E9finir un constructeur d''arguments de variable. msg.varargs.fun =\ La m\u00E9thode "{0}" doit \u00EAtre statique avec la signature "(Context cx, Scriptable thisObj, arguments Object[], Function funObj)" pour d\u00E9finir une fonction d''arguments de variable msg.incompat.call =\ La m\u00E9thode "{0}" a \u00E9t\u00E9 appel\u00E9e dans un objet non compatible msg.bad.parms =\ Les param\u00E8tres de la m\u00E9thode sont incorrects pour "{0}" msg.no.overload =\ La m\u00E9thode "{0}" appara\u00EEt plusieurs fois dans la classe "{1}" msg.method.not.found =\ La m\u00E9thode "{0}" est introuvable dans "{1}" msg.bad.for.in.lhs =\ La partie gauche de la boucle for..in est incorrecte msg.bad.lhs.assign =\ La partie gauche de l''affectation est incorrecte msg.mult.index =\ Une seule variable est autoris\u00E9e dans la boucle for..in msg.cant.convert =\ La conversion en type "{0}" est impossible msg.cant.call.indirect =\ La fonction "{0}" doit \u00EAtre appel\u00E9e directement et non par l''interm\u00E9diaire d''une fonction portant un autre nom msg.eval.nonstring =\ Si vous appelez la fonction eval() avec une valeur qui n''appartient pas \u00E0 une cha\u00EEne primitive, c''est la valeur en question qui est renvoy\u00E9e. \u00E9tait-ce votre intention ? msg.only.from.new =\ {0} ne peut \u00EAtre appel\u00E9e qu''\u00E0 partir d''une "nouvelle" expression. msg.deprec.ctor =\ Le constructeur "{0}" est d\u00E9conseill\u00E9 msg.no.function.ref.found =\ aucune source n''a \u00E9t\u00E9 trouv\u00E9e pour d\u00E9compiler la r\u00E9f\u00E9rence de fonction {0} msg.arg.isnt.array =\ le second argument de la m\u00E9thode Function.prototype.apply doit \u00EAtre un tableau msg.bad.esc.mask =\ le masque d''\u00E9chappement de cha\u00EEne est incorrect msg.cant.instantiate =\ erreur lors de l''instanciation ({0}) : la classe {1} est une classe interface ou abstract msg.bad.ctor.sig =\ Un constructeur avec une signature incorrecte a \u00E9t\u00E9 d\u00E9tect\u00E9 : {0} qui appelle {1} avec la signature {2} msg.not.java.obj =\ L''argument attendu pour la fonction getClass() doit \u00EAtre un objet Java msg.no.java.ctor =\ Le constructeur Java de "{0}" avec les arguments "{1}" est introuvable msg.method.ambiguous =\ Le choix de la m\u00E9thode Java {0}.{1} correspondant aux types d''argument JavaScript ({2}) est ambigu. Les m\u00E9thodes propos\u00E9es sont les suivantes : {3} msg.constructor.ambiguous =\ Le choix du constructeur Java {0} correspondant aux types d''argument JavaScript ({1}) est ambigu. Les constructeurs propos\u00E9s sont les suivants : {2} msg.conversion.not.allowed =\ Impossible de convertir {0} en {1} msg.not.classloader =\ Le constructeur de "Packages" attend un argument de type java.lang.Classloader msg.bad.quant =\ Le quantificateur {0} est incorrect msg.overlarge.max =\ Le maximum {0} est trop important msg.zero.quant =\ Le quantificateur {0} est nul msg.max.lt.min =\ Le maximum {0} est inf\u00E9rieur au minimum msg.unterm.quant =\ Le quantificateur {0} n''a pas de limite msg.unterm.paren =\ Les parenth\u00E8ses {0} n''ont pas de limite msg.unterm.class =\ La classe de caract\u00E8res {0} n''a pas de limite msg.bad.range =\ La classe de caract\u00E8res contient une plage de valeurs incorrecte msg.trail.backslash =\ \\ au d\u00E9but d''une expression r\u00E9guli\u00E8re msg.no.regexp =\ Les expressions r\u00E9guli\u00E8res ne sont pas disponibles msg.bad.backref =\ la r\u00E9f\u00E9rence ant\u00E9rieure d\u00E9passe le nombre de parenth\u00E8ses de capture msg.dup.label =\ Le libell\u00E9 {0} existe d\u00E9j\u00E0 msg.undef.label =\ Le libell\u00E9 {0} n''est pas d\u00E9fini msg.bad.break =\ Le saut non libell\u00E9 doit se trouver dans la boucle ou dans l''aiguillage msg.continue.outside =\ continue doit se trouver dans la boucle msg.continue.nonloop =\ Il n''est possible de continuer que dans l''instruction d''it\u00E9ration libell\u00E9e msg.fn.redecl =\ La fonction "{0}" a \u00E9t\u00E9 de nouveau d\u00E9clar\u00E9e. La d\u00E9finition pr\u00E9c\u00E9dente sera ignor\u00E9e msg.no.paren.parms =\ il manque ''('' avant les param\u00E8tres de la fonction msg.no.parm =\ il manque un param\u00E8tre de forme msg.no.paren.after.parms =\ il manque '')'' apr\u00E8s les param\u00E8tres de forme msg.no.brace.body =\ il manque '{' avant le corps d''une fonction msg.no.brace.after.body =\ il manque ''}'' apr\u00E8s le corps d''une fonction msg.no.paren.cond =\ il manque ''('' avant une condition msg.no.paren.after.cond =\ il manque '')'' apr\u00E8s une condition msg.no.semi.stmt =\ il manque '';'' avant une instruction msg.no.name.after.dot =\ il manque un nom apr\u00E8s un op\u00E9rateur ''.'' msg.no.bracket.index =\ il manque '']'' dans l''expression de l''indice msg.no.paren.switch =\ il manque ''('' avant l''expression d''un aiguillage msg.no.paren.after.switch =\ il manque '')'' apr\u00E8s l''expression d''un aiguillage msg.no.brace.switch =\ il manque '{' avant le corps d''un aiguillage msg.bad.switch =\ l''instruction d''aiguillage est incorrecte msg.no.colon.case =\ il manque '':'' apr\u00E8s l''expression d''un cas msg.no.while.do =\ il manque ''while'' apr\u00E8s le corps d''une boucle do-loop msg.no.paren.for =\ il manque ''('' apr\u00E8s for msg.no.semi.for =\ Il manque '';'' apr\u00E8s l''initialiseur for-loop msg.no.semi.for.cond =\ il manque '';'' apr\u00E8s la condition for-loop msg.no.paren.for.ctrl =\ il manque '')'' apr\u00E8s le contrôle for-loop msg.no.paren.with =\ il manque ''('' avant un objet with-statement msg.no.paren.after.with =\ il manque '')'' apr\u00E8s un objet with-statement msg.bad.return =\ la valeur renvoy\u00E9e est incorrecte msg.no.brace.block =\ il manque ''}'' dans une instruction compos\u00E9e msg.bad.label =\ le libell\u00E9 est incorrect msg.bad.var =\ il manque un nom de variable msg.bad.var.init =\ l''initialisation de la variable est incorrecte msg.no.colon.cond =\ il manque '':'' dans une expression conditionnelle msg.no.paren.arg =\ il manque '')'' apr\u00E8s une liste d''arguments msg.no.bracket.arg =\ il manque '']'' apr\u00E8s une liste d''\u00E9l\u00E9ments msg.bad.prop =\ l''identifiant de propri\u00E9t\u00E9 est incorrect msg.no.colon.prop =\ il manque '':'' apr\u00E8s un identifiant de propri\u00E9t\u00E9 msg.no.brace.prop =\ il manque ''}'' apr\u00E8s une liste de propri\u00E9t\u00E9s msg.no.paren =\ il manque '')'' dans des parenth\u00E8ses msg.reserved.id =\ l''identifiant est un mot r\u00E9serv\u00E9 msg.no.paren.catch =\ il manque ''('' avant une condition catch-block msg.bad.catchcond =\ la condition catch-block est incorrecte msg.catch.unreachable =\ aucune clause catch suivant une interception non qualifi\u00E9e ne peut \u00EAtre atteinte msg.no.brace.catchblock =\ il manque '{' avant le corps catch-block msg.try.no.catchfinally =\ ''try'' a \u00E9t\u00E9 d\u00E9tect\u00E9 sans ''catch'' ni ''finally'' msg.syntax =\ erreur de syntaxe msg.assn.create =\ Une variable va \u00EAtre cr\u00E9\u00E9e en raison de l''affectation \u00E0 un ''{0}'' non d\u00E9fini. Ajoutez une instruction de variable \u00E0 la port\u00E9e sup\u00E9rieure pour que cet avertissement ne soit plus affich\u00E9 msg.prop.not.found =\ La propri\u00E9t\u00E9 est introuvable msg.invalid.type =\ Valeur JavaScript de type {0} incorrecte msg.primitive.expected =\ Un type primitif \u00E9tait attendu (et non {0}) msg.null.to.object =\ Il est impossible de convertir la valeur null en objet msg.undef.to.object =\ Il est impossible de convertir une valeur non d\u00E9finie en objet msg.cyclic.value =\ La valeur cyclique {0} n''est pas autoris\u00E9e msg.is.not.defined =\ "{0}" n''est pas d\u00E9fini msg.isnt.function =\ {0} n''est pas une fonction, est un {1} msg.bad.default.value =\ La m\u00E9thode getDefaultValue() de l''objet a renvoy\u00E9 un objet msg.instanceof.not.object =\ Il est impossible d''utiliser une instance d''un \u00E9l\u00E9ment autre qu''un objet msg.instanceof.bad.prototype =\ La propri\u00E9t\u00E9 ''prototype'' de {0} n''est pas un objet msg.bad.radix =\ la base {0} n''est pas autoris\u00E9e msg.default.value =\ La valeur par d\u00E9faut de l''objet est introuvable msg.zero.arg.ctor =\ Il est impossible de charger la classe "{0}", qui ne poss\u00E8de pas de constructeur de param\u00E8tre z\u00E9ro msg.multiple.ctors =\ Les m\u00E9thodes {0} et {1} ont \u00E9t\u00E9 d\u00E9tect\u00E9es alors qu''il est impossible d''utiliser plusieurs m\u00E9thodes constructor msg.ctor.multiple.parms =\ Il est impossible de d\u00E9finir le constructeur ou la classe {0} car plusieurs constructeurs poss\u00E8dent plusieurs param\u00E8tres msg.extend.scriptable =\ {0} doit \u00E9tendre ScriptableObject afin de d\u00E9finir la propri\u00E9t\u00E9 {1} msg.bad.getter.parms =\ Pour d\u00E9finir une propri\u00E9t\u00E9, la m\u00E9thode d''obtention {0} doit avoir des param\u00E8tres z\u00E9ro ou un seul param\u00E8tre ScriptableObject msg.obj.getter.parms =\ La m\u00E9thode d''obtention statique ou d\u00E9l\u00E9gu\u00E9e {0} doit utiliser un param\u00E8tre ScriptableObject msg.getter.static =\ La m\u00E9thode d''obtention et la m\u00E9thode de d\u00E9finition doivent toutes deux avoir le m\u00EAme \u00E9tat (statique ou non) msg.setter2.parms =\ La m\u00E9thode de d\u00E9finition \u00E0 deux param\u00E8tres doit utiliser un param\u00E8tre ScriptableObject comme premier param\u00E8tre msg.setter1.parms =\ Une m\u00E9thode d''obtention \u00E0 param\u00E8tre unique est attendue pour {0} msg.setter2.expected =\ La m\u00E9thode de d\u00E9finition statique ou d\u00E9l\u00E9gu\u00E9e {0} doit utiliser deux param\u00E8tres msg.setter.parms =\ Un ou deux param\u00E8tres sont attendus pour la m\u00E9thode de d\u00E9finition msg.add.sealed =\ Il est impossible d''ajouter une propri\u00E9t\u00E9 \u00E0 un objet ferm\u00E9 msg.remove.sealed =\ Il est impossible de supprimer une propri\u00E9t\u00E9 d''un objet ferm\u00E9 msg.token.replaces.pushback =\ le jeton de non-obtention {0} remplace le jeton de renvoi {1} msg.missing.exponent =\ il manque un exposant msg.caught.nfe =\ erreur de format de nombre : {0} msg.unterminated.string.lit =\ le litt\u00E9ral de la cha\u00EEne n''a pas de limite msg.unterminated.comment =\ le commentaire n''a pas de limite msg.unterminated.re.lit =\ le litt\u00E9ral de l''expression r\u00E9guli\u00E8re n''a pas de limite msg.invalid.re.flag =\ une expression r\u00E9guli\u00E8re est suivie d''un indicateur incorrect msg.no.re.input.for =\ il n''y a pas d''entr\u00E9e pour {0} msg.illegal.character =\ caract\u00E8re non autoris\u00E9 msg.invalid.escape =\ la s\u00E9quence d''\u00E9chappement Unicode est incorrecte msg.bad.octal.literal =\ le chiffre octal du litt\u00E9ral, {0}, n''est pas autoris\u00E9 et sera interpr\u00E9t\u00E9 comme un chiffre d\u00E9cimal msg.reserved.keyword =\ l''utilisation du futur mot-cl\u00E9 r\u00E9serv\u00E9 {0} n''est pas autoris\u00E9e et celui-ci sera interpr\u00E9t\u00E9 comme un identifiant ordinaire msg.undefined =\ La valeur non d\u00E9finie ne poss\u00E8de pas de propri\u00E9t\u00E9 msg.java.internal.field.type =\ Erreur interne : la conversion de type de {0} afin d''affecter {1} \u00E0 {2} a \u00E9chou\u00E9 msg.java.conversion.implicit_method =\ La m\u00E9thode de conversion "{0}" est introuvable dans la classe {1} sg.java.method.assign =\ La m\u00E9thode Java "{0}" ne peut pas \u00EAtre affect\u00E9e \u00E0 msg.java.internal.private =\ Erreur interne : une tentative d''acc\u00E9der \u00E0 un champ "{0}" priv\u00E9/prot\u00E9g\u00E9 a \u00E9t\u00E9 d\u00E9tect\u00E9e msg.java.no_such_method =\ La m\u00E9thode ''{0}'' est introuvable msg.script.is.not.constructor =\ Les objets Script ne sont pas des constructeurs msg.nonjava.method =\ La m\u00E9thode Java "{0}" a \u00E9t\u00E9 appel\u00E9e avec une valeur ''this'' qui n''est pas un objet Java msg.java.member.not.found =\ La classe Java "{0}" ne poss\u00E8de aucun champ ou aucune m\u00E9thode d''instance publique appel\u00E9 "{1}" msg.java.array.index.out.of.bounds =\ Array index {0} is out of bounds [0..{1}]. msg.pkg.int =\ Les noms de package Java ne peuvent pas \u00EAtre des nombres msg.ambig.import =\ Importation ambigu\u00EB : "{0}" et "{1}" msg.not.pkg =\ La fonction importPackage doit \u00EAtre appel\u00E9e avec un package et non avec "{0}" msg.not.class =\ La fonction importClass doit \u00EAtre appel\u00E9e avec une classe et non avec "{0}" msg.prop.defined =\ Il est impossible d''importer "{0}" car une propri\u00E9t\u00E9 portant le m\u00EAme nom a d\u00E9j\u00E0 \u00E9t\u00E9 d\u00E9finie sg.arraylength.bad =\ La longueur du tableau n''est pas appropri\u00E9e msg.bad.uri =\ La s\u00E9quence URI n''est pas form\u00E9e correctement msg.bad.precision =\ La pr\u00E9cision {0} ne se trouve pas dans la plage de valeurs htmlunit-core-js-2.8/rhino/src/org/mozilla/javascript/optimizer/0000755000175000017500000000000011530107756024750 5ustar cavedoncavedonhtmlunit-core-js-2.8/rhino/src/org/mozilla/javascript/optimizer/OptRuntime.java0000644000175000017500000002613311111044312027705 0ustar cavedoncavedon/* ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is Rhino code, released * May 6, 1999. * * The Initial Developer of the Original Code is * Netscape Communications Corporation. * Portions created by the Initial Developer are Copyright (C) 1997-2000 * the Initial Developer. All Rights Reserved. * * Contributor(s): * Norris Boyd * Roger Lawrence * Hannes Wallnoefer * * Alternatively, the contents of this file may be used under the terms of * the GNU General Public License Version 2 or later (the "GPL"), in which * case the provisions of the GPL are applicable instead of those above. If * you wish to allow use of your version of this file only under the terms of * the GPL and not to allow others to use your version of this file under the * MPL, indicate your decision by deleting the provisions above and replacing * them with the notice and other provisions required by the GPL. If you do * not delete the provisions above, a recipient may use your version of this * file under either the MPL or the GPL. * * ***** END LICENSE BLOCK ***** */ package org.mozilla.javascript.optimizer; import org.mozilla.javascript.*; public final class OptRuntime extends ScriptRuntime { public static final Double zeroObj = new Double(0.0); public static final Double oneObj = new Double(1.0); public static final Double minusOneObj = new Double(-1.0); /** * Implement ....() call shrinking optimizer code. */ public static Object call0(Callable fun, Scriptable thisObj, Context cx, Scriptable scope) { return fun.call(cx, scope, thisObj, ScriptRuntime.emptyArgs); } /** * Implement ....(arg) call shrinking optimizer code. */ public static Object call1(Callable fun, Scriptable thisObj, Object arg0, Context cx, Scriptable scope) { return fun.call(cx, scope, thisObj, new Object[] { arg0 } ); } /** * Implement ....(arg0, arg1) call shrinking optimizer code. */ public static Object call2(Callable fun, Scriptable thisObj, Object arg0, Object arg1, Context cx, Scriptable scope) { return fun.call(cx, scope, thisObj, new Object[] { arg0, arg1 }); } /** * Implement ....(arg0, arg1, ...) call shrinking optimizer code. */ public static Object callN(Callable fun, Scriptable thisObj, Object[] args, Context cx, Scriptable scope) { return fun.call(cx, scope, thisObj, args); } /** * Implement name(args) call shrinking optimizer code. */ public static Object callName(Object[] args, String name, Context cx, Scriptable scope) { Callable f = getNameFunctionAndThis(name, cx, scope); Scriptable thisObj = lastStoredScriptable(cx); return f.call(cx, scope, thisObj, args); } /** * Implement name() call shrinking optimizer code. */ public static Object callName0(String name, Context cx, Scriptable scope) { Callable f = getNameFunctionAndThis(name, cx, scope); Scriptable thisObj = lastStoredScriptable(cx); return f.call(cx, scope, thisObj, ScriptRuntime.emptyArgs); } /** * Implement x.property() call shrinking optimizer code. */ public static Object callProp0(Object value, String property, Context cx, Scriptable scope) { Callable f = getPropFunctionAndThis(value, property, cx, scope); Scriptable thisObj = lastStoredScriptable(cx); return f.call(cx, scope, thisObj, ScriptRuntime.emptyArgs); } public static Object add(Object val1, double val2) { if (val1 instanceof Scriptable) val1 = ((Scriptable) val1).getDefaultValue(null); if (!(val1 instanceof String)) return wrapDouble(toNumber(val1) + val2); return ((String)val1).concat(toString(val2)); } public static Object add(double val1, Object val2) { if (val2 instanceof Scriptable) val2 = ((Scriptable) val2).getDefaultValue(null); if (!(val2 instanceof String)) return wrapDouble(toNumber(val2) + val1); return toString(val1).concat((String)val2); } public static Object elemIncrDecr(Object obj, double index, Context cx, int incrDecrMask) { return ScriptRuntime.elemIncrDecr(obj, new Double(index), cx, incrDecrMask); } public static Object[] padStart(Object[] currentArgs, int count) { Object[] result = new Object[currentArgs.length + count]; System.arraycopy(currentArgs, 0, result, count, currentArgs.length); return result; } public static void initFunction(NativeFunction fn, int functionType, Scriptable scope, Context cx) { ScriptRuntime.initFunction(cx, scope, fn, functionType, false); } public static Object callSpecial(Context cx, Callable fun, Scriptable thisObj, Object[] args, Scriptable scope, Scriptable callerThis, int callType, String fileName, int lineNumber) { return ScriptRuntime.callSpecial(cx, fun, thisObj, args, scope, callerThis, callType, fileName, lineNumber); } public static Object newObjectSpecial(Context cx, Object fun, Object[] args, Scriptable scope, Scriptable callerThis, int callType) { return ScriptRuntime.newSpecial(cx, fun, args, scope, callType); } public static Double wrapDouble(double num) { if (num == 0.0) { if (1 / num > 0) { // +0.0 return zeroObj; } } else if (num == 1.0) { return oneObj; } else if (num == -1.0) { return minusOneObj; } else if (num != num) { return NaNobj; } return new Double(num); } static String encodeIntArray(int[] array) { // XXX: this extremely inefficient for small integers if (array == null) { return null; } int n = array.length; char[] buffer = new char[1 + n * 2]; buffer[0] = 1; for (int i = 0; i != n; ++i) { int value = array[i]; int shift = 1 + i * 2; buffer[shift] = (char)(value >>> 16); buffer[shift + 1] = (char)value; } return new String(buffer); } private static int[] decodeIntArray(String str, int arraySize) { // XXX: this extremely inefficient for small integers if (arraySize == 0) { if (str != null) throw new IllegalArgumentException(); return null; } if (str.length() != 1 + arraySize * 2 && str.charAt(0) != 1) { throw new IllegalArgumentException(); } int[] array = new int[arraySize]; for (int i = 0; i != arraySize; ++i) { int shift = 1 + i * 2; array[i] = (str.charAt(shift) << 16) | str.charAt(shift + 1); } return array; } public static Scriptable newArrayLiteral(Object[] objects, String encodedInts, int skipCount, Context cx, Scriptable scope) { int[] skipIndexces = decodeIntArray(encodedInts, skipCount); return newArrayLiteral(objects, skipIndexces, cx, scope); } public static void main(final Script script, final String[] args) { ContextFactory.getGlobal().call(new ContextAction() { public Object run(Context cx) { ScriptableObject global = getGlobal(cx); // get the command line arguments and define "arguments" // array in the top-level object Object[] argsCopy = new Object[args.length]; System.arraycopy(args, 0, argsCopy, 0, args.length); Scriptable argsObj = cx.newArray(global, argsCopy); global.defineProperty("arguments", argsObj, ScriptableObject.DONTENUM); script.exec(cx, global); return null; } }); } public static void throwStopIteration(Object obj) { throw new JavaScriptException( NativeIterator.getStopIterationObject((Scriptable)obj), "", 0); } public static Scriptable createNativeGenerator(NativeFunction funObj, Scriptable scope, Scriptable thisObj, int maxLocals, int maxStack) { return new NativeGenerator(scope, funObj, new GeneratorState(thisObj, maxLocals, maxStack)); } public static Object[] getGeneratorStackState(Object obj) { GeneratorState rgs = (GeneratorState) obj; if (rgs.stackState == null) rgs.stackState = new Object[rgs.maxStack]; return rgs.stackState; } public static Object[] getGeneratorLocalsState(Object obj) { GeneratorState rgs = (GeneratorState) obj; if (rgs.localsState == null) rgs.localsState = new Object[rgs.maxLocals]; return rgs.localsState; } public static class GeneratorState { static final String CLASS_NAME = "org/mozilla/javascript/optimizer/OptRuntime$GeneratorState"; public int resumptionPoint; static final String resumptionPoint_NAME = "resumptionPoint"; static final String resumptionPoint_TYPE = "I"; public Scriptable thisObj; static final String thisObj_NAME = "thisObj"; static final String thisObj_TYPE = "Lorg/mozilla/javascript/Scriptable;"; Object[] stackState; Object[] localsState; int maxLocals; int maxStack; GeneratorState(Scriptable thisObj, int maxLocals, int maxStack) { this.thisObj = thisObj; this.maxLocals = maxLocals; this.maxStack = maxStack; } } } htmlunit-core-js-2.8/rhino/src/org/mozilla/javascript/optimizer/Optimizer.java0000644000175000017500000005127511321335670027603 0ustar cavedoncavedon/* ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is Rhino code, released * May 6, 1999. * * The Initial Developer of the Original Code is * Netscape Communications Corporation. * Portions created by the Initial Developer are Copyright (C) 1997-1999 * the Initial Developer. All Rights Reserved. * * Contributor(s): * Norris Boyd * Roger Lawrence * * Alternatively, the contents of this file may be used under the terms of * the GNU General Public License Version 2 or later (the "GPL"), in which * case the provisions of the GPL are applicable instead of those above. If * you wish to allow use of your version of this file only under the terms of * the GPL and not to allow others to use your version of this file under the * MPL, indicate your decision by deleting the provisions above and replacing * them with the notice and other provisions required by the GPL. If you do * not delete the provisions above, a recipient may use your version of this * file under either the MPL or the GPL. * * ***** END LICENSE BLOCK ***** */ package org.mozilla.javascript.optimizer; import org.mozilla.javascript.*; import org.mozilla.javascript.ast.ScriptNode; class Optimizer { static final int NoType = 0; static final int NumberType = 1; static final int AnyType = 3; // It is assumed that (NumberType | AnyType) == AnyType void optimize(ScriptNode scriptOrFn) { // run on one function at a time for now int functionCount = scriptOrFn.getFunctionCount(); for (int i = 0; i != functionCount; ++i) { OptFunctionNode f = OptFunctionNode.get(scriptOrFn, i); optimizeFunction(f); } } private void optimizeFunction(OptFunctionNode theFunction) { if (theFunction.fnode.requiresActivation()) return; inDirectCallFunction = theFunction.isTargetOfDirectCall(); this.theFunction = theFunction; ObjArray statementsArray = new ObjArray(); buildStatementList_r(theFunction.fnode, statementsArray); Node[] theStatementNodes = new Node[statementsArray.size()]; statementsArray.toArray(theStatementNodes); Block.runFlowAnalyzes(theFunction, theStatementNodes); if (!theFunction.fnode.requiresActivation()) { /* * Now that we know which local vars are in fact always * Numbers, we re-write the tree to take advantage of * that. Any arithmetic or assignment op involving just * Number typed vars is marked so that the codegen will * generate non-object code. */ parameterUsedInNumberContext = false; for (int i = 0; i < theStatementNodes.length; i++) { rewriteForNumberVariables(theStatementNodes[i], NumberType); } theFunction.setParameterNumberContext(parameterUsedInNumberContext); } } /* Each directCall parameter is passed as a pair of values - an object and a double. The value passed depends on the type of value available at the call site. If a double is available, the object in java/lang/Void.TYPE is passed as the object value, and if an object value is available, then 0.0 is passed as the double value. The receiving routine always tests the object value before proceeding. If the parameter is being accessed in a 'Number Context' then the code sequence is : if ("parameter_objectValue" == java/lang/Void.TYPE) ...fine..., use the parameter_doubleValue else toNumber(parameter_objectValue) and if the parameter is being referenced in an Object context, the code is if ("parameter_objectValue" == java/lang/Void.TYPE) new Double(parameter_doubleValue) else ...fine..., use the parameter_objectValue If the receiving code never uses the doubleValue, it is converted on entry to a Double instead. */ /* We're referencing a node in a Number context (i.e. we'd prefer it was a double value). If the node is a parameter in a directCall function, mark it as being referenced in this context. */ private void markDCPNumberContext(Node n) { if (inDirectCallFunction && n.getType() == Token.GETVAR) { int varIndex = theFunction.getVarIndex(n); if (theFunction.isParameter(varIndex)) { parameterUsedInNumberContext = true; } } } private boolean convertParameter(Node n) { if (inDirectCallFunction && n.getType() == Token.GETVAR) { int varIndex = theFunction.getVarIndex(n); if (theFunction.isParameter(varIndex)) { n.removeProp(Node.ISNUMBER_PROP); return true; } } return false; } private int rewriteForNumberVariables(Node n, int desired) { switch (n.getType()) { case Token.EXPR_VOID : { Node child = n.getFirstChild(); int type = rewriteForNumberVariables(child, NumberType); if (type == NumberType) n.putIntProp(Node.ISNUMBER_PROP, Node.BOTH); return NoType; } case Token.NUMBER : n.putIntProp(Node.ISNUMBER_PROP, Node.BOTH); return NumberType; case Token.GETVAR : { int varIndex = theFunction.getVarIndex(n); if (inDirectCallFunction && theFunction.isParameter(varIndex) && desired == NumberType) { n.putIntProp(Node.ISNUMBER_PROP, Node.BOTH); return NumberType; } else if (theFunction.isNumberVar(varIndex)) { n.putIntProp(Node.ISNUMBER_PROP, Node.BOTH); return NumberType; } return NoType; } case Token.INC : case Token.DEC : { Node child = n.getFirstChild(); // "child" will be GETVAR or GETPROP or GETELEM if (child.getType() == Token.GETVAR) { if (rewriteForNumberVariables(child, NumberType) == NumberType && !convertParameter(child)) { n.putIntProp(Node.ISNUMBER_PROP, Node.BOTH); markDCPNumberContext(child); return NumberType; } return NoType; } else if (child.getType() == Token.GETELEM) { return rewriteForNumberVariables(child, NumberType); } return NoType; } case Token.SETVAR : { Node lChild = n.getFirstChild(); Node rChild = lChild.getNext(); int rType = rewriteForNumberVariables(rChild, NumberType); int varIndex = theFunction.getVarIndex(n); if (inDirectCallFunction && theFunction.isParameter(varIndex)) { if (rType == NumberType) { if (!convertParameter(rChild)) { n.putIntProp(Node.ISNUMBER_PROP, Node.BOTH); return NumberType; } markDCPNumberContext(rChild); return NoType; } else return rType; } else if (theFunction.isNumberVar(varIndex)) { if (rType != NumberType) { n.removeChild(rChild); n.addChildToBack( new Node(Token.TO_DOUBLE, rChild)); } n.putIntProp(Node.ISNUMBER_PROP, Node.BOTH); markDCPNumberContext(rChild); return NumberType; } else { if (rType == NumberType) { if (!convertParameter(rChild)) { n.removeChild(rChild); n.addChildToBack( new Node(Token.TO_OBJECT, rChild)); } } return NoType; } } case Token.LE : case Token.LT : case Token.GE : case Token.GT : { Node lChild = n.getFirstChild(); Node rChild = lChild.getNext(); int lType = rewriteForNumberVariables(lChild, NumberType); int rType = rewriteForNumberVariables(rChild, NumberType); markDCPNumberContext(lChild); markDCPNumberContext(rChild); if (convertParameter(lChild)) { if (convertParameter(rChild)) { return NoType; } else if (rType == NumberType) { n.putIntProp(Node.ISNUMBER_PROP, Node.RIGHT); } } else if (convertParameter(rChild)) { if (lType == NumberType) { n.putIntProp(Node.ISNUMBER_PROP, Node.LEFT); } } else { if (lType == NumberType) { if (rType == NumberType) { n.putIntProp(Node.ISNUMBER_PROP, Node.BOTH); } else { n.putIntProp(Node.ISNUMBER_PROP, Node.LEFT); } } else { if (rType == NumberType) { n.putIntProp(Node.ISNUMBER_PROP, Node.RIGHT); } } } // we actually build a boolean value return NoType; } case Token.ADD : { Node lChild = n.getFirstChild(); Node rChild = lChild.getNext(); int lType = rewriteForNumberVariables(lChild, NumberType); int rType = rewriteForNumberVariables(rChild, NumberType); if (convertParameter(lChild)) { if (convertParameter(rChild)) { return NoType; } else { if (rType == NumberType) { n.putIntProp(Node.ISNUMBER_PROP, Node.RIGHT); } } } else { if (convertParameter(rChild)) { if (lType == NumberType) { n.putIntProp(Node.ISNUMBER_PROP, Node.LEFT); } } else { if (lType == NumberType) { if (rType == NumberType) { n.putIntProp(Node.ISNUMBER_PROP, Node.BOTH); return NumberType; } else { n.putIntProp(Node.ISNUMBER_PROP, Node.LEFT); } } else { if (rType == NumberType) { n.putIntProp(Node.ISNUMBER_PROP, Node.RIGHT); } } } } return NoType; } case Token.BITXOR : case Token.BITOR : case Token.BITAND : case Token.RSH : case Token.LSH : case Token.SUB : case Token.MUL : case Token.DIV : case Token.MOD : { Node lChild = n.getFirstChild(); Node rChild = lChild.getNext(); int lType = rewriteForNumberVariables(lChild, NumberType); int rType = rewriteForNumberVariables(rChild, NumberType); markDCPNumberContext(lChild); markDCPNumberContext(rChild); if (lType == NumberType) { if (rType == NumberType) { n.putIntProp(Node.ISNUMBER_PROP, Node.BOTH); return NumberType; } else { if (!convertParameter(rChild)) { n.removeChild(rChild); n.addChildToBack( new Node(Token.TO_DOUBLE, rChild)); n.putIntProp(Node.ISNUMBER_PROP, Node.BOTH); } return NumberType; } } else { if (rType == NumberType) { if (!convertParameter(lChild)) { n.removeChild(lChild); n.addChildToFront( new Node(Token.TO_DOUBLE, lChild)); n.putIntProp(Node.ISNUMBER_PROP, Node.BOTH); } return NumberType; } else { if (!convertParameter(lChild)) { n.removeChild(lChild); n.addChildToFront( new Node(Token.TO_DOUBLE, lChild)); } if (!convertParameter(rChild)) { n.removeChild(rChild); n.addChildToBack( new Node(Token.TO_DOUBLE, rChild)); } n.putIntProp(Node.ISNUMBER_PROP, Node.BOTH); return NumberType; } } } case Token.SETELEM : case Token.SETELEM_OP : { Node arrayBase = n.getFirstChild(); Node arrayIndex = arrayBase.getNext(); Node rValue = arrayIndex.getNext(); int baseType = rewriteForNumberVariables(arrayBase, NumberType); if (baseType == NumberType) {// can never happen ??? if (!convertParameter(arrayBase)) { n.removeChild(arrayBase); n.addChildToFront( new Node(Token.TO_OBJECT, arrayBase)); } } int indexType = rewriteForNumberVariables(arrayIndex, NumberType); if (indexType == NumberType) { if (!convertParameter(arrayIndex)) { // setting the ISNUMBER_PROP signals the codegen // to use the OptRuntime.setObjectIndex that takes // a double index n.putIntProp(Node.ISNUMBER_PROP, Node.LEFT); } } int rValueType = rewriteForNumberVariables(rValue, NumberType); if (rValueType == NumberType) { if (!convertParameter(rValue)) { n.removeChild(rValue); n.addChildToBack( new Node(Token.TO_OBJECT, rValue)); } } return NoType; } case Token.GETELEM : { Node arrayBase = n.getFirstChild(); Node arrayIndex = arrayBase.getNext(); int baseType = rewriteForNumberVariables(arrayBase, NumberType); if (baseType == NumberType) {// can never happen ??? if (!convertParameter(arrayBase)) { n.removeChild(arrayBase); n.addChildToFront( new Node(Token.TO_OBJECT, arrayBase)); } } int indexType = rewriteForNumberVariables(arrayIndex, NumberType); if (indexType == NumberType) { if (!convertParameter(arrayIndex)) { // setting the ISNUMBER_PROP signals the codegen // to use the OptRuntime.getObjectIndex that takes // a double index n.putIntProp(Node.ISNUMBER_PROP, Node.RIGHT); } } return NoType; } case Token.CALL : { Node child = n.getFirstChild(); // the function node // must be an object rewriteAsObjectChildren(child, child.getFirstChild()); child = child.getNext(); // the first arg OptFunctionNode target = (OptFunctionNode)n.getProp(Node.DIRECTCALL_PROP); if (target != null) { /* we leave each child as a Number if it can be. The codegen will handle moving the pairs of parameters. */ while (child != null) { int type = rewriteForNumberVariables(child, NumberType); if (type == NumberType) { markDCPNumberContext(child); } child = child.getNext(); } } else { rewriteAsObjectChildren(n, child); } return NoType; } default : { rewriteAsObjectChildren(n, n.getFirstChild()); return NoType; } } } private void rewriteAsObjectChildren(Node n, Node child) { // Force optimized children to be objects while (child != null) { Node nextChild = child.getNext(); int type = rewriteForNumberVariables(child, NoType); if (type == NumberType) { if (!convertParameter(child)) { n.removeChild(child); Node nuChild = new Node(Token.TO_OBJECT, child); if (nextChild == null) n.addChildToBack(nuChild); else n.addChildBefore(nuChild, nextChild); } } child = nextChild; } } private static void buildStatementList_r(Node node, ObjArray statements) { int type = node.getType(); if (type == Token.BLOCK || type == Token.LOCAL_BLOCK || type == Token.LOOP || type == Token.FUNCTION) { Node child = node.getFirstChild(); while (child != null) { buildStatementList_r(child, statements); child = child.getNext(); } } else { statements.add(node); } } private boolean inDirectCallFunction; OptFunctionNode theFunction; private boolean parameterUsedInNumberContext; } htmlunit-core-js-2.8/rhino/src/org/mozilla/javascript/optimizer/OptTransformer.java0000644000175000017500000001156511222455466030612 0ustar cavedoncavedon/* ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is Rhino code, released * May 6, 1999. * * The Initial Developer of the Original Code is * Netscape Communications Corporation. * Portions created by the Initial Developer are Copyright (C) 1997-1999 * the Initial Developer. All Rights Reserved. * * Contributor(s): * Norris Boyd * Roger Lawrence * * Alternatively, the contents of this file may be used under the terms of * the GNU General Public License Version 2 or later (the "GPL"), in which * case the provisions of the GPL are applicable instead of those above. If * you wish to allow use of your version of this file only under the terms of * the GPL and not to allow others to use your version of this file under the * MPL, indicate your decision by deleting the provisions above and replacing * them with the notice and other provisions required by the GPL. If you do * not delete the provisions above, a recipient may use your version of this * file under either the MPL or the GPL. * * ***** END LICENSE BLOCK ***** */ package org.mozilla.javascript.optimizer; import org.mozilla.javascript.*; import org.mozilla.javascript.ast.ScriptNode; import java.util.Map; /** * This class performs node transforms to prepare for optimization. * * @see NodeTransformer * @author Norris Boyd */ class OptTransformer extends NodeTransformer { OptTransformer(Map possibleDirectCalls, ObjArray directCallTargets) { this.possibleDirectCalls = possibleDirectCalls; this.directCallTargets = directCallTargets; } @Override protected void visitNew(Node node, ScriptNode tree) { detectDirectCall(node, tree); super.visitNew(node, tree); } @Override protected void visitCall(Node node, ScriptNode tree) { detectDirectCall(node, tree); super.visitCall(node, tree); } private void detectDirectCall(Node node, ScriptNode tree) { if (tree.getType() == Token.FUNCTION) { Node left = node.getFirstChild(); // count the arguments int argCount = 0; Node arg = left.getNext(); while (arg != null) { arg = arg.getNext(); argCount++; } if (argCount == 0) { OptFunctionNode.get(tree).itsContainsCalls0 = true; } /* * Optimize a call site by converting call("a", b, c) into : * * FunctionObjectFor"a" <-- instance variable init'd by constructor * * // this is a DIRECTCALL node * fn = GetProp(tmp = GetBase("a"), "a"); * if (fn == FunctionObjectFor"a") * fn.call(tmp, b, c) * else * ScriptRuntime.Call(fn, tmp, b, c) */ if (possibleDirectCalls != null) { String targetName = null; if (left.getType() == Token.NAME) { targetName = left.getString(); } else if (left.getType() == Token.GETPROP) { targetName = left.getFirstChild().getNext().getString(); } else if (left.getType() == Token.GETPROPNOWARN) { throw Kit.codeBug(); } if (targetName != null) { OptFunctionNode ofn; ofn = possibleDirectCalls.get(targetName); if (ofn != null && argCount == ofn.fnode.getParamCount() && !ofn.fnode.requiresActivation()) { // Refuse to directCall any function with more // than 32 parameters - prevent code explosion // for wacky test cases if (argCount <= 32) { node.putProp(Node.DIRECTCALL_PROP, ofn); if (!ofn.isTargetOfDirectCall()) { int index = directCallTargets.size(); directCallTargets.add(ofn); ofn.setDirectTargetIndex(index); } } } } } } } private Map possibleDirectCalls; private ObjArray directCallTargets; } htmlunit-core-js-2.8/rhino/src/org/mozilla/javascript/optimizer/ClassCompiler.java0000644000175000017500000001727411222455466030370 0ustar cavedoncavedon/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- * * ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is Rhino code, released * May 6, 1999. * * The Initial Developer of the Original Code is * Netscape Communications Corporation. * Portions created by the Initial Developer are Copyright (C) 1997-2000 * the Initial Developer. All Rights Reserved. * * Contributor(s): * Igor Bukanov * * Alternatively, the contents of this file may be used under the terms of * the GNU General Public License Version 2 or later (the "GPL"), in which * case the provisions of the GPL are applicable instead of those above. If * you wish to allow use of your version of this file only under the terms of * the GPL and not to allow others to use your version of this file under the * MPL, indicate your decision by deleting the provisions above and replacing * them with the notice and other provisions required by the GPL. If you do * not delete the provisions above, a recipient may use your version of this * file under either the MPL or the GPL. * * ***** END LICENSE BLOCK ***** */ package org.mozilla.javascript.optimizer; import org.mozilla.javascript.*; import org.mozilla.javascript.ast.AstRoot; import org.mozilla.javascript.ast.FunctionNode; import org.mozilla.javascript.ast.ScriptNode; /** * Generates class files from script sources. * * since 1.5 Release 5 * @author Igor Bukanov */ public class ClassCompiler { /** * Construct ClassCompiler that uses the specified compiler environment * when generating classes. */ public ClassCompiler(CompilerEnvirons compilerEnv) { if (compilerEnv == null) throw new IllegalArgumentException(); this.compilerEnv = compilerEnv; this.mainMethodClassName = Codegen.DEFAULT_MAIN_METHOD_CLASS; } /** * Set the class name to use for main method implementation. * The class must have a method matching * public static void main(Script sc, String[] args), it will be * called when main(String[] args) is called in the generated * class. The class name should be fully qulified name and include the * package name like in org.foo.Bar. */ public void setMainMethodClass(String className) { // XXX Should this check for a valid class name? mainMethodClassName = className; } /** * Get the name of the class for main method implementation. * @see #setMainMethodClass(String) */ public String getMainMethodClass() { return mainMethodClassName; } /** * Get the compiler environment the compiler uses. */ public CompilerEnvirons getCompilerEnv() { return compilerEnv; } /** * Get the class that the generated target will extend. */ public Class getTargetExtends() { return targetExtends; } /** * Set the class that the generated target will extend. * * @param extendsClass the class it extends */ public void setTargetExtends(Class extendsClass) { targetExtends = extendsClass; } /** * Get the interfaces that the generated target will implement. */ public Class[] getTargetImplements() { return targetImplements == null ? null : (Class[])targetImplements.clone(); } /** * Set the interfaces that the generated target will implement. * * @param implementsClasses an array of Class objects, one for each * interface the target will extend */ public void setTargetImplements(Class[] implementsClasses) { targetImplements = implementsClasses == null ? null : (Class[])implementsClasses.clone(); } /** * Build class name for a auxiliary class generated by compiler. * If the compiler needs to generate extra classes beyond the main class, * it will call this function to build the auxiliary class name. * The default implementation simply appends auxMarker to mainClassName * but this can be overridden. */ protected String makeAuxiliaryClassName(String mainClassName, String auxMarker) { return mainClassName+auxMarker; } /** * Compile JavaScript source into one or more Java class files. * The first compiled class will have name mainClassName. * If the results of {@link #getTargetExtends()} or * {@link #getTargetImplements()} are not null, then the first compiled * class will extend the specified super class and implement * specified interfaces. * * @return array where elements with even indexes specifies class name * and the following odd index gives class file body as byte[] * array. The initial element of the array always holds * mainClassName and array[1] holds its byte code. */ public Object[] compileToClassFiles(String source, String sourceLocation, int lineno, String mainClassName) { Parser p = new Parser(compilerEnv); AstRoot ast = p.parse(source, sourceLocation, lineno); IRFactory irf = new IRFactory(compilerEnv); ScriptNode tree = irf.transformTree(ast); // release reference to original parse tree & parser irf = null; ast = null; p = null; Class superClass = getTargetExtends(); Class[] interfaces = getTargetImplements(); String scriptClassName; boolean isPrimary = (interfaces == null && superClass == null); if (isPrimary) { scriptClassName = mainClassName; } else { scriptClassName = makeAuxiliaryClassName(mainClassName, "1"); } Codegen codegen = new Codegen(); codegen.setMainMethodClass(mainMethodClassName); byte[] scriptClassBytes = codegen.compileToClassFile(compilerEnv, scriptClassName, tree, tree.getEncodedSource(), false); if (isPrimary) { return new Object[] { scriptClassName, scriptClassBytes }; } int functionCount = tree.getFunctionCount(); ObjToIntMap functionNames = new ObjToIntMap(functionCount); for (int i = 0; i != functionCount; ++i) { FunctionNode ofn = tree.getFunctionNode(i); String name = ofn.getName(); if (name != null && name.length() != 0) { functionNames.put(name, ofn.getParamCount()); } } if (superClass == null) { superClass = ScriptRuntime.ObjectClass; } byte[] mainClassBytes = JavaAdapter.createAdapterCode( functionNames, mainClassName, superClass, interfaces, scriptClassName); return new Object[] { mainClassName, mainClassBytes, scriptClassName, scriptClassBytes }; } private String mainMethodClassName; private CompilerEnvirons compilerEnv; private Class targetExtends; private Class[] targetImplements; } htmlunit-core-js-2.8/rhino/src/org/mozilla/javascript/optimizer/Codegen.java0000644000175000017500000057277011321335670027175 0ustar cavedoncavedon/* ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is Rhino code, released * May 6, 1999. * * The Initial Developer of the Original Code is * Netscape Communications Corporation. * Portions created by the Initial Developer are Copyright (C) 1997-2000 * the Initial Developer. All Rights Reserved. * * Contributor(s): * Norris Boyd * Kemal Bayram * Igor Bukanov * Bob Jervis * Roger Lawrence * Andi Vajda * Hannes Wallnoefer * * Alternatively, the contents of this file may be used under the terms of * the GNU General Public License Version 2 or later (the "GPL"), in which * case the provisions of the GPL are applicable instead of those above. If * you wish to allow use of your version of this file only under the terms of * the GPL and not to allow others to use your version of this file under the * MPL, indicate your decision by deleting the provisions above and replacing * them with the notice and other provisions required by the GPL. If you do * not delete the provisions above, a recipient may use your version of this * file under either the MPL or the GPL. * * ***** END LICENSE BLOCK ***** */ package org.mozilla.javascript.optimizer; import org.mozilla.javascript.*; import org.mozilla.javascript.ast.FunctionNode; import org.mozilla.javascript.ast.Jump; import org.mozilla.javascript.ast.Name; import org.mozilla.javascript.ast.ScriptNode; import org.mozilla.classfile.*; import java.util.*; import java.lang.reflect.Constructor; /** * This class generates code for a given IR tree. * * @author Norris Boyd * @author Roger Lawrence */ public class Codegen implements Evaluator { public void captureStackInfo(RhinoException ex) { throw new UnsupportedOperationException(); } public String getSourcePositionFromStack(Context cx, int[] linep) { throw new UnsupportedOperationException(); } public String getPatchedStack(RhinoException ex, String nativeStackTrace) { throw new UnsupportedOperationException(); } public List getScriptStack(RhinoException ex) { throw new UnsupportedOperationException(); } public void setEvalScriptFlag(Script script) { throw new UnsupportedOperationException(); } public Object compile(CompilerEnvirons compilerEnv, ScriptNode tree, String encodedSource, boolean returnFunction) { int serial; synchronized (globalLock) { serial = ++globalSerialClassCounter; } String baseName = "c"; if (tree.getSourceName().length() > 0) { baseName = tree.getSourceName().replaceAll("\\W", "_"); if (!Character.isJavaIdentifierStart(baseName.charAt(0))) { baseName = "_" + baseName; } } String mainClassName = "org.mozilla.javascript.gen." + baseName + "_" + serial; byte[] mainClassBytes = compileToClassFile(compilerEnv, mainClassName, tree, encodedSource, returnFunction); return new Object[] { mainClassName, mainClassBytes }; } public Script createScriptObject(Object bytecode, Object staticSecurityDomain) { Class cl = defineClass(bytecode, staticSecurityDomain); Script script; try { script = (Script)cl.newInstance(); } catch (Exception ex) { throw new RuntimeException ("Unable to instantiate compiled class:"+ex.toString()); } return script; } public Function createFunctionObject(Context cx, Scriptable scope, Object bytecode, Object staticSecurityDomain) { Class cl = defineClass(bytecode, staticSecurityDomain); NativeFunction f; try { Constructorctor = cl.getConstructors()[0]; Object[] initArgs = { scope, cx, Integer.valueOf(0) }; f = (NativeFunction)ctor.newInstance(initArgs); } catch (Exception ex) { throw new RuntimeException ("Unable to instantiate compiled class:"+ex.toString()); } return f; } private Class defineClass(Object bytecode, Object staticSecurityDomain) { Object[] nameBytesPair = (Object[])bytecode; String className = (String)nameBytesPair[0]; byte[] classBytes = (byte[])nameBytesPair[1]; // The generated classes in this case refer only to Rhino classes // which must be accessible through this class loader ClassLoader rhinoLoader = getClass().getClassLoader(); GeneratedClassLoader loader; loader = SecurityController.createLoader(rhinoLoader, staticSecurityDomain); Exception e; try { Class cl = loader.defineClass(className, classBytes); loader.linkClass(cl); return cl; } catch (SecurityException x) { e = x; } catch (IllegalArgumentException x) { e = x; } throw new RuntimeException("Malformed optimizer package " + e); } byte[] compileToClassFile(CompilerEnvirons compilerEnv, String mainClassName, ScriptNode scriptOrFn, String encodedSource, boolean returnFunction) { this.compilerEnv = compilerEnv; transform(scriptOrFn); if (Token.printTrees) { System.out.println(scriptOrFn.toStringTree(scriptOrFn)); } if (returnFunction) { scriptOrFn = scriptOrFn.getFunctionNode(0); } initScriptNodesData(scriptOrFn); this.mainClassName = mainClassName; this.mainClassSignature = ClassFileWriter.classNameToSignature(mainClassName); try { return generateCode(encodedSource); } catch (ClassFileWriter.ClassFileFormatException e) { throw reportClassFileFormatException(scriptOrFn, e.getMessage()); } } private RuntimeException reportClassFileFormatException( ScriptNode scriptOrFn, String message) { String msg = scriptOrFn instanceof FunctionNode ? ScriptRuntime.getMessage2("msg.while.compiling.fn", ((FunctionNode)scriptOrFn).getFunctionName(), message) : ScriptRuntime.getMessage1("msg.while.compiling.script", message); return Context.reportRuntimeError(msg, scriptOrFn.getSourceName(), scriptOrFn.getLineno(), null, 0); } private void transform(ScriptNode tree) { initOptFunctions_r(tree); int optLevel = compilerEnv.getOptimizationLevel(); Map possibleDirectCalls = null; if (optLevel > 0) { /* * Collect all of the contained functions into a hashtable * so that the call optimizer can access the class name & parameter * count for any call it encounters */ if (tree.getType() == Token.SCRIPT) { int functionCount = tree.getFunctionCount(); for (int i = 0; i != functionCount; ++i) { OptFunctionNode ofn = OptFunctionNode.get(tree, i); if (ofn.fnode.getFunctionType() == FunctionNode.FUNCTION_STATEMENT) { String name = ofn.fnode.getName(); if (name.length() != 0) { if (possibleDirectCalls == null) { possibleDirectCalls = new HashMap(); } possibleDirectCalls.put(name, ofn); } } } } } if (possibleDirectCalls != null) { directCallTargets = new ObjArray(); } OptTransformer ot = new OptTransformer(possibleDirectCalls, directCallTargets); ot.transform(tree); if (optLevel > 0) { (new Optimizer()).optimize(tree); } } private static void initOptFunctions_r(ScriptNode scriptOrFn) { for (int i = 0, N = scriptOrFn.getFunctionCount(); i != N; ++i) { FunctionNode fn = scriptOrFn.getFunctionNode(i); new OptFunctionNode(fn); initOptFunctions_r(fn); } } private void initScriptNodesData(ScriptNode scriptOrFn) { ObjArray x = new ObjArray(); collectScriptNodes_r(scriptOrFn, x); int count = x.size(); scriptOrFnNodes = new ScriptNode[count]; x.toArray(scriptOrFnNodes); scriptOrFnIndexes = new ObjToIntMap(count); for (int i = 0; i != count; ++i) { scriptOrFnIndexes.put(scriptOrFnNodes[i], i); } } private static void collectScriptNodes_r(ScriptNode n, ObjArray x) { x.add(n); int nestedCount = n.getFunctionCount(); for (int i = 0; i != nestedCount; ++i) { collectScriptNodes_r(n.getFunctionNode(i), x); } } private byte[] generateCode(String encodedSource) { boolean hasScript = (scriptOrFnNodes[0].getType() == Token.SCRIPT); boolean hasFunctions = (scriptOrFnNodes.length > 1 || !hasScript); String sourceFile = null; if (compilerEnv.isGenerateDebugInfo()) { sourceFile = scriptOrFnNodes[0].getSourceName(); } ClassFileWriter cfw = new ClassFileWriter(mainClassName, SUPER_CLASS_NAME, sourceFile); cfw.addField(ID_FIELD_NAME, "I", ClassFileWriter.ACC_PRIVATE); cfw.addField(DIRECT_CALL_PARENT_FIELD, mainClassSignature, ClassFileWriter.ACC_PRIVATE); cfw.addField(REGEXP_ARRAY_FIELD_NAME, REGEXP_ARRAY_FIELD_TYPE, ClassFileWriter.ACC_PRIVATE); if (hasFunctions) { generateFunctionConstructor(cfw); } if (hasScript) { cfw.addInterface("org/mozilla/javascript/Script"); generateScriptCtor(cfw); generateMain(cfw); generateExecute(cfw); } generateCallMethod(cfw); generateResumeGenerator(cfw); generateNativeFunctionOverrides(cfw, encodedSource); int count = scriptOrFnNodes.length; for (int i = 0; i != count; ++i) { ScriptNode n = scriptOrFnNodes[i]; BodyCodegen bodygen = new BodyCodegen(); bodygen.cfw = cfw; bodygen.codegen = this; bodygen.compilerEnv = compilerEnv; bodygen.scriptOrFn = n; bodygen.scriptOrFnIndex = i; try { bodygen.generateBodyCode(); } catch (ClassFileWriter.ClassFileFormatException e) { throw reportClassFileFormatException(n, e.getMessage()); } if (n.getType() == Token.FUNCTION) { OptFunctionNode ofn = OptFunctionNode.get(n); generateFunctionInit(cfw, ofn); if (ofn.isTargetOfDirectCall()) { emitDirectConstructor(cfw, ofn); } } } if (directCallTargets != null) { int N = directCallTargets.size(); for (int j = 0; j != N; ++j) { cfw.addField(getDirectTargetFieldName(j), mainClassSignature, ClassFileWriter.ACC_PRIVATE); } } emitRegExpInit(cfw); emitConstantDudeInitializers(cfw); return cfw.toByteArray(); } private void emitDirectConstructor(ClassFileWriter cfw, OptFunctionNode ofn) { /* we generate .. Scriptable directConstruct() { Scriptable newInstance = createObject(cx, scope); Object val = (cx, scope, newInstance, ); if (val instanceof Scriptable) { return (Scriptable) val; } return newInstance; } */ cfw.startMethod(getDirectCtorName(ofn.fnode), getBodyMethodSignature(ofn.fnode), (short)(ClassFileWriter.ACC_STATIC | ClassFileWriter.ACC_PRIVATE)); int argCount = ofn.fnode.getParamCount(); int firstLocal = (4 + argCount * 3) + 1; cfw.addALoad(0); // this cfw.addALoad(1); // cx cfw.addALoad(2); // scope cfw.addInvoke(ByteCode.INVOKEVIRTUAL, "org/mozilla/javascript/BaseFunction", "createObject", "(Lorg/mozilla/javascript/Context;" +"Lorg/mozilla/javascript/Scriptable;" +")Lorg/mozilla/javascript/Scriptable;"); cfw.addAStore(firstLocal); cfw.addALoad(0); cfw.addALoad(1); cfw.addALoad(2); cfw.addALoad(firstLocal); for (int i = 0; i < argCount; i++) { cfw.addALoad(4 + (i * 3)); cfw.addDLoad(5 + (i * 3)); } cfw.addALoad(4 + argCount * 3); cfw.addInvoke(ByteCode.INVOKESTATIC, mainClassName, getBodyMethodName(ofn.fnode), getBodyMethodSignature(ofn.fnode)); int exitLabel = cfw.acquireLabel(); cfw.add(ByteCode.DUP); // make a copy of direct call result cfw.add(ByteCode.INSTANCEOF, "org/mozilla/javascript/Scriptable"); cfw.add(ByteCode.IFEQ, exitLabel); // cast direct call result cfw.add(ByteCode.CHECKCAST, "org/mozilla/javascript/Scriptable"); cfw.add(ByteCode.ARETURN); cfw.markLabel(exitLabel); cfw.addALoad(firstLocal); cfw.add(ByteCode.ARETURN); cfw.stopMethod((short)(firstLocal + 1)); } static boolean isGenerator(ScriptNode node) { return (node.getType() == Token.FUNCTION ) && ((FunctionNode)node).isGenerator(); } // How dispatch to generators works: // Two methods are generated corresponding to a user-written generator. // One of these creates a generator object (NativeGenerator), which is // returned to the user. The other method contains all of the body code // of the generator. // When a user calls a generator, the call() method dispatches control to // to the method that creates the NativeGenerator object. Subsequently when // the user invokes .next(), .send() or any such method on the generator // object, the resumeGenerator() below dispatches the call to the // method corresponding to the generator body. As a matter of convention // the generator body is given the name of the generator activation function // appended by "_gen". private void generateResumeGenerator(ClassFileWriter cfw) { boolean hasGenerators = false; for (int i=0; i < scriptOrFnNodes.length; i++) { if (isGenerator(scriptOrFnNodes[i])) hasGenerators = true; } // if there are no generators defined, we don't implement a // resumeGenerator(). The base class provides a default implementation. if (!hasGenerators) return; cfw.startMethod("resumeGenerator", "(Lorg/mozilla/javascript/Context;" + "Lorg/mozilla/javascript/Scriptable;" + "ILjava/lang/Object;" + "Ljava/lang/Object;)Ljava/lang/Object;", (short)(ClassFileWriter.ACC_PUBLIC | ClassFileWriter.ACC_FINAL)); // load arguments for dispatch to the corresponding *_gen method cfw.addALoad(0); cfw.addALoad(1); cfw.addALoad(2); cfw.addALoad(4); cfw.addALoad(5); cfw.addILoad(3); cfw.addLoadThis(); cfw.add(ByteCode.GETFIELD, cfw.getClassName(), ID_FIELD_NAME, "I"); int startSwitch = cfw.addTableSwitch(0, scriptOrFnNodes.length - 1); cfw.markTableSwitchDefault(startSwitch); int endlabel = cfw.acquireLabel(); for (int i = 0; i < scriptOrFnNodes.length; i++) { ScriptNode n = scriptOrFnNodes[i]; cfw.markTableSwitchCase(startSwitch, i, (short)6); if (isGenerator(n)) { String type = "(" + mainClassSignature + "Lorg/mozilla/javascript/Context;" + "Lorg/mozilla/javascript/Scriptable;" + "Ljava/lang/Object;" + "Ljava/lang/Object;I)Ljava/lang/Object;"; cfw.addInvoke(ByteCode.INVOKESTATIC, mainClassName, getBodyMethodName(n) + "_gen", type); cfw.add(ByteCode.ARETURN); } else { cfw.add(ByteCode.GOTO, endlabel); } } cfw.markLabel(endlabel); pushUndefined(cfw); cfw.add(ByteCode.ARETURN); // this method uses as many locals as there are arguments (hence 6) cfw.stopMethod((short)6); } private void generateCallMethod(ClassFileWriter cfw) { cfw.startMethod("call", "(Lorg/mozilla/javascript/Context;" + "Lorg/mozilla/javascript/Scriptable;" + "Lorg/mozilla/javascript/Scriptable;" + "[Ljava/lang/Object;)Ljava/lang/Object;", (short)(ClassFileWriter.ACC_PUBLIC | ClassFileWriter.ACC_FINAL)); // Generate code for: // if (!ScriptRuntime.hasTopCall(cx)) { // return ScriptRuntime.doTopCall(this, cx, scope, thisObj, args); // } int nonTopCallLabel = cfw.acquireLabel(); cfw.addALoad(1); //cx cfw.addInvoke(ByteCode.INVOKESTATIC, "org/mozilla/javascript/ScriptRuntime", "hasTopCall", "(Lorg/mozilla/javascript/Context;" +")Z"); cfw.add(ByteCode.IFNE, nonTopCallLabel); cfw.addALoad(0); cfw.addALoad(1); cfw.addALoad(2); cfw.addALoad(3); cfw.addALoad(4); cfw.addInvoke(ByteCode.INVOKESTATIC, "org/mozilla/javascript/ScriptRuntime", "doTopCall", "(Lorg/mozilla/javascript/Callable;" +"Lorg/mozilla/javascript/Context;" +"Lorg/mozilla/javascript/Scriptable;" +"Lorg/mozilla/javascript/Scriptable;" +"[Ljava/lang/Object;" +")Ljava/lang/Object;"); cfw.add(ByteCode.ARETURN); cfw.markLabel(nonTopCallLabel); // Now generate switch to call the real methods cfw.addALoad(0); cfw.addALoad(1); cfw.addALoad(2); cfw.addALoad(3); cfw.addALoad(4); int end = scriptOrFnNodes.length; boolean generateSwitch = (2 <= end); int switchStart = 0; int switchStackTop = 0; if (generateSwitch) { cfw.addLoadThis(); cfw.add(ByteCode.GETFIELD, cfw.getClassName(), ID_FIELD_NAME, "I"); // do switch from (1, end - 1) mapping 0 to // the default case switchStart = cfw.addTableSwitch(1, end - 1); } for (int i = 0; i != end; ++i) { ScriptNode n = scriptOrFnNodes[i]; if (generateSwitch) { if (i == 0) { cfw.markTableSwitchDefault(switchStart); switchStackTop = cfw.getStackTop(); } else { cfw.markTableSwitchCase(switchStart, i - 1, switchStackTop); } } if (n.getType() == Token.FUNCTION) { OptFunctionNode ofn = OptFunctionNode.get(n); if (ofn.isTargetOfDirectCall()) { int pcount = ofn.fnode.getParamCount(); if (pcount != 0) { // loop invariant: // stack top == arguments array from addALoad4() for (int p = 0; p != pcount; ++p) { cfw.add(ByteCode.ARRAYLENGTH); cfw.addPush(p); int undefArg = cfw.acquireLabel(); int beyond = cfw.acquireLabel(); cfw.add(ByteCode.IF_ICMPLE, undefArg); // get array[p] cfw.addALoad(4); cfw.addPush(p); cfw.add(ByteCode.AALOAD); cfw.add(ByteCode.GOTO, beyond); cfw.markLabel(undefArg); pushUndefined(cfw); cfw.markLabel(beyond); // Only one push cfw.adjustStackTop(-1); cfw.addPush(0.0); // restore invariant cfw.addALoad(4); } } } } cfw.addInvoke(ByteCode.INVOKESTATIC, mainClassName, getBodyMethodName(n), getBodyMethodSignature(n)); cfw.add(ByteCode.ARETURN); } cfw.stopMethod((short)5); // 5: this, cx, scope, js this, args[] } private void generateMain(ClassFileWriter cfw) { cfw.startMethod("main", "([Ljava/lang/String;)V", (short)(ClassFileWriter.ACC_PUBLIC | ClassFileWriter.ACC_STATIC)); // load new ScriptImpl() cfw.add(ByteCode.NEW, cfw.getClassName()); cfw.add(ByteCode.DUP); cfw.addInvoke(ByteCode.INVOKESPECIAL, cfw.getClassName(), "", "()V"); // load 'args' cfw.add(ByteCode.ALOAD_0); // Call mainMethodClass.main(Script script, String[] args) cfw.addInvoke(ByteCode.INVOKESTATIC, mainMethodClass, "main", "(Lorg/mozilla/javascript/Script;[Ljava/lang/String;)V"); cfw.add(ByteCode.RETURN); // 1 = String[] args cfw.stopMethod((short)1); } private void generateExecute(ClassFileWriter cfw) { cfw.startMethod("exec", "(Lorg/mozilla/javascript/Context;" +"Lorg/mozilla/javascript/Scriptable;" +")Ljava/lang/Object;", (short)(ClassFileWriter.ACC_PUBLIC | ClassFileWriter.ACC_FINAL)); final int CONTEXT_ARG = 1; final int SCOPE_ARG = 2; cfw.addLoadThis(); cfw.addALoad(CONTEXT_ARG); cfw.addALoad(SCOPE_ARG); cfw.add(ByteCode.DUP); cfw.add(ByteCode.ACONST_NULL); cfw.addInvoke(ByteCode.INVOKEVIRTUAL, cfw.getClassName(), "call", "(Lorg/mozilla/javascript/Context;" +"Lorg/mozilla/javascript/Scriptable;" +"Lorg/mozilla/javascript/Scriptable;" +"[Ljava/lang/Object;" +")Ljava/lang/Object;"); cfw.add(ByteCode.ARETURN); // 3 = this + context + scope cfw.stopMethod((short)3); } private void generateScriptCtor(ClassFileWriter cfw) { cfw.startMethod("", "()V", ClassFileWriter.ACC_PUBLIC); cfw.addLoadThis(); cfw.addInvoke(ByteCode.INVOKESPECIAL, SUPER_CLASS_NAME, "", "()V"); // set id to 0 cfw.addLoadThis(); cfw.addPush(0); cfw.add(ByteCode.PUTFIELD, cfw.getClassName(), ID_FIELD_NAME, "I"); cfw.add(ByteCode.RETURN); // 1 parameter = this cfw.stopMethod((short)1); } private void generateFunctionConstructor(ClassFileWriter cfw) { final int SCOPE_ARG = 1; final int CONTEXT_ARG = 2; final int ID_ARG = 3; cfw.startMethod("", FUNCTION_CONSTRUCTOR_SIGNATURE, ClassFileWriter.ACC_PUBLIC); cfw.addALoad(0); cfw.addInvoke(ByteCode.INVOKESPECIAL, SUPER_CLASS_NAME, "", "()V"); cfw.addLoadThis(); cfw.addILoad(ID_ARG); cfw.add(ByteCode.PUTFIELD, cfw.getClassName(), ID_FIELD_NAME, "I"); cfw.addLoadThis(); cfw.addALoad(CONTEXT_ARG); cfw.addALoad(SCOPE_ARG); int start = (scriptOrFnNodes[0].getType() == Token.SCRIPT) ? 1 : 0; int end = scriptOrFnNodes.length; if (start == end) throw badTree(); boolean generateSwitch = (2 <= end - start); int switchStart = 0; int switchStackTop = 0; if (generateSwitch) { cfw.addILoad(ID_ARG); // do switch from (start + 1, end - 1) mapping start to // the default case switchStart = cfw.addTableSwitch(start + 1, end - 1); } for (int i = start; i != end; ++i) { if (generateSwitch) { if (i == start) { cfw.markTableSwitchDefault(switchStart); switchStackTop = cfw.getStackTop(); } else { cfw.markTableSwitchCase(switchStart, i - 1 - start, switchStackTop); } } OptFunctionNode ofn = OptFunctionNode.get(scriptOrFnNodes[i]); cfw.addInvoke(ByteCode.INVOKEVIRTUAL, mainClassName, getFunctionInitMethodName(ofn), FUNCTION_INIT_SIGNATURE); cfw.add(ByteCode.RETURN); } // 4 = this + scope + context + id cfw.stopMethod((short)4); } private void generateFunctionInit(ClassFileWriter cfw, OptFunctionNode ofn) { final int CONTEXT_ARG = 1; final int SCOPE_ARG = 2; cfw.startMethod(getFunctionInitMethodName(ofn), FUNCTION_INIT_SIGNATURE, (short)(ClassFileWriter.ACC_PRIVATE | ClassFileWriter.ACC_FINAL)); // Call NativeFunction.initScriptFunction cfw.addLoadThis(); cfw.addALoad(CONTEXT_ARG); cfw.addALoad(SCOPE_ARG); cfw.addInvoke(ByteCode.INVOKEVIRTUAL, "org/mozilla/javascript/NativeFunction", "initScriptFunction", "(Lorg/mozilla/javascript/Context;" +"Lorg/mozilla/javascript/Scriptable;" +")V"); // precompile all regexp literals int regexpCount = ofn.fnode.getRegexpCount(); if (regexpCount != 0) { cfw.addLoadThis(); pushRegExpArray(cfw, ofn.fnode, CONTEXT_ARG, SCOPE_ARG); cfw.add(ByteCode.PUTFIELD, mainClassName, REGEXP_ARRAY_FIELD_NAME, REGEXP_ARRAY_FIELD_TYPE); } cfw.add(ByteCode.RETURN); // 3 = (scriptThis/functionRef) + scope + context cfw.stopMethod((short)3); } private void generateNativeFunctionOverrides(ClassFileWriter cfw, String encodedSource) { // Override NativeFunction.getLanguageVersion() with // public int getLanguageVersion() { return ; } cfw.startMethod("getLanguageVersion", "()I", ClassFileWriter.ACC_PUBLIC); cfw.addPush(compilerEnv.getLanguageVersion()); cfw.add(ByteCode.IRETURN); // 1: this and no argument or locals cfw.stopMethod((short)1); // The rest of NativeFunction overrides require specific code for each // script/function id final int Do_getFunctionName = 0; final int Do_getParamCount = 1; final int Do_getParamAndVarCount = 2; final int Do_getParamOrVarName = 3; final int Do_getEncodedSource = 4; final int Do_getParamOrVarConst = 5; final int SWITCH_COUNT = 6; for (int methodIndex = 0; methodIndex != SWITCH_COUNT; ++methodIndex) { if (methodIndex == Do_getEncodedSource && encodedSource == null) { continue; } // Generate: // prologue; // switch over function id to implement function-specific action // epilogue short methodLocals; switch (methodIndex) { case Do_getFunctionName: methodLocals = 1; // Only this cfw.startMethod("getFunctionName", "()Ljava/lang/String;", ClassFileWriter.ACC_PUBLIC); break; case Do_getParamCount: methodLocals = 1; // Only this cfw.startMethod("getParamCount", "()I", ClassFileWriter.ACC_PUBLIC); break; case Do_getParamAndVarCount: methodLocals = 1; // Only this cfw.startMethod("getParamAndVarCount", "()I", ClassFileWriter.ACC_PUBLIC); break; case Do_getParamOrVarName: methodLocals = 1 + 1; // this + paramOrVarIndex cfw.startMethod("getParamOrVarName", "(I)Ljava/lang/String;", ClassFileWriter.ACC_PUBLIC); break; case Do_getParamOrVarConst: methodLocals = 1 + 1 + 1; // this + paramOrVarName cfw.startMethod("getParamOrVarConst", "(I)Z", ClassFileWriter.ACC_PUBLIC); break; case Do_getEncodedSource: methodLocals = 1; // Only this cfw.startMethod("getEncodedSource", "()Ljava/lang/String;", ClassFileWriter.ACC_PUBLIC); cfw.addPush(encodedSource); break; default: throw Kit.codeBug(); } int count = scriptOrFnNodes.length; int switchStart = 0; int switchStackTop = 0; if (count > 1) { // Generate switch but only if there is more then one // script/function cfw.addLoadThis(); cfw.add(ByteCode.GETFIELD, cfw.getClassName(), ID_FIELD_NAME, "I"); // do switch from 1 .. count - 1 mapping 0 to the default case switchStart = cfw.addTableSwitch(1, count - 1); } for (int i = 0; i != count; ++i) { ScriptNode n = scriptOrFnNodes[i]; if (i == 0) { if (count > 1) { cfw.markTableSwitchDefault(switchStart); switchStackTop = cfw.getStackTop(); } } else { cfw.markTableSwitchCase(switchStart, i - 1, switchStackTop); } // Impelemnet method-specific switch code switch (methodIndex) { case Do_getFunctionName: // Push function name if (n.getType() == Token.SCRIPT) { cfw.addPush(""); } else { String name = ((FunctionNode)n).getName(); cfw.addPush(name); } cfw.add(ByteCode.ARETURN); break; case Do_getParamCount: // Push number of defined parameters cfw.addPush(n.getParamCount()); cfw.add(ByteCode.IRETURN); break; case Do_getParamAndVarCount: // Push number of defined parameters and declared variables cfw.addPush(n.getParamAndVarCount()); cfw.add(ByteCode.IRETURN); break; case Do_getParamOrVarName: // Push name of parameter using another switch // over paramAndVarCount int paramAndVarCount = n.getParamAndVarCount(); if (paramAndVarCount == 0) { // The runtime should never call the method in this // case but to make bytecode verifier happy return null // as throwing execption takes more code cfw.add(ByteCode.ACONST_NULL); cfw.add(ByteCode.ARETURN); } else if (paramAndVarCount == 1) { // As above do not check for valid index but always // return the name of the first param cfw.addPush(n.getParamOrVarName(0)); cfw.add(ByteCode.ARETURN); } else { // Do switch over getParamOrVarName cfw.addILoad(1); // param or var index // do switch from 1 .. paramAndVarCount - 1 mapping 0 // to the default case int paramSwitchStart = cfw.addTableSwitch( 1, paramAndVarCount - 1); for (int j = 0; j != paramAndVarCount; ++j) { if (cfw.getStackTop() != 0) Kit.codeBug(); String s = n.getParamOrVarName(j); if (j == 0) { cfw.markTableSwitchDefault(paramSwitchStart); } else { cfw.markTableSwitchCase(paramSwitchStart, j - 1, 0); } cfw.addPush(s); cfw.add(ByteCode.ARETURN); } } break; case Do_getParamOrVarConst: // Push name of parameter using another switch // over paramAndVarCount paramAndVarCount = n.getParamAndVarCount(); boolean [] constness = n.getParamAndVarConst(); if (paramAndVarCount == 0) { // The runtime should never call the method in this // case but to make bytecode verifier happy return null // as throwing execption takes more code cfw.add(ByteCode.ICONST_0); cfw.add(ByteCode.IRETURN); } else if (paramAndVarCount == 1) { // As above do not check for valid index but always // return the name of the first param cfw.addPush(constness[0]); cfw.add(ByteCode.IRETURN); } else { // Do switch over getParamOrVarName cfw.addILoad(1); // param or var index // do switch from 1 .. paramAndVarCount - 1 mapping 0 // to the default case int paramSwitchStart = cfw.addTableSwitch( 1, paramAndVarCount - 1); for (int j = 0; j != paramAndVarCount; ++j) { if (cfw.getStackTop() != 0) Kit.codeBug(); if (j == 0) { cfw.markTableSwitchDefault(paramSwitchStart); } else { cfw.markTableSwitchCase(paramSwitchStart, j - 1, 0); } cfw.addPush(constness[j]); cfw.add(ByteCode.IRETURN); } } break; case Do_getEncodedSource: // Push number encoded source start and end // to prepare for encodedSource.substring(start, end) cfw.addPush(n.getEncodedSourceStart()); cfw.addPush(n.getEncodedSourceEnd()); cfw.addInvoke(ByteCode.INVOKEVIRTUAL, "java/lang/String", "substring", "(II)Ljava/lang/String;"); cfw.add(ByteCode.ARETURN); break; default: throw Kit.codeBug(); } } cfw.stopMethod(methodLocals); } } private void emitRegExpInit(ClassFileWriter cfw) { // precompile all regexp literals int totalRegCount = 0; for (int i = 0; i != scriptOrFnNodes.length; ++i) { totalRegCount += scriptOrFnNodes[i].getRegexpCount(); } if (totalRegCount == 0) { return; } cfw.startMethod(REGEXP_INIT_METHOD_NAME, REGEXP_INIT_METHOD_SIGNATURE, (short)(ClassFileWriter.ACC_STATIC | ClassFileWriter.ACC_PRIVATE | ClassFileWriter.ACC_SYNCHRONIZED)); cfw.addField("_reInitDone", "Z", (short)(ClassFileWriter.ACC_STATIC | ClassFileWriter.ACC_PRIVATE)); cfw.add(ByteCode.GETSTATIC, mainClassName, "_reInitDone", "Z"); int doInit = cfw.acquireLabel(); cfw.add(ByteCode.IFEQ, doInit); cfw.add(ByteCode.RETURN); cfw.markLabel(doInit); for (int i = 0; i != scriptOrFnNodes.length; ++i) { ScriptNode n = scriptOrFnNodes[i]; int regCount = n.getRegexpCount(); for (int j = 0; j != regCount; ++j) { String reFieldName = getCompiledRegexpName(n, j); String reFieldType = "Ljava/lang/Object;"; String reString = n.getRegexpString(j); String reFlags = n.getRegexpFlags(j); cfw.addField(reFieldName, reFieldType, (short)(ClassFileWriter.ACC_STATIC | ClassFileWriter.ACC_PRIVATE)); cfw.addALoad(0); // proxy cfw.addALoad(1); // context cfw.addPush(reString); if (reFlags == null) { cfw.add(ByteCode.ACONST_NULL); } else { cfw.addPush(reFlags); } cfw.addInvoke(ByteCode.INVOKEINTERFACE, "org/mozilla/javascript/RegExpProxy", "compileRegExp", "(Lorg/mozilla/javascript/Context;" +"Ljava/lang/String;Ljava/lang/String;" +")Ljava/lang/Object;"); cfw.add(ByteCode.PUTSTATIC, mainClassName, reFieldName, reFieldType); } } cfw.addPush(1); cfw.add(ByteCode.PUTSTATIC, mainClassName, "_reInitDone", "Z"); cfw.add(ByteCode.RETURN); cfw.stopMethod((short)2); } private void emitConstantDudeInitializers(ClassFileWriter cfw) { int N = itsConstantListSize; if (N == 0) return; cfw.startMethod("", "()V", (short)(ClassFileWriter.ACC_STATIC | ClassFileWriter.ACC_FINAL)); double[] array = itsConstantList; for (int i = 0; i != N; ++i) { double num = array[i]; String constantName = "_k" + i; String constantType = getStaticConstantWrapperType(num); cfw.addField(constantName, constantType, (short)(ClassFileWriter.ACC_STATIC | ClassFileWriter.ACC_PRIVATE)); int inum = (int)num; if (inum == num) { cfw.add(ByteCode.NEW, "java/lang/Integer"); cfw.add(ByteCode.DUP); cfw.addPush(inum); cfw.addInvoke(ByteCode.INVOKESPECIAL, "java/lang/Integer", "", "(I)V"); } else { cfw.addPush(num); addDoubleWrap(cfw); } cfw.add(ByteCode.PUTSTATIC, mainClassName, constantName, constantType); } cfw.add(ByteCode.RETURN); cfw.stopMethod((short)0); } void pushRegExpArray(ClassFileWriter cfw, ScriptNode n, int contextArg, int scopeArg) { int regexpCount = n.getRegexpCount(); if (regexpCount == 0) throw badTree(); cfw.addPush(regexpCount); cfw.add(ByteCode.ANEWARRAY, "java/lang/Object"); cfw.addALoad(contextArg); cfw.addInvoke(ByteCode.INVOKESTATIC, "org/mozilla/javascript/ScriptRuntime", "checkRegExpProxy", "(Lorg/mozilla/javascript/Context;" +")Lorg/mozilla/javascript/RegExpProxy;"); // Stack: proxy, array cfw.add(ByteCode.DUP); cfw.addALoad(contextArg); cfw.addInvoke(ByteCode.INVOKESTATIC, mainClassName, REGEXP_INIT_METHOD_NAME, REGEXP_INIT_METHOD_SIGNATURE); for (int i = 0; i != regexpCount; ++i) { // Stack: proxy, array cfw.add(ByteCode.DUP2); cfw.addALoad(contextArg); cfw.addALoad(scopeArg); cfw.add(ByteCode.GETSTATIC, mainClassName, getCompiledRegexpName(n, i), "Ljava/lang/Object;"); // Stack: compiledRegExp, scope, cx, proxy, array, proxy, array cfw.addInvoke(ByteCode.INVOKEINTERFACE, "org/mozilla/javascript/RegExpProxy", "wrapRegExp", "(Lorg/mozilla/javascript/Context;" +"Lorg/mozilla/javascript/Scriptable;" +"Ljava/lang/Object;" +")Lorg/mozilla/javascript/Scriptable;"); // Stack: wrappedRegExp, array, proxy, array cfw.addPush(i); cfw.add(ByteCode.SWAP); cfw.add(ByteCode.AASTORE); // Stack: proxy, array } // remove proxy cfw.add(ByteCode.POP); } void pushNumberAsObject(ClassFileWriter cfw, double num) { if (num == 0.0) { if (1 / num > 0) { // +0.0 cfw.add(ByteCode.GETSTATIC, "org/mozilla/javascript/optimizer/OptRuntime", "zeroObj", "Ljava/lang/Double;"); } else { cfw.addPush(num); addDoubleWrap(cfw); } } else if (num == 1.0) { cfw.add(ByteCode.GETSTATIC, "org/mozilla/javascript/optimizer/OptRuntime", "oneObj", "Ljava/lang/Double;"); return; } else if (num == -1.0) { cfw.add(ByteCode.GETSTATIC, "org/mozilla/javascript/optimizer/OptRuntime", "minusOneObj", "Ljava/lang/Double;"); } else if (num != num) { cfw.add(ByteCode.GETSTATIC, "org/mozilla/javascript/ScriptRuntime", "NaNobj", "Ljava/lang/Double;"); } else if (itsConstantListSize >= 2000) { // There appears to be a limit in the JVM on either the number // of static fields in a class or the size of the class // initializer. Either way, we can't have any more than 2000 // statically init'd constants. cfw.addPush(num); addDoubleWrap(cfw); } else { int N = itsConstantListSize; int index = 0; if (N == 0) { itsConstantList = new double[64]; } else { double[] array = itsConstantList; while (index != N && array[index] != num) { ++index; } if (N == array.length) { array = new double[N * 2]; System.arraycopy(itsConstantList, 0, array, 0, N); itsConstantList = array; } } if (index == N) { itsConstantList[N] = num; itsConstantListSize = N + 1; } String constantName = "_k" + index; String constantType = getStaticConstantWrapperType(num); cfw.add(ByteCode.GETSTATIC, mainClassName, constantName, constantType); } } private static void addDoubleWrap(ClassFileWriter cfw) { cfw.addInvoke(ByteCode.INVOKESTATIC, "org/mozilla/javascript/optimizer/OptRuntime", "wrapDouble", "(D)Ljava/lang/Double;"); } private static String getStaticConstantWrapperType(double num) { int inum = (int)num; if (inum == num) { return "Ljava/lang/Integer;"; } else { return "Ljava/lang/Double;"; } } static void pushUndefined(ClassFileWriter cfw) { cfw.add(ByteCode.GETSTATIC, "org/mozilla/javascript/Undefined", "instance", "Ljava/lang/Object;"); } int getIndex(ScriptNode n) { return scriptOrFnIndexes.getExisting(n); } static String getDirectTargetFieldName(int i) { return "_dt" + i; } String getDirectCtorName(ScriptNode n) { return "_n" + getIndex(n); } String getBodyMethodName(ScriptNode n) { return "_c_" + cleanName(n) + "_" + getIndex(n); } /** * Gets a Java-compatible "informative" name for the the ScriptOrFnNode */ String cleanName(final ScriptNode n) { String result = ""; if (n instanceof FunctionNode) { Name name = ((FunctionNode) n).getFunctionName(); if (name == null) { result = "anonymous"; } else { result = name.getIdentifier(); } } else { result = "script"; } return result; } String getBodyMethodSignature(ScriptNode n) { StringBuffer sb = new StringBuffer(); sb.append('('); sb.append(mainClassSignature); sb.append("Lorg/mozilla/javascript/Context;" +"Lorg/mozilla/javascript/Scriptable;" +"Lorg/mozilla/javascript/Scriptable;"); if (n.getType() == Token.FUNCTION) { OptFunctionNode ofn = OptFunctionNode.get(n); if (ofn.isTargetOfDirectCall()) { int pCount = ofn.fnode.getParamCount(); for (int i = 0; i != pCount; i++) { sb.append("Ljava/lang/Object;D"); } } } sb.append("[Ljava/lang/Object;)Ljava/lang/Object;"); return sb.toString(); } String getFunctionInitMethodName(OptFunctionNode ofn) { return "_i"+getIndex(ofn.fnode); } String getCompiledRegexpName(ScriptNode n, int regexpIndex) { return "_re"+getIndex(n)+"_"+regexpIndex; } static RuntimeException badTree() { throw new RuntimeException("Bad tree in codegen"); } void setMainMethodClass(String className) { mainMethodClass = className; } static final String DEFAULT_MAIN_METHOD_CLASS = "org.mozilla.javascript.optimizer.OptRuntime"; private static final String SUPER_CLASS_NAME = "org.mozilla.javascript.NativeFunction"; static final String DIRECT_CALL_PARENT_FIELD = "_dcp"; private static final String ID_FIELD_NAME = "_id"; private static final String REGEXP_INIT_METHOD_NAME = "_reInit"; private static final String REGEXP_INIT_METHOD_SIGNATURE = "(Lorg/mozilla/javascript/RegExpProxy;" +"Lorg/mozilla/javascript/Context;" +")V"; static final String REGEXP_ARRAY_FIELD_NAME = "_re"; static final String REGEXP_ARRAY_FIELD_TYPE = "[Ljava/lang/Object;"; static final String FUNCTION_INIT_SIGNATURE = "(Lorg/mozilla/javascript/Context;" +"Lorg/mozilla/javascript/Scriptable;" +")V"; static final String FUNCTION_CONSTRUCTOR_SIGNATURE = "(Lorg/mozilla/javascript/Scriptable;" +"Lorg/mozilla/javascript/Context;I)V"; private static final Object globalLock = new Object(); private static int globalSerialClassCounter; private CompilerEnvirons compilerEnv; private ObjArray directCallTargets; ScriptNode[] scriptOrFnNodes; private ObjToIntMap scriptOrFnIndexes; private String mainMethodClass = DEFAULT_MAIN_METHOD_CLASS; String mainClassName; String mainClassSignature; private double[] itsConstantList; private int itsConstantListSize; } class BodyCodegen { void generateBodyCode() { isGenerator = Codegen.isGenerator(scriptOrFn); // generate the body of the current function or script object initBodyGeneration(); if (isGenerator) { // All functions in the generated bytecode have a unique name. Every // generator has a unique prefix followed by _gen String type = "(" + codegen.mainClassSignature + "Lorg/mozilla/javascript/Context;" + "Lorg/mozilla/javascript/Scriptable;" + "Ljava/lang/Object;" + "Ljava/lang/Object;I)Ljava/lang/Object;"; cfw.startMethod(codegen.getBodyMethodName(scriptOrFn) + "_gen", type, (short)(ClassFileWriter.ACC_STATIC | ClassFileWriter.ACC_PRIVATE)); } else { cfw.startMethod(codegen.getBodyMethodName(scriptOrFn), codegen.getBodyMethodSignature(scriptOrFn), (short)(ClassFileWriter.ACC_STATIC | ClassFileWriter.ACC_PRIVATE)); } generatePrologue(); Node treeTop; if (fnCurrent != null) { treeTop = scriptOrFn.getLastChild(); } else { treeTop = scriptOrFn; } generateStatement(treeTop); generateEpilogue(); cfw.stopMethod((short)(localsMax + 1)); if (isGenerator) { // generate the user visible method which when invoked will // return a generator object generateGenerator(); } } // This creates a the user-facing function that returns a NativeGenerator // object. private void generateGenerator() { cfw.startMethod(codegen.getBodyMethodName(scriptOrFn), codegen.getBodyMethodSignature(scriptOrFn), (short)(ClassFileWriter.ACC_STATIC | ClassFileWriter.ACC_PRIVATE)); initBodyGeneration(); argsLocal = firstFreeLocal++; localsMax = firstFreeLocal; // get top level scope if (fnCurrent != null && !inDirectCallFunction && (!compilerEnv.isUseDynamicScope() || fnCurrent.fnode.getIgnoreDynamicScope())) { // Unless we're either in a direct call or using dynamic scope, // use the enclosing scope of the function as our variable object. cfw.addALoad(funObjLocal); cfw.addInvoke(ByteCode.INVOKEINTERFACE, "org/mozilla/javascript/Scriptable", "getParentScope", "()Lorg/mozilla/javascript/Scriptable;"); cfw.addAStore(variableObjectLocal); } // generators are forced to have an activation record cfw.addALoad(funObjLocal); cfw.addALoad(variableObjectLocal); cfw.addALoad(argsLocal); addScriptRuntimeInvoke("createFunctionActivation", "(Lorg/mozilla/javascript/NativeFunction;" +"Lorg/mozilla/javascript/Scriptable;" +"[Ljava/lang/Object;" +")Lorg/mozilla/javascript/Scriptable;"); cfw.addAStore(variableObjectLocal); // create a function object cfw.add(ByteCode.NEW, codegen.mainClassName); // Call function constructor cfw.add(ByteCode.DUP); cfw.addALoad(variableObjectLocal); cfw.addALoad(contextLocal); // load 'cx' cfw.addPush(scriptOrFnIndex); cfw.addInvoke(ByteCode.INVOKESPECIAL, codegen.mainClassName, "", Codegen.FUNCTION_CONSTRUCTOR_SIGNATURE); // Init mainScript field cfw.add(ByteCode.DUP); if (isTopLevel) Kit.codeBug(); // Only functions can be generators cfw.add(ByteCode.ALOAD_0); cfw.add(ByteCode.GETFIELD, codegen.mainClassName, Codegen.DIRECT_CALL_PARENT_FIELD, codegen.mainClassSignature); cfw.add(ByteCode.PUTFIELD, codegen.mainClassName, Codegen.DIRECT_CALL_PARENT_FIELD, codegen.mainClassSignature); generateNestedFunctionInits(); // create the NativeGenerator object that we return cfw.addALoad(variableObjectLocal); cfw.addALoad(thisObjLocal); cfw.addLoadConstant(maxLocals); cfw.addLoadConstant(maxStack); addOptRuntimeInvoke("createNativeGenerator", "(Lorg/mozilla/javascript/NativeFunction;" +"Lorg/mozilla/javascript/Scriptable;" +"Lorg/mozilla/javascript/Scriptable;II" +")Lorg/mozilla/javascript/Scriptable;"); cfw.add(ByteCode.ARETURN); cfw.stopMethod((short)(localsMax + 1)); } private void generateNestedFunctionInits() { int functionCount = scriptOrFn.getFunctionCount(); for (int i = 0; i != functionCount; i++) { OptFunctionNode ofn = OptFunctionNode.get(scriptOrFn, i); if (ofn.fnode.getFunctionType() == FunctionNode.FUNCTION_STATEMENT) { visitFunction(ofn, FunctionNode.FUNCTION_STATEMENT); } } } private void initBodyGeneration() { isTopLevel = (scriptOrFn == codegen.scriptOrFnNodes[0]); varRegisters = null; if (scriptOrFn.getType() == Token.FUNCTION) { fnCurrent = OptFunctionNode.get(scriptOrFn); hasVarsInRegs = !fnCurrent.fnode.requiresActivation(); if (hasVarsInRegs) { int n = fnCurrent.fnode.getParamAndVarCount(); if (n != 0) { varRegisters = new short[n]; } } inDirectCallFunction = fnCurrent.isTargetOfDirectCall(); if (inDirectCallFunction && !hasVarsInRegs) Codegen.badTree(); } else { fnCurrent = null; hasVarsInRegs = false; inDirectCallFunction = false; } locals = new int[MAX_LOCALS]; funObjLocal = 0; contextLocal = 1; variableObjectLocal = 2; thisObjLocal = 3; localsMax = (short) 4; // number of parms + "this" firstFreeLocal = 4; popvLocal = -1; argsLocal = -1; itsZeroArgArray = -1; itsOneArgArray = -1; scriptRegexpLocal = -1; epilogueLabel = -1; enterAreaStartLabel = -1; generatorStateLocal = -1; } /** * Generate the prologue for a function or script. */ private void generatePrologue() { if (inDirectCallFunction) { int directParameterCount = scriptOrFn.getParamCount(); // 0 is reserved for function Object 'this' // 1 is reserved for context // 2 is reserved for parentScope // 3 is reserved for script 'this' if (firstFreeLocal != 4) Kit.codeBug(); for (int i = 0; i != directParameterCount; ++i) { varRegisters[i] = firstFreeLocal; // 3 is 1 for Object parm and 2 for double parm firstFreeLocal += 3; } if (!fnCurrent.getParameterNumberContext()) { // make sure that all parameters are objects itsForcedObjectParameters = true; for (int i = 0; i != directParameterCount; ++i) { short reg = varRegisters[i]; cfw.addALoad(reg); cfw.add(ByteCode.GETSTATIC, "java/lang/Void", "TYPE", "Ljava/lang/Class;"); int isObjectLabel = cfw.acquireLabel(); cfw.add(ByteCode.IF_ACMPNE, isObjectLabel); cfw.addDLoad(reg + 1); addDoubleWrap(); cfw.addAStore(reg); cfw.markLabel(isObjectLabel); } } } if (fnCurrent != null && !inDirectCallFunction && (!compilerEnv.isUseDynamicScope() || fnCurrent.fnode.getIgnoreDynamicScope())) { // Unless we're either in a direct call or using dynamic scope, // use the enclosing scope of the function as our variable object. cfw.addALoad(funObjLocal); cfw.addInvoke(ByteCode.INVOKEINTERFACE, "org/mozilla/javascript/Scriptable", "getParentScope", "()Lorg/mozilla/javascript/Scriptable;"); cfw.addAStore(variableObjectLocal); } // reserve 'args[]' argsLocal = firstFreeLocal++; localsMax = firstFreeLocal; // Generate Generator specific prelude if (isGenerator) { // reserve 'args[]' operationLocal = firstFreeLocal++; localsMax = firstFreeLocal; // Local 3 is a reference to a GeneratorState object. The rest // of codegen expects local 3 to be a reference to the thisObj. // So move the value in local 3 to generatorStateLocal, and load // the saved thisObj from the GeneratorState object. cfw.addALoad(thisObjLocal); generatorStateLocal = firstFreeLocal++; localsMax = firstFreeLocal; cfw.add(ByteCode.CHECKCAST, OptRuntime.GeneratorState.CLASS_NAME); cfw.add(ByteCode.DUP); cfw.addAStore(generatorStateLocal); cfw.add(ByteCode.GETFIELD, OptRuntime.GeneratorState.CLASS_NAME, OptRuntime.GeneratorState.thisObj_NAME, OptRuntime.GeneratorState.thisObj_TYPE); cfw.addAStore(thisObjLocal); if (epilogueLabel == -1) { epilogueLabel = cfw.acquireLabel(); } List targets = ((FunctionNode)scriptOrFn).getResumptionPoints(); if (targets != null) { // get resumption point generateGetGeneratorResumptionPoint(); // generate dispatch table generatorSwitch = cfw.addTableSwitch(0, targets.size() + GENERATOR_START); generateCheckForThrowOrClose(-1, false, GENERATOR_START); } } if (fnCurrent == null) { // See comments in case Token.REGEXP if (scriptOrFn.getRegexpCount() != 0) { scriptRegexpLocal = getNewWordLocal(); codegen.pushRegExpArray(cfw, scriptOrFn, contextLocal, variableObjectLocal); cfw.addAStore(scriptRegexpLocal); } } if (compilerEnv.isGenerateObserverCount()) saveCurrentCodeOffset(); if (hasVarsInRegs) { // No need to create activation. Pad arguments if need be. int parmCount = scriptOrFn.getParamCount(); if (parmCount > 0 && !inDirectCallFunction) { // Set up args array // check length of arguments, pad if need be cfw.addALoad(argsLocal); cfw.add(ByteCode.ARRAYLENGTH); cfw.addPush(parmCount); int label = cfw.acquireLabel(); cfw.add(ByteCode.IF_ICMPGE, label); cfw.addALoad(argsLocal); cfw.addPush(parmCount); addScriptRuntimeInvoke("padArguments", "([Ljava/lang/Object;I" +")[Ljava/lang/Object;"); cfw.addAStore(argsLocal); cfw.markLabel(label); } int paramCount = fnCurrent.fnode.getParamCount(); int varCount = fnCurrent.fnode.getParamAndVarCount(); boolean [] constDeclarations = fnCurrent.fnode.getParamAndVarConst(); // REMIND - only need to initialize the vars that don't get a value // before the next call and are used in the function short firstUndefVar = -1; for (int i = 0; i != varCount; ++i) { short reg = -1; if (i < paramCount) { if (!inDirectCallFunction) { reg = getNewWordLocal(); cfw.addALoad(argsLocal); cfw.addPush(i); cfw.add(ByteCode.AALOAD); cfw.addAStore(reg); } } else if (fnCurrent.isNumberVar(i)) { reg = getNewWordPairLocal(constDeclarations[i]); cfw.addPush(0.0); cfw.addDStore(reg); } else { reg = getNewWordLocal(constDeclarations[i]); if (firstUndefVar == -1) { Codegen.pushUndefined(cfw); firstUndefVar = reg; } else { cfw.addALoad(firstUndefVar); } cfw.addAStore(reg); } if (reg >= 0) { if (constDeclarations[i]) { cfw.addPush(0); cfw.addIStore(reg + (fnCurrent.isNumberVar(i) ? 2 : 1)); } varRegisters[i] = reg; } // Add debug table entry if we're generating debug info if (compilerEnv.isGenerateDebugInfo()) { String name = fnCurrent.fnode.getParamOrVarName(i); String type = fnCurrent.isNumberVar(i) ? "D" : "Ljava/lang/Object;"; int startPC = cfw.getCurrentCodeOffset(); if (reg < 0) { reg = varRegisters[i]; } cfw.addVariableDescriptor(name, type, startPC, reg); } } // Skip creating activation object. return; } // skip creating activation object for the body of a generator. The // activation record required by a generator has already been created // in generateGenerator(). if (isGenerator) return; String debugVariableName; if (fnCurrent != null) { debugVariableName = "activation"; cfw.addALoad(funObjLocal); cfw.addALoad(variableObjectLocal); cfw.addALoad(argsLocal); addScriptRuntimeInvoke("createFunctionActivation", "(Lorg/mozilla/javascript/NativeFunction;" +"Lorg/mozilla/javascript/Scriptable;" +"[Ljava/lang/Object;" +")Lorg/mozilla/javascript/Scriptable;"); cfw.addAStore(variableObjectLocal); cfw.addALoad(contextLocal); cfw.addALoad(variableObjectLocal); addScriptRuntimeInvoke("enterActivationFunction", "(Lorg/mozilla/javascript/Context;" +"Lorg/mozilla/javascript/Scriptable;" +")V"); } else { debugVariableName = "global"; cfw.addALoad(funObjLocal); cfw.addALoad(thisObjLocal); cfw.addALoad(contextLocal); cfw.addALoad(variableObjectLocal); cfw.addPush(0); // false to indicate it is not eval script addScriptRuntimeInvoke("initScript", "(Lorg/mozilla/javascript/NativeFunction;" +"Lorg/mozilla/javascript/Scriptable;" +"Lorg/mozilla/javascript/Context;" +"Lorg/mozilla/javascript/Scriptable;" +"Z" +")V"); } enterAreaStartLabel = cfw.acquireLabel(); epilogueLabel = cfw.acquireLabel(); cfw.markLabel(enterAreaStartLabel); generateNestedFunctionInits(); // default is to generate debug info if (compilerEnv.isGenerateDebugInfo()) { cfw.addVariableDescriptor(debugVariableName, "Lorg/mozilla/javascript/Scriptable;", cfw.getCurrentCodeOffset(), variableObjectLocal); } if (fnCurrent == null) { // OPT: use dataflow to prove that this assignment is dead popvLocal = getNewWordLocal(); Codegen.pushUndefined(cfw); cfw.addAStore(popvLocal); int linenum = scriptOrFn.getEndLineno(); if (linenum != -1) cfw.addLineNumberEntry((short)linenum); } else { if (fnCurrent.itsContainsCalls0) { itsZeroArgArray = getNewWordLocal(); cfw.add(ByteCode.GETSTATIC, "org/mozilla/javascript/ScriptRuntime", "emptyArgs", "[Ljava/lang/Object;"); cfw.addAStore(itsZeroArgArray); } if (fnCurrent.itsContainsCalls1) { itsOneArgArray = getNewWordLocal(); cfw.addPush(1); cfw.add(ByteCode.ANEWARRAY, "java/lang/Object"); cfw.addAStore(itsOneArgArray); } } } private void generateGetGeneratorResumptionPoint() { cfw.addALoad(generatorStateLocal); cfw.add(ByteCode.GETFIELD, OptRuntime.GeneratorState.CLASS_NAME, OptRuntime.GeneratorState.resumptionPoint_NAME, OptRuntime.GeneratorState.resumptionPoint_TYPE); } private void generateSetGeneratorResumptionPoint(int nextState) { cfw.addALoad(generatorStateLocal); cfw.addLoadConstant(nextState); cfw.add(ByteCode.PUTFIELD, OptRuntime.GeneratorState.CLASS_NAME, OptRuntime.GeneratorState.resumptionPoint_NAME, OptRuntime.GeneratorState.resumptionPoint_TYPE); } private void generateGetGeneratorStackState() { cfw.addALoad(generatorStateLocal); addOptRuntimeInvoke("getGeneratorStackState", "(Ljava/lang/Object;)[Ljava/lang/Object;"); } private void generateEpilogue() { if (compilerEnv.isGenerateObserverCount()) addInstructionCount(); if (isGenerator) { // generate locals initialization Map liveLocals = ((FunctionNode)scriptOrFn).getLiveLocals(); if (liveLocals != null) { List nodes = ((FunctionNode)scriptOrFn).getResumptionPoints(); for (int i = 0; i < nodes.size(); i++) { Node node = nodes.get(i); int[] live = liveLocals.get(node); if (live != null) { cfw.markTableSwitchCase(generatorSwitch, getNextGeneratorState(node)); generateGetGeneratorLocalsState(); for (int j = 0; j < live.length; j++) { cfw.add(ByteCode.DUP); cfw.addLoadConstant(j); cfw.add(ByteCode.AALOAD); cfw.addAStore(live[j]); } cfw.add(ByteCode.POP); cfw.add(ByteCode.GOTO, getTargetLabel(node)); } } } // generate dispatch tables for finally if (finallys != null) { for (Node n: finallys.keySet()) { if (n.getType() == Token.FINALLY) { FinallyReturnPoint ret = finallys.get(n); // the finally will jump here cfw.markLabel(ret.tableLabel, (short)1); // start generating a dispatch table int startSwitch = cfw.addTableSwitch(0, ret.jsrPoints.size() - 1); int c = 0; cfw.markTableSwitchDefault(startSwitch); for (int i = 0; i < ret.jsrPoints.size(); i++) { // generate gotos back to the JSR location cfw.markTableSwitchCase(startSwitch, c); cfw.add(ByteCode.GOTO, ret.jsrPoints.get(i).intValue()); c++; } } } } } if (epilogueLabel != -1) { cfw.markLabel(epilogueLabel); } if (hasVarsInRegs) { cfw.add(ByteCode.ARETURN); return; } else if (isGenerator) { if (((FunctionNode)scriptOrFn).getResumptionPoints() != null) { cfw.markTableSwitchDefault(generatorSwitch); } // change state for re-entry generateSetGeneratorResumptionPoint(GENERATOR_TERMINATE); // throw StopIteration cfw.addALoad(variableObjectLocal); addOptRuntimeInvoke("throwStopIteration", "(Ljava/lang/Object;)V"); Codegen.pushUndefined(cfw); cfw.add(ByteCode.ARETURN); } else if (fnCurrent == null) { cfw.addALoad(popvLocal); cfw.add(ByteCode.ARETURN); } else { generateActivationExit(); cfw.add(ByteCode.ARETURN); // Generate catch block to catch all and rethrow to call exit code // under exception propagation as well. int finallyHandler = cfw.acquireLabel(); cfw.markHandler(finallyHandler); short exceptionObject = getNewWordLocal(); cfw.addAStore(exceptionObject); // Duplicate generateActivationExit() in the catch block since it // takes less space then full-featured ByteCode.JSR/ByteCode.RET generateActivationExit(); cfw.addALoad(exceptionObject); releaseWordLocal(exceptionObject); // rethrow cfw.add(ByteCode.ATHROW); // mark the handler cfw.addExceptionHandler(enterAreaStartLabel, epilogueLabel, finallyHandler, null); // catch any } } private void generateGetGeneratorLocalsState() { cfw.addALoad(generatorStateLocal); addOptRuntimeInvoke("getGeneratorLocalsState", "(Ljava/lang/Object;)[Ljava/lang/Object;"); } private void generateActivationExit() { if (fnCurrent == null || hasVarsInRegs) throw Kit.codeBug(); cfw.addALoad(contextLocal); addScriptRuntimeInvoke("exitActivationFunction", "(Lorg/mozilla/javascript/Context;)V"); } private void generateStatement(Node node) { updateLineNumber(node); int type = node.getType(); Node child = node.getFirstChild(); switch (type) { case Token.LOOP: case Token.LABEL: case Token.WITH: case Token.SCRIPT: case Token.BLOCK: case Token.EMPTY: // no-ops. if (compilerEnv.isGenerateObserverCount()) { // Need to add instruction count even for no-ops to catch // cases like while (1) {} addInstructionCount(1); } while (child != null) { generateStatement(child); child = child.getNext(); } break; case Token.LOCAL_BLOCK: { int local = getNewWordLocal(); if (isGenerator) { cfw.add(ByteCode.ACONST_NULL); cfw.addAStore(local); } node.putIntProp(Node.LOCAL_PROP, local); while (child != null) { generateStatement(child); child = child.getNext(); } releaseWordLocal((short)local); node.removeProp(Node.LOCAL_PROP); break; } case Token.FUNCTION: { int fnIndex = node.getExistingIntProp(Node.FUNCTION_PROP); OptFunctionNode ofn = OptFunctionNode.get(scriptOrFn, fnIndex); int t = ofn.fnode.getFunctionType(); if (t == FunctionNode.FUNCTION_EXPRESSION_STATEMENT) { visitFunction(ofn, t); } else { if (t != FunctionNode.FUNCTION_STATEMENT) { throw Codegen.badTree(); } } break; } case Token.TRY: visitTryCatchFinally((Jump)node, child); break; case Token.CATCH_SCOPE: { // nothing stays on the stack on entry into a catch scope cfw.setStackTop((short) 0); int local = getLocalBlockRegister(node); int scopeIndex = node.getExistingIntProp(Node.CATCH_SCOPE_PROP); String name = child.getString(); // name of exception child = child.getNext(); generateExpression(child, node); // load expression object if (scopeIndex == 0) { cfw.add(ByteCode.ACONST_NULL); } else { // Load previous catch scope object cfw.addALoad(local); } cfw.addPush(name); cfw.addALoad(contextLocal); cfw.addALoad(variableObjectLocal); addScriptRuntimeInvoke( "newCatchScope", "(Ljava/lang/Throwable;" +"Lorg/mozilla/javascript/Scriptable;" +"Ljava/lang/String;" +"Lorg/mozilla/javascript/Context;" +"Lorg/mozilla/javascript/Scriptable;" +")Lorg/mozilla/javascript/Scriptable;"); cfw.addAStore(local); } break; case Token.THROW: generateExpression(child, node); if (compilerEnv.isGenerateObserverCount()) addInstructionCount(); generateThrowJavaScriptException(); break; case Token.RETHROW: if (compilerEnv.isGenerateObserverCount()) addInstructionCount(); cfw.addALoad(getLocalBlockRegister(node)); cfw.add(ByteCode.ATHROW); break; case Token.RETURN_RESULT: case Token.RETURN: if (!isGenerator) { if (child != null) { generateExpression(child, node); } else if (type == Token.RETURN) { Codegen.pushUndefined(cfw); } else { if (popvLocal < 0) throw Codegen.badTree(); cfw.addALoad(popvLocal); } } if (compilerEnv.isGenerateObserverCount()) addInstructionCount(); if (epilogueLabel == -1) { if (!hasVarsInRegs) throw Codegen.badTree(); epilogueLabel = cfw.acquireLabel(); } cfw.add(ByteCode.GOTO, epilogueLabel); break; case Token.SWITCH: if (compilerEnv.isGenerateObserverCount()) addInstructionCount(); visitSwitch((Jump)node, child); break; case Token.ENTERWITH: generateExpression(child, node); cfw.addALoad(contextLocal); cfw.addALoad(variableObjectLocal); addScriptRuntimeInvoke( "enterWith", "(Ljava/lang/Object;" +"Lorg/mozilla/javascript/Context;" +"Lorg/mozilla/javascript/Scriptable;" +")Lorg/mozilla/javascript/Scriptable;"); cfw.addAStore(variableObjectLocal); incReferenceWordLocal(variableObjectLocal); break; case Token.LEAVEWITH: cfw.addALoad(variableObjectLocal); addScriptRuntimeInvoke( "leaveWith", "(Lorg/mozilla/javascript/Scriptable;" +")Lorg/mozilla/javascript/Scriptable;"); cfw.addAStore(variableObjectLocal); decReferenceWordLocal(variableObjectLocal); break; case Token.ENUM_INIT_KEYS: case Token.ENUM_INIT_VALUES: case Token.ENUM_INIT_ARRAY: generateExpression(child, node); cfw.addALoad(contextLocal); int enumType = type == Token.ENUM_INIT_KEYS ? ScriptRuntime.ENUMERATE_KEYS : type == Token.ENUM_INIT_VALUES ? ScriptRuntime.ENUMERATE_VALUES : ScriptRuntime.ENUMERATE_ARRAY; cfw.addPush(enumType); addScriptRuntimeInvoke("enumInit", "(Ljava/lang/Object;" +"Lorg/mozilla/javascript/Context;" +"I" +")Ljava/lang/Object;"); cfw.addAStore(getLocalBlockRegister(node)); break; case Token.EXPR_VOID: if (child.getType() == Token.SETVAR) { /* special case this so as to avoid unnecessary load's & pop's */ visitSetVar(child, child.getFirstChild(), false); } else if (child.getType() == Token.SETCONSTVAR) { /* special case this so as to avoid unnecessary load's & pop's */ visitSetConstVar(child, child.getFirstChild(), false); } else if (child.getType() == Token.YIELD) { generateYieldPoint(child, false); } else { generateExpression(child, node); if (node.getIntProp(Node.ISNUMBER_PROP, -1) != -1) cfw.add(ByteCode.POP2); else cfw.add(ByteCode.POP); } break; case Token.EXPR_RESULT: generateExpression(child, node); if (popvLocal < 0) { popvLocal = getNewWordLocal(); } cfw.addAStore(popvLocal); break; case Token.TARGET: { if (compilerEnv.isGenerateObserverCount()) addInstructionCount(); int label = getTargetLabel(node); cfw.markLabel(label); if (compilerEnv.isGenerateObserverCount()) saveCurrentCodeOffset(); } break; case Token.JSR: case Token.GOTO: case Token.IFEQ: case Token.IFNE: if (compilerEnv.isGenerateObserverCount()) addInstructionCount(); visitGoto((Jump)node, type, child); break; case Token.FINALLY: { if (compilerEnv.isGenerateObserverCount()) saveCurrentCodeOffset(); // there is exactly one value on the stack when enterring // finally blocks: the return address (or its int encoding) cfw.setStackTop((short)1); // Save return address in a new local int finallyRegister = getNewWordLocal(); if (isGenerator) generateIntegerWrap(); cfw.addAStore(finallyRegister); while (child != null) { generateStatement(child); child = child.getNext(); } if (isGenerator) { cfw.addALoad(finallyRegister); cfw.add(ByteCode.CHECKCAST, "java/lang/Integer"); generateIntegerUnwrap(); FinallyReturnPoint ret = finallys.get(node); ret.tableLabel = cfw.acquireLabel(); cfw.add(ByteCode.GOTO, ret.tableLabel); } else { cfw.add(ByteCode.RET, finallyRegister); } releaseWordLocal((short)finallyRegister); } break; case Token.DEBUGGER: break; default: throw Codegen.badTree(); } } private void generateIntegerWrap() { cfw.addInvoke(ByteCode.INVOKESTATIC, "java/lang/Integer", "valueOf", "(I)Ljava/lang/Integer;"); } private void generateIntegerUnwrap() { cfw.addInvoke(ByteCode.INVOKEVIRTUAL, "java/lang/Integer", "intValue", "()I"); } private void generateThrowJavaScriptException() { cfw.add(ByteCode.NEW, "org/mozilla/javascript/JavaScriptException"); cfw.add(ByteCode.DUP_X1); cfw.add(ByteCode.SWAP); cfw.addPush(scriptOrFn.getSourceName()); cfw.addPush(itsLineNumber); cfw.addInvoke( ByteCode.INVOKESPECIAL, "org/mozilla/javascript/JavaScriptException", "", "(Ljava/lang/Object;Ljava/lang/String;I)V"); cfw.add(ByteCode.ATHROW); } private int getNextGeneratorState(Node node) { int nodeIndex = ((FunctionNode)scriptOrFn).getResumptionPoints() .indexOf(node); return nodeIndex + GENERATOR_YIELD_START; } private void generateExpression(Node node, Node parent) { int type = node.getType(); Node child = node.getFirstChild(); switch (type) { case Token.USE_STACK: break; case Token.FUNCTION: if (fnCurrent != null || parent.getType() != Token.SCRIPT) { int fnIndex = node.getExistingIntProp(Node.FUNCTION_PROP); OptFunctionNode ofn = OptFunctionNode.get(scriptOrFn, fnIndex); int t = ofn.fnode.getFunctionType(); if (t != FunctionNode.FUNCTION_EXPRESSION) { throw Codegen.badTree(); } visitFunction(ofn, t); } break; case Token.NAME: { cfw.addALoad(contextLocal); cfw.addALoad(variableObjectLocal); cfw.addPush(node.getString()); addScriptRuntimeInvoke( "name", "(Lorg/mozilla/javascript/Context;" +"Lorg/mozilla/javascript/Scriptable;" +"Ljava/lang/String;" +")Ljava/lang/Object;"); } break; case Token.CALL: case Token.NEW: { int specialType = node.getIntProp(Node.SPECIALCALL_PROP, Node.NON_SPECIALCALL); if (specialType == Node.NON_SPECIALCALL) { OptFunctionNode target; target = (OptFunctionNode)node.getProp( Node.DIRECTCALL_PROP); if (target != null) { visitOptimizedCall(node, target, type, child); } else if (type == Token.CALL) { visitStandardCall(node, child); } else { visitStandardNew(node, child); } } else { visitSpecialCall(node, type, specialType, child); } } break; case Token.REF_CALL: generateFunctionAndThisObj(child, node); // stack: ... functionObj thisObj child = child.getNext(); generateCallArgArray(node, child, false); cfw.addALoad(contextLocal); addScriptRuntimeInvoke( "callRef", "(Lorg/mozilla/javascript/Callable;" +"Lorg/mozilla/javascript/Scriptable;" +"[Ljava/lang/Object;" +"Lorg/mozilla/javascript/Context;" +")Lorg/mozilla/javascript/Ref;"); break; case Token.NUMBER: { double num = node.getDouble(); if (node.getIntProp(Node.ISNUMBER_PROP, -1) != -1) { cfw.addPush(num); } else { codegen.pushNumberAsObject(cfw, num); } } break; case Token.STRING: cfw.addPush(node.getString()); break; case Token.THIS: cfw.addALoad(thisObjLocal); break; case Token.THISFN: cfw.add(ByteCode.ALOAD_0); break; case Token.NULL: cfw.add(ByteCode.ACONST_NULL); break; case Token.TRUE: cfw.add(ByteCode.GETSTATIC, "java/lang/Boolean", "TRUE", "Ljava/lang/Boolean;"); break; case Token.FALSE: cfw.add(ByteCode.GETSTATIC, "java/lang/Boolean", "FALSE", "Ljava/lang/Boolean;"); break; case Token.REGEXP: { int i = node.getExistingIntProp(Node.REGEXP_PROP); // Scripts can not use REGEXP_ARRAY_FIELD_NAME since // it it will make script.exec non-reentrant so they // store regexp array in a local variable while // functions always access precomputed // REGEXP_ARRAY_FIELD_NAME not to consume locals if (fnCurrent == null) { cfw.addALoad(scriptRegexpLocal); } else { cfw.addALoad(funObjLocal); cfw.add(ByteCode.GETFIELD, codegen.mainClassName, Codegen.REGEXP_ARRAY_FIELD_NAME, Codegen.REGEXP_ARRAY_FIELD_TYPE); } cfw.addPush(i); cfw.add(ByteCode.AALOAD); } break; case Token.COMMA: { Node next = child.getNext(); while (next != null) { generateExpression(child, node); cfw.add(ByteCode.POP); child = next; next = next.getNext(); } generateExpression(child, node); break; } case Token.ENUM_NEXT: case Token.ENUM_ID: { int local = getLocalBlockRegister(node); cfw.addALoad(local); if (type == Token.ENUM_NEXT) { addScriptRuntimeInvoke( "enumNext", "(Ljava/lang/Object;)Ljava/lang/Boolean;"); } else { cfw.addALoad(contextLocal); addScriptRuntimeInvoke("enumId", "(Ljava/lang/Object;" +"Lorg/mozilla/javascript/Context;" +")Ljava/lang/Object;"); } break; } case Token.ARRAYLIT: visitArrayLiteral(node, child); break; case Token.OBJECTLIT: visitObjectLiteral(node, child); break; case Token.NOT: { int trueTarget = cfw.acquireLabel(); int falseTarget = cfw.acquireLabel(); int beyond = cfw.acquireLabel(); generateIfJump(child, node, trueTarget, falseTarget); cfw.markLabel(trueTarget); cfw.add(ByteCode.GETSTATIC, "java/lang/Boolean", "FALSE", "Ljava/lang/Boolean;"); cfw.add(ByteCode.GOTO, beyond); cfw.markLabel(falseTarget); cfw.add(ByteCode.GETSTATIC, "java/lang/Boolean", "TRUE", "Ljava/lang/Boolean;"); cfw.markLabel(beyond); cfw.adjustStackTop(-1); break; } case Token.BITNOT: generateExpression(child, node); addScriptRuntimeInvoke("toInt32", "(Ljava/lang/Object;)I"); cfw.addPush(-1); // implement ~a as (a ^ -1) cfw.add(ByteCode.IXOR); cfw.add(ByteCode.I2D); addDoubleWrap(); break; case Token.VOID: generateExpression(child, node); cfw.add(ByteCode.POP); Codegen.pushUndefined(cfw); break; case Token.TYPEOF: generateExpression(child, node); addScriptRuntimeInvoke("typeof", "(Ljava/lang/Object;" +")Ljava/lang/String;"); break; case Token.TYPEOFNAME: visitTypeofname(node); break; case Token.INC: case Token.DEC: visitIncDec(node); break; case Token.OR: case Token.AND: { generateExpression(child, node); cfw.add(ByteCode.DUP); addScriptRuntimeInvoke("toBoolean", "(Ljava/lang/Object;)Z"); int falseTarget = cfw.acquireLabel(); if (type == Token.AND) cfw.add(ByteCode.IFEQ, falseTarget); else cfw.add(ByteCode.IFNE, falseTarget); cfw.add(ByteCode.POP); generateExpression(child.getNext(), node); cfw.markLabel(falseTarget); } break; case Token.HOOK : { Node ifThen = child.getNext(); Node ifElse = ifThen.getNext(); generateExpression(child, node); addScriptRuntimeInvoke("toBoolean", "(Ljava/lang/Object;)Z"); int elseTarget = cfw.acquireLabel(); cfw.add(ByteCode.IFEQ, elseTarget); short stack = cfw.getStackTop(); generateExpression(ifThen, node); int afterHook = cfw.acquireLabel(); cfw.add(ByteCode.GOTO, afterHook); cfw.markLabel(elseTarget, stack); generateExpression(ifElse, node); cfw.markLabel(afterHook); } break; case Token.ADD: { generateExpression(child, node); generateExpression(child.getNext(), node); switch (node.getIntProp(Node.ISNUMBER_PROP, -1)) { case Node.BOTH: cfw.add(ByteCode.DADD); break; case Node.LEFT: addOptRuntimeInvoke("add", "(DLjava/lang/Object;)Ljava/lang/Object;"); break; case Node.RIGHT: addOptRuntimeInvoke("add", "(Ljava/lang/Object;D)Ljava/lang/Object;"); break; default: if (child.getType() == Token.STRING) { addScriptRuntimeInvoke("add", "(Ljava/lang/String;" +"Ljava/lang/Object;" +")Ljava/lang/String;"); } else if (child.getNext().getType() == Token.STRING) { addScriptRuntimeInvoke("add", "(Ljava/lang/Object;" +"Ljava/lang/String;" +")Ljava/lang/String;"); } else { cfw.addALoad(contextLocal); addScriptRuntimeInvoke("add", "(Ljava/lang/Object;" +"Ljava/lang/Object;" +"Lorg/mozilla/javascript/Context;" +")Ljava/lang/Object;"); } } } break; case Token.MUL: visitArithmetic(node, ByteCode.DMUL, child, parent); break; case Token.SUB: visitArithmetic(node, ByteCode.DSUB, child, parent); break; case Token.DIV: case Token.MOD: visitArithmetic(node, type == Token.DIV ? ByteCode.DDIV : ByteCode.DREM, child, parent); break; case Token.BITOR: case Token.BITXOR: case Token.BITAND: case Token.LSH: case Token.RSH: case Token.URSH: visitBitOp(node, type, child); break; case Token.POS: case Token.NEG: generateExpression(child, node); addObjectToDouble(); if (type == Token.NEG) { cfw.add(ByteCode.DNEG); } addDoubleWrap(); break; case Token.TO_DOUBLE: // cnvt to double (not Double) generateExpression(child, node); addObjectToDouble(); break; case Token.TO_OBJECT: { // convert from double int prop = -1; if (child.getType() == Token.NUMBER) { prop = child.getIntProp(Node.ISNUMBER_PROP, -1); } if (prop != -1) { child.removeProp(Node.ISNUMBER_PROP); generateExpression(child, node); child.putIntProp(Node.ISNUMBER_PROP, prop); } else { generateExpression(child, node); addDoubleWrap(); } break; } case Token.IN: case Token.INSTANCEOF: case Token.LE: case Token.LT: case Token.GE: case Token.GT: { int trueGOTO = cfw.acquireLabel(); int falseGOTO = cfw.acquireLabel(); visitIfJumpRelOp(node, child, trueGOTO, falseGOTO); addJumpedBooleanWrap(trueGOTO, falseGOTO); break; } case Token.EQ: case Token.NE: case Token.SHEQ: case Token.SHNE: { int trueGOTO = cfw.acquireLabel(); int falseGOTO = cfw.acquireLabel(); visitIfJumpEqOp(node, child, trueGOTO, falseGOTO); addJumpedBooleanWrap(trueGOTO, falseGOTO); break; } case Token.GETPROP: case Token.GETPROPNOWARN: visitGetProp(node, child); break; case Token.GETELEM: generateExpression(child, node); // object generateExpression(child.getNext(), node); // id cfw.addALoad(contextLocal); if (node.getIntProp(Node.ISNUMBER_PROP, -1) != -1) { addScriptRuntimeInvoke( "getObjectIndex", "(Ljava/lang/Object;D" +"Lorg/mozilla/javascript/Context;" +")Ljava/lang/Object;"); } else { cfw.addALoad(variableObjectLocal); addScriptRuntimeInvoke( "getObjectElem", "(Ljava/lang/Object;" +"Ljava/lang/Object;" +"Lorg/mozilla/javascript/Context;" +"Lorg/mozilla/javascript/Scriptable;" +")Ljava/lang/Object;"); } break; case Token.GET_REF: generateExpression(child, node); // reference cfw.addALoad(contextLocal); addScriptRuntimeInvoke( "refGet", "(Lorg/mozilla/javascript/Ref;" +"Lorg/mozilla/javascript/Context;" +")Ljava/lang/Object;"); break; case Token.GETVAR: visitGetVar(node); break; case Token.SETVAR: visitSetVar(node, child, true); break; case Token.SETNAME: visitSetName(node, child); break; case Token.STRICT_SETNAME: visitStrictSetName(node, child); break; case Token.SETCONST: visitSetConst(node, child); break; case Token.SETCONSTVAR: visitSetConstVar(node, child, true); break; case Token.SETPROP: case Token.SETPROP_OP: visitSetProp(type, node, child); break; case Token.SETELEM: case Token.SETELEM_OP: visitSetElem(type, node, child); break; case Token.SET_REF: case Token.SET_REF_OP: { generateExpression(child, node); child = child.getNext(); if (type == Token.SET_REF_OP) { cfw.add(ByteCode.DUP); cfw.addALoad(contextLocal); addScriptRuntimeInvoke( "refGet", "(Lorg/mozilla/javascript/Ref;" +"Lorg/mozilla/javascript/Context;" +")Ljava/lang/Object;"); } generateExpression(child, node); cfw.addALoad(contextLocal); addScriptRuntimeInvoke( "refSet", "(Lorg/mozilla/javascript/Ref;" +"Ljava/lang/Object;" +"Lorg/mozilla/javascript/Context;" +")Ljava/lang/Object;"); } break; case Token.DEL_REF: generateExpression(child, node); cfw.addALoad(contextLocal); addScriptRuntimeInvoke("refDel", "(Lorg/mozilla/javascript/Ref;" +"Lorg/mozilla/javascript/Context;" +")Ljava/lang/Object;"); break; case Token.DELPROP: generateExpression(child, node); child = child.getNext(); generateExpression(child, node); cfw.addALoad(contextLocal); addScriptRuntimeInvoke("delete", "(Ljava/lang/Object;" +"Ljava/lang/Object;" +"Lorg/mozilla/javascript/Context;" +")Ljava/lang/Object;"); break; case Token.BINDNAME: { while (child != null) { generateExpression(child, node); child = child.getNext(); } // Generate code for "ScriptRuntime.bind(varObj, "s")" cfw.addALoad(contextLocal); cfw.addALoad(variableObjectLocal); cfw.addPush(node.getString()); addScriptRuntimeInvoke( "bind", "(Lorg/mozilla/javascript/Context;" +"Lorg/mozilla/javascript/Scriptable;" +"Ljava/lang/String;" +")Lorg/mozilla/javascript/Scriptable;"); } break; case Token.LOCAL_LOAD: cfw.addALoad(getLocalBlockRegister(node)); break; case Token.REF_SPECIAL: { String special = (String)node.getProp(Node.NAME_PROP); generateExpression(child, node); cfw.addPush(special); cfw.addALoad(contextLocal); addScriptRuntimeInvoke( "specialRef", "(Ljava/lang/Object;" +"Ljava/lang/String;" +"Lorg/mozilla/javascript/Context;" +")Lorg/mozilla/javascript/Ref;"); } 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 do { generateExpression(child, node); child = child.getNext(); } while (child != null); cfw.addALoad(contextLocal); String methodName, signature; switch (type) { case Token.REF_MEMBER: methodName = "memberRef"; signature = "(Ljava/lang/Object;" +"Ljava/lang/Object;" +"Lorg/mozilla/javascript/Context;" +"I" +")Lorg/mozilla/javascript/Ref;"; break; case Token.REF_NS_MEMBER: methodName = "memberRef"; signature = "(Ljava/lang/Object;" +"Ljava/lang/Object;" +"Ljava/lang/Object;" +"Lorg/mozilla/javascript/Context;" +"I" +")Lorg/mozilla/javascript/Ref;"; break; case Token.REF_NAME: methodName = "nameRef"; signature = "(Ljava/lang/Object;" +"Lorg/mozilla/javascript/Context;" +"Lorg/mozilla/javascript/Scriptable;" +"I" +")Lorg/mozilla/javascript/Ref;"; cfw.addALoad(variableObjectLocal); break; case Token.REF_NS_NAME: methodName = "nameRef"; signature = "(Ljava/lang/Object;" +"Ljava/lang/Object;" +"Lorg/mozilla/javascript/Context;" +"Lorg/mozilla/javascript/Scriptable;" +"I" +")Lorg/mozilla/javascript/Ref;"; cfw.addALoad(variableObjectLocal); break; default: throw Kit.codeBug(); } cfw.addPush(memberTypeFlags); addScriptRuntimeInvoke(methodName, signature); } break; case Token.DOTQUERY: visitDotQuery(node, child); break; case Token.ESCXMLATTR: generateExpression(child, node); cfw.addALoad(contextLocal); addScriptRuntimeInvoke("escapeAttributeValue", "(Ljava/lang/Object;" +"Lorg/mozilla/javascript/Context;" +")Ljava/lang/String;"); break; case Token.ESCXMLTEXT: generateExpression(child, node); cfw.addALoad(contextLocal); addScriptRuntimeInvoke("escapeTextValue", "(Ljava/lang/Object;" +"Lorg/mozilla/javascript/Context;" +")Ljava/lang/String;"); break; case Token.DEFAULTNAMESPACE: generateExpression(child, node); cfw.addALoad(contextLocal); addScriptRuntimeInvoke("setDefaultNamespace", "(Ljava/lang/Object;" +"Lorg/mozilla/javascript/Context;" +")Ljava/lang/Object;"); break; case Token.YIELD: generateYieldPoint(node, true); break; case Token.WITHEXPR: { Node enterWith = child; Node with = enterWith.getNext(); Node leaveWith = with.getNext(); generateStatement(enterWith); generateExpression(with.getFirstChild(), with); generateStatement(leaveWith); break; } case Token.ARRAYCOMP: { Node initStmt = child; Node expr = child.getNext(); generateStatement(initStmt); generateExpression(expr, node); break; } default: throw new RuntimeException("Unexpected node type "+type); } } private void generateYieldPoint(Node node, boolean exprContext) { // save stack state int top = cfw.getStackTop(); maxStack = maxStack > top ? maxStack : top; if (cfw.getStackTop() != 0) { generateGetGeneratorStackState(); for (int i = 0; i < top; i++) { cfw.add(ByteCode.DUP_X1); cfw.add(ByteCode.SWAP); cfw.addLoadConstant(i); cfw.add(ByteCode.SWAP); cfw.add(ByteCode.AASTORE); } // pop the array object cfw.add(ByteCode.POP); } // generate the yield argument Node child = node.getFirstChild(); if (child != null) generateExpression(child, node); else Codegen.pushUndefined(cfw); // change the resumption state int nextState = getNextGeneratorState(node); generateSetGeneratorResumptionPoint(nextState); boolean hasLocals = generateSaveLocals(node); cfw.add(ByteCode.ARETURN); generateCheckForThrowOrClose(getTargetLabel(node), hasLocals, nextState); // reconstruct the stack if (top != 0) { generateGetGeneratorStackState(); for (int i = 0; i < top; i++) { cfw.add(ByteCode.DUP); cfw.addLoadConstant(top - i - 1); cfw.add(ByteCode.AALOAD); cfw.add(ByteCode.SWAP); } cfw.add(ByteCode.POP); } // load return value from yield if (exprContext) { cfw.addALoad(argsLocal); } } private void generateCheckForThrowOrClose(int label, boolean hasLocals, int nextState) { int throwLabel = cfw.acquireLabel(); int closeLabel = cfw.acquireLabel(); // throw the user provided object, if the operation is .throw() cfw.markLabel(throwLabel); cfw.addALoad(argsLocal); generateThrowJavaScriptException(); // throw our special internal exception if the generator is being closed cfw.markLabel(closeLabel); cfw.addALoad(argsLocal); cfw.add(ByteCode.CHECKCAST, "java/lang/Throwable"); cfw.add(ByteCode.ATHROW); // mark the re-entry point // jump here after initializing the locals if (label != -1) cfw.markLabel(label); if (!hasLocals) { // jump here directly if there are no locals cfw.markTableSwitchCase(generatorSwitch, nextState); } // see if we need to dispatch for .close() or .throw() cfw.addILoad(operationLocal); cfw.addLoadConstant(NativeGenerator.GENERATOR_CLOSE); cfw.add(ByteCode.IF_ICMPEQ, closeLabel); cfw.addILoad(operationLocal); cfw.addLoadConstant(NativeGenerator.GENERATOR_THROW); cfw.add(ByteCode.IF_ICMPEQ, throwLabel); } private void generateIfJump(Node node, Node parent, int trueLabel, int falseLabel) { // System.out.println("gen code for " + node.toString()); int type = node.getType(); Node child = node.getFirstChild(); switch (type) { case Token.NOT: generateIfJump(child, node, falseLabel, trueLabel); break; case Token.OR: case Token.AND: { int interLabel = cfw.acquireLabel(); if (type == Token.AND) { generateIfJump(child, node, interLabel, falseLabel); } else { generateIfJump(child, node, trueLabel, interLabel); } cfw.markLabel(interLabel); child = child.getNext(); generateIfJump(child, node, trueLabel, falseLabel); break; } case Token.IN: case Token.INSTANCEOF: case Token.LE: case Token.LT: case Token.GE: case Token.GT: visitIfJumpRelOp(node, child, trueLabel, falseLabel); break; case Token.EQ: case Token.NE: case Token.SHEQ: case Token.SHNE: visitIfJumpEqOp(node, child, trueLabel, falseLabel); break; default: // Generate generic code for non-optimized jump generateExpression(node, parent); addScriptRuntimeInvoke("toBoolean", "(Ljava/lang/Object;)Z"); cfw.add(ByteCode.IFNE, trueLabel); cfw.add(ByteCode.GOTO, falseLabel); } } private void visitFunction(OptFunctionNode ofn, int functionType) { int fnIndex = codegen.getIndex(ofn.fnode); cfw.add(ByteCode.NEW, codegen.mainClassName); // Call function constructor cfw.add(ByteCode.DUP); cfw.addALoad(variableObjectLocal); cfw.addALoad(contextLocal); // load 'cx' cfw.addPush(fnIndex); cfw.addInvoke(ByteCode.INVOKESPECIAL, codegen.mainClassName, "", Codegen.FUNCTION_CONSTRUCTOR_SIGNATURE); // Init mainScript field; cfw.add(ByteCode.DUP); if (isTopLevel) { cfw.add(ByteCode.ALOAD_0); } else { cfw.add(ByteCode.ALOAD_0); cfw.add(ByteCode.GETFIELD, codegen.mainClassName, Codegen.DIRECT_CALL_PARENT_FIELD, codegen.mainClassSignature); } cfw.add(ByteCode.PUTFIELD, codegen.mainClassName, Codegen.DIRECT_CALL_PARENT_FIELD, codegen.mainClassSignature); int directTargetIndex = ofn.getDirectTargetIndex(); if (directTargetIndex >= 0) { cfw.add(ByteCode.DUP); if (isTopLevel) { cfw.add(ByteCode.ALOAD_0); } else { cfw.add(ByteCode.ALOAD_0); cfw.add(ByteCode.GETFIELD, codegen.mainClassName, Codegen.DIRECT_CALL_PARENT_FIELD, codegen.mainClassSignature); } cfw.add(ByteCode.SWAP); cfw.add(ByteCode.PUTFIELD, codegen.mainClassName, Codegen.getDirectTargetFieldName(directTargetIndex), codegen.mainClassSignature); } if (functionType == FunctionNode.FUNCTION_EXPRESSION) { // Leave closure object on stack and do not pass it to // initFunction which suppose to connect statements to scope return; } cfw.addPush(functionType); cfw.addALoad(variableObjectLocal); cfw.addALoad(contextLocal); // load 'cx' addOptRuntimeInvoke("initFunction", "(Lorg/mozilla/javascript/NativeFunction;" +"I" +"Lorg/mozilla/javascript/Scriptable;" +"Lorg/mozilla/javascript/Context;" +")V"); } private int getTargetLabel(Node target) { int labelId = target.labelId(); if (labelId == -1) { labelId = cfw.acquireLabel(); target.labelId(labelId); } return labelId; } private void visitGoto(Jump node, int type, Node child) { Node target = node.target; if (type == Token.IFEQ || type == Token.IFNE) { if (child == null) throw Codegen.badTree(); int targetLabel = getTargetLabel(target); int fallThruLabel = cfw.acquireLabel(); if (type == Token.IFEQ) generateIfJump(child, node, targetLabel, fallThruLabel); else generateIfJump(child, node, fallThruLabel, targetLabel); cfw.markLabel(fallThruLabel); } else { if (type == Token.JSR) { if (isGenerator) { addGotoWithReturn(target); } else { addGoto(target, ByteCode.JSR); } } else { addGoto(target, ByteCode.GOTO); } } } private void addGotoWithReturn(Node target) { FinallyReturnPoint ret = finallys.get(target); cfw.addLoadConstant(ret.jsrPoints.size()); addGoto(target, ByteCode.GOTO); int retLabel = cfw.acquireLabel(); cfw.markLabel(retLabel); ret.jsrPoints.add(Integer.valueOf(retLabel)); } private void visitArrayLiteral(Node node, Node child) { int count = 0; for (Node cursor = child; cursor != null; cursor = cursor.getNext()) { ++count; } // load array to store array literal objects addNewObjectArray(count); for (int i = 0; i != count; ++i) { cfw.add(ByteCode.DUP); cfw.addPush(i); generateExpression(child, node); cfw.add(ByteCode.AASTORE); child = child.getNext(); } int[] skipIndexes = (int[])node.getProp(Node.SKIP_INDEXES_PROP); if (skipIndexes == null) { cfw.add(ByteCode.ACONST_NULL); cfw.add(ByteCode.ICONST_0); } else { cfw.addPush(OptRuntime.encodeIntArray(skipIndexes)); cfw.addPush(skipIndexes.length); } cfw.addALoad(contextLocal); cfw.addALoad(variableObjectLocal); addOptRuntimeInvoke("newArrayLiteral", "([Ljava/lang/Object;" +"Ljava/lang/String;" +"I" +"Lorg/mozilla/javascript/Context;" +"Lorg/mozilla/javascript/Scriptable;" +")Lorg/mozilla/javascript/Scriptable;"); } private void visitObjectLiteral(Node node, Node child) { Object[] properties = (Object[])node.getProp(Node.OBJECT_IDS_PROP); int count = properties.length; // load array with property ids addNewObjectArray(count); for (int i = 0; i != count; ++i) { cfw.add(ByteCode.DUP); cfw.addPush(i); Object id = properties[i]; if (id instanceof String) { cfw.addPush((String)id); } else { cfw.addPush(((Integer)id).intValue()); addScriptRuntimeInvoke("wrapInt", "(I)Ljava/lang/Integer;"); } cfw.add(ByteCode.AASTORE); } // load array with property values addNewObjectArray(count); Node child2 = child; for (int i = 0; i != count; ++i) { cfw.add(ByteCode.DUP); cfw.addPush(i); int childType = child.getType(); if (childType == Token.GET) { generateExpression(child.getFirstChild(), node); } else if (childType == Token.SET) { generateExpression(child.getFirstChild(), node); } else { generateExpression(child, node); } cfw.add(ByteCode.AASTORE); child = child.getNext(); } // load array with getterSetter values cfw.addPush(count); cfw.add(ByteCode.NEWARRAY, ByteCode.T_INT); for (int i = 0; i != count; ++i) { cfw.add(ByteCode.DUP); cfw.addPush(i); int childType = child2.getType(); if (childType == Token.GET) { cfw.add(ByteCode.ICONST_M1); } else if (childType == Token.SET) { cfw.add(ByteCode.ICONST_1); } else { cfw.add(ByteCode.ICONST_0); } cfw.add(ByteCode.IASTORE); child2 = child2.getNext(); } cfw.addALoad(contextLocal); cfw.addALoad(variableObjectLocal); addScriptRuntimeInvoke("newObjectLiteral", "([Ljava/lang/Object;" +"[Ljava/lang/Object;" +"[I" +"Lorg/mozilla/javascript/Context;" +"Lorg/mozilla/javascript/Scriptable;" +")Lorg/mozilla/javascript/Scriptable;"); } private void visitSpecialCall(Node node, int type, int specialType, Node child) { cfw.addALoad(contextLocal); if (type == Token.NEW) { generateExpression(child, node); // stack: ... cx functionObj } else { generateFunctionAndThisObj(child, node); // stack: ... cx functionObj thisObj } child = child.getNext(); generateCallArgArray(node, child, false); String methodName; String callSignature; if (type == Token.NEW) { methodName = "newObjectSpecial"; callSignature = "(Lorg/mozilla/javascript/Context;" +"Ljava/lang/Object;" +"[Ljava/lang/Object;" +"Lorg/mozilla/javascript/Scriptable;" +"Lorg/mozilla/javascript/Scriptable;" +"I" // call type +")Ljava/lang/Object;"; cfw.addALoad(variableObjectLocal); cfw.addALoad(thisObjLocal); cfw.addPush(specialType); } else { methodName = "callSpecial"; callSignature = "(Lorg/mozilla/javascript/Context;" +"Lorg/mozilla/javascript/Callable;" +"Lorg/mozilla/javascript/Scriptable;" +"[Ljava/lang/Object;" +"Lorg/mozilla/javascript/Scriptable;" +"Lorg/mozilla/javascript/Scriptable;" +"I" // call type +"Ljava/lang/String;I" // filename, linenumber +")Ljava/lang/Object;"; cfw.addALoad(variableObjectLocal); cfw.addALoad(thisObjLocal); cfw.addPush(specialType); String sourceName = scriptOrFn.getSourceName(); cfw.addPush(sourceName == null ? "" : sourceName); cfw.addPush(itsLineNumber); } addOptRuntimeInvoke(methodName, callSignature); } private void visitStandardCall(Node node, Node child) { if (node.getType() != Token.CALL) throw Codegen.badTree(); Node firstArgChild = child.getNext(); int childType = child.getType(); String methodName; String signature; if (firstArgChild == null) { if (childType == Token.NAME) { // name() call String name = child.getString(); cfw.addPush(name); methodName = "callName0"; signature = "(Ljava/lang/String;" +"Lorg/mozilla/javascript/Context;" +"Lorg/mozilla/javascript/Scriptable;" +")Ljava/lang/Object;"; } else if (childType == Token.GETPROP) { // x.name() call Node propTarget = child.getFirstChild(); generateExpression(propTarget, node); Node id = propTarget.getNext(); String property = id.getString(); cfw.addPush(property); methodName = "callProp0"; signature = "(Ljava/lang/Object;" +"Ljava/lang/String;" +"Lorg/mozilla/javascript/Context;" +"Lorg/mozilla/javascript/Scriptable;" +")Ljava/lang/Object;"; } else if (childType == Token.GETPROPNOWARN) { throw Kit.codeBug(); } else { generateFunctionAndThisObj(child, node); methodName = "call0"; signature = "(Lorg/mozilla/javascript/Callable;" +"Lorg/mozilla/javascript/Scriptable;" +"Lorg/mozilla/javascript/Context;" +"Lorg/mozilla/javascript/Scriptable;" +")Ljava/lang/Object;"; } } else if (childType == Token.NAME) { // XXX: this optimization is only possible if name // resolution // is not affected by arguments evaluation and currently // there are no checks for it String name = child.getString(); generateCallArgArray(node, firstArgChild, false); cfw.addPush(name); methodName = "callName"; signature = "([Ljava/lang/Object;" +"Ljava/lang/String;" +"Lorg/mozilla/javascript/Context;" +"Lorg/mozilla/javascript/Scriptable;" +")Ljava/lang/Object;"; } else { int argCount = 0; for (Node arg = firstArgChild; arg != null; arg = arg.getNext()) { ++argCount; } generateFunctionAndThisObj(child, node); // stack: ... functionObj thisObj if (argCount == 1) { generateExpression(firstArgChild, node); methodName = "call1"; signature = "(Lorg/mozilla/javascript/Callable;" +"Lorg/mozilla/javascript/Scriptable;" +"Ljava/lang/Object;" +"Lorg/mozilla/javascript/Context;" +"Lorg/mozilla/javascript/Scriptable;" +")Ljava/lang/Object;"; } else if (argCount == 2) { generateExpression(firstArgChild, node); generateExpression(firstArgChild.getNext(), node); methodName = "call2"; signature = "(Lorg/mozilla/javascript/Callable;" +"Lorg/mozilla/javascript/Scriptable;" +"Ljava/lang/Object;" +"Ljava/lang/Object;" +"Lorg/mozilla/javascript/Context;" +"Lorg/mozilla/javascript/Scriptable;" +")Ljava/lang/Object;"; } else { generateCallArgArray(node, firstArgChild, false); methodName = "callN"; signature = "(Lorg/mozilla/javascript/Callable;" +"Lorg/mozilla/javascript/Scriptable;" +"[Ljava/lang/Object;" +"Lorg/mozilla/javascript/Context;" +"Lorg/mozilla/javascript/Scriptable;" +")Ljava/lang/Object;"; } } cfw.addALoad(contextLocal); cfw.addALoad(variableObjectLocal); addOptRuntimeInvoke(methodName, signature); } private void visitStandardNew(Node node, Node child) { if (node.getType() != Token.NEW) throw Codegen.badTree(); Node firstArgChild = child.getNext(); generateExpression(child, node); // stack: ... functionObj cfw.addALoad(contextLocal); cfw.addALoad(variableObjectLocal); // stack: ... functionObj cx scope generateCallArgArray(node, firstArgChild, false); addScriptRuntimeInvoke( "newObject", "(Ljava/lang/Object;" +"Lorg/mozilla/javascript/Context;" +"Lorg/mozilla/javascript/Scriptable;" +"[Ljava/lang/Object;" +")Lorg/mozilla/javascript/Scriptable;"); } private void visitOptimizedCall(Node node, OptFunctionNode target, int type, Node child) { Node firstArgChild = child.getNext(); short thisObjLocal = 0; if (type == Token.NEW) { generateExpression(child, node); } else { generateFunctionAndThisObj(child, node); thisObjLocal = getNewWordLocal(); cfw.addAStore(thisObjLocal); } // stack: ... functionObj int beyond = cfw.acquireLabel(); int directTargetIndex = target.getDirectTargetIndex(); if (isTopLevel) { cfw.add(ByteCode.ALOAD_0); } else { cfw.add(ByteCode.ALOAD_0); cfw.add(ByteCode.GETFIELD, codegen.mainClassName, Codegen.DIRECT_CALL_PARENT_FIELD, codegen.mainClassSignature); } cfw.add(ByteCode.GETFIELD, codegen.mainClassName, Codegen.getDirectTargetFieldName(directTargetIndex), codegen.mainClassSignature); cfw.add(ByteCode.DUP2); // stack: ... functionObj directFunct functionObj directFunct int regularCall = cfw.acquireLabel(); cfw.add(ByteCode.IF_ACMPNE, regularCall); // stack: ... functionObj directFunct short stackHeight = cfw.getStackTop(); cfw.add(ByteCode.SWAP); cfw.add(ByteCode.POP); // stack: ... directFunct if (compilerEnv.isUseDynamicScope()) { cfw.addALoad(contextLocal); cfw.addALoad(variableObjectLocal); } else { cfw.add(ByteCode.DUP); // stack: ... directFunct directFunct cfw.addInvoke(ByteCode.INVOKEINTERFACE, "org/mozilla/javascript/Scriptable", "getParentScope", "()Lorg/mozilla/javascript/Scriptable;"); // stack: ... directFunct scope cfw.addALoad(contextLocal); // stack: ... directFunct scope cx cfw.add(ByteCode.SWAP); } // stack: ... directFunc cx scope if (type == Token.NEW) { cfw.add(ByteCode.ACONST_NULL); } else { cfw.addALoad(thisObjLocal); } // stack: ... directFunc cx scope thisObj /* Remember that directCall parameters are paired in 1 aReg and 1 dReg If the argument is an incoming arg, just pass the orginal pair thru. Else, if the argument is known to be typed 'Number', pass Void.TYPE in the aReg and the number is the dReg Else pass the JS object in the aReg and 0.0 in the dReg. */ Node argChild = firstArgChild; while (argChild != null) { int dcp_register = nodeIsDirectCallParameter(argChild); if (dcp_register >= 0) { cfw.addALoad(dcp_register); cfw.addDLoad(dcp_register + 1); } else if (argChild.getIntProp(Node.ISNUMBER_PROP, -1) == Node.BOTH) { cfw.add(ByteCode.GETSTATIC, "java/lang/Void", "TYPE", "Ljava/lang/Class;"); generateExpression(argChild, node); } else { generateExpression(argChild, node); cfw.addPush(0.0); } argChild = argChild.getNext(); } cfw.add(ByteCode.GETSTATIC, "org/mozilla/javascript/ScriptRuntime", "emptyArgs", "[Ljava/lang/Object;"); cfw.addInvoke(ByteCode.INVOKESTATIC, codegen.mainClassName, (type == Token.NEW) ? codegen.getDirectCtorName(target.fnode) : codegen.getBodyMethodName(target.fnode), codegen.getBodyMethodSignature(target.fnode)); cfw.add(ByteCode.GOTO, beyond); cfw.markLabel(regularCall, stackHeight); // stack: ... functionObj directFunct cfw.add(ByteCode.POP); cfw.addALoad(contextLocal); cfw.addALoad(variableObjectLocal); // stack: ... functionObj cx scope if (type != Token.NEW) { cfw.addALoad(thisObjLocal); releaseWordLocal(thisObjLocal); // stack: ... functionObj cx scope thisObj } // XXX: this will generate code for the child array the second time, // so expression code generation better not to alter tree structure... generateCallArgArray(node, firstArgChild, true); if (type == Token.NEW) { addScriptRuntimeInvoke( "newObject", "(Ljava/lang/Object;" +"Lorg/mozilla/javascript/Context;" +"Lorg/mozilla/javascript/Scriptable;" +"[Ljava/lang/Object;" +")Lorg/mozilla/javascript/Scriptable;"); } else { cfw.addInvoke(ByteCode.INVOKEINTERFACE, "org/mozilla/javascript/Callable", "call", "(Lorg/mozilla/javascript/Context;" +"Lorg/mozilla/javascript/Scriptable;" +"Lorg/mozilla/javascript/Scriptable;" +"[Ljava/lang/Object;" +")Ljava/lang/Object;"); } cfw.markLabel(beyond); } private void generateCallArgArray(Node node, Node argChild, boolean directCall) { int argCount = 0; for (Node child = argChild; child != null; child = child.getNext()) { ++argCount; } // load array object to set arguments if (argCount == 1 && itsOneArgArray >= 0) { cfw.addALoad(itsOneArgArray); } else { addNewObjectArray(argCount); } // Copy arguments into it for (int i = 0; i != argCount; ++i) { // If we are compiling a generator an argument could be the result // of a yield. In that case we will have an immediate on the stack // which we need to avoid if (!isGenerator) { cfw.add(ByteCode.DUP); cfw.addPush(i); } if (!directCall) { generateExpression(argChild, node); } else { // If this has also been a directCall sequence, the Number // flag will have remained set for any parameter so that // the values could be copied directly into the outgoing // args. Here we want to force it to be treated as not in // a Number context, so we set the flag off. int dcp_register = nodeIsDirectCallParameter(argChild); if (dcp_register >= 0) { dcpLoadAsObject(dcp_register); } else { generateExpression(argChild, node); int childNumberFlag = argChild.getIntProp(Node.ISNUMBER_PROP, -1); if (childNumberFlag == Node.BOTH) { addDoubleWrap(); } } } // When compiling generators, any argument to a method may be a // yield expression. Hence we compile the argument first and then // load the argument index and assign the value to the args array. if (isGenerator) { short tempLocal = getNewWordLocal(); cfw.addAStore(tempLocal); cfw.add(ByteCode.CHECKCAST, "[Ljava/lang/Object;"); cfw.add(ByteCode.DUP); cfw.addPush(i); cfw.addALoad(tempLocal); releaseWordLocal(tempLocal); } cfw.add(ByteCode.AASTORE); argChild = argChild.getNext(); } } private void generateFunctionAndThisObj(Node node, Node parent) { // Place on stack (function object, function this) pair int type = node.getType(); switch (node.getType()) { case Token.GETPROPNOWARN: throw Kit.codeBug(); case Token.GETPROP: case Token.GETELEM: { Node target = node.getFirstChild(); generateExpression(target, node); Node id = target.getNext(); if (type == Token.GETPROP) { String property = id.getString(); cfw.addPush(property); cfw.addALoad(contextLocal); cfw.addALoad(variableObjectLocal); addScriptRuntimeInvoke( "getPropFunctionAndThis", "(Ljava/lang/Object;" +"Ljava/lang/String;" +"Lorg/mozilla/javascript/Context;" +"Lorg/mozilla/javascript/Scriptable;" +")Lorg/mozilla/javascript/Callable;"); } else { // Optimizer do not optimize this case for now if (node.getIntProp(Node.ISNUMBER_PROP, -1) != -1) throw Codegen.badTree(); generateExpression(id, node); // id cfw.addALoad(contextLocal); addScriptRuntimeInvoke( "getElemFunctionAndThis", "(Ljava/lang/Object;" +"Ljava/lang/Object;" +"Lorg/mozilla/javascript/Context;" +")Lorg/mozilla/javascript/Callable;"); } break; } case Token.NAME: { String name = node.getString(); cfw.addPush(name); cfw.addALoad(contextLocal); cfw.addALoad(variableObjectLocal); addScriptRuntimeInvoke( "getNameFunctionAndThis", "(Ljava/lang/String;" +"Lorg/mozilla/javascript/Context;" +"Lorg/mozilla/javascript/Scriptable;" +")Lorg/mozilla/javascript/Callable;"); break; } default: // including GETVAR generateExpression(node, parent); cfw.addALoad(contextLocal); addScriptRuntimeInvoke( "getValueFunctionAndThis", "(Ljava/lang/Object;" +"Lorg/mozilla/javascript/Context;" +")Lorg/mozilla/javascript/Callable;"); break; } // Get thisObj prepared by get(Name|Prop|Elem|Value)FunctionAndThis cfw.addALoad(contextLocal); addScriptRuntimeInvoke( "lastStoredScriptable", "(Lorg/mozilla/javascript/Context;" +")Lorg/mozilla/javascript/Scriptable;"); } private void updateLineNumber(Node node) { itsLineNumber = node.getLineno(); if (itsLineNumber == -1) return; cfw.addLineNumberEntry((short)itsLineNumber); } private void visitTryCatchFinally(Jump node, Node child) { /* Save the variable object, in case there are with statements * enclosed by the try block and we catch some exception. * We'll restore it for the catch block so that catch block * statements get the right scope. */ // OPT we only need to do this if there are enclosed WITH // statements; could statically check and omit this if there aren't any. // XXX OPT Maybe instead do syntactic transforms to associate // each 'with' with a try/finally block that does the exitwith. short savedVariableObject = getNewWordLocal(); cfw.addALoad(variableObjectLocal); cfw.addAStore(savedVariableObject); /* * Generate the code for the tree; most of the work is done in IRFactory * and NodeTransformer; Codegen just adds the java handlers for the * javascript catch and finally clauses. */ int startLabel = cfw.acquireLabel(); cfw.markLabel(startLabel, (short)0); Node catchTarget = node.target; Node finallyTarget = node.getFinally(); // create a table for the equivalent of JSR returns if (isGenerator && finallyTarget != null) { FinallyReturnPoint ret = new FinallyReturnPoint(); if (finallys == null) { finallys = new HashMap(); } // add the finally target to hashtable finallys.put(finallyTarget, ret); // add the finally node as well to the hash table finallys.put(finallyTarget.getNext(), ret); } while (child != null) { generateStatement(child); child = child.getNext(); } // control flow skips the handlers int realEnd = cfw.acquireLabel(); cfw.add(ByteCode.GOTO, realEnd); int exceptionLocal = getLocalBlockRegister(node); // javascript handler; unwrap exception and GOTO to javascript // catch area. if (catchTarget != null) { // get the label to goto int catchLabel = catchTarget.labelId(); generateCatchBlock(JAVASCRIPT_EXCEPTION, savedVariableObject, catchLabel, startLabel, exceptionLocal); /* * catch WrappedExceptions, see if they are wrapped * JavaScriptExceptions. Otherwise, rethrow. */ generateCatchBlock(EVALUATOR_EXCEPTION, savedVariableObject, catchLabel, startLabel, exceptionLocal); /* we also need to catch EcmaErrors and feed the associated error object to the handler */ generateCatchBlock(ECMAERROR_EXCEPTION, savedVariableObject, catchLabel, startLabel, exceptionLocal); Context cx = Context.getCurrentContext(); if (cx != null && cx.hasFeature(Context.FEATURE_ENHANCED_JAVA_ACCESS)) { generateCatchBlock(THROWABLE_EXCEPTION, savedVariableObject, catchLabel, startLabel, exceptionLocal); } } // finally handler; catch all exceptions, store to a local; JSR to // the finally, then re-throw. if (finallyTarget != null) { int finallyHandler = cfw.acquireLabel(); cfw.markHandler(finallyHandler); cfw.addAStore(exceptionLocal); // reset the variable object local cfw.addALoad(savedVariableObject); cfw.addAStore(variableObjectLocal); // get the label to JSR to int finallyLabel = finallyTarget.labelId(); if (isGenerator) addGotoWithReturn(finallyTarget); else cfw.add(ByteCode.JSR, finallyLabel); // rethrow cfw.addALoad(exceptionLocal); if (isGenerator) cfw.add(ByteCode.CHECKCAST, "java/lang/Throwable"); cfw.add(ByteCode.ATHROW); // mark the handler cfw.addExceptionHandler(startLabel, finallyLabel, finallyHandler, null); // catch any } releaseWordLocal(savedVariableObject); cfw.markLabel(realEnd); } private static final int JAVASCRIPT_EXCEPTION = 0; private static final int EVALUATOR_EXCEPTION = 1; private static final int ECMAERROR_EXCEPTION = 2; private static final int THROWABLE_EXCEPTION = 3; private void generateCatchBlock(int exceptionType, short savedVariableObject, int catchLabel, int startLabel, int exceptionLocal) { int handler = cfw.acquireLabel(); cfw.markHandler(handler); // MS JVM gets cranky if the exception object is left on the stack cfw.addAStore(exceptionLocal); // reset the variable object local cfw.addALoad(savedVariableObject); cfw.addAStore(variableObjectLocal); String exceptionName; if (exceptionType == JAVASCRIPT_EXCEPTION) { exceptionName = "org/mozilla/javascript/JavaScriptException"; } else if (exceptionType == EVALUATOR_EXCEPTION) { exceptionName = "org/mozilla/javascript/EvaluatorException"; } else if (exceptionType == ECMAERROR_EXCEPTION) { exceptionName = "org/mozilla/javascript/EcmaError"; } else if (exceptionType == THROWABLE_EXCEPTION) { exceptionName = "java/lang/Throwable"; } else { throw Kit.codeBug(); } // mark the handler cfw.addExceptionHandler(startLabel, catchLabel, handler, exceptionName); cfw.add(ByteCode.GOTO, catchLabel); } private boolean generateSaveLocals(Node node) { int count = 0; for (int i = 0; i < firstFreeLocal; i++) { if (locals[i] != 0) count++; } if (count == 0) { ((FunctionNode)scriptOrFn).addLiveLocals(node, null); return false; } // calculate the max locals maxLocals = maxLocals > count ? maxLocals : count; // create a locals list int[] ls = new int[count]; int s = 0; for (int i = 0; i < firstFreeLocal; i++) { if (locals[i] != 0) { ls[s] = i; s++; } } // save the locals ((FunctionNode)scriptOrFn).addLiveLocals(node, ls); // save locals generateGetGeneratorLocalsState(); for (int i = 0; i < count; i++) { cfw.add(ByteCode.DUP); cfw.addLoadConstant(i); cfw.addALoad(ls[i]); cfw.add(ByteCode.AASTORE); } // pop the array off the stack cfw.add(ByteCode.POP); return true; } private void visitSwitch(Jump switchNode, Node child) { // See comments in IRFactory.createSwitch() for description // of SWITCH node generateExpression(child, switchNode); // save selector value short selector = getNewWordLocal(); cfw.addAStore(selector); for (Jump caseNode = (Jump)child.getNext(); caseNode != null; caseNode = (Jump)caseNode.getNext()) { if (caseNode.getType() != Token.CASE) throw Codegen.badTree(); Node test = caseNode.getFirstChild(); generateExpression(test, caseNode); cfw.addALoad(selector); addScriptRuntimeInvoke("shallowEq", "(Ljava/lang/Object;" +"Ljava/lang/Object;" +")Z"); addGoto(caseNode.target, ByteCode.IFNE); } releaseWordLocal(selector); } private void visitTypeofname(Node node) { if (hasVarsInRegs) { int varIndex = fnCurrent.fnode.getIndexForNameNode(node); if (varIndex >= 0) { if (fnCurrent.isNumberVar(varIndex)) { cfw.addPush("number"); } else if (varIsDirectCallParameter(varIndex)) { int dcp_register = varRegisters[varIndex]; cfw.addALoad(dcp_register); cfw.add(ByteCode.GETSTATIC, "java/lang/Void", "TYPE", "Ljava/lang/Class;"); int isNumberLabel = cfw.acquireLabel(); cfw.add(ByteCode.IF_ACMPEQ, isNumberLabel); short stack = cfw.getStackTop(); cfw.addALoad(dcp_register); addScriptRuntimeInvoke("typeof", "(Ljava/lang/Object;" +")Ljava/lang/String;"); int beyond = cfw.acquireLabel(); cfw.add(ByteCode.GOTO, beyond); cfw.markLabel(isNumberLabel, stack); cfw.addPush("number"); cfw.markLabel(beyond); } else { cfw.addALoad(varRegisters[varIndex]); addScriptRuntimeInvoke("typeof", "(Ljava/lang/Object;" +")Ljava/lang/String;"); } return; } } cfw.addALoad(variableObjectLocal); cfw.addPush(node.getString()); addScriptRuntimeInvoke("typeofName", "(Lorg/mozilla/javascript/Scriptable;" +"Ljava/lang/String;" +")Ljava/lang/String;"); } /** * Save the current code offset. This saved code offset is used to * compute instruction counts in subsequent calls to * {@link #addInstructionCount()}. */ private void saveCurrentCodeOffset() { savedCodeOffset = cfw.getCurrentCodeOffset(); } /** * Generate calls to ScriptRuntime.addInstructionCount to keep track of * executed instructions and call observeInstructionCount() * if a threshold is exceeded.
* Calculates the count from getCurrentCodeOffset - savedCodeOffset */ private void addInstructionCount() { int count = cfw.getCurrentCodeOffset() - savedCodeOffset; if (count == 0) return; addInstructionCount(count); } /** * Generate calls to ScriptRuntime.addInstructionCount to keep track of * executed instructions and call observeInstructionCount() * if a threshold is exceeded.
* Takes the count as a parameter - used to add monitoring to loops and * other blocks that don't have any ops - this allows * for monitoring/killing of while(true) loops and such. */ private void addInstructionCount(int count) { cfw.addALoad(contextLocal); cfw.addPush(count); addScriptRuntimeInvoke("addInstructionCount", "(Lorg/mozilla/javascript/Context;" +"I)V"); } private void visitIncDec(Node node) { int incrDecrMask = node.getExistingIntProp(Node.INCRDECR_PROP); Node child = node.getFirstChild(); switch (child.getType()) { case Token.GETVAR: if (!hasVarsInRegs) Kit.codeBug(); if (node.getIntProp(Node.ISNUMBER_PROP, -1) != -1) { boolean post = ((incrDecrMask & Node.POST_FLAG) != 0); int varIndex = fnCurrent.getVarIndex(child); short reg = varRegisters[varIndex]; int offset = varIsDirectCallParameter(varIndex) ? 1 : 0; cfw.addDLoad(reg + offset); if (post) { cfw.add(ByteCode.DUP2); } cfw.addPush(1.0); if ((incrDecrMask & Node.DECR_FLAG) == 0) { cfw.add(ByteCode.DADD); } else { cfw.add(ByteCode.DSUB); } if (!post) { cfw.add(ByteCode.DUP2); } cfw.addDStore(reg + offset); } else { boolean post = ((incrDecrMask & Node.POST_FLAG) != 0); int varIndex = fnCurrent.getVarIndex(child); short reg = varRegisters[varIndex]; cfw.addALoad(reg); if (post) { cfw.add(ByteCode.DUP); } addObjectToDouble(); cfw.addPush(1.0); if ((incrDecrMask & Node.DECR_FLAG) == 0) { cfw.add(ByteCode.DADD); } else { cfw.add(ByteCode.DSUB); } addDoubleWrap(); if (!post) { cfw.add(ByteCode.DUP); } cfw.addAStore(reg); break; } break; case Token.NAME: cfw.addALoad(variableObjectLocal); cfw.addPush(child.getString()); // push name cfw.addALoad(contextLocal); cfw.addPush(incrDecrMask); addScriptRuntimeInvoke("nameIncrDecr", "(Lorg/mozilla/javascript/Scriptable;" +"Ljava/lang/String;" +"Lorg/mozilla/javascript/Context;" +"I)Ljava/lang/Object;"); break; case Token.GETPROPNOWARN: throw Kit.codeBug(); case Token.GETPROP: { Node getPropChild = child.getFirstChild(); generateExpression(getPropChild, node); generateExpression(getPropChild.getNext(), node); cfw.addALoad(contextLocal); cfw.addPush(incrDecrMask); addScriptRuntimeInvoke("propIncrDecr", "(Ljava/lang/Object;" +"Ljava/lang/String;" +"Lorg/mozilla/javascript/Context;" +"I)Ljava/lang/Object;"); break; } case Token.GETELEM: { Node elemChild = child.getFirstChild(); generateExpression(elemChild, node); generateExpression(elemChild.getNext(), node); cfw.addALoad(contextLocal); cfw.addPush(incrDecrMask); if (elemChild.getNext().getIntProp(Node.ISNUMBER_PROP, -1) != -1) { addOptRuntimeInvoke("elemIncrDecr", "(Ljava/lang/Object;" +"D" +"Lorg/mozilla/javascript/Context;" +"I" +")Ljava/lang/Object;"); } else { addScriptRuntimeInvoke("elemIncrDecr", "(Ljava/lang/Object;" +"Ljava/lang/Object;" +"Lorg/mozilla/javascript/Context;" +"I" +")Ljava/lang/Object;"); } break; } case Token.GET_REF: { Node refChild = child.getFirstChild(); generateExpression(refChild, node); cfw.addALoad(contextLocal); cfw.addPush(incrDecrMask); addScriptRuntimeInvoke( "refIncrDecr", "(Lorg/mozilla/javascript/Ref;" +"Lorg/mozilla/javascript/Context;" +"I)Ljava/lang/Object;"); break; } default: Codegen.badTree(); } } private static boolean isArithmeticNode(Node node) { int type = node.getType(); return (type == Token.SUB) || (type == Token.MOD) || (type == Token.DIV) || (type == Token.MUL); } private void visitArithmetic(Node node, int opCode, Node child, Node parent) { int childNumberFlag = node.getIntProp(Node.ISNUMBER_PROP, -1); if (childNumberFlag != -1) { generateExpression(child, node); generateExpression(child.getNext(), node); cfw.add(opCode); } else { boolean childOfArithmetic = isArithmeticNode(parent); generateExpression(child, node); if (!isArithmeticNode(child)) addObjectToDouble(); generateExpression(child.getNext(), node); if (!isArithmeticNode(child.getNext())) addObjectToDouble(); cfw.add(opCode); if (!childOfArithmetic) { addDoubleWrap(); } } } private void visitBitOp(Node node, int type, Node child) { int childNumberFlag = node.getIntProp(Node.ISNUMBER_PROP, -1); generateExpression(child, node); // special-case URSH; work with the target arg as a long, so // that we can return a 32-bit unsigned value, and call // toUint32 instead of toInt32. if (type == Token.URSH) { addScriptRuntimeInvoke("toUint32", "(Ljava/lang/Object;)J"); generateExpression(child.getNext(), node); addScriptRuntimeInvoke("toInt32", "(Ljava/lang/Object;)I"); // Looks like we need to explicitly mask the shift to 5 bits - // LUSHR takes 6 bits. cfw.addPush(31); cfw.add(ByteCode.IAND); cfw.add(ByteCode.LUSHR); cfw.add(ByteCode.L2D); addDoubleWrap(); return; } if (childNumberFlag == -1) { addScriptRuntimeInvoke("toInt32", "(Ljava/lang/Object;)I"); generateExpression(child.getNext(), node); addScriptRuntimeInvoke("toInt32", "(Ljava/lang/Object;)I"); } else { addScriptRuntimeInvoke("toInt32", "(D)I"); generateExpression(child.getNext(), node); addScriptRuntimeInvoke("toInt32", "(D)I"); } switch (type) { case Token.BITOR: cfw.add(ByteCode.IOR); break; case Token.BITXOR: cfw.add(ByteCode.IXOR); break; case Token.BITAND: cfw.add(ByteCode.IAND); break; case Token.RSH: cfw.add(ByteCode.ISHR); break; case Token.LSH: cfw.add(ByteCode.ISHL); break; default: throw Codegen.badTree(); } cfw.add(ByteCode.I2D); if (childNumberFlag == -1) { addDoubleWrap(); } } private int nodeIsDirectCallParameter(Node node) { if (node.getType() == Token.GETVAR && inDirectCallFunction && !itsForcedObjectParameters) { int varIndex = fnCurrent.getVarIndex(node); if (fnCurrent.isParameter(varIndex)) { return varRegisters[varIndex]; } } return -1; } private boolean varIsDirectCallParameter(int varIndex) { return fnCurrent.isParameter(varIndex) && inDirectCallFunction && !itsForcedObjectParameters; } private void genSimpleCompare(int type, int trueGOTO, int falseGOTO) { if (trueGOTO == -1) throw Codegen.badTree(); switch (type) { case Token.LE : cfw.add(ByteCode.DCMPG); cfw.add(ByteCode.IFLE, trueGOTO); break; case Token.GE : cfw.add(ByteCode.DCMPL); cfw.add(ByteCode.IFGE, trueGOTO); break; case Token.LT : cfw.add(ByteCode.DCMPG); cfw.add(ByteCode.IFLT, trueGOTO); break; case Token.GT : cfw.add(ByteCode.DCMPL); cfw.add(ByteCode.IFGT, trueGOTO); break; default : throw Codegen.badTree(); } if (falseGOTO != -1) cfw.add(ByteCode.GOTO, falseGOTO); } private void visitIfJumpRelOp(Node node, Node child, int trueGOTO, int falseGOTO) { if (trueGOTO == -1 || falseGOTO == -1) throw Codegen.badTree(); int type = node.getType(); Node rChild = child.getNext(); if (type == Token.INSTANCEOF || type == Token.IN) { generateExpression(child, node); generateExpression(rChild, node); cfw.addALoad(contextLocal); addScriptRuntimeInvoke( (type == Token.INSTANCEOF) ? "instanceOf" : "in", "(Ljava/lang/Object;" +"Ljava/lang/Object;" +"Lorg/mozilla/javascript/Context;" +")Z"); cfw.add(ByteCode.IFNE, trueGOTO); cfw.add(ByteCode.GOTO, falseGOTO); return; } int childNumberFlag = node.getIntProp(Node.ISNUMBER_PROP, -1); int left_dcp_register = nodeIsDirectCallParameter(child); int right_dcp_register = nodeIsDirectCallParameter(rChild); if (childNumberFlag != -1) { // Force numeric context on both parameters and optimize // direct call case as Optimizer currently does not handle it if (childNumberFlag != Node.RIGHT) { // Left already has number content generateExpression(child, node); } else if (left_dcp_register != -1) { dcpLoadAsNumber(left_dcp_register); } else { generateExpression(child, node); addObjectToDouble(); } if (childNumberFlag != Node.LEFT) { // Right already has number content generateExpression(rChild, node); } else if (right_dcp_register != -1) { dcpLoadAsNumber(right_dcp_register); } else { generateExpression(rChild, node); addObjectToDouble(); } genSimpleCompare(type, trueGOTO, falseGOTO); } else { if (left_dcp_register != -1 && right_dcp_register != -1) { // Generate code to dynamically check for number content // if both operands are dcp short stack = cfw.getStackTop(); int leftIsNotNumber = cfw.acquireLabel(); cfw.addALoad(left_dcp_register); cfw.add(ByteCode.GETSTATIC, "java/lang/Void", "TYPE", "Ljava/lang/Class;"); cfw.add(ByteCode.IF_ACMPNE, leftIsNotNumber); cfw.addDLoad(left_dcp_register + 1); dcpLoadAsNumber(right_dcp_register); genSimpleCompare(type, trueGOTO, falseGOTO); if (stack != cfw.getStackTop()) throw Codegen.badTree(); cfw.markLabel(leftIsNotNumber); int rightIsNotNumber = cfw.acquireLabel(); cfw.addALoad(right_dcp_register); cfw.add(ByteCode.GETSTATIC, "java/lang/Void", "TYPE", "Ljava/lang/Class;"); cfw.add(ByteCode.IF_ACMPNE, rightIsNotNumber); cfw.addALoad(left_dcp_register); addObjectToDouble(); cfw.addDLoad(right_dcp_register + 1); genSimpleCompare(type, trueGOTO, falseGOTO); if (stack != cfw.getStackTop()) throw Codegen.badTree(); cfw.markLabel(rightIsNotNumber); // Load both register as objects to call generic cmp_* cfw.addALoad(left_dcp_register); cfw.addALoad(right_dcp_register); } else { generateExpression(child, node); generateExpression(rChild, node); } if (type == Token.GE || type == Token.GT) { cfw.add(ByteCode.SWAP); } String routine = ((type == Token.LT) || (type == Token.GT)) ? "cmp_LT" : "cmp_LE"; addScriptRuntimeInvoke(routine, "(Ljava/lang/Object;" +"Ljava/lang/Object;" +")Z"); cfw.add(ByteCode.IFNE, trueGOTO); cfw.add(ByteCode.GOTO, falseGOTO); } } private void visitIfJumpEqOp(Node node, Node child, int trueGOTO, int falseGOTO) { if (trueGOTO == -1 || falseGOTO == -1) throw Codegen.badTree(); short stackInitial = cfw.getStackTop(); int type = node.getType(); Node rChild = child.getNext(); // Optimize if one of operands is null if (child.getType() == Token.NULL || rChild.getType() == Token.NULL) { // eq is symmetric in this case if (child.getType() == Token.NULL) { child = rChild; } generateExpression(child, node); if (type == Token.SHEQ || type == Token.SHNE) { int testCode = (type == Token.SHEQ) ? ByteCode.IFNULL : ByteCode.IFNONNULL; cfw.add(testCode, trueGOTO); } else { if (type != Token.EQ) { // swap false/true targets for != if (type != Token.NE) throw Codegen.badTree(); int tmp = trueGOTO; trueGOTO = falseGOTO; falseGOTO = tmp; } cfw.add(ByteCode.DUP); int undefCheckLabel = cfw.acquireLabel(); cfw.add(ByteCode.IFNONNULL, undefCheckLabel); short stack = cfw.getStackTop(); cfw.add(ByteCode.POP); cfw.add(ByteCode.GOTO, trueGOTO); cfw.markLabel(undefCheckLabel, stack); Codegen.pushUndefined(cfw); cfw.add(ByteCode.IF_ACMPEQ, trueGOTO); } cfw.add(ByteCode.GOTO, falseGOTO); } else { int child_dcp_register = nodeIsDirectCallParameter(child); if (child_dcp_register != -1 && rChild.getType() == Token.TO_OBJECT) { Node convertChild = rChild.getFirstChild(); if (convertChild.getType() == Token.NUMBER) { cfw.addALoad(child_dcp_register); cfw.add(ByteCode.GETSTATIC, "java/lang/Void", "TYPE", "Ljava/lang/Class;"); int notNumbersLabel = cfw.acquireLabel(); cfw.add(ByteCode.IF_ACMPNE, notNumbersLabel); cfw.addDLoad(child_dcp_register + 1); cfw.addPush(convertChild.getDouble()); cfw.add(ByteCode.DCMPL); if (type == Token.EQ) cfw.add(ByteCode.IFEQ, trueGOTO); else cfw.add(ByteCode.IFNE, trueGOTO); cfw.add(ByteCode.GOTO, falseGOTO); cfw.markLabel(notNumbersLabel); // fall thru into generic handling } } generateExpression(child, node); generateExpression(rChild, node); String name; int testCode; switch (type) { case Token.EQ: name = "eq"; testCode = ByteCode.IFNE; break; case Token.NE: name = "eq"; testCode = ByteCode.IFEQ; break; case Token.SHEQ: name = "shallowEq"; testCode = ByteCode.IFNE; break; case Token.SHNE: name = "shallowEq"; testCode = ByteCode.IFEQ; break; default: throw Codegen.badTree(); } addScriptRuntimeInvoke(name, "(Ljava/lang/Object;" +"Ljava/lang/Object;" +")Z"); cfw.add(testCode, trueGOTO); cfw.add(ByteCode.GOTO, falseGOTO); } if (stackInitial != cfw.getStackTop()) throw Codegen.badTree(); } private void visitSetName(Node node, Node child) { String name = node.getFirstChild().getString(); while (child != null) { generateExpression(child, node); child = child.getNext(); } cfw.addALoad(contextLocal); cfw.addALoad(variableObjectLocal); cfw.addPush(name); addScriptRuntimeInvoke( "setName", "(Lorg/mozilla/javascript/Scriptable;" +"Ljava/lang/Object;" +"Lorg/mozilla/javascript/Context;" +"Lorg/mozilla/javascript/Scriptable;" +"Ljava/lang/String;" +")Ljava/lang/Object;"); } private void visitStrictSetName(Node node, Node child) { String name = node.getFirstChild().getString(); while (child != null) { generateExpression(child, node); child = child.getNext(); } cfw.addALoad(contextLocal); cfw.addALoad(variableObjectLocal); cfw.addPush(name); addScriptRuntimeInvoke( "strictSetName", "(Lorg/mozilla/javascript/Scriptable;" +"Ljava/lang/Object;" +"Lorg/mozilla/javascript/Context;" +"Lorg/mozilla/javascript/Scriptable;" +"Ljava/lang/String;" +")Ljava/lang/Object;"); } private void visitSetConst(Node node, Node child) { String name = node.getFirstChild().getString(); while (child != null) { generateExpression(child, node); child = child.getNext(); } cfw.addALoad(contextLocal); cfw.addPush(name); addScriptRuntimeInvoke( "setConst", "(Lorg/mozilla/javascript/Scriptable;" +"Ljava/lang/Object;" +"Lorg/mozilla/javascript/Context;" +"Ljava/lang/String;" +")Ljava/lang/Object;"); } private void visitGetVar(Node node) { if (!hasVarsInRegs) Kit.codeBug(); int varIndex = fnCurrent.getVarIndex(node); short reg = varRegisters[varIndex]; if (varIsDirectCallParameter(varIndex)) { // Remember that here the isNumber flag means that we // want to use the incoming parameter in a Number // context, so test the object type and convert the // value as necessary. if (node.getIntProp(Node.ISNUMBER_PROP, -1) != -1) { dcpLoadAsNumber(reg); } else { dcpLoadAsObject(reg); } } else if (fnCurrent.isNumberVar(varIndex)) { cfw.addDLoad(reg); } else { cfw.addALoad(reg); } } private void visitSetVar(Node node, Node child, boolean needValue) { if (!hasVarsInRegs) Kit.codeBug(); int varIndex = fnCurrent.getVarIndex(node); generateExpression(child.getNext(), node); boolean isNumber = (node.getIntProp(Node.ISNUMBER_PROP, -1) != -1); short reg = varRegisters[varIndex]; boolean [] constDeclarations = fnCurrent.fnode.getParamAndVarConst(); if (constDeclarations[varIndex]) { if (!needValue) { if (isNumber) cfw.add(ByteCode.POP2); else cfw.add(ByteCode.POP); } } else if (varIsDirectCallParameter(varIndex)) { if (isNumber) { if (needValue) cfw.add(ByteCode.DUP2); cfw.addALoad(reg); cfw.add(ByteCode.GETSTATIC, "java/lang/Void", "TYPE", "Ljava/lang/Class;"); int isNumberLabel = cfw.acquireLabel(); int beyond = cfw.acquireLabel(); cfw.add(ByteCode.IF_ACMPEQ, isNumberLabel); short stack = cfw.getStackTop(); addDoubleWrap(); cfw.addAStore(reg); cfw.add(ByteCode.GOTO, beyond); cfw.markLabel(isNumberLabel, stack); cfw.addDStore(reg + 1); cfw.markLabel(beyond); } else { if (needValue) cfw.add(ByteCode.DUP); cfw.addAStore(reg); } } else { boolean isNumberVar = fnCurrent.isNumberVar(varIndex); if (isNumber) { if (isNumberVar) { cfw.addDStore(reg); if (needValue) cfw.addDLoad(reg); } else { if (needValue) cfw.add(ByteCode.DUP2); // Cannot save number in variable since !isNumberVar, // so convert to object addDoubleWrap(); cfw.addAStore(reg); } } else { if (isNumberVar) Kit.codeBug(); cfw.addAStore(reg); if (needValue) cfw.addALoad(reg); } } } private void visitSetConstVar(Node node, Node child, boolean needValue) { if (!hasVarsInRegs) Kit.codeBug(); int varIndex = fnCurrent.getVarIndex(node); generateExpression(child.getNext(), node); boolean isNumber = (node.getIntProp(Node.ISNUMBER_PROP, -1) != -1); short reg = varRegisters[varIndex]; int beyond = cfw.acquireLabel(); int noAssign = cfw.acquireLabel(); if (isNumber) { cfw.addILoad(reg + 2); cfw.add(ByteCode.IFNE, noAssign); short stack = cfw.getStackTop(); cfw.addPush(1); cfw.addIStore(reg + 2); cfw.addDStore(reg); if (needValue) { cfw.addDLoad(reg); cfw.markLabel(noAssign, stack); } else { cfw.add(ByteCode.GOTO, beyond); cfw.markLabel(noAssign, stack); cfw.add(ByteCode.POP2); } } else { cfw.addILoad(reg + 1); cfw.add(ByteCode.IFNE, noAssign); short stack = cfw.getStackTop(); cfw.addPush(1); cfw.addIStore(reg + 1); cfw.addAStore(reg); if (needValue) { cfw.addALoad(reg); cfw.markLabel(noAssign, stack); } else { cfw.add(ByteCode.GOTO, beyond); cfw.markLabel(noAssign, stack); cfw.add(ByteCode.POP); } } cfw.markLabel(beyond); } private void visitGetProp(Node node, Node child) { generateExpression(child, node); // object Node nameChild = child.getNext(); generateExpression(nameChild, node); // the name if (node.getType() == Token.GETPROPNOWARN) { cfw.addALoad(contextLocal); addScriptRuntimeInvoke( "getObjectPropNoWarn", "(Ljava/lang/Object;" +"Ljava/lang/String;" +"Lorg/mozilla/javascript/Context;" +")Ljava/lang/Object;"); return; } /* for 'this.foo' we call getObjectProp(Scriptable...) which can skip some casting overhead. */ int childType = child.getType(); if (childType == Token.THIS && nameChild.getType() == Token.STRING) { cfw.addALoad(contextLocal); addScriptRuntimeInvoke( "getObjectProp", "(Lorg/mozilla/javascript/Scriptable;" +"Ljava/lang/String;" +"Lorg/mozilla/javascript/Context;" +")Ljava/lang/Object;"); } else { cfw.addALoad(contextLocal); cfw.addALoad(variableObjectLocal); addScriptRuntimeInvoke( "getObjectProp", "(Ljava/lang/Object;" +"Ljava/lang/String;" +"Lorg/mozilla/javascript/Context;" +"Lorg/mozilla/javascript/Scriptable;" +")Ljava/lang/Object;"); } } private void visitSetProp(int type, Node node, Node child) { Node objectChild = child; generateExpression(child, node); child = child.getNext(); if (type == Token.SETPROP_OP) { cfw.add(ByteCode.DUP); } Node nameChild = child; generateExpression(child, node); child = child.getNext(); if (type == Token.SETPROP_OP) { // stack: ... object object name -> ... object name object name cfw.add(ByteCode.DUP_X1); //for 'this.foo += ...' we call thisGet which can skip some //casting overhead. if (objectChild.getType() == Token.THIS && nameChild.getType() == Token.STRING) { cfw.addALoad(contextLocal); addScriptRuntimeInvoke( "getObjectProp", "(Lorg/mozilla/javascript/Scriptable;" +"Ljava/lang/String;" +"Lorg/mozilla/javascript/Context;" +")Ljava/lang/Object;"); } else { cfw.addALoad(contextLocal); addScriptRuntimeInvoke( "getObjectProp", "(Ljava/lang/Object;" +"Ljava/lang/String;" +"Lorg/mozilla/javascript/Context;" +")Ljava/lang/Object;"); } } generateExpression(child, node); cfw.addALoad(contextLocal); addScriptRuntimeInvoke( "setObjectProp", "(Ljava/lang/Object;" +"Ljava/lang/String;" +"Ljava/lang/Object;" +"Lorg/mozilla/javascript/Context;" +")Ljava/lang/Object;"); } private void visitSetElem(int type, Node node, Node child) { generateExpression(child, node); child = child.getNext(); if (type == Token.SETELEM_OP) { cfw.add(ByteCode.DUP); } generateExpression(child, node); child = child.getNext(); boolean indexIsNumber = (node.getIntProp(Node.ISNUMBER_PROP, -1) != -1); if (type == Token.SETELEM_OP) { if (indexIsNumber) { // stack: ... object object number // -> ... object number object number cfw.add(ByteCode.DUP2_X1); cfw.addALoad(contextLocal); addOptRuntimeInvoke( "getObjectIndex", "(Ljava/lang/Object;D" +"Lorg/mozilla/javascript/Context;" +")Ljava/lang/Object;"); } else { // stack: ... object object indexObject // -> ... object indexObject object indexObject cfw.add(ByteCode.DUP_X1); cfw.addALoad(contextLocal); addScriptRuntimeInvoke( "getObjectElem", "(Ljava/lang/Object;" +"Ljava/lang/Object;" +"Lorg/mozilla/javascript/Context;" +")Ljava/lang/Object;"); } } generateExpression(child, node); cfw.addALoad(contextLocal); if (indexIsNumber) { addScriptRuntimeInvoke( "setObjectIndex", "(Ljava/lang/Object;" +"D" +"Ljava/lang/Object;" +"Lorg/mozilla/javascript/Context;" +")Ljava/lang/Object;"); } else { addScriptRuntimeInvoke( "setObjectElem", "(Ljava/lang/Object;" +"Ljava/lang/Object;" +"Ljava/lang/Object;" +"Lorg/mozilla/javascript/Context;" +")Ljava/lang/Object;"); } } private void visitDotQuery(Node node, Node child) { updateLineNumber(node); generateExpression(child, node); cfw.addALoad(variableObjectLocal); addScriptRuntimeInvoke("enterDotQuery", "(Ljava/lang/Object;" +"Lorg/mozilla/javascript/Scriptable;" +")Lorg/mozilla/javascript/Scriptable;"); cfw.addAStore(variableObjectLocal); // add push null/pop with label in between to simplify code for loop // continue when it is necessary to pop the null result from // updateDotQuery cfw.add(ByteCode.ACONST_NULL); int queryLoopStart = cfw.acquireLabel(); cfw.markLabel(queryLoopStart); // loop continue jumps here cfw.add(ByteCode.POP); generateExpression(child.getNext(), node); addScriptRuntimeInvoke("toBoolean", "(Ljava/lang/Object;)Z"); cfw.addALoad(variableObjectLocal); addScriptRuntimeInvoke("updateDotQuery", "(Z" +"Lorg/mozilla/javascript/Scriptable;" +")Ljava/lang/Object;"); cfw.add(ByteCode.DUP); cfw.add(ByteCode.IFNULL, queryLoopStart); // stack: ... non_null_result_of_updateDotQuery cfw.addALoad(variableObjectLocal); addScriptRuntimeInvoke("leaveDotQuery", "(Lorg/mozilla/javascript/Scriptable;" +")Lorg/mozilla/javascript/Scriptable;"); cfw.addAStore(variableObjectLocal); } private int getLocalBlockRegister(Node node) { Node localBlock = (Node)node.getProp(Node.LOCAL_BLOCK_PROP); int localSlot = localBlock.getExistingIntProp(Node.LOCAL_PROP); return localSlot; } private void dcpLoadAsNumber(int dcp_register) { cfw.addALoad(dcp_register); cfw.add(ByteCode.GETSTATIC, "java/lang/Void", "TYPE", "Ljava/lang/Class;"); int isNumberLabel = cfw.acquireLabel(); cfw.add(ByteCode.IF_ACMPEQ, isNumberLabel); short stack = cfw.getStackTop(); cfw.addALoad(dcp_register); addObjectToDouble(); int beyond = cfw.acquireLabel(); cfw.add(ByteCode.GOTO, beyond); cfw.markLabel(isNumberLabel, stack); cfw.addDLoad(dcp_register + 1); cfw.markLabel(beyond); } private void dcpLoadAsObject(int dcp_register) { cfw.addALoad(dcp_register); cfw.add(ByteCode.GETSTATIC, "java/lang/Void", "TYPE", "Ljava/lang/Class;"); int isNumberLabel = cfw.acquireLabel(); cfw.add(ByteCode.IF_ACMPEQ, isNumberLabel); short stack = cfw.getStackTop(); cfw.addALoad(dcp_register); int beyond = cfw.acquireLabel(); cfw.add(ByteCode.GOTO, beyond); cfw.markLabel(isNumberLabel, stack); cfw.addDLoad(dcp_register + 1); addDoubleWrap(); cfw.markLabel(beyond); } private void addGoto(Node target, int jumpcode) { int targetLabel = getTargetLabel(target); cfw.add(jumpcode, targetLabel); } private void addObjectToDouble() { addScriptRuntimeInvoke("toNumber", "(Ljava/lang/Object;)D"); } private void addNewObjectArray(int size) { if (size == 0) { if (itsZeroArgArray >= 0) { cfw.addALoad(itsZeroArgArray); } else { cfw.add(ByteCode.GETSTATIC, "org/mozilla/javascript/ScriptRuntime", "emptyArgs", "[Ljava/lang/Object;"); } } else { cfw.addPush(size); cfw.add(ByteCode.ANEWARRAY, "java/lang/Object"); } } private void addScriptRuntimeInvoke(String methodName, String methodSignature) { cfw.addInvoke(ByteCode.INVOKESTATIC, "org.mozilla.javascript.ScriptRuntime", methodName, methodSignature); } private void addOptRuntimeInvoke(String methodName, String methodSignature) { cfw.addInvoke(ByteCode.INVOKESTATIC, "org/mozilla/javascript/optimizer/OptRuntime", methodName, methodSignature); } private void addJumpedBooleanWrap(int trueLabel, int falseLabel) { cfw.markLabel(falseLabel); int skip = cfw.acquireLabel(); cfw.add(ByteCode.GETSTATIC, "java/lang/Boolean", "FALSE", "Ljava/lang/Boolean;"); cfw.add(ByteCode.GOTO, skip); cfw.markLabel(trueLabel); cfw.add(ByteCode.GETSTATIC, "java/lang/Boolean", "TRUE", "Ljava/lang/Boolean;"); cfw.markLabel(skip); cfw.adjustStackTop(-1); // only have 1 of true/false } private void addDoubleWrap() { addOptRuntimeInvoke("wrapDouble", "(D)Ljava/lang/Double;"); } /** * Const locals use an extra slot to hold the has-been-assigned-once flag at * runtime. * @param isConst true iff the variable is const * @return the register for the word pair (double/long) */ private short getNewWordPairLocal(boolean isConst) { short result = getConsecutiveSlots(2, isConst); if (result < (MAX_LOCALS - 1)) { locals[result] = 1; locals[result + 1] = 1; if (isConst) locals[result + 2] = 1; if (result == firstFreeLocal) { for (int i = firstFreeLocal + 2; i < MAX_LOCALS; i++) { if (locals[i] == 0) { firstFreeLocal = (short) i; if (localsMax < firstFreeLocal) localsMax = firstFreeLocal; return result; } } } else { return result; } } throw Context.reportRuntimeError("Program too complex " + "(out of locals)"); } private short getNewWordLocal(boolean isConst) { short result = getConsecutiveSlots(1, isConst); if (result < (MAX_LOCALS - 1)) { locals[result] = 1; if (isConst) locals[result + 1] = 1; if (result == firstFreeLocal) { for (int i = firstFreeLocal + 2; i < MAX_LOCALS; i++) { if (locals[i] == 0) { firstFreeLocal = (short) i; if (localsMax < firstFreeLocal) localsMax = firstFreeLocal; return result; } } } else { return result; } } throw Context.reportRuntimeError("Program too complex " + "(out of locals)"); } private short getNewWordLocal() { short result = firstFreeLocal; locals[result] = 1; for (int i = firstFreeLocal + 1; i < MAX_LOCALS; i++) { if (locals[i] == 0) { firstFreeLocal = (short) i; if (localsMax < firstFreeLocal) localsMax = firstFreeLocal; return result; } } throw Context.reportRuntimeError("Program too complex " + "(out of locals)"); } private short getConsecutiveSlots(int count, boolean isConst) { if (isConst) count++; short result = firstFreeLocal; while (true) { if (result >= (MAX_LOCALS - 1)) break; int i; for (i = 0; i < count; i++) if (locals[result + i] != 0) break; if (i >= count) break; result++; } return result; } // This is a valid call only for a local that is allocated by default. private void incReferenceWordLocal(short local) { locals[local]++; } // This is a valid call only for a local that is allocated by default. private void decReferenceWordLocal(short local) { locals[local]--; } private void releaseWordLocal(short local) { if (local < firstFreeLocal) firstFreeLocal = local; locals[local] = 0; } static final int GENERATOR_TERMINATE = -1; static final int GENERATOR_START = 0; static final int GENERATOR_YIELD_START = 1; ClassFileWriter cfw; Codegen codegen; CompilerEnvirons compilerEnv; ScriptNode scriptOrFn; public int scriptOrFnIndex; private int savedCodeOffset; private OptFunctionNode fnCurrent; private boolean isTopLevel; private static final int MAX_LOCALS = 256; private int[] locals; private short firstFreeLocal; private short localsMax; private int itsLineNumber; private boolean hasVarsInRegs; private short[] varRegisters; private boolean inDirectCallFunction; private boolean itsForcedObjectParameters; private int enterAreaStartLabel; private int epilogueLabel; // special known locals. If you add a new local here, be sure // to initialize it to -1 in initBodyGeneration private short variableObjectLocal; private short popvLocal; private short contextLocal; private short argsLocal; private short operationLocal; private short thisObjLocal; private short funObjLocal; private short itsZeroArgArray; private short itsOneArgArray; private short scriptRegexpLocal; private short generatorStateLocal; private boolean isGenerator; private int generatorSwitch; private int maxLocals = 0; private int maxStack = 0; private Map finallys; static class FinallyReturnPoint { public List jsrPoints = new ArrayList(); public int tableLabel = 0; } } htmlunit-core-js-2.8/rhino/src/org/mozilla/javascript/optimizer/DataFlowBitSet.java0000644000175000017500000000770510776622373030450 0ustar cavedoncavedon/* ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is Rhino code, released * May 6, 1999. * * The Initial Developer of the Original Code is * Netscape Communications Corporation. * Portions created by the Initial Developer are Copyright (C) 1997-1999 * the Initial Developer. All Rights Reserved. * * Contributor(s): * Norris Boyd * Roger Lawrence * * Alternatively, the contents of this file may be used under the terms of * the GNU General Public License Version 2 or later (the "GPL"), in which * case the provisions of the GPL are applicable instead of those above. If * you wish to allow use of your version of this file only under the terms of * the GPL and not to allow others to use your version of this file under the * MPL, indicate your decision by deleting the provisions above and replacing * them with the notice and other provisions required by the GPL. If you do * not delete the provisions above, a recipient may use your version of this * file under either the MPL or the GPL. * * ***** END LICENSE BLOCK ***** */ package org.mozilla.javascript.optimizer; class DataFlowBitSet { private int itsBits[]; private int itsSize; DataFlowBitSet(int size) { itsSize = size; itsBits = new int[(size + 31) >> 5]; } void set(int n) { if (!(0 <= n && n < itsSize)) badIndex(n); itsBits[n >> 5] |= 1 << (n & 31); } boolean test(int n) { if (!(0 <= n && n < itsSize)) badIndex(n); return ((itsBits[n >> 5] & (1 << (n & 31))) != 0); } void not() { int bitsLength = itsBits.length; for (int i = 0; i < bitsLength; i++) itsBits[i] = ~itsBits[i]; } void clear(int n) { if (!(0 <= n && n < itsSize)) badIndex(n); itsBits[n >> 5] &= ~(1 << (n & 31)); } void clear() { int bitsLength = itsBits.length; for (int i = 0; i < bitsLength; i++) itsBits[i] = 0; } void or(DataFlowBitSet b) { int bitsLength = itsBits.length; for (int i = 0; i < bitsLength; i++) itsBits[i] |= b.itsBits[i]; } @Override public String toString() { StringBuffer sb = new StringBuffer(); sb.append("DataFlowBitSet, size = "); sb.append(itsSize); sb.append('\n'); int bitsLength = itsBits.length; for (int i = 0; i < bitsLength; i++) { sb.append(Integer.toHexString(itsBits[i])); sb.append(' '); } return sb.toString(); } boolean df(DataFlowBitSet in, DataFlowBitSet gen, DataFlowBitSet notKill) { int bitsLength = itsBits.length; boolean changed = false; for (int i = 0; i < bitsLength; i++) { int oldBits = itsBits[i]; itsBits[i] = (in.itsBits[i] | gen.itsBits[i]) & notKill.itsBits[i]; changed |= (oldBits != itsBits[i]); } return changed; } boolean df2(DataFlowBitSet in, DataFlowBitSet gen, DataFlowBitSet notKill) { int bitsLength = itsBits.length; boolean changed = false; for (int i = 0; i < bitsLength; i++) { int oldBits = itsBits[i]; itsBits[i] = (in.itsBits[i] & notKill.itsBits[i]) | gen.itsBits[i]; changed |= (oldBits != itsBits[i]); } return changed; } private void badIndex(int n) { throw new RuntimeException("DataFlowBitSet bad index " + n); } } htmlunit-core-js-2.8/rhino/src/org/mozilla/javascript/optimizer/OptFunctionNode.java0000644000175000017500000001062111222455466030673 0ustar cavedoncavedon/* ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is Rhino code, released * May 6, 1999. * * The Initial Developer of the Original Code is * Netscape Communications Corporation. * Portions created by the Initial Developer are Copyright (C) 1997-1999 * the Initial Developer. All Rights Reserved. * * Contributor(s): * Norris Boyd * Bob Jervis * Roger Lawrence * * Alternatively, the contents of this file may be used under the terms of * the GNU General Public License Version 2 or later (the "GPL"), in which * case the provisions of the GPL are applicable instead of those above. If * you wish to allow use of your version of this file only under the terms of * the GPL and not to allow others to use your version of this file under the * MPL, indicate your decision by deleting the provisions above and replacing * them with the notice and other provisions required by the GPL. If you do * not delete the provisions above, a recipient may use your version of this * file under either the MPL or the GPL. * * ***** END LICENSE BLOCK ***** */ package org.mozilla.javascript.optimizer; import org.mozilla.javascript.*; import org.mozilla.javascript.ast.FunctionNode; import org.mozilla.javascript.ast.ScriptNode; final class OptFunctionNode { OptFunctionNode(FunctionNode fnode) { this.fnode = fnode; fnode.setCompilerData(this); } static OptFunctionNode get(ScriptNode scriptOrFn, int i) { FunctionNode fnode = scriptOrFn.getFunctionNode(i); return (OptFunctionNode)fnode.getCompilerData(); } static OptFunctionNode get(ScriptNode scriptOrFn) { return (OptFunctionNode)scriptOrFn.getCompilerData(); } boolean isTargetOfDirectCall() { return directTargetIndex >= 0; } int getDirectTargetIndex() { return directTargetIndex; } void setDirectTargetIndex(int directTargetIndex) { // One time action if (directTargetIndex < 0 || this.directTargetIndex >= 0) Kit.codeBug(); this.directTargetIndex = directTargetIndex; } void setParameterNumberContext(boolean b) { itsParameterNumberContext = b; } boolean getParameterNumberContext() { return itsParameterNumberContext; } int getVarCount() { return fnode.getParamAndVarCount(); } boolean isParameter(int varIndex) { return varIndex < fnode.getParamCount(); } boolean isNumberVar(int varIndex) { varIndex -= fnode.getParamCount(); if (varIndex >= 0 && numberVarFlags != null) { return numberVarFlags[varIndex]; } return false; } void setIsNumberVar(int varIndex) { varIndex -= fnode.getParamCount(); // Can only be used with non-parameters if (varIndex < 0) Kit.codeBug(); if (numberVarFlags == null) { int size = fnode.getParamAndVarCount() - fnode.getParamCount(); numberVarFlags = new boolean[size]; } numberVarFlags[varIndex] = true; } int getVarIndex(Node n) { int index = n.getIntProp(Node.VARIABLE_PROP, -1); if (index == -1) { Node node; int type = n.getType(); if (type == Token.GETVAR) { node = n; } else if (type == Token.SETVAR || type == Token.SETCONSTVAR) { node = n.getFirstChild(); } else { throw Kit.codeBug(); } index = fnode.getIndexForNameNode(node); if (index < 0) throw Kit.codeBug(); n.putIntProp(Node.VARIABLE_PROP, index); } return index; } FunctionNode fnode; private boolean[] numberVarFlags; private int directTargetIndex = -1; private boolean itsParameterNumberContext; boolean itsContainsCalls0; boolean itsContainsCalls1; } htmlunit-core-js-2.8/rhino/src/org/mozilla/javascript/optimizer/Block.java0000644000175000017500000005335611222455466026663 0ustar cavedoncavedon/* ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is Rhino code, released * May 6, 1999. * * The Initial Developer of the Original Code is * Netscape Communications Corporation. * Portions created by the Initial Developer are Copyright (C) 1997-1999 * the Initial Developer. All Rights Reserved. * * Contributor(s): * Norris Boyd * Igor Bukanov * Roger Lawrence * Cameron McCormack * * Alternatively, the contents of this file may be used under the terms of * the GNU General Public License Version 2 or later (the "GPL"), in which * case the provisions of the GPL are applicable instead of those above. If * you wish to allow use of your version of this file only under the terms of * the GPL and not to allow others to use your version of this file under the * MPL, indicate your decision by deleting the provisions above and replacing * them with the notice and other provisions required by the GPL. If you do * not delete the provisions above, a recipient may use your version of this * file under either the MPL or the GPL. * * ***** END LICENSE BLOCK ***** */ package org.mozilla.javascript.optimizer; import org.mozilla.javascript.*; import org.mozilla.javascript.ast.Jump; import java.util.HashMap; import java.util.Map; import java.io.PrintWriter; import java.io.StringWriter; class Block { private static class FatBlock { private static Block[] reduceToArray(ObjToIntMap map) { Block[] result = null; if (!map.isEmpty()) { result = new Block[map.size()]; int i = 0; ObjToIntMap.Iterator iter = map.newIterator(); for (iter.start(); !iter.done(); iter.next()) { FatBlock fb = (FatBlock)(iter.getKey()); result[i++] = fb.realBlock; } } return result; } void addSuccessor(FatBlock b) { successors.put(b, 0); } void addPredecessor(FatBlock b) { predecessors.put(b, 0); } Block[] getSuccessors() { return reduceToArray(successors); } Block[] getPredecessors() { return reduceToArray(predecessors); } // all the Blocks that come immediately after this private ObjToIntMap successors = new ObjToIntMap(); // all the Blocks that come immediately before this private ObjToIntMap predecessors = new ObjToIntMap(); Block realBlock; } Block(int startNodeIndex, int endNodeIndex) { itsStartNodeIndex = startNodeIndex; itsEndNodeIndex = endNodeIndex; } static void runFlowAnalyzes(OptFunctionNode fn, Node[] statementNodes) { int paramCount = fn.fnode.getParamCount(); int varCount = fn.fnode.getParamAndVarCount(); int[] varTypes = new int[varCount]; // If the variable is a parameter, it could have any type. for (int i = 0; i != paramCount; ++i) { varTypes[i] = Optimizer.AnyType; } // If the variable is from a "var" statement, its typeEvent will be set // when we see the setVar node. for (int i = paramCount; i != varCount; ++i) { varTypes[i] = Optimizer.NoType; } Block[] theBlocks = buildBlocks(statementNodes); if (DEBUG) { ++debug_blockCount; System.out.println("-------------------"+fn.fnode.getFunctionName()+" "+debug_blockCount+"--------"); System.out.println(toString(theBlocks, statementNodes)); } reachingDefDataFlow(fn, statementNodes, theBlocks, varTypes); typeFlow(fn, statementNodes, theBlocks, varTypes); if (DEBUG) { for (int i = 0; i < theBlocks.length; i++) { System.out.println("For block " + theBlocks[i].itsBlockID); theBlocks[i].printLiveOnEntrySet(fn); } System.out.println("Variable Table, size = " + varCount); for (int i = 0; i != varCount; i++) { System.out.println("["+i+"] type: "+varTypes[i]); } } for (int i = paramCount; i != varCount; i++) { if (varTypes[i] == Optimizer.NumberType) { fn.setIsNumberVar(i); } } } private static Block[] buildBlocks(Node[] statementNodes) { // a mapping from each target node to the block it begins Map theTargetBlocks = new HashMap(); ObjArray theBlocks = new ObjArray(); // there's a block that starts at index 0 int beginNodeIndex = 0; for (int i = 0; i < statementNodes.length; i++) { switch (statementNodes[i].getType()) { case Token.TARGET : { if (i != beginNodeIndex) { FatBlock fb = newFatBlock(beginNodeIndex, i - 1); if (statementNodes[beginNodeIndex].getType() == Token.TARGET) theTargetBlocks.put(statementNodes[beginNodeIndex], fb); theBlocks.add(fb); // start the next block at this node beginNodeIndex = i; } } break; case Token.IFNE : case Token.IFEQ : case Token.GOTO : { FatBlock fb = newFatBlock(beginNodeIndex, i); if (statementNodes[beginNodeIndex].getType() == Token.TARGET) theTargetBlocks.put(statementNodes[beginNodeIndex], fb); theBlocks.add(fb); // start the next block at the next node beginNodeIndex = i + 1; } break; } } if (beginNodeIndex != statementNodes.length) { FatBlock fb = newFatBlock(beginNodeIndex, statementNodes.length - 1); if (statementNodes[beginNodeIndex].getType() == Token.TARGET) theTargetBlocks.put(statementNodes[beginNodeIndex], fb); theBlocks.add(fb); } // build successor and predecessor links for (int i = 0; i < theBlocks.size(); i++) { FatBlock fb = (FatBlock)(theBlocks.get(i)); Node blockEndNode = statementNodes[fb.realBlock.itsEndNodeIndex]; int blockEndNodeType = blockEndNode.getType(); if ((blockEndNodeType != Token.GOTO) && (i < (theBlocks.size() - 1))) { FatBlock fallThruTarget = (FatBlock)(theBlocks.get(i + 1)); fb.addSuccessor(fallThruTarget); fallThruTarget.addPredecessor(fb); } if ( (blockEndNodeType == Token.IFNE) || (blockEndNodeType == Token.IFEQ) || (blockEndNodeType == Token.GOTO) ) { Node target = ((Jump)blockEndNode).target; FatBlock branchTargetBlock = theTargetBlocks.get(target); target.putProp(Node.TARGETBLOCK_PROP, branchTargetBlock.realBlock); fb.addSuccessor(branchTargetBlock); branchTargetBlock.addPredecessor(fb); } } Block[] result = new Block[theBlocks.size()]; for (int i = 0; i < theBlocks.size(); i++) { FatBlock fb = (FatBlock)(theBlocks.get(i)); Block b = fb.realBlock; b.itsSuccessors = fb.getSuccessors(); b.itsPredecessors = fb.getPredecessors(); b.itsBlockID = i; result[i] = b; } return result; } private static FatBlock newFatBlock(int startNodeIndex, int endNodeIndex) { FatBlock fb = new FatBlock(); fb.realBlock = new Block(startNodeIndex, endNodeIndex); return fb; } private static String toString(Block[] blockList, Node[] statementNodes) { if (!DEBUG) return null; StringWriter sw = new StringWriter(); PrintWriter pw = new PrintWriter(sw); pw.println(blockList.length + " Blocks"); for (int i = 0; i < blockList.length; i++) { Block b = blockList[i]; pw.println("#" + b.itsBlockID); pw.println("from " + b.itsStartNodeIndex + " " + statementNodes[b.itsStartNodeIndex].toString()); pw.println("thru " + b.itsEndNodeIndex + " " + statementNodes[b.itsEndNodeIndex].toString()); pw.print("Predecessors "); if (b.itsPredecessors != null) { for (int j = 0; j < b.itsPredecessors.length; j++) pw.print(b.itsPredecessors[j].itsBlockID + " "); pw.println(); } else pw.println("none"); pw.print("Successors "); if (b.itsSuccessors != null) { for (int j = 0; j < b.itsSuccessors.length; j++) pw.print(b.itsSuccessors[j].itsBlockID + " "); pw.println(); } else pw.println("none"); } return sw.toString(); } private static void reachingDefDataFlow(OptFunctionNode fn, Node[] statementNodes, Block theBlocks[], int[] varTypes) { /* initialize the liveOnEntry and liveOnExit sets, then discover the variables that are def'd by each function, and those that are used before being def'd (hence liveOnEntry) */ for (int i = 0; i < theBlocks.length; i++) { theBlocks[i].initLiveOnEntrySets(fn, statementNodes); } /* this visits every block starting at the last, re-adding the predecessors of any block whose inputs change as a result of the dataflow. REMIND, better would be to visit in CFG postorder */ boolean visit[] = new boolean[theBlocks.length]; boolean doneOnce[] = new boolean[theBlocks.length]; int vIndex = theBlocks.length - 1; boolean needRescan = false; visit[vIndex] = true; while (true) { if (visit[vIndex] || !doneOnce[vIndex]) { doneOnce[vIndex] = true; visit[vIndex] = false; if (theBlocks[vIndex].doReachedUseDataFlow()) { Block pred[] = theBlocks[vIndex].itsPredecessors; if (pred != null) { for (int i = 0; i < pred.length; i++) { int index = pred[i].itsBlockID; visit[index] = true; needRescan |= (index > vIndex); } } } } if (vIndex == 0) { if (needRescan) { vIndex = theBlocks.length - 1; needRescan = false; } else break; } else vIndex--; } /* if any variable is live on entry to block 0, we have to mark it as not jRegable - since it means that someone is trying to access the 'undefined'-ness of that variable. */ theBlocks[0].markAnyTypeVariables(varTypes); } private static void typeFlow(OptFunctionNode fn, Node[] statementNodes, Block theBlocks[], int[] varTypes) { boolean visit[] = new boolean[theBlocks.length]; boolean doneOnce[] = new boolean[theBlocks.length]; int vIndex = 0; boolean needRescan = false; visit[vIndex] = true; while (true) { if (visit[vIndex] || !doneOnce[vIndex]) { doneOnce[vIndex] = true; visit[vIndex] = false; if (theBlocks[vIndex].doTypeFlow(fn, statementNodes, varTypes)) { Block succ[] = theBlocks[vIndex].itsSuccessors; if (succ != null) { for (int i = 0; i < succ.length; i++) { int index = succ[i].itsBlockID; visit[index] = true; needRescan |= (index < vIndex); } } } } if (vIndex == (theBlocks.length - 1)) { if (needRescan) { vIndex = 0; needRescan = false; } else break; } else vIndex++; } } private static boolean assignType(int[] varTypes, int index, int type) { return type != (varTypes[index] |= type); } private void markAnyTypeVariables(int[] varTypes) { for (int i = 0; i != varTypes.length; i++) { if (itsLiveOnEntrySet.test(i)) { assignType(varTypes, i, Optimizer.AnyType); } } } /* We're tracking uses and defs - in order to build the def set and to identify the last use nodes. The itsNotDefSet is built reversed then flipped later. */ private void lookForVariableAccess(OptFunctionNode fn, Node n) { switch (n.getType()) { case Token.DEC : case Token.INC : { Node child = n.getFirstChild(); if (child.getType() == Token.GETVAR) { int varIndex = fn.getVarIndex(child); if (!itsNotDefSet.test(varIndex)) itsUseBeforeDefSet.set(varIndex); itsNotDefSet.set(varIndex); } } break; case Token.SETVAR : { Node lhs = n.getFirstChild(); Node rhs = lhs.getNext(); lookForVariableAccess(fn, rhs); itsNotDefSet.set(fn.getVarIndex(n)); } break; case Token.GETVAR : { int varIndex = fn.getVarIndex(n); if (!itsNotDefSet.test(varIndex)) itsUseBeforeDefSet.set(varIndex); } break; default : Node child = n.getFirstChild(); while (child != null) { lookForVariableAccess(fn, child); child = child.getNext(); } break; } } /* build the live on entry/exit sets. Then walk the trees looking for defs/uses of variables and build the def and useBeforeDef sets. */ private void initLiveOnEntrySets(OptFunctionNode fn, Node[] statementNodes) { int listLength = fn.getVarCount(); itsUseBeforeDefSet = new DataFlowBitSet(listLength); itsNotDefSet = new DataFlowBitSet(listLength); itsLiveOnEntrySet = new DataFlowBitSet(listLength); itsLiveOnExitSet = new DataFlowBitSet(listLength); for (int i = itsStartNodeIndex; i <= itsEndNodeIndex; i++) { Node n = statementNodes[i]; lookForVariableAccess(fn, n); } itsNotDefSet.not(); // truth in advertising } /* the liveOnEntry of each successor is the liveOnExit for this block. The liveOnEntry for this block is - liveOnEntry = liveOnExit - defsInThisBlock + useBeforeDefsInThisBlock */ private boolean doReachedUseDataFlow() { itsLiveOnExitSet.clear(); if (itsSuccessors != null) for (int i = 0; i < itsSuccessors.length; i++) itsLiveOnExitSet.or(itsSuccessors[i].itsLiveOnEntrySet); return itsLiveOnEntrySet.df2(itsLiveOnExitSet, itsUseBeforeDefSet, itsNotDefSet); } /* the type of an expression is relatively unknown. Cases we can be sure about are - Literals, Arithmetic operations - always return a Number */ private static int findExpressionType(OptFunctionNode fn, Node n, int[] varTypes) { switch (n.getType()) { case Token.NUMBER: return Optimizer.NumberType; case Token.CALL: case Token.NEW: case Token.REF_CALL: return Optimizer.AnyType; case Token.GETELEM: return Optimizer.AnyType; case Token.GETVAR: return varTypes[fn.getVarIndex(n)]; case Token.INC: case Token.DEC: case Token.MUL: case Token.DIV: case Token.MOD: case Token.BITOR: case Token.BITXOR: case Token.BITAND: case Token.LSH: case Token.RSH: case Token.URSH: case Token.SUB: case Token.POS: case Token.NEG: return Optimizer.NumberType; case Token.ARRAYLIT: case Token.OBJECTLIT: return Optimizer.AnyType; // XXX: actually, we know it's not // number, but no type yet for that case Token.ADD: { // if the lhs & rhs are known to be numbers, we can be sure that's // the result, otherwise it could be a string. Node child = n.getFirstChild(); int lType = findExpressionType(fn, child, varTypes); int rType = findExpressionType(fn, child.getNext(), varTypes); return lType | rType; // we're not distinguishing strings yet } } Node child = n.getFirstChild(); if (child == null) { return Optimizer.AnyType; } else { int result = Optimizer.NoType; while (child != null) { result |= findExpressionType(fn, child, varTypes); child = child.getNext(); } return result; } } private static boolean findDefPoints(OptFunctionNode fn, Node n, int[] varTypes) { boolean result = false; Node child = n.getFirstChild(); switch (n.getType()) { default : while (child != null) { result |= findDefPoints(fn, child, varTypes); child = child.getNext(); } break; case Token.DEC : case Token.INC : if (child.getType() == Token.GETVAR) { // theVar is a Number now int i = fn.getVarIndex(child); result |= assignType(varTypes, i, Optimizer.NumberType); } break; case Token.SETPROP : case Token.SETPROP_OP : if (child.getType() == Token.GETVAR) { int i = fn.getVarIndex(child); assignType(varTypes, i, Optimizer.AnyType); } while (child != null) { result |= findDefPoints(fn, child, varTypes); child = child.getNext(); } break; case Token.SETVAR : { Node rValue = child.getNext(); int theType = findExpressionType(fn, rValue, varTypes); int i = fn.getVarIndex(n); result |= assignType(varTypes, i, theType); break; } } return result; } private boolean doTypeFlow(OptFunctionNode fn, Node[] statementNodes, int[] varTypes) { boolean changed = false; for (int i = itsStartNodeIndex; i <= itsEndNodeIndex; i++) { Node n = statementNodes[i]; if (n != null) changed |= findDefPoints(fn, n, varTypes); } return changed; } private void printLiveOnEntrySet(OptFunctionNode fn) { if (DEBUG) { for (int i = 0; i < fn.getVarCount(); i++) { String name = fn.fnode.getParamOrVarName(i); if (itsUseBeforeDefSet.test(i)) System.out.println(name + " is used before def'd"); if (itsNotDefSet.test(i)) System.out.println(name + " is not def'd"); if (itsLiveOnEntrySet.test(i)) System.out.println(name + " is live on entry"); if (itsLiveOnExitSet.test(i)) System.out.println(name + " is live on exit"); } } } // all the Blocks that come immediately after this private Block[] itsSuccessors; // all the Blocks that come immediately before this private Block[] itsPredecessors; private int itsStartNodeIndex; // the Node at the start of the block private int itsEndNodeIndex; // the Node at the end of the block private int itsBlockID; // a unique index for each block // reaching def bit sets - private DataFlowBitSet itsLiveOnEntrySet; private DataFlowBitSet itsLiveOnExitSet; private DataFlowBitSet itsUseBeforeDefSet; private DataFlowBitSet itsNotDefSet; static final boolean DEBUG = false; private static int debug_blockCount; } htmlunit-core-js-2.8/rhino/src/org/mozilla/javascript/Token.java0000644000175000017500000004420711321335670024654 0ustar cavedoncavedon/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- * * ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is Rhino code, released * May 6, 1999. * * The Initial Developer of the Original Code is * Netscape Communications Corporation. * Portions created by the Initial Developer are Copyright (C) 1997-1999 * the Initial Developer. All Rights Reserved. * * Contributor(s): * Roger Lawrence * Mike McCabe * Igor Bukanov * Bob Jervis * Milen Nankov * * Alternatively, the contents of this file may be used under the terms of * the GNU General Public License Version 2 or later (the "GPL"), in which * case the provisions of the GPL are applicable instead of those above. If * you wish to allow use of your version of this file only under the terms of * the GPL and not to allow others to use your version of this file under the * MPL, indicate your decision by deleting the provisions above and replacing * them with the notice and other provisions required by the GPL. If you do * not delete the provisions above, a recipient may use your version of this * file under either the MPL or the GPL. * * ***** END LICENSE BLOCK ***** */ package org.mozilla.javascript; /** * This class implements the JavaScript scanner. * * It is based on the C source files jsscan.c and jsscan.h * in the jsref package. * * @see org.mozilla.javascript.Parser * * @author Mike McCabe * @author Brendan Eich */ public class Token { public static enum CommentType { LINE, BLOCK_COMMENT, JSDOC, HTML } // debug flags public static final boolean printTrees = false; static final boolean printICode = false; static final boolean printNames = printTrees || printICode; /** * Token types. These values correspond to JSTokenType values in * jsscan.c. */ public final static int // start enum ERROR = -1, // well-known as the only code < EOF EOF = 0, // end of file token - (not EOF_CHAR) EOL = 1, // end of line // Interpreter reuses the following as bytecodes FIRST_BYTECODE_TOKEN = 2, ENTERWITH = 2, LEAVEWITH = 3, RETURN = 4, GOTO = 5, IFEQ = 6, IFNE = 7, SETNAME = 8, BITOR = 9, BITXOR = 10, BITAND = 11, EQ = 12, NE = 13, LT = 14, LE = 15, GT = 16, GE = 17, LSH = 18, RSH = 19, URSH = 20, ADD = 21, SUB = 22, MUL = 23, DIV = 24, MOD = 25, NOT = 26, BITNOT = 27, POS = 28, NEG = 29, NEW = 30, DELPROP = 31, TYPEOF = 32, GETPROP = 33, GETPROPNOWARN = 34, SETPROP = 35, GETELEM = 36, SETELEM = 37, CALL = 38, NAME = 39, NUMBER = 40, STRING = 41, NULL = 42, THIS = 43, FALSE = 44, TRUE = 45, SHEQ = 46, // shallow equality (===) SHNE = 47, // shallow inequality (!==) REGEXP = 48, BINDNAME = 49, THROW = 50, RETHROW = 51, // rethrow caught exception: catch (e if ) use it IN = 52, INSTANCEOF = 53, LOCAL_LOAD = 54, GETVAR = 55, SETVAR = 56, CATCH_SCOPE = 57, ENUM_INIT_KEYS = 58, ENUM_INIT_VALUES = 59, ENUM_INIT_ARRAY= 60, ENUM_NEXT = 61, ENUM_ID = 62, THISFN = 63, RETURN_RESULT = 64, // to return previously stored return result ARRAYLIT = 65, // array literal OBJECTLIT = 66, // object literal GET_REF = 67, // *reference SET_REF = 68, // *reference = something DEL_REF = 69, // delete reference REF_CALL = 70, // f(args) = something or f(args)++ REF_SPECIAL = 71, // reference for special properties like __proto YIELD = 72, // JS 1.7 yield pseudo keyword STRICT_SETNAME = 73, // For XML support: DEFAULTNAMESPACE = 74, // default xml namespace = ESCXMLATTR = 75, ESCXMLTEXT = 76, REF_MEMBER = 77, // Reference for x.@y, x..y etc. REF_NS_MEMBER = 78, // Reference for x.ns::y, x..ns::y etc. REF_NAME = 79, // Reference for @y, @[y] etc. REF_NS_NAME = 80; // Reference for ns::y, @ns::y@[y] etc. // End of interpreter bytecodes public final static int LAST_BYTECODE_TOKEN = REF_NS_NAME, TRY = 81, SEMI = 82, // semicolon LB = 83, // left and right brackets RB = 84, LC = 85, // left and right curlies (braces) RC = 86, LP = 87, // left and right parentheses RP = 88, COMMA = 89, // comma operator ASSIGN = 90, // simple assignment (=) ASSIGN_BITOR = 91, // |= ASSIGN_BITXOR = 92, // ^= ASSIGN_BITAND = 93, // |= ASSIGN_LSH = 94, // <<= ASSIGN_RSH = 95, // >>= ASSIGN_URSH = 96, // >>>= ASSIGN_ADD = 97, // += ASSIGN_SUB = 98, // -= ASSIGN_MUL = 99, // *= ASSIGN_DIV = 100, // /= ASSIGN_MOD = 101; // %= public final static int FIRST_ASSIGN = ASSIGN, LAST_ASSIGN = ASSIGN_MOD, HOOK = 102, // conditional (?:) COLON = 103, OR = 104, // logical or (||) AND = 105, // logical and (&&) INC = 106, // increment/decrement (++ --) DEC = 107, DOT = 108, // member operator (.) FUNCTION = 109, // function keyword EXPORT = 110, // export keyword IMPORT = 111, // import keyword IF = 112, // if keyword ELSE = 113, // else keyword SWITCH = 114, // switch keyword CASE = 115, // case keyword DEFAULT = 116, // default keyword WHILE = 117, // while keyword DO = 118, // do keyword FOR = 119, // for keyword BREAK = 120, // break keyword CONTINUE = 121, // continue keyword VAR = 122, // var keyword WITH = 123, // with keyword CATCH = 124, // catch keyword FINALLY = 125, // finally keyword VOID = 126, // void keyword RESERVED = 127, // reserved keywords EMPTY = 128, /* types used for the parse tree - these never get returned * by the scanner. */ BLOCK = 129, // statement block LABEL = 130, // label TARGET = 131, LOOP = 132, EXPR_VOID = 133, // expression statement in functions EXPR_RESULT = 134, // expression statement in scripts JSR = 135, SCRIPT = 136, // top-level node for entire script TYPEOFNAME = 137, // for typeof(simple-name) USE_STACK = 138, SETPROP_OP = 139, // x.y op= something SETELEM_OP = 140, // x[y] op= something LOCAL_BLOCK = 141, SET_REF_OP = 142, // *reference op= something // For XML support: DOTDOT = 143, // member operator (..) COLONCOLON = 144, // namespace::name XML = 145, // XML type DOTQUERY = 146, // .() -- e.g., x.emps.emp.(name == "terry") XMLATTR = 147, // @ XMLEND = 148, // Optimizer-only-tokens TO_OBJECT = 149, TO_DOUBLE = 150, GET = 151, // JS 1.5 get pseudo keyword SET = 152, // JS 1.5 set pseudo keyword LET = 153, // JS 1.7 let pseudo keyword CONST = 154, SETCONST = 155, SETCONSTVAR = 156, ARRAYCOMP = 157, // array comprehension LETEXPR = 158, WITHEXPR = 159, DEBUGGER = 160, COMMENT = 161, LAST_TOKEN = 162; /** * Returns a name for the token. If Rhino is compiled with certain * hardcoded debugging flags in this file, it calls {@code #typeToName}; * otherwise it returns a string whose value is the token number. */ public static String name(int token) { if (!printNames) { return String.valueOf(token); } return typeToName(token); } /** * Always returns a human-readable string for the token name. * For instance, {@link #FINALLY} has the name "FINALLY". * @param token the token code * @return the actual name for the token code */ public static String typeToName(int token) { switch (token) { case ERROR: return "ERROR"; case EOF: return "EOF"; case EOL: return "EOL"; case ENTERWITH: return "ENTERWITH"; case LEAVEWITH: return "LEAVEWITH"; case RETURN: return "RETURN"; case GOTO: return "GOTO"; case IFEQ: return "IFEQ"; case IFNE: return "IFNE"; case SETNAME: return "SETNAME"; case BITOR: return "BITOR"; case BITXOR: return "BITXOR"; case BITAND: return "BITAND"; case EQ: return "EQ"; case NE: return "NE"; case LT: return "LT"; case LE: return "LE"; case GT: return "GT"; case GE: return "GE"; case LSH: return "LSH"; case RSH: return "RSH"; case URSH: return "URSH"; case ADD: return "ADD"; case SUB: return "SUB"; case MUL: return "MUL"; case DIV: return "DIV"; case MOD: return "MOD"; case NOT: return "NOT"; case BITNOT: return "BITNOT"; case POS: return "POS"; case NEG: return "NEG"; case NEW: return "NEW"; case DELPROP: return "DELPROP"; case TYPEOF: return "TYPEOF"; case GETPROP: return "GETPROP"; case GETPROPNOWARN: return "GETPROPNOWARN"; case SETPROP: return "SETPROP"; case GETELEM: return "GETELEM"; case SETELEM: return "SETELEM"; case CALL: return "CALL"; case NAME: return "NAME"; case NUMBER: return "NUMBER"; case STRING: return "STRING"; case NULL: return "NULL"; case THIS: return "THIS"; case FALSE: return "FALSE"; case TRUE: return "TRUE"; case SHEQ: return "SHEQ"; case SHNE: return "SHNE"; case REGEXP: return "REGEXP"; case BINDNAME: return "BINDNAME"; case THROW: return "THROW"; case RETHROW: return "RETHROW"; case IN: return "IN"; case INSTANCEOF: return "INSTANCEOF"; case LOCAL_LOAD: return "LOCAL_LOAD"; case GETVAR: return "GETVAR"; case SETVAR: return "SETVAR"; case CATCH_SCOPE: return "CATCH_SCOPE"; case ENUM_INIT_KEYS: return "ENUM_INIT_KEYS"; case ENUM_INIT_VALUES:return "ENUM_INIT_VALUES"; case ENUM_INIT_ARRAY: return "ENUM_INIT_ARRAY"; case ENUM_NEXT: return "ENUM_NEXT"; case ENUM_ID: return "ENUM_ID"; case THISFN: return "THISFN"; case RETURN_RESULT: return "RETURN_RESULT"; case ARRAYLIT: return "ARRAYLIT"; case OBJECTLIT: return "OBJECTLIT"; case GET_REF: return "GET_REF"; case SET_REF: return "SET_REF"; case DEL_REF: return "DEL_REF"; case REF_CALL: return "REF_CALL"; case REF_SPECIAL: return "REF_SPECIAL"; case DEFAULTNAMESPACE:return "DEFAULTNAMESPACE"; case ESCXMLTEXT: return "ESCXMLTEXT"; case ESCXMLATTR: return "ESCXMLATTR"; case REF_MEMBER: return "REF_MEMBER"; case REF_NS_MEMBER: return "REF_NS_MEMBER"; case REF_NAME: return "REF_NAME"; case REF_NS_NAME: return "REF_NS_NAME"; case TRY: return "TRY"; case SEMI: return "SEMI"; case LB: return "LB"; case RB: return "RB"; case LC: return "LC"; case RC: return "RC"; case LP: return "LP"; case RP: return "RP"; case COMMA: return "COMMA"; case ASSIGN: return "ASSIGN"; case ASSIGN_BITOR: return "ASSIGN_BITOR"; case ASSIGN_BITXOR: return "ASSIGN_BITXOR"; case ASSIGN_BITAND: return "ASSIGN_BITAND"; case ASSIGN_LSH: return "ASSIGN_LSH"; case ASSIGN_RSH: return "ASSIGN_RSH"; case ASSIGN_URSH: return "ASSIGN_URSH"; case ASSIGN_ADD: return "ASSIGN_ADD"; case ASSIGN_SUB: return "ASSIGN_SUB"; case ASSIGN_MUL: return "ASSIGN_MUL"; case ASSIGN_DIV: return "ASSIGN_DIV"; case ASSIGN_MOD: return "ASSIGN_MOD"; case HOOK: return "HOOK"; case COLON: return "COLON"; case OR: return "OR"; case AND: return "AND"; case INC: return "INC"; case DEC: return "DEC"; case DOT: return "DOT"; case FUNCTION: return "FUNCTION"; case EXPORT: return "EXPORT"; case IMPORT: return "IMPORT"; case IF: return "IF"; case ELSE: return "ELSE"; case SWITCH: return "SWITCH"; case CASE: return "CASE"; case DEFAULT: return "DEFAULT"; case WHILE: return "WHILE"; case DO: return "DO"; case FOR: return "FOR"; case BREAK: return "BREAK"; case CONTINUE: return "CONTINUE"; case VAR: return "VAR"; case WITH: return "WITH"; case CATCH: return "CATCH"; case FINALLY: return "FINALLY"; case VOID: return "VOID"; case RESERVED: return "RESERVED"; case EMPTY: return "EMPTY"; case BLOCK: return "BLOCK"; case LABEL: return "LABEL"; case TARGET: return "TARGET"; case LOOP: return "LOOP"; case EXPR_VOID: return "EXPR_VOID"; case EXPR_RESULT: return "EXPR_RESULT"; case JSR: return "JSR"; case SCRIPT: return "SCRIPT"; case TYPEOFNAME: return "TYPEOFNAME"; case USE_STACK: return "USE_STACK"; case SETPROP_OP: return "SETPROP_OP"; case SETELEM_OP: return "SETELEM_OP"; case LOCAL_BLOCK: return "LOCAL_BLOCK"; case SET_REF_OP: return "SET_REF_OP"; case DOTDOT: return "DOTDOT"; case COLONCOLON: return "COLONCOLON"; case XML: return "XML"; case DOTQUERY: return "DOTQUERY"; case XMLATTR: return "XMLATTR"; case XMLEND: return "XMLEND"; case TO_OBJECT: return "TO_OBJECT"; case TO_DOUBLE: return "TO_DOUBLE"; case GET: return "GET"; case SET: return "SET"; case LET: return "LET"; case YIELD: return "YIELD"; case CONST: return "CONST"; case SETCONST: return "SETCONST"; case ARRAYCOMP: return "ARRAYCOMP"; case WITHEXPR: return "WITHEXPR"; case LETEXPR: return "LETEXPR"; case DEBUGGER: return "DEBUGGER"; case COMMENT: return "COMMENT"; } // Token without name throw new IllegalStateException(String.valueOf(token)); } /** * Return true if the passed code is a valid Token constant. * @param code a potential token code * @return true if it's a known token */ public static boolean isValidToken(int code) { return code >= ERROR && code <= LAST_TOKEN; } } htmlunit-core-js-2.8/rhino/src/org/mozilla/javascript/RefCallable.java0000644000175000017500000000451710776622373025744 0ustar cavedoncavedon/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- * * ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is Rhino code, released * May 6, 1999. * * The Initial Developer of the Original Code is * Netscape Communications Corporation. * Portions created by the Initial Developer are Copyright (C) 1997-1999 * the Initial Developer. All Rights Reserved. * * Contributor(s): * Igor Bukanov, igor@mir2.org * * Alternatively, the contents of this file may be used under the terms of * the GNU General Public License Version 2 or later (the "GPL"), in which * case the provisions of the GPL are applicable instead of those above. If * you wish to allow use of your version of this file only under the terms of * the GPL and not to allow others to use your version of this file under the * MPL, indicate your decision by deleting the provisions above and replacing * them with the notice and other provisions required by the GPL. If you do * not delete the provisions above, a recipient may use your version of this * file under either the MPL or the GPL. * * ***** END LICENSE BLOCK ***** */ package org.mozilla.javascript; /** * Object that can allows assignments to the result of function calls. */ public interface RefCallable extends Callable { /** * Perform function call in reference context. * The args array reference should not be stored in any object that is * can be GC-reachable after this method returns. If this is necessary, * for example, to implement {@link Ref} methods, then store args.clone(), * not args array itself. * * @param cx the current Context for this thread * @param thisObj the JavaScript this object * @param args the array of arguments */ public Ref refCall(Context cx, Scriptable thisObj, Object[] args); } htmlunit-core-js-2.8/rhino/src/org/mozilla/javascript/Function.java0000644000175000017500000000624010776622373025370 0ustar cavedoncavedon/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- * * ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is Rhino code, released * May 6, 1999. * * The Initial Developer of the Original Code is * Netscape Communications Corporation. * Portions created by the Initial Developer are Copyright (C) 1997-1999 * the Initial Developer. All Rights Reserved. * * Contributor(s): * Norris Boyd * * Alternatively, the contents of this file may be used under the terms of * the GNU General Public License Version 2 or later (the "GPL"), in which * case the provisions of the GPL are applicable instead of those above. If * you wish to allow use of your version of this file only under the terms of * the GPL and not to allow others to use your version of this file under the * MPL, indicate your decision by deleting the provisions above and replacing * them with the notice and other provisions required by the GPL. If you do * not delete the provisions above, a recipient may use your version of this * file under either the MPL or the GPL. * * ***** END LICENSE BLOCK ***** */ // 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 this 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 new 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); } htmlunit-core-js-2.8/rhino/src/org/mozilla/javascript/LazilyLoadedCtor.java0000644000175000017500000001315111222455466027001 0ustar cavedoncavedon/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- * * ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is Rhino code, released * May 6, 1999. * * The Initial Developer of the Original Code is * Netscape Communications Corporation. * Portions created by the Initial Developer are Copyright (C) 1997-2000 * the Initial Developer. All Rights Reserved. * * Contributor(s): * Norris Boyd * Igor Bukanov * * Alternatively, the contents of this file may be used under the terms of * the GNU General Public License Version 2 or later (the "GPL"), in which * case the provisions of the GPL are applicable instead of those above. If * you wish to allow use of your version of this file only under the terms of * the GPL and not to allow others to use your version of this file under the * MPL, indicate your decision by deleting the provisions above and replacing * them with the notice and other provisions required by the GPL. If you do * not delete the provisions above, a recipient may use your version of this * file under either the MPL or the GPL. * * ***** END LICENSE BLOCK ***** */ package org.mozilla.javascript; import java.lang.reflect.*; import java.security.AccessController; import java.security.PrivilegedAction; /** * Avoid loading classes unless they are used. * *

This improves startup time and average memory usage. */ public final class LazilyLoadedCtor implements java.io.Serializable { private static final long serialVersionUID = 1L; private static final int STATE_BEFORE_INIT = 0; private static final int STATE_INITIALIZING = 1; private static final int STATE_WITH_VALUE = 2; private final ScriptableObject scope; private final String propertyName; private final String className; private final boolean sealed; private final boolean privileged; private Object initializedValue; private int state; public LazilyLoadedCtor(ScriptableObject scope, String propertyName, String className, boolean sealed) { this(scope, propertyName, className, sealed, false); } LazilyLoadedCtor(ScriptableObject scope, String propertyName, String className, boolean sealed, boolean privileged) { this.scope = scope; this.propertyName = propertyName; this.className = className; this.sealed = sealed; this.privileged = privileged; this.state = STATE_BEFORE_INIT; scope.addLazilyInitializedValue(propertyName, 0, this, ScriptableObject.DONTENUM); } void init() { synchronized (this) { if (state == STATE_INITIALIZING) throw new IllegalStateException( "Recursive initialization for "+propertyName); if (state == STATE_BEFORE_INIT) { state = STATE_INITIALIZING; // Set value now to have something to set in finally block if // buildValue throws. Object value = Scriptable.NOT_FOUND; try { value = buildValue(); } finally { initializedValue = value; state = STATE_WITH_VALUE; } } } } Object getValue() { if (state != STATE_WITH_VALUE) throw new IllegalStateException(propertyName); return initializedValue; } private Object buildValue() { if(privileged) { return AccessController.doPrivileged(new PrivilegedAction() { public Object run() { return buildValue0(); } }); } else { return buildValue0(); } } private Object buildValue0() { Class cl = cast(Kit.classOrNull(className)); if (cl != null) { try { Object value = ScriptableObject.buildClassCtor(scope, cl, sealed, false); if (value != null) { return value; } else { // cl has own static initializer which is expected // to set the property on its own. value = scope.get(propertyName, scope); if (value != Scriptable.NOT_FOUND) return value; } } catch (InvocationTargetException ex) { Throwable target = ex.getTargetException(); if (target instanceof RuntimeException) { throw (RuntimeException)target; } } catch (RhinoException ex) { } catch (InstantiationException ex) { } catch (IllegalAccessException ex) { } catch (SecurityException ex) { } } return Scriptable.NOT_FOUND; } @SuppressWarnings({"unchecked"}) private Class cast(Class cl) { return (Class)cl; } } htmlunit-core-js-2.8/rhino/src/org/mozilla/javascript/json/0000755000175000017500000000000011530107743023673 5ustar cavedoncavedonhtmlunit-core-js-2.8/rhino/src/org/mozilla/javascript/json/JsonParser.java0000644000175000017500000003025311321335670026627 0ustar cavedoncavedon/* -*- Mode: java; tab-width: 4; indent-tabs-mode: 1; c-basic-offset: 4 -*- * * ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is Rhino code, released * May 6, 1999. * * The Initial Developer of the Original Code is * Netscape Communications Corporation. * Portions created by the Initial Developer are Copyright (C) 1997-1999 * the Initial Developer. All Rights Reserved. * * Contributor(s): * Norris Boyd * Raphael Speyer * Hannes Wallnoefer * * Alternatively, the contents of this file may be used under the terms of * the GNU General Public License Version 2 or later (the "GPL"), in which * case the provisions of the GPL are applicable instead of those above. If * you wish to allow use of your version of this file only under the terms of * the GPL and not to allow others to use your version of this file under the * MPL, indicate your decision by deleting the provisions above and replacing * them with the notice and other provisions required by the GPL. If you do * not delete the provisions above, a recipient may use your version of this * file under either the MPL or the GPL. * * ***** END LICENSE BLOCK ***** */ package org.mozilla.javascript.json; import org.mozilla.javascript.Context; import org.mozilla.javascript.Scriptable; import org.mozilla.javascript.ScriptRuntime; import java.util.ArrayList; import java.util.List; /** * This class converts a stream of JSON tokens into a JSON value. * * See ECMA 15.12. * @author Raphael Speyer * @author Hannes Wallnoefer */ public class JsonParser { private Context cx; private Scriptable scope; private int pos; private int length; private String src; public JsonParser(Context cx, Scriptable scope) { this.cx = cx; this.scope = scope; } public synchronized Object parseValue(String json) throws ParseException { if (json == null) { throw new ParseException("Input string may not be null"); } pos = 0; length = json.length(); src = json; Object value = readValue(); consumeWhitespace(); if (pos < length) { throw new ParseException("Expected end of stream at char " + pos); } return value; } private Object readValue() throws ParseException { consumeWhitespace(); while (pos < length) { char c = src.charAt(pos++); switch (c) { case '{': return readObject(); case '[': return readArray(); case 't': return readTrue(); case 'f': return readFalse(); case '"': return readString(); case 'n': return readNull(); case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': case '0': case '-': return readNumber(c); default: throw new ParseException("Unexpected token: " + c); } } throw new ParseException("Empty JSON string"); } private Object readObject() throws ParseException { Scriptable object = cx.newObject(scope); String id; Object value; boolean needsComma = false; consumeWhitespace(); while (pos < length) { char c = src.charAt(pos++); switch(c) { case '}': return object; case ',': if (!needsComma) { throw new ParseException("Unexpected comma in object literal"); } needsComma = false; break; case '"': if (needsComma) { throw new ParseException("Missing comma in object literal"); } id = readString(); consume(':'); value = readValue(); double d = ScriptRuntime.toNumber(id); int index = (int) d; if (d != index) { object.put(id, object, value); } else { object.put(index, object, value); } needsComma = true; break; default: throw new ParseException("Unexpected token in object literal"); } consumeWhitespace(); } throw new ParseException("Unterminated object literal"); } private Object readArray() throws ParseException { List list = new ArrayList(); boolean needsComma = false; consumeWhitespace(); while (pos < length) { char c = src.charAt(pos); switch(c) { case ']': pos += 1; return cx.newArray(scope, list.toArray()); case ',': if (!needsComma) { throw new ParseException("Unexpected comma in array literal"); } needsComma = false; pos += 1; break; default: if (needsComma) { throw new ParseException("Missing comma in array literal"); } list.add(readValue()); needsComma = true; } consumeWhitespace(); } throw new ParseException("Unterminated array literal"); } private String readString() throws ParseException { StringBuilder b = new StringBuilder(); while (pos < length) { char c = src.charAt(pos++); if (c <= '\u001F') { throw new ParseException("String contains control character"); } switch(c) { case '\\': if (pos >= length) { throw new ParseException("Unterminated string"); } c = src.charAt(pos++); switch (c) { case '"': b.append('"'); break; case '\\': b.append('\\'); break; case '/': b.append('/'); break; case 'b': b.append('\b'); break; case 'f': b.append('\f'); break; case 'n': b.append('\n'); break; case 'r': b.append('\r'); break; case 't': b.append('\t'); break; case 'u': if (length - pos < 5) { throw new ParseException("Invalid character code: \\u" + src.substring(pos)); } try { b.append((char) Integer.parseInt(src.substring(pos, pos + 4), 16)); pos += 4; } catch (NumberFormatException nfx) { throw new ParseException("Invalid character code: " + src.substring(pos, pos + 4)); } break; default: throw new ParseException("Unexcpected character in string: '\\" + c + "'"); } break; case '"': return b.toString(); default: b.append(c); break; } } throw new ParseException("Unterminated string literal"); } private Number readNumber(char first) throws ParseException { StringBuilder b = new StringBuilder(); b.append(first); while (pos < length) { char c = src.charAt(pos); if (!Character.isDigit(c) && c != '-' && c != '+' && c != '.' && c != 'e' && c != 'E') { break; } pos += 1; b.append(c); } String num = b.toString(); int numLength = num.length(); try { // check for leading zeroes for (int i = 0; i < numLength; i++) { char c = num.charAt(i); if (Character.isDigit(c)) { if (c == '0' && numLength > i + 1 && Character.isDigit(num.charAt(i + 1))) { throw new ParseException("Unsupported number format: " + num); } break; } } double d = Double.valueOf(num); if ((int)d == d) { return new Integer((int) d); } else { return new Double(d); } } catch (NumberFormatException nfe) { throw new ParseException("Unsupported number format: " + num); } } private Boolean readTrue() throws ParseException { if (length - pos < 3 || src.charAt(pos) != 'r' || src.charAt(pos + 1) != 'u' || src.charAt(pos + 2) != 'e') { throw new ParseException("Unexpected token: t"); } pos += 3; return Boolean.TRUE; } private Boolean readFalse() throws ParseException { if (length - pos < 4 || src.charAt(pos) != 'a' || src.charAt(pos + 1) != 'l' || src.charAt(pos + 2) != 's' || src.charAt(pos + 3) != 'e') { throw new ParseException("Unexpected token: f"); } pos += 4; return Boolean.FALSE; } private Object readNull() throws ParseException { if (length - pos < 3 || src.charAt(pos) != 'u' || src.charAt(pos + 1) != 'l' || src.charAt(pos + 2) != 'l') { throw new ParseException("Unexpected token: n"); } pos += 3; return null; } private void consumeWhitespace() { while (pos < length) { char c = src.charAt(pos); switch (c) { case ' ': case '\t': case '\r': case '\n': pos += 1; break; default: return; } } } private void consume(char token) throws ParseException { consumeWhitespace(); if (pos >= length) { throw new ParseException("Expected " + token + " but reached end of stream"); } char c = src.charAt(pos++); if (c == token) { return; } else { throw new ParseException("Expected " + token + " found " + c); } } public static class ParseException extends Exception { ParseException(String message) { super(message); } ParseException(Exception cause) { super(cause); } } } htmlunit-core-js-2.8/rhino/src/org/mozilla/javascript/ScriptableObject.java0000644000175000017500000034447011321335670027020 0ustar cavedoncavedon/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- * * ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is Rhino code, released * May 6, 1999. * * The Initial Developer of the Original Code is * Netscape Communications Corporation. * Portions created by the Initial Developer are Copyright (C) 1997-1999 * the Initial Developer. All Rights Reserved. * * Contributor(s): * Norris Boyd * Igor Bukanov * Daniel Gredler * Bob Jervis * Roger Lawrence * Cameron McCormack * Steve Weiss * Hannes Wallnoefer * * Alternatively, the contents of this file may be used under the terms of * the GNU General Public License Version 2 or later (the "GPL"), in which * case the provisions of the GPL are applicable instead of those above. If * you wish to allow use of your version of this file only under the terms of * the GPL and not to allow others to use your version of this file under the * MPL, indicate your decision by deleting the provisions above and replacing * them with the notice and other provisions required by the GPL. If you do * not delete the provisions above, a recipient may use your version of this * file under either the MPL or the GPL. * * ***** END LICENSE BLOCK ***** */ // API class package org.mozilla.javascript; import java.lang.reflect.*; import java.lang.annotation.Annotation; import java.util.*; import java.io.*; import org.mozilla.javascript.debug.DebuggableObject; import org.mozilla.javascript.annotations.*; /** * This is the default implementation of the Scriptable interface. This * class provides convenient default behavior that makes it easier to * define host objects. *

* Various properties and methods of JavaScript objects can be conveniently * defined using methods of ScriptableObject. *

* Classes extending ScriptableObject must define the getClassName method. * * @see org.mozilla.javascript.Scriptable * @author Norris Boyd */ public abstract class ScriptableObject implements Scriptable, Serializable, DebuggableObject, ConstProperties, Map { /** * The empty property attribute. * * Used by getAttributes() and setAttributes(). * * @see org.mozilla.javascript.ScriptableObject#getAttributes(String) * @see org.mozilla.javascript.ScriptableObject#setAttributes(String, int) */ public static final int EMPTY = 0x00; /** * Property attribute indicating assignment to this property is ignored. * * @see org.mozilla.javascript.ScriptableObject * #put(String, Scriptable, Object) * @see org.mozilla.javascript.ScriptableObject#getAttributes(String) * @see org.mozilla.javascript.ScriptableObject#setAttributes(String, int) */ public static final int READONLY = 0x01; /** * Property attribute indicating property is not enumerated. * * Only enumerated properties will be returned by getIds(). * * @see org.mozilla.javascript.ScriptableObject#getIds() * @see org.mozilla.javascript.ScriptableObject#getAttributes(String) * @see org.mozilla.javascript.ScriptableObject#setAttributes(String, int) */ public static final int DONTENUM = 0x02; /** * Property attribute indicating property cannot be deleted. * * @see org.mozilla.javascript.ScriptableObject#delete(String) * @see org.mozilla.javascript.ScriptableObject#getAttributes(String) * @see org.mozilla.javascript.ScriptableObject#setAttributes(String, int) */ public static final int PERMANENT = 0x04; /** * Property attribute indicating that this is a const property that has not * been assigned yet. The first 'const' assignment to the property will * clear this bit. */ public static final int UNINITIALIZED_CONST = 0x08; public static final int CONST = PERMANENT|READONLY|UNINITIALIZED_CONST; /** * The prototype of this object. */ private Scriptable prototypeObject; /** * The parent scope of this object. */ private Scriptable parentScopeObject; private static final Slot REMOVED = new Slot(null, 0, READONLY); static { REMOVED.wasDeleted = true; } private transient Slot[] slots; // If count >= 0, it gives number of keys or if count < 0, // it indicates sealed object where ~count gives number of keys private int count; // gateways into the definition-order linked list of slots private transient Slot firstAdded; private transient Slot lastAdded; // cache; may be removed for smaller memory footprint private transient Slot lastAccess = REMOVED; private volatile Map associatedValues; private static final int SLOT_QUERY = 1; private static final int SLOT_MODIFY = 2; private static final int SLOT_REMOVE = 3; private static final int SLOT_MODIFY_GETTER_SETTER = 4; private static final int SLOT_MODIFY_CONST = 5; private static final int SLOT_CONVERT_ACCESSOR_TO_DATA = 6; private boolean isExtensible = true; private static class Slot implements Serializable { private static final long serialVersionUID = -6090581677123995491L; String name; // This can change due to caching int indexOrHash; private volatile short attributes; transient volatile boolean wasDeleted; volatile Object value; transient volatile Slot next; // next in hash table bucket transient volatile Slot orderedNext; // next in linked list Slot(String name, int indexOrHash, int attributes) { this.name = name; this.indexOrHash = indexOrHash; this.attributes = (short)attributes; } private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { in.defaultReadObject(); if (name != null) { indexOrHash = name.hashCode(); } } final int getAttributes() { return attributes; } final synchronized void setAttributes(int value) { checkValidAttributes(value); attributes = (short)value; } final void checkNotReadonly() { if ((attributes & READONLY) != 0) { String str = (name != null ? name : Integer.toString(indexOrHash)); throw Context.reportRuntimeError1("msg.modify.readonly", str); } } ScriptableObject getPropertyDescriptor(Context cx, Scriptable scope) { return buildDataDescriptor( scope, (value == null ? Undefined.instance : value), attributes); } } protected static ScriptableObject buildDataDescriptor(Scriptable scope, Object value, int attributes) { ScriptableObject desc = new NativeObject(); ScriptRuntime.setObjectProtoAndParent(desc, scope); desc.defineProperty("value", value, EMPTY); desc.defineProperty("writable", (attributes & READONLY) == 0, EMPTY); desc.defineProperty("enumerable", (attributes & DONTENUM) == 0, EMPTY); desc.defineProperty("configurable", (attributes & PERMANENT) == 0, EMPTY); return desc; } private static final class GetterSlot extends Slot { static final long serialVersionUID = -4900574849788797588L; Object getter; Object setter; GetterSlot(String name, int indexOrHash, int attributes) { super(name, indexOrHash, attributes); } @Override ScriptableObject getPropertyDescriptor(Context cx, Scriptable parent) { ScriptableObject desc = super.getPropertyDescriptor(cx, parent); desc.delete("value"); desc.delete("writable"); if (getter != null) desc.defineProperty("get", getter, EMPTY); if (setter != null) desc.defineProperty("set", setter, EMPTY); return desc; } } static void checkValidAttributes(int attributes) { final int mask = READONLY | DONTENUM | PERMANENT | UNINITIALIZED_CONST; if ((attributes & ~mask) != 0) { throw new IllegalArgumentException(String.valueOf(attributes)); } } public ScriptableObject() { } public ScriptableObject(Scriptable scope, Scriptable prototype) { if (scope == null) throw new IllegalArgumentException(); parentScopeObject = scope; prototypeObject = prototype; } /** * Gets the value that will be returned by calling the typeof operator on this object. * @return default is "object" unless {@link #avoidObjectDetection()} is true in which * case it returns "undefined" */ public String getTypeOf() { return avoidObjectDetection() ? "undefined" : "object"; } /** * Return the name of the class. * * This is typically the same name as the constructor. * Classes extending ScriptableObject must implement this abstract * method. */ public abstract String getClassName(); /** * Returns true if the named property is defined. * * @param name the name of the property * @param start the object in which the lookup began * @return true if and only if the property was found in the object */ public boolean has(String name, Scriptable start) { return null != getSlot(name, 0, SLOT_QUERY); } /** * Returns true if the property index is defined. * * @param index the numeric index for the property * @param start the object in which the lookup began * @return true if and only if the property was found in the object */ public boolean has(int index, Scriptable start) { return null != getSlot(null, index, SLOT_QUERY); } /** * Returns the value of the named property or NOT_FOUND. * * If the property was created using defineProperty, the * appropriate getter method is called. * * @param name the name of the property * @param start the object in which the lookup began * @return the value of the property (may be null), or NOT_FOUND */ public Object get(String name, Scriptable start) { return getImpl(name, 0, start); } /** * Returns the value of the indexed property or NOT_FOUND. * * @param index the numeric index for the property * @param start the object in which the lookup began * @return the value of the property (may be null), or NOT_FOUND */ public Object get(int index, Scriptable start) { return getImpl(null, index, start); } /** * Sets the value of the named property, creating it if need be. * * If the property was created using defineProperty, the * appropriate setter method is called.

* * If the property's attributes include READONLY, no action is * taken. * This method will actually set the property in the start * object. * * @param name the name of the property * @param start the object whose property is being set * @param value value to set the property to */ public void put(String name, Scriptable start, Object value) { if (putImpl(name, 0, start, value, EMPTY)) return; if (start == this) throw Kit.codeBug(); start.put(name, start, value); } /** * Sets the value of the indexed property, creating it if need be. * * @param index the numeric index for the property * @param start the object whose property is being set * @param value value to set the property to */ public void put(int index, Scriptable start, Object value) { if (putImpl(null, index, start, value, EMPTY)) return; if (start == this) throw Kit.codeBug(); start.put(index, start, value); } /** * Removes a named property from the object. * * If the property is not found, or it has the PERMANENT attribute, * no action is taken. * * @param name the name of the property */ public void delete(String name) { checkNotSealed(name, 0); accessSlot(name, 0, SLOT_REMOVE); } /** * Removes the indexed property from the object. * * If the property is not found, or it has the PERMANENT attribute, * no action is taken. * * @param index the numeric index for the property */ public void delete(int index) { checkNotSealed(null, index); accessSlot(null, index, SLOT_REMOVE); } /** * Sets the value of the named const property, creating it if need be. * * If the property was created using defineProperty, the * appropriate setter method is called.

* * If the property's attributes include READONLY, no action is * taken. * This method will actually set the property in the start * object. * * @param name the name of the property * @param start the object whose property is being set * @param value value to set the property to */ public void putConst(String name, Scriptable start, Object value) { if (putImpl(name, 0, start, value, READONLY)) return; if (start == this) throw Kit.codeBug(); if (start instanceof ConstProperties) ((ConstProperties)start).putConst(name, start, value); else start.put(name, start, value); } public void defineConst(String name, Scriptable start) { if (putImpl(name, 0, start, Undefined.instance, UNINITIALIZED_CONST)) return; if (start == this) throw Kit.codeBug(); if (start instanceof ConstProperties) ((ConstProperties)start).defineConst(name, 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) { Slot slot = getSlot(name, 0, SLOT_QUERY); if (slot == null) { return false; } return (slot.getAttributes() & (PERMANENT|READONLY)) == (PERMANENT|READONLY); } /** * @deprecated Use {@link #getAttributes(String name)}. The engine always * ignored the start argument. */ public final int getAttributes(String name, Scriptable start) { return getAttributes(name); } /** * @deprecated Use {@link #getAttributes(int index)}. The engine always * ignored the start argument. */ public final int getAttributes(int index, Scriptable start) { return getAttributes(index); } /** * @deprecated Use {@link #setAttributes(String name, int attributes)}. * The engine always ignored the start argument. */ public final void setAttributes(String name, Scriptable start, int attributes) { setAttributes(name, attributes); } /** * @deprecated Use {@link #setAttributes(int index, int attributes)}. * The engine always ignored the start argument. */ public void setAttributes(int index, Scriptable start, int attributes) { setAttributes(index, attributes); } /** * Get the attributes of a named property. * * The property is specified by name * as defined for has.

* * @param name the identifier for the property * @return the bitset of attributes * @exception EvaluatorException if the named property is not found * @see org.mozilla.javascript.ScriptableObject#has(String, Scriptable) * @see org.mozilla.javascript.ScriptableObject#READONLY * @see org.mozilla.javascript.ScriptableObject#DONTENUM * @see org.mozilla.javascript.ScriptableObject#PERMANENT * @see org.mozilla.javascript.ScriptableObject#EMPTY */ public int getAttributes(String name) { return findAttributeSlot(name, 0, SLOT_QUERY).getAttributes(); } /** * Get the attributes of an indexed property. * * @param index the numeric index for the property * @exception EvaluatorException if the named property is not found * is not found * @return the bitset of attributes * @see org.mozilla.javascript.ScriptableObject#has(String, Scriptable) * @see org.mozilla.javascript.ScriptableObject#READONLY * @see org.mozilla.javascript.ScriptableObject#DONTENUM * @see org.mozilla.javascript.ScriptableObject#PERMANENT * @see org.mozilla.javascript.ScriptableObject#EMPTY */ public int getAttributes(int index) { return findAttributeSlot(null, index, SLOT_QUERY).getAttributes(); } /** * Set the attributes of a named property. * * The property is specified by name * as defined for has.

* * The possible attributes are READONLY, DONTENUM, * and PERMANENT. Combinations of attributes * are expressed by the bitwise OR of attributes. * EMPTY is the state of no attributes set. Any unused * bits are reserved for future use. * * @param name the name of the property * @param attributes the bitset of attributes * @exception EvaluatorException if the named property is not found * @see org.mozilla.javascript.Scriptable#has(String, Scriptable) * @see org.mozilla.javascript.ScriptableObject#READONLY * @see org.mozilla.javascript.ScriptableObject#DONTENUM * @see org.mozilla.javascript.ScriptableObject#PERMANENT * @see org.mozilla.javascript.ScriptableObject#EMPTY */ public void setAttributes(String name, int attributes) { checkNotSealed(name, 0); findAttributeSlot(name, 0, SLOT_MODIFY).setAttributes(attributes); } /** * Set the attributes of an indexed property. * * @param index the numeric index for the property * @param attributes the bitset of attributes * @exception EvaluatorException if the named property is not found * @see org.mozilla.javascript.Scriptable#has(String, Scriptable) * @see org.mozilla.javascript.ScriptableObject#READONLY * @see org.mozilla.javascript.ScriptableObject#DONTENUM * @see org.mozilla.javascript.ScriptableObject#PERMANENT * @see org.mozilla.javascript.ScriptableObject#EMPTY */ public void setAttributes(int index, int attributes) { checkNotSealed(null, index); findAttributeSlot(null, index, SLOT_MODIFY).setAttributes(attributes); } /** * XXX: write docs. */ public void setGetterOrSetter(String name, int index, Callable getterOrSetter, boolean isSetter) { setGetterOrSetter(name, index, getterOrSetter, isSetter, false); } private void setGetterOrSetter(String name, int index, Callable getterOrSetter, boolean isSetter, boolean force) { if (name != null && index != 0) throw new IllegalArgumentException(name); if (!force) { checkNotSealed(name, index); } final GetterSlot gslot; if (isExtensible()) { gslot = (GetterSlot)getSlot(name, index, SLOT_MODIFY_GETTER_SETTER); } else { gslot = (GetterSlot)getSlot(name, index, SLOT_QUERY); if (gslot == null) return; } if (!force) { gslot.checkNotReadonly(); } if (isSetter) { gslot.setter = getterOrSetter; } else { gslot.getter = getterOrSetter; } gslot.value = Undefined.instance; } /** * Get the getter or setter for a given property. Used by __lookupGetter__ * and __lookupSetter__. * * @param name Name of the object. If nonnull, index must be 0. * @param index Index of the object. If nonzero, name must be null. * @param isSetter If true, return the setter, otherwise return the getter. * @exception IllegalArgumentException if both name and index are nonnull * and nonzero respectively. * @return Null if the property does not exist. Otherwise returns either * the getter or the setter for the property, depending on * the value of isSetter (may be undefined if unset). */ public Object getGetterOrSetter(String name, int index, boolean isSetter) { if (name != null && index != 0) throw new IllegalArgumentException(name); Slot slot = getSlot(name, index, SLOT_QUERY); if (slot == null) return null; if (slot instanceof GetterSlot) { GetterSlot gslot = (GetterSlot)slot; Object result = isSetter ? gslot.setter : gslot.getter; return result != null ? result : Undefined.instance; } else return Undefined.instance; } /** * Returns whether a property is a getter or a setter * @param name property name * @param index property index * @param setter true to check for a setter, false for a getter * @return whether the property is a getter or a setter */ protected boolean isGetterOrSetter(String name, int index, boolean setter) { Slot slot = getSlot(name, index, SLOT_QUERY); if (slot instanceof GetterSlot) { if (setter && ((GetterSlot)slot).setter != null) return true; if (!setter && ((GetterSlot)slot).getter != null) return true; } return false; } void addLazilyInitializedValue(String name, int index, LazilyLoadedCtor init, int attributes) { if (name != null && index != 0) throw new IllegalArgumentException(name); checkNotSealed(name, index); GetterSlot gslot = (GetterSlot)getSlot(name, index, SLOT_MODIFY_GETTER_SETTER); gslot.setAttributes(attributes); gslot.getter = null; gslot.setter = null; gslot.value = init; } /** * Returns the prototype of the object. */ public Scriptable getPrototype() { return prototypeObject; } /** * Sets the prototype of the object. */ public void setPrototype(Scriptable m) { prototypeObject = m; } /** * Returns the parent (enclosing) scope of the object. */ public Scriptable getParentScope() { return parentScopeObject; } /** * Sets the parent (enclosing) scope of the object. */ public void setParentScope(Scriptable m) { parentScopeObject = m; } /** * Returns an array of ids for the properties of the object. * *

Any properties with the attribute DONTENUM are not listed.

* * @return an array of java.lang.Objects with an entry for every * listed property. Properties accessed via an integer index will * have a corresponding * Integer entry in the returned array. Properties accessed by * a String will have a String entry in the returned array. */ public Object[] getIds() { return getIds(false); } /** * Returns an array of ids for the properties of the object. * *

All properties, even those with attribute DONTENUM, are listed.

* * @return an array of java.lang.Objects with an entry for every * listed property. Properties accessed via an integer index will * have a corresponding * Integer entry in the returned array. Properties accessed by * a String will have a String entry in the returned array. */ public Object[] getAllIds() { return getIds(true); } /** * Implements the [[DefaultValue]] internal method. * *

Note that the toPrimitive conversion is a no-op for * every type other than Object, for which [[DefaultValue]] * is called. See ECMA 9.1.

* * A hint of null means "no hint". * * @param typeHint the type hint * @return the default value for the object * * See ECMA 8.6.2.6. */ public Object getDefaultValue(Class typeHint) { return getDefaultValue(this, typeHint); } public static Object getDefaultValue(Scriptable object, Class typeHint) { Context cx = null; for (int i=0; i < 2; i++) { boolean tryToString; if (typeHint == ScriptRuntime.StringClass) { tryToString = (i == 0); } else { tryToString = (i == 1); } String methodName; Object[] args; if (tryToString) { methodName = "toString"; args = ScriptRuntime.emptyArgs; } else { methodName = "valueOf"; args = new Object[1]; String hint; if (typeHint == null) { hint = "undefined"; } else if (typeHint == ScriptRuntime.StringClass) { hint = "string"; } else if (typeHint == ScriptRuntime.ScriptableClass) { hint = "object"; } else if (typeHint == ScriptRuntime.FunctionClass) { hint = "function"; } else if (typeHint == ScriptRuntime.BooleanClass || typeHint == Boolean.TYPE) { hint = "boolean"; } else if (typeHint == ScriptRuntime.NumberClass || typeHint == ScriptRuntime.ByteClass || typeHint == Byte.TYPE || typeHint == ScriptRuntime.ShortClass || typeHint == Short.TYPE || typeHint == ScriptRuntime.IntegerClass || typeHint == Integer.TYPE || typeHint == ScriptRuntime.FloatClass || typeHint == Float.TYPE || typeHint == ScriptRuntime.DoubleClass || typeHint == Double.TYPE) { hint = "number"; } else { throw Context.reportRuntimeError1( "msg.invalid.type", typeHint.toString()); } args[0] = hint; } Object v = getProperty(object, methodName); if (!(v instanceof Function)) continue; Function fun = (Function) v; if (cx == null) cx = Context.getContext(); v = fun.call(cx, fun.getParentScope(), object, args); if (v != null) { if (!(v instanceof Scriptable)) { return v; } if (typeHint == ScriptRuntime.ScriptableClass || typeHint == ScriptRuntime.FunctionClass) { return v; } if (tryToString && v instanceof Wrapper) { // Let a wrapped java.lang.String pass for a primitive // string. Object u = ((Wrapper)v).unwrap(); if (u instanceof String) return u; } } } // fall through to error String arg = (typeHint == null) ? "undefined" : typeHint.getName(); throw ScriptRuntime.typeError1("msg.default.value", arg); } /** * Implements the instanceof operator. * *

This operator has been proposed to ECMA. * * @param instance The value that appeared on the LHS of the instanceof * operator * @return true if "this" appears in value's prototype chain * */ public boolean hasInstance(Scriptable instance) { // Default for JS objects (other than Function) is to do prototype // chasing. This will be overridden in NativeFunction and non-JS // objects. return ScriptRuntime.jsDelegatesTo(instance, this); } /** * Emulate the SpiderMonkey (and Firefox) feature of allowing * custom objects to avoid detection by normal "object detection" * code patterns. This is used to implement document.all. * See https://bugzilla.mozilla.org/show_bug.cgi?id=412247. * This is an analog to JOF_DETECTING from SpiderMonkey; see * https://bugzilla.mozilla.org/show_bug.cgi?id=248549. * Other than this special case, embeddings should return false. * @return true if this object should avoid object detection * @since 1.7R1 */ public boolean avoidObjectDetection() { return false; } /** * Custom == operator. * Must return {@link Scriptable#NOT_FOUND} if this object does not * have custom equality operator for the given value, * Boolean.TRUE if this object is equivalent to value, * Boolean.FALSE if this object is not equivalent to * value. *

* The default implementation returns Boolean.TRUE * if this == value or {@link Scriptable#NOT_FOUND} otherwise. * It indicates that by default custom equality is available only if * value is this in which case true is returned. */ protected Object equivalentValues(Object value) { return (this == value) ? Boolean.TRUE : Scriptable.NOT_FOUND; } /** * Defines JavaScript objects from a Java class that implements Scriptable. * * If the given class has a method *

     * static void init(Context cx, Scriptable scope, boolean sealed);
* * or its compatibility form *
     * static void init(Scriptable scope);
* * then it is invoked and no further initialization is done.

* * However, if no such a method is found, then the class's constructors and * methods are used to initialize a class in the following manner.

* * First, the zero-parameter constructor of the class is called to * create the prototype. If no such constructor exists, * a {@link EvaluatorException} is thrown.

* * Next, all methods are scanned for special prefixes that indicate that they * have special meaning for defining JavaScript objects. * These special prefixes are *

    *
  • jsFunction_ for a JavaScript function *
  • jsStaticFunction_ for a JavaScript function that * is a property of the constructor *
  • jsGet_ for a getter of a JavaScript property *
  • jsSet_ for a setter of a JavaScript property *
  • jsConstructor for a JavaScript function that * is the constructor *

* * If the method's name begins with "jsFunction_", a JavaScript function * is created with a name formed from the rest of the Java method name * following "jsFunction_". So a Java method named "jsFunction_foo" will * define a JavaScript method "foo". Calling this JavaScript function * will cause the Java method to be called. The parameters of the method * must be of number and types as defined by the FunctionObject class. * The JavaScript function is then added as a property * of the prototype.

* * If the method's name begins with "jsStaticFunction_", it is handled * similarly except that the resulting JavaScript function is added as a * property of the constructor object. The Java method must be static. * * If the method's name begins with "jsGet_" or "jsSet_", the method is * considered to define a property. Accesses to the defined property * will result in calls to these getter and setter methods. If no * setter is defined, the property is defined as READONLY.

* * If the method's name is "jsConstructor", the method is * considered to define the body of the constructor. Only one * method of this name may be defined. You may use the varargs forms * for constructors documented in {@link FunctionObject#FunctionObject(String, Member, Scriptable)} * * If no method is found that can serve as constructor, a Java * constructor will be selected to serve as the JavaScript * constructor in the following manner. If the class has only one * Java constructor, that constructor is used to define * the JavaScript constructor. If the the class has two constructors, * one must be the zero-argument constructor (otherwise an * {@link EvaluatorException} would have already been thrown * when the prototype was to be created). In this case * the Java constructor with one or more parameters will be used * to define the JavaScript constructor. If the class has three * or more constructors, an {@link EvaluatorException} * will be thrown.

* * Finally, if there is a method *

     * static void finishInit(Scriptable scope, FunctionObject constructor,
     *                        Scriptable prototype)
* * it will be called to finish any initialization. The scope * argument will be passed, along with the newly created constructor and * the newly created prototype.

* * @param scope The scope in which to define the constructor. * @param clazz The Java class to use to define the JavaScript objects * and properties. * @exception IllegalAccessException if access is not available * to a reflected class member * @exception InstantiationException if unable to instantiate * the named class * @exception InvocationTargetException if an exception is thrown * during execution of methods of the named class * @see org.mozilla.javascript.Function * @see org.mozilla.javascript.FunctionObject * @see org.mozilla.javascript.ScriptableObject#READONLY * @see org.mozilla.javascript.ScriptableObject * #defineProperty(String, Class, int) */ public static void defineClass( Scriptable scope, Class clazz) throws IllegalAccessException, InstantiationException, InvocationTargetException { defineClass(scope, clazz, false, false); } /** * Defines JavaScript objects from a Java class, optionally * allowing sealing. * * Similar to defineClass(Scriptable scope, Class clazz) * except that sealing is allowed. An object that is sealed cannot have * properties added or removed. Note that sealing is not allowed in * the current ECMA/ISO language specification, but is likely for * the next version. * * @param scope The scope in which to define the constructor. * @param clazz The Java class to use to define the JavaScript objects * and properties. The class must implement Scriptable. * @param sealed Whether or not to create sealed standard objects that * cannot be modified. * @exception IllegalAccessException if access is not available * to a reflected class member * @exception InstantiationException if unable to instantiate * the named class * @exception InvocationTargetException if an exception is thrown * during execution of methods of the named class * @since 1.4R3 */ public static void defineClass( Scriptable scope, Class clazz, boolean sealed) throws IllegalAccessException, InstantiationException, InvocationTargetException { defineClass(scope, clazz, sealed, false); } /** * Defines JavaScript objects from a Java class, optionally * allowing sealing and mapping of Java inheritance to JavaScript * prototype-based inheritance. * * Similar to defineClass(Scriptable scope, Class clazz) * except that sealing and inheritance mapping are allowed. An object * that is sealed cannot have properties added or removed. Note that * sealing is not allowed in the current ECMA/ISO language specification, * but is likely for the next version. * * @param scope The scope in which to define the constructor. * @param clazz The Java class to use to define the JavaScript objects * and properties. The class must implement Scriptable. * @param sealed Whether or not to create sealed standard objects that * cannot be modified. * @param mapInheritance Whether or not to map Java inheritance to * JavaScript prototype-based inheritance. * @return the class name for the prototype of the specified class * @exception IllegalAccessException if access is not available * to a reflected class member * @exception InstantiationException if unable to instantiate * the named class * @exception InvocationTargetException if an exception is thrown * during execution of methods of the named class * @since 1.6R2 */ public static String defineClass( Scriptable scope, Class clazz, boolean sealed, boolean mapInheritance) throws IllegalAccessException, InstantiationException, InvocationTargetException { BaseFunction ctor = buildClassCtor(scope, clazz, sealed, mapInheritance); if (ctor == null) return null; String name = ctor.getClassPrototype().getClassName(); defineProperty(scope, name, ctor, ScriptableObject.DONTENUM); return name; } static BaseFunction buildClassCtor( Scriptable scope, Class clazz, boolean sealed, boolean mapInheritance) throws IllegalAccessException, InstantiationException, InvocationTargetException { Method[] methods = FunctionObject.getMethodList(clazz); for (int i=0; i < methods.length; i++) { Method method = methods[i]; if (!method.getName().equals("init")) continue; Class[] parmTypes = method.getParameterTypes(); if (parmTypes.length == 3 && parmTypes[0] == ScriptRuntime.ContextClass && parmTypes[1] == ScriptRuntime.ScriptableClass && parmTypes[2] == Boolean.TYPE && Modifier.isStatic(method.getModifiers())) { Object args[] = { Context.getContext(), scope, sealed ? Boolean.TRUE : Boolean.FALSE }; method.invoke(null, args); return null; } if (parmTypes.length == 1 && parmTypes[0] == ScriptRuntime.ScriptableClass && Modifier.isStatic(method.getModifiers())) { Object args[] = { scope }; method.invoke(null, args); return null; } } // If we got here, there isn't an "init" method with the right // parameter types. Constructor[] ctors = clazz.getConstructors(); Constructor protoCtor = null; for (int i=0; i < ctors.length; i++) { if (ctors[i].getParameterTypes().length == 0) { protoCtor = ctors[i]; break; } } if (protoCtor == null) { throw Context.reportRuntimeError1( "msg.zero.arg.ctor", clazz.getName()); } Scriptable proto = (Scriptable) protoCtor.newInstance(ScriptRuntime.emptyArgs); String className = proto.getClassName(); // Set the prototype's prototype, trying to map Java inheritance to JS // prototype-based inheritance if requested to do so. Scriptable superProto = null; if (mapInheritance) { Class superClass = clazz.getSuperclass(); if (ScriptRuntime.ScriptableClass.isAssignableFrom(superClass) && !Modifier.isAbstract(superClass.getModifiers())) { Class superScriptable = extendsScriptable(superClass); String name = ScriptableObject.defineClass(scope, superScriptable, sealed, mapInheritance); if (name != null) { superProto = ScriptableObject.getClassPrototype(scope, name); } } } if (superProto == null) { superProto = ScriptableObject.getObjectPrototype(scope); } proto.setPrototype(superProto); // Find out whether there are any methods that begin with // "js". If so, then only methods that begin with special // prefixes will be defined as JavaScript entities. final String functionPrefix = "jsFunction_"; final String staticFunctionPrefix = "jsStaticFunction_"; final String getterPrefix = "jsGet_"; final String setterPrefix = "jsSet_"; final String ctorName = "jsConstructor"; Member ctorMember = findAnnotatedMember(methods, JSConstructor.class); if (ctorMember == null) { ctorMember = findAnnotatedMember(ctors, JSConstructor.class); } if (ctorMember == null) { ctorMember = FunctionObject.findSingleMethod(methods, ctorName); } if (ctorMember == null) { if (ctors.length == 1) { ctorMember = ctors[0]; } else if (ctors.length == 2) { if (ctors[0].getParameterTypes().length == 0) ctorMember = ctors[1]; else if (ctors[1].getParameterTypes().length == 0) ctorMember = ctors[0]; } if (ctorMember == null) { throw Context.reportRuntimeError1( "msg.ctor.multiple.parms", clazz.getName()); } } FunctionObject ctor = new FunctionObject(className, ctorMember, scope); if (ctor.isVarArgsMethod()) { throw Context.reportRuntimeError1 ("msg.varargs.ctor", ctorMember.getName()); } ctor.initAsConstructor(scope, proto); Method finishInit = null; HashSet names = new HashSet(methods.length); for (Method method : methods) { if (method == ctorMember) { continue; } String name = method.getName(); if (name.equals("finishInit")) { Class[] parmTypes = method.getParameterTypes(); if (parmTypes.length == 3 && parmTypes[0] == ScriptRuntime.ScriptableClass && parmTypes[1] == FunctionObject.class && parmTypes[2] == ScriptRuntime.ScriptableClass && Modifier.isStatic(method.getModifiers())) { finishInit = method; continue; } } // ignore any compiler generated methods. if (name.indexOf('$') != -1) continue; if (name.equals(ctorName)) continue; Annotation annotation = null; String prefix = null; if (method.isAnnotationPresent(JSFunction.class)) { annotation = method.getAnnotation(JSFunction.class); } else if (method.isAnnotationPresent(JSStaticFunction.class)) { annotation = method.getAnnotation(JSStaticFunction.class); } else if (method.isAnnotationPresent(JSGetter.class)) { annotation = method.getAnnotation(JSGetter.class); } else if (method.isAnnotationPresent(JSSetter.class)) { continue; } if (annotation == null) { if (name.startsWith(functionPrefix)) { prefix = functionPrefix; } else if (name.startsWith(staticFunctionPrefix)) { prefix = staticFunctionPrefix; } else if (name.startsWith(getterPrefix)) { prefix = getterPrefix; } else if (annotation == null) { // note that setterPrefix is among the unhandled names here - // we deal with that when we see the getter continue; } } String propName = getPropertyName(name, prefix, annotation); if (names.contains(propName)) { throw Context.reportRuntimeError2("duplicate.defineClass.name", name, propName); } names.add(propName); name = propName; if (annotation instanceof JSGetter || prefix == getterPrefix) { if (!(proto instanceof ScriptableObject)) { throw Context.reportRuntimeError2( "msg.extend.scriptable", proto.getClass().toString(), name); } Method setter = findSetterMethod(methods, name, setterPrefix); int attr = ScriptableObject.PERMANENT | ScriptableObject.DONTENUM | (setter != null ? 0 : ScriptableObject.READONLY); ((ScriptableObject) proto).defineProperty(name, null, method, setter, attr); continue; } boolean isStatic = annotation instanceof JSStaticFunction || prefix == staticFunctionPrefix; if (isStatic && !Modifier.isStatic(method.getModifiers())) { throw Context.reportRuntimeError( "jsStaticFunction must be used with static method."); } FunctionObject f = new FunctionObject(name, method, proto); if (f.isVarArgsConstructor()) { throw Context.reportRuntimeError1 ("msg.varargs.fun", ctorMember.getName()); } defineProperty(isStatic ? ctor : proto, name, f, DONTENUM); if (sealed) { f.sealObject(); } } // Call user code to complete initialization if necessary. if (finishInit != null) { Object[] finishArgs = { scope, ctor, proto }; finishInit.invoke(null, finishArgs); } // Seal the object if necessary. if (sealed) { ctor.sealObject(); if (proto instanceof ScriptableObject) { ((ScriptableObject) proto).sealObject(); } } return ctor; } private static Member findAnnotatedMember(AccessibleObject[] members, Class annotation) { for (AccessibleObject member : members) { if (member.isAnnotationPresent(annotation)) { return (Member) member; } } return null; } private static Method findSetterMethod(Method[] methods, String name, String prefix) { String newStyleName = "set" + Character.toUpperCase(name.charAt(0)) + name.substring(1); for (Method method : methods) { JSSetter annotation = method.getAnnotation(JSSetter.class); if (annotation != null) { if (name.equals(annotation.value()) || ("".equals(annotation.value()) && newStyleName.equals(method.getName()))) { return method; } } } String oldStyleName = prefix + name; for (Method method : methods) { if (oldStyleName.equals(method.getName())) { return method; } } return null; } private static String getPropertyName(String methodName, String prefix, Annotation annotation) { if (prefix != null) { return methodName.substring(prefix.length()); } String propName = null; if (annotation instanceof JSGetter) { propName = ((JSGetter) annotation).value(); if (propName == null || propName.length() == 0) { if (methodName.length() > 3 && methodName.startsWith("get")) { propName = methodName.substring(3); if (Character.isUpperCase(propName.charAt(0))) { if (propName.length() == 1) { propName = propName.toLowerCase(); } else if (!Character.isUpperCase(propName.charAt(1))){ propName = Character.toLowerCase(propName.charAt(0)) + propName.substring(1); } } } } } else if (annotation instanceof JSFunction) { propName = ((JSFunction) annotation).value(); } else if (annotation instanceof JSStaticFunction) { propName = ((JSStaticFunction) annotation).value(); } if (propName == null || propName.length() == 0) { propName = methodName; } return propName; } @SuppressWarnings({"unchecked"}) private static Class extendsScriptable(Class c) { if (ScriptRuntime.ScriptableClass.isAssignableFrom(c)) return (Class) c; return null; } /** * Define a JavaScript property. * * Creates the property with an initial value and sets its attributes. * * @param propertyName the name of the property to define. * @param value the initial value of the property * @param attributes the attributes of the JavaScript property * @see org.mozilla.javascript.Scriptable#put(String, Scriptable, Object) */ public void defineProperty(String propertyName, Object value, int attributes) { checkNotSealed(propertyName, 0); put(propertyName, this, value); setAttributes(propertyName, attributes); } /** * Utility method to add properties to arbitrary Scriptable object. * If destination is instance of ScriptableObject, calls * defineProperty there, otherwise calls put in destination * ignoring attributes */ public static void defineProperty(Scriptable destination, String propertyName, Object value, int attributes) { if (!(destination instanceof ScriptableObject)) { destination.put(propertyName, destination, value); return; } ScriptableObject so = (ScriptableObject)destination; so.defineProperty(propertyName, value, attributes); } /** * Utility method to add properties to arbitrary Scriptable object. * If destination is instance of ScriptableObject, calls * defineProperty there, otherwise calls put in destination * ignoring attributes */ public static void defineConstProperty(Scriptable destination, String propertyName) { if (destination instanceof ConstProperties) { ConstProperties cp = (ConstProperties)destination; cp.defineConst(propertyName, destination); } else defineProperty(destination, propertyName, Undefined.instance, CONST); } /** * Define a JavaScript property with getter and setter side effects. * * If the setter is not found, the attribute READONLY is added to * the given attributes.

* * The getter must be a method with zero parameters, and the setter, if * found, must be a method with one parameter.

* * @param propertyName the name of the property to define. This name * also affects the name of the setter and getter * to search for. If the propertyId is "foo", then * clazz will be searched for "getFoo" * and "setFoo" methods. * @param clazz the Java class to search for the getter and setter * @param attributes the attributes of the JavaScript property * @see org.mozilla.javascript.Scriptable#put(String, Scriptable, Object) */ public void defineProperty(String propertyName, Class clazz, int attributes) { int length = propertyName.length(); if (length == 0) throw new IllegalArgumentException(); char[] buf = new char[3 + length]; propertyName.getChars(0, length, buf, 3); buf[3] = Character.toUpperCase(buf[3]); buf[0] = 'g'; buf[1] = 'e'; buf[2] = 't'; String getterName = new String(buf); buf[0] = 's'; String setterName = new String(buf); Method[] methods = FunctionObject.getMethodList(clazz); Method getter = FunctionObject.findSingleMethod(methods, getterName); Method setter = FunctionObject.findSingleMethod(methods, setterName); if (setter == null) attributes |= ScriptableObject.READONLY; defineProperty(propertyName, null, getter, setter == null ? null : setter, attributes); } /** * Define a JavaScript property. * * Use this method only if you wish to define getters and setters for * a given property in a ScriptableObject. To create a property without * special getter or setter side effects, use * defineProperty(String,int). * * If setter is null, the attribute READONLY is added to * the given attributes.

* * Several forms of getters or setters are allowed. In all cases the * type of the value parameter can be any one of the following types: * Object, String, boolean, Scriptable, byte, short, int, long, float, * or double. The runtime will perform appropriate conversions based * upon the type of the parameter (see description in FunctionObject). * The first forms are nonstatic methods of the class referred to * by 'this': *

     * Object getFoo();
     * void setFoo(SomeType value);
* Next are static methods that may be of any class; the object whose * property is being accessed is passed in as an extra argument: *
     * static Object getFoo(Scriptable obj);
     * static void setFoo(Scriptable obj, SomeType value);
* Finally, it is possible to delegate to another object entirely using * the delegateTo parameter. In this case the methods are * nonstatic methods of the class delegated to, and the object whose * property is being accessed is passed in as an extra argument: *
     * Object getFoo(Scriptable obj);
     * void setFoo(Scriptable obj, SomeType value);
* * @param propertyName the name of the property to define. * @param delegateTo an object to call the getter and setter methods on, * or null, depending on the form used above. * @param getter the method to invoke to get the value of the property * @param setter the method to invoke to set the value of the property * @param attributes the attributes of the JavaScript property */ public void defineProperty(String propertyName, Object delegateTo, Method getter, Method setter, int attributes) { MemberBox getterBox = null; if (getter != null) { getterBox = new MemberBox(getter); boolean delegatedForm; if (!Modifier.isStatic(getter.getModifiers())) { delegatedForm = (delegateTo != null); getterBox.delegateTo = delegateTo; } else { delegatedForm = true; // Ignore delegateTo for static getter but store // non-null delegateTo indicator. getterBox.delegateTo = Void.TYPE; } String errorId = null; Class[] parmTypes = getter.getParameterTypes(); if (parmTypes.length == 0) { if (delegatedForm) { errorId = "msg.obj.getter.parms"; } } else if (parmTypes.length == 1) { Object argType = parmTypes[0]; // Allow ScriptableObject for compatibility if (!(argType == ScriptRuntime.ScriptableClass || argType == ScriptRuntime.ScriptableObjectClass)) { errorId = "msg.bad.getter.parms"; } else if (!delegatedForm) { errorId = "msg.bad.getter.parms"; } } else { errorId = "msg.bad.getter.parms"; } if (errorId != null) { throw Context.reportRuntimeError1(errorId, getter.toString()); } } MemberBox setterBox = null; if (setter != null) { if (setter.getReturnType() != Void.TYPE) throw Context.reportRuntimeError1("msg.setter.return", setter.toString()); setterBox = new MemberBox(setter); boolean delegatedForm; if (!Modifier.isStatic(setter.getModifiers())) { delegatedForm = (delegateTo != null); setterBox.delegateTo = delegateTo; } else { delegatedForm = true; // Ignore delegateTo for static setter but store // non-null delegateTo indicator. setterBox.delegateTo = Void.TYPE; } String errorId = null; Class[] parmTypes = setter.getParameterTypes(); if (parmTypes.length == 1) { if (delegatedForm) { errorId = "msg.setter2.expected"; } } else if (parmTypes.length == 2) { Object argType = parmTypes[0]; // Allow ScriptableObject for compatibility if (!(argType == ScriptRuntime.ScriptableClass || argType == ScriptRuntime.ScriptableObjectClass)) { errorId = "msg.setter2.parms"; } else if (!delegatedForm) { errorId = "msg.setter1.parms"; } } else { errorId = "msg.setter.parms"; } if (errorId != null) { throw Context.reportRuntimeError1(errorId, setter.toString()); } } GetterSlot gslot = (GetterSlot)getSlot(propertyName, 0, SLOT_MODIFY_GETTER_SETTER); gslot.setAttributes(attributes); gslot.getter = getterBox; gslot.setter = setterBox; } public void defineOwnProperties(Context cx, ScriptableObject props) { Object[] ids = props.getIds(); for (Object id : ids) { String name = ScriptRuntime.toString(id); Object descObj = props.get(id); ScriptableObject desc = ensureScriptableObject(descObj); checkValidPropertyDefinition(getSlot(name, 0, SLOT_QUERY), desc); } for (Object id : ids) { String name = ScriptRuntime.toString(id); ScriptableObject desc = (ScriptableObject) props.get(id); defineOwnProperty(cx, name, desc, false); } } /** * Defines a property on an object * * Based on [[DefineOwnProperty]] from 8.12.10 of the spec * * @param cx the current Context * @param id the name/index of the property * @param desc the new property descriptor, as described in 8.6.1 */ public void defineOwnProperty(Context cx, Object id, ScriptableObject desc) { defineOwnProperty(cx, id, desc, true); } private void defineOwnProperty(Context cx, Object id, ScriptableObject desc, boolean checkValid) { Slot slot = getSlot(cx, id, SLOT_QUERY); if (checkValid) checkValidPropertyDefinition(slot, desc); final int attributes; if (slot == null) { // new slot slot = getSlot(cx, id, SLOT_MODIFY); attributes = applyDescriptorToAttributeBitset(DONTENUM|READONLY|PERMANENT, desc); } else { attributes = applyDescriptorToAttributeBitset(slot.getAttributes(), desc); } defineOwnProperty(cx, slot, desc, attributes); } private void defineOwnProperty(Context cx, Slot slot, ScriptableObject desc, int attributes) { String name = slot.name; int index = slot.indexOrHash; if (isAccessorDescriptor(desc)) { if ( !(slot instanceof GetterSlot) ) { slot = getSlot(cx, (name != null ? name : index), SLOT_MODIFY_GETTER_SETTER); } GetterSlot gslot = (GetterSlot) slot; Object getter = getProperty(desc, "get"); if (getter != NOT_FOUND) { gslot.getter = getter; } Object setter = getProperty(desc, "set"); if (setter != NOT_FOUND) { gslot.setter = setter; } gslot.value = Undefined.instance; gslot.setAttributes(attributes); } else { if (slot instanceof GetterSlot && isDataDescriptor(desc)) { slot = getSlot(cx, (name != null ? name : index), SLOT_CONVERT_ACCESSOR_TO_DATA); } Object value = getProperty(desc, "value"); if (value != NOT_FOUND) { slot.value = value; } slot.setAttributes(attributes); } } private void checkValidPropertyDefinition(Slot slot, ScriptableObject desc) { Object getter = getProperty(desc, "get"); if (getter != NOT_FOUND && getter != Undefined.instance && !(getter instanceof Callable)) { throw ScriptRuntime.notFunctionError(getter); } Object setter = getProperty(desc, "set"); if (setter != NOT_FOUND && setter != Undefined.instance && !(setter instanceof Callable)) { throw ScriptRuntime.notFunctionError(setter); } if (isDataDescriptor(desc) && isAccessorDescriptor(desc)) { throw ScriptRuntime.typeError0("msg.both.data.and.accessor.desc"); } if (slot == null) { // new property if (!isExtensible()) throw ScriptRuntime.typeError("msg.not.extensible"); } else { String name = slot.name; ScriptableObject current = getOwnPropertyDescriptor(Context.getContext(), name); if (isFalse(current.get("configurable", current))) { if (isTrue(getProperty(desc, "configurable"))) throw ScriptRuntime.typeError1("msg.change.configurable.false.to.true", name); if (isTrue(current.get("enumerable", current)) != isTrue(getProperty(desc, "enumerable"))) throw ScriptRuntime.typeError1("msg.change.enumerable.with.configurable.false", name); if (isGenericDescriptor(desc)) { // no further validation required } else if (isDataDescriptor(desc) && isDataDescriptor(current)) { if (isFalse(current.get("writable", current))) { if (isTrue(getProperty(desc, "writable"))) throw ScriptRuntime.typeError1("msg.change.writable.false.to.true.with.configurable.false", name); if (changes(current.get("value", current), getProperty(desc, "value"))) throw ScriptRuntime.typeError1("msg.change.value.with.writable.false", name); } } else if (isAccessorDescriptor(desc) && isAccessorDescriptor(current)) { if (changes(current.get("set", current), setter)) throw ScriptRuntime.typeError1("msg.change.setter.with.configurable.false", name); if (changes(current.get("get", current), getter)) throw ScriptRuntime.typeError1("msg.change.getter.with.configurable.false", name); } else { if (isDataDescriptor(current)) throw ScriptRuntime.typeError1("msg.change.property.data.to.accessor.with.configurable.false", name); else throw ScriptRuntime.typeError1("msg.change.property.accessor.to.data.with.configurable.false", name); } } } } protected static boolean isTrue(Object value) { return (value == NOT_FOUND) ? false : ScriptRuntime.toBoolean(value); } protected static boolean isFalse(Object value) { return !isTrue(value); } private boolean changes(Object currentValue, Object newValue) { if (newValue == NOT_FOUND) return false; if (currentValue == NOT_FOUND) { currentValue = Undefined.instance; } return !ScriptRuntime.shallowEq(currentValue, newValue); } protected int applyDescriptorToAttributeBitset(int attributes, ScriptableObject desc) { Object enumerable = getProperty(desc, "enumerable"); if (enumerable != NOT_FOUND) { attributes = ScriptRuntime.toBoolean(enumerable) ? attributes & ~DONTENUM : attributes | DONTENUM; } Object writable = getProperty(desc, "writable"); if (writable != NOT_FOUND) { attributes = ScriptRuntime.toBoolean(writable) ? attributes & ~READONLY : attributes | READONLY; } Object configurable = getProperty(desc, "configurable"); if (configurable != NOT_FOUND) { attributes = ScriptRuntime.toBoolean(configurable) ? attributes & ~PERMANENT : attributes | PERMANENT; } return attributes; } protected boolean isDataDescriptor(ScriptableObject desc) { return hasProperty(desc, "value") || hasProperty(desc, "writable"); } protected boolean isAccessorDescriptor(ScriptableObject desc) { return hasProperty(desc, "get") || hasProperty(desc, "set"); } protected boolean isGenericDescriptor(ScriptableObject desc) { return !isDataDescriptor(desc) && !isAccessorDescriptor(desc); } protected Scriptable ensureScriptable(Object arg) { if ( !(arg instanceof Scriptable) ) throw ScriptRuntime.typeError1("msg.arg.not.object", ScriptRuntime.typeof(arg)); return (Scriptable) arg; } protected ScriptableObject ensureScriptableObject(Object arg) { if ( !(arg instanceof ScriptableObject) ) throw ScriptRuntime.typeError1("msg.arg.not.object", ScriptRuntime.typeof(arg)); return (ScriptableObject) arg; } /** * Search for names in a class, adding the resulting methods * as properties. * *

Uses reflection to find the methods of the given names. Then * FunctionObjects are constructed from the methods found, and * are added to this object as properties with the given names. * * @param names the names of the Methods to add as function properties * @param clazz the class to search for the Methods * @param attributes the attributes of the new properties * @see org.mozilla.javascript.FunctionObject */ public void defineFunctionProperties(String[] names, Class clazz, int attributes) { Method[] methods = FunctionObject.getMethodList(clazz); for (int i=0; i < names.length; i++) { String name = names[i]; Method m = FunctionObject.findSingleMethod(methods, name); if (m == null) { throw Context.reportRuntimeError2( "msg.method.not.found", name, clazz.getName()); } FunctionObject f = new FunctionObject(name, m, this); defineProperty(name, f, attributes); } } /** * Get the Object.prototype property. * See ECMA 15.2.4. */ public static Scriptable getObjectPrototype(Scriptable scope) { return getClassPrototype(scope, "Object"); } /** * Get the Function.prototype property. * See ECMA 15.3.4. */ public static Scriptable getFunctionPrototype(Scriptable scope) { return getClassPrototype(scope, "Function"); } public static Scriptable getArrayPrototype(Scriptable scope) { return getClassPrototype(scope, "Array"); } /** * Get the prototype for the named class. * * For example, getClassPrototype(s, "Date") will first * walk up the parent chain to find the outermost scope, then will * search that scope for the Date constructor, and then will * return Date.prototype. If any of the lookups fail, or * the prototype is not a JavaScript object, then null will * be returned. * * @param scope an object in the scope chain * @param className the name of the constructor * @return the prototype for the named class, or null if it * cannot be found. */ public static Scriptable getClassPrototype(Scriptable scope, String className) { scope = getTopLevelScope(scope); Object ctor = getProperty(scope, className); Object proto; if (ctor instanceof BaseFunction) { proto = ((BaseFunction)ctor).getPrototypeProperty(); } else if (ctor instanceof Scriptable) { Scriptable ctorObj = (Scriptable)ctor; proto = ctorObj.get("prototype", ctorObj); } else { return null; } if (proto instanceof Scriptable) { return (Scriptable)proto; } return null; } /** * Get the global scope. * *

Walks the parent scope chain to find an object with a null * parent scope (the global object). * * @param obj a JavaScript object * @return the corresponding global scope */ public static Scriptable getTopLevelScope(Scriptable obj) { for (;;) { Scriptable parent = obj.getParentScope(); if (parent == null) { return obj; } obj = parent; } } public boolean isExtensible() { return isExtensible; } public void preventExtensions() { isExtensible = false; } /** * Seal this object. * * It is an error to add properties to or delete properties from * a sealed object. It is possible to change the value of an * existing property. Once an object is sealed it may not be unsealed. * * @since 1.4R3 */ public synchronized void sealObject() { if (count >= 0) { // Make sure all LazilyLoadedCtors are initialized before sealing. Slot slot = firstAdded; while (slot != null) { if (slot.value instanceof LazilyLoadedCtor) { LazilyLoadedCtor initializer = (LazilyLoadedCtor) slot.value; try { initializer.init(); } finally { slot.value = initializer.getValue(); } } slot = slot.orderedNext; } count = ~count; } } /** * Return true if this object is sealed. * * @return true if sealed, false otherwise. * @since 1.4R3 * @see #sealObject() */ public final boolean isSealed() { return count < 0; } private void checkNotSealed(String name, int index) { if (!isSealed()) return; String str = (name != null) ? name : Integer.toString(index); throw Context.reportRuntimeError1("msg.modify.sealed", str); } /** * Gets a named property from an object or any object in its prototype chain. *

* Searches the prototype chain for a property named name. *

* @param obj a JavaScript object * @param name a property name * @return the value of a property with name name found in * obj or any object in its prototype chain, or * Scriptable.NOT_FOUND if not found * @since 1.5R2 */ public static Object getProperty(Scriptable obj, String name) { Scriptable start = obj; Object result; do { result = obj.get(name, start); if (result != Scriptable.NOT_FOUND) break; obj = obj.getPrototype(); } while (obj != null); return result; } /** * Gets an indexed property from an object or any object in its prototype chain. *

* Searches the prototype chain for a property with integral index * index. Note that if you wish to look for properties with numerical * but non-integral indicies, you should use getProperty(Scriptable,String) with * the string value of the index. *

* @param obj a JavaScript object * @param index an integral index * @return the value of a property with index index found in * obj or any object in its prototype chain, or * Scriptable.NOT_FOUND if not found * @since 1.5R2 */ public static Object getProperty(Scriptable obj, int index) { Scriptable start = obj; Object result; do { result = obj.get(index, start); if (result != Scriptable.NOT_FOUND) break; obj = obj.getPrototype(); } while (obj != null); return result; } /** * Returns whether a named property is defined in an object or any object * in its prototype chain. *

* Searches the prototype chain for a property named name. *

* @param obj a JavaScript object * @param name a property name * @return the true if property was found * @since 1.5R2 */ public static boolean hasProperty(Scriptable obj, String name) { return null != getBase(obj, name); } /** * If hasProperty(obj, name) would return true, then if the property that * was found is compatible with the new property, this method just returns. * If the property is not compatible, then an exception is thrown. * * A property redefinition is incompatible if the first definition was a * const declaration or if this one is. They are compatible only if neither * was const. */ public static void redefineProperty(Scriptable obj, String name, boolean isConst) { Scriptable base = getBase(obj, name); if (base == null) return; if (base instanceof ConstProperties) { ConstProperties cp = (ConstProperties)base; if (cp.isConst(name)) throw Context.reportRuntimeError1("msg.const.redecl", name); } if (isConst) throw Context.reportRuntimeError1("msg.var.redecl", name); } /** * Returns whether an indexed property is defined in an object or any object * in its prototype chain. *

* Searches the prototype chain for a property with index index. *

* @param obj a JavaScript object * @param index a property index * @return the true if property was found * @since 1.5R2 */ public static boolean hasProperty(Scriptable obj, int index) { return null != getBase(obj, index); } /** * Puts a named property in an object or in an object in its prototype chain. *

* Searches for the named property in the prototype chain. If it is found, * the value of the property in obj is changed through a call * to {@link Scriptable#put(String, Scriptable, Object)} on the * prototype passing obj as the start argument. * This allows the prototype to veto the property setting in case the * prototype defines the property with [[ReadOnly]] attribute. If the * property is not found, it is added in obj. * @param obj a JavaScript object * @param name a property name * @param value any JavaScript value accepted by Scriptable.put * @since 1.5R2 */ public static void putProperty(Scriptable obj, String name, Object value) { Scriptable base = getBase(obj, name); if (base == null) base = obj; base.put(name, obj, value); } /** * Puts a named property in an object or in an object in its prototype chain. *

* Searches for the named property in the prototype chain. If it is found, * the value of the property in obj is changed through a call * to {@link Scriptable#put(String, Scriptable, Object)} on the * prototype passing obj as the start argument. * This allows the prototype to veto the property setting in case the * prototype defines the property with [[ReadOnly]] attribute. If the * property is not found, it is added in obj. * @param obj a JavaScript object * @param name a property name * @param value any JavaScript value accepted by Scriptable.put * @since 1.5R2 */ public static void putConstProperty(Scriptable obj, String name, Object value) { Scriptable base = getBase(obj, name); if (base == null) base = obj; if (base instanceof ConstProperties) ((ConstProperties)base).putConst(name, obj, value); } /** * Puts an indexed property in an object or in an object in its prototype chain. *

* Searches for the indexed property in the prototype chain. If it is found, * the value of the property in obj is changed through a call * to {@link Scriptable#put(int, Scriptable, Object)} on the prototype * passing obj as the start argument. This allows * the prototype to veto the property setting in case the prototype defines * the property with [[ReadOnly]] attribute. If the property is not found, * it is added in obj. * @param obj a JavaScript object * @param index a property index * @param value any JavaScript value accepted by Scriptable.put * @since 1.5R2 */ public static void putProperty(Scriptable obj, int index, Object value) { Scriptable base = getBase(obj, index); if (base == null) base = obj; base.put(index, obj, value); } /** * Removes the property from an object or its prototype chain. *

* Searches for a property with name in obj or * its prototype chain. If it is found, the object's delete * method is called. * @param obj a JavaScript object * @param name a property name * @return true if the property doesn't exist or was successfully removed * @since 1.5R2 */ public static boolean deleteProperty(Scriptable obj, String name) { Scriptable base = getBase(obj, name); if (base == null) return true; base.delete(name); return !base.has(name, obj); } /** * Removes the property from an object or its prototype chain. *

* Searches for a property with index in obj or * its prototype chain. If it is found, the object's delete * method is called. * @param obj a JavaScript object * @param index a property index * @return true if the property doesn't exist or was successfully removed * @since 1.5R2 */ public static boolean deleteProperty(Scriptable obj, int index) { Scriptable base = getBase(obj, index); if (base == null) return true; base.delete(index); return !base.has(index, obj); } /** * Returns an array of all ids from an object and its prototypes. *

* @param obj a JavaScript object * @return an array of all ids from all object in the prototype chain. * If a given id occurs multiple times in the prototype chain, * it will occur only once in this list. * @since 1.5R2 */ public static Object[] getPropertyIds(Scriptable obj) { if (obj == null) { return ScriptRuntime.emptyArgs; } Object[] result = obj.getIds(); ObjToIntMap map = null; for (;;) { obj = obj.getPrototype(); if (obj == null) { break; } Object[] ids = obj.getIds(); if (ids.length == 0) { continue; } if (map == null) { if (result.length == 0) { result = ids; continue; } map = new ObjToIntMap(result.length + ids.length); for (int i = 0; i != result.length; ++i) { map.intern(result[i]); } result = null; // Allow to GC the result } for (int i = 0; i != ids.length; ++i) { map.intern(ids[i]); } } if (map != null) { result = map.getKeys(); } return result; } /** * Call a method of an object. * @param obj the JavaScript object * @param methodName the name of the function property * @param args the arguments for the call * * @see Context#getCurrentContext() */ public static Object callMethod(Scriptable obj, String methodName, Object[] args) { return callMethod(null, obj, methodName, args); } /** * Call a method of an object. * @param cx the Context object associated with the current thread. * @param obj the JavaScript object * @param methodName the name of the function property * @param args the arguments for the call */ public static Object callMethod(Context cx, Scriptable obj, String methodName, Object[] args) { Object funObj = getProperty(obj, methodName); if (!(funObj instanceof Function)) { throw ScriptRuntime.notFunctionError(obj, methodName); } Function fun = (Function)funObj; // XXX: What should be the scope when calling funObj? // The following favor scope stored in the object on the assumption // that is more useful especially under dynamic scope setup. // An alternative is to check for dynamic scope flag // and use ScriptableObject.getTopLevelScope(fun) if the flag is not // set. But that require access to Context and messy code // so for now it is not checked. Scriptable scope = ScriptableObject.getTopLevelScope(obj); if (cx != null) { return fun.call(cx, scope, obj, args); } else { return Context.call(null, fun, scope, obj, args); } } private static Scriptable getBase(Scriptable obj, String name) { do { if (obj.has(name, obj)) break; obj = obj.getPrototype(); } while(obj != null); return obj; } private static Scriptable getBase(Scriptable obj, int index) { do { if (obj.has(index, obj)) break; obj = obj.getPrototype(); } while(obj != null); return obj; } /** * Get arbitrary application-specific value associated with this object. * @param key key object to select particular value. * @see #associateValue(Object key, Object value) */ public final Object getAssociatedValue(Object key) { Map h = associatedValues; if (h == null) return null; return h.get(key); } /** * Get arbitrary application-specific value associated with the top scope * of the given scope. * The method first calls {@link #getTopLevelScope(Scriptable scope)} * and then searches the prototype chain of the top scope for the first * object containing the associated value with the given key. * * @param scope the starting scope. * @param key key object to select particular value. * @see #getAssociatedValue(Object key) */ public static Object getTopScopeValue(Scriptable scope, Object key) { scope = ScriptableObject.getTopLevelScope(scope); for (;;) { if (scope instanceof ScriptableObject) { ScriptableObject so = (ScriptableObject)scope; Object value = so.getAssociatedValue(key); if (value != null) { return value; } } scope = scope.getPrototype(); if (scope == null) { return null; } } } /** * Associate arbitrary application-specific value with this object. * Value can only be associated with the given object and key only once. * The method ignores any subsequent attempts to change the already * associated value. *

The associated values are not serialized. * @param key key object to select particular value. * @param value the value to associate * @return the passed value if the method is called first time for the * given key or old value for any subsequent calls. * @see #getAssociatedValue(Object key) */ public synchronized final Object associateValue(Object key, Object value) { if (value == null) throw new IllegalArgumentException(); Map h = associatedValues; if (h == null) { h = new HashMap(); associatedValues = h; } return Kit.initHash(h, key, value); } private Object getImpl(String name, int index, Scriptable start) { Slot slot = getSlot(name, index, SLOT_QUERY); if (slot == null) { return Scriptable.NOT_FOUND; } if (!(slot instanceof GetterSlot)) { return slot.value; } Object getterObj = ((GetterSlot)slot).getter; if (getterObj != null) { if (getterObj instanceof MemberBox) { MemberBox nativeGetter = (MemberBox)getterObj; Object getterThis; Object[] args; if (nativeGetter.delegateTo == null) { getterThis = start; args = ScriptRuntime.emptyArgs; } else { getterThis = nativeGetter.delegateTo; args = new Object[] { start }; } return nativeGetter.invoke(getterThis, args); } else { Function f = (Function)getterObj; Context cx = Context.getContext(); return f.call(cx, f.getParentScope(), start, ScriptRuntime.emptyArgs); } } Object value = slot.value; if (value instanceof LazilyLoadedCtor) { LazilyLoadedCtor initializer = (LazilyLoadedCtor)value; try { initializer.init(); } finally { value = initializer.getValue(); slot.value = value; } } return value; } /** * * @param name * @param index * @param start * @param value * @param constFlag EMPTY means normal put. UNINITIALIZED_CONST means * defineConstProperty. READONLY means const initialization expression. * @return false if this != start and no slot was found. true if this == start * or this != start and a READONLY slot was found. */ private boolean putImpl(String name, int index, Scriptable start, Object value, int constFlag) { Slot slot; if (this != start) { slot = getSlot(name, index, SLOT_QUERY); if (slot == null) { return false; } } else if (!isExtensible()) { slot = getSlot(name, index, SLOT_QUERY); if (slot == null) { return true; } } else { checkNotSealed(name, index); // either const hoisted declaration or initialization if (constFlag != EMPTY) { slot = getSlot(name, index, SLOT_MODIFY_CONST); int attr = slot.getAttributes(); if ((attr & READONLY) == 0) throw Context.reportRuntimeError1("msg.var.redecl", name); if ((attr & UNINITIALIZED_CONST) != 0) { slot.value = value; // clear the bit on const initialization if (constFlag != UNINITIALIZED_CONST) slot.setAttributes(attr & ~UNINITIALIZED_CONST); } return true; } slot = getSlot(name, index, SLOT_MODIFY); } if ((slot.getAttributes() & READONLY) != 0) return true; if (slot instanceof GetterSlot) { final GetterSlot getterSlot = (GetterSlot)slot; final Object setterObj = getterSlot.setter; if (setterObj == null) { if (getterSlot.getter != null) { if (Context.getContext().hasFeature(Context.FEATURE_STRICT_MODE)) { // Based on TC39 ES3.1 Draft of 9-Feb-2009, 8.12.4, step 2, // we should throw a TypeError in this case. throw ScriptRuntime.typeError1("msg.set.prop.no.setter", name); } if (Context.getContext().hasFeature(Context.FEATURE_HTMLUNIT_WRITE_READONLY_PROPERTIES)) { // Odd case: Assignment to a property with only a getter // defined. The assignment cancels out the getter. ((GetterSlot)slot).getter = null; } else { // Based on TC39 ES3.1 Draft of 9-Feb-2009, 8.12.4, step 2, // we should throw a TypeError in this case. throw ScriptRuntime.typeError1("msg.set.prop.no.setter", name); } } } else { Context cx = Context.getContext(); if (setterObj instanceof MemberBox) { MemberBox nativeSetter = (MemberBox)setterObj; Class pTypes[] = nativeSetter.argTypes; // XXX: cache tag since it is already calculated in // defineProperty ? Class valueType = pTypes[pTypes.length - 1]; int tag = FunctionObject.getTypeTag(valueType); Object actualArg = FunctionObject.convertArg(cx, start, value, tag); Object setterThis; Object[] args; if (nativeSetter.delegateTo == null) { setterThis = start; args = new Object[] { actualArg }; } else { setterThis = nativeSetter.delegateTo; args = new Object[] { start, actualArg }; } nativeSetter.invoke(setterThis, args); } else { Function f = (Function)setterObj; f.call(cx, f.getParentScope(), start, new Object[] { value }); } return true; } } else if ((slot.getAttributes() & READONLY) != 0) { return true; } if (this == start) { slot.value = value; return true; } else { return false; } } private Slot findAttributeSlot(String name, int index, int accessType) { Slot slot = getSlot(name, index, accessType); if (slot == null) { String str = (name != null ? name : Integer.toString(index)); throw Context.reportRuntimeError1("msg.prop.not.found", str); } return slot; } /** * Locate the slot with given name or index. * * @param name property name or null if slot holds spare array index. * @param index index or 0 if slot holds property name. */ private Slot getSlot(String name, int index, int accessType) { Slot slot; // Query last access cache and check that it was not deleted. lastAccessCheck: { slot = lastAccess; if (name != null) { if (name != slot.name) break lastAccessCheck; // No String.equals here as successful slot search update // name object with fresh reference of the same string. } else { if (slot.name != null || index != slot.indexOrHash) break lastAccessCheck; } if (slot.wasDeleted) break lastAccessCheck; if (accessType == SLOT_MODIFY_GETTER_SETTER && !(slot instanceof GetterSlot)) break lastAccessCheck; if (accessType == SLOT_CONVERT_ACCESSOR_TO_DATA && (slot instanceof GetterSlot)) break lastAccessCheck; return slot; } slot = accessSlot(name, index, accessType); if (slot != null) { // Update the cache lastAccess = slot; } return slot; } private Slot accessSlot(String name, int index, int accessType) { int indexOrHash = (name != null ? name.hashCode() : index); if (accessType == SLOT_QUERY || accessType == SLOT_MODIFY || accessType == SLOT_MODIFY_CONST || accessType == SLOT_MODIFY_GETTER_SETTER || accessType == SLOT_CONVERT_ACCESSOR_TO_DATA) { // Check the hashtable without using synchronization Slot[] slotsLocalRef = slots; // Get stable local reference if (slotsLocalRef == null) { if (accessType == SLOT_QUERY) return null; } else { int tableSize = slotsLocalRef.length; int slotIndex = getSlotIndex(tableSize, indexOrHash); Slot slot = slotsLocalRef[slotIndex]; while (slot != null) { String sname = slot.name; if (sname != null) { if (sname == name) break; if (name != null && indexOrHash == slot.indexOrHash) { if (name.equals(sname)) { // This will avoid calling String.equals when // slot is accessed with same string object // next time. slot.name = name; break; } } } else if (name == null && indexOrHash == slot.indexOrHash) { break; } slot = slot.next; } if (accessType == SLOT_QUERY) { return slot; } else if (accessType == SLOT_MODIFY) { if (slot != null) return slot; } else if (accessType == SLOT_MODIFY_GETTER_SETTER) { if (slot instanceof GetterSlot) return slot; } else if (accessType == SLOT_MODIFY_CONST) { if (slot != null) return slot; } else if (accessType == SLOT_CONVERT_ACCESSOR_TO_DATA) { if ( !(slot instanceof GetterSlot) ) return slot; } } // A new slot has to be inserted or the old has to be replaced // by GetterSlot. Time to synchronize. synchronized (this) { // Refresh local ref if another thread triggered grow slotsLocalRef = slots; int insertPos; if (count == 0) { // Always throw away old slots if any on empty insert slotsLocalRef = new Slot[5]; slots = slotsLocalRef; insertPos = getSlotIndex(slotsLocalRef.length, indexOrHash); } else { int tableSize = slotsLocalRef.length; insertPos = getSlotIndex(tableSize, indexOrHash); Slot prev = slotsLocalRef[insertPos]; Slot slot = prev; while (slot != null) { if (slot.indexOrHash == indexOrHash && (slot.name == name || (name != null && name.equals(slot.name)))) { break; } prev = slot; slot = slot.next; } if (slot != null) { // Another thread just added a slot with same // name/index before this one entered synchronized // block. This is a race in application code and // probably indicates bug there. But for the hashtable // implementation it is harmless with the only // complication is the need to replace the added slot // if we need GetterSlot and the old one is not. Slot newSlot; if (accessType == SLOT_MODIFY_GETTER_SETTER && !(slot instanceof GetterSlot)) { newSlot = new GetterSlot(name, indexOrHash, slot.getAttributes()); } else if (accessType == SLOT_CONVERT_ACCESSOR_TO_DATA && (slot instanceof GetterSlot)) { newSlot = new Slot(name, indexOrHash, slot.getAttributes()); } else if (accessType == SLOT_MODIFY_CONST) { return null; } else { return slot; } newSlot.value = slot.value; newSlot.next = slot.next; // add new slot to linked list if (lastAdded != null) lastAdded.orderedNext = newSlot; if (firstAdded == null) firstAdded = newSlot; lastAdded = newSlot; // add new slot to hash table if (prev == slot) { slotsLocalRef[insertPos] = newSlot; } else { prev.next = newSlot; } // other housekeeping slot.wasDeleted = true; slot.value = null; slot.name = null; if (slot == lastAccess) { lastAccess = REMOVED; } return newSlot; } else { // Check if the table is not too full before inserting. if (4 * (count + 1) > 3 * slotsLocalRef.length) { slotsLocalRef = new Slot[slotsLocalRef.length * 2 + 1]; copyTable(slots, slotsLocalRef, count); slots = slotsLocalRef; insertPos = getSlotIndex(slotsLocalRef.length, indexOrHash); } } } Slot newSlot = (accessType == SLOT_MODIFY_GETTER_SETTER ? new GetterSlot(name, indexOrHash, 0) : new Slot(name, indexOrHash, 0)); if (accessType == SLOT_MODIFY_CONST) newSlot.setAttributes(CONST); ++count; // add new slot to linked list if (lastAdded != null) lastAdded.orderedNext = newSlot; if (firstAdded == null) firstAdded = newSlot; lastAdded = newSlot; // add new slot to hash table, return it addKnownAbsentSlot(slotsLocalRef, newSlot, insertPos); return newSlot; } } else if (accessType == SLOT_REMOVE) { synchronized (this) { Slot[] slotsLocalRef = slots; if (count != 0) { int tableSize = slots.length; int slotIndex = getSlotIndex(tableSize, indexOrHash); Slot prev = slotsLocalRef[slotIndex]; Slot slot = prev; while (slot != null) { if (slot.indexOrHash == indexOrHash && (slot.name == name || (name != null && name.equals(slot.name)))) { break; } prev = slot; slot = slot.next; } if (slot != null && (slot.getAttributes() & PERMANENT) == 0) { count--; // remove slot from hash table if (prev == slot) { slotsLocalRef[slotIndex] = slot.next; } else { prev.next = slot.next; } // Mark the slot as removed. It is still referenced // from the order-added linked list, but will be // cleaned up later slot.wasDeleted = true; slot.value = null; slot.name = null; if (slot == lastAccess) { lastAccess = REMOVED; } } } } return null; } else { throw Kit.codeBug(); } } private static int getSlotIndex(int tableSize, int indexOrHash) { return (indexOrHash & 0x7fffffff) % tableSize; } // Must be inside synchronized (this) private static void copyTable(Slot[] slots, Slot[] newSlots, int count) { if (count == 0) throw Kit.codeBug(); int tableSize = newSlots.length; int i = slots.length; for (;;) { --i; Slot slot = slots[i]; while (slot != null) { int insertPos = getSlotIndex(tableSize, slot.indexOrHash); Slot next = slot.next; addKnownAbsentSlot(newSlots, slot, insertPos); slot.next = null; slot = next; if (--count == 0) return; } } } /** * Add slot with keys that are known to absent from the table. * This is an optimization to use when inserting into empty table, * after table growth or during deserialization. */ private static void addKnownAbsentSlot(Slot[] slots, Slot slot, int insertPos) { if (slots[insertPos] == null) { slots[insertPos] = slot; } else { Slot prev = slots[insertPos]; while (prev.next != null) { prev = prev.next; } prev.next = slot; } } Object[] getIds(boolean getAll) { Slot[] s = slots; Object[] a = ScriptRuntime.emptyArgs; if (s == null) return a; int c = 0; Slot slot = firstAdded; while (slot != null && slot.wasDeleted) { // as long as we're traversing the order-added linked list, // remove deleted slots slot = slot.orderedNext; } firstAdded = slot; if (slot != null) { for (;;) { if (getAll || (slot.getAttributes() & DONTENUM) == 0) { if (c == 0) a = new Object[s.length]; a[c++] = slot.name != null ? (Object) slot.name : Integer.valueOf(slot.indexOrHash); } Slot next = slot.orderedNext; while (next != null && next.wasDeleted) { // remove deleted slots next = next.orderedNext; } slot.orderedNext = next; if (next == null) { break; } slot = next; } } lastAdded = slot; if (c == a.length) return a; Object[] result = new Object[c]; System.arraycopy(a, 0, result, 0, c); return result; } private synchronized void writeObject(ObjectOutputStream out) throws IOException { out.defaultWriteObject(); int objectsCount = count; if (objectsCount < 0) { // "this" was sealed objectsCount = ~objectsCount; } if (objectsCount == 0) { out.writeInt(0); } else { out.writeInt(slots.length); Slot slot = firstAdded; while (slot != null && slot.wasDeleted) { // as long as we're traversing the order-added linked list, // remove deleted slots slot = slot.orderedNext; } firstAdded = slot; while (slot != null) { out.writeObject(slot); Slot next = slot.orderedNext; while (next != null && next.wasDeleted) { // remove deleted slots next = next.orderedNext; } slot.orderedNext = next; slot = next; } } } private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { in.defaultReadObject(); lastAccess = REMOVED; int tableSize = in.readInt(); if (tableSize != 0) { slots = new Slot[tableSize]; int objectsCount = count; if (objectsCount < 0) { // "this" was sealed objectsCount = ~objectsCount; } Slot prev = null; for (int i=0; i != objectsCount; ++i) { lastAdded = (Slot)in.readObject(); if (i==0) { firstAdded = lastAdded; } else { prev.orderedNext = lastAdded; } int slotIndex = getSlotIndex(tableSize, lastAdded.indexOrHash); addKnownAbsentSlot(slots, lastAdded, slotIndex); prev = lastAdded; } } } protected ScriptableObject getOwnPropertyDescriptor(Context cx, Object id) { Slot slot = getSlot(cx, id, SLOT_QUERY); if (slot == null) return null; Scriptable scope = getParentScope(); return slot.getPropertyDescriptor(cx, (scope == null ? this : scope)); } protected Slot getSlot(Context cx, Object id, int accessType) { final Slot slot; String name = ScriptRuntime.toStringIdOrIndex(cx, id); if (name == null) { int index = ScriptRuntime.lastIndexResult(cx); slot = getSlot(null, index, accessType); } else { slot = getSlot(name, 0, accessType); } return slot; } // Methods and classes to implement java.util.Map interface public int size() { return count; } public boolean isEmpty() { return count == 0; } public boolean containsKey(Object key) { if (key instanceof String) { return has((String) key, this); } else if (key instanceof Number) { return has(((Number) key).intValue(), this); } return false; } public boolean containsValue(Object value) { for (Object obj : values()) { if (value == obj || value != null && value.equals(obj)) { return true; } } return false; } public Object get(Object key) { Object value = null; if (key instanceof String) { value = get((String) key, this); } else if (key instanceof Number) { value = get(((Number) key).intValue(), this); } if (value == Scriptable.NOT_FOUND || value == Undefined.instance) { return null; } else if (value instanceof Wrapper) { return ((Wrapper) value).unwrap(); } else { return value; } } public Object remove(Object key) { Object value = get(key); if (key instanceof String) { delete((String) key); } else if (key instanceof Number) { delete(((Number) key).intValue()); } return value; } public Set keySet() { return new KeySet(); } public Collection values() { return new ValueCollection(); } public Set> entrySet() { return new EntrySet(); } public Object put(Object key, Object value) { throw new UnsupportedOperationException(); } public void putAll(Map m) { throw new UnsupportedOperationException(); } public void clear() { throw new UnsupportedOperationException(); } class EntrySet extends AbstractSet> { @Override public Iterator> iterator() { return new Iterator>() { Object[] ids = getIds(); Object key = null; int index = 0; public boolean hasNext() { return index < ids.length; } public Map.Entry next() { final Object ekey = key = ids[index++]; final Object value = get(key); return new Map.Entry() { public Object getKey() { return ekey; } public Object getValue() { return value; } public Object setValue(Object value) { throw new UnsupportedOperationException(); } public boolean equals(Object other) { if (!(other instanceof Map.Entry)) { return false; } Map.Entry e = (Map.Entry) other; return (ekey == null ? e.getKey() == null : ekey.equals(e.getKey())) && (value == null ? e.getValue() == null : value.equals(e.getValue())); } public int hashCode() { return (ekey == null ? 0 : ekey.hashCode()) ^ (value == null ? 0 : value.hashCode()); } public String toString() { return ekey + "=" + value; } }; } public void remove() { if (key == null) { throw new IllegalStateException(); } ScriptableObject.this.remove(key); key = null; } }; } @Override public int size() { return count; } } class KeySet extends AbstractSet { @Override public boolean contains(Object key) { return containsKey(key); } @Override public Iterator iterator() { return new Iterator() { Object[] ids = getIds(); Object key; int index = 0; public boolean hasNext() { return index < ids.length; } public Object next() { return (key = ids[index++]); } public void remove() { if (key == null) { throw new IllegalStateException(); } ScriptableObject.this.remove(key); key = null; } }; } @Override public int size() { return count; } } class ValueCollection extends AbstractCollection { @Override public Iterator iterator() { return new Iterator() { Object[] ids = getIds(); Object key; int index = 0; public boolean hasNext() { return index < ids.length; } public Object next() { return get((key = ids[index++])); } public void remove() { if (key == null) { throw new IllegalStateException(); } ScriptableObject.this.remove(key); key = null; } }; } @Override public int size() { return count; } } } htmlunit-core-js-2.8/rhino/src/org/mozilla/javascript/InterpretedFunction.java0000644000175000017500000001676711311524415027575 0ustar cavedoncavedon/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- * * ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is Rhino code, released * May 6, 1999. * * The Initial Developer of the Original Code is * Netscape Communications Corporation. * Portions created by the Initial Developer are Copyright (C) 1997-2000 * the Initial Developer. All Rights Reserved. * * Contributor(s): * Igor Bukanov * Bob Jervis * Roger Lawrence * * Alternatively, the contents of this file may be used under the terms of * the GNU General Public License Version 2 or later (the "GPL"), in which * case the provisions of the GPL are applicable instead of those above. If * you wish to allow use of your version of this file only under the terms of * the GPL and not to allow others to use your version of this file under the * MPL, indicate your decision by deleting the provisions above and replacing * them with the notice and other provisions required by the GPL. If you do * not delete the provisions above, a recipient may use your version of this * file under either the MPL or the GPL. * * ***** END LICENSE BLOCK ***** */ package org.mozilla.javascript; import org.mozilla.javascript.debug.DebuggableScript; final class InterpretedFunction extends NativeFunction implements Script { static final long serialVersionUID = 541475680333911468L; InterpreterData idata; SecurityController securityController; Object securityDomain; Scriptable[] functionRegExps; private InterpretedFunction(InterpreterData idata, Object staticSecurityDomain) { this.idata = idata; // Always get Context from the current thread to // avoid security breaches via passing mangled Context instances // with bogus SecurityController Context cx = Context.getContext(); SecurityController sc = cx.getSecurityController(); Object dynamicDomain; if (sc != null) { dynamicDomain = sc.getDynamicSecurityDomain(staticSecurityDomain); } else { if (staticSecurityDomain != null) { throw new IllegalArgumentException(); } dynamicDomain = null; } this.securityController = sc; this.securityDomain = dynamicDomain; } private InterpretedFunction(InterpretedFunction parent, int index) { this.idata = parent.idata.itsNestedFunctions[index]; this.securityController = parent.securityController; this.securityDomain = parent.securityDomain; } /** * Create script from compiled bytecode. */ static InterpretedFunction createScript(InterpreterData idata, Object staticSecurityDomain) { InterpretedFunction f; f = new InterpretedFunction(idata, staticSecurityDomain); return f; } /** * Create function compiled from Function(...) constructor. */ static InterpretedFunction createFunction(Context cx,Scriptable scope, InterpreterData idata, Object staticSecurityDomain) { InterpretedFunction f; f = new InterpretedFunction(idata, staticSecurityDomain); f.initInterpretedFunction(cx, scope); return f; } /** * Create function embedded in script or another function. */ static InterpretedFunction createFunction(Context cx, Scriptable scope, InterpretedFunction parent, int index) { InterpretedFunction f = new InterpretedFunction(parent, index); f.initInterpretedFunction(cx, scope); return f; } Scriptable[] createRegExpWraps(Context cx, Scriptable scope) { if (idata.itsRegExpLiterals == null) Kit.codeBug(); RegExpProxy rep = ScriptRuntime.checkRegExpProxy(cx); int N = idata.itsRegExpLiterals.length; Scriptable[] array = new Scriptable[N]; for (int i = 0; i != N; ++i) { array[i] = rep.wrapRegExp(cx, scope, idata.itsRegExpLiterals[i]); } return array; } private void initInterpretedFunction(Context cx, Scriptable scope) { initScriptFunction(cx, scope); if (idata.itsRegExpLiterals != null) { functionRegExps = createRegExpWraps(cx, scope); } } @Override public String getFunctionName() { return (idata.itsName == null) ? "" : idata.itsName; } /** * Calls the function. * @param cx the current context * @param scope the scope used for the call * @param thisObj the value of "this" * @param args function arguments. Must not be null. You can use * {@link ScriptRuntime#emptyArgs} to pass empty arguments. * @return the result of the function call. */ @Override public Object call(Context cx, Scriptable scope, Scriptable thisObj, Object[] args) { if (!ScriptRuntime.hasTopCall(cx)) { return ScriptRuntime.doTopCall(this, cx, scope, thisObj, args); } return Interpreter.interpret(this, cx, scope, thisObj, args); } public Object exec(Context cx, Scriptable scope) { if (!isScript()) { // Can only be applied to scripts throw new IllegalStateException(); } if (!ScriptRuntime.hasTopCall(cx)) { // It will go through "call" path. but they are equivalent return ScriptRuntime.doTopCall( this, cx, scope, scope, ScriptRuntime.emptyArgs); } return Interpreter.interpret( this, cx, scope, scope, ScriptRuntime.emptyArgs); } public boolean isScript() { return idata.itsFunctionType == 0; } @Override public String getEncodedSource() { return Interpreter.getEncodedSource(idata); } @Override public DebuggableScript getDebuggableView() { return idata; } @Override public Object resumeGenerator(Context cx, Scriptable scope, int operation, Object state, Object value) { return Interpreter.resumeGenerator(cx, scope, operation, state, value); } @Override protected int getLanguageVersion() { return idata.languageVersion; } @Override protected int getParamCount() { return idata.argCount; } @Override protected int getParamAndVarCount() { return idata.argNames.length; } @Override protected String getParamOrVarName(int index) { return idata.argNames[index]; } @Override protected boolean getParamOrVarConst(int index) { return idata.argIsConst[index]; } /** * Provides the decompiled source of the function what is helpful * while debugging. */ @Override public String toString() { return decompile(2, 0); } } htmlunit-core-js-2.8/rhino/src/org/mozilla/javascript/Wrapper.java0000644000175000017500000000400010776622373025213 0ustar cavedoncavedon/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- * * ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is Rhino code, released * May 6, 1999. * * The Initial Developer of the Original Code is * Netscape Communications Corporation. * Portions created by the Initial Developer are Copyright (C) 1997-2000 * the Initial Developer. All Rights Reserved. * * Contributor(s): * Norris Boyd * * Alternatively, the contents of this file may be used under the terms of * the GNU General Public License Version 2 or later (the "GPL"), in which * case the provisions of the GPL are applicable instead of those above. If * you wish to allow use of your version of this file only under the terms of * the GPL and not to allow others to use your version of this file under the * MPL, indicate your decision by deleting the provisions above and replacing * them with the notice and other provisions required by the GPL. If you do * not delete the provisions above, a recipient may use your version of this * file under either the MPL or the GPL. * * ***** END LICENSE BLOCK ***** */ // API class package org.mozilla.javascript; /** * Objects that can wrap other values for reflection in the JS environment * will implement Wrapper. * * Wrapper defines a single method that can be called to unwrap the object. */ public interface Wrapper { /** * Unwrap the object by returning the wrapped value. * * @return a wrapped value */ public Object unwrap(); } htmlunit-core-js-2.8/rhino/src/org/mozilla/javascript/JavaScriptException.java0000644000175000017500000000710611222455466027524 0ustar cavedoncavedon/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- * * ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is Rhino code, released * May 6, 1999. * * The Initial Developer of the Original Code is * Netscape Communications Corporation. * Portions created by the Initial Developer are Copyright (C) 1997-1999 * the Initial Developer. All Rights Reserved. * * Contributor(s): * Norris Boyd * Bojan Cekrlic * Hannes Wallnoefer * * Alternatively, the contents of this file may be used under the terms of * the GNU General Public License Version 2 or later (the "GPL"), in which * case the provisions of the GPL are applicable instead of those above. If * you wish to allow use of your version of this file only under the terms of * the GPL and not to allow others to use your version of this file under the * MPL, indicate your decision by deleting the provisions above and replacing * them with the notice and other provisions required by the GPL. If you do * not delete the provisions above, a recipient may use your version of this * file under either the MPL or the GPL. * * ***** END LICENSE BLOCK ***** */ // API class package org.mozilla.javascript; /** * Java reflection of JavaScript exceptions. * Instances of this class are thrown by the JavaScript 'throw' keyword. * * @author Mike McCabe */ public class JavaScriptException extends RhinoException { static final long serialVersionUID = -7666130513694669293L; /** * @deprecated * Use {@link WrappedException#WrappedException(Throwable)} to report * exceptions in Java code. */ public JavaScriptException(Object value) { this(value, "", 0); } /** * Create a JavaScript exception wrapping the given JavaScript value * * @param value the JavaScript value thrown. */ public JavaScriptException(Object value, String sourceName, int lineNumber) { recordErrorOrigin(sourceName, lineNumber, null, 0); this.value = value; } @Override public String details() { if (value == null) { return "null"; } else if (value instanceof NativeError) { return value.toString(); } try { return ScriptRuntime.toString(value); } catch (RuntimeException rte) { // ScriptRuntime.toString may throw a RuntimeException if (value instanceof Scriptable) { return ScriptRuntime.defaultObjectToString((Scriptable)value); } else { return value.toString(); } } } /** * @return the value wrapped by this exception */ public Object getValue() { return value; } /** * @deprecated Use {@link RhinoException#sourceName()} from the super class. */ public String getSourceName() { return sourceName(); } /** * @deprecated Use {@link RhinoException#lineNumber()} from the super class. */ public int getLineNumber() { return lineNumber(); } private Object value; } htmlunit-core-js-2.8/rhino/src/org/mozilla/javascript/NativeError.java0000644000175000017500000002077611343213760026040 0ustar cavedoncavedon/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- * * ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is Rhino code, released * May 6, 1999. * * The Initial Developer of the Original Code is * Netscape Communications Corporation. * Portions created by the Initial Developer are Copyright (C) 1997-1999 * the Initial Developer. All Rights Reserved. * * Contributor(s): * Igor Bukanov * Roger Lawrence * * Alternatively, the contents of this file may be used under the terms of * the GNU General Public License Version 2 or later (the "GPL"), in which * case the provisions of the GPL are applicable instead of those above. If * you wish to allow use of your version of this file only under the terms of * the GPL and not to allow others to use your version of this file under the * MPL, indicate your decision by deleting the provisions above and replacing * them with the notice and other provisions required by the GPL. If you do * not delete the provisions above, a recipient may use your version of this * file under either the MPL or the GPL. * * ***** END LICENSE BLOCK ***** */ package org.mozilla.javascript; /** * * The class of error objects * * ECMA 15.11 */ final class NativeError extends IdScriptableObject { static final long serialVersionUID = -5338413581437645187L; private static final Object ERROR_TAG = "Error"; static void init(Scriptable scope, boolean sealed) { NativeError obj = new NativeError(); ScriptableObject.putProperty(obj, "name", "Error"); ScriptableObject.putProperty(obj, "message", ""); ScriptableObject.putProperty(obj, "fileName", ""); ScriptableObject.putProperty(obj, "lineNumber", Integer.valueOf(0)); obj.exportAsJSClass(MAX_PROTOTYPE_ID, scope, sealed); } static NativeError make(Context cx, Scriptable scope, IdFunctionObject ctorObj, Object[] args) { Scriptable proto = (Scriptable)(ctorObj.get("prototype", ctorObj)); NativeError obj = new NativeError(); obj.setPrototype(proto); obj.setParentScope(scope); int arglen = args.length; if (arglen >= 1) { ScriptableObject.putProperty(obj, "message", ScriptRuntime.toString(args[0])); if (arglen >= 2) { ScriptableObject.putProperty(obj, "fileName", args[1]); if (arglen >= 3) { int line = ScriptRuntime.toInt32(args[2]); ScriptableObject.putProperty(obj, "lineNumber", Integer.valueOf(line)); if (arglen >= 4) { ScriptableObject.putProperty(obj, "stack", args[3]); } } } } if(arglen < 3 && cx.hasFeature(Context.FEATURE_LOCATION_INFORMATION_IN_ERROR)) { // Fill in fileName and lineNumber automatically when not specified // explicitly, see Bugzilla issue #342807 int[] linep = new int[1]; String fileName = Context.getSourcePositionFromStack(linep); ScriptableObject.putProperty(obj, "lineNumber", Integer.valueOf(linep[0])); if(arglen < 2) { ScriptableObject.putProperty(obj, "fileName", fileName); } } return obj; } @Override public String getClassName() { return "Error"; } @Override public String toString() { // According to spec, Error.prototype.toString() may return undefined. Object toString = js_toString(this); return toString instanceof String ? (String) toString : super.toString(); } @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=0; s="toSource"; break; default: throw new IllegalArgumentException(String.valueOf(id)); } initPrototypeMethod(ERROR_TAG, id, s, arity); } @Override public Object execIdCall(IdFunctionObject f, Context cx, Scriptable scope, Scriptable thisObj, Object[] args) { if (!f.hasTag(ERROR_TAG)) { return super.execIdCall(f, cx, scope, thisObj, args); } int id = f.methodId(); switch (id) { case Id_constructor: return make(cx, scope, f, args); case Id_toString: return js_toString(thisObj); case Id_toSource: return js_toSource(cx, scope, thisObj); } throw new IllegalArgumentException(String.valueOf(id)); } private static Object js_toString(Scriptable thisObj) { Object name = ScriptableObject.getProperty(thisObj, "name"); if (name == NOT_FOUND || name == Undefined.instance) { name = "Error"; } else { name = ScriptRuntime.toString(name); } Object msg = ScriptableObject.getProperty(thisObj, "message"); final Object result; if (msg == NOT_FOUND || msg == Undefined.instance) { result = Undefined.instance; } else { result = ((String) name) + ": " + ScriptRuntime.toString(msg); } return result; } private static String js_toSource(Context cx, Scriptable scope, Scriptable thisObj) { // Emulation of SpiderMonkey behavior Object name = ScriptableObject.getProperty(thisObj, "name"); Object message = ScriptableObject.getProperty(thisObj, "message"); Object fileName = ScriptableObject.getProperty(thisObj, "fileName"); Object lineNumber = ScriptableObject.getProperty(thisObj, "lineNumber"); StringBuffer sb = new StringBuffer(); sb.append("(new "); if (name == NOT_FOUND) { name = Undefined.instance; } sb.append(ScriptRuntime.toString(name)); sb.append("("); if (message != NOT_FOUND || fileName != NOT_FOUND || lineNumber != NOT_FOUND) { if (message == NOT_FOUND) { message = ""; } sb.append(ScriptRuntime.uneval(cx, scope, message)); if (fileName != NOT_FOUND || lineNumber != NOT_FOUND) { sb.append(", "); if (fileName == NOT_FOUND) { fileName = ""; } sb.append(ScriptRuntime.uneval(cx, scope, fileName)); if (lineNumber != NOT_FOUND) { int line = ScriptRuntime.toInt32(lineNumber); if (line != 0) { sb.append(", "); sb.append(ScriptRuntime.toString(line)); } } } } sb.append("))"); return sb.toString(); } private static String getString(Scriptable obj, String id) { Object value = ScriptableObject.getProperty(obj, id); if (value == NOT_FOUND) return ""; return ScriptRuntime.toString(value); } @Override protected int findPrototypeId(String s) { int id; // #string_id_map# // #generated# Last update: 2007-05-09 08:15:45 EDT L0: { id = 0; String X = null; int c; int s_length = s.length(); if (s_length==8) { c=s.charAt(3); if (c=='o') { X="toSource";id=Id_toSource; } else if (c=='t') { X="toString";id=Id_toString; } } else if (s_length==11) { X="constructor";id=Id_constructor; } 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, MAX_PROTOTYPE_ID = 3; // #/string_id_map# } htmlunit-core-js-2.8/rhino/src/org/mozilla/javascript/ClassCache.java0000644000175000017500000001672011222455466025572 0ustar cavedoncavedon/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- * * ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is Rhino code, released * May 6, 1999. * * The Initial Developer of the Original Code is * Netscape Communications Corporation. * Portions created by the Initial Developer are Copyright (C) 1997-1999 * the Initial Developer. All Rights Reserved. * * Contributor(s): * Igor Bukanov, igor@fastmail.fm * Norris Boyd * * Alternatively, the contents of this file may be used under the terms of * the GNU General Public License Version 2 or later (the "GPL"), in which * case the provisions of the GPL are applicable instead of those above. If * you wish to allow use of your version of this file only under the terms of * the GPL and not to allow others to use your version of this file under the * MPL, indicate your decision by deleting the provisions above and replacing * them with the notice and other provisions required by the GPL. If you do * not delete the provisions above, a recipient may use your version of this * file under either the MPL or the GPL. * * ***** END LICENSE BLOCK ***** */ package org.mozilla.javascript; import java.util.Map; import java.util.HashMap; 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 HashMap,JavaMembers> classTable; private transient HashMap> classAdapterCache; private transient HashMap,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. *

* By default, the engine will cache the results of * Class.getMethods() 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. *

* If caching is enabled and this method is called with a * false argument, the caches will be emptied. *

* 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,JavaMembers> getClassCacheMap() { if (classTable == null) { classTable = new HashMap,JavaMembers>(); } return classTable; } Map> getInterfaceAdapterCacheMap() { if (classAdapterCache == null) { classAdapterCache = new HashMap>(); } return classAdapterCache; } /** * @deprecated * The method always returns false. * @see #setInvokerOptimizationEnabled(boolean enabled) */ 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. */ 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 HashMap,Object>(); } interfaceAdapterCache.put(cl, iadapter); } } Scriptable getAssociatedScope() { return associatedScope; } } htmlunit-core-js-2.8/rhino/src/org/mozilla/javascript/ContinuationPending.java0000644000175000017500000000754011222455466027560 0ustar cavedoncavedon/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- * * ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is Rhino code, released * May 6, 1999. * * The Initial Developer of the Original Code is * Netscape Communications Corporation. * Portions created by the Initial Developer are Copyright (C) 1997-1999 * the Initial Developer. All Rights Reserved. * * Contributor(s): * Norris Boyd * * Alternatively, the contents of this file may be used under the terms of * the GNU General Public License Version 2 or later (the "GPL"), in which * case the provisions of the GPL are applicable instead of those above. If * you wish to allow use of your version of this file only under the terms of * the GPL and not to allow others to use your version of this file under the * MPL, indicate your decision by deleting the provisions above and replacing * them with the notice and other provisions required by the GPL. If you do * not delete the provisions above, a recipient may use your version of this * file under either the MPL or the GPL. * * ***** END LICENSE BLOCK ***** */ package org.mozilla.javascript; /** * 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[])} * @param continuationState Internal Continuation object */ 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; } /** * @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; } } htmlunit-core-js-2.8/rhino/src/org/mozilla/javascript/Interpreter.java0000644000175000017500000034151511321335670026101 0ustar cavedoncavedon/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- * * ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is Rhino code, released * May 6, 1999. * * The Initial Developer of the Original Code is * Netscape Communications Corporation. * Portions created by the Initial Developer are Copyright (C) 1997-2000 * the Initial Developer. All Rights Reserved. * * Contributor(s): * Patrick Beard * Norris Boyd * Igor Bukanov * Ethan Hugg * Bob Jervis * Terry Lucas * Roger Lawrence * Milen Nankov * Hannes Wallnoefer * * Alternatively, the contents of this file may be used under the terms of * the GNU General Public License Version 2 or later (the "GPL"), in which * case the provisions of the GPL are applicable instead of those above. If * you wish to allow use of your version of this file only under the terms of * the GPL and not to allow others to use your version of this file under the * MPL, indicate your decision by deleting the provisions above and replacing * them with the notice and other provisions required by the GPL. If you do * not delete the provisions above, a recipient may use your version of this * file under either the MPL or the GPL. * * ***** END LICENSE BLOCK ***** */ package org.mozilla.javascript; import java.io.PrintStream; import java.io.Serializable; import java.util.List; import java.util.ArrayList; import org.mozilla.javascript.ast.FunctionNode; import org.mozilla.javascript.ast.ScriptNode; import org.mozilla.javascript.ScriptRuntime.NoSuchMethodShim; import org.mozilla.javascript.debug.DebugFrame; public final class Interpreter extends Icode implements Evaluator { // data for parsing CompilerEnvirons compilerEnv; InterpreterData itsData; static final int EXCEPTION_TRY_START_SLOT = 0; static final int EXCEPTION_TRY_END_SLOT = 1; static final int EXCEPTION_HANDLER_SLOT = 2; static final int EXCEPTION_TYPE_SLOT = 3; static final int EXCEPTION_LOCAL_SLOT = 4; static final int EXCEPTION_SCOPE_SLOT = 5; // SLOT_SIZE: space for try start/end, handler, start, handler type, // exception local and scope local static final int EXCEPTION_SLOT_SIZE = 6; /** * Class to hold data corresponding to one interpreted call stack frame. */ private static class CallFrame implements Cloneable, Serializable { static final long serialVersionUID = -2843792508994958978L; CallFrame parentFrame; // amount of stack frames before this one on the interpretation stack int frameIndex; // If true indicates read-only frame that is a part of continuation boolean frozen; InterpretedFunction fnOrScript; InterpreterData idata; // Stack structure // stack[0 <= i < localShift]: arguments and local variables // stack[localShift <= i <= emptyStackTop]: used for local temporaries // stack[emptyStackTop < i < stack.length]: stack data // sDbl[i]: if stack[i] is UniqueTag.DOUBLE_MARK, sDbl[i] holds the number value Object[] stack; int[] stackAttributes; double[] sDbl; CallFrame varSource; // defaults to this unless continuation frame int localShift; int emptyStackTop; DebugFrame debuggerFrame; boolean useActivation; boolean isContinuationsTopFrame; Scriptable thisObj; Scriptable[] scriptRegExps; // The values that change during interpretation Object result; double resultDbl; int pc; int pcPrevBranch; int pcSourceLineStart; Scriptable scope; int savedStackTop; int savedCallOp; Object throwable; CallFrame cloneFrozen() { if (!frozen) Kit.codeBug(); CallFrame copy; try { copy = (CallFrame)clone(); } catch (CloneNotSupportedException ex) { throw new IllegalStateException(); } // clone stack but keep varSource to point to values // from this frame to share variables. copy.stack = stack.clone(); copy.stackAttributes = stackAttributes.clone(); copy.sDbl = sDbl.clone(); copy.frozen = false; return copy; } } private static final class ContinuationJump implements Serializable { static final long serialVersionUID = 7687739156004308247L; CallFrame capturedFrame; CallFrame branchFrame; Object result; double resultDbl; ContinuationJump(NativeContinuation c, CallFrame current) { this.capturedFrame = (CallFrame)c.getImplementation(); if (this.capturedFrame == null || current == null) { // Continuation and current execution does not share // any frames if there is nothing to capture or // if there is no currently executed frames this.branchFrame = null; } else { // Search for branch frame where parent frame chains starting // from captured and current meet. CallFrame chain1 = this.capturedFrame; CallFrame chain2 = current; // First work parents of chain1 or chain2 until the same // frame depth. int diff = chain1.frameIndex - chain2.frameIndex; if (diff != 0) { if (diff < 0) { // swap to make sure that // chain1.frameIndex > chain2.frameIndex and diff > 0 chain1 = current; chain2 = this.capturedFrame; diff = -diff; } do { chain1 = chain1.parentFrame; } while (--diff != 0); if (chain1.frameIndex != chain2.frameIndex) Kit.codeBug(); } // Now walk parents in parallel until a shared frame is found // or until the root is reached. while (chain1 != chain2 && chain1 != null) { chain1 = chain1.parentFrame; chain2 = chain2.parentFrame; } this.branchFrame = chain1; if (this.branchFrame != null && !this.branchFrame.frozen) Kit.codeBug(); } } } private static CallFrame captureFrameForGenerator(CallFrame frame) { frame.frozen = true; CallFrame result = frame.cloneFrozen(); frame.frozen = false; // now isolate this frame from its previous context result.parentFrame = null; result.frameIndex = 0; return result; } static { // Checks for byte code consistencies, good compiler can eliminate them if (Token.LAST_BYTECODE_TOKEN > 127) { String str = "Violation of Token.LAST_BYTECODE_TOKEN <= 127"; System.err.println(str); throw new IllegalStateException(str); } if (MIN_ICODE < -128) { String str = "Violation of Interpreter.MIN_ICODE >= -128"; System.err.println(str); throw new IllegalStateException(str); } } public Object compile(CompilerEnvirons compilerEnv, ScriptNode tree, String encodedSource, boolean returnFunction) { this.compilerEnv = compilerEnv; CodeGenerator cgen = new CodeGenerator(); itsData = cgen.compile(compilerEnv, tree, encodedSource, returnFunction); return itsData; } public Script createScriptObject(Object bytecode, Object staticSecurityDomain) { if(bytecode != itsData) { Kit.codeBug(); } return InterpretedFunction.createScript(itsData, staticSecurityDomain); } public void setEvalScriptFlag(Script script) { ((InterpretedFunction)script).idata.evalScriptFlag = true; } public Function createFunctionObject(Context cx, Scriptable scope, Object bytecode, Object staticSecurityDomain) { if(bytecode != itsData) { Kit.codeBug(); } return InterpretedFunction.createFunction(cx, scope, itsData, staticSecurityDomain); } private static int getShort(byte[] iCode, int pc) { return (iCode[pc] << 8) | (iCode[pc + 1] & 0xFF); } private static int getIndex(byte[] iCode, int pc) { return ((iCode[pc] & 0xFF) << 8) | (iCode[pc + 1] & 0xFF); } private static int getInt(byte[] iCode, int pc) { return (iCode[pc] << 24) | ((iCode[pc + 1] & 0xFF) << 16) | ((iCode[pc + 2] & 0xFF) << 8) | (iCode[pc + 3] & 0xFF); } private static int getExceptionHandler(CallFrame frame, boolean onlyFinally) { int[] exceptionTable = frame.idata.itsExceptionTable; if (exceptionTable == null) { // No exception handlers return -1; } // Icode switch in the interpreter increments PC immediately // and it is necessary to subtract 1 from the saved PC // to point it before the start of the next instruction. int pc = frame.pc - 1; // OPT: use binary search int best = -1, bestStart = 0, bestEnd = 0; for (int i = 0; i != exceptionTable.length; i += EXCEPTION_SLOT_SIZE) { int start = exceptionTable[i + EXCEPTION_TRY_START_SLOT]; int end = exceptionTable[i + EXCEPTION_TRY_END_SLOT]; if (!(start <= pc && pc < end)) { continue; } if (onlyFinally && exceptionTable[i + EXCEPTION_TYPE_SLOT] != 1) { continue; } if (best >= 0) { // Since handlers always nest and they never have shared end // although they can share start it is sufficient to compare // handlers ends if (bestEnd < end) { continue; } // Check the above assumption if (bestStart > start) Kit.codeBug(); // should be nested if (bestEnd == end) Kit.codeBug(); // no ens sharing } best = i; bestStart = start; bestEnd = end; } return best; } static void dumpICode(InterpreterData idata) { if (!Token.printICode) { return; } byte iCode[] = idata.itsICode; int iCodeLength = iCode.length; String[] strings = idata.itsStringTable; PrintStream out = System.out; out.println("ICode dump, for " + idata.itsName + ", length = " + iCodeLength); out.println("MaxStack = " + idata.itsMaxStack); int indexReg = 0; for (int pc = 0; pc < iCodeLength; ) { out.flush(); out.print(" [" + pc + "] "); int token = iCode[pc]; int icodeLength = bytecodeSpan(token); String tname = Icode.bytecodeName(token); int old_pc = pc; ++pc; switch (token) { default: if (icodeLength != 1) Kit.codeBug(); out.println(tname); break; case Icode_GOSUB : case Token.GOTO : case Token.IFEQ : case Token.IFNE : case Icode_IFEQ_POP : case Icode_LEAVEDQ : { int newPC = pc + getShort(iCode, pc) - 1; out.println(tname + " " + newPC); pc += 2; break; } case Icode_VAR_INC_DEC : case Icode_NAME_INC_DEC : case Icode_PROP_INC_DEC : case Icode_ELEM_INC_DEC : case Icode_REF_INC_DEC: { int incrDecrType = iCode[pc]; out.println(tname + " " + incrDecrType); ++pc; break; } case Icode_CALLSPECIAL : { int callType = iCode[pc] & 0xFF; boolean isNew = (iCode[pc + 1] != 0); int line = getIndex(iCode, pc+2); out.println(tname+" "+callType+" "+isNew+" "+indexReg+" "+line); pc += 4; break; } case Token.CATCH_SCOPE: { boolean afterFisrtFlag = (iCode[pc] != 0); out.println(tname+" "+afterFisrtFlag); ++pc; } break; case Token.REGEXP : out.println(tname+" "+idata.itsRegExpLiterals[indexReg]); break; case Token.OBJECTLIT : case Icode_SPARE_ARRAYLIT : out.println(tname+" "+idata.literalIds[indexReg]); break; case Icode_CLOSURE_EXPR : case Icode_CLOSURE_STMT : out.println(tname+" "+idata.itsNestedFunctions[indexReg]); break; case Token.CALL : case Icode_TAIL_CALL : case Token.REF_CALL : case Token.NEW : out.println(tname+' '+indexReg); break; case Token.THROW : case Token.YIELD : case Icode_GENERATOR : case Icode_GENERATOR_END : { int line = getIndex(iCode, pc); out.println(tname + " : " + line); pc += 2; break; } case Icode_SHORTNUMBER : { int value = getShort(iCode, pc); out.println(tname + " " + value); pc += 2; break; } case Icode_INTNUMBER : { int value = getInt(iCode, pc); out.println(tname + " " + value); pc += 4; break; } case Token.NUMBER : { double value = idata.itsDoubleTable[indexReg]; out.println(tname + " " + value); break; } case Icode_LINE : { int line = getIndex(iCode, pc); out.println(tname + " : " + line); pc += 2; break; } case Icode_REG_STR1: { String str = strings[0xFF & iCode[pc]]; out.println(tname + " \"" + str + '"'); ++pc; break; } case Icode_REG_STR2: { String str = strings[getIndex(iCode, pc)]; out.println(tname + " \"" + str + '"'); pc += 2; break; } case Icode_REG_STR4: { String str = strings[getInt(iCode, pc)]; out.println(tname + " \"" + str + '"'); pc += 4; break; } case Icode_REG_IND_C0: indexReg = 0; out.println(tname); break; case Icode_REG_IND_C1: indexReg = 1; out.println(tname); break; case Icode_REG_IND_C2: indexReg = 2; out.println(tname); break; case Icode_REG_IND_C3: indexReg = 3; out.println(tname); break; case Icode_REG_IND_C4: indexReg = 4; out.println(tname); break; case Icode_REG_IND_C5: indexReg = 5; out.println(tname); break; case Icode_REG_IND1: { indexReg = 0xFF & iCode[pc]; out.println(tname+" "+indexReg); ++pc; break; } case Icode_REG_IND2: { indexReg = getIndex(iCode, pc); out.println(tname+" "+indexReg); pc += 2; break; } case Icode_REG_IND4: { indexReg = getInt(iCode, pc); out.println(tname+" "+indexReg); pc += 4; break; } case Icode_GETVAR1: case Icode_SETVAR1: case Icode_SETCONSTVAR1: indexReg = iCode[pc]; out.println(tname+" "+indexReg); ++pc; break; } if (old_pc + icodeLength != pc) Kit.codeBug(); } int[] table = idata.itsExceptionTable; if (table != null) { out.println("Exception handlers: " +table.length / EXCEPTION_SLOT_SIZE); for (int i = 0; i != table.length; i += EXCEPTION_SLOT_SIZE) { int tryStart = table[i + EXCEPTION_TRY_START_SLOT]; int tryEnd = table[i + EXCEPTION_TRY_END_SLOT]; int handlerStart = table[i + EXCEPTION_HANDLER_SLOT]; int type = table[i + EXCEPTION_TYPE_SLOT]; int exceptionLocal = table[i + EXCEPTION_LOCAL_SLOT]; int scopeLocal = table[i + EXCEPTION_SCOPE_SLOT]; out.println(" tryStart="+tryStart+" tryEnd="+tryEnd +" handlerStart="+handlerStart +" type="+(type == 0 ? "catch" : "finally") +" exceptionLocal="+exceptionLocal); } } out.flush(); } private static int bytecodeSpan(int bytecode) { switch (bytecode) { case Token.THROW : case Token.YIELD: case Icode_GENERATOR: case Icode_GENERATOR_END: // source line return 1 + 2; case Icode_GOSUB : case Token.GOTO : case Token.IFEQ : case Token.IFNE : case Icode_IFEQ_POP : case Icode_LEAVEDQ : // target pc offset return 1 + 2; case Icode_CALLSPECIAL : // call type // is new // line number return 1 + 1 + 1 + 2; case Token.CATCH_SCOPE: // scope flag return 1 + 1; case Icode_VAR_INC_DEC: case Icode_NAME_INC_DEC: case Icode_PROP_INC_DEC: case Icode_ELEM_INC_DEC: case Icode_REF_INC_DEC: // type of ++/-- return 1 + 1; case Icode_SHORTNUMBER : // short number return 1 + 2; case Icode_INTNUMBER : // int number return 1 + 4; case Icode_REG_IND1: // ubyte index return 1 + 1; case Icode_REG_IND2: // ushort index return 1 + 2; case Icode_REG_IND4: // int index return 1 + 4; case Icode_REG_STR1: // ubyte string index return 1 + 1; case Icode_REG_STR2: // ushort string index return 1 + 2; case Icode_REG_STR4: // int string index return 1 + 4; case Icode_GETVAR1: case Icode_SETVAR1: case Icode_SETCONSTVAR1: // byte var index return 1 + 1; case Icode_LINE : // line number return 1 + 2; } if (!validBytecode(bytecode)) throw Kit.codeBug(); return 1; } static int[] getLineNumbers(InterpreterData data) { UintMap presentLines = new UintMap(); byte[] iCode = data.itsICode; int iCodeLength = iCode.length; for (int pc = 0; pc != iCodeLength;) { int bytecode = iCode[pc]; int span = bytecodeSpan(bytecode); if (bytecode == Icode_LINE) { if (span != 3) Kit.codeBug(); int line = getIndex(iCode, pc + 1); presentLines.put(line, 0); } pc += span; } return presentLines.getKeys(); } public void captureStackInfo(RhinoException ex) { Context cx = Context.getCurrentContext(); if (cx == null || cx.lastInterpreterFrame == null) { // No interpreter invocations ex.interpreterStackInfo = null; ex.interpreterLineData = null; return; } // has interpreter frame on the stack CallFrame[] array; if (cx.previousInterpreterInvocations == null || cx.previousInterpreterInvocations.size() == 0) { array = new CallFrame[1]; } else { int previousCount = cx.previousInterpreterInvocations.size(); if (cx.previousInterpreterInvocations.peek() == cx.lastInterpreterFrame) { // It can happen if exception was generated after // frame was pushed to cx.previousInterpreterInvocations // but before assignment to cx.lastInterpreterFrame. // In this case frames has to be ignored. --previousCount; } array = new CallFrame[previousCount + 1]; cx.previousInterpreterInvocations.toArray(array); } array[array.length - 1] = (CallFrame)cx.lastInterpreterFrame; int interpreterFrameCount = 0; for (int i = 0; i != array.length; ++i) { interpreterFrameCount += 1 + array[i].frameIndex; } int[] linePC = new int[interpreterFrameCount]; // Fill linePC with pc positions from all interpreter frames. // Start from the most nested frame int linePCIndex = interpreterFrameCount; for (int i = array.length; i != 0;) { --i; CallFrame frame = array[i]; while (frame != null) { --linePCIndex; linePC[linePCIndex] = frame.pcSourceLineStart; frame = frame.parentFrame; } } if (linePCIndex != 0) Kit.codeBug(); ex.interpreterStackInfo = array; ex.interpreterLineData = linePC; } public String getSourcePositionFromStack(Context cx, int[] linep) { CallFrame frame = (CallFrame)cx.lastInterpreterFrame; InterpreterData idata = frame.idata; if (frame.pcSourceLineStart >= 0) { linep[0] = getIndex(idata.itsICode, frame.pcSourceLineStart); } else { linep[0] = 0; } return idata.itsSourceFile; } public String getPatchedStack(RhinoException ex, String nativeStackTrace) { String tag = "org.mozilla.javascript.Interpreter.interpretLoop"; StringBuffer sb = new StringBuffer(nativeStackTrace.length() + 1000); String lineSeparator = SecurityUtilities.getSystemProperty("line.separator"); CallFrame[] array = (CallFrame[])ex.interpreterStackInfo; int[] linePC = ex.interpreterLineData; int arrayIndex = array.length; int linePCIndex = linePC.length; int offset = 0; while (arrayIndex != 0) { --arrayIndex; int pos = nativeStackTrace.indexOf(tag, offset); if (pos < 0) { break; } // Skip tag length pos += tag.length(); // Skip until the end of line for (; pos != nativeStackTrace.length(); ++pos) { char c = nativeStackTrace.charAt(pos); if (c == '\n' || c == '\r') { break; } } sb.append(nativeStackTrace.substring(offset, pos)); offset = pos; CallFrame frame = array[arrayIndex]; while (frame != null) { if (linePCIndex == 0) Kit.codeBug(); --linePCIndex; InterpreterData idata = frame.idata; sb.append(lineSeparator); sb.append("\tat script"); if (idata.itsName != null && idata.itsName.length() != 0) { sb.append('.'); sb.append(idata.itsName); } sb.append('('); sb.append(idata.itsSourceFile); int pc = linePC[linePCIndex]; if (pc >= 0) { // Include line info only if available sb.append(':'); sb.append(getIndex(idata.itsICode, pc)); } sb.append(')'); frame = frame.parentFrame; } } sb.append(nativeStackTrace.substring(offset)); return sb.toString(); } public List getScriptStack(RhinoException ex) { if (ex.interpreterStackInfo == null) { return null; } List list = new ArrayList(); String lineSeparator = SecurityUtilities.getSystemProperty("line.separator"); CallFrame[] array = (CallFrame[])ex.interpreterStackInfo; int[] linePC = ex.interpreterLineData; int arrayIndex = array.length; int linePCIndex = linePC.length; while (arrayIndex != 0) { --arrayIndex; StringBuilder sb = new StringBuilder(); CallFrame frame = array[arrayIndex]; while (frame != null) { if (linePCIndex == 0) Kit.codeBug(); --linePCIndex; InterpreterData idata = frame.idata; sb.append("\tat "); sb.append(idata.itsSourceFile); int pc = linePC[linePCIndex]; if (pc >= 0) { // Include line info only if available sb.append(':'); sb.append(getIndex(idata.itsICode, pc)); } if (idata.itsName != null && idata.itsName.length() != 0) { sb.append(" ("); sb.append(idata.itsName); sb.append(')'); } sb.append(lineSeparator); frame = frame.parentFrame; } list.add(sb.toString()); } return list; } static String getEncodedSource(InterpreterData idata) { if (idata.encodedSource == null) { return null; } return idata.encodedSource.substring(idata.encodedSourceStart, idata.encodedSourceEnd); } private static void initFunction(Context cx, Scriptable scope, InterpretedFunction parent, int index) { InterpretedFunction fn; fn = InterpretedFunction.createFunction(cx, scope, parent, index); ScriptRuntime.initFunction(cx, scope, fn, fn.idata.itsFunctionType, parent.idata.evalScriptFlag); } static Object interpret(InterpretedFunction ifun, Context cx, Scriptable scope, Scriptable thisObj, Object[] args) { if (!ScriptRuntime.hasTopCall(cx)) Kit.codeBug(); if (cx.interpreterSecurityDomain != ifun.securityDomain) { Object savedDomain = cx.interpreterSecurityDomain; cx.interpreterSecurityDomain = ifun.securityDomain; try { return ifun.securityController.callWithDomain( ifun.securityDomain, cx, ifun, scope, thisObj, args); } finally { cx.interpreterSecurityDomain = savedDomain; } } CallFrame frame = new CallFrame(); initFrame(cx, scope, thisObj, args, null, 0, args.length, ifun, null, frame); frame.isContinuationsTopFrame = cx.isContinuationsTopCall; cx.isContinuationsTopCall = false; return interpretLoop(cx, frame, null); } static class GeneratorState { GeneratorState(int operation, Object value) { this.operation = operation; this.value = value; } int operation; Object value; RuntimeException returnedException; } public static Object resumeGenerator(Context cx, Scriptable scope, int operation, Object savedState, Object value) { CallFrame frame = (CallFrame) savedState; GeneratorState generatorState = new GeneratorState(operation, value); if (operation == NativeGenerator.GENERATOR_CLOSE) { try { return interpretLoop(cx, frame, generatorState); } catch (RuntimeException e) { // Only propagate exceptions other than closingException if (e != value) throw e; } return Undefined.instance; } Object result = interpretLoop(cx, frame, generatorState); if (generatorState.returnedException != null) throw generatorState.returnedException; return result; } public static Object restartContinuation(NativeContinuation c, Context cx, Scriptable scope, Object[] args) { if (!ScriptRuntime.hasTopCall(cx)) { return ScriptRuntime.doTopCall(c, cx, scope, null, args); } Object arg; if (args.length == 0) { arg = Undefined.instance; } else { arg = args[0]; } CallFrame capturedFrame = (CallFrame)c.getImplementation(); if (capturedFrame == null) { // No frames to restart return arg; } ContinuationJump cjump = new ContinuationJump(c, null); cjump.result = arg; return interpretLoop(cx, null, cjump); } private static Object interpretLoop(Context cx, CallFrame frame, Object throwable) { // throwable holds exception object to rethrow or catch // It is also used for continuation restart in which case // it holds ContinuationJump final Object DBL_MRK = UniqueTag.DOUBLE_MARK; final Object undefined = Undefined.instance; final boolean instructionCounting = (cx.instructionThreshold != 0); // arbitrary number to add to instructionCount when calling // other functions final int INVOCATION_COST = 100; // arbitrary exception cost for instruction counting final int EXCEPTION_COST = 100; String stringReg = null; int indexReg = -1; if (cx.lastInterpreterFrame != null) { // save the top frame from the previous interpretLoop // invocation on the stack if (cx.previousInterpreterInvocations == null) { cx.previousInterpreterInvocations = new ObjArray(); } cx.previousInterpreterInvocations.push(cx.lastInterpreterFrame); } // When restarting continuation throwable is not null and to jump // to the code that rewind continuation state indexReg should be set // to -1. // With the normal call throwable == null and indexReg == -1 allows to // catch bugs with using indeReg to access array elements before // initializing indexReg. GeneratorState generatorState = null; if (throwable != null) { if (throwable instanceof GeneratorState) { generatorState = (GeneratorState) throwable; // reestablish this call frame enterFrame(cx, frame, ScriptRuntime.emptyArgs, true); throwable = null; } else if (!(throwable instanceof ContinuationJump)) { // It should be continuation Kit.codeBug(); } } Object interpreterResult = null; double interpreterResultDbl = 0.0; StateLoop: for (;;) { withoutExceptions: try { if (throwable != null) { // Need to return both 'frame' and 'throwable' from // 'processThrowable', so just added a 'throwable' // member in 'frame'. frame = processThrowable(cx, throwable, frame, indexReg, instructionCounting); throwable = frame.throwable; frame.throwable = null; } else { if (generatorState == null && frame.frozen) Kit.codeBug(); } // Use local variables for constant values in frame // for faster access Object[] stack = frame.stack; double[] sDbl = frame.sDbl; Object[] vars = frame.varSource.stack; double[] varDbls = frame.varSource.sDbl; int[] varAttributes = frame.varSource.stackAttributes; byte[] iCode = frame.idata.itsICode; String[] strings = frame.idata.itsStringTable; // Use local for stackTop as well. Since execption handlers // can only exist at statement level where stack is empty, // it is necessary to save/restore stackTop only across // function calls and normal returns. int stackTop = frame.savedStackTop; // Store new frame in cx which is used for error reporting etc. cx.lastInterpreterFrame = frame; Loop: for (;;) { // Exception handler assumes that PC is already incremented // pass the instruction start when it searches the // exception handler int op = iCode[frame.pc++]; jumplessRun: { // Back indent to ease implementation reading switch (op) { case Icode_GENERATOR: { if (!frame.frozen) { // First time encountering this opcode: create new generator // object and return frame.pc--; // we want to come back here when we resume CallFrame generatorFrame = captureFrameForGenerator(frame); generatorFrame.frozen = true; NativeGenerator generator = new NativeGenerator(frame.scope, generatorFrame.fnOrScript, generatorFrame); frame.result = generator; break Loop; } else { // We are now resuming execution. Fall through to YIELD case. } } // fall through... case Token.YIELD: { if (!frame.frozen) { return freezeGenerator(cx, frame, stackTop, generatorState); } else { Object obj = thawGenerator(frame, stackTop, generatorState, op); if (obj != Scriptable.NOT_FOUND) { throwable = obj; break withoutExceptions; } continue Loop; } } case Icode_GENERATOR_END: { // throw StopIteration frame.frozen = true; int sourceLine = getIndex(iCode, frame.pc); generatorState.returnedException = new JavaScriptException( NativeIterator.getStopIterationObject(frame.scope), frame.idata.itsSourceFile, sourceLine); break Loop; } case Token.STRICT_SETNAME: { Object rhs = stack[stackTop]; if (rhs == DBL_MRK) rhs = ScriptRuntime.wrapNumber(sDbl[stackTop]); --stackTop; Scriptable lhs = (Scriptable)stack[stackTop]; if (lhs != null) { stack[stackTop] = ScriptRuntime.setName(lhs, rhs, cx, frame.scope, stringReg); continue Loop; } stack[stackTop] = cx.newObject(frame.scope, "ReferenceError", new Object[] { stringReg }); } /* fall through */ case Token.THROW: { Object value = stack[stackTop]; if (value == DBL_MRK) value = ScriptRuntime.wrapNumber(sDbl[stackTop]); --stackTop; int sourceLine = getIndex(iCode, frame.pc); throwable = new JavaScriptException(value, frame.idata.itsSourceFile, sourceLine); break withoutExceptions; } case Token.RETHROW: { indexReg += frame.localShift; throwable = stack[indexReg]; break withoutExceptions; } case Token.GE : case Token.LE : case Token.GT : case Token.LT : { --stackTop; Object rhs = stack[stackTop + 1]; Object lhs = stack[stackTop]; boolean valBln; object_compare: { number_compare: { double rDbl, lDbl; if (rhs == DBL_MRK) { rDbl = sDbl[stackTop + 1]; lDbl = stack_double(frame, stackTop); } else if (lhs == DBL_MRK) { rDbl = ScriptRuntime.toNumber(rhs); lDbl = sDbl[stackTop]; } else { break number_compare; } switch (op) { case Token.GE: valBln = (lDbl >= rDbl); break object_compare; case Token.LE: valBln = (lDbl <= rDbl); break object_compare; case Token.GT: valBln = (lDbl > rDbl); break object_compare; case Token.LT: valBln = (lDbl < rDbl); break object_compare; default: throw Kit.codeBug(); } } switch (op) { case Token.GE: valBln = ScriptRuntime.cmp_LE(rhs, lhs); break; case Token.LE: valBln = ScriptRuntime.cmp_LE(lhs, rhs); break; case Token.GT: valBln = ScriptRuntime.cmp_LT(rhs, lhs); break; case Token.LT: valBln = ScriptRuntime.cmp_LT(lhs, rhs); break; default: throw Kit.codeBug(); } } stack[stackTop] = ScriptRuntime.wrapBoolean(valBln); continue Loop; } case Token.IN : case Token.INSTANCEOF : { Object rhs = stack[stackTop]; if (rhs == DBL_MRK) rhs = ScriptRuntime.wrapNumber(sDbl[stackTop]); --stackTop; Object lhs = stack[stackTop]; if (lhs == DBL_MRK) lhs = ScriptRuntime.wrapNumber(sDbl[stackTop]); boolean valBln; if (op == Token.IN) { valBln = ScriptRuntime.in(lhs, rhs, cx); } else { valBln = ScriptRuntime.instanceOf(lhs, rhs, cx); } stack[stackTop] = ScriptRuntime.wrapBoolean(valBln); continue Loop; } case Token.EQ : case Token.NE : { --stackTop; boolean valBln; Object rhs = stack[stackTop + 1]; Object lhs = stack[stackTop]; if (rhs == DBL_MRK) { if (lhs == DBL_MRK) { valBln = (sDbl[stackTop] == sDbl[stackTop + 1]); } else { valBln = ScriptRuntime.eqNumber(sDbl[stackTop + 1], lhs); } } else { if (lhs == DBL_MRK) { valBln = ScriptRuntime.eqNumber(sDbl[stackTop], rhs); } else { valBln = ScriptRuntime.eq(lhs, rhs); } } valBln ^= (op == Token.NE); stack[stackTop] = ScriptRuntime.wrapBoolean(valBln); continue Loop; } case Token.SHEQ : case Token.SHNE : { --stackTop; boolean valBln = shallowEquals(stack, sDbl, stackTop); valBln ^= (op == Token.SHNE); stack[stackTop] = ScriptRuntime.wrapBoolean(valBln); continue Loop; } case Token.IFNE : if (stack_boolean(frame, stackTop--)) { frame.pc += 2; continue Loop; } break jumplessRun; case Token.IFEQ : if (!stack_boolean(frame, stackTop--)) { frame.pc += 2; continue Loop; } break jumplessRun; case Icode_IFEQ_POP : if (!stack_boolean(frame, stackTop--)) { frame.pc += 2; continue Loop; } stack[stackTop--] = null; break jumplessRun; case Token.GOTO : break jumplessRun; case Icode_GOSUB : ++stackTop; stack[stackTop] = DBL_MRK; sDbl[stackTop] = frame.pc + 2; break jumplessRun; case Icode_STARTSUB : if (stackTop == frame.emptyStackTop + 1) { // Call from Icode_GOSUB: store return PC address in the local indexReg += frame.localShift; stack[indexReg] = stack[stackTop]; sDbl[indexReg] = sDbl[stackTop]; --stackTop; } else { // Call from exception handler: exception object is already stored // in the local if (stackTop != frame.emptyStackTop) Kit.codeBug(); } continue Loop; case Icode_RETSUB : { // indexReg: local to store return address if (instructionCounting) { addInstructionCount(cx, frame, 0); } indexReg += frame.localShift; Object value = stack[indexReg]; if (value != DBL_MRK) { // Invocation from exception handler, restore object to rethrow throwable = value; break withoutExceptions; } // Normal return from GOSUB frame.pc = (int)sDbl[indexReg]; if (instructionCounting) { frame.pcPrevBranch = frame.pc; } continue Loop; } case Icode_POP : stack[stackTop] = null; stackTop--; continue Loop; case Icode_POP_RESULT : frame.result = stack[stackTop]; frame.resultDbl = sDbl[stackTop]; stack[stackTop] = null; --stackTop; continue Loop; case Icode_DUP : stack[stackTop + 1] = stack[stackTop]; sDbl[stackTop + 1] = sDbl[stackTop]; stackTop++; continue Loop; case Icode_DUP2 : stack[stackTop + 1] = stack[stackTop - 1]; sDbl[stackTop + 1] = sDbl[stackTop - 1]; stack[stackTop + 2] = stack[stackTop]; sDbl[stackTop + 2] = sDbl[stackTop]; stackTop += 2; continue Loop; case Icode_SWAP : { Object o = stack[stackTop]; stack[stackTop] = stack[stackTop - 1]; stack[stackTop - 1] = o; double d = sDbl[stackTop]; sDbl[stackTop] = sDbl[stackTop - 1]; sDbl[stackTop - 1] = d; continue Loop; } case Token.RETURN : frame.result = stack[stackTop]; frame.resultDbl = sDbl[stackTop]; --stackTop; break Loop; case Token.RETURN_RESULT : break Loop; case Icode_RETUNDEF : frame.result = undefined; break Loop; case Token.BITNOT : { int rIntValue = stack_int32(frame, stackTop); stack[stackTop] = DBL_MRK; sDbl[stackTop] = ~rIntValue; continue Loop; } case Token.BITAND : case Token.BITOR : case Token.BITXOR : case Token.LSH : case Token.RSH : { int lIntValue = stack_int32(frame, stackTop-1); int rIntValue = stack_int32(frame, stackTop); stack[--stackTop] = DBL_MRK; switch (op) { case Token.BITAND: lIntValue &= rIntValue; break; case Token.BITOR: lIntValue |= rIntValue; break; case Token.BITXOR: lIntValue ^= rIntValue; break; case Token.LSH: lIntValue <<= rIntValue; break; case Token.RSH: lIntValue >>= rIntValue; break; } sDbl[stackTop] = lIntValue; continue Loop; } case Token.URSH : { double lDbl = stack_double(frame, stackTop-1); int rIntValue = stack_int32(frame, stackTop) & 0x1F; stack[--stackTop] = DBL_MRK; sDbl[stackTop] = ScriptRuntime.toUint32(lDbl) >>> rIntValue; continue Loop; } case Token.NEG : case Token.POS : { double rDbl = stack_double(frame, stackTop); stack[stackTop] = DBL_MRK; if (op == Token.NEG) { rDbl = -rDbl; } sDbl[stackTop] = rDbl; continue Loop; } case Token.ADD : --stackTop; do_add(stack, sDbl, stackTop, cx); continue Loop; case Token.SUB : case Token.MUL : case Token.DIV : case Token.MOD : { double rDbl = stack_double(frame, stackTop); --stackTop; double lDbl = stack_double(frame, stackTop); stack[stackTop] = DBL_MRK; switch (op) { case Token.SUB: lDbl -= rDbl; break; case Token.MUL: lDbl *= rDbl; break; case Token.DIV: lDbl /= rDbl; break; case Token.MOD: lDbl %= rDbl; break; } sDbl[stackTop] = lDbl; continue Loop; } case Token.NOT : stack[stackTop] = ScriptRuntime.wrapBoolean( !stack_boolean(frame, stackTop)); continue Loop; case Token.BINDNAME : stack[++stackTop] = ScriptRuntime.bind(cx, frame.scope, stringReg); continue Loop; case Token.SETNAME : { Object rhs = stack[stackTop]; if (rhs == DBL_MRK) rhs = ScriptRuntime.wrapNumber(sDbl[stackTop]); --stackTop; Scriptable lhs = (Scriptable)stack[stackTop]; stack[stackTop] = ScriptRuntime.setName(lhs, rhs, cx, frame.scope, stringReg); continue Loop; } case Icode_SETCONST: { Object rhs = stack[stackTop]; if (rhs == DBL_MRK) rhs = ScriptRuntime.wrapNumber(sDbl[stackTop]); --stackTop; Scriptable lhs = (Scriptable)stack[stackTop]; stack[stackTop] = ScriptRuntime.setConst(lhs, rhs, cx, stringReg); continue Loop; } case Token.DELPROP : { Object rhs = stack[stackTop]; if (rhs == DBL_MRK) rhs = ScriptRuntime.wrapNumber(sDbl[stackTop]); --stackTop; Object lhs = stack[stackTop]; if (lhs == DBL_MRK) lhs = ScriptRuntime.wrapNumber(sDbl[stackTop]); stack[stackTop] = ScriptRuntime.delete(lhs, rhs, cx); continue Loop; } case Token.GETPROPNOWARN : { Object lhs = stack[stackTop]; if (lhs == DBL_MRK) lhs = ScriptRuntime.wrapNumber(sDbl[stackTop]); stack[stackTop] = ScriptRuntime.getObjectPropNoWarn(lhs, stringReg, cx); continue Loop; } case Token.GETPROP : { Object lhs = stack[stackTop]; if (lhs == DBL_MRK) lhs = ScriptRuntime.wrapNumber(sDbl[stackTop]); stack[stackTop] = ScriptRuntime.getObjectProp(lhs, stringReg, cx, frame.scope); continue Loop; } case Token.SETPROP : { Object rhs = stack[stackTop]; if (rhs == DBL_MRK) rhs = ScriptRuntime.wrapNumber(sDbl[stackTop]); --stackTop; Object lhs = stack[stackTop]; if (lhs == DBL_MRK) lhs = ScriptRuntime.wrapNumber(sDbl[stackTop]); stack[stackTop] = ScriptRuntime.setObjectProp(lhs, stringReg, rhs, cx); continue Loop; } case Icode_PROP_INC_DEC : { Object lhs = stack[stackTop]; if (lhs == DBL_MRK) lhs = ScriptRuntime.wrapNumber(sDbl[stackTop]); stack[stackTop] = ScriptRuntime.propIncrDecr(lhs, stringReg, cx, iCode[frame.pc]); ++frame.pc; continue Loop; } case Token.GETELEM : { --stackTop; Object lhs = stack[stackTop]; if (lhs == DBL_MRK) { lhs = ScriptRuntime.wrapNumber(sDbl[stackTop]); } Object value; Object id = stack[stackTop + 1]; if (id != DBL_MRK) { value = ScriptRuntime.getObjectElem(lhs, id, cx, frame.scope); } else { double d = sDbl[stackTop + 1]; value = ScriptRuntime.getObjectIndex(lhs, d, cx); } stack[stackTop] = value; continue Loop; } case Token.SETELEM : { stackTop -= 2; Object rhs = stack[stackTop + 2]; if (rhs == DBL_MRK) { rhs = ScriptRuntime.wrapNumber(sDbl[stackTop + 2]); } Object lhs = stack[stackTop]; if (lhs == DBL_MRK) { lhs = ScriptRuntime.wrapNumber(sDbl[stackTop]); } Object value; Object id = stack[stackTop + 1]; if (id != DBL_MRK) { value = ScriptRuntime.setObjectElem(lhs, id, rhs, cx); } else { double d = sDbl[stackTop + 1]; value = ScriptRuntime.setObjectIndex(lhs, d, rhs, cx); } stack[stackTop] = value; continue Loop; } case Icode_ELEM_INC_DEC: { Object rhs = stack[stackTop]; if (rhs == DBL_MRK) rhs = ScriptRuntime.wrapNumber(sDbl[stackTop]); --stackTop; Object lhs = stack[stackTop]; if (lhs == DBL_MRK) lhs = ScriptRuntime.wrapNumber(sDbl[stackTop]); stack[stackTop] = ScriptRuntime.elemIncrDecr(lhs, rhs, cx, iCode[frame.pc]); ++frame.pc; continue Loop; } case Token.GET_REF : { Ref ref = (Ref)stack[stackTop]; stack[stackTop] = ScriptRuntime.refGet(ref, cx); continue Loop; } case Token.SET_REF : { Object value = stack[stackTop]; if (value == DBL_MRK) value = ScriptRuntime.wrapNumber(sDbl[stackTop]); --stackTop; Ref ref = (Ref)stack[stackTop]; stack[stackTop] = ScriptRuntime.refSet(ref, value, cx); continue Loop; } case Token.DEL_REF : { Ref ref = (Ref)stack[stackTop]; stack[stackTop] = ScriptRuntime.refDel(ref, cx); continue Loop; } case Icode_REF_INC_DEC : { Ref ref = (Ref)stack[stackTop]; stack[stackTop] = ScriptRuntime.refIncrDecr(ref, cx, iCode[frame.pc]); ++frame.pc; continue Loop; } case Token.LOCAL_LOAD : ++stackTop; indexReg += frame.localShift; stack[stackTop] = stack[indexReg]; sDbl[stackTop] = sDbl[indexReg]; continue Loop; case Icode_LOCAL_CLEAR : indexReg += frame.localShift; stack[indexReg] = null; continue Loop; case Icode_NAME_AND_THIS : // stringReg: name ++stackTop; stack[stackTop] = ScriptRuntime.getNameFunctionAndThis(stringReg, cx, frame.scope); ++stackTop; stack[stackTop] = ScriptRuntime.lastStoredScriptable(cx); continue Loop; case Icode_PROP_AND_THIS: { Object obj = stack[stackTop]; if (obj == DBL_MRK) obj = ScriptRuntime.wrapNumber(sDbl[stackTop]); // stringReg: property stack[stackTop] = ScriptRuntime.getPropFunctionAndThis(obj, stringReg, cx, frame.scope); ++stackTop; stack[stackTop] = ScriptRuntime.lastStoredScriptable(cx); continue Loop; } case Icode_ELEM_AND_THIS: { Object obj = stack[stackTop - 1]; if (obj == DBL_MRK) obj = ScriptRuntime.wrapNumber(sDbl[stackTop - 1]); Object id = stack[stackTop]; if (id == DBL_MRK) id = ScriptRuntime.wrapNumber(sDbl[stackTop]); stack[stackTop - 1] = ScriptRuntime.getElemFunctionAndThis(obj, id, cx); stack[stackTop] = ScriptRuntime.lastStoredScriptable(cx); continue Loop; } case Icode_VALUE_AND_THIS : { Object value = stack[stackTop]; if (value == DBL_MRK) value = ScriptRuntime.wrapNumber(sDbl[stackTop]); stack[stackTop] = ScriptRuntime.getValueFunctionAndThis(value, cx); ++stackTop; stack[stackTop] = ScriptRuntime.lastStoredScriptable(cx); continue Loop; } case Icode_CALLSPECIAL : { if (instructionCounting) { cx.instructionCount += INVOCATION_COST; } int callType = iCode[frame.pc] & 0xFF; boolean isNew = (iCode[frame.pc + 1] != 0); int sourceLine = getIndex(iCode, frame.pc + 2); // indexReg: number of arguments if (isNew) { // stack change: function arg0 .. argN -> newResult stackTop -= indexReg; Object function = stack[stackTop]; if (function == DBL_MRK) function = ScriptRuntime.wrapNumber(sDbl[stackTop]); Object[] outArgs = getArgsArray( stack, sDbl, stackTop + 1, indexReg); stack[stackTop] = ScriptRuntime.newSpecial( cx, function, outArgs, frame.scope, callType); } else { // stack change: function thisObj arg0 .. argN -> result stackTop -= 1 + indexReg; // Call code generation ensure that stack here // is ... Callable Scriptable Scriptable functionThis = (Scriptable)stack[stackTop + 1]; Callable function = (Callable)stack[stackTop]; Object[] outArgs = getArgsArray( stack, sDbl, stackTop + 2, indexReg); stack[stackTop] = ScriptRuntime.callSpecial( cx, function, functionThis, outArgs, frame.scope, frame.thisObj, callType, frame.idata.itsSourceFile, sourceLine); } frame.pc += 4; continue Loop; } case Token.CALL : case Icode_TAIL_CALL : case Token.REF_CALL : { if (instructionCounting) { cx.instructionCount += INVOCATION_COST; } // stack change: function thisObj arg0 .. argN -> result // indexReg: number of arguments stackTop -= 1 + indexReg; // CALL generation ensures that fun and funThisObj // are already Scriptable and Callable objects respectively Callable fun = (Callable)stack[stackTop]; Scriptable funThisObj = (Scriptable)stack[stackTop + 1]; if (op == Token.REF_CALL) { Object[] outArgs = getArgsArray(stack, sDbl, stackTop + 2, indexReg); stack[stackTop] = ScriptRuntime.callRef(fun, funThisObj, outArgs, cx); continue Loop; } Scriptable calleeScope = frame.scope; if (frame.useActivation) { calleeScope = ScriptableObject.getTopLevelScope(frame.scope); } if (fun instanceof InterpretedFunction) { InterpretedFunction ifun = (InterpretedFunction)fun; if (frame.fnOrScript.securityDomain == ifun.securityDomain) { CallFrame callParentFrame = frame; CallFrame calleeFrame = new CallFrame(); if (op == Icode_TAIL_CALL) { // In principle tail call can re-use the current // frame and its stack arrays but it is hard to // do properly. Any exceptions that can legally // happen during frame re-initialization including // StackOverflowException during innocent looking // System.arraycopy may leave the current frame // data corrupted leading to undefined behaviour // in the catch code bellow that unwinds JS stack // on exceptions. Then there is issue about frame release // end exceptions there. // To avoid frame allocation a released frame // can be cached for re-use which would also benefit // non-tail calls but it is not clear that this caching // would gain in performance due to potentially // bad interaction with GC. callParentFrame = frame.parentFrame; // Release the current frame. See Bug #344501 to see why // it is being done here. exitFrame(cx, frame, null); } initFrame(cx, calleeScope, funThisObj, stack, sDbl, stackTop + 2, indexReg, ifun, callParentFrame, calleeFrame); if (op != Icode_TAIL_CALL) { frame.savedStackTop = stackTop; frame.savedCallOp = op; } frame = calleeFrame; continue StateLoop; } } if (fun instanceof NativeContinuation) { // Jump to the captured continuation ContinuationJump cjump; cjump = new ContinuationJump((NativeContinuation)fun, frame); // continuation result is the first argument if any // of continuation call if (indexReg == 0) { cjump.result = undefined; } else { cjump.result = stack[stackTop + 2]; cjump.resultDbl = sDbl[stackTop + 2]; } // Start the real unwind job throwable = cjump; break withoutExceptions; } if (fun instanceof IdFunctionObject) { IdFunctionObject ifun = (IdFunctionObject)fun; if (NativeContinuation.isContinuationConstructor(ifun)) { frame.stack[stackTop] = captureContinuation(cx, frame.parentFrame, false); continue Loop; } // Bug 405654 -- make best effort to keep Function.apply and // Function.call within this interpreter loop invocation if (BaseFunction.isApplyOrCall(ifun)) { Callable applyCallable = ScriptRuntime.getCallable(funThisObj); if (applyCallable instanceof InterpretedFunction) { InterpretedFunction iApplyCallable = (InterpretedFunction)applyCallable; if (frame.fnOrScript.securityDomain == iApplyCallable.securityDomain) { frame = initFrameForApplyOrCall(cx, frame, indexReg, stack, sDbl, stackTop, op, calleeScope, ifun, iApplyCallable); continue StateLoop; } } } } // Bug 447697 -- make best effort to keep __noSuchMethod__ within this // interpreter loop invocation if (fun instanceof NoSuchMethodShim) { // get the shim and the actual method NoSuchMethodShim noSuchMethodShim = (NoSuchMethodShim) fun; Callable noSuchMethodMethod = noSuchMethodShim.noSuchMethodMethod; // if the method is in fact an InterpretedFunction if (noSuchMethodMethod instanceof InterpretedFunction) { InterpretedFunction ifun = (InterpretedFunction) noSuchMethodMethod; if (frame.fnOrScript.securityDomain == ifun.securityDomain) { frame = initFrameForNoSuchMethod(cx, frame, indexReg, stack, sDbl, stackTop, op, funThisObj, calleeScope, noSuchMethodShim, ifun); continue StateLoop; } } } cx.lastInterpreterFrame = frame; frame.savedCallOp = op; frame.savedStackTop = stackTop; stack[stackTop] = fun.call(cx, calleeScope, funThisObj, getArgsArray(stack, sDbl, stackTop + 2, indexReg)); continue Loop; } case Token.NEW : { if (instructionCounting) { cx.instructionCount += INVOCATION_COST; } // stack change: function arg0 .. argN -> newResult // indexReg: number of arguments stackTop -= indexReg; Object lhs = stack[stackTop]; if (lhs instanceof InterpretedFunction) { InterpretedFunction f = (InterpretedFunction)lhs; if (frame.fnOrScript.securityDomain == f.securityDomain) { Scriptable newInstance = f.createObject(cx, frame.scope); CallFrame calleeFrame = new CallFrame(); initFrame(cx, frame.scope, newInstance, stack, sDbl, stackTop + 1, indexReg, f, frame, calleeFrame); stack[stackTop] = newInstance; frame.savedStackTop = stackTop; frame.savedCallOp = op; frame = calleeFrame; continue StateLoop; } } if (!(lhs instanceof Function)) { if (lhs == DBL_MRK) lhs = ScriptRuntime.wrapNumber(sDbl[stackTop]); throw ScriptRuntime.notFunctionError(lhs); } Function fun = (Function)lhs; if (fun instanceof IdFunctionObject) { IdFunctionObject ifun = (IdFunctionObject)fun; if (NativeContinuation.isContinuationConstructor(ifun)) { frame.stack[stackTop] = captureContinuation(cx, frame.parentFrame, false); continue Loop; } } Object[] outArgs = getArgsArray(stack, sDbl, stackTop + 1, indexReg); stack[stackTop] = fun.construct(cx, frame.scope, outArgs); continue Loop; } case Token.TYPEOF : { Object lhs = stack[stackTop]; if (lhs == DBL_MRK) lhs = ScriptRuntime.wrapNumber(sDbl[stackTop]); stack[stackTop] = ScriptRuntime.typeof(lhs); continue Loop; } case Icode_TYPEOFNAME : stack[++stackTop] = ScriptRuntime.typeofName(frame.scope, stringReg); continue Loop; case Token.STRING : stack[++stackTop] = stringReg; continue Loop; case Icode_SHORTNUMBER : ++stackTop; stack[stackTop] = DBL_MRK; sDbl[stackTop] = getShort(iCode, frame.pc); frame.pc += 2; continue Loop; case Icode_INTNUMBER : ++stackTop; stack[stackTop] = DBL_MRK; sDbl[stackTop] = getInt(iCode, frame.pc); frame.pc += 4; continue Loop; case Token.NUMBER : ++stackTop; stack[stackTop] = DBL_MRK; sDbl[stackTop] = frame.idata.itsDoubleTable[indexReg]; continue Loop; case Token.NAME : stack[++stackTop] = ScriptRuntime.name(cx, frame.scope, stringReg); continue Loop; case Icode_NAME_INC_DEC : stack[++stackTop] = ScriptRuntime.nameIncrDecr(frame.scope, stringReg, cx, iCode[frame.pc]); ++frame.pc; continue Loop; case Icode_SETCONSTVAR1: indexReg = iCode[frame.pc++]; // fallthrough case Token.SETCONSTVAR : if (!frame.useActivation) { if ((varAttributes[indexReg] & ScriptableObject.READONLY) == 0) { throw Context.reportRuntimeError1("msg.var.redecl", frame.idata.argNames[indexReg]); } if ((varAttributes[indexReg] & ScriptableObject.UNINITIALIZED_CONST) != 0) { vars[indexReg] = stack[stackTop]; varAttributes[indexReg] &= ~ScriptableObject.UNINITIALIZED_CONST; varDbls[indexReg] = sDbl[stackTop]; } } else { Object val = stack[stackTop]; if (val == DBL_MRK) val = ScriptRuntime.wrapNumber(sDbl[stackTop]); stringReg = frame.idata.argNames[indexReg]; if (frame.scope instanceof ConstProperties) { ConstProperties cp = (ConstProperties)frame.scope; cp.putConst(stringReg, frame.scope, val); } else throw Kit.codeBug(); } continue Loop; case Icode_SETVAR1: indexReg = iCode[frame.pc++]; // fallthrough case Token.SETVAR : if (!frame.useActivation) { if ((varAttributes[indexReg] & ScriptableObject.READONLY) == 0) { vars[indexReg] = stack[stackTop]; varDbls[indexReg] = sDbl[stackTop]; } } else { Object val = stack[stackTop]; if (val == DBL_MRK) val = ScriptRuntime.wrapNumber(sDbl[stackTop]); stringReg = frame.idata.argNames[indexReg]; frame.scope.put(stringReg, frame.scope, val); } continue Loop; case Icode_GETVAR1: indexReg = iCode[frame.pc++]; // fallthrough case Token.GETVAR : ++stackTop; if (!frame.useActivation) { stack[stackTop] = vars[indexReg]; sDbl[stackTop] = varDbls[indexReg]; } else { stringReg = frame.idata.argNames[indexReg]; stack[stackTop] = frame.scope.get(stringReg, frame.scope); } continue Loop; case Icode_VAR_INC_DEC : { // indexReg : varindex ++stackTop; int incrDecrMask = iCode[frame.pc]; if (!frame.useActivation) { stack[stackTop] = DBL_MRK; Object varValue = vars[indexReg]; double d; if (varValue == DBL_MRK) { d = varDbls[indexReg]; } else { d = ScriptRuntime.toNumber(varValue); vars[indexReg] = DBL_MRK; } double d2 = ((incrDecrMask & Node.DECR_FLAG) == 0) ? d + 1.0 : d - 1.0; varDbls[indexReg] = d2; sDbl[stackTop] = ((incrDecrMask & Node.POST_FLAG) == 0) ? d2 : d; } else { String varName = frame.idata.argNames[indexReg]; stack[stackTop] = ScriptRuntime.nameIncrDecr(frame.scope, varName, cx, incrDecrMask); } ++frame.pc; continue Loop; } case Icode_ZERO : ++stackTop; stack[stackTop] = DBL_MRK; sDbl[stackTop] = 0; continue Loop; case Icode_ONE : ++stackTop; stack[stackTop] = DBL_MRK; sDbl[stackTop] = 1; continue Loop; case Token.NULL : stack[++stackTop] = null; continue Loop; case Token.THIS : stack[++stackTop] = frame.thisObj; continue Loop; case Token.THISFN : stack[++stackTop] = frame.fnOrScript; continue Loop; case Token.FALSE : stack[++stackTop] = Boolean.FALSE; continue Loop; case Token.TRUE : stack[++stackTop] = Boolean.TRUE; continue Loop; case Icode_UNDEF : stack[++stackTop] = undefined; continue Loop; case Token.ENTERWITH : { Object lhs = stack[stackTop]; if (lhs == DBL_MRK) lhs = ScriptRuntime.wrapNumber(sDbl[stackTop]); --stackTop; frame.scope = ScriptRuntime.enterWith(lhs, cx, frame.scope); continue Loop; } case Token.LEAVEWITH : frame.scope = ScriptRuntime.leaveWith(frame.scope); continue Loop; case Token.CATCH_SCOPE : { // stack top: exception object // stringReg: name of exception variable // indexReg: local for exception scope --stackTop; indexReg += frame.localShift; boolean afterFirstScope = (frame.idata.itsICode[frame.pc] != 0); Throwable caughtException = (Throwable)stack[stackTop + 1]; Scriptable lastCatchScope; if (!afterFirstScope) { lastCatchScope = null; } else { lastCatchScope = (Scriptable)stack[indexReg]; } stack[indexReg] = ScriptRuntime.newCatchScope(caughtException, lastCatchScope, stringReg, cx, frame.scope); ++frame.pc; continue Loop; } case Token.ENUM_INIT_KEYS : case Token.ENUM_INIT_VALUES : case Token.ENUM_INIT_ARRAY : { Object lhs = stack[stackTop]; if (lhs == DBL_MRK) lhs = ScriptRuntime.wrapNumber(sDbl[stackTop]); --stackTop; indexReg += frame.localShift; int enumType = op == Token.ENUM_INIT_KEYS ? ScriptRuntime.ENUMERATE_KEYS : op == Token.ENUM_INIT_VALUES ? ScriptRuntime.ENUMERATE_VALUES : ScriptRuntime.ENUMERATE_ARRAY; stack[indexReg] = ScriptRuntime.enumInit(lhs, cx, enumType); continue Loop; } case Token.ENUM_NEXT : case Token.ENUM_ID : { indexReg += frame.localShift; Object val = stack[indexReg]; ++stackTop; stack[stackTop] = (op == Token.ENUM_NEXT) ? (Object)ScriptRuntime.enumNext(val) : (Object)ScriptRuntime.enumId(val, cx); continue Loop; } case Token.REF_SPECIAL : { //stringReg: name of special property Object obj = stack[stackTop]; if (obj == DBL_MRK) obj = ScriptRuntime.wrapNumber(sDbl[stackTop]); stack[stackTop] = ScriptRuntime.specialRef(obj, stringReg, cx); continue Loop; } case Token.REF_MEMBER: { //indexReg: flags Object elem = stack[stackTop]; if (elem == DBL_MRK) elem = ScriptRuntime.wrapNumber(sDbl[stackTop]); --stackTop; Object obj = stack[stackTop]; if (obj == DBL_MRK) obj = ScriptRuntime.wrapNumber(sDbl[stackTop]); stack[stackTop] = ScriptRuntime.memberRef(obj, elem, cx, indexReg); continue Loop; } case Token.REF_NS_MEMBER: { //indexReg: flags Object elem = stack[stackTop]; if (elem == DBL_MRK) elem = ScriptRuntime.wrapNumber(sDbl[stackTop]); --stackTop; Object ns = stack[stackTop]; if (ns == DBL_MRK) ns = ScriptRuntime.wrapNumber(sDbl[stackTop]); --stackTop; Object obj = stack[stackTop]; if (obj == DBL_MRK) obj = ScriptRuntime.wrapNumber(sDbl[stackTop]); stack[stackTop] = ScriptRuntime.memberRef(obj, ns, elem, cx, indexReg); continue Loop; } case Token.REF_NAME: { //indexReg: flags Object name = stack[stackTop]; if (name == DBL_MRK) name = ScriptRuntime.wrapNumber(sDbl[stackTop]); stack[stackTop] = ScriptRuntime.nameRef(name, cx, frame.scope, indexReg); continue Loop; } case Token.REF_NS_NAME: { //indexReg: flags Object name = stack[stackTop]; if (name == DBL_MRK) name = ScriptRuntime.wrapNumber(sDbl[stackTop]); --stackTop; Object ns = stack[stackTop]; if (ns == DBL_MRK) ns = ScriptRuntime.wrapNumber(sDbl[stackTop]); stack[stackTop] = ScriptRuntime.nameRef(ns, name, cx, frame.scope, indexReg); continue Loop; } case Icode_SCOPE_LOAD : indexReg += frame.localShift; frame.scope = (Scriptable)stack[indexReg]; continue Loop; case Icode_SCOPE_SAVE : indexReg += frame.localShift; stack[indexReg] = frame.scope; continue Loop; case Icode_CLOSURE_EXPR : stack[++stackTop] = InterpretedFunction.createFunction(cx, frame.scope, frame.fnOrScript, indexReg); continue Loop; case Icode_CLOSURE_STMT : initFunction(cx, frame.scope, frame.fnOrScript, indexReg); continue Loop; case Token.REGEXP : stack[++stackTop] = frame.scriptRegExps[indexReg]; continue Loop; case Icode_LITERAL_NEW : // indexReg: number of values in the literal ++stackTop; stack[stackTop] = new int[indexReg]; ++stackTop; stack[stackTop] = new Object[indexReg]; sDbl[stackTop] = 0; continue Loop; case Icode_LITERAL_SET : { Object value = stack[stackTop]; if (value == DBL_MRK) value = ScriptRuntime.wrapNumber(sDbl[stackTop]); --stackTop; int i = (int)sDbl[stackTop]; ((Object[])stack[stackTop])[i] = value; sDbl[stackTop] = i + 1; continue Loop; } case Icode_LITERAL_GETTER : { Object value = stack[stackTop]; --stackTop; int i = (int)sDbl[stackTop]; ((Object[])stack[stackTop])[i] = value; ((int[])stack[stackTop - 1])[i] = -1; sDbl[stackTop] = i + 1; continue Loop; } case Icode_LITERAL_SETTER : { Object value = stack[stackTop]; --stackTop; int i = (int)sDbl[stackTop]; ((Object[])stack[stackTop])[i] = value; ((int[])stack[stackTop - 1])[i] = +1; sDbl[stackTop] = i + 1; continue Loop; } case Token.ARRAYLIT : case Icode_SPARE_ARRAYLIT : case Token.OBJECTLIT : { Object[] data = (Object[])stack[stackTop]; --stackTop; int[] getterSetters = (int[])stack[stackTop]; Object val; if (op == Token.OBJECTLIT) { Object[] ids = (Object[])frame.idata.literalIds[indexReg]; val = ScriptRuntime.newObjectLiteral(ids, data, getterSetters, cx, frame.scope); } else { int[] skipIndexces = null; if (op == Icode_SPARE_ARRAYLIT) { skipIndexces = (int[])frame.idata.literalIds[indexReg]; } val = ScriptRuntime.newArrayLiteral(data, skipIndexces, cx, frame.scope); } stack[stackTop] = val; continue Loop; } case Icode_ENTERDQ : { Object lhs = stack[stackTop]; if (lhs == DBL_MRK) lhs = ScriptRuntime.wrapNumber(sDbl[stackTop]); --stackTop; frame.scope = ScriptRuntime.enterDotQuery(lhs, frame.scope); continue Loop; } case Icode_LEAVEDQ : { boolean valBln = stack_boolean(frame, stackTop); Object x = ScriptRuntime.updateDotQuery(valBln, frame.scope); if (x != null) { stack[stackTop] = x; frame.scope = ScriptRuntime.leaveDotQuery(frame.scope); frame.pc += 2; continue Loop; } // reset stack and PC to code after ENTERDQ --stackTop; break jumplessRun; } case Token.DEFAULTNAMESPACE : { Object value = stack[stackTop]; if (value == DBL_MRK) value = ScriptRuntime.wrapNumber(sDbl[stackTop]); stack[stackTop] = ScriptRuntime.setDefaultNamespace(value, cx); continue Loop; } case Token.ESCXMLATTR : { Object value = stack[stackTop]; if (value != DBL_MRK) { stack[stackTop] = ScriptRuntime.escapeAttributeValue(value, cx); } continue Loop; } case Token.ESCXMLTEXT : { Object value = stack[stackTop]; if (value != DBL_MRK) { stack[stackTop] = ScriptRuntime.escapeTextValue(value, cx); } continue Loop; } case Icode_DEBUGGER: if (frame.debuggerFrame != null) { frame.debuggerFrame.onDebuggerStatement(cx); } continue Loop; case Icode_LINE : frame.pcSourceLineStart = frame.pc; if (frame.debuggerFrame != null) { int line = getIndex(iCode, frame.pc); frame.debuggerFrame.onLineChange(cx, line); } frame.pc += 2; continue Loop; case Icode_REG_IND_C0: indexReg = 0; continue Loop; case Icode_REG_IND_C1: indexReg = 1; continue Loop; case Icode_REG_IND_C2: indexReg = 2; continue Loop; case Icode_REG_IND_C3: indexReg = 3; continue Loop; case Icode_REG_IND_C4: indexReg = 4; continue Loop; case Icode_REG_IND_C5: indexReg = 5; continue Loop; case Icode_REG_IND1: indexReg = 0xFF & iCode[frame.pc]; ++frame.pc; continue Loop; case Icode_REG_IND2: indexReg = getIndex(iCode, frame.pc); frame.pc += 2; continue Loop; case Icode_REG_IND4: indexReg = getInt(iCode, frame.pc); frame.pc += 4; continue Loop; case Icode_REG_STR_C0: stringReg = strings[0]; continue Loop; case Icode_REG_STR_C1: stringReg = strings[1]; continue Loop; case Icode_REG_STR_C2: stringReg = strings[2]; continue Loop; case Icode_REG_STR_C3: stringReg = strings[3]; continue Loop; case Icode_REG_STR1: stringReg = strings[0xFF & iCode[frame.pc]]; ++frame.pc; continue Loop; case Icode_REG_STR2: stringReg = strings[getIndex(iCode, frame.pc)]; frame.pc += 2; continue Loop; case Icode_REG_STR4: stringReg = strings[getInt(iCode, frame.pc)]; frame.pc += 4; continue Loop; default : dumpICode(frame.idata); throw new RuntimeException( "Unknown icode : "+op+" @ pc : "+(frame.pc-1)); } // end of interpreter switch } // end of jumplessRun label block // This should be reachable only for jump implementation // when pc points to encoded target offset if (instructionCounting) { addInstructionCount(cx, frame, 2); } int offset = getShort(iCode, frame.pc); if (offset != 0) { // -1 accounts for pc pointing to jump opcode + 1 frame.pc += offset - 1; } else { frame.pc = frame.idata.longJumps. getExistingInt(frame.pc); } if (instructionCounting) { frame.pcPrevBranch = frame.pc; } continue Loop; } // end of Loop: for exitFrame(cx, frame, null); interpreterResult = frame.result; interpreterResultDbl = frame.resultDbl; if (frame.parentFrame != null) { frame = frame.parentFrame; if (frame.frozen) { frame = frame.cloneFrozen(); } setCallResult( frame, interpreterResult, interpreterResultDbl); interpreterResult = null; // Help GC continue StateLoop; } break StateLoop; } // end of interpreter withoutExceptions: try catch (Throwable ex) { if (throwable != null) { // This is serious bug and it is better to track it ASAP ex.printStackTrace(System.err); throw new IllegalStateException(); } throwable = ex; } // This should be reachable only after above catch or from // finally when it needs to propagate exception or from // explicit throw if (throwable == null) Kit.codeBug(); // Exception type final int EX_CATCH_STATE = 2; // Can execute JS catch final int EX_FINALLY_STATE = 1; // Can execute JS finally final int EX_NO_JS_STATE = 0; // Terminate JS execution int exState; ContinuationJump cjump = null; if (generatorState != null && generatorState.operation == NativeGenerator.GENERATOR_CLOSE && throwable == generatorState.value) { exState = EX_FINALLY_STATE; } else if (throwable instanceof JavaScriptException) { exState = EX_CATCH_STATE; } else if (throwable instanceof EcmaError) { // an offical ECMA error object, exState = EX_CATCH_STATE; } else if (throwable instanceof EvaluatorException) { exState = EX_CATCH_STATE; } else if (throwable instanceof RuntimeException) { exState = cx.hasFeature(Context.FEATURE_ENHANCED_JAVA_ACCESS) ? EX_CATCH_STATE : EX_FINALLY_STATE; } else if (throwable instanceof Error) { exState = cx.hasFeature(Context.FEATURE_ENHANCED_JAVA_ACCESS) ? EX_CATCH_STATE : EX_NO_JS_STATE; } else if (throwable instanceof ContinuationJump) { // It must be ContinuationJump exState = EX_FINALLY_STATE; cjump = (ContinuationJump)throwable; } else { exState = cx.hasFeature(Context.FEATURE_ENHANCED_JAVA_ACCESS) ? EX_CATCH_STATE : EX_FINALLY_STATE; } if (instructionCounting) { try { addInstructionCount(cx, frame, EXCEPTION_COST); } catch (RuntimeException ex) { throwable = ex; exState = EX_FINALLY_STATE; } catch (Error ex) { // Error from instruction counting // => unconditionally terminate JS throwable = ex; cjump = null; exState = EX_NO_JS_STATE; } } if (frame.debuggerFrame != null && throwable instanceof RuntimeException) { // Call debugger only for RuntimeException RuntimeException rex = (RuntimeException)throwable; try { frame.debuggerFrame.onExceptionThrown(cx, rex); } catch (Throwable ex) { // Any exception from debugger // => unconditionally terminate JS throwable = ex; cjump = null; exState = EX_NO_JS_STATE; } } for (;;) { if (exState != EX_NO_JS_STATE) { boolean onlyFinally = (exState != EX_CATCH_STATE); indexReg = getExceptionHandler(frame, onlyFinally); if (indexReg >= 0) { // We caught an exception, restart the loop // with exception pending the processing at the loop // start continue StateLoop; } } // No allowed exception handlers in this frame, unwind // to parent and try to look there exitFrame(cx, frame, throwable); frame = frame.parentFrame; if (frame == null) { break; } if (cjump != null && cjump.branchFrame == frame) { // Continuation branch point was hit, // restart the state loop to reenter continuation indexReg = -1; continue StateLoop; } } // No more frames, rethrow the exception or deal with continuation if (cjump != null) { if (cjump.branchFrame != null) { // The above loop should locate the top frame Kit.codeBug(); } if (cjump.capturedFrame != null) { // Restarting detached continuation indexReg = -1; continue StateLoop; } // Return continuation result to the caller interpreterResult = cjump.result; interpreterResultDbl = cjump.resultDbl; throwable = null; } break StateLoop; } // end of StateLoop: for(;;) // Do cleanups/restorations before the final return or throw if (cx.previousInterpreterInvocations != null && cx.previousInterpreterInvocations.size() != 0) { cx.lastInterpreterFrame = cx.previousInterpreterInvocations.pop(); } else { // It was the last interpreter frame on the stack cx.lastInterpreterFrame = null; // Force GC of the value cx.previousInterpreterInvocations cx.previousInterpreterInvocations = null; } if (throwable != null) { if (throwable instanceof RuntimeException) { throw (RuntimeException)throwable; } else { // Must be instance of Error or code bug throw (Error)throwable; } } return (interpreterResult != DBL_MRK) ? interpreterResult : ScriptRuntime.wrapNumber(interpreterResultDbl); } /** * Call __noSuchMethod__. */ private static CallFrame initFrameForNoSuchMethod(Context cx, CallFrame frame, int indexReg, Object[] stack, double[] sDbl, int stackTop, int op, Scriptable funThisObj, Scriptable calleeScope, NoSuchMethodShim noSuchMethodShim, InterpretedFunction ifun) { // create an args array from the stack Object[] argsArray = null; // exactly like getArgsArray except that the first argument // is the method name from the shim int shift = stackTop + 2; Object[] elements = new Object[indexReg]; for (int i=0; i < indexReg; ++i, ++shift) { Object val = stack[shift]; if (val == UniqueTag.DOUBLE_MARK) { val = ScriptRuntime.wrapNumber(sDbl[shift]); } elements[i] = val; } argsArray = new Object[2]; argsArray[0] = noSuchMethodShim.methodName; argsArray[1] = cx.newArray(calleeScope, elements); // exactly the same as if it's a regular InterpretedFunction CallFrame callParentFrame = frame; CallFrame calleeFrame = new CallFrame(); if (op == Icode_TAIL_CALL) { callParentFrame = frame.parentFrame; exitFrame(cx, frame, null); } // init the frame with the underlying method with the // adjusted args array and shim's function initFrame(cx, calleeScope, funThisObj, argsArray, null, 0, 2, ifun, callParentFrame, calleeFrame); if (op != Icode_TAIL_CALL) { frame.savedStackTop = stackTop; frame.savedCallOp = op; } return calleeFrame; } private static boolean shallowEquals(Object[] stack, double[] sDbl, int stackTop) { Object rhs = stack[stackTop + 1]; Object lhs = stack[stackTop]; final Object DBL_MRK = UniqueTag.DOUBLE_MARK; double rdbl, ldbl; if (rhs == DBL_MRK) { rdbl = sDbl[stackTop + 1]; if (lhs == DBL_MRK) { ldbl = sDbl[stackTop]; } else if (lhs instanceof Number) { ldbl = ((Number)lhs).doubleValue(); } else { return false; } } else if (lhs == DBL_MRK) { ldbl = sDbl[stackTop]; if (rhs == DBL_MRK) { rdbl = sDbl[stackTop + 1]; } else if (rhs instanceof Number) { rdbl = ((Number)rhs).doubleValue(); } else { return false; } } else { return ScriptRuntime.shallowEq(lhs, rhs); } return (ldbl == rdbl); } private static CallFrame processThrowable(Context cx, Object throwable, CallFrame frame, int indexReg, boolean instructionCounting) { // Recovering from exception, indexReg contains // the index of handler if (indexReg >= 0) { // Normal exception handler, transfer // control appropriately if (frame.frozen) { // XXX Deal with exceptios!!! frame = frame.cloneFrozen(); } int[] table = frame.idata.itsExceptionTable; frame.pc = table[indexReg + EXCEPTION_HANDLER_SLOT]; if (instructionCounting) { frame.pcPrevBranch = frame.pc; } frame.savedStackTop = frame.emptyStackTop; int scopeLocal = frame.localShift + table[indexReg + EXCEPTION_SCOPE_SLOT]; int exLocal = frame.localShift + table[indexReg + EXCEPTION_LOCAL_SLOT]; frame.scope = (Scriptable)frame.stack[scopeLocal]; frame.stack[exLocal] = throwable; throwable = null; } else { // Continuation restoration ContinuationJump cjump = (ContinuationJump)throwable; // Clear throwable to indicate that exceptions are OK throwable = null; if (cjump.branchFrame != frame) Kit.codeBug(); // Check that we have at least one frozen frame // in the case of detached continuation restoration: // unwind code ensure that if (cjump.capturedFrame == null) Kit.codeBug(); // Need to rewind branchFrame, capturedFrame // and all frames in between int rewindCount = cjump.capturedFrame.frameIndex + 1; if (cjump.branchFrame != null) { rewindCount -= cjump.branchFrame.frameIndex; } int enterCount = 0; CallFrame[] enterFrames = null; CallFrame x = cjump.capturedFrame; for (int i = 0; i != rewindCount; ++i) { if (!x.frozen) Kit.codeBug(); if (isFrameEnterExitRequired(x)) { if (enterFrames == null) { // Allocate enough space to store the rest // of rewind frames in case all of them // would require to enter enterFrames = new CallFrame[rewindCount - i]; } enterFrames[enterCount] = x; ++enterCount; } x = x.parentFrame; } while (enterCount != 0) { // execute enter: walk enterFrames in the reverse // order since they were stored starting from // the capturedFrame, not branchFrame --enterCount; x = enterFrames[enterCount]; enterFrame(cx, x, ScriptRuntime.emptyArgs, true); } // Continuation jump is almost done: capturedFrame // points to the call to the function that captured // continuation, so clone capturedFrame and // emulate return that function with the suplied result frame = cjump.capturedFrame.cloneFrozen(); setCallResult(frame, cjump.result, cjump.resultDbl); // restart the execution } frame.throwable = throwable; return frame; } private static Object freezeGenerator(Context cx, CallFrame frame, int stackTop, GeneratorState generatorState) { if (generatorState.operation == NativeGenerator.GENERATOR_CLOSE) { // Error: no yields when generator is closing throw ScriptRuntime.typeError0("msg.yield.closing"); } // return to our caller (which should be a method of NativeGenerator) frame.frozen = true; frame.result = frame.stack[stackTop]; frame.resultDbl = frame.sDbl[stackTop]; frame.savedStackTop = stackTop; frame.pc--; // we want to come back here when we resume ScriptRuntime.exitActivationFunction(cx); return (frame.result != UniqueTag.DOUBLE_MARK) ? frame.result : ScriptRuntime.wrapNumber(frame.resultDbl); } private static Object thawGenerator(CallFrame frame, int stackTop, GeneratorState generatorState, int op) { // we are resuming execution frame.frozen = false; int sourceLine = getIndex(frame.idata.itsICode, frame.pc); frame.pc += 2; // skip line number data if (generatorState.operation == NativeGenerator.GENERATOR_THROW) { // processing a call to .throw(exception): must // act as if exception was thrown from resumption point return new JavaScriptException(generatorState.value, frame.idata.itsSourceFile, sourceLine); } if (generatorState.operation == NativeGenerator.GENERATOR_CLOSE) { return generatorState.value; } if (generatorState.operation != NativeGenerator.GENERATOR_SEND) throw Kit.codeBug(); if (op == Token.YIELD) frame.stack[stackTop] = generatorState.value; return Scriptable.NOT_FOUND; } private static CallFrame initFrameForApplyOrCall(Context cx, CallFrame frame, int indexReg, Object[] stack, double[] sDbl, int stackTop, int op, Scriptable calleeScope, IdFunctionObject ifun, InterpretedFunction iApplyCallable) { Scriptable applyThis; if (indexReg != 0) { Object obj = stack[stackTop + 2]; if (obj == UniqueTag.DOUBLE_MARK) obj = ScriptRuntime.wrapNumber(sDbl[stackTop + 2]); applyThis = ScriptRuntime.toObjectOrNull(cx, obj); } else { applyThis = null; } if (applyThis == null) { // This covers the case of args[0] == (null|undefined) as well. applyThis = ScriptRuntime.getTopCallScope(cx); } if(op == Icode_TAIL_CALL) { exitFrame(cx, frame, null); frame = frame.parentFrame; } else { frame.savedStackTop = stackTop; frame.savedCallOp = op; } CallFrame calleeFrame = new CallFrame(); if(BaseFunction.isApply(ifun)) { Object[] callArgs = indexReg < 2 ? ScriptRuntime.emptyArgs : ScriptRuntime.getApplyArguments(cx, stack[stackTop + 3]); initFrame(cx, calleeScope, applyThis, callArgs, null, 0, callArgs.length, iApplyCallable, frame, calleeFrame); } else { // Shift args left for(int i = 1; i < indexReg; ++i) { stack[stackTop + 1 + i] = stack[stackTop + 2 + i]; sDbl[stackTop + 1 + i] = sDbl[stackTop + 2 + i]; } int argCount = indexReg < 2 ? 0 : indexReg - 1; initFrame(cx, calleeScope, applyThis, stack, sDbl, stackTop + 2, argCount, iApplyCallable, frame, calleeFrame); } frame = calleeFrame; return frame; } private static void initFrame(Context cx, Scriptable callerScope, Scriptable thisObj, Object[] args, double[] argsDbl, int argShift, int argCount, InterpretedFunction fnOrScript, CallFrame parentFrame, CallFrame frame) { InterpreterData idata = fnOrScript.idata; boolean useActivation = idata.itsNeedsActivation; DebugFrame debuggerFrame = null; if (cx.debugger != null) { debuggerFrame = cx.debugger.getFrame(cx, idata); if (debuggerFrame != null) { useActivation = true; } } if (useActivation) { // Copy args to new array to pass to enterActivationFunction // or debuggerFrame.onEnter if (argsDbl != null) { args = getArgsArray(args, argsDbl, argShift, argCount); } argShift = 0; argsDbl = null; } Scriptable scope; if (idata.itsFunctionType != 0) { if (!idata.useDynamicScope) { scope = fnOrScript.getParentScope(); } else { scope = callerScope; } if (useActivation) { scope = ScriptRuntime.createFunctionActivation( fnOrScript, scope, args); } } else { scope = callerScope; ScriptRuntime.initScript(fnOrScript, thisObj, cx, scope, fnOrScript.idata.evalScriptFlag); } if (idata.itsNestedFunctions != null) { if (idata.itsFunctionType != 0 && !idata.itsNeedsActivation) Kit.codeBug(); for (int i = 0; i < idata.itsNestedFunctions.length; i++) { InterpreterData fdata = idata.itsNestedFunctions[i]; if (fdata.itsFunctionType == FunctionNode.FUNCTION_STATEMENT) { initFunction(cx, scope, fnOrScript, i); } } } Scriptable[] scriptRegExps = null; if (idata.itsRegExpLiterals != null) { // Wrapped regexps for functions are stored in // InterpretedFunction // but for script which should not contain references to scope // the regexps re-wrapped during each script execution if (idata.itsFunctionType != 0) { scriptRegExps = fnOrScript.functionRegExps; } else { scriptRegExps = fnOrScript.createRegExpWraps(cx, scope); } } // Initialize args, vars, locals and stack int emptyStackTop = idata.itsMaxVars + idata.itsMaxLocals - 1; int maxFrameArray = idata.itsMaxFrameArray; if (maxFrameArray != emptyStackTop + idata.itsMaxStack + 1) Kit.codeBug(); Object[] stack; int[] stackAttributes; double[] sDbl; boolean stackReuse; if (frame.stack != null && maxFrameArray <= frame.stack.length) { // Reuse stacks from old frame stackReuse = true; stack = frame.stack; stackAttributes = frame.stackAttributes; sDbl = frame.sDbl; } else { stackReuse = false; stack = new Object[maxFrameArray]; stackAttributes = new int[maxFrameArray]; sDbl = new double[maxFrameArray]; } int varCount = idata.getParamAndVarCount(); for (int i = 0; i < varCount; i++) { if (idata.getParamOrVarConst(i)) stackAttributes[i] = ScriptableObject.CONST; } int definedArgs = idata.argCount; if (definedArgs > argCount) { definedArgs = argCount; } // Fill the frame structure frame.parentFrame = parentFrame; frame.frameIndex = (parentFrame == null) ? 0 : parentFrame.frameIndex + 1; if(frame.frameIndex > cx.getMaximumInterpreterStackDepth()) { throw Context.reportRuntimeError("Exceeded maximum stack depth"); } frame.frozen = false; frame.fnOrScript = fnOrScript; frame.idata = idata; frame.stack = stack; frame.stackAttributes = stackAttributes; frame.sDbl = sDbl; frame.varSource = frame; frame.localShift = idata.itsMaxVars; frame.emptyStackTop = emptyStackTop; frame.debuggerFrame = debuggerFrame; frame.useActivation = useActivation; frame.thisObj = thisObj; frame.scriptRegExps = scriptRegExps; // Initialize initial values of variables that change during // interpretation. frame.result = Undefined.instance; frame.pc = 0; frame.pcPrevBranch = 0; frame.pcSourceLineStart = idata.firstLinePC; frame.scope = scope; frame.savedStackTop = emptyStackTop; frame.savedCallOp = 0; System.arraycopy(args, argShift, stack, 0, definedArgs); if (argsDbl != null) { System.arraycopy(argsDbl, argShift, sDbl, 0, definedArgs); } for (int i = definedArgs; i != idata.itsMaxVars; ++i) { stack[i] = Undefined.instance; } if (stackReuse) { // Clean the stack part and space beyond stack if any // of the old array to allow to GC objects there for (int i = emptyStackTop + 1; i != stack.length; ++i) { stack[i] = null; } } enterFrame(cx, frame, args, false); } private static boolean isFrameEnterExitRequired(CallFrame frame) { return frame.debuggerFrame != null || frame.idata.itsNeedsActivation; } private static void enterFrame(Context cx, CallFrame frame, Object[] args, boolean continuationRestart) { if (frame.parentFrame != null && !frame.parentFrame.fnOrScript.isScript()) frame.fnOrScript.defaultPut("caller", frame.parentFrame.fnOrScript); boolean usesActivation = frame.idata.itsNeedsActivation; boolean isDebugged = frame.debuggerFrame != null; if(usesActivation || isDebugged) { Scriptable scope = frame.scope; if(scope == null) { Kit.codeBug(); } else if (continuationRestart) { // Walk the parent chain of frame.scope until a NativeCall is // found. Normally, frame.scope is a NativeCall when called // from initFrame() for a debugged or activatable function. // However, when called from interpretLoop() as part of // restarting a continuation, it can also be a NativeWith if // the continuation was captured within a "with" or "catch" // block ("catch" implicitly uses NativeWith to create a scope // to expose the exception variable). for(;;) { if(scope instanceof NativeWith) { scope = scope.getParentScope(); if (scope == null || (frame.parentFrame != null && frame.parentFrame.scope == scope)) { // If we get here, we didn't find a NativeCall in // the call chain before reaching parent frame's // scope. This should not be possible. Kit.codeBug(); break; // Never reached, but keeps the static analyzer happy about "scope" not being null 5 lines above. } } else { break; } } } if (isDebugged) { frame.debuggerFrame.onEnter(cx, scope, frame.thisObj, args); } // Enter activation only when itsNeedsActivation true, // since debugger should not interfere with activation // chaining if (usesActivation) { ScriptRuntime.enterActivationFunction(cx, scope); } } } private static void exitFrame(Context cx, CallFrame frame, Object throwable) { frame.fnOrScript.delete("caller"); if (frame.idata.itsNeedsActivation) { ScriptRuntime.exitActivationFunction(cx); } if (frame.debuggerFrame != null) { try { if (throwable instanceof Throwable) { frame.debuggerFrame.onExit(cx, true, throwable); } else { Object result; ContinuationJump cjump = (ContinuationJump)throwable; if (cjump == null) { result = frame.result; } else { result = cjump.result; } if (result == UniqueTag.DOUBLE_MARK) { double resultDbl; if (cjump == null) { resultDbl = frame.resultDbl; } else { resultDbl = cjump.resultDbl; } result = ScriptRuntime.wrapNumber(resultDbl); } frame.debuggerFrame.onExit(cx, false, result); } } catch (Throwable ex) { System.err.println( "RHINO USAGE WARNING: onExit terminated with exception"); ex.printStackTrace(System.err); } } } private static void setCallResult(CallFrame frame, Object callResult, double callResultDbl) { if (frame.savedCallOp == Token.CALL) { frame.stack[frame.savedStackTop] = callResult; frame.sDbl[frame.savedStackTop] = callResultDbl; } else if (frame.savedCallOp == Token.NEW) { // If construct returns scriptable, // then it replaces on stack top saved original instance // of the object. if (callResult instanceof Scriptable) { frame.stack[frame.savedStackTop] = callResult; } } else { Kit.codeBug(); } frame.savedCallOp = 0; } public static NativeContinuation captureContinuation(Context cx) { if (cx.lastInterpreterFrame == null || !(cx.lastInterpreterFrame instanceof CallFrame)) { throw new IllegalStateException("Interpreter frames not found"); } return captureContinuation(cx, (CallFrame)cx.lastInterpreterFrame, true); } private static NativeContinuation captureContinuation(Context cx, CallFrame frame, boolean requireContinuationsTopFrame) { NativeContinuation c = new NativeContinuation(); ScriptRuntime.setObjectProtoAndParent( c, ScriptRuntime.getTopCallScope(cx)); // Make sure that all frames are frozen CallFrame x = frame; CallFrame outermost = frame; while (x != null && !x.frozen) { x.frozen = true; // Allow to GC unused stack space for (int i = x.savedStackTop + 1; i != x.stack.length; ++i) { // Allow to GC unused stack space x.stack[i] = null; x.stackAttributes[i] = ScriptableObject.EMPTY; } if (x.savedCallOp == Token.CALL) { // the call will always overwrite the stack top with the result x.stack[x.savedStackTop] = null; } else { if (x.savedCallOp != Token.NEW) Kit.codeBug(); // the new operator uses stack top to store the constructed // object so it shall not be cleared: see comments in // setCallResult } outermost = x; x = x.parentFrame; } if (requireContinuationsTopFrame) { while (outermost.parentFrame != null) outermost = outermost.parentFrame; if (!outermost.isContinuationsTopFrame) { throw new IllegalStateException("Cannot capture continuation " + "from JavaScript code not called directly by " + "executeScriptWithContinuations or " + "callFunctionWithContinuations"); } } c.initImplementation(frame); return c; } private static int stack_int32(CallFrame frame, int i) { Object x = frame.stack[i]; double value; if (x == UniqueTag.DOUBLE_MARK) { value = frame.sDbl[i]; } else { value = ScriptRuntime.toNumber(x); } return ScriptRuntime.toInt32(value); } private static double stack_double(CallFrame frame, int i) { Object x = frame.stack[i]; if (x != UniqueTag.DOUBLE_MARK) { return ScriptRuntime.toNumber(x); } else { return frame.sDbl[i]; } } private static boolean stack_boolean(CallFrame frame, int i) { Object x = frame.stack[i]; if (x == Boolean.TRUE) { return true; } else if (x == Boolean.FALSE) { return false; } else if (x == UniqueTag.DOUBLE_MARK) { double d = frame.sDbl[i]; return d == d && d != 0.0; } else if (x == null || x == Undefined.instance) { return false; } else if (x instanceof Number) { double d = ((Number)x).doubleValue(); return (d == d && d != 0.0); } else if (x instanceof Boolean) { return ((Boolean)x).booleanValue(); } else { return ScriptRuntime.toBoolean(x); } } private static void do_add(Object[] stack, double[] sDbl, int stackTop, Context cx) { Object rhs = stack[stackTop + 1]; Object lhs = stack[stackTop]; double d; boolean leftRightOrder; if (rhs == UniqueTag.DOUBLE_MARK) { d = sDbl[stackTop + 1]; if (lhs == UniqueTag.DOUBLE_MARK) { sDbl[stackTop] += d; return; } leftRightOrder = true; // fallthrough to object + number code } else if (lhs == UniqueTag.DOUBLE_MARK) { d = sDbl[stackTop]; lhs = rhs; leftRightOrder = false; // fallthrough to object + number code } else { if (lhs instanceof Scriptable || rhs instanceof Scriptable) { stack[stackTop] = ScriptRuntime.add(lhs, rhs, cx); } else if (lhs instanceof String) { String lstr = (String)lhs; String rstr = ScriptRuntime.toString(rhs); stack[stackTop] = lstr.concat(rstr); } else if (rhs instanceof String) { String lstr = ScriptRuntime.toString(lhs); String rstr = (String)rhs; stack[stackTop] = lstr.concat(rstr); } else { double lDbl = (lhs instanceof Number) ? ((Number)lhs).doubleValue() : ScriptRuntime.toNumber(lhs); double rDbl = (rhs instanceof Number) ? ((Number)rhs).doubleValue() : ScriptRuntime.toNumber(rhs); stack[stackTop] = UniqueTag.DOUBLE_MARK; sDbl[stackTop] = lDbl + rDbl; } return; } // handle object(lhs) + number(d) code if (lhs instanceof Scriptable) { rhs = ScriptRuntime.wrapNumber(d); if (!leftRightOrder) { Object tmp = lhs; lhs = rhs; rhs = tmp; } stack[stackTop] = ScriptRuntime.add(lhs, rhs, cx); } else if (lhs instanceof String) { String lstr = (String)lhs; String rstr = ScriptRuntime.toString(d); if (leftRightOrder) { stack[stackTop] = lstr.concat(rstr); } else { stack[stackTop] = rstr.concat(lstr); } } else { double lDbl = (lhs instanceof Number) ? ((Number)lhs).doubleValue() : ScriptRuntime.toNumber(lhs); stack[stackTop] = UniqueTag.DOUBLE_MARK; sDbl[stackTop] = lDbl + d; } } private static Object[] getArgsArray(Object[] stack, double[] sDbl, int shift, int count) { if (count == 0) { return ScriptRuntime.emptyArgs; } Object[] args = new Object[count]; for (int i = 0; i != count; ++i, ++shift) { Object val = stack[shift]; if (val == UniqueTag.DOUBLE_MARK) { val = ScriptRuntime.wrapNumber(sDbl[shift]); } args[i] = val; } return args; } private static void addInstructionCount(Context cx, CallFrame frame, int extra) { cx.instructionCount += frame.pc - frame.pcPrevBranch + extra; if (cx.instructionCount > cx.instructionThreshold) { cx.observeInstructionCount(cx.instructionCount); cx.instructionCount = 0; } } } htmlunit-core-js-2.8/rhino/src/org/mozilla/javascript/NativeGenerator.java0000755000175000017500000002462311222455466026702 0ustar cavedoncavedon/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- * * ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * Contributor(s): * Norris Boyd * * Alternatively, the contents of this file may be used under the terms of * the GNU General Public License Version 2 or later (the "GPL"), in which * case the provisions of the GPL are applicable instead of those above. If * you wish to allow use of your version of this file only under the terms of * the GPL and not to allow others to use your version of this file under the * MPL, indicate your decision by deleting the provisions above and replacing * them with the notice and other provisions required by the GPL. If you do * not delete the provisions above, a recipient may use your version of this * file under either the MPL or the GPL. * * ***** END LICENSE BLOCK ***** */ package org.mozilla.javascript; /** * This class implements generator objects. See * http://developer.mozilla.org/en/docs/New_in_JavaScript_1.7#Generators * * @author Norris Boyd */ public final class NativeGenerator extends IdScriptableObject { private static final long serialVersionUID = 1645892441041347273L; private static final Object GENERATOR_TAG = "Generator"; static NativeGenerator init(ScriptableObject scope, boolean sealed) { // Generator // Can't use "NativeGenerator().exportAsJSClass" since we don't want // to define "Generator" as a constructor in the top-level scope. NativeGenerator prototype = new NativeGenerator(); if (scope != null) { prototype.setParentScope(scope); prototype.setPrototype(getObjectPrototype(scope)); } prototype.activatePrototypeMap(MAX_PROTOTYPE_ID); if (sealed) { prototype.sealObject(); } // Need to access Generator prototype when constructing // Generator instances, but don't have a generator constructor // to use to find the prototype. Use the "associateValue" // approach instead. if (scope != null) { scope.associateValue(GENERATOR_TAG, prototype); } return prototype; } /** * Only for constructing the prototype object. */ private NativeGenerator() { } public NativeGenerator(Scriptable scope, NativeFunction function, Object savedState) { this.function = function; this.savedState = savedState; // Set parent and prototype properties. Since we don't have a // "Generator" constructor in the top scope, we stash the // prototype in the top scope's associated value. Scriptable top = ScriptableObject.getTopLevelScope(scope); this.setParentScope(top); NativeGenerator prototype = (NativeGenerator) ScriptableObject.getTopScopeValue(top, GENERATOR_TAG); this.setPrototype(prototype); } public static final int GENERATOR_SEND = 0, GENERATOR_THROW = 1, GENERATOR_CLOSE = 2; @Override public String getClassName() { return "Generator"; } /** * Close the generator if it is still open. */ @Override protected void finalize() throws Throwable { if (savedState != null) { // This is a little tricky since we are most likely running in // a different thread. We need to get a Context to run this, and // we must call "doTopCall" since this will likely be the outermost // JavaScript frame on this thread. Context cx = Context.getCurrentContext(); ContextFactory factory = cx != null ? cx.getFactory() : ContextFactory.getGlobal(); factory.call(new CloseGeneratorAction(this)); } } private static class CloseGeneratorAction implements ContextAction { private NativeGenerator generator; CloseGeneratorAction(NativeGenerator generator) { this.generator = generator; } public Object run(Context cx) { Scriptable scope = ScriptableObject.getTopLevelScope(generator); Callable closeGenerator = new Callable() { public Object call(Context cx, Scriptable scope, Scriptable thisObj, Object[] args) { return ((NativeGenerator)thisObj).resume(cx, scope, GENERATOR_CLOSE, new GeneratorClosedException()); } }; return ScriptRuntime.doTopCall(closeGenerator, cx, scope, generator, null); } } @Override protected void initPrototypeId(int id) { String s; int arity; switch (id) { case Id_close: arity=1; s="close"; break; case Id_next: arity=1; s="next"; break; case Id_send: arity=0; s="send"; break; case Id_throw: arity=0; s="throw"; break; case Id___iterator__: arity=1; s="__iterator__"; break; default: throw new IllegalArgumentException(String.valueOf(id)); } initPrototypeMethod(GENERATOR_TAG, id, s, arity); } @Override public Object execIdCall(IdFunctionObject f, Context cx, Scriptable scope, Scriptable thisObj, Object[] args) { if (!f.hasTag(GENERATOR_TAG)) { return super.execIdCall(f, cx, scope, thisObj, args); } int id = f.methodId(); if (!(thisObj instanceof NativeGenerator)) throw incompatibleCallError(f); NativeGenerator generator = (NativeGenerator) thisObj; switch (id) { case Id_close: // need to run any pending finally clauses return generator.resume(cx, scope, GENERATOR_CLOSE, new GeneratorClosedException()); case Id_next: // arguments to next() are ignored generator.firstTime = false; return generator.resume(cx, scope, GENERATOR_SEND, Undefined.instance); case Id_send: { Object arg = args.length > 0 ? args[0] : Undefined.instance; if (generator.firstTime && !arg.equals(Undefined.instance)) { throw ScriptRuntime.typeError0("msg.send.newborn"); } return generator.resume(cx, scope, GENERATOR_SEND, arg); } case Id_throw: return generator.resume(cx, scope, GENERATOR_THROW, args.length > 0 ? args[0] : Undefined.instance); case Id___iterator__: return thisObj; default: throw new IllegalArgumentException(String.valueOf(id)); } } private Object resume(Context cx, Scriptable scope, int operation, Object value) { if (savedState == null) { if (operation == GENERATOR_CLOSE) return Undefined.instance; Object thrown; if (operation == GENERATOR_THROW) { thrown = value; } else { thrown = NativeIterator.getStopIterationObject(scope); } throw new JavaScriptException(thrown, lineSource, lineNumber); } try { synchronized (this) { // generator execution is necessarily single-threaded and // non-reentrant. // See https://bugzilla.mozilla.org/show_bug.cgi?id=349263 if (locked) throw ScriptRuntime.typeError0("msg.already.exec.gen"); locked = true; } return function.resumeGenerator(cx, scope, operation, savedState, value); } catch (GeneratorClosedException e) { // On closing a generator in the compile path, the generator // throws a special exception. This ensures execution of all pending // finalizers and will not get caught by user code. return Undefined.instance; } catch (RhinoException e) { lineNumber = e.lineNumber(); lineSource = e.lineSource(); savedState = null; throw e; } finally { synchronized (this) { locked = false; } if (operation == GENERATOR_CLOSE) savedState = null; } } // #string_id_map# @Override protected int findPrototypeId(String s) { int id; // #generated# Last update: 2007-06-14 13:13:03 EDT L0: { id = 0; String X = null; int c; int s_length = s.length(); if (s_length==4) { c=s.charAt(0); if (c=='n') { X="next";id=Id_next; } else if (c=='s') { X="send";id=Id_send; } } else if (s_length==5) { c=s.charAt(0); if (c=='c') { X="close";id=Id_close; } else if (c=='t') { X="throw";id=Id_throw; } } else if (s_length==12) { X="__iterator__";id=Id___iterator__; } if (X!=null && X!=s && !X.equals(s)) id = 0; break L0; } // #/generated# return id; } private static final int Id_close = 1, Id_next = 2, Id_send = 3, Id_throw = 4, Id___iterator__ = 5, MAX_PROTOTYPE_ID = 5; // #/string_id_map# private NativeFunction function; private Object savedState; private String lineSource; private int lineNumber; private boolean firstTime = true; private boolean locked; public static class GeneratorClosedException extends RuntimeException { private static final long serialVersionUID = 2561315658662379681L; } } htmlunit-core-js-2.8/rhino/src/org/mozilla/javascript/Context.java0000644000175000017500000030117611321335670025221 0ustar cavedoncavedon/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- * * ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is Rhino code, released * May 6, 1999. * * The Initial Developer of the Original Code is * Netscape Communications Corporation. * Portions created by the Initial Developer are Copyright (C) 1997-2000 * the Initial Developer. All Rights Reserved. * * Contributor(s): * Bob Jervis * * Alternatively, the contents of this file may be used under the terms of * the GNU General Public License Version 2 or later (the "GPL"), in which * case the provisions of the GPL are applicable instead of those above. If * you wish to allow use of your version of this file only under the terms of * the GPL and not to allow others to use your version of this file under the * MPL, indicate your decision by deleting the provisions above and replacing * them with the notice and other provisions required by the GPL. If you do * not delete the provisions above, a recipient may use your version of this * file under either the MPL or the GPL. * * ***** END LICENSE BLOCK ***** */ // API class package org.mozilla.javascript; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.io.CharArrayWriter; import java.io.IOException; 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.util.Map; import java.util.HashMap; import java.util.Set; import java.util.HashSet; import java.util.Locale; 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.

* * 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.

* * 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; /** * Controls behaviour of Date.prototype.getYear(). * If hasFeature(FEATURE_NON_ECMA_GET_YEAR) 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 hasFeature(FEATURE_MEMBER_EXPR_AS_FUNCTION_NAME) returns * true, allow function memberExpression(args) { body } to be * syntax sugar for memberExpression = function(args) { body }, * 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 hasFeature(RESERVED_KEYWORD_AS_IDENTIFIER) 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 toString() should returns the same result * as toSource() when applied to objects and arrays. * If hasFeature(FEATURE_TO_STRING_AS_SOURCE) returns true, * calling toString() on JS objects gives the same result as * calling toSource(). That is it returns JS source with code * to create an object with all enumeratable fields of the original object * instead of printing [object result of * {@link Scriptable#getClassName()}]. *

* 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 __proto__ and __parent__ * are treated specially. * If hasFeature(FEATURE_PARENT_PROTO_PROPERTIES) returns true, * treat __parent__ and __proto__ as special properties. *

* 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 x.__proto__ = y changes the prototype * chain of the object x to point to y, * x["__proto__"] = y simply assigns a new value to the property * __proto__ in x 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. */ 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. *

* 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. *

* This is useful to define shared scope containing functions that can * be called from scripts and functions using private scopes. *

* 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. *

* 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. *

* 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. *

* 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. *

* 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. *

* Note that this feature should only be enabled for trusted scripts. *

* By default {@link #hasFeature(int)} returns false. * @since 1.7 Release 1 */ public static final int FEATURE_ENHANCED_JAVA_ACCESS = 13; /** * Special to HtmlUnit's Rhino fork. * Enable assignment to properties with only a getter defined. * This was Rhino's standard behaviour until 1.7R2. * By default {@link #hasFeature(int)} returns false. */ public static final int FEATURE_HTMLUNIT_WRITE_READONLY_PROPERTIES = 14; /** * Special to HtmlUnit's Rhino fork. * Indicates if a JavaScript catch statement can catch Java exceptions * (exceptions occurring in host objects). * By default {@link #hasFeature(int)} returns true. */ public static final int FEATURE_HTMLUNIT_JS_CATCH_JAVA_EXCEPTION = 15; 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. */ 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; setLanguageVersion(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.

* * @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. *

* The same as enter() except that cx * is associated with the current thread and returned if * the current thread has no associated context and cx * 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) */ 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 exit() 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 * ContextFactory.getGlobal().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)}. * @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)}. */ 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)}. *

* It is allowed but not advisable to use null for factory * 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(ContextFactory.Listener) * @see ContextFactory#getGlobal() */ 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(ContextFactory.Listener) * @see ContextFactory#getGlobal() */ 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. *

* If sealKey is not null, calling * {@link #unseal(Object sealKey)} with the same key unseals * the object. If sealKey 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 sealKey argument should not be null and should match * sealKey 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. *

* 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. * *

* 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: 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. * *

* The implementation version is of the form *

     *    "name langVer release relNum date"
     * 
* where name is the name of the product, langVer is * the language version, relNum is the release number, and * date 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() { // XXX Probably it would be better to embed this directly into source // with special build preprocessing but that would require some ant // tweaking and then replacing token in resource files was simpler if (implementationVersion == null) { implementationVersion = ScriptRuntime.getMessage0("implementation.version"); } 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.

* * This method must be called to initialize a scope before scripts * can be evaluated in that scope.

* * 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. * * 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.

* * This method must be called to initialize a scope before scripts * can be evaluated in that scope.

* * 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. * * 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.

* * This method must be called to initialize a scope before scripts * can be evaluated in that scope.

* * This method does not affect the Context it is called upon.

* * 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); } /** * 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); } /** * 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. *

* 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. *

* 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. if (errorseen && p.eof()) return false; else return true; } /** * @deprecated * @see #compileReader(Reader in, String sourceName, int lineno, * Object securityDomain) */ 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. *

* 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. *

* 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); } protected 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. *

* 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. *

* 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. *

* Decompiles a previously compiled JavaScript function object to * canonical source. *

* 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. *

* 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 final Scriptable newObject(Scriptable scope) { return newObject(scope, "Object", ScriptRuntime.emptyArgs); } /** * Create a new JavaScript object by executing the named constructor. * * The call newObject(scope, "Foo") 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 final Scriptable newObject(Scriptable scope, String constructorName) { return newObject(scope, constructorName, ScriptRuntime.emptyArgs); } /** * Creates a new JavaScript object by executing the named constructor. * * Searches scope for the named constructor, calls it with * the given arguments, and returns the result.

* * The code *

     * Object[] args = { "a", "b" };
     * newObject(scope, "Foo", args)
* is equivalent to evaluating "new Foo('a', 'b')", assuming that the Foo * constructor has been defined in scope. * * @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 final Scriptable newObject(Scriptable scope, String constructorName, Object[] args) { scope = ScriptableObject.getTopLevelScope(scope); Function ctor = ScriptRuntime.getExistingCtor(this, scope, constructorName); if (args == null) { args = ScriptRuntime.emptyArgs; } return ctor.construct(this, scope, args); } /** * Create an array with a specified initial length. *

* @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 final Scriptable newArray(Scriptable scope, int length) { NativeArray result = new NativeArray(length); ScriptRuntime.setObjectProtoAndParent(result, scope); 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 final Scriptable newArray(Scriptable scope, Object[] elements) { if (elements.getClass().getComponentType() != ScriptRuntime.ObjectClass) throw new IllegalArgumentException(); NativeArray result = new NativeArray(elements); ScriptRuntime.setObjectProtoAndParent(result, scope); return result; } /** * Get the elements of a JavaScript array. *

* 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. *

* 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. *

* Returns a Java double for the JavaScript Number. *

* 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. *

* See ECMA 9.8. *

* @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. *

* Note that a scope must be provided to look up the constructors * for Number, Boolean, and String. *

* See ECMA 9.9. *

* 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) */ 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. *

* 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. *

* Note that for Number instances during any arithmetic operation in * JavaScript the engine will always use the result of * Number.doubleValue() resulting in a precision loss if * the number can not fit into double. *

* If value is an instance of Character, it will be converted to string of * length 1 and its JavaScript type will be string. *

* 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: *

     *    Context cx = Context.getCurrentContext();
     *    return cx.getWrapFactory().wrap(cx, scope, value, null);
     * 
* * @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. */ 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. *

* This method always throws an exception, its return value is provided * only for convenience to allow a usage like: *

     * throw Context.throwAsScriptRuntimeEx(ex);
     * 
* 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. *

* 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. *

* 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. *

* 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. *

* 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. *

SecurityController may only be set if it is currently null * and {@link SecurityController#hasGlobal()} is false. * 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. *

{@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. *

* Since the Context is associated with a thread it can be * used to maintain values that can be later retrieved using * the current thread. *

* 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. *

* @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(); 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 #FEATURE_DYNAMIC_SCOPE * @see #hasFeature(int) */ public final boolean hasCompileFunctionsWithDynamicScope() { return compileFunctionsWithDynamicScopeFlag; } /** * @deprecated * @see #FEATURE_DYNAMIC_SCOPE * @see #hasFeature(int) */ public final void setCompileFunctionsWithDynamicScope(boolean flag) { if (sealed) onSealedMutation(); compileFunctionsWithDynamicScopeFlag = flag; } /** * @deprecated * @see ClassCache#get(Scriptable) * @see ClassCache#setCachingEnabled(boolean) */ public static void setCachingEnabled(boolean cachingEnabled) { } /** * Set a WrapFactory for this Context. *

* 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. *

* 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 featureIndex 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 Context. Note that the XMLLib.Factory interface should * be considered experimental. * * The default implementation uses the implementation provided by this * Context's {@link ContextFactory}. * * @return An XMLLib.Factory. Should not return null 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 * observeInstructionCount(). * When the threshold is zero, instruction counting is disabled, * otherwise each time the run-time executes at least the threshold value * of script instructions, observeInstructionCount() will * be called. */ public final int getInstructionObserverThreshold() { return instructionThreshold; } /** * Set threshold of executed instructions counter that triggers call to * observeInstructionCount(). * When the threshold is zero, instruction counting is disabled, * otherwise each time the run-time executes at least the threshold value * of script instructions, observeInstructionCount() will * be called.

* 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 * threshold 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 setInstructionObserverThreshold(). * The method is useful to observe long running scripts and if necessary * to terminate them. *

* 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 observeInstructionCount * @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; } 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. */ CharArrayWriter writer = new CharArrayWriter(); RuntimeException re = new RuntimeException(); re.printStackTrace(new PrintWriter(writer)); String s = writer.toString(); int open = -1; int close = -1; int colon = -1; for (int i=0; i < s.length(); i++) { char c = s.charAt(i); if (c == ':') colon = i; else if (c == '(') open = i; else if (c == ')') close = i; else if (c == '\n' && open != -1 && close != -1 && colon != -1 && open < colon && colon < close) { String fileStr = s.substring(open + 1, colon); if (!fileStr.endsWith(".java")) { String lineStr = s.substring(colon + 1, close); try { linep[0] = Integer.parseInt(lineStr); if (linep[0] < 0) { linep[0] = 0; } return fileStr; } catch (NumberFormatException e) { // fall through } } open = close = colon = -1; } } 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(); 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); } private static String implementationVersion; private final ContextFactory factory; private boolean sealed; private Object sealKey; Scriptable topCallScope; boolean isContinuationsTopCall; NativeCall currentActivationCall; XMLLib cachedXMLLib; // 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 compileFunctionsWithDynamicScopeFlag; boolean useDynamicScope; private int optimizationLevel; private int maximumInterpreterStackDepth; private WrapFactory wrapFactory; Debugger debugger; private Object debuggerData; private int enterCount; private Object propertyListeners; private Map threadLocalMap; private ClassLoader applicationClassLoader; /** * This is the list of names of objects forcing the creation of * function activation records. */ Set 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; } htmlunit-core-js-2.8/rhino/src/org/mozilla/javascript/JavaMembers.java0000644000175000017500000010764411222455466026003 0ustar cavedoncavedon/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- * * ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is Rhino code, released * May 6, 1999. * * The Initial Developer of the Original Code is * Netscape Communications Corporation. * Portions created by the Initial Developer are Copyright (C) 1997-2000 * the Initial Developer. All Rights Reserved. * * Contributor(s): * Norris Boyd * Cameron McCormack * Frank Mitchell * Mike Shaver * Kurt Westerfeld * * Alternatively, the contents of this file may be used under the terms of * the GNU General Public License Version 2 or later (the "GPL"), in which * case the provisions of the GPL are applicable instead of those above. If * you wish to allow use of your version of this file only under the terms of * the GPL and not to allow others to use your version of this file under the * MPL, indicate your decision by deleting the provisions above and replacing * them with the notice and other provisions required by the GPL. If you do * not delete the provisions above, a recipient may use your version of this * file under either the MPL or the GPL. * * ***** END LICENSE BLOCK ***** */ package org.mozilla.javascript; import java.lang.reflect.*; import java.util.*; /** * * @author Mike Shaver * @author Norris Boyd * @see NativeJavaObject * @see NativeJavaClass */ class JavaMembers { JavaMembers(Scriptable scope, Class cl) { this(scope, cl, false); } JavaMembers(Scriptable scope, Class cl, boolean includeProtected) { try { Context cx = ContextFactory.getGlobal().enterContext(); ClassShutter shutter = cx.getClassShutter(); if (shutter != null && !shutter.visibleToScripts(cl.getName())) { throw Context.reportRuntimeError1("msg.access.prohibited", cl.getName()); } this.includePrivate = cx.hasFeature( Context.FEATURE_ENHANCED_JAVA_ACCESS); this.members = new HashMap(); this.staticMembers = new HashMap(); this.cl = cl; reflect(scope, includeProtected); } finally { Context.exit(); } } boolean has(String name, boolean isStatic) { Map ht = isStatic ? staticMembers : members; Object obj = ht.get(name); if (obj != null) { return true; } return findExplicitFunction(name, isStatic) != null; } Object get(Scriptable scope, String name, Object javaObject, boolean isStatic) { Map ht = isStatic ? staticMembers : members; Object member = ht.get(name); if (!isStatic && member == null) { // Try to get static member from instance (LC3) member = staticMembers.get(name); } if (member == null) { member = this.getExplicitFunction(scope, name, javaObject, isStatic); if (member == null) return Scriptable.NOT_FOUND; } if (member instanceof Scriptable) { return member; } Context cx = Context.getContext(); Object rval; Class type; try { if (member instanceof BeanProperty) { BeanProperty bp = (BeanProperty) member; if (bp.getter == null) return Scriptable.NOT_FOUND; rval = bp.getter.invoke(javaObject, Context.emptyArgs); type = bp.getter.method().getReturnType(); } else { Field field = (Field) member; rval = field.get(isStatic ? null : javaObject); type = field.getType(); } } catch (Exception ex) { throw Context.throwAsScriptRuntimeEx(ex); } // Need to wrap the object before we return it. scope = ScriptableObject.getTopLevelScope(scope); return cx.getWrapFactory().wrap(cx, scope, rval, type); } void put(Scriptable scope, String name, Object javaObject, Object value, boolean isStatic) { Map ht = isStatic ? staticMembers : members; Object member = ht.get(name); if (!isStatic && member == null) { // Try to get static member from instance (LC3) member = staticMembers.get(name); } if (member == null) throw reportMemberNotFound(name); if (member instanceof FieldAndMethods) { FieldAndMethods fam = (FieldAndMethods) ht.get(name); member = fam.field; } // Is this a bean property "set"? if (member instanceof BeanProperty) { BeanProperty bp = (BeanProperty)member; if (bp.setter == null) { throw reportMemberNotFound(name); } // If there's only one setter or if the value is null, use the // main setter. Otherwise, let the NativeJavaMethod decide which // setter to use: if (bp.setters == null || value == null) { Class setType = bp.setter.argTypes[0]; Object[] args = { Context.jsToJava(value, setType) }; try { bp.setter.invoke(javaObject, args); } catch (Exception ex) { throw Context.throwAsScriptRuntimeEx(ex); } } else { Object[] args = { value }; bp.setters.call(Context.getContext(), ScriptableObject.getTopLevelScope(scope), scope, args); } } else { if (!(member instanceof Field)) { String str = (member == null) ? "msg.java.internal.private" : "msg.java.method.assign"; throw Context.reportRuntimeError1(str, name); } Field field = (Field)member; Object javaValue = Context.jsToJava(value, field.getType()); try { field.set(javaObject, javaValue); } catch (IllegalAccessException accessEx) { if ((field.getModifiers() & Modifier.FINAL) != 0) { // treat Java final the same as JavaScript [[READONLY]] return; } throw Context.throwAsScriptRuntimeEx(accessEx); } catch (IllegalArgumentException argEx) { throw Context.reportRuntimeError3( "msg.java.internal.field.type", value.getClass().getName(), field, javaObject.getClass().getName()); } } } Object[] getIds(boolean isStatic) { Map map = isStatic ? staticMembers : members; return map.keySet().toArray(new Object[map.size()]); } static String javaSignature(Class type) { if (!type.isArray()) { return type.getName(); } else { int arrayDimension = 0; do { ++arrayDimension; type = type.getComponentType(); } while (type.isArray()); String name = type.getName(); String suffix = "[]"; if (arrayDimension == 1) { return name.concat(suffix); } else { int length = name.length() + arrayDimension * suffix.length(); StringBuffer sb = new StringBuffer(length); sb.append(name); while (arrayDimension != 0) { --arrayDimension; sb.append(suffix); } return sb.toString(); } } } static String liveConnectSignature(Class[] argTypes) { int N = argTypes.length; if (N == 0) { return "()"; } StringBuffer sb = new StringBuffer(); sb.append('('); for (int i = 0; i != N; ++i) { if (i != 0) { sb.append(','); } sb.append(javaSignature(argTypes[i])); } sb.append(')'); return sb.toString(); } private MemberBox findExplicitFunction(String name, boolean isStatic) { int sigStart = name.indexOf('('); if (sigStart < 0) { return null; } Map ht = isStatic ? staticMembers : members; MemberBox[] methodsOrCtors = null; boolean isCtor = (isStatic && sigStart == 0); if (isCtor) { // Explicit request for an overloaded constructor methodsOrCtors = ctors; } else { // Explicit request for an overloaded method String trueName = name.substring(0,sigStart); Object obj = ht.get(trueName); if (!isStatic && obj == null) { // Try to get static member from instance (LC3) obj = staticMembers.get(trueName); } if (obj instanceof NativeJavaMethod) { NativeJavaMethod njm = (NativeJavaMethod)obj; methodsOrCtors = njm.methods; } } if (methodsOrCtors != null) { for (int i = 0; i < methodsOrCtors.length; i++) { Class[] type = methodsOrCtors[i].argTypes; String sig = liveConnectSignature(type); if (sigStart + sig.length() == name.length() && name.regionMatches(sigStart, sig, 0, sig.length())) { return methodsOrCtors[i]; } } } return null; } private Object getExplicitFunction(Scriptable scope, String name, Object javaObject, boolean isStatic) { Map ht = isStatic ? staticMembers : members; Object member = null; MemberBox methodOrCtor = findExplicitFunction(name, isStatic); if (methodOrCtor != null) { Scriptable prototype = ScriptableObject.getFunctionPrototype(scope); if (methodOrCtor.isCtor()) { NativeJavaConstructor fun = new NativeJavaConstructor(methodOrCtor); fun.setPrototype(prototype); member = fun; ht.put(name, fun); } else { String trueName = methodOrCtor.getName(); member = ht.get(trueName); if (member instanceof NativeJavaMethod && ((NativeJavaMethod)member).methods.length > 1 ) { NativeJavaMethod fun = new NativeJavaMethod(methodOrCtor, name); fun.setPrototype(prototype); ht.put(name, fun); member = fun; } } } return member; } /** * Retrieves mapping of methods to accessible methods for a class. * In case the class is not public, retrieves methods with same * signature as its public methods from public superclasses and * interfaces (if they exist). Basically upcasts every method to the * nearest accessible method. */ private static Method[] discoverAccessibleMethods(Class clazz, boolean includeProtected, boolean includePrivate) { Map map = new HashMap(); discoverAccessibleMethods(clazz, map, includeProtected, includePrivate); return map.values().toArray(new Method[map.size()]); } private static void discoverAccessibleMethods(Class clazz, Map map, boolean includeProtected, boolean includePrivate) { if (Modifier.isPublic(clazz.getModifiers()) || includePrivate) { try { if (includeProtected || includePrivate) { while (clazz != null) { try { Method[] methods = clazz.getDeclaredMethods(); for (int i = 0; i < methods.length; i++) { Method method = methods[i]; int mods = method.getModifiers(); if (Modifier.isPublic(mods) || Modifier.isProtected(mods) || includePrivate) { if (includePrivate) method.setAccessible(true); map.put(new MethodSignature(method), method); } } clazz = clazz.getSuperclass(); } catch (SecurityException e) { // Some security settings (i.e., applets) disallow // access to Class.getDeclaredMethods. Fall back to // Class.getMethods. Method[] methods = clazz.getMethods(); for (int i = 0; i < methods.length; i++) { Method method = methods[i]; MethodSignature sig = new MethodSignature(method); if (map.get(sig) == null) map.put(sig, method); } break; // getMethods gets superclass methods, no // need to loop any more } } } else { Method[] methods = clazz.getMethods(); for (int i = 0; i < methods.length; i++) { Method method = methods[i]; MethodSignature sig = new MethodSignature(method); map.put(sig, method); } } return; } catch (SecurityException e) { Context.reportWarning( "Could not discover accessible methods of class " + clazz.getName() + " due to lack of privileges, " + "attemping superclasses/interfaces."); // Fall through and attempt to discover superclass/interface // methods } } Class[] interfaces = clazz.getInterfaces(); for (int i = 0; i < interfaces.length; i++) { discoverAccessibleMethods(interfaces[i], map, includeProtected, includePrivate); } Class superclass = clazz.getSuperclass(); if (superclass != null) { discoverAccessibleMethods(superclass, map, includeProtected, includePrivate); } } private static final class MethodSignature { private final String name; private final Class[] args; private MethodSignature(String name, Class[] args) { this.name = name; this.args = args; } MethodSignature(Method method) { this(method.getName(), method.getParameterTypes()); } @Override public boolean equals(Object o) { if(o instanceof MethodSignature) { MethodSignature ms = (MethodSignature)o; return ms.name.equals(name) && Arrays.equals(args, ms.args); } return false; } @Override public int hashCode() { return name.hashCode() ^ args.length; } } private void reflect(Scriptable scope, boolean includeProtected) { // We reflect methods first, because we want overloaded field/method // names to be allocated to the NativeJavaMethod before the field // gets in the way. Method[] methods = discoverAccessibleMethods(cl, includeProtected, includePrivate); for (int i = 0; i < methods.length; i++) { Method method = methods[i]; int mods = method.getModifiers(); boolean isStatic = Modifier.isStatic(mods); Map ht = isStatic ? staticMembers : members; String name = method.getName(); Object value = ht.get(name); if (value == null) { ht.put(name, method); } else { ObjArray overloadedMethods; if (value instanceof ObjArray) { overloadedMethods = (ObjArray)value; } else { if (!(value instanceof Method)) Kit.codeBug(); // value should be instance of Method as at this stage // staticMembers and members can only contain methods overloadedMethods = new ObjArray(); overloadedMethods.add(value); ht.put(name, overloadedMethods); } overloadedMethods.add(method); } } // replace Method instances by wrapped NativeJavaMethod objects // first in staticMembers and then in members for (int tableCursor = 0; tableCursor != 2; ++tableCursor) { boolean isStatic = (tableCursor == 0); Map ht = isStatic ? staticMembers : members; for (Map.Entry entry: ht.entrySet()) { MemberBox[] methodBoxes; Object value = entry.getValue(); if (value instanceof Method) { methodBoxes = new MemberBox[1]; methodBoxes[0] = new MemberBox((Method)value); } else { ObjArray overloadedMethods = (ObjArray)value; int N = overloadedMethods.size(); if (N < 2) Kit.codeBug(); methodBoxes = new MemberBox[N]; for (int i = 0; i != N; ++i) { Method method = (Method)overloadedMethods.get(i); methodBoxes[i] = new MemberBox(method); } } NativeJavaMethod fun = new NativeJavaMethod(methodBoxes); if (scope != null) { ScriptRuntime.setFunctionProtoAndParent(fun, scope); } ht.put(entry.getKey(), fun); } } // Reflect fields. Field[] fields = getAccessibleFields(); for (int i = 0; i < fields.length; i++) { Field field = fields[i]; String name = field.getName(); int mods = field.getModifiers(); if (!includePrivate && !Modifier.isPublic(mods)) { continue; } try { boolean isStatic = Modifier.isStatic(mods); Map ht = isStatic ? staticMembers : members; Object member = ht.get(name); if (member == null) { ht.put(name, field); } else if (member instanceof NativeJavaMethod) { NativeJavaMethod method = (NativeJavaMethod) member; FieldAndMethods fam = new FieldAndMethods(scope, method.methods, field); Map fmht = isStatic ? staticFieldAndMethods : fieldAndMethods; if (fmht == null) { fmht = new HashMap(); if (isStatic) { staticFieldAndMethods = fmht; } else { fieldAndMethods = fmht; } } fmht.put(name, fam); ht.put(name, fam); } else if (member instanceof Field) { Field oldField = (Field) member; // If this newly reflected field shadows an inherited field, // then replace it. Otherwise, since access to the field // would be ambiguous from Java, no field should be // reflected. // For now, the first field found wins, unless another field // explicitly shadows it. if (oldField.getDeclaringClass(). isAssignableFrom(field.getDeclaringClass())) { ht.put(name, field); } } else { // "unknown member type" Kit.codeBug(); } } catch (SecurityException e) { // skip this field Context.reportWarning("Could not access field " + name + " of class " + cl.getName() + " due to lack of privileges."); } } // Create bean properties from corresponding get/set methods first for // static members and then for instance members for (int tableCursor = 0; tableCursor != 2; ++tableCursor) { boolean isStatic = (tableCursor == 0); Map ht = isStatic ? staticMembers : members; Map toAdd = new HashMap(); // Now, For each member, make "bean" properties. for (String name: ht.keySet()) { // Is this a getter? boolean memberIsGetMethod = name.startsWith("get"); boolean memberIsSetMethod = name.startsWith("set"); boolean memberIsIsMethod = name.startsWith("is"); if (memberIsGetMethod || memberIsIsMethod || memberIsSetMethod) { // Double check name component. String nameComponent = name.substring(memberIsIsMethod ? 2 : 3); if (nameComponent.length() == 0) continue; // Make the bean property name. String beanPropertyName = nameComponent; char ch0 = nameComponent.charAt(0); if (Character.isUpperCase(ch0)) { if (nameComponent.length() == 1) { beanPropertyName = nameComponent.toLowerCase(); } else { char ch1 = nameComponent.charAt(1); if (!Character.isUpperCase(ch1)) { beanPropertyName = Character.toLowerCase(ch0) +nameComponent.substring(1); } } } // If we already have a member by this name, don't do this // property. if (toAdd.containsKey(beanPropertyName)) continue; Object v = ht.get(beanPropertyName); if (v != null) { // A private field shouldn't mask a public getter/setter if (!includePrivate || !(v instanceof Member) || !Modifier.isPrivate(((Member)v).getModifiers())) { continue; } } // Find the getter method, or if there is none, the is- // method. MemberBox getter = null; getter = findGetter(isStatic, ht, "get", nameComponent); // If there was no valid getter, check for an is- method. if (getter == null) { getter = findGetter(isStatic, ht, "is", nameComponent); } // setter MemberBox setter = null; NativeJavaMethod setters = null; String setterName = "set".concat(nameComponent); if (ht.containsKey(setterName)) { // Is this value a method? Object member = ht.get(setterName); if (member instanceof NativeJavaMethod) { NativeJavaMethod njmSet = (NativeJavaMethod)member; if (getter != null) { // We have a getter. Now, do we have a matching // setter? Class type = getter.method().getReturnType(); setter = extractSetMethod(type, njmSet.methods, isStatic); } else { // No getter, find any set method setter = extractSetMethod(njmSet.methods, isStatic); } if (njmSet.methods.length > 1) { setters = njmSet; } } } // Make the property. BeanProperty bp = new BeanProperty(getter, setter, setters); toAdd.put(beanPropertyName, bp); } } // Add the new bean properties. for (String key: toAdd.keySet()) { Object value = toAdd.get(key); ht.put(key, value); } } // Reflect constructors Constructor[] constructors = getAccessibleConstructors(); ctors = new MemberBox[constructors.length]; for (int i = 0; i != constructors.length; ++i) { ctors[i] = new MemberBox(constructors[i]); } } private Constructor[] getAccessibleConstructors() { // The JVM currently doesn't allow changing access on java.lang.Class // constructors, so don't try if (includePrivate && cl != ScriptRuntime.ClassClass) { try { Constructor[] cons = cl.getDeclaredConstructors(); AccessibleObject.setAccessible(cons, true); return cons; } catch (SecurityException e) { // Fall through to !includePrivate case Context.reportWarning("Could not access constructor " + " of class " + cl.getName() + " due to lack of privileges."); } } return cl.getConstructors(); } private Field[] getAccessibleFields() { if (includePrivate) { try { List fieldsList = new ArrayList(); Class currentClass = cl; while (currentClass != null) { // get all declared fields in this class, make them // accessible, and save Field[] declared = currentClass.getDeclaredFields(); for (int i = 0; i < declared.length; i++) { declared[i].setAccessible(true); fieldsList.add(declared[i]); } // walk up superclass chain. no need to deal specially with // interfaces, since they can't have fields currentClass = currentClass.getSuperclass(); } return fieldsList.toArray(new Field[fieldsList.size()]); } catch (SecurityException e) { // fall through to !includePrivate case } } return cl.getFields(); } private MemberBox findGetter(boolean isStatic, Map ht, String prefix, String propertyName) { String getterName = prefix.concat(propertyName); if (ht.containsKey(getterName)) { // Check that the getter is a method. Object member = ht.get(getterName); if (member instanceof NativeJavaMethod) { NativeJavaMethod njmGet = (NativeJavaMethod) member; return extractGetMethod(njmGet.methods, isStatic); } } return null; } private static MemberBox extractGetMethod(MemberBox[] methods, boolean isStatic) { // Inspect the list of all MemberBox for the only one having no // parameters for (int methodIdx = 0; methodIdx < methods.length; methodIdx++) { MemberBox method = methods[methodIdx]; // Does getter method have an empty parameter list with a return // value (eg. a getSomething() or isSomething())? if (method.argTypes.length == 0 && (!isStatic || method.isStatic())) { Class type = method.method().getReturnType(); if (type != Void.TYPE) { return method; } break; } } return null; } private static MemberBox extractSetMethod(Class type, MemberBox[] methods, boolean isStatic) { // // Note: it may be preferable to allow NativeJavaMethod.findFunction() // to find the appropriate setter; unfortunately, it requires an // instance of the target arg to determine that. // // Make two passes: one to find a method with direct type assignment, // and one to find a widening conversion. for (int pass = 1; pass <= 2; ++pass) { for (int i = 0; i < methods.length; ++i) { MemberBox method = methods[i]; if (!isStatic || method.isStatic()) { Class[] params = method.argTypes; if (params.length == 1) { if (pass == 1) { if (params[0] == type) { return method; } } else { if (pass != 2) Kit.codeBug(); if (params[0].isAssignableFrom(type)) { return method; } } } } } } return null; } private static MemberBox extractSetMethod(MemberBox[] methods, boolean isStatic) { for (int i = 0; i < methods.length; ++i) { MemberBox method = methods[i]; if (!isStatic || method.isStatic()) { if (method.method().getReturnType() == Void.TYPE) { if (method.argTypes.length == 1) { return method; } } } } return null; } Map getFieldAndMethodsObjects(Scriptable scope, Object javaObject, boolean isStatic) { Map ht = isStatic ? staticFieldAndMethods : fieldAndMethods; if (ht == null) return null; int len = ht.size(); Map result = new HashMap(len); for (FieldAndMethods fam: ht.values()) { FieldAndMethods famNew = new FieldAndMethods(scope, fam.methods, fam.field); famNew.javaObject = javaObject; result.put(fam.field.getName(), famNew); } return result; } static JavaMembers lookupClass(Scriptable scope, Class dynamicType, Class staticType, boolean includeProtected) { JavaMembers members; ClassCache cache = ClassCache.get(scope); Map,JavaMembers> ct = cache.getClassCacheMap(); Class cl = dynamicType; for (;;) { members = ct.get(cl); if (members != null) { return members; } try { members = new JavaMembers(cache.getAssociatedScope(), cl, includeProtected); break; } catch (SecurityException e) { // Reflection may fail for objects that are in a restricted // access package (e.g. sun.*). If we get a security // exception, try again with the static type if it is interface. // Otherwise, try superclass if (staticType != null && staticType.isInterface()) { cl = staticType; staticType = null; // try staticType only once } else { Class parent = cl.getSuperclass(); if (parent == null) { if (cl.isInterface()) { // last resort after failed staticType interface parent = ScriptRuntime.ObjectClass; } else { throw e; } } cl = parent; } } } if (cache.isCachingEnabled()) ct.put(cl, members); return members; } RuntimeException reportMemberNotFound(String memberName) { return Context.reportRuntimeError2( "msg.java.member.not.found", cl.getName(), memberName); } private Class cl; private Map members; private Map fieldAndMethods; private Map staticMembers; private Map staticFieldAndMethods; MemberBox[] ctors; private boolean includePrivate; } class BeanProperty { BeanProperty(MemberBox getter, MemberBox setter, NativeJavaMethod setters) { this.getter = getter; this.setter = setter; this.setters = setters; } MemberBox getter; MemberBox setter; NativeJavaMethod setters; } class FieldAndMethods extends NativeJavaMethod { static final long serialVersionUID = -9222428244284796755L; FieldAndMethods(Scriptable scope, MemberBox[] methods, Field field) { super(methods); this.field = field; setParentScope(scope); setPrototype(ScriptableObject.getFunctionPrototype(scope)); } @Override public Object getDefaultValue(Class hint) { if (hint == ScriptRuntime.FunctionClass) return this; Object rval; Class type; try { rval = field.get(javaObject); type = field.getType(); } catch (IllegalAccessException accEx) { throw Context.reportRuntimeError1( "msg.java.internal.private", field.getName()); } Context cx = Context.getContext(); rval = cx.getWrapFactory().wrap(cx, this, rval, type); if (rval instanceof Scriptable) { rval = ((Scriptable) rval).getDefaultValue(hint); } return rval; } Field field; Object javaObject; } htmlunit-core-js-2.8/rhino/src/org/mozilla/javascript/NativeWith.java0000644000175000017500000001376611111044312025647 0ustar cavedoncavedon/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- * * ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is Rhino code, released * May 6, 1999. * * The Initial Developer of the Original Code is * Netscape Communications Corporation. * Portions created by the Initial Developer are Copyright (C) 1997-1999 * the Initial Developer. All Rights Reserved. * * Contributor(s): * Norris Boyd * Igor Bukanov * * Alternatively, the contents of this file may be used under the terms of * the GNU General Public License Version 2 or later (the "GPL"), in which * case the provisions of the GPL are applicable instead of those above. If * you wish to allow use of your version of this file only under the terms of * the GPL and not to allow others to use your version of this file under the * MPL, indicate your decision by deleting the provisions above and replacing * them with the notice and other provisions required by the GPL. If you do * not delete the provisions above, a recipient may use your version of this * file under either the MPL or the GPL. * * ***** END LICENSE BLOCK ***** */ package org.mozilla.javascript; import java.io.Serializable; /** * This class implements the object lookup required for the * with statement. * It simply delegates every action to its prototype except * for operations on its parent. */ public class NativeWith implements Scriptable, IdFunctionCall, Serializable { private static final long serialVersionUID = 1L; static void init(Scriptable scope, boolean sealed) { NativeWith obj = new NativeWith(); obj.setParentScope(scope); obj.setPrototype(ScriptableObject.getObjectPrototype(scope)); IdFunctionObject ctor = new IdFunctionObject(obj, FTAG, Id_constructor, "With", 0, scope); ctor.markAsConstructor(obj); if (sealed) { ctor.sealObject(); } ctor.exportAsScopeProperty(); } private NativeWith() { } protected NativeWith(Scriptable parent, Scriptable prototype) { this.parent = parent; this.prototype = prototype; } public String getClassName() { return "With"; } public boolean has(String id, Scriptable start) { return prototype.has(id, prototype); } public boolean has(int index, Scriptable start) { return prototype.has(index, prototype); } public Object get(String id, Scriptable start) { if (start == this) start = prototype; return prototype.get(id, start); } public Object get(int index, Scriptable start) { if (start == this) start = prototype; return prototype.get(index, start); } public void put(String id, Scriptable start, Object value) { if (start == this) start = prototype; prototype.put(id, start, value); } public void put(int index, Scriptable start, Object value) { if (start == this) start = prototype; prototype.put(index, start, value); } public void delete(String id) { prototype.delete(id); } public void delete(int index) { prototype.delete(index); } public Scriptable getPrototype() { return prototype; } public void setPrototype(Scriptable prototype) { this.prototype = prototype; } public Scriptable getParentScope() { return parent; } public void setParentScope(Scriptable parent) { this.parent = parent; } public Object[] getIds() { return prototype.getIds(); } public Object getDefaultValue(Class typeHint) { return prototype.getDefaultValue(typeHint); } public boolean hasInstance(Scriptable value) { return prototype.hasInstance(value); } /** * Must return null to continue looping or the final collection result. */ protected Object updateDotQuery(boolean value) { // NativeWith itself does not support it throw new IllegalStateException(); } public Object execIdCall(IdFunctionObject f, Context cx, Scriptable scope, Scriptable thisObj, Object[] args) { if (f.hasTag(FTAG)) { if (f.methodId() == Id_constructor) { throw Context.reportRuntimeError1("msg.cant.call.indirect", "With"); } } throw f.unknown(); } static boolean isWithFunction(Object functionObj) { if (functionObj instanceof IdFunctionObject) { IdFunctionObject f = (IdFunctionObject)functionObj; return f.hasTag(FTAG) && f.methodId() == Id_constructor; } return false; } static Object newWithSpecial(Context cx, Scriptable scope, Object[] args) { ScriptRuntime.checkDeprecated(cx, "With"); scope = ScriptableObject.getTopLevelScope(scope); NativeWith thisObj = new NativeWith(); thisObj.setPrototype(args.length == 0 ? ScriptableObject.getClassPrototype(scope, "Object") : ScriptRuntime.toObject(cx, scope, args[0])); thisObj.setParentScope(scope); return thisObj; } private static final Object FTAG = "With"; private static final int Id_constructor = 1; protected Scriptable prototype; protected Scriptable parent; } htmlunit-core-js-2.8/rhino/src/org/mozilla/javascript/Parser.java0000644000175000017500000040046311321335670025030 0ustar cavedoncavedon/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- * * ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is Rhino code, released * May 6, 1999. * * The Initial Developer of the Original Code is * Netscape Communications Corporation. * Portions created by the Initial Developer are Copyright (C) 1997-1999 * the Initial Developer. All Rights Reserved. * * Contributor(s): * Mike Ang * Igor Bukanov * Yuh-Ruey Chen * Ethan Hugg * Bob Jervis * Terry Lucas * Mike McCabe * Milen Nankov * Norris Boyd * Steve Yegge * * Alternatively, the contents of this file may be used under the terms of * the GNU General Public License Version 2 or later (the "GPL"), in which * case the provisions of the GPL are applicable instead of those above. If * you wish to allow use of your version of this file only under the terms of * the GPL and not to allow others to use your version of this file under the * MPL, indicate your decision by deleting the provisions above and replacing * them with the notice and other provisions required by the GPL. If you do * not delete the provisions above, a recipient may use your version of this * file under either the MPL or the GPL. * * ***** END LICENSE BLOCK ***** */ package org.mozilla.javascript; import org.mozilla.javascript.ast.*; // we use basically every class import java.io.BufferedReader; import java.io.IOException; import java.io.Reader; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; import java.util.HashSet; /** * This class implements the JavaScript parser.

* * It is based on the SpiderMonkey C source files jsparse.c and jsparse.h in the * jsref package.

* * The parser generates an {@link AstRoot} parse tree representing the source * code. No tree rewriting is permitted at this stage, so that the parse tree * is a faithful representation of the source for frontend processing tools and * IDEs.

* * This parser implementation is not intended to be reused after a parse * finishes, and will throw an IllegalStateException() if invoked again.

* * @see TokenStream * * @author Mike McCabe * @author Brendan Eich */ public class Parser { /** * Maximum number of allowed function or constructor arguments, * to follow SpiderMonkey. */ public static final int ARGC_LIMIT = 1 << 16; // TokenInformation flags : currentFlaggedToken stores them together // with token type final static int CLEAR_TI_MASK = 0xFFFF, // mask to clear token information bits TI_AFTER_EOL = 1 << 16, // first token of the source line TI_CHECK_LABEL = 1 << 17; // indicates to check for label CompilerEnvirons compilerEnv; private ErrorReporter errorReporter; private IdeErrorReporter errorCollector; private String sourceURI; private char[] sourceChars; boolean calledByCompileFunction; // ugly - set directly by Context private boolean parseFinished; // set when finished to prevent reuse private TokenStream ts; private int currentFlaggedToken = Token.EOF; private int currentToken; private int syntaxErrorCount; private List scannedComments; private String currentJsDocComment; protected int nestingOfFunction; private LabeledStatement currentLabel; private boolean inDestructuringAssignment; protected boolean inUseStrictDirective; // The following are per function variables and should be saved/restored // during function parsing. See PerFunctionVariables class below. ScriptNode currentScriptOrFn; Scope currentScope; int nestingOfWith; private int endFlags; private boolean inForInit; // bound temporarily during forStatement() private Map labelSet; private List loopSet; private List loopAndSwitchSet; // end of per function variables // Lacking 2-token lookahead, labels become a problem. // These vars store the token info of the last matched name, // iff it wasn't the last matched token. private int prevNameTokenStart; private String prevNameTokenString = ""; private int prevNameTokenLineno; // Exception to unwind private static class ParserException extends RuntimeException { static final long serialVersionUID = 5882582646773765630L; } public Parser() { this(new CompilerEnvirons()); } public Parser(CompilerEnvirons compilerEnv) { this(compilerEnv, compilerEnv.getErrorReporter()); } public Parser(CompilerEnvirons compilerEnv, ErrorReporter errorReporter) { this.compilerEnv = compilerEnv; this.errorReporter = errorReporter; if (errorReporter instanceof IdeErrorReporter) { errorCollector = (IdeErrorReporter)errorReporter; } } // Add a strict warning on the last matched token. void addStrictWarning(String messageId, String messageArg) { int beg = -1, end = -1; if (ts != null) { beg = ts.tokenBeg; end = ts.tokenEnd - ts.tokenBeg; } addStrictWarning(messageId, messageArg, beg, end); } void addStrictWarning(String messageId, String messageArg, int position, int length) { if (compilerEnv.isStrictMode()) addWarning(messageId, messageArg, position, length); } void addWarning(String messageId, String messageArg) { int beg = -1, end = -1; if (ts != null) { beg = ts.tokenBeg; end = ts.tokenEnd - ts.tokenBeg; } addWarning(messageId, messageArg, beg, end); } void addWarning(String messageId, int position, int length) { addWarning(messageId, null, position, length); } void addWarning(String messageId, String messageArg, int position, int length) { String message = lookupMessage(messageId, messageArg); if (compilerEnv.reportWarningAsError()) { addError(messageId, messageArg, position, length); } else if (errorCollector != null) { errorCollector.warning(message, sourceURI, position, length); } else { errorReporter.warning(message, sourceURI, ts.getLineno(), ts.getLine(), ts.getOffset()); } } void addError(String messageId) { addError(messageId, ts.tokenBeg, ts.tokenEnd - ts.tokenBeg); } void addError(String messageId, int position, int length) { addError(messageId, null, position, length); } void addError(String messageId, String messageArg) { addError(messageId, messageArg, ts.tokenBeg, ts.tokenEnd - ts.tokenBeg); } void addError(String messageId, String messageArg, int position, int length) { ++syntaxErrorCount; String message = lookupMessage(messageId, messageArg); if (errorCollector != null) { errorCollector.error(message, sourceURI, position, length); } else { int lineno = 1, offset = 1; String line = ""; if (ts != null) { // happens in some regression tests lineno = ts.getLineno(); line = ts.getLine(); offset = ts.getOffset(); } errorReporter.error(message, sourceURI, lineno, line, offset); } } String lookupMessage(String messageId) { return lookupMessage(messageId, null); } String lookupMessage(String messageId, String messageArg) { return messageArg == null ? ScriptRuntime.getMessage0(messageId) : ScriptRuntime.getMessage1(messageId, messageArg); } void reportError(String messageId) { reportError(messageId, null); } void reportError(String messageId, String messageArg) { if (ts == null) { // happens in some regression tests reportError(messageId, messageArg, 1, 1); } else { reportError(messageId, messageArg, ts.tokenBeg, ts.tokenEnd - ts.tokenBeg); } } void reportError(String messageId, int position, int length) { reportError(messageId, null, position, length); } void reportError(String messageId, String messageArg, int position, int length) { addError(messageId, position, length); if (!compilerEnv.recoverFromErrors()) { throw new ParserException(); } } // Computes the absolute end offset of node N. // Use with caution! Assumes n.getPosition() is -absolute-, which // is only true before the node is added to its parent. private int getNodeEnd(AstNode n) { return n.getPosition() + n.getLength(); } private void recordComment(int lineno) { if (scannedComments == null) { scannedComments = new ArrayList(); } String comment = ts.getAndResetCurrentComment(); if (ts.commentType == Token.CommentType.JSDOC && compilerEnv.isRecordingLocalJsDocComments()) { currentJsDocComment = comment; } Comment commentNode = new Comment(ts.tokenBeg, ts.getTokenLength(), ts.commentType, comment); commentNode.setLineno(lineno); scannedComments.add(commentNode); } private String getAndResetJsDoc() { String saved = currentJsDocComment; currentJsDocComment = null; return saved; } // Returns the next token without consuming it. // If previous token was consumed, calls scanner to get new token. // If previous token was -not- consumed, returns it (idempotent). // // This function will not return a newline (Token.EOL - instead, it // gobbles newlines until it finds a non-newline token, and flags // that token as appearing just after a newline. // // This function will also not return a Token.COMMENT. Instead, it // records comments in the scannedComments list. If the token // returned by this function immediately follows a jsdoc comment, // the token is flagged as such. // // Note that this function always returned the un-flagged token! // The flags, if any, are saved in currentFlaggedToken. private int peekToken() throws IOException { // By far the most common case: last token hasn't been consumed, // so return already-peeked token. if (currentFlaggedToken != Token.EOF) { return currentToken; } int lineno = ts.getLineno(); int tt = ts.getToken(); boolean sawEOL = false; // process comments and whitespace while (tt == Token.EOL || tt == Token.COMMENT) { if (tt == Token.EOL) { lineno++; sawEOL = true; } else { sawEOL = false; if (compilerEnv.isRecordingComments()) { recordComment(lineno); } } tt = ts.getToken(); } currentToken = tt; currentFlaggedToken = tt | (sawEOL ? TI_AFTER_EOL : 0); return currentToken; // return unflagged token } private int peekFlaggedToken() throws IOException { peekToken(); return currentFlaggedToken; } private void consumeToken() { currentFlaggedToken = Token.EOF; } private int nextToken() throws IOException { int tt = peekToken(); consumeToken(); return tt; } private int nextFlaggedToken() throws IOException { peekToken(); int ttFlagged = currentFlaggedToken; consumeToken(); return ttFlagged; } private boolean matchToken(int toMatch) throws IOException { if (peekToken() != toMatch) { return false; } consumeToken(); return true; } // Returns Token.EOL if the current token follows a newline, else returns // the current token. Used in situations where we don't consider certain // token types valid if they are preceded by a newline. One example is the // postfix ++ or -- operator, which has to be on the same line as its // operand. private int peekTokenOrEOL() throws IOException { int tt = peekToken(); // Check for last peeked token flags if ((currentFlaggedToken & TI_AFTER_EOL) != 0) { tt = Token.EOL; } return tt; } private boolean mustMatchToken(int toMatch, String messageId) throws IOException { return mustMatchToken(toMatch, messageId, ts.tokenBeg, ts.tokenEnd - ts.tokenBeg); } private boolean mustMatchToken(int toMatch, String msgId, int pos, int len) throws IOException { if (matchToken(toMatch)) { return true; } reportError(msgId, pos, len); return false; } private void mustHaveXML() { if (!compilerEnv.isXmlAvailable()) { reportError("msg.XML.not.available"); } } public boolean eof() { return ts.eof(); } boolean insideFunction() { return nestingOfFunction != 0; } void pushScope(Scope scope) { Scope parent = scope.getParentScope(); // During codegen, parent scope chain may already be initialized, // in which case we just need to set currentScope variable. if (parent != null) { if (parent != currentScope) codeBug(); } else { currentScope.addChildScope(scope); } currentScope = scope; } void popScope() { currentScope = currentScope.getParentScope(); } private void enterLoop(Loop loop) { if (loopSet == null) loopSet = new ArrayList(); loopSet.add(loop); if (loopAndSwitchSet == null) loopAndSwitchSet = new ArrayList(); loopAndSwitchSet.add(loop); pushScope(loop); if (currentLabel != null) { currentLabel.setStatement(loop); currentLabel.getFirstLabel().setLoop(loop); // This is the only time during parsing that we set a node's parent // before parsing the children. In order for the child node offsets // to be correct, we adjust the loop's reported position back to an // absolute source offset, and restore it when we call exitLoop(). loop.setRelative(-currentLabel.getPosition()); } } private void exitLoop() { Loop loop = loopSet.remove(loopSet.size() - 1); loopAndSwitchSet.remove(loopAndSwitchSet.size() - 1); if (loop.getParent() != null) { // see comment in enterLoop loop.setRelative(loop.getParent().getPosition()); } popScope(); } private void enterSwitch(SwitchStatement node) { if (loopAndSwitchSet == null) loopAndSwitchSet = new ArrayList(); loopAndSwitchSet.add(node); } private void exitSwitch() { loopAndSwitchSet.remove(loopAndSwitchSet.size() - 1); } /** * Builds a parse tree from the given source string. * * @return an {@link AstRoot} object representing the parsed program. If * the parse fails, {@code null} will be returned. (The parse failure will * result in a call to the {@link ErrorReporter} from * {@link CompilerEnvirons}.) */ public AstRoot parse(String sourceString, String sourceURI, int lineno) { if (parseFinished) throw new IllegalStateException("parser reused"); this.sourceURI = sourceURI; if (compilerEnv.isIdeMode()) { this.sourceChars = sourceString.toCharArray(); } this.ts = new TokenStream(this, null, sourceString, lineno); try { return parse(); } catch (IOException iox) { // Should never happen throw new IllegalStateException(); } finally { parseFinished = true; } } /** * Builds a parse tree from the given sourcereader. * @see #parse(String,String,int) * @throws IOException if the {@link Reader} encounters an error */ public AstRoot parse(Reader sourceReader, String sourceURI, int lineno) throws IOException { if (parseFinished) throw new IllegalStateException("parser reused"); if (compilerEnv.isIdeMode()) { return parse(readFully(sourceReader), sourceURI, lineno); } try { this.sourceURI = sourceURI; ts = new TokenStream(this, sourceReader, null, lineno); return parse(); } finally { parseFinished = true; } } private AstRoot parse() throws IOException { int pos = 0; AstRoot root = new AstRoot(pos); currentScope = currentScriptOrFn = root; int baseLineno = ts.lineno; // line number where source starts int end = pos; // in case source is empty boolean inDirectivePrologue = true; boolean savedStrictMode = inUseStrictDirective; // TODO: eval code should get strict mode from invoking code inUseStrictDirective = false; try { for (;;) { int tt = peekToken(); if (tt <= Token.EOF) { break; } AstNode n; if (tt == Token.FUNCTION) { consumeToken(); try { n = function(calledByCompileFunction ? FunctionNode.FUNCTION_EXPRESSION : FunctionNode.FUNCTION_STATEMENT); } catch (ParserException e) { break; } } else { n = statement(); if (inDirectivePrologue) { String directive = getDirective(n); if (directive == null) { inDirectivePrologue = false; } else if (directive.equals("use strict")) { inUseStrictDirective = true; root.setInStrictMode(true); } } } end = getNodeEnd(n); root.addChildToBack(n); n.setParent(root); } } catch (StackOverflowError ex) { String msg = lookupMessage("msg.too.deep.parser.recursion"); if (!compilerEnv.isIdeMode()) throw Context.reportRuntimeError(msg, sourceURI, ts.lineno, null, 0); } finally { inUseStrictDirective = savedStrictMode; } if (this.syntaxErrorCount != 0) { String msg = String.valueOf(this.syntaxErrorCount); msg = lookupMessage("msg.got.syntax.errors", msg); if (!compilerEnv.isIdeMode()) throw errorReporter.runtimeError(msg, sourceURI, baseLineno, null, 0); } // add comments to root in lexical order if (scannedComments != null) { // If we find a comment beyond end of our last statement or // function, extend the root bounds to the end of that comment. int last = scannedComments.size() - 1; end = Math.max(end, getNodeEnd(scannedComments.get(last))); for (Comment c : scannedComments) { root.addComment(c); } } root.setLength(end - pos); root.setSourceName(sourceURI); root.setBaseLineno(baseLineno); root.setEndLineno(ts.lineno); return root; } private AstNode parseFunctionBody() throws IOException { if (!matchToken(Token.LC)) { if (compilerEnv.getLanguageVersion() < Context.VERSION_1_8) { reportError("msg.no.brace.body"); } return parseFunctionBodyExpr(); } ++nestingOfFunction; int pos = ts.tokenBeg; Block pn = new Block(pos); // starts at LC position boolean inDirectivePrologue = true; boolean savedStrictMode = inUseStrictDirective; // Don't set 'inUseStrictDirective' to false: inherit strict mode. pn.setLineno(ts.lineno); try { bodyLoop: for (;;) { AstNode n; int tt = peekToken(); switch (tt) { case Token.ERROR: case Token.EOF: case Token.RC: break bodyLoop; case Token.FUNCTION: consumeToken(); n = function(FunctionNode.FUNCTION_STATEMENT); break; default: n = statement(); if (inDirectivePrologue) { String directive = getDirective(n); if (directive == null) { inDirectivePrologue = false; } else if (directive.equals("use strict")) { inUseStrictDirective = true; } } break; } pn.addStatement(n); } } catch (ParserException e) { // Ignore it } finally { --nestingOfFunction; inUseStrictDirective = savedStrictMode; } int end = ts.tokenEnd; getAndResetJsDoc(); if (mustMatchToken(Token.RC, "msg.no.brace.after.body")) end = ts.tokenEnd; pn.setLength(end - pos); return pn; } private String getDirective(AstNode n) { if (n instanceof ExpressionStatement) { AstNode e = ((ExpressionStatement) n).getExpression(); if (e instanceof StringLiteral) { return ((StringLiteral) e).getValue(); } } return null; } private void parseFunctionParams(FunctionNode fnNode) throws IOException { if (matchToken(Token.RP)) { fnNode.setRp(ts.tokenBeg - fnNode.getPosition()); return; } // Would prefer not to call createDestructuringAssignment until codegen, // but the symbol definitions have to happen now, before body is parsed. Map destructuring = null; Set paramNames = new HashSet(); do { int tt = peekToken(); if (tt == Token.LB || tt == Token.LC) { AstNode expr = destructuringPrimaryExpr(); markDestructuring(expr); fnNode.addParam(expr); // Destructuring assignment for parameters: add a dummy // parameter name, and add a statement to the body to initialize // variables from the destructuring assignment if (destructuring == null) { destructuring = new HashMap(); } String pname = currentScriptOrFn.getNextTempName(); defineSymbol(Token.LP, pname, false); destructuring.put(pname, expr); } else { if (mustMatchToken(Token.NAME, "msg.no.parm")) { fnNode.addParam(createNameNode()); String paramName = ts.getString(); defineSymbol(Token.LP, paramName); if (this.inUseStrictDirective) { if ("eval".equals(paramName) || "arguments".equals(paramName)) { reportError("msg.bad.id.strict", paramName); } if (paramNames.contains(paramName)) addError("msg.dup.param.strict", paramName); paramNames.add(paramName); } } else { fnNode.addParam(makeErrorNode()); } } } while (matchToken(Token.COMMA)); if (destructuring != null) { Node destructuringNode = new Node(Token.COMMA); // Add assignment helper for each destructuring parameter for (Map.Entry param: destructuring.entrySet()) { Node assign = createDestructuringAssignment(Token.VAR, param.getValue(), createName(param.getKey())); destructuringNode.addChildToBack(assign); } fnNode.putProp(Node.DESTRUCTURING_PARAMS, destructuringNode); } if (mustMatchToken(Token.RP, "msg.no.paren.after.parms")) { fnNode.setRp(ts.tokenBeg - fnNode.getPosition()); } } private AstNode parseFunctionBodyExpr() throws IOException { ++nestingOfFunction; int lineno = ts.getLineno(); ReturnStatement n = new ReturnStatement(lineno); n.putProp(Node.EXPRESSION_CLOSURE_PROP, Boolean.TRUE); try { n.setReturnValue(assignExpr()); } finally { --nestingOfFunction; } return n; } private FunctionNode function(int type) throws IOException { int syntheticType = type; int baseLineno = ts.lineno; // line number where source starts int functionSourceStart = ts.tokenBeg; // start of "function" kwd Name name = null; AstNode memberExprNode = null; if (matchToken(Token.NAME)) { name = createNameNode(true, Token.NAME); if (inUseStrictDirective) { String id = name.getIdentifier(); if ("eval".equals(id)|| "arguments".equals(id)) { reportError("msg.bad.id.strict", id); } } if (!matchToken(Token.LP)) { if (compilerEnv.isAllowMemberExprAsFunctionName()) { AstNode memberExprHead = name; name = null; memberExprNode = memberExprTail(false, memberExprHead); } mustMatchToken(Token.LP, "msg.no.paren.parms"); } } else if (matchToken(Token.LP)) { // Anonymous function: leave name as null } else { if (compilerEnv.isAllowMemberExprAsFunctionName()) { // Note that memberExpr can not start with '(' like // in function (1+2).toString(), because 'function (' already // processed as anonymous function memberExprNode = memberExpr(false); } mustMatchToken(Token.LP, "msg.no.paren.parms"); } int lpPos = currentToken == Token.LP ? ts.tokenBeg : -1; if (memberExprNode != null) { syntheticType = FunctionNode.FUNCTION_EXPRESSION; } if (syntheticType != FunctionNode.FUNCTION_EXPRESSION && name != null && name.length() > 0) { // Function statements define a symbol in the enclosing scope defineSymbol(Token.FUNCTION, name.getIdentifier()); } FunctionNode fnNode = new FunctionNode(functionSourceStart, name); fnNode.setFunctionType(type); if (lpPos != -1) fnNode.setLp(lpPos - functionSourceStart); if (insideFunction() || nestingOfWith > 0) { // 1. Nested functions are not affected by the dynamic scope flag // as dynamic scope is already a parent of their scope. // 2. Functions defined under the with statement also immune to // this setup, in which case dynamic scope is ignored in favor // of the with object. fnNode.setIgnoreDynamicScope(); } fnNode.setJsDoc(getAndResetJsDoc()); PerFunctionVariables savedVars = new PerFunctionVariables(fnNode); try { parseFunctionParams(fnNode); fnNode.setBody(parseFunctionBody()); fnNode.setEncodedSourceBounds(functionSourceStart, ts.tokenEnd); fnNode.setLength(ts.tokenEnd - functionSourceStart); if (compilerEnv.isStrictMode() && !fnNode.getBody().hasConsistentReturnUsage()) { String msg = (name != null && name.length() > 0) ? "msg.no.return.value" : "msg.anon.no.return.value"; addStrictWarning(msg, name.getIdentifier()); } // Function expressions define a name only in the body of the // function, and only if not hidden by a parameter name if (syntheticType == FunctionNode.FUNCTION_EXPRESSION && name != null && name.length() > 0 && currentScope.getSymbol(name.getIdentifier()) == null) { defineSymbol(Token.FUNCTION, name.getIdentifier()); } } finally { savedVars.restore(); } if (memberExprNode != null) { // TODO(stevey): fix missing functionality Kit.codeBug(); fnNode.setMemberExprNode(memberExprNode); // rewrite later /* old code: if (memberExprNode != null) { pn = nf.createAssignment(Token.ASSIGN, memberExprNode, pn); if (functionType != FunctionNode.FUNCTION_EXPRESSION) { // XXX check JScript behavior: should it be createExprStatement? pn = nf.createExprStatementNoReturn(pn, baseLineno); } } */ } fnNode.setSourceName(sourceURI); fnNode.setBaseLineno(baseLineno); fnNode.setEndLineno(ts.lineno); // Set the parent scope. Needed for finding undeclared vars. // Have to wait until after parsing the function to set its parent // scope, since defineSymbol needs the defining-scope check to stop // at the function boundary when checking for redeclarations. if (compilerEnv.isIdeMode()) { fnNode.setParentScope(currentScope); } return fnNode; } // This function does not match the closing RC: the caller matches // the RC so it can provide a suitable error message if not matched. // This means it's up to the caller to set the length of the node to // include the closing RC. The node start pos is set to the // absolute buffer start position, and the caller should fix it up // to be relative to the parent node. All children of this block // node are given relative start positions and correct lengths. private AstNode statements(AstNode parent) throws IOException { if (currentToken != Token.LC // assertion can be invalid in bad code && !compilerEnv.isIdeMode()) codeBug(); int pos = ts.tokenBeg; AstNode block = parent != null ? parent : new Block(pos); block.setLineno(ts.lineno); int tt; while ((tt = peekToken()) > Token.EOF && tt != Token.RC) { block.addChild(statement()); } block.setLength(ts.tokenBeg - pos); return block; } private AstNode statements() throws IOException { return statements(null); } private static class ConditionData { AstNode condition; int lp = -1; int rp = -1; } // parse and return a parenthesized expression private ConditionData condition() throws IOException { ConditionData data = new ConditionData(); if (mustMatchToken(Token.LP, "msg.no.paren.cond")) data.lp = ts.tokenBeg; data.condition = expr(); if (mustMatchToken(Token.RP, "msg.no.paren.after.cond")) data.rp = ts.tokenBeg; // Report strict warning on code like "if (a = 7) ...". Suppress the // warning if the condition is parenthesized, like "if ((a = 7)) ...". if (data.condition instanceof Assignment) { addStrictWarning("msg.equal.as.assign", "", data.condition.getPosition(), data.condition.getLength()); } return data; } private AstNode statement() throws IOException { int pos = ts.tokenBeg; try { AstNode pn = statementHelper(); if (pn != null) { if (compilerEnv.isStrictMode() && !pn.hasSideEffects()) { int beg = pn.getPosition(); beg = Math.max(beg, lineBeginningFor(beg)); addStrictWarning(pn instanceof EmptyExpression ? "msg.extra.trailing.semi" : "msg.no.side.effects", "", beg, nodeEnd(pn) - beg); } return pn; } } catch (ParserException e) { // an ErrorNode was added to the ErrorReporter } // error: skip ahead to a probable statement boundary guessingStatementEnd: for (;;) { int tt = peekTokenOrEOL(); consumeToken(); switch (tt) { case Token.ERROR: case Token.EOF: case Token.EOL: case Token.SEMI: break guessingStatementEnd; } } // We don't make error nodes explicitly part of the tree; // they get added to the ErrorReporter. May need to do // something different here. return new EmptyExpression(pos, ts.tokenBeg - pos); } private AstNode statementHelper() throws IOException { // If the statement is set, then it's been told its label by now. if (currentLabel != null && currentLabel.getStatement() != null) currentLabel = null; AstNode pn = null; int tt = peekToken(), pos = ts.tokenBeg; switch (tt) { case Token.IF: return ifStatement(); case Token.SWITCH: return switchStatement(); case Token.WHILE: return whileLoop(); case Token.DO: return doLoop(); case Token.FOR: return forLoop(); case Token.TRY: return tryStatement(); case Token.THROW: pn = throwStatement(); break; case Token.BREAK: pn = breakStatement(); break; case Token.CONTINUE: pn = continueStatement(); break; case Token.WITH: if (this.inUseStrictDirective) { reportError("msg.no.with.strict"); } return withStatement(); case Token.CONST: case Token.VAR: consumeToken(); int lineno = ts.lineno; pn = variables(currentToken, ts.tokenBeg); pn.setLineno(lineno); break; case Token.LET: pn = letStatement(); if (pn instanceof VariableDeclaration && peekToken() == Token.SEMI) break; return pn; case Token.RETURN: case Token.YIELD: pn = returnOrYield(tt, false); break; case Token.DEBUGGER: consumeToken(); pn = new KeywordLiteral(ts.tokenBeg, ts.tokenEnd - ts.tokenBeg, tt); pn.setLineno(ts.lineno); break; case Token.LC: return block(); case Token.ERROR: consumeToken(); return makeErrorNode(); case Token.SEMI: consumeToken(); pos = ts.tokenBeg; pn = new EmptyExpression(pos, ts.tokenEnd - pos); pn.setLineno(ts.lineno); return pn; case Token.FUNCTION: consumeToken(); return function(FunctionNode.FUNCTION_EXPRESSION_STATEMENT); case Token.DEFAULT : pn = defaultXmlNamespace(); break; case Token.NAME: pn = nameOrLabel(); if (pn instanceof ExpressionStatement) break; return pn; // LabeledStatement default: lineno = ts.lineno; pn = new ExpressionStatement(expr(), !insideFunction()); pn.setLineno(lineno); break; } autoInsertSemicolon(pn); return pn; } private void autoInsertSemicolon(AstNode pn) throws IOException { int ttFlagged = peekFlaggedToken(); int pos = pn.getPosition(); switch (ttFlagged & CLEAR_TI_MASK) { case Token.SEMI: // Consume ';' as a part of expression consumeToken(); // extend the node bounds to include the semicolon. pn.setLength(ts.tokenEnd - pos); break; case Token.ERROR: case Token.EOF: case Token.RC: // Autoinsert ; warnMissingSemi(pos, nodeEnd(pn)); break; default: if ((ttFlagged & TI_AFTER_EOL) == 0) { // Report error if no EOL or autoinsert ; otherwise reportError("msg.no.semi.stmt"); } else { warnMissingSemi(pos, nodeEnd(pn)); } break; } } private IfStatement ifStatement() throws IOException { if (currentToken != Token.IF) codeBug(); consumeToken(); int pos = ts.tokenBeg, lineno = ts.lineno, elsePos = -1; ConditionData data = condition(); AstNode ifTrue = statement(), ifFalse = null; if (matchToken(Token.ELSE)) { elsePos = ts.tokenBeg - pos; ifFalse = statement(); } int end = getNodeEnd(ifFalse != null ? ifFalse : ifTrue); IfStatement pn = new IfStatement(pos, end - pos); pn.setCondition(data.condition); pn.setParens(data.lp - pos, data.rp - pos); pn.setThenPart(ifTrue); pn.setElsePart(ifFalse); pn.setElsePosition(elsePos); pn.setLineno(lineno); return pn; } private SwitchStatement switchStatement() throws IOException { if (currentToken != Token.SWITCH) codeBug(); consumeToken(); int pos = ts.tokenBeg; SwitchStatement pn = new SwitchStatement(pos); if (mustMatchToken(Token.LP, "msg.no.paren.switch")) pn.setLp(ts.tokenBeg - pos); pn.setLineno(ts.lineno); AstNode discriminant = expr(); pn.setExpression(discriminant); enterSwitch(pn); try { if (mustMatchToken(Token.RP, "msg.no.paren.after.switch")) pn.setRp(ts.tokenBeg - pos); mustMatchToken(Token.LC, "msg.no.brace.switch"); boolean hasDefault = false; int tt; switchLoop: for (;;) { tt = nextToken(); int casePos = ts.tokenBeg; int caseLineno = ts.lineno; AstNode caseExpression = null; switch (tt) { case Token.RC: pn.setLength(ts.tokenEnd - pos); break switchLoop; case Token.CASE: caseExpression = expr(); mustMatchToken(Token.COLON, "msg.no.colon.case"); break; case Token.DEFAULT: if (hasDefault) { reportError("msg.double.switch.default"); } hasDefault = true; caseExpression = null; mustMatchToken(Token.COLON, "msg.no.colon.case"); break; default: reportError("msg.bad.switch"); break switchLoop; } SwitchCase caseNode = new SwitchCase(casePos); caseNode.setExpression(caseExpression); caseNode.setLength(ts.tokenEnd - pos); // include colon caseNode.setLineno(caseLineno); while ((tt = peekToken()) != Token.RC && tt != Token.CASE && tt != Token.DEFAULT && tt != Token.EOF) { caseNode.addStatement(statement()); // updates length } pn.addCase(caseNode); } } finally { exitSwitch(); } return pn; } private WhileLoop whileLoop() throws IOException { if (currentToken != Token.WHILE) codeBug(); consumeToken(); int pos = ts.tokenBeg; WhileLoop pn = new WhileLoop(pos); pn.setLineno(ts.lineno); enterLoop(pn); try { ConditionData data = condition(); pn.setCondition(data.condition); pn.setParens(data.lp - pos, data.rp - pos); AstNode body = statement(); pn.setLength(getNodeEnd(body) - pos); pn.setBody(body); } finally { exitLoop(); } return pn; } private DoLoop doLoop() throws IOException { if (currentToken != Token.DO) codeBug(); consumeToken(); int pos = ts.tokenBeg, end; DoLoop pn = new DoLoop(pos); pn.setLineno(ts.lineno); enterLoop(pn); try { AstNode body = statement(); mustMatchToken(Token.WHILE, "msg.no.while.do"); pn.setWhilePosition(ts.tokenBeg - pos); ConditionData data = condition(); pn.setCondition(data.condition); pn.setParens(data.lp - pos, data.rp - pos); end = getNodeEnd(body); pn.setBody(body); } finally { exitLoop(); } // Always auto-insert semicolon to follow SpiderMonkey: // It is required by ECMAScript but is ignored by the rest of // world, see bug 238945 if (matchToken(Token.SEMI)) { end = ts.tokenEnd; } pn.setLength(end - pos); return pn; } private Loop forLoop() throws IOException { if (currentToken != Token.FOR) codeBug(); consumeToken(); int forPos = ts.tokenBeg, lineno = ts.lineno; boolean isForEach = false, isForIn = false; int eachPos = -1, inPos = -1, lp = -1, rp = -1; AstNode init = null; // init is also foo in 'foo in object' AstNode cond = null; // cond is also object in 'foo in object' AstNode incr = null; Loop pn = null; Scope tempScope = new Scope(); pushScope(tempScope); // decide below what AST class to use try { // See if this is a for each () instead of just a for () if (matchToken(Token.NAME)) { if ("each".equals(ts.getString())) { isForEach = true; eachPos = ts.tokenBeg - forPos; } else { reportError("msg.no.paren.for"); } } if (mustMatchToken(Token.LP, "msg.no.paren.for")) lp = ts.tokenBeg - forPos; int tt = peekToken(); init = forLoopInit(tt); if (matchToken(Token.IN)) { isForIn = true; inPos = ts.tokenBeg - forPos; cond = expr(); // object over which we're iterating } else { // ordinary for-loop mustMatchToken(Token.SEMI, "msg.no.semi.for"); if (peekToken() == Token.SEMI) { // no loop condition cond = new EmptyExpression(ts.tokenBeg, 1); cond.setLineno(ts.lineno); } else { cond = expr(); } mustMatchToken(Token.SEMI, "msg.no.semi.for.cond"); int tmpPos = ts.tokenEnd; if (peekToken() == Token.RP) { incr = new EmptyExpression(tmpPos, 1); incr.setLineno(ts.lineno); } else { incr = expr(); } } if (mustMatchToken(Token.RP, "msg.no.paren.for.ctrl")) rp = ts.tokenBeg - forPos; if (isForIn) { ForInLoop fis = new ForInLoop(forPos); if (init instanceof VariableDeclaration) { // check that there was only one variable given if (((VariableDeclaration)init).getVariables().size() > 1) { reportError("msg.mult.index"); } } fis.setIterator(init); fis.setIteratedObject(cond); fis.setInPosition(inPos); fis.setIsForEach(isForEach); fis.setEachPosition(eachPos); pn = fis; } else { ForLoop fl = new ForLoop(forPos); fl.setInitializer(init); fl.setCondition(cond); fl.setIncrement(incr); pn = fl; } // replace temp scope with the new loop object currentScope.replaceWith(pn); popScope(); // We have to parse the body -after- creating the loop node, // so that the loop node appears in the loopSet, allowing // break/continue statements to find the enclosing loop. enterLoop(pn); try { AstNode body = statement(); pn.setLength(getNodeEnd(body) - forPos); pn.setBody(body); } finally { exitLoop(); } } finally { if (currentScope == tempScope) { popScope(); } } pn.setParens(lp, rp); pn.setLineno(lineno); return pn; } private AstNode forLoopInit(int tt) throws IOException { try { inForInit = true; // checked by variables() and relExpr() AstNode init = null; if (tt == Token.SEMI) { init = new EmptyExpression(ts.tokenBeg, 1); init.setLineno(ts.lineno); } else if (tt == Token.VAR || tt == Token.LET) { consumeToken(); init = variables(tt, ts.tokenBeg); } else { init = expr(); markDestructuring(init); } return init; } finally { inForInit = false; } } private TryStatement tryStatement() throws IOException { if (currentToken != Token.TRY) codeBug(); consumeToken(); // Pull out JSDoc info and reset it before recursing. String jsdoc = getAndResetJsDoc(); int tryPos = ts.tokenBeg, lineno = ts.lineno, finallyPos = -1; if (peekToken() != Token.LC) { reportError("msg.no.brace.try"); } AstNode tryBlock = statement(); int tryEnd = getNodeEnd(tryBlock); List clauses = null; boolean sawDefaultCatch = false; int peek = peekToken(); if (peek == Token.CATCH) { while (matchToken(Token.CATCH)) { int catchLineNum = ts.lineno; if (sawDefaultCatch) { reportError("msg.catch.unreachable"); } int catchPos = ts.tokenBeg, lp = -1, rp = -1, guardPos = -1; if (mustMatchToken(Token.LP, "msg.no.paren.catch")) lp = ts.tokenBeg; mustMatchToken(Token.NAME, "msg.bad.catchcond"); Name varName = createNameNode(); String varNameString = varName.getIdentifier(); if (inUseStrictDirective) { if ("eval".equals(varNameString) || "arguments".equals(varNameString)) { reportError("msg.bad.id.strict", varNameString); } } AstNode catchCond = null; if (matchToken(Token.IF)) { guardPos = ts.tokenBeg; catchCond = expr(); } else { sawDefaultCatch = true; } if (mustMatchToken(Token.RP, "msg.bad.catchcond")) rp = ts.tokenBeg; mustMatchToken(Token.LC, "msg.no.brace.catchblock"); Block catchBlock = (Block)statements(); tryEnd = getNodeEnd(catchBlock); CatchClause catchNode = new CatchClause(catchPos); catchNode.setVarName(varName); catchNode.setCatchCondition(catchCond); catchNode.setBody(catchBlock); if (guardPos != -1) { catchNode.setIfPosition(guardPos - catchPos); } catchNode.setParens(lp, rp); catchNode.setLineno(catchLineNum); if (mustMatchToken(Token.RC, "msg.no.brace.after.body")) tryEnd = ts.tokenEnd; catchNode.setLength(tryEnd - catchPos); if (clauses == null) clauses = new ArrayList(); clauses.add(catchNode); } } else if (peek != Token.FINALLY) { mustMatchToken(Token.FINALLY, "msg.try.no.catchfinally"); } AstNode finallyBlock = null; if (matchToken(Token.FINALLY)) { finallyPos = ts.tokenBeg; finallyBlock = statement(); tryEnd = getNodeEnd(finallyBlock); } TryStatement pn = new TryStatement(tryPos, tryEnd - tryPos); pn.setTryBlock(tryBlock); pn.setCatchClauses(clauses); pn.setFinallyBlock(finallyBlock); if (finallyPos != -1) { pn.setFinallyPosition(finallyPos - tryPos); } pn.setLineno(lineno); if (jsdoc != null) { pn.setJsDoc(jsdoc); } return pn; } private ThrowStatement throwStatement() throws IOException { if (currentToken != Token.THROW) codeBug(); consumeToken(); int pos = ts.tokenBeg, lineno = ts.lineno; if (peekTokenOrEOL() == Token.EOL) { // ECMAScript does not allow new lines before throw expression, // see bug 256617 reportError("msg.bad.throw.eol"); } AstNode expr = expr(); ThrowStatement pn = new ThrowStatement(pos, getNodeEnd(expr), expr); pn.setLineno(lineno); return pn; } // If we match a NAME, consume the token and return the statement // with that label. If the name does not match an existing label, // reports an error. Returns the labeled statement node, or null if // the peeked token was not a name. Side effect: sets scanner token // information for the label identifier (tokenBeg, tokenEnd, etc.) private LabeledStatement matchJumpLabelName() throws IOException { LabeledStatement label = null; if (peekTokenOrEOL() == Token.NAME) { consumeToken(); if (labelSet != null) { label = labelSet.get(ts.getString()); } if (label == null) { reportError("msg.undef.label"); } } return label; } private BreakStatement breakStatement() throws IOException { if (currentToken != Token.BREAK) codeBug(); consumeToken(); int lineno = ts.lineno, pos = ts.tokenBeg, end = ts.tokenEnd; Name breakLabel = null; if (peekTokenOrEOL() == Token.NAME) { breakLabel = createNameNode(); end = getNodeEnd(breakLabel); } // matchJumpLabelName only matches if there is one LabeledStatement labels = matchJumpLabelName(); // always use first label as target Jump breakTarget = labels == null ? null : labels.getFirstLabel(); if (breakTarget == null && breakLabel == null) { if (loopAndSwitchSet == null || loopAndSwitchSet.size() == 0) { if (breakLabel == null) { reportError("msg.bad.break", pos, end - pos); } } else { breakTarget = loopAndSwitchSet.get(loopAndSwitchSet.size() - 1); } } BreakStatement pn = new BreakStatement(pos, end - pos); pn.setBreakLabel(breakLabel); // can be null if it's a bad break in error-recovery mode if (breakTarget != null) pn.setBreakTarget(breakTarget); pn.setLineno(lineno); return pn; } private ContinueStatement continueStatement() throws IOException { if (currentToken != Token.CONTINUE) codeBug(); consumeToken(); int lineno = ts.lineno, pos = ts.tokenBeg, end = ts.tokenEnd; Name label = null; if (peekTokenOrEOL() == Token.NAME) { label = createNameNode(); end = getNodeEnd(label); } // matchJumpLabelName only matches if there is one LabeledStatement labels = matchJumpLabelName(); Loop target = null; if (labels == null && label == null) { if (loopSet == null || loopSet.size() == 0) { reportError("msg.continue.outside"); } else { target = loopSet.get(loopSet.size() - 1); } } else { if (labels == null || !(labels.getStatement() instanceof Loop)) { reportError("msg.continue.nonloop", pos, end - pos); } target = labels == null ? null : (Loop)labels.getStatement(); } ContinueStatement pn = new ContinueStatement(pos, end - pos); if (target != null) // can be null in error-recovery mode pn.setTarget(target); pn.setLabel(label); pn.setLineno(lineno); return pn; } private WithStatement withStatement() throws IOException { if (currentToken != Token.WITH) codeBug(); consumeToken(); int lineno = ts.lineno, pos = ts.tokenBeg, lp = -1, rp = -1; if (mustMatchToken(Token.LP, "msg.no.paren.with")) lp = ts.tokenBeg; AstNode obj = expr(); if (mustMatchToken(Token.RP, "msg.no.paren.after.with")) rp = ts.tokenBeg; ++nestingOfWith; AstNode body; try { body = statement(); } finally { --nestingOfWith; } WithStatement pn = new WithStatement(pos, getNodeEnd(body) - pos); pn.setJsDoc(getAndResetJsDoc()); pn.setExpression(obj); pn.setStatement(body); pn.setParens(lp, rp); pn.setLineno(lineno); return pn; } private AstNode letStatement() throws IOException { if (currentToken != Token.LET) codeBug(); consumeToken(); int lineno = ts.lineno, pos = ts.tokenBeg; AstNode pn; if (peekToken() == Token.LP) { pn = let(true, pos); } else { pn = variables(Token.LET, pos); // else, e.g.: let x=6, y=7; } pn.setLineno(lineno); return pn; } /** * Returns whether or not the bits in the mask have changed to all set. * @param before bits before change * @param after bits after change * @param mask mask for bits * @return {@code true} if all the bits in the mask are set in "after" * but not in "before" */ private static final boolean nowAllSet(int before, int after, int mask) { return ((before & mask) != mask) && ((after & mask) == mask); } private AstNode returnOrYield(int tt, boolean exprContext) throws IOException { if (!insideFunction()) { reportError(tt == Token.RETURN ? "msg.bad.return" : "msg.bad.yield"); } consumeToken(); int lineno = ts.lineno, pos = ts.tokenBeg, end = ts.tokenEnd; AstNode e = null; // This is ugly, but we don't want to require a semicolon. switch (peekTokenOrEOL()) { case Token.SEMI: case Token.RC: case Token.RB: case Token.RP: case Token.EOF: case Token.EOL: case Token.ERROR: case Token.YIELD: break; default: e = expr(); end = getNodeEnd(e); } int before = endFlags; AstNode ret; if (tt == Token.RETURN) { endFlags |= e == null ? Node.END_RETURNS : Node.END_RETURNS_VALUE; ret = new ReturnStatement(pos, end - pos, e); // see if we need a strict mode warning if (nowAllSet(before, endFlags, Node.END_RETURNS|Node.END_RETURNS_VALUE)) addStrictWarning("msg.return.inconsistent", "", pos, end - pos); } else { if (!insideFunction()) reportError("msg.bad.yield"); endFlags |= Node.END_YIELDS; ret = new Yield(pos, end - pos, e); setRequiresActivation(); setIsGenerator(); if (!exprContext) { ret = new ExpressionStatement(ret); } } // see if we are mixing yields and value returns. if (insideFunction() && nowAllSet(before, endFlags, Node.END_YIELDS|Node.END_RETURNS_VALUE)) { Name name = ((FunctionNode)currentScriptOrFn).getFunctionName(); if (name == null || name.length() == 0) addError("msg.anon.generator.returns", ""); else addError("msg.generator.returns", name.getIdentifier()); } ret.setLineno(lineno); return ret; } private AstNode block() throws IOException { if (currentToken != Token.LC) codeBug(); consumeToken(); int pos = ts.tokenBeg; Scope block = new Scope(pos); block.setLineno(ts.lineno); pushScope(block); try { statements(block); mustMatchToken(Token.RC, "msg.no.brace.block"); block.setLength(ts.tokenEnd - pos); return block; } finally { popScope(); } } private AstNode defaultXmlNamespace() throws IOException { if (currentToken != Token.DEFAULT) codeBug(); consumeToken(); mustHaveXML(); setRequiresActivation(); int lineno = ts.lineno, pos = ts.tokenBeg; if (!(matchToken(Token.NAME) && "xml".equals(ts.getString()))) { reportError("msg.bad.namespace"); } if (!(matchToken(Token.NAME) && "namespace".equals(ts.getString()))) { reportError("msg.bad.namespace"); } if (!matchToken(Token.ASSIGN)) { reportError("msg.bad.namespace"); } AstNode e = expr(); UnaryExpression dxmln = new UnaryExpression(pos, getNodeEnd(e) - pos); dxmln.setOperator(Token.DEFAULTNAMESPACE); dxmln.setOperand(e); dxmln.setLineno(lineno); ExpressionStatement es = new ExpressionStatement(dxmln, true); return es; } private void recordLabel(Label label, LabeledStatement bundle) throws IOException { // current token should be colon that primaryExpr left untouched if (peekToken() != Token.COLON) codeBug(); consumeToken(); String name = label.getName(); if (labelSet == null) { labelSet = new HashMap(); } else { LabeledStatement ls = labelSet.get(name); if (ls != null) { if (compilerEnv.isIdeMode()) { Label dup = ls.getLabelByName(name); reportError("msg.dup.label", dup.getAbsolutePosition(), dup.getLength()); } reportError("msg.dup.label", label.getPosition(), label.getLength()); } } bundle.addLabel(label); labelSet.put(name, bundle); } /** * Found a name in a statement context. If it's a label, we gather * up any following labels and the next non-label statement into a * {@link LabeledStatement} "bundle" and return that. Otherwise we parse * an expression and return it wrapped in an {@link ExpressionStatement}. */ private AstNode nameOrLabel() throws IOException { if (currentToken != Token.NAME) throw codeBug(); int pos = ts.tokenBeg; // set check for label and call down to primaryExpr currentFlaggedToken |= TI_CHECK_LABEL; AstNode expr = expr(); if (expr.getType() != Token.LABEL) { AstNode n = new ExpressionStatement(expr, !insideFunction()); n.lineno = expr.lineno; return n; } LabeledStatement bundle = new LabeledStatement(pos); recordLabel((Label)expr, bundle); bundle.setLineno(ts.lineno); // look for more labels AstNode stmt = null; while (peekToken() == Token.NAME) { currentFlaggedToken |= TI_CHECK_LABEL; expr = expr(); if (expr.getType() != Token.LABEL) { stmt = new ExpressionStatement(expr, !insideFunction()); autoInsertSemicolon(stmt); break; } recordLabel((Label)expr, bundle); } // no more labels; now parse the labeled statement try { currentLabel = bundle; if (stmt == null) { stmt = statementHelper(); } } finally { currentLabel = null; // remove the labels for this statement from the global set for (Label lb : bundle.getLabels()) { labelSet.remove(lb.getName()); } } bundle.setLength(getNodeEnd(stmt) - pos); bundle.setStatement(stmt); return bundle; } /** * Parse a 'var' or 'const' statement, or a 'var' init list in a for * statement. * @param declType A token value: either VAR, CONST, or LET depending on * context. * @param pos the position where the node should start. It's sometimes * the var/const/let keyword, and other times the beginning of the first * token in the first variable declaration. * @return the parsed variable list */ private VariableDeclaration variables(int declType, int pos) throws IOException { int end; VariableDeclaration pn = new VariableDeclaration(pos); pn.setType(declType); pn.setLineno(ts.lineno); String varjsdoc = getAndResetJsDoc(); if (varjsdoc != null) { pn.setJsDoc(varjsdoc); } // Example: // var foo = {a: 1, b: 2}, bar = [3, 4]; // var {b: s2, a: s1} = foo, x = 6, y, [s3, s4] = bar; for (;;) { AstNode destructuring = null; Name name = null; int tt = peekToken(), kidPos = ts.tokenBeg; end = ts.tokenEnd; if (tt == Token.LB || tt == Token.LC) { // Destructuring assignment, e.g., var [a,b] = ... destructuring = destructuringPrimaryExpr(); end = getNodeEnd(destructuring); if (!(destructuring instanceof DestructuringForm)) reportError("msg.bad.assign.left", kidPos, end - kidPos); markDestructuring(destructuring); } else { // Simple variable name mustMatchToken(Token.NAME, "msg.bad.var"); name = createNameNode(); name.setLineno(ts.getLineno()); if (inUseStrictDirective) { String id = ts.getString(); if ("eval".equals(id) || "arguments".equals(ts.getString())) { reportError("msg.bad.id.strict", id); } } defineSymbol(declType, ts.getString(), inForInit); } int lineno = ts.lineno; String jsdoc = getAndResetJsDoc(); AstNode init = null; if (matchToken(Token.ASSIGN)) { init = assignExpr(); end = getNodeEnd(init); } VariableInitializer vi = new VariableInitializer(kidPos, end - kidPos); if (destructuring != null) { if (init == null && !inForInit) { reportError("msg.destruct.assign.no.init"); } vi.setTarget(destructuring); } else { vi.setTarget(name); } vi.setInitializer(init); vi.setType(declType); vi.setJsDoc(jsdoc); vi.setLineno(lineno); pn.addVariable(vi); if (!matchToken(Token.COMMA)) break; } pn.setLength(end - pos); return pn; } // have to pass in 'let' kwd position to compute kid offsets properly private AstNode let(boolean isStatement, int pos) throws IOException { LetNode pn = new LetNode(pos); pn.setLineno(ts.lineno); if (mustMatchToken(Token.LP, "msg.no.paren.after.let")) pn.setLp(ts.tokenBeg - pos); pushScope(pn); try { VariableDeclaration vars = variables(Token.LET, ts.tokenBeg); pn.setVariables(vars); if (mustMatchToken(Token.RP, "msg.no.paren.let")) { pn.setRp(ts.tokenBeg - pos); } if (isStatement && peekToken() == Token.LC) { // let statement consumeToken(); int beg = ts.tokenBeg; // position stmt at LC AstNode stmt = statements(); mustMatchToken(Token.RC, "msg.no.curly.let"); stmt.setLength(ts.tokenEnd - beg); pn.setLength(ts.tokenEnd - pos); pn.setBody(stmt); pn.setType(Token.LET); } else { // let expression AstNode expr = expr(); pn.setLength(getNodeEnd(expr) - pos); pn.setBody(expr); if (isStatement) { // let expression in statement context ExpressionStatement es = new ExpressionStatement(pn, !insideFunction()); es.setLineno(pn.getLineno()); return es; } } } finally { popScope(); } return pn; } void defineSymbol(int declType, String name) { defineSymbol(declType, name, false); } void defineSymbol(int declType, String name, boolean ignoreNotInBlock) { if (name == null) { if (compilerEnv.isIdeMode()) { // be robust in IDE-mode return; } else { codeBug(); } } Scope definingScope = currentScope.getDefiningScope(name); Symbol symbol = definingScope != null ? definingScope.getSymbol(name) : null; int symDeclType = symbol != null ? symbol.getDeclType() : -1; if (symbol != null && (symDeclType == Token.CONST || declType == Token.CONST || (definingScope == currentScope && symDeclType == Token.LET))) { addError(symDeclType == Token.CONST ? "msg.const.redecl" : symDeclType == Token.LET ? "msg.let.redecl" : symDeclType == Token.VAR ? "msg.var.redecl" : symDeclType == Token.FUNCTION ? "msg.fn.redecl" : "msg.parm.redecl", name); return; } switch (declType) { case Token.LET: if (!ignoreNotInBlock && ((currentScope.getType() == Token.IF) || currentScope instanceof Loop)) { addError("msg.let.decl.not.in.block"); return; } currentScope.putSymbol(new Symbol(declType, name)); return; case Token.VAR: case Token.CONST: case Token.FUNCTION: if (symbol != null) { if (symDeclType == Token.VAR) addStrictWarning("msg.var.redecl", name); else if (symDeclType == Token.LP) { addStrictWarning("msg.var.hides.arg", name); } } else { currentScriptOrFn.putSymbol(new Symbol(declType, name)); } return; case Token.LP: if (symbol != null) { // must be duplicate parameter. Second parameter hides the // first, so go ahead and add the second parameter addWarning("msg.dup.parms", name); } currentScriptOrFn.putSymbol(new Symbol(declType, name)); return; default: throw codeBug(); } } private AstNode expr() throws IOException { AstNode pn = assignExpr(); int pos = pn.getPosition(); while (matchToken(Token.COMMA)) { int lineno = ts.lineno; int opPos = ts.tokenBeg; if (compilerEnv.isStrictMode() && !pn.hasSideEffects()) addStrictWarning("msg.no.side.effects", "", pos, nodeEnd(pn) - pos); if (peekToken() == Token.YIELD) reportError("msg.yield.parenthesized"); pn = new InfixExpression(Token.COMMA, pn, assignExpr(), opPos); pn.setLineno(lineno); } return pn; } private AstNode assignExpr() throws IOException { int tt = peekToken(); if (tt == Token.YIELD) { return returnOrYield(tt, true); } AstNode pn = condExpr(); tt = peekToken(); if (Token.FIRST_ASSIGN <= tt && tt <= Token.LAST_ASSIGN) { consumeToken(); // Pull out JSDoc info and reset it before recursing. String jsdoc = getAndResetJsDoc(); markDestructuring(pn); int opPos = ts.tokenBeg; int opLineno = ts.getLineno(); pn = new Assignment(tt, pn, assignExpr(), opPos); pn.setLineno(opLineno); if (jsdoc != null) { pn.setJsDoc(jsdoc); } } else if (tt == Token.SEMI && pn.getType() == Token.GETPROP) { // This may be dead code added intentionally, for JSDoc purposes. // For example: /** @type Number */ C.prototype.x; if (currentJsDocComment != null) { pn.setJsDoc(getAndResetJsDoc()); } } return pn; } private AstNode condExpr() throws IOException { AstNode pn = orExpr(); if (matchToken(Token.HOOK)) { int line = ts.lineno; int qmarkPos = ts.tokenBeg, colonPos = -1; AstNode ifTrue = assignExpr(); if (mustMatchToken(Token.COLON, "msg.no.colon.cond")) colonPos = ts.tokenBeg; AstNode ifFalse = assignExpr(); int beg = pn.getPosition(), len = getNodeEnd(ifFalse) - beg; ConditionalExpression ce = new ConditionalExpression(beg, len); ce.setLineno(line); ce.setTestExpression(pn); ce.setTrueExpression(ifTrue); ce.setFalseExpression(ifFalse); ce.setQuestionMarkPosition(qmarkPos - beg); ce.setColonPosition(colonPos - beg); pn = ce; } return pn; } private AstNode orExpr() throws IOException { AstNode pn = andExpr(); if (matchToken(Token.OR)) { int opPos = ts.tokenBeg; int lineno = ts.lineno; pn = new InfixExpression(Token.OR, pn, orExpr(), opPos); pn.setLineno(lineno); } return pn; } private AstNode andExpr() throws IOException { AstNode pn = bitOrExpr(); if (matchToken(Token.AND)) { int opPos = ts.tokenBeg; int lineno = ts.lineno; pn = new InfixExpression(Token.AND, pn, andExpr(), opPos); pn.setLineno(lineno); } return pn; } private AstNode bitOrExpr() throws IOException { AstNode pn = bitXorExpr(); while (matchToken(Token.BITOR)) { int opPos = ts.tokenBeg; int lineno = ts.lineno; pn = new InfixExpression(Token.BITOR, pn, bitXorExpr(), opPos); pn.setLineno(lineno); } return pn; } private AstNode bitXorExpr() throws IOException { AstNode pn = bitAndExpr(); while (matchToken(Token.BITXOR)) { int opPos = ts.tokenBeg; int lineno = ts.lineno; pn = new InfixExpression(Token.BITXOR, pn, bitAndExpr(), opPos); pn.setLineno(lineno); } return pn; } private AstNode bitAndExpr() throws IOException { AstNode pn = eqExpr(); while (matchToken(Token.BITAND)) { int opPos = ts.tokenBeg; int lineno = ts.lineno; pn = new InfixExpression(Token.BITAND, pn, eqExpr(), opPos); pn.setLineno(lineno); } return pn; } private AstNode eqExpr() throws IOException { AstNode pn = relExpr(); for (;;) { int tt = peekToken(), opPos = ts.tokenBeg; int lineno = ts.lineno; switch (tt) { case Token.EQ: case Token.NE: case Token.SHEQ: case Token.SHNE: consumeToken(); int parseToken = tt; if (compilerEnv.getLanguageVersion() == Context.VERSION_1_2) { // JavaScript 1.2 uses shallow equality for == and != . if (tt == Token.EQ) parseToken = Token.SHEQ; else if (tt == Token.NE) parseToken = Token.SHNE; } pn = new InfixExpression(parseToken, pn, relExpr(), opPos); pn.setLineno(lineno); continue; } break; } return pn; } private AstNode relExpr() throws IOException { AstNode pn = shiftExpr(); for (;;) { int tt = peekToken(), opPos = ts.tokenBeg; int line = ts.lineno; switch (tt) { case Token.IN: if (inForInit) break; // fall through case Token.INSTANCEOF: case Token.LE: case Token.LT: case Token.GE: case Token.GT: consumeToken(); pn = new InfixExpression(tt, pn, shiftExpr(), opPos); pn.setLineno(line); continue; } break; } return pn; } private AstNode shiftExpr() throws IOException { AstNode pn = addExpr(); for (;;) { int tt = peekToken(), opPos = ts.tokenBeg; int lineno = ts.lineno; switch (tt) { case Token.LSH: case Token.URSH: case Token.RSH: consumeToken(); pn = new InfixExpression(tt, pn, addExpr(), opPos); pn.setLineno(lineno); continue; } break; } return pn; } private AstNode addExpr() throws IOException { AstNode pn = mulExpr(); for (;;) { int tt = peekToken(), opPos = ts.tokenBeg; if (tt == Token.ADD || tt == Token.SUB) { consumeToken(); int lineno = ts.lineno; pn = new InfixExpression(tt, pn, mulExpr(), opPos); pn.setLineno(lineno); continue; } break; } return pn; } private AstNode mulExpr() throws IOException { AstNode pn = unaryExpr(); for (;;) { int tt = peekToken(), opPos = ts.tokenBeg; switch (tt) { case Token.MUL: case Token.DIV: case Token.MOD: consumeToken(); int line = ts.lineno; pn = new InfixExpression(tt, pn, unaryExpr(), opPos); pn.setLineno(line); continue; } break; } return pn; } private AstNode unaryExpr() throws IOException { AstNode node; int tt = peekToken(); int line = ts.lineno; switch(tt) { case Token.VOID: case Token.NOT: case Token.BITNOT: case Token.TYPEOF: consumeToken(); node = new UnaryExpression(tt, ts.tokenBeg, unaryExpr()); node.setLineno(line); return node; case Token.ADD: consumeToken(); // Convert to special POS token in parse tree node = new UnaryExpression(Token.POS, ts.tokenBeg, unaryExpr()); node.setLineno(line); return node; case Token.SUB: consumeToken(); // Convert to special NEG token in parse tree node = new UnaryExpression(Token.NEG, ts.tokenBeg, unaryExpr()); node.setLineno(line); return node; case Token.INC: case Token.DEC: consumeToken(); UnaryExpression expr = new UnaryExpression(tt, ts.tokenBeg, memberExpr(true)); expr.setLineno(line); checkBadIncDec(expr); return expr; case Token.DELPROP: consumeToken(); node = new UnaryExpression(tt, ts.tokenBeg, unaryExpr()); node.setLineno(line); return node; case Token.ERROR: consumeToken(); return makeErrorNode(); case Token.LT: // XML stream encountered in expression. if (compilerEnv.isXmlAvailable()) { consumeToken(); return memberExprTail(true, xmlInitializer()); } // Fall thru to the default handling of RELOP default: AstNode pn = memberExpr(true); // Don't look across a newline boundary for a postfix incop. tt = peekTokenOrEOL(); if (!(tt == Token.INC || tt == Token.DEC)) { return pn; } consumeToken(); UnaryExpression uexpr = new UnaryExpression(tt, ts.tokenBeg, pn, true); uexpr.setLineno(line); checkBadIncDec(uexpr); return uexpr; } } private AstNode xmlInitializer() throws IOException { if (currentToken != Token.LT) codeBug(); int pos = ts.tokenBeg, tt = ts.getFirstXMLToken(); if (tt != Token.XML && tt != Token.XMLEND) { reportError("msg.syntax"); return makeErrorNode(); } XmlLiteral pn = new XmlLiteral(pos); pn.setLineno(ts.lineno); for (;;tt = ts.getNextXMLToken()) { switch (tt) { case Token.XML: pn.addFragment(new XmlString(ts.tokenBeg, ts.getString())); mustMatchToken(Token.LC, "msg.syntax"); int beg = ts.tokenBeg; AstNode expr = (peekToken() == Token.RC) ? new EmptyExpression(beg, ts.tokenEnd - beg) : expr(); mustMatchToken(Token.RC, "msg.syntax"); XmlExpression xexpr = new XmlExpression(beg, expr); xexpr.setIsXmlAttribute(ts.isXMLAttribute()); xexpr.setLength(ts.tokenEnd - beg); pn.addFragment(xexpr); break; case Token.XMLEND: pn.addFragment(new XmlString(ts.tokenBeg, ts.getString())); return pn; default: reportError("msg.syntax"); return makeErrorNode(); } } } private List argumentList() throws IOException { if (matchToken(Token.RP)) return null; List result = new ArrayList(); boolean wasInForInit = inForInit; inForInit = false; try { do { if (peekToken() == Token.YIELD) reportError("msg.yield.parenthesized"); result.add(assignExpr()); } while (matchToken(Token.COMMA)); } finally { inForInit = wasInForInit; } mustMatchToken(Token.RP, "msg.no.paren.arg"); return result; } /** * Parse a new-expression, or if next token isn't {@link Token#NEW}, * a primary expression. * @param allowCallSyntax passed down to {@link #memberExprTail} */ private AstNode memberExpr(boolean allowCallSyntax) throws IOException { int tt = peekToken(), lineno = ts.lineno; AstNode pn; if (tt != Token.NEW) { pn = primaryExpr(); } else { consumeToken(); int pos = ts.tokenBeg; NewExpression nx = new NewExpression(pos); AstNode target = memberExpr(false); int end = getNodeEnd(target); nx.setTarget(target); int lp = -1; if (matchToken(Token.LP)) { lp = ts.tokenBeg; List args = argumentList(); if (args != null && args.size() > ARGC_LIMIT) reportError("msg.too.many.constructor.args"); int rp = ts.tokenBeg; end = ts.tokenEnd; if (args != null) nx.setArguments(args); nx.setParens(lp - pos, rp - pos); } // Experimental syntax: allow an object literal to follow a new // expression, which will mean a kind of anonymous class built with // the JavaAdapter. the object literal will be passed as an // additional argument to the constructor. if (matchToken(Token.LC)) { ObjectLiteral initializer = objectLiteral(); end = getNodeEnd(initializer); nx.setInitializer(initializer); } nx.setLength(end - pos); pn = nx; } pn.setLineno(lineno); AstNode tail = memberExprTail(allowCallSyntax, pn); return tail; } /** * Parse any number of "(expr)", "[expr]" ".expr", "..expr", * or ".(expr)" constructs trailing the passed expression. * @param pn the non-null parent node * @return the outermost (lexically last occurring) expression, * which will have the passed parent node as a descendant */ private AstNode memberExprTail(boolean allowCallSyntax, AstNode pn) throws IOException { // we no longer return null for errors, so this won't be null if (pn == null) codeBug(); int pos = pn.getPosition(); int lineno; tailLoop: for (;;) { int tt = peekToken(); switch (tt) { case Token.DOT: case Token.DOTDOT: lineno = ts.lineno; pn = propertyAccess(tt, pn); pn.setLineno(lineno); break; case Token.DOTQUERY: consumeToken(); int opPos = ts.tokenBeg, rp = -1; lineno = ts.lineno; mustHaveXML(); setRequiresActivation(); AstNode filter = expr(); int end = getNodeEnd(filter); if (mustMatchToken(Token.RP, "msg.no.paren")) { rp = ts.tokenBeg; end = ts.tokenEnd; } XmlDotQuery q = new XmlDotQuery(pos, end - pos); q.setLeft(pn); q.setRight(filter); q.setOperatorPosition(opPos); q.setRp(rp - pos); q.setLineno(lineno); pn = q; break; case Token.LB: consumeToken(); int lb = ts.tokenBeg, rb = -1; lineno = ts.lineno; AstNode expr = expr(); end = getNodeEnd(expr); if (mustMatchToken(Token.RB, "msg.no.bracket.index")) { rb = ts.tokenBeg; end = ts.tokenEnd; } ElementGet g = new ElementGet(pos, end - pos); g.setTarget(pn); g.setElement(expr); g.setParens(lb, rb); g.setLineno(lineno); pn = g; break; case Token.LP: if (!allowCallSyntax) { break tailLoop; } lineno = ts.lineno; consumeToken(); checkCallRequiresActivation(pn); FunctionCall f = new FunctionCall(pos); f.setTarget(pn); // Assign the line number for the function call to where // the paren appeared, not where the name expression started. f.setLineno(lineno); f.setLp(ts.tokenBeg - pos); List args = argumentList(); if (args != null && args.size() > ARGC_LIMIT) reportError("msg.too.many.function.args"); f.setArguments(args); f.setRp(ts.tokenBeg - pos); f.setLength(ts.tokenEnd - pos); pn = f; break; default: break tailLoop; } } return pn; } /** * Handles any construct following a "." or ".." operator. * @param pn the left-hand side (target) of the operator. Never null. * @return a PropertyGet, XmlMemberGet, or ErrorNode */ private AstNode propertyAccess(int tt, AstNode pn) throws IOException { if (pn == null) codeBug(); int memberTypeFlags = 0, lineno = ts.lineno, dotPos = ts.tokenBeg; consumeToken(); if (tt == Token.DOTDOT) { mustHaveXML(); memberTypeFlags = Node.DESCENDANTS_FLAG; } if (!compilerEnv.isXmlAvailable()) { mustMatchToken(Token.NAME, "msg.no.name.after.dot"); Name name = createNameNode(true, Token.GETPROP); PropertyGet pg = new PropertyGet(pn, name, dotPos); pg.setLineno(lineno); return pg; } AstNode ref = null; // right side of . or .. operator switch (nextToken()) { case Token.THROW: // needed for generator.throw(); saveNameTokenData(ts.tokenBeg, "throw", ts.lineno); ref = propertyName(-1, "throw", memberTypeFlags); break; case Token.NAME: // handles: name, ns::name, ns::*, ns::[expr] ref = propertyName(-1, ts.getString(), memberTypeFlags); break; case Token.MUL: // handles: *, *::name, *::*, *::[expr] saveNameTokenData(ts.tokenBeg, "*", ts.lineno); ref = propertyName(-1, "*", memberTypeFlags); break; case Token.XMLATTR: // handles: '@attr', '@ns::attr', '@ns::*', '@ns::*', // '@::attr', '@::*', '@*', '@*::attr', '@*::*' ref = attributeAccess(); break; default: reportError("msg.no.name.after.dot"); return makeErrorNode(); } boolean xml = ref instanceof XmlRef; InfixExpression result = xml ? new XmlMemberGet() : new PropertyGet(); if (xml && tt == Token.DOT) result.setType(Token.DOT); int pos = pn.getPosition(); result.setPosition(pos); result.setLength(getNodeEnd(ref) - pos); result.setOperatorPosition(dotPos - pos); result.setLineno(lineno); result.setLeft(pn); // do this after setting position result.setRight(ref); return result; } /** * Xml attribute expression:

* {@code @attr}, {@code @ns::attr}, {@code @ns::*}, {@code @ns::*}, * {@code @*}, {@code @*::attr}, {@code @*::*}, {@code @ns::[expr]}, * {@code @*::[expr]}, {@code @[expr]}

* Called if we peeked an '@' token. */ private AstNode attributeAccess() throws IOException { int tt = nextToken(), atPos = ts.tokenBeg; switch (tt) { // handles: @name, @ns::name, @ns::*, @ns::[expr] case Token.NAME: return propertyName(atPos, ts.getString(), 0); // handles: @*, @*::name, @*::*, @*::[expr] case Token.MUL: saveNameTokenData(ts.tokenBeg, "*", ts.lineno); return propertyName(atPos, "*", 0); // handles @[expr] case Token.LB: return xmlElemRef(atPos, null, -1); default: reportError("msg.no.name.after.xmlAttr"); return makeErrorNode(); } } /** * Check if :: follows name in which case it becomes a qualified name. * * @param atPos a natural number if we just read an '@' token, else -1 * * @param s the name or string that was matched (an identifier, "throw" or * "*"). * * @param memberTypeFlags flags tracking whether we're a '.' or '..' child * * @return an XmlRef node if it's an attribute access, a child of a * '..' operator, or the name is followed by ::. For a plain name, * returns a Name node. Returns an ErrorNode for malformed XML * expressions. (For now - might change to return a partial XmlRef.) */ private AstNode propertyName(int atPos, String s, int memberTypeFlags) throws IOException { int pos = atPos != -1 ? atPos : ts.tokenBeg, lineno = ts.lineno; int colonPos = -1; Name name = createNameNode(true, currentToken); Name ns = null; if (matchToken(Token.COLONCOLON)) { ns = name; colonPos = ts.tokenBeg; switch (nextToken()) { // handles name::name case Token.NAME: name = createNameNode(); break; // handles name::* case Token.MUL: saveNameTokenData(ts.tokenBeg, "*", ts.lineno); name = createNameNode(false, -1); break; // handles name::[expr] or *::[expr] case Token.LB: return xmlElemRef(atPos, ns, colonPos); default: reportError("msg.no.name.after.coloncolon"); return makeErrorNode(); } } if (ns == null && memberTypeFlags == 0 && atPos == -1) { return name; } XmlPropRef ref = new XmlPropRef(pos, getNodeEnd(name) - pos); ref.setAtPos(atPos); ref.setNamespace(ns); ref.setColonPos(colonPos); ref.setPropName(name); ref.setLineno(lineno); return ref; } /** * Parse the [expr] portion of an xml element reference, e.g. * @[expr], @*::[expr], or ns::[expr]. */ private XmlElemRef xmlElemRef(int atPos, Name namespace, int colonPos) throws IOException { int lb = ts.tokenBeg, rb = -1, pos = atPos != -1 ? atPos : lb; AstNode expr = expr(); int end = getNodeEnd(expr); if (mustMatchToken(Token.RB, "msg.no.bracket.index")) { rb = ts.tokenBeg; end = ts.tokenEnd; } XmlElemRef ref = new XmlElemRef(pos, end - pos); ref.setNamespace(namespace); ref.setColonPos(colonPos); ref.setAtPos(atPos); ref.setExpression(expr); ref.setBrackets(lb, rb); return ref; } private AstNode destructuringPrimaryExpr() throws IOException, ParserException { try { inDestructuringAssignment = true; return primaryExpr(); } finally { inDestructuringAssignment = false; } } private AstNode primaryExpr() throws IOException { int ttFlagged = nextFlaggedToken(); int tt = ttFlagged & CLEAR_TI_MASK; switch(tt) { case Token.FUNCTION: return function(FunctionNode.FUNCTION_EXPRESSION); case Token.LB: return arrayLiteral(); case Token.LC: return objectLiteral(); case Token.LET: return let(false, ts.tokenBeg); case Token.LP: return parenExpr(); case Token.XMLATTR: mustHaveXML(); return attributeAccess(); case Token.NAME: return name(ttFlagged, tt); case Token.NUMBER: { String s = ts.getString(); if (this.inUseStrictDirective && ts.isNumberOctal()) { reportError("msg.no.octal.strict"); } return new NumberLiteral(ts.tokenBeg, s, ts.getNumber()); } case Token.STRING: return createStringLiteral(); case Token.DIV: case Token.ASSIGN_DIV: // Got / or /= which in this context means a regexp ts.readRegExp(tt); int pos = ts.tokenBeg, end = ts.tokenEnd; RegExpLiteral re = new RegExpLiteral(pos, end - pos); re.setValue(ts.getString()); re.setFlags(ts.readAndClearRegExpFlags()); return re; case Token.NULL: case Token.THIS: case Token.FALSE: case Token.TRUE: pos = ts.tokenBeg; end = ts.tokenEnd; return new KeywordLiteral(pos, end - pos, tt); case Token.RESERVED: reportError("msg.reserved.id"); break; case Token.ERROR: // the scanner or one of its subroutines reported the error. break; case Token.EOF: reportError("msg.unexpected.eof"); break; default: reportError("msg.syntax"); break; } // should only be reachable in IDE/error-recovery mode return makeErrorNode(); } private AstNode parenExpr() throws IOException { boolean wasInForInit = inForInit; inForInit = false; try { String jsdoc = getAndResetJsDoc(); int lineno = ts.lineno; AstNode e = expr(); ParenthesizedExpression pn = new ParenthesizedExpression(e); if (jsdoc == null) { jsdoc = getAndResetJsDoc(); } if (jsdoc != null) { pn.setJsDoc(jsdoc); } mustMatchToken(Token.RP, "msg.no.paren"); pn.setLength(ts.tokenEnd - pn.getPosition()); pn.setLineno(lineno); return pn; } finally { inForInit = wasInForInit; } } private AstNode name(int ttFlagged, int tt) throws IOException { String nameString = ts.getString(); int namePos = ts.tokenBeg, nameLineno = ts.lineno; if (0 != (ttFlagged & TI_CHECK_LABEL) && peekToken() == Token.COLON) { // Do not consume colon. It is used as an unwind indicator // to return to statementHelper. Label label = new Label(namePos, ts.tokenEnd - namePos); label.setName(nameString); label.setLineno(ts.lineno); return label; } // Not a label. Unfortunately peeking the next token to check for // a colon has biffed ts.tokenBeg, ts.tokenEnd. We store the name's // bounds in instance vars and createNameNode uses them. saveNameTokenData(namePos, nameString, nameLineno); if (compilerEnv.isXmlAvailable()) { return propertyName(-1, nameString, 0); } else { return createNameNode(true, Token.NAME); } } /** * May return an {@link ArrayLiteral} or {@link ArrayComprehension}. */ private AstNode arrayLiteral() throws IOException { if (currentToken != Token.LB) codeBug(); int pos = ts.tokenBeg, end = ts.tokenEnd; List elements = new ArrayList(); ArrayLiteral pn = new ArrayLiteral(pos); boolean after_lb_or_comma = true; int afterComma = -1; int skipCount = 0; for (;;) { int tt = peekToken(); if (tt == Token.COMMA) { consumeToken(); afterComma = ts.tokenEnd; if (!after_lb_or_comma) { after_lb_or_comma = true; } else { elements.add(new EmptyExpression(ts.tokenBeg, 1)); skipCount++; } } else if (tt == Token.RB) { consumeToken(); // for ([a,] in obj) is legal, but for ([a] in obj) is // not since we have both key and value supplied. The // trick is that [a,] and [a] are equivalent in other // array literal contexts. So we calculate a special // length value just for destructuring assignment. end = ts.tokenEnd; pn.setDestructuringLength(elements.size() + (after_lb_or_comma ? 1 : 0)); pn.setSkipCount(skipCount); if (afterComma != -1) warnTrailingComma("msg.array.trailing.comma", pos, elements, afterComma); break; } else if (tt == Token.FOR && !after_lb_or_comma && elements.size() == 1) { return arrayComprehension(elements.get(0), pos); } else if (tt == Token.EOF) { end = ts.tokenBeg; break; } else { if (!after_lb_or_comma) { reportError("msg.no.bracket.arg"); } elements.add(assignExpr()); after_lb_or_comma = false; afterComma = -1; } } for (AstNode e : elements) { pn.addElement(e); } pn.setLength(end - pos); return pn; } /** * Parse a JavaScript 1.7 Array comprehension. * @param result the first expression after the opening left-bracket * @param pos start of LB token that begins the array comprehension * @return the array comprehension or an error node */ private AstNode arrayComprehension(AstNode result, int pos) throws IOException { List loops = new ArrayList(); while (peekToken() == Token.FOR) { loops.add(arrayComprehensionLoop()); } int ifPos = -1; ConditionData data = null; if (peekToken() == Token.IF) { consumeToken(); ifPos = ts.tokenBeg - pos; data = condition(); } mustMatchToken(Token.RB, "msg.no.bracket.arg"); ArrayComprehension pn = new ArrayComprehension(pos, ts.tokenEnd - pos); pn.setResult(result); pn.setLoops(loops); if (data != null) { pn.setIfPosition(ifPos); pn.setFilter(data.condition); pn.setFilterLp(data.lp - pos); pn.setFilterRp(data.rp - pos); } return pn; } private ArrayComprehensionLoop arrayComprehensionLoop() throws IOException { if (nextToken() != Token.FOR) codeBug(); int pos = ts.tokenBeg; int eachPos = -1, lp = -1, rp = -1, inPos = -1; ArrayComprehensionLoop pn = new ArrayComprehensionLoop(pos); pushScope(pn); try { if (matchToken(Token.NAME)) { if (ts.getString().equals("each")) { eachPos = ts.tokenBeg - pos; } else { reportError("msg.no.paren.for"); } } if (mustMatchToken(Token.LP, "msg.no.paren.for")) { lp = ts.tokenBeg - pos; } AstNode iter = null; switch (peekToken()) { case Token.LB: case Token.LC: // handle destructuring assignment iter = destructuringPrimaryExpr(); markDestructuring(iter); break; case Token.NAME: consumeToken(); iter = createNameNode(); break; default: reportError("msg.bad.var"); } // Define as a let since we want the scope of the variable to // be restricted to the array comprehension if (iter.getType() == Token.NAME) { defineSymbol(Token.LET, ts.getString(), true); } if (mustMatchToken(Token.IN, "msg.in.after.for.name")) inPos = ts.tokenBeg - pos; AstNode obj = expr(); if (mustMatchToken(Token.RP, "msg.no.paren.for.ctrl")) rp = ts.tokenBeg - pos; pn.setLength(ts.tokenEnd - pos); pn.setIterator(iter); pn.setIteratedObject(obj); pn.setInPosition(inPos); pn.setEachPosition(eachPos); pn.setIsForEach(eachPos != -1); pn.setParens(lp, rp); return pn; } finally { popScope(); } } private ObjectLiteral objectLiteral() throws IOException { int pos = ts.tokenBeg, lineno = ts.lineno; int afterComma = -1; List elems = new ArrayList(); Set propertyNames = new HashSet(); commaLoop: for (;;) { String propertyName = null; int tt = peekToken(); String jsdoc = getAndResetJsDoc(); switch(tt) { case Token.NAME: case Token.STRING: afterComma = -1; saveNameTokenData(ts.tokenBeg, ts.getString(), ts.lineno); consumeToken(); StringLiteral stringProp = null; if (tt == Token.STRING) { stringProp = createStringLiteral(); } Name name = createNameNode(); propertyName = ts.getString(); int ppos = ts.tokenBeg; if ((tt == Token.NAME && peekToken() == Token.NAME && ("get".equals(propertyName) || "set".equals(propertyName)))) { consumeToken(); name = createNameNode(); name.setJsDoc(jsdoc); ObjectProperty objectProp = getterSetterProperty(ppos, name, "get".equals(propertyName)); elems.add(objectProp); propertyName = objectProp.getLeft().getString(); } else { AstNode pname = stringProp != null ? stringProp : name; pname.setJsDoc(jsdoc); elems.add(plainProperty(pname, tt)); } break; case Token.NUMBER: consumeToken(); afterComma = -1; AstNode nl = new NumberLiteral(ts.tokenBeg, ts.getString(), ts.getNumber()); nl.setJsDoc(jsdoc); propertyName = ts.getString(); elems.add(plainProperty(nl, tt)); break; case Token.RC: if (afterComma != -1 && compilerEnv.getWarnTrailingComma()) warnTrailingComma("msg.extra.trailing.comma", pos, elems, afterComma); break commaLoop; default: reportError("msg.bad.prop"); break; } if (this.inUseStrictDirective) { if (propertyNames.contains(propertyName)) { addError("msg.dup.obj.lit.prop.strict", propertyName); } propertyNames.add(propertyName); } // Eat any dangling jsdoc in the property. getAndResetJsDoc(); jsdoc = null; if (matchToken(Token.COMMA)) { afterComma = ts.tokenEnd; } else { break commaLoop; } } mustMatchToken(Token.RC, "msg.no.brace.prop"); ObjectLiteral pn = new ObjectLiteral(pos, ts.tokenEnd - pos); pn.setElements(elems); pn.setLineno(lineno); return pn; } private ObjectProperty plainProperty(AstNode property, int ptt) throws IOException { // Support, e.g., |var {x, y} = o| as destructuring shorthand // for |var {x: x, y: y} = o|, as implemented in spidermonkey JS 1.8. int tt = peekToken(); if ((tt == Token.COMMA || tt == Token.RC) && ptt == Token.NAME && compilerEnv.getLanguageVersion() >= Context.VERSION_1_8) { if (!inDestructuringAssignment) { reportError("msg.bad.object.init"); } AstNode nn = new Name(property.getPosition(), property.getString()); ObjectProperty pn = new ObjectProperty(); pn.putProp(Node.DESTRUCTURING_SHORTHAND, Boolean.TRUE); pn.setLeftAndRight(property, nn); return pn; } mustMatchToken(Token.COLON, "msg.no.colon.prop"); ObjectProperty pn = new ObjectProperty(); pn.setOperatorPosition(ts.tokenBeg); pn.setLeftAndRight(property, assignExpr()); return pn; } private ObjectProperty getterSetterProperty(int pos, AstNode propName, boolean isGetter) throws IOException { FunctionNode fn = function(FunctionNode.FUNCTION_EXPRESSION); // We've already parsed the function name, so fn should be anonymous. Name name = fn.getFunctionName(); if (name != null && name.length() != 0) { reportError("msg.bad.prop"); } ObjectProperty pn = new ObjectProperty(pos); if (isGetter) { pn.setIsGetter(); } else { pn.setIsSetter(); } int end = getNodeEnd(fn); pn.setLeft(propName); pn.setRight(fn); pn.setLength(end - pos); return pn; } private Name createNameNode() { return createNameNode(false, Token.NAME); } /** * Create a {@code Name} node using the token info from the * last scanned name. In some cases we need to either synthesize * a name node, or we lost the name token information by peeking. * If the {@code token} parameter is not {@link Token#NAME}, then * we use token info saved in instance vars. */ private Name createNameNode(boolean checkActivation, int token) { int beg = ts.tokenBeg; String s = ts.getString(); int lineno = ts.lineno; if (currentToken != Token.NAME) { beg = prevNameTokenStart; s = prevNameTokenString; lineno = prevNameTokenLineno; prevNameTokenStart = 0; prevNameTokenString = ""; prevNameTokenLineno = 0; } if (s == null) { if (compilerEnv.isIdeMode()) { s = ""; } else { codeBug(); } } Name name = new Name(beg, s); name.setLineno(lineno); if (checkActivation) { checkActivationName(s, token); } return name; } private StringLiteral createStringLiteral() { int pos = ts.tokenBeg, end = ts.tokenEnd; StringLiteral s = new StringLiteral(pos, end - pos); s.setLineno(ts.lineno); s.setValue(ts.getString()); s.setQuoteCharacter(ts.getQuoteChar()); return s; } protected void checkActivationName(String name, int token) { if (!insideFunction()) { return; } boolean activation = false; if ("arguments".equals(name) || (compilerEnv.getActivationNames() != null && compilerEnv.getActivationNames().contains(name))) { activation = true; } else if ("length".equals(name)) { if (token == Token.GETPROP && compilerEnv.getLanguageVersion() == Context.VERSION_1_2) { // Use of "length" in 1.2 requires an activation object. activation = true; } } if (activation) { setRequiresActivation(); } } protected void setRequiresActivation() { if (insideFunction()) { ((FunctionNode)currentScriptOrFn).setRequiresActivation(); } } private void checkCallRequiresActivation(AstNode pn) { if ((pn.getType() == Token.NAME && "eval".equals(((Name)pn).getIdentifier())) || (pn.getType() == Token.GETPROP && "eval".equals(((PropertyGet)pn).getProperty().getIdentifier()))) setRequiresActivation(); } protected void setIsGenerator() { if (insideFunction()) { ((FunctionNode)currentScriptOrFn).setIsGenerator(); } } private void checkBadIncDec(UnaryExpression expr) { AstNode op = removeParens(expr.getOperand()); int tt = op.getType(); if (!(tt == Token.NAME || tt == Token.GETPROP || tt == Token.GETELEM || tt == Token.GET_REF || tt == Token.CALL)) reportError(expr.getType() == Token.INC ? "msg.bad.incr" : "msg.bad.decr"); } private ErrorNode makeErrorNode() { ErrorNode pn = new ErrorNode(ts.tokenBeg, ts.tokenEnd - ts.tokenBeg); pn.setLineno(ts.lineno); return pn; } // Return end of node. Assumes node does NOT have a parent yet. private int nodeEnd(AstNode node) { return node.getPosition() + node.getLength(); } private void saveNameTokenData(int pos, String name, int lineno) { prevNameTokenStart = pos; prevNameTokenString = name; prevNameTokenLineno = lineno; } /** * Return the file offset of the beginning of the input source line * containing the passed position. * * @param pos an offset into the input source stream. If the offset * is negative, it's converted to 0, and if it's beyond the end of * the source buffer, the last source position is used. * * @return the offset of the beginning of the line containing pos * (i.e. 1+ the offset of the first preceding newline). Returns -1 * if the {@link CompilerEnvirons} is not set to ide-mode, * and {@link #parse(java.io.Reader,String,int)} was used. */ private int lineBeginningFor(int pos) { if (sourceChars == null) { return -1; } if (pos <= 0) { return 0; } char[] buf = sourceChars; if (pos >= buf.length) { pos = buf.length - 1; } while (--pos >= 0) { char c = buf[pos]; if (c == '\n' || c == '\r') { return pos + 1; // want position after the newline } } return 0; } private void warnMissingSemi(int pos, int end) { // Should probably change this to be a CompilerEnvirons setting, // with an enum Never, Always, Permissive, where Permissive means // don't warn for 1-line functions like function (s) {return x+2} if (compilerEnv.isStrictMode()) { int beg = Math.max(pos, lineBeginningFor(end)); if (end == -1) end = ts.cursor; addStrictWarning("msg.missing.semi", "", beg, end - beg); } } private void warnTrailingComma(String messageId, int pos, List elems, int commaPos) { if (compilerEnv.getWarnTrailingComma()) { // back up from comma to beginning of line or array/objlit if (!elems.isEmpty()) { pos = ((AstNode)elems.get(0)).getPosition(); } pos = Math.max(pos, lineBeginningFor(commaPos)); addWarning("msg.extra.trailing.comma", pos, commaPos - pos); } } private String readFully(Reader reader) throws IOException { BufferedReader in = new BufferedReader(reader); try { char[] cbuf = new char[1024]; StringBuilder sb = new StringBuilder(1024); int bytes_read; while ((bytes_read = in.read(cbuf, 0, 1024)) != -1) { sb.append(cbuf, 0, bytes_read); } return sb.toString(); } finally { in.close(); } } // helps reduce clutter in the already-large function() method protected class PerFunctionVariables { private ScriptNode savedCurrentScriptOrFn; private Scope savedCurrentScope; private int savedNestingOfWith; private int savedEndFlags; private boolean savedInForInit; private Map savedLabelSet; private List savedLoopSet; private List savedLoopAndSwitchSet; PerFunctionVariables(FunctionNode fnNode) { savedCurrentScriptOrFn = Parser.this.currentScriptOrFn; Parser.this.currentScriptOrFn = fnNode; savedCurrentScope = Parser.this.currentScope; Parser.this.currentScope = fnNode; savedNestingOfWith = Parser.this.nestingOfWith; Parser.this.nestingOfWith = 0; savedLabelSet = Parser.this.labelSet; Parser.this.labelSet = null; savedLoopSet = Parser.this.loopSet; Parser.this.loopSet = null; savedLoopAndSwitchSet = Parser.this.loopAndSwitchSet; Parser.this.loopAndSwitchSet = null; savedEndFlags = Parser.this.endFlags; Parser.this.endFlags = 0; savedInForInit = Parser.this.inForInit; Parser.this.inForInit = false; } void restore() { Parser.this.currentScriptOrFn = savedCurrentScriptOrFn; Parser.this.currentScope = savedCurrentScope; Parser.this.nestingOfWith = savedNestingOfWith; Parser.this.labelSet = savedLabelSet; Parser.this.loopSet = savedLoopSet; Parser.this.loopAndSwitchSet = savedLoopAndSwitchSet; Parser.this.endFlags = savedEndFlags; Parser.this.inForInit = savedInForInit; } } /** * Given a destructuring assignment with a left hand side parsed * as an array or object literal and a right hand side expression, * rewrite as a series of assignments to the variables defined in * left from property accesses to the expression on the right. * @param type declaration type: Token.VAR or Token.LET or -1 * @param left array or object literal containing NAME nodes for * variables to assign * @param right expression to assign from * @return expression that performs a series of assignments to * the variables defined in left */ Node createDestructuringAssignment(int type, Node left, Node right) { String tempName = currentScriptOrFn.getNextTempName(); Node result = destructuringAssignmentHelper(type, left, right, tempName); Node comma = result.getLastChild(); comma.addChildToBack(createName(tempName)); return result; } Node destructuringAssignmentHelper(int variableType, Node left, Node right, String tempName) { Scope result = createScopeNode(Token.LETEXPR, left.getLineno()); result.addChildToFront(new Node(Token.LET, createName(Token.NAME, tempName, right))); try { pushScope(result); defineSymbol(Token.LET, tempName, true); } finally { popScope(); } Node comma = new Node(Token.COMMA); result.addChildToBack(comma); List destructuringNames = new ArrayList(); boolean empty = true; switch (left.getType()) { case Token.ARRAYLIT: empty = destructuringArray((ArrayLiteral)left, variableType, tempName, comma, destructuringNames); break; case Token.OBJECTLIT: empty = destructuringObject((ObjectLiteral)left, variableType, tempName, comma, destructuringNames); break; case Token.GETPROP: case Token.GETELEM: comma.addChildToBack(simpleAssignment(left, createName(tempName))); break; default: reportError("msg.bad.assign.left"); } if (empty) { // Don't want a COMMA node with no children. Just add a zero. comma.addChildToBack(createNumber(0)); } result.putProp(Node.DESTRUCTURING_NAMES, destructuringNames); return result; } boolean destructuringArray(ArrayLiteral array, int variableType, String tempName, Node parent, List destructuringNames) { boolean empty = true; int setOp = variableType == Token.CONST ? Token.SETCONST : Token.SETNAME; int index = 0; for (AstNode n : array.getElements()) { if (n.getType() == Token.EMPTY) { index++; continue; } Node rightElem = new Node(Token.GETELEM, createName(tempName), createNumber(index)); if (n.getType() == Token.NAME) { String name = n.getString(); parent.addChildToBack(new Node(setOp, createName(Token.BINDNAME, name, null), rightElem)); if (variableType != -1) { defineSymbol(variableType, name, true); destructuringNames.add(name); } } else { parent.addChildToBack (destructuringAssignmentHelper (variableType, n, rightElem, currentScriptOrFn.getNextTempName())); } index++; empty = false; } return empty; } boolean destructuringObject(ObjectLiteral node, int variableType, String tempName, Node parent, List destructuringNames) { boolean empty = true; int setOp = variableType == Token.CONST ? Token.SETCONST : Token.SETNAME; for (ObjectProperty prop : node.getElements()) { int lineno = 0; // This function is sometimes called from the IRFactory when // when executing regression tests, and in those cases the // tokenStream isn't set. Deal with it. if (ts != null) { lineno = ts.lineno; } AstNode id = prop.getLeft(); Node rightElem = null; if (id instanceof Name) { Node s = Node.newString(((Name)id).getIdentifier()); rightElem = new Node(Token.GETPROP, createName(tempName), s); } else if (id instanceof StringLiteral) { Node s = Node.newString(((StringLiteral)id).getValue()); rightElem = new Node(Token.GETPROP, createName(tempName), s); } else if (id instanceof NumberLiteral) { Node s = createNumber((int)((NumberLiteral)id).getNumber()); rightElem = new Node(Token.GETELEM, createName(tempName), s); } else { throw codeBug(); } rightElem.setLineno(lineno); AstNode value = prop.getRight(); if (value.getType() == Token.NAME) { String name = ((Name)value).getIdentifier(); parent.addChildToBack(new Node(setOp, createName(Token.BINDNAME, name, null), rightElem)); if (variableType != -1) { defineSymbol(variableType, name, true); destructuringNames.add(name); } } else { parent.addChildToBack (destructuringAssignmentHelper (variableType, value, rightElem, currentScriptOrFn.getNextTempName())); } empty = false; } return empty; } protected Node createName(String name) { checkActivationName(name, Token.NAME); return Node.newString(Token.NAME, name); } protected Node createName(int type, String name, Node child) { Node result = createName(name); result.setType(type); if (child != null) result.addChildToBack(child); return result; } protected Node createNumber(double number) { return Node.newNumber(number); } /** * Create a node that can be used to hold lexically scoped variable * definitions (via let declarations). * * @param token the token of the node to create * @param lineno line number of source * @return the created node */ protected Scope createScopeNode(int token, int lineno) { Scope scope =new Scope(); scope.setType(token); scope.setLineno(lineno); return scope; } // Quickie tutorial for some of the interpreter bytecodes. // // GETPROP - for normal foo.bar prop access; right side is a name // GETELEM - for normal foo[bar] element access; rhs is an expr // SETPROP - for assignment when left side is a GETPROP // SETELEM - for assignment when left side is a GETELEM // DELPROP - used for delete foo.bar or foo[bar] // // GET_REF, SET_REF, DEL_REF - in general, these mean you're using // get/set/delete on a right-hand side expression (possibly with no // explicit left-hand side) that doesn't use the normal JavaScript // Object (i.e. ScriptableObject) get/set/delete functions, but wants // to provide its own versions instead. It will ultimately implement // Ref, and currently SpecialRef (for __proto__ etc.) and XmlName // (for E4X XML objects) are the only implementations. The runtime // notices these bytecodes and delegates get/set/delete to the object. // // BINDNAME: used in assignments. LHS is evaluated first to get a // specific object containing the property ("binding" the property // to the object) so that it's always the same object, regardless of // side effects in the RHS. protected Node simpleAssignment(Node left, Node right) { int nodeType = left.getType(); switch (nodeType) { case Token.NAME: if (inUseStrictDirective && "eval".equals(((Name) left).getIdentifier())) { reportError("msg.bad.id.strict", ((Name) left).getIdentifier()); } left.setType(Token.BINDNAME); return new Node(Token.SETNAME, left, right); case Token.GETPROP: case Token.GETELEM: { Node obj, id; // If it's a PropertyGet or ElementGet, we're in the parse pass. // We could alternately have PropertyGet and ElementGet // override getFirstChild/getLastChild and return the appropriate // field, but that seems just as ugly as this casting. if (left instanceof PropertyGet) { obj = ((PropertyGet)left).getTarget(); id = ((PropertyGet)left).getProperty(); } else if (left instanceof ElementGet) { obj = ((ElementGet)left).getTarget(); id = ((ElementGet)left).getElement(); } else { // This branch is called during IRFactory transform pass. obj = left.getFirstChild(); id = left.getLastChild(); } int type; if (nodeType == Token.GETPROP) { type = Token.SETPROP; // TODO(stevey) - see https://bugzilla.mozilla.org/show_bug.cgi?id=492036 // The new AST code generates NAME tokens for GETPROP ids where the old parser // generated STRING nodes. If we don't set the type to STRING below, this will // cause java.lang.VerifyError in codegen for code like // "var obj={p:3};[obj.p]=[9];" id.setType(Token.STRING); } else { type = Token.SETELEM; } return new Node(type, obj, id, right); } case Token.GET_REF: { Node ref = left.getFirstChild(); checkMutableReference(ref); return new Node(Token.SET_REF, ref, right); } } throw codeBug(); } protected void checkMutableReference(Node n) { int memberTypeFlags = n.getIntProp(Node.MEMBER_TYPE_PROP, 0); if ((memberTypeFlags & Node.DESCENDANTS_FLAG) != 0) { reportError("msg.bad.assign.left"); } } // remove any ParenthesizedExpression wrappers protected AstNode removeParens(AstNode node) { while (node instanceof ParenthesizedExpression) { node = ((ParenthesizedExpression)node).getExpression(); } return node; } void markDestructuring(AstNode node) { if (node instanceof DestructuringForm) { ((DestructuringForm)node).setIsDestructuring(true); } else if (node instanceof ParenthesizedExpression) { markDestructuring(((ParenthesizedExpression)node).getExpression()); } } // throw a failed-assertion with some helpful debugging info private RuntimeException codeBug() throws RuntimeException { throw Kit.codeBug("ts.cursor=" + ts.cursor + ", ts.tokenBeg=" + ts.tokenBeg + ", currentToken=" + currentToken); } } htmlunit-core-js-2.8/rhino/src/org/mozilla/javascript/Evaluator.java0000644000175000017500000001052211222455466025535 0ustar cavedoncavedon/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- * * ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * Contributor(s): * Norris Boyd * * Alternatively, the contents of this file may be used under the terms of * the GNU General Public License Version 2 or later (the "GPL"), in which * case the provisions of the GPL are applicable instead of those above. If * you wish to allow use of your version of this file only under the terms of * the GPL and not to allow others to use your version of this file under the * MPL, indicate your decision by deleting the provisions above and replacing * them with the notice and other provisions required by the GPL. If you do * not delete the provisions above, a recipient may use your version of this * file under either the MPL or the GPL. * * ***** END LICENSE BLOCK ***** */ package org.mozilla.javascript; import 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 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); } htmlunit-core-js-2.8/rhino/src/org/mozilla/javascript/PolicySecurityController.java0000644000175000017500000002104210776622373030633 0ustar cavedoncavedon/* ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is Rhino code, released May 6, 1999. * * The Initial Developer of the Original Code is * Netscape Communications Corporation. * Portions created by the Initial Developer are Copyright (C) 1997-1999 * the Initial Developer. All Rights Reserved. * * Contributor(s): * * Alternatively, the contents of this file may be used under the terms of * the GNU General Public License Version 2 or later (the "GPL"), in which * case the provisions of the GPL are applicable instead of those above. If * you wish to allow use of your version of this file only under the terms of * the GPL and not to allow others to use your version of this file under the * MPL, indicate your decision by deleting the provisions above and replacing * them with the notice and other provisions required by the GPL. If you do * not delete the provisions above, a recipient may use your version of this * file under either the MPL or the GPL. * * ***** END LICENSE BLOCK ***** */ package org.mozilla.javascript; import java.lang.ref.SoftReference; import java.lang.reflect.UndeclaredThrowableException; import java.security.AccessController; import java.security.CodeSource; import java.security.Policy; import java.security.PrivilegedAction; import java.security.PrivilegedActionException; import java.security.PrivilegedExceptionAction; import java.security.SecureClassLoader; import java.util.Map; import java.util.WeakHashMap; import org.mozilla.classfile.ByteCode; import org.mozilla.classfile.ClassFileWriter; /** * A security controller relying on Java {@link Policy} in effect. When you use * this security controller, your securityDomain objects must be instances of * {@link CodeSource} representing the location from where you load your * scripts. Any Java policy "grant" statements matching the URL and certificate * in code sources will apply to the scripts. If you specify any certificates * within your {@link CodeSource} objects, it is your responsibility to verify * (or not) that the script source files are signed in whatever * implementation-specific way you're using. * @author Attila Szegedi */ public class PolicySecurityController extends SecurityController { private static final byte[] secureCallerImplBytecode = loadBytecode(); // We're storing a CodeSource -> (ClassLoader -> SecureRenderer), since we // need to have one renderer per class loader. We're using weak hash maps // and soft references all the way, since we don't want to interfere with // cleanup of either CodeSource or ClassLoader objects. private static final Map>> callers = new WeakHashMap>>(); @Override public Class getStaticSecurityDomainClassInternal() { return CodeSource.class; } private static class Loader extends SecureClassLoader implements GeneratedClassLoader { private final CodeSource codeSource; Loader(ClassLoader parent, CodeSource codeSource) { super(parent); this.codeSource = codeSource; } public Class defineClass(String name, byte[] data) { return defineClass(name, data, 0, data.length, codeSource); } public void linkClass(Class cl) { resolveClass(cl); } } @Override public GeneratedClassLoader createClassLoader(final ClassLoader parent, final Object securityDomain) { return (Loader)AccessController.doPrivileged( new PrivilegedAction() { public Object run() { return new Loader(parent, (CodeSource)securityDomain); } }); } @Override public Object getDynamicSecurityDomain(Object securityDomain) { // No separate notion of dynamic security domain - just return what was // passed in. return securityDomain; } @Override public Object callWithDomain(final Object securityDomain, final Context cx, Callable callable, Scriptable scope, Scriptable thisObj, Object[] args) { // Run in doPrivileged as we might be checked for "getClassLoader" // runtime permission final ClassLoader classLoader = (ClassLoader)AccessController.doPrivileged( new PrivilegedAction() { public Object run() { return cx.getApplicationClassLoader(); } }); final CodeSource codeSource = (CodeSource)securityDomain; Map> classLoaderMap; synchronized (callers) { classLoaderMap = callers.get(codeSource); if(classLoaderMap == null) { classLoaderMap = new WeakHashMap>(); callers.put(codeSource, classLoaderMap); } } SecureCaller caller; synchronized (classLoaderMap) { SoftReference ref = classLoaderMap.get(classLoader); if (ref != null) { caller = ref.get(); } else { caller = null; } if (caller == null) { try { // Run in doPrivileged as we'll be checked for // "createClassLoader" runtime permission caller = (SecureCaller)AccessController.doPrivileged( new PrivilegedExceptionAction() { public Object run() throws Exception { Loader loader = new Loader(classLoader, codeSource); Class c = loader.defineClass( SecureCaller.class.getName() + "Impl", secureCallerImplBytecode); return c.newInstance(); } }); classLoaderMap.put(classLoader, new SoftReference(caller)); } catch(PrivilegedActionException ex) { throw new UndeclaredThrowableException(ex.getCause()); } } } return caller.call(callable, cx, scope, thisObj, args); } public abstract static class SecureCaller { public abstract Object call(Callable callable, Context cx, Scriptable scope, Scriptable thisObj, Object[] args); } private static byte[] loadBytecode() { String secureCallerClassName = SecureCaller.class.getName(); ClassFileWriter cfw = new ClassFileWriter( secureCallerClassName + "Impl", secureCallerClassName, ""); cfw.startMethod("", "()V", ClassFileWriter.ACC_PUBLIC); cfw.addALoad(0); cfw.addInvoke(ByteCode.INVOKESPECIAL, secureCallerClassName, "", "()V"); cfw.add(ByteCode.RETURN); cfw.stopMethod((short)1); String callableCallSig = "Lorg/mozilla/javascript/Context;" + "Lorg/mozilla/javascript/Scriptable;" + "Lorg/mozilla/javascript/Scriptable;" + "[Ljava/lang/Object;)Ljava/lang/Object;"; cfw.startMethod("call", "(Lorg/mozilla/javascript/Callable;" + callableCallSig, (short)(ClassFileWriter.ACC_PUBLIC | ClassFileWriter.ACC_FINAL)); for(int i = 1; i < 6; ++i) { cfw.addALoad(i); } cfw.addInvoke(ByteCode.INVOKEINTERFACE, "org/mozilla/javascript/Callable", "call", "(" + callableCallSig); cfw.add(ByteCode.ARETURN); cfw.stopMethod((short)6); return cfw.toByteArray(); } }htmlunit-core-js-2.8/rhino/src/org/mozilla/javascript/ObjToIntMap.java0000644000175000017500000005143110776622373025733 0ustar cavedoncavedon/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- * * ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is Rhino code, released * May 6, 1999. * * The Initial Developer of the Original Code is * Netscape Communications Corporation. * Portions created by the Initial Developer are Copyright (C) 1997-2000 * the Initial Developer. All Rights Reserved. * * Contributor(s): * Igor Bukanov * * Alternatively, the contents of this file may be used under the terms of * the GNU General Public License Version 2 or later (the "GPL"), in which * case the provisions of the GPL are applicable instead of those above. If * you wish to allow use of your version of this file only under the terms of * the GPL and not to allow others to use your version of this file under the * MPL, indicate your decision by deleting the provisions above and replacing * them with the notice and other provisions required by the GPL. If you do * not delete the provisions above, a recipient may use your version of this * file under either the MPL or the GPL. * * ***** END LICENSE BLOCK ***** */ package org.mozilla.javascript; import java.io.Serializable; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; /** * Map to associate objects to integers. * The map does not synchronize any of its operation, so either use * it from a single thread or do own synchronization or perform all mutation * operations on one thread before passing the map to others * * @author Igor Bukanov * */ public class ObjToIntMap implements Serializable { static final long serialVersionUID = -1542220580748809402L; // Map implementation via hashtable, // follows "The Art of Computer Programming" by Donald E. Knuth // ObjToIntMap is a copy cat of ObjToIntMap with API adjusted to object keys public static class Iterator { Iterator(ObjToIntMap master) { this.master = master; } final void init(Object[] keys, int[] values, int keyCount) { this.keys = keys; this.values = values; this.cursor = -1; this.remaining = keyCount; } public void start() { master.initIterator(this); next(); } public boolean done() { return remaining < 0; } public void next() { if (remaining == -1) Kit.codeBug(); if (remaining == 0) { remaining = -1; cursor = -1; }else { for (++cursor; ; ++cursor) { Object key = keys[cursor]; if (key != null && key != DELETED) { --remaining; break; } } } } public Object getKey() { Object key = keys[cursor]; if (key == UniqueTag.NULL_VALUE) { key = null; } return key; } public int getValue() { return values[cursor]; } public void setValue(int value) { values[cursor] = value; } ObjToIntMap master; private int cursor; private int remaining; private Object[] keys; private int[] values; } public ObjToIntMap() { this(4); } public ObjToIntMap(int keyCountHint) { if (keyCountHint < 0) Kit.codeBug(); // Table grow when number of stored keys >= 3/4 of max capacity int minimalCapacity = keyCountHint * 4 / 3; int i; for (i = 2; (1 << i) < minimalCapacity; ++i) { } power = i; if (check && power < 2) Kit.codeBug(); } public boolean isEmpty() { return keyCount == 0; } public int size() { return keyCount; } public boolean has(Object key) { if (key == null) { key = UniqueTag.NULL_VALUE; } return 0 <= findIndex(key); } /** * Get integer value assigned with key. * @return key integer value or defaultValue if key is absent */ public int get(Object key, int defaultValue) { if (key == null) { key = UniqueTag.NULL_VALUE; } int index = findIndex(key); if (0 <= index) { return values[index]; } return defaultValue; } /** * Get integer value assigned with key. * @return key integer value * @throws RuntimeException if key does not exist */ public int getExisting(Object key) { if (key == null) { key = UniqueTag.NULL_VALUE; } int index = findIndex(key); if (0 <= index) { return values[index]; } // Key must exist Kit.codeBug(); return 0; } public void put(Object key, int value) { if (key == null) { key = UniqueTag.NULL_VALUE; } int index = ensureIndex(key); values[index] = value; } /** * If table already contains a key that equals to keyArg, return that key * while setting its value to zero, otherwise add keyArg with 0 value to * the table and return it. */ public Object intern(Object keyArg) { boolean nullKey = false; if (keyArg == null) { nullKey = true; keyArg = UniqueTag.NULL_VALUE; } int index = ensureIndex(keyArg); values[index] = 0; return (nullKey) ? null : keys[index]; } public void remove(Object key) { if (key == null) { key = UniqueTag.NULL_VALUE; } int index = findIndex(key); if (0 <= index) { keys[index] = DELETED; --keyCount; } } public void clear() { int i = keys.length; while (i != 0) { keys[--i] = null; } keyCount = 0; occupiedCount = 0; } public Iterator newIterator() { return new Iterator(this); } // The sole purpose of the method is to avoid accessing private fields // from the Iterator inner class to workaround JDK 1.1 compiler bug which // generates code triggering VerifierError on recent JVMs final void initIterator(Iterator i) { i.init(keys, values, keyCount); } /** Return array of present keys */ public Object[] getKeys() { Object[] array = new Object[keyCount]; getKeys(array, 0); return array; } public void getKeys(Object[] array, int offset) { int count = keyCount; for (int i = 0; count != 0; ++i) { Object key = keys[i]; if (key != null && key != DELETED) { if (key == UniqueTag.NULL_VALUE) { key = null; } array[offset] = key; ++offset; --count; } } } private static int tableLookupStep(int fraction, int mask, int power) { int shift = 32 - 2 * power; if (shift >= 0) { return ((fraction >>> shift) & mask) | 1; } else { return (fraction & (mask >>> -shift)) | 1; } } private int findIndex(Object key) { if (keys != null) { int hash = key.hashCode(); int fraction = hash * A; int index = fraction >>> (32 - power); Object test = keys[index]; if (test != null) { int N = 1 << power; if (test == key || (values[N + index] == hash && test.equals(key))) { return index; } // Search in table after first failed attempt int mask = N - 1; int step = tableLookupStep(fraction, mask, power); int n = 0; for (;;) { if (check) { if (n >= occupiedCount) Kit.codeBug(); ++n; } index = (index + step) & mask; test = keys[index]; if (test == null) { break; } if (test == key || (values[N + index] == hash && test.equals(key))) { return index; } } } } return -1; } // Insert key that is not present to table without deleted entries // and enough free space private int insertNewKey(Object key, int hash) { if (check && occupiedCount != keyCount) Kit.codeBug(); if (check && keyCount == 1 << power) Kit.codeBug(); int fraction = hash * A; int index = fraction >>> (32 - power); int N = 1 << power; if (keys[index] != null) { int mask = N - 1; int step = tableLookupStep(fraction, mask, power); int firstIndex = index; do { if (check && keys[index] == DELETED) Kit.codeBug(); index = (index + step) & mask; if (check && firstIndex == index) Kit.codeBug(); } while (keys[index] != null); } keys[index] = key; values[N + index] = hash; ++occupiedCount; ++keyCount; return index; } private void rehashTable() { if (keys == null) { if (check && keyCount != 0) Kit.codeBug(); if (check && occupiedCount != 0) Kit.codeBug(); int N = 1 << power; keys = new Object[N]; values = new int[2 * N]; } else { // Check if removing deleted entries would free enough space if (keyCount * 2 >= occupiedCount) { // Need to grow: less then half of deleted entries ++power; } int N = 1 << power; Object[] oldKeys = keys; int[] oldValues = values; int oldN = oldKeys.length; keys = new Object[N]; values = new int[2 * N]; int remaining = keyCount; occupiedCount = keyCount = 0; for (int i = 0; remaining != 0; ++i) { Object key = oldKeys[i]; if (key != null && key != DELETED) { int keyHash = oldValues[oldN + i]; int index = insertNewKey(key, keyHash); values[index] = oldValues[i]; --remaining; } } } } // Ensure key index creating one if necessary private int ensureIndex(Object key) { int hash = key.hashCode(); int index = -1; int firstDeleted = -1; if (keys != null) { int fraction = hash * A; index = fraction >>> (32 - power); Object test = keys[index]; if (test != null) { int N = 1 << power; if (test == key || (values[N + index] == hash && test.equals(key))) { return index; } if (test == DELETED) { firstDeleted = index; } // Search in table after first failed attempt int mask = N - 1; int step = tableLookupStep(fraction, mask, power); int n = 0; for (;;) { if (check) { if (n >= occupiedCount) Kit.codeBug(); ++n; } index = (index + step) & mask; test = keys[index]; if (test == null) { break; } if (test == key || (values[N + index] == hash && test.equals(key))) { return index; } if (test == DELETED && firstDeleted < 0) { firstDeleted = index; } } } } // Inserting of new key if (check && keys != null && keys[index] != null) Kit.codeBug(); if (firstDeleted >= 0) { index = firstDeleted; } else { // Need to consume empty entry: check occupation level if (keys == null || occupiedCount * 4 >= (1 << power) * 3) { // Too litle unused entries: rehash rehashTable(); return insertNewKey(key, hash); } ++occupiedCount; } keys[index] = key; values[(1 << power) + index] = hash; ++keyCount; return index; } private void writeObject(ObjectOutputStream out) throws IOException { out.defaultWriteObject(); int count = keyCount; for (int i = 0; count != 0; ++i) { Object key = keys[i]; if (key != null && key != DELETED) { --count; out.writeObject(key); out.writeInt(values[i]); } } } private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { in.defaultReadObject(); int writtenKeyCount = keyCount; if (writtenKeyCount != 0) { keyCount = 0; int N = 1 << power; keys = new Object[N]; values = new int[2 * N]; for (int i = 0; i != writtenKeyCount; ++i) { Object key = in.readObject(); int hash = key.hashCode(); int index = insertNewKey(key, hash); values[index] = in.readInt(); } } } // A == golden_ratio * (1 << 32) = ((sqrt(5) - 1) / 2) * (1 << 32) // See Knuth etc. private static final int A = 0x9e3779b9; private static final Object DELETED = new Object(); // Structure of kyes and values arrays (N == 1 << power): // keys[0 <= i < N]: key value or null or DELETED mark // values[0 <= i < N]: value of key at keys[i] // values[N <= i < 2*N]: hash code of key at keys[i-N] private transient Object[] keys; private transient int[] values; private int power; private int keyCount; private transient int occupiedCount; // == keyCount + deleted_count // If true, enables consitency checks private static final boolean check = false; /* TEST START public static void main(String[] args) { if (!check) { System.err.println("Set check to true and re-run"); throw new RuntimeException("Set check to true and re-run"); } ObjToIntMap map; map = new ObjToIntMap(0); testHash(map, 3); map = new ObjToIntMap(0); testHash(map, 10 * 1000); map = new ObjToIntMap(); testHash(map, 10 * 1000); map = new ObjToIntMap(30 * 1000); testHash(map, 10 * 100); map.clear(); testHash(map, 4); map = new ObjToIntMap(0); testHash(map, 10 * 100); } private static void testHash(ObjToIntMap map, int N) { System.out.print("."); System.out.flush(); for (int i = 0; i != N; ++i) { Object key = testKey(i); check(-1 == map.get(key, -1)); map.put(key, i); check(i == map.get(key, -1)); } System.out.print("."); System.out.flush(); for (int i = 0; i != N; ++i) { Object key = testKey(i); map.put(key, i); check(i == map.get(key, -1)); } check(map.size() == N); System.out.print("."); System.out.flush(); Object[] keys = map.getKeys(); check(keys.length == N); for (int i = 0; i != N; ++i) { Object key = keys[i]; check(map.has(key)); } System.out.print("."); System.out.flush(); for (int i = 0; i != N; ++i) { Object key = testKey(i); check(i == map.get(key, -1)); } int Nsqrt = -1; for (int i = 0; ; ++i) { if (i * i >= N) { Nsqrt = i; break; } } System.out.print("."); System.out.flush(); for (int i = 0; i != N; ++i) { Object key = testKey(i * i); map.put(key, i); check(i == map.get(key, -1)); } check(map.size() == 2 * N - Nsqrt); System.out.print("."); System.out.flush(); for (int i = 0; i != N; ++i) { Object key = testKey(i * i); check(i == map.get(key, -1)); } System.out.print("."); System.out.flush(); for (int i = 0; i != N; ++i) { Object key = testKey(-1 - i * i); map.put(key, i); check(i == map.get(key, -1)); } check(map.size() == 3 * N - Nsqrt); System.out.print("."); System.out.flush(); for (int i = 0; i != N; ++i) { Object key = testKey(-1 - i * i); map.remove(key); check(!map.has(key)); } check(map.size() == 2 * N - Nsqrt); System.out.print("."); System.out.flush(); for (int i = 0; i != N; ++i) { Object key = testKey(i * i); check(i == map.get(key, -1)); } System.out.print("."); System.out.flush(); for (int i = 0; i != N; ++i) { Object key = testKey(i); int j = intSqrt(i); if (j * j == i) { check(j == map.get(key, -1)); }else { check(i == map.get(key, -1)); } } System.out.print("."); System.out.flush(); for (int i = 0; i != N; ++i) { Object key = testKey(i * i); map.remove(key); check(-2 == map.get(key, -2)); } System.out.print("."); System.out.flush(); for (int i = 0; i != N; ++i) { Object key = testKey(i); map.put(key, i); check(i == map.get(key, -2)); } check(map.size() == N); System.out.print("."); System.out.flush(); for (int i = 0; i != N; ++i) { Object key = testKey(i); check(i == map.get(key, -1)); } System.out.print("."); System.out.flush(); ObjToIntMap copy = (ObjToIntMap)writeAndRead(map); check(copy.size() == N); for (int i = 0; i != N; ++i) { Object key = testKey(i); check(i == copy.get(key, -1)); } System.out.print("."); System.out.flush(); checkSameMaps(copy, map); System.out.println(); System.out.flush(); } private static void checkSameMaps(ObjToIntMap map1, ObjToIntMap map2) { check(map1.size() == map2.size()); Object[] keys = map1.getKeys(); check(keys.length == map1.size()); for (int i = 0; i != keys.length; ++i) { check(map1.get(keys[i], -1) == map2.get(keys[i], -1)); } } private static void check(boolean condition) { if (!condition) Kit.codeBug(); } private static Object[] testPool; private static Object testKey(int i) { int MAX_POOL = 100; if (0 <= i && i < MAX_POOL) { if (testPool != null && testPool[i] != null) { return testPool[i]; } } Object x = new Double(i + 0.5); if (0 <= i && i < MAX_POOL) { if (testPool == null) { testPool = new Object[MAX_POOL]; } testPool[i] = x; } return x; } private static int intSqrt(int i) { int approx = (int)Math.sqrt(i) + 1; while (approx * approx > i) { --approx; } return approx; } private static Object writeAndRead(Object obj) { try { java.io.ByteArrayOutputStream bos = new java.io.ByteArrayOutputStream(); java.io.ObjectOutputStream out = new java.io.ObjectOutputStream(bos); out.writeObject(obj); out.close(); byte[] data = bos.toByteArray(); java.io.ByteArrayInputStream bis = new java.io.ByteArrayInputStream(data); java.io.ObjectInputStream in = new java.io.ObjectInputStream(bis); Object result = in.readObject(); in.close(); return result; }catch (Exception ex) { throw new RuntimeException("Unexpected"); } } // TEST END */ } htmlunit-core-js-2.8/rhino/src/org/mozilla/javascript/Icode.java0000644000175000017500000002522011222455466024617 0ustar cavedoncavedon/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- * * ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is Rhino code, released * May 6, 1999. * * The Initial Developer of the Original Code is * Netscape Communications Corporation. * Portions created by the Initial Developer are Copyright (C) 1997-1999 * the Initial Developer. All Rights Reserved. * * Contributor(s): * Mike Ang * Igor Bukanov * Yuh-Ruey Chen * Ethan Hugg * Bob Jervis * Terry Lucas * Mike McCabe * Milen Nankov * Norris Boyd * Steve Yegge * * Alternatively, the contents of this file may be used under the terms of * the GNU General Public License Version 2 or later (the "GPL"), in which * case the provisions of the GPL are applicable instead of those above. If * you wish to allow use of your version of this file only under the terms of * the GPL and not to allow others to use your version of this file under the * MPL, indicate your decision by deleting the provisions above and replacing * them with the notice and other provisions required by the GPL. If you do * not delete the provisions above, a recipient may use your version of this * file under either the MPL or the GPL. * * ***** END LICENSE BLOCK ***** */ package org.mozilla.javascript; /** * Additional interpreter-specific codes */ abstract class Icode { static final int // 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 unefined 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 <= -1; } 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); } } htmlunit-core-js-2.8/rhino/src/org/mozilla/javascript/IdFunctionCall.java0000644000175000017500000000405310776622373026441 0ustar cavedoncavedon/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- * * ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is Rhino code, released * May 6, 1999. * * The Initial Developer of the Original Code is * Netscape Communications Corporation. * Portions created by the Initial Developer are Copyright (C) 1997-1999 * the Initial Developer. All Rights Reserved. * * Contributor(s): * Igor Bukanov * * Alternatively, the contents of this file may be used under the terms of * the GNU General Public License Version 2 or later (the "GPL"), in which * case the provisions of the GPL are applicable instead of those above. If * you wish to allow use of your version of this file only under the terms of * the GPL and not to allow others to use your version of this file under the * MPL, indicate your decision by deleting the provisions above and replacing * them with the notice and other provisions required by the GPL. If you do * not delete the provisions above, a recipient may use your version of this * file under either the MPL or the GPL. * * ***** END LICENSE BLOCK ***** */ package org.mozilla.javascript; /** * 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); } htmlunit-core-js-2.8/rhino/src/org/mozilla/javascript/SecureCaller.java0000644000175000017500000001640610776622373026161 0ustar cavedoncavedon/* ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is Rhino code, released May 6, 1999. * * The Initial Developer of the Original Code is * Netscape Communications Corporation. * Portions created by the Initial Developer are Copyright (C) 1997-1999 * the Initial Developer. All Rights Reserved. * * Contributor(s): * * Alternatively, the contents of this file may be used under the terms of * the GNU General Public License Version 2 or later (the "GPL"), in which * case the provisions of the GPL are applicable instead of those above. If * you wish to allow use of your version of this file only under the terms of * the GPL and not to allow others to use your version of this file under the * MPL, indicate your decision by deleting the provisions above and replacing * them with the notice and other provisions required by the GPL. If you do * not delete the provisions above, a recipient may use your version of this * file under either the MPL or the GPL. * * ***** END LICENSE BLOCK ***** */ package org.mozilla.javascript; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.lang.ref.SoftReference; import java.lang.reflect.UndeclaredThrowableException; import java.net.URL; import java.security.AccessController; import java.security.CodeSource; import java.security.PrivilegedAction; import java.security.PrivilegedActionException; import java.security.PrivilegedExceptionAction; import java.security.SecureClassLoader; import java.util.Map; import java.util.WeakHashMap; /** * @author Attila Szegedi */ public abstract class SecureCaller { private static final byte[] secureCallerImplBytecode = loadBytecode(); // We're storing a CodeSource -> (ClassLoader -> SecureRenderer), since we // need to have one renderer per class loader. We're using weak hash maps // and soft references all the way, since we don't want to interfere with // cleanup of either CodeSource or ClassLoader objects. private static final Map>> callers = new WeakHashMap>>(); public abstract Object call(Callable callable, Context cx, Scriptable scope, Scriptable thisObj, Object[] args); /** * Call the specified callable using a protection domain belonging to the * specified code source. */ static Object callSecurely(final CodeSource codeSource, Callable callable, Context cx, Scriptable scope, Scriptable thisObj, Object[] args) { final Thread thread = Thread.currentThread(); // Run in doPrivileged as we might be checked for "getClassLoader" // runtime permission final ClassLoader classLoader = (ClassLoader)AccessController.doPrivileged( new PrivilegedAction() { public Object run() { return thread.getContextClassLoader(); } }); Map> classLoaderMap; synchronized(callers) { classLoaderMap = callers.get(codeSource); if(classLoaderMap == null) { classLoaderMap = new WeakHashMap>(); callers.put(codeSource, classLoaderMap); } } SecureCaller caller; synchronized(classLoaderMap) { SoftReference ref = classLoaderMap.get(classLoader); if (ref != null) { caller = ref.get(); } else { caller = null; } if (caller == null) { try { // Run in doPrivileged as we'll be checked for // "createClassLoader" runtime permission caller = (SecureCaller)AccessController.doPrivileged( new PrivilegedExceptionAction() { public Object run() throws Exception { ClassLoader effectiveClassLoader; Class thisClass = getClass(); if(classLoader.loadClass(thisClass.getName()) != thisClass) { effectiveClassLoader = thisClass.getClassLoader(); } else { effectiveClassLoader = classLoader; } SecureClassLoaderImpl secCl = new SecureClassLoaderImpl(effectiveClassLoader); Class c = secCl.defineAndLinkClass( SecureCaller.class.getName() + "Impl", secureCallerImplBytecode, codeSource); return c.newInstance(); } }); classLoaderMap.put(classLoader, new SoftReference(caller)); } catch(PrivilegedActionException ex) { throw new UndeclaredThrowableException(ex.getCause()); } } } return caller.call(callable, cx, scope, thisObj, args); } private static class SecureClassLoaderImpl extends SecureClassLoader { SecureClassLoaderImpl(ClassLoader parent) { super(parent); } Class defineAndLinkClass(String name, byte[] bytes, CodeSource cs) { Class cl = defineClass(name, bytes, 0, bytes.length, cs); resolveClass(cl); return cl; } } private static byte[] loadBytecode() { return (byte[])AccessController.doPrivileged(new PrivilegedAction() { public Object run() { return loadBytecodePrivileged(); } }); } private static byte[] loadBytecodePrivileged() { URL url = SecureCaller.class.getResource("SecureCallerImpl.clazz"); try { InputStream in = url.openStream(); try { ByteArrayOutputStream bout = new ByteArrayOutputStream(); for(;;) { int r = in.read(); if(r == -1) { return bout.toByteArray(); } bout.write(r); } } finally { in.close(); } } catch(IOException e) { throw new UndeclaredThrowableException(e); } } } htmlunit-core-js-2.8/rhino/src/org/mozilla/javascript/NativeJavaClass.java0000644000175000017500000003027611222455466026621 0ustar cavedoncavedon/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- * * ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is Rhino code, released * May 6, 1999. * * The Initial Developer of the Original Code is * Netscape Communications Corporation. * Portions created by the Initial Developer are Copyright (C) 1997-1999 * the Initial Developer. All Rights Reserved. * * Contributor(s): * Norris Boyd * Frank Mitchell * Mike Shaver * Kurt Westerfeld * Kemal Bayram * Ulrike Mueller * * Alternatively, the contents of this file may be used under the terms of * the GNU General Public License Version 2 or later (the "GPL"), in which * case the provisions of the GPL are applicable instead of those above. If * you wish to allow use of your version of this file only under the terms of * the GPL and not to allow others to use your version of this file under the * MPL, indicate your decision by deleting the provisions above and replacing * them with the notice and other provisions required by the GPL. If you do * not delete the provisions above, a recipient may use your version of this * file under either the MPL or the GPL. * * ***** END LICENSE BLOCK ***** */ package org.mozilla.javascript; import java.lang.reflect.*; import java.util.Map; /** * This class reflects Java classes into the JavaScript environment, mainly * for constructors and static members. We lazily reflect properties, * and currently do not guarantee that a single j.l.Class is only * reflected once into the JS environment, although we should. * The only known case where multiple reflections * are possible occurs when a j.l.Class is wrapped as part of a * method return or property access, rather than by walking the * Packages/java tree. * * @author Mike Shaver * @see NativeJavaArray * @see NativeJavaObject * @see NativeJavaPackage */ public class NativeJavaClass extends NativeJavaObject implements Function { static final long serialVersionUID = -6460763940409461664L; // Special property for getting the underlying Java class object. static final String javaClassPropertyName = "__javaObject__"; public NativeJavaClass() { } public NativeJavaClass(Scriptable scope, Class cl) { this.parent = scope; this.javaObject = cl; initMembers(); } @Override protected void initMembers() { Class cl = (Class)javaObject; members = JavaMembers.lookupClass(parent, cl, cl, false); staticFieldAndMethods = members.getFieldAndMethodsObjects(this, cl, true); } @Override public String getClassName() { return "JavaClass"; } @Override public boolean has(String name, Scriptable start) { return members.has(name, true) || javaClassPropertyName.equals(name); } @Override public Object get(String name, Scriptable start) { // When used as a constructor, ScriptRuntime.newObject() asks // for our prototype to create an object of the correct type. // We don't really care what the object is, since we're returning // one constructed out of whole cloth, so we return null. if (name.equals("prototype")) return null; if (staticFieldAndMethods != null) { Object result = staticFieldAndMethods.get(name); if (result != null) return result; } if (members.has(name, true)) { return members.get(this, name, javaObject, true); } if (javaClassPropertyName.equals(name)) { Context cx = Context.getContext(); Scriptable scope = ScriptableObject.getTopLevelScope(start); return cx.getWrapFactory().wrap(cx, scope, javaObject, ScriptRuntime.ClassClass); } // experimental: look for nested classes by appending $name to // current class' name. Class nestedClass = findNestedClass(getClassObject(), name); if (nestedClass != null) { NativeJavaClass nestedValue = new NativeJavaClass (ScriptableObject.getTopLevelScope(this), nestedClass); nestedValue.setParentScope(this); return nestedValue; } throw members.reportMemberNotFound(name); } @Override public void put(String name, Scriptable start, Object value) { members.put(this, name, javaObject, value, true); } @Override public Object[] getIds() { return members.getIds(true); } public Class getClassObject() { return (Class) super.unwrap(); } @Override public Object getDefaultValue(Class hint) { if (hint == null || hint == ScriptRuntime.StringClass) return this.toString(); if (hint == ScriptRuntime.BooleanClass) return Boolean.TRUE; if (hint == ScriptRuntime.NumberClass) return ScriptRuntime.NaNobj; return this; } public Object call(Context cx, Scriptable scope, Scriptable thisObj, Object[] args) { // If it looks like a "cast" of an object to this class type, // walk the prototype chain to see if there's a wrapper of a // object that's an instanceof this class. if (args.length == 1 && args[0] instanceof Scriptable) { Class c = getClassObject(); Scriptable p = (Scriptable) args[0]; do { if (p instanceof Wrapper) { Object o = ((Wrapper) p).unwrap(); if (c.isInstance(o)) return p; } p = p.getPrototype(); } while (p != null); } return construct(cx, scope, args); } public Scriptable construct(Context cx, Scriptable scope, Object[] args) { Class classObject = getClassObject(); int modifiers = classObject.getModifiers(); if (! (Modifier.isInterface(modifiers) || Modifier.isAbstract(modifiers))) { MemberBox[] ctors = members.ctors; int index = NativeJavaMethod.findFunction(cx, ctors, args); if (index < 0) { String sig = NativeJavaMethod.scriptSignature(args); throw Context.reportRuntimeError2( "msg.no.java.ctor", classObject.getName(), sig); } // Found the constructor, so try invoking it. return constructSpecific(cx, scope, args, ctors[index]); } else { Scriptable topLevel = ScriptableObject.getTopLevelScope(this); String msg = ""; try { // trying to construct an interface; use JavaAdapter to // construct a new class on the fly that implements this // interface. Object v = topLevel.get("JavaAdapter", topLevel); if (v != NOT_FOUND) { Function f = (Function) v; // Args are (interface, js object) Object[] adapterArgs = { this, args[0] }; return f.construct(cx, topLevel, adapterArgs); } } catch (Exception ex) { // fall through to error String m = ex.getMessage(); if (m != null) msg = m; } throw Context.reportRuntimeError2( "msg.cant.instantiate", msg, classObject.getName()); } } static Scriptable constructSpecific(Context cx, Scriptable scope, Object[] args, MemberBox ctor) { Scriptable topLevel = ScriptableObject.getTopLevelScope(scope); Class[] argTypes = ctor.argTypes; if (ctor.vararg) { // marshall the explicit parameter Object[] newArgs = new Object[argTypes.length]; for (int i = 0; i < argTypes.length-1; i++) { newArgs[i] = Context.jsToJava(args[i], argTypes[i]); } Object varArgs; // Handle special situation where a single variable parameter // is given and it is a Java or ECMA array. if (args.length == argTypes.length && (args[args.length-1] == null || args[args.length-1] instanceof NativeArray || args[args.length-1] instanceof NativeJavaArray)) { // convert the ECMA array into a native array varArgs = Context.jsToJava(args[args.length-1], argTypes[argTypes.length - 1]); } else { // marshall the variable parameter Class componentType = argTypes[argTypes.length - 1]. getComponentType(); varArgs = Array.newInstance(componentType, args.length - argTypes.length + 1); for (int i=0; i < Array.getLength(varArgs); i++) { Object value = Context.jsToJava(args[argTypes.length-1 + i], componentType); Array.set(varArgs, i, value); } } // add varargs newArgs[argTypes.length-1] = varArgs; // replace the original args with the new one args = newArgs; } else { Object[] origArgs = args; for (int i = 0; i < args.length; i++) { Object arg = args[i]; Object x = Context.jsToJava(arg, argTypes[i]); if (x != arg) { if (args == origArgs) { args = origArgs.clone(); } args[i] = x; } } } Object instance = ctor.newInstance(args); // we need to force this to be wrapped, because construct _has_ // to return a scriptable return cx.getWrapFactory().wrapNewObject(cx, topLevel, instance); } @Override public String toString() { return "[JavaClass " + getClassObject().getName() + "]"; } /** * Determines if prototype is a wrapped Java object and performs * a Java "instanceof". * Exception: if value is an instance of NativeJavaClass, it isn't * considered an instance of the Java class; this forestalls any * name conflicts between java.lang.Class's methods and the * static methods exposed by a JavaNativeClass. */ @Override public boolean hasInstance(Scriptable value) { if (value instanceof Wrapper && !(value instanceof NativeJavaClass)) { Object instance = ((Wrapper)value).unwrap(); return getClassObject().isInstance(instance); } // value wasn't something we understand return false; } private static Class findNestedClass(Class parentClass, String name) { String nestedClassName = parentClass.getName() + '$' + name; ClassLoader loader = parentClass.getClassLoader(); if (loader == null) { // ALERT: if loader is null, nested class should be loaded // via system class loader which can be different from the // loader that brought Rhino classes that Class.forName() would // use, but ClassLoader.getSystemClassLoader() is Java 2 only return Kit.classOrNull(nestedClassName); } else { return Kit.classOrNull(loader, nestedClassName); } } private Map staticFieldAndMethods; } htmlunit-core-js-2.8/rhino/src/org/mozilla/javascript/CompilerEnvirons.java0000644000175000017500000002377211222455466027104 0ustar cavedoncavedon/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- * * ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is Rhino code, released * May 6, 1999. * * The Initial Developer of the Original Code is * Netscape Communications Corporation. * Portions created by the Initial Developer are Copyright (C) 1997-1999 * the Initial Developer. All Rights Reserved. * * Contributor(s): * Igor Bukanov, igor@fastmail.fm * Bob Jervis * Steve Yegge * * Alternatively, the contents of this file may be used under the terms of * the GNU General Public License Version 2 or later (the "GPL"), in which * case the provisions of the GPL are applicable instead of those above. If * you wish to allow use of your version of this file only under the terms of * the GPL and not to allow others to use your version of this file under the * MPL, indicate your decision by deleting the provisions above and replacing * them with the notice and other provisions required by the GPL. If you do * not delete the provisions above, a recipient may use your version of this * file under either the MPL or the GPL. * * ***** END LICENSE BLOCK ***** */ package org.mozilla.javascript; import java.util.Set; import org.mozilla.javascript.ast.ErrorCollector; public class CompilerEnvirons { public CompilerEnvirons() { errorReporter = DefaultErrorReporter.instance; languageVersion = Context.VERSION_DEFAULT; generateDebugInfo = true; useDynamicScope = false; reservedKeywordAsIdentifier = false; allowMemberExprAsFunctionName = false; xmlAvailable = true; optimizationLevel = 0; generatingSource = true; strictMode = false; warningAsError = false; generateObserverCount = false; allowSharpComments = false; } public void initFromContext(Context cx) { setErrorReporter(cx.getErrorReporter()); this.languageVersion = cx.getLanguageVersion(); useDynamicScope = cx.compileFunctionsWithDynamicScopeFlag; 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 isUseDynamicScope() { return useDynamicScope; } public final boolean isReservedKeywordAsIdentifier() { return reservedKeywordAsIdentifier; } public void setReservedKeywordAsIdentifier(boolean flag) { reservedKeywordAsIdentifier = flag; } /** * Extension to ECMA: if 'function <name>' is not followed * by '(', assume <name> 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. *

* 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 getActivationNames() { return activationNames; } public void setActivationNames(Set 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 useDynamicScope; 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 activationNames; } htmlunit-core-js-2.8/rhino/src/org/mozilla/javascript/InterfaceAdapter.java0000644000175000017500000001344410776622373027010 0ustar cavedoncavedon/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- * * ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is Rhino code, released * May 6, 1999. * * The Initial Developer of the Original Code is * Netscape Communications Corporation. * Portions created by the Initial Developer are Copyright (C) 1997-1999 * the Initial Developer. All Rights Reserved. * * Contributor(s): * Igor Bukanov * * Alternatively, the contents of this file may be used under the terms of * the GNU General Public License Version 2 or later (the "GPL"), in which * case the provisions of the GPL are applicable instead of those above. If * you wish to allow use of your version of this file only under the terms of * the GPL and not to allow others to use your version of this file under the * MPL, indicate your decision by deleting the provisions above and replacing * them with the notice and other provisions required by the GPL. If you do * not delete the provisions above, a recipient may use your version of this * file under either the MPL or the GPL. * * ***** END LICENSE BLOCK ***** */ package org.mozilla.javascript; import java.lang.reflect.Method; /** * Adapter to use JS function as implementation of Java interfaces with * single method or multiple methods with the same signature. */ public class InterfaceAdapter { private final Object proxyHelper; /** * Make glue object implementing interface cl that will * call the supplied JS function when called. * Only interfaces were all methods have the same signature is supported. * * @return The glue object or null if cl is not interface or * has methods with different signatures. */ static Object create(Context cx, Class cl, Callable function) { if (!cl.isInterface()) throw new IllegalArgumentException(); Scriptable topScope = ScriptRuntime.getTopCallScope(cx); ClassCache cache = ClassCache.get(topScope); InterfaceAdapter adapter; adapter = (InterfaceAdapter)cache.getInterfaceAdapter(cl); ContextFactory cf = cx.getFactory(); if (adapter == null) { Method[] methods = cl.getMethods(); if (methods.length == 0) { throw Context.reportRuntimeError2( "msg.no.empty.interface.conversion", String.valueOf(function), cl.getClass().getName()); } boolean canCallFunction = false; canCallFunctionChecks: { Class[] argTypes = methods[0].getParameterTypes(); // check that the rest of methods has the same signature for (int i = 1; i != methods.length; ++i) { Class[] types2 = methods[i].getParameterTypes(); if (types2.length != argTypes.length) { break canCallFunctionChecks; } for (int j = 0; j != argTypes.length; ++j) { if (types2[j] != argTypes[j]) { break canCallFunctionChecks; } } } canCallFunction= true; } if (!canCallFunction) { throw Context.reportRuntimeError2( "msg.no.function.interface.conversion", String.valueOf(function), cl.getClass().getName()); } adapter = new InterfaceAdapter(cf, cl); cache.cacheInterfaceAdapter(cl, adapter); } return VMBridge.instance.newInterfaceProxy( adapter.proxyHelper, cf, adapter, function, topScope); } private InterfaceAdapter(ContextFactory cf, Class cl) { this.proxyHelper = VMBridge.instance.getInterfaceProxyHelper( cf, new Class[] { cl }); } public Object invoke(ContextFactory cf, final Object target, final Scriptable topScope, final Method method, final Object[] args) { ContextAction action = new ContextAction() { public Object run(Context cx) { return invokeImpl(cx, target, topScope, method, args); } }; return cf.call(action); } Object invokeImpl(Context cx, Object target, Scriptable topScope, Method method, Object[] args) { int N = (args == null) ? 0 : args.length; Callable function = (Callable)target; Scriptable thisObj = topScope; Object[] jsargs = new Object[N + 1]; jsargs[N] = method.getName(); if (N != 0) { WrapFactory wf = cx.getWrapFactory(); for (int i = 0; i != N; ++i) { jsargs[i] = wf.wrap(cx, topScope, args[i], null); } } Object result = function.call(cx, topScope, thisObj, jsargs); Class javaResultType = method.getReturnType(); if (javaResultType == Void.TYPE) { result = null; } else { result = Context.jsToJava(result, javaResultType); } return result; } } htmlunit-core-js-2.8/rhino/src/org/mozilla/javascript/MemberBox.java0000644000175000017500000003015311332527432025450 0ustar cavedoncavedon/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- * * ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is Rhino code, released * May 6, 1999. * * The Initial Developer of the Original Code is * Netscape Communications Corporation. * Portions created by the Initial Developer are Copyright (C) 1997-1999 * the Initial Developer. All Rights Reserved. * * Contributor(s): * Igor Bukanov * Felix Meschberger * Norris Boyd * Ulrike Mueller * * Alternatively, the contents of this file may be used under the terms of * the GNU General Public License Version 2 or later (the "GPL"), in which * case the provisions of the GPL are applicable instead of those above. If * you wish to allow use of your version of this file only under the terms of * the GPL and not to allow others to use your version of this file under the * MPL, indicate your decision by deleting the provisions above and replacing * them with the notice and other provisions required by the GPL. If you do * not delete the provisions above, a recipient may use your version of this * file under either the MPL or the GPL. * * ***** END LICENSE BLOCK ***** */ package org.mozilla.javascript; import java.lang.reflect.*; import java.io.*; /** * Wrappper class for Method and Constructor instances to cache * getParameterTypes() results, recover from IllegalAccessException * in some cases and provide serialization support. * * @author Igor Bukanov */ final class MemberBox implements Serializable { static final long serialVersionUID = 6358550398665688245L; private transient Member memberObject; transient Class[] argTypes; transient Object delegateTo; transient boolean vararg; MemberBox(Method method) { init(method); } MemberBox(Constructor constructor) { init(constructor); } private void init(Method method) { this.memberObject = method; this.argTypes = method.getParameterTypes(); this.vararg = VMBridge.instance.isVarArgs(method); } private void init(Constructor constructor) { this.memberObject = constructor; this.argTypes = constructor.getParameterTypes(); this.vararg = VMBridge.instance.isVarArgs(constructor); } Method method() { return (Method)memberObject; } Constructor ctor() { return (Constructor)memberObject; } Member member() { return memberObject; } boolean isMethod() { return memberObject instanceof Method; } boolean isCtor() { return memberObject instanceof Constructor; } boolean isStatic() { return Modifier.isStatic(memberObject.getModifiers()); } String getName() { return memberObject.getName(); } Class getDeclaringClass() { return memberObject.getDeclaringClass(); } String toJavaDeclaration() { StringBuffer sb = new StringBuffer(); if (isMethod()) { Method method = method(); sb.append(method.getReturnType()); sb.append(' '); sb.append(method.getName()); } else { Constructor ctor = ctor(); String name = ctor.getDeclaringClass().getName(); int lastDot = name.lastIndexOf('.'); if (lastDot >= 0) { name = name.substring(lastDot + 1); } sb.append(name); } sb.append(JavaMembers.liveConnectSignature(argTypes)); return sb.toString(); } @Override public String toString() { return memberObject.toString(); } Object invoke(Object target, Object[] args) { Method method = method(); // handle delegators if (target instanceof Delegator) { target = ((Delegator) target).getDelegee(); } for (int i=0; i ctor = ctor(); try { try { return ctor.newInstance(args); } catch (IllegalAccessException ex) { if (!VMBridge.instance.tryToMakeAccessible(ctor)) { throw Context.throwAsScriptRuntimeEx(ex); } } return ctor.newInstance(args); } catch (Exception ex) { throw Context.throwAsScriptRuntimeEx(ex); } } private static Method searchAccessibleMethod(Method method, Class[] params) { int modifiers = method.getModifiers(); if (Modifier.isPublic(modifiers) && !Modifier.isStatic(modifiers)) { Class c = method.getDeclaringClass(); if (!Modifier.isPublic(c.getModifiers())) { String name = method.getName(); Class[] intfs = c.getInterfaces(); for (int i = 0, N = intfs.length; i != N; ++i) { Class intf = intfs[i]; if (Modifier.isPublic(intf.getModifiers())) { try { return intf.getMethod(name, params); } catch (NoSuchMethodException ex) { } catch (SecurityException ex) { } } } for (;;) { c = c.getSuperclass(); if (c == null) { break; } if (Modifier.isPublic(c.getModifiers())) { try { Method m = c.getMethod(name, params); int mModifiers = m.getModifiers(); if (Modifier.isPublic(mModifiers) && !Modifier.isStatic(mModifiers)) { return m; } } catch (NoSuchMethodException ex) { } catch (SecurityException ex) { } } } } } return null; } private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { in.defaultReadObject(); Member member = readMember(in); if (member instanceof Method) { init((Method)member); } else { init((Constructor)member); } } private void writeObject(ObjectOutputStream out) throws IOException { out.defaultWriteObject(); writeMember(out, memberObject); } /** * Writes a Constructor or Method object. * * Methods and Constructors are not serializable, so we must serialize * information about the class, the name, and the parameters and * recreate upon deserialization. */ private static void writeMember(ObjectOutputStream out, Member member) throws IOException { if (member == null) { out.writeBoolean(false); return; } out.writeBoolean(true); if (!(member instanceof Method || member instanceof Constructor)) throw new IllegalArgumentException("not Method or Constructor"); out.writeBoolean(member instanceof Method); out.writeObject(member.getName()); out.writeObject(member.getDeclaringClass()); if (member instanceof Method) { writeParameters(out, ((Method) member).getParameterTypes()); } else { writeParameters(out, ((Constructor) member).getParameterTypes()); } } /** * Reads a Method or a Constructor from the stream. */ private static Member readMember(ObjectInputStream in) throws IOException, ClassNotFoundException { if (!in.readBoolean()) return null; boolean isMethod = in.readBoolean(); String name = (String) in.readObject(); Class declaring = (Class) in.readObject(); Class[] parms = readParameters(in); try { if (isMethod) { return declaring.getMethod(name, parms); } else { return declaring.getConstructor(parms); } } catch (NoSuchMethodException e) { throw new IOException("Cannot find member: " + e); } } private static final Class[] primitives = { Boolean.TYPE, Byte.TYPE, Character.TYPE, Double.TYPE, Float.TYPE, Integer.TYPE, Long.TYPE, Short.TYPE, Void.TYPE }; /** * Writes an array of parameter types to the stream. * * Requires special handling because primitive types cannot be * found upon deserialization by the default Java implementation. */ private static void writeParameters(ObjectOutputStream out, Class[] parms) throws IOException { out.writeShort(parms.length); outer: for (int i=0; i < parms.length; i++) { Class parm = parms[i]; boolean primitive = parm.isPrimitive(); out.writeBoolean(primitive); if (!primitive) { out.writeObject(parm); continue; } for (int j=0; j < primitives.length; j++) { if (parm.equals(primitives[j])) { out.writeByte(j); continue outer; } } throw new IllegalArgumentException("Primitive " + parm + " not found"); } } /** * Reads an array of parameter types from the stream. */ private static Class[] readParameters(ObjectInputStream in) throws IOException, ClassNotFoundException { Class[] result = new Class[in.readShort()]; for (int i=0; i < result.length; i++) { if (!in.readBoolean()) { result[i] = (Class) in.readObject(); continue; } result[i] = primitives[in.readByte()]; } return result; } } htmlunit-core-js-2.8/rhino/src/org/mozilla/javascript/ClassShutter.java0000644000175000017500000000740110776622373026227 0ustar cavedoncavedon/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- * * ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is Rhino code, released * May 6, 1999. * * The Initial Developer of the Original Code is * Netscape Communications Corporation. * Portions created by the Initial Developer are Copyright (C) 1997-1999 * the Initial Developer. All Rights Reserved. * * Contributor(s): * Norris Boyd * Igor Bukanov * * Alternatively, the contents of this file may be used under the terms of * the GNU General Public License Version 2 or later (the "GPL"), in which * case the provisions of the GPL are applicable instead of those above. If * you wish to allow use of your version of this file only under the terms of * the GPL and not to allow others to use your version of this file under the * MPL, indicate your decision by deleting the provisions above and replacing * them with the notice and other provisions required by the GPL. If you do * not delete the provisions above, a recipient may use your version of this * file under either the MPL or the GPL. * * ***** END LICENSE BLOCK ***** */ // 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. *

* An embedding may filter which Java classes are exposed through * LiveConnect to JavaScript scripts. *

* 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. *

* 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. *

* @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); } htmlunit-core-js-2.8/rhino/src/org/mozilla/classfile/0000755000175000017500000000000011530107756022525 5ustar cavedoncavedonhtmlunit-core-js-2.8/rhino/src/org/mozilla/classfile/ClassFileWriter.java0000644000175000017500000032655511321335670026446 0ustar cavedoncavedon/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- * * ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is Rhino code, released * May 6, 1999. * * The Initial Developer of the Original Code is * Netscape Communications Corporation. * Portions created by the Initial Developer are Copyright (C) 1997-1999 * the Initial Developer. All Rights Reserved. * * Contributor(s): * Roger Lawrence * * Alternatively, the contents of this file may be used under the terms of * the GNU General Public License Version 2 or later (the "GPL"), in which * case the provisions of the GPL are applicable instead of those above. If * you wish to allow use of your version of this file only under the terms of * the GPL and not to allow others to use your version of this file under the * MPL, indicate your decision by deleting the provisions above and replacing * them with the notice and other provisions required by the GPL. If you do * not delete the provisions above, a recipient may use your version of this * file under either the MPL or the GPL. * * ***** END LICENSE BLOCK ***** */ package org.mozilla.classfile; import org.mozilla.javascript.ObjToIntMap; import org.mozilla.javascript.ObjArray; import org.mozilla.javascript.UintMap; import java.io.*; /** * 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); itsFlags = ACC_PUBLIC; } 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_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(methodNameIndex, typeIndex, flags); itsMethods.add(itsCurrentMethod); } /** * Complete generation of the method. * * After this method is called, no more code can be added to the * method begun with startMethod. * * @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; 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 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; 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++; 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); } } itsCurrentMethod.setCodeAttribute(codeAttribute); itsExceptionTable = null; itsExceptionTableTop = 0; itsLineNumberTableTop = 0; itsCodeBufferTop = 0; itsCurrentMethod = null; itsMaxStack = 0; itsStackTop = 0; itsLabelTableTop = 0; itsFixupTableTop = 0; itsVarDescriptors = 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); } } /** * 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 : // 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); } 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); } 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 // StringBuffer sb = new StringBuffer(length); // sb.append(loadConstant(piece_1)); // ... // sb.append(loadConstant(piece_N)); // sb.toString(); final String SB = "java/lang/StringBuffer"; add(ByteCode.NEW, SB); add(ByteCode.DUP); addPush(length); addInvoke(ByteCode.INVOKESPECIAL, SB, "", "(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/StringBuffer;"); 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) { setTableSwitchJump(switchStart, -1, itsCodeBufferTop); } public final void markTableSwitchCase(int switchStart, int caseIndex) { 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; setTableSwitchJump(switchStart, caseIndex, itsCodeBufferTop); } 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); } private 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 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; } /** * 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 = putInt64(FileHeaderConstant, 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; // fall thru 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': // fall thru } // fall thru 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; // fall thru case 'B' : case 'S' : case 'C' : case 'I' : case 'Z' : case 'F' : case 'L' : case '[' : ++stackDiff; // fall thru 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; } /** * 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); } */ 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; } private static final int LineNumberTableSize = 16; private static final int ExceptionTableSize = 4; private final static long FileHeaderConstant = 0xCAFEBABE0003002DL; // 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(short nameIndex, short typeIndex, short flags) { itsNameIndex = nameIndex; 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; } 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; private 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); return (short)(itsTopIndex++); } int addConstant(long k) { ensure(9); itsPool[itsTop++] = CONSTANT_Long; itsTop = ClassFileWriter.putInt64(k, itsPool, itsTop); int index = itsTopIndex; itsTopIndex += 2; return index; } int addConstant(float k) { ensure(5); itsPool[itsTop++] = CONSTANT_Float; int bits = Float.floatToIntBits(k); itsTop = ClassFileWriter.putInt32(bits, itsPool, itsTop); 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; 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); } 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 start <= i <= end and * s.substring(start, i) 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"); } } 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); 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); } } } 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); } 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); } 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); return (short)(itsTopIndex++); } 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 byte itsPool[]; } final class FieldOrMethodRef { FieldOrMethodRef(String className, String name, String type) { this.className = className; this.name = name; this.type = 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; } htmlunit-core-js-2.8/rhino/src/org/mozilla/classfile/ByteCode.java0000644000175000017500000001560310776622373025103 0ustar cavedoncavedon/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- * * ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is Rhino code, released * May 6, 1999. * * The Initial Developer of the Original Code is * Netscape Communications Corporation. * Portions created by the Initial Developer are Copyright (C) 1997-1999 * the Initial Developer. All Rights Reserved. * * Contributor(s): * Roger Lawrence * * Alternatively, the contents of this file may be used under the terms of * the GNU General Public License Version 2 or later (the "GPL"), in which * case the provisions of the GPL are applicable instead of those above. If * you wish to allow use of your version of this file only under the terms of * the GPL and not to allow others to use your version of this file under the * MPL, indicate your decision by deleting the provisions above and replacing * them with the notice and other provisions required by the GPL. If you do * not delete the provisions above, a recipient may use your version of this * file under either the MPL or the GPL. * * ***** END LICENSE BLOCK ***** */ package org.mozilla.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; } htmlunit-core-js-2.8/rhino/build-date0000644000175000017500000000004710776624011017470 0ustar cavedoncavedonThis version was built on @datestamp@. htmlunit-core-js-2.8/rhino/examples/0000755000175000017500000000000011530107756017351 5ustar cavedoncavedonhtmlunit-core-js-2.8/rhino/examples/NervousText.html0000644000175000017500000000440310776624170022553 0ustar cavedoncavedon This is the NervousText applet in javascript:


The test assumes that applet code is generated with:
java -classpath js.jar org.mozilla.javascript.tools.jsc.Main \
  -extends java.applet.Applet \
  -implements java.lang.Runnable \
  NervousText.js
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.

The test also assumes that js.jar from Rhino distribution is available in the same directory. htmlunit-core-js-2.8/rhino/examples/checkParam.js0000644000175000017500000001010310776624170021745 0ustar cavedoncavedon/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- * * ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is Rhino code, released * May 6, 1999. * * The Initial Developer of the Original Code is * Netscape Communications Corporation. * Portions created by the Initial Developer are Copyright (C) 1997-1999 * the Initial Developer. All Rights Reserved. * * Contributor(s): * Norris Boyd * * Alternatively, the contents of this file may be used under the terms of * the GNU General Public License Version 2 or later (the "GPL"), in which * case the provisions of the GPL are applicable instead of those above. If * you wish to allow use of your version of this file only under the terms of * the GPL and not to allow others to use your version of this file under the * MPL, indicate your decision by deleting the provisions above and replacing * them with the notice and other provisions required by the GPL. If you do * not delete the provisions above, a recipient may use your version of this * file under either the MPL or the GPL. * * ***** END LICENSE BLOCK ***** */ /** * 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. *

* 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."); htmlunit-core-js-2.8/rhino/examples/liveConnect.js0000644000175000017500000000436610776624170022176 0ustar cavedoncavedon/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- * * ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is Rhino code, released * May 6, 1999. * * The Initial Developer of the Original Code is * Netscape Communications Corporation. * Portions created by the Initial Developer are Copyright (C) 1997-1999 * the Initial Developer. All Rights Reserved. * * Contributor(s): * Norris Boyd * * Alternatively, the contents of this file may be used under the terms of * the GNU General Public License Version 2 or later (the "GPL"), in which * case the provisions of the GPL are applicable instead of those above. If * you wish to allow use of your version of this file only under the terms of * the GPL and not to allow others to use your version of this file under the * MPL, indicate your decision by deleting the provisions above and replacing * them with the notice and other provisions required by the GPL. If you do * not delete the provisions above, a recipient may use your version of this * file under either the MPL or the GPL. * * ***** END LICENSE BLOCK ***** */ /** * 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); htmlunit-core-js-2.8/rhino/examples/unique.js0000644000175000017500000000416410776624170021227 0ustar cavedoncavedon/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- * * ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is Rhino code, released * May 6, 1999. * * The Initial Developer of the Original Code is * Netscape Communications Corporation. * Portions created by the Initial Developer are Copyright (C) 1997-1999 * the Initial Developer. All Rights Reserved. * * Contributor(s): * Norris Boyd * * Alternatively, the contents of this file may be used under the terms of * the GNU General Public License Version 2 or later (the "GPL"), in which * case the provisions of the GPL are applicable instead of those above. If * you wish to allow use of your version of this file only under the terms of * the GPL and not to allow others to use your version of this file under the * MPL, indicate your decision by deleting the provisions above and replacing * them with the notice and other provisions required by the GPL. If you do * not delete the provisions above, a recipient may use your version of this * file under either the MPL or the GPL. * * ***** END LICENSE BLOCK ***** */ // 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); } htmlunit-core-js-2.8/rhino/examples/RunScript2.java0000644000175000017500000000470710776624170022244 0ustar cavedoncavedon/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- * * ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is Rhino code, released * May 6, 1998. * * The Initial Developer of the Original Code is * Netscape Communications Corporation. * Portions created by the Initial Developer are Copyright (C) 1999 * the Initial Developer. All Rights Reserved. * * Contributor(s): * * Alternatively, the contents of this file may be used under the terms of * the GNU General Public License Version 2 or later (the "GPL"), in which * case the provisions of the GPL are applicable instead of those above. If * you wish to allow use of your version of this file only under the terms of * the GPL and not to allow others to use your version of this file under the * MPL, indicate your decision by deleting the provisions above and replacing * them with the notice and other provisions required by the GPL. If you do * not delete the provisions above, a recipient may use your version of this * file under either the MPL or the GPL. * * ***** END LICENSE BLOCK ***** */ 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, "", 1, null); System.err.println(Context.toString(result)); } finally { Context.exit(); } } } htmlunit-core-js-2.8/rhino/examples/E4X/0000755000175000017500000000000011530107756017751 5ustar cavedoncavedonhtmlunit-core-js-2.8/rhino/examples/E4X/e4x_example.js0000644000175000017500000001615610776624170022540 0ustar cavedoncavedon/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- * * ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is Rhino code, released * May 6, 1999. * * The Initial Developer of the Original Code is * Netscape Communications Corporation. * Portions created by the Initial Developer are Copyright (C) 1997-1999 * the Initial Developer. All Rights Reserved. * * Contributor(s): * John Schneider * * Alternatively, the contents of this file may be used under the terms of * the GNU General Public License Version 2 or later (the "GPL"), in which * case the provisions of the GPL are applicable instead of those above. If * you wish to allow use of your version of this file only under the terms of * the GPL and not to allow others to use your version of this file under the * MPL, indicate your decision by deleting the provisions above and replacing * them with the notice and other provisions required by the GPL. If you do * not delete the provisions above, a recipient may use your version of this * file under either the MPL or the GPL. * * ***** END LICENSE BLOCK ***** */ print("----------------------------------------"); // Use the XML constructor to parse an string into an XML object var John = "John25"; var Sue ="Sue32"; var tagName = "employees"; var employees = new XML("<" + tagName +">" + John + Sue + ""); print("The employees XML object constructed from a string is:\n" + employees); print("----------------------------------------"); // Use an XML literal to create an XML object var order = John Doe Big Screen Television 1299.99 1 // 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.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 += Catapult139.95; 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}; print("The dynamically computed element value is:\n" + x.toXMLString()); print("----------------------------------------"); // Create a SOAP message var message = DIS // 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.a = "one"; x.b = "two"; x.c = three; print("XML object constructed using the default xml namespace:\n" + x); default xml namespace=""; print("----------------------------------------"); var order = John Doe Big Screen Television 1299.99 1 DVD Player 399.99 1 ; // 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 = Joe20 Sue30 ; // 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("----------------------------------------"); htmlunit-core-js-2.8/rhino/examples/SwingApplication.js0000644000175000017500000001010010776624170023157 0ustar cavedoncavedon/* ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is Rhino code, released May 6, 1999. * * The Initial Developer of the Original Code is * Netscape Communications Corporation. * Portions created by the Initial Developer are Copyright (C) 1997-1999 * the Initial Developer. All Rights Reserved. * * Contributor(s): * * Alternatively, the contents of this file may be used under the terms of * the GNU General Public License Version 2 or later (the "GPL"), in which * case the provisions of the GPL are applicable instead of those above. If * you wish to allow use of your version of this file only under the terms of * the GPL and not to allow others to use your version of this file under the * MPL, indicate your decision by deleting the provisions above and replacing * them with the notice and other provisions required by the GPL. If you do * not delete the provisions above, a recipient may use your version of this * file under either the MPL or the GPL. * * ***** END LICENSE BLOCK ***** */ /* * 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); } htmlunit-core-js-2.8/rhino/examples/Matrix.java0000644000175000017500000001774211111054626021463 0ustar cavedoncavedon/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- * * ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is Rhino code, released * May 6, 1998. * * The Initial Developer of the Original Code is * Netscape Communications Corporation. * Portions created by the Initial Developer are Copyright (C) 1997-1999 * the Initial Developer. All Rights Reserved. * * Contributor(s): * * Alternatively, the contents of this file may be used under the terms of * the GNU General Public License Version 2 or later (the "GPL"), in which * case the provisions of the GPL are applicable instead of those above. If * you wish to allow use of your version of this file only under the terms of * the GPL and not to allow others to use your version of this file under the * MPL, indicate your decision by deleting the provisions above and replacing * them with the notice and other provisions required by the GPL. If you do * not delete the provisions above, a recipient may use your version of this * file under either the MPL or the GPL. * * ***** END LICENSE BLOCK ***** */ 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: *

 * 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
 * 
* * @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(); } /** * 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". *

* 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. *

* 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. *

* Look up the element in the associated list and return * it if it exists. If it doesn't exist, create it.

* @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 this appears in value'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 list; private Scriptable prototype, parent; } htmlunit-core-js-2.8/rhino/examples/RunScript3.java0000644000175000017500000000627511111054626022232 0ustar cavedoncavedon/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- * * ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is Rhino code, released * May 6, 1998. * * The Initial Developer of the Original Code is * Netscape Communications Corporation. * Portions created by the Initial Developer are Copyright (C) 1999 * the Initial Developer. All Rights Reserved. * * Contributor(s): * * Alternatively, the contents of this file may be used under the terms of * the GNU General Public License Version 2 or later (the "GPL"), in which * case the provisions of the GPL are applicable instead of those above. If * you wish to allow use of your version of this file only under the terms of * the GPL and not to allow others to use your version of this file under the * MPL, indicate your decision by deleting the provisions above and replacing * them with the notice and other provisions required by the GPL. If you do * not delete the provisions above, a recipient may use your version of this * file under either the MPL or the GPL. * * ***** END LICENSE BLOCK ***** */ 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, "", 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(); } } } htmlunit-core-js-2.8/rhino/examples/PrimitiveWrapFactory.java0000644000175000017500000000554511111054626024347 0ustar cavedoncavedon/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- * * ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is Rhino code, released * May 6, 1998. * * The Initial Developer of the Original Code is * Netscape Communications Corporation. * Portions created by the Initial Developer are Copyright (C) 1997-1999 * the Initial Developer. All Rights Reserved. * * Contributor(s): * Norris Boyd * * Alternatively, the contents of this file may be used under the terms of * the GNU General Public License Version 2 or later (the "GPL"), in which * case the provisions of the GPL are applicable instead of those above. If * you wish to allow use of your version of this file only under the terms of * the GPL and not to allow others to use your version of this file under the * MPL, indicate your decision by deleting the provisions above and replacing * them with the notice and other provisions required by the GPL. If you do * not delete the provisions above, a recipient may use your version of this * file under either the MPL or the GPL. * * ***** END LICENSE BLOCK ***** */ 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. *

* 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. *

* 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); } } htmlunit-core-js-2.8/rhino/examples/Foo.java0000644000175000017500000001376511111054626020743 0ustar cavedoncavedon/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- * * ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is Rhino code, released * May 6, 1998. * * The Initial Developer of the Original Code is * Netscape Communications Corporation. * Portions created by the Initial Developer are Copyright (C) 1997-1999 * the Initial Developer. All Rights Reserved. * * Contributor(s): * * Alternatively, the contents of this file may be used under the terms of * the GNU General Public License Version 2 or later (the "GPL"), in which * case the provisions of the GPL are applicable instead of those above. If * you wish to allow use of your version of this file only under the terms of * the GPL and not to allow others to use your version of this file under the * MPL, indicate your decision by deleting the provisions above and replacing * them with the notice and other provisions required by the GPL. If you do * not delete the provisions above, a recipient may use your version of this * file under either the MPL or the GPL. * * ***** END LICENSE BLOCK ***** */ import org.mozilla.javascript.*; /** * An example host object class. * * Here's a shell session showing the Foo object in action: *

 * js> defineClass("Foo")
 * js> foo = new Foo();         A constructor call, see Foo below.
 * [object Foo]                 The "Foo" here comes from getClassName.
 * js> foo.counter;             The counter property is defined by the defineProperty
 * 0                            call below and implemented by the getCounter
 * js> foo.counter;             method below.
 * 1
 * js> foo.counter;
 * 2
 * js> foo.resetCounter();      Results in a call to resetCounter.
 * js> foo.counter;             Now the counter has been reset.
 * 0
 * js> foo.counter;
 * 1
 * js> bar = new Foo(37);       Create a new instance.
 * [object Foo]
 * js> bar.counter;             This instance's counter is distinct from
 * 37                           the other instance's counter.
 * js> foo.varargs(3, "hi");    Calls varargs.
 * this = [object Foo]; args = [3, hi]
 * js> foo[7] = 34;             Since we extended ScriptableObject, we get
 * 34                           all the behavior of a JavaScript object
 * js> foo.a = 23;              for free.
 * 23
 * js> foo.a + foo[7];
 * 57
 * js>
 * 
* * @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. */ public void jsFunction_resetCounter() { counter = 0; } /** * The Java method implementing the getter for the counter property. *

* If "setCounter" had been defined in this class, the runtime would * call the setter when the property is assigned to. */ public int jsGet_counter() { 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.

* @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 */ public static Object jsFunction_varargs(Context cx, Scriptable thisObj, Object[] args, Function funObj) { StringBuffer buf = new StringBuffer(); 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; } htmlunit-core-js-2.8/rhino/examples/RunScript4.java0000644000175000017500000000551510776624170022244 0ustar cavedoncavedon/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- * * ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is Rhino code, released * May 6, 1998. * * The Initial Developer of the Original Code is * Netscape Communications Corporation. * Portions created by the Initial Developer are Copyright (C) 1999 * the Initial Developer. All Rights Reserved. * * Contributor(s): * * Alternatively, the contents of this file may be used under the terms of * the GNU General Public License Version 2 or later (the "GPL"), in which * case the provisions of the GPL are applicable instead of those above. If * you wish to allow use of your version of this file only under the terms of * the GPL and not to allow others to use your version of this file under the * MPL, indicate your decision by deleting the provisions above and replacing * them with the notice and other provisions required by the GPL. If you do * not delete the provisions above, a recipient may use your version of this * file under either the MPL or the GPL. * * ***** END LICENSE BLOCK ***** */ 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, "", 1, null); System.err.println(Context.toString(result)); } finally { Context.exit(); } } } htmlunit-core-js-2.8/rhino/examples/Shell.java0000644000175000017500000003011311111054626021251 0ustar cavedoncavedon/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- * * ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is Rhino code, released * May 6, 1998. * * The Initial Developer of the Original Code is * Netscape Communications Corporation. * Portions created by the Initial Developer are Copyright (C) 1997-1999 * the Initial Developer. All Rights Reserved. * * Contributor(s): * * Alternatively, the contents of this file may be used under the terms of * the GNU General Public License Version 2 or later (the "GPL"), in which * case the provisions of the GPL are applicable instead of those above. If * you wish to allow use of your version of this file only under the terms of * the GPL and not to allow others to use your version of this file under the * MPL, indicate your decision by deleting the provisions above and replacing * them with the notice and other provisions required by the GPL. If you do * not delete the provisions above, a recipient may use your version of this * file under either the MPL or the GPL. * * ***** END LICENSE BLOCK ***** */ 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 = ""; 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; } htmlunit-core-js-2.8/rhino/examples/File.java0000644000175000017500000002623011111054626021066 0ustar cavedoncavedon/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- * * ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is Rhino code, released * May 6, 1998. * * The Initial Developer of the Original Code is * Netscape Communications Corporation. * Portions created by the Initial Developer are Copyright (C) 1997-2000 * the Initial Developer. All Rights Reserved. * * Contributor(s): * Norris Boyd * * Alternatively, the contents of this file may be used under the terms of * the GNU General Public License Version 2 or later (the "GPL"), in which * case the provisions of the GPL are applicable instead of those above. If * you wish to allow use of your version of this file only under the terms of * the GPL and not to allow others to use your version of this file under the * MPL, indicate your decision by deleting the provisions above and replacing * them with the notice and other provisions required by the GPL. If you do * not delete the provisions above, a recipient may use your version of this * file under either the MPL or the GPL. * * ***** END LICENSE BLOCK ***** */ import org.mozilla.javascript.*; 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: *

 * js> defineClass("File")
 * js> file = new File("myfile.txt");
 * [object File]
 * js> file.writeLine("one");                       only now is file actually opened
 * js> file.writeLine("two");
 * js> file.writeLine("thr", "ee");
 * js> file.close();                                must close file before we can reopen for reading
 * js> var a = file.readLines();                    creates and fills an array with the contents of the file
 * js> a;
 * one,two,three
 * js>
 * 
* * * 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.

* * Otherwise System.in or System.out is assumed as appropriate * to the use. */ 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. */ public String jsGet_name() { return name; } /** * Read the remaining lines in the file and return them in an array. * * Implements a JavaScript function.

* * 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 */ public Object jsFunction_readLines() throws IOException { List list = new ArrayList(); String s; while ((s = jsFunction_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 */ public String jsFunction_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 */ public String jsFunction_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.

* * 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 */ public static void jsFunction_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 * */ public static void jsFunction_writeLine(Context cx, Scriptable thisObj, Object[] args, Function funObj) throws IOException { write0(thisObj, args, true); } public int jsGet_lineNumber() 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 */ public void jsFunction_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 { jsFunction_close(); } catch (IOException e) { } } /** * Get the Java reader. */ public Object jsFunction_getReader() { 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#jsFunction_getReader * */ public Object jsFunction_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: *

     * js> defineClass("File");
     * js> o = {};
     * [object Object]
     * js> o.__proto__ = File.prototype;
     * [object File]
     * js> o.write("hi");
     * js: called on incompatible object
     * 
* 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; } htmlunit-core-js-2.8/rhino/examples/Control.java0000644000175000017500000000733510776624170021651 0ustar cavedoncavedon/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- * * ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is Rhino code, released * May 6, 1998. * * The Initial Developer of the Original Code is * Netscape Communications Corporation. * Portions created by the Initial Developer are Copyright (C) 1997-1999 * the Initial Developer. All Rights Reserved. * * Contributor(s): * * Alternatively, the contents of this file may be used under the terms of * the GNU General Public License Version 2 or later (the "GPL"), in which * case the provisions of the GPL are applicable instead of those above. If * you wish to allow use of your version of this file only under the terms of * the GPL and not to allow others to use your version of this file under the * MPL, indicate your decision by deleting the provisions above and replacing * them with the notice and other provisions required by the GPL. If you do * not delete the provisions above, a recipient may use your version of this * file under either the MPL or the GPL. * * ***** END LICENSE BLOCK ***** */ 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(); } } } htmlunit-core-js-2.8/rhino/examples/enum.js0000644000175000017500000000470210776624170020663 0ustar cavedoncavedon/* -*- tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is Rhino code, released * May 6, 1999. * * The Initial Developer of the Original Code is * Netscape Communications Corporation. * Portions created by the Initial Developer are Copyright (C) 1997-1999 * the Initial Developer. All Rights Reserved. * * Contributor(s): * Patrick Beard * * Alternatively, the contents of this file may be used under the terms of * the GNU General Public License Version 2 or later (the "GPL"), in which * case the provisions of the GPL are applicable instead of those above. If * you wish to allow use of your version of this file only under the terms of * the GPL and not to allow others to use your version of this file under the * MPL, indicate your decision by deleting the provisions above and replacing * them with the notice and other provisions required by the GPL. If you do * not delete the provisions above, a recipient may use your version of this * file under either the MPL or the GPL. * * ***** END LICENSE BLOCK ***** */ /* 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()); htmlunit-core-js-2.8/rhino/examples/jsdoc.js0000644000175000017500000004030110776624170021014 0ustar cavedoncavedon/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- * * ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is Rhino code, released * May 6, 1999. * * The Initial Developer of the Original Code is * Netscape Communications Corporation. * Portions created by the Initial Developer are Copyright (C) 1997-1999 * the Initial Developer. All Rights Reserved. * * Contributor(s): * Norris Boyd * Roland Pennings * * Alternatively, the contents of this file may be used under the terms of * the GNU General Public License Version 2 or later (the "GPL"), in which * case the provisions of the GPL are applicable instead of those above. If * you wish to allow use of your version of this file only under the terms of * the GPL and not to allow others to use your version of this file under the * MPL, indicate your decision by deleting the provisions above and replacing * them with the notice and other provisions required by the GPL. If you do * not delete the provisions above, a recipient may use your version of this * file under either the MPL or the GPL. * * ***** END LICENSE BLOCK ***** */ /** * 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 f, writing jsdoc to * file out. * @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('
' + fname + ''); if (inputdir != null) { outstr = '
Index Files ';
	  outstr += 'Index Functions

'; 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('

File ' + fname + '

'); out.writeLine(processComment(comment,firstLine,fname)); out.writeLine('
'); 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 ' + name + '
'); } } out.writeLine('
'); // Now write the saved function documentation. for (i=0; i < functionDocArray.length; i++) { with (functionDocArray[i]) { out.writeLine(''); out.writeLine(text); } } out.writeLine(''); // 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 "

Function " + name + "

" + "
" +
		"function " + name + "(" + args + ")" +
		"
" + processComment(comment,0,name) + "



"; } /** * 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 "

Method " + proto + ".prototype." + name + "

" + "
" +
		proto + ".prototype." + name + " = function(" + args + ")" +
		"
" + processComment(comment,0,name) + "



"; } /** * 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 + '

'; 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 += ''+m[1]+'' + ''+m[2]+''; } out += ''; out += ''; out += ''; out += ''; out += params; out += '
ParameterDescription

'; } if (tags["return"]) { out += "

Returns:
"; out += tags["return"][0] + "

"; } if (tags["author"]) { // List the authors together, separated by commas. out += '

Author:
'; var array = tags["author"]; for (var i=0; i < array.length; i++) { out += array[i]; if (i+1 < array.length) out += ", "; } out += '

'; } if (tags["version"]) { // Show the version. out += '

Version:
'; var array = tags["version"]; for (var i=0; i < array.length; i++) { out += array[i]; if (i+1 < array.length) out += "
"; } out += '

'; } if (tags["see"]) { // List the see modules together, separated by
. out += '

Dependencies:
'; var array = tags["see"]; for (var i=0; i < array.length; i++) { out += array[i]; if (i+1 < array.length) out += "
"; } out += '

'; } if (tags["lastmodified"]) { // Shows a last modified description with client-side js. out += '

Last modified:
'; out += '\n'; out += '

'; } // 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('

File Index - directory: ' + dirname + ''); out.writeLine('

File Index - directory: ' + dirname + '

\n'); out.writeLine(''); out.writeLine(''); out.writeLine(''); out.writeLine(''); 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('\n'); } out.writeLine('
FileDescription
' + fname + ''); if (indexFileArray[fname]) out.writeLine(indexFileArray[fname]); else out.writeLine('No comments'); out.writeLine('
'); out.close(); // construct the functions index file var out = CreateOutputFile(outputdir,indexFunction); // write the beginning of the file out.writeLine('
Function Index - directory: ' + dirname + ''); out.writeLine('

Function Index - directory: ' + dirname + '

\n'); out.writeLine(''); out.writeLine(''); out.writeLine(''); out.writeLine(''); // 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 = ''; out.writeLine(outstr); } } out.writeLine('
FunctionFiles
' + funcname + ''; var filelst = filename.split("|"); for (var i in filelst) { var htmlfile = filelst[i].replace(/\.js$/, ".html"); outstr += '' + filelst[i] + ' '; } outstr += '
'); 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); } htmlunit-core-js-2.8/rhino/examples/Counter.java0000644000175000017500000000461011111054626021624 0ustar cavedoncavedon/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- * * ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is Rhino code, released * May 6, 1998. * * The Initial Developer of the Original Code is * Netscape Communications Corporation. * Portions created by the Initial Developer are Copyright (C) 1999 * the Initial Developer. All Rights Reserved. * * Contributor(s): * Norris Boyd * * Alternatively, the contents of this file may be used under the terms of * the GNU General Public License Version 2 or later (the "GPL"), in which * case the provisions of the GPL are applicable instead of those above. If * you wish to allow use of your version of this file only under the terms of * the GPL and not to allow others to use your version of this file under the * MPL, indicate your decision by deleting the provisions above and replacing * them with the notice and other provisions required by the GPL. If you do * not delete the provisions above, a recipient may use your version of this * file under either the MPL or the GPL. * * ***** END LICENSE BLOCK ***** */ import org.mozilla.javascript.*; public class Counter extends ScriptableObject { private static final long serialVersionUID = 438270592527335642L; // The zero-argument constructor used by Rhino runtime to create instances public Counter() { } // Method jsConstructor defines the JavaScript constructor public void jsConstructor(int a) { count = a; } // The class name is defined by the getClassName method @Override public String getClassName() { return "Counter"; } // The method jsGet_count defines the count property. public int jsGet_count() { return count++; } // Methods can be defined using the jsFunction_ prefix. Here we define // resetCount for JavaScript. public void jsFunction_resetCount() { count = 0; } private int count; } htmlunit-core-js-2.8/rhino/examples/DynamicScopes.java0000644000175000017500000001654611111054626022761 0ustar cavedoncavedon/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- * * ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is Rhino code, released * May 6, 1998. * * The Initial Developer of the Original Code is * Netscape Communications Corporation. * Portions created by the Initial Developer are Copyright (C) 1997-2000 * the Initial Developer. All Rights Reserved. * * Contributor(s): * Norris Boyd * * Alternatively, the contents of this file may be used under the terms of * the GNU General Public License Version 2 or later (the "GPL"), in which * case the provisions of the GPL are applicable instead of those above. If * you wish to allow use of your version of this file only under the terms of * the GPL and not to allow others to use your version of this file under the * MPL, indicate your decision by deleting the provisions above and replacing * them with the notice and other provisions required by the GPL. If you do * not delete the provisions above, a recipient may use your version of this * file under either the MPL or the GPL. * * ***** END LICENSE BLOCK ***** */ 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 *
     * sharedScope
     * nested:sharedScope
     * sharedScope
     * nested:sharedScope
     * sharedScope
     * nested:sharedScope
     * thread0
     * nested:thread0
     * thread1
     * nested:thread1
     * thread2
     * nested:thread2
     * 
* 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: //
        //            ------------------                ------------------
        //           | per-thread scope | -prototype-> |   shared scope   |
        //            ------------------                ------------------
        //                    ^
        //                    |
        //               parentScope
        //                    |
        //            ------------------
        //           | f's activation   |
        //            ------------------
        // 
// 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; } } htmlunit-core-js-2.8/rhino/examples/CounterTest.java0000644000175000017500000000550110776624170022501 0ustar cavedoncavedon/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- * * ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is Rhino code, released * May 6, 1998. * * The Initial Developer of the Original Code is * Netscape Communications Corporation. * Portions created by the Initial Developer are Copyright (C) 1999 * the Initial Developer. All Rights Reserved. * * Contributor(s): * Norris Boyd * * Alternatively, the contents of this file may be used under the terms of * the GNU General Public License Version 2 or later (the "GPL"), in which * case the provisions of the GPL are applicable instead of those above. If * you wish to allow use of your version of this file only under the terms of * the GPL and not to allow others to use your version of this file under the * MPL, indicate your decision by deleting the provisions above and replacing * them with the notice and other provisions required by the GPL. If you do * not delete the provisions above, a recipient may use your version of this * file under either the MPL or the GPL. * * ***** END LICENSE BLOCK ***** */ import org.mozilla.javascript.*; /** * An example illustrating how to create a JavaScript object and retrieve * properties and call methods. *

* Output should be: *

 * count = 0
 * count = 1
 * resetCount
 * count = 0
 * 
*/ 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(); } } } htmlunit-core-js-2.8/rhino/examples/RunScript.java0000644000175000017500000000553010776624170022155 0ustar cavedoncavedon/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- * * ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is Rhino code, released * May 6, 1998. * * The Initial Developer of the Original Code is * Netscape Communications Corporation. * Portions created by the Initial Developer are Copyright (C) 1999 * the Initial Developer. All Rights Reserved. * * Contributor(s): * * Alternatively, the contents of this file may be used under the terms of * the GNU General Public License Version 2 or later (the "GPL"), in which * case the provisions of the GPL are applicable instead of those above. If * you wish to allow use of your version of this file only under the terms of * the GPL and not to allow others to use your version of this file under the * MPL, indicate your decision by deleting the provisions above and replacing * them with the notice and other provisions required by the GPL. If you do * not delete the provisions above, a recipient may use your version of this * file under either the MPL or the GPL. * * ***** END LICENSE BLOCK ***** */ 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, "", 1, null); // Convert the result to a string and print it. System.err.println(Context.toString(result)); } finally { // Exit from the context. Context.exit(); } } } htmlunit-core-js-2.8/rhino/examples/NervousText.js0000644000175000017500000000624410776624170022230 0ustar cavedoncavedon/* ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is Rhino code, released May 6, 1999. * * The Initial Developer of the Original Code is * Netscape Communications Corporation. * Portions created by the Initial Developer are Copyright (C) 1997-1999 * the Initial Developer. All Rights Reserved. * * Contributor(s): * * Alternatively, the contents of this file may be used under the terms of * the GNU General Public License Version 2 or later (the "GPL"), in which * case the provisions of the GPL are applicable instead of those above. If * you wish to allow use of your version of this file only under the terms of * the GPL and not to allow others to use your version of this file under the * MPL, indicate your decision by deleting the provisions above and replacing * them with the notice and other provisions required by the GPL. If you do * not delete the provisions above, a recipient may use your version of this * file under either the MPL or the GPL. * * ***** END LICENSE BLOCK ***** */ // 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'); default xml namespace = "http://something"; var otherData = new XML(); otherData['@anAtt'] = "anATTValue"; tmp.data.otherData=otherData; "success"; htmlunit-core-js-2.8/rhino/testsrc/jstests/420012.jstest0000644000175000017500000000034310776623544022720 0ustar cavedoncavedonvar o = new Object; o.setX = function (id) { this.oid = id; } function setX(n) { if (n == "" || n == null) n = 0; var s = new Object; s.xyz = n; if (s != null) { o.setX(s.xyz); } } setX('x'); "success"; htmlunit-core-js-2.8/rhino/testsrc/jstests/destructuringLvalue.jstest0000644000175000017500000000072411222460357026232 0ustar cavedoncavedon/* TODO(stevey): fix this test var obj = { p:3 }; var arr = [ 3 ]; [obj.p] = [9]; if (obj.p != 9) throw "obj.p not set by array destructuring assignment"; [arr[0]] = [9]; if (arr[0] != 9) throw "arr[0] not set by array destructuring assignment"; ({prop:obj.p} = {prop:12}); if (obj.p != 12) throw "obj.p not set by object destructuring assignment"; ({prop:arr[0]} = {prop:12}); if (arr[0] != 12) throw "arr[0] not set by object destructuring assignment"; */ "success" htmlunit-core-js-2.8/rhino/testsrc/jstests/437988.jstest0000644000175000017500000000056511111054626022743 0ustar cavedoncavedon// Rhino must discover the abstract methods in the interface // of AbstractTableModel var tableModel = new javax.swing.table.AbstractTableModel() { getRowCount: function() { return 2; }, getColumnCount: function() { return 2; }, getValueAt: function(row, column) { return "ABC"; } }; var jTable = new javax.swing.JTable(tableModel); "success"; htmlunit-core-js-2.8/rhino/testsrc/base.skip0000644000175000017500000005561611222460357021036 0ustar cavedoncavedon# Rhino base skip list: these are tests that are always skipped for Rhino # These tests are skipped by Rhino either because a bug with a regression # test has yet to be fixed, or because the test is not applicable to Rhino. # # bad test: cannot write a property that has only a getter defined js1_5/extensions/regress-341956-01.js # timer resolution test js1_5/extensions/regress-363258.js # Needs investigation js1_7/regress/regress-406477.js e4x/extensions/regress-410192.js # should be investigated: OutOfMemoryError js1_5/Regress/regress-330352.js # test consumes much memory, will get OutOfMemoryError depending on JVM # settings js1_5/extensions/regress-367501-04.js # stress test that can potentially time out js1_5/Regress/regress-404755.js # should be investigated: semicolon insertion ecma_3/LexicalConventions/7.9.1.js ecma_3/extensions/7.9.1.js # tests that do not work on non-English locales or for timezones outside the US ecma_3/Date/15.9.5.5.js js1_5/Regress/regress-58116.js # Fails on Macs? lc2/JavaToJS/char-002.js # Stress test; Reports of StackOverflowError (Mac only?) js1_5/Regress/regress-98901.js # performance regression test js1_5/Array/regress-99120-01.js js1_5/extensions/regress-371636.js # large concatenation of strings js1_5/Function/regress-338121-01.js js1_5/Function/regress-338121-02.js js1_5/Function/regress-338121-03.js # needs investigation: Date corner case ecma_3/Date/15.9.5.5-02.js # Infinite recursion e4x/Regress/regress-394941.js # GC tests js1_5/GC # bad test: random string generated will be too long about 1% of the time lc3/JavaArray/ToArray-001.js # would imply we would always need an activation for every non-leaf func js1_5/Regress/regress-383682.js # test depends on E4X, but test framework calls version(150) js1_5/Regress/regress-309242.js # performance test: Global vars should not be more than 2.5 times slower than local js1_5/Regress/regress-169559.js # infinite recursion js1_5/Regress/regress-234389.js # object watch not implemented js1_5/Regress/regress-240577.js js1_5/Function/regress-364023.js js1_5/Object/regress-362872-01.js js1_5/Object/regress-362872-02.js js1_5/Regress/regress-385393-06.js js1_5/extensions/regress-385393-09.js js1_7/GC/regress-381374.js # toLocaleFormat not implemented js1_5/extensions/toLocaleFormat-01.js js1_5/extensions/toLocaleFormat-02.js # source too complex js1_5/Expressions/regress-394673.js # import, export not implemented js1_5/Regress/regress-249211.js js1_7/lexical/regress-346642-03.js js1_5/Regress/regress-362583.js js1_5/extensions/regress-355622.js # sharp-variables not implemented js1_5/extensions/regress-379523.js # concatentated string too large js1_5/Regress/regress-280769-1.js # stack overflow js1_5/Regress/regress-280769-2.js # performance tests js1_5/Regress/regress-313967-01.js js1_5/Regress/regress-313967-02.js js1_5/Array/regress-99120-02.js # concatentated string too large js1_5/Regress/regress-347306-01.js # import, export not implemented js1_5/decompilation/regress-349484.js # concatenated string too large js1_5/String/regress-157334-01.js js1_5/String/regress-56940-01.js js1_5/String/regress-56940-02.js # runs out of heap js1_5/Regress/regress-271716-n.js js1_5/Regress/regress-303213.js js1_5/Regress/regress-312588.js js1_5/Array/regress-157652.js # Tests that create very large strings by concatentation js1_5/extensions/regress-336409-1.js js1_5/extensions/regress-336409-2.js js1_5/extensions/regress-336410-1.js js1_5/extensions/regress-336410-2.js e4x/XML/regress-324422-1.js js1_5/Function/regress-338001.js js1_5/Regress/regress-159334.js js1_5/Regress/regress-191633.js js1_5/Regress/regress-280769-3.js js1_5/Regress/regress-280769-4.js js1_5/String/regress-314890.js js1_5/String/regress-322772.js js1_5/extensions/regress-363988.js # bug 152646 Will not fix this in Rhino; too much of a corner case js1_5/Regress/regress-152646.js #Verify error for bad branch js1_5/Regress/regress-96526-001.js js1_5/Regress/regress-96526-002.js js1_5/Regress/regress-96526-003.js # JSObject not used for Rhino LiveConnect lc3/ConvertJSObject lc3/Exceptions/throw_js_types.js lc3/JavaClass/ToJSObject-001.js lc3/JSObject/ToJSObject-001.js #Rhino implements Date.toLocaleTimeString() differently than SpiderMonkey ecma_3/Date/15.9.5.7.js #Rhino - as permitted by ECMA - does not allow indirect calls to eval js1_4/Eval/eval-001.js js1_4/Eval/eval-002.js js1_4/Eval/eval-003.js js1_5/Regress/regress-68498-003.js #Rhino compiled mode is limited by Java classfile size limitations #js1_5/Regress/regress-80981.js #js1_5/Regress/regress-90445.js #js1_5/Regress/regress-111557.js #Rhino relies on JVM to throw StackOverflow exception and does not #detect too deep recursion explicitly. js1_5/extensions/regress-192465.js js1_5/extensions/regress-226507.js js1_5/Regress/regress-89443.js # Skip these two; see http://bugzilla.mozilla.org/show_bug.cgi?id=81086, large # switch statement #ecma_3/Statements/regress-74474-002.js #ecma_3/Statements/regress-74474-003.js #Compiled mode cannot catch infinite recursion errors js1_5/Regress/regress-96128-n.js js1_5/Exceptions/regress-121658.js # This test uses the (non-ECMA) 'it' object of SpiderMonkey js1_2/version120/regress-99663.js # This test uses the gc() function of SpiderMonkey ecma_3/Function/regress-104584.js #This test uses the Error.stack property of SpiderMonkey (non-ECMA) js1_5/Exceptions/errstack-001.js #This test uses the clone() function in SpiderMonkey's js.c file #js1_5/Regress/regress-127557.js # apparently works, which doesn't make sense #These tests break with new Unicode in JDK 1.4 ecma/String/15.5.4.11-2.js ecma/String/15.5.4.11-5.js ecma/String/15.5.4.12-1.js ecma/String/15.5.4.12-4.js ecma/String/15.5.4.12-5.js # Rhino doesn't implement the (non-ECMA) f.caller property js1_5/Function/regress-222029-001.js js1_5/Function/regress-222029-002.js # WONTFIX bug 119719 js1_5/Regress/regress-119719.js # Bug Number 240317 relaxed errors for reserved identifiers but Rhino did not js1_5/Regress/regress-240317.js # Spidermonkey now defaults lineNumber and fileName # to the location and file where the exception occured. # exclude new test which assumes the defaults are # set according to Spidermonkey. js1_5/extensions/regress-50447-1.js # Invalid bug e4x/Regress/regress-278112.js # Invalid test? Cannot convert NaN to java.lang.Long lc3/template.js # Depends on generators being closed due to a call to gc(). Java finalizers # are not run immediately in a call to gc(), but instead usuallly are run # later on a different thread. js1_7/geniter/regress-347739.js js1_7/geniter/regress-349012-01.js js1_7/geniter/regress-349331.js # function named "yield" js1_7/lexical/regress-351515.js # keywords used as identifiers js1_5/extensions/regress-381304.js # Needs investigation: syntax errors in setters js1_5/Regress/regress-361617.js js1_5/extensions/regress-356106.js # decompilation js1_7/block/regress-344601.js js1_7/block/regress-351794.js js1_5/Regress/regress-10278.js # bad test: will fail if time of day increments a second between calls to Date() ecma/Date/15.9.2.1.js ecma/Date/15.9.2.2-2.js # JS 1.7 not yet implemented js1_7/decompilation # "y" flag for regexps js1_7/regexp/yflag.js # yield and xml-filtering predicate js1_7/geniter/regress-352605.js # js1_7 needs investigation js1_7/extensions/basic-for-each.js js1_7/extensions/regress-346642-06.js js1_7/extensions/regress-351102-03.js js1_7/extensions/regress-351102-04.js js1_7/extensions/regress-351102-05.js js1_7/extensions/regress-351102-07.js js1_7/extensions/regress-353214-01.js js1_7/extensions/regress-353214-02.js js1_7/extensions/regress-353249.js js1_7/extensions/regress-353454.js js1_7/extensions/regress-354945-02.js js1_7/extensions/regress-355145.js js1_7/extensions/regress-367629.js js1_7/extensions/regress-368213.js js1_7/extensions/regress-368224.js js1_7/extensions/regress-379482.js js1_7/extensions/regress-379566.js js1_7/extensions/regress-381301.js js1_7/extensions/regress-381303.js js1_7/iterable/regress-340526-02.js js1_7/regress/regress-350387.js js1_7/regress/regress-351503-01.js js1_7/regress/regress-351503-02.js js1_7/regress/regress-352870-01.js js1_7/regress/regress-352870-02.js js1_7/regress/regress-363040-01.js js1_7/regress/regress-363040-02.js js1_7/regress/regress-375695.js js1_7/regress/regress-379483.js # JS 1.8 not yet implemented js1_8 # nondeterministic js1_5/Regress/regress-211590.js # long-running tests ecma/Date/15.9.5.10-2.js ecma/Date/15.9.5.11-2.js ecma/Date/15.9.5.12-2.js ecma/Date/15.9.5.8.js js1_5/Regress/regress-366122.js # "options" built-in function ecma_2/Exceptions/lexical-011.js ecma_2/Exceptions/lexical-014.js ecma_2/Exceptions/lexical-016.js ecma_2/Exceptions/lexical-021.js ecma_2/LexicalConventions/keywords-001.js js1_6/Regress/regress-378492.js js1_5/Regress/regress-115436.js js1_5/Regress/regress-214761.js js1_5/Regress/regress-253150.js js1_5/Regress/regress-306633.js js1_7/iterable/regress-355075-01.js js1_7/iterable/regress-355075-02.js js1_7/block/regress-347559.js js1_5/Regress/regress-383674.js # Function "exec" must be called directly, and not by way of a function of # another name. js1_5/extensions/regress-367119-01.js js1_5/extensions/regress-367119-02.js # Obsolete JS 1.2 behavior js1_2/operator/equality.js js1_3/regress/function-001-n.js js1_3/Script/function-001-n.js js1_2/function/function-001-n.js ecma_2/Exceptions/function-001.js # likely bugs. need investigation js1_6/Array/regress-386030.js ecma_3/Array/regress-387501.js js1_7/lexical/regress-336376-01.js # minor decompilation incompatibility js1_5/extensions/regress-384680.js # bad tests? Looks like Daylight savings time failures. ecma/Date/15.9.5.28-1.js ecma/Date/15.9.5.29-1.js # uninvestigated failures. May be some bugs in here. e4x/Regress/regress-373082.js e4x/XML/regress-376773.js e4x/decompilation/regress-352013.js e4x/decompilation/regress-352789.js e4x/extensions/regress-374163.js js1_5/Regress/regress-346237.js js1_5/decompilation/regress-351219.js js1_5/decompilation/regress-352453.js js1_5/decompilation/regress-353146.js js1_5/decompilation/regress-375882.js js1_5/extensions/regress-330569.js js1_5/extensions/regress-351448.js js1_5/extensions/regress-355736.js js1_5/extensions/regress-374589.js e4x/Expressions/11.1.4-01.js e4x/Expressions/11.1.4-02.js e4x/Expressions/11.1.4-03.js e4x/Expressions/11.1.4-04.js e4x/Expressions/11.1.4-08.js e4x/Expressions/11.1.4.js e4x/Expressions/11.6.1.js e4x/GC/regress-280844-1.js e4x/GC/regress-280844-2.js e4x/GC/regress-313952-02.js e4x/GC/regress-324278.js e4x/GC/regress-339785.js e4x/GC/regress-357063-01.js e4x/GC/regress-357063-02.js e4x/Global/13.1.2.1.js e4x/Regress/regress-257679.js e4x/Regress/regress-308111.js e4x/Regress/regress-309897.js e4x/Regress/regress-311580.js e4x/Regress/regress-319872.js e4x/Regress/regress-321547.js e4x/Regress/regress-322499.js e4x/Regress/regress-323338-1.js e4x/Regress/regress-323338-2.js e4x/Regress/regress-327564.js e4x/Regress/regress-329257.js e4x/Regress/regress-331558.js e4x/Regress/regress-344455.js e4x/Regress/regress-347155.js e4x/decompilation/regress-350226.js e4x/Regress/regress-350238.js e4x/decompilation/regress-350531.js e4x/Regress/regress-350629.js e4x/decompilation/regress-351706.js e4x/decompilation/regress-351988.js e4x/Regress/regress-352097.js e4x/Regress/regress-352223.js e4x/decompilation/regress-352649.js e4x/Regress/regress-354998.js e4x/Regress/regress-355478.js e4x/Regress/regress-356238-02.js e4x/Regress/regress-356238-03.js e4x/Regress/regress-361451.js e4x/Regress/regress-364017.js e4x/Regress/regress-369740.js e4x/Regress/regress-370016.js e4x/Regress/regress-370048-01.js e4x/Regress/regress-370048-02.js e4x/Regress/regress-370372.js e4x/Regress/regress-371369.js e4x/Regress/regress-372563.js e4x/TypeConversion/10.2.1.js e4x/TypeConversion/10.5.1.js e4x/TypeConversion/10.5.js e4x/TypeConversion/10.6.1.js e4x/TypeConversion/10.6.js e4x/TypeConversion/regress-302097.js e4x/Types/9.1.1.10.js e4x/Types/9.1.1.11.js e4x/Types/9.1.1.12.js e4x/Types/9.1.1.13.js e4x/Types/9.1.1.4.js e4x/Types/9.1.1.5.js e4x/Types/9.1.1.7.js e4x/Types/9.1.1.8.js e4x/Types/9.1.1.9.js e4x/Types/9.2.1.10.js e4x/Types/9.2.1.3.js e4x/Types/9.2.1.4.js e4x/Types/9.2.1.5.js e4x/Types/9.2.1.6.js e4x/Types/9.2.1.7.js e4x/Types/9.2.1.9.js e4x/XML/13.4.3.js e4x/XML/13.4.4.1.js e4x/XML/13.4.4.10.js e4x/XML/13.4.4.17.js e4x/XML/13.4.4.26.js e4x/XML/13.4.4.28.js e4x/XML/13.4.4.3-01.js e4x/XML/13.4.4.3-02.js e4x/XML/regress-324422-2.js e4x/XMLList/regress-373072.js e4x/decompilation/decompile-xml-escapes.js e4x/extensions/regress-312196.js e4x/extensions/regress-313080.js e4x/extensions/regress-337226.js e4x/extensions/regress-352846-01.js e4x/extensions/regress-352846-02.js e4x/extensions/regress-352846-03.js e4x/extensions/regress-353165.js ecma/Array/15.4.3.1-2.js ecma/Array/15.4.5.1-1.js ecma/Boolean/15.6.3.1-1.js ecma/FunctionObjects/15.3.3.1-2.js ecma/Number/15.7.3.1-3.js ecma/ObjectObjects/15.2.3.1-1.js ecma/Statements/12.6.3-11.js ecma/Statements/12.6.3-2.js ecma/String/15.5.3.1-1.js ecma_2/RegExp/exec-001.js ecma_2/RegExp/regexp-enumerate-001.js ecma_2/String/replace-001.js ecma_2/instanceof/instanceof-003.js ecma_3/Array/regress-322135-02.js ecma_3/Array/regress-322135-03.js ecma_3/Array/regress-322135-04.js ecma_3/Date/15.9.3.2-1.js ecma_3/Exceptions/15.11.7.6-001.js ecma_3/Object/8.6.1-01.js ecma_3/RegExp/regress-188206.js ecma_3/RegExp/regress-289669.js ecma_3/RegExp/regress-307456.js ecma_3/RegExp/regress-309840.js ecma_3/RegExp/regress-311414.js ecma_3/RegExp/regress-330684.js ecma_3/RegExp/regress-334158.js ecma_3/RegExp/regress-367888.js ecma_3/Statements/regress-121744.js ecma_3/String/15.5.4.14.js ecma_3/String/regress-304376.js ecma_3/extensions/regress-274152.js js1_1/regress/function-001.js js1_2/function/Function_object.js js1_2/function/regexparg-1.js js1_2/function/tostring-1.js js1_2/function/tostring-2.js js1_5/Array/regress-313153.js js1_5/Array/regress-330812.js js1_5/Array/regress-345961.js js1_5/Array/regress-350256-03.js js1_5/Array/regress-364104.js js1_5/Date/regress-301738-02.js js1_5/Date/regress-309925-02.js js1_5/Date/regress-346363.js js1_5/Date/toLocaleFormat.js js1_5/Exceptions/regress-315147.js js1_5/Exceptions/regress-332472.js js1_5/Exceptions/regress-333728.js js1_5/Exceptions/regress-342359.js js1_5/Exceptions/regress-350650-n.js js1_5/decompilation/regress-346902.js js1_5/decompilation/regress-346904.js js1_5/Expressions/regress-96526-delelem.js js1_5/Function/regress-344120.js js1_5/GC/regress-203278-2.js js1_5/GC/regress-278725.js js1_5/GC/regress-316885-01.js js1_5/GC/regress-324278.js js1_5/GC/regress-346794.js js1_5/GC/regress-348532.js js1_5/GetSet/getset-002.js js1_5/GetSet/regress-353264.js js1_5/LexicalConventions/regress-343675.js js1_5/Object/regress-308806-01.js js1_5/Regress/regress-103602.js js1_5/Regress/regress-106244.js js1_5/Regress/regress-139316.js js1_5/Regress/regress-173067.js js1_5/Regress/regress-203278-1.js js1_5/Regress/regress-213482.js js1_5/Regress/regress-247179.js js1_5/Regress/regress-248444.js js1_5/Regress/regress-252892.js js1_5/Regress/regress-261886.js js1_5/Regress/regress-261887.js js1_5/Regress/regress-274035.js js1_5/Regress/regress-280769-5.js js1_5/Regress/regress-280769.js js1_5/Regress/regress-281606.js js1_5/Regress/regress-290575.js js1_5/Regress/regress-294302.js js1_5/Regress/regress-315974.js js1_5/Regress/regress-317533.js js1_5/Regress/regress-319391.js js1_5/Regress/regress-320119.js js1_5/Regress/regress-321971.js js1_5/Regress/regress-323314-1.js js1_5/Regress/regress-325925.js js1_5/Regress/regress-328664.js js1_5/Regress/regress-329530.js js1_5/Regress/regress-334807-02.js js1_5/Regress/regress-334807-04.js js1_5/Regress/regress-336100.js js1_5/decompilation/regress-346892.js js1_5/decompilation/regress-346915.js js1_5/decompilation/regress-349491.js js1_5/decompilation/regress-349596.js js1_5/Regress/regress-349648.js js1_5/decompilation/regress-349650.js js1_5/decompilation/regress-350242.js js1_5/decompilation/regress-350263.js js1_5/Regress/regress-350268.js js1_5/decompilation/regress-350271.js js1_5/decompilation/regress-350666.js js1_5/Regress/regress-350692.js js1_5/decompilation/regress-351104.js js1_5/decompilation/regress-351597.js js1_5/decompilation/regress-351693.js js1_5/decompilation/regress-351793.js js1_5/Regress/regress-352009.js js1_5/decompilation/regress-352013.js js1_5/Regress/regress-352197.js js1_5/decompilation/regress-352202.js js1_5/decompilation/regress-352375.js js1_5/decompilation/regress-352649.js js1_5/decompilation/regress-353000.js js1_5/Regress/regress-354924.js js1_5/Regress/regress-355341.js js1_5/Regress/regress-355344.js js1_5/Regress/regress-355556.js js1_5/decompilation/regress-355992.js js1_5/Regress/regress-356693.js js1_5/Regress/regress-360969-05.js js1_5/Regress/regress-360969-06.js js1_5/Regress/regress-361467.js js1_5/Regress/regress-3649-n.js js1_5/Regress/regress-372364.js js1_5/extensions/getset-001.js js1_5/extensions/getset-003.js js1_5/extensions/regress-164697.js js1_5/extensions/regress-245148.js js1_5/extensions/regress-254375.js js1_5/extensions/regress-303277.js js1_5/extensions/regress-306738.js js1_5/extensions/regress-313630.js js1_5/extensions/regress-333541.js js1_5/extensions/regress-335700.js js1_5/extensions/regress-338804-02.js js1_5/extensions/regress-342960.js js1_5/extensions/regress-345967.js js1_5/extensions/regress-346494.js js1_5/extensions/regress-347306-02.js js1_5/extensions/regress-348986.js js1_5/extensions/regress-349616.js js1_5/extensions/regress-350531.js js1_5/extensions/regress-352060.js js1_5/extensions/regress-352094.js js1_5/extensions/regress-352372.js js1_5/extensions/regress-352455.js js1_5/extensions/regress-353214.js js1_5/extensions/regress-354541-02.js js1_5/extensions/regress-354541-04.js js1_5/extensions/regress-355339.js js1_5/extensions/regress-355497.js js1_5/extensions/regress-355820.js js1_5/extensions/regress-356085.js js1_5/extensions/regress-361346.js js1_5/extensions/regress-361360.js js1_5/extensions/regress-361552.js js1_5/extensions/regress-361558.js js1_5/extensions/regress-361571.js js1_5/extensions/regress-361964.js js1_5/extensions/regress-365869.js js1_5/extensions/regress-367923.js js1_5/extensions/regress-368859.js js1_6/Array/regress-290592.js js1_6/Array/regress-310425-01.js js1_6/Array/regress-320887.js js1_6/Regress/regress-350417.js js1_6/decompilation/regress-352084.js js1_6/decompilation/regress-352613-01.js js1_6/decompilation/regress-352613-02.js js1_6/Regress/regress-355002.js js1_6/Regress/regress-372565.js js1_6/String/regress-306591.js js1_6/extensions/regress-312385-01.js js1_6/extensions/regress-352392.js lc2/Arrays/array-008-n.js e4x/Expressions/regress-366123.js e4x/decompilation/regress-352459.js ecma/Date/15.9.5.31-1.js ecma/Date/15.9.5.35-1.js ecma_3/RegExp/regress-375642.js js1_5/Regress/regress-306727.js js1_5/Regress/regress-308566.js js1_5/Regress/regress-312260.js js1_5/Regress/regress-322430.js js1_5/decompilation/regress-356083.js js1_5/decompilation/regress-356248.js js1_5/extensions/regress-361856.js js1_5/extensions/regress-365527.js js1_5/extensions/regress-376052.js js1_6/Regress/regress-353078.js ecma_3/RegExp/regress-375715-01-n.js js1_5/extensions/regress-380581.js js1_5/extensions/regress-381205.js js1_5/extensions/regress-381211.js e4x/Regress/regress-383255.js ecma_3/RegExp/regress-375711.js ecma_3/RegExp/regress-375715-04.js js1_5/Regress/regress-367561-03.js js1_5/extensions/regress-367630.js js1_5/extensions/regress-375801.js js1_5/extensions/regress-380831.js js1_5/extensions/regress-382509.js js1_5/extensions/regress-383965.js js1_6/Regress/regress-382509.js e4x/Regress/regress-380833.js js1_5/extensions/regress-358594-01.js js1_5/extensions/regress-358594-02.js js1_5/extensions/regress-358594-03.js js1_5/extensions/regress-358594-04.js js1_5/extensions/regress-358594-05.js js1_5/extensions/regress-358594-06.js js1_7/extensions/regress-380933.js ecma_3/extensions/regress-368516.js js1_5/extensions/regress-351463-01.js js1_5/extensions/regress-355655.js js1_7/block/regress-352422.js js1_7/block/regress-352786.js js1_7/block/regress-352907.js js1_7/block/regress-376410.js js1_7/block/regress-411279.js ecma_3/Number/15.7.4.2-01.js ecma_3/Number/15.7.4.3-01.js ecma_3/Number/15.7.4.7-2.js e4x/Regress/regress-355569.js ecma_3/Array/15.4.5.1-01.js ecma_3/Operators/order-01.js ecma_3/Statements/regress-444979.js ecma_3/String/15.5.4.11.js ecma_3/Unicode/regress-352044-01.js ecma_3/extensions/regress-430740.js ecma_3_1/Object/regress-444787.js ecma_3_1/RegExp/regress-305064.js js1_5/Array/regress-456845.js js1_5/Regress/regress-352604.js js1_5/Regress/regress-410852.js js1_5/Regress/regress-416628.js js1_5/Regress/regress-420919.js js1_5/Regress/regress-422348.js js1_5/Regress/regress-449627.js js1_5/Regress/regress-450369.js js1_5/Regress/regress-451946.js js1_5/Regress/regress-452008.js js1_5/Regress/regress-452170.js js1_5/Regress/regress-452333.js js1_5/Regress/regress-452336.js js1_5/Regress/regress-452495.js js1_5/Regress/regress-452573-01.js js1_5/Regress/regress-452573-02.js js1_5/Regress/regress-452713.js js1_5/Regress/regress-452724-01.js js1_5/Regress/regress-452724-02.js js1_5/Regress/regress-452853.js js1_5/Regress/regress-452884-01.js js1_5/Regress/regress-452884-02.js js1_5/Regress/regress-453173.js js1_5/Regress/regress-453397.js js1_5/Regress/regress-453701.js js1_5/Regress/regress-453747.js js1_5/Regress/regress-454682.js js1_5/Regress/regress-454981.js js1_5/Regress/regress-455605.js js1_5/Regress/regress-455748.js js1_5/Regress/regress-455758-01.js js1_5/Regress/regress-455758-02.js js1_5/Regress/regress-456477-01.js js1_5/Regress/regress-456477-02.js js1_5/Regress/regress-456494.js js1_5/Regress/regress-456540-01.js js1_5/Regress/regress-456540-02.js js1_5/Regress/regress-457456.js js1_5/Regress/regress-457778.js js1_5/Regress/regress-459085.js js1_5/decompilation/regress-437288-02.js js1_5/decompilation/regress-457824.js js1_5/extensions/regress-352604.js js1_5/extensions/regress-356378.js js1_5/extensions/regress-359024.js js1_5/extensions/regress-416834.js js1_5/extensions/regress-418730.js js1_5/extensions/regress-420612.js js1_5/extensions/regress-420869-01.js js1_5/extensions/regress-421621.js js1_5/extensions/regress-424257.js js1_5/extensions/regress-424683-01.js js1_5/extensions/regress-432075.js js1_5/extensions/regress-434837-01.js js1_5/extensions/regress-435345-01.js js1_5/extensions/regress-437288-01.js js1_5/extensions/regress-452178.js js1_5/extensions/regress-452338.js js1_5/extensions/regress-452372.js js1_5/extensions/regress-452565.js js1_5/extensions/regress-453249.js js1_5/extensions/regress-455380.js js1_5/extensions/regress-455408.js js1_5/extensions/regress-455413.js js1_6/extensions/regress-455464-01.js js1_6/extensions/regress-455464-02.js js1_6/extensions/regress-455464-03.js js1_6/extensions/regress-456826.js js1_7/extensions/regress-455982-01.js js1_7/extensions/regress-455982-02.js js1_7/regress/regress-385133-01.js js1_7/regress/regress-385133-02.js js1_7/regress/regress-410649.js js1_7/regress/regress-420399.js js1_7/regress/regress-452703.js js1_7/regress/regress-452960.js js1_7/regress/regress-453049.js js1_7/regress/regress-453051.js js1_7/regress/regress-453411.js htmlunit-core-js-2.8/rhino/testsrc/opt9.tests0000644000175000017500000014726511321335670021214 0ustar cavedoncavedone4x/Expressions/11.1.1.js e4x/Expressions/11.1.2.js e4x/Expressions/11.1.3.js e4x/Expressions/11.1.4-06.js e4x/Expressions/11.1.4-07.js e4x/Expressions/11.1.5.js e4x/Expressions/11.2.1.js e4x/Expressions/11.2.2.js e4x/Expressions/11.2.3.js e4x/Expressions/11.2.4.js e4x/Expressions/11.3.1.js e4x/Expressions/11.3.2.js e4x/Expressions/11.4.1.js e4x/Expressions/11.5.1.js e4x/Expressions/11.6.3.js e4x/Expressions/regress-301545.js e4x/Expressions/regress-302531.js e4x/Expressions/regress-340024.js e4x/GC/regress-292455.js e4x/GC/regress-313952-01.js e4x/GC/regress-324117.js e4x/Namespace/13.2.1.js e4x/Namespace/13.2.2.js e4x/Namespace/13.2.5.js e4x/Namespace/regress-283972.js e4x/Namespace/regress-292863.js e4x/Namespace/regress-350442.js e4x/QName/13.3.1.js e4x/QName/13.3.2.js e4x/QName/13.3.5.js e4x/QName/regress-373595-01.js e4x/QName/regress-373595-02.js e4x/QName/regress-373595-03.js e4x/Regress/regress-263935.js e4x/Regress/regress-263936.js e4x/Regress/regress-264369.js e4x/Regress/regress-271545.js e4x/Regress/regress-277650.js e4x/Regress/regress-277664.js e4x/Regress/regress-277683.js e4x/Regress/regress-277935.js e4x/Regress/regress-283349.js e4x/Regress/regress-290056.js e4x/Regress/regress-301573.js e4x/Regress/regress-301596.js e4x/Regress/regress-301692.js e4x/Regress/regress-313799.js e4x/Regress/regress-325425.js e4x/Regress/regress-327691-01.js e4x/Regress/regress-327691-02.js e4x/Regress/regress-327697.js e4x/Regress/regress-328249.js e4x/Regress/regress-329257.js e4x/Regress/regress-331664.js e4x/Regress/regress-350206-1.js e4x/Regress/regress-350206.js e4x/Regress/regress-352103.js e4x/Regress/regress-354145-01.js e4x/Regress/regress-354145-02.js e4x/Regress/regress-354145-03.js e4x/Regress/regress-354145-04.js e4x/Regress/regress-354145-05.js e4x/Regress/regress-354145-07.js e4x/Regress/regress-355474-02.js e4x/Regress/regress-356238-01.js e4x/Regress/regress-369032.js e4x/Regress/regress-369536.js e4x/Regress/regress-372564.js e4x/Regress/regress-374106.js e4x/Regress/regress-374112.js e4x/Regress/regress-374116.js e4x/Regress/regress-374160.js e4x/Regress/regress-378492.js e4x/Regress/regress-407323.js e4x/Statements/12.1.js e4x/Statements/12.2.js e4x/Statements/12.3-01.js e4x/TypeConversion/10.1.2.js e4x/TypeConversion/10.3.1.js e4x/TypeConversion/10.3.js e4x/TypeConversion/10.4.1.js e4x/TypeConversion/10.4.js e4x/Types/9.1.1.1.js e4x/Types/9.1.1.2.js e4x/Types/9.1.1.3.js e4x/Types/9.1.1.6.js e4x/Types/9.2.1.1.js e4x/Types/9.2.1.2.js e4x/Types/9.2.1.8.js e4x/XML/13.4.1.js e4x/XML/13.4.2.js e4x/XML/13.4.3.10.js e4x/XML/13.4.4.12-1.js e4x/XML/13.4.4.12.js e4x/XML/13.4.4.13.js e4x/XML/13.4.4.14.js e4x/XML/13.4.4.15.js e4x/XML/13.4.4.16.js e4x/XML/13.4.4.18.js e4x/XML/13.4.4.19.js e4x/XML/13.4.4.2.js e4x/XML/13.4.4.20.js e4x/XML/13.4.4.21.js e4x/XML/13.4.4.23.js e4x/XML/13.4.4.24.js e4x/XML/13.4.4.25.js e4x/XML/13.4.4.27.js e4x/XML/13.4.4.3.js e4x/XML/13.4.4.30.js e4x/XML/13.4.4.31.js e4x/XML/13.4.4.32-01.js e4x/XML/13.4.4.32.js e4x/XML/13.4.4.33.js e4x/XML/13.4.4.34.js e4x/XML/13.4.4.35.js e4x/XML/13.4.4.36.js e4x/XML/13.4.4.37.js e4x/XML/13.4.4.38.js e4x/XML/13.4.4.39.js e4x/XML/13.4.4.4.js e4x/XML/13.4.4.40.js e4x/XML/13.4.4.5.js e4x/XML/13.4.4.7.js e4x/XML/13.4.4.8.js e4x/XML/regress-291930.js e4x/XML/regress-324688.js e4x/XML/regress-336921.js e4x/XMLList/13.5.1.js e4x/XMLList/13.5.2.js e4x/XMLList/13.5.4.10.js e4x/XMLList/13.5.4.11.js e4x/XMLList/13.5.4.12.js e4x/XMLList/13.5.4.13.js e4x/XMLList/13.5.4.14.js e4x/XMLList/13.5.4.15.js e4x/XMLList/13.5.4.16.js e4x/XMLList/13.5.4.17.js e4x/XMLList/13.5.4.18.js e4x/XMLList/13.5.4.19.js e4x/XMLList/13.5.4.2.js e4x/XMLList/13.5.4.20.js e4x/XMLList/13.5.4.21.js e4x/XMLList/13.5.4.22.js e4x/XMLList/13.5.4.3.js e4x/XMLList/13.5.4.4.js e4x/XMLList/13.5.4.5.js e4x/XMLList/13.5.4.6.js e4x/XMLList/13.5.4.7.js e4x/XMLList/13.5.4.8.js e4x/XMLList/13.5.4.9.js e4x/decompilation/regress-349814.js e4x/decompilation/regress-349815.js e4x/decompilation/regress-349822.js e4x/decompilation/regress-349956.js e4x/decompilation/regress-355474-01.js e4x/decompilation/regress-373678.js e4x/extensions/regress-305335.js e4x/extensions/regress-321547.js e4x/extensions/regress-327534.js e4x/extensions/regress-327897.js e4x/extensions/regress-354145-06.js e4x/extensions/regress-354151-01.js ecma/Array/15.4-1.js ecma/Array/15.4-2.js ecma/Array/15.4.1.1.js ecma/Array/15.4.1.2.js ecma/Array/15.4.1.3.js ecma/Array/15.4.1.js ecma/Array/15.4.2.1-1.js ecma/Array/15.4.2.1-2.js ecma/Array/15.4.2.1-3.js ecma/Array/15.4.2.2-1.js ecma/Array/15.4.2.2-2.js ecma/Array/15.4.2.3.js ecma/Array/15.4.3.2.js ecma/Array/15.4.4.1.js ecma/Array/15.4.4.2.js ecma/Array/15.4.4.3-1.js ecma/Array/15.4.4.4-1.js ecma/Array/15.4.4.4-2.js ecma/Array/15.4.4.5-1.js ecma/Array/15.4.4.5-2.js ecma/Array/15.4.4.js ecma/Array/15.4.5.1-2.js ecma/Array/15.4.5.2-1.js ecma/Array/15.4.5.2-2.js ecma/Boolean/15.6.2.js ecma/Boolean/15.6.3.1-1.js ecma/Boolean/15.6.3.1-2.js ecma/Boolean/15.6.3.1.js ecma/Boolean/15.6.4-1.js ecma/Boolean/15.6.4.1.js ecma/Boolean/15.6.4.2-2.js ecma/Boolean/15.6.4.2-3.js ecma/Boolean/15.6.4.2-4-n.js ecma/Boolean/15.6.4.3-1.js ecma/Boolean/15.6.4.3-2.js ecma/Boolean/15.6.4.3-3.js ecma/Boolean/15.6.4.3-4-n.js ecma/Boolean/15.6.4.3.js ecma/Boolean/15.6.4.js ecma/Date/15.9.1.1-1.js ecma/Date/15.9.1.1-2.js ecma/Date/15.9.1.13-1.js ecma/Date/15.9.2.1.js ecma/Date/15.9.2.2-1.js ecma/Date/15.9.2.2-2.js ecma/Date/15.9.2.2-3.js ecma/Date/15.9.2.2-5.js ecma/Date/15.9.2.2-6.js ecma/Date/15.9.3.1-2.js ecma/Date/15.9.3.1-3.js ecma/Date/15.9.3.1-4.js ecma/Date/15.9.3.1-5.js ecma/Date/15.9.3.2-2.js ecma/Date/15.9.3.2-3.js ecma/Date/15.9.3.2-4.js ecma/Date/15.9.3.2-5.js ecma/Date/15.9.3.8-1.js ecma/Date/15.9.3.8-2.js ecma/Date/15.9.3.8-3.js ecma/Date/15.9.3.8-4.js ecma/Date/15.9.3.8-5.js ecma/Date/15.9.4.2.js ecma/Date/15.9.4.3.js ecma/Date/15.9.5.1.js ecma/Date/15.9.5.10-1.js ecma/Date/15.9.5.10-10.js ecma/Date/15.9.5.10-11.js ecma/Date/15.9.5.10-12.js ecma/Date/15.9.5.10-13.js ecma/Date/15.9.5.10-4.js ecma/Date/15.9.5.10-5.js ecma/Date/15.9.5.10-6.js ecma/Date/15.9.5.10-7.js ecma/Date/15.9.5.10-8.js ecma/Date/15.9.5.10-9.js ecma/Date/15.9.5.11-1.js ecma/Date/15.9.5.11-3.js ecma/Date/15.9.5.11-4.js ecma/Date/15.9.5.11-5.js ecma/Date/15.9.5.11-6.js ecma/Date/15.9.5.11-7.js ecma/Date/15.9.5.12-1.js ecma/Date/15.9.5.12-3.js ecma/Date/15.9.5.12-4.js ecma/Date/15.9.5.12-5.js ecma/Date/15.9.5.12-6.js ecma/Date/15.9.5.12-7.js ecma/Date/15.9.5.12-8.js ecma/Date/15.9.5.13-1.js ecma/Date/15.9.5.13-2.js ecma/Date/15.9.5.13-3.js ecma/Date/15.9.5.13-4.js ecma/Date/15.9.5.13-5.js ecma/Date/15.9.5.13-6.js ecma/Date/15.9.5.13-7.js ecma/Date/15.9.5.13-8.js ecma/Date/15.9.5.14.js ecma/Date/15.9.5.15.js ecma/Date/15.9.5.16.js ecma/Date/15.9.5.17.js ecma/Date/15.9.5.19.js ecma/Date/15.9.5.2-2-n.js ecma/Date/15.9.5.2.js ecma/Date/15.9.5.20.js ecma/Date/15.9.5.21-1.js ecma/Date/15.9.5.21-2.js ecma/Date/15.9.5.21-3.js ecma/Date/15.9.5.21-4.js ecma/Date/15.9.5.21-5.js ecma/Date/15.9.5.21-6.js ecma/Date/15.9.5.21-7.js ecma/Date/15.9.5.21-8.js ecma/Date/15.9.5.22-2.js ecma/Date/15.9.5.22-3.js ecma/Date/15.9.5.22-4.js ecma/Date/15.9.5.22-5.js ecma/Date/15.9.5.22-6.js ecma/Date/15.9.5.22-7.js ecma/Date/15.9.5.22-8.js ecma/Date/15.9.5.23-1.js ecma/Date/15.9.5.23-10.js ecma/Date/15.9.5.23-11.js ecma/Date/15.9.5.23-12.js ecma/Date/15.9.5.23-13.js ecma/Date/15.9.5.23-14.js ecma/Date/15.9.5.23-15.js ecma/Date/15.9.5.23-16.js ecma/Date/15.9.5.23-17.js ecma/Date/15.9.5.23-18.js ecma/Date/15.9.5.23-2.js ecma/Date/15.9.5.23-3-n.js ecma/Date/15.9.5.23-4.js ecma/Date/15.9.5.23-5.js ecma/Date/15.9.5.23-6.js ecma/Date/15.9.5.23-7.js ecma/Date/15.9.5.23-8.js ecma/Date/15.9.5.23-9.js ecma/Date/15.9.5.24-1.js ecma/Date/15.9.5.24-2.js ecma/Date/15.9.5.24-3.js ecma/Date/15.9.5.24-4.js ecma/Date/15.9.5.24-5.js ecma/Date/15.9.5.24-6.js ecma/Date/15.9.5.24-7.js ecma/Date/15.9.5.24-8.js ecma/Date/15.9.5.25-1.js ecma/Date/15.9.5.26-1.js ecma/Date/15.9.5.27-1.js ecma/Date/15.9.5.28-1.js ecma/Date/15.9.5.29-1.js ecma/Date/15.9.5.3-2.js ecma/Date/15.9.5.30-1.js ecma/Date/15.9.5.31-1.js ecma/Date/15.9.5.32-1.js ecma/Date/15.9.5.33-1.js ecma/Date/15.9.5.34-1.js ecma/Date/15.9.5.35-1.js ecma/Date/15.9.5.36-1.js ecma/Date/15.9.5.36-2.js ecma/Date/15.9.5.36-4.js ecma/Date/15.9.5.36-5.js ecma/Date/15.9.5.36-6.js ecma/Date/15.9.5.36-7.js ecma/Date/15.9.5.37-2.js ecma/Date/15.9.5.37-3.js ecma/Date/15.9.5.37-4.js ecma/Date/15.9.5.37-5.js ecma/Date/15.9.5.4-1.js ecma/Date/15.9.5.4-2-n.js ecma/Date/15.9.5.6.js ecma/Date/15.9.5.7.js ecma/Date/15.9.5.8.js ecma/Date/15.9.5.9.js ecma/Date/15.9.5.js ecma/ExecutionContexts/10.1.3-1.js ecma/ExecutionContexts/10.1.3-2.js ecma/ExecutionContexts/10.1.3.js ecma/ExecutionContexts/10.1.4-1.js ecma/ExecutionContexts/10.1.4-10.js ecma/ExecutionContexts/10.1.4-3.js ecma/ExecutionContexts/10.1.4-4.js ecma/ExecutionContexts/10.1.4-5.js ecma/ExecutionContexts/10.1.4-6.js ecma/ExecutionContexts/10.1.4-7.js ecma/ExecutionContexts/10.1.4-8.js ecma/ExecutionContexts/10.1.5-1.js ecma/ExecutionContexts/10.1.5-2.js ecma/ExecutionContexts/10.1.5-3.js ecma/ExecutionContexts/10.1.5-4.js ecma/ExecutionContexts/10.1.8-2.js ecma/ExecutionContexts/10.1.8-3.js ecma/ExecutionContexts/10.2.1.js ecma/ExecutionContexts/10.2.2-1.js ecma/ExecutionContexts/10.2.2-2.js ecma/ExecutionContexts/10.2.3-1.js ecma/ExecutionContexts/10.2.3-2.js ecma/Expressions/11.1.1.js ecma/Expressions/11.10-1.js ecma/Expressions/11.10-2.js ecma/Expressions/11.10-3.js ecma/Expressions/11.12-1.js ecma/Expressions/11.12-2-n.js ecma/Expressions/11.12-3.js ecma/Expressions/11.12-4.js ecma/Expressions/11.13.1.js ecma/Expressions/11.13.2-1.js ecma/Expressions/11.13.2-2.js ecma/Expressions/11.13.2-3.js ecma/Expressions/11.13.2-4.js ecma/Expressions/11.13.2-5.js ecma/Expressions/11.14-1.js ecma/Expressions/11.2.1-1.js ecma/Expressions/11.2.1-2.js ecma/Expressions/11.2.1-3-n.js ecma/Expressions/11.2.1-4-n.js ecma/Expressions/11.2.1-5.js ecma/Expressions/11.2.2-1-n.js ecma/Expressions/11.2.2-1.js ecma/Expressions/11.2.2-10-n.js ecma/Expressions/11.2.2-11.js ecma/Expressions/11.2.2-2-n.js ecma/Expressions/11.2.2-3-n.js ecma/Expressions/11.2.2-4-n.js ecma/Expressions/11.2.2-5-n.js ecma/Expressions/11.2.2-6-n.js ecma/Expressions/11.2.2-7-n.js ecma/Expressions/11.2.2-8-n.js ecma/Expressions/11.2.2-9-n.js ecma/Expressions/11.2.3-1.js ecma/Expressions/11.2.3-2-n.js ecma/Expressions/11.2.3-3-n.js ecma/Expressions/11.2.3-4-n.js ecma/Expressions/11.2.3-5.js ecma/Expressions/11.3.1.js ecma/Expressions/11.3.2.js ecma/Expressions/11.4.2.js ecma/Expressions/11.4.3.js ecma/Expressions/11.4.4.js ecma/Expressions/11.4.5.js ecma/Expressions/11.4.6.js ecma/Expressions/11.4.8.js ecma/Expressions/11.4.9.js ecma/Expressions/11.5.1.js ecma/Expressions/11.5.2.js ecma/Expressions/11.5.3.js ecma/Expressions/11.6.1-1.js ecma/Expressions/11.6.1-2.js ecma/Expressions/11.6.1-3.js ecma/Expressions/11.6.2-1.js ecma/Expressions/11.6.3.js ecma/Expressions/11.7.1.js ecma/Expressions/11.7.2.js ecma/Expressions/11.8.1.js ecma/Expressions/11.8.2.js ecma/Expressions/11.8.3.js ecma/Expressions/11.9.2.js ecma/Expressions/11.9.3.js ecma/FunctionObjects/15.3.1.1-1.js ecma/FunctionObjects/15.3.1.1-2.js ecma/FunctionObjects/15.3.1.1-3.js ecma/FunctionObjects/15.3.2.1-1.js ecma/FunctionObjects/15.3.2.1-2.js ecma/FunctionObjects/15.3.2.1-3.js ecma/FunctionObjects/15.3.3.1-2.js ecma/FunctionObjects/15.3.3.1-3.js ecma/FunctionObjects/15.3.3.1-4.js ecma/FunctionObjects/15.3.3.2.js ecma/FunctionObjects/15.3.4-1.js ecma/FunctionObjects/15.3.4.1.js ecma/FunctionObjects/15.3.4.js ecma/FunctionObjects/15.3.5-1.js ecma/FunctionObjects/15.3.5-2.js ecma/FunctionObjects/15.3.5.1.js ecma/FunctionObjects/15.3.5.3.js ecma/GlobalObject/15.1-1-n.js ecma/GlobalObject/15.1-2-n.js ecma/GlobalObject/15.1.1.1.js ecma/GlobalObject/15.1.1.2.js ecma/GlobalObject/15.1.2.1-2.js ecma/GlobalObject/15.1.2.2-2.js ecma/GlobalObject/15.1.2.3-2.js ecma/GlobalObject/15.1.2.5-2.js ecma/GlobalObject/15.1.2.5-3.js ecma/LexicalConventions/7.1-1.js ecma/LexicalConventions/7.1-2.js ecma/LexicalConventions/7.1-3.js ecma/LexicalConventions/7.2-1.js ecma/LexicalConventions/7.2-2-n.js ecma/LexicalConventions/7.2-3-n.js ecma/LexicalConventions/7.2-4-n.js ecma/LexicalConventions/7.2-5-n.js ecma/LexicalConventions/7.2-6.js ecma/LexicalConventions/7.3-1.js ecma/LexicalConventions/7.3-10.js ecma/LexicalConventions/7.3-11.js ecma/LexicalConventions/7.3-12.js ecma/LexicalConventions/7.3-13-n.js ecma/LexicalConventions/7.3-2.js ecma/LexicalConventions/7.3-3.js ecma/LexicalConventions/7.3-4.js ecma/LexicalConventions/7.3-5.js ecma/LexicalConventions/7.3-6.js ecma/LexicalConventions/7.3-8.js ecma/LexicalConventions/7.3-9.js ecma/LexicalConventions/7.4.1-1-n.js ecma/LexicalConventions/7.4.1-2-n.js ecma/LexicalConventions/7.4.1-3-n.js ecma/LexicalConventions/7.4.2-1-n.js ecma/LexicalConventions/7.4.2-10-n.js ecma/LexicalConventions/7.4.2-11-n.js ecma/LexicalConventions/7.4.2-12-n.js ecma/LexicalConventions/7.4.2-13-n.js ecma/LexicalConventions/7.4.2-14-n.js ecma/LexicalConventions/7.4.2-15-n.js ecma/LexicalConventions/7.4.2-16-n.js ecma/LexicalConventions/7.4.2-2-n.js ecma/LexicalConventions/7.4.2-3-n.js ecma/LexicalConventions/7.4.2-4-n.js ecma/LexicalConventions/7.4.2-5-n.js ecma/LexicalConventions/7.4.2-6-n.js ecma/LexicalConventions/7.4.2-7-n.js ecma/LexicalConventions/7.4.2-8-n.js ecma/LexicalConventions/7.4.3-1-n.js ecma/LexicalConventions/7.4.3-10-n.js ecma/LexicalConventions/7.4.3-11-n.js ecma/LexicalConventions/7.4.3-13-n.js ecma/LexicalConventions/7.4.3-15-n.js ecma/LexicalConventions/7.4.3-16-n.js ecma/LexicalConventions/7.4.3-2-n.js ecma/LexicalConventions/7.4.3-3-n.js ecma/LexicalConventions/7.4.3-4-n.js ecma/LexicalConventions/7.4.3-5-n.js ecma/LexicalConventions/7.4.3-6-n.js ecma/LexicalConventions/7.4.3-7-n.js ecma/LexicalConventions/7.4.3-8-n.js ecma/LexicalConventions/7.4.3-9-n.js ecma/LexicalConventions/7.5-1.js ecma/LexicalConventions/7.5-10-n.js ecma/LexicalConventions/7.5-2-n.js ecma/LexicalConventions/7.5-3-n.js ecma/LexicalConventions/7.5-4-n.js ecma/LexicalConventions/7.5-5-n.js ecma/LexicalConventions/7.5-6.js ecma/LexicalConventions/7.5-7.js ecma/LexicalConventions/7.5-8-n.js ecma/LexicalConventions/7.5-9-n.js ecma/LexicalConventions/7.6.js ecma/LexicalConventions/7.7.1.js ecma/LexicalConventions/7.7.2.js ecma/LexicalConventions/7.7.3-1.js ecma/LexicalConventions/7.7.3-2.js ecma/LexicalConventions/7.7.3.js ecma/LexicalConventions/7.7.4.js ecma/LexicalConventions/7.8.2-n.js ecma/Math/15.8-2-n.js ecma/Math/15.8-3-n.js ecma/Math/15.8.1.1-1.js ecma/Math/15.8.1.1-2.js ecma/Math/15.8.1.2-1.js ecma/Math/15.8.1.3-1.js ecma/Math/15.8.1.3-2.js ecma/Math/15.8.1.4-1.js ecma/Math/15.8.1.4-2.js ecma/Math/15.8.1.5-1.js ecma/Math/15.8.1.5-2.js ecma/Math/15.8.1.6-1.js ecma/Math/15.8.1.6-2.js ecma/Math/15.8.1.7-1.js ecma/Math/15.8.1.7-2.js ecma/Math/15.8.1.8-1.js ecma/Math/15.8.1.8-2.js ecma/Math/15.8.1.8-3.js ecma/Math/15.8.2.1.js ecma/Math/15.8.2.10.js ecma/Math/15.8.2.12.js ecma/Math/15.8.2.13.js ecma/Math/15.8.2.14.js ecma/Math/15.8.2.15.js ecma/Math/15.8.2.16.js ecma/Math/15.8.2.17.js ecma/Math/15.8.2.18.js ecma/Math/15.8.2.2.js ecma/Math/15.8.2.3.js ecma/Math/15.8.2.4.js ecma/Math/15.8.2.5.js ecma/Math/15.8.2.6.js ecma/Math/15.8.2.7.js ecma/Math/15.8.2.8.js ecma/Math/15.8.2.9.js ecma/Number/15.7.2.js ecma/Number/15.7.3.1-1.js ecma/Number/15.7.3.1-2.js ecma/Number/15.7.3.1-3.js ecma/Number/15.7.3.2-1.js ecma/Number/15.7.3.2-2.js ecma/Number/15.7.3.2-3.js ecma/Number/15.7.3.3-1.js ecma/Number/15.7.3.3-2.js ecma/Number/15.7.3.3-3.js ecma/Number/15.7.3.4-1.js ecma/Number/15.7.3.4-2.js ecma/Number/15.7.3.4-3.js ecma/Number/15.7.3.4-4.js ecma/Number/15.7.3.5-1.js ecma/Number/15.7.3.5-2.js ecma/Number/15.7.3.5-3.js ecma/Number/15.7.3.5-4.js ecma/Number/15.7.3.6-1.js ecma/Number/15.7.3.6-4.js ecma/Number/15.7.3.js ecma/Number/15.7.4-1.js ecma/Number/15.7.4.1.js ecma/Number/15.7.4.2-1.js ecma/Number/15.7.4.2-2-n.js ecma/Number/15.7.4.2-3-n.js ecma/Number/15.7.4.2-4.js ecma/Number/15.7.4.3-1.js ecma/Number/15.7.4.3-2.js ecma/ObjectObjects/15.2.1.2.js ecma/ObjectObjects/15.2.2.1.js ecma/ObjectObjects/15.2.2.2.js ecma/ObjectObjects/15.2.3.1-1.js ecma/ObjectObjects/15.2.3.1-2.js ecma/ObjectObjects/15.2.3.1-3.js ecma/ObjectObjects/15.2.3.1-4.js ecma/ObjectObjects/15.2.3.js ecma/ObjectObjects/15.2.4.1.js ecma/ObjectObjects/15.2.4.2.js ecma/ObjectObjects/15.2.4.3.js ecma/SourceText/6-1.js ecma/SourceText/6-2.js ecma/Statements/12.10-1.js ecma/Statements/12.10.js ecma/Statements/12.5-1.js ecma/Statements/12.5-2.js ecma/Statements/12.6.2-1.js ecma/Statements/12.6.2-2.js ecma/Statements/12.6.2-4.js ecma/Statements/12.6.2-5.js ecma/Statements/12.6.2-6.js ecma/Statements/12.6.2-7.js ecma/Statements/12.6.2-8.js ecma/Statements/12.6.2-9-n.js ecma/Statements/12.6.3-1.js ecma/Statements/12.6.3-10.js ecma/Statements/12.6.3-11.js ecma/Statements/12.6.3-12.js ecma/Statements/12.6.3-19.js ecma/Statements/12.6.3-2.js ecma/Statements/12.6.3-3.js ecma/Statements/12.6.3-4.js ecma/Statements/12.6.3-5-n.js ecma/Statements/12.6.3-6-n.js ecma/Statements/12.6.3-7-n.js ecma/Statements/12.6.3-9-n.js ecma/Statements/12.7-1-n.js ecma/Statements/12.8-1-n.js ecma/Statements/12.9-1-n.js ecma/String/15.5.1.js ecma/String/15.5.2.js ecma/String/15.5.3.1-1.js ecma/String/15.5.3.1-2.js ecma/String/15.5.3.1-3.js ecma/String/15.5.3.1-4.js ecma/String/15.5.3.2-1.js ecma/String/15.5.3.2-2.js ecma/String/15.5.3.2-3.js ecma/String/15.5.3.js ecma/String/15.5.4.1.js ecma/String/15.5.4.10-1.js ecma/String/15.5.4.11-1.js ecma/String/15.5.4.11-3.js ecma/String/15.5.4.11-4.js ecma/String/15.5.4.11-6.js ecma/String/15.5.4.12-2.js ecma/String/15.5.4.12-3.js ecma/String/15.5.4.2-1.js ecma/String/15.5.4.2-2-n.js ecma/String/15.5.4.2-3.js ecma/String/15.5.4.2.js ecma/String/15.5.4.3-1.js ecma/String/15.5.4.3-2.js ecma/String/15.5.4.3-3-n.js ecma/String/15.5.4.4-1.js ecma/String/15.5.4.4-2.js ecma/String/15.5.4.4-3.js ecma/String/15.5.4.4-4.js ecma/String/15.5.4.5-1.js ecma/String/15.5.4.5-2.js ecma/String/15.5.4.5-3.js ecma/String/15.5.4.5-4.js ecma/String/15.5.4.5-5.js ecma/String/15.5.4.6-1.js ecma/String/15.5.4.7-2.js ecma/String/15.5.4.8-1.js ecma/String/15.5.4.8-3.js ecma/String/15.5.4.9-1.js ecma/String/15.5.4.js ecma/String/15.5.5.1.js ecma/TypeConversion/9.2.js ecma/TypeConversion/9.3-1.js ecma/TypeConversion/9.3.1-1.js ecma/TypeConversion/9.3.1-2.js ecma/TypeConversion/9.3.1-3.js ecma/TypeConversion/9.3.js ecma/TypeConversion/9.4-1.js ecma/TypeConversion/9.4-2.js ecma/TypeConversion/9.5-2.js ecma/TypeConversion/9.6.js ecma/TypeConversion/9.7.js ecma/TypeConversion/9.8.1.js ecma/TypeConversion/9.9-1.js ecma/Types/8.1.js ecma/Types/8.4.js ecma/Types/8.6.2.1-1.js ecma/extensions/10.1.4-9.js ecma/extensions/10.1.6.js ecma/extensions/10.1.8-1.js ecma/extensions/11.6.1-1.js ecma/extensions/11.6.1-2.js ecma/extensions/11.6.1-3.js ecma/extensions/11.6.2-1.js ecma/extensions/15-2.js ecma/extensions/15.2.1.1.js ecma/extensions/15.2.3-1.js ecma/extensions/15.2.4.js ecma/extensions/15.3.1.1-2.js ecma/extensions/15.3.2.1-1.js ecma/extensions/15.3.2.1-2.js ecma/extensions/15.4.3.js ecma/extensions/15.5.3.js ecma/extensions/15.5.4.2.js ecma/extensions/15.5.4.4-4.js ecma/extensions/15.5.4.5-6.js ecma/extensions/15.5.4.7-3.js ecma/extensions/15.6.3.1-5.js ecma/extensions/15.6.3.js ecma/extensions/15.6.4-2.js ecma/extensions/15.7.3.js ecma/extensions/15.7.4.js ecma/extensions/15.8-1.js ecma/extensions/15.9.5.js ecma/extensions/8.6.2.1-1.js ecma/extensions/9.9-1.js ecma/jsref.js ecma_2/Exceptions/boolean-001.js ecma_2/Exceptions/date-001.js ecma_2/Exceptions/date-002.js ecma_2/Exceptions/date-004.js ecma_2/Exceptions/exception-001.js ecma_2/Exceptions/exception-002.js ecma_2/Exceptions/exception-004.js ecma_2/Exceptions/exception-005.js ecma_2/Exceptions/exception-006.js ecma_2/Exceptions/exception-007.js ecma_2/Exceptions/exception-008.js ecma_2/Exceptions/exception-009.js ecma_2/Exceptions/exception-010-n.js ecma_2/Exceptions/exception-011-n.js ecma_2/Exceptions/expression-002.js ecma_2/Exceptions/expression-004.js ecma_2/Exceptions/expression-005.js ecma_2/Exceptions/expression-006.js ecma_2/Exceptions/expression-007.js ecma_2/Exceptions/expression-008.js ecma_2/Exceptions/expression-009.js ecma_2/Exceptions/expression-010.js ecma_2/Exceptions/expression-011.js ecma_2/Exceptions/expression-012.js ecma_2/Exceptions/expression-013.js ecma_2/Exceptions/expression-014.js ecma_2/Exceptions/expression-015.js ecma_2/Exceptions/expression-016.js ecma_2/Exceptions/expression-017.js ecma_2/Exceptions/global-001.js ecma_2/Exceptions/global-002.js ecma_2/Exceptions/lexical-001.js ecma_2/Exceptions/lexical-002.js ecma_2/Exceptions/lexical-003.js ecma_2/Exceptions/lexical-004.js ecma_2/Exceptions/lexical-005.js ecma_2/Exceptions/lexical-006.js ecma_2/Exceptions/lexical-007.js ecma_2/Exceptions/lexical-009.js ecma_2/Exceptions/lexical-010.js ecma_2/Exceptions/lexical-011.js ecma_2/Exceptions/lexical-012.js ecma_2/Exceptions/lexical-013.js ecma_2/Exceptions/lexical-014.js ecma_2/Exceptions/lexical-015.js ecma_2/Exceptions/lexical-016.js ecma_2/Exceptions/lexical-017.js ecma_2/Exceptions/lexical-018.js ecma_2/Exceptions/lexical-019.js ecma_2/Exceptions/lexical-020.js ecma_2/Exceptions/lexical-022.js ecma_2/Exceptions/lexical-023.js ecma_2/Exceptions/lexical-024.js ecma_2/Exceptions/lexical-025.js ecma_2/Exceptions/lexical-026.js ecma_2/Exceptions/lexical-027.js ecma_2/Exceptions/lexical-028.js ecma_2/Exceptions/lexical-029.js ecma_2/Exceptions/lexical-030.js ecma_2/Exceptions/lexical-031.js ecma_2/Exceptions/lexical-032.js ecma_2/Exceptions/lexical-033.js ecma_2/Exceptions/lexical-034.js ecma_2/Exceptions/lexical-035.js ecma_2/Exceptions/lexical-036.js ecma_2/Exceptions/lexical-037.js ecma_2/Exceptions/lexical-038.js ecma_2/Exceptions/lexical-039.js ecma_2/Exceptions/lexical-040.js ecma_2/Exceptions/lexical-041.js ecma_2/Exceptions/lexical-042.js ecma_2/Exceptions/lexical-047.js ecma_2/Exceptions/lexical-048.js ecma_2/Exceptions/lexical-049.js ecma_2/Exceptions/lexical-050.js ecma_2/Exceptions/lexical-051.js ecma_2/Exceptions/lexical-053.js ecma_2/Exceptions/lexical-054.js ecma_2/Exceptions/number-002.js ecma_2/Exceptions/number-003.js ecma_2/Exceptions/statement-001.js ecma_2/Exceptions/statement-002.js ecma_2/Exceptions/statement-003.js ecma_2/Exceptions/statement-004.js ecma_2/Exceptions/statement-005.js ecma_2/Exceptions/statement-006.js ecma_2/Exceptions/statement-007.js ecma_2/Exceptions/statement-008.js ecma_2/Exceptions/string-001.js ecma_2/Exceptions/string-002.js ecma_2/Expressions/StrictEquality-001.js ecma_2/FunctionObjects/apply-001-n.js ecma_2/FunctionObjects/call-1.js ecma_2/LexicalConventions/keywords-001.js ecma_2/LexicalConventions/regexp-literals-001.js ecma_2/LexicalConventions/regexp-literals-002.js ecma_2/RegExp/constructor-001.js ecma_2/RegExp/exec-002.js ecma_2/RegExp/function-001.js ecma_2/RegExp/hex-001.js ecma_2/RegExp/multiline-001.js ecma_2/RegExp/octal-001.js ecma_2/RegExp/octal-002.js ecma_2/RegExp/octal-003.js ecma_2/RegExp/properties-001.js ecma_2/RegExp/properties-002.js ecma_2/RegExp/regress-001.js ecma_2/RegExp/unicode-001.js ecma_2/Statements/dowhile-001.js ecma_2/Statements/dowhile-002.js ecma_2/Statements/dowhile-003.js ecma_2/Statements/dowhile-004.js ecma_2/Statements/dowhile-005.js ecma_2/Statements/dowhile-006.js ecma_2/Statements/dowhile-007.js ecma_2/Statements/forin-001.js ecma_2/Statements/forin-002.js ecma_2/Statements/if-001.js ecma_2/Statements/label-001.js ecma_2/Statements/label-002.js ecma_2/Statements/switch-002.js ecma_2/Statements/switch-003.js ecma_2/Statements/switch-004.js ecma_2/Statements/try-001.js ecma_2/Statements/try-003.js ecma_2/Statements/try-004.js ecma_2/Statements/try-005.js ecma_2/Statements/try-007.js ecma_2/Statements/try-008.js ecma_2/Statements/try-009.js ecma_2/Statements/try-012.js ecma_2/Statements/while-001.js ecma_2/Statements/while-002.js ecma_2/Statements/while-003.js ecma_2/Statements/while-004.js ecma_2/String/match-001.js ecma_2/String/match-002.js ecma_2/String/match-003.js ecma_2/String/match-004.js ecma_2/String/split-001.js ecma_2/String/split-002.js ecma_2/String/split-003.js ecma_2/extensions/constructor-001.js ecma_2/extensions/function-001.js ecma_2/extensions/instanceof-001.js ecma_2/extensions/instanceof-002.js ecma_2/extensions/instanceof-006.js ecma_2/instanceof/instanceof-001.js ecma_2/instanceof/instanceof-002.js ecma_2/instanceof/regress-7635.js ecma_2/jsref.js ecma_3/Array/15.4.4.11-01.js ecma_3/Array/15.4.4.3-1.js ecma_3/Array/15.4.4.4-001.js ecma_3/Array/regress-101488.js ecma_3/Array/regress-130451.js ecma_3/Array/regress-322135-01.js ecma_3/Date/15.9.4.3.js ecma_3/Date/15.9.5.3.js ecma_3/Date/15.9.5.4.js ecma_3/Date/15.9.5.5.js ecma_3/Date/15.9.5.6.js ecma_3/Date/15.9.5.7.js ecma_3/Exceptions/15.11.1.1.js ecma_3/Exceptions/15.11.4.4-1.js ecma_3/Exceptions/15.11.7.6-001.js ecma_3/Exceptions/15.11.7.6-002.js ecma_3/Exceptions/15.11.7.6-003.js ecma_3/Exceptions/binding-001.js ecma_3/Exceptions/regress-95101.js ecma_3/ExecutionContexts/10.1.3-1.js ecma_3/ExecutionContexts/10.1.3-2.js ecma_3/ExecutionContexts/10.1.3.js ecma_3/ExecutionContexts/10.1.4-1.js ecma_3/ExecutionContexts/10.6.1-01.js ecma_3/ExecutionContexts/regress-23346.js ecma_3/Expressions/11.10-01.js ecma_3/Expressions/11.10-03.js ecma_3/Expressions/11.6.1-1.js ecma_3/Expressions/11.7.1-01.js ecma_3/Expressions/11.7.2-01.js ecma_3/Expressions/11.7.3-01.js ecma_3/Expressions/11.9.6-1.js ecma_3/FunExpr/fe-001-n.js ecma_3/FunExpr/fe-001.js ecma_3/FunExpr/fe-002.js ecma_3/Function/15.3.4.3-1.js ecma_3/Function/15.3.4.4-1.js ecma_3/Function/arguments-002.js ecma_3/Function/call-001.js ecma_3/Function/regress-131964.js ecma_3/Function/regress-137181.js ecma_3/Function/regress-193555.js ecma_3/Function/regress-313570.js ecma_3/Function/regress-49286.js ecma_3/Function/regress-58274.js ecma_3/Function/regress-85880.js ecma_3/Function/regress-94506.js ecma_3/Function/regress-97921.js ecma_3/Function/scope-001.js ecma_3/Function/scope-002.js ecma_3/Number/15.7.4.5-1.js ecma_3/Number/15.7.4.6-1.js ecma_3/Number/15.7.4.7-1.js ecma_3/Number/15.7.4.7-2.js ecma_3/NumberFormatting/tostring-001.js ecma_3/Object/8.6.2.6-001.js ecma_3/Object/class-001.js ecma_3/Object/class-002.js ecma_3/Object/class-003.js ecma_3/Object/class-004.js ecma_3/Object/class-005.js ecma_3/Object/regress-361274.js ecma_3/Object/regress-385393-07.js ecma_3/Object/regress-72773.js ecma_3/Object/regress-79129-001.js ecma_3/Operators/11.13.1-001.js ecma_3/Operators/11.13.1-002.js ecma_3/Operators/11.4.1-001.js ecma_3/RegExp/15.10.2-1.js ecma_3/RegExp/15.10.2.12.js ecma_3/RegExp/15.10.3.1-1.js ecma_3/RegExp/15.10.3.1-2.js ecma_3/RegExp/15.10.4.1-1.js ecma_3/RegExp/15.10.4.1-2.js ecma_3/RegExp/15.10.4.1-3.js ecma_3/RegExp/15.10.4.1-4.js ecma_3/RegExp/15.10.4.1-5-n.js ecma_3/RegExp/15.10.6.2-1.js ecma_3/RegExp/15.10.6.2-2.js ecma_3/RegExp/octal-001.js ecma_3/RegExp/octal-002.js ecma_3/RegExp/perlstress-001.js ecma_3/RegExp/perlstress-002.js ecma_3/RegExp/regress-100199.js ecma_3/RegExp/regress-105972.js ecma_3/RegExp/regress-119909.js ecma_3/RegExp/regress-122076.js ecma_3/RegExp/regress-123437.js ecma_3/RegExp/regress-165353.js ecma_3/RegExp/regress-169497.js ecma_3/RegExp/regress-169534.js ecma_3/RegExp/regress-187133.js ecma_3/RegExp/regress-191479.js ecma_3/RegExp/regress-202564.js ecma_3/RegExp/regress-209067.js ecma_3/RegExp/regress-209919.js ecma_3/RegExp/regress-216591.js ecma_3/RegExp/regress-220367-001.js ecma_3/RegExp/regress-223273.js ecma_3/RegExp/regress-223535.js ecma_3/RegExp/regress-224676.js ecma_3/RegExp/regress-225289.js ecma_3/RegExp/regress-225343.js ecma_3/RegExp/regress-24712.js ecma_3/RegExp/regress-28686.js ecma_3/RegExp/regress-309840.js ecma_3/RegExp/regress-312351.js ecma_3/RegExp/regress-31316.js ecma_3/RegExp/regress-346090.js ecma_3/RegExp/regress-375715-02.js ecma_3/RegExp/regress-375715-03.js ecma_3/RegExp/regress-57572.js ecma_3/RegExp/regress-57631.js ecma_3/RegExp/regress-67773.js ecma_3/RegExp/regress-76683.js ecma_3/RegExp/regress-78156.js ecma_3/RegExp/regress-85721.js ecma_3/RegExp/regress-87231.js ecma_3/RegExp/regress-98306.js ecma_3/Statements/12.6.3.js ecma_3/Statements/regress-131348.js ecma_3/Statements/regress-157509.js ecma_3/Statements/regress-194364.js ecma_3/Statements/regress-226517.js ecma_3/Statements/regress-302439.js ecma_3/Statements/regress-324650.js ecma_3/Statements/regress-74474-001.js ecma_3/Statements/regress-74474-002.js ecma_3/Statements/regress-74474-003.js ecma_3/Statements/regress-83532-001.js ecma_3/Statements/regress-83532-002.js ecma_3/Statements/switch-001.js ecma_3/String/regress-104375.js ecma_3/String/regress-189898.js ecma_3/String/regress-313567.js ecma_3/String/regress-83293.js ecma_3/Unicode/uc-001-n.js ecma_3/Unicode/uc-001.js ecma_3/Unicode/uc-002-n.js ecma_3/Unicode/uc-002.js ecma_3/Unicode/uc-003.js ecma_3/Unicode/uc-004.js ecma_3/Unicode/uc-005.js ecma_3/extensions/regress-103087.js ecma_3/extensions/regress-188206-01.js ecma_3/extensions/regress-188206-02.js ecma_3/extensions/regress-220367-002.js ecma_3/extensions/regress-228087.js ecma_3/extensions/regress-320854.js ecma_3/extensions/regress-327170.js ecma_3/extensions/regress-385393-03.js js-test-driver-begin.js js-test-driver-end.js js1_1/jsref.js js1_2/Array/array_split_1.js js1_2/Array/general1.js js1_2/Array/general2.js js1_2/Array/slice.js js1_2/Array/splice1.js js1_2/Array/splice2.js js1_2/Array/tostring_1.js js1_2/Array/tostring_2.js js1_2/Objects/toString-001.js js1_2/String/charCodeAt.js js1_2/String/concat.js js1_2/String/match.js js1_2/String/slice.js js1_2/function/Number.js js1_2/function/String.js js1_2/function/definition-1.js js1_2/function/length.js js1_2/function/nesting-1.js js1_2/function/nesting.js js1_2/function/regexparg-2-n.js js1_2/jsref.js js1_2/operator/strictEquality.js js1_2/regexp/RegExp_dollar_number.js js1_2/regexp/RegExp_input.js js1_2/regexp/RegExp_input_as_array.js js1_2/regexp/RegExp_lastIndex.js js1_2/regexp/RegExp_lastMatch.js js1_2/regexp/RegExp_lastMatch_as_array.js js1_2/regexp/RegExp_lastParen.js js1_2/regexp/RegExp_lastParen_as_array.js js1_2/regexp/RegExp_leftContext.js js1_2/regexp/RegExp_leftContext_as_array.js js1_2/regexp/RegExp_multiline.js js1_2/regexp/RegExp_multiline_as_array.js js1_2/regexp/RegExp_object.js js1_2/regexp/RegExp_rightContext.js js1_2/regexp/RegExp_rightContext_as_array.js js1_2/regexp/alphanumeric.js js1_2/regexp/asterisk.js js1_2/regexp/backslash.js js1_2/regexp/backspace.js js1_2/regexp/beginLine.js js1_2/regexp/character_class.js js1_2/regexp/compile.js js1_2/regexp/control_characters.js js1_2/regexp/digit.js js1_2/regexp/dot.js js1_2/regexp/endLine.js js1_2/regexp/everything.js js1_2/regexp/exec.js js1_2/regexp/flags.js js1_2/regexp/global.js js1_2/regexp/hexadecimal.js js1_2/regexp/ignoreCase.js js1_2/regexp/interval.js js1_2/regexp/octal.js js1_2/regexp/parentheses.js js1_2/regexp/regress-6359.js js1_2/regexp/regress-9141.js js1_2/regexp/simple_form.js js1_2/regexp/source.js js1_2/regexp/special_characters.js js1_2/regexp/string_replace.js js1_2/regexp/string_search.js js1_2/regexp/string_split.js js1_2/regexp/test.js js1_2/regexp/toString.js js1_2/regexp/vertical_bar.js js1_2/regexp/whitespace.js js1_2/regexp/word_boundary.js js1_2/regress/regress-144834.js js1_2/regress/regress-7703.js js1_2/statements/break.js js1_2/statements/do_while.js js1_2/statements/switch.js js1_2/statements/switch2.js js1_2/version120/boolean-001.js js1_3/Boolean/boolean-001.js js1_3/Script/delete-001.js js1_3/Script/function-002.js js1_3/Script/new-001.js js1_3/Script/switch-001.js js1_3/extensions/proto_10.js js1_3/extensions/proto_2.js js1_3/extensions/proto_5.js js1_3/inherit/proto_1.js js1_3/inherit/proto_10.js js1_3/inherit/proto_11.js js1_3/inherit/proto_12.js js1_3/inherit/proto_3.js js1_3/inherit/proto_4.js js1_3/inherit/proto_6.js js1_3/inherit/proto_7.js js1_3/inherit/proto_8.js js1_3/inherit/proto_9.js js1_3/jsref.js js1_3/regress/delete-001.js js1_3/regress/function-002.js js1_3/regress/new-001.js js1_3/regress/switch-001.js js1_4/Eval/eval-001.js js1_4/Eval/eval-002.js js1_4/Eval/eval-003.js js1_4/Functions/function-001.js js1_4/Regress/date-001-n.js js1_4/Regress/function-001.js js1_4/Regress/function-002.js js1_4/Regress/function-003.js js1_4/Regress/function-004-n.js js1_4/Regress/regress-7224.js js1_4/Regress/toString-001-n.js js1_4/jsref.js js1_5/Array/11.1.4.js js1_5/Array/array-001.js js1_5/Array/regress-101964.js js1_5/Array/regress-107138.js js1_5/Array/regress-108440.js js1_5/Array/regress-154338.js js1_5/Array/regress-178722.js js1_5/Array/regress-255555.js js1_5/Array/regress-299644.js js1_5/Array/regress-300858.js js1_5/Array/regress-310351.js js1_5/Array/regress-311515.js js1_5/Array/regress-313153.js js1_5/Array/regress-315509-01.js js1_5/Array/regress-345961.js js1_5/Array/regress-348810.js js1_5/Array/regress-350256-01.js js1_5/Array/regress-350256-02.js js1_5/Array/regress-360681-01.js js1_5/Array/regress-360681-02.js js1_5/Array/regress-364104.js js1_5/Array/regress-94257.js js1_5/Date/regress-188211.js js1_5/Date/regress-301738-01.js js1_5/Date/regress-309925-01.js js1_5/Date/regress-346027.js js1_5/Exceptions/catchguard-002-n.js js1_5/Exceptions/catchguard-003-n.js js1_5/Exceptions/regress-123002.js js1_5/Exceptions/regress-232182.js js1_5/Exceptions/regress-273931.js js1_5/Exceptions/regress-347674.js js1_5/Exceptions/regress-350837.js js1_5/Expressions/regress-192288.js js1_5/Expressions/regress-96526-argsub.js js1_5/Expressions/regress-96526-noargsub.js js1_5/Function/10.1.6.js js1_5/Function/15.3.4.4.js js1_5/Function/regress-123371.js js1_5/Function/regress-178389.js js1_5/Function/regress-292215.js js1_5/Function/regress-344052.js js1_5/GetSet/regress-375976.js js1_5/LexicalConventions/lexical-001.js js1_5/LexicalConventions/regress-177314.js js1_5/Object/regress-137000.js js1_5/Object/regress-192105.js js1_5/Object/regress-338709.js js1_5/Object/regress-382503.js js1_5/Object/regress-382532.js js1_5/Object/regress-90596-003.js js1_5/Regress/regress-104077.js js1_5/Regress/regress-110286.js js1_5/Regress/regress-111557.js js1_5/Regress/regress-114491.js js1_5/Regress/regress-114493.js js1_5/Regress/regress-115436.js js1_5/Regress/regress-116228.js js1_5/Regress/regress-118849.js js1_5/Regress/regress-127243.js js1_5/Regress/regress-127557.js js1_5/Regress/regress-131510-001.js js1_5/Regress/regress-140852.js js1_5/Regress/regress-140974.js js1_5/Regress/regress-146596.js js1_5/Regress/regress-152646.js js1_5/Regress/regress-159334.js js1_5/Regress/regress-162392.js js1_5/Regress/regress-165201.js js1_5/Regress/regress-167658.js js1_5/Regress/regress-168347.js js1_5/Regress/regress-170193.js js1_5/Regress/regress-172699.js js1_5/Regress/regress-174709.js js1_5/Regress/regress-176125.js js1_5/Regress/regress-185165.js js1_5/Regress/regress-191633.js js1_5/Regress/regress-192414.js js1_5/Regress/regress-193418.js js1_5/Regress/regress-203402.js js1_5/Regress/regress-203841.js js1_5/Regress/regress-204210.js js1_5/Regress/regress-210682.js js1_5/Regress/regress-211590.js js1_5/Regress/regress-214761.js js1_5/Regress/regress-216320.js js1_5/Regress/regress-224956.js js1_5/Regress/regress-229006.js js1_5/Regress/regress-230216-1.js js1_5/Regress/regress-230216-2.js js1_5/Regress/regress-230216-3.js js1_5/Regress/regress-233483-2.js js1_5/Regress/regress-233483.js js1_5/Regress/regress-238881.js js1_5/Regress/regress-238945.js js1_5/Regress/regress-243174.js js1_5/Regress/regress-243389-n.js js1_5/Regress/regress-243869.js js1_5/Regress/regress-244470.js js1_5/Regress/regress-244619.js js1_5/Regress/regress-245113.js js1_5/Regress/regress-245308.js js1_5/Regress/regress-246911.js js1_5/Regress/regress-246964.js js1_5/Regress/regress-253150.js js1_5/Regress/regress-254296.js js1_5/Regress/regress-254974.js js1_5/Regress/regress-256501.js js1_5/Regress/regress-256617.js js1_5/Regress/regress-256798.js js1_5/Regress/regress-260541.js js1_5/Regress/regress-261887.js js1_5/Regress/regress-274888.js js1_5/Regress/regress-275378.js js1_5/Regress/regress-276103.js js1_5/Regress/regress-278873.js js1_5/Regress/regress-280769-3.js js1_5/Regress/regress-280769-4.js js1_5/Regress/regress-281487.js js1_5/Regress/regress-281930.js js1_5/Regress/regress-283477.js js1_5/Regress/regress-286216.js js1_5/Regress/regress-288688.js js1_5/Regress/regress-289094.js js1_5/Regress/regress-290656.js js1_5/Regress/regress-294191.js js1_5/Regress/regress-294195-01.js js1_5/Regress/regress-294195-02.js js1_5/Regress/regress-295052.js js1_5/Regress/regress-295666.js js1_5/Regress/regress-306633.js js1_5/Regress/regress-306727.js js1_5/Regress/regress-306794.js js1_5/Regress/regress-308566.js js1_5/Regress/regress-310295.js js1_5/Regress/regress-310607.js js1_5/Regress/regress-310993.js js1_5/Regress/regress-311071.js js1_5/Regress/regress-311629.js js1_5/Regress/regress-312260.js js1_5/Regress/regress-31255.js js1_5/Regress/regress-314401.js js1_5/Regress/regress-315990.js js1_5/Regress/regress-317476.js js1_5/Regress/regress-317714-02.js js1_5/Regress/regress-319384.js js1_5/Regress/regress-320032.js js1_5/Regress/regress-321757.js js1_5/Regress/regress-321874.js js1_5/Regress/regress-322430.js js1_5/Regress/regress-326467.js js1_5/Regress/regress-328012.js js1_5/Regress/regress-328897.js js1_5/Regress/regress-329383.js js1_5/Regress/regress-330951.js js1_5/Regress/regress-334807-05.js js1_5/Regress/regress-334807-06.js js1_5/Regress/regress-338307.js js1_5/Regress/regress-340369.js js1_5/Regress/regress-341360.js js1_5/Regress/regress-343966.js js1_5/Regress/regress-344804.js js1_5/Regress/regress-344959.js js1_5/Regress/regress-346801.js js1_5/Regress/regress-349482-02.js js1_5/Regress/regress-349592.js js1_5/Regress/regress-350253.js js1_5/Regress/regress-350312.js js1_5/Regress/regress-350415.js js1_5/Regress/regress-351116.js js1_5/Regress/regress-351515.js js1_5/Regress/regress-352009.js js1_5/Regress/regress-352208.js js1_5/Regress/regress-360969-01.js js1_5/Regress/regress-360969-02.js js1_5/Regress/regress-360969-03.js js1_5/Regress/regress-360969-04.js js1_5/Regress/regress-366468.js js1_5/Regress/regress-367561-01.js js1_5/Regress/regress-379245.js js1_5/Regress/regress-39309.js js1_5/Regress/regress-398609.js js1_5/Regress/regress-406769.js js1_5/Regress/regress-407024.js js1_5/Regress/regress-407323.js js1_5/Regress/regress-407957.js js1_5/Regress/regress-57043.js js1_5/Regress/regress-68498-001.js js1_5/Regress/regress-68498-002.js js1_5/Regress/regress-68498-004.js js1_5/Regress/regress-69607.js js1_5/Regress/regress-71107.js js1_5/Regress/regress-76054.js js1_5/Regress/regress-80981.js js1_5/Regress/regress-82306.js js1_5/Regress/regress-90445.js js1_5/Regress/regress-96526-001.js js1_5/Regress/regress-96526-003.js js1_5/Scope/regress-154693.js js1_5/Scope/regress-181834.js js1_5/Scope/regress-184107.js js1_5/Scope/regress-185485.js js1_5/Scope/regress-191276.js js1_5/Scope/regress-192226.js js1_5/Scope/regress-202678-001.js js1_5/Scope/regress-202678-002.js js1_5/Scope/regress-208496-001.js js1_5/Scope/regress-208496-002.js js1_5/Scope/regress-220362.js js1_5/Scope/regress-77578-001.js js1_5/Scope/scope-002.js js1_5/Scope/scope-003.js js1_5/String/regress-107771.js js1_5/String/regress-112626.js js1_5/String/regress-179068.js js1_5/String/regress-314890.js js1_5/decompilation/regress-344120.js js1_5/decompilation/regress-349489.js js1_5/decompilation/regress-349663.js js1_5/decompilation/regress-350670.js js1_5/decompilation/regress-351625.js js1_5/decompilation/regress-351626.js js1_5/decompilation/regress-352022.js js1_5/decompilation/regress-352073.js js1_5/decompilation/regress-352360.js js1_5/decompilation/regress-352873-01.js js1_5/decompilation/regress-352873-02.js js1_5/decompilation/regress-353120.js js1_5/decompilation/regress-354878.js js1_5/decompilation/regress-354910.js js1_5/decompilation/regress-371692.js js1_5/decompilation/regress-373678.js js1_5/decompilation/regress-375639.js js1_5/decompilation/regress-383721.js js1_5/decompilation/regress-406555.js js1_5/extensions/catchguard-001.js js1_5/extensions/catchguard-002.js js1_5/extensions/catchguard-003.js js1_5/extensions/getset-004.js js1_5/extensions/getset-005.js js1_5/extensions/getset-006.js js1_5/extensions/no-such-method.js js1_5/extensions/regress-104077.js js1_5/extensions/regress-178722.js js1_5/extensions/regress-220584.js js1_5/extensions/regress-225831.js js1_5/extensions/regress-226078.js js1_5/extensions/regress-237461.js js1_5/extensions/regress-245795.js js1_5/extensions/regress-255245.js js1_5/extensions/regress-291213.js js1_5/extensions/regress-311161.js js1_5/extensions/regress-311583.js js1_5/extensions/regress-311792-01.js js1_5/extensions/regress-311792-02.js js1_5/extensions/regress-312278.js js1_5/extensions/regress-313500.js js1_5/extensions/regress-313630.js js1_5/extensions/regress-313763.js js1_5/extensions/regress-313803.js js1_5/extensions/regress-313938.js js1_5/extensions/regress-314874.js js1_5/extensions/regress-319683.js js1_5/extensions/regress-322957.js js1_5/extensions/regress-325269.js js1_5/extensions/regress-327608.js js1_5/extensions/regress-328556.js js1_5/extensions/regress-338804-01.js js1_5/extensions/regress-338804-03.js js1_5/extensions/regress-339685.js js1_5/extensions/regress-340199.js js1_5/extensions/regress-341956-02.js js1_5/extensions/regress-341956-03.js js1_5/extensions/regress-346494-01.js js1_5/extensions/regress-350312-01.js js1_5/extensions/regress-350312-02.js js1_5/extensions/regress-350312-03.js js1_5/extensions/regress-351102-01.js js1_5/extensions/regress-351102-02.js js1_5/extensions/regress-351102-06.js js1_5/extensions/regress-351973.js js1_5/extensions/regress-352261.js js1_5/extensions/regress-352281.js js1_5/extensions/regress-354297.js js1_5/extensions/regress-354541-01.js js1_5/extensions/regress-354541-03.js js1_5/extensions/regress-355982.js js1_5/extensions/regress-356402.js js1_5/extensions/regress-363988.js js1_5/extensions/regress-365527.js js1_5/extensions/regress-365692.js js1_5/extensions/regress-366288.js js1_5/extensions/regress-366292.js js1_5/extensions/regress-366396.js js1_5/extensions/regress-367118-01.js js1_5/extensions/regress-367118-02.js js1_5/extensions/regress-367120-01.js js1_5/extensions/regress-367120-02.js js1_5/extensions/regress-367121.js js1_5/extensions/regress-367501-01.js js1_5/extensions/regress-367501-02.js js1_5/extensions/regress-367501-03.js js1_5/extensions/regress-367589.js js1_5/extensions/regress-369404.js js1_5/extensions/regress-374589.js js1_5/extensions/regress-375183.js js1_5/extensions/regress-380889.js js1_5/extensions/regress-385134.js js1_5/extensions/regress-394967.js js1_5/extensions/regress-396326.js js1_5/extensions/regress-407501.js js1_5/extensions/regress-44009.js js1_5/extensions/regress-90596-001.js js1_5/extensions/regress-90596-002.js js1_5/extensions/regress-96284-001.js js1_5/extensions/regress-96284-002.js js1_5/extensions/scope-001.js js1_6/Array/filter.js js1_6/Array/regress-304828.js js1_6/Array/regress-305002.js js1_6/Array/regress-310425-01.js js1_6/Array/regress-310425-02.js js1_6/Array/regress-320887.js js1_6/Array/regress-352742-01.js js1_6/Array/regress-352742-02.js js1_6/Array/regress-415451.js js1_6/Array/regress-415540.js js1_6/Regress/regress-301574.js js1_6/Regress/regress-311157-01.js js1_6/Regress/regress-311157-02.js js1_6/Regress/regress-314887.js js1_6/Regress/regress-351795.js js1_6/Regress/regress-352271.js js1_6/Regress/regress-378492.js js1_6/decompilation/regress-352084.js js1_6/extensions/regress-385393-08.js js1_7/GC/regress-341675.js js1_7/block/order-of-operation.js js1_7/block/regress-341939.js js1_7/block/regress-344139.js js1_7/block/regress-344370.js js1_7/block/regress-345542.js js1_7/block/regress-348685.js js1_7/block/regress-349283.js js1_7/block/regress-349298.js js1_7/block/regress-349507.js js1_7/block/regress-349653.js js1_7/block/regress-349962.js js1_7/block/regress-350279.js js1_7/block/regress-350730.js js1_7/block/regress-350793-01.js js1_7/block/regress-351497.js js1_7/block/regress-351606.js js1_7/block/regress-352092.js js1_7/block/regress-352185.js js1_7/block/regress-352212.js js1_7/block/regress-352267.js js1_7/block/regress-352616.js js1_7/block/regress-352624.js js1_7/block/regress-352907.js js1_7/block/regress-357754.js js1_7/block/regress-376410.js js1_7/block/regress-396900.js js1_7/block/regress-411279.js js1_7/decompilation/regress-349633.js js1_7/decompilation/regress-350810.js js1_7/decompilation/regress-352015.js js1_7/decompilation/regress-352025.js js1_7/decompilation/regress-352269.js js1_7/decompilation/regress-352272.js js1_7/decompilation/regress-352283.js js1_7/decompilation/regress-352732.js js1_7/decompilation/regress-355635.js js1_7/decompilation/regress-355786.js js1_7/decompilation/regress-375794.js js1_7/decompilation/regress-380506.js js1_7/expressions/destructuring-scope.js js1_7/expressions/regress-346203.js js1_7/expressions/regress-346645-01.js js1_7/expressions/regress-346645-02.js js1_7/expressions/regress-346645-03.js js1_7/expressions/regress-349624.js js1_7/expressions/regress-349818.js js1_7/extensions/basic-Iterator.js js1_7/extensions/basic-for-in.js js1_7/extensions/destructuring-order.js js1_7/extensions/iterator-ctor.js js1_7/extensions/regress-346021.js js1_7/extensions/regress-346642-02.js js1_7/extensions/regress-346773.js js1_7/extensions/regress-349619.js js1_7/extensions/regress-350312.js js1_7/extensions/regress-351070-02.js js1_7/extensions/regress-352797-01.js js1_7/extensions/regress-352885-01.js js1_7/extensions/regress-352885-02.js js1_7/extensions/regress-353214-02.js js1_7/extensions/regress-354499-01.js js1_7/extensions/regress-354499-02.js js1_7/extensions/regress-354945-01.js js1_7/extensions/regress-355052-01.js js1_7/extensions/regress-355052-02.js js1_7/extensions/regress-355052-03.js js1_7/extensions/regress-355410.js js1_7/extensions/regress-355512.js js1_7/extensions/regress-355578.js js1_7/extensions/regress-355583.js js1_7/extensions/regress-363040-01.js js1_7/extensions/regress-363040-02.js js1_7/extensions/regress-366668-01.js js1_7/extensions/regress-366668-02.js js1_7/extensions/regress-387955-01.js js1_7/extensions/regress-392308.js js1_7/extensions/regress-396326.js js1_7/geniter/326466-01.js js1_7/geniter/builtin-Iterator-function.js js1_7/geniter/evens.js js1_7/geniter/fibonacci-matrix-generator.js js1_7/geniter/iterator-toString.js js1_7/geniter/message-value-passing.js js1_7/geniter/multiple-close.js js1_7/geniter/nested-yield.js js1_7/geniter/pi-generator.js js1_7/geniter/regress-345736.js js1_7/geniter/regress-345855.js js1_7/geniter/regress-345879-01.js js1_7/geniter/regress-347593.js js1_7/geniter/regress-349012-02.js js1_7/geniter/regress-349012-03.js js1_7/geniter/regress-349012-04.js js1_7/geniter/regress-349012-05.js js1_7/geniter/regress-349023-01.js js1_7/geniter/regress-349023-02.js js1_7/geniter/regress-349023-03.js js1_7/geniter/regress-349362.js js1_7/geniter/regress-349851.js js1_7/geniter/regress-350621.js js1_7/geniter/regress-350809.js js1_7/geniter/regress-351120.js js1_7/geniter/regress-352197.js js1_7/geniter/regress-352876.js js1_7/geniter/regress-355834.js js1_7/geniter/regress-359062.js js1_7/geniter/regress-366941.js js1_7/geniter/regress-382335.js js1_7/geniter/regress-390918.js js1_7/geniter/send-no-rhs.js js1_7/geniter/sequential-yields.js js1_7/geniter/throw-after-close.js js1_7/geniter/throw-forever.js js1_7/geniter/unreachable-yield.js js1_7/geniter/yield-undefined.js js1_7/iterable/regress-341499.js js1_7/iterable/regress-341510.js js1_7/iterable/regress-341815.js js1_7/iterable/regress-341821.js js1_7/iterable/regress-354750-01.js js1_7/iterable/regress-355025.js js1_7/iterable/regress-355075-01.js js1_7/iterable/regress-355090.js js1_7/iterable/regress-412467.js js1_7/lexical/regress-346642-04.js js1_7/regress/regress-352640-01.js js1_7/regress/regress-352640-02.js js1_7/regress/regress-352640-03.js js1_7/regress/regress-352640-04.js js1_7/regress/regress-352797-02.js js1_7/regress/regress-352870-03.js js1_7/regress/regress-353079.js js1_7/regress/regress-355023.js js1_7/regress/regress-355832-01.js js1_7/regress/regress-361566.js js1_7/regress/regress-369666-01.js js1_7/regress/regress-369666-02.js js1_7/regress/regress-372331.js js1_7/regress/regress-373827-01.js js1_7/regress/regress-373827-02.js js1_7/regress/regress-373828.js js1_7/regress/regress-379442.js js1_7/regress/regress-385393-05.js js1_7/regress/regress-407727-01.js js1_7/regress/regress-407727-02.js js1_7/regress/regress-407957.js js1_7/regress/regress-414553.js lc2/Arrays/array-001.js lc2/Arrays/array-002.js lc2/Arrays/array-003.js lc2/Arrays/array-004.js lc2/Arrays/array-005.js lc2/Arrays/array-006-n.js lc2/Arrays/array-007-n.js lc2/Classes/class-001.js lc2/Classes/class-002.js lc2/JSToJava/character-001.js lc2/JSToJava/double-001.js lc2/JSToJava/double-002.js lc2/JSToJava/float-001.js lc2/JSToJava/float-002.js lc2/JSToJava/integer-001.js lc2/JSToJava/integer-002.js lc2/JSToJava/long-001.js lc2/JSToJava/long-002.js lc2/JSToJava/long-003-n.js lc2/JSToJava/short-001.js lc2/JSToJava/short-002.js lc2/JSToJava/short-003-n.js lc2/JavaToJS/String-001.js lc2/JavaToJS/boolean-001.js lc2/JavaToJS/boolean-003.js lc2/JavaToJS/boolean-004.js lc2/JavaToJS/boolean-005.js lc2/JavaToJS/char-001.js lc2/JavaToJS/char-002.js lc2/JavaToJS/enum-001.js lc2/JavaToJS/enum-002.js lc2/JavaToJS/null-001.js lc2/JavaToJS/number-001.js lc2/JavaToJS/number-002.js lc2/Methods/method-001.js lc2/Methods/method-002.js lc2/Methods/method-003.js lc2/Methods/method-004-n.js lc2/Methods/method-005.js lc2/Methods/method-006-n.js lc2/Methods/println-001.js lc2/Objects/object-001.js lc2/Objects/object-002.js lc2/Objects/object-003.js lc2/Objects/object-004.js lc2/Objects/object-005.js lc2/Objects/object-006.js lc2/Packages/package-001.js lc2/Packages/package-002.js lc2/Packages/package-003.js lc2/Packages/package-005.js lc2/Packages/package-006.js lc2/Packages/package-007-n.js lc2/Packages/package-008-n.js lc2/misc/constructor.js lc3/ArrayMethods/byte-002.js lc3/ConvertBoolean/boolean-005-n.js lc3/ConvertBoolean/boolean-006-n.js lc3/ConvertBoolean/boolean-007-n.js lc3/ConvertBoolean/boolean-008-n.js lc3/ConvertBoolean/boolean-009-n.js lc3/ConvertBoolean/boolean-010-n.js lc3/ConvertBoolean/boolean-011-n.js lc3/ConvertBoolean/boolean-012-n.js lc3/ConvertBoolean/boolean-013-n.js lc3/ConvertNull/null-002.js lc3/ConvertNull/null-003-n.js lc3/ConvertNull/null-004-n.js lc3/ConvertNull/null-006-n.js lc3/ConvertString/string-004-n.js lc3/ConvertString/string-005-n.js lc3/ConvertString/string-007-n.js lc3/ConvertUndefined/undefined-001-n.js lc3/JSBoolean/boolean-002-n.js lc3/JSBoolean/boolean-003-n.js lc3/JSBoolean/boolean-004-n.js lc3/JSBoolean/boolean-005-n.js lc3/JSBoolean/boolean-006-n.js lc3/JSBoolean/boolean-007-n.js lc3/JSBoolean/boolean-008-n.js lc3/JSNull/ToBoolean-001-n.js lc3/JSNull/ToLong-001-n.js lc3/JSNull/ToNumber-001-n.js lc3/JSNumber/ToByte-002-n.js lc3/JSNumber/ToByte-003-n.js lc3/JSNumber/ToByte-005-n.js lc3/JSNumber/ToChar-002-n.js lc3/JSNumber/ToChar-003-n.js lc3/JSNumber/ToChar-005-n.js lc3/JSNumber/ToChar-006-n.js lc3/JSNumber/ToInt-002-n.js lc3/JSNumber/ToInt-003-n.js lc3/JSNumber/ToLong-002-n.js lc3/JSNumber/ToLong-003-n.js lc3/JSNumber/ToLong-004-n.js lc3/JSNumber/ToLong-005-n.js lc3/JSNumber/ToLong-006-n.js lc3/JSNumber/ToLong-007-n.js lc3/JSNumber/ToLong-008-n.js lc3/JSNumber/ToLong-009-n.js lc3/JSNumber/ToLong-010-n.js lc3/JSNumber/ToLong-011-n.js lc3/JSNumber/ToShort-003-n.js lc3/JSNumber/ToShort-005-n.js lc3/JSObject/ToDouble-002-n.js lc3/JSObject/ToDouble-003-n.js lc3/JSObject/ToFloat-002-n.js lc3/JSObject/ToFloat-003-n.js lc3/JSUndefined/undefined-002-n.js lc3/JSUndefined/undefined-003-n.js lc3/JSUndefined/undefined-004-n.js lc3/JSUndefined/undefined-005-n.js lc3/JSUndefined/undefined-006-n.js lc3/JSUndefined/undefined-008-n.js lc3/JSUndefined/undefined-009-n.js lc3/JSUndefined/undefined-010-n.js lc3/JavaArray/ToArray-002-n.js lc3/JavaArray/ToBoolean-001-n.js lc3/JavaObject/JavaObjectToBoolean-002-n.js lc3/JavaObject/JavaObjectToByte-002-n.js lc3/JavaObject/JavaObjectToByte-007-n.js lc3/JavaObject/JavaObjectToByte-008-n.js lc3/JavaObject/JavaObjectToChar-003-n.js lc3/JavaObject/JavaObjectToChar-005-n.js lc3/JavaObject/JavaObjectToChar-006-n.js lc3/JavaObject/JavaObjectToInt-002-n.js lc3/JavaObject/JavaObjectToInt-003-n.js lc3/JavaObject/JavaObjectToInt-004-n.js lc3/JavaObject/JavaObjectToLong-002-n.js lc3/JavaObject/JavaObjectToLong-003-n.js lc3/JavaObject/JavaObjectToLong-004-n.js lc3/JavaObject/JavaObjectToLong-006-n.js lc3/JavaObject/JavaObjectToShort-002-n.js lc3/JavaObject/JavaObjectToShort-003-n.js lc3/JavaObject/JavaObjectToShort-004-n.js lc3/StringMethods/string-001.js lc3/StringMethods/string-001.js htmlunit-core-js-2.8/rhino/testsrc/opt-1.tests0000644000175000017500000014763611321335670021263 0ustar cavedoncavedone4x/Expressions/11.1.1.js e4x/Expressions/11.1.2.js e4x/Expressions/11.1.3.js e4x/Expressions/11.1.4-06.js e4x/Expressions/11.1.4-07.js e4x/Expressions/11.1.5.js e4x/Expressions/11.2.1.js e4x/Expressions/11.2.2.js e4x/Expressions/11.2.3.js e4x/Expressions/11.2.4.js e4x/Expressions/11.3.1.js e4x/Expressions/11.3.2.js e4x/Expressions/11.4.1.js e4x/Expressions/11.5.1.js e4x/Expressions/11.6.3.js e4x/Expressions/regress-301545.js e4x/Expressions/regress-302531.js e4x/Expressions/regress-340024.js e4x/GC/regress-292455.js e4x/GC/regress-313952-01.js e4x/GC/regress-324117.js e4x/Namespace/13.2.1.js e4x/Namespace/13.2.2.js e4x/Namespace/13.2.5.js e4x/Namespace/regress-283972.js e4x/Namespace/regress-292863.js e4x/Namespace/regress-350442.js e4x/QName/13.3.1.js e4x/QName/13.3.2.js e4x/QName/13.3.5.js e4x/QName/regress-373595-01.js e4x/QName/regress-373595-02.js e4x/QName/regress-373595-03.js e4x/Regress/regress-263935.js e4x/Regress/regress-263936.js e4x/Regress/regress-264369.js e4x/Regress/regress-271545.js e4x/Regress/regress-277650.js e4x/Regress/regress-277664.js e4x/Regress/regress-277683.js e4x/Regress/regress-277935.js e4x/Regress/regress-283349.js e4x/Regress/regress-290056.js e4x/Regress/regress-301573.js e4x/Regress/regress-301596.js e4x/Regress/regress-301692.js e4x/Regress/regress-313799.js e4x/Regress/regress-325425.js e4x/Regress/regress-327691-01.js e4x/Regress/regress-327691-02.js e4x/Regress/regress-327697.js e4x/Regress/regress-328249.js e4x/Regress/regress-329257.js e4x/Regress/regress-331664.js e4x/Regress/regress-350206-1.js e4x/Regress/regress-350206.js e4x/Regress/regress-352103.js e4x/Regress/regress-354145-01.js e4x/Regress/regress-354145-02.js e4x/Regress/regress-354145-03.js e4x/Regress/regress-354145-04.js e4x/Regress/regress-354145-05.js e4x/Regress/regress-354145-07.js e4x/Regress/regress-355474-02.js e4x/Regress/regress-356238-01.js e4x/Regress/regress-369032.js e4x/Regress/regress-369536.js e4x/Regress/regress-372564.js e4x/Regress/regress-374106.js e4x/Regress/regress-374112.js e4x/Regress/regress-374116.js e4x/Regress/regress-374160.js e4x/Regress/regress-378492.js e4x/Regress/regress-407323.js e4x/Statements/12.1.js e4x/Statements/12.2.js e4x/Statements/12.3-01.js e4x/TypeConversion/10.1.2.js e4x/TypeConversion/10.3.1.js e4x/TypeConversion/10.3.js e4x/TypeConversion/10.4.1.js e4x/TypeConversion/10.4.js e4x/Types/9.1.1.1.js e4x/Types/9.1.1.2.js e4x/Types/9.1.1.3.js e4x/Types/9.1.1.6.js e4x/Types/9.2.1.1.js e4x/Types/9.2.1.2.js e4x/Types/9.2.1.8.js e4x/XML/13.4.1.js e4x/XML/13.4.2.js e4x/XML/13.4.3.10.js e4x/XML/13.4.4.12-1.js e4x/XML/13.4.4.12.js e4x/XML/13.4.4.13.js e4x/XML/13.4.4.14.js e4x/XML/13.4.4.15.js e4x/XML/13.4.4.16.js e4x/XML/13.4.4.18.js e4x/XML/13.4.4.19.js e4x/XML/13.4.4.2.js e4x/XML/13.4.4.20.js e4x/XML/13.4.4.21.js e4x/XML/13.4.4.23.js e4x/XML/13.4.4.24.js e4x/XML/13.4.4.25.js e4x/XML/13.4.4.27.js e4x/XML/13.4.4.3.js e4x/XML/13.4.4.30.js e4x/XML/13.4.4.31.js e4x/XML/13.4.4.32-01.js e4x/XML/13.4.4.32.js e4x/XML/13.4.4.33.js e4x/XML/13.4.4.34.js e4x/XML/13.4.4.35.js e4x/XML/13.4.4.36.js e4x/XML/13.4.4.37.js e4x/XML/13.4.4.38.js e4x/XML/13.4.4.39.js e4x/XML/13.4.4.4.js e4x/XML/13.4.4.40.js e4x/XML/13.4.4.5.js e4x/XML/13.4.4.7.js e4x/XML/13.4.4.8.js e4x/XML/regress-291930.js e4x/XML/regress-324688.js e4x/XML/regress-336921.js e4x/XMLList/13.5.1.js e4x/XMLList/13.5.2.js e4x/XMLList/13.5.4.10.js e4x/XMLList/13.5.4.11.js e4x/XMLList/13.5.4.12.js e4x/XMLList/13.5.4.13.js e4x/XMLList/13.5.4.14.js e4x/XMLList/13.5.4.15.js e4x/XMLList/13.5.4.16.js e4x/XMLList/13.5.4.17.js e4x/XMLList/13.5.4.18.js e4x/XMLList/13.5.4.19.js e4x/XMLList/13.5.4.2.js e4x/XMLList/13.5.4.20.js e4x/XMLList/13.5.4.21.js e4x/XMLList/13.5.4.22.js e4x/XMLList/13.5.4.3.js e4x/XMLList/13.5.4.4.js e4x/XMLList/13.5.4.5.js e4x/XMLList/13.5.4.6.js e4x/XMLList/13.5.4.7.js e4x/XMLList/13.5.4.8.js e4x/XMLList/13.5.4.9.js e4x/decompilation/regress-349814.js e4x/decompilation/regress-349815.js e4x/decompilation/regress-349822.js e4x/decompilation/regress-349956.js e4x/decompilation/regress-355474-01.js e4x/decompilation/regress-373678.js e4x/extensions/regress-305335.js e4x/extensions/regress-321547.js e4x/extensions/regress-327534.js e4x/extensions/regress-327897.js e4x/extensions/regress-354145-06.js e4x/extensions/regress-354151-01.js ecma/Array/15.4-1.js ecma/Array/15.4-2.js ecma/Array/15.4.1.1.js ecma/Array/15.4.1.2.js ecma/Array/15.4.1.3.js ecma/Array/15.4.1.js ecma/Array/15.4.2.1-1.js ecma/Array/15.4.2.1-2.js ecma/Array/15.4.2.1-3.js ecma/Array/15.4.2.2-1.js ecma/Array/15.4.2.2-2.js ecma/Array/15.4.2.3.js ecma/Array/15.4.3.2.js ecma/Array/15.4.4.1.js ecma/Array/15.4.4.2.js ecma/Array/15.4.4.3-1.js ecma/Array/15.4.4.4-1.js ecma/Array/15.4.4.4-2.js ecma/Array/15.4.4.5-1.js ecma/Array/15.4.4.5-2.js ecma/Array/15.4.4.js ecma/Array/15.4.5.1-2.js ecma/Array/15.4.5.2-1.js ecma/Array/15.4.5.2-2.js ecma/Boolean/15.6.2.js ecma/Boolean/15.6.3.1-1.js ecma/Boolean/15.6.3.1-2.js ecma/Boolean/15.6.3.1.js ecma/Boolean/15.6.4-1.js ecma/Boolean/15.6.4.1.js ecma/Boolean/15.6.4.2-2.js ecma/Boolean/15.6.4.2-3.js ecma/Boolean/15.6.4.2-4-n.js ecma/Boolean/15.6.4.3-1.js ecma/Boolean/15.6.4.3-2.js ecma/Boolean/15.6.4.3-3.js ecma/Boolean/15.6.4.3-4-n.js ecma/Boolean/15.6.4.3.js ecma/Boolean/15.6.4.js ecma/Date/15.9.1.1-1.js ecma/Date/15.9.1.1-2.js ecma/Date/15.9.1.13-1.js ecma/Date/15.9.2.1.js ecma/Date/15.9.2.2-1.js ecma/Date/15.9.2.2-2.js ecma/Date/15.9.2.2-3.js ecma/Date/15.9.2.2-5.js ecma/Date/15.9.2.2-6.js ecma/Date/15.9.3.1-2.js ecma/Date/15.9.3.1-3.js ecma/Date/15.9.3.1-4.js ecma/Date/15.9.3.1-5.js ecma/Date/15.9.3.2-2.js ecma/Date/15.9.3.2-3.js ecma/Date/15.9.3.2-4.js ecma/Date/15.9.3.2-5.js ecma/Date/15.9.3.8-1.js ecma/Date/15.9.3.8-2.js ecma/Date/15.9.3.8-3.js ecma/Date/15.9.3.8-4.js ecma/Date/15.9.3.8-5.js ecma/Date/15.9.4.2.js ecma/Date/15.9.4.3.js ecma/Date/15.9.5.1.js ecma/Date/15.9.5.10-1.js ecma/Date/15.9.5.10-10.js ecma/Date/15.9.5.10-11.js ecma/Date/15.9.5.10-12.js ecma/Date/15.9.5.10-13.js ecma/Date/15.9.5.10-4.js ecma/Date/15.9.5.10-5.js ecma/Date/15.9.5.10-6.js ecma/Date/15.9.5.10-7.js ecma/Date/15.9.5.10-8.js ecma/Date/15.9.5.10-9.js ecma/Date/15.9.5.11-1.js ecma/Date/15.9.5.11-3.js ecma/Date/15.9.5.11-4.js ecma/Date/15.9.5.11-5.js ecma/Date/15.9.5.11-6.js ecma/Date/15.9.5.11-7.js ecma/Date/15.9.5.12-1.js ecma/Date/15.9.5.12-3.js ecma/Date/15.9.5.12-4.js ecma/Date/15.9.5.12-5.js ecma/Date/15.9.5.12-6.js ecma/Date/15.9.5.12-7.js ecma/Date/15.9.5.12-8.js ecma/Date/15.9.5.13-1.js ecma/Date/15.9.5.13-2.js ecma/Date/15.9.5.13-3.js ecma/Date/15.9.5.13-4.js ecma/Date/15.9.5.13-5.js ecma/Date/15.9.5.13-6.js ecma/Date/15.9.5.13-7.js ecma/Date/15.9.5.13-8.js ecma/Date/15.9.5.14.js ecma/Date/15.9.5.15.js ecma/Date/15.9.5.16.js ecma/Date/15.9.5.17.js ecma/Date/15.9.5.19.js ecma/Date/15.9.5.2-2-n.js ecma/Date/15.9.5.2.js ecma/Date/15.9.5.20.js ecma/Date/15.9.5.21-1.js ecma/Date/15.9.5.21-2.js ecma/Date/15.9.5.21-3.js ecma/Date/15.9.5.21-4.js ecma/Date/15.9.5.21-5.js ecma/Date/15.9.5.21-6.js ecma/Date/15.9.5.21-7.js ecma/Date/15.9.5.21-8.js ecma/Date/15.9.5.22-2.js ecma/Date/15.9.5.22-3.js ecma/Date/15.9.5.22-4.js ecma/Date/15.9.5.22-5.js ecma/Date/15.9.5.22-6.js ecma/Date/15.9.5.22-7.js ecma/Date/15.9.5.22-8.js ecma/Date/15.9.5.23-1.js ecma/Date/15.9.5.23-10.js ecma/Date/15.9.5.23-11.js ecma/Date/15.9.5.23-12.js ecma/Date/15.9.5.23-13.js ecma/Date/15.9.5.23-14.js ecma/Date/15.9.5.23-15.js ecma/Date/15.9.5.23-16.js ecma/Date/15.9.5.23-17.js ecma/Date/15.9.5.23-18.js ecma/Date/15.9.5.23-2.js ecma/Date/15.9.5.23-3-n.js ecma/Date/15.9.5.23-4.js ecma/Date/15.9.5.23-5.js ecma/Date/15.9.5.23-6.js ecma/Date/15.9.5.23-7.js ecma/Date/15.9.5.23-8.js ecma/Date/15.9.5.23-9.js ecma/Date/15.9.5.24-1.js ecma/Date/15.9.5.24-2.js ecma/Date/15.9.5.24-3.js ecma/Date/15.9.5.24-4.js ecma/Date/15.9.5.24-5.js ecma/Date/15.9.5.24-6.js ecma/Date/15.9.5.24-7.js ecma/Date/15.9.5.24-8.js ecma/Date/15.9.5.25-1.js ecma/Date/15.9.5.26-1.js ecma/Date/15.9.5.27-1.js ecma/Date/15.9.5.28-1.js ecma/Date/15.9.5.29-1.js ecma/Date/15.9.5.3-2.js ecma/Date/15.9.5.30-1.js ecma/Date/15.9.5.31-1.js ecma/Date/15.9.5.32-1.js ecma/Date/15.9.5.33-1.js ecma/Date/15.9.5.34-1.js ecma/Date/15.9.5.35-1.js ecma/Date/15.9.5.36-1.js ecma/Date/15.9.5.36-2.js ecma/Date/15.9.5.36-4.js ecma/Date/15.9.5.36-5.js ecma/Date/15.9.5.36-6.js ecma/Date/15.9.5.36-7.js ecma/Date/15.9.5.37-2.js ecma/Date/15.9.5.37-3.js ecma/Date/15.9.5.37-4.js ecma/Date/15.9.5.37-5.js ecma/Date/15.9.5.4-1.js ecma/Date/15.9.5.4-2-n.js ecma/Date/15.9.5.6.js ecma/Date/15.9.5.7.js ecma/Date/15.9.5.8.js ecma/Date/15.9.5.9.js ecma/Date/15.9.5.js ecma/ExecutionContexts/10.1.3-1.js ecma/ExecutionContexts/10.1.3-2.js ecma/ExecutionContexts/10.1.3.js ecma/ExecutionContexts/10.1.4-1.js ecma/ExecutionContexts/10.1.4-10.js ecma/ExecutionContexts/10.1.4-3.js ecma/ExecutionContexts/10.1.4-4.js ecma/ExecutionContexts/10.1.4-5.js ecma/ExecutionContexts/10.1.4-6.js ecma/ExecutionContexts/10.1.4-7.js ecma/ExecutionContexts/10.1.4-8.js ecma/ExecutionContexts/10.1.5-1.js ecma/ExecutionContexts/10.1.5-2.js ecma/ExecutionContexts/10.1.5-3.js ecma/ExecutionContexts/10.1.5-4.js ecma/ExecutionContexts/10.1.8-2.js ecma/ExecutionContexts/10.1.8-3.js ecma/ExecutionContexts/10.2.1.js ecma/ExecutionContexts/10.2.2-1.js ecma/ExecutionContexts/10.2.2-2.js ecma/ExecutionContexts/10.2.3-1.js ecma/ExecutionContexts/10.2.3-2.js ecma/Expressions/11.1.1.js ecma/Expressions/11.10-1.js ecma/Expressions/11.10-2.js ecma/Expressions/11.10-3.js ecma/Expressions/11.12-1.js ecma/Expressions/11.12-2-n.js ecma/Expressions/11.12-3.js ecma/Expressions/11.12-4.js ecma/Expressions/11.13.1.js ecma/Expressions/11.13.2-1.js ecma/Expressions/11.13.2-2.js ecma/Expressions/11.13.2-3.js ecma/Expressions/11.13.2-4.js ecma/Expressions/11.13.2-5.js ecma/Expressions/11.14-1.js ecma/Expressions/11.2.1-1.js ecma/Expressions/11.2.1-2.js ecma/Expressions/11.2.1-3-n.js ecma/Expressions/11.2.1-4-n.js ecma/Expressions/11.2.1-5.js ecma/Expressions/11.2.2-1-n.js ecma/Expressions/11.2.2-1.js ecma/Expressions/11.2.2-10-n.js ecma/Expressions/11.2.2-11.js ecma/Expressions/11.2.2-2-n.js ecma/Expressions/11.2.2-3-n.js ecma/Expressions/11.2.2-4-n.js ecma/Expressions/11.2.2-5-n.js ecma/Expressions/11.2.2-6-n.js ecma/Expressions/11.2.2-7-n.js ecma/Expressions/11.2.2-8-n.js ecma/Expressions/11.2.2-9-n.js ecma/Expressions/11.2.3-1.js ecma/Expressions/11.2.3-2-n.js ecma/Expressions/11.2.3-3-n.js ecma/Expressions/11.2.3-4-n.js ecma/Expressions/11.2.3-5.js ecma/Expressions/11.3.1.js ecma/Expressions/11.3.2.js ecma/Expressions/11.4.2.js ecma/Expressions/11.4.3.js ecma/Expressions/11.4.4.js ecma/Expressions/11.4.5.js ecma/Expressions/11.4.6.js ecma/Expressions/11.4.8.js ecma/Expressions/11.4.9.js ecma/Expressions/11.5.1.js ecma/Expressions/11.5.2.js ecma/Expressions/11.5.3.js ecma/Expressions/11.6.1-1.js ecma/Expressions/11.6.1-2.js ecma/Expressions/11.6.1-3.js ecma/Expressions/11.6.2-1.js ecma/Expressions/11.6.3.js ecma/Expressions/11.7.1.js ecma/Expressions/11.7.2.js ecma/Expressions/11.8.1.js ecma/Expressions/11.8.2.js ecma/Expressions/11.8.3.js ecma/Expressions/11.9.2.js ecma/Expressions/11.9.3.js ecma/FunctionObjects/15.3.1.1-1.js ecma/FunctionObjects/15.3.1.1-2.js ecma/FunctionObjects/15.3.1.1-3.js ecma/FunctionObjects/15.3.2.1-1.js ecma/FunctionObjects/15.3.2.1-2.js ecma/FunctionObjects/15.3.2.1-3.js ecma/FunctionObjects/15.3.3.1-2.js ecma/FunctionObjects/15.3.3.1-3.js ecma/FunctionObjects/15.3.3.1-4.js ecma/FunctionObjects/15.3.3.2.js ecma/FunctionObjects/15.3.4-1.js ecma/FunctionObjects/15.3.4.1.js ecma/FunctionObjects/15.3.4.js ecma/FunctionObjects/15.3.5-1.js ecma/FunctionObjects/15.3.5-2.js ecma/FunctionObjects/15.3.5.1.js ecma/FunctionObjects/15.3.5.3.js ecma/GlobalObject/15.1-1-n.js ecma/GlobalObject/15.1-2-n.js ecma/GlobalObject/15.1.1.1.js ecma/GlobalObject/15.1.1.2.js ecma/GlobalObject/15.1.2.1-2.js ecma/GlobalObject/15.1.2.2-2.js ecma/GlobalObject/15.1.2.3-2.js ecma/GlobalObject/15.1.2.5-2.js ecma/GlobalObject/15.1.2.5-3.js ecma/LexicalConventions/7.1-1.js ecma/LexicalConventions/7.1-2.js ecma/LexicalConventions/7.1-3.js ecma/LexicalConventions/7.2-1.js ecma/LexicalConventions/7.2-2-n.js ecma/LexicalConventions/7.2-3-n.js ecma/LexicalConventions/7.2-4-n.js ecma/LexicalConventions/7.2-5-n.js ecma/LexicalConventions/7.2-6.js ecma/LexicalConventions/7.3-1.js ecma/LexicalConventions/7.3-10.js ecma/LexicalConventions/7.3-11.js ecma/LexicalConventions/7.3-12.js ecma/LexicalConventions/7.3-13-n.js ecma/LexicalConventions/7.3-2.js ecma/LexicalConventions/7.3-3.js ecma/LexicalConventions/7.3-4.js ecma/LexicalConventions/7.3-5.js ecma/LexicalConventions/7.3-6.js ecma/LexicalConventions/7.3-8.js ecma/LexicalConventions/7.3-9.js ecma/LexicalConventions/7.4.1-1-n.js ecma/LexicalConventions/7.4.1-2-n.js ecma/LexicalConventions/7.4.1-3-n.js ecma/LexicalConventions/7.4.2-1-n.js ecma/LexicalConventions/7.4.2-10-n.js ecma/LexicalConventions/7.4.2-11-n.js ecma/LexicalConventions/7.4.2-12-n.js ecma/LexicalConventions/7.4.2-13-n.js ecma/LexicalConventions/7.4.2-14-n.js ecma/LexicalConventions/7.4.2-15-n.js ecma/LexicalConventions/7.4.2-16-n.js ecma/LexicalConventions/7.4.2-2-n.js ecma/LexicalConventions/7.4.2-3-n.js ecma/LexicalConventions/7.4.2-4-n.js ecma/LexicalConventions/7.4.2-5-n.js ecma/LexicalConventions/7.4.2-6-n.js ecma/LexicalConventions/7.4.2-7-n.js ecma/LexicalConventions/7.4.2-8-n.js ecma/LexicalConventions/7.4.3-1-n.js ecma/LexicalConventions/7.4.3-10-n.js ecma/LexicalConventions/7.4.3-11-n.js ecma/LexicalConventions/7.4.3-13-n.js ecma/LexicalConventions/7.4.3-15-n.js ecma/LexicalConventions/7.4.3-16-n.js ecma/LexicalConventions/7.4.3-2-n.js ecma/LexicalConventions/7.4.3-3-n.js ecma/LexicalConventions/7.4.3-4-n.js ecma/LexicalConventions/7.4.3-5-n.js ecma/LexicalConventions/7.4.3-6-n.js ecma/LexicalConventions/7.4.3-7-n.js ecma/LexicalConventions/7.4.3-8-n.js ecma/LexicalConventions/7.4.3-9-n.js ecma/LexicalConventions/7.5-1.js ecma/LexicalConventions/7.5-10-n.js ecma/LexicalConventions/7.5-2-n.js ecma/LexicalConventions/7.5-3-n.js ecma/LexicalConventions/7.5-4-n.js ecma/LexicalConventions/7.5-5-n.js ecma/LexicalConventions/7.5-6.js ecma/LexicalConventions/7.5-7.js ecma/LexicalConventions/7.5-8-n.js ecma/LexicalConventions/7.5-9-n.js ecma/LexicalConventions/7.6.js ecma/LexicalConventions/7.7.1.js ecma/LexicalConventions/7.7.2.js ecma/LexicalConventions/7.7.3-1.js ecma/LexicalConventions/7.7.3-2.js ecma/LexicalConventions/7.7.3.js ecma/LexicalConventions/7.7.4.js ecma/LexicalConventions/7.8.2-n.js ecma/Math/15.8-2-n.js ecma/Math/15.8-3-n.js ecma/Math/15.8.1.1-1.js ecma/Math/15.8.1.1-2.js ecma/Math/15.8.1.2-1.js ecma/Math/15.8.1.3-1.js ecma/Math/15.8.1.3-2.js ecma/Math/15.8.1.4-1.js ecma/Math/15.8.1.4-2.js ecma/Math/15.8.1.5-1.js ecma/Math/15.8.1.5-2.js ecma/Math/15.8.1.6-1.js ecma/Math/15.8.1.6-2.js ecma/Math/15.8.1.7-1.js ecma/Math/15.8.1.7-2.js ecma/Math/15.8.1.8-1.js ecma/Math/15.8.1.8-2.js ecma/Math/15.8.1.8-3.js ecma/Math/15.8.2.1.js ecma/Math/15.8.2.10.js ecma/Math/15.8.2.12.js ecma/Math/15.8.2.13.js ecma/Math/15.8.2.14.js ecma/Math/15.8.2.15.js ecma/Math/15.8.2.16.js ecma/Math/15.8.2.17.js ecma/Math/15.8.2.18.js ecma/Math/15.8.2.2.js ecma/Math/15.8.2.3.js ecma/Math/15.8.2.4.js ecma/Math/15.8.2.5.js ecma/Math/15.8.2.6.js ecma/Math/15.8.2.7.js ecma/Math/15.8.2.8.js ecma/Math/15.8.2.9.js ecma/Number/15.7.2.js ecma/Number/15.7.3.1-1.js ecma/Number/15.7.3.1-2.js ecma/Number/15.7.3.1-3.js ecma/Number/15.7.3.2-1.js ecma/Number/15.7.3.2-2.js ecma/Number/15.7.3.2-3.js ecma/Number/15.7.3.3-1.js ecma/Number/15.7.3.3-2.js ecma/Number/15.7.3.3-3.js ecma/Number/15.7.3.4-1.js ecma/Number/15.7.3.4-2.js ecma/Number/15.7.3.4-3.js ecma/Number/15.7.3.4-4.js ecma/Number/15.7.3.5-1.js ecma/Number/15.7.3.5-2.js ecma/Number/15.7.3.5-3.js ecma/Number/15.7.3.5-4.js ecma/Number/15.7.3.6-1.js ecma/Number/15.7.3.6-4.js ecma/Number/15.7.3.js ecma/Number/15.7.4-1.js ecma/Number/15.7.4.1.js ecma/Number/15.7.4.2-1.js ecma/Number/15.7.4.2-2-n.js ecma/Number/15.7.4.2-3-n.js ecma/Number/15.7.4.2-4.js ecma/Number/15.7.4.3-1.js ecma/Number/15.7.4.3-2.js ecma/ObjectObjects/15.2.1.2.js ecma/ObjectObjects/15.2.2.1.js ecma/ObjectObjects/15.2.2.2.js ecma/ObjectObjects/15.2.3.1-1.js ecma/ObjectObjects/15.2.3.1-2.js ecma/ObjectObjects/15.2.3.1-3.js ecma/ObjectObjects/15.2.3.1-4.js ecma/ObjectObjects/15.2.3.js ecma/ObjectObjects/15.2.4.1.js ecma/ObjectObjects/15.2.4.2.js ecma/ObjectObjects/15.2.4.3.js ecma/SourceText/6-1.js ecma/SourceText/6-2.js ecma/Statements/12.10-1.js ecma/Statements/12.10.js ecma/Statements/12.5-1.js ecma/Statements/12.5-2.js ecma/Statements/12.6.2-1.js ecma/Statements/12.6.2-2.js ecma/Statements/12.6.2-4.js ecma/Statements/12.6.2-5.js ecma/Statements/12.6.2-6.js ecma/Statements/12.6.2-7.js ecma/Statements/12.6.2-8.js ecma/Statements/12.6.2-9-n.js ecma/Statements/12.6.3-1.js ecma/Statements/12.6.3-10.js ecma/Statements/12.6.3-11.js ecma/Statements/12.6.3-12.js ecma/Statements/12.6.3-19.js ecma/Statements/12.6.3-2.js ecma/Statements/12.6.3-3.js ecma/Statements/12.6.3-4.js ecma/Statements/12.6.3-5-n.js ecma/Statements/12.6.3-6-n.js ecma/Statements/12.6.3-7-n.js ecma/Statements/12.6.3-9-n.js ecma/Statements/12.7-1-n.js ecma/Statements/12.8-1-n.js ecma/Statements/12.9-1-n.js ecma/String/15.5.1.js ecma/String/15.5.2.js ecma/String/15.5.3.1-1.js ecma/String/15.5.3.1-2.js ecma/String/15.5.3.1-3.js ecma/String/15.5.3.1-4.js ecma/String/15.5.3.2-1.js ecma/String/15.5.3.2-2.js ecma/String/15.5.3.2-3.js ecma/String/15.5.3.js ecma/String/15.5.4.1.js ecma/String/15.5.4.10-1.js ecma/String/15.5.4.11-1.js ecma/String/15.5.4.11-3.js ecma/String/15.5.4.11-4.js ecma/String/15.5.4.11-6.js ecma/String/15.5.4.12-2.js ecma/String/15.5.4.12-3.js ecma/String/15.5.4.2-1.js ecma/String/15.5.4.2-2-n.js ecma/String/15.5.4.2-3.js ecma/String/15.5.4.2.js ecma/String/15.5.4.3-1.js ecma/String/15.5.4.3-2.js ecma/String/15.5.4.3-3-n.js ecma/String/15.5.4.4-1.js ecma/String/15.5.4.4-2.js ecma/String/15.5.4.4-3.js ecma/String/15.5.4.4-4.js ecma/String/15.5.4.5-1.js ecma/String/15.5.4.5-2.js ecma/String/15.5.4.5-3.js ecma/String/15.5.4.5-4.js ecma/String/15.5.4.5-5.js ecma/String/15.5.4.6-1.js ecma/String/15.5.4.7-2.js ecma/String/15.5.4.8-1.js ecma/String/15.5.4.8-3.js ecma/String/15.5.4.9-1.js ecma/String/15.5.4.js ecma/String/15.5.5.1.js ecma/TypeConversion/9.2.js ecma/TypeConversion/9.3-1.js ecma/TypeConversion/9.3.1-1.js ecma/TypeConversion/9.3.1-2.js ecma/TypeConversion/9.3.1-3.js ecma/TypeConversion/9.3.js ecma/TypeConversion/9.4-1.js ecma/TypeConversion/9.4-2.js ecma/TypeConversion/9.5-2.js ecma/TypeConversion/9.6.js ecma/TypeConversion/9.7.js ecma/TypeConversion/9.8.1.js ecma/TypeConversion/9.9-1.js ecma/Types/8.1.js ecma/Types/8.4.js ecma/Types/8.6.2.1-1.js ecma/extensions/10.1.4-9.js ecma/extensions/10.1.6.js ecma/extensions/10.1.8-1.js ecma/extensions/11.6.1-1.js ecma/extensions/11.6.1-2.js ecma/extensions/11.6.1-3.js ecma/extensions/11.6.2-1.js ecma/extensions/15-2.js ecma/extensions/15.2.1.1.js ecma/extensions/15.2.3-1.js ecma/extensions/15.2.4.js ecma/extensions/15.3.1.1-2.js ecma/extensions/15.3.2.1-1.js ecma/extensions/15.3.2.1-2.js ecma/extensions/15.4.3.js ecma/extensions/15.5.3.js ecma/extensions/15.5.4.2.js ecma/extensions/15.5.4.4-4.js ecma/extensions/15.5.4.5-6.js ecma/extensions/15.5.4.7-3.js ecma/extensions/15.6.3.1-5.js ecma/extensions/15.6.3.js ecma/extensions/15.6.4-2.js ecma/extensions/15.7.3.js ecma/extensions/15.7.4.js ecma/extensions/15.8-1.js ecma/extensions/15.9.5.js ecma/extensions/8.6.2.1-1.js ecma/extensions/9.9-1.js ecma/jsref.js ecma_2/Exceptions/boolean-001.js ecma_2/Exceptions/date-001.js ecma_2/Exceptions/date-002.js ecma_2/Exceptions/date-004.js ecma_2/Exceptions/exception-001.js ecma_2/Exceptions/exception-002.js ecma_2/Exceptions/exception-004.js ecma_2/Exceptions/exception-005.js ecma_2/Exceptions/exception-006.js ecma_2/Exceptions/exception-007.js ecma_2/Exceptions/exception-008.js ecma_2/Exceptions/exception-009.js ecma_2/Exceptions/exception-010-n.js ecma_2/Exceptions/exception-011-n.js ecma_2/Exceptions/expression-002.js ecma_2/Exceptions/expression-004.js ecma_2/Exceptions/expression-005.js ecma_2/Exceptions/expression-006.js ecma_2/Exceptions/expression-007.js ecma_2/Exceptions/expression-008.js ecma_2/Exceptions/expression-009.js ecma_2/Exceptions/expression-010.js ecma_2/Exceptions/expression-011.js ecma_2/Exceptions/expression-012.js ecma_2/Exceptions/expression-013.js ecma_2/Exceptions/expression-014.js ecma_2/Exceptions/expression-015.js ecma_2/Exceptions/expression-016.js ecma_2/Exceptions/expression-017.js ecma_2/Exceptions/global-001.js ecma_2/Exceptions/global-002.js ecma_2/Exceptions/lexical-001.js ecma_2/Exceptions/lexical-002.js ecma_2/Exceptions/lexical-003.js ecma_2/Exceptions/lexical-004.js ecma_2/Exceptions/lexical-005.js ecma_2/Exceptions/lexical-006.js ecma_2/Exceptions/lexical-007.js ecma_2/Exceptions/lexical-009.js ecma_2/Exceptions/lexical-010.js ecma_2/Exceptions/lexical-011.js ecma_2/Exceptions/lexical-012.js ecma_2/Exceptions/lexical-013.js ecma_2/Exceptions/lexical-014.js ecma_2/Exceptions/lexical-015.js ecma_2/Exceptions/lexical-016.js ecma_2/Exceptions/lexical-017.js ecma_2/Exceptions/lexical-018.js ecma_2/Exceptions/lexical-019.js ecma_2/Exceptions/lexical-020.js ecma_2/Exceptions/lexical-022.js ecma_2/Exceptions/lexical-023.js ecma_2/Exceptions/lexical-024.js ecma_2/Exceptions/lexical-025.js ecma_2/Exceptions/lexical-026.js ecma_2/Exceptions/lexical-027.js ecma_2/Exceptions/lexical-028.js ecma_2/Exceptions/lexical-029.js ecma_2/Exceptions/lexical-030.js ecma_2/Exceptions/lexical-031.js ecma_2/Exceptions/lexical-032.js ecma_2/Exceptions/lexical-033.js ecma_2/Exceptions/lexical-034.js ecma_2/Exceptions/lexical-035.js ecma_2/Exceptions/lexical-036.js ecma_2/Exceptions/lexical-037.js ecma_2/Exceptions/lexical-038.js ecma_2/Exceptions/lexical-039.js ecma_2/Exceptions/lexical-040.js ecma_2/Exceptions/lexical-041.js ecma_2/Exceptions/lexical-042.js ecma_2/Exceptions/lexical-047.js ecma_2/Exceptions/lexical-048.js ecma_2/Exceptions/lexical-049.js ecma_2/Exceptions/lexical-050.js ecma_2/Exceptions/lexical-051.js ecma_2/Exceptions/lexical-053.js ecma_2/Exceptions/lexical-054.js ecma_2/Exceptions/number-002.js ecma_2/Exceptions/number-003.js ecma_2/Exceptions/statement-001.js ecma_2/Exceptions/statement-002.js ecma_2/Exceptions/statement-003.js ecma_2/Exceptions/statement-004.js ecma_2/Exceptions/statement-005.js ecma_2/Exceptions/statement-006.js ecma_2/Exceptions/statement-007.js ecma_2/Exceptions/statement-008.js ecma_2/Exceptions/string-001.js ecma_2/Exceptions/string-002.js ecma_2/Expressions/StrictEquality-001.js ecma_2/FunctionObjects/apply-001-n.js ecma_2/FunctionObjects/call-1.js ecma_2/LexicalConventions/keywords-001.js ecma_2/LexicalConventions/regexp-literals-001.js ecma_2/LexicalConventions/regexp-literals-002.js ecma_2/RegExp/constructor-001.js ecma_2/RegExp/exec-002.js ecma_2/RegExp/function-001.js ecma_2/RegExp/hex-001.js ecma_2/RegExp/multiline-001.js ecma_2/RegExp/octal-001.js ecma_2/RegExp/octal-002.js ecma_2/RegExp/octal-003.js ecma_2/RegExp/properties-001.js ecma_2/RegExp/properties-002.js ecma_2/RegExp/regress-001.js ecma_2/RegExp/unicode-001.js ecma_2/Statements/dowhile-001.js ecma_2/Statements/dowhile-002.js ecma_2/Statements/dowhile-003.js ecma_2/Statements/dowhile-004.js ecma_2/Statements/dowhile-005.js ecma_2/Statements/dowhile-006.js ecma_2/Statements/dowhile-007.js ecma_2/Statements/forin-001.js ecma_2/Statements/forin-002.js ecma_2/Statements/if-001.js ecma_2/Statements/label-001.js ecma_2/Statements/label-002.js ecma_2/Statements/switch-002.js ecma_2/Statements/switch-003.js ecma_2/Statements/switch-004.js ecma_2/Statements/try-001.js ecma_2/Statements/try-003.js ecma_2/Statements/try-004.js ecma_2/Statements/try-005.js ecma_2/Statements/try-007.js ecma_2/Statements/try-008.js ecma_2/Statements/try-009.js ecma_2/Statements/try-012.js ecma_2/Statements/while-001.js ecma_2/Statements/while-002.js ecma_2/Statements/while-003.js ecma_2/Statements/while-004.js ecma_2/String/match-001.js ecma_2/String/match-002.js ecma_2/String/match-003.js ecma_2/String/match-004.js ecma_2/String/split-001.js ecma_2/String/split-002.js ecma_2/String/split-003.js ecma_2/extensions/constructor-001.js ecma_2/extensions/function-001.js ecma_2/extensions/instanceof-001.js ecma_2/extensions/instanceof-002.js ecma_2/extensions/instanceof-006.js ecma_2/instanceof/instanceof-001.js ecma_2/instanceof/instanceof-002.js ecma_2/instanceof/regress-7635.js ecma_2/jsref.js ecma_3/Array/15.4.4.11-01.js ecma_3/Array/15.4.4.3-1.js ecma_3/Array/15.4.4.4-001.js ecma_3/Array/regress-101488.js ecma_3/Array/regress-130451.js ecma_3/Array/regress-322135-01.js ecma_3/Date/15.9.4.3.js ecma_3/Date/15.9.5.3.js ecma_3/Date/15.9.5.4.js ecma_3/Date/15.9.5.6.js ecma_3/Date/15.9.5.7.js ecma_3/Exceptions/15.11.1.1.js ecma_3/Exceptions/15.11.4.4-1.js ecma_3/Exceptions/15.11.7.6-001.js ecma_3/Exceptions/15.11.7.6-002.js ecma_3/Exceptions/15.11.7.6-003.js ecma_3/Exceptions/binding-001.js ecma_3/Exceptions/regress-95101.js ecma_3/ExecutionContexts/10.1.3-1.js ecma_3/ExecutionContexts/10.1.3-2.js ecma_3/ExecutionContexts/10.1.3.js ecma_3/ExecutionContexts/10.1.4-1.js ecma_3/ExecutionContexts/10.6.1-01.js ecma_3/ExecutionContexts/regress-23346.js ecma_3/Expressions/11.10-01.js ecma_3/Expressions/11.10-03.js ecma_3/Expressions/11.6.1-1.js ecma_3/Expressions/11.7.1-01.js ecma_3/Expressions/11.7.2-01.js ecma_3/Expressions/11.7.3-01.js ecma_3/Expressions/11.9.6-1.js ecma_3/FunExpr/fe-001-n.js ecma_3/FunExpr/fe-001.js ecma_3/FunExpr/fe-002.js ecma_3/Function/15.3.4.3-1.js ecma_3/Function/15.3.4.4-1.js ecma_3/Function/arguments-002.js ecma_3/Function/call-001.js ecma_3/Function/regress-131964.js ecma_3/Function/regress-137181.js ecma_3/Function/regress-193555.js ecma_3/Function/regress-313570.js ecma_3/Function/regress-49286.js ecma_3/Function/regress-58274.js ecma_3/Function/regress-85880.js ecma_3/Function/regress-94506.js ecma_3/Function/regress-97921.js ecma_3/Function/scope-001.js ecma_3/Function/scope-002.js ecma_3/Number/15.7.4.5-1.js ecma_3/Number/15.7.4.6-1.js ecma_3/Number/15.7.4.7-1.js ecma_3/Number/15.7.4.7-2.js ecma_3/NumberFormatting/tostring-001.js ecma_3/Object/8.6.2.6-001.js ecma_3/Object/class-001.js ecma_3/Object/class-002.js ecma_3/Object/class-003.js ecma_3/Object/class-004.js ecma_3/Object/class-005.js ecma_3/Object/regress-361274.js ecma_3/Object/regress-385393-07.js ecma_3/Object/regress-72773.js ecma_3/Object/regress-79129-001.js ecma_3/Operators/11.13.1-001.js ecma_3/Operators/11.13.1-002.js ecma_3/Operators/11.4.1-001.js ecma_3/RegExp/15.10.2-1.js ecma_3/RegExp/15.10.2.12.js ecma_3/RegExp/15.10.3.1-1.js ecma_3/RegExp/15.10.3.1-2.js ecma_3/RegExp/15.10.4.1-1.js ecma_3/RegExp/15.10.4.1-2.js ecma_3/RegExp/15.10.4.1-3.js ecma_3/RegExp/15.10.4.1-4.js ecma_3/RegExp/15.10.4.1-5-n.js ecma_3/RegExp/15.10.6.2-1.js ecma_3/RegExp/15.10.6.2-2.js ecma_3/RegExp/octal-001.js ecma_3/RegExp/octal-002.js ecma_3/RegExp/perlstress-001.js ecma_3/RegExp/perlstress-002.js ecma_3/RegExp/regress-100199.js ecma_3/RegExp/regress-105972.js ecma_3/RegExp/regress-119909.js ecma_3/RegExp/regress-122076.js ecma_3/RegExp/regress-123437.js ecma_3/RegExp/regress-165353.js ecma_3/RegExp/regress-169497.js ecma_3/RegExp/regress-169534.js ecma_3/RegExp/regress-187133.js ecma_3/RegExp/regress-191479.js ecma_3/RegExp/regress-202564.js ecma_3/RegExp/regress-209067.js ecma_3/RegExp/regress-209919.js ecma_3/RegExp/regress-216591.js ecma_3/RegExp/regress-220367-001.js ecma_3/RegExp/regress-223273.js ecma_3/RegExp/regress-223535.js ecma_3/RegExp/regress-224676.js ecma_3/RegExp/regress-225289.js ecma_3/RegExp/regress-225343.js ecma_3/RegExp/regress-24712.js ecma_3/RegExp/regress-28686.js ecma_3/RegExp/regress-309840.js ecma_3/RegExp/regress-312351.js ecma_3/RegExp/regress-31316.js ecma_3/RegExp/regress-346090.js ecma_3/RegExp/regress-375715-02.js ecma_3/RegExp/regress-375715-03.js ecma_3/RegExp/regress-57572.js ecma_3/RegExp/regress-57631.js ecma_3/RegExp/regress-67773.js ecma_3/RegExp/regress-76683.js ecma_3/RegExp/regress-78156.js ecma_3/RegExp/regress-85721.js ecma_3/RegExp/regress-87231.js ecma_3/RegExp/regress-98306.js ecma_3/Statements/12.6.3.js ecma_3/Statements/regress-131348.js ecma_3/Statements/regress-157509.js ecma_3/Statements/regress-194364.js ecma_3/Statements/regress-226517.js ecma_3/Statements/regress-302439.js ecma_3/Statements/regress-324650.js ecma_3/Statements/regress-74474-001.js ecma_3/Statements/regress-74474-002.js ecma_3/Statements/regress-74474-003.js ecma_3/Statements/regress-83532-001.js ecma_3/Statements/regress-83532-002.js ecma_3/Statements/switch-001.js ecma_3/String/regress-104375.js ecma_3/String/regress-189898.js ecma_3/String/regress-313567.js ecma_3/String/regress-83293.js ecma_3/Unicode/uc-001-n.js ecma_3/Unicode/uc-001.js ecma_3/Unicode/uc-002-n.js ecma_3/Unicode/uc-002.js ecma_3/Unicode/uc-003.js ecma_3/Unicode/uc-004.js ecma_3/Unicode/uc-005.js ecma_3/extensions/regress-103087.js ecma_3/extensions/regress-188206-01.js ecma_3/extensions/regress-188206-02.js ecma_3/extensions/regress-220367-002.js ecma_3/extensions/regress-228087.js ecma_3/extensions/regress-320854.js ecma_3/extensions/regress-327170.js ecma_3/extensions/regress-385393-03.js js-test-driver-begin.js js-test-driver-end.js js1_1/jsref.js js1_2/Array/array_split_1.js js1_2/Array/general1.js js1_2/Array/general2.js js1_2/Array/slice.js js1_2/Array/splice1.js js1_2/Array/splice2.js js1_2/Array/tostring_1.js js1_2/Array/tostring_2.js js1_2/Objects/toString-001.js js1_2/String/charCodeAt.js js1_2/String/concat.js js1_2/String/match.js js1_2/String/slice.js js1_2/function/Number.js js1_2/function/String.js js1_2/function/definition-1.js js1_2/function/length.js js1_2/function/nesting-1.js js1_2/function/nesting.js js1_2/function/regexparg-2-n.js js1_2/jsref.js js1_2/operator/strictEquality.js js1_2/regexp/RegExp_dollar_number.js js1_2/regexp/RegExp_input.js js1_2/regexp/RegExp_input_as_array.js js1_2/regexp/RegExp_lastIndex.js js1_2/regexp/RegExp_lastMatch.js js1_2/regexp/RegExp_lastMatch_as_array.js js1_2/regexp/RegExp_lastParen.js js1_2/regexp/RegExp_lastParen_as_array.js js1_2/regexp/RegExp_leftContext.js js1_2/regexp/RegExp_leftContext_as_array.js js1_2/regexp/RegExp_multiline.js js1_2/regexp/RegExp_multiline_as_array.js js1_2/regexp/RegExp_object.js js1_2/regexp/RegExp_rightContext.js js1_2/regexp/RegExp_rightContext_as_array.js js1_2/regexp/alphanumeric.js js1_2/regexp/asterisk.js js1_2/regexp/backslash.js js1_2/regexp/backspace.js js1_2/regexp/beginLine.js js1_2/regexp/character_class.js js1_2/regexp/compile.js js1_2/regexp/control_characters.js js1_2/regexp/digit.js js1_2/regexp/dot.js js1_2/regexp/endLine.js js1_2/regexp/everything.js js1_2/regexp/exec.js js1_2/regexp/flags.js js1_2/regexp/global.js js1_2/regexp/hexadecimal.js js1_2/regexp/ignoreCase.js js1_2/regexp/interval.js js1_2/regexp/octal.js js1_2/regexp/parentheses.js js1_2/regexp/regress-6359.js js1_2/regexp/regress-9141.js js1_2/regexp/simple_form.js js1_2/regexp/source.js js1_2/regexp/special_characters.js js1_2/regexp/string_replace.js js1_2/regexp/string_search.js js1_2/regexp/string_split.js js1_2/regexp/test.js js1_2/regexp/toString.js js1_2/regexp/vertical_bar.js js1_2/regexp/whitespace.js js1_2/regexp/word_boundary.js js1_2/regress/regress-144834.js js1_2/regress/regress-7703.js js1_2/statements/break.js js1_2/statements/do_while.js js1_2/statements/switch.js js1_2/statements/switch2.js js1_2/version120/boolean-001.js js1_3/Boolean/boolean-001.js js1_3/Script/delete-001.js js1_3/Script/function-002.js js1_3/Script/new-001.js js1_3/Script/switch-001.js js1_3/extensions/proto_10.js js1_3/extensions/proto_2.js js1_3/extensions/proto_5.js js1_3/inherit/proto_1.js js1_3/inherit/proto_10.js js1_3/inherit/proto_11.js js1_3/inherit/proto_12.js js1_3/inherit/proto_3.js js1_3/inherit/proto_4.js js1_3/inherit/proto_6.js js1_3/inherit/proto_7.js js1_3/inherit/proto_8.js js1_3/inherit/proto_9.js js1_3/jsref.js js1_3/regress/delete-001.js js1_3/regress/function-002.js js1_3/regress/new-001.js js1_3/regress/switch-001.js js1_4/Eval/eval-001.js js1_4/Eval/eval-002.js js1_4/Eval/eval-003.js js1_4/Functions/function-001.js js1_4/Regress/date-001-n.js js1_4/Regress/function-001.js js1_4/Regress/function-002.js js1_4/Regress/function-003.js js1_4/Regress/function-004-n.js js1_4/Regress/regress-7224.js js1_4/Regress/toString-001-n.js js1_4/jsref.js js1_5/Array/11.1.4.js js1_5/Array/array-001.js js1_5/Array/regress-101964.js js1_5/Array/regress-107138.js js1_5/Array/regress-108440.js js1_5/Array/regress-154338.js js1_5/Array/regress-178722.js js1_5/Array/regress-255555.js js1_5/Array/regress-299644.js js1_5/Array/regress-300858.js js1_5/Array/regress-310351.js js1_5/Array/regress-311515.js js1_5/Array/regress-313153.js js1_5/Array/regress-315509-01.js js1_5/Array/regress-345961.js js1_5/Array/regress-348810.js js1_5/Array/regress-350256-01.js js1_5/Array/regress-350256-02.js js1_5/Array/regress-360681-01.js js1_5/Array/regress-360681-02.js js1_5/Array/regress-364104.js js1_5/Array/regress-94257.js js1_5/Date/regress-188211.js js1_5/Date/regress-301738-01.js js1_5/Date/regress-309925-01.js js1_5/Date/regress-346027.js js1_5/Exceptions/catchguard-002-n.js js1_5/Exceptions/catchguard-003-n.js js1_5/Exceptions/regress-123002.js js1_5/Exceptions/regress-232182.js js1_5/Exceptions/regress-257751.js js1_5/Exceptions/regress-273931.js js1_5/Exceptions/regress-347674.js js1_5/Exceptions/regress-350837.js js1_5/Expressions/regress-192288.js js1_5/Expressions/regress-96526-argsub.js js1_5/Expressions/regress-96526-noargsub.js js1_5/Function/10.1.6.js js1_5/Function/15.3.4.4.js js1_5/Function/regress-123371.js js1_5/Function/regress-178389.js js1_5/Function/regress-292215.js js1_5/Function/regress-344052.js js1_5/GetSet/regress-375976.js js1_5/LexicalConventions/lexical-001.js js1_5/LexicalConventions/regress-177314.js js1_5/Object/regress-137000.js js1_5/Object/regress-192105.js js1_5/Object/regress-338709.js js1_5/Object/regress-382503.js js1_5/Object/regress-382532.js js1_5/Object/regress-90596-003.js js1_5/Regress/regress-104077.js js1_5/Regress/regress-110286.js js1_5/Regress/regress-111557.js js1_5/Regress/regress-114491.js js1_5/Regress/regress-114493.js js1_5/Regress/regress-115436.js js1_5/Regress/regress-116228.js js1_5/Regress/regress-118849.js js1_5/Regress/regress-127243.js js1_5/Regress/regress-127557.js js1_5/Regress/regress-131510-001.js js1_5/Regress/regress-140852.js js1_5/Regress/regress-140974.js js1_5/Regress/regress-146596.js js1_5/Regress/regress-152646.js js1_5/Regress/regress-155081-2.js js1_5/Regress/regress-155081.js js1_5/Regress/regress-159334.js js1_5/Regress/regress-162392.js js1_5/Regress/regress-165201.js js1_5/Regress/regress-167328.js js1_5/Regress/regress-167658.js js1_5/Regress/regress-168347.js js1_5/Regress/regress-170193.js js1_5/Regress/regress-172699.js js1_5/Regress/regress-174709.js js1_5/Regress/regress-176125.js js1_5/Regress/regress-185165.js js1_5/Regress/regress-191633.js js1_5/Regress/regress-192414.js js1_5/Regress/regress-193418.js js1_5/Regress/regress-203402.js js1_5/Regress/regress-203841.js js1_5/Regress/regress-204210.js js1_5/Regress/regress-210682.js js1_5/Regress/regress-211590.js js1_5/Regress/regress-214761.js js1_5/Regress/regress-216320.js js1_5/Regress/regress-224956.js js1_5/Regress/regress-229006.js js1_5/Regress/regress-230216-1.js js1_5/Regress/regress-230216-2.js js1_5/Regress/regress-230216-3.js js1_5/Regress/regress-233483-2.js js1_5/Regress/regress-233483.js js1_5/Regress/regress-238881.js js1_5/Regress/regress-238945.js js1_5/Regress/regress-243174.js js1_5/Regress/regress-243389-n.js js1_5/Regress/regress-243869.js js1_5/Regress/regress-244470.js js1_5/Regress/regress-244619.js js1_5/Regress/regress-245113.js js1_5/Regress/regress-245308.js js1_5/Regress/regress-246911.js js1_5/Regress/regress-246964.js js1_5/Regress/regress-253150.js js1_5/Regress/regress-254296.js js1_5/Regress/regress-254974.js js1_5/Regress/regress-256501.js js1_5/Regress/regress-256617.js js1_5/Regress/regress-256798.js js1_5/Regress/regress-260541.js js1_5/Regress/regress-261887.js js1_5/Regress/regress-274888.js js1_5/Regress/regress-275378.js js1_5/Regress/regress-276103.js js1_5/Regress/regress-278873.js js1_5/Regress/regress-280769-3.js js1_5/Regress/regress-280769-4.js js1_5/Regress/regress-281487.js js1_5/Regress/regress-281930.js js1_5/Regress/regress-283477.js js1_5/Regress/regress-286216.js js1_5/Regress/regress-288688.js js1_5/Regress/regress-289094.js js1_5/Regress/regress-290656.js js1_5/Regress/regress-294191.js js1_5/Regress/regress-294195-01.js js1_5/Regress/regress-294195-02.js js1_5/Regress/regress-295052.js js1_5/Regress/regress-295666.js js1_5/Regress/regress-306633.js js1_5/Regress/regress-306727.js js1_5/Regress/regress-306794.js js1_5/Regress/regress-308566.js js1_5/Regress/regress-310295.js js1_5/Regress/regress-310607.js js1_5/Regress/regress-310993.js js1_5/Regress/regress-311071.js js1_5/Regress/regress-311629.js js1_5/Regress/regress-312260.js js1_5/Regress/regress-31255.js js1_5/Regress/regress-314401.js js1_5/Regress/regress-315990.js js1_5/Regress/regress-317476.js js1_5/Regress/regress-317714-02.js js1_5/Regress/regress-319384.js js1_5/Regress/regress-320032.js js1_5/Regress/regress-321757.js js1_5/Regress/regress-321874.js js1_5/Regress/regress-322430.js js1_5/Regress/regress-326467.js js1_5/Regress/regress-328012.js js1_5/Regress/regress-328897.js js1_5/Regress/regress-329383.js js1_5/Regress/regress-330951.js js1_5/Regress/regress-334807-05.js js1_5/Regress/regress-334807-06.js js1_5/Regress/regress-338307.js js1_5/Regress/regress-340369.js js1_5/Regress/regress-341360.js js1_5/Regress/regress-343966.js js1_5/Regress/regress-344804.js js1_5/Regress/regress-344959.js js1_5/Regress/regress-346801.js js1_5/Regress/regress-349482-01.js js1_5/Regress/regress-349482-02.js js1_5/Regress/regress-349592.js js1_5/Regress/regress-350253.js js1_5/Regress/regress-350312.js js1_5/Regress/regress-350415.js js1_5/Regress/regress-351116.js js1_5/Regress/regress-351515.js js1_5/Regress/regress-352009.js js1_5/Regress/regress-352208.js js1_5/Regress/regress-360969-01.js js1_5/Regress/regress-360969-02.js js1_5/Regress/regress-360969-03.js js1_5/Regress/regress-360969-04.js js1_5/Regress/regress-366468.js js1_5/Regress/regress-367561-01.js js1_5/Regress/regress-379245.js js1_5/Regress/regress-39309.js js1_5/Regress/regress-398609.js js1_5/Regress/regress-406769.js js1_5/Regress/regress-407024.js js1_5/Regress/regress-407323.js js1_5/Regress/regress-407957.js js1_5/Regress/regress-57043.js js1_5/Regress/regress-68498-001.js js1_5/Regress/regress-68498-002.js js1_5/Regress/regress-68498-004.js js1_5/Regress/regress-69607.js js1_5/Regress/regress-71107.js js1_5/Regress/regress-76054.js js1_5/Regress/regress-80981.js js1_5/Regress/regress-82306.js js1_5/Regress/regress-90445.js js1_5/Regress/regress-96526-001.js js1_5/Regress/regress-96526-003.js js1_5/Scope/regress-154693.js js1_5/Scope/regress-181834.js js1_5/Scope/regress-184107.js js1_5/Scope/regress-185485.js js1_5/Scope/regress-191276.js js1_5/Scope/regress-192226.js js1_5/Scope/regress-202678-001.js js1_5/Scope/regress-202678-002.js js1_5/Scope/regress-208496-001.js js1_5/Scope/regress-208496-002.js js1_5/Scope/regress-220362.js js1_5/Scope/regress-77578-001.js js1_5/Scope/scope-002.js js1_5/Scope/scope-003.js js1_5/String/regress-107771.js js1_5/String/regress-112626.js js1_5/String/regress-179068.js js1_5/String/regress-314890.js js1_5/decompilation/regress-344120.js js1_5/decompilation/regress-349489.js js1_5/decompilation/regress-349663.js js1_5/decompilation/regress-350670.js js1_5/decompilation/regress-351625.js js1_5/decompilation/regress-351626.js js1_5/decompilation/regress-352022.js js1_5/decompilation/regress-352073.js js1_5/decompilation/regress-352360.js js1_5/decompilation/regress-352873-01.js js1_5/decompilation/regress-352873-02.js js1_5/decompilation/regress-353120.js js1_5/decompilation/regress-354878.js js1_5/decompilation/regress-354910.js js1_5/decompilation/regress-371692.js js1_5/decompilation/regress-373678.js js1_5/decompilation/regress-375639.js js1_5/decompilation/regress-383721.js js1_5/decompilation/regress-406555.js js1_5/extensions/catchguard-001.js js1_5/extensions/catchguard-002.js js1_5/extensions/catchguard-003.js js1_5/extensions/getset-004.js js1_5/extensions/getset-005.js js1_5/extensions/getset-006.js js1_5/extensions/no-such-method.js js1_5/extensions/regress-104077.js js1_5/extensions/regress-178722.js js1_5/extensions/regress-220584.js js1_5/extensions/regress-225831.js js1_5/extensions/regress-226078.js js1_5/extensions/regress-226507.js js1_5/extensions/regress-237461.js js1_5/extensions/regress-245795.js js1_5/extensions/regress-255245.js js1_5/extensions/regress-291213.js js1_5/extensions/regress-311161.js js1_5/extensions/regress-311583.js js1_5/extensions/regress-311792-01.js js1_5/extensions/regress-311792-02.js js1_5/extensions/regress-312278.js js1_5/extensions/regress-313500.js js1_5/extensions/regress-313630.js js1_5/extensions/regress-313763.js js1_5/extensions/regress-313803.js js1_5/extensions/regress-313938.js js1_5/extensions/regress-314874.js js1_5/extensions/regress-319683.js js1_5/extensions/regress-322957.js js1_5/extensions/regress-325269.js js1_5/extensions/regress-327608.js js1_5/extensions/regress-328556.js js1_5/extensions/regress-338804-01.js js1_5/extensions/regress-338804-03.js js1_5/extensions/regress-339685.js js1_5/extensions/regress-340199.js js1_5/extensions/regress-341956-02.js js1_5/extensions/regress-341956-03.js js1_5/extensions/regress-346494-01.js js1_5/extensions/regress-350312-01.js js1_5/extensions/regress-350312-02.js js1_5/extensions/regress-350312-03.js js1_5/extensions/regress-351102-01.js js1_5/extensions/regress-351102-02.js js1_5/extensions/regress-351102-06.js js1_5/extensions/regress-351973.js js1_5/extensions/regress-352261.js js1_5/extensions/regress-352281.js js1_5/extensions/regress-354297.js js1_5/extensions/regress-354541-01.js js1_5/extensions/regress-354541-03.js js1_5/extensions/regress-355982.js js1_5/extensions/regress-356402.js js1_5/extensions/regress-363988.js js1_5/extensions/regress-365527.js js1_5/extensions/regress-365692.js js1_5/extensions/regress-366288.js js1_5/extensions/regress-366292.js js1_5/extensions/regress-366396.js js1_5/extensions/regress-367118-01.js js1_5/extensions/regress-367118-02.js js1_5/extensions/regress-367120-01.js js1_5/extensions/regress-367120-02.js js1_5/extensions/regress-367121.js js1_5/extensions/regress-367501-01.js js1_5/extensions/regress-367501-02.js js1_5/extensions/regress-367501-03.js js1_5/extensions/regress-367589.js js1_5/extensions/regress-369404.js js1_5/extensions/regress-374589.js js1_5/extensions/regress-375183.js js1_5/extensions/regress-380889.js js1_5/extensions/regress-385134.js js1_5/extensions/regress-394967.js js1_5/extensions/regress-396326.js js1_5/extensions/regress-407501.js js1_5/extensions/regress-44009.js js1_5/extensions/regress-50447.js js1_5/extensions/regress-90596-001.js js1_5/extensions/regress-90596-002.js js1_5/extensions/regress-96284-001.js js1_5/extensions/regress-96284-002.js js1_5/extensions/scope-001.js js1_6/Array/filter.js js1_6/Array/regress-304828.js js1_6/Array/regress-305002.js js1_6/Array/regress-310425-01.js js1_6/Array/regress-310425-02.js js1_6/Array/regress-320887.js js1_6/Array/regress-352742-01.js js1_6/Array/regress-352742-02.js js1_6/Array/regress-415451.js js1_6/Array/regress-415540.js js1_6/Regress/regress-301574.js js1_6/Regress/regress-311157-01.js js1_6/Regress/regress-311157-02.js js1_6/Regress/regress-314887.js js1_6/Regress/regress-351795.js js1_6/Regress/regress-352271.js js1_6/Regress/regress-378492.js js1_6/decompilation/regress-352084.js js1_6/extensions/regress-385393-08.js js1_7/GC/regress-341675.js js1_7/block/order-of-operation.js js1_7/block/regress-341939.js js1_7/block/regress-344139.js js1_7/block/regress-344370.js js1_7/block/regress-345542.js js1_7/block/regress-348685.js js1_7/block/regress-349283.js js1_7/block/regress-349298.js js1_7/block/regress-349507.js js1_7/block/regress-349653.js js1_7/block/regress-349962.js js1_7/block/regress-350279.js js1_7/block/regress-350730.js js1_7/block/regress-350793-01.js js1_7/block/regress-351497.js js1_7/block/regress-351606.js js1_7/block/regress-352092.js js1_7/block/regress-352185.js js1_7/block/regress-352212.js js1_7/block/regress-352267.js js1_7/block/regress-352616.js js1_7/block/regress-352624.js js1_7/block/regress-352907.js js1_7/block/regress-357754.js js1_7/block/regress-376410.js js1_7/block/regress-396900.js js1_7/block/regress-411279.js js1_7/decompilation/regress-349633.js js1_7/decompilation/regress-350810.js js1_7/decompilation/regress-352015.js js1_7/decompilation/regress-352025.js js1_7/decompilation/regress-352269.js js1_7/decompilation/regress-352272.js js1_7/decompilation/regress-352283.js js1_7/decompilation/regress-352732.js js1_7/decompilation/regress-355635.js js1_7/decompilation/regress-355786.js js1_7/decompilation/regress-375794.js js1_7/decompilation/regress-380506.js js1_7/expressions/destructuring-scope.js js1_7/expressions/regress-346203.js js1_7/expressions/regress-346645-01.js js1_7/expressions/regress-346645-02.js js1_7/expressions/regress-346645-03.js js1_7/expressions/regress-349624.js js1_7/expressions/regress-349818.js js1_7/extensions/basic-Iterator.js js1_7/extensions/basic-for-in.js js1_7/extensions/destructuring-order.js js1_7/extensions/iterator-ctor.js js1_7/extensions/regress-346021.js js1_7/extensions/regress-346642-02.js js1_7/extensions/regress-346773.js js1_7/extensions/regress-349619.js js1_7/extensions/regress-350312.js js1_7/extensions/regress-351070-02.js js1_7/extensions/regress-352797-01.js js1_7/extensions/regress-352885-01.js js1_7/extensions/regress-352885-02.js js1_7/extensions/regress-353214-02.js js1_7/extensions/regress-354499-01.js js1_7/extensions/regress-354499-02.js js1_7/extensions/regress-354945-01.js js1_7/extensions/regress-355052-01.js js1_7/extensions/regress-355052-02.js js1_7/extensions/regress-355052-03.js js1_7/extensions/regress-355410.js js1_7/extensions/regress-355512.js js1_7/extensions/regress-355578.js js1_7/extensions/regress-355583.js js1_7/extensions/regress-363040-01.js js1_7/extensions/regress-363040-02.js js1_7/extensions/regress-366668-01.js js1_7/extensions/regress-366668-02.js js1_7/extensions/regress-387955-01.js js1_7/extensions/regress-392308.js js1_7/extensions/regress-396326.js js1_7/geniter/326466-01.js js1_7/geniter/builtin-Iterator-function.js js1_7/geniter/evens.js js1_7/geniter/fibonacci-matrix-generator.js js1_7/geniter/iterator-toString.js js1_7/geniter/message-value-passing.js js1_7/geniter/multiple-close.js js1_7/geniter/nested-yield.js js1_7/geniter/pi-generator.js js1_7/geniter/regress-345736.js js1_7/geniter/regress-345855.js js1_7/geniter/regress-345879-01.js js1_7/geniter/regress-347593.js js1_7/geniter/regress-349012-02.js js1_7/geniter/regress-349012-03.js js1_7/geniter/regress-349012-04.js js1_7/geniter/regress-349012-05.js js1_7/geniter/regress-349023-01.js js1_7/geniter/regress-349023-02.js js1_7/geniter/regress-349023-03.js js1_7/geniter/regress-349362.js js1_7/geniter/regress-349851.js js1_7/geniter/regress-350621.js js1_7/geniter/regress-350809.js js1_7/geniter/regress-351120.js js1_7/geniter/regress-352197.js js1_7/geniter/regress-352876.js js1_7/geniter/regress-355834.js js1_7/geniter/regress-359062.js js1_7/geniter/regress-366941.js js1_7/geniter/regress-382335.js js1_7/geniter/regress-390918.js js1_7/geniter/send-no-rhs.js js1_7/geniter/sequential-yields.js js1_7/geniter/throw-after-close.js js1_7/geniter/throw-forever.js js1_7/geniter/unreachable-yield.js js1_7/geniter/yield-undefined.js js1_7/iterable/regress-341499.js js1_7/iterable/regress-341510.js js1_7/iterable/regress-341815.js js1_7/iterable/regress-341821.js js1_7/iterable/regress-354750-01.js js1_7/iterable/regress-355025.js js1_7/iterable/regress-355075-01.js js1_7/iterable/regress-355090.js js1_7/iterable/regress-412467.js js1_7/lexical/regress-346642-04.js js1_7/regress/regress-352640-01.js js1_7/regress/regress-352640-02.js js1_7/regress/regress-352640-03.js js1_7/regress/regress-352640-04.js js1_7/regress/regress-352797-02.js js1_7/regress/regress-352870-03.js js1_7/regress/regress-353079.js js1_7/regress/regress-355023.js js1_7/regress/regress-355832-01.js js1_7/regress/regress-361566.js js1_7/regress/regress-369666-01.js js1_7/regress/regress-369666-02.js js1_7/regress/regress-372331.js js1_7/regress/regress-373827-01.js js1_7/regress/regress-373827-02.js js1_7/regress/regress-373828.js js1_7/regress/regress-379442.js js1_7/regress/regress-385393-05.js js1_7/regress/regress-407727-01.js js1_7/regress/regress-407727-02.js js1_7/regress/regress-407957.js js1_7/regress/regress-414553.js lc2/Arrays/array-001.js lc2/Arrays/array-002.js lc2/Arrays/array-003.js lc2/Arrays/array-004.js lc2/Arrays/array-005.js lc2/Arrays/array-006-n.js lc2/Arrays/array-007-n.js lc2/Classes/class-001.js lc2/Classes/class-002.js lc2/JSToJava/character-001.js lc2/JSToJava/double-001.js lc2/JSToJava/double-002.js lc2/JSToJava/float-001.js lc2/JSToJava/float-002.js lc2/JSToJava/integer-001.js lc2/JSToJava/integer-002.js lc2/JSToJava/long-001.js lc2/JSToJava/long-002.js lc2/JSToJava/long-003-n.js lc2/JSToJava/short-001.js lc2/JSToJava/short-002.js lc2/JSToJava/short-003-n.js lc2/JavaToJS/String-001.js lc2/JavaToJS/boolean-001.js lc2/JavaToJS/boolean-003.js lc2/JavaToJS/boolean-004.js lc2/JavaToJS/boolean-005.js lc2/JavaToJS/char-001.js lc2/JavaToJS/char-002.js lc2/JavaToJS/enum-001.js lc2/JavaToJS/enum-002.js lc2/JavaToJS/null-001.js lc2/JavaToJS/number-001.js lc2/JavaToJS/number-002.js lc2/Methods/method-001.js lc2/Methods/method-002.js lc2/Methods/method-003.js lc2/Methods/method-004-n.js lc2/Methods/method-005.js lc2/Methods/method-006-n.js lc2/Methods/println-001.js lc2/Objects/object-001.js lc2/Objects/object-002.js lc2/Objects/object-003.js lc2/Objects/object-004.js lc2/Objects/object-005.js lc2/Objects/object-006.js lc2/Packages/package-001.js lc2/Packages/package-002.js lc2/Packages/package-003.js lc2/Packages/package-005.js lc2/Packages/package-006.js lc2/Packages/package-007-n.js lc2/Packages/package-008-n.js lc2/misc/constructor.js lc2/misc/wrapUnwrap.js lc3/ArrayMethods/byte-001.js lc3/ArrayMethods/byte-002.js lc3/ConvertBoolean/boolean-005-n.js lc3/ConvertBoolean/boolean-006-n.js lc3/ConvertBoolean/boolean-007-n.js lc3/ConvertBoolean/boolean-008-n.js lc3/ConvertBoolean/boolean-009-n.js lc3/ConvertBoolean/boolean-010-n.js lc3/ConvertBoolean/boolean-011-n.js lc3/ConvertBoolean/boolean-012-n.js lc3/ConvertBoolean/boolean-013-n.js lc3/ConvertNull/null-002.js lc3/ConvertNull/null-003-n.js lc3/ConvertNull/null-004-n.js lc3/ConvertNull/null-006-n.js lc3/ConvertString/string-004-n.js lc3/ConvertString/string-005-n.js lc3/ConvertString/string-007-n.js lc3/ConvertUndefined/undefined-001-n.js lc3/JSBoolean/boolean-002-n.js lc3/JSBoolean/boolean-003-n.js lc3/JSBoolean/boolean-004-n.js lc3/JSBoolean/boolean-005-n.js lc3/JSBoolean/boolean-006-n.js lc3/JSBoolean/boolean-007-n.js lc3/JSBoolean/boolean-008-n.js lc3/JSNull/ToBoolean-001-n.js lc3/JSNull/ToLong-001-n.js lc3/JSNull/ToNumber-001-n.js lc3/JSNumber/ToByte-002-n.js lc3/JSNumber/ToByte-003-n.js lc3/JSNumber/ToByte-005-n.js lc3/JSNumber/ToChar-002-n.js lc3/JSNumber/ToChar-003-n.js lc3/JSNumber/ToChar-005-n.js lc3/JSNumber/ToChar-006-n.js lc3/JSNumber/ToInt-002-n.js lc3/JSNumber/ToInt-003-n.js lc3/JSNumber/ToLong-002-n.js lc3/JSNumber/ToLong-003-n.js lc3/JSNumber/ToLong-004-n.js lc3/JSNumber/ToLong-005-n.js lc3/JSNumber/ToLong-006-n.js lc3/JSNumber/ToLong-007-n.js lc3/JSNumber/ToLong-008-n.js lc3/JSNumber/ToLong-009-n.js lc3/JSNumber/ToLong-010-n.js lc3/JSNumber/ToLong-011-n.js lc3/JSNumber/ToShort-003-n.js lc3/JSNumber/ToShort-005-n.js lc3/JSObject/ToDouble-002-n.js lc3/JSObject/ToDouble-003-n.js lc3/JSObject/ToFloat-002-n.js lc3/JSObject/ToFloat-003-n.js lc3/JSUndefined/undefined-002-n.js lc3/JSUndefined/undefined-003-n.js lc3/JSUndefined/undefined-004-n.js lc3/JSUndefined/undefined-005-n.js lc3/JSUndefined/undefined-006-n.js lc3/JSUndefined/undefined-008-n.js lc3/JSUndefined/undefined-009-n.js lc3/JSUndefined/undefined-010-n.js lc3/JavaArray/ToArray-002-n.js lc3/JavaArray/ToBoolean-001-n.js lc3/JavaObject/JavaObjectToBoolean-002-n.js lc3/JavaObject/JavaObjectToByte-002-n.js lc3/JavaObject/JavaObjectToByte-007-n.js lc3/JavaObject/JavaObjectToByte-008-n.js lc3/JavaObject/JavaObjectToChar-003-n.js lc3/JavaObject/JavaObjectToChar-005-n.js lc3/JavaObject/JavaObjectToChar-006-n.js lc3/JavaObject/JavaObjectToInt-002-n.js lc3/JavaObject/JavaObjectToInt-003-n.js lc3/JavaObject/JavaObjectToInt-004-n.js lc3/JavaObject/JavaObjectToLong-002-n.js lc3/JavaObject/JavaObjectToLong-003-n.js lc3/JavaObject/JavaObjectToLong-004-n.js lc3/JavaObject/JavaObjectToLong-006-n.js lc3/JavaObject/JavaObjectToShort-002-n.js lc3/JavaObject/JavaObjectToShort-003-n.js lc3/JavaObject/JavaObjectToShort-004-n.js lc3/StringMethods/string-001.js htmlunit-core-js-2.8/rhino/testsrc/doctests/0000755000175000017500000000000011530107756021052 5ustar cavedoncavedonhtmlunit-core-js-2.8/rhino/testsrc/doctests/object.keys.doctest0000644000175000017500000000241011222460357024653 0ustar cavedoncavedonjs> load('testsrc/doctests/util.js'); js> Object.keys; function keys() { [native code for Object.keys, arity=1] } js> expectTypeError(function() { Object.keys() }) js> [undefined, null, true, 1, 'hello'].forEach(function(value) { > expectTypeError(function() { Object.keys(value) }) > }) js> Object.keys({}).toSource(); [] js> Object.keys({a:2}).toSource(); ["a"] js> Object.keys({a:1, b:2}).toSource(); ["a", "b"] js> Object.keys({'a.b':1, 'c d':2}).toSource(); ["a.b", "c d"] js> Object.keys([]).toSource(); [] js> Object.keys(['a', 'b', 'c']).toSource(); ["0", "1", "2"] js> function UserDefined() { this.a = 1; this.b = 2 }; js> var obj = new UserDefined() js> Object.keys(obj).toSource() ["a", "b"] js> UserDefined.prototype.c = 3; 3 js> Object.keys(obj).toSource() ["a", "b"] js> // test properties of result are enumerable js> for (var p in Object.keys({a:2, b:3})) print(p) 0 1 js> // test that properties of result are writable js> var k = Object.keys({a:2, b:3}); js> k[1] = 'c'; k.toSource(); ["a", "c"] js> // test that properties of result are configurable js> var k = Object.keys({a:2, b:3}) js> delete k[1]; true js> k a, js> // TODO test that the attributes of the properties can be changed js> var k = Object.keys({ a:1, 3:2 }); js> typeof k[1]; string htmlunit-core-js-2.8/rhino/testsrc/doctests/date.tojson.doctest0000644000175000017500000000142211255674656024704 0ustar cavedoncavedonjs> load('testsrc/doctests/util.js'); js> Date.prototype.toJSON; function toJSON() { [native code for Date.toJSON, arity=1] } js> Date.prototype.toJSON.call({ > valueOf: function() { return Infinity; } > }, '') null js> expectError(function() { > Date.prototype.toJSON.call({}, '') > }, TypeError) js> expectError(function() { > Date.prototype.toJSON.call(5, '') > }, TypeError) js> expectError(function() { > Date.prototype.toJSON.call({toISOString:5}, '') > }, TypeError) js> expectError(function() { > Date.prototype.toJSON.call({toISOString:function(){ return [] }}, '') > }, TypeError) js> Date.prototype.toJSON.call({toISOString: function() { return 'w00t' }}, '') w00t js> var now = new Date() js> now.toJSON('') === now.toISOString() true htmlunit-core-js-2.8/rhino/testsrc/doctests/json.doctest0000644000175000017500000000016011321335670023403 0ustar cavedoncavedonjs> ({"1": true})["1"] true js> JSON.parse("{\"1\": true}")["1"] true js> JSON.parse("{\"a\": true}")["a"] true htmlunit-core-js-2.8/rhino/testsrc/doctests/iterable.doctest0000644000175000017500000000053210776623544024241 0ustar cavedoncavedon// Test of Creating a JavaScript Iterator from a Java Iterable or Iterator // See http://developer.mozilla.org/en/docs/New_in_Rhino_1.7R1 js> m = new java.util.LinkedHashMap() {} js> m.put("a",1); m.put("b",2); m {a=1.0, b=2.0} js> for (i in Iterator(m.values())) print(i) 1.0 2.0 js> for (i in Iterator(m.values().iterator())) print(i) 1.0 2.0 htmlunit-core-js-2.8/rhino/testsrc/doctests/date.toisostring.doctest0000644000175000017500000000143111255674656025754 0ustar cavedoncavedonjs> load('testsrc/doctests/util.js'); js> Date.prototype.toISOString; function toISOString() { [native code for Date.toISOString, arity=0] } js> expectError(function() { > new Date(Infinity).toISOString() > }, RangeError); js> new Date(0).toISOString() 1970-01-01T00:00:00.000Z js> var isoFormat = /(\d\d\d\d)-(\d\d)-(\d\d)T(\d\d):(\d\d):(\d\d).(\d\d\d)Z/; js> var now = new Date(); js> var matches = isoFormat.exec(now.toISOString()); js> matches[0] === now.toISOString() true js> matches[1] == now.getUTCFullYear() true js> matches[2] == now.getUTCMonth()+1 true js> matches[3] == now.getUTCDate() true js> matches[4] == now.getUTCHours() true js> matches[5] == now.getUTCMinutes() true js> matches[6] == now.getUTCSeconds() true js> matches[7] == now.getUTCMilliseconds() true htmlunit-core-js-2.8/rhino/testsrc/doctests/473761.doctest0000644000175000017500000000033511222460357023212 0ustar cavedoncavedonjs> var xml = ; js> var order = xml.customer.order; js> order.orderid = "1"; 1 js> order.test = "expected_string"; expected_string js> xml.customer.order.test; expected_string htmlunit-core-js-2.8/rhino/testsrc/doctests/serialize.doctest0000644000175000017500000000043711111054626024424 0ustar cavedoncavedonjs> var obj = { a:3, b:"hi", 9:"nine", 12:1200 }; js> serialize(obj, "foo.bin"); js> obj2 = deserialize("foo.bin"); [object Object] js> uneval(obj) ({a:3, b:"hi", 9:"nine", 12:1200}) js> uneval(obj2) ({a:3, b:"hi", 9:"nine", 12:1200}) js> (new java.io.File("foo.bin"))["delete"](); true htmlunit-core-js-2.8/rhino/testsrc/doctests/util.js0000644000175000017500000000036411255674656022404 0ustar cavedoncavedonfunction expectTypeError(code) { expectError(code, TypeError); } function expectError(code, error) { try { code(); throw (code.toSource() + ' should have thrown a '+error); } catch (e if e instanceof error) { // all good } } htmlunit-core-js-2.8/rhino/testsrc/doctests/439530.doctest0000644000175000017500000000014411111054626023177 0ustar cavedoncavedonjs> var obj = { run: function () { print("\nrunning"); } } js> var r = new java.lang.Runnable(obj); htmlunit-core-js-2.8/rhino/testsrc/doctests/434041.doctest0000644000175000017500000000042511222460357023176 0ustar cavedoncavedon// Regression test for bug https://bugzilla.mozilla.org/show_bug.cgi?id=434041 js> function add(_object, _key, _value) { > _object[_key] = _value; > } js> var o = {}; js> add(o, 'a', 'b'); js> o.toSource(); ({a:"b"}) js> add(o, 3, 'c'); js> o.toSource(); ({a:"b", 3:"c"})htmlunit-core-js-2.8/rhino/testsrc/doctests/arrays.doctest0000644000175000017500000000152711255674656023763 0ustar cavedoncavedonjs> [1,2,undefined,4].join(';') 1;2;;4 js> [1,2,null,4].join(';') 1;2;;4 js> var arr = []; arr[0] = 1; arr[1] = 2; arr[3] = 4; arr.join(';') 1;2;;4 js> var arr = [1,2,3,4]; delete arr[2]; arr.join(';') 1;2;;4 js> var arr = ["a","b","c","d"]; js> var _ = arr.length = 2; js> arr[2] === undefined true js> arr[1] === "b" true js> [1,2,3].reverse().toSource() [3, 2, 1] js> [2,1,3].sort().toSource() [1, 2, 3] js> var arr = [1,2,3]; arr.push(4); arr.toSource() [1, 2, 3, 4] js> var arr = [1,2,3]; arr.pop(); 3 js> arr.toSource() [1, 2] js> var arr = [1,2,3]; arr.shift(); 1 js> arr.toSource() [2, 3] js> var arr = [2,3]; arr.unshift(1); arr.toSource() [1, 2, 3] js> var arr = [1,2,3]; arr.splice(1, 1, "a", "b").toSource() [2] js> arr.toSource() [1, "a", "b", 3] js> [1,2,3].concat([4,5,6]).toSource() [1, 2, 3, 4, 5, 6] js> [1,2,3].indexOf(2) 1 htmlunit-core-js-2.8/rhino/testsrc/doctests/441417.doctest0000644000175000017500000000115111111054626023173 0ustar cavedoncavedonjs> var friendInfo = xmlns="http://ode.apache.org/simpel/1.0/definition/XmlData"> xmlns=""/>; js> var msgIn = xmlns:xd="http://ode.apache.org/simpel/1.0/definition/XmlData"> > > John > Doe > (999)999-9999 > > ; js> friendInfo.name = msgIn.person.firstName.text() + " " + > msgIn.person.lastName.text(); John Doe htmlunit-core-js-2.8/rhino/testsrc/doctests/393794.doctest0000644000175000017500000000011011222460357023210 0ustar cavedoncavedonjs> var x = { foo: "bar" } js> var y = { __proto__: x }; js> y.foo; bar htmlunit-core-js-2.8/rhino/testsrc/doctests/object.getprototypeof.doctest0000644000175000017500000000126211222460357026776 0ustar cavedoncavedonjs> load('testsrc/doctests/util.js'); js> Object.getPrototypeOf; function getPrototypeOf() { [native code for Object.getPrototypeOf, arity=1] } js> expectTypeError(function() { Object.getPrototypeOf() }) js> [undefined, null, true, 1, 'hello'].forEach(function(value) { > expectTypeError(function() { Object.getPrototypeOf(value) }) > }) js> [(function(){}), [], {}].every(function(obj) { > return Object.getPrototypeOf(obj) === obj.__proto__; > }); true js> function UserDefined() {} js> [Date, UserDefined].every(function(type) { > var instance; > eval('instance = new '+type.name); > return Object.getPrototypeOf(instance) === type.prototype; > }); true htmlunit-core-js-2.8/rhino/testsrc/doctests/object.extensible.doctest0000644000175000017500000000157411222460357026054 0ustar cavedoncavedonjs> load('testsrc/doctests/util.js'); js> Object.isExtensible; function isExtensible() { [native code for Object.isExtensible, arity=1] } js> expectTypeError(function() { Object.isExtensible() }); js> [undefined, null, true, 1, 'hello'].forEach(function(value) { > expectTypeError(function() { Object.isExtensible(value) }) > }) js> Object.preventExtensions; function preventExtensions() { [native code for Object.preventExtensions, arity=1] } js> expectTypeError(function() { Object.preventExtensions() }); js> [undefined, null, true, 1, 'hello'].forEach(function(value) { > expectTypeError(function() { Object.preventExtensions(value) }) > }) js> var x = {}; js> Object.isExtensible(x); true js> var y = Object.preventExtensions(x); js> y === x; true js> Object.isExtensible(x); false js> x.a = 1; x.a js> js> x.__defineGetter__('b', function() { return 1 }); x.b js> htmlunit-core-js-2.8/rhino/testsrc/doctests/Counter.doctest0000644000175000017500000000021511111054626024046 0ustar cavedoncavedonjs> defineClass("Counter") js> c = new Counter(7) [object Counter] js> c.count 7 js> c.count 8 js> c.count 9 js> c.resetCount() js> c.count 0htmlunit-core-js-2.8/rhino/testsrc/doctests/error.tostring.doctest0000644000175000017500000000151411321335670025437 0ustar cavedoncavedonjs> load('testsrc/doctests/util.js') js> var str = Error.prototype.toString js> str.call(new TypeError("msg")) TypeError: msg js> str.call(new TypeError()) // message is initialised to '' TypeError: js> str.call(new Error("msg")) Error: msg js> str.call(new Error()) // message is initialised to '' Error: js> str.call({name:"my error", message:"my message"}) my error: my message js> str.call({}) === undefined true js> str.call({name:"no message defined"}) === undefined true js> str.call({name:"message is undefined", message:undefined}) === undefined true js> str.call({name:"null message", message:null}) null message: null js> str.call({message:"no name defined"}) Error: no name defined js> str.call({name:undefined, message:"name is undefined"}) Error: name is undefined js> str.call({name:null, message:"null name"}) null: null name htmlunit-core-js-2.8/rhino/testsrc/doctests/413838.doctest0000644000175000017500000000114410776623544023224 0ustar cavedoncavedonjs> var map = new java.util.HashMap(); js> map.put("a","hi"); null js> map.put("b","hi"); null js> map.get("a") == map.get("b") true js> map.put("c",1) null js> map.put("c",1) 1.0 js> map.put("d",1) null js> map.get("c") == map.get("d") true js> map.get("a") == map.get("d") false js> map.put("e","1") null js> map.get("d") == map.get("e") true js> map.put("f", true) null js> map.put("g", true) null js> map.get("f") == map.get("g") true js> var obj = {} js> map.put("h", obj) null js> map.put("i", obj) null js> map.get("h") == map.get("i") true js> map.put("j", {}) null js> map.get("i") == map.get("j") falsehtmlunit-core-js-2.8/rhino/testsrc/doctests/eval.doctest0000644000175000017500000000122111255674656023400 0ustar cavedoncavedonjs> // only direct calls to eval should use scope of call js> // indirect calls should be allowed, but use global scope instead js> var value = 'outer'; js> (function() { var value = "inner"; return eval("value"); })(); inner js> (function(_eval) { var value = "inner"; return _eval("value"); })(eval); outer js> (function(obj) { var value = "inner"; return obj.eval("value"); })({eval:eval}); outer js> (function(obj) { var value = "inner"; return obj.f("value"); })({f:eval}); outer js> (function(arr) { var value = "inner"; return arr[0]("value"); })([eval]); outer js> (function() { var value = "inner"; return eval("eval")("value"); })(); outer htmlunit-core-js-2.8/rhino/testsrc/doctests/iteratorKeys.doctest0000755000175000017500000000033311222460357025125 0ustar cavedoncavedonjs> version(170) 0 js> var foo = { > __iterator__ : function(onlyKeys) { > print(onlyKeys); > yield [0, "a"]; > } > }; js> for each (let f in foo) {} false js> for (let f in foo) {} truehtmlunit-core-js-2.8/rhino/testsrc/doctests/433878.doctest0000644000175000017500000000054611111054626023216 0ustar cavedoncavedonjs> version(170) 0 js> function f(a,b,c) { > let sum = a + b + c; > return sum / 3; > } js> f.toString() function f(a, b, c) { let sum = a + b + c; return sum / 3; } js> try { > eval("function f() { for (;;) let a=3; return 3; }"); > } catch (e) { > e; > } SyntaxError: SyntaxError: let declaration not directly within block htmlunit-core-js-2.8/rhino/testsrc/doctests/controlchars.doctest0000644000175000017500000000163411255674656025162 0ustar cavedoncavedonjs> var controlChars = [ > 0x200C, 0x200D, 0x200E, 0x200F, > 0x202A, 0x202B, 0x202C, 0x202D, 0x202E, > 0x00AD, > 0x2061, 0x2062, 0x2063, 0x2064, > 0x206A, 0x206B, 0x206C, 0x206D, 0x206E, 0x206F > ]; js> function validInRegExpLiteral(num) { > eval('/.'+String.fromCharCode(num)+'./'); > } js> function validInStringLiteral(num) { > eval('"'+String.fromCharCode(num)+'"'); > } js> function validInComments(num) { > eval('/*'+String.fromCharCode(num)+'*/'); > } js> function check(test) { > return function(codePoint) { > try { > test(codePoint); > return true; > } catch (e) { > throw "problem with U+"+codePoint.toString(16).toUpperCase()+": "+e; > } > }; > } js> controlChars.every(check(validInRegExpLiteral)) true js> controlChars.every(check(validInStringLiteral)) true js> controlChars.every(check(validInComments)) true htmlunit-core-js-2.8/rhino/testsrc/doctests/date.parse.doctest0000644000175000017500000000075711255674656024514 0ustar cavedoncavedonjs> Date.parse('1970-01-01T00:00:00.000Z') 0 js> Date.parse('1970-01-01T00:00:00.000A') NaN js> Date.parse('1971-02-02T10:10:10.001Z') 34337410001 js> var d = new Date() js> var _ = d.setMilliseconds(0); js> Date.parse(d.toISOString()) === d.valueOf(); true js> Date.parse(d.toISOString()) === Date.parse(d.toString()); true js> Date.parse(d.toISOString()) === Date.parse(d.toUTCString()); true js> Date.parse('1970-01-01T00:00:00.000Z a b c') NaN js> Date.parse('1970-01-01T00:00:00.000A') NaN htmlunit-core-js-2.8/rhino/testsrc/doctests/canonicalize.doctest0000644000175000017500000000052410776623544025112 0ustar cavedoncavedonjs> var obj = new java.lang.Object(); js> obj java.lang.Object@97a560 js> obj + "%%" java.lang.Object@97a560%% js> var obj = new java.lang.Object(); js> obj java.lang.Object@1d15445 js> "foo" + obj + "bar" foojava.lang.Object@1d15445bar js> var obj2 = new java.lang.Object(); js> obj + obj2 java.lang.Object@1d15445java.lang.Object@1f3aa07 htmlunit-core-js-2.8/rhino/testsrc/doctests/467396.doctest0000755000175000017500000000046011222460357023223 0ustar cavedoncavedonjs> var a = java.lang.reflect.Array.newInstance(java.lang.Integer, [17,4]); js> a [[Ljava.lang.Integer;@1543c88 js> a.length 17 js> a[0].length 4 js> var a = java.lang.reflect.Array.newInstance(java.lang.Integer, 17, 4); js> a [[Ljava.lang.Integer;@f11404 js> a.length 17 js> a[0].length 4 htmlunit-core-js-2.8/rhino/testsrc/doctests/524931.doctest0000644000175000017500000000021311321335670023200 0ustar cavedoncavedonjs> var x = bar; js> x.foo[0] = "baz"; baz js> x.foo[1] = "barf"; barf js> x baz barf htmlunit-core-js-2.8/rhino/testsrc/doctests/string.trim.doctest0000644000175000017500000000147111255674656024740 0ustar cavedoncavedonjs> load('testsrc/doctests/util.js'); js> String.prototype.trim; function trim() { [native code for String.trim, arity=0] } js> String.prototype.trim.call({toString: function() { return "a" }}); a js> " hello ".trim() === "hello"; true js> var chr = String.fromCharCode; js> var str = "" + > // ecma whitespace > chr(0x0009) + chr(0x000B) + chr(0x000C) + chr(0x0020) + chr(0x00A0) + chr(0xFEFF) + > // unicode whitespace > chr(0x1680) + chr(0x180E) + > chr(0x2000) + chr(0x2001) + chr(0x2002) + chr(0x2003) + chr(0x2004) + chr(0x2005) + chr(0x2006) + chr(0x2007) + chr(0x2008) + chr(0x2009) + chr(0x200A) + > chr(0x202F) + chr(0x205F) + chr(0x3000) + > // ecma line terminators > chr(0x000A) + chr(0x000D) + chr(0x2028) + chr(0x2029) + > > "abc"; js> str.trim() === "abc"; true htmlunit-core-js-2.8/rhino/testsrc/doctests/object.isfrozen.doctest0000644000175000017500000000204611222460357025544 0ustar cavedoncavedonjs> load('testsrc/doctests/util.js'); js> Object.isFrozen function isFrozen() { [native code for Object.isFrozen, arity=1] } js> expectTypeError(function() { Object.isFrozen() }); js> [undefined, null, true, 1, 'hello'].forEach(function(value) { > expectTypeError(function() { Object.isFrozen(value) }) > }) js> Object.isFrozen({}) false js> var obj = Object.preventExtensions({}); js> Object.isFrozen(obj); true js> var obj = Object.defineProperty({}, 'a', {configurable:true, writable:false}) js> var _ = Object.preventExtensions(obj); js> Object.isFrozen(obj); false js> var obj = Object.defineProperty({}, 'a', {configurable:false, writable:true}) js> var _ = Object.preventExtensions(obj); js> Object.isFrozen(obj); false js> var obj = Object.defineProperty({}, 'a', {configurable:false, writable:false}) js> var _ = Object.preventExtensions(obj); js> Object.isFrozen(obj); true js> var obj = Object.defineProperty({}, 'a', {configurable:false, set: function(){} }) js> var _ = Object.preventExtensions(obj); js> Object.isFrozen(obj); true htmlunit-core-js-2.8/rhino/testsrc/doctests/object.defineproperties.doctest0000644000175000017500000000241511222460357027254 0ustar cavedoncavedonjs> load('testsrc/doctests/util.js'); js> Object.defineProperties function defineProperties() { [native code for Object.defineProperties, arity=2] } js> expectTypeError(function() { Object.defineProperties() }); js> expectTypeError(function() { Object.defineProperties({}) }); js> [undefined, null, true, 1, 'hello'].forEach(function(value) { > expectTypeError(function() { Object.defineProperties(value, {}) }) > }) js> Object.defineProperties({}, {p: {value:1}}).p 1 js> var obj = Object.defineProperties({}, {a: {value:1}, b: {value:2}}); js> [obj.a, obj.b].toSource(); [1, 2] js> Object.defineProperties({}, {'wierd name': {value:1}})['wierd name'] 1 js> Object.defineProperties({}, {}).toSource() ({}) js> var obj = {a:1}; js> var obj = Object.defineProperties(obj, {a:{value:2}, b:{value:3}}); js> [obj.a, obj.b].toSource() [2, 3] js> expectTypeError(function() { Object.defineProperties({}, {a: null}) }) js> expectTypeError(function() { Object.defineProperties({}, {a: 1}) }) js> expectTypeError(function() { Object.defineProperties({}, {a: {get: 1}}) }) js> var obj = {a:1} js> expectTypeError(function() { > obj = Object.defineProperties(obj, {b: {value:1}, c:1}); > }); js> obj.b js> js> Object.defineProperties({}, {'0.0': {value:1}, 0: {value:2}})['0'] 2 htmlunit-core-js-2.8/rhino/testsrc/doctests/array.length.doctest0000644000175000017500000000026311255674656025054 0ustar cavedoncavedonjs> function Array() { throw "don't call this" } js> [].length 0 js> [1].length 1 js> [,1,2].length 3 js> [1,,2].length 3 js> [1,2,].length 2 js> [,].length 1 js> [1,,].length 2 htmlunit-core-js-2.8/rhino/testsrc/doctests/429121.doctest0000644000175000017500000000005611111054626023174 0ustar cavedoncavedonjs> encodeURIComponent('$ a ;') %24%20a%20%3B htmlunit-core-js-2.8/rhino/testsrc/doctests/object.issealed.doctest0000644000175000017500000000130711222460357025475 0ustar cavedoncavedonjs> load('testsrc/doctests/util.js'); js> Object.isSealed function isSealed() { [native code for Object.isSealed, arity=1] } js> expectTypeError(function() { Object.isSealed() }); js> [undefined, null, true, 1, 'hello'].forEach(function(value) { > expectTypeError(function() { Object.isSealed(value) }) > }) js> Object.isSealed({}) false js> var obj = Object.preventExtensions({}); js> Object.isSealed(obj); true js> var obj = Object.defineProperty({}, 'a', {configurable:false}); js> var _ = Object.preventExtensions(obj); js> Object.isSealed(obj); true js> var obj = Object.defineProperty({}, 'a', {configurable:true}); js> var _ = Object.preventExtensions(obj); js> Object.isSealed(obj); false htmlunit-core-js-2.8/rhino/testsrc/doctests/480758.doctest0000755000175000017500000000063311222460357023222 0ustar cavedoncavedonjs> function primBeget(proto) { > if (proto === null) { fail("Cannot beget from null."); } > if (proto === (void 0)) { fail("Cannot beget from undefined."); } > function F() {} > F.prototype = proto; > var result = new F(); > return result; > } js> var x = [1].concat(primBeget(Array.prototype)); js> x 1, js> x[1] js> typeof x[1] object js> x[1] instanceof Array truehtmlunit-core-js-2.8/rhino/testsrc/doctests/368019.doctest0000644000175000017500000000033111111054626023200 0ustar cavedoncavedon// Regression test for bug https://bugzilla.mozilla.org/show_bug.cgi?id=368019 // - regular expression (regex) parses /[/]/ incorrectly js> var re; js> re = /[^/]*/; /[^/]*/ js> re = /[/]/; /[/]/ js> re = /\[/; /\[/ htmlunit-core-js-2.8/rhino/testsrc/doctests/object.getownpropertydescriptor.doctest0000644000175000017500000000423711255674656031137 0ustar cavedoncavedonjs> load('testsrc/doctests/util.js'); js> Object.getOwnPropertyDescriptor; function getOwnPropertyDescriptor() { [native code for Object.getOwnPropertyDescriptor, arity=2] } js> expectTypeError(function() { Object.getOwnPropertyDescriptor() }) js> var desc = Object.getOwnPropertyDescriptor({undefined:3}); js> desc.value 3 js> [undefined, null, true, 1, 'hello'].forEach(function(value) { > expectTypeError(function() { Object.getOwnPropertyDescriptor(value, 'p') }) > }) js> Object.getOwnPropertyDescriptor({}, 'p') === undefined; true js> var desc = Object.getOwnPropertyDescriptor({p:1}, 'p'); js> desc.value 1 js> desc.writable true js> desc.enumerable true js> desc.configurable true js> var desc = Object.getOwnPropertyDescriptor({ get p() {}, set p() {} }, 'p'); js> desc.value === undefined; true js> desc.writable === undefined; true js> desc.get.toSource() (function () {}) js> desc.set.toSource() (function () {}) js> desc.enumerable true js> desc.configurable true js> desc.__proto__ === Object.prototype true js> desc.__parent__; [object global] js> var func = function(){} js> func.a = 1; Object.getOwnPropertyDescriptor(func, 'a').toSource() ({value:1, writable:true, enumerable:true, configurable:true}) js> Object.getOwnPropertyDescriptor({undefined: 1}, undefined).toSource() ({value:1, writable:true, enumerable:true, configurable:true}) js> Object.getOwnPropertyDescriptor({0:1}, 0).toSource() ({value:1, writable:true, enumerable:true, configurable:true}) js> Object.getOwnPropertyDescriptor([1], 0).toSource() ({value:1, writable:true, enumerable:true, configurable:true}) js> Object.getOwnPropertyDescriptor([1], '0').toSource() ({value:1, writable:true, enumerable:true, configurable:true}) js> Object.getOwnPropertyDescriptor([1], 1) === undefined true js> Object.getOwnPropertyDescriptor([1], -1) === undefined true js> var arr = []; js> arr.a = 1; 1 js> Object.getOwnPropertyDescriptor(arr, 'a').toSource() ({value:1, writable:true, enumerable:true, configurable:true}) js> var arr = Object.defineProperty([], 'a', {value:1, writable:false,}) js> var desc = Object.getOwnPropertyDescriptor(arr, 'a'); ([desc.value, desc.writable]).toSource() [1, false] htmlunit-core-js-2.8/rhino/testsrc/doctests/442922.doctest0000644000175000017500000000027711111054626023205 0ustar cavedoncavedonjs> var x =
; js> serialize(x, "x.ser"); js> deserialize("x.ser"); js> (new java.io.File("x.ser"))["delete"](); truehtmlunit-core-js-2.8/rhino/testsrc/doctests/object.getownpropertynames.doctest0000644000175000017500000000302511222460357030037 0ustar cavedoncavedonjs> load('testsrc/doctests/util.js'); js> Object.getOwnPropertyNames; function getOwnPropertyNames() { [native code for Object.getOwnPropertyNames, arity=1] } js> expectTypeError(function() { Object.getOwnPropertyNames() }) js> [undefined, null, true, 1, 'hello'].forEach(function(value) { > expectTypeError(function() { Object.getOwnPropertyNames(value) }) > }) js> Object.getOwnPropertyNames({}).toSource(); [] js> Object.getOwnPropertyNames({a:2}).toSource(); ["a"] js> Object.getOwnPropertyNames({a:1, b:2}).toSource(); ["a", "b"] js> Object.getOwnPropertyNames({'a.b':1, 'c d':2}).toSource(); ["a.b", "c d"] js> Object.getOwnPropertyNames([]).toSource(); ["length"] js> Object.getOwnPropertyNames(['a', 'b', 'c']).toSource(); ["0", "1", "2", "length"] js> function UserDefined() { this.a = 1; this.b = 2 }; js> var obj = new UserDefined() js> Object.getOwnPropertyNames(obj).toSource() ["a", "b"] js> UserDefined.prototype.c = 3; 3 js> Object.getOwnPropertyNames(obj).toSource() ["a", "b"] js> // test properties of result are enumerable js> for (var p in Object.getOwnPropertyNames({a:2, b:3})) print(p) 0 1 js> // test that properties of result are writable js> var k = Object.getOwnPropertyNames({a:2, b:3}); js> k[1] = 'c'; k.toSource(); ["a", "c"] js> // test that properties of result are configurable js> var k = Object.getOwnPropertyNames({a:2, b:3}) js> delete k[1]; true js> k a, js> // TODO test that the attributes of the properties can be changed js> var k = Object.getOwnPropertyNames({a:2, 5:6}) js> typeof k[1] string htmlunit-core-js-2.8/rhino/testsrc/doctests/arguments.doctest0000644000175000017500000000631011321335670024442 0ustar cavedoncavedonjs> var args = (function() { return arguments })() js> Object.getPrototypeOf(args) === Object.prototype true js> args.constructor === Object.prototype.constructor true js> Object.getOwnPropertyDescriptor(args, 'constructor').toSource(); ({value:function Object() { [native code for Object.Object, arity=1] } , writable:true, enumerable:false, configurable:true}) js> args.toString() [object Arguments] js> var toStr = Object.prototype.toString; js> var _ = Object.prototype.toString = function() { > return this === args ? > "executes Object.prototype.toString.call(arguments)" : > "'this' should be 'arguments'" > } js> args.toString() executes Object.prototype.toString.call(arguments) js> Object.prototype.toString = toStr; undefined js> var toLocStr = Object.prototype.toLocaleString; js> var _ = Object.prototype.toLocaleString = function() { > return this === args ? > "executes Object.prototype.toLocaleString.call(arguments)" : > "'this' should be 'arguments'" > } js> args.toLocaleString() executes Object.prototype.toLocaleString.call(arguments) js> Object.prototype.toLocaleString = toLocStr; undefined; js> (function() { return arguments[2] })('a','b','c') c js> (function(x,y,z) { return arguments[2] })('a','b','c') c js> (function(x) { > arguments[0] = "modified"; > return x; > })("original") modified js> (function(x) { > x = "modified"; > return arguments[0]; > })("original") modified js> (function(x) { > delete arguments[0]; > arguments[0] = "modified"; > return x; > })("original") original js> (function(x) { > delete x; > var x = "modified"; > return arguments[0] > })("original") modified js> (function(x) { > Object.defineProperty(arguments, 0, {get:function(){return "modified"}}); > return arguments[0]; > })("original") modified js> (function(x) { > Object.defineProperty(arguments, 0, {get:function(){return "modified"}}); > return x; > })("original") original js> (function(x) { > Object.defineProperty(arguments, 0, {value:"modified"}); > return arguments[0]; > })("original") modified js> (function(x) { > Object.defineProperty(arguments, 0, {value:"modified"}); > return x; > })("original") modified js> (function() { for (var i in arguments) print(i); })('a','b','c') 0 1 2 js> (function() { > arguments.a = 1; > Object.defineProperty(arguments, 'b', {value:2, enumerable:true}); > Object.defineProperty(arguments, 'c', {value:3, enumerable:false}); > Object.defineProperty(arguments, 0, {enumerable:false}); > for (var p in arguments) print(p); > })('hi') a b js> (function() { return Object.getOwnPropertyDescriptor(arguments, 0) === undefined })() true js> (function() { return Object.getOwnPropertyDescriptor(arguments, 0).toSource(); })("a") ({value:"a", writable:true, enumerable:true, configurable:true}) js> (function(x) { > Object.defineProperty(arguments, 0, {enumerable:false}); > return Object.getOwnPropertyDescriptor(arguments, 0).enumerable; > })("original") false js> (function() { > Object.defineProperty(arguments, 0, {value:2, writable:false}); > arguments[0] = 3; > return arguments[0]; > })(1); 2 htmlunit-core-js-2.8/rhino/testsrc/doctests/array.isarray.doctest0000644000175000017500000000071611255674656025250 0ustar cavedoncavedonjs> Array.isArray; function isArray() { [native code for Array.isArray, arity=1] } js> Array.isArray() false js> Array.isArray(undefined); false js> Array.isArray(null); false js> Array.isArray(true); false js> Array.isArray(1); false js> Array.isArray('hello'); false js> Array.isArray({}); false js> Array.isArray(function(){}) false js> (function() { print(Array.isArray(arguments)) })() false js> Array.isArray([]) true js> Array.isArray(new Array()) true htmlunit-core-js-2.8/rhino/testsrc/doctests/object.freeze.doctest0000644000175000017500000000146011321335670025163 0ustar cavedoncavedonjs> load('testsrc/doctests/util.js'); js> Object.freeze; function freeze() { [native code for Object.freeze, arity=1] } js> [undefined, null, true, 1, 'hello'].forEach(function(value) { > expectTypeError(function() { Object.freeze(value) }) > }) js> expectTypeError(function() { Object.freeze() }) js> var x = {} js> var y = Object.freeze(x) js> x === y true js> var obj = Object.defineProperty({}, 'a', {configurable:true, writable:true}) js> var _ = Object.freeze(obj) js> var a = Object.getOwnPropertyDescriptor(obj, 'a'); js> a.configurable false js> a.writable false js> Object.isExtensible(obj) false js> Object.isFrozen(obj) true js> var _ = Object.freeze([]) js> var _ = Object.freeze({}) js> var _ = Object.freeze(function(){}) js> var _ = Object.freeze(/a/) js> var _ = Object.freeze(RegExp) htmlunit-core-js-2.8/rhino/testsrc/doctests/object.defineproperty.doctest0000644000175000017500000001750711255674656026773 0ustar cavedoncavedonjs> load('testsrc/doctests/util.js'); js> Object.defineProperty function defineProperty() { [native code for Object.defineProperty, arity=3] } js> expectTypeError(function() { Object.defineProperty() }); js> expectTypeError(function() { Object.defineProperty({}) }); js> expectTypeError(function() { Object.defineProperty({}, 'p') }); js> [undefined, null, true, 1, 'hello'].forEach(function(value) { > expectTypeError(function() { Object.defineProperty(value, 'p', {}) }) > }) js> Object.defineProperty({}, 'p', {value:1}).p 1 js> var obj = {} js> Object.defineProperty(obj, 'a', { > value: 1, > enumerable: false, > writable: false, > configurable: false > }) [object Object] js> for (var p in obj) print(p); // check it has no enumerable properties js> obj.a = 2; obj.a; // check that the property is not writable 1 js> delete obj.a; obj.a // check that the property is not deletable 1 js> var define = Object.defineProperty; js> var describe = Object.getOwnPropertyDescriptor; js> // when define new property with empty descriptor then default values are used for the descriptor js> var obj = define({}, 'a', {}); js> describe(obj, 'a').toSource() ({value:undefined, writable:false, enumerable:false, configurable:false}) js> // when define new property with data descriptor then those values are used for the descriptor js> var obj = define({}, 'a', { value: 2, writable: true }); js> var {value:v, writable:w} = describe(obj, 'a'); [v, w].toSource(); [2, true] js> obj.a 2 js> // when define new property with accessor descriptor then those values are used for the descriptor js> var obj = define({}, 'a', { get: function() { return 3; }, set: function(value) {} }); js> var {get:g, set:s} = describe(obj, 'a'); [g, s].toSource(); [(function () {return 3;}), (function (value) {})] js> obj.a 3 js> // when define existing property with empty descriptor then descriptor is left unchanged js> var descriptor = {value:1, writable:true, enumerable:true, configurable:true}; js> var obj = define({}, 'a', descriptor); js> var obj = define(obj, 'a', {}); js> describe(obj, 'a').toSource() ({value:1, writable:true, enumerable:true, configurable:true}) js> // when define existing property with same descriptor then descriptor is left unchanged js> var descriptor = {value:1, writable:true, enumerable:true, configurable:true}; js> var obj = define({}, 'a', descriptor); js> var obj = define(obj, 'a', descriptor); js> describe(obj, 'a').toSource() ({value:1, writable:true, enumerable:true, configurable:true}) js> // may not change configurable from false to true js> expectTypeError(function() { > var obj = define({}, 'a', {configurable : false}); > define(obj, 'a', {configurable : true}); > }); js> // may not change enumerable when configurable is false js> expectTypeError(function() { > var obj = define({}, 'a', {enumerable : true, configurable:false}); > define(obj, 'a', {enumerable : false}); > }); js> // may not change writable from false to true when configurable is false js> expectTypeError(function() { > var obj = define({}, 'a', {writable : false, configurable: false}); > define(obj, 'a', {writable : true}); > }); js> // may not change value when writable is false js> expectTypeError(function() { > var obj = define({}, 'a', {value : 1, writable:false}); > define(obj, 'a', {value : 2}); > }); js> // may not change getter when configurable is false js> expectTypeError(function() { > var obj = define({}, 'a', {get: function() { return 1 }, configurable:false}); > define(obj, 'a', {get: function() { return 1 }}); > }); js> // may not change setter when configurable is false js> expectTypeError(function() { > var obj = define({}, 'a', {set: function(val) {}, configurable:false}); > define(obj, 'a', {set: function(val) {}}); > }); js> // may not change from data property to accessor property when configurable is false js> expectTypeError(function() { > var obj = define({}, 'a', {value : 1, configurable:false}); > define(obj, 'a', {get : function() { return 1 }}); > }); js> // may not change from accessor property to data property when configurable is false js> expectTypeError(function() { > var obj = define({}, 'a', {get : function() { return 1 }, configurable:false}); > define(obj, 'a', {value : 1}); > }); js> // can change writable from true to false when configurable is false js> var obj = define({}, 'a', {writable:true, configurable:false}); js> var obj = define(obj, 'a', {writable:false}); js> // can set enumerable to the same value when configurable is false js> var obj = define({}, 'a', {enumerable:true, configurable:false}); js> var obj = define(obj, 'a', {enumerable:true}); js> // can change from data property to accessor property when configurable is true js> var obj = define({}, 'a', {value : 1, configurable: true}); js> var obj = define(obj, 'a', {get : function() { return 4 }}); js> obj.a 4 js> describe(obj, 'a').toSource() ({enumerable:false, configurable:true, get:(function () {return 4;})}) js> // can change from accessor property to data property when configurable is true js> var obj = define({}, 'a', {get : function() { return 2 }, configurable:true}); js> var obj = define(obj, 'a', {value : 5}); js> obj.a 5 js> describe(obj, 'a').toSource() ({value:5, writable:false, enumerable:false, configurable:true}) js> // can change enumerable and writable to true when configurable is true js> var obj = define({}, 'a', {writable : false, enumerable : false, configurable:true}); js> var obj = define(obj, 'a', {writable : true, enumerable : true, configurable:true}); js> // can change the value if writable is true js> var obj = define({}, 'a', {value:6, writable:true}) js> obj.a 6 js> var obj = define(obj, 'a', {value:7}) js> obj.a 7 js> // defining a new property should fail loudly when object is not extensible js> var obj = Object.preventExtensions({}); js> expectTypeError(function() { define(obj, 'a', {value:1}) }) js> // defining new property should succeed when object is extensible js> var obj = {} js> Object.isExtensible(obj); true js> obj.a = 8; obj.a 8 js> // changing existing property should succeed when object is not extensible js> var obj = define({}, 'a', {value:1, writable:true}); js> var obj = Object.preventExtensions(obj); js> obj.a = 9; obj.a 9 js> // defined getters and setters must be functions js> expectTypeError(function() { define({}, 'a', {get:1}); }) js> expectTypeError(function() { define({}, 'a', {set:1}); }) js> // make sure defineProperty works properly with numbers as ids js> Object.defineProperty({}, 0, {value:1, enumerable:true})['0'] 1 js> // make sure defineProperty works properly with arrays js> Object.defineProperty([], 0, {value:1, enumerable:true})[0] 1 js> // make sure defineProperty works properly with arrays js> Object.defineProperty([], 'a', {value:1, enumerable:true})['a'] 1 js> // make sure defineProperty updates length properly for arrays js> Object.defineProperty([], 0, {value:1}).length 1 js> // make sure that getters and setters are actually used to get and set property js> Object.defineProperty({}, 'a', {get:function() { return "get called"; }}).a get called js> Object.defineProperty({}, 'a', {set:function(val) { print("set called with "+val); }}).a = 1; undefined; set called with 1 js> // make sure defineProperty works for builtin properties js> Object.defineProperty(JSON, 'stringify', {value:1}).stringify 1 js> Object.defineProperty(JSON, 'parse', {get:function() {print('do get'); return undefined}}).parse do get js> // an accessor property without a setter behaves as if the setter were undefined js> // and thus the setter can be set to undefined even when configurable is false js> var obj = Object.defineProperty({}, 'a', {get:function(){return 1}}) js> var _ = Object.defineProperty(obj, 'a', {set:undefined}) js> htmlunit-core-js-2.8/rhino/testsrc/doctests/whitespace.doctest0000644000175000017500000000056311255674656024615 0ustar cavedoncavedonjs> load('testsrc/doctests/util.js') js> var bom = String.fromCharCode(0xFEFF); js> eval(bom); js> var _ = eval("(function(){return"+bom+"1;})"); js> expectError(function() { > eval("i"+bom+"f (false);"); > }, SyntaxError); js> parseInt(bom+"1") 1 js> parseFloat(bom+"1.5"); 1.5 js> (bom+"abc"+bom).trim().length 3 js> /\s/.test(bom) true js> (bom+"1"+bom) * 1 1 htmlunit-core-js-2.8/rhino/testsrc/doctests/477233.doctest0000644000175000017500000000066411222460357023215 0ustar cavedoncavedonjs> var xml = > > One > > > Two > > ; js> var atom = new Namespace("http://www.w3.org/2005/Atom"); js> print(xml.atom::entry.(atom::title == "One")); One htmlunit-core-js-2.8/rhino/testsrc/doctests/object.seal.doctest0000644000175000017500000000111111222460357024621 0ustar cavedoncavedonjs> load('testsrc/doctests/util.js'); js> Object.seal; function seal() { [native code for Object.seal, arity=1] } js> [undefined, null, true, 1, 'hello'].forEach(function(value) { > expectTypeError(function() { Object.seal(value) }) > }) js> expectTypeError(function() { Object.seal() }) js> var x = {} js> var y = Object.seal(x) js> x === y true js> var obj = Object.defineProperty({}, 'a', {configurable:true}) js> var _ = Object.seal(obj) js> Object.getOwnPropertyDescriptor(obj, 'a').configurable false js> Object.isExtensible(obj) false js> Object.isSealed(obj) true htmlunit-core-js-2.8/rhino/testsrc/doctests/Matrix.doctest0000644000175000017500000000106211111054626023674 0ustar cavedoncavedonTest of Matrix example. 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 htmlunit-core-js-2.8/rhino/testsrc/doctests/function.bind.doctest0000644000175000017500000000236311255674656025221 0ustar cavedoncavedonjs> load('testsrc/doctests/util.js'); js> Function.prototype.bind function bind() { [native code for Function.bind, arity=1] } js> expectTypeError(function() { > Function.prototype.bind.call({}) > }); js> typeof (function(){}).bind({}) function js> function Val() { > this.val = 0; > this.change = function(newVal) { this.val = newVal }; > this.valueOf = function() { return 1; } > } js> var a = new Val(), b = new Val(); js> a.change.bind(b)(1) js> [a.val, b.val].toSource() [0, 1] js> new (Val.bind({})) instanceof Val true js> new Val() instanceof Val.bind({}) true js> function add(a, b) { return a + b } js> var add1 = add.bind({}, 1) js> add1(2) 3 js> var add5 = add.bind({}, 5) js> add5(1) 6 js> add1(3) 4 js> function LazyAdd(a, b) { this.result = function() { return a + b } } js> var LazyAdd1 = LazyAdd.bind({}, 1) js> new LazyAdd1(4).result() 5 js> add1.length 1 js> Object.isExtensible(add1) true js> Object.getPrototypeOf(add1) === Function.prototype true js> expectTypeError(function() { > var x = add1.caller > }) js> expectTypeError(function() { > add1.caller = 1 > }) js> expectTypeError(function() { > var x = add1.arguments > }) js> expectTypeError(function() { > add1.arguments = 1 > }) htmlunit-core-js-2.8/rhino/testsrc/doctests/xmlOptions.doctest0000755000175000017500000000050611222460357024616 0ustar cavedoncavedonjs> var x = 1; js> x 1 js> var xmlLib = org.mozilla.javascript.xml.XMLLib.extractFromScope(this); js> xmlLib.isPrettyPrinting(); true js> xmlLib.setPrettyPrinting(false); js> xmlLib.isPrettyPrinting(); false js> x 1htmlunit-core-js-2.8/rhino/testsrc/doctests/test2.doctest0000644000175000017500000000031510776623544023512 0ustar cavedoncavedonjs> a = [] js> a[0] = 10 10 js> a[1] = 11 11 js> a[3] = 13 13 js> a[4] = 14 14 js> a[5] = 15 15 js> a.reverse() 15,14,13,,11,10 js> a.reverse() 10,11,,13,14,15 js> a.concat([16,17]) 10,11,,13,14,15,16,17 htmlunit-core-js-2.8/rhino/testsrc/doctests/object.create.doctest0000644000175000017500000000172411255674656025171 0ustar cavedoncavedonjs> load('testsrc/doctests/util.js'); js> Object.create; function create() { [native code for Object.create, arity=2] } js> expectTypeError(function() { Object.create() }); js> [undefined, true, 1, 'hello'].forEach(function(value) { > expectTypeError(function() { Object.create(value) }) > }) js> expectTypeError(function() { Object.create({}, null) }) js> var obj = Object.create({}); js> var obj = Object.create({}, {}); js> var obj = Object.create({}, undefined); js> var orig = {} js> var next = Object.create(orig); js> Object.getPrototypeOf(next) === orig; true js> var obj = Object.create({}, {a: {value:1}, b: {value:2}}); js> [obj.a, obj.b].toSource(); [1, 2] js> var orig = {a:1}; js> var obj = Object.create(orig, {a:{value:2}, b:{value:3}}); js> [obj.a, obj.b].toSource() [2, 3] js> expectTypeError(function() { Object.create({}, {b: {value:1}, c:1}) }); js> var obj = Object.create(null, {a: {value:1}}) js> Object.getPrototypeOf(obj) === null true htmlunit-core-js-2.8/rhino/testsrc/doctests/tail-call-in-try.doctest0000644000175000017500000000052610776623544025537 0ustar cavedoncavedon// Fix bug reported in newsgroup: // Tail call optimization was interfering with catching exceptions. // The following program should print 7, but was resulting in an uncaught // exception. js> function g() { > throw 3; > } js> function f() { > try { > return g(); > } catch (e) { > return 7; > } > } js> f() 7htmlunit-core-js-2.8/rhino/testsrc/build.xml0000644000175000017500000001531411255674656021063 0ustar cavedoncavedon htmlunit-core-js-2.8/rhino/testsrc/opt0.tests0000644000175000017500000014726511321335670021203 0ustar cavedoncavedone4x/Expressions/11.1.1.js e4x/Expressions/11.1.2.js e4x/Expressions/11.1.3.js e4x/Expressions/11.1.4-06.js e4x/Expressions/11.1.4-07.js e4x/Expressions/11.1.5.js e4x/Expressions/11.2.1.js e4x/Expressions/11.2.2.js e4x/Expressions/11.2.3.js e4x/Expressions/11.2.4.js e4x/Expressions/11.3.1.js e4x/Expressions/11.3.2.js e4x/Expressions/11.4.1.js e4x/Expressions/11.5.1.js e4x/Expressions/11.6.3.js e4x/Expressions/regress-301545.js e4x/Expressions/regress-302531.js e4x/Expressions/regress-340024.js e4x/GC/regress-292455.js e4x/GC/regress-313952-01.js e4x/GC/regress-324117.js e4x/Namespace/13.2.1.js e4x/Namespace/13.2.2.js e4x/Namespace/13.2.5.js e4x/Namespace/regress-283972.js e4x/Namespace/regress-292863.js e4x/Namespace/regress-350442.js e4x/QName/13.3.1.js e4x/QName/13.3.2.js e4x/QName/13.3.5.js e4x/QName/regress-373595-01.js e4x/QName/regress-373595-02.js e4x/QName/regress-373595-03.js e4x/Regress/regress-263935.js e4x/Regress/regress-263936.js e4x/Regress/regress-264369.js e4x/Regress/regress-271545.js e4x/Regress/regress-277650.js e4x/Regress/regress-277664.js e4x/Regress/regress-277683.js e4x/Regress/regress-277935.js e4x/Regress/regress-283349.js e4x/Regress/regress-290056.js e4x/Regress/regress-301573.js e4x/Regress/regress-301596.js e4x/Regress/regress-301692.js e4x/Regress/regress-313799.js e4x/Regress/regress-325425.js e4x/Regress/regress-327691-01.js e4x/Regress/regress-327691-02.js e4x/Regress/regress-327697.js e4x/Regress/regress-328249.js e4x/Regress/regress-329257.js e4x/Regress/regress-331664.js e4x/Regress/regress-350206-1.js e4x/Regress/regress-350206.js e4x/Regress/regress-352103.js e4x/Regress/regress-354145-01.js e4x/Regress/regress-354145-02.js e4x/Regress/regress-354145-03.js e4x/Regress/regress-354145-04.js e4x/Regress/regress-354145-05.js e4x/Regress/regress-354145-07.js e4x/Regress/regress-355474-02.js e4x/Regress/regress-356238-01.js e4x/Regress/regress-369032.js e4x/Regress/regress-369536.js e4x/Regress/regress-372564.js e4x/Regress/regress-374106.js e4x/Regress/regress-374112.js e4x/Regress/regress-374116.js e4x/Regress/regress-374160.js e4x/Regress/regress-378492.js e4x/Regress/regress-407323.js e4x/Statements/12.1.js e4x/Statements/12.2.js e4x/Statements/12.3-01.js e4x/TypeConversion/10.1.2.js e4x/TypeConversion/10.3.1.js e4x/TypeConversion/10.3.js e4x/TypeConversion/10.4.1.js e4x/TypeConversion/10.4.js e4x/Types/9.1.1.1.js e4x/Types/9.1.1.2.js e4x/Types/9.1.1.3.js e4x/Types/9.1.1.6.js e4x/Types/9.2.1.1.js e4x/Types/9.2.1.2.js e4x/Types/9.2.1.8.js e4x/XML/13.4.1.js e4x/XML/13.4.2.js e4x/XML/13.4.3.10.js e4x/XML/13.4.4.12-1.js e4x/XML/13.4.4.12.js e4x/XML/13.4.4.13.js e4x/XML/13.4.4.14.js e4x/XML/13.4.4.15.js e4x/XML/13.4.4.16.js e4x/XML/13.4.4.18.js e4x/XML/13.4.4.19.js e4x/XML/13.4.4.2.js e4x/XML/13.4.4.20.js e4x/XML/13.4.4.21.js e4x/XML/13.4.4.23.js e4x/XML/13.4.4.24.js e4x/XML/13.4.4.25.js e4x/XML/13.4.4.27.js e4x/XML/13.4.4.3.js e4x/XML/13.4.4.30.js e4x/XML/13.4.4.31.js e4x/XML/13.4.4.32-01.js e4x/XML/13.4.4.32.js e4x/XML/13.4.4.33.js e4x/XML/13.4.4.34.js e4x/XML/13.4.4.35.js e4x/XML/13.4.4.36.js e4x/XML/13.4.4.37.js e4x/XML/13.4.4.38.js e4x/XML/13.4.4.39.js e4x/XML/13.4.4.4.js e4x/XML/13.4.4.40.js e4x/XML/13.4.4.5.js e4x/XML/13.4.4.7.js e4x/XML/13.4.4.8.js e4x/XML/regress-291930.js e4x/XML/regress-324688.js e4x/XML/regress-336921.js e4x/XMLList/13.5.1.js e4x/XMLList/13.5.2.js e4x/XMLList/13.5.4.10.js e4x/XMLList/13.5.4.11.js e4x/XMLList/13.5.4.12.js e4x/XMLList/13.5.4.13.js e4x/XMLList/13.5.4.14.js e4x/XMLList/13.5.4.15.js e4x/XMLList/13.5.4.16.js e4x/XMLList/13.5.4.17.js e4x/XMLList/13.5.4.18.js e4x/XMLList/13.5.4.19.js e4x/XMLList/13.5.4.2.js e4x/XMLList/13.5.4.20.js e4x/XMLList/13.5.4.21.js e4x/XMLList/13.5.4.22.js e4x/XMLList/13.5.4.3.js e4x/XMLList/13.5.4.4.js e4x/XMLList/13.5.4.5.js e4x/XMLList/13.5.4.6.js e4x/XMLList/13.5.4.7.js e4x/XMLList/13.5.4.8.js e4x/XMLList/13.5.4.9.js e4x/decompilation/regress-349814.js e4x/decompilation/regress-349815.js e4x/decompilation/regress-349822.js e4x/decompilation/regress-349956.js e4x/decompilation/regress-355474-01.js e4x/decompilation/regress-373678.js e4x/extensions/regress-305335.js e4x/extensions/regress-321547.js e4x/extensions/regress-327534.js e4x/extensions/regress-327897.js e4x/extensions/regress-354145-06.js e4x/extensions/regress-354151-01.js ecma/Array/15.4-1.js ecma/Array/15.4-2.js ecma/Array/15.4.1.1.js ecma/Array/15.4.1.2.js ecma/Array/15.4.1.3.js ecma/Array/15.4.1.js ecma/Array/15.4.2.1-1.js ecma/Array/15.4.2.1-2.js ecma/Array/15.4.2.1-3.js ecma/Array/15.4.2.2-1.js ecma/Array/15.4.2.2-2.js ecma/Array/15.4.2.3.js ecma/Array/15.4.3.2.js ecma/Array/15.4.4.1.js ecma/Array/15.4.4.2.js ecma/Array/15.4.4.3-1.js ecma/Array/15.4.4.4-1.js ecma/Array/15.4.4.4-2.js ecma/Array/15.4.4.5-1.js ecma/Array/15.4.4.5-2.js ecma/Array/15.4.4.js ecma/Array/15.4.5.1-2.js ecma/Array/15.4.5.2-1.js ecma/Array/15.4.5.2-2.js ecma/Boolean/15.6.2.js ecma/Boolean/15.6.3.1-1.js ecma/Boolean/15.6.3.1-2.js ecma/Boolean/15.6.3.1.js ecma/Boolean/15.6.4-1.js ecma/Boolean/15.6.4.1.js ecma/Boolean/15.6.4.2-2.js ecma/Boolean/15.6.4.2-3.js ecma/Boolean/15.6.4.2-4-n.js ecma/Boolean/15.6.4.3-1.js ecma/Boolean/15.6.4.3-2.js ecma/Boolean/15.6.4.3-3.js ecma/Boolean/15.6.4.3-4-n.js ecma/Boolean/15.6.4.3.js ecma/Boolean/15.6.4.js ecma/Date/15.9.1.1-1.js ecma/Date/15.9.1.1-2.js ecma/Date/15.9.1.13-1.js ecma/Date/15.9.2.1.js ecma/Date/15.9.2.2-1.js ecma/Date/15.9.2.2-2.js ecma/Date/15.9.2.2-3.js ecma/Date/15.9.2.2-5.js ecma/Date/15.9.2.2-6.js ecma/Date/15.9.3.1-2.js ecma/Date/15.9.3.1-3.js ecma/Date/15.9.3.1-4.js ecma/Date/15.9.3.1-5.js ecma/Date/15.9.3.2-2.js ecma/Date/15.9.3.2-3.js ecma/Date/15.9.3.2-4.js ecma/Date/15.9.3.2-5.js ecma/Date/15.9.3.8-1.js ecma/Date/15.9.3.8-2.js ecma/Date/15.9.3.8-3.js ecma/Date/15.9.3.8-4.js ecma/Date/15.9.3.8-5.js ecma/Date/15.9.4.2.js ecma/Date/15.9.4.3.js ecma/Date/15.9.5.1.js ecma/Date/15.9.5.10-1.js ecma/Date/15.9.5.10-10.js ecma/Date/15.9.5.10-11.js ecma/Date/15.9.5.10-12.js ecma/Date/15.9.5.10-13.js ecma/Date/15.9.5.10-4.js ecma/Date/15.9.5.10-5.js ecma/Date/15.9.5.10-6.js ecma/Date/15.9.5.10-7.js ecma/Date/15.9.5.10-8.js ecma/Date/15.9.5.10-9.js ecma/Date/15.9.5.11-1.js ecma/Date/15.9.5.11-3.js ecma/Date/15.9.5.11-4.js ecma/Date/15.9.5.11-5.js ecma/Date/15.9.5.11-6.js ecma/Date/15.9.5.11-7.js ecma/Date/15.9.5.12-1.js ecma/Date/15.9.5.12-3.js ecma/Date/15.9.5.12-4.js ecma/Date/15.9.5.12-5.js ecma/Date/15.9.5.12-6.js ecma/Date/15.9.5.12-7.js ecma/Date/15.9.5.12-8.js ecma/Date/15.9.5.13-1.js ecma/Date/15.9.5.13-2.js ecma/Date/15.9.5.13-3.js ecma/Date/15.9.5.13-4.js ecma/Date/15.9.5.13-5.js ecma/Date/15.9.5.13-6.js ecma/Date/15.9.5.13-7.js ecma/Date/15.9.5.13-8.js ecma/Date/15.9.5.14.js ecma/Date/15.9.5.15.js ecma/Date/15.9.5.16.js ecma/Date/15.9.5.17.js ecma/Date/15.9.5.19.js ecma/Date/15.9.5.2-2-n.js ecma/Date/15.9.5.2.js ecma/Date/15.9.5.20.js ecma/Date/15.9.5.21-1.js ecma/Date/15.9.5.21-2.js ecma/Date/15.9.5.21-3.js ecma/Date/15.9.5.21-4.js ecma/Date/15.9.5.21-5.js ecma/Date/15.9.5.21-6.js ecma/Date/15.9.5.21-7.js ecma/Date/15.9.5.21-8.js ecma/Date/15.9.5.22-2.js ecma/Date/15.9.5.22-3.js ecma/Date/15.9.5.22-4.js ecma/Date/15.9.5.22-5.js ecma/Date/15.9.5.22-6.js ecma/Date/15.9.5.22-7.js ecma/Date/15.9.5.22-8.js ecma/Date/15.9.5.23-1.js ecma/Date/15.9.5.23-10.js ecma/Date/15.9.5.23-11.js ecma/Date/15.9.5.23-12.js ecma/Date/15.9.5.23-13.js ecma/Date/15.9.5.23-14.js ecma/Date/15.9.5.23-15.js ecma/Date/15.9.5.23-16.js ecma/Date/15.9.5.23-17.js ecma/Date/15.9.5.23-18.js ecma/Date/15.9.5.23-2.js ecma/Date/15.9.5.23-3-n.js ecma/Date/15.9.5.23-4.js ecma/Date/15.9.5.23-5.js ecma/Date/15.9.5.23-6.js ecma/Date/15.9.5.23-7.js ecma/Date/15.9.5.23-8.js ecma/Date/15.9.5.23-9.js ecma/Date/15.9.5.24-1.js ecma/Date/15.9.5.24-2.js ecma/Date/15.9.5.24-3.js ecma/Date/15.9.5.24-4.js ecma/Date/15.9.5.24-5.js ecma/Date/15.9.5.24-6.js ecma/Date/15.9.5.24-7.js ecma/Date/15.9.5.24-8.js ecma/Date/15.9.5.25-1.js ecma/Date/15.9.5.26-1.js ecma/Date/15.9.5.27-1.js ecma/Date/15.9.5.28-1.js ecma/Date/15.9.5.29-1.js ecma/Date/15.9.5.3-2.js ecma/Date/15.9.5.30-1.js ecma/Date/15.9.5.31-1.js ecma/Date/15.9.5.32-1.js ecma/Date/15.9.5.33-1.js ecma/Date/15.9.5.34-1.js ecma/Date/15.9.5.35-1.js ecma/Date/15.9.5.36-1.js ecma/Date/15.9.5.36-2.js ecma/Date/15.9.5.36-4.js ecma/Date/15.9.5.36-5.js ecma/Date/15.9.5.36-6.js ecma/Date/15.9.5.36-7.js ecma/Date/15.9.5.37-2.js ecma/Date/15.9.5.37-3.js ecma/Date/15.9.5.37-4.js ecma/Date/15.9.5.37-5.js ecma/Date/15.9.5.4-1.js ecma/Date/15.9.5.4-2-n.js ecma/Date/15.9.5.6.js ecma/Date/15.9.5.7.js ecma/Date/15.9.5.8.js ecma/Date/15.9.5.9.js ecma/Date/15.9.5.js ecma/ExecutionContexts/10.1.3-1.js ecma/ExecutionContexts/10.1.3-2.js ecma/ExecutionContexts/10.1.3.js ecma/ExecutionContexts/10.1.4-1.js ecma/ExecutionContexts/10.1.4-10.js ecma/ExecutionContexts/10.1.4-3.js ecma/ExecutionContexts/10.1.4-4.js ecma/ExecutionContexts/10.1.4-5.js ecma/ExecutionContexts/10.1.4-6.js ecma/ExecutionContexts/10.1.4-7.js ecma/ExecutionContexts/10.1.4-8.js ecma/ExecutionContexts/10.1.5-1.js ecma/ExecutionContexts/10.1.5-2.js ecma/ExecutionContexts/10.1.5-3.js ecma/ExecutionContexts/10.1.5-4.js ecma/ExecutionContexts/10.1.8-2.js ecma/ExecutionContexts/10.1.8-3.js ecma/ExecutionContexts/10.2.1.js ecma/ExecutionContexts/10.2.2-1.js ecma/ExecutionContexts/10.2.2-2.js ecma/ExecutionContexts/10.2.3-1.js ecma/ExecutionContexts/10.2.3-2.js ecma/Expressions/11.1.1.js ecma/Expressions/11.10-1.js ecma/Expressions/11.10-2.js ecma/Expressions/11.10-3.js ecma/Expressions/11.12-1.js ecma/Expressions/11.12-2-n.js ecma/Expressions/11.12-3.js ecma/Expressions/11.12-4.js ecma/Expressions/11.13.1.js ecma/Expressions/11.13.2-1.js ecma/Expressions/11.13.2-2.js ecma/Expressions/11.13.2-3.js ecma/Expressions/11.13.2-4.js ecma/Expressions/11.13.2-5.js ecma/Expressions/11.14-1.js ecma/Expressions/11.2.1-1.js ecma/Expressions/11.2.1-2.js ecma/Expressions/11.2.1-3-n.js ecma/Expressions/11.2.1-4-n.js ecma/Expressions/11.2.1-5.js ecma/Expressions/11.2.2-1-n.js ecma/Expressions/11.2.2-1.js ecma/Expressions/11.2.2-10-n.js ecma/Expressions/11.2.2-11.js ecma/Expressions/11.2.2-2-n.js ecma/Expressions/11.2.2-3-n.js ecma/Expressions/11.2.2-4-n.js ecma/Expressions/11.2.2-5-n.js ecma/Expressions/11.2.2-6-n.js ecma/Expressions/11.2.2-7-n.js ecma/Expressions/11.2.2-8-n.js ecma/Expressions/11.2.2-9-n.js ecma/Expressions/11.2.3-1.js ecma/Expressions/11.2.3-2-n.js ecma/Expressions/11.2.3-3-n.js ecma/Expressions/11.2.3-4-n.js ecma/Expressions/11.2.3-5.js ecma/Expressions/11.3.1.js ecma/Expressions/11.3.2.js ecma/Expressions/11.4.2.js ecma/Expressions/11.4.3.js ecma/Expressions/11.4.4.js ecma/Expressions/11.4.5.js ecma/Expressions/11.4.6.js ecma/Expressions/11.4.8.js ecma/Expressions/11.4.9.js ecma/Expressions/11.5.1.js ecma/Expressions/11.5.2.js ecma/Expressions/11.5.3.js ecma/Expressions/11.6.1-1.js ecma/Expressions/11.6.1-2.js ecma/Expressions/11.6.1-3.js ecma/Expressions/11.6.2-1.js ecma/Expressions/11.6.3.js ecma/Expressions/11.7.1.js ecma/Expressions/11.7.2.js ecma/Expressions/11.8.1.js ecma/Expressions/11.8.2.js ecma/Expressions/11.8.3.js ecma/Expressions/11.9.2.js ecma/Expressions/11.9.3.js ecma/FunctionObjects/15.3.1.1-1.js ecma/FunctionObjects/15.3.1.1-2.js ecma/FunctionObjects/15.3.1.1-3.js ecma/FunctionObjects/15.3.2.1-1.js ecma/FunctionObjects/15.3.2.1-2.js ecma/FunctionObjects/15.3.2.1-3.js ecma/FunctionObjects/15.3.3.1-2.js ecma/FunctionObjects/15.3.3.1-3.js ecma/FunctionObjects/15.3.3.1-4.js ecma/FunctionObjects/15.3.3.2.js ecma/FunctionObjects/15.3.4-1.js ecma/FunctionObjects/15.3.4.1.js ecma/FunctionObjects/15.3.4.js ecma/FunctionObjects/15.3.5-1.js ecma/FunctionObjects/15.3.5-2.js ecma/FunctionObjects/15.3.5.1.js ecma/FunctionObjects/15.3.5.3.js ecma/GlobalObject/15.1-1-n.js ecma/GlobalObject/15.1-2-n.js ecma/GlobalObject/15.1.1.1.js ecma/GlobalObject/15.1.1.2.js ecma/GlobalObject/15.1.2.1-2.js ecma/GlobalObject/15.1.2.2-2.js ecma/GlobalObject/15.1.2.3-2.js ecma/GlobalObject/15.1.2.5-2.js ecma/GlobalObject/15.1.2.5-3.js ecma/LexicalConventions/7.1-1.js ecma/LexicalConventions/7.1-2.js ecma/LexicalConventions/7.1-3.js ecma/LexicalConventions/7.2-1.js ecma/LexicalConventions/7.2-2-n.js ecma/LexicalConventions/7.2-3-n.js ecma/LexicalConventions/7.2-4-n.js ecma/LexicalConventions/7.2-5-n.js ecma/LexicalConventions/7.2-6.js ecma/LexicalConventions/7.3-1.js ecma/LexicalConventions/7.3-10.js ecma/LexicalConventions/7.3-11.js ecma/LexicalConventions/7.3-12.js ecma/LexicalConventions/7.3-13-n.js ecma/LexicalConventions/7.3-2.js ecma/LexicalConventions/7.3-3.js ecma/LexicalConventions/7.3-4.js ecma/LexicalConventions/7.3-5.js ecma/LexicalConventions/7.3-6.js ecma/LexicalConventions/7.3-8.js ecma/LexicalConventions/7.3-9.js ecma/LexicalConventions/7.4.1-1-n.js ecma/LexicalConventions/7.4.1-2-n.js ecma/LexicalConventions/7.4.1-3-n.js ecma/LexicalConventions/7.4.2-1-n.js ecma/LexicalConventions/7.4.2-10-n.js ecma/LexicalConventions/7.4.2-11-n.js ecma/LexicalConventions/7.4.2-12-n.js ecma/LexicalConventions/7.4.2-13-n.js ecma/LexicalConventions/7.4.2-14-n.js ecma/LexicalConventions/7.4.2-15-n.js ecma/LexicalConventions/7.4.2-16-n.js ecma/LexicalConventions/7.4.2-2-n.js ecma/LexicalConventions/7.4.2-3-n.js ecma/LexicalConventions/7.4.2-4-n.js ecma/LexicalConventions/7.4.2-5-n.js ecma/LexicalConventions/7.4.2-6-n.js ecma/LexicalConventions/7.4.2-7-n.js ecma/LexicalConventions/7.4.2-8-n.js ecma/LexicalConventions/7.4.3-1-n.js ecma/LexicalConventions/7.4.3-10-n.js ecma/LexicalConventions/7.4.3-11-n.js ecma/LexicalConventions/7.4.3-13-n.js ecma/LexicalConventions/7.4.3-15-n.js ecma/LexicalConventions/7.4.3-16-n.js ecma/LexicalConventions/7.4.3-2-n.js ecma/LexicalConventions/7.4.3-3-n.js ecma/LexicalConventions/7.4.3-4-n.js ecma/LexicalConventions/7.4.3-5-n.js ecma/LexicalConventions/7.4.3-6-n.js ecma/LexicalConventions/7.4.3-7-n.js ecma/LexicalConventions/7.4.3-8-n.js ecma/LexicalConventions/7.4.3-9-n.js ecma/LexicalConventions/7.5-1.js ecma/LexicalConventions/7.5-10-n.js ecma/LexicalConventions/7.5-2-n.js ecma/LexicalConventions/7.5-3-n.js ecma/LexicalConventions/7.5-4-n.js ecma/LexicalConventions/7.5-5-n.js ecma/LexicalConventions/7.5-6.js ecma/LexicalConventions/7.5-7.js ecma/LexicalConventions/7.5-8-n.js ecma/LexicalConventions/7.5-9-n.js ecma/LexicalConventions/7.6.js ecma/LexicalConventions/7.7.1.js ecma/LexicalConventions/7.7.2.js ecma/LexicalConventions/7.7.3-1.js ecma/LexicalConventions/7.7.3-2.js ecma/LexicalConventions/7.7.3.js ecma/LexicalConventions/7.7.4.js ecma/LexicalConventions/7.8.2-n.js ecma/Math/15.8-2-n.js ecma/Math/15.8-3-n.js ecma/Math/15.8.1.1-1.js ecma/Math/15.8.1.1-2.js ecma/Math/15.8.1.2-1.js ecma/Math/15.8.1.3-1.js ecma/Math/15.8.1.3-2.js ecma/Math/15.8.1.4-1.js ecma/Math/15.8.1.4-2.js ecma/Math/15.8.1.5-1.js ecma/Math/15.8.1.5-2.js ecma/Math/15.8.1.6-1.js ecma/Math/15.8.1.6-2.js ecma/Math/15.8.1.7-1.js ecma/Math/15.8.1.7-2.js ecma/Math/15.8.1.8-1.js ecma/Math/15.8.1.8-2.js ecma/Math/15.8.1.8-3.js ecma/Math/15.8.2.1.js ecma/Math/15.8.2.10.js ecma/Math/15.8.2.12.js ecma/Math/15.8.2.13.js ecma/Math/15.8.2.14.js ecma/Math/15.8.2.15.js ecma/Math/15.8.2.16.js ecma/Math/15.8.2.17.js ecma/Math/15.8.2.18.js ecma/Math/15.8.2.2.js ecma/Math/15.8.2.3.js ecma/Math/15.8.2.4.js ecma/Math/15.8.2.5.js ecma/Math/15.8.2.6.js ecma/Math/15.8.2.7.js ecma/Math/15.8.2.8.js ecma/Math/15.8.2.9.js ecma/Number/15.7.2.js ecma/Number/15.7.3.1-1.js ecma/Number/15.7.3.1-2.js ecma/Number/15.7.3.1-3.js ecma/Number/15.7.3.2-1.js ecma/Number/15.7.3.2-2.js ecma/Number/15.7.3.2-3.js ecma/Number/15.7.3.3-1.js ecma/Number/15.7.3.3-2.js ecma/Number/15.7.3.3-3.js ecma/Number/15.7.3.4-1.js ecma/Number/15.7.3.4-2.js ecma/Number/15.7.3.4-3.js ecma/Number/15.7.3.4-4.js ecma/Number/15.7.3.5-1.js ecma/Number/15.7.3.5-2.js ecma/Number/15.7.3.5-3.js ecma/Number/15.7.3.5-4.js ecma/Number/15.7.3.6-1.js ecma/Number/15.7.3.6-4.js ecma/Number/15.7.3.js ecma/Number/15.7.4-1.js ecma/Number/15.7.4.1.js ecma/Number/15.7.4.2-1.js ecma/Number/15.7.4.2-2-n.js ecma/Number/15.7.4.2-3-n.js ecma/Number/15.7.4.2-4.js ecma/Number/15.7.4.3-1.js ecma/Number/15.7.4.3-2.js ecma/ObjectObjects/15.2.1.2.js ecma/ObjectObjects/15.2.2.1.js ecma/ObjectObjects/15.2.2.2.js ecma/ObjectObjects/15.2.3.1-1.js ecma/ObjectObjects/15.2.3.1-2.js ecma/ObjectObjects/15.2.3.1-3.js ecma/ObjectObjects/15.2.3.1-4.js ecma/ObjectObjects/15.2.3.js ecma/ObjectObjects/15.2.4.1.js ecma/ObjectObjects/15.2.4.2.js ecma/ObjectObjects/15.2.4.3.js ecma/SourceText/6-1.js ecma/SourceText/6-2.js ecma/Statements/12.10-1.js ecma/Statements/12.10.js ecma/Statements/12.5-1.js ecma/Statements/12.5-2.js ecma/Statements/12.6.2-1.js ecma/Statements/12.6.2-2.js ecma/Statements/12.6.2-4.js ecma/Statements/12.6.2-5.js ecma/Statements/12.6.2-6.js ecma/Statements/12.6.2-7.js ecma/Statements/12.6.2-8.js ecma/Statements/12.6.2-9-n.js ecma/Statements/12.6.3-1.js ecma/Statements/12.6.3-10.js ecma/Statements/12.6.3-11.js ecma/Statements/12.6.3-12.js ecma/Statements/12.6.3-19.js ecma/Statements/12.6.3-2.js ecma/Statements/12.6.3-3.js ecma/Statements/12.6.3-4.js ecma/Statements/12.6.3-5-n.js ecma/Statements/12.6.3-6-n.js ecma/Statements/12.6.3-7-n.js ecma/Statements/12.6.3-9-n.js ecma/Statements/12.7-1-n.js ecma/Statements/12.8-1-n.js ecma/Statements/12.9-1-n.js ecma/String/15.5.1.js ecma/String/15.5.2.js ecma/String/15.5.3.1-1.js ecma/String/15.5.3.1-2.js ecma/String/15.5.3.1-3.js ecma/String/15.5.3.1-4.js ecma/String/15.5.3.2-1.js ecma/String/15.5.3.2-2.js ecma/String/15.5.3.2-3.js ecma/String/15.5.3.js ecma/String/15.5.4.1.js ecma/String/15.5.4.10-1.js ecma/String/15.5.4.11-1.js ecma/String/15.5.4.11-3.js ecma/String/15.5.4.11-4.js ecma/String/15.5.4.11-6.js ecma/String/15.5.4.12-2.js ecma/String/15.5.4.12-3.js ecma/String/15.5.4.2-1.js ecma/String/15.5.4.2-2-n.js ecma/String/15.5.4.2-3.js ecma/String/15.5.4.2.js ecma/String/15.5.4.3-1.js ecma/String/15.5.4.3-2.js ecma/String/15.5.4.3-3-n.js ecma/String/15.5.4.4-1.js ecma/String/15.5.4.4-2.js ecma/String/15.5.4.4-3.js ecma/String/15.5.4.4-4.js ecma/String/15.5.4.5-1.js ecma/String/15.5.4.5-2.js ecma/String/15.5.4.5-3.js ecma/String/15.5.4.5-4.js ecma/String/15.5.4.5-5.js ecma/String/15.5.4.6-1.js ecma/String/15.5.4.7-2.js ecma/String/15.5.4.8-1.js ecma/String/15.5.4.8-3.js ecma/String/15.5.4.9-1.js ecma/String/15.5.4.js ecma/String/15.5.5.1.js ecma/TypeConversion/9.2.js ecma/TypeConversion/9.3-1.js ecma/TypeConversion/9.3.1-1.js ecma/TypeConversion/9.3.1-2.js ecma/TypeConversion/9.3.1-3.js ecma/TypeConversion/9.3.js ecma/TypeConversion/9.4-1.js ecma/TypeConversion/9.4-2.js ecma/TypeConversion/9.5-2.js ecma/TypeConversion/9.6.js ecma/TypeConversion/9.7.js ecma/TypeConversion/9.8.1.js ecma/TypeConversion/9.9-1.js ecma/Types/8.1.js ecma/Types/8.4.js ecma/Types/8.6.2.1-1.js ecma/extensions/10.1.4-9.js ecma/extensions/10.1.6.js ecma/extensions/10.1.8-1.js ecma/extensions/11.6.1-1.js ecma/extensions/11.6.1-2.js ecma/extensions/11.6.1-3.js ecma/extensions/11.6.2-1.js ecma/extensions/15-2.js ecma/extensions/15.2.1.1.js ecma/extensions/15.2.3-1.js ecma/extensions/15.2.4.js ecma/extensions/15.3.1.1-2.js ecma/extensions/15.3.2.1-1.js ecma/extensions/15.3.2.1-2.js ecma/extensions/15.4.3.js ecma/extensions/15.5.3.js ecma/extensions/15.5.4.2.js ecma/extensions/15.5.4.4-4.js ecma/extensions/15.5.4.5-6.js ecma/extensions/15.5.4.7-3.js ecma/extensions/15.6.3.1-5.js ecma/extensions/15.6.3.js ecma/extensions/15.6.4-2.js ecma/extensions/15.7.3.js ecma/extensions/15.7.4.js ecma/extensions/15.8-1.js ecma/extensions/15.9.5.js ecma/extensions/8.6.2.1-1.js ecma/extensions/9.9-1.js ecma/jsref.js ecma_2/Exceptions/boolean-001.js ecma_2/Exceptions/date-001.js ecma_2/Exceptions/date-002.js ecma_2/Exceptions/date-004.js ecma_2/Exceptions/exception-001.js ecma_2/Exceptions/exception-002.js ecma_2/Exceptions/exception-004.js ecma_2/Exceptions/exception-005.js ecma_2/Exceptions/exception-006.js ecma_2/Exceptions/exception-007.js ecma_2/Exceptions/exception-008.js ecma_2/Exceptions/exception-009.js ecma_2/Exceptions/exception-010-n.js ecma_2/Exceptions/exception-011-n.js ecma_2/Exceptions/expression-002.js ecma_2/Exceptions/expression-004.js ecma_2/Exceptions/expression-005.js ecma_2/Exceptions/expression-006.js ecma_2/Exceptions/expression-007.js ecma_2/Exceptions/expression-008.js ecma_2/Exceptions/expression-009.js ecma_2/Exceptions/expression-010.js ecma_2/Exceptions/expression-011.js ecma_2/Exceptions/expression-012.js ecma_2/Exceptions/expression-013.js ecma_2/Exceptions/expression-014.js ecma_2/Exceptions/expression-015.js ecma_2/Exceptions/expression-016.js ecma_2/Exceptions/expression-017.js ecma_2/Exceptions/global-001.js ecma_2/Exceptions/global-002.js ecma_2/Exceptions/lexical-001.js ecma_2/Exceptions/lexical-002.js ecma_2/Exceptions/lexical-003.js ecma_2/Exceptions/lexical-004.js ecma_2/Exceptions/lexical-005.js ecma_2/Exceptions/lexical-006.js ecma_2/Exceptions/lexical-007.js ecma_2/Exceptions/lexical-009.js ecma_2/Exceptions/lexical-010.js ecma_2/Exceptions/lexical-011.js ecma_2/Exceptions/lexical-012.js ecma_2/Exceptions/lexical-013.js ecma_2/Exceptions/lexical-014.js ecma_2/Exceptions/lexical-015.js ecma_2/Exceptions/lexical-016.js ecma_2/Exceptions/lexical-017.js ecma_2/Exceptions/lexical-018.js ecma_2/Exceptions/lexical-019.js ecma_2/Exceptions/lexical-020.js ecma_2/Exceptions/lexical-022.js ecma_2/Exceptions/lexical-023.js ecma_2/Exceptions/lexical-024.js ecma_2/Exceptions/lexical-025.js ecma_2/Exceptions/lexical-026.js ecma_2/Exceptions/lexical-027.js ecma_2/Exceptions/lexical-028.js ecma_2/Exceptions/lexical-029.js ecma_2/Exceptions/lexical-030.js ecma_2/Exceptions/lexical-031.js ecma_2/Exceptions/lexical-032.js ecma_2/Exceptions/lexical-033.js ecma_2/Exceptions/lexical-034.js ecma_2/Exceptions/lexical-035.js ecma_2/Exceptions/lexical-036.js ecma_2/Exceptions/lexical-037.js ecma_2/Exceptions/lexical-038.js ecma_2/Exceptions/lexical-039.js ecma_2/Exceptions/lexical-040.js ecma_2/Exceptions/lexical-041.js ecma_2/Exceptions/lexical-042.js ecma_2/Exceptions/lexical-047.js ecma_2/Exceptions/lexical-048.js ecma_2/Exceptions/lexical-049.js ecma_2/Exceptions/lexical-050.js ecma_2/Exceptions/lexical-051.js ecma_2/Exceptions/lexical-053.js ecma_2/Exceptions/lexical-054.js ecma_2/Exceptions/number-002.js ecma_2/Exceptions/number-003.js ecma_2/Exceptions/statement-001.js ecma_2/Exceptions/statement-002.js ecma_2/Exceptions/statement-003.js ecma_2/Exceptions/statement-004.js ecma_2/Exceptions/statement-005.js ecma_2/Exceptions/statement-006.js ecma_2/Exceptions/statement-007.js ecma_2/Exceptions/statement-008.js ecma_2/Exceptions/string-001.js ecma_2/Exceptions/string-002.js ecma_2/Expressions/StrictEquality-001.js ecma_2/FunctionObjects/apply-001-n.js ecma_2/FunctionObjects/call-1.js ecma_2/LexicalConventions/keywords-001.js ecma_2/LexicalConventions/regexp-literals-001.js ecma_2/LexicalConventions/regexp-literals-002.js ecma_2/RegExp/constructor-001.js ecma_2/RegExp/exec-002.js ecma_2/RegExp/function-001.js ecma_2/RegExp/hex-001.js ecma_2/RegExp/multiline-001.js ecma_2/RegExp/octal-001.js ecma_2/RegExp/octal-002.js ecma_2/RegExp/octal-003.js ecma_2/RegExp/properties-001.js ecma_2/RegExp/properties-002.js ecma_2/RegExp/regress-001.js ecma_2/RegExp/unicode-001.js ecma_2/Statements/dowhile-001.js ecma_2/Statements/dowhile-002.js ecma_2/Statements/dowhile-003.js ecma_2/Statements/dowhile-004.js ecma_2/Statements/dowhile-005.js ecma_2/Statements/dowhile-006.js ecma_2/Statements/dowhile-007.js ecma_2/Statements/forin-001.js ecma_2/Statements/forin-002.js ecma_2/Statements/if-001.js ecma_2/Statements/label-001.js ecma_2/Statements/label-002.js ecma_2/Statements/switch-002.js ecma_2/Statements/switch-003.js ecma_2/Statements/switch-004.js ecma_2/Statements/try-001.js ecma_2/Statements/try-003.js ecma_2/Statements/try-004.js ecma_2/Statements/try-005.js ecma_2/Statements/try-007.js ecma_2/Statements/try-008.js ecma_2/Statements/try-009.js ecma_2/Statements/try-012.js ecma_2/Statements/while-001.js ecma_2/Statements/while-002.js ecma_2/Statements/while-003.js ecma_2/Statements/while-004.js ecma_2/String/match-001.js ecma_2/String/match-002.js ecma_2/String/match-003.js ecma_2/String/match-004.js ecma_2/String/split-001.js ecma_2/String/split-002.js ecma_2/String/split-003.js ecma_2/extensions/constructor-001.js ecma_2/extensions/function-001.js ecma_2/extensions/instanceof-001.js ecma_2/extensions/instanceof-002.js ecma_2/extensions/instanceof-006.js ecma_2/instanceof/instanceof-001.js ecma_2/instanceof/instanceof-002.js ecma_2/instanceof/regress-7635.js ecma_2/jsref.js ecma_3/Array/15.4.4.11-01.js ecma_3/Array/15.4.4.3-1.js ecma_3/Array/15.4.4.4-001.js ecma_3/Array/regress-101488.js ecma_3/Array/regress-130451.js ecma_3/Array/regress-322135-01.js ecma_3/Date/15.9.4.3.js ecma_3/Date/15.9.5.3.js ecma_3/Date/15.9.5.4.js ecma_3/Date/15.9.5.5.js ecma_3/Date/15.9.5.6.js ecma_3/Date/15.9.5.7.js ecma_3/Exceptions/15.11.1.1.js ecma_3/Exceptions/15.11.4.4-1.js ecma_3/Exceptions/15.11.7.6-001.js ecma_3/Exceptions/15.11.7.6-002.js ecma_3/Exceptions/15.11.7.6-003.js ecma_3/Exceptions/binding-001.js ecma_3/Exceptions/regress-95101.js ecma_3/ExecutionContexts/10.1.3-1.js ecma_3/ExecutionContexts/10.1.3-2.js ecma_3/ExecutionContexts/10.1.3.js ecma_3/ExecutionContexts/10.1.4-1.js ecma_3/ExecutionContexts/10.6.1-01.js ecma_3/ExecutionContexts/regress-23346.js ecma_3/Expressions/11.10-01.js ecma_3/Expressions/11.10-03.js ecma_3/Expressions/11.6.1-1.js ecma_3/Expressions/11.7.1-01.js ecma_3/Expressions/11.7.2-01.js ecma_3/Expressions/11.7.3-01.js ecma_3/Expressions/11.9.6-1.js ecma_3/FunExpr/fe-001-n.js ecma_3/FunExpr/fe-001.js ecma_3/FunExpr/fe-002.js ecma_3/Function/15.3.4.3-1.js ecma_3/Function/15.3.4.4-1.js ecma_3/Function/arguments-002.js ecma_3/Function/call-001.js ecma_3/Function/regress-131964.js ecma_3/Function/regress-137181.js ecma_3/Function/regress-193555.js ecma_3/Function/regress-313570.js ecma_3/Function/regress-49286.js ecma_3/Function/regress-58274.js ecma_3/Function/regress-85880.js ecma_3/Function/regress-94506.js ecma_3/Function/regress-97921.js ecma_3/Function/scope-001.js ecma_3/Function/scope-002.js ecma_3/Number/15.7.4.5-1.js ecma_3/Number/15.7.4.6-1.js ecma_3/Number/15.7.4.7-1.js ecma_3/Number/15.7.4.7-2.js ecma_3/NumberFormatting/tostring-001.js ecma_3/Object/8.6.2.6-001.js ecma_3/Object/class-001.js ecma_3/Object/class-002.js ecma_3/Object/class-003.js ecma_3/Object/class-004.js ecma_3/Object/class-005.js ecma_3/Object/regress-361274.js ecma_3/Object/regress-385393-07.js ecma_3/Object/regress-72773.js ecma_3/Object/regress-79129-001.js ecma_3/Operators/11.13.1-001.js ecma_3/Operators/11.13.1-002.js ecma_3/Operators/11.4.1-001.js ecma_3/RegExp/15.10.2-1.js ecma_3/RegExp/15.10.2.12.js ecma_3/RegExp/15.10.3.1-1.js ecma_3/RegExp/15.10.3.1-2.js ecma_3/RegExp/15.10.4.1-1.js ecma_3/RegExp/15.10.4.1-2.js ecma_3/RegExp/15.10.4.1-3.js ecma_3/RegExp/15.10.4.1-4.js ecma_3/RegExp/15.10.4.1-5-n.js ecma_3/RegExp/15.10.6.2-1.js ecma_3/RegExp/15.10.6.2-2.js ecma_3/RegExp/octal-001.js ecma_3/RegExp/octal-002.js ecma_3/RegExp/perlstress-001.js ecma_3/RegExp/perlstress-002.js ecma_3/RegExp/regress-100199.js ecma_3/RegExp/regress-105972.js ecma_3/RegExp/regress-119909.js ecma_3/RegExp/regress-122076.js ecma_3/RegExp/regress-123437.js ecma_3/RegExp/regress-165353.js ecma_3/RegExp/regress-169497.js ecma_3/RegExp/regress-169534.js ecma_3/RegExp/regress-187133.js ecma_3/RegExp/regress-191479.js ecma_3/RegExp/regress-202564.js ecma_3/RegExp/regress-209067.js ecma_3/RegExp/regress-209919.js ecma_3/RegExp/regress-216591.js ecma_3/RegExp/regress-220367-001.js ecma_3/RegExp/regress-223273.js ecma_3/RegExp/regress-223535.js ecma_3/RegExp/regress-224676.js ecma_3/RegExp/regress-225289.js ecma_3/RegExp/regress-225343.js ecma_3/RegExp/regress-24712.js ecma_3/RegExp/regress-28686.js ecma_3/RegExp/regress-309840.js ecma_3/RegExp/regress-312351.js ecma_3/RegExp/regress-31316.js ecma_3/RegExp/regress-346090.js ecma_3/RegExp/regress-375715-02.js ecma_3/RegExp/regress-375715-03.js ecma_3/RegExp/regress-57572.js ecma_3/RegExp/regress-57631.js ecma_3/RegExp/regress-67773.js ecma_3/RegExp/regress-76683.js ecma_3/RegExp/regress-78156.js ecma_3/RegExp/regress-85721.js ecma_3/RegExp/regress-87231.js ecma_3/RegExp/regress-98306.js ecma_3/Statements/12.6.3.js ecma_3/Statements/regress-131348.js ecma_3/Statements/regress-157509.js ecma_3/Statements/regress-194364.js ecma_3/Statements/regress-226517.js ecma_3/Statements/regress-302439.js ecma_3/Statements/regress-324650.js ecma_3/Statements/regress-74474-001.js ecma_3/Statements/regress-74474-002.js ecma_3/Statements/regress-74474-003.js ecma_3/Statements/regress-83532-001.js ecma_3/Statements/regress-83532-002.js ecma_3/Statements/switch-001.js ecma_3/String/regress-104375.js ecma_3/String/regress-189898.js ecma_3/String/regress-313567.js ecma_3/String/regress-83293.js ecma_3/Unicode/uc-001-n.js ecma_3/Unicode/uc-001.js ecma_3/Unicode/uc-002-n.js ecma_3/Unicode/uc-002.js ecma_3/Unicode/uc-003.js ecma_3/Unicode/uc-004.js ecma_3/Unicode/uc-005.js ecma_3/extensions/regress-103087.js ecma_3/extensions/regress-188206-01.js ecma_3/extensions/regress-188206-02.js ecma_3/extensions/regress-220367-002.js ecma_3/extensions/regress-228087.js ecma_3/extensions/regress-320854.js ecma_3/extensions/regress-327170.js ecma_3/extensions/regress-385393-03.js js-test-driver-begin.js js-test-driver-end.js js1_1/jsref.js js1_2/Array/array_split_1.js js1_2/Array/general1.js js1_2/Array/general2.js js1_2/Array/slice.js js1_2/Array/splice1.js js1_2/Array/splice2.js js1_2/Array/tostring_1.js js1_2/Array/tostring_2.js js1_2/Objects/toString-001.js js1_2/String/charCodeAt.js js1_2/String/concat.js js1_2/String/match.js js1_2/String/slice.js js1_2/function/Number.js js1_2/function/String.js js1_2/function/definition-1.js js1_2/function/length.js js1_2/function/nesting-1.js js1_2/function/nesting.js js1_2/function/regexparg-2-n.js js1_2/jsref.js js1_2/operator/strictEquality.js js1_2/regexp/RegExp_dollar_number.js js1_2/regexp/RegExp_input.js js1_2/regexp/RegExp_input_as_array.js js1_2/regexp/RegExp_lastIndex.js js1_2/regexp/RegExp_lastMatch.js js1_2/regexp/RegExp_lastMatch_as_array.js js1_2/regexp/RegExp_lastParen.js js1_2/regexp/RegExp_lastParen_as_array.js js1_2/regexp/RegExp_leftContext.js js1_2/regexp/RegExp_leftContext_as_array.js js1_2/regexp/RegExp_multiline.js js1_2/regexp/RegExp_multiline_as_array.js js1_2/regexp/RegExp_object.js js1_2/regexp/RegExp_rightContext.js js1_2/regexp/RegExp_rightContext_as_array.js js1_2/regexp/alphanumeric.js js1_2/regexp/asterisk.js js1_2/regexp/backslash.js js1_2/regexp/backspace.js js1_2/regexp/beginLine.js js1_2/regexp/character_class.js js1_2/regexp/compile.js js1_2/regexp/control_characters.js js1_2/regexp/digit.js js1_2/regexp/dot.js js1_2/regexp/endLine.js js1_2/regexp/everything.js js1_2/regexp/exec.js js1_2/regexp/flags.js js1_2/regexp/global.js js1_2/regexp/hexadecimal.js js1_2/regexp/ignoreCase.js js1_2/regexp/interval.js js1_2/regexp/octal.js js1_2/regexp/parentheses.js js1_2/regexp/regress-6359.js js1_2/regexp/regress-9141.js js1_2/regexp/simple_form.js js1_2/regexp/source.js js1_2/regexp/special_characters.js js1_2/regexp/string_replace.js js1_2/regexp/string_search.js js1_2/regexp/string_split.js js1_2/regexp/test.js js1_2/regexp/toString.js js1_2/regexp/vertical_bar.js js1_2/regexp/whitespace.js js1_2/regexp/word_boundary.js js1_2/regress/regress-144834.js js1_2/regress/regress-7703.js js1_2/statements/break.js js1_2/statements/do_while.js js1_2/statements/switch.js js1_2/statements/switch2.js js1_2/version120/boolean-001.js js1_3/Boolean/boolean-001.js js1_3/Script/delete-001.js js1_3/Script/function-002.js js1_3/Script/new-001.js js1_3/Script/switch-001.js js1_3/extensions/proto_10.js js1_3/extensions/proto_2.js js1_3/extensions/proto_5.js js1_3/inherit/proto_1.js js1_3/inherit/proto_10.js js1_3/inherit/proto_11.js js1_3/inherit/proto_12.js js1_3/inherit/proto_3.js js1_3/inherit/proto_4.js js1_3/inherit/proto_6.js js1_3/inherit/proto_7.js js1_3/inherit/proto_8.js js1_3/inherit/proto_9.js js1_3/jsref.js js1_3/regress/delete-001.js js1_3/regress/function-002.js js1_3/regress/new-001.js js1_3/regress/switch-001.js js1_4/Eval/eval-001.js js1_4/Eval/eval-002.js js1_4/Eval/eval-003.js js1_4/Functions/function-001.js js1_4/Regress/date-001-n.js js1_4/Regress/function-001.js js1_4/Regress/function-002.js js1_4/Regress/function-003.js js1_4/Regress/function-004-n.js js1_4/Regress/regress-7224.js js1_4/Regress/toString-001-n.js js1_4/jsref.js js1_5/Array/11.1.4.js js1_5/Array/array-001.js js1_5/Array/regress-101964.js js1_5/Array/regress-107138.js js1_5/Array/regress-108440.js js1_5/Array/regress-154338.js js1_5/Array/regress-178722.js js1_5/Array/regress-255555.js js1_5/Array/regress-299644.js js1_5/Array/regress-300858.js js1_5/Array/regress-310351.js js1_5/Array/regress-311515.js js1_5/Array/regress-313153.js js1_5/Array/regress-315509-01.js js1_5/Array/regress-345961.js js1_5/Array/regress-348810.js js1_5/Array/regress-350256-01.js js1_5/Array/regress-350256-02.js js1_5/Array/regress-360681-01.js js1_5/Array/regress-360681-02.js js1_5/Array/regress-364104.js js1_5/Array/regress-94257.js js1_5/Date/regress-188211.js js1_5/Date/regress-301738-01.js js1_5/Date/regress-309925-01.js js1_5/Date/regress-346027.js js1_5/Exceptions/catchguard-002-n.js js1_5/Exceptions/catchguard-003-n.js js1_5/Exceptions/regress-123002.js js1_5/Exceptions/regress-232182.js js1_5/Exceptions/regress-273931.js js1_5/Exceptions/regress-347674.js js1_5/Exceptions/regress-350837.js js1_5/Expressions/regress-192288.js js1_5/Expressions/regress-96526-argsub.js js1_5/Expressions/regress-96526-noargsub.js js1_5/Function/10.1.6.js js1_5/Function/15.3.4.4.js js1_5/Function/regress-123371.js js1_5/Function/regress-178389.js js1_5/Function/regress-292215.js js1_5/Function/regress-344052.js js1_5/GetSet/regress-375976.js js1_5/LexicalConventions/lexical-001.js js1_5/LexicalConventions/regress-177314.js js1_5/Object/regress-137000.js js1_5/Object/regress-192105.js js1_5/Object/regress-338709.js js1_5/Object/regress-382503.js js1_5/Object/regress-382532.js js1_5/Object/regress-90596-003.js js1_5/Regress/regress-104077.js js1_5/Regress/regress-110286.js js1_5/Regress/regress-111557.js js1_5/Regress/regress-114491.js js1_5/Regress/regress-114493.js js1_5/Regress/regress-115436.js js1_5/Regress/regress-116228.js js1_5/Regress/regress-118849.js js1_5/Regress/regress-127243.js js1_5/Regress/regress-127557.js js1_5/Regress/regress-131510-001.js js1_5/Regress/regress-140852.js js1_5/Regress/regress-140974.js js1_5/Regress/regress-146596.js js1_5/Regress/regress-152646.js js1_5/Regress/regress-159334.js js1_5/Regress/regress-162392.js js1_5/Regress/regress-165201.js js1_5/Regress/regress-167658.js js1_5/Regress/regress-168347.js js1_5/Regress/regress-170193.js js1_5/Regress/regress-172699.js js1_5/Regress/regress-174709.js js1_5/Regress/regress-176125.js js1_5/Regress/regress-185165.js js1_5/Regress/regress-191633.js js1_5/Regress/regress-192414.js js1_5/Regress/regress-193418.js js1_5/Regress/regress-203402.js js1_5/Regress/regress-203841.js js1_5/Regress/regress-204210.js js1_5/Regress/regress-210682.js js1_5/Regress/regress-211590.js js1_5/Regress/regress-214761.js js1_5/Regress/regress-216320.js js1_5/Regress/regress-224956.js js1_5/Regress/regress-229006.js js1_5/Regress/regress-230216-1.js js1_5/Regress/regress-230216-2.js js1_5/Regress/regress-230216-3.js js1_5/Regress/regress-233483-2.js js1_5/Regress/regress-233483.js js1_5/Regress/regress-238881.js js1_5/Regress/regress-238945.js js1_5/Regress/regress-243174.js js1_5/Regress/regress-243389-n.js js1_5/Regress/regress-243869.js js1_5/Regress/regress-244470.js js1_5/Regress/regress-244619.js js1_5/Regress/regress-245113.js js1_5/Regress/regress-245308.js js1_5/Regress/regress-246911.js js1_5/Regress/regress-246964.js js1_5/Regress/regress-253150.js js1_5/Regress/regress-254296.js js1_5/Regress/regress-254974.js js1_5/Regress/regress-256501.js js1_5/Regress/regress-256617.js js1_5/Regress/regress-256798.js js1_5/Regress/regress-260541.js js1_5/Regress/regress-261887.js js1_5/Regress/regress-274888.js js1_5/Regress/regress-275378.js js1_5/Regress/regress-276103.js js1_5/Regress/regress-278873.js js1_5/Regress/regress-280769-3.js js1_5/Regress/regress-280769-4.js js1_5/Regress/regress-281487.js js1_5/Regress/regress-281930.js js1_5/Regress/regress-283477.js js1_5/Regress/regress-286216.js js1_5/Regress/regress-288688.js js1_5/Regress/regress-289094.js js1_5/Regress/regress-290656.js js1_5/Regress/regress-294191.js js1_5/Regress/regress-294195-01.js js1_5/Regress/regress-294195-02.js js1_5/Regress/regress-295052.js js1_5/Regress/regress-295666.js js1_5/Regress/regress-306633.js js1_5/Regress/regress-306727.js js1_5/Regress/regress-306794.js js1_5/Regress/regress-308566.js js1_5/Regress/regress-310295.js js1_5/Regress/regress-310607.js js1_5/Regress/regress-310993.js js1_5/Regress/regress-311071.js js1_5/Regress/regress-311629.js js1_5/Regress/regress-312260.js js1_5/Regress/regress-31255.js js1_5/Regress/regress-314401.js js1_5/Regress/regress-315990.js js1_5/Regress/regress-317476.js js1_5/Regress/regress-317714-02.js js1_5/Regress/regress-319384.js js1_5/Regress/regress-320032.js js1_5/Regress/regress-321757.js js1_5/Regress/regress-321874.js js1_5/Regress/regress-322430.js js1_5/Regress/regress-326467.js js1_5/Regress/regress-328012.js js1_5/Regress/regress-328897.js js1_5/Regress/regress-329383.js js1_5/Regress/regress-330951.js js1_5/Regress/regress-334807-05.js js1_5/Regress/regress-334807-06.js js1_5/Regress/regress-338307.js js1_5/Regress/regress-340369.js js1_5/Regress/regress-341360.js js1_5/Regress/regress-343966.js js1_5/Regress/regress-344804.js js1_5/Regress/regress-344959.js js1_5/Regress/regress-346801.js js1_5/Regress/regress-349482-02.js js1_5/Regress/regress-349592.js js1_5/Regress/regress-350253.js js1_5/Regress/regress-350312.js js1_5/Regress/regress-350415.js js1_5/Regress/regress-351116.js js1_5/Regress/regress-351515.js js1_5/Regress/regress-352009.js js1_5/Regress/regress-352208.js js1_5/Regress/regress-360969-01.js js1_5/Regress/regress-360969-02.js js1_5/Regress/regress-360969-03.js js1_5/Regress/regress-360969-04.js js1_5/Regress/regress-366468.js js1_5/Regress/regress-367561-01.js js1_5/Regress/regress-379245.js js1_5/Regress/regress-39309.js js1_5/Regress/regress-398609.js js1_5/Regress/regress-406769.js js1_5/Regress/regress-407024.js js1_5/Regress/regress-407323.js js1_5/Regress/regress-407957.js js1_5/Regress/regress-57043.js js1_5/Regress/regress-68498-001.js js1_5/Regress/regress-68498-002.js js1_5/Regress/regress-68498-004.js js1_5/Regress/regress-69607.js js1_5/Regress/regress-71107.js js1_5/Regress/regress-76054.js js1_5/Regress/regress-80981.js js1_5/Regress/regress-82306.js js1_5/Regress/regress-90445.js js1_5/Regress/regress-96526-001.js js1_5/Regress/regress-96526-003.js js1_5/Scope/regress-154693.js js1_5/Scope/regress-181834.js js1_5/Scope/regress-184107.js js1_5/Scope/regress-185485.js js1_5/Scope/regress-191276.js js1_5/Scope/regress-192226.js js1_5/Scope/regress-202678-001.js js1_5/Scope/regress-202678-002.js js1_5/Scope/regress-208496-001.js js1_5/Scope/regress-208496-002.js js1_5/Scope/regress-220362.js js1_5/Scope/regress-77578-001.js js1_5/Scope/scope-002.js js1_5/Scope/scope-003.js js1_5/String/regress-107771.js js1_5/String/regress-112626.js js1_5/String/regress-179068.js js1_5/String/regress-314890.js js1_5/decompilation/regress-344120.js js1_5/decompilation/regress-349489.js js1_5/decompilation/regress-349663.js js1_5/decompilation/regress-350670.js js1_5/decompilation/regress-351625.js js1_5/decompilation/regress-351626.js js1_5/decompilation/regress-352022.js js1_5/decompilation/regress-352073.js js1_5/decompilation/regress-352360.js js1_5/decompilation/regress-352873-01.js js1_5/decompilation/regress-352873-02.js js1_5/decompilation/regress-353120.js js1_5/decompilation/regress-354878.js js1_5/decompilation/regress-354910.js js1_5/decompilation/regress-371692.js js1_5/decompilation/regress-373678.js js1_5/decompilation/regress-375639.js js1_5/decompilation/regress-383721.js js1_5/decompilation/regress-406555.js js1_5/extensions/catchguard-001.js js1_5/extensions/catchguard-002.js js1_5/extensions/catchguard-003.js js1_5/extensions/getset-004.js js1_5/extensions/getset-005.js js1_5/extensions/getset-006.js js1_5/extensions/no-such-method.js js1_5/extensions/regress-104077.js js1_5/extensions/regress-178722.js js1_5/extensions/regress-220584.js js1_5/extensions/regress-225831.js js1_5/extensions/regress-226078.js js1_5/extensions/regress-237461.js js1_5/extensions/regress-245795.js js1_5/extensions/regress-255245.js js1_5/extensions/regress-291213.js js1_5/extensions/regress-311161.js js1_5/extensions/regress-311583.js js1_5/extensions/regress-311792-01.js js1_5/extensions/regress-311792-02.js js1_5/extensions/regress-312278.js js1_5/extensions/regress-313500.js js1_5/extensions/regress-313630.js js1_5/extensions/regress-313763.js js1_5/extensions/regress-313803.js js1_5/extensions/regress-313938.js js1_5/extensions/regress-314874.js js1_5/extensions/regress-319683.js js1_5/extensions/regress-322957.js js1_5/extensions/regress-325269.js js1_5/extensions/regress-327608.js js1_5/extensions/regress-328556.js js1_5/extensions/regress-338804-01.js js1_5/extensions/regress-338804-03.js js1_5/extensions/regress-339685.js js1_5/extensions/regress-340199.js js1_5/extensions/regress-341956-02.js js1_5/extensions/regress-341956-03.js js1_5/extensions/regress-346494-01.js js1_5/extensions/regress-350312-01.js js1_5/extensions/regress-350312-02.js js1_5/extensions/regress-350312-03.js js1_5/extensions/regress-351102-01.js js1_5/extensions/regress-351102-02.js js1_5/extensions/regress-351102-06.js js1_5/extensions/regress-351973.js js1_5/extensions/regress-352261.js js1_5/extensions/regress-352281.js js1_5/extensions/regress-354297.js js1_5/extensions/regress-354541-01.js js1_5/extensions/regress-354541-03.js js1_5/extensions/regress-355982.js js1_5/extensions/regress-356402.js js1_5/extensions/regress-363988.js js1_5/extensions/regress-365527.js js1_5/extensions/regress-365692.js js1_5/extensions/regress-366288.js js1_5/extensions/regress-366292.js js1_5/extensions/regress-366396.js js1_5/extensions/regress-367118-01.js js1_5/extensions/regress-367118-02.js js1_5/extensions/regress-367120-01.js js1_5/extensions/regress-367120-02.js js1_5/extensions/regress-367121.js js1_5/extensions/regress-367501-01.js js1_5/extensions/regress-367501-02.js js1_5/extensions/regress-367501-03.js js1_5/extensions/regress-367589.js js1_5/extensions/regress-369404.js js1_5/extensions/regress-374589.js js1_5/extensions/regress-375183.js js1_5/extensions/regress-380889.js js1_5/extensions/regress-385134.js js1_5/extensions/regress-394967.js js1_5/extensions/regress-396326.js js1_5/extensions/regress-407501.js js1_5/extensions/regress-44009.js js1_5/extensions/regress-90596-001.js js1_5/extensions/regress-90596-002.js js1_5/extensions/regress-96284-001.js js1_5/extensions/regress-96284-002.js js1_5/extensions/scope-001.js js1_6/Array/filter.js js1_6/Array/regress-304828.js js1_6/Array/regress-305002.js js1_6/Array/regress-310425-01.js js1_6/Array/regress-310425-02.js js1_6/Array/regress-320887.js js1_6/Array/regress-352742-01.js js1_6/Array/regress-352742-02.js js1_6/Array/regress-415451.js js1_6/Array/regress-415540.js js1_6/Regress/regress-301574.js js1_6/Regress/regress-311157-01.js js1_6/Regress/regress-311157-02.js js1_6/Regress/regress-314887.js js1_6/Regress/regress-351795.js js1_6/Regress/regress-352271.js js1_6/Regress/regress-378492.js js1_6/decompilation/regress-352084.js js1_6/extensions/regress-385393-08.js js1_7/GC/regress-341675.js js1_7/block/order-of-operation.js js1_7/block/regress-341939.js js1_7/block/regress-344139.js js1_7/block/regress-344370.js js1_7/block/regress-345542.js js1_7/block/regress-348685.js js1_7/block/regress-349283.js js1_7/block/regress-349298.js js1_7/block/regress-349507.js js1_7/block/regress-349653.js js1_7/block/regress-349962.js js1_7/block/regress-350279.js js1_7/block/regress-350730.js js1_7/block/regress-350793-01.js js1_7/block/regress-351497.js js1_7/block/regress-351606.js js1_7/block/regress-352092.js js1_7/block/regress-352185.js js1_7/block/regress-352212.js js1_7/block/regress-352267.js js1_7/block/regress-352616.js js1_7/block/regress-352624.js js1_7/block/regress-352907.js js1_7/block/regress-357754.js js1_7/block/regress-376410.js js1_7/block/regress-396900.js js1_7/block/regress-411279.js js1_7/decompilation/regress-349633.js js1_7/decompilation/regress-350810.js js1_7/decompilation/regress-352015.js js1_7/decompilation/regress-352025.js js1_7/decompilation/regress-352269.js js1_7/decompilation/regress-352272.js js1_7/decompilation/regress-352283.js js1_7/decompilation/regress-352732.js js1_7/decompilation/regress-355635.js js1_7/decompilation/regress-355786.js js1_7/decompilation/regress-375794.js js1_7/decompilation/regress-380506.js js1_7/expressions/destructuring-scope.js js1_7/expressions/regress-346203.js js1_7/expressions/regress-346645-01.js js1_7/expressions/regress-346645-02.js js1_7/expressions/regress-346645-03.js js1_7/expressions/regress-349624.js js1_7/expressions/regress-349818.js js1_7/extensions/basic-Iterator.js js1_7/extensions/basic-for-in.js js1_7/extensions/destructuring-order.js js1_7/extensions/iterator-ctor.js js1_7/extensions/regress-346021.js js1_7/extensions/regress-346642-02.js js1_7/extensions/regress-346773.js js1_7/extensions/regress-349619.js js1_7/extensions/regress-350312.js js1_7/extensions/regress-351070-02.js js1_7/extensions/regress-352797-01.js js1_7/extensions/regress-352885-01.js js1_7/extensions/regress-352885-02.js js1_7/extensions/regress-353214-02.js js1_7/extensions/regress-354499-01.js js1_7/extensions/regress-354499-02.js js1_7/extensions/regress-354945-01.js js1_7/extensions/regress-355052-01.js js1_7/extensions/regress-355052-02.js js1_7/extensions/regress-355052-03.js js1_7/extensions/regress-355410.js js1_7/extensions/regress-355512.js js1_7/extensions/regress-355578.js js1_7/extensions/regress-355583.js js1_7/extensions/regress-363040-01.js js1_7/extensions/regress-363040-02.js js1_7/extensions/regress-366668-01.js js1_7/extensions/regress-366668-02.js js1_7/extensions/regress-387955-01.js js1_7/extensions/regress-392308.js js1_7/extensions/regress-396326.js js1_7/geniter/326466-01.js js1_7/geniter/builtin-Iterator-function.js js1_7/geniter/evens.js js1_7/geniter/fibonacci-matrix-generator.js js1_7/geniter/iterator-toString.js js1_7/geniter/message-value-passing.js js1_7/geniter/multiple-close.js js1_7/geniter/nested-yield.js js1_7/geniter/pi-generator.js js1_7/geniter/regress-345736.js js1_7/geniter/regress-345855.js js1_7/geniter/regress-345879-01.js js1_7/geniter/regress-347593.js js1_7/geniter/regress-349012-02.js js1_7/geniter/regress-349012-03.js js1_7/geniter/regress-349012-04.js js1_7/geniter/regress-349012-05.js js1_7/geniter/regress-349023-01.js js1_7/geniter/regress-349023-02.js js1_7/geniter/regress-349023-03.js js1_7/geniter/regress-349362.js js1_7/geniter/regress-349851.js js1_7/geniter/regress-350621.js js1_7/geniter/regress-350809.js js1_7/geniter/regress-351120.js js1_7/geniter/regress-352197.js js1_7/geniter/regress-352876.js js1_7/geniter/regress-355834.js js1_7/geniter/regress-359062.js js1_7/geniter/regress-366941.js js1_7/geniter/regress-382335.js js1_7/geniter/regress-390918.js js1_7/geniter/send-no-rhs.js js1_7/geniter/sequential-yields.js js1_7/geniter/throw-after-close.js js1_7/geniter/throw-forever.js js1_7/geniter/unreachable-yield.js js1_7/geniter/yield-undefined.js js1_7/iterable/regress-341499.js js1_7/iterable/regress-341510.js js1_7/iterable/regress-341815.js js1_7/iterable/regress-341821.js js1_7/iterable/regress-354750-01.js js1_7/iterable/regress-355025.js js1_7/iterable/regress-355075-01.js js1_7/iterable/regress-355090.js js1_7/iterable/regress-412467.js js1_7/lexical/regress-346642-04.js js1_7/regress/regress-352640-01.js js1_7/regress/regress-352640-02.js js1_7/regress/regress-352640-03.js js1_7/regress/regress-352640-04.js js1_7/regress/regress-352797-02.js js1_7/regress/regress-352870-03.js js1_7/regress/regress-353079.js js1_7/regress/regress-355023.js js1_7/regress/regress-355832-01.js js1_7/regress/regress-361566.js js1_7/regress/regress-369666-01.js js1_7/regress/regress-369666-02.js js1_7/regress/regress-372331.js js1_7/regress/regress-373827-01.js js1_7/regress/regress-373827-02.js js1_7/regress/regress-373828.js js1_7/regress/regress-379442.js js1_7/regress/regress-385393-05.js js1_7/regress/regress-407727-01.js js1_7/regress/regress-407727-02.js js1_7/regress/regress-407957.js js1_7/regress/regress-414553.js lc2/Arrays/array-001.js lc2/Arrays/array-002.js lc2/Arrays/array-003.js lc2/Arrays/array-004.js lc2/Arrays/array-005.js lc2/Arrays/array-006-n.js lc2/Arrays/array-007-n.js lc2/Classes/class-001.js lc2/Classes/class-002.js lc2/JSToJava/character-001.js lc2/JSToJava/double-001.js lc2/JSToJava/double-002.js lc2/JSToJava/float-001.js lc2/JSToJava/float-002.js lc2/JSToJava/integer-001.js lc2/JSToJava/integer-002.js lc2/JSToJava/long-001.js lc2/JSToJava/long-002.js lc2/JSToJava/long-003-n.js lc2/JSToJava/short-001.js lc2/JSToJava/short-002.js lc2/JSToJava/short-003-n.js lc2/JavaToJS/String-001.js lc2/JavaToJS/boolean-001.js lc2/JavaToJS/boolean-003.js lc2/JavaToJS/boolean-004.js lc2/JavaToJS/boolean-005.js lc2/JavaToJS/char-001.js lc2/JavaToJS/char-002.js lc2/JavaToJS/enum-001.js lc2/JavaToJS/enum-002.js lc2/JavaToJS/null-001.js lc2/JavaToJS/number-001.js lc2/JavaToJS/number-002.js lc2/Methods/method-001.js lc2/Methods/method-002.js lc2/Methods/method-003.js lc2/Methods/method-004-n.js lc2/Methods/method-005.js lc2/Methods/method-006-n.js lc2/Methods/println-001.js lc2/Objects/object-001.js lc2/Objects/object-002.js lc2/Objects/object-003.js lc2/Objects/object-004.js lc2/Objects/object-005.js lc2/Objects/object-006.js lc2/Packages/package-001.js lc2/Packages/package-002.js lc2/Packages/package-003.js lc2/Packages/package-005.js lc2/Packages/package-006.js lc2/Packages/package-007-n.js lc2/Packages/package-008-n.js lc2/misc/constructor.js lc3/ArrayMethods/byte-002.js lc3/ConvertBoolean/boolean-005-n.js lc3/ConvertBoolean/boolean-006-n.js lc3/ConvertBoolean/boolean-007-n.js lc3/ConvertBoolean/boolean-008-n.js lc3/ConvertBoolean/boolean-009-n.js lc3/ConvertBoolean/boolean-010-n.js lc3/ConvertBoolean/boolean-011-n.js lc3/ConvertBoolean/boolean-012-n.js lc3/ConvertBoolean/boolean-013-n.js lc3/ConvertNull/null-002.js lc3/ConvertNull/null-003-n.js lc3/ConvertNull/null-004-n.js lc3/ConvertNull/null-006-n.js lc3/ConvertString/string-004-n.js lc3/ConvertString/string-005-n.js lc3/ConvertString/string-007-n.js lc3/ConvertUndefined/undefined-001-n.js lc3/JSBoolean/boolean-002-n.js lc3/JSBoolean/boolean-003-n.js lc3/JSBoolean/boolean-004-n.js lc3/JSBoolean/boolean-005-n.js lc3/JSBoolean/boolean-006-n.js lc3/JSBoolean/boolean-007-n.js lc3/JSBoolean/boolean-008-n.js lc3/JSNull/ToBoolean-001-n.js lc3/JSNull/ToLong-001-n.js lc3/JSNull/ToNumber-001-n.js lc3/JSNumber/ToByte-002-n.js lc3/JSNumber/ToByte-003-n.js lc3/JSNumber/ToByte-005-n.js lc3/JSNumber/ToChar-002-n.js lc3/JSNumber/ToChar-003-n.js lc3/JSNumber/ToChar-005-n.js lc3/JSNumber/ToChar-006-n.js lc3/JSNumber/ToInt-002-n.js lc3/JSNumber/ToInt-003-n.js lc3/JSNumber/ToLong-002-n.js lc3/JSNumber/ToLong-003-n.js lc3/JSNumber/ToLong-004-n.js lc3/JSNumber/ToLong-005-n.js lc3/JSNumber/ToLong-006-n.js lc3/JSNumber/ToLong-007-n.js lc3/JSNumber/ToLong-008-n.js lc3/JSNumber/ToLong-009-n.js lc3/JSNumber/ToLong-010-n.js lc3/JSNumber/ToLong-011-n.js lc3/JSNumber/ToShort-003-n.js lc3/JSNumber/ToShort-005-n.js lc3/JSObject/ToDouble-002-n.js lc3/JSObject/ToDouble-003-n.js lc3/JSObject/ToFloat-002-n.js lc3/JSObject/ToFloat-003-n.js lc3/JSUndefined/undefined-002-n.js lc3/JSUndefined/undefined-003-n.js lc3/JSUndefined/undefined-004-n.js lc3/JSUndefined/undefined-005-n.js lc3/JSUndefined/undefined-006-n.js lc3/JSUndefined/undefined-008-n.js lc3/JSUndefined/undefined-009-n.js lc3/JSUndefined/undefined-010-n.js lc3/JavaArray/ToArray-002-n.js lc3/JavaArray/ToBoolean-001-n.js lc3/JavaObject/JavaObjectToBoolean-002-n.js lc3/JavaObject/JavaObjectToByte-002-n.js lc3/JavaObject/JavaObjectToByte-007-n.js lc3/JavaObject/JavaObjectToByte-008-n.js lc3/JavaObject/JavaObjectToChar-003-n.js lc3/JavaObject/JavaObjectToChar-005-n.js lc3/JavaObject/JavaObjectToChar-006-n.js lc3/JavaObject/JavaObjectToInt-002-n.js lc3/JavaObject/JavaObjectToInt-003-n.js lc3/JavaObject/JavaObjectToInt-004-n.js lc3/JavaObject/JavaObjectToLong-002-n.js lc3/JavaObject/JavaObjectToLong-003-n.js lc3/JavaObject/JavaObjectToLong-004-n.js lc3/JavaObject/JavaObjectToLong-006-n.js lc3/JavaObject/JavaObjectToShort-002-n.js lc3/JavaObject/JavaObjectToShort-003-n.js lc3/JavaObject/JavaObjectToShort-004-n.js lc3/StringMethods/string-001.js lc3/StringMethods/string-001.js htmlunit-core-js-2.8/rhino/testsrc/org/0000755000175000017500000000000011530107756020011 5ustar cavedoncavedonhtmlunit-core-js-2.8/rhino/testsrc/org/mozilla/0000755000175000017500000000000011530107756021460 5ustar cavedoncavedonhtmlunit-core-js-2.8/rhino/testsrc/org/mozilla/javascript/0000755000175000017500000000000011530107756023626 5ustar cavedoncavedonhtmlunit-core-js-2.8/rhino/testsrc/org/mozilla/javascript/testing/0000755000175000017500000000000011530107756025303 5ustar cavedoncavedonhtmlunit-core-js-2.8/rhino/testsrc/org/mozilla/javascript/testing/TestErrorReporter.java0000644000175000017500000000425711222460357031627 0ustar cavedoncavedonpackage org.mozilla.javascript.testing; import org.mozilla.javascript.ErrorReporter; import org.mozilla.javascript.EvaluatorException; import junit.framework.Assert; /** *

An error reporter for testing that verifies that messages reported to the * reporter are expected.

* *

Sample use

*
 * TestErrorReporter e =
 *   new TestErrorReporter(null, new String[] { "first warning" });
 * ...
 * assertTrue(e.hasEncounteredAllWarnings());
 * 
* * @author Pascal-Louis Perez */ public final class TestErrorReporter extends Assert implements ErrorReporter { private final String[] errors; private final String[] warnings; private int errorsIndex = 0; private int warningsIndex = 0; public TestErrorReporter(String[] errors, String[] warnings) { this.errors = errors; this.warnings = warnings; } public void error(String message, String sourceName, int line, String lineSource, int lineOffset) { if (errors != null && errorsIndex < errors.length) { assertEquals(errors[errorsIndex++], message); } else { fail("extra error: " + message); } } public void warning(String message, String sourceName, int line, String lineSource, int lineOffset) { if (warnings != null && warningsIndex < warnings.length) { assertEquals(warnings[warningsIndex++], message); } else { fail("extra warning: " + message); } } public EvaluatorException runtimeError( String message, String sourceName, int line, String lineSource, int lineOffset) { throw new UnsupportedOperationException(); } /** * Returns whether all warnings were reported to this reporter. */ public boolean hasEncounteredAllWarnings() { return (warnings == null) ? warningsIndex == 0 : warnings.length == warningsIndex; } /** * Returns whether all errors were reported to this reporter. */ public boolean hasEncounteredAllErrors() { return (errors == null) ? errorsIndex == 0 : errors.length == errorsIndex; } }htmlunit-core-js-2.8/rhino/testsrc/org/mozilla/javascript/drivers/0000755000175000017500000000000011530107756025304 5ustar cavedoncavedonhtmlunit-core-js-2.8/rhino/testsrc/org/mozilla/javascript/drivers/TestUtils.java0000644000175000017500000000506011222460357030105 0ustar cavedoncavedonpackage org.mozilla.javascript.drivers; import java.io.*; import java.util.ArrayList; import java.util.List; import java.util.Properties; import java.util.Arrays; import org.mozilla.javascript.ContextFactory; public class TestUtils { private static ContextFactory.GlobalSetter globalSetter; public static void GrabContextFactoryGlobalSetter() { if (globalSetter == null) { globalSetter = ContextFactory.getGlobalSetter(); } } public static void setGlobalContextFactory(ContextFactory factory) { GrabContextFactoryGlobalSetter(); globalSetter.setContextFactoryGlobal(factory); } public static File[] recursiveListFiles(File dir, FileFilter filter) { if (!dir.isDirectory()) throw new IllegalArgumentException(dir + " is not a directory"); List fileList = new ArrayList(); recursiveListFilesHelper(dir, filter, fileList); return fileList.toArray(new File[fileList.size()]); } public static void recursiveListFilesHelper(File dir, FileFilter filter, List fileList) { for (File f: dir.listFiles()) { if (f.isDirectory()) { recursiveListFilesHelper(f, filter, fileList); } else { if (filter.accept(f)) fileList.add(f); } } } public static void addTestsFromFile(String filename, List list) throws IOException { addTestsFromStream(new FileInputStream(new File(filename)), list); } public static void addTestsFromStream(InputStream in, List list) throws IOException { Properties props = new Properties(); props.load(in); for (Object obj: props.keySet()) { list.add(obj.toString()); } } public static String[] loadTestsFromResource(String resource, String[] inherited) throws IOException { List list = inherited == null ? new ArrayList() : new ArrayList(Arrays.asList(inherited)); InputStream in = StandardTests.class.getResourceAsStream(resource); if (in != null) addTestsFromStream(in, list); return list.toArray(new String[0]); } public static boolean matches(String[] patterns, String path) { for (int i=0; i * * Alternatively, the contents of this file may be used under the terms of * the GNU General Public License Version 2 or later (the "GPL"), in which * case the provisions of the GPL are applicable instead of those above. If * you wish to allow use of your version of this file only under the terms of * the GPL and not to allow others to use your version of this file under the * MPL, indicate your decision by deleting the provisions above and replacing * them with the notice and other provisions required by the GPL. If you do * not delete the provisions above, a recipient may use your version of this * file under either the MPL or the GPL. * * ***** END LICENSE BLOCK ***** */ package org.mozilla.javascript.drivers; import java.io.File; import java.io.FileNotFoundException; import java.net.URL; import java.util.Arrays; import junit.framework.Assert; import junit.framework.TestCase; import junit.framework.TestSuite; import org.mozilla.javascript.tools.shell.ShellContextFactory; /** * Executes the tests in the js/tests directory, much like jsDriver.pl does. * Excludes tests found in the js/tests/rhino-n.tests file. * @author Attila Szegedi * @version $Id: StandardTests.java 4990 2009-09-21 13:03:42Z mguillem $ */ public class StandardTests extends TestSuite { // Disable this suite in favor of // org.mozilla.javascript.tests.MozillaSuiteTest private static final boolean DISABLE = true; public static TestSuite suite() throws Exception { TestSuite suite = new TestSuite("Standard JavaScript tests"); if (!DISABLE) { File testDir = null; if (System.getProperty("mozilla.js.tests") != null) { testDir = new File(System.getProperty("mozilla.js.tests")); } else { URL url = StandardTests.class.getResource("."); String path = url.getFile(); int jsIndex = path.lastIndexOf("/js"); if(jsIndex == -1) { throw new IllegalStateException("You aren't running the tests from within the standard mozilla/js directory structure"); } path = path.substring(0, jsIndex + 3).replace('/', File.separatorChar); path = path.replace("%20", " "); testDir = new File(path, "tests"); } if(!testDir.isDirectory()) { throw new FileNotFoundException(testDir + " is not a directory"); } String[] excludes = TestUtils.loadTestsFromResource("/base.skip", null); String[] opt1Excludes = TestUtils.loadTestsFromResource("/opt1.skip", excludes); for(int i = -1; i < 2; ++i) { TestSuite optimizationLevelSuite = new TestSuite("Optimization level " + i); addSuites(optimizationLevelSuite, testDir, i == -1 ? excludes : opt1Excludes, i); suite.addTest(optimizationLevelSuite); } } return suite; } private static void addSuites(TestSuite topLevel, File testDir, String[] excludes, int optimizationLevel) { File[] subdirs = testDir.listFiles(ShellTest.DIRECTORY_FILTER); Arrays.sort(subdirs); for (int i = 0; i < subdirs.length; i++) { File subdir = subdirs[i]; String name = subdir.getName(); if (TestUtils.matches(excludes, name)) { continue; } TestSuite testSuite = new TestSuite(name); addCategories(testSuite, subdir, name + "/", excludes, optimizationLevel); topLevel.addTest(testSuite); } } private static void addCategories(TestSuite suite, File suiteDir, String prefix, String[] excludes, int optimizationLevel) { File[] subdirs = suiteDir.listFiles(ShellTest.DIRECTORY_FILTER); Arrays.sort(subdirs); for (int i = 0; i < subdirs.length; i++) { File subdir = subdirs[i]; String name = subdir.getName(); TestSuite testCategory = new TestSuite(name); addTests(testCategory, subdir, prefix + name + "/", excludes, optimizationLevel); suite.addTest(testCategory); } } private static void addTests(TestSuite suite, File suiteDir, String prefix, String[] excludes, int optimizationLevel) { File[] jsFiles = suiteDir.listFiles(ShellTest.TEST_FILTER); Arrays.sort(jsFiles); for (int i = 0; i < jsFiles.length; i++) { File jsFile = jsFiles[i]; String name = jsFile.getName(); if (!TestUtils.matches(excludes, prefix + name)) { suite.addTest(new JsTestCase(jsFile, optimizationLevel)); } } } public static class JunitStatus extends ShellTest.Status { @Override public final void running(File jsFile) { // do nothing } @Override public final void failed(String s) { Assert.fail(s); } @Override public final void exitCodesWere(int expected, int actual) { Assert.assertEquals("Unexpected exit code", expected, actual); } @Override public final void outputWas(String s) { // Do nothing; we don't want to see the output when running JUnit // tests. } @Override public final void threw(Throwable t) { Assert.fail(ShellTest.getStackTrace(t)); } @Override public final void timedOut() { failed("Timed out."); } } public static final class JsTestCase extends TestCase { private final File jsFile; private final int optimizationLevel; JsTestCase(File jsFile, int optimizationLevel) { super(jsFile.getName() + (optimizationLevel == 1 ? "-compiled" : "-interpreted")); this.jsFile = jsFile; this.optimizationLevel = optimizationLevel; } @Override public int countTestCases() { return 1; } public static class ShellTestParameters extends ShellTest.Parameters { @Override public int getTimeoutMilliseconds() { if (System.getProperty("mozilla.js.tests.timeout") != null) { return Integer.parseInt(System.getProperty("mozilla.js.tests.timeout")); } return 60000; } } @Override public void runBare() throws Exception { final ShellContextFactory shellContextFactory = new ShellContextFactory(); shellContextFactory.setOptimizationLevel(optimizationLevel); ShellTestParameters params = new ShellTestParameters(); ShellTest.run(shellContextFactory, jsFile, params, new JunitStatus()); } } } htmlunit-core-js-2.8/rhino/testsrc/org/mozilla/javascript/drivers/results.html0000644000175000017500000000400510776623544027703 0ustar cavedoncavedon Rhino: Test Results

Results of JavaScript Test Library for Rhino

Summary

Test List
Skip List
Results
Platform, JRE
Classpath
Time Execution took , ending at

Failure Details Retest List

Failure Details

Testcase path failed Bug Number XXX

				
				
				
htmlunit-core-js-2.8/rhino/testsrc/org/mozilla/javascript/drivers/ShellTest.java0000644000175000017500000003214111222460357030054 0ustar cavedoncavedon/* ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is the Java port of jsDriver.pl. * * The Initial Developer of the Original Code is * David P. Caldwell. * Portions created by David P. Caldwell are Copyright (C) * 2007 David P. Caldwell. All Rights Reserved. * * * Contributor(s): * David P. Caldwell * * Alternatively, the contents of this file may be used under the terms of * the GNU General Public License Version 2 or later (the "GPL"), in which * case the provisions of the GPL are applicable instead of those above. If * you wish to allow use of your version of this file only under the terms of * the GPL and not to allow others to use your version of this file under the * MPL, indicate your decision by deleting the provisions above and replacing * them with the notice and other provisions required by the GPL. If you do * not delete the provisions above, a recipient may use your version of this * file under either the MPL or the GPL. * * ***** END LICENSE BLOCK ***** */ package org.mozilla.javascript.drivers; import java.io.BufferedReader; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileFilter; import java.io.InputStreamReader; import java.io.PrintStream; import java.util.ArrayList; import org.mozilla.javascript.*; import org.mozilla.javascript.tools.shell.Global; import org.mozilla.javascript.tools.shell.Main; import org.mozilla.javascript.tools.shell.ShellContextFactory; /** * @version $Id: ShellTest.java 4668 2009-06-30 19:01:03Z mguillem $ */ public class ShellTest { public static final FileFilter DIRECTORY_FILTER = new FileFilter() { public boolean accept(File pathname) { return pathname.isDirectory() && !pathname.getName().equals("CVS"); } }; public static final FileFilter TEST_FILTER = new FileFilter() { public boolean accept(File pathname) { return pathname.getName().endsWith(".js") && !pathname.getName().equals("shell.js") && !pathname.getName().equals("browser.js") && !pathname.getName().equals("template.js"); } }; public static String getStackTrace(Throwable t) { ByteArrayOutputStream bytes = new ByteArrayOutputStream(); t.printStackTrace(new PrintStream(bytes)); return new String(bytes.toByteArray()); } private static void runFileIfExists(Context cx, Scriptable global, File f) { if(f.isFile()) { Main.processFile(cx, global, f.getPath()); } } private static class TestState { boolean finished; ErrorReporterWrapper errors; int exitCode = 0; } public static abstract class Status { private boolean negative; public final void setNegative() { this.negative = true; } public final boolean isNegative() { return this.negative; } public final void hadErrors(JsError[] errors) { if (!negative && errors.length > 0) { failed("JavaScript errors:\n" + JsError.toString(errors)); } else if (negative && errors.length == 0) { failed("Should have produced runtime error."); } } public abstract void running(File jsFile); public abstract void failed(String s); public abstract void threw(Throwable t); public abstract void timedOut(); public abstract void exitCodesWere(int expected, int actual); public abstract void outputWas(String s); static Status compose(final Status[] array) { return new Status() { @Override public void running(File file) { for (int i=0; i errors = new ArrayList(); ErrorReporterWrapper(ErrorReporter original) { this.original = original; } private void addError(String string, String string0, int i, String string1, int i0) { errors.add( new Status.JsError(string, string0, i, string1, i0) ); } public void warning(String string, String string0, int i, String string1, int i0) { original.warning(string, string0, i, string1, i0); } public EvaluatorException runtimeError(String string, String string0, int i, String string1, int i0) { return original.runtimeError(string, string0, i, string1, i0); } public void error(String string, String string0, int i, String string1, int i0) { addError(string, string0, i, string1, i0); } } public static abstract class Parameters { public abstract int getTimeoutMilliseconds(); } @SuppressWarnings(value={"deprecation"}) private static void callStop(Thread t) { t.stop(); } public static void run(final ShellContextFactory shellContextFactory, final File jsFile, final Parameters parameters, final Status status) throws Exception { final Global global = new Global(); final ByteArrayOutputStream out = new ByteArrayOutputStream(); final PrintStream p = new PrintStream(out); global.setOut(p); global.setErr(p); global.defineFunctionProperties( new String[] { "options" }, ShellTest.class, ScriptableObject.DONTENUM | ScriptableObject.PERMANENT | ScriptableObject.READONLY); final TestState testState = new TestState(); if (jsFile.getName().endsWith("-n.js")) { status.setNegative(); } final Throwable thrown[] = {null}; Thread t = new Thread(new Runnable() { public void run() { try { shellContextFactory.call(new ContextAction() { public Object run(Context cx) { status.running(jsFile); testState.errors = new ErrorReporterWrapper(cx.getErrorReporter()); cx.setErrorReporter( testState.errors ); global.init(cx); try { runFileIfExists(cx, global, new File(jsFile.getParentFile().getParentFile().getParentFile(), "shell.js")); runFileIfExists(cx, global, new File(jsFile.getParentFile().getParentFile(), "shell.js")); runFileIfExists(cx, global, new File(jsFile.getParentFile(), "shell.js")); runFileIfExists(cx, global, jsFile); status.hadErrors(testState.errors.errors.toArray(new Status.JsError[0])); } catch (ThreadDeath e) { } catch (Throwable t) { status.threw(t); } return null; } }); } catch (Error t) { thrown[0] = t; } catch (RuntimeException t) { thrown[0] = t; } finally { synchronized(testState) { testState.finished = true; } } } }, jsFile.getPath()); t.setDaemon(true); t.start(); t.join(parameters.getTimeoutMilliseconds()); synchronized(testState) { if(!testState.finished) { callStop(t); status.timedOut(); } } int expectedExitCode = 0; p.flush(); status.outputWas(new String(out.toByteArray())); BufferedReader r = new BufferedReader(new InputStreamReader( new ByteArrayInputStream(out.toByteArray()))); String failures = ""; for(;;) { String s = r.readLine(); if(s == null) { break; } if(s.indexOf("FAILED!") != -1) { failures += s + '\n'; } int expex = s.indexOf("EXPECT EXIT CODE "); if(expex != -1) { expectedExitCode = s.charAt(expex + "EXPECT EXIT CODE ".length()) - '0'; } } if (thrown[0] != null) { status.threw(thrown[0]); } status.exitCodesWere(expectedExitCode, testState.exitCode); if(failures != "") { status.failed(failures); } } // Global function to mimic options() function in spidermonkey. // It looks like this toggles jit compiler mode in spidermonkey // when called with "jit" as argument. Our version is a no-op // and returns an empty string. public static String options() { return ""; } } htmlunit-core-js-2.8/rhino/testsrc/org/mozilla/javascript/drivers/JsDriver.java0000644000175000017500000007250611222460357027706 0ustar cavedoncavedon/* ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is the Java port of jsDriver.pl. * * The Initial Developer of the Original Code is * David P. Caldwell. * Portions created by David P. Caldwell are Copyright (C) * 2007 David P. Caldwell. All Rights Reserved. * * * Contributor(s): * David P. Caldwell * Norris Boyd * * Alternatively, the contents of this file may be used under the terms of * the GNU General Public License Version 2 or later (the "GPL"), in which * case the provisions of the GPL are applicable instead of those above. If * you wish to allow use of your version of this file only under the terms of * the GPL and not to allow others to use your version of this file under the * MPL, indicate your decision by deleting the provisions above and replacing * them with the notice and other provisions required by the GPL. If you do * not delete the provisions above, a recipient may use your version of this * file under either the MPL or the GPL. * * ***** END LICENSE BLOCK ***** */ package org.mozilla.javascript.drivers; import java.io.*; import java.util.*; import org.w3c.dom.*; import org.mozilla.javascript.tools.shell.*; /** * @version $Id: JsDriver.java 4668 2009-06-30 19:01:03Z mguillem $ */ public class JsDriver { private JsDriver() { } private static String join(String[] list) { String rv = ""; for (int i=0; i list = new ArrayList(); for (int i=0; i < tests.length; i++) { if (tests[i].startsWith("@")) TestUtils.addTestsFromFile(tests[i].substring(1), list); else list.add(tests[i]); } return list.toArray(new String[0]); } private boolean matches(String path) { if (list.length == 0) return true; return TestUtils.matches(list, path); } private boolean excluded(String path) { if (skip.length == 0) return false; return TestUtils.matches(skip, path); } private void addFiles(List