From ebe1c27e9aca6cc5035fe4e639020a86e0b196bf Mon Sep 17 00:00:00 2001 From: Volker Berlin Date: Sun, 27 Oct 2019 20:11:47 +0100 Subject: [PATCH] Add support for outsourcing of a constructor to JavaScript --- .../module/ImportSyntheticFunctionName.java | 62 +++++++++++++++++++ .../jwebassembly/module/WasmCodeBuilder.java | 31 +++++++++- 2 files changed, 92 insertions(+), 1 deletion(-) create mode 100644 src/de/inetsoftware/jwebassembly/module/ImportSyntheticFunctionName.java diff --git a/src/de/inetsoftware/jwebassembly/module/ImportSyntheticFunctionName.java b/src/de/inetsoftware/jwebassembly/module/ImportSyntheticFunctionName.java new file mode 100644 index 0000000..866a3a8 --- /dev/null +++ b/src/de/inetsoftware/jwebassembly/module/ImportSyntheticFunctionName.java @@ -0,0 +1,62 @@ +/* + Copyright 2019 Volker Berlin (i-net software) + + Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ +package de.inetsoftware.jwebassembly.module; + +import java.util.function.Function; + +/** + * Synthetic/dynamic method based on import annotation. + * + * @author Volker Berlin + */ +class ImportSyntheticFunctionName extends SyntheticFunctionName { + + private final Function importAnannotation; + + /** + * create a new instance + * + * @param className + * the Java class name + * @param name + * the function name + * @param signature + * the method signature, first the parameters, then null and the the return types + * @param importAnannotation + * the annotations + */ + ImportSyntheticFunctionName( String className, String name, String signature, Function importAnannotation ) { + super( className, name, signature ); + this.importAnannotation = importAnannotation; + } + + /** + * {@inheritDoc} + */ + @Override + protected boolean hasWasmCode() { + return false; + } + + /** + * {@inheritDoc} + */ + @Override + protected Function getAnnotation() { + return importAnannotation; + } +} diff --git a/src/de/inetsoftware/jwebassembly/module/WasmCodeBuilder.java b/src/de/inetsoftware/jwebassembly/module/WasmCodeBuilder.java index 673f592..073394c 100644 --- a/src/de/inetsoftware/jwebassembly/module/WasmCodeBuilder.java +++ b/src/de/inetsoftware/jwebassembly/module/WasmCodeBuilder.java @@ -18,6 +18,7 @@ package de.inetsoftware.jwebassembly.module; import java.io.IOException; import java.util.ArrayList; import java.util.List; +import java.util.function.Function; import javax.annotation.Nonnegative; import javax.annotation.Nonnull; @@ -358,7 +359,35 @@ public abstract class WasmCodeBuilder { * the line number in the Java source code */ protected void addCallInstruction( FunctionName name, int javaCodePos, int lineNumber ) { - instructions.add( new WasmCallInstruction( name, javaCodePos, lineNumber, types ) ); + WasmCallInstruction instruction = new WasmCallInstruction( name, javaCodePos, lineNumber, types ); + + if( "".equals( name.methodName ) ) { + Function importAnannotation = functions.getImportAnannotation( name ); + if( importAnannotation != null ) { + // if there a JavaScript replacement for a constructor we need also replace the create instance instruction + List instructions = this.instructions; + for( int i = instructions.size() - 1; i >= 0; i-- ) { + WasmInstruction instr = instructions.get( i ); + if( instr.getType() == Type.Struct ) { + WasmStructInstruction struct = (WasmStructInstruction)instr; + if( struct.getOperator() == StructOperator.NEW_DEFAULT ) { + instructions.remove( i ); // NEW_DEFAULT + instructions.remove( i ); // SET temp from a dup of the instance reference + instructions.remove( i ); // GET temp from a dup of the instance reference + instructions.remove( i ); // GET temp from a dup of the instance reference + break; + } + } + } + // The new signature need a return value. The of Java has ever a void return value + String signature = name.signature; + signature = signature.substring( 0, signature.length() - 1 ) + "Ljava/lang/Object;"; + FunctionName name2 = new ImportSyntheticFunctionName( "String", "init", signature, importAnannotation ); + instruction = new WasmCallInstruction( name2, javaCodePos, lineNumber, types ); + } + } + + instructions.add( instruction ); } /**