frontend-hamroun 1.2.65 → 1.2.67
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/cli.js +190 -2
- package/dist/index.d.ts +2 -0
- package/dist/wasm.d.ts +36 -0
- package/package.json +1 -1
- package/templates/go/README.md +150 -0
- package/templates/go/build.bat +36 -0
- package/templates/go/build.sh +43 -0
- package/templates/go/example.go +137 -0
- package/templates/go-wasm-app/.tmp-wasm-build/example.go +75 -0
- package/templates/go-wasm-app/.tmp-wasm-build/go.mod +3 -0
- package/templates/go-wasm-app/README.md +21 -0
- package/templates/go-wasm-app/build-wasm.js +218 -0
- package/templates/go-wasm-app/package-lock.json +4123 -0
- package/templates/go-wasm-app/package.json +20 -0
- package/templates/go-wasm-app/public/index.html +13 -0
- package/templates/go-wasm-app/public/styles.css +167 -0
- package/templates/go-wasm-app/src/App.jsx +64 -0
- package/templates/go-wasm-app/src/components/WasmDemo.jsx +119 -0
- package/templates/go-wasm-app/src/main.jsx +7 -0
- package/templates/go-wasm-app/src/wasm/example.go +75 -0
- package/templates/go-wasm-app/vite.config.js +28 -0
package/bin/cli.js
CHANGED
@@ -149,13 +149,15 @@ async function chooseTemplate() {
|
|
149
149
|
'basic-app': '🚀',
|
150
150
|
'ssr-template': '🌐',
|
151
151
|
'fullstack-app': '⚡',
|
152
|
+
'go-wasm-app': '🔄',
|
152
153
|
};
|
153
154
|
|
154
155
|
// Detailed descriptions
|
155
156
|
const templateDescriptions = {
|
156
157
|
'basic-app': 'Single-page application with just the essentials. Perfect for learning the framework or building simple apps.',
|
157
158
|
'ssr-template': 'Server-side rendered application with hydration. Optimized for SEO and fast initial load.',
|
158
|
-
'fullstack-app': 'Complete solution with API routes, authentication, and database integration ready to go.'
|
159
|
+
'fullstack-app': 'Complete solution with API routes, authentication, and database integration ready to go.',
|
160
|
+
'go-wasm-app': 'WebAssembly integration with Go for high-performance computing in the browser and Node.js.'
|
159
161
|
};
|
160
162
|
|
161
163
|
console.log(boxen(
|
@@ -165,7 +167,8 @@ async function chooseTemplate() {
|
|
165
167
|
const shortDesc = {
|
166
168
|
'basic-app': 'Simple client-side application',
|
167
169
|
'ssr-template': 'Server-side rendering with hydration',
|
168
|
-
'fullstack-app': 'Complete fullstack application with API'
|
170
|
+
'fullstack-app': 'Complete fullstack application with API',
|
171
|
+
'go-wasm-app': 'Go WebAssembly application'
|
169
172
|
}[template] || 'Application template';
|
170
173
|
|
171
174
|
return `${icon} ${chalk.cyan(template)}\n ${chalk.dim(shortDesc)}`;
|
@@ -253,6 +256,23 @@ async function chooseTemplate() {
|
|
253
256
|
'• Full production applications',
|
254
257
|
'• Apps needing authentication',
|
255
258
|
'• Projects requiring database integration'
|
259
|
+
],
|
260
|
+
'go-wasm-app': [
|
261
|
+
`${chalk.bold('Go WASM App Template')} ${templateIcons['go-wasm-app']}`,
|
262
|
+
'',
|
263
|
+
`${chalk.dim('WebAssembly integration with Go programming language.')}`,
|
264
|
+
'',
|
265
|
+
`${chalk.yellow('Features:')}`,
|
266
|
+
'• Go + WebAssembly integration',
|
267
|
+
'• High-performance computation in browser',
|
268
|
+
'• Server-side WASM processing',
|
269
|
+
'• Shared code between Go and JavaScript',
|
270
|
+
'• Optimized build pipeline',
|
271
|
+
'',
|
272
|
+
`${chalk.yellow('Best for:')}`,
|
273
|
+
'• Computation-heavy applications',
|
274
|
+
'• Projects requiring Go libraries',
|
275
|
+
'• Performance-critical features'
|
256
276
|
]
|
257
277
|
}[answers.template] || ['No detailed information available for this template'];
|
258
278
|
|
@@ -765,6 +785,174 @@ program
|
|
765
785
|
console.log("The dev:tools command has been improved in your version.");
|
766
786
|
});
|
767
787
|
|
788
|
+
// Add Go WASM specific command
|
789
|
+
program
|
790
|
+
.command('add:wasm [name]')
|
791
|
+
.description('Create a new WebAssembly module with Go')
|
792
|
+
.option('-p, --path <path>', 'Path where the Go WASM module should be created')
|
793
|
+
.option('-t, --type <type>', 'Type of WASM module (go, rust, c)', 'go')
|
794
|
+
.action(async (moduleName, options) => {
|
795
|
+
displayBanner();
|
796
|
+
createSection('Create Go WASM Module');
|
797
|
+
|
798
|
+
// Validate Go installation
|
799
|
+
const goInstalled = await checkGo();
|
800
|
+
if (!goInstalled) {
|
801
|
+
console.log(chalk.red('Go must be installed to create WASM modules.'));
|
802
|
+
console.log(chalk.yellow(`Please install Go from ${terminalLink('https://golang.org/dl/', 'https://golang.org/dl/')}`));
|
803
|
+
return;
|
804
|
+
}
|
805
|
+
|
806
|
+
// Get module name if not provided
|
807
|
+
if (!moduleName) {
|
808
|
+
const answers = await inquirer.prompt([
|
809
|
+
{
|
810
|
+
type: 'input',
|
811
|
+
name: 'moduleName',
|
812
|
+
message: chalk.green('What is your WASM module name?'),
|
813
|
+
default: 'gomodule',
|
814
|
+
validate: input =>
|
815
|
+
/^[a-z0-9-_]+$/.test(input)
|
816
|
+
? true
|
817
|
+
: 'Module name can only contain lowercase letters, numbers, hyphens, and underscores'
|
818
|
+
}
|
819
|
+
]);
|
820
|
+
moduleName = answers.moduleName;
|
821
|
+
}
|
822
|
+
|
823
|
+
// Get module path
|
824
|
+
let modulePath = options.path;
|
825
|
+
if (!modulePath) {
|
826
|
+
const answers = await inquirer.prompt([
|
827
|
+
{
|
828
|
+
type: 'input',
|
829
|
+
name: 'path',
|
830
|
+
message: chalk.green('Where do you want to create this Go WASM module?'),
|
831
|
+
default: 'src/wasm',
|
832
|
+
validate: input => /^[a-zA-Z0-9-_/\\]+$/.test(input)
|
833
|
+
? true
|
834
|
+
: 'Path can only contain letters, numbers, slashes, hyphens and underscores'
|
835
|
+
}
|
836
|
+
]);
|
837
|
+
modulePath = answers.path;
|
838
|
+
}
|
839
|
+
|
840
|
+
// Choose Go module capabilities
|
841
|
+
const capabilities = await inquirer.prompt([
|
842
|
+
{
|
843
|
+
type: 'checkbox',
|
844
|
+
name: 'features',
|
845
|
+
message: chalk.green('Select module capabilities:'),
|
846
|
+
choices: [
|
847
|
+
{ name: 'Basic Functions (add, subtract, etc.)', value: 'basic', checked: true },
|
848
|
+
{ name: 'JSON Processing', value: 'json', checked: true },
|
849
|
+
{ name: 'Complex Calculations', value: 'complex' },
|
850
|
+
{ name: 'Data Compression', value: 'compression' },
|
851
|
+
{ name: 'String Operations', value: 'string' }
|
852
|
+
]
|
853
|
+
}
|
854
|
+
]);
|
855
|
+
|
856
|
+
// Generate the module
|
857
|
+
const spinner = ora({
|
858
|
+
text: `Creating Go WASM module ${moduleName}...`,
|
859
|
+
color: 'cyan'
|
860
|
+
}).start();
|
861
|
+
|
862
|
+
try {
|
863
|
+
const fullPath = path.join(process.cwd(), modulePath);
|
864
|
+
await fs.ensureDir(fullPath);
|
865
|
+
|
866
|
+
// Copy example.go with appropriate modifications
|
867
|
+
const sourceFile = path.join(__dirname, '..', 'templates', 'go', 'example.go');
|
868
|
+
const destFile = path.join(fullPath, `${moduleName}.go`);
|
869
|
+
|
870
|
+
await fs.copy(sourceFile, destFile);
|
871
|
+
|
872
|
+
// Create build files
|
873
|
+
const buildBatFile = path.join(fullPath, 'build.bat');
|
874
|
+
const buildShFile = path.join(fullPath, 'build.sh');
|
875
|
+
|
876
|
+
// Create build.bat
|
877
|
+
await fs.writeFile(buildBatFile, `@echo off
|
878
|
+
echo Building ${moduleName} Go WASM module...
|
879
|
+
|
880
|
+
set GOOS=js
|
881
|
+
set GOARCH=wasm
|
882
|
+
go build -o ${moduleName}.wasm ${moduleName}.go
|
883
|
+
|
884
|
+
if %ERRORLEVEL% NEQ 0 (
|
885
|
+
echo Error: Failed to build Go WASM module
|
886
|
+
exit /b 1
|
887
|
+
)
|
888
|
+
|
889
|
+
for /f "tokens=*" %%g in ('go env GOROOT') do (set GOROOT=%%g)
|
890
|
+
copy "%GOROOT%\\misc\\wasm\\wasm_exec.js" .
|
891
|
+
|
892
|
+
echo Build complete!
|
893
|
+
`);
|
894
|
+
|
895
|
+
// Create build.sh
|
896
|
+
await fs.writeFile(buildShFile, `#!/bin/bash
|
897
|
+
echo "Building ${moduleName} Go WASM module..."
|
898
|
+
|
899
|
+
GOOS=js GOARCH=wasm go build -o ${moduleName}.wasm ${moduleName}.go
|
900
|
+
|
901
|
+
if [ $? -ne 0 ]; then
|
902
|
+
echo "Error: Failed to build Go WASM module"
|
903
|
+
exit 1
|
904
|
+
fi
|
905
|
+
|
906
|
+
GOROOT=$(go env GOROOT)
|
907
|
+
cp "$GOROOT/misc/wasm/wasm_exec.js" .
|
908
|
+
|
909
|
+
echo "Build complete!"
|
910
|
+
`);
|
911
|
+
|
912
|
+
// Make build.sh executable
|
913
|
+
try {
|
914
|
+
await fs.chmod(buildShFile, 0o755);
|
915
|
+
} catch (error) {
|
916
|
+
console.log(chalk.yellow('Note: Could not make build.sh executable. You may need to run "chmod +x build.sh" manually.'));
|
917
|
+
}
|
918
|
+
|
919
|
+
spinner.succeed(`Go WASM module created at ${chalk.green(fullPath)}`);
|
920
|
+
|
921
|
+
// Show usage instructions
|
922
|
+
console.log(boxen(
|
923
|
+
`${chalk.bold.green('Go WASM Module Created Successfully!')}\n\n` +
|
924
|
+
`${chalk.bold('To build the WASM module:')}\n` +
|
925
|
+
chalk.cyan(` cd ${path.relative(process.cwd(), fullPath)}\n`) +
|
926
|
+
chalk.cyan(` ${process.platform === 'win32' ? 'build.bat' : './build.sh'}\n\n`) +
|
927
|
+
`${chalk.bold('To use in your code:')}\n` +
|
928
|
+
chalk.cyan(`import { loadGoWasm } from 'frontend-hamroun';\n\n`) +
|
929
|
+
chalk.cyan(`// Load the WASM module\n`) +
|
930
|
+
chalk.cyan(`const wasm = await loadGoWasm('/${path.basename(modulePath)}/${moduleName}.wasm');\n\n`) +
|
931
|
+
chalk.cyan(`// Call a function\n`) +
|
932
|
+
chalk.cyan(`const result = wasm.functions.goAdd(5, 7);\n`),
|
933
|
+
{
|
934
|
+
padding: 1,
|
935
|
+
margin: 1,
|
936
|
+
borderStyle: 'round',
|
937
|
+
borderColor: 'green'
|
938
|
+
}
|
939
|
+
));
|
940
|
+
} catch (error) {
|
941
|
+
spinner.fail(`Failed to create Go WASM module`);
|
942
|
+
console.error(chalk.red(`Error: ${error.message}`));
|
943
|
+
}
|
944
|
+
});
|
945
|
+
|
946
|
+
// Helper function to check if Go is installed
|
947
|
+
async function checkGo() {
|
948
|
+
try {
|
949
|
+
await execAsync('go version');
|
950
|
+
return true;
|
951
|
+
} catch (error) {
|
952
|
+
return false;
|
953
|
+
}
|
954
|
+
}
|
955
|
+
|
768
956
|
// Default command when no arguments
|
769
957
|
if (process.argv.length <= 2) {
|
770
958
|
showDashboard();
|
package/dist/index.d.ts
CHANGED
@@ -4,6 +4,8 @@ export { batchUpdates } from './batch';
|
|
4
4
|
export { jsx, jsxs, Fragment } from './jsx-runtime';
|
5
5
|
export { render, hydrate } from './renderer';
|
6
6
|
export { renderToString } from './server-renderer';
|
7
|
+
export { loadGoWasm, createTypedWasmFunction, goValues } from './wasm';
|
8
|
+
export type { GoWasmInstance, GoWasmOptions } from './wasm';
|
7
9
|
export type { Context } from './context';
|
8
10
|
export type { VNode } from './types';
|
9
11
|
export type { Server, ServerConfig, User, DbConfig, MiddlewareFunction } from './server-types';
|
package/dist/wasm.d.ts
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
/**
|
2
|
+
* Go WebAssembly Integration Utilities
|
3
|
+
*
|
4
|
+
* This module provides tools for loading and interacting with Go WASM modules
|
5
|
+
* in browser and server environments.
|
6
|
+
*/
|
7
|
+
export interface GoWasmInstance {
|
8
|
+
instance: WebAssembly.Instance;
|
9
|
+
module: WebAssembly.Module;
|
10
|
+
exports: any;
|
11
|
+
functions: Record<string, Function>;
|
12
|
+
}
|
13
|
+
export interface GoWasmOptions {
|
14
|
+
importObject?: WebAssembly.Imports;
|
15
|
+
goWasmPath?: string;
|
16
|
+
loadGo?: boolean;
|
17
|
+
onLoad?: (instance: GoWasmInstance) => void;
|
18
|
+
debug?: boolean;
|
19
|
+
}
|
20
|
+
/**
|
21
|
+
* Load a Go WASM module from a URL
|
22
|
+
*/
|
23
|
+
export declare function loadGoWasm(wasmUrl: string, options?: GoWasmOptions): Promise<GoWasmInstance>;
|
24
|
+
/**
|
25
|
+
* Create a TypeScript-friendly wrapper for Go WASM functions
|
26
|
+
*/
|
27
|
+
export declare function createTypedWasmFunction<T extends (...args: any[]) => any>(instance: GoWasmInstance, functionName: string): T;
|
28
|
+
/**
|
29
|
+
* Helper to convert JavaScript values to Go-compatible formats
|
30
|
+
*/
|
31
|
+
export declare const goValues: {
|
32
|
+
stringToGo: (instance: GoWasmInstance, str: string) => number;
|
33
|
+
stringFromGo: (instance: GoWasmInstance, ptr: number) => string;
|
34
|
+
objectToGo: (instance: GoWasmInstance, obj: any) => number;
|
35
|
+
objectFromGo: (instance: GoWasmInstance, ptr: number) => any;
|
36
|
+
};
|
package/package.json
CHANGED
@@ -0,0 +1,150 @@
|
|
1
|
+
# Go WebAssembly Integration
|
2
|
+
|
3
|
+
This directory contains tools and examples for integrating Go with Frontend Hamroun via WebAssembly (WASM).
|
4
|
+
|
5
|
+
## Getting Started
|
6
|
+
|
7
|
+
### Prerequisites
|
8
|
+
|
9
|
+
1. Go 1.16+ installed on your system
|
10
|
+
2. Basic understanding of Go programming language
|
11
|
+
|
12
|
+
### Compiling Go to WebAssembly
|
13
|
+
|
14
|
+
To compile a Go file to WebAssembly for browser usage:
|
15
|
+
|
16
|
+
```bash
|
17
|
+
GOOS=js GOARCH=wasm go build -o mymodule.wasm myfile.go
|
18
|
+
```
|
19
|
+
|
20
|
+
For optimized production builds:
|
21
|
+
|
22
|
+
```bash
|
23
|
+
GOOS=js GOARCH=wasm go build -ldflags="-s -w" -o mymodule.wasm myfile.go
|
24
|
+
```
|
25
|
+
|
26
|
+
### Required Files
|
27
|
+
|
28
|
+
Copy these files to your project:
|
29
|
+
|
30
|
+
1. `wasm_exec.js` - for browser usage
|
31
|
+
2. `wasm_exec_node.js` - for Node.js (server-side) usage
|
32
|
+
|
33
|
+
You can find these files in your Go installation:
|
34
|
+
- Browser: `$(go env GOROOT)/misc/wasm/wasm_exec.js`
|
35
|
+
- Node.js: `$(go env GOROOT)/misc/wasm/wasm_exec_node.js`
|
36
|
+
|
37
|
+
## Usage Examples
|
38
|
+
|
39
|
+
### Browser Usage
|
40
|
+
|
41
|
+
```jsx
|
42
|
+
import { loadGoWasm, createTypedWasmFunction } from 'frontend-hamroun';
|
43
|
+
|
44
|
+
function GoCalculator() {
|
45
|
+
const [result, setResult] = useState(0);
|
46
|
+
const [wasmInstance, setWasmInstance] = useState(null);
|
47
|
+
|
48
|
+
useEffect(() => {
|
49
|
+
async function loadWasm() {
|
50
|
+
const instance = await loadGoWasm('/mymodule.wasm', {
|
51
|
+
goWasmPath: '/wasm_exec.js', // Path to the Go runtime JS file
|
52
|
+
debug: true
|
53
|
+
});
|
54
|
+
|
55
|
+
setWasmInstance(instance);
|
56
|
+
}
|
57
|
+
|
58
|
+
loadWasm();
|
59
|
+
}, []);
|
60
|
+
|
61
|
+
const handleCalculate = () => {
|
62
|
+
if (wasmInstance) {
|
63
|
+
// Call Go function from WASM
|
64
|
+
const goAdd = createTypedWasmFunction<(a: number, b: number) => number>(
|
65
|
+
wasmInstance,
|
66
|
+
'goAdd'
|
67
|
+
);
|
68
|
+
|
69
|
+
const sum = goAdd(5, 7);
|
70
|
+
setResult(sum);
|
71
|
+
}
|
72
|
+
};
|
73
|
+
|
74
|
+
return (
|
75
|
+
<div>
|
76
|
+
<button onClick={handleCalculate}>Calculate 5 + 7</button>
|
77
|
+
<p>Result: {result}</p>
|
78
|
+
</div>
|
79
|
+
);
|
80
|
+
}
|
81
|
+
```
|
82
|
+
|
83
|
+
### Server Usage
|
84
|
+
|
85
|
+
```js
|
86
|
+
import { loadGoWasmFromFile } from 'frontend-hamroun/server';
|
87
|
+
import path from 'path';
|
88
|
+
|
89
|
+
export async function get(req, res) {
|
90
|
+
const wasmPath = path.join(process.cwd(), 'lib', 'mymodule.wasm');
|
91
|
+
|
92
|
+
try {
|
93
|
+
const wasm = await loadGoWasmFromFile(wasmPath);
|
94
|
+
|
95
|
+
// Call Go function
|
96
|
+
const result = wasm.functions.goProcessData({
|
97
|
+
values: [1, 2, 3, 4, 5],
|
98
|
+
operation: 'sum'
|
99
|
+
});
|
100
|
+
|
101
|
+
res.json(JSON.parse(result));
|
102
|
+
} catch (error) {
|
103
|
+
res.status(500).json({ error: error.message });
|
104
|
+
}
|
105
|
+
}
|
106
|
+
```
|
107
|
+
|
108
|
+
## Advanced Usage
|
109
|
+
|
110
|
+
### Passing Complex Data Between JavaScript and Go
|
111
|
+
|
112
|
+
For complex data types, use JSON serialization:
|
113
|
+
|
114
|
+
```go
|
115
|
+
// In Go
|
116
|
+
func processData(this js.Value, args []js.Value) interface{} {
|
117
|
+
// Get JSON string from JS
|
118
|
+
jsonStr := args[0].String()
|
119
|
+
|
120
|
+
// Parse JSON
|
121
|
+
var data map[string]interface{}
|
122
|
+
json.Unmarshal([]byte(jsonStr), &data)
|
123
|
+
|
124
|
+
// Process data...
|
125
|
+
|
126
|
+
// Return as JSON string
|
127
|
+
resultJSON, _ := json.Marshal(result)
|
128
|
+
return js.ValueOf(string(resultJSON))
|
129
|
+
}
|
130
|
+
```
|
131
|
+
|
132
|
+
```js
|
133
|
+
// In JavaScript
|
134
|
+
const dataToProcess = { items: [1, 2, 3], config: { name: "test" } };
|
135
|
+
const jsonStr = JSON.stringify(dataToProcess);
|
136
|
+
const resultJson = wasmInstance.functions.processData(jsonStr);
|
137
|
+
const result = JSON.parse(resultJson);
|
138
|
+
```
|
139
|
+
|
140
|
+
## Performance Considerations
|
141
|
+
|
142
|
+
- WebAssembly functions run in the same thread as JavaScript
|
143
|
+
- For CPU-intensive tasks, consider using Web Workers
|
144
|
+
- Go's garbage collector can cause occasional pauses
|
145
|
+
- Large WASM files can increase initial load time
|
146
|
+
|
147
|
+
## Resources
|
148
|
+
|
149
|
+
- [Go WebAssembly Wiki](https://github.com/golang/go/wiki/WebAssembly)
|
150
|
+
- [Frontend Hamroun Documentation](https://github.com/hamroun/frontend-hamroun)
|
@@ -0,0 +1,36 @@
|
|
1
|
+
@echo off
|
2
|
+
echo Building Go WASM module...
|
3
|
+
|
4
|
+
REM Check if Go is installed
|
5
|
+
where go >nul 2>&1
|
6
|
+
if %ERRORLEVEL% NEQ 0 (
|
7
|
+
echo Error: Go is not installed
|
8
|
+
exit /b 1
|
9
|
+
)
|
10
|
+
|
11
|
+
REM Build WASM module
|
12
|
+
set GOOS=js
|
13
|
+
set GOARCH=wasm
|
14
|
+
go build -o example.wasm example.go
|
15
|
+
if %ERRORLEVEL% NEQ 0 (
|
16
|
+
echo Error: Failed to build Go WASM module
|
17
|
+
exit /b 1
|
18
|
+
)
|
19
|
+
|
20
|
+
REM Copy wasm_exec.js files
|
21
|
+
for /f "tokens=*" %%g in ('go env GOROOT') do (set GOROOT=%%g)
|
22
|
+
|
23
|
+
echo Copying WASM runtime files from %GOROOT%\misc\wasm\
|
24
|
+
copy "%GOROOT%\misc\wasm\wasm_exec.js" .
|
25
|
+
copy "%GOROOT%\misc\wasm\wasm_exec_node.js" .
|
26
|
+
|
27
|
+
echo Build complete!
|
28
|
+
echo Files created:
|
29
|
+
echo - example.wasm - WebAssembly module
|
30
|
+
echo - wasm_exec.js - Browser runtime
|
31
|
+
echo - wasm_exec_node.js - Node.js runtime
|
32
|
+
|
33
|
+
echo.
|
34
|
+
echo Usage:
|
35
|
+
echo 1. Copy these files to your project's public directory
|
36
|
+
echo 2. Load the WASM module using the provided utilities
|
@@ -0,0 +1,43 @@
|
|
1
|
+
#!/bin/bash
|
2
|
+
|
3
|
+
# Build script for Go WASM modules
|
4
|
+
|
5
|
+
# Ensure Go is installed
|
6
|
+
if ! command -v go &> /dev/null; then
|
7
|
+
echo "Error: Go is not installed"
|
8
|
+
exit 1
|
9
|
+
fi
|
10
|
+
|
11
|
+
# Check Go version
|
12
|
+
GO_VERSION=$(go version | cut -d ' ' -f 3 | sed 's/go//')
|
13
|
+
GO_VERSION_MAJOR=$(echo $GO_VERSION | cut -d '.' -f 1)
|
14
|
+
GO_VERSION_MINOR=$(echo $GO_VERSION | cut -d '.' -f 2)
|
15
|
+
|
16
|
+
if [ $GO_VERSION_MAJOR -lt 1 ] || ([ $GO_VERSION_MAJOR -eq 1 ] && [ $GO_VERSION_MINOR -lt 16 ]); then
|
17
|
+
echo "Warning: Go version 1.16+ recommended for WebAssembly, detected $GO_VERSION"
|
18
|
+
fi
|
19
|
+
|
20
|
+
# Build example WASM module
|
21
|
+
echo "Building example Go WASM module..."
|
22
|
+
GOOS=js GOARCH=wasm go build -o example.wasm example.go
|
23
|
+
if [ $? -ne 0 ]; then
|
24
|
+
echo "Error: Failed to build Go WASM module"
|
25
|
+
exit 1
|
26
|
+
fi
|
27
|
+
|
28
|
+
# Copy wasm_exec.js files for browser and Node.js from Go installation
|
29
|
+
GO_ROOT=$(go env GOROOT)
|
30
|
+
echo "Copying wasm_exec.js files from $GO_ROOT/misc/wasm/"
|
31
|
+
cp "$GO_ROOT/misc/wasm/wasm_exec.js" ./
|
32
|
+
cp "$GO_ROOT/misc/wasm/wasm_exec_node.js" ./
|
33
|
+
|
34
|
+
echo "Build complete!"
|
35
|
+
echo "Files created:"
|
36
|
+
echo "- example.wasm - WebAssembly module"
|
37
|
+
echo "- wasm_exec.js - Browser runtime"
|
38
|
+
echo "- wasm_exec_node.js - Node.js runtime"
|
39
|
+
|
40
|
+
echo ""
|
41
|
+
echo "Usage:"
|
42
|
+
echo "1. Copy these files to your project's public directory"
|
43
|
+
echo "2. Load the WASM module using the provided utilities"
|
@@ -0,0 +1,137 @@
|
|
1
|
+
//go:build js && wasm
|
2
|
+
// +build js,wasm
|
3
|
+
|
4
|
+
package main
|
5
|
+
|
6
|
+
import (
|
7
|
+
"encoding/json"
|
8
|
+
"fmt"
|
9
|
+
"syscall/js"
|
10
|
+
)
|
11
|
+
|
12
|
+
// Example Go function to be called from JavaScript
|
13
|
+
func add(this js.Value, args []js.Value) interface{} {
|
14
|
+
if len(args) != 2 {
|
15
|
+
return js.ValueOf("Error: Expected two arguments")
|
16
|
+
}
|
17
|
+
|
18
|
+
a := args[0].Int()
|
19
|
+
b := args[1].Int()
|
20
|
+
return js.ValueOf(a + b)
|
21
|
+
}
|
22
|
+
|
23
|
+
// Helper to convert Go string to JS string
|
24
|
+
func stringToJS(s string) js.Value {
|
25
|
+
return js.ValueOf(s)
|
26
|
+
}
|
27
|
+
|
28
|
+
// Helper to convert JS string to Go string
|
29
|
+
func stringFromJS(jsStr js.Value) string {
|
30
|
+
return jsStr.String()
|
31
|
+
}
|
32
|
+
|
33
|
+
// Helper to convert Go object to JS object (via JSON)
|
34
|
+
func objectToJS(obj interface{}) js.Value {
|
35
|
+
data, err := json.Marshal(obj)
|
36
|
+
if err != nil {
|
37
|
+
return js.ValueOf("Error: Failed to marshal JSON")
|
38
|
+
}
|
39
|
+
return stringToJS(string(data))
|
40
|
+
}
|
41
|
+
|
42
|
+
// Helper to convert JS object to Go object (via JSON)
|
43
|
+
func objectFromJS(jsObj js.Value) (interface{}, error) {
|
44
|
+
jsonStr := jsObj.String()
|
45
|
+
var result interface{}
|
46
|
+
err := json.Unmarshal([]byte(jsonStr), &result)
|
47
|
+
return result, err
|
48
|
+
}
|
49
|
+
|
50
|
+
// Complex example: process data in Go
|
51
|
+
func processData(this js.Value, args []js.Value) interface{} {
|
52
|
+
if len(args) == 0 {
|
53
|
+
return js.ValueOf("Error: Expected at least one argument")
|
54
|
+
}
|
55
|
+
|
56
|
+
// Get input data
|
57
|
+
data := args[0]
|
58
|
+
if data.Type() != js.TypeObject {
|
59
|
+
return js.ValueOf("Error: Expected JSON object")
|
60
|
+
}
|
61
|
+
|
62
|
+
// Convert JS object to Go map
|
63
|
+
jsonStr := js.Global().Get("JSON").Call("stringify", data).String()
|
64
|
+
var inputMap map[string]interface{}
|
65
|
+
if err := json.Unmarshal([]byte(jsonStr), &inputMap); err != nil {
|
66
|
+
return js.ValueOf(fmt.Sprintf("Error parsing JSON: %s", err.Error()))
|
67
|
+
}
|
68
|
+
|
69
|
+
// Add new fields
|
70
|
+
inputMap["processed"] = true
|
71
|
+
inputMap["processor"] = "Go WASM"
|
72
|
+
|
73
|
+
// Add some computed fields
|
74
|
+
if values, ok := inputMap["values"].([]interface{}); ok {
|
75
|
+
sum := 0.0
|
76
|
+
for _, v := range values {
|
77
|
+
if num, ok := v.(float64); ok {
|
78
|
+
sum += num
|
79
|
+
}
|
80
|
+
}
|
81
|
+
inputMap["sum"] = sum
|
82
|
+
}
|
83
|
+
|
84
|
+
// Convert back to JS
|
85
|
+
resultJSON, err := json.Marshal(inputMap)
|
86
|
+
if err != nil {
|
87
|
+
return js.ValueOf(fmt.Sprintf("Error generating JSON: %s", err.Error()))
|
88
|
+
}
|
89
|
+
|
90
|
+
return js.ValueOf(string(resultJSON))
|
91
|
+
}
|
92
|
+
|
93
|
+
// Helper functions exposed to JavaScript
|
94
|
+
func registerHelperFunctions() {
|
95
|
+
js.Global().Set("__stringToGo", js.FuncOf(func(this js.Value, args []js.Value) interface{} {
|
96
|
+
if len(args) != 1 {
|
97
|
+
return nil
|
98
|
+
}
|
99
|
+
return stringToJS(stringFromJS(args[0]))
|
100
|
+
}))
|
101
|
+
|
102
|
+
js.Global().Set("__stringFromGo", js.FuncOf(func(this js.Value, args []js.Value) interface{} {
|
103
|
+
if len(args) != 1 {
|
104
|
+
return nil
|
105
|
+
}
|
106
|
+
return stringToJS(stringFromJS(args[0]))
|
107
|
+
}))
|
108
|
+
|
109
|
+
js.Global().Set("__objectToGo", js.FuncOf(func(this js.Value, args []js.Value) interface{} {
|
110
|
+
if len(args) != 1 {
|
111
|
+
return nil
|
112
|
+
}
|
113
|
+
obj, _ := objectFromJS(args[0])
|
114
|
+
return objectToJS(obj)
|
115
|
+
}))
|
116
|
+
|
117
|
+
js.Global().Set("__objectFromGo", js.FuncOf(func(this js.Value, args []js.Value) interface{} {
|
118
|
+
if len(args) != 1 {
|
119
|
+
return nil
|
120
|
+
}
|
121
|
+
return stringToJS(stringFromJS(args[0]))
|
122
|
+
}))
|
123
|
+
}
|
124
|
+
|
125
|
+
func main() {
|
126
|
+
fmt.Println("Go WASM Module initialized")
|
127
|
+
|
128
|
+
// Register functions to be callable from JavaScript
|
129
|
+
js.Global().Set("goAdd", js.FuncOf(add))
|
130
|
+
js.Global().Set("goProcessData", js.FuncOf(processData))
|
131
|
+
|
132
|
+
// Register helper functions
|
133
|
+
registerHelperFunctions()
|
134
|
+
|
135
|
+
// Keep the program running
|
136
|
+
<-make(chan bool)
|
137
|
+
}
|