Skip to content

Commit 75ec368

Browse files
Googlercopybara-github
authored andcommitted
[WASM] JsInterop - In preparation for interfaces and other changes, remove the unused JS prototype from interface vtables
Some refactoring around AstUtils utility methods to allow interfaces to be treated separately. PiperOrigin-RevId: 890019615
1 parent b6e706b commit 75ec368

9 files changed

Lines changed: 33 additions & 33 deletions

File tree

transpiler/java/com/google/j2cl/transpiler/ast/AstUtils.java

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1340,24 +1340,39 @@ public static boolean isAnnotatedWithWasm(HasAnnotations node) {
13401340
* <p>A new prototype is populated if the type adds exported members.
13411341
*/
13421342
public static boolean hasWasmJsPrototype(TypeDeclaration typeDeclaration) {
1343+
return !typeDeclaration.isInterface() && declaresWasmJsExports(typeDeclaration);
1344+
}
1345+
1346+
/** Returns true if the given type has any exported members in Wasm. */
1347+
public static boolean declaresWasmJsExports(TypeDeclaration typeDeclaration) {
13431348
return !typeDeclaration.isNative()
1344-
&& !typeDeclaration.isInterface()
13451349
&& (typeDeclaration.getDeclaredMethodDescriptors().stream()
13461350
.anyMatch(methodDescriptor -> AstUtils.needsWasmJsExport(methodDescriptor))
13471351
|| typeDeclaration.getDeclaredFieldDescriptors().stream()
13481352
.anyMatch(fieldDescriptor -> AstUtils.needsWasmJsExport(fieldDescriptor)));
13491353
}
13501354

1355+
/** Returns true if this type defined in Wasm is exported to/visible in JS. */
1356+
public static boolean isWasmJsExportedType(TypeDeclaration typeDeclaration) {
1357+
return findSuperTypeWithWasmJsExportsIncludingSelf(typeDeclaration) != null;
1358+
}
1359+
1360+
/** Returns true if this type defined in Wasm is exported to/visible in JS. */
1361+
public static boolean isWasmJsExportedType(TypeDescriptor typeDescriptor) {
1362+
return typeDescriptor instanceof DeclaredTypeDescriptor dtd
1363+
&& findSuperTypeWithWasmJsExportsIncludingSelf(dtd) != null;
1364+
}
1365+
13511366
/**
13521367
* Returns the first supertype of the given type that has a JS prototype in Wasm, including the
13531368
* type itself.
13541369
*
13551370
* <p>If no supertype has a JS prototype, returns null.
13561371
*/
13571372
@Nullable
1358-
public static DeclaredTypeDescriptor findSuperTypeWithWasmJsPrototypeIncludingSelf(
1373+
public static DeclaredTypeDescriptor findSuperTypeWithWasmJsExportsIncludingSelf(
13591374
TypeDeclaration typeDeclaration) {
1360-
return findSuperTypeWithWasmJsPrototypeIncludingSelf(typeDeclaration.toDescriptor());
1375+
return findSuperTypeWithWasmJsExportsIncludingSelf(typeDeclaration.toDescriptor());
13611376
}
13621377

13631378
/**
@@ -1367,14 +1382,13 @@ public static DeclaredTypeDescriptor findSuperTypeWithWasmJsPrototypeIncludingSe
13671382
* <p>If no supertype has a JS prototype, returns null.
13681383
*/
13691384
@Nullable
1370-
public static DeclaredTypeDescriptor findSuperTypeWithWasmJsPrototypeIncludingSelf(
1385+
public static DeclaredTypeDescriptor findSuperTypeWithWasmJsExportsIncludingSelf(
13711386
@Nullable DeclaredTypeDescriptor typeDescriptor) {
1372-
DeclaredTypeDescriptor superTypeWithJsPrototype = typeDescriptor;
1373-
while (superTypeWithJsPrototype != null) {
1374-
if (hasWasmJsPrototype(superTypeWithJsPrototype.getTypeDeclaration())) {
1375-
return superTypeWithJsPrototype;
1387+
while (typeDescriptor != null) {
1388+
if (declaresWasmJsExports(typeDescriptor.getTypeDeclaration())) {
1389+
return typeDescriptor;
13761390
}
1377-
superTypeWithJsPrototype = superTypeWithJsPrototype.getSuperTypeDescriptor();
1391+
typeDescriptor = typeDescriptor.getSuperTypeDescriptor();
13781392
}
13791393
return null;
13801394
}

transpiler/java/com/google/j2cl/transpiler/backend/wasm/JsExternsGenerator.java

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
*/
1616
package com.google.j2cl.transpiler.backend.wasm;
1717

18-
import static com.google.j2cl.transpiler.ast.AstUtils.findSuperTypeWithWasmJsPrototypeIncludingSelf;
18+
import static com.google.j2cl.transpiler.ast.AstUtils.isWasmJsExportedType;
1919

2020
import com.google.j2cl.common.OutputUtils.Output;
2121
import com.google.j2cl.transpiler.ast.AstUtils;
@@ -74,10 +74,8 @@ private boolean shouldGenerateExtern(DeclaredTypeDescriptor typeDescriptor) {
7474
return false;
7575
}
7676

77-
// Generate externs if the type has a JS prototype or if the type has a supertype with a JS
78-
// prototype. In practice, because j.l.Object has a JS prototype, this nearly all types (some
79-
// exclusions such as interfaces and native types)
80-
return findSuperTypeWithWasmJsPrototypeIncludingSelf(typeDescriptor) != null;
77+
// Generate externs if this type or a supertype is visible to JS.
78+
return isWasmJsExportedType(typeDescriptor);
8179
}
8280

8381
private void generateExtern(Type type) {

transpiler/java/com/google/j2cl/transpiler/backend/wasm/WasmConstructsGenerator.java

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717

1818
import static com.google.common.base.Predicates.not;
1919
import static com.google.common.collect.ImmutableList.toImmutableList;
20-
import static com.google.j2cl.transpiler.ast.AstUtils.findSuperTypeWithWasmJsPrototypeIncludingSelf;
20+
import static com.google.j2cl.transpiler.ast.AstUtils.findSuperTypeWithWasmJsExportsIncludingSelf;
2121
import static com.google.j2cl.transpiler.ast.AstUtils.hasWasmJsPrototype;
2222
import static com.google.j2cl.transpiler.backend.wasm.WasmGenerationEnvironment.getWasmInfo;
2323
import static java.lang.String.format;
@@ -209,11 +209,11 @@ private void renderVtableStruct(Type type, Collection<MethodDescriptor> methods)
209209
/* descriptorClause= */ type.isInterface()
210210
? null
211211
: format("describes %s", environment.getWasmTypeName(type.getTypeDescriptor())),
212-
() -> renderVtableEntries(methods));
212+
() -> renderVtableEntries(type, methods));
213213
}
214214

215-
private void renderVtableEntries(Collection<MethodDescriptor> methodDescriptors) {
216-
if (environment.isCustomDescriptorsJsInteropEnabled()) {
215+
private void renderVtableEntries(Type type, Collection<MethodDescriptor> methodDescriptors) {
216+
if (environment.isCustomDescriptorsJsInteropEnabled() && !type.isInterface()) {
217217
// The first entry of the vtable is the JS prototype. This is used to export JsTypes to JS.
218218
// Because all types extend j.l.Object, they must have this first field to allow vtables to
219219
// extend each other.
@@ -596,9 +596,9 @@ private void emitVtableInitialization(
596596
builder.append(format("(struct.new %s", environment.getWasmVtableTypeName(implementedType)));
597597

598598
builder.indent();
599-
if (environment.isCustomDescriptorsJsInteropEnabled()) {
599+
if (environment.isCustomDescriptorsJsInteropEnabled() && !implementedType.isInterface()) {
600600
// The first field of the vtable for JsTypes is the JS prototype.
601-
var jsPrototypeType = findSuperTypeWithWasmJsPrototypeIncludingSelf(implementedType);
601+
var jsPrototypeType = findSuperTypeWithWasmJsExportsIncludingSelf(implementedType);
602602
builder.newLine();
603603
if (jsPrototypeType != null) {
604604
builder.append(

transpiler/java/com/google/j2cl/transpiler/passes/JsInteropRestrictionsChecker.java

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1745,10 +1745,7 @@ private boolean canCrossWasmJavaScriptBoundary(TypeDescriptor typeDescriptor) {
17451745
return typeDescriptor.isPrimitive()
17461746
|| TypeDescriptors.isJavaLangString(typeDescriptor)
17471747
|| typeDescriptor.isNative()
1748-
|| (checkWasmCustomDescriptorsJsInterop
1749-
&& typeDescriptor instanceof DeclaredTypeDescriptor declaredTypeDescriptor
1750-
&& AstUtils.findSuperTypeWithWasmJsPrototypeIncludingSelf(declaredTypeDescriptor)
1751-
!= null);
1748+
|| (checkWasmCustomDescriptorsJsInterop && AstUtils.isWasmJsExportedType(typeDescriptor));
17521749
}
17531750

17541751
private void checkMethodSignature(

transpiler/javatests/com/google/j2cl/readable/java/jsmethod/output_wasm/contents.wat.txt

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,6 @@
9999
)
100100
(global $jsmethod.JsMethodExample.I.vtable@$jsmethod.JsMethodExample.Sub (ref $jsmethod.JsMethodExample.I.vtable)
101101
(struct.new $jsmethod.JsMethodExample.I.vtable
102-
(ref.null extern)
103102
(ref.func $m_m__java_lang_String__void@jsmethod.JsMethodExample.Sub)
104103
)
105104
)
@@ -158,7 +157,6 @@
158157
)
159158
(global $jsmethod.JsMethodExample.InterfaceExposingJsMethods.vtable@$jsmethod.JsMethodExample.ExposesOverrideableJsMethod (ref $jsmethod.JsMethodExample.InterfaceExposingJsMethods.vtable)
160159
(struct.new $jsmethod.JsMethodExample.InterfaceExposingJsMethods.vtable
161-
(ref.null extern)
162160
(ref.func $m_m__void@jsmethod.JsMethodExample.ExposesOverrideableJsMethod)
163161
(ref.func $m_n__void@jsmethod.JsMethodExample.SuperClassWithFinalMethod)
164162
)

transpiler/javatests/com/google/j2cl/readable/java/jsmethod/output_wasm/types.wat.txt

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,9 @@
11

22
(type $jsmethod.JsMethodExample.I.vtable (sub (struct
3-
(field $js_prototype (ref null extern))
43
(field $m_m__java_lang_String__void (ref $function.m_m__java_lang_String__void))
54
))
65
)
76
(type $jsmethod.JsMethodExample.InterfaceWithMethod.vtable (sub (struct
8-
(field $js_prototype (ref null extern))
97
(field $m_m__void (ref $function.m_m__void))
108
(field $m_n__void (ref $function.m_n__void))
119
))
@@ -52,7 +50,6 @@
5250
))
5351
)
5452
(type $jsmethod.JsMethodExample.InterfaceExposingJsMethods.vtable (sub $jsmethod.JsMethodExample.InterfaceWithMethod.vtable (struct
55-
(field $js_prototype (ref null extern))
5653
(field $m_m__void (ref $function.m_m__void))
5754
(field $m_n__void (ref $function.m_n__void))
5855
))

transpiler/javatests/com/google/j2cl/readable/java/jsproperties/output_wasm/contents.wat.txt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,6 @@
8989
)
9090
(global $jsproperties.InterfaceWithDefaultJsProperties.vtable@$jsproperties.ImplementsInterfaceWithDefaultJsProperties (ref $jsproperties.InterfaceWithDefaultJsProperties.vtable)
9191
(struct.new $jsproperties.InterfaceWithDefaultJsProperties.vtable
92-
(ref.null extern)
9392
(ref.func $m_getM__int@jsproperties.ImplementsInterfaceWithDefaultJsProperties)
9493
(ref.func $m_setM__int__void@jsproperties.ImplementsInterfaceWithDefaultJsProperties)
9594
)

transpiler/javatests/com/google/j2cl/readable/java/jsproperties/output_wasm/types.wat.txt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11

22
(type $jsproperties.InterfaceWithDefaultJsProperties.vtable (sub (struct
3-
(field $js_prototype (ref null extern))
43
(field $m_getM__int (ref $function.m_getM__int))
54
(field $m_setM__int__void (ref $function.m_setM__int__void))
65
))

transpiler/javatests/com/google/j2cl/readable/java/jstype/output_wasm/types.wat.txt

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,8 @@
11

22
(type $jstype.SomeJsType.Star.$Overlay.vtable (sub (struct
3-
(field $js_prototype (ref null extern))
43
))
54
)
65
(type $jstype.SomeJsType.Wildcard.$Overlay.vtable (sub (struct
7-
(field $js_prototype (ref null extern))
86
))
97
)
108
(type $jstype.SomeJsType (sub $java.lang.Object (descriptor $jstype.SomeJsType.vtable) (struct

0 commit comments

Comments
 (0)