@necpp-engine/wasm 0.1.0

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/dist/loader.js ADDED
@@ -0,0 +1,144 @@
1
+ import { NecInputError, NecRuntimeError } from "./errors.js";
2
+ import { abiVersion, engineVersion } from "./versions.js";
3
+ import generatedFactory from "./nec2pp.generated.js";
4
+ const textDecoder = new TextDecoder();
5
+ function copyWasmBinary(binary) {
6
+ try {
7
+ if (binary instanceof Uint8Array) {
8
+ return new Uint8Array(binary);
9
+ }
10
+ if (binary instanceof ArrayBuffer) {
11
+ return new Uint8Array(binary.slice(0));
12
+ }
13
+ }
14
+ catch (cause) {
15
+ throw new NecInputError("wasmBinary must reference readable WASM bytes", {
16
+ cause,
17
+ });
18
+ }
19
+ throw new NecInputError("wasmBinary must be an ArrayBuffer or Uint8Array");
20
+ }
21
+ function resolveWasmUrl(value) {
22
+ if (value === undefined) {
23
+ return new URL("./nec2pp.wasm", import.meta.url).href;
24
+ }
25
+ if (value instanceof URL) {
26
+ return value.href;
27
+ }
28
+ if (typeof value !== "string" || value.trim().length === 0) {
29
+ throw new NecInputError("wasmUrl must be a nonempty string or URL");
30
+ }
31
+ try {
32
+ return new URL(value, import.meta.url).href;
33
+ }
34
+ catch (cause) {
35
+ throw new NecInputError("wasmUrl is not a valid URL", { cause });
36
+ }
37
+ }
38
+ function isHttpUrl(url) {
39
+ return url.startsWith("http://") || url.startsWith("https://");
40
+ }
41
+ async function downloadWasmBinary(wasmUrl) {
42
+ try {
43
+ const response = await fetch(wasmUrl);
44
+ if (!response.ok) {
45
+ throw new NecRuntimeError(`Failed to download WASM from ${wasmUrl}`, {
46
+ details: { status: response.status, wasmUrl },
47
+ });
48
+ }
49
+ return new Uint8Array(await response.arrayBuffer());
50
+ }
51
+ catch (error) {
52
+ if (error instanceof NecRuntimeError) {
53
+ throw error;
54
+ }
55
+ throw new NecRuntimeError("Failed to download WASM", {
56
+ cause: error,
57
+ details: { wasmUrl },
58
+ });
59
+ }
60
+ }
61
+ async function moduleOptions(options) {
62
+ if (options !== undefined && (typeof options !== "object" || options === null)) {
63
+ throw new NecInputError("WASM loading options must be an object");
64
+ }
65
+ if (options?.wasmUrl !== undefined && options.wasmBinary !== undefined) {
66
+ throw new NecInputError("wasmUrl and wasmBinary cannot both be supplied");
67
+ }
68
+ if (options?.wasmBinary !== undefined) {
69
+ return { wasmBinary: copyWasmBinary(options.wasmBinary) };
70
+ }
71
+ const wasmUrl = resolveWasmUrl(options?.wasmUrl);
72
+ if (isHttpUrl(wasmUrl)) {
73
+ return { wasmBinary: await downloadWasmBinary(wasmUrl) };
74
+ }
75
+ return {
76
+ locateFile(path, prefix) {
77
+ return path.endsWith(".wasm") ? wasmUrl : `${prefix}${path}`;
78
+ },
79
+ };
80
+ }
81
+ function decodeCString(module, pointer) {
82
+ if (!Number.isSafeInteger(pointer)
83
+ || pointer <= 0
84
+ || pointer >= module.HEAPU8.length) {
85
+ throw new NecRuntimeError("The native module returned an invalid version string");
86
+ }
87
+ const end = module.HEAPU8.indexOf(0, pointer);
88
+ if (end < 0) {
89
+ throw new NecRuntimeError("The native module returned an unterminated version string");
90
+ }
91
+ return textDecoder.decode(module.HEAPU8.slice(pointer, end));
92
+ }
93
+ function validateModule(module) {
94
+ if (typeof module !== "object"
95
+ || module === null
96
+ || typeof module._necpp_wasm_v1_abi_version !== "function"
97
+ || typeof module._necpp_wasm_v1_model_create !== "function"
98
+ || typeof module._necpp_wasm_v1_deck_create !== "function"
99
+ || typeof module._malloc !== "function"
100
+ || typeof module._free !== "function"
101
+ || !(module.HEAPU8 instanceof Uint8Array)
102
+ || !(module.HEAP32 instanceof Int32Array)
103
+ || !(module.HEAPF64 instanceof Float64Array)) {
104
+ throw new NecRuntimeError("The loaded Emscripten module has an invalid surface");
105
+ }
106
+ const nativeAbiVersion = module._necpp_wasm_v1_abi_version();
107
+ if (nativeAbiVersion !== abiVersion) {
108
+ throw new NecRuntimeError(`Unsupported NEC WASM ABI version ${nativeAbiVersion}; expected ${abiVersion}`, {
109
+ details: {
110
+ actualAbiVersion: nativeAbiVersion,
111
+ expectedAbiVersion: abiVersion,
112
+ },
113
+ });
114
+ }
115
+ const nativeEngineVersion = decodeCString(module, module._necpp_wasm_v1_engine_version());
116
+ if (nativeEngineVersion !== engineVersion) {
117
+ throw new NecRuntimeError(`NEC engine version ${nativeEngineVersion} does not match package engine ${engineVersion}`, {
118
+ details: {
119
+ actualEngineVersion: nativeEngineVersion,
120
+ expectedEngineVersion: engineVersion,
121
+ },
122
+ });
123
+ }
124
+ }
125
+ export async function instantiateNecModule(options, factory) {
126
+ try {
127
+ const selectedOptions = await moduleOptions(options);
128
+ const selectedFactory = factory ?? generatedFactory;
129
+ if (typeof selectedFactory !== "function") {
130
+ throw new NecRuntimeError("The generated Emscripten module does not export a default factory");
131
+ }
132
+ const module = await selectedFactory(selectedOptions);
133
+ validateModule(module);
134
+ return module;
135
+ }
136
+ catch (error) {
137
+ if (error instanceof NecInputError || error instanceof NecRuntimeError) {
138
+ throw error;
139
+ }
140
+ throw new NecRuntimeError("Failed to load or instantiate NEC WebAssembly", {
141
+ cause: error,
142
+ });
143
+ }
144
+ }
@@ -0,0 +1,21 @@
1
+ import type { ComplexVector, CompleteGeometryOptions, EmbeddedFarFieldResult, EmbeddedFieldNormalization, FarFieldRequest, FarFieldResult, GroundModel, ImpedanceResult, LoadDefinition, NecModel, NecModelState, PortDefinition, PortSolution, PrepareOptions, WireDefinition } from "./types.js";
2
+ import type { NecWasmModule } from "./wasm-internal.js";
3
+ export declare class WasmNecModel implements NecModel {
4
+ #private;
5
+ constructor(module: NecWasmModule, handle: number);
6
+ get state(): NecModelState;
7
+ addWire(wire: WireDefinition): void;
8
+ completeGeometry(options?: CompleteGeometryOptions): void;
9
+ definePorts(ports: readonly PortDefinition[]): void;
10
+ addLoad(load: LoadDefinition): void;
11
+ clearLoads(): void;
12
+ setGround(ground: GroundModel): void;
13
+ prepare(options: PrepareOptions): void;
14
+ computeImpedanceMatrix(): ImpedanceResult;
15
+ solveVoltages(voltages: ComplexVector): PortSolution;
16
+ solveCurrents(currents: ComplexVector): PortSolution;
17
+ computeFarField(request: FarFieldRequest): FarFieldResult;
18
+ computeEmbeddedFarFields(request: FarFieldRequest, normalization?: EmbeddedFieldNormalization): EmbeddedFarFieldResult;
19
+ dispose(): void;
20
+ }
21
+ export declare function createModelFromModule(module: NecWasmModule): NecModel;