Skip to content

Commit 0b7e0ff

Browse files
committed
add intermediate prototype for foreign objects
1 parent 7f4bbb6 commit 0b7e0ff

File tree

4 files changed

+68
-8
lines changed

4 files changed

+68
-8
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,13 @@ See [version roadmap](https://www.graalvm.org/release-notes/version-roadmap/) fo
88
## Version 22.2.0
99
* GraalVM JavaScript is now an installable component of GraalVM. It can be installed with `gu install js`.
1010
* Enabled option `js.foreign-object-prototype` by default. Polyglot Interop objects now get a fitting JavaScript prototype assigned unless explicitly turned off using this flag.
11+
* Added intermediate prototype for foreign objects to simplify adapting functionality.
1112
* Removed deprecated experimental option `experimental-foreign-object-prototype`.
1213
* Removed experimental option `commonjs-global-properties`. The same functionality can be achieved in user code with a direct call to `require()` after context creation.
1314
* Added an experimental option `--js.zone-rules-based-time-zones` that allows to use timezone-related data from `ZoneRulesProvider` (instead of ICU4J data files).
1415
* Temporal objects can be converted to compatible Java objects when possible, using the `Value` API's methods like `asDate()`.
1516

17+
1618
## Version 22.1.0
1719
* Updated Node.js to version 16.14.2.
1820
* Graal.js now requires Java 11+ and no longer supports Java 8.

graal-js/src/com.oracle.truffle.js/src/com/oracle/truffle/js/nodes/interop/ForeignObjectPrototypeNode.java

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -64,23 +64,23 @@ public JSDynamicObject doTruffleObject(Object truffleObject,
6464
@CachedLibrary("truffleObject") InteropLibrary interop) {
6565
JSRealm realm = getRealm();
6666
if (interop.hasArrayElements(truffleObject)) {
67-
return realm.getArrayPrototype();
67+
return realm.getForeignArrayPrototype();
6868
} else if (interop.isInstant(truffleObject)) {
69-
return realm.getDatePrototype();
69+
return realm.getForeignDatePrototype();
7070
} else if (interop.hasHashEntries(truffleObject)) {
71-
return realm.getMapPrototype();
71+
return realm.getForeignMapPrototype();
7272
} else if (interop.hasIterator(truffleObject)) {
7373
return realm.getForeignIterablePrototype();
7474
} else if (interop.isString(truffleObject)) {
75-
return realm.getStringPrototype();
75+
return realm.getForeignStringPrototype();
7676
} else if (interop.isNumber(truffleObject)) {
77-
return realm.getNumberPrototype();
77+
return realm.getForeignNumberPrototype();
7878
} else if (interop.isBoolean(truffleObject)) {
79-
return realm.getBooleanPrototype();
79+
return realm.getForeignBooleanPrototype();
8080
} else if (interop.isExecutable(truffleObject) || interop.isInstantiable(truffleObject)) {
81-
return realm.getFunctionPrototype();
81+
return realm.getForeignFunctionPrototype();
8282
} else {
83-
return realm.getObjectPrototype();
83+
return realm.getForeignObjectPrototype();
8484
}
8585
}
8686

graal-js/src/com.oracle.truffle.js/src/com/oracle/truffle/js/runtime/JSContext.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1498,6 +1498,10 @@ public boolean isOptionAsyncStackTraces() {
14981498
return contextOptions.isAsyncStackTraces();
14991499
}
15001500

1501+
public boolean isOptionForeignObjectPrototype () {
1502+
return contextOptions.hasForeignObjectPrototype();
1503+
}
1504+
15011505
public long getTimerResolution() {
15021506
assert !(getInitialEnvironment() != null && getInitialEnvironment().isPreInitialization()) : "Patchable option timer-resolution accessed during context pre-initialization.";
15031507
return contextOptions.getTimerResolution();

graal-js/src/com.oracle.truffle.js/src/com/oracle/truffle/js/runtime/JSRealm.java

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@
5757
import java.util.SplittableRandom;
5858
import java.util.WeakHashMap;
5959

60+
import com.oracle.truffle.js.runtime.objects.Null;
6061
import org.graalvm.collections.Pair;
6162
import org.graalvm.home.HomeFinder;
6263
import org.graalvm.options.OptionValues;
@@ -274,6 +275,15 @@ public class JSRealm {
274275
private final JSFunctionObject callSiteConstructor;
275276
private final JSDynamicObject callSitePrototype;
276277

278+
private final JSDynamicObject foreignArrayPrototype;
279+
private final JSDynamicObject foreignDatePrototype;
280+
private final JSDynamicObject foreignMapPrototype;
281+
private final JSDynamicObject foreignStringPrototype;
282+
private final JSDynamicObject foreignNumberPrototype;
283+
private final JSDynamicObject foreignBooleanPrototype;
284+
private final JSDynamicObject foreignFunctionPrototype;
285+
private final JSDynamicObject foreignObjectPrototype;
286+
277287
private final Shape initialRegExpPrototypeShape;
278288
private final JSObjectFactory.RealmData objectFactories;
279289

@@ -974,6 +984,18 @@ protected JSRealm(JSContext context, TruffleLanguage.Env env, JSRealm parentReal
974984
this.temporalZonedDateTimeConstructor = null;
975985
this.temporalZonedDateTimePrototype = null;
976986
}
987+
988+
// always create, regardless of context.isOptionForeignObjectPrototype()
989+
// we use them in some scenarios even when option is turned off
990+
this.foreignArrayPrototype = JSOrdinary.createInit(this, this.arrayPrototype);
991+
this.foreignDatePrototype = JSOrdinary.createInit(this, this.datePrototype);
992+
// mapPrototype can be null in ES5 mode
993+
this.foreignMapPrototype = JSOrdinary.createInit(this, this.mapPrototype == null ? Null.instance : this.mapPrototype);
994+
this.foreignStringPrototype = JSOrdinary.createInit(this, this.stringPrototype);
995+
this.foreignNumberPrototype = JSOrdinary.createInit(this, this.numberPrototype);
996+
this.foreignBooleanPrototype = JSOrdinary.createInit(this, this.booleanPrototype);
997+
this.foreignFunctionPrototype = JSOrdinary.createInit(this, this.functionPrototype);
998+
this.foreignObjectPrototype = JSOrdinary.createInit(this, this.objectPrototype);
977999
}
9781000

9791001
private void initializeTypedArrayConstructors() {
@@ -1492,6 +1514,38 @@ public JSDynamicObject getTemporalZonedDateTimePrototype() {
14921514
return temporalZonedDateTimePrototype;
14931515
}
14941516

1517+
public final JSDynamicObject getForeignArrayPrototype() {
1518+
return foreignArrayPrototype;
1519+
}
1520+
1521+
public final JSDynamicObject getForeignDatePrototype() {
1522+
return foreignDatePrototype;
1523+
}
1524+
1525+
public JSDynamicObject getForeignMapPrototype() {
1526+
return foreignMapPrototype;
1527+
}
1528+
1529+
public JSDynamicObject getForeignStringPrototype() {
1530+
return foreignStringPrototype;
1531+
}
1532+
1533+
public JSDynamicObject getForeignNumberPrototype() {
1534+
return foreignNumberPrototype;
1535+
}
1536+
1537+
public JSDynamicObject getForeignBooleanPrototype() {
1538+
return foreignBooleanPrototype;
1539+
}
1540+
1541+
public JSDynamicObject getForeignFunctionPrototype() {
1542+
return foreignFunctionPrototype;
1543+
}
1544+
1545+
public JSDynamicObject getForeignObjectPrototype() {
1546+
return foreignObjectPrototype;
1547+
}
1548+
14951549
public final Map<Object, JSDynamicObject> getTemplateRegistry() {
14961550
if (templateRegistry == null) {
14971551
createTemplateRegistry();

0 commit comments

Comments
 (0)