diff --git a/src/de/inetsoftware/jwebassembly/module/TypeManager.java b/src/de/inetsoftware/jwebassembly/module/TypeManager.java
index d69e7ab..f60be2b 100644
--- a/src/de/inetsoftware/jwebassembly/module/TypeManager.java
+++ b/src/de/inetsoftware/jwebassembly/module/TypeManager.java
@@ -395,22 +395,35 @@ public class TypeManager {
*
* @param method
* the name BootstrapMethod from the parsed class file
- * @param params
- * the parameters of the constructor and type fields
- * @param interfaceType
- * the implemented interface
+ * @param factorySignature
+ * Get the signature of the factory method. For example "()Ljava.lang.Runnable;" for the lambda expression
+ * Runnable run = () -> foo();
* @param interfaceMethodName
* the name of the implemented method in the interface
+ * @param lineNumber
+ * the line number in the Java source code
* @return the type
*/
- LambdaType lambdaType( @Nonnull BootstrapMethod method, ArrayList params, StructType interfaceType, String interfaceMethodName ) {
+ LambdaType lambdaType( @Nonnull BootstrapMethod method, String factorySignature, String interfaceMethodName, int lineNumber ) {
ConstantRef implMethod = method.getImplMethod();
- FunctionName methodName = new FunctionName( implMethod );
+ FunctionName syntheticLambdaFunctionName = new FunctionName( implMethod );
+
+ Iterator parser = new ValueTypeParser( factorySignature, this );
+ ArrayList params = new ArrayList<>();
+ do {
+ AnyType param = parser.next();
+ if( param == null ) {
+ break;
+ }
+ params.add( param );
+ } while( true );
+ StructType interfaceType = (StructType)parser.next();
+
String typeName = implMethod.getClassName() + "$$" + implMethod.getName() + "/" + Math.abs( implMethod.getName().hashCode() );
LambdaType type = (LambdaType)structTypes.get( typeName );
if( type == null ) {
- type = new LambdaType( typeName, method, params, interfaceType, methodName, interfaceMethodName, this );
+ type = new LambdaType( typeName, method, params, interfaceType, syntheticLambdaFunctionName, interfaceMethodName, this, lineNumber );
structTypes.put( typeName, type );
}
@@ -1215,8 +1228,10 @@ public class TypeManager {
* the name of the implemented method in the interface
* @param manager
* the manager which hold all StructTypes
+ * @param lineNumber
+ * the line number in the Java source code
*/
- LambdaType( @Nonnull String name, @Nonnull BootstrapMethod method, ArrayList params, StructType interfaceType, FunctionName syntheticLambdaFunctionName, String interfaceMethodName, @Nonnull TypeManager manager ) {
+ LambdaType( @Nonnull String name, @Nonnull BootstrapMethod method, ArrayList params, StructType interfaceType, FunctionName syntheticLambdaFunctionName, String interfaceMethodName, @Nonnull TypeManager manager, int lineNumber ) {
super( name, StructTypeKind.lambda, manager );
this.paramFields = new ArrayList<>( params.size() );
for( int i = 0; i < params.size(); i++ ) {
@@ -1246,10 +1261,10 @@ public class TypeManager {
}
watParser.reset( null, null, sig.iterator() );
- // first add the values from the Lambda constructor which is saves in the syntetic class
+ // first add the values from the Lambda constructor which is saved in the synthetic class
for( int i = 0; i < paramFields.size(); i++ ) {
codebuilder.addLoadStoreInstruction( LambdaType.this, true, 0, 0, -1 );
- codebuilder.addStructInstruction( StructOperator.GET, name, paramFields.get( i ), 0, -1 );
+ codebuilder.addStructInstruction( StructOperator.GET, name, paramFields.get( i ), 0, lineNumber );
}
// forward the parameter from the current call without the THIS parameter because the call lambda method is static
@@ -1258,10 +1273,20 @@ public class TypeManager {
if( anyType == null ) {
break;
}
- codebuilder.addLoadStoreInstruction( anyType, true, i, 0, -1 );
+ codebuilder.addLoadStoreInstruction( anyType, true, i, 0, lineNumber );
}
- codebuilder.addCallInstruction( syntheticLambdaFunctionName, false, 0, -1 );
+ boolean needThisParameter = false;
+ try {
+ // a lambda expression function is mostly static else it need access to field.
+ ClassFile classFile = classFileLoader.get( syntheticLambdaFunctionName.className );
+ MethodInfo methodInfo = classFile.getMethod( syntheticLambdaFunctionName.methodName, syntheticLambdaFunctionName.signature );
+ needThisParameter = !methodInfo.isStatic();
+ } catch( Exception ex ) {
+ throw WasmException.create( ex, null, syntheticLambdaFunctionName.className, syntheticLambdaFunctionName.methodName, lineNumber );
+ }
+
+ codebuilder.addCallInstruction( syntheticLambdaFunctionName, needThisParameter, 0, lineNumber );
return watParser;
}
};
diff --git a/src/de/inetsoftware/jwebassembly/module/WasmCodeBuilder.java b/src/de/inetsoftware/jwebassembly/module/WasmCodeBuilder.java
index 995cb4e..ad4ce64 100644
--- a/src/de/inetsoftware/jwebassembly/module/WasmCodeBuilder.java
+++ b/src/de/inetsoftware/jwebassembly/module/WasmCodeBuilder.java
@@ -36,7 +36,6 @@ import de.inetsoftware.jwebassembly.WasmException;
import de.inetsoftware.jwebassembly.javascript.NonGC;
import de.inetsoftware.jwebassembly.module.StackInspector.StackValue;
import de.inetsoftware.jwebassembly.module.TypeManager.LambdaType;
-import de.inetsoftware.jwebassembly.module.TypeManager.StructType;
import de.inetsoftware.jwebassembly.module.WasmInstruction.Type;
import de.inetsoftware.jwebassembly.wasm.AnyType;
import de.inetsoftware.jwebassembly.wasm.ArrayOperator;
@@ -650,13 +649,14 @@ public abstract class WasmCodeBuilder {
*
* @param name
* the function name that should be called
- * @param needThisParameter true, if the hidden THIS parameter is needed, If it is an instance method call.
+ * @param needThisParameter
+ * true, if the hidden THIS parameter is needed, If it is an instance method call.
* @param javaCodePos
* the code position/offset in the Java method
* @param lineNumber
* the line number in the Java source code
*/
- protected void addCallInstruction( FunctionName name, boolean needThisParameter, int javaCodePos, int lineNumber ) {
+ protected void addCallInstruction( @Nonnull FunctionName name, boolean needThisParameter, int javaCodePos, int lineNumber ) {
name = functions.markAsNeeded( name, needThisParameter );
WasmCallInstruction instruction = new WasmCallInstruction( name, javaCodePos, lineNumber, types, needThisParameter );
@@ -970,7 +970,7 @@ public abstract class WasmCodeBuilder {
* @param method
* the BootstrapMethod, described the method that should be executed
* @param factorySignature
- * Get the signature of the factory method. For example "()Ljava.lang.Runnable;" for the lamba expression
+ * Get the signature of the factory method. For example "()Ljava.lang.Runnable;" for the lambda expression
* Runnable run = () -> foo();
* @param interfaceMethodName
* The simple name of the generated method of the single function interface.
@@ -981,17 +981,7 @@ public abstract class WasmCodeBuilder {
*/
protected void addInvokeDynamic( BootstrapMethod method, String factorySignature, String interfaceMethodName, int javaCodePos, int lineNumber ) {
// Create the synthetic lambda class that hold the lambda expression.
- ValueTypeParser parser = new ValueTypeParser( factorySignature, types );
- ArrayList params = new ArrayList<>();
- do {
- AnyType param = parser.next();
- if( param == null ) {
- break;
- }
- params.add( param );
- } while( true );
- StructType interfaceType = (StructType)parser.next();
- LambdaType type = types.lambdaType( method, params, interfaceType, interfaceMethodName );
+ LambdaType type = types.lambdaType( method, factorySignature, interfaceMethodName, lineNumber );
functions.markAsNeeded( type.getLambdaMethod(), true );
String lambdaTypeName = type.getName();
diff --git a/test/de/inetsoftware/jwebassembly/runtime/StructsNonGC.java b/test/de/inetsoftware/jwebassembly/runtime/StructsNonGC.java
index 0c07fe8..f7dac9f 100644
--- a/test/de/inetsoftware/jwebassembly/runtime/StructsNonGC.java
+++ b/test/de/inetsoftware/jwebassembly/runtime/StructsNonGC.java
@@ -76,6 +76,7 @@ public class StructsNonGC extends AbstractBaseTest {
addParam( list, script, "lambda1" );
addParam( list, script, "lambda2" );
addParam( list, script, "lambda3" );
+ addParam( list, script, "lambdaWithInstanceAccess" );
addParam( list, script, "simpleName_Object" );
addParam( list, script, "simpleName_Anonymous" );
addParam( list, script, "simpleName_Array" );
@@ -336,6 +337,18 @@ public class StructsNonGC extends AbstractBaseTest {
return val.applyAsDouble( 13 );
}
+ @Export
+ public static int lambdaWithInstanceAccess() {
+ TestClass test = new TestClass();
+ return test.lambdaWithInstanceAccessImpl();
+ }
+ private int field;
+ private int lambdaWithInstanceAccessImpl() {
+ field = 13;
+ IntSupplier val = () -> field;
+ return val.getAsInt();
+ }
+
@Export
static boolean isPrimitive_int() {
return int.class.isPrimitive();