├── .gitignore ├── test └── de │ └── inetsoftware │ └── jwebassembly │ ├── samples │ ├── basic │ │ ├── EmptyClass.wasm │ │ ├── EmptyClass.wat │ │ └── EmptyClass.java │ ├── FunctionParameters.wasm │ ├── FunctionParameters.wat │ └── FunctionParameters.java │ ├── nodetest.js │ ├── SpiderMonkeyWatTest.js │ ├── SpiderMonkeyTest.js │ ├── WatTest.js │ ├── runtime │ ├── StaticValues.java │ ├── MultiArrayOperations.java │ ├── AbstractBaseTest.java │ ├── Checksums.java │ ├── Stacks.java │ ├── ThreadTest.java │ ├── Enums.java │ ├── DynamicValues.java │ ├── CallFunctions.java │ ├── StringOperations.java │ └── RuntimeErrors.java │ ├── sourcemap │ └── SourceMapWriterTest.java │ ├── ScriptEngine.java │ ├── Node.java │ └── javascript │ └── JavaScriptWriterTest.java ├── .settings ├── org.eclipse.core.runtime.prefs ├── org.eclipse.buildship.core.prefs ├── org.eclipse.core.resources.prefs └── org.eclipse.jdt.core.prefs ├── docs └── samples │ └── HelloWorld │ ├── HelloWorld.wasm │ ├── HelloWorld.html │ ├── HelloWorld.java │ ├── HelloWorld.wasm.js │ └── HelloWorld.wasm.map ├── settings.gradle ├── .gitattributes ├── .github └── workflows │ ├── build8.yml │ └── build11.yml ├── .project ├── src └── de │ └── inetsoftware │ ├── jwebassembly │ ├── wasm │ │ ├── VariableOperator.java │ │ ├── MemoryOperator.java │ │ ├── ArrayOperator.java │ │ ├── StructOperator.java │ │ ├── FunctionType.java │ │ ├── WasmBlockOperator.java │ │ ├── NumericOperator.java │ │ ├── AnyType.java │ │ ├── ValueType.java │ │ ├── LittleEndianOutputStream.java │ │ └── ValueTypeParser.java │ ├── module │ │ ├── JavaBlockOperator.java │ │ ├── ValueTypeConvertion.java │ │ ├── nativecode │ │ │ ├── ReplacementForMethodHandles.java │ │ │ └── ReplacementForEnums.java │ │ ├── ImportSyntheticFunctionName.java │ │ ├── WasmNopInstruction.java │ │ ├── WasmLoadStoreInstruction.java │ │ ├── SyntheticFunctionName.java │ │ ├── CodeOptimizer.java │ │ ├── ArraySyntheticFunctionName.java │ │ ├── WasmTableInstruction.java │ │ ├── WasmCallIndirectInstruction.java │ │ ├── JumpInstruction.java │ │ ├── WatCodeSyntheticFunctionName.java │ │ ├── WasmCallInterfaceInstruction.java │ │ ├── WasmCallVirtualInstruction.java │ │ ├── WasmEmbbeddedCode.java │ │ ├── DupThis.java │ │ ├── WasmMemoryInstruction.java │ │ ├── WasmInstruction.java │ │ ├── WasmGlobalInstruction.java │ │ └── WasmConvertInstruction.java │ ├── binary │ │ ├── ExternalKind.java │ │ ├── SectionEntry.java │ │ ├── Global.java │ │ ├── SectionType.java │ │ ├── ImportFunction.java │ │ ├── ExportEntry.java │ │ ├── TypeEntry.java │ │ ├── ArrayTypeEntry.java │ │ ├── FunctionTypeEntry.java │ │ ├── StructTypeEntry.java │ │ └── Function.java │ ├── text │ │ └── Function.java │ ├── javascript │ │ ├── NonGC.java │ │ └── JavaScriptSyntheticFunctionName.java │ └── sourcemap │ │ ├── SourceMapping.java │ │ └── Base64VLQ.java │ └── classparser │ ├── ConstantFieldRef.java │ ├── ConstantInterfaceRef.java │ ├── ConstantMethodRef.java │ ├── ConstantClass.java │ ├── ConstantNameAndType.java │ ├── Member.java │ ├── WeakValueCache.java │ ├── Exceptions.java │ ├── ConstantRef.java │ ├── TryCatchFinally.java │ ├── ConstantInvokeDynamic.java │ ├── FieldInfo.java │ ├── LocalVariableTable.java │ ├── LineNumberTable.java │ ├── Attributes.java │ ├── LocalVariable.java │ └── CodeInputStream.java ├── .classpath ├── .travis.yml ├── CONTRIBUTING.md └── test11 └── de └── inetsoftware └── jwebassembly └── runtime └── VarHandleTest.java /.gitignore: -------------------------------------------------------------------------------- 1 | /.gradle/ 2 | /bin/ 3 | /build/ 4 | -------------------------------------------------------------------------------- /test/de/inetsoftware/jwebassembly/samples/basic/EmptyClass.wasm: -------------------------------------------------------------------------------- 1 | asm -------------------------------------------------------------------------------- /test/de/inetsoftware/jwebassembly/samples/basic/EmptyClass.wat: -------------------------------------------------------------------------------- 1 | (module 2 | ) -------------------------------------------------------------------------------- /.settings/org.eclipse.core.runtime.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | line.separator=\n 3 | -------------------------------------------------------------------------------- /.settings/org.eclipse.buildship.core.prefs: -------------------------------------------------------------------------------- 1 | connection.project.dir= 2 | eclipse.preferences.version=1 3 | -------------------------------------------------------------------------------- /.settings/org.eclipse.core.resources.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | encoding/=UTF8 3 | -------------------------------------------------------------------------------- /test/de/inetsoftware/jwebassembly/samples/FunctionParameters.wasm: -------------------------------------------------------------------------------- 1 | asm`abc 2 |   Aj! -------------------------------------------------------------------------------- /docs/samples/HelloWorld/HelloWorld.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/i-net-software/JWebAssembly/HEAD/docs/samples/HelloWorld/HelloWorld.wasm -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name='JWebAssembly' 2 | 3 | if( file( '../JWebAssembly-API' ).isDirectory() ) { 4 | includeBuild '../JWebAssembly-API' 5 | } 6 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | 7 | *.java text eol=lf 8 | *.java diff=java 9 | -------------------------------------------------------------------------------- /.settings/org.eclipse.jdt.core.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 3 | org.eclipse.jdt.core.compiler.compliance=1.8 4 | org.eclipse.jdt.core.compiler.source=1.8 5 | -------------------------------------------------------------------------------- /.github/workflows/build8.yml: -------------------------------------------------------------------------------- 1 | name: Build with Java 8 2 | 3 | on: [push, pull_request] 4 | 5 | jobs: 6 | build: 7 | runs-on: ubuntu-latest 8 | 9 | steps: 10 | - uses: actions/checkout@v3 11 | - name: Set up JDK 8 12 | uses: actions/setup-java@v3 13 | with: 14 | java-version: '8' 15 | distribution: 'temurin' 16 | - name: Build with Gradle 17 | run: gradle build --stacktrace 18 | -------------------------------------------------------------------------------- /test/de/inetsoftware/jwebassembly/samples/FunctionParameters.wat: -------------------------------------------------------------------------------- 1 | (module 2 | (type $t0 (func(param i32))) 3 | (export "abc" (func $de/inetsoftware/jwebassembly/samples/FunctionParameters.singleInt)) 4 | (func $de/inetsoftware/jwebassembly/samples/FunctionParameters.singleInt 5 | (param i32) 6 | (local i32) 7 | local.get 0 8 | i32.const 1 9 | i32.add 10 | local.set 1 11 | return 12 | ) 13 | ) -------------------------------------------------------------------------------- /.github/workflows/build11.yml: -------------------------------------------------------------------------------- 1 | name: Build with Java 11 2 | 3 | on: [push, pull_request] 4 | 5 | jobs: 6 | build: 7 | runs-on: ubuntu-latest 8 | 9 | steps: 10 | - uses: actions/checkout@v3 11 | - name: Set up JDK 11 12 | uses: actions/setup-java@v3 13 | with: 14 | java-version: '11' 15 | distribution: 'temurin' 16 | - name: Build with Gradle 17 | run: gradle build --stacktrace 18 | -------------------------------------------------------------------------------- /docs/samples/HelloWorld/HelloWorld.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 12 | 13 | -------------------------------------------------------------------------------- /.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | JWebAssembly 4 | 5 | 6 | 7 | 8 | 9 | org.eclipse.jdt.core.javabuilder 10 | 11 | 12 | 13 | 14 | org.eclipse.buildship.core.gradleprojectbuilder 15 | 16 | 17 | 18 | 19 | 20 | org.eclipse.jdt.core.javanature 21 | org.eclipse.buildship.core.gradleprojectnature 22 | 23 | 24 | -------------------------------------------------------------------------------- /test/de/inetsoftware/jwebassembly/samples/basic/EmptyClass.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Volker Berlin (i-net software) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package de.inetsoftware.jwebassembly.samples.basic; 17 | 18 | /** 19 | * 20 | * @author Volker Berlin 21 | * 22 | */ 23 | public class EmptyClass { 24 | 25 | } 26 | -------------------------------------------------------------------------------- /src/de/inetsoftware/jwebassembly/wasm/VariableOperator.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2019 Volker Berlin (i-net software) 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | 16 | */ 17 | package de.inetsoftware.jwebassembly.wasm; 18 | 19 | /** 20 | * Operation on Variables. 21 | * 22 | * @author Volker Berlin 23 | */ 24 | public enum VariableOperator { 25 | get, 26 | set, 27 | tee, 28 | } -------------------------------------------------------------------------------- /src/de/inetsoftware/jwebassembly/wasm/MemoryOperator.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2019 Volker Berlin (i-net software) 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | 16 | */ 17 | package de.inetsoftware.jwebassembly.wasm; 18 | 19 | /** 20 | * @author Volker Berlin 21 | */ 22 | public enum MemoryOperator { 23 | load8_s, 24 | load8_u, 25 | load16_s, 26 | load16_u, 27 | load, 28 | } 29 | -------------------------------------------------------------------------------- /src/de/inetsoftware/jwebassembly/wasm/ArrayOperator.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2018 - 2021 Volker Berlin (i-net software) 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | 16 | */ 17 | package de.inetsoftware.jwebassembly.wasm; 18 | 19 | /** 20 | * Operation on Arrays. 21 | * 22 | * @author Volker Berlin 23 | */ 24 | public enum ArrayOperator { 25 | NEW, 26 | GET, 27 | GET_S, 28 | GET_U, 29 | SET, 30 | LEN, 31 | NEW_ARRAY_WITH_RTT, 32 | } -------------------------------------------------------------------------------- /src/de/inetsoftware/classparser/ConstantFieldRef.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2011 - 2017 Volker Berlin (i-net software) 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | 16 | */ 17 | package de.inetsoftware.classparser; 18 | 19 | /** 20 | * @author Volker Berlin 21 | */ 22 | public class ConstantFieldRef extends ConstantRef { 23 | 24 | ConstantFieldRef( ConstantClass constClass, ConstantNameAndType nameAndType ) { 25 | super( constClass, nameAndType ); 26 | } 27 | } -------------------------------------------------------------------------------- /test/de/inetsoftware/jwebassembly/nodetest.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | var fs = require('fs'); 4 | 5 | const wasmImports = require( "./{test}.wasm.js" ); 6 | var filename = './{test}.wasm'; 7 | var wasm = fs.readFileSync(filename); 8 | var testData = JSON.parse( fs.readFileSync( "testdata.json", "utf8" ) ); 9 | 10 | // save the test result 11 | function saveResults(result) { 12 | fs.writeFileSync( "testresult.json", JSON.stringify(result) ); 13 | } 14 | 15 | function callExport( instance, wasmImports ) { 16 | wasmImports.exports = instance.exports; 17 | var result = {}; 18 | for (var method in testData) { 19 | try{ 20 | result[method] = String(instance.exports[method]( ...testData[method] )); 21 | }catch(err){ 22 | result[method] = err.stack; 23 | } 24 | } 25 | saveResults(result); 26 | } 27 | 28 | WebAssembly.instantiate( wasm, wasmImports ).then( 29 | obj => callExport( obj.instance, wasmImports ), 30 | reason => console.log(reason) 31 | ); 32 | -------------------------------------------------------------------------------- /src/de/inetsoftware/jwebassembly/module/JavaBlockOperator.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2018 - 2022 Volker Berlin (i-net software) 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | 16 | */ 17 | package de.inetsoftware.jwebassembly.module; 18 | 19 | /** 20 | * Block operators in the Java byte code. 21 | * 22 | * @author Volker Berlin 23 | * 24 | */ 25 | public enum JavaBlockOperator { 26 | IF, 27 | GOTO, 28 | SWITCH, 29 | LOOP, 30 | TRY, 31 | RETURN, 32 | } 33 | -------------------------------------------------------------------------------- /src/de/inetsoftware/classparser/ConstantInterfaceRef.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2017 Volker Berlin (i-net software) 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | 16 | */ 17 | package de.inetsoftware.classparser; 18 | 19 | /** 20 | * @author Volker Berlin 21 | */ 22 | public class ConstantInterfaceRef extends ConstantRef { 23 | 24 | ConstantInterfaceRef( ConstantClass constClass, ConstantNameAndType nameAndType ) { 25 | super( constClass, nameAndType ); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/de/inetsoftware/classparser/ConstantMethodRef.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2011 - 2017 Volker Berlin (i-net software) 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | 16 | */ 17 | package de.inetsoftware.classparser; 18 | 19 | /** 20 | * @author Volker Berlin 21 | */ 22 | public class ConstantMethodRef extends ConstantRef { 23 | 24 | ConstantMethodRef( ConstantClass constClass, ConstantNameAndType nameAndType ) { 25 | super( constClass, nameAndType ); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /test/de/inetsoftware/jwebassembly/SpiderMonkeyWatTest.js: -------------------------------------------------------------------------------- 1 | load( "{test}.wasm.js" ); 2 | var wasm = wasmTextToBinary( read( "{test}.wat" ) ); 3 | // os.file.writeTypedArrayToFile( "debug.wasm", wasm ); 4 | var testData = JSON.parse( read( "testdata.json" ) ); 5 | 6 | // save the test result 7 | function saveResults(result) { 8 | const original = redirect( "testresult.json" ); 9 | putstr( JSON.stringify(result) ); 10 | redirect( original ); 11 | } 12 | 13 | function callExport( instance, wasmImports ) { 14 | wasmImports.exports = instance.exports; 15 | var result = {}; 16 | for (var method in testData) { 17 | try{ 18 | result[method] = String(instance.exports[method]( ...testData[method] )); 19 | }catch(err){ 20 | result[method] = err.toString() + '\n' + err.stack; 21 | } 22 | } 23 | saveResults(result); 24 | } 25 | 26 | WebAssembly.instantiate( wasm, wasmImports ).then( 27 | obj => callExport( obj.instance, wasmImports ), 28 | reason => console.log(reason) 29 | ); 30 | -------------------------------------------------------------------------------- /src/de/inetsoftware/classparser/ConstantClass.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2011 - 2017 Volker Berlin (i-net software) 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | 16 | */ 17 | package de.inetsoftware.classparser; 18 | 19 | /** 20 | * @author Volker Berlin 21 | */ 22 | public class ConstantClass { 23 | private final String name; 24 | 25 | ConstantClass( String name ) { 26 | this.name = name; 27 | } 28 | 29 | public String getName() { 30 | return name; 31 | } 32 | } -------------------------------------------------------------------------------- /src/de/inetsoftware/jwebassembly/binary/ExternalKind.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Volker Berlin (i-net software) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package de.inetsoftware.jwebassembly.binary; 17 | 18 | /** 19 | * A single-byte unsigned integer indicating the kind of definition being imported or defined. 20 | * 21 | * @author Volker Berlin 22 | * 23 | */ 24 | enum ExternalKind { 25 | Function, 26 | Table, 27 | Memory, 28 | Global, 29 | Tag, 30 | } 31 | -------------------------------------------------------------------------------- /src/de/inetsoftware/jwebassembly/wasm/StructOperator.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2018 - 2021 Volker Berlin (i-net software) 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | 16 | */ 17 | package de.inetsoftware.jwebassembly.wasm; 18 | 19 | /** 20 | * Operation on structs. 21 | * 22 | * @author Volker Berlin 23 | */ 24 | public enum StructOperator { 25 | NEW, 26 | NEW_DEFAULT, 27 | GET, 28 | SET, 29 | NULL, 30 | CAST, 31 | INSTANCEOF, 32 | RTT_CANON, 33 | NEW_WITH_RTT, 34 | } -------------------------------------------------------------------------------- /test/de/inetsoftware/jwebassembly/SpiderMonkeyTest.js: -------------------------------------------------------------------------------- 1 | load( "{test.wasm}.js" ); 2 | var wasm = read( "{test.wasm}", "binary" ); // https://developer.mozilla.org/en-US/docs/Mozilla/Projects/SpiderMonkey/Shell_global_objects 3 | var testData = JSON.parse( read( "testdata.json" ) ); 4 | 5 | // save the test result 6 | function saveResults(result) { 7 | const original = redirect( "testresult.json" ); 8 | putstr( JSON.stringify(result) ); 9 | redirect( original ); 10 | } 11 | 12 | function callExport( instance, wasmImports ) { 13 | wasmImports.exports = instance.exports; 14 | var result = {}; 15 | for (var method in testData) { 16 | try{ 17 | result[method] = String(instance.exports[method]( ...testData[method] )); 18 | }catch(err){ 19 | result[method] = err.toString() + '\n' + err.stack; 20 | } 21 | } 22 | saveResults(result); 23 | } 24 | 25 | WebAssembly.instantiate( wasm, wasmImports ).then( 26 | obj => callExport( obj.instance, wasmImports ), 27 | reason => console.log(reason) 28 | ); 29 | -------------------------------------------------------------------------------- /test/de/inetsoftware/jwebassembly/samples/FunctionParameters.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 - 2018 Volker Berlin (i-net software) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package de.inetsoftware.jwebassembly.samples; 17 | 18 | import de.inetsoftware.jwebassembly.api.annotation.Export; 19 | 20 | /** 21 | * 22 | * @author Volker Berlin 23 | * 24 | */ 25 | public class FunctionParameters { 26 | 27 | @Export(name="abc") 28 | static void singleInt( int a ) { 29 | int b = a + 1; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/de/inetsoftware/jwebassembly/text/Function.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 - 2019 Volker Berlin (i-net software) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package de.inetsoftware.jwebassembly.text; 17 | 18 | /** 19 | * A function in the wasm. 20 | * 21 | * @author Volker Berlin 22 | */ 23 | class Function { 24 | 25 | int id; 26 | 27 | int typeId = -1; // -1 not init, use an invalid value to fail hard if it used without init 28 | 29 | final StringBuilder output = new StringBuilder(); 30 | 31 | String name; 32 | } 33 | -------------------------------------------------------------------------------- /src/de/inetsoftware/jwebassembly/wasm/FunctionType.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Volker Berlin (i-net software) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package de.inetsoftware.jwebassembly.wasm; 17 | 18 | /** 19 | * Type of function name. 20 | * 21 | * @author Volker Berlin 22 | */ 23 | public enum FunctionType { 24 | /** imported function */ 25 | Import, 26 | /** has real code */ 27 | Code, 28 | /** abstract or interface, only used for indirrect call */ 29 | Abstract, 30 | /** the function of start section, should occur only once */ 31 | Start, 32 | } 33 | -------------------------------------------------------------------------------- /src/de/inetsoftware/jwebassembly/javascript/NonGC.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Volker Berlin (i-net software) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package de.inetsoftware.jwebassembly.javascript; 17 | 18 | import de.inetsoftware.jwebassembly.api.annotation.Import; 19 | 20 | /** 21 | * Workaround/polyfill for the missing GC feature of WebAssembly. This call add import functions to allocate the objects in the JavaScript host. 22 | * 23 | * @author Volker Berlin 24 | * 25 | */ 26 | public abstract class NonGC { 27 | 28 | 29 | @Import( js = "(a,b) => a === b" ) 30 | native static int ref_eq( Object a, Object b ); 31 | } 32 | -------------------------------------------------------------------------------- /src/de/inetsoftware/jwebassembly/module/ValueTypeConvertion.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 - 2019 Volker Berlin (i-net software) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package de.inetsoftware.jwebassembly.module; 17 | 18 | /** 19 | * Cast operations for converting one data type to another 20 | * 21 | * @author Volker Berlin 22 | * 23 | */ 24 | public enum ValueTypeConvertion { 25 | i2l, 26 | i2f, 27 | i2d, 28 | l2i, 29 | l2f, 30 | l2d, 31 | f2i, 32 | f2l, 33 | f2d, 34 | d2i, 35 | d2l, 36 | d2f, 37 | i2b, 38 | i2c, 39 | i2s, 40 | f2i_re, 41 | i2f_re, 42 | d2l_re, 43 | l2d_re, 44 | } -------------------------------------------------------------------------------- /src/de/inetsoftware/jwebassembly/wasm/WasmBlockOperator.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2018 - 2022 Volker Berlin (i-net software) 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | 16 | */ 17 | package de.inetsoftware.jwebassembly.wasm; 18 | 19 | /** 20 | * Block operators in the WASM byte code. 21 | * 22 | * @author Volker Berlin 23 | * 24 | */ 25 | public enum WasmBlockOperator { 26 | RETURN, 27 | IF, 28 | ELSE, 29 | END, 30 | DROP, 31 | BLOCK, 32 | BR, 33 | BR_IF, 34 | BR_TABLE, 35 | BR_ON_NULL, 36 | LOOP, 37 | UNREACHABLE, 38 | TRY, 39 | CATCH, 40 | THROW, 41 | RETHROW, 42 | BR_ON_EXN, 43 | MONITOR_ENTER, 44 | MONITOR_EXIT, 45 | } 46 | -------------------------------------------------------------------------------- /src/de/inetsoftware/jwebassembly/binary/SectionEntry.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 Volker Berlin (i-net software) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package de.inetsoftware.jwebassembly.binary; 17 | 18 | import java.io.IOException; 19 | 20 | /** 21 | * Signature for an entry in a section 22 | * 23 | * @author Volker Berlin 24 | */ 25 | abstract class SectionEntry { 26 | 27 | /** 28 | * Write this single entry to a section 29 | * 30 | * @param stream 31 | * the target 32 | * @throws IOException 33 | * if any I/O error occur 34 | */ 35 | abstract void writeSectionEntry( WasmOutputStream stream ) throws IOException; 36 | } 37 | -------------------------------------------------------------------------------- /.classpath: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /test/de/inetsoftware/jwebassembly/WatTest.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | var fs = require('fs'); 4 | require("wabt")().then(wabt => { 5 | 6 | const wasmImports = require( "./{test}.wasm.js" ); 7 | var filename = '{test}.wat'; 8 | var text = fs.readFileSync(filename, "utf8"); 9 | var testData = JSON.parse( fs.readFileSync( "testdata.json", "utf8" ) ); 10 | 11 | var features = {'sat_float_to_int':true, 'sign_extension':true, 'exceptions':true, 'reference_types':true, 'gc':true}; 12 | var wasm = wabt.parseWat(filename, text, features); 13 | wasm = wasm.toBinary({}).buffer; 14 | 15 | // save the test result 16 | function saveResults(result) { 17 | fs.writeFileSync( "testresult.json", JSON.stringify(result) ); 18 | } 19 | 20 | function callExport( instance, wasmImports ) { 21 | wasmImports.exports = instance.exports; 22 | var result = {}; 23 | for (var method in testData) { 24 | try{ 25 | result[method] = String(instance.exports[method]( ...testData[method] )); 26 | }catch(err){ 27 | result[method] = err.stack; 28 | } 29 | } 30 | saveResults(result); 31 | } 32 | 33 | WebAssembly.instantiate( wasm, wasmImports ).then( 34 | obj => callExport( obj.instance, wasmImports ), 35 | reason => console.log(reason) 36 | ); 37 | 38 | }); // wabt -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | dist: jammy 2 | language: java 3 | 4 | jdk: 5 | - openjdk8 6 | 7 | before_install: 8 | # Download and install Gradle 6.9.3 9 | - wget https://services.gradle.org/distributions/gradle-6.9.3-bin.zip 10 | - unzip -qq gradle-6.9.3-bin.zip 11 | - export GRADLE_HOME=$PWD/gradle-6.9.3 12 | - export PATH=$GRADLE_HOME/bin:$PATH 13 | - gradle -v 14 | 15 | deploy: 16 | # deploy to Github 17 | provider: releases 18 | api_key: 19 | secure: kdYGXbUNskdjLSPBRRnlpdNa1l6nFfTkjU92Wj0ihOaF1bQ5tzxc2oxRnFolDbL7OhlmbX12L1qx5cdXj4imLqNVz9raMPJgl1NwgjC6eFmYit1ZeUr4InX9jJSrRkbb4aX3p49Phz9OIYvT9cW1YaGbgwunwlBYyO7lVSAiFNENwr2doz9PL+jOjjBNVLHOwn4OewsOrq9IhIdrrWnCgMwjThRqLzG5mX59lUnqVKXjv4uPmiNOdWt0i3paa7xk3lw8VUsNzvhvBSR5xRYcmSqy1A+mC8T37SdMCrqr26W34l/B3MpOSXyhjC97CwWZbOxCu/CKdb28NJxAFTcuTQqfY/tdXl/KoaVbLOM1yk1s1mdrP3Edh3FRq/ALeMKW789wZNzXj3505ESzMVaZIojkVR4ATC8k/r6ly4sP9+7oYVuRTgtxmeU3/p9/l6ZXAYdqRRF/8cItPvriOcZ9JgSLV3bQsPC+S8V5SwPJDrvaNwAZBz9xiWdAM0X5FkC4gwqhwm5A5ioX9yD6H0t6Woq/gS06Q8x2Xfsat25a/ie1yLHpMXq+yXI1ksS5UCgGk6QhrkGsNYE/rXmmuDPKR0V7JYrsjrGEQWj0Tt8Xl3UrXJiqMTXfJ5D2/n/7cdaVXlIIe4mRRQCfk+/wIFbyGazBZyNfs7pG0f0KsWRjJ/g= 20 | file_glob: true 21 | file: "./build/libs/jwebassembly-compiler-*.jar" 22 | skip_cleanup: true 23 | overwrite: true 24 | on: 25 | repo: i-net-software/JWebAssembly 26 | tags: true 27 | -------------------------------------------------------------------------------- /src/de/inetsoftware/jwebassembly/wasm/NumericOperator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 - 2019 Volker Berlin (i-net software) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package de.inetsoftware.jwebassembly.wasm; 17 | 18 | /** 19 | * @author Volker Berlin 20 | */ 21 | public enum NumericOperator { 22 | add, 23 | sub, 24 | neg, 25 | mul, 26 | div, 27 | rem, 28 | and, 29 | or, 30 | xor, 31 | shl, 32 | shr_s, 33 | shr_u, 34 | eqz, 35 | eq, 36 | ne, 37 | gt, 38 | lt, 39 | le, 40 | ge, 41 | max, 42 | min, 43 | ifnull, 44 | ifnonnull, 45 | ref_eq, 46 | ref_ne, 47 | sqrt, 48 | abs, 49 | ceil, 50 | floor, 51 | trunc, 52 | nearest, 53 | copysign, 54 | } 55 | -------------------------------------------------------------------------------- /src/de/inetsoftware/classparser/ConstantNameAndType.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2011 - 2017 Volker Berlin (i-net software) 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | 16 | */ 17 | package de.inetsoftware.classparser; 18 | 19 | /** 20 | * @author Volker Berlin 21 | */ 22 | public class ConstantNameAndType{ 23 | 24 | private final String name; 25 | private final String type; 26 | 27 | public ConstantNameAndType(String name, String type){ 28 | this.name = name; 29 | this.type = type; 30 | } 31 | 32 | public String getName(){ 33 | return name; 34 | } 35 | 36 | /** 37 | * The type of the variable in class file syntax. 38 | * @return the type 39 | */ 40 | public String getType(){ 41 | return type; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /docs/samples/HelloWorld/HelloWorld.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Volker Berlin (i-net software) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | import de.inetsoftware.jwebassembly.api.annotation.Export; 17 | import de.inetsoftware.jwebassembly.web.dom.Document; 18 | import de.inetsoftware.jwebassembly.web.dom.HTMLElement; 19 | import de.inetsoftware.jwebassembly.web.dom.Text; 20 | import de.inetsoftware.jwebassembly.web.dom.Window; 21 | 22 | public class HelloWorld { 23 | 24 | @Export 25 | public static void main() { 26 | Document document = Window.document(); 27 | HTMLElement div = document.createElement("div"); 28 | Text text = document.createTextNode("Hello World, this text come from WebAssembly."); 29 | div.appendChild( text ); 30 | document.body().appendChild( div ); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/de/inetsoftware/classparser/Member.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2018 - 2021 Volker Berlin (i-net software) 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | 16 | */ 17 | package de.inetsoftware.classparser; 18 | 19 | /** 20 | * Described a field, method, function, etc. 21 | * 22 | * @author Volker Berlin 23 | * 24 | */ 25 | public interface Member { 26 | 27 | /** 28 | * The simple name without package 29 | * 30 | * @return the name 31 | */ 32 | String getName(); 33 | 34 | /** 35 | * The class name of the declaring class like "java/lang/Object". 36 | * 37 | * @return the class name 38 | */ 39 | String getClassName(); 40 | 41 | /** 42 | * Get the type of the method or field. For example "(Ljava.lang.String;)I" 43 | * 44 | * @return the type 45 | */ 46 | String getType(); 47 | } 48 | -------------------------------------------------------------------------------- /src/de/inetsoftware/jwebassembly/binary/Global.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 - 2019 Volker Berlin (i-net software) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package de.inetsoftware.jwebassembly.binary; 17 | 18 | import java.io.IOException; 19 | 20 | import de.inetsoftware.jwebassembly.wasm.AnyType; 21 | 22 | /** 23 | * An entry in the global section of the WebAssembly. 24 | * 25 | * @author Volker Berlin 26 | */ 27 | class Global extends SectionEntry { 28 | 29 | int id; 30 | 31 | AnyType type; 32 | 33 | boolean mutability; 34 | 35 | /** 36 | * {@inheritDoc} 37 | */ 38 | @Override 39 | void writeSectionEntry( WasmOutputStream stream ) throws IOException { 40 | stream.writeRefValueType( this.type ); 41 | stream.write( this.mutability ? 1 : 0 ); 42 | stream.writeDefaultValue( this.type ); 43 | stream.writeOpCode( InstructionOpcodes.END ); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/de/inetsoftware/jwebassembly/binary/SectionType.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Volker Berlin (i-net software) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package de.inetsoftware.jwebassembly.binary; 17 | 18 | /** 19 | * @author Volker Berlin 20 | */ 21 | enum SectionType { 22 | Custom, // 0 23 | Type, // 1 Function signature declarations 24 | Import, // 2 Import declarations 25 | Function, // 3 Function declarations 26 | Table, // 4 Indirect function table and other tables 27 | Memory, // 5 Memory attributes 28 | Global, // 6 Global declarations 29 | Export, // 7 Exports 30 | Start, // 8 Start function declaration 31 | Element, // 9 Elements section 32 | Code, // 10 Function bodies (code) 33 | Data, // 11 Data segments 34 | DataCount,//12 Count of data segments https://github.com/WebAssembly/bulk-memory-operations/blob/master/proposals/bulk-memory-operations/Overview.md 35 | Tag, // 13 Tag declarations, Exceptions 36 | } 37 | -------------------------------------------------------------------------------- /src/de/inetsoftware/classparser/WeakValueCache.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2019 Volker Berlin (i-net software) 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | 16 | */ 17 | package de.inetsoftware.classparser; 18 | 19 | import java.lang.ref.WeakReference; 20 | import java.util.HashMap; 21 | 22 | /** 23 | * A simple cache for weak values. 24 | * 25 | * @param 26 | * the key type 27 | * @param 28 | * the value type 29 | * @author Volker Berlin 30 | */ 31 | public class WeakValueCache { 32 | 33 | private final HashMap> map = new HashMap<>(); 34 | 35 | /** 36 | * Put a value 37 | * 38 | * @param key 39 | * the key 40 | * @param value 41 | * the value 42 | */ 43 | public void put( K key, V value ) { 44 | map.put( key, new WeakReference( value ) ); 45 | } 46 | 47 | /** 48 | * Get the value if in the cache 49 | * 50 | * @param key 51 | * the key 52 | * @return the value or null 53 | */ 54 | public V get( K key ) { 55 | WeakReference valueRef = map.get( key ); 56 | return valueRef == null ? null : valueRef.get(); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/de/inetsoftware/classparser/Exceptions.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2017 Volker Berlin (i-net software) 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | 16 | */ 17 | package de.inetsoftware.classparser; 18 | 19 | import java.io.DataInputStream; 20 | import java.io.IOException; 21 | 22 | /** 23 | * Exceptions attribute of methods. 24 | * 25 | * @author Volker Berlin 26 | */ 27 | public class Exceptions { 28 | 29 | ConstantClass[] classes; 30 | 31 | /** 32 | * Read the Exceptions structure. 33 | * http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html#jvms-4.7.5 34 | * http://docs.oracle.com/javase/specs/jvms/se5.0/html/ClassFile.doc.html#3129 35 | * 36 | * @param input 37 | * @param constantPool 38 | * @throws IOException 39 | */ 40 | Exceptions( DataInputStream input, ConstantPool constantPool ) throws IOException { 41 | int count = input.readUnsignedShort(); 42 | classes = new ConstantClass[count]; 43 | for( int i = 0; i < count; i++ ) { 44 | int idx = input.readUnsignedShort(); 45 | classes[i] = (ConstantClass)constantPool.get( idx ); 46 | } 47 | } 48 | 49 | public ConstantClass[] getClasses() { 50 | return classes; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/de/inetsoftware/jwebassembly/binary/ImportFunction.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 Volker Berlin (i-net software) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package de.inetsoftware.jwebassembly.binary; 17 | 18 | import java.io.IOException; 19 | import java.nio.charset.StandardCharsets; 20 | 21 | /** 22 | * An entry in the import section of the WebAssembly. 23 | * 24 | * @author Volker Berlin 25 | */ 26 | class ImportFunction extends Function { 27 | 28 | final String module; 29 | 30 | final String name; 31 | 32 | ImportFunction( String module, String name ) { 33 | this.module = module; 34 | this.name = name; 35 | } 36 | 37 | /** 38 | * {@inheritDoc} 39 | */ 40 | @Override 41 | void writeSectionEntry( WasmOutputStream stream ) throws IOException { 42 | byte[] bytes = this.module.getBytes( StandardCharsets.UTF_8 ); 43 | stream.writeVaruint32( bytes.length ); 44 | stream.write( bytes ); 45 | bytes = this.name.getBytes( StandardCharsets.UTF_8 ); 46 | stream.writeVaruint32( bytes.length ); 47 | stream.write( bytes ); 48 | stream.writeVaruint32( ExternalKind.Function.ordinal() ); 49 | stream.writeVaruint32( this.typeId ); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/de/inetsoftware/jwebassembly/module/nativecode/ReplacementForMethodHandles.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2023 Volker Berlin (i-net software) 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | 16 | */ 17 | package de.inetsoftware.jwebassembly.module.nativecode; 18 | 19 | import java.lang.invoke.MethodHandles.Lookup; 20 | 21 | import de.inetsoftware.jwebassembly.api.annotation.Replace; 22 | 23 | /** 24 | * Replacement for java.lang.invoke.MethodHandles 25 | * 26 | * @author Volker Berlin 27 | */ 28 | public class ReplacementForMethodHandles { 29 | 30 | /** 31 | * Replacement for static code. 32 | */ 33 | @Replace( "java/lang/invoke/MethodHandles.()V" ) 34 | private static void init() { 35 | // nothing 36 | } 37 | 38 | /** 39 | * Replacement for static lookup(). 40 | */ 41 | @Replace( "java/lang/invoke/MethodHandles.lookup()Ljava/lang/invoke/MethodHandles$Lookup;" ) 42 | static Lookup lookup() { 43 | return null; 44 | } 45 | 46 | /** 47 | * Replacement for static lookup(). 48 | */ 49 | @Replace( "java/lang/invoke/MethodHandles$Lookup.findVarHandle(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/Class;)Ljava/lang/invoke/VarHandle;" ) 50 | Object findVarHandle(Class recv, String name, Class type) { 51 | return null; 52 | } 53 | 54 | } 55 | -------------------------------------------------------------------------------- /src/de/inetsoftware/jwebassembly/binary/ExportEntry.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Volker Berlin (i-net software) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package de.inetsoftware.jwebassembly.binary; 17 | 18 | import java.io.IOException; 19 | 20 | /** 21 | * An entry in the function section of the WebAssembly. 22 | * 23 | * @author Volker Berlin 24 | */ 25 | class ExportEntry extends SectionEntry { 26 | 27 | private String name; 28 | 29 | private ExternalKind kind; 30 | 31 | private int id; 32 | 33 | /** 34 | * Create an entry for the export section. This section contains a mapping from the external index to the type 35 | * signature index. 36 | * 37 | * @param name 38 | * the exported name 39 | * @param kind 40 | * the type of exported object 41 | * @param id 42 | * the id inside the list of the related type 43 | */ 44 | ExportEntry( String name, ExternalKind kind, int id ) { 45 | this.name = name; 46 | this.kind = kind; 47 | this.id = id; 48 | } 49 | 50 | /** 51 | * {@inheritDoc} 52 | */ 53 | @Override 54 | void writeSectionEntry( WasmOutputStream stream ) throws IOException { 55 | stream.writeString( name ); 56 | stream.writeVaruint32( kind.ordinal() ); 57 | stream.writeVaruint32( id ); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/de/inetsoftware/jwebassembly/binary/TypeEntry.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Volker Berlin (i-net software) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package de.inetsoftware.jwebassembly.binary; 17 | 18 | import java.io.IOException; 19 | 20 | import de.inetsoftware.jwebassembly.wasm.ValueType; 21 | 22 | /** 23 | * An entry in the type section of the WebAssembly. 24 | * 25 | * @author Volker Berlin 26 | */ 27 | abstract class TypeEntry extends SectionEntry { 28 | 29 | /** 30 | * {@inheritDoc} 31 | */ 32 | @Override 33 | final void writeSectionEntry( WasmOutputStream stream ) throws IOException { 34 | stream.writeValueType( getTypeForm() ); 35 | writeSectionEntryDetails( stream ); 36 | } 37 | 38 | /** 39 | * Get the form of the type. 40 | * @return the form 41 | */ 42 | abstract ValueType getTypeForm(); 43 | 44 | /** 45 | * Write this single entry to a section 46 | * 47 | * @param stream 48 | * the target 49 | * @throws IOException 50 | * if any I/O error occur 51 | */ 52 | abstract void writeSectionEntryDetails( WasmOutputStream stream ) throws IOException; 53 | 54 | /** 55 | * {@inheritDoc} 56 | */ 57 | @Override 58 | public abstract int hashCode(); 59 | 60 | /** 61 | * {@inheritDoc} 62 | */ 63 | @Override 64 | public abstract boolean equals( Object obj ); 65 | } 66 | -------------------------------------------------------------------------------- /test/de/inetsoftware/jwebassembly/runtime/StaticValues.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 - 2019 Volker Berlin (i-net software) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package de.inetsoftware.jwebassembly.runtime; 17 | 18 | import java.util.ArrayList; 19 | import java.util.Collection; 20 | 21 | import org.junit.ClassRule; 22 | import org.junit.runners.Parameterized.Parameters; 23 | 24 | import de.inetsoftware.jwebassembly.ScriptEngine; 25 | import de.inetsoftware.jwebassembly.WasmRule; 26 | import de.inetsoftware.jwebassembly.api.annotation.Export; 27 | 28 | public class StaticValues extends AbstractBaseTest { 29 | 30 | @ClassRule 31 | public static WasmRule rule = new WasmRule( TestClass.class ); 32 | 33 | public StaticValues( ScriptEngine script, String method, Object[] params ) { 34 | super( rule, script, method, params ); 35 | } 36 | 37 | @Parameters( name = "{0}-{1}" ) 38 | public static Collection data() { 39 | ArrayList list = new ArrayList<>(); 40 | for( ScriptEngine script : ScriptEngine.testEngines() ) { 41 | addParam( list, script, "abc" ); 42 | } 43 | rule.setTestParameters( list ); 44 | return list; 45 | } 46 | 47 | static class TestClass { 48 | 49 | static int condition; 50 | 51 | @Export 52 | static int abc() { 53 | condition = 42; 54 | return condition; 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/de/inetsoftware/jwebassembly/module/ImportSyntheticFunctionName.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2019 Volker Berlin (i-net software) 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | 16 | */ 17 | package de.inetsoftware.jwebassembly.module; 18 | 19 | import java.util.function.Function; 20 | 21 | /** 22 | * Synthetic/dynamic method based on import annotation. 23 | * 24 | * @author Volker Berlin 25 | */ 26 | class ImportSyntheticFunctionName extends SyntheticFunctionName { 27 | 28 | private final Function importAnannotation; 29 | 30 | /** 31 | * create a new instance 32 | * 33 | * @param className 34 | * the Java class name 35 | * @param name 36 | * the function name 37 | * @param signature 38 | * the method signature, first the parameters, then null and the the return types 39 | * @param importAnannotation 40 | * the annotations 41 | */ 42 | ImportSyntheticFunctionName( String className, String name, String signature, Function importAnannotation ) { 43 | super( className, name, signature ); 44 | this.importAnannotation = importAnannotation; 45 | } 46 | 47 | /** 48 | * {@inheritDoc} 49 | */ 50 | @Override 51 | protected boolean hasWasmCode() { 52 | return false; 53 | } 54 | 55 | /** 56 | * {@inheritDoc} 57 | */ 58 | @Override 59 | protected Function getAnnotation() { 60 | return importAnannotation; 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/de/inetsoftware/jwebassembly/wasm/AnyType.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 - 2020 Volker Berlin (i-net software) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package de.inetsoftware.jwebassembly.wasm; 17 | 18 | import javax.annotation.Nonnull; 19 | 20 | /** 21 | * Interface of all possible types in WebAssembly. This are predefined (native) types and custom types in the type section. 22 | *

23 |  * numtype ::= i32 | i64 | f32 | f64
24 |  * packedtype ::= i8 | i16
25 |  * reftype ::= anyref | funcref | nullref
26 |  * valtype ::= numtype | reftype
27 |  * deftype ::= functype | structtype | arraytype
28 |  * 
29 |  * storagetype ::= valtype | packedtype
30 |  * 
31 | * @author Volker Berlin 32 | */ 33 | public interface AnyType { 34 | 35 | /** 36 | * The type code(typeidx) in WebAssembly. Predefined types have an negative typeidx. Custom types have the positive index in the type section. 37 | * 38 | * @return the code 39 | */ 40 | public int getCode(); 41 | 42 | /** 43 | * If the type is a reference type. A GC reference to the heap. 44 | * 45 | * @return true, is GC type 46 | */ 47 | public boolean isRefType(); 48 | 49 | /** 50 | * Check if this is a sub type of given type. 51 | * 52 | * @param other 53 | * type to check 54 | * @return true, if both are identical or this is a sub type of other. Or if other is a parent type of this. 55 | */ 56 | public boolean isSubTypeOf( @Nonnull AnyType other ); 57 | } 58 | -------------------------------------------------------------------------------- /src/de/inetsoftware/classparser/ConstantRef.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2017 - 2018 Volker Berlin (i-net software) 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | 16 | */ 17 | package de.inetsoftware.classparser; 18 | 19 | /** 20 | * A reference to an member that is described in the constant pool of a Java class. 21 | * 22 | * @author Volker Berlin 23 | */ 24 | public abstract class ConstantRef implements Member { 25 | 26 | private final ConstantClass constClass; 27 | 28 | private final ConstantNameAndType nameAndType; 29 | 30 | /** 31 | * Create a new instance. 32 | * 33 | * @param constClass 34 | * the class description 35 | * @param nameAndType 36 | * the name and type description 37 | */ 38 | ConstantRef( ConstantClass constClass, ConstantNameAndType nameAndType ) { 39 | this.constClass = constClass; 40 | this.nameAndType = nameAndType; 41 | } 42 | 43 | /** 44 | * {@inheritDoc} 45 | */ 46 | @Override 47 | public String getName() { 48 | return nameAndType.getName(); 49 | } 50 | 51 | /** 52 | * {@inheritDoc} 53 | */ 54 | @Override 55 | public String getClassName() { 56 | return getConstantClass().getName(); 57 | } 58 | 59 | /** 60 | * Get the type of the method. For example "(Ljava.lang.String;)I" 61 | */ 62 | @Override 63 | public String getType() { 64 | return nameAndType.getType(); 65 | } 66 | 67 | public ConstantClass getConstantClass() { 68 | return constClass; 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to JWebAssembly 2 | 3 | If you want contribute to JWebAssembly then you can: 4 | 5 | ## Write suggestions 6 | 7 | Post a [recommendation](https://github.com/i-net-software/JWebAssembly/issues) or comments on existing recommendation. Such recommendations can to the API or to a runtime library. 8 | 9 | ## Write a third party tool/plugin/library 10 | 11 | We need a large infrastructure on tools that based on JWebAssembly. We will happy to support you. For example with specific features. Inform us if you have start and we can link your project. 12 | 13 | ## Test JWebAssembly 14 | 15 | Currently it is a little difficult to test JWebAssembly because the missing infrastructure. If you find problems, we will appreciate it if you post a [bug report](https://github.com/i-net-software/JWebAssembly/issues). 16 | 17 | # Pull Requests (PR) 18 | 19 | If you want contribute to JWebAssembly via a PR then 20 | 21 | * Notify us if you work on some larger changes to prevent conflicts with other. 22 | 23 | * Checkin only needed files for the PR. 24 | 25 | * Does not reformat existing files. Format new code with the same style as existing code. 26 | 27 | * Write API documentation for new code. 28 | 29 | * Write tests for your code. Preferred are functional tests that compile Java code to Wasm code. 30 | 31 | * Run the test locally before commit to prevent a regression. 32 | 33 | * Do the smallest possible PR. If there bugs that block a feature PR then create a separatly PR for the bug. A easer to review a smaller PR. 34 | 35 | ## Where to start? 36 | 37 | * In the issues some issue are marked with "good first issue". 38 | 39 | * In the sister project https://github.com/i-net-software/JWebAssembly-API/tree/master/src/de/inetsoftware/jwebassembly/web/dom there are many wrappers to complete for the API on the web. 40 | 41 | * replacement for native Java methods https://github.com/i-net-software/JWebAssembly-API/tree/master/src/de/inetsoftware/jwebassembly/api. Write pure Java code for some native Java methods for example java.util.zip.Adler32 or find JavaScript replacements. You can see how you can do this in the examples already implemented. 42 | -------------------------------------------------------------------------------- /test/de/inetsoftware/jwebassembly/sourcemap/SourceMapWriterTest.java: -------------------------------------------------------------------------------- 1 | package de.inetsoftware.jwebassembly.sourcemap; 2 | 3 | import static org.junit.Assert.assertEquals; 4 | 5 | import java.io.IOException; 6 | 7 | import org.junit.Test; 8 | 9 | public class SourceMapWriterTest { 10 | 11 | @Test 12 | public void simple() throws IOException { 13 | SourceMapWriter map = new SourceMapWriter( null ); 14 | 15 | map.addMapping( new SourceMapping( 0, 1, "Test1.java" ) ); 16 | map.addMapping( new SourceMapping( 5, 2, "Test1.java" ) ); 17 | map.addMapping( new SourceMapping( 0, 4, "Test2.java" ) ); 18 | map.addMapping( new SourceMapping( 5, 9, "Test2.java" ) ); 19 | 20 | StringBuilder generate = new StringBuilder(); 21 | map.generate( generate ); 22 | String expected = "{\n" + 23 | "\"version\":3,\n" + 24 | "\"sources\":[\"Test1.java\",\"Test2.java\"],\n" + 25 | "\"names\":[],\n" + 26 | "\"mappings\":\"AAAA,KACA,LCEA,KAKA;\"\n" + 27 | "}"; 28 | assertEquals( expected, generate.toString() ); 29 | } 30 | 31 | @Test 32 | public void sourceRootNotNull() throws IOException { 33 | SourceMapWriter map = new SourceMapWriter( "../../src/main/java/" ); 34 | 35 | map.addMapping( new SourceMapping( 0, 1, "Test1.java" ) ); 36 | map.addMapping( new SourceMapping( 5, 2, "Test1.java" ) ); 37 | map.addMapping( new SourceMapping( 0, 4, "Test2.java" ) ); 38 | map.addMapping( new SourceMapping( 5, 9, "Test2.java" ) ); 39 | 40 | StringBuilder generate = new StringBuilder(); 41 | map.generate( generate ); 42 | String expected = "{\n" + 43 | "\"version\":3,\n" + 44 | "\"sourceRoot\":\"../../src/main/java/\",\n" + 45 | "\"sources\":[\"Test1.java\",\"Test2.java\"],\n" + 46 | "\"names\":[],\n" + 47 | "\"mappings\":\"AAAA,KACA,LCEA,KAKA;\"\n" + 48 | "}"; 49 | assertEquals( expected, generate.toString() ); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/de/inetsoftware/jwebassembly/module/WasmNopInstruction.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2018 - 2021 Volker Berlin (i-net software) 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | 16 | */ 17 | package de.inetsoftware.jwebassembly.module; 18 | 19 | import java.io.IOException; 20 | 21 | import javax.annotation.Nonnull; 22 | 23 | import de.inetsoftware.jwebassembly.wasm.AnyType; 24 | 25 | /** 26 | * WasmInstruction for nop. 27 | * 28 | * @author Volker Berlin 29 | * 30 | */ 31 | class WasmNopInstruction extends WasmInstruction { 32 | 33 | /** 34 | * Create an instance of a nop instruction 35 | * 36 | * @param javaCodePos 37 | * the code position/offset in the Java method 38 | * @param lineNumber 39 | * the line number in the Java source code 40 | */ 41 | WasmNopInstruction( int javaCodePos, int lineNumber ) { 42 | super( javaCodePos, lineNumber ); 43 | } 44 | 45 | /** 46 | * {@inheritDoc} 47 | */ 48 | @Override 49 | Type getType() { 50 | return Type.Nop; 51 | } 52 | 53 | /** 54 | * {@inheritDoc} 55 | */ 56 | public void writeTo( @Nonnull ModuleWriter writer ) throws IOException { 57 | // nothing 58 | } 59 | 60 | /** 61 | * {@inheritDoc} 62 | */ 63 | AnyType getPushValueType() { 64 | return null; 65 | } 66 | 67 | /** 68 | * {@inheritDoc} 69 | */ 70 | @Override 71 | int getPopCount() { 72 | return 0; 73 | } 74 | 75 | /** 76 | * {@inheritDoc} 77 | */ 78 | @Override 79 | AnyType[] getPopValueTypes() { 80 | return null; 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /test/de/inetsoftware/jwebassembly/runtime/MultiArrayOperations.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Volker Berlin (i-net software) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package de.inetsoftware.jwebassembly.runtime; 17 | 18 | import java.util.ArrayList; 19 | import java.util.Arrays; 20 | import java.util.Collection; 21 | import java.util.zip.CRC32; 22 | 23 | import org.junit.Assume; 24 | import org.junit.ClassRule; 25 | import org.junit.Test; 26 | import org.junit.runners.Parameterized.Parameters; 27 | 28 | import de.inetsoftware.jwebassembly.ScriptEngine; 29 | import de.inetsoftware.jwebassembly.WasmRule; 30 | import de.inetsoftware.jwebassembly.api.annotation.Export; 31 | 32 | public class MultiArrayOperations extends AbstractBaseTest { 33 | 34 | @ClassRule 35 | public static WasmRule rule = new WasmRule( TestClass.class ); 36 | 37 | public MultiArrayOperations( ScriptEngine script, String method, Object[] params ) { 38 | super( rule, script, method, params ); 39 | } 40 | 41 | @Parameters( name = "{0}-{1}" ) 42 | public static Collection data() { 43 | ArrayList list = new ArrayList<>(); 44 | 45 | ScriptEngine[] engines = ScriptEngine.testEngines(); 46 | for( ScriptEngine script : engines ) { 47 | addParam( list, script, "multi" ); 48 | } 49 | rule.setTestParameters( list ); 50 | return list; 51 | } 52 | 53 | @Test 54 | @Override 55 | public void test() { 56 | super.test(); 57 | } 58 | 59 | static class TestClass { 60 | 61 | @Export 62 | static int multi() { 63 | int[][][] val = new int[1][2][3]; 64 | return val.length; 65 | } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/de/inetsoftware/jwebassembly/module/WasmLoadStoreInstruction.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2018 - 2022 Volker Berlin (i-net software) 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | 16 | */ 17 | package de.inetsoftware.jwebassembly.module; 18 | 19 | import javax.annotation.Nonnegative; 20 | import javax.annotation.Nonnull; 21 | 22 | import de.inetsoftware.jwebassembly.wasm.VariableOperator; 23 | 24 | /** 25 | * WasmInstruction for load and store local variables. 26 | * 27 | * @author Volker Berlin 28 | * 29 | */ 30 | class WasmLoadStoreInstruction extends WasmLocalInstruction { 31 | 32 | /** 33 | * Create an instance of a load/store instruction 34 | * 35 | * @param op 36 | * the operation 37 | * @param slot 38 | * the memory/slot idx of the variable 39 | * @param localVariables 40 | * the manager for local variables 41 | * @param javaCodePos 42 | * the code position/offset in the Java method 43 | * @param lineNumber 44 | * the line number in the Java source code 45 | */ 46 | WasmLoadStoreInstruction( @Nonnull VariableOperator op, @Nonnegative int slot, LocaleVariableManager localVariables, int javaCodePos, int lineNumber ) { 47 | super( op, slot, localVariables, javaCodePos, lineNumber ); 48 | } 49 | 50 | /** 51 | * {@inheritDoc} 52 | */ 53 | @Override 54 | int getIndex() { 55 | return localVariables.get( super.getIndex(), getCodePosition() ); // translate slot index to position index 56 | } 57 | 58 | /** 59 | * Get the slot of this variable from Java 60 | * 61 | * @return the slot 62 | */ 63 | int getSlot() { 64 | return super.getIndex(); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/de/inetsoftware/classparser/TryCatchFinally.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2017 - 2021 Volker Berlin (i-net software) 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | 16 | */ 17 | package de.inetsoftware.classparser; 18 | 19 | import java.io.DataInputStream; 20 | import java.io.IOException; 21 | 22 | import javax.annotation.Nonnull; 23 | 24 | /** 25 | * @author Volker Berlin 26 | */ 27 | public class TryCatchFinally { 28 | 29 | private int start; 30 | 31 | private int end; 32 | 33 | private final int handler; 34 | 35 | private final ConstantClass type; 36 | 37 | /** 38 | * http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html#jvms-4.7.3 39 | * http://docs.oracle.com/javase/specs/jvms/se5.0/html/ClassFile.doc.html#1546 40 | * 41 | * @param input 42 | * @param constantPool 43 | * @throws IOException 44 | */ 45 | TryCatchFinally( DataInputStream input, @Nonnull ConstantPool constantPool ) throws IOException { 46 | start = input.readUnsignedShort(); 47 | end = input.readUnsignedShort(); 48 | handler = input.readUnsignedShort(); 49 | type = (ConstantClass)constantPool.get( input.readUnsignedShort() ); 50 | } 51 | 52 | public int getStart() { 53 | return start; 54 | } 55 | 56 | public int getEnd() { 57 | return end; 58 | } 59 | 60 | public int getHandler() { 61 | return handler; 62 | } 63 | 64 | public ConstantClass getType() { 65 | return type; 66 | } 67 | 68 | public boolean isFinally() { 69 | return type == null; 70 | } 71 | 72 | void setStart( int start ) { 73 | this.start = start; 74 | } 75 | 76 | void setEnd( int end ) { 77 | this.end = end; 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /src/de/inetsoftware/classparser/ConstantInvokeDynamic.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2019 - 2020 Volker Berlin (i-net software) 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | 16 | */ 17 | package de.inetsoftware.classparser; 18 | 19 | /** 20 | * @author Volker Berlin 21 | */ 22 | public class ConstantInvokeDynamic { 23 | 24 | private final ConstantNameAndType nameAndType; 25 | 26 | private final int bootstrapMethodIndex; 27 | 28 | /** 29 | * Invoke dynamic info in the constant pool. 30 | * https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.4.10 31 | * 32 | * @param bootstrapMethodAttrIndex 33 | * a valid index into the bootstrap_methods array of the bootstrap method table 34 | * @param nameAndType 35 | * the name and type 36 | */ 37 | ConstantInvokeDynamic( int bootstrapMethodAttrIndex, ConstantNameAndType nameAndType ) { 38 | this.bootstrapMethodIndex = bootstrapMethodAttrIndex; 39 | this.nameAndType = nameAndType; 40 | } 41 | 42 | /** 43 | * The simple name of the generated method of the single function interface. 44 | * 45 | * @return the name 46 | */ 47 | public String getName() { 48 | return nameAndType.getName(); 49 | } 50 | 51 | /** 52 | * Get the signature of the factory method. For example "()Ljava.lang.Runnable;" for the lamba expression 53 | * "Runnable run = () -> foo();" 54 | * 55 | * @return the type 56 | */ 57 | public String getType() { 58 | return nameAndType.getType(); 59 | } 60 | 61 | /** 62 | * Get the index to the bootstrap methods. 63 | * 64 | * @return the index 65 | */ 66 | public int getBootstrapMethodIndex() { 67 | return bootstrapMethodIndex; 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/de/inetsoftware/jwebassembly/module/nativecode/ReplacementForEnums.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021 - 2022 Volker Berlin (i-net software) 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | 16 | */ 17 | package de.inetsoftware.jwebassembly.module.nativecode; 18 | 19 | import java.util.HashMap; 20 | import java.util.Map; 21 | 22 | /** 23 | * Replacement for java.lang.Enum 24 | * 25 | * @author Volker Berlin 26 | */ 27 | public abstract class ReplacementForEnums { 28 | 29 | private static transient Map enumConstantDirectory; 30 | 31 | /** 32 | * Placeholder for existing public method. 33 | */ 34 | public native String name(); 35 | 36 | /** 37 | * Placeholder for existing public method. 38 | */ 39 | public native static ReplacementForEnums[] values(); 40 | 41 | /** 42 | * Replacement code for generated Enum.valueOf( String ) 43 | * @param name the enum name 44 | * @return The singleton instance for the name 45 | */ 46 | static ReplacementForEnums valueOf_( String name ) { 47 | Map map = enumConstantDirectory; 48 | if( map == null ) { 49 | ReplacementForEnums[] universe = values(); 50 | map = new HashMap<>( universe.length ); 51 | for( ReplacementForEnums constant : universe ) { 52 | map.put( constant.name(), constant ); 53 | } 54 | enumConstantDirectory = map; 55 | } 56 | 57 | ReplacementForEnums result = map.get( name ); 58 | if( result != null ) { 59 | return result; 60 | } 61 | if( name == null ) { 62 | throw new NullPointerException( "Name is null" ); 63 | } 64 | throw new IllegalArgumentException( "No enum constant " + ReplacementForEnums.class + "." + name ); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/de/inetsoftware/jwebassembly/sourcemap/SourceMapping.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Volker Berlin (i-net software) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package de.inetsoftware.jwebassembly.sourcemap; 17 | 18 | /** 19 | * Mapping for Source Map. 20 | */ 21 | public class SourceMapping { 22 | private int generatedColumn; 23 | 24 | private int sourceLine; 25 | 26 | private String sourceFileName; 27 | 28 | /** 29 | * Create a mapping between a Java code line and a WebAssembly code position 30 | * 31 | * @param generatedColumn 32 | * position in WebAssembly 33 | * @param sourceLine 34 | * Java source line 35 | * @param sourceFileName 36 | * Java source file 37 | */ 38 | public SourceMapping( int generatedColumn, int sourceLine, String sourceFileName ) { 39 | this.generatedColumn = generatedColumn; 40 | this.sourceLine = sourceLine - 1; // The first line is coded as zero 41 | this.sourceFileName = sourceFileName; 42 | } 43 | 44 | /** 45 | * The generated column. This is equals to the binary offset in the *.wasm file 46 | * 47 | * @return binary offset 48 | */ 49 | int getGeneratedColumn() { 50 | return generatedColumn; 51 | } 52 | 53 | /** 54 | * The source line 55 | * 56 | * @return the line number 57 | */ 58 | int getSourceLine() { 59 | return sourceLine; 60 | } 61 | 62 | /** 63 | * Source file name 64 | * 65 | * @return the name 66 | */ 67 | String getSourceFileName() { 68 | return sourceFileName; 69 | } 70 | 71 | /** 72 | * Ad an offset to the generated column 73 | * @param offset the offset 74 | */ 75 | public void addOffset( int offset ) { 76 | generatedColumn += offset; 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /src/de/inetsoftware/jwebassembly/binary/ArrayTypeEntry.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 Volker Berlin (i-net software) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package de.inetsoftware.jwebassembly.binary; 17 | 18 | import java.io.IOException; 19 | import java.util.List; 20 | 21 | import de.inetsoftware.jwebassembly.wasm.NamedStorageType; 22 | import de.inetsoftware.jwebassembly.wasm.ValueType; 23 | 24 | /** 25 | * An array type entry in the type section of the WebAssembly. 26 | * 27 | * @author Volker Berlin 28 | */ 29 | class ArrayTypeEntry extends TypeEntry { 30 | 31 | private final NamedStorageType field; 32 | 33 | /** 34 | * Create a new instance. 35 | * 36 | * @param fields 37 | * the fields of the array 38 | */ 39 | ArrayTypeEntry( List fields ) { 40 | this.field = fields.get( 0 ); 41 | } 42 | 43 | /** 44 | * {@inheritDoc} 45 | */ 46 | @Override 47 | ValueType getTypeForm() { 48 | return ValueType.array; 49 | } 50 | 51 | /** 52 | * {@inheritDoc} 53 | */ 54 | @Override 55 | void writeSectionEntryDetails( WasmOutputStream stream ) throws IOException { 56 | stream.writeRefValueType( field.getType() ); 57 | stream.writeVarint( 1 ); // 0 - immutable; 1 - mutable 58 | } 59 | 60 | /** 61 | * {@inheritDoc} 62 | */ 63 | @Override 64 | public int hashCode() { 65 | return field.hashCode(); 66 | } 67 | 68 | /** 69 | * {@inheritDoc} 70 | */ 71 | @Override 72 | public boolean equals( Object obj ) { 73 | if( obj == this ) { 74 | return true; 75 | } 76 | if( obj == null || obj.getClass() != getClass() ) { 77 | return false; 78 | } 79 | ArrayTypeEntry entry = (ArrayTypeEntry)obj; 80 | return field.equals( entry.field ); 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /src/de/inetsoftware/jwebassembly/javascript/JavaScriptSyntheticFunctionName.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2019 Volker Berlin (i-net software) 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | 16 | */ 17 | package de.inetsoftware.jwebassembly.javascript; 18 | 19 | import java.util.function.Function; 20 | import java.util.function.Supplier; 21 | 22 | import de.inetsoftware.jwebassembly.module.ArraySyntheticFunctionName; 23 | import de.inetsoftware.jwebassembly.wasm.AnyType; 24 | 25 | /** 26 | * Synthetic JavaScript import function. 27 | * 28 | * @author Volker Berlin 29 | * 30 | */ 31 | public class JavaScriptSyntheticFunctionName extends ArraySyntheticFunctionName { 32 | 33 | private final Supplier js; 34 | 35 | /** 36 | * Create a synthetic function which based on imported, dynamic generated JavaScript. 37 | * 38 | * @param module 39 | * the module name 40 | * @param functionName 41 | * the name of the function 42 | * @param js 43 | * the dynamic JavaScript as a lambda expression 44 | * @param signature 45 | * the types of the signature 46 | */ 47 | public JavaScriptSyntheticFunctionName( String module, String functionName, Supplier js, AnyType... signature ) { 48 | super( module, functionName, signature ); 49 | this.js = js; 50 | } 51 | 52 | /** 53 | * {@inheritDoc} 54 | */ 55 | @Override 56 | protected boolean hasWasmCode() { 57 | return false; 58 | } 59 | 60 | /** 61 | * {@inheritDoc} 62 | */ 63 | @Override 64 | protected Function getAnnotation() { 65 | return ( key ) -> { 66 | switch( key ) { 67 | case JavaScriptWriter.JAVA_SCRIPT_CONTENT: 68 | return js.get(); 69 | default: 70 | } 71 | return null; 72 | }; 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /test/de/inetsoftware/jwebassembly/runtime/AbstractBaseTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 - 2019 Volker Berlin (i-net software) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package de.inetsoftware.jwebassembly.runtime; 17 | 18 | import java.util.ArrayList; 19 | 20 | import org.junit.Before; 21 | import org.junit.Test; 22 | import org.junit.runner.RunWith; 23 | import org.junit.runners.Parameterized; 24 | 25 | import de.inetsoftware.jwebassembly.ScriptEngine; 26 | import de.inetsoftware.jwebassembly.WasmRule; 27 | 28 | /** 29 | * @author Volker Berlin 30 | */ 31 | @RunWith( Parameterized.class ) 32 | public abstract class AbstractBaseTest { 33 | 34 | private final WasmRule wasm; 35 | 36 | private final ScriptEngine script; 37 | 38 | private final String method; 39 | 40 | private final Object[] params; 41 | 42 | protected AbstractBaseTest( WasmRule wasm, ScriptEngine script, String method, Object[] params ) { 43 | this.wasm = wasm; 44 | this.script = script; 45 | this.method = method; 46 | this.params = params; 47 | } 48 | 49 | protected static void addParam( ArrayList list, ScriptEngine script, String method, Object ...params ) { 50 | list.add( new Object[]{script, method, params} ); 51 | } 52 | 53 | /** 54 | * Get the ScriptEngine with which the test is running. 55 | * 56 | * @return the engine 57 | */ 58 | protected ScriptEngine getScriptEngine() { 59 | return script; 60 | } 61 | 62 | /** 63 | * Get the name of the method that is currently tested 64 | * @return the name 65 | */ 66 | protected String getMethod() { 67 | return method; 68 | } 69 | 70 | @Before 71 | public void before() throws Exception { 72 | wasm.before( script ); 73 | } 74 | 75 | @Test 76 | public void test() { 77 | wasm.test( script, method, params ); 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /test/de/inetsoftware/jwebassembly/runtime/Checksums.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Volker Berlin (i-net software) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package de.inetsoftware.jwebassembly.runtime; 17 | 18 | import java.util.ArrayList; 19 | import java.util.Collection; 20 | import java.util.zip.CRC32; 21 | 22 | import org.junit.ClassRule; 23 | import org.junit.runners.Parameterized.Parameters; 24 | 25 | import de.inetsoftware.jwebassembly.ScriptEngine; 26 | import de.inetsoftware.jwebassembly.WasmRule; 27 | import de.inetsoftware.jwebassembly.api.annotation.Export; 28 | 29 | /** 30 | * @author Volker Berlin 31 | */ 32 | public class Checksums extends AbstractBaseTest { 33 | 34 | @ClassRule 35 | public static WasmRule rule = new WasmRule( TestClass.class ); 36 | 37 | public Checksums( ScriptEngine script, String method, Object[] params ) { 38 | super( rule, script, method, params ); 39 | } 40 | 41 | @Parameters(name="{0}-{1}") 42 | public static Collection data() { 43 | ArrayList list = new ArrayList<>(); 44 | for( ScriptEngine script : ScriptEngine.testEngines() ) { 45 | addParam( list, script, "crcUpdate" ); 46 | addParam( list, script, "crcUpdateBytes" ); 47 | } 48 | rule.setTestParameters( list ); 49 | return list; 50 | } 51 | 52 | static class TestClass { 53 | 54 | @Export 55 | static int crcUpdate() { 56 | CRC32 crc = new CRC32(); 57 | crc.update( 42 ); 58 | return (int)crc.getValue(); 59 | } 60 | 61 | @Export 62 | static int crcUpdateBytes() { 63 | CRC32 crc = new CRC32(); 64 | byte[] a = new byte[1000]; 65 | for( int i = 0; i < a.length; i++ ) { 66 | a[i] = (byte)i; 67 | } 68 | crc.update( a ); 69 | return (int)crc.getValue(); 70 | } 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /src/de/inetsoftware/jwebassembly/module/SyntheticFunctionName.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2019 - 2021 Volker Berlin (i-net software) 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | 16 | */ 17 | package de.inetsoftware.jwebassembly.module; 18 | 19 | import java.util.function.Function; 20 | 21 | import de.inetsoftware.jwebassembly.watparser.WatParser; 22 | 23 | /** 24 | * Synthetic/dynamic method. 25 | * 26 | * @author Volker Berlin 27 | */ 28 | public abstract class SyntheticFunctionName extends FunctionName { 29 | 30 | /** 31 | * Create a new instance. 32 | * 33 | * @param className 34 | * the Java class name 35 | * @param name 36 | * the function name 37 | * @param signature 38 | * the method signature, first the parameters, then null and the the return types 39 | */ 40 | public SyntheticFunctionName( String className, String name, String signature ) { 41 | super( className, name, signature ); 42 | } 43 | 44 | /** 45 | * If this function has WASM code or if this function is a import with JavaScript code. 46 | * 47 | * @return true, if WASM code 48 | */ 49 | protected abstract boolean hasWasmCode(); 50 | 51 | /** 52 | * Get the WasmCodeBuilder for the synthetic WASM code. 53 | * 54 | * @param watParser 55 | * a helping WatParser 56 | * @return the code 57 | */ 58 | protected WasmCodeBuilder getCodeBuilder( WatParser watParser ) { 59 | return null; 60 | } 61 | 62 | /** 63 | * Get the synthetic annotation of a import function. 64 | * 65 | * @return the annotation 66 | */ 67 | protected Function getAnnotation() { 68 | return null; 69 | } 70 | 71 | /** 72 | * Is a static method or if it need a this parameter. 73 | * 74 | * @return true, id static 75 | */ 76 | protected boolean istStatic() { 77 | return true; 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /src/de/inetsoftware/jwebassembly/wasm/ValueType.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 - 2022 Volker Berlin (i-net software) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package de.inetsoftware.jwebassembly.wasm; 17 | 18 | /** 19 | * @author Volker Berlin 20 | */ 21 | public enum ValueType implements AnyType { 22 | i32(-0x01), 23 | i64(-0x02), 24 | f32(-0x03), 25 | f64(-0x04), 26 | v128(-0x05), 27 | bool(-0x06), 28 | i8(-0x06), 29 | i16(-0x07), 30 | u16(-0x07), 31 | funcref(-0x10), 32 | externref(-0x11), //TODO rename to any 33 | anyref(-0x12), // TODO obsolete 34 | eqref(-0x13), 35 | optref(-0x14), 36 | ref(-0x15), 37 | exnref(-0x18), // https://github.com/WebAssembly/exception-handling/blob/master/proposals/Exceptions.md 38 | func(-0x20), 39 | struct(-0x21), 40 | array(-0x22), 41 | empty(-0x40), // empty/void block_type 42 | ; 43 | 44 | private final int code; 45 | 46 | /** 47 | * Create instance of the enum 48 | * 49 | * @param code 50 | * the operation code in WebAssembly 51 | */ 52 | private ValueType( int code ) { 53 | this.code = code; 54 | } 55 | 56 | /** 57 | * The operation code in WebAssembly. 58 | * 59 | * @return the code 60 | */ 61 | @Override 62 | public int getCode() { 63 | return code; 64 | } 65 | 66 | /** 67 | * {@inheritDoc} 68 | */ 69 | @Override 70 | public boolean isRefType() { 71 | return false; 72 | } 73 | 74 | /** 75 | * {@inheritDoc} 76 | */ 77 | @Override 78 | public boolean isSubTypeOf( AnyType type ) { 79 | if( type == this ) { 80 | return true; 81 | } 82 | switch( this ) { 83 | case externref: 84 | return type.isRefType(); 85 | case eqref: 86 | return type.isRefType() || type == externref; 87 | default: 88 | return false; 89 | } 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /src/de/inetsoftware/jwebassembly/module/CodeOptimizer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 - 2020 Volker Berlin (i-net software) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package de.inetsoftware.jwebassembly.module; 17 | 18 | import java.util.List; 19 | 20 | import de.inetsoftware.jwebassembly.module.WasmInstruction.Type; 21 | import de.inetsoftware.jwebassembly.wasm.VariableOperator; 22 | 23 | /** 24 | * Optimize the code of a single method/function through using of WebAssembly features without equivalent in Java. 25 | * 26 | * @author Volker Berlin 27 | */ 28 | class CodeOptimizer { 29 | 30 | /** 31 | * Optimize the code before writing. 32 | * 33 | * @param instructions 34 | * the list of instructions 35 | */ 36 | void optimize( List instructions ) { 37 | for( int i = instructions.size()-1; i >= 0; i-- ) { 38 | WasmInstruction instr = instructions.get( i ); 39 | switch( instr.getType() ) { 40 | case Local: 41 | // merge local.set, local.get --> local.tee 42 | if( i == 0 ) { 43 | continue; 44 | } 45 | if( instructions.get( i-1 ).getType() != Type.Local ) { 46 | continue; 47 | } 48 | WasmLocalInstruction local1 = (WasmLocalInstruction)instructions.get( i-1 ); 49 | WasmLocalInstruction local2 = (WasmLocalInstruction)instr; 50 | if( local1.getIndex() != local2.getIndex() ) { 51 | continue; 52 | } 53 | if( local1.getOperator() == VariableOperator.set && local2.getOperator() == VariableOperator.get ) { 54 | local1.setOperator( VariableOperator.tee ); 55 | instructions.remove( i ); 56 | } 57 | break; 58 | default: 59 | } 60 | } 61 | 62 | } 63 | 64 | } 65 | -------------------------------------------------------------------------------- /src/de/inetsoftware/jwebassembly/binary/FunctionTypeEntry.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 - 2019 Volker Berlin (i-net software) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package de.inetsoftware.jwebassembly.binary; 17 | 18 | import java.io.IOException; 19 | import java.util.ArrayList; 20 | import java.util.List; 21 | 22 | import de.inetsoftware.jwebassembly.wasm.AnyType; 23 | import de.inetsoftware.jwebassembly.wasm.ValueType; 24 | 25 | /** 26 | * An entry in the type section of the WebAssembly. 27 | * 28 | * @author Volker Berlin 29 | */ 30 | class FunctionTypeEntry extends TypeEntry { 31 | 32 | final List params = new ArrayList<>(); 33 | 34 | final List results = new ArrayList<>(); 35 | 36 | /** 37 | * {@inheritDoc} 38 | */ 39 | @Override 40 | ValueType getTypeForm() { 41 | return ValueType.func; 42 | } 43 | 44 | /** 45 | * {@inheritDoc} 46 | */ 47 | @Override 48 | void writeSectionEntryDetails( WasmOutputStream stream ) throws IOException { 49 | stream.writeVaruint32( this.params.size() ); 50 | for( AnyType valueType : this.params ) { 51 | stream.writeRefValueType( valueType ); 52 | } 53 | stream.writeVaruint32( this.results.size() ); 54 | for( AnyType valueType : this.results ) { 55 | stream.writeRefValueType( valueType ); 56 | } 57 | } 58 | 59 | /** 60 | * {@inheritDoc} 61 | */ 62 | @Override 63 | public int hashCode() { 64 | return params.hashCode() + 31 * results.hashCode(); 65 | } 66 | 67 | /** 68 | * {@inheritDoc} 69 | */ 70 | @Override 71 | public boolean equals( Object obj ) { 72 | if( obj == this ) { 73 | return true; 74 | } 75 | if( obj == null || obj.getClass() != getClass() ) { 76 | return false; 77 | } 78 | FunctionTypeEntry type = (FunctionTypeEntry)obj; 79 | return params.equals( type.params ) && results.equals( type.results ); 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /src/de/inetsoftware/jwebassembly/binary/StructTypeEntry.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Volker Berlin (i-net software) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package de.inetsoftware.jwebassembly.binary; 17 | 18 | import java.io.IOException; 19 | import java.util.List; 20 | 21 | import de.inetsoftware.jwebassembly.wasm.NamedStorageType; 22 | import de.inetsoftware.jwebassembly.wasm.ValueType; 23 | 24 | /** 25 | * An struct type entry in the type section of the WebAssembly. 26 | * 27 | * @author Volker Berlin 28 | */ 29 | class StructTypeEntry extends TypeEntry { 30 | 31 | private final List fields; 32 | 33 | /** 34 | * Create a new instance. 35 | * 36 | * @param fields 37 | * the fields of the struct 38 | */ 39 | StructTypeEntry( List fields ) { 40 | this.fields = fields; 41 | } 42 | 43 | /** 44 | * {@inheritDoc} 45 | */ 46 | @Override 47 | ValueType getTypeForm() { 48 | return ValueType.struct; 49 | } 50 | 51 | /** 52 | * {@inheritDoc} 53 | */ 54 | @Override 55 | void writeSectionEntryDetails( WasmOutputStream stream ) throws IOException { 56 | stream.writeVaruint32( this.fields.size() ); 57 | for( NamedStorageType field : this.fields ) { 58 | stream.writeRefValueType( field.getType() ); 59 | stream.writeVarint( 1 ); // 0 - immutable; 1 - mutable 60 | } 61 | } 62 | 63 | /** 64 | * {@inheritDoc} 65 | */ 66 | @Override 67 | public int hashCode() { 68 | return fields.hashCode(); 69 | } 70 | 71 | /** 72 | * {@inheritDoc} 73 | */ 74 | @Override 75 | public boolean equals( Object obj ) { 76 | if( obj == this ) { 77 | return true; 78 | } 79 | if( obj == null || obj.getClass() != getClass() ) { 80 | return false; 81 | } 82 | StructTypeEntry type = (StructTypeEntry)obj; 83 | return fields.equals( type.fields ); 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /src/de/inetsoftware/jwebassembly/sourcemap/Base64VLQ.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Volker Berlin (i-net software) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package de.inetsoftware.jwebassembly.sourcemap; 17 | 18 | import java.io.IOException; 19 | 20 | /** 21 | * Encode an integer value as Base64VLQ 22 | */ 23 | class Base64VLQ { 24 | private static final int VLQ_BASE_SHIFT = 5; 25 | 26 | private static final int VLQ_BASE = 1 << VLQ_BASE_SHIFT; 27 | 28 | private static final int VLQ_BASE_MASK = VLQ_BASE - 1; 29 | 30 | private static final int VLQ_CONTINUATION_BIT = VLQ_BASE; 31 | 32 | private static final String BASE64_MAP = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; 33 | 34 | /** 35 | * no instance 36 | */ 37 | private Base64VLQ() { 38 | // nothing 39 | } 40 | 41 | /** 42 | * Move the signet bit from the first position (two-complement value) to the last bit position. 43 | * 44 | * examples: 1 -> 2; -1 -> 3; 2 -> 4; -2 -> 5 45 | * 46 | * @param value 47 | * two-complement value 48 | * @return converted value 49 | */ 50 | private static int toVLQSigned( int value ) { 51 | return (value < 0) ? (((-value) << 1) + 1) : ((value << 1) + 0); 52 | } 53 | 54 | /** 55 | * Writes a VLQ encoded value to the provide target. 56 | * 57 | * @param out 58 | * the target 59 | * @param value 60 | * the value 61 | * @throws IOException 62 | * if any I/O error occur 63 | */ 64 | static void appendBase64VLQ( Appendable out, int value ) throws IOException { 65 | value = toVLQSigned( value ); 66 | do { 67 | int digit = value & VLQ_BASE_MASK; 68 | value >>>= VLQ_BASE_SHIFT; 69 | if( value > 0 ) { 70 | digit |= VLQ_CONTINUATION_BIT; 71 | } 72 | out.append( BASE64_MAP.charAt( digit ) ); 73 | } while( value > 0 ); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /src/de/inetsoftware/jwebassembly/binary/Function.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 - 2019 Volker Berlin (i-net software) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package de.inetsoftware.jwebassembly.binary; 17 | 18 | import java.io.IOException; 19 | import java.util.ArrayList; 20 | import java.util.List; 21 | 22 | import de.inetsoftware.jwebassembly.sourcemap.SourceMapping; 23 | 24 | /** 25 | * An entry in the function section of the WebAssembly. 26 | * 27 | * @author Volker Berlin 28 | */ 29 | class Function extends SectionEntry { 30 | 31 | int id; 32 | 33 | int typeId; 34 | 35 | List paramNames; 36 | 37 | WasmOutputStream functionsStream; 38 | 39 | ArrayList sourceMappings; 40 | 41 | /** 42 | * {@inheritDoc} 43 | */ 44 | @Override 45 | void writeSectionEntry( WasmOutputStream stream ) throws IOException { 46 | stream.writeVaruint32( this.typeId ); 47 | } 48 | 49 | /** 50 | * Add code position marker for a source map. 51 | * 52 | * @param streamPosition 53 | * the position in the function stream 54 | * @param javaSourceLine 55 | * the position in the Java Source file 56 | * @param sourceFileName 57 | * the name of the Java source file 58 | */ 59 | void markCodePosition( int streamPosition, int javaSourceLine, String sourceFileName ) { 60 | if( sourceMappings == null ) { 61 | sourceMappings = new ArrayList<>(); 62 | } 63 | sourceMappings.add( new SourceMapping( streamPosition, javaSourceLine, sourceFileName ) ); 64 | } 65 | 66 | /** 67 | * Add an offset to the marked code position in the source map 68 | * 69 | * @param offset 70 | * the offset 71 | */ 72 | void addCodeOffset( int offset ) { 73 | if( sourceMappings != null ) { 74 | for( SourceMapping mapping : sourceMappings ) { 75 | mapping.addOffset( offset ); 76 | } 77 | } 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /src/de/inetsoftware/jwebassembly/module/ArraySyntheticFunctionName.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2019 - 2022 Volker Berlin (i-net software) 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | 16 | */ 17 | package de.inetsoftware.jwebassembly.module; 18 | 19 | import java.util.Arrays; 20 | import java.util.Iterator; 21 | 22 | import de.inetsoftware.jwebassembly.wasm.AnyType; 23 | 24 | /** 25 | * Synthetic/dynamic method with a signature as array of types. 26 | * 27 | * @author Volker Berlin 28 | */ 29 | public abstract class ArraySyntheticFunctionName extends SyntheticFunctionName { 30 | 31 | private final AnyType[] signatureTypes; 32 | 33 | /** 34 | * Create a new instance. 35 | * 36 | * @param className 37 | * the Java class name 38 | * @param name 39 | * the function name 40 | * @param signatureTypes 41 | * the method signature, first the parameters, then null and the the return types 42 | */ 43 | public ArraySyntheticFunctionName( String className, String name, AnyType... signatureTypes ) { 44 | this( className, name, "()V", signatureTypes ); //TODO better signature name 45 | } 46 | 47 | /** 48 | * Create a new instance. 49 | * 50 | * @param className 51 | * the Java class name 52 | * @param name 53 | * the function name 54 | * @param signature 55 | * the string signature 56 | * @param signatureTypes 57 | * the method signature, first the parameters, then null and the the return types 58 | */ 59 | public ArraySyntheticFunctionName( String className, String name, String signature, AnyType... signatureTypes ) { 60 | super( className, name, signature ); 61 | this.signatureTypes = signatureTypes; 62 | } 63 | 64 | /** 65 | * {@inheritDoc} 66 | */ 67 | @Override 68 | public Iterator getSignature( TypeManager types ) { 69 | if( signatureTypes != null ) { 70 | return Arrays.asList( signatureTypes ).iterator(); 71 | } else { 72 | return super.getSignature( types ); 73 | } 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /test/de/inetsoftware/jwebassembly/runtime/Stacks.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 - 2019 Volker Berlin (i-net software) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package de.inetsoftware.jwebassembly.runtime; 17 | 18 | import java.util.ArrayList; 19 | import java.util.Collection; 20 | 21 | import org.junit.ClassRule; 22 | import org.junit.runners.Parameterized.Parameters; 23 | 24 | import de.inetsoftware.jwebassembly.ScriptEngine; 25 | import de.inetsoftware.jwebassembly.WasmRule; 26 | import de.inetsoftware.jwebassembly.api.annotation.Export; 27 | 28 | public class Stacks extends AbstractBaseTest { 29 | 30 | @ClassRule 31 | public static WasmRule rule = new WasmRule( TestClass.class ); 32 | 33 | public Stacks( ScriptEngine script, String method, Object[] params ) { 34 | super( rule, script, method, params ); 35 | } 36 | 37 | @Parameters( name = "{0}-{1}" ) 38 | public static Collection data() { 39 | ArrayList list = new ArrayList<>(); 40 | for( ScriptEngine script : ScriptEngine.testEngines() ) { 41 | addParam( list, script, "dupInt" ); 42 | addParam( list, script, "dupFloat" ); 43 | addParam( list, script, "dupDouble" ); 44 | addParam( list, script, "dupLong" ); 45 | } 46 | rule.setTestParameters( list ); 47 | return list; 48 | } 49 | 50 | static class TestClass { 51 | 52 | @Export 53 | static int dupInt() { 54 | int a, b, c, d; 55 | a = b = c = d = 3; 56 | return b; 57 | } 58 | 59 | @Export 60 | static float dupFloat() { 61 | float a = 1; 62 | float b = 2; 63 | a = b = 3.25F; 64 | return b; 65 | } 66 | 67 | @Export 68 | static double dupDouble() { 69 | double a = 1; 70 | double b = 2; 71 | a = b = 3.25; 72 | return b; 73 | } 74 | 75 | @Export 76 | static int dupLong() { 77 | long a = 1; 78 | long b = 2; 79 | a = b = 3; 80 | return (int)b; 81 | } 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /test/de/inetsoftware/jwebassembly/runtime/ThreadTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Volker Berlin (i-net software) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package de.inetsoftware.jwebassembly.runtime; 17 | 18 | import java.util.ArrayList; 19 | import java.util.Collection; 20 | 21 | import org.junit.ClassRule; 22 | import org.junit.runners.Parameterized.Parameters; 23 | 24 | import de.inetsoftware.jwebassembly.ScriptEngine; 25 | import de.inetsoftware.jwebassembly.WasmRule; 26 | import de.inetsoftware.jwebassembly.api.annotation.Export; 27 | import de.inetsoftware.jwebassembly.web.DOMString; 28 | import de.inetsoftware.jwebassembly.web.JSObject; 29 | 30 | /** 31 | * @author Volker Berlin 32 | */ 33 | public class ThreadTest extends AbstractBaseTest { 34 | 35 | @ClassRule 36 | public static WasmRule rule = new WasmRule( TestClass.class ); 37 | 38 | public ThreadTest( ScriptEngine script, String method, Object[] params ) { 39 | super( rule, script, method, params ); 40 | } 41 | 42 | @Parameters( name = "{0}-{1}" ) 43 | public static Collection data() { 44 | ArrayList list = new ArrayList<>(); 45 | for( ScriptEngine script : ScriptEngine.testEngines() ) { 46 | addParam( list, script, "currentThreadName" ); 47 | addParam( list, script, "groupThreadName" ); 48 | } 49 | rule.setTestParameters( list ); 50 | return list; 51 | } 52 | 53 | static class TestClass { 54 | 55 | @Export 56 | static boolean currentThreadName() { 57 | Thread thread = Thread.currentThread(); 58 | String name = thread.getName(); // with Gradle the name is "Test worker" 59 | return name.isEmpty(); 60 | } 61 | 62 | @Export 63 | static DOMString groupThreadName() { 64 | Thread thread = Thread.currentThread(); 65 | ThreadGroup group = thread.getThreadGroup(); 66 | String name; 67 | do { 68 | name = group.getName(); 69 | group = group.getParent(); 70 | } while( group != null ); 71 | return JSObject.domString( name ); 72 | } 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /src/de/inetsoftware/jwebassembly/module/WasmTableInstruction.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2019 - 2021 Volker Berlin (i-net software) 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | 16 | */ 17 | package de.inetsoftware.jwebassembly.module; 18 | 19 | import java.io.IOException; 20 | 21 | import javax.annotation.Nonnegative; 22 | import javax.annotation.Nonnull; 23 | 24 | import de.inetsoftware.jwebassembly.wasm.AnyType; 25 | import de.inetsoftware.jwebassembly.wasm.ValueType; 26 | 27 | /** 28 | * WasmInstruction for load and store a element in a table. 29 | * 30 | * @author Volker Berlin 31 | * 32 | */ 33 | class WasmTableInstruction extends WasmInstruction { 34 | 35 | private boolean load; 36 | 37 | private int idx; 38 | 39 | /** 40 | * Create an instance of a load/store instruction 41 | * 42 | * @param load 43 | * true: if "get" else "set" 44 | * @param idx 45 | * the index of the table 46 | * @param javaCodePos 47 | * the code position/offset in the Java method 48 | * @param lineNumber 49 | * the line number in the Java source code 50 | */ 51 | WasmTableInstruction( boolean load, @Nonnegative int idx, int javaCodePos, int lineNumber ) { 52 | super( javaCodePos, lineNumber ); 53 | this.load = load; 54 | this.idx = idx; 55 | } 56 | 57 | /** 58 | * {@inheritDoc} 59 | */ 60 | @Override 61 | Type getType() { 62 | return Type.Table; 63 | } 64 | 65 | /** 66 | * {@inheritDoc} 67 | */ 68 | @Override 69 | public void writeTo( @Nonnull ModuleWriter writer ) throws IOException { 70 | writer.writeTable( load, idx ); 71 | } 72 | 73 | /** 74 | * {@inheritDoc} 75 | */ 76 | @Override 77 | AnyType getPushValueType() { 78 | return load ? ValueType.externref : null; 79 | } 80 | 81 | /** 82 | * {@inheritDoc} 83 | */ 84 | @Override 85 | int getPopCount() { 86 | return load ? 0 : 1; 87 | } 88 | 89 | /** 90 | * {@inheritDoc} 91 | */ 92 | @Override 93 | AnyType[] getPopValueTypes() { 94 | return load ? null : new AnyType[] { ValueType.externref }; 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /test11/de/inetsoftware/jwebassembly/runtime/VarHandleTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Volker Berlin (i-net software) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package de.inetsoftware.jwebassembly.runtime; 17 | 18 | 19 | import java.lang.invoke.MethodHandles; 20 | import java.lang.invoke.VarHandle; 21 | import java.util.ArrayList; 22 | import java.util.Collection; 23 | import java.util.logging.Level; 24 | 25 | import org.junit.ClassRule; 26 | import org.junit.runners.Parameterized.Parameters; 27 | 28 | import de.inetsoftware.jwebassembly.JWebAssembly; 29 | import de.inetsoftware.jwebassembly.ScriptEngine; 30 | import de.inetsoftware.jwebassembly.WasmRule; 31 | import de.inetsoftware.jwebassembly.api.annotation.Export; 32 | import de.inetsoftware.jwebassembly.web.DOMString; 33 | import de.inetsoftware.jwebassembly.web.JSObject; 34 | 35 | /** 36 | * @author Volker Berlin 37 | */ 38 | public class VarHandleTest extends AbstractBaseTest { 39 | 40 | @ClassRule 41 | public static WasmRule rule = new WasmRule( TestClass.class ); 42 | 43 | public VarHandleTest( ScriptEngine script, String method, Object[] params ) { 44 | super( rule, script, method, params ); 45 | } 46 | 47 | @Parameters( name = "{0}-{1}" ) 48 | public static Collection data() { 49 | ArrayList list = new ArrayList<>(); 50 | for( ScriptEngine script : ScriptEngine.testEngines() ) { 51 | addParam( list, script, "set" ); 52 | } 53 | rule.setTestParameters( list ); 54 | 55 | return list; 56 | } 57 | 58 | static class TestClass { 59 | 60 | private static final VarHandle STR; 61 | static { 62 | try { 63 | MethodHandles.Lookup l = MethodHandles.lookup(); 64 | STR = l.findVarHandle(TestData.class, "str", String.class); 65 | } catch (ReflectiveOperationException e) { 66 | throw new ExceptionInInitializerError(e); 67 | } 68 | } 69 | 70 | @Export 71 | static DOMString set() { 72 | TestData data = new TestData(); 73 | STR.set( data, "abc" ); 74 | return JSObject.domString( data.str ); 75 | } 76 | } 77 | 78 | static class TestData { 79 | String str; 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /src/de/inetsoftware/classparser/FieldInfo.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2011 - 2019 Volker Berlin (i-net software) 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | 16 | */ 17 | package de.inetsoftware.classparser; 18 | 19 | import java.io.DataInputStream; 20 | import java.io.IOException; 21 | 22 | /** 23 | * Described a Field of a class. 24 | * http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html#jvms-4.5 25 | * http://docs.oracle.com/javase/specs/jvms/se5.0/html/ClassFile.doc.html#2877 26 | * 27 | * @author Volker Berlin 28 | */ 29 | public class FieldInfo { 30 | private final int accessFlags; 31 | 32 | private final String name; 33 | 34 | private final String description; 35 | 36 | private final Attributes attributes; 37 | 38 | /** 39 | * Read a single FieldInfo. 40 | * http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html#jvms-4.5 41 | * http://docs.oracle.com/javase/specs/jvms/se5.0/html/ClassFile.doc.html#2877 42 | * @param input 43 | * @param constantPool 44 | * @throws IOException 45 | */ 46 | FieldInfo(DataInputStream input, ConstantPool constantPool) throws IOException { 47 | this.accessFlags = input.readUnsignedShort(); 48 | this.name = (String)constantPool.get( input.readUnsignedShort() ); 49 | this.description = (String)constantPool.get( input.readUnsignedShort() ); 50 | this.attributes = new Attributes( input, constantPool ); 51 | } 52 | 53 | /** 54 | * Get the access flags of the method. 55 | * http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html#jvms-4.5-200-A 56 | * http://docs.oracle.com/javase/specs/jvms/se5.0/html/ClassFile.doc.html#87652 57 | * 58 | * @return the flags 59 | */ 60 | public int getAccessFlags() { 61 | return accessFlags; 62 | } 63 | 64 | /** 65 | * If this field is static or not 66 | * @return true, if static 67 | */ 68 | public boolean isStatic() { 69 | return (accessFlags & 0x0008) > 0; 70 | } 71 | 72 | /** 73 | * Get the name of the field 74 | * @return the name 75 | */ 76 | public String getName() { 77 | return name; 78 | } 79 | 80 | /** 81 | * Get the type of the field. 82 | * 83 | * @return the type 84 | */ 85 | public String getType() { 86 | return description; 87 | } 88 | } -------------------------------------------------------------------------------- /test/de/inetsoftware/jwebassembly/runtime/Enums.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Volker Berlin (i-net software) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package de.inetsoftware.jwebassembly.runtime; 17 | 18 | import java.util.ArrayList; 19 | import java.util.Collection; 20 | 21 | import org.junit.ClassRule; 22 | import org.junit.runners.Parameterized.Parameters; 23 | 24 | import de.inetsoftware.jwebassembly.ScriptEngine; 25 | import de.inetsoftware.jwebassembly.WasmRule; 26 | import de.inetsoftware.jwebassembly.api.annotation.Export; 27 | import de.inetsoftware.jwebassembly.web.DOMString; 28 | import de.inetsoftware.jwebassembly.web.JSObject; 29 | 30 | /** 31 | * @author Volker Berlin 32 | */ 33 | public class Enums extends AbstractBaseTest { 34 | 35 | @ClassRule 36 | public static WasmRule rule = new WasmRule( TestClass.class ); 37 | 38 | public Enums( ScriptEngine script, String method, Object[] params ) { 39 | super( rule, script, method, params ); 40 | } 41 | 42 | @Parameters( name = "{0}-{1}" ) 43 | public static Collection data() { 44 | ArrayList list = new ArrayList<>(); 45 | for( ScriptEngine script : ScriptEngine.testEngines() ) { 46 | addParam( list, script, "ordinal" ); 47 | addParam( list, script, "name" ); 48 | addParam( list, script, "values" ); 49 | addParam( list, script, "valueOf" ); 50 | } 51 | rule.setTestParameters( list ); 52 | return list; 53 | } 54 | 55 | static class TestClass { 56 | 57 | @Export 58 | static int ordinal() { 59 | return TestEnum.Foobar.ordinal(); 60 | } 61 | 62 | @Export 63 | static DOMString name() { 64 | return JSObject.domString( TestEnum.Foobar.name() ); 65 | } 66 | 67 | @Export 68 | static DOMString values() { 69 | StringBuilder builder = new StringBuilder(); 70 | for( TestEnum testEnum : TestEnum.values() ) { 71 | builder.append( testEnum.name() ); 72 | } 73 | return JSObject.domString( builder.toString() ); 74 | } 75 | 76 | @Export 77 | static DOMString valueOf() { 78 | return JSObject.domString( TestEnum.valueOf( "Bar" ).toString() ); 79 | } 80 | } 81 | 82 | static enum TestEnum { 83 | Foo, Bar, Foobar; 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /src/de/inetsoftware/jwebassembly/module/WasmCallIndirectInstruction.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2019 - 2022 Volker Berlin (i-net software) 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | 16 | */ 17 | package de.inetsoftware.jwebassembly.module; 18 | 19 | import de.inetsoftware.jwebassembly.module.TypeManager.StructType; 20 | 21 | /** 22 | * WasmInstruction for a function call. 23 | * 24 | * @author Volker Berlin 25 | * 26 | */ 27 | abstract class WasmCallIndirectInstruction extends WasmCallInstruction { 28 | 29 | private final StructType type; 30 | 31 | private int tempVarSlot; 32 | 33 | private LocaleVariableManager localVariables; 34 | 35 | /** 36 | * Create an instance of a function call instruction 37 | * 38 | * @param name 39 | * the function name that should be called 40 | * @param javaCodePos 41 | * the code position/offset in the Java method 42 | * @param lineNumber 43 | * the line number in the Java source code 44 | * @param types 45 | * the type manager 46 | */ 47 | WasmCallIndirectInstruction( FunctionName name, int javaCodePos, int lineNumber, TypeManager types ) { 48 | super( name, javaCodePos, lineNumber, types, true ); 49 | this.type = types.valueOf( name.className ); 50 | } 51 | 52 | /** 53 | * Get the type of this. 54 | * 55 | * @return the type 56 | */ 57 | StructType getThisType() { 58 | return type; 59 | } 60 | 61 | /** 62 | * Set the Java variable slot on which THIS can be found. 63 | * @param tempVarSlot the slot 64 | * @param localVariables 65 | * the manager for local variables to resolve the index 66 | */ 67 | void setVariableSlotOfThis( int tempVarSlot, LocaleVariableManager localVariables ) { 68 | this.tempVarSlot = tempVarSlot; 69 | this.localVariables = localVariables; 70 | } 71 | 72 | /** 73 | * Get the variable index on which this can be found. 74 | * 75 | * @return the index of the variable 76 | */ 77 | int getVariableIndexOfThis() { 78 | return localVariables.get( tempVarSlot, getCodePosition() ); 79 | } 80 | 81 | /** 82 | * if this call is executed virtual or if is was optimized. 83 | * 84 | * @return true, virtual call 85 | */ 86 | abstract boolean isVirtual(); 87 | } 88 | -------------------------------------------------------------------------------- /src/de/inetsoftware/classparser/LocalVariableTable.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2011 - 2019 Volker Berlin (i-net software) 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | 16 | */ 17 | package de.inetsoftware.classparser; 18 | 19 | import java.io.DataInputStream; 20 | import java.io.IOException; 21 | 22 | /** 23 | * @author Volker Berlin 24 | */ 25 | public class LocalVariableTable { 26 | 27 | private final int maxLocals; 28 | 29 | private LocalVariable[] table; 30 | 31 | /** 32 | * Create a new instance of the code attribute "LocalVariableTable". 33 | * 34 | * http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html#jvms-4.7.13 35 | * http://docs.oracle.com/javase/specs/jvms/se5.0/html/ClassFile.doc.html#5956 36 | 37 | * @param maxLocals 38 | * the count of local variables in the memory 39 | * @param constantPool 40 | * Reference to the current ConstantPool 41 | * @param input 42 | * the stream of the class 43 | * @throws IOException 44 | * if any I/O error occurs. 45 | */ 46 | LocalVariableTable( int maxLocals, ConstantPool constantPool, DataInputStream input ) throws IOException { 47 | this.maxLocals = maxLocals; 48 | 49 | int count = input.readUnsignedShort(); 50 | table = new LocalVariable[count]; 51 | for( int i = 0; i < count; i++ ) { 52 | table[i] = new LocalVariable( input, constantPool ); 53 | } 54 | } 55 | 56 | /** 57 | * Create an instance without any debug details. 58 | * 59 | * @param maxLocals 60 | * the count of local variables in the memory 61 | */ 62 | LocalVariableTable( int maxLocals ) { 63 | this.maxLocals = maxLocals; 64 | 65 | table = new LocalVariable[0]; 66 | } 67 | 68 | /** 69 | * Get the count of variables/slots. This is not the count of declared LocalVariable in this table. There can be 70 | * unnamed helper variables for the compiler which are not in the table. There can be reused slots for different 71 | * variables. 72 | * 73 | * @return the count 74 | */ 75 | public int getMaxLocals() { 76 | return maxLocals; 77 | } 78 | 79 | /** 80 | * Get the declared local variables 81 | * 82 | * @return the variables 83 | */ 84 | public LocalVariable[] getTable() { 85 | return table; 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /test/de/inetsoftware/jwebassembly/runtime/DynamicValues.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Volker Berlin (i-net software) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package de.inetsoftware.jwebassembly.runtime; 17 | 18 | import static org.junit.Assert.assertEquals; 19 | import static org.junit.Assert.assertTrue; 20 | import static org.junit.Assume.assumeFalse; 21 | 22 | import java.util.Collection; 23 | 24 | import org.junit.ClassRule; 25 | import org.junit.Test; 26 | import org.junit.runner.RunWith; 27 | import org.junit.runners.Parameterized; 28 | import org.junit.runners.Parameterized.Parameters; 29 | 30 | import de.inetsoftware.jwebassembly.ScriptEngine; 31 | import de.inetsoftware.jwebassembly.WasmRule; 32 | import de.inetsoftware.jwebassembly.api.annotation.Export; 33 | 34 | /** 35 | * Run some tests which not return static/fix values likes times or random value and which are difficult to compare. 36 | * 37 | * @author Volker Berlin 38 | * 39 | */ 40 | @RunWith( Parameterized.class ) 41 | public class DynamicValues { 42 | 43 | @ClassRule 44 | public static WasmRule rule = new WasmRule( TestClass.class ); 45 | 46 | private final ScriptEngine script; 47 | 48 | public DynamicValues( ScriptEngine script ) { 49 | this.script = script; 50 | } 51 | 52 | @Parameters( name = "{0}" ) 53 | public static Collection data() { 54 | return ScriptEngine.testParams(); 55 | } 56 | 57 | @Test 58 | public void currentTimeMillis() { 59 | long before = System.currentTimeMillis(); 60 | String result = rule.evalWasm( script, "currentTimeMillis" ); 61 | long after = System.currentTimeMillis(); 62 | long val = Long.parseLong( result ); 63 | assertTrue( before + "<=" + val + "<=" + after, before <= val && val <= after ); 64 | } 65 | 66 | static class TestClass { 67 | 68 | @Export 69 | static long currentTimeMillis() { 70 | return System.currentTimeMillis(); 71 | } 72 | 73 | @Export 74 | static int testHashCode() { 75 | Object obj1 = new Object(); 76 | Object obj2 = new Object(); 77 | int result = 0; 78 | result |= obj1.hashCode() != 0 ? 1 : 0; 79 | result |= obj1.hashCode() != obj2.hashCode() ? 2 : 0; 80 | result |= obj1.hashCode() == obj1.hashCode() ? 4 : 0; 81 | return result; 82 | } 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /src/de/inetsoftware/jwebassembly/module/JumpInstruction.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2020 - 2021 Volker Berlin (i-net software) 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | 16 | */ 17 | package de.inetsoftware.jwebassembly.module; 18 | 19 | import java.io.IOException; 20 | 21 | import javax.annotation.Nonnull; 22 | 23 | import de.inetsoftware.jwebassembly.wasm.AnyType; 24 | 25 | /** 26 | * Placeholder for a jump to inspect the stack. It is like a nop operation. 27 | * 28 | * @author Volker Berlin 29 | * 30 | */ 31 | class JumpInstruction extends WasmInstruction { 32 | 33 | private int jumpPos; 34 | 35 | private int popCount; 36 | 37 | private AnyType pushValueType; 38 | 39 | /** 40 | * Create an instance of a nop instruction 41 | * 42 | * @param jumpPos 43 | * the position of the jump 44 | * @param popCount 45 | * the the count of values that are removed from the stack. 46 | * @param pushValueType 47 | * optional type of a push value 48 | * @param javaCodePos 49 | * the code position/offset in the Java method 50 | * @param lineNumber 51 | * the line number in the Java source code 52 | */ 53 | JumpInstruction( int jumpPos, int popCount, AnyType pushValueType, int javaCodePos, int lineNumber ) { 54 | super( javaCodePos, lineNumber ); 55 | this.jumpPos = jumpPos; 56 | this.popCount = popCount; 57 | this.pushValueType = pushValueType; 58 | } 59 | 60 | /** 61 | * {@inheritDoc} 62 | */ 63 | @Override 64 | Type getType() { 65 | return Type.Jump; 66 | } 67 | 68 | /** 69 | * {@inheritDoc} 70 | */ 71 | public void writeTo( @Nonnull ModuleWriter writer ) throws IOException { 72 | // nothing 73 | } 74 | 75 | /** 76 | * {@inheritDoc} 77 | */ 78 | AnyType getPushValueType() { 79 | return pushValueType; 80 | } 81 | 82 | /** 83 | * {@inheritDoc} 84 | */ 85 | @Override 86 | int getPopCount() { 87 | return popCount; 88 | } 89 | 90 | /** 91 | * Get the jump position 92 | * 93 | * @return the position 94 | */ 95 | int getJumpPosition() { 96 | return jumpPos; 97 | } 98 | 99 | /** 100 | * {@inheritDoc} 101 | */ 102 | @Override 103 | AnyType[] getPopValueTypes() { 104 | // TODO 105 | return null; 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /src/de/inetsoftware/jwebassembly/module/WatCodeSyntheticFunctionName.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2019 - 2022 Volker Berlin (i-net software) 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | 16 | */ 17 | package de.inetsoftware.jwebassembly.module; 18 | 19 | import javax.annotation.Nonnull; 20 | 21 | import de.inetsoftware.jwebassembly.wasm.AnyType; 22 | import de.inetsoftware.jwebassembly.watparser.WatParser; 23 | 24 | /** 25 | * Synthetic/dynamic method based on WAT code (WASM in text form). 26 | * 27 | * @author Volker Berlin 28 | */ 29 | class WatCodeSyntheticFunctionName extends ArraySyntheticFunctionName { 30 | 31 | private final String code; 32 | 33 | /** 34 | * Create a new instance. 35 | * 36 | * @param name 37 | * the function name 38 | * @param code 39 | * the WAT code (WASM in text form) 40 | * @param signatureTypes 41 | * the method signature, first the parameters, then null and the the return types 42 | */ 43 | public WatCodeSyntheticFunctionName( String name, String code, AnyType... signatureTypes ) { 44 | super( "", name, signatureTypes ); 45 | this.code = code; 46 | } 47 | 48 | /** 49 | * Create a new instance. 50 | * 51 | * @param className 52 | * the Java class name 53 | * @param name 54 | * the function name 55 | * @param code 56 | * the WAT code (WASM in text form) 57 | * @param signature 58 | * the string signature 59 | * @param signatureTypes 60 | * the method signature, first the parameters, then null and the the return types 61 | */ 62 | public WatCodeSyntheticFunctionName( String className, String name, String signature, @Nonnull String code, AnyType... signatureTypes ) { 63 | super( className, name, signature, signatureTypes ); 64 | this.code = code; 65 | } 66 | 67 | /** 68 | * Get Wat code, can be overridden. 69 | * 70 | * @return the code 71 | */ 72 | @Nonnull 73 | protected String getCode() { 74 | return code; 75 | } 76 | 77 | /** 78 | * {@inheritDoc} 79 | */ 80 | @Override 81 | protected boolean hasWasmCode() { 82 | return true; 83 | } 84 | 85 | /** 86 | * {@inheritDoc} 87 | */ 88 | @Override 89 | protected WasmCodeBuilder getCodeBuilder( WatParser watParser ) { 90 | watParser.parse( getCode(), null, getSignature( watParser.getTypeManager() ), -1 ); 91 | return watParser; 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /test/de/inetsoftware/jwebassembly/runtime/CallFunctions.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 - 2019 Volker Berlin (i-net software) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package de.inetsoftware.jwebassembly.runtime; 17 | 18 | import java.util.ArrayList; 19 | import java.util.Collection; 20 | 21 | import org.junit.ClassRule; 22 | import org.junit.runners.Parameterized.Parameters; 23 | 24 | import de.inetsoftware.jwebassembly.ScriptEngine; 25 | import de.inetsoftware.jwebassembly.WasmRule; 26 | import de.inetsoftware.jwebassembly.api.annotation.Export; 27 | import de.inetsoftware.jwebassembly.api.annotation.Import; 28 | import de.inetsoftware.jwebassembly.api.annotation.WasmTextCode; 29 | 30 | /** 31 | * @author Volker Berlin 32 | */ 33 | public class CallFunctions extends AbstractBaseTest { 34 | 35 | @ClassRule 36 | public static WasmRule rule = new WasmRule( TestClass.class ); 37 | 38 | public CallFunctions( ScriptEngine script, String method, Object[] params ) { 39 | super( rule, script, method, params ); 40 | } 41 | 42 | @Parameters(name="{0}-{1}") 43 | public static Collection data() { 44 | ArrayList list = new ArrayList<>(); 45 | for( ScriptEngine script : ScriptEngine.testEngines() ) { 46 | addParam( list, script, "intCall" ); 47 | addParam( list, script, "nativeCall" ); 48 | } 49 | rule.setTestParameters( list ); 50 | return list; 51 | } 52 | 53 | static class TestClass { 54 | 55 | @Export 56 | static int intCall() { 57 | intConst(); 58 | doubleConst(); 59 | emptyMethod(); 60 | return abc( 4,5) + intConst() * 100; 61 | } 62 | 63 | static int intConst() { 64 | return -42; 65 | } 66 | 67 | static double doubleConst() { 68 | return 3.5; 69 | } 70 | 71 | static void emptyMethod() { 72 | 73 | } 74 | 75 | @Import( module = "Math", name = "max" ) 76 | static int abc( int a, int b) { 77 | return Math.max( a, b ); 78 | } 79 | 80 | @Export 81 | static float nativeCall() { 82 | return nativeMax( 4.5F,5.5F); 83 | } 84 | 85 | @WasmTextCode( "local.get 0 " // 86 | + "local.get 1 " // 87 | + "f32.max " // 88 | + "return" ) 89 | private static float nativeMax( float a, float b) { 90 | return Math.max( a, b ); 91 | } 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /src/de/inetsoftware/jwebassembly/module/WasmCallInterfaceInstruction.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2020 Volker Berlin (i-net software) 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | 16 | */ 17 | package de.inetsoftware.jwebassembly.module; 18 | 19 | import java.io.IOException; 20 | 21 | import javax.annotation.Nonnull; 22 | 23 | import de.inetsoftware.jwebassembly.module.TypeManager.StructType; 24 | import de.inetsoftware.jwebassembly.wasm.ValueType; 25 | import de.inetsoftware.jwebassembly.wasm.VariableOperator; 26 | 27 | /** 28 | * WasmInstruction for a function call. 29 | * 30 | * @author Volker Berlin 31 | * 32 | */ 33 | class WasmCallInterfaceInstruction extends WasmCallIndirectInstruction { 34 | 35 | private final WasmOptions options; 36 | 37 | /** 38 | * Create an instance of a function call instruction 39 | * 40 | * @param name 41 | * the function name that should be called 42 | * @param javaCodePos 43 | * the code position/offset in the Java method 44 | * @param lineNumber 45 | * the line number in the Java source code 46 | * @param types 47 | * the type manager 48 | * @param options 49 | * compiler properties 50 | */ 51 | WasmCallInterfaceInstruction( FunctionName name, int javaCodePos, int lineNumber, TypeManager types, WasmOptions options ) { 52 | super( name, javaCodePos, lineNumber, types ); 53 | this.options = options; 54 | } 55 | 56 | /** 57 | * {@inheritDoc} 58 | */ 59 | @Override 60 | Type getType() { 61 | return Type.CallInterface; 62 | } 63 | 64 | /** 65 | * {@inheritDoc} 66 | */ 67 | @Override 68 | boolean isVirtual() { 69 | return true; 70 | } 71 | 72 | /** 73 | * {@inheritDoc} 74 | */ 75 | public void writeTo( @Nonnull ModuleWriter writer ) throws IOException { 76 | FunctionName name = getFunctionName(); 77 | StructType type = getThisType(); 78 | int classIndex = type.getClassIndex(); 79 | int interfaceFunctionIdx = options.functions.getITableIndex( name ); 80 | 81 | // duplicate this on the stack 82 | writer.writeLocal( VariableOperator.get, getVariableIndexOfThis() ); 83 | writer.writeConst( classIndex, ValueType.i32 ); 84 | writer.writeConst( interfaceFunctionIdx * 4, ValueType.i32 ); 85 | writer.writeFunctionCall( options.getCallInterface(), null ); // parameters: this, classIndex, functionIndex 86 | 87 | writer.writeVirtualFunctionCall( name, type ); 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /src/de/inetsoftware/classparser/LineNumberTable.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2011 - 2021 Volker Berlin (i-net software) 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | 16 | */ 17 | package de.inetsoftware.classparser; 18 | 19 | import java.io.DataInputStream; 20 | import java.io.IOException; 21 | 22 | /** 23 | * @author Volker Berlin 24 | */ 25 | public class LineNumberTable { 26 | 27 | private final int start_pc[]; 28 | 29 | private final int line_number[]; 30 | 31 | /** 32 | * http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html#jvms-4.7.12 33 | * http://docs.oracle.com/javase/specs/jvms/se5.0/html/ClassFile.doc.html#22856 34 | * 35 | * @param input 36 | * the stream of the class 37 | * @throws IOException 38 | * if any i/O error occur 39 | */ 40 | LineNumberTable( DataInputStream input ) throws IOException { 41 | int count = input.readUnsignedShort(); 42 | start_pc = new int[count]; 43 | line_number = new int[count]; 44 | for( int i = 0; i < count; i++ ) { 45 | start_pc[i] = input.readUnsignedShort(); 46 | line_number[i] = input.readUnsignedShort(); 47 | } 48 | } 49 | 50 | /** 51 | * Count of entries 52 | * 53 | * @return the count 54 | */ 55 | public int size() { 56 | return start_pc.length; 57 | } 58 | 59 | /** 60 | * Get the offset of the code 61 | * 62 | * @param idx 63 | * the table position 64 | * @return the code offset 65 | */ 66 | public int getStartOffset( int idx ) { 67 | return start_pc[idx]; 68 | } 69 | 70 | /** 71 | * Get the line number 72 | * 73 | * @param idx 74 | * the table position 75 | * @return the line number 76 | */ 77 | public int getLineNumber( int idx ) { 78 | return line_number[idx]; 79 | } 80 | 81 | /** 82 | * Get the line number of the last code block. 83 | * @return the line number 84 | */ 85 | public int getLastLineNr() { 86 | return line_number[line_number.length - 1]; 87 | } 88 | 89 | public int getMinLineNr(){ 90 | int min = 0xFFFF; 91 | for( int nr : line_number ){ 92 | min = Math.min( min, nr ); 93 | } 94 | return min; 95 | } 96 | 97 | public int getMaxLineNr(){ 98 | int max = -1; 99 | for( int nr : line_number ){ 100 | max = Math.max( max, nr ); 101 | } 102 | return max; 103 | } 104 | 105 | } 106 | -------------------------------------------------------------------------------- /test/de/inetsoftware/jwebassembly/runtime/StringOperations.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 - 2020 Volker Berlin (i-net software) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package de.inetsoftware.jwebassembly.runtime; 17 | 18 | import java.util.ArrayList; 19 | import java.util.Collection; 20 | 21 | import org.junit.Assume; 22 | import org.junit.ClassRule; 23 | import org.junit.Test; 24 | import org.junit.runners.Parameterized.Parameters; 25 | 26 | import de.inetsoftware.jwebassembly.ScriptEngine; 27 | import de.inetsoftware.jwebassembly.WasmRule; 28 | import de.inetsoftware.jwebassembly.api.annotation.Export; 29 | import de.inetsoftware.jwebassembly.web.DOMString; 30 | import de.inetsoftware.jwebassembly.web.JSObject; 31 | 32 | public class StringOperations extends AbstractBaseTest { 33 | 34 | @ClassRule 35 | public static WasmRule rule = new WasmRule( TestClass.class ); 36 | 37 | public StringOperations( ScriptEngine script, String method, Object[] params ) { 38 | super( rule, script, method, params ); 39 | } 40 | 41 | @Parameters( name = "{0}-{1}" ) 42 | public static Collection data() { 43 | ArrayList list = new ArrayList<>(); 44 | for( ScriptEngine script : ScriptEngine.testEngines() ) { 45 | addParam( list, script, "newFromChars" ); 46 | addParam( list, script, "newFromBytes" ); 47 | addParam( list, script, "constant" ); 48 | addParam( list, script, "objToString" ); 49 | } 50 | rule.setTestParameters( list ); 51 | return list; 52 | } 53 | 54 | static class TestClass { 55 | 56 | @Export 57 | static DOMString newFromChars() { 58 | char[] chars = {'ä','ö','ü'}; 59 | return JSObject.domString( new String( chars ) ); 60 | } 61 | 62 | @Export 63 | static DOMString newFromBytes() { 64 | byte[] bytes = {(byte)0xC3,(byte)0xA4}; 65 | return JSObject.domString( new String( bytes ) ); 66 | } 67 | 68 | @Export 69 | static DOMString constant() { 70 | // string larger as 128 bytes 71 | String constant = "1234567890 äöüäöüß " // umlaute 72 | + "𝟘𝟙𝟚𝟛𝟜𝟝𝟞𝟟𝟠𝟡 𝒥𝒶𝓋𝒶𝓈𝒸𝓇𝒾𝓅𝓉 " // surrogate chars 73 | + "abcdefghijklmnopqrstuvwxyz"; 74 | return JSObject.domString( constant ); 75 | } 76 | 77 | @Export 78 | static DOMString objToString() { 79 | Object obj = new Object(); 80 | return JSObject.domString( obj.toString().substring( 0, 17 ) ); 81 | } 82 | 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /src/de/inetsoftware/jwebassembly/module/WasmCallVirtualInstruction.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2019 - 2020 Volker Berlin (i-net software) 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | 16 | */ 17 | package de.inetsoftware.jwebassembly.module; 18 | 19 | import java.io.IOException; 20 | 21 | import javax.annotation.Nonnull; 22 | 23 | import de.inetsoftware.jwebassembly.module.TypeManager.StructType; 24 | import de.inetsoftware.jwebassembly.wasm.ValueType; 25 | import de.inetsoftware.jwebassembly.wasm.VariableOperator; 26 | 27 | /** 28 | * WasmInstruction for a function call. 29 | * 30 | * @author Volker Berlin 31 | * 32 | */ 33 | class WasmCallVirtualInstruction extends WasmCallIndirectInstruction { 34 | 35 | private final WasmOptions options; 36 | 37 | /** 38 | * Create an instance of a function call instruction 39 | * 40 | * @param name 41 | * the function name that should be called 42 | * @param javaCodePos 43 | * the code position/offset in the Java method 44 | * @param lineNumber 45 | * the line number in the Java source code 46 | * @param types 47 | * the type manager 48 | * @param options 49 | * compiler properties 50 | */ 51 | WasmCallVirtualInstruction( FunctionName name, int javaCodePos, int lineNumber, TypeManager types, WasmOptions options ) { 52 | super( name, javaCodePos, lineNumber, types ); 53 | this.options = options; 54 | } 55 | 56 | /** 57 | * {@inheritDoc} 58 | */ 59 | @Override 60 | Type getType() { 61 | return Type.CallVirtual; 62 | } 63 | 64 | /** 65 | * if this call is executed virtual or if is was optimized. 66 | * 67 | * @return true, virtual call 68 | */ 69 | boolean isVirtual() { 70 | return options.functions.getVTableIndex( getFunctionName() ) > 0; 71 | } 72 | 73 | /** 74 | * {@inheritDoc} 75 | */ 76 | @Override 77 | public void writeTo( @Nonnull ModuleWriter writer ) throws IOException { 78 | int virtualFunctionIdx = options.functions.getVTableIndex( getFunctionName() ); 79 | if( virtualFunctionIdx < 0 ) { 80 | super.writeTo( writer ); 81 | } else { 82 | // duplicate this on the stack 83 | writer.writeLocal( VariableOperator.get, getVariableIndexOfThis() ); 84 | 85 | writer.writeConst( virtualFunctionIdx * 4, ValueType.i32 ); 86 | writer.writeFunctionCall( options.getCallVirtual(), null ); 87 | StructType type = getThisType(); 88 | writer.writeVirtualFunctionCall( getFunctionName(), type ); 89 | } 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /src/de/inetsoftware/classparser/Attributes.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2011 - 2017 Volker Berlin (i-net software) 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | 16 | */ 17 | package de.inetsoftware.classparser; 18 | 19 | import java.io.ByteArrayInputStream; 20 | import java.io.DataInputStream; 21 | import java.io.IOException; 22 | 23 | import javax.annotation.Nonnull; 24 | import javax.annotation.Nullable; 25 | 26 | /** 27 | * @author Volker Berlin 28 | */ 29 | public class Attributes { 30 | 31 | private final AttributeInfo[] attributes; 32 | 33 | private final ConstantPool constantPool; 34 | 35 | Attributes( @Nonnull DataInputStream input, @Nonnull ConstantPool constantPool ) throws IOException { 36 | this.constantPool = constantPool; 37 | this.attributes = readAttributs( input ); 38 | } 39 | 40 | private AttributeInfo[] readAttributs( @Nonnull DataInputStream input ) throws IOException { 41 | AttributeInfo[] attrs = new AttributeInfo[input.readUnsignedShort()]; 42 | for( int i = 0; i < attrs.length; i++ ) { 43 | attrs[i] = new AttributeInfo( input, constantPool ); 44 | } 45 | return attrs; 46 | } 47 | 48 | @Nullable 49 | AttributeInfo get( String name ) { 50 | for( AttributeInfo attr : attributes ) { 51 | if( attr.getName().equals( name ) ) { 52 | return attr; 53 | } 54 | } 55 | return null; 56 | } 57 | 58 | static class AttributeInfo { 59 | 60 | private final String name; 61 | 62 | private final byte[] info; 63 | 64 | AttributeInfo( @Nonnull DataInputStream input, @Nonnull ConstantPool constantPool ) throws IOException { 65 | this.name = (String)constantPool.get( input.readUnsignedShort() ); 66 | this.info = new byte[input.readInt()]; 67 | input.readFully( this.info ); 68 | } 69 | 70 | String getName() { 71 | return name; 72 | } 73 | 74 | byte[] getData() { 75 | return info; 76 | } 77 | 78 | DataInputStream getDataInputStream(){ 79 | return new DataInputStream( new ByteArrayInputStream( info ) ); 80 | } 81 | } 82 | 83 | /** 84 | * Get value of SourceFile if available. 85 | * @return the source file name or null. 86 | * @throws IOException if an I/O error occurs. 87 | */ 88 | public String getSourceFile() throws IOException{ 89 | AttributeInfo data = get( "SourceFile" ); 90 | if( data == null ) { 91 | return null; 92 | } 93 | return (String)constantPool.get( data.getDataInputStream().readUnsignedShort() ); 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /docs/samples/HelloWorld/HelloWorld.wasm.js: -------------------------------------------------------------------------------- 1 | 'use strict';var wasmImports = { 2 | Web:{ 3 | win_get0:(p)=>window[p], 4 | get0:(o,p)=>o[p], 5 | fromChars:(v)=>{v=v[2];var s='';for(var i=0;io[m](p1) 7 | }, 8 | NonGC:{ 9 | array_new_u16:(l)=>Object.seal({0:648,1:0,2:Object.seal(new Array(l).fill(null))}), 10 | new_java_lang_StringBuilder:() => Object.seal({0:976,1:0,2:null,3:0}), 11 | new_java_util_Collections$EmptySet:() => Object.seal({0:2548,1:0}), 12 | new_java_util_Collections$UnmodifiableList:() => Object.seal({0:2272,1:0,2:null,3:null}), 13 | new_de_inetsoftware_jwebassembly_web_dom_HTMLElement:() => Object.seal({0:324,1:0,2:null}), 14 | new_java_lang_OutOfMemoryError:() => Object.seal({0:1448,1:0,2:null,3:null,4:null,5:null}), 15 | new_java_lang_ThreadLocal:() => Object.seal({0:1740,1:0,2:0}), 16 | new_java_util_concurrent_atomic_AtomicInteger:() => Object.seal({0:2316,1:0,2:0}), 17 | get_i32:(a,i) => a[i], 18 | new_de_inetsoftware_jwebassembly_web_dom_Document:() => Object.seal({0:252,1:0,2:null}), 19 | array_new_i32:(l)=>Object.seal({0:1196,1:0,2:new Int32Array(l)}), 20 | new_java_lang_StringIndexOutOfBoundsException:() => Object.seal({0:924,1:0,2:null,3:null,4:null,5:null}), 21 | new_java_lang_NullPointerException:() => Object.seal({0:2464,1:0,2:null,3:null,4:null,5:null}), 22 | ref_eq:(a,b) => a === b, 23 | new_java_lang_IllegalArgumentException:() => Object.seal({0:1228,1:0,2:null,3:null,4:null,5:null}), 24 | get_anyref:(a,i) => a[i], 25 | array_new_java_lang_StackTraceElement:(l)=>Object.seal({0:1384,1:0,2:Object.seal(new Array(l).fill(null))}), 26 | set_anyref:(a,v,i) => a[i]=v, 27 | array_get_i32:(a,i)=>a[2][i], 28 | new_java_lang_String:() => Object.seal({0:452,1:0,2:null,3:0,4:null}), 29 | get_externref:(a,i) => a[i], 30 | new_java_util_Collections$UnmodifiableRandomAccessList:() => Object.seal({0:2220,1:0,2:null,3:null}), 31 | new_de_inetsoftware_jwebassembly_web_dom_Node:() => Object.seal({0:532,1:0,2:null}), 32 | array_new_java_lang_Throwable:(l)=>Object.seal({0:2052,1:0,2:Object.seal(new Array(l).fill(null))}), 33 | array_set_i32:(a,i,v)=>a[2][i]=v, 34 | new_java_lang_AssertionError:() => Object.seal({0:2116,1:0,2:null,3:null,4:null,5:null}), 35 | array_new_java_io_ObjectStreamField:(l)=>Object.seal({0:1644,1:0,2:Object.seal(new Array(l).fill(null))}), 36 | new_java_lang_String$CaseInsensitiveComparator:() => Object.seal({0:1676,1:0}), 37 | new_java_util_Collections$EmptyMap:() => Object.seal({0:2712,1:0}), 38 | array_new_i8:(l)=>Object.seal({0:588,1:0,2:new Uint8Array(l)}), 39 | array_len:(a)=>a[2].length, 40 | new_java_util_ArrayList:() => Object.seal({0:2000,1:0,2:0,3:null}), 41 | new_java_lang_Class:() => Object.seal({0:1804,1:0,2:0}), 42 | new_de_inetsoftware_jwebassembly_web_dom_Text:() => Object.seal({0:388,1:0,2:null}), 43 | new_java_util_Collections$EmptyList:() => Object.seal({0:2628,1:0,2:0}), 44 | set_i32:(a,v,i) => a[i]=v, 45 | array_new_java_lang_Object:(l)=>Object.seal({0:2160,1:0,2:Object.seal(new Array(l).fill(null))}) 46 | }, 47 | System:{ 48 | arraycopy:(src,srcPos,dest,destPos,length)=>{src=src[2];dest=dest[2];if(destPos=0;i--)dest[i+destPos]=src[i+srcPos];}} 49 | } 50 | }; 51 | if (typeof module !== 'undefined') module.exports = wasmImports; -------------------------------------------------------------------------------- /src/de/inetsoftware/classparser/LocalVariable.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2011 - 2019 Volker Berlin (i-net software) 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | 16 | */ 17 | package de.inetsoftware.classparser; 18 | 19 | import java.io.DataInputStream; 20 | import java.io.IOException; 21 | 22 | /** 23 | * @author Volker Berlin 24 | */ 25 | public class LocalVariable { 26 | 27 | private final int start_pc; 28 | 29 | private final int length; 30 | 31 | private final String name; 32 | 33 | private final String signature; 34 | 35 | private final int index; 36 | 37 | /** 38 | * http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html#jvms-4.7.13 39 | * http://docs.oracle.com/javase/specs/jvms/se5.0/html/ClassFile.doc.html#5956 40 | * 41 | * @param input 42 | * the stream of the class 43 | * @param position 44 | * the position in the LocalVariableTable 45 | * @param constantPool 46 | * Reference to the current ConstantPool 47 | * @throws IOException 48 | * if any I/O error occurs. 49 | */ 50 | LocalVariable( DataInputStream input, ConstantPool constantPool ) throws IOException { 51 | start_pc = input.readUnsignedShort(); 52 | length = input.readUnsignedShort(); 53 | name = (String)constantPool.get( input.readUnsignedShort() ); 54 | signature = (String)constantPool.get( input.readUnsignedShort() ); 55 | index = input.readUnsignedShort(); 56 | } 57 | 58 | /** 59 | * Get the index in the local variable table (memory location/slot). 60 | * 61 | * @return the index. 62 | */ 63 | public int getIndex() { 64 | return index; 65 | } 66 | 67 | /** 68 | * Get the name of the variable 69 | * 70 | * @return the name 71 | */ 72 | public String getName() { 73 | return name; 74 | } 75 | 76 | /** 77 | * Get the type/signature of the variable 78 | * 79 | * @return the signature 80 | */ 81 | public String getSignature() { 82 | return signature; 83 | } 84 | 85 | /** 86 | * Get the code position within the local variable has a value. The first set operation to the variable will start 87 | * before this position. 88 | * 89 | * @return the position. 90 | */ 91 | public int getStartPosition() { 92 | return start_pc; 93 | } 94 | 95 | /** 96 | * Get the code position length within the local variable has a value. 97 | * 98 | * @return the length 99 | */ 100 | public int getLengthPosition() { 101 | return length; 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /test/de/inetsoftware/jwebassembly/runtime/RuntimeErrors.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 - 2022 Volker Berlin (i-net software) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package de.inetsoftware.jwebassembly.runtime; 17 | 18 | import static org.junit.Assert.assertTrue; 19 | import static org.junit.Assert.fail; 20 | 21 | import java.io.IOException; 22 | import java.util.Collection; 23 | 24 | import org.junit.Test; 25 | import org.junit.runner.RunWith; 26 | import org.junit.runners.Parameterized; 27 | import org.junit.runners.Parameterized.Parameters; 28 | 29 | import de.inetsoftware.jwebassembly.ScriptEngine; 30 | import de.inetsoftware.jwebassembly.WasmException; 31 | import de.inetsoftware.jwebassembly.WasmRule; 32 | import de.inetsoftware.jwebassembly.api.annotation.Export; 33 | import de.inetsoftware.jwebassembly.api.annotation.Import; 34 | 35 | /** 36 | * @author Volker Berlin 37 | */ 38 | @RunWith( Parameterized.class ) 39 | public class RuntimeErrors { 40 | 41 | private final ScriptEngine script; 42 | 43 | public RuntimeErrors( ScriptEngine script ) { 44 | this.script = script; 45 | } 46 | 47 | @Parameters( name = "{0}" ) 48 | public static Collection data() { 49 | return ScriptEngine.testParams(); 50 | } 51 | 52 | private void compileErrorTest( String expectedMessge, Class classes ) throws IOException { 53 | WasmRule wasm = new WasmRule( classes ); 54 | try { 55 | wasm.compile(); 56 | fail( "Exception expected with: " + expectedMessge ); 57 | } catch( WasmException ex ) { 58 | assertTrue( "Wrong error message: " + ex.getMessage(), ex.getMessage().contains( expectedMessge ) ); 59 | } finally { 60 | wasm.delete(); 61 | } 62 | 63 | } 64 | 65 | @Test 66 | public void nonStaticExport() throws IOException { 67 | compileErrorTest( "Export method must be static:", NonStaticExport.class ); 68 | } 69 | 70 | static class NonStaticExport { 71 | @Export 72 | float function() { 73 | return 1; 74 | } 75 | } 76 | 77 | @Test 78 | public void nonStaticImport() throws IOException { 79 | compileErrorTest( "Import method must be static:", NonStaticImport.class ); 80 | } 81 | 82 | static class NonStaticImport { 83 | @Import( module = "m", name = "n" ) 84 | float function() { 85 | return 1; 86 | } 87 | } 88 | 89 | @Test 90 | public void nativeMethod() throws IOException { 91 | compileErrorTest( "Native methods cannot be compiled to WebAssembly:", NativeMethod.class ); 92 | } 93 | 94 | static class NativeMethod { 95 | @Export 96 | native static float function(); 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /src/de/inetsoftware/jwebassembly/module/WasmEmbbeddedCode.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2020 Volker Berlin (i-net software) 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | 16 | */ 17 | package de.inetsoftware.jwebassembly.module; 18 | 19 | import de.inetsoftware.jwebassembly.api.annotation.WasmTextCode; 20 | 21 | /** 22 | * Code that will directly embedded in the compiler output. The code can be written in Java or via Wat code. This is not 23 | * a replacement of runtime API. It emulate the behavior of the Java VM. 24 | *

25 | * The class should not have any references to classes of the JWebAssembly compiler to prevent that parts of the 26 | * compiler will be embedded. 27 | * 28 | * @author Volker Berlin 29 | */ 30 | class WasmEmbbeddedCode { 31 | 32 | /** 33 | * Integer division that throw an ArithmeticException on a division by zero instead a trap of the WebAssembly 34 | * engine. 35 | * 36 | * @param quotient 37 | * the quotient of the operation 38 | * @param divisor 39 | * the divisor of the operation 40 | * @return the result 41 | */ 42 | @WasmTextCode( "local.get 1 " + // 43 | "i32.eqz " + // 44 | "if " + // 45 | "call $de/inetsoftware/jwebassembly/module/WasmEmbbeddedCode.createDivByZero()Ljava/lang/ArithmeticException; " + // 46 | "throw " + // 47 | "end " + // 48 | "local.get 0 " + // 49 | "local.get 1 " + // 50 | "i32.div_s " + // 51 | "return" ) 52 | static native int idiv( int quotient, int divisor ); 53 | 54 | /** 55 | * Long division that throw an ArithmeticException on a division by zero instead a trap of the WebAssembly engine. 56 | * 57 | * @param quotient 58 | * the quotient 59 | * @param divisor 60 | * the divisior 61 | * @return the result 62 | */ 63 | @WasmTextCode( "local.get 1 " + // 64 | "i64.eqz " + // 65 | "if " + // 66 | "call $de/inetsoftware/jwebassembly/module/WasmEmbbeddedCode.createDivByZero()Ljava/lang/ArithmeticException; " + // 67 | "throw " + // 68 | "end " + // 69 | "local.get 0 " + // 70 | "local.get 1 " + // 71 | "i64.div_s " + // 72 | "return" ) 73 | static native long ldiv( long quotient, long divisor ); 74 | 75 | /** 76 | * Create an ArithmeticException with message "/ by zero" 77 | * 78 | * @return the exception 79 | */ 80 | static ArithmeticException createDivByZero() { 81 | return new ArithmeticException( "/ by zero" ); 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /src/de/inetsoftware/jwebassembly/module/DupThis.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2019 - 2022 Volker Berlin (i-net software) 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | 16 | */ 17 | package de.inetsoftware.jwebassembly.module; 18 | 19 | import java.io.IOException; 20 | 21 | import javax.annotation.Nonnull; 22 | 23 | import de.inetsoftware.jwebassembly.wasm.AnyType; 24 | import de.inetsoftware.jwebassembly.wasm.VariableOperator; 25 | 26 | /** 27 | * This class save a reference of THIS to a temporary variable for a later virtual caLL. The reference of THIS is used for accessing the vtable of the object. 28 | * 29 | * @author Volker Berlin 30 | */ 31 | class DupThis extends WasmInstruction { 32 | 33 | @Nonnull 34 | private WasmCallIndirectInstruction virtualCall; 35 | 36 | private int tempVarSlot; 37 | 38 | private LocaleVariableManager localVariables; 39 | 40 | /** 41 | * Create a instance. 42 | * 43 | * @param virtualCall 44 | * the related virtual function call. 45 | * @param tempVarSlot 46 | * the slot of the temporary variable 47 | * @param localVariables 48 | * the manager for local variables 49 | * @param javaCodePos 50 | * the code position 51 | */ 52 | DupThis( @Nonnull WasmCallIndirectInstruction virtualCall, int tempVarSlot, LocaleVariableManager localVariables, int javaCodePos ) { 53 | super( javaCodePos, virtualCall.getLineNumber() ); 54 | this.virtualCall = virtualCall; 55 | this.tempVarSlot = tempVarSlot; 56 | this.localVariables = localVariables; 57 | } 58 | 59 | /** 60 | * Get the related virtual function call. 61 | * @return the call 62 | */ 63 | @Nonnull 64 | WasmCallIndirectInstruction getValue() { 65 | return virtualCall; 66 | } 67 | 68 | /** 69 | * {@inheritDoc} 70 | */ 71 | @Override 72 | Type getType() { 73 | return Type.DupThis; 74 | } 75 | 76 | /** 77 | * {@inheritDoc} 78 | */ 79 | @Override 80 | void writeTo( ModuleWriter writer ) throws IOException { 81 | if( virtualCall.isVirtual() ) { 82 | writer.writeLocal( VariableOperator.tee, localVariables.get( tempVarSlot, getCodePosition() ) ); 83 | } 84 | } 85 | 86 | /** 87 | * {@inheritDoc} 88 | */ 89 | @Override 90 | AnyType getPushValueType() { 91 | return null; 92 | } 93 | 94 | /** 95 | * {@inheritDoc} 96 | */ 97 | @Override 98 | int getPopCount() { 99 | return 0; 100 | } 101 | 102 | /** 103 | * {@inheritDoc} 104 | */ 105 | @Override 106 | AnyType[] getPopValueTypes() { 107 | return null; 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /src/de/inetsoftware/jwebassembly/module/WasmMemoryInstruction.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2019 - 2021 Volker Berlin (i-net software) 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | 16 | */ 17 | package de.inetsoftware.jwebassembly.module; 18 | 19 | import java.io.IOException; 20 | 21 | import javax.annotation.Nonnull; 22 | 23 | import de.inetsoftware.jwebassembly.wasm.AnyType; 24 | import de.inetsoftware.jwebassembly.wasm.MemoryOperator; 25 | import de.inetsoftware.jwebassembly.wasm.ValueType; 26 | 27 | /** 28 | * WasmInstruction for load and store to the linear memory. 29 | * 30 | * @author Volker Berlin 31 | * 32 | */ 33 | class WasmMemoryInstruction extends WasmInstruction { 34 | 35 | private MemoryOperator op; 36 | 37 | private ValueType type; 38 | 39 | private int offset; 40 | 41 | private int alignment; 42 | 43 | /** 44 | * Create an instance of a load/store to the linear memory instruction 45 | * 46 | * @param op 47 | * the operation 48 | * @param type 49 | * the type of the static field 50 | * @param offset 51 | * the base offset which will be added to the offset value on the stack 52 | * @param alignment 53 | * the alignment of the value on the linear memory (0: 8 Bit; 1: 16 Bit; 2: 32 Bit) 54 | * @param javaCodePos 55 | * the code position/offset in the Java method 56 | * @param lineNumber 57 | * the line number in the Java source code 58 | */ 59 | WasmMemoryInstruction( MemoryOperator op, ValueType type, int offset, int alignment, int javaCodePos, int lineNumber ) { 60 | super( javaCodePos, lineNumber ); 61 | this.op = op; 62 | this.type = type; 63 | this.offset = offset; 64 | this.alignment = alignment; 65 | } 66 | 67 | /** 68 | * {@inheritDoc} 69 | */ 70 | @Override 71 | Type getType() { 72 | return Type.Memory; 73 | } 74 | 75 | /** 76 | * {@inheritDoc} 77 | */ 78 | @Override 79 | public void writeTo( @Nonnull ModuleWriter writer ) throws IOException { 80 | writer.writeMemoryOperator( op, type, offset, alignment ); 81 | } 82 | 83 | /** 84 | * {@inheritDoc} 85 | */ 86 | @Override 87 | AnyType getPushValueType() { 88 | return op.name().startsWith( "load" ) ? type : null; 89 | } 90 | 91 | /** 92 | * {@inheritDoc} 93 | */ 94 | @Override 95 | int getPopCount() { 96 | return op.name().startsWith( "load" ) ? 0 : 1; 97 | } 98 | 99 | /** 100 | * {@inheritDoc} 101 | */ 102 | @Override 103 | AnyType[] getPopValueTypes() { 104 | return op.name().startsWith( "load" ) ? null : new AnyType[] { type }; 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /src/de/inetsoftware/jwebassembly/wasm/LittleEndianOutputStream.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Volker Berlin (i-net software) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package de.inetsoftware.jwebassembly.wasm; 17 | 18 | import java.io.ByteArrayOutputStream; 19 | import java.io.FilterOutputStream; 20 | import java.io.IOException; 21 | import java.io.OutputStream; 22 | 23 | /** 24 | * outputStream with little endian encoding like in Wasm. 25 | * 26 | * @author Volker Berlin 27 | */ 28 | public class LittleEndianOutputStream extends FilterOutputStream { 29 | 30 | private int count; 31 | 32 | /** 33 | * Create a in memory stream. 34 | */ 35 | public LittleEndianOutputStream() { 36 | super( new ByteArrayOutputStream() ); 37 | } 38 | 39 | /** 40 | * Create a wrapped stream. 41 | * 42 | * @param output 43 | * the target of data 44 | */ 45 | public LittleEndianOutputStream( OutputStream output ) { 46 | super( output ); 47 | } 48 | 49 | /** 50 | * {@inheritDoc} 51 | */ 52 | @Override 53 | public void write( int b ) throws IOException { 54 | out.write( b ); 55 | count++; 56 | } 57 | 58 | /** 59 | * {@inheritDoc} 60 | */ 61 | @Override 62 | public void write( byte[] b, int off, int len ) throws IOException { 63 | out.write( b, off, len ); 64 | count += len; 65 | } 66 | 67 | /** 68 | * Write a integer little endian (ever 4 bytes) 69 | * 70 | * @param value 71 | * the value 72 | * @throws IOException 73 | * if an I/O error occurs. 74 | */ 75 | public void writeInt32( int value ) throws IOException { 76 | write( value >>> 0 ); 77 | write( value >>> 8 ); 78 | write( value >>> 16 ); 79 | write( value >>> 24 ); 80 | } 81 | 82 | /** 83 | * Write the data of this stream to the output. Work only for in memory stream. 84 | * 85 | * @param output 86 | * the target 87 | * @throws IOException 88 | * if any I/O error occur 89 | */ 90 | public void writeTo( OutputStream output ) throws IOException { 91 | ByteArrayOutputStream baos = (ByteArrayOutputStream)out; 92 | baos.writeTo( output ); 93 | } 94 | 95 | /** 96 | * The count of bytes in the stream. 97 | * 98 | * @return the data size 99 | */ 100 | public int size() { 101 | return count; 102 | } 103 | 104 | /** 105 | * Reset the stream. Work only for in memory stream. 106 | */ 107 | public void reset() { 108 | ByteArrayOutputStream baos = (ByteArrayOutputStream)out; 109 | baos.reset(); 110 | count = 0; 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /src/de/inetsoftware/jwebassembly/module/WasmInstruction.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2018 - 2022 Volker Berlin (i-net software) 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | 16 | */ 17 | package de.inetsoftware.jwebassembly.module; 18 | 19 | import java.io.IOException; 20 | 21 | import javax.annotation.Nonnull; 22 | import javax.annotation.Nullable; 23 | 24 | import de.inetsoftware.jwebassembly.wasm.AnyType; 25 | 26 | /** 27 | * Base class of all WasmInstruction. 28 | * 29 | * @author Volker Berlin 30 | * 31 | */ 32 | abstract class WasmInstruction { 33 | 34 | /** 35 | * Type of instruction to faster differ as with instanceof. 36 | */ 37 | static enum Type { 38 | Const, String, Clazz, Convert, Local, Global, Table, Memory, Block, Numeric, Nop, Jump, Call, CallVirtual, CallInterface, Array, Struct, DupThis; 39 | } 40 | 41 | private int javaCodePos; 42 | 43 | private final int lineNumber; 44 | 45 | /** 46 | * Create a new instance of an instruction 47 | * 48 | * @param javaCodePos 49 | * the code position/offset in the Java method 50 | * @param lineNumber 51 | * the line number in the Java source code 52 | */ 53 | WasmInstruction( int javaCodePos, int lineNumber ) { 54 | this.javaCodePos = javaCodePos; 55 | this.lineNumber = lineNumber; 56 | } 57 | 58 | /** 59 | * Get the type of instruction 60 | * 61 | * @return the type 62 | */ 63 | @Nonnull 64 | abstract Type getType(); 65 | 66 | /** 67 | * Write this instruction to the WASM module. 68 | * 69 | * @param writer 70 | * the target writer 71 | * @throws IOException 72 | * if any I/O error occur 73 | */ 74 | abstract void writeTo( @Nonnull ModuleWriter writer ) throws IOException; 75 | 76 | /** 77 | * Get current code position in Java method. 78 | * 79 | * @return the position 80 | */ 81 | int getCodePosition() { 82 | return javaCodePos; 83 | } 84 | 85 | /** 86 | * Get the line number in the Java source file 87 | * 88 | * @return the line number 89 | */ 90 | int getLineNumber() { 91 | return lineNumber; 92 | } 93 | 94 | /** 95 | * Set a new code position after reorganize the order 96 | * 97 | * @param newPos 98 | * new position 99 | */ 100 | void setCodePosition( int newPos ) { 101 | this.javaCodePos = newPos; 102 | } 103 | 104 | /** 105 | * Get the ValueType if this instruction push a value on the stack. 106 | * 107 | * @return the ValueType or null if no value is push 108 | */ 109 | @Nullable 110 | abstract AnyType getPushValueType(); 111 | 112 | /** 113 | * Get the count of values that are removed from the stack. 114 | * 115 | * @return the count 116 | */ 117 | abstract int getPopCount(); 118 | 119 | abstract AnyType[] getPopValueTypes(); 120 | } 121 | -------------------------------------------------------------------------------- /docs/samples/HelloWorld/HelloWorld.wasm.map: -------------------------------------------------------------------------------- 1 | { 2 | "version":3, 3 | "sources":["java/lang/Double.java","java/lang/Float.java","java/lang/Object.java","de/inetsoftware/jwebassembly/web/JSObject.java","java/lang/StringCoding.java","java/lang/System.java","java/lang/Throwable.java","HelloWorld.java","de/inetsoftware/jwebassembly/web/dom/Window.java","de/inetsoftware/jwebassembly/module/nativecode/StringTable.java","de/inetsoftware/jwebassembly/web/dom/Document.java","de/inetsoftware/jwebassembly/web/dom/Node.java","java/lang/String.java","de/inetsoftware/jwebassembly/web/dom/HTMLElement.java","de/inetsoftware/jwebassembly/web/dom/Text.java","de/inetsoftware/jwebassembly/web/dom/Element.java","de/inetsoftware/jwebassembly/web/dom/CharacterData.java","de/inetsoftware/jwebassembly/web/dom/EventTarget.java","java/util/Arrays.java","java/lang/StringIndexOutOfBoundsException.java","java/lang/Math.java","java/lang/StringBuilder.java","java/lang/IndexOutOfBoundsException.java","java/lang/AbstractStringBuilder.java","java/lang/RuntimeException.java","java/lang/Integer.java","java/lang/Exception.java","java/lang/IllegalArgumentException.java","java/lang/OutOfMemoryError.java","java/lang/VirtualMachineError.java","java/lang/Error.java","java/lang/ThreadLocal.java","java/lang/ReplacementForClass.java","java/util/ArrayList.java","java/util/Collections.java","java/lang/AssertionError.java","java/util/AbstractList.java","java/util/concurrent/atomic/ReplacementForAtomicInteger.java","java/util/AbstractCollection.java","java/lang/NullPointerException.java","java/lang/Number.java","java/util/AbstractSet.java","java/util/AbstractMap.java"], 4 | "names":[], 5 | "mappings":"qnFAmCA,OAWA,OCXA,OCFA,MCwBA,QACA,CAEA,iBACA,QAEA,cC9BA,IACA,SACA,SAoBA,AApBA,EACA,mBAEA,IAEA,QACA,6BACA,OACA,iDACA,AACA,oEAEA,gCAEA,aAGA,uBAjBA,EAoBA,uBCtBA,ICHA,IAEA,IAOA,cCdA,IACA,eACA,iBACA,aACA,wBACA,MCYA,mCCLA,MACA,EACA,KAIA,aACA,IAEA,IAEA,iBACA,cACA,OACA,MAGA,UACA,aACA,eADA,SAGA,eAEA,MACA,QCnBA,+CAWA,iCASA,iBACA,CACA,KAEA,eCzBA,sBACA,IDXA,MACA,8BEqhBA,YACA,cCvhBA,MACA,ICDA,MACA,IHDA,MACA,IRoCA,US2dA,IACA,QACA,cACA,ITpaA,qBY/FA,MACA,ICDA,MACA,Ib+DA,gBcjEA,MACA,Id8GA,oBSqsFA,YACA,sBACA,MVhzFA,MUuVA,KACA,aACA,MACA,aACA,WACA,gBACA,OMk4FA,MACA,cACA,EADA,EAEA,Mf5tGA,IACA,QACA,MgBwBA,mDACA,ICkvCA,iBC/tCA,MACA,IA8CA,OACA,MAuEA,OACA,QAsMA,0BC/VA,MACA,ICUA,IACA,UACA,MAwXA,GACA,OACA,cACA,aACA,2BACA,eACA,QAwNA,SACA,kBACA,GAEA,qBACA,KACA,WACA,MACA,YACA,QACA,SXveA,IACA,KACA,aAEA,MACA,OACA,iBAEA,OACA,oBACA,CAIA,WACA,gBAEA,kBACA,IYlJA,MACA,QD6aA,QACA,SACA,QACA,cACA,gBACA,gBACA,gBACA,QACA,MX2HA,YWpfA,cACA,cACA,EADA,MAGA,OXkrBA,KACA,aAEA,YACA,aAEA,MACA,gBAEA,oBACA,ManWA,IACA,aACA,QAFA,mBArCA,IACA,IAEA,KACA,MACA,OAIA,YACA,UAEA,sBACA,IACA,iBACA,mBAMA,mBACA,gBACA,iBACA,IACA,OAEA,KACA,eAEA,aP4nGA,OACA,GACA,uEACA,OACA,iBACA,EADA,EAEA,MQjhHA,MACA,MHmFA,gBACA,MACA,MAEA,8BACA,KADA,KItGA,MACA,IrBmNA,IAnEA,QAaA,QAiBA,QAsCA,YACA,QACA,MiB3GA,YACA,WAEA,0BKnHA,IACA,ICNA,IACA,ICcA,IACA,MlBsEA,MA+hCA,gBVvnCA,EACA,MEaA,UAEA,UAGA,UcWA,gCbDA,EAaA,IA2BA,IAcA,IAIA,IA2EA,UelGA,4BA6oCA,UACA,aAqjCA,OACA,gBKruEA,QAKA,wYAyQA,mhCAaA,mhCAgHA,wInBjWA,4BA6CA,MAuDA,UACA,IA00BA,Uer9BA,iBAAA,iBTslCA,SmB9gCA,IA/DA,SAgEA,UC7CA,OACA,EACA,KAaA,eACA,aAEA,OACA,MAkHA,QZskEA,yCACA,mCYlmEA,waAEA,kBAEA,MAEA,MAEA,MAEA,MAEA,MAEA,MAEA,MAEA,MAEA,YC/EA,KACA,KACA,YACA,MACA,UAEA,yDAGA,UCumCA,wCtBrGA,UmBzjCA,8CClDA,IACA,QACA,cGRA,IACA,UvBw4CA,QACA,gBACA,cAEA,mBACA,gBADA,SAGA,WAEA,gBAlfA,MACA,KAEA,WACA,WACA,UACA,SACA,cACA,QACA,IACA,gBACA,eACA,KACA,UAEA,MAGA,OwBv5BA,KA6gBA,QA5gBA,oEFsyCA,OACA,IA9FA,OACA,QACA,MGpsCA,QACA,WACA,qBCpBA,IACA,MJ67BA,IACA,GACA,YACA,SACA,IKx8BA,KACA,IfVA,KACA,IEEA,IACA,MKoCA,e9B8CA,YDEA,YiCnBA,MAOA,gBCwjIA,aAsHA,aAqGA,iBG52IA,KACA,IH6qIA,SAuHA,SA6IA,SMj6IA,QN6pIA,SAuHA,SA6IA,SOz5IA,KACA,ICSA,IACA;" 6 | } -------------------------------------------------------------------------------- /test/de/inetsoftware/jwebassembly/ScriptEngine.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 - 2021 Volker Berlin (i-net software) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package de.inetsoftware.jwebassembly; 17 | 18 | import java.util.ArrayList; 19 | import java.util.Collection; 20 | 21 | /** 22 | * @author Volker Berlin 23 | */ 24 | public enum ScriptEngine { 25 | /** 26 | * Test the binary output with a fix version nodejs JavaScript runtime. GC is disabled. 27 | */ 28 | NodeJS, 29 | /** 30 | * Test the binary output with the nightly SpiderMonkey JavaScript runtime. GC is disabled. 31 | */ 32 | SpiderMonkey, 33 | /** 34 | * Convert the text output with the nightly wabt.js (https://github.com/AssemblyScript/wabt.js/) and test it 35 | * with nodejs. GC is disabled. 36 | */ 37 | NodeWat, 38 | /** 39 | * Convert the text output with wasmTextToBinary function form nightly SpiderMonkey. GC is disabled. 40 | */ 41 | SpiderMonkeyWat, 42 | /** 43 | * Convert the text output with wat2wasm https://github.com/WebAssembly/wabt and test it with nodejs. GC is 44 | * disabled. 45 | */ 46 | Wat2Wasm, 47 | /** 48 | * Test the binary output with a fix version nodejs JavaScript runtime. GC is enabled. 49 | */ 50 | NodeJsGC( true ), 51 | /** 52 | * Test the binary output with the nightly SpiderMonkey JavaScript runtime. GC is enabled. 53 | */ 54 | SpiderMonkeyGC( true ), 55 | /** 56 | * Convert the text output with the nightly wabt.js (https://github.com/AssemblyScript/wabt.js/) and tun the test 57 | * with nodejs. GC is enabled. 58 | */ 59 | NodeWatGC( true ), 60 | /** 61 | * Convert the text output with wasmTextToBinary function form nightly SpiderMonkey. GC is enabled. 62 | */ 63 | SpiderMonkeyWatGC( true ), 64 | /** 65 | * Convert the text output with wat2wasm https://github.com/WebAssembly/wabt and test it with nodejs. GC is enabled. 66 | */ 67 | Wat2WasmGC( true ), 68 | ; 69 | 70 | public final String useGC; 71 | 72 | private ScriptEngine() { 73 | this.useGC = null; 74 | } 75 | 76 | private ScriptEngine( boolean useGC ) { 77 | this.useGC = Boolean.toString( useGC ); 78 | } 79 | 80 | public static ScriptEngine[] testEngines() { 81 | ScriptEngine[] val = { // 82 | SpiderMonkey, // 83 | NodeJS, // 84 | // NodeWat, // disabled because https://github.com/AssemblyScript/wabt.js/issues/26 85 | SpiderMonkeyWat,// 86 | Wat2Wasm, // 87 | }; 88 | return val; 89 | } 90 | 91 | public static Collection testParams() { 92 | ArrayList val = new ArrayList<>(); 93 | for( ScriptEngine script : ScriptEngine.testEngines() ) { 94 | val.add( new ScriptEngine[] { script } ); 95 | } 96 | return val; 97 | } 98 | } 99 | 100 | -------------------------------------------------------------------------------- /test/de/inetsoftware/jwebassembly/Node.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 - 2022 Volker Berlin (i-net software) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package de.inetsoftware.jwebassembly; 17 | 18 | import static de.inetsoftware.jwebassembly.SpiderMonkey.extractStream; 19 | 20 | import java.io.File; 21 | import java.io.IOException; 22 | import java.io.InputStream; 23 | import java.net.HttpURLConnection; 24 | import java.net.URL; 25 | import java.text.MessageFormat; 26 | 27 | /** 28 | * Download the node tool. 29 | * 30 | * @author Volker Berlin 31 | */ 32 | public class Node { 33 | 34 | private String command; 35 | 36 | private static final String BASE_URL = "https://nodejs.org/download/v8-canary/"; 37 | 38 | private static final String REVISION = "17.0.0-v8-canary20211019bcdcfc880b"; 39 | 40 | /** 41 | * Check if there is a new version of the script engine 42 | * 43 | * @throws IOException 44 | * if any error occur 45 | */ 46 | private void download() throws IOException { 47 | String fileName; 48 | String ext; 49 | final String os = System.getProperty( "os.name", "" ).toLowerCase(); 50 | if( os.contains( "windows" ) ) { 51 | boolean is32 = "32".equals( System.getProperty( "sun.arch.data.model" ) ); 52 | fileName = is32 ? "win-x86" : "win-x64"; 53 | ext = "zip"; 54 | } else if( os.contains( "mac" ) ) { 55 | fileName = "darwin-x64"; 56 | ext = "tar.gz"; 57 | } else if( os.contains( "linux" ) ) { 58 | fileName = "linux-x64"; 59 | ext = "tar.gz"; 60 | } else { 61 | throw new IllegalStateException( "Unknown OS: " + os ); 62 | } 63 | String urlStr = MessageFormat.format( "{0}v{1}/node-v{1}-{2}.{3}", BASE_URL, REVISION, fileName, ext ); 64 | 65 | File target = new File( System.getProperty( "java.io.tmpdir" ) + "/node" ); 66 | File commandDir = new File( target.getAbsolutePath() + MessageFormat.format( "/node-v{1}-{2}", BASE_URL, REVISION, fileName, ext ) ); 67 | 68 | if( commandDir.isDirectory() && commandDir.list().length > 1 ) { 69 | // no download needed 70 | System.out.println( "\tUP-TP-DATE, use version from " + commandDir ); 71 | } else { 72 | URL url = new URL( urlStr ); 73 | System.out.println( "\tDownload: " + url ); 74 | HttpURLConnection conn = (HttpURLConnection)url.openConnection(); 75 | conn.setConnectTimeout( 5000 ); 76 | 77 | InputStream input = conn.getInputStream(); 78 | 79 | extractStream( input, "tar.gz".equals( ext ), target ); 80 | } 81 | 82 | command = commandDir.getAbsolutePath(); 83 | } 84 | 85 | /** 86 | * Get the node command. If file not exists then download it. 87 | * 88 | * @return the path to the executable 89 | * @throws IOException 90 | * if any I/O error occur 91 | */ 92 | public String getNodeDir() throws IOException { 93 | if( command == null ) { 94 | download(); 95 | } 96 | return command; 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /src/de/inetsoftware/jwebassembly/module/WasmGlobalInstruction.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2018 - 2022 Volker Berlin (i-net software) 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | 16 | */ 17 | package de.inetsoftware.jwebassembly.module; 18 | 19 | import java.io.IOException; 20 | 21 | import javax.annotation.Nonnull; 22 | import javax.annotation.Nullable; 23 | 24 | import de.inetsoftware.jwebassembly.wasm.AnyType; 25 | 26 | /** 27 | * WasmInstruction for set and get global variables. 28 | * 29 | * @author Volker Berlin 30 | * 31 | */ 32 | class WasmGlobalInstruction extends WasmInstruction { 33 | 34 | private boolean load; 35 | 36 | private FunctionName name; 37 | 38 | private AnyType type; 39 | 40 | private FunctionName clinit; 41 | 42 | /** 43 | * Create an instance of a load/store instruction 44 | * 45 | * @param load 46 | * true: if load or GET 47 | * @param name 48 | * the name of the static field 49 | * @param type 50 | * the type of the static field 51 | * @param clinit 52 | * a reference to the class/static constructor which should executed before access a static field 53 | * @param javaCodePos 54 | * the code position/offset in the Java method 55 | * @param lineNumber 56 | * the line number in the Java source code 57 | */ 58 | WasmGlobalInstruction( boolean load, @Nonnull FunctionName name, AnyType type, @Nullable FunctionName clinit, int javaCodePos, int lineNumber ) { 59 | super( javaCodePos, lineNumber ); 60 | this.load = load; 61 | this.name = name; 62 | this.type = type; 63 | this.clinit = clinit; 64 | } 65 | 66 | /** 67 | * {@inheritDoc} 68 | */ 69 | @Override 70 | Type getType() { 71 | return Type.Global; 72 | } 73 | 74 | /** 75 | * The name of the field 76 | * 77 | * @return the field 78 | */ 79 | @Nonnull 80 | FunctionName getFieldName() { 81 | return name; 82 | } 83 | 84 | /** 85 | * {@inheritDoc} 86 | */ 87 | @Override 88 | public void writeTo( @Nonnull ModuleWriter writer ) throws IOException { 89 | if( clinit != null ) { 90 | writer.writeFunctionCall( clinit, clinit.signatureName ); 91 | } 92 | writer.writeGlobalAccess( load, name, type ); 93 | } 94 | 95 | /** 96 | * {@inheritDoc} 97 | */ 98 | @Override 99 | AnyType getPushValueType() { 100 | return load ? type : null; 101 | } 102 | 103 | /** 104 | * {@inheritDoc} 105 | */ 106 | @Override 107 | int getPopCount() { 108 | return load ? 0 : 1; 109 | } 110 | 111 | /** 112 | * {@inheritDoc} 113 | */ 114 | @Override 115 | AnyType[] getPopValueTypes() { 116 | return load ? null : new AnyType[] { type }; 117 | } 118 | 119 | /** 120 | * Only used for debugging 121 | */ 122 | @Override 123 | public String toString() { 124 | return getClass().getSimpleName() + ": global." + (load ? "get $" : "set $") + name.fullName; 125 | } 126 | } 127 | -------------------------------------------------------------------------------- /src/de/inetsoftware/classparser/CodeInputStream.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2011 - 2018 Volker Berlin (i-net software) 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | 16 | */ 17 | package de.inetsoftware.classparser; 18 | 19 | import java.io.ByteArrayInputStream; 20 | import java.io.DataInputStream; 21 | import java.io.IOException; 22 | 23 | /** 24 | * Extends the DataInputStream with a code position. 25 | * 26 | * @author Volker Berlin 27 | */ 28 | public class CodeInputStream extends DataInputStream { 29 | 30 | private Code code; 31 | 32 | /** 33 | * Create a new instance of CodeInputStream. 34 | * 35 | * @param buf 36 | * the buffer with the Java byte code 37 | * @param offset 38 | * the offset in the array 39 | * @param length 40 | * the length 41 | * @param code 42 | * the calling code to get the line numbers 43 | */ 44 | CodeInputStream( byte[] buf, int offset, int length, Code code ) { 45 | this( new ByteCodeArrayInputStream( buf, offset, length ) ); 46 | this.code = code; 47 | } 48 | 49 | private CodeInputStream( ByteCodeArrayInputStream in ) { 50 | super( in ); 51 | } 52 | 53 | /** 54 | * Get the code index of the current read position. 55 | * 56 | * @return the position 57 | */ 58 | public int getCodePosition() { 59 | return ((ByteCodeArrayInputStream)in).getCodePosition(); 60 | } 61 | 62 | /** 63 | * Line number in the source code or -1 if not available 64 | * 65 | * @return the line number 66 | */ 67 | public int getLineNumber() { 68 | int lineNumber = -1; 69 | try { 70 | LineNumberTable lineNumberTable = code.getLineNumberTable(); 71 | if( lineNumberTable != null ) { 72 | int codePos = getCodePosition(); 73 | for( int i = 0; i < lineNumberTable.size(); i++ ) { 74 | int offset = lineNumberTable.getStartOffset( i ); 75 | if( offset > codePos ) { 76 | break; 77 | } 78 | lineNumber = lineNumberTable.getLineNumber( i ); 79 | } 80 | } 81 | } catch( IOException e ) { 82 | // ignore, line naumber are only needed for debug information 83 | } 84 | return lineNumber; 85 | } 86 | 87 | private static class ByteCodeArrayInputStream extends ByteArrayInputStream { 88 | 89 | ByteCodeArrayInputStream( byte[] buf, int offset, int length ) { 90 | super( buf, offset, length ); 91 | } 92 | 93 | int getCodePosition() { 94 | return pos; 95 | } 96 | } 97 | 98 | /** 99 | * Read an unsigned index. For example for a variable. 100 | * 101 | * @param wide 102 | * true, 2 byte index 103 | * @return the unsigned value 104 | * @throws IOException 105 | * if any I/O errors occur 106 | */ 107 | public int readUnsignedIndex( boolean wide ) throws IOException { 108 | return wide ? readUnsignedShort() : readUnsignedByte(); 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /src/de/inetsoftware/jwebassembly/module/WasmConvertInstruction.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 - 2021 Volker Berlin (i-net software) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package de.inetsoftware.jwebassembly.module; 17 | 18 | import java.io.IOException; 19 | 20 | import de.inetsoftware.jwebassembly.wasm.AnyType; 21 | import de.inetsoftware.jwebassembly.wasm.ValueType; 22 | 23 | /** 24 | * Cast operations for converting one data type to another 25 | * 26 | * @author Volker Berlin 27 | * 28 | */ 29 | class WasmConvertInstruction extends WasmInstruction { 30 | 31 | private ValueTypeConvertion conversion; 32 | 33 | /** 34 | * Create an instance of a convert instruction 35 | * 36 | * @param conversion 37 | * the conversion type 38 | * @param javaCodePos 39 | * the code position/offset in the Java method 40 | * @param lineNumber 41 | * the line number in the Java source code 42 | */ 43 | WasmConvertInstruction( ValueTypeConvertion conversion, int javaCodePos, int lineNumber ) { 44 | super( javaCodePos, lineNumber ); 45 | this.conversion = conversion; 46 | } 47 | 48 | /** 49 | * {@inheritDoc} 50 | */ 51 | @Override 52 | Type getType() { 53 | return Type.Convert; 54 | } 55 | 56 | /** 57 | * {@inheritDoc} 58 | */ 59 | @Override 60 | public void writeTo( ModuleWriter writer ) throws IOException { 61 | writer.writeCast( conversion ); 62 | } 63 | 64 | /** 65 | * {@inheritDoc} 66 | */ 67 | AnyType getPushValueType() { 68 | switch( conversion ) { 69 | case l2i: 70 | case f2i: 71 | case d2i: 72 | case i2b: 73 | case i2c: 74 | case i2s: 75 | return ValueType.i32; 76 | case i2l: 77 | case f2l: 78 | case d2l: 79 | return ValueType.i64; 80 | case i2f: 81 | case l2f: 82 | case d2f: 83 | return ValueType.f32; 84 | case i2d: 85 | case l2d: 86 | case f2d: 87 | return ValueType.f64; 88 | default: 89 | throw new Error( conversion.toString() ); 90 | } 91 | } 92 | 93 | /** 94 | * {@inheritDoc} 95 | */ 96 | @Override 97 | int getPopCount() { 98 | return 1; 99 | } 100 | 101 | /** 102 | * {@inheritDoc} 103 | */ 104 | @Override 105 | AnyType[] getPopValueTypes() { 106 | switch( conversion ) { 107 | case i2b: 108 | case i2c: 109 | case i2s: 110 | case i2l: 111 | case i2f: 112 | case i2d: 113 | return new AnyType[] { ValueType.i32 }; 114 | case l2i: 115 | case l2f: 116 | case l2d: 117 | return new AnyType[] { ValueType.i64 }; 118 | case f2i: 119 | case f2l: 120 | case f2d: 121 | return new AnyType[] { ValueType.f32 }; 122 | case d2i: 123 | case d2l: 124 | case d2f: 125 | return new AnyType[] { ValueType.f64 }; 126 | default: 127 | throw new Error( conversion.toString() ); 128 | } 129 | } 130 | } 131 | -------------------------------------------------------------------------------- /test/de/inetsoftware/jwebassembly/javascript/JavaScriptWriterTest.java: -------------------------------------------------------------------------------- 1 | package de.inetsoftware.jwebassembly.javascript; 2 | 3 | import static org.junit.Assert.assertEquals; 4 | 5 | import java.io.IOException; 6 | import java.util.Collections; 7 | import java.util.Map; 8 | import java.util.function.Function; 9 | 10 | import org.junit.ClassRule; 11 | import org.junit.Test; 12 | import org.junit.rules.TemporaryFolder; 13 | 14 | import de.inetsoftware.jwebassembly.module.WasmTarget; 15 | 16 | public class JavaScriptWriterTest { 17 | 18 | @ClassRule 19 | public static TemporaryFolder temp = new TemporaryFolder(); 20 | 21 | Function f(Map map) { 22 | return (key) -> map.get( key ); 23 | } 24 | 25 | @Test 26 | public void single() throws IOException { 27 | JavaScriptWriter writer = new JavaScriptWriter( new WasmTarget( temp.newFile() ) ); 28 | writer.addImport( "Foo", "bar", f( Collections.singletonMap( JavaScriptWriter.JAVA_SCRIPT_CONTENT, "1 + 1" ) ) ); 29 | StringBuilder builder = new StringBuilder(); 30 | writer.finish( builder ); 31 | assertEquals( "'use strict';var wasmImports = {\n" + 32 | "Foo:{\n" + 33 | "bar:1 + 1\n" + 34 | "}\n" + 35 | "};\n" + 36 | "if (typeof module !== 'undefined') module.exports = wasmImports;", builder.toString() ); 37 | } 38 | 39 | @Test 40 | public void twoFunctions() throws IOException { 41 | JavaScriptWriter writer = new JavaScriptWriter( new WasmTarget( temp.newFile() ) ); 42 | writer.addImport( "Foo", "bar", f( Collections.singletonMap( JavaScriptWriter.JAVA_SCRIPT_CONTENT, "1 + 1" ) ) ); 43 | writer.addImport( "Foo", "xyz", f( Collections.singletonMap( JavaScriptWriter.JAVA_SCRIPT_CONTENT, "3" ) ) ); 44 | StringBuilder builder = new StringBuilder(); 45 | writer.finish( builder ); 46 | assertEquals( "'use strict';var wasmImports = {\n" + 47 | "Foo:{\n" + 48 | "bar:1 + 1,\n" + 49 | "xyz:3\n" + 50 | "}\n" + 51 | "};\n" + 52 | "if (typeof module !== 'undefined') module.exports = wasmImports;", builder.toString() ); 53 | } 54 | 55 | @Test 56 | public void twoModules() throws IOException { 57 | JavaScriptWriter writer = new JavaScriptWriter( new WasmTarget( temp.newFile() ) ); 58 | writer.addImport( "Foo", "foo", f( Collections.singletonMap( JavaScriptWriter.JAVA_SCRIPT_CONTENT, "1 + 1" ) ) ); 59 | writer.addImport( "Bar", "bar", f( Collections.singletonMap( JavaScriptWriter.JAVA_SCRIPT_CONTENT, "3" ) ) ); 60 | StringBuilder builder = new StringBuilder(); 61 | writer.finish( builder ); 62 | assertEquals( "'use strict';var wasmImports = {\n" + 63 | "Bar:{\n" + 64 | "bar:3\n" + 65 | "},\n" + 66 | "Foo:{\n" + 67 | "foo:1 + 1\n" + 68 | "}\n" + 69 | "};\n" + 70 | "if (typeof module !== 'undefined') module.exports = wasmImports;", builder.toString() ); 71 | } 72 | 73 | @Test 74 | public void rootModule() throws IOException { 75 | JavaScriptWriter writer = new JavaScriptWriter( new WasmTarget( temp.newFile() ) ); 76 | writer.addImport( "Foo", "foo", f( Collections.emptyMap() ) ); 77 | writer.addImport( "Foo", "bar", f( Collections.emptyMap() ) ); 78 | StringBuilder builder = new StringBuilder(); 79 | writer.finish( builder ); 80 | assertEquals( "'use strict';var wasmImports = {\n" + 81 | "Foo:Foo\n" + 82 | "};\n" + 83 | "if (typeof module !== 'undefined') module.exports = wasmImports;", builder.toString() ); 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /src/de/inetsoftware/jwebassembly/wasm/ValueTypeParser.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 - 2019 Volker Berlin (i-net software) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package de.inetsoftware.jwebassembly.wasm; 17 | 18 | import java.util.Iterator; 19 | import java.util.NoSuchElementException; 20 | 21 | import de.inetsoftware.jwebassembly.WasmException; 22 | import de.inetsoftware.jwebassembly.module.TypeManager; 23 | 24 | /** 25 | * Parser for a Java signature. This can be a method signature or a signature of a field. 26 | * 27 | * @author Volker Berlin 28 | */ 29 | public class ValueTypeParser implements Iterator { 30 | private final String sig; 31 | 32 | private int idx; 33 | 34 | private final TypeManager types; 35 | 36 | /** 37 | * Create a new parser. 38 | * 39 | * @param javaSignature 40 | * the Java signature 41 | * @param types 42 | * the optional type manager 43 | */ 44 | public ValueTypeParser( String javaSignature, TypeManager types ) { 45 | this.sig = javaSignature; 46 | this.types = types; 47 | if( javaSignature.startsWith( "(" ) ) { 48 | idx++; 49 | } 50 | } 51 | 52 | /** 53 | * {@inheritDoc} 54 | */ 55 | public boolean hasNext() { 56 | return idx < sig.length(); 57 | } 58 | 59 | /** 60 | * Get the next value in the signature or null if the parameter are end or the signature is end. 61 | * 62 | * @return next type or null 63 | */ 64 | public AnyType next() { 65 | return next( false ); 66 | } 67 | 68 | /** 69 | * Get the next value in the signature or null if the parameter are end or the signature is end. 70 | * 71 | * @param isArray 72 | * true, if this is an element type of an array 73 | * @return next type or null 74 | */ 75 | private AnyType next( boolean isArray ) { 76 | if( !hasNext() ) { 77 | throw new NoSuchElementException(); 78 | } 79 | switch( sig.charAt( idx++ ) ) { 80 | case ')': 81 | return null; 82 | case '[': // array 83 | return types.arrayType( next( true ) ); 84 | case 'L': 85 | int idx2 = sig.indexOf( ';', idx ); 86 | String name = sig.substring( idx, idx2 ); 87 | idx = idx2 + 1; 88 | return types.valueOf( name ); 89 | case 'Z': // boolean 90 | return isArray ? ValueType.bool : ValueType.i32; 91 | case 'B': // byte 92 | return isArray ? ValueType.i8 : ValueType.i32; 93 | case 'C': // char 94 | return isArray ? ValueType.u16 : ValueType.i32; 95 | case 'S': // short 96 | return isArray ? ValueType.i16 : ValueType.i32; 97 | case 'I': // int 98 | return ValueType.i32; 99 | case 'D': // double 100 | return ValueType.f64; 101 | case 'F': // float 102 | return ValueType.f32; 103 | case 'J': // long 104 | return ValueType.i64; 105 | case 'V': // void 106 | return null; 107 | default: 108 | throw new WasmException( "Not supported Java data type in method signature: " + sig.substring( idx - 1 ), -1 ); 109 | } 110 | 111 | } 112 | } 113 | --------------------------------------------------------------------------------