Skip to content

Commit e6217c5

Browse files
committed
Allow updating of name of a function, as required by the standard
See mozilla#1297
1 parent dd9c638 commit e6217c5

File tree

3 files changed

+54
-3
lines changed

3 files changed

+54
-3
lines changed

src/org/mozilla/javascript/BaseFunction.java

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66

77
package org.mozilla.javascript;
88

9+
import sun.font.ScriptRun;
10+
911
/**
1012
* The base class for Function objects. That is one of two purposes. It is also the prototype for
1113
* every "function" defined except those that are used as GeneratorFunctions via the ES6 "function
@@ -169,7 +171,7 @@ protected Object getInstanceIdValue(int id) {
169171
case Id_arity:
170172
return arityPropertyAttributes >= 0 ? getArity() : NOT_FOUND;
171173
case Id_name:
172-
return namePropertyAttributes >= 0 ? getFunctionName() : NOT_FOUND;
174+
return namePropertyAttributes >= 0 ? (nameValue != null ? nameValue : getFunctionName()) : NOT_FOUND;
173175
case Id_prototype:
174176
return getPrototypeProperty();
175177
case Id_arguments:
@@ -200,6 +202,9 @@ protected void setInstanceIdValue(int id, Object value) {
200202
case Id_name:
201203
if (value == NOT_FOUND) {
202204
namePropertyAttributes = -1;
205+
nameValue = null;
206+
} else {
207+
nameValue = ScriptRuntime.toString(value);
203208
}
204209
return;
205210
case Id_arity:
@@ -650,6 +655,7 @@ protected int findPrototypeId(String s) {
650655

651656
private Object prototypeProperty;
652657
private Object argumentsObj = NOT_FOUND;
658+
private String nameValue = null;
653659
private boolean isGeneratorFunction = false;
654660

655661
// For function object instances, attributes are
@@ -658,6 +664,6 @@ protected int findPrototypeId(String s) {
658664
private int prototypePropertyAttributes = PERMANENT | DONTENUM;
659665
private int argumentsAttributes = PERMANENT | DONTENUM;
660666
private int arityPropertyAttributes = PERMANENT | READONLY | DONTENUM;
661-
private int namePropertyAttributes = PERMANENT | READONLY | DONTENUM;
667+
private int namePropertyAttributes = READONLY | DONTENUM;
662668
private int lengthPropertyAttributes = PERMANENT | READONLY | DONTENUM;
663669
}

src/org/mozilla/javascript/IdScriptableObject.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -867,13 +867,14 @@ protected void defineOwnProperty(
867867
checkPropertyChange(name, current, desc);
868868
int attr = (info >>> 16);
869869
Object value = getProperty(desc, "value");
870+
attr = applyDescriptorToAttributeBitset(attr, desc);
871+
setAttributes(name, attr);
870872
if (value != NOT_FOUND && (attr & READONLY) == 0) {
871873
Object currentValue = getInstanceIdValue(id);
872874
if (!sameValue(value, currentValue)) {
873875
setInstanceIdValue(id, value);
874876
}
875877
}
876-
setAttributes(name, applyDescriptorToAttributeBitset(attr, desc));
877878
return;
878879
}
879880
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
/* This Source Code Form is subject to the terms of the Mozilla Public
2+
* License, v. 2.0. If a copy of the MPL was not distributed with this
3+
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4+
5+
package org.mozilla.javascript.tests;
6+
7+
import static org.junit.Assert.assertEquals;
8+
9+
import org.junit.Test;
10+
import org.mozilla.javascript.Context;
11+
import org.mozilla.javascript.Scriptable;
12+
13+
/**
14+
* Test that we can redefine a function's name.
15+
*/
16+
public class Issue1297FunctionNameTest {
17+
private static final String source = "'use strict';" +
18+
"function X() {};\n" +
19+
"Object.defineProperty(X, 'name', {value: 'y', configurable: true, writable: true});" +
20+
"X.name";
21+
22+
@Test
23+
public void canSetFunctionNameInCompiledClasses() {
24+
try (Context cx = Context.enter()) {
25+
Scriptable scope = cx.initStandardObjects(null);
26+
Object result = cx.evaluateString(scope,
27+
source,
28+
"test", 1, null);
29+
assertEquals("y", result);
30+
}
31+
}
32+
33+
@Test
34+
public void canSetFunctionNameInInterpreter() {
35+
try (Context cx = Context.enter()) {
36+
cx.setOptimizationLevel(-1);
37+
Scriptable scope = cx.initStandardObjects(null);
38+
Object result = cx.evaluateString(scope,
39+
source,
40+
"test", 1, null);
41+
assertEquals("y", result);
42+
}
43+
}
44+
}

0 commit comments

Comments
 (0)