Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 36 additions & 12 deletions rhino/src/main/java/org/mozilla/javascript/BaseFunction.java
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,16 @@ static LambdaConstructor init(Context cx, Scriptable scope, boolean sealed) {
if (cx.getLanguageVersion() >= Context.VERSION_ES6) {
ctor.setStandardPropertyAttributes(READONLY | DONTENUM);
}

if (!cx.isStrictMode() && cx.getLanguageVersion() >= Context.VERSION_ES6) {
ctor.definePrototypeProperty(
cx,
"arguments",
BaseFunction::js_protoArgumentsGetter,
BaseFunction::js_protoArgumentsSetter,
DONTENUM | READONLY);
}

ScriptableObject.defineProperty(scope, FUNCTION_CLASS, ctor, DONTENUM);
if (sealed) {
ctor.sealObject();
Expand Down Expand Up @@ -177,20 +187,21 @@ protected void createProperties() {
DONTENUM | READONLY,
BaseFunction::nameGetter,
BaseFunction::nameSetter);
if (includeNonStandardProps()) {

Context cx = Context.getCurrentContext();
if (cx == null || !cx.isStrictMode()) {
ScriptableObject.defineBuiltInProperty(
this, "arity", PERMANENT | DONTENUM | READONLY, BaseFunction::arityGetter);
ScriptableObject.defineBuiltInProperty(
this,
"arguments",
PERMANENT | DONTENUM,
BaseFunction::argumentsGetter,
BaseFunction::argumentsSetter);
}
}

protected boolean includeNonStandardProps() {
return !Context.isCurrentContextStrict();
if (cx == null || cx.getLanguageVersion() < Context.VERSION_ES6) {
ScriptableObject.defineBuiltInProperty(
this,
"arguments",
PERMANENT | DONTENUM,
BaseFunction::argumentsGetter,
BaseFunction::argumentsSetter);
}
}
}

private static Object lengthGetter(BaseFunction function, Scriptable start) {
Expand Down Expand Up @@ -627,6 +638,14 @@ public int getLength() {
return 0;
}

private static Object js_protoArgumentsGetter(Scriptable thisObj) {
return LambdaConstructor.convertThisObject(thisObj, BaseFunction.class).getArguments();
}

private static void js_protoArgumentsSetter(Scriptable thisObj, Object value) {
LambdaConstructor.convertThisObject(thisObj, BaseFunction.class).setArguments(value);
}

public String getFunctionName() {
return "";
}
Expand Down Expand Up @@ -713,7 +732,7 @@ protected synchronized Object setupDefaultPrototype(Scriptable scope) {
return obj;
}

private Object getArguments() {
Object getArguments() {
// <Function name>.arguments is deprecated, so we use a slow
// way of getting it that doesn't add to the invocation cost.
// TODO: add warning, error based on version
Expand All @@ -731,13 +750,18 @@ private Object getArguments() {
if (activation == null) {
return null;
}
if (activation.isStrict && cx.getLanguageVersion() >= Context.VERSION_ES6) {
ScriptRuntime.ThrowTypeError.throwNotAllowed();
}
Object arguments = activation.get("arguments", activation);
if (arguments instanceof Arguments && cx.getLanguageVersion() >= Context.VERSION_ES6) {
return new Arguments.ReadonlyArguments((Arguments) arguments, cx);
}
return arguments;
}

void setArguments(Object caller) {}

private static Scriptable jsConstructor(
Context cx, Scriptable scope, Object[] args, boolean isGeneratorFunction) {
int arglen = args.length;
Expand Down
17 changes: 15 additions & 2 deletions rhino/src/main/java/org/mozilla/javascript/BoundFunction.java
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,21 @@ public BoundFunction(
Function thrower = ScriptRuntime.typeErrorThrower(cx);
var throwing = new DescriptorInfo(false, NOT_FOUND, false, thrower, thrower, NOT_FOUND);

this.defineOwnProperty(cx, "caller", throwing, false);
this.defineOwnProperty(cx, "arguments", throwing, false);
defineOwnProperty(cx, "caller", throwing, false);
if (cx.getLanguageVersion() < Context.VERSION_ES6) {
defineOwnProperty(cx, "arguments", throwing, false);
}
}

@Override
Object getArguments() {
ScriptRuntime.ThrowTypeError.throwNotAllowed();
return null;
}

@Override
void setArguments(Object caller) {
ScriptRuntime.ThrowTypeError.throwNotAllowed();
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ public static BaseFunction typeErrorThrower(Context cx) {
return cx.typeErrorThrower;
}

private static final class ThrowTypeError extends BaseFunction {
static final class ThrowTypeError extends BaseFunction {
private static final long serialVersionUID = -5891740962154902286L;

ThrowTypeError(Scriptable scope) {
Expand All @@ -101,6 +101,11 @@ private static Slot removeWithoutChecking(

@Override
public Object call(Context cx, Scriptable scope, Scriptable thisObj, Object[] args) {
throwNotAllowed();
return null;
}

public static void throwNotAllowed() {
throw typeErrorById("msg.op.not.allowed");
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,7 @@ public void argumentsShouldBeNullOutsideFunctionStrict() {
+ "res";

// Utils.assertWithAllModes_ES6("ex [object Arguments] ex ex", code);
Utils.assertWithAllModes_ES6("null [object Arguments] null null", code);
Utils.assertWithAllModes_ES6("null [object Arguments] ex null", code);
Utils.assertWithAllModes_1_8("null [object Arguments] null null", code);
}

Expand All @@ -255,7 +255,7 @@ public void argumentsOutsideFunction() {
+ "res";

// Utils.assertWithAllModes_ES6("undefined length,name,prototype", code);
Utils.assertWithAllModes_ES6("[object Object] arguments,arity,length,name,prototype", code);
Utils.assertWithAllModes_ES6("undefined arity,length,name,prototype", code);
Utils.assertWithAllModes_1_8("[object Object] arguments,arity,length,name,prototype", code);
}

Expand Down Expand Up @@ -340,8 +340,7 @@ public void passedCountDifferentFromDeclaredStrict() {
+ "test('hi', 'there');\n"
+ "res";

// Utils.assertWithAllModes_ES6("2 ex", code);
Utils.assertWithAllModes_ES6("2 null", code);
Utils.assertWithAllModes_ES6("2 ex", code);
Utils.assertWithAllModes_1_8("2 null", code);
}

Expand Down Expand Up @@ -636,7 +635,7 @@ public void argumentsEqualsFnArgumentsStrict() {
+ "function test() {\n"
+ " try {\n"
+ " res += ' ' + (arguments == test.arguments);\n"
+ " } catch(e) { res += 'ex'; }"
+ " } catch(e) { res += ' ex'; }"
+ " try {\n"
+ " res += ' ' + (arguments === test.arguments);\n"
+ " } catch(e) { res += ' ex'; }"
Expand All @@ -645,8 +644,7 @@ public void argumentsEqualsFnArgumentsStrict() {
+ "test('hello', 'world');\n"
+ "res";

// Utils.assertWithAllModes_ES6("ex ex", code);
Utils.assertWithAllModes_ES6("null false false", code);
Utils.assertWithAllModes_ES6("null ex ex", code);
Utils.assertWithAllModes_1_8("null false false", code);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

/*
* Tests for the Object.getOwnPropertyDescriptor(obj, prop) method
*/
package org.mozilla.javascript.tests.es6;

import org.junit.Test;
import org.mozilla.javascript.testutils.Utils;

/*
* Tests for BoundFunction
*/
public class BoundFunctionTest {

@Test
Expand All @@ -20,7 +20,7 @@ public void name() {
}

@Test
public void lenght() {
public void length() {
Utils.assertWithAllModes_ES6(0, "function foo() {}; foo.bind({}).length;");

Utils.assertWithAllModes_ES6(1, "function foo(a) {}; foo.bind({}).length;");
Expand All @@ -39,6 +39,30 @@ public void lenght() {
Utils.assertWithAllModes_ES6(1, "function foo(a, b, c) {}; foo.bind({}, 'x', 'y').length;");
}

@Test
public void arguments() {
String code =
"function foo() { return 'Hello!'; };\n"
+ "var boundFoo = foo.bind({});\n"
+ "'' + Object.getOwnPropertyDescriptor(boundFoo, 'arguments');";
Utils.assertWithAllModes_ES6("undefined", code);
Utils.assertWithAllModes_1_8("[object Object]", code);
}

@Test
public void argumentsAccess() {
String code =
"function foo() { return 'Hello!'; };\n"
+ "var boundFoo = foo.bind({});\n"
+ "let res = '';\n"
+ "try { boundFoo.arguments; res += 'no ex'; } catch (e) { res += e.message; };\n"
+ "try { boundFoo.arguments = 7; res += ' no ex'; } catch (e) { res += ' ' + e.message; };";
Utils.assertWithAllModes_ES6(
"This operation is not allowed. This operation is not allowed.", code);
Utils.assertWithAllModes_1_8(
"This operation is not allowed. This operation is not allowed.", code);
}

@Test
public void fooArgs0_boundArgs0_invokeArgs0() {
Utils.assertWithAllModes_ES6("boundThis []", constructCode(0, 0, "(", 0, false));
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

package org.mozilla.javascript.tests.es6;

import org.junit.jupiter.api.Test;
import org.mozilla.javascript.testutils.Utils;

class FunctionArityTest {

@Test
void simple() {
// todo Utils.assertWithAllModes_ES6("undefined", "function f(a,b) {}; '' + f.arity");
// todo Utils.assertWithAllModes_ES6("undefined", "function f() {}; '' + f.arity");
Utils.assertWithAllModes_ES6("2", "function f(a,b) {}; '' + f.arity");
Utils.assertWithAllModes_ES6("0", "function f() {}; '' + f.arity");

Utils.assertWithAllModes_1_8("2", "function f(a,b) {}; '' + f.arity");
Utils.assertWithAllModes_1_8("0", "function f() {}; '' + f.arity");
}

@Test
void arrow() {
// todo Utils.assertWithAllModes_ES6("undefined", "'' + ((a,b) => {}).arity");
// todo Utils.assertWithAllModes_ES6("undefined", "'' + (() => {}).arity");
Utils.assertWithAllModes_ES6("2", "'' + ((a,b) => {}).arity");
Utils.assertWithAllModes_ES6("0", "'' + (() => {}).arity");

Utils.assertWithAllModes_1_8("2", "'' + ((a,b) => {}).arity");
Utils.assertWithAllModes_1_8("0", "'' + (() => {}).arity");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

package org.mozilla.javascript.tests.es6;

import org.junit.Test;
import org.mozilla.javascript.testutils.Utils;

/*
* Tests for GeneratorFunction
*/
public class GeneratorFunctionTest {

@Test
public void arguments() {
String code =
"function* foo() { yield 'Hello!'; };\n"
+ "'' + Object.getOwnPropertyDescriptor(foo, 'arguments');";
Utils.assertWithAllModes_ES6("undefined", code);
}

@Test
public void argumentsAccess() {
String code =
"function* foo() { yield 'Hello!'; };\n"
+ "let res = '';\n"
+ "try { foo.arguments; res += 'no ex'; } catch (e) { res += e.message; };\n"
+ "try { foo.arguments = 7; res += ' no ex'; } catch (e) { res += ' ' + e.message; };";
// todo Utils.assertWithAllModes_ES6("This operation is not allowed. This operation is not
// allowed.", code);
Utils.assertWithAllModes_ES6("no ex no ex", code);
}
}
Loading
Loading