From 9da6d8e73650e2b72f89d820a16a17e9b2990023 Mon Sep 17 00:00:00 2001 From: Volker Berlin Date: Sun, 26 Jun 2022 17:36:30 +0200 Subject: [PATCH] Add the compiler flag "IgnoreNative" to generate stubs for rall not replaced, referenced native methods. #43 --- src/de/inetsoftware/jwebassembly/JWebAssembly.java | 5 +++++ .../module/ArraySyntheticFunctionName.java | 8 ++++++-- .../jwebassembly/module/ModuleGenerator.java | 10 +++++++++- .../jwebassembly/module/WasmOptions.java | 13 +++++++++++++ .../jwebassembly/runtime/RuntimeErrors.java | 4 ++-- 5 files changed, 35 insertions(+), 5 deletions(-) diff --git a/src/de/inetsoftware/jwebassembly/JWebAssembly.java b/src/de/inetsoftware/jwebassembly/JWebAssembly.java index 1d57d363..f0347ade 100644 --- a/src/de/inetsoftware/jwebassembly/JWebAssembly.java +++ b/src/de/inetsoftware/jwebassembly/JWebAssembly.java @@ -103,6 +103,11 @@ public class JWebAssembly { */ public static final String WASM_USE_EH = "wasm.use_eh"; + /** + * Compiler property to ignore all referenced native methods without declared replacement in a library and replace them with a stub that throws an exception at runtime. + */ + public static final String IGNORE_NATIVE = "IgnoreNative"; + /** * The logger instance */ diff --git a/src/de/inetsoftware/jwebassembly/module/ArraySyntheticFunctionName.java b/src/de/inetsoftware/jwebassembly/module/ArraySyntheticFunctionName.java index 4df7594d..533f03c7 100644 --- a/src/de/inetsoftware/jwebassembly/module/ArraySyntheticFunctionName.java +++ b/src/de/inetsoftware/jwebassembly/module/ArraySyntheticFunctionName.java @@ -1,5 +1,5 @@ /* - Copyright 2019 Volker Berlin (i-net software) + Copyright 2019 - 2022 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. @@ -66,6 +66,10 @@ public ArraySyntheticFunctionName( String className, String name, String signatu */ @Override public Iterator getSignature( TypeManager types ) { - return Arrays.asList( signatureTypes ).iterator(); + if( signatureTypes != null ) { + return Arrays.asList( signatureTypes ).iterator(); + } else { + return super.getSignature( types ); + } } } diff --git a/src/de/inetsoftware/jwebassembly/module/ModuleGenerator.java b/src/de/inetsoftware/jwebassembly/module/ModuleGenerator.java index 53bdcc85..2ec77107 100644 --- a/src/de/inetsoftware/jwebassembly/module/ModuleGenerator.java +++ b/src/de/inetsoftware/jwebassembly/module/ModuleGenerator.java @@ -602,7 +602,15 @@ private WasmCodeBuilder createInstructions( MethodInfo method ) throws IOExcepti strings.getStringConstantFunction(); return null; } - throw new WasmException( "Abstract or native method can not be used: " + name.signatureName +"\nIf you want to use classes with native code, you must use a library that implements these native methods, such as 'de.inetsoftware:jwebassembly-api:+'.", -1 ); + + if( writer.options.ignoreNative() ) { + JWebAssembly.LOGGER.severe( "Native method will throw an exception at runtime: " + name.signatureName ); + WatCodeSyntheticFunctionName nativeStub = new WatCodeSyntheticFunctionName( name.className, name.methodName, name.signature, "unreachable", (AnyType[])null ); + functions.markAsNeededAndReplaceIfExists( nativeStub ); + return null; + } + + throw new WasmException( "Native methods cannot be compiled to WebAssembly: " + name.signatureName +"\nIf you want to use classes with native code, you must use a library that implements these native methods, such as 'de.inetsoftware:jwebassembly-api:+' or implements this native method self.", -1 ); } } catch( Throwable ioex ) { int lineNumber = code == null ? -1 : code.getFirstLineNr(); diff --git a/src/de/inetsoftware/jwebassembly/module/WasmOptions.java b/src/de/inetsoftware/jwebassembly/module/WasmOptions.java index da92e465..28cb6907 100644 --- a/src/de/inetsoftware/jwebassembly/module/WasmOptions.java +++ b/src/de/inetsoftware/jwebassembly/module/WasmOptions.java @@ -48,6 +48,8 @@ public class WasmOptions { private final boolean useEH; + private final boolean ignoreNative; + @Nonnull private final String sourceMapBase; @@ -76,6 +78,8 @@ public WasmOptions( HashMap properties ) { debugNames = Boolean.parseBoolean( properties.get( JWebAssembly.DEBUG_NAMES ) ); useGC = Boolean.parseBoolean( properties.getOrDefault( JWebAssembly.WASM_USE_GC, "false" ) ); useEH = Boolean.parseBoolean( properties.getOrDefault( JWebAssembly.WASM_USE_EH, "false" ) ); + ignoreNative = Boolean.parseBoolean( properties.getOrDefault( JWebAssembly.IGNORE_NATIVE, "false" ) ); + String base = properties.getOrDefault( JWebAssembly.SOURCE_MAP_BASE, "" ); if( !base.isEmpty() && !base.endsWith( "/" ) ) { base += "/"; @@ -110,6 +114,15 @@ public boolean useEH() { return useEH; } + /** + * Compiler property to add a stub for all referenced native methods that has no replacement. + * + * @return true, if ignore missing native methods + */ + public boolean ignoreNative() { + return ignoreNative; + } + /** * Get the relative path between the final wasm file location and the source files location. * If not empty it should end with a slash like "../../src/main/java/". diff --git a/test/de/inetsoftware/jwebassembly/runtime/RuntimeErrors.java b/test/de/inetsoftware/jwebassembly/runtime/RuntimeErrors.java index e341e77f..e6dc073e 100644 --- a/test/de/inetsoftware/jwebassembly/runtime/RuntimeErrors.java +++ b/test/de/inetsoftware/jwebassembly/runtime/RuntimeErrors.java @@ -1,5 +1,5 @@ /* - * Copyright 2017 - 2021 Volker Berlin (i-net software) + * Copyright 2017 - 2022 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. @@ -88,7 +88,7 @@ float function() { @Test public void nativeMethod() throws IOException { - compileErrorTest( "Abstract or native method can not be used:", NativeMethod.class ); + compileErrorTest( "Native methods cannot be compiled to WebAssembly:", NativeMethod.class ); } static class NativeMethod {