Set up a basic "front-end" for the webassembly module to be tested locally from a data folder (I use python -m http.server). The WebAssembly application is now responsible for all setup/rendering through the WebGL2 context.
This commit is contained in:
236
data/gl_functions.js
Normal file
236
data/gl_functions.js
Normal file
@@ -0,0 +1,236 @@
|
||||
|
||||
import { appGlobals } from './globals.js'
|
||||
import { wasmPntrToJsString, wasmPntrAndLengthToJsString } from './wasm_functions.js'
|
||||
|
||||
export var glObjects = {
|
||||
buffers: [ null ],
|
||||
vaos: [ null ],
|
||||
shaders: [ null ],
|
||||
programs: [ null ],
|
||||
};
|
||||
|
||||
// +--------------------------------------------------------------+
|
||||
// | Helpers |
|
||||
// +--------------------------------------------------------------+
|
||||
export function verifyGlBufferId(bufferId, allowZero)
|
||||
{
|
||||
if (typeof(bufferId) != "number") { return "BufferId is not a number!"; }
|
||||
if (bufferId == 0) { return allowZero ? null : "BufferId is 0!"; }
|
||||
if (glObjects == null || glObjects.buffers == null) { return "Buffers array has not been initialized yet!"; }
|
||||
if (bufferId >= glObjects.buffers.length) { return "BufferId is too high!"; }
|
||||
if (glObjects.buffers[bufferId] == null) { return "BufferId is for a destroyed vertBuffer!"; }
|
||||
return null;
|
||||
}
|
||||
export function verifyGlVaoId(vaoId, allowZero)
|
||||
{
|
||||
if (typeof(vaoId) != "number") { return "VaoId is not a number!"; }
|
||||
if (vaoId == 0) { return allowZero ? null : "VaoId is 0!"; }
|
||||
if (glObjects == null || glObjects.vaos == null) { return "Vaos array has not been initialized yet!"; }
|
||||
if (vaoId >= glObjects.vaos.length) { return "VaoId is too high!"; }
|
||||
if (glObjects.vaos[vaoId] == null) { return "VaoId is for a destroyed array!"; }
|
||||
return null;
|
||||
}
|
||||
export function verifyGlShaderId(shaderId, allowZero)
|
||||
{
|
||||
if (typeof(shaderId) != "number") { return "ShaderId is not a number!"; }
|
||||
if (shaderId == 0) { return allowZero ? null : "ShaderId is 0!"; }
|
||||
if (glObjects == null || glObjects.shaders == null) { return "Shaders array has not been initialized yet!"; }
|
||||
if (shaderId >= glObjects.shaders.length) { return "ShaderId is too high!"; }
|
||||
if (glObjects.shaders[shaderId] == null) { return "ShaderId is for a destroyed shader!"; }
|
||||
return null;
|
||||
}
|
||||
export function verifyGlProgramId(programId, allowZero)
|
||||
{
|
||||
if (typeof(programId) != "number") { return "ProgramId is not a number!"; }
|
||||
if (programId == 0) { return allowZero ? null : "ProgramId is 0!"; }
|
||||
if (glObjects == null || glObjects.programs == null) { return "Programs array has not been initialized yet!"; }
|
||||
if (programId >= glObjects.programs.length) { return "ProgramId is too high!"; }
|
||||
if (glObjects.programs[programId] == null) { return "ProgramId is for a destroyed program!"; }
|
||||
return null;
|
||||
}
|
||||
export function verifyParameter(verifyResult, functionName, parameterName, parameterValue)
|
||||
{
|
||||
if (verifyResult == null) { return true; }
|
||||
console.error("Invalid argument \"" + parameterName + "\" passed to " + functionName + ": " + verifyResult);
|
||||
console.error("Argument value: " + parameterValue);
|
||||
return false;
|
||||
}
|
||||
|
||||
// +--------------------------------------------------------------+
|
||||
// | WebGL API |
|
||||
// +--------------------------------------------------------------+
|
||||
export function jsGlCreateBuffer()
|
||||
{
|
||||
let newBuffer = appGlobals.glContext.createBuffer();
|
||||
let newBufferId = glObjects.buffers.length;
|
||||
glObjects.buffers.push(newBuffer);
|
||||
return newBufferId;
|
||||
}
|
||||
|
||||
export function jsGlBindBuffer(bufferType, bufferId)
|
||||
{
|
||||
if (!verifyParameter(verifyGlBufferId(bufferId, true), "gl.bindBuffer", "bufferId", bufferId)) { return; }
|
||||
let buffer = glObjects.buffers[bufferId];
|
||||
appGlobals.glContext.bindBuffer(bufferType, buffer);
|
||||
}
|
||||
|
||||
export function jsGlBufferData(bufferType, dataLength, dataPntr, usageHint)
|
||||
{
|
||||
let dataArray = appGlobals.memDataView.buffer.slice(dataPntr, dataPntr + dataLength)
|
||||
appGlobals.glContext.bufferData(bufferType, dataArray, usageHint);
|
||||
}
|
||||
|
||||
export function jsGlCreateVertexArray()
|
||||
{
|
||||
let newVao = appGlobals.glContext.createVertexArray();
|
||||
let newVaoId = glObjects.vaos.length;
|
||||
glObjects.vaos.push(newVao);
|
||||
return newVaoId;
|
||||
}
|
||||
|
||||
export function jsGlBindVertexArray(vaoId)
|
||||
{
|
||||
if (!verifyParameter(verifyGlVaoId(vaoId, true), "gl.bindVertexArray", "vaoId", vaoId)) { return; }
|
||||
let vao = glObjects.vaos[vaoId];
|
||||
appGlobals.glContext.bindVertexArray(vao);
|
||||
}
|
||||
|
||||
export function jsGlEnableVertexAttribArray(location)
|
||||
{
|
||||
appGlobals.glContext.enableVertexAttribArray(location);
|
||||
}
|
||||
|
||||
export function jsGlVertexAttribPointer(attribLocation, componentCount, componentType, normalized, stride, offset)
|
||||
{
|
||||
appGlobals.glContext.vertexAttribPointer(attribLocation, componentCount, componentType, normalized, stride, offset);
|
||||
}
|
||||
|
||||
export function jsGlCreateShader(shaderType)
|
||||
{
|
||||
let newShader = appGlobals.glContext.createShader(shaderType);
|
||||
let newShaderId = glObjects.shaders.length;
|
||||
glObjects.shaders.push(newShader);
|
||||
return newShaderId;
|
||||
}
|
||||
|
||||
export function jsGlShaderSource(shaderId, sourceLength, sourcePntr)
|
||||
{
|
||||
if (!verifyParameter(verifyGlShaderId(shaderId, false), "gl.shaderSource", "shaderId", shaderId)) { return; }
|
||||
let shader = glObjects.shaders[shaderId];
|
||||
let sourceStr = wasmPntrAndLengthToJsString(sourcePntr, sourceLength);
|
||||
appGlobals.glContext.shaderSource(shader, sourceStr);
|
||||
}
|
||||
|
||||
export function jsGlCompileShader(shaderId)
|
||||
{
|
||||
if (!verifyParameter(verifyGlShaderId(shaderId, false), "gl.compileShader", "shaderId", shaderId)) { return; }
|
||||
let shader = glObjects.shaders[shaderId];
|
||||
appGlobals.glContext.compileShader(shader);
|
||||
}
|
||||
|
||||
export function jsGlGetShaderParameterBool(shaderId, parameter)
|
||||
{
|
||||
if (!verifyParameter(verifyGlShaderId(shaderId, false), "gl.getShaderParameter", "shaderId", shaderId)) { return false; }
|
||||
let shader = glObjects.shaders[shaderId];
|
||||
let paramValue = appGlobals.glContext.getShaderParameter(shader, parameter);
|
||||
if (typeof(paramValue) != "boolean") { console.error("Tried to get GL parameter " + parameter + " as bool when it's actually: " + typeof(paramValue)); return false; }
|
||||
return paramValue;
|
||||
}
|
||||
export function jsGlGetShaderParameterInt(shaderId, parameter)
|
||||
{
|
||||
if (!verifyParameter(verifyGlShaderId(shaderId, false), "gl.getShaderParameter", "shaderId", shaderId)) { return false; }
|
||||
let shader = glObjects.shaders[shaderId];
|
||||
let paramValue = appGlobals.glContext.getShaderParameter(shader, parameter);
|
||||
if (typeof(paramValue) != "number") { console.error("Tried to get GL parameter " + parameter + " as number when it's actually: " + typeof(paramValue)); return false; }
|
||||
return paramValue;
|
||||
}
|
||||
|
||||
export function jsGlCreateProgram()
|
||||
{
|
||||
let newProgram = appGlobals.glContext.createProgram();
|
||||
let newProgramId = glObjects.programs.length;
|
||||
glObjects.programs.push(newProgram);
|
||||
return newProgramId;
|
||||
}
|
||||
|
||||
export function jsGlAttachShader(programId, shaderId)
|
||||
{
|
||||
if (!verifyParameter(verifyGlProgramId(programId, false), "gl.attachShader", "programId", programId)) { return; }
|
||||
if (!verifyParameter(verifyGlShaderId(shaderId, false), "gl.attachShader", "shaderId", shaderId)) { return; }
|
||||
let program = glObjects.programs[programId];
|
||||
let shader = glObjects.shaders[shaderId];
|
||||
appGlobals.glContext.attachShader(program, shader);
|
||||
}
|
||||
|
||||
export function jsGlLinkProgram(programId)
|
||||
{
|
||||
if (!verifyParameter(verifyGlProgramId(programId, false), "gl.linkProgram", "programId", programId)) { return; }
|
||||
let program = glObjects.programs[programId];
|
||||
appGlobals.glContext.linkProgram(program);
|
||||
}
|
||||
|
||||
export function jsGlUseProgram(programId)
|
||||
{
|
||||
if (!verifyParameter(verifyGlProgramId(programId, true), "gl.useProgram", "programId", programId)) { return; }
|
||||
let program = glObjects.programs[programId];
|
||||
appGlobals.glContext.useProgram(program);
|
||||
}
|
||||
|
||||
export function jsGlGetProgramParameterBool(programId, parameter)
|
||||
{
|
||||
if (!verifyParameter(verifyGlProgramId(programId, false), "gl.getProgramParameter", "programId", programId)) { return false; }
|
||||
let program = glObjects.programs[programId];
|
||||
let paramValue = appGlobals.glContext.getProgramParameter(program, parameter);
|
||||
if (typeof(paramValue) != "boolean") { console.error("Tried to get GL parameter " + parameter + " as bool when it's actually: " + typeof(paramValue)); return false; }
|
||||
return paramValue;
|
||||
}
|
||||
export function jsGlGetProgramParameterInt(programId, parameter)
|
||||
{
|
||||
if (!verifyParameter(verifyGlProgramId(programId, false), "gl.getProgramParameter", "programId", programId)) { return false; }
|
||||
let program = glObjects.programs[programId];
|
||||
let paramValue = appGlobals.glContext.getProgramParameter(program, parameter);
|
||||
if (typeof(paramValue) != "number") { console.error("Tried to get GL parameter " + parameter + " as number when it's actually: " + typeof(paramValue)); return false; }
|
||||
return paramValue;
|
||||
}
|
||||
|
||||
export function jsGlClearColor(rValue, gValue, bValue, aValue)
|
||||
{
|
||||
appGlobals.glContext.clearColor(rValue, gValue, bValue, aValue);
|
||||
}
|
||||
|
||||
export function jsGlClear(bufferBits)
|
||||
{
|
||||
appGlobals.glContext.clear(bufferBits);
|
||||
}
|
||||
|
||||
export function jsGlDrawArrays(geometryType, startIndex, count)
|
||||
{
|
||||
appGlobals.glContext.drawArrays(geometryType, startIndex, count);
|
||||
}
|
||||
|
||||
export let jsGlFunctions = {
|
||||
jsGlCreateBuffer: jsGlCreateBuffer,
|
||||
jsGlBindBuffer: jsGlBindBuffer,
|
||||
jsGlBufferData: jsGlBufferData,
|
||||
jsGlCreateVertexArray: jsGlCreateVertexArray,
|
||||
jsGlBindVertexArray: jsGlBindVertexArray,
|
||||
jsGlEnableVertexAttribArray: jsGlEnableVertexAttribArray,
|
||||
jsGlVertexAttribPointer: jsGlVertexAttribPointer,
|
||||
jsGlCreateShader: jsGlCreateShader,
|
||||
jsGlShaderSource: jsGlShaderSource,
|
||||
jsGlCompileShader: jsGlCompileShader,
|
||||
jsGlGetShaderParameterBool: jsGlGetShaderParameterBool,
|
||||
jsGlGetShaderParameterInt: jsGlGetShaderParameterInt,
|
||||
jsGlCreateProgram: jsGlCreateProgram,
|
||||
jsGlAttachShader: jsGlAttachShader,
|
||||
jsGlLinkProgram: jsGlLinkProgram,
|
||||
jsGlUseProgram: jsGlUseProgram,
|
||||
jsGlGetProgramParameterBool: jsGlGetProgramParameterBool,
|
||||
jsGlGetProgramParameterInt: jsGlGetProgramParameterInt,
|
||||
jsGlClearColor: jsGlClearColor,
|
||||
jsGlClear: jsGlClear,
|
||||
jsGlDrawArrays: jsGlDrawArrays,
|
||||
};
|
||||
|
||||
//TODO: string getShaderInfoLog(shaderId)
|
||||
//TODO: string getProgramInfoLog(programId)
|
||||
14
data/globals.js
Normal file
14
data/globals.js
Normal file
@@ -0,0 +1,14 @@
|
||||
|
||||
export const WASM_MEMORY_PAGE_SIZE = (64 * 1024); //64kB or 65,536b
|
||||
export const WASM_MEMORY_MAX_NUM_PAGES = (64 * 1024) //65,536 pages * 64 kB/page = 4GB
|
||||
export const WASM_MEMORY_MAX_SIZE = (WASM_MEMORY_MAX_NUM_PAGES * WASM_MEMORY_PAGE_SIZE)
|
||||
|
||||
export var appGlobals =
|
||||
{
|
||||
heapBase: 0,
|
||||
canvas: null,
|
||||
glContext: null,
|
||||
memDataView: null,
|
||||
wasmModule: null,
|
||||
textDecoder: null,
|
||||
};
|
||||
20
data/index.html
Normal file
20
data/index.html
Normal file
@@ -0,0 +1,20 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<link rel="stylesheet" href="main.css" />
|
||||
<meta content="text/html;charset=utf-8" http-equiv="Content-Type">
|
||||
<meta content="utf-8" http-equiv="encoding">
|
||||
</head>
|
||||
<body>
|
||||
<div class="main_section">
|
||||
<p>🠟 The canvas is below 🠟</p>
|
||||
<div id="canvas_container">
|
||||
<canvas>
|
||||
Your browser does not support the HTML5 canvas tag.
|
||||
</canvas>
|
||||
</div>
|
||||
<p>🠝 The canvas is above 🠝</p>
|
||||
</div>
|
||||
<script async type="module" src="main.js" ></script>
|
||||
</body>
|
||||
</html>
|
||||
22
data/main.css
Normal file
22
data/main.css
Normal file
@@ -0,0 +1,22 @@
|
||||
body
|
||||
{
|
||||
/* TODO: Where does this collection of font names come from? Is it standard or something? */
|
||||
font-family: -apple-system,BlinkMacSystemFont,segoe ui,Helvetica,Arial,sans-serif,apple color emoji,segoe ui emoji,segoe ui symbol;
|
||||
}
|
||||
|
||||
.main_section
|
||||
{
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#canvas_container
|
||||
{
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
canvas
|
||||
{
|
||||
border: 1px solid black;
|
||||
width: 640px;
|
||||
height: 480px;
|
||||
}
|
||||
80
data/main.js
Normal file
80
data/main.js
Normal file
@@ -0,0 +1,80 @@
|
||||
|
||||
import { WASM_MEMORY_PAGE_SIZE, appGlobals } from './globals.js'
|
||||
import { loadWasmModule, wasmPntrToJsString, wasmPntrAndLengthToJsString } from './wasm_functions.js'
|
||||
import { jsStdFunctions } from './std_functions.js'
|
||||
import { jsGlFunctions } from './gl_functions.js'
|
||||
|
||||
function AcquireCanvas(canvasWidth, canvasHeight)
|
||||
{
|
||||
var canvas = document.getElementsByTagName("canvas")[0];
|
||||
// console.log(canvas);
|
||||
|
||||
// set the display size of the canvas.
|
||||
canvas.style.width = canvasWidth + "px";
|
||||
canvas.style.height = canvasHeight + "px";
|
||||
|
||||
// set the size of the drawingBuffer
|
||||
var devicePixelRatio = window.devicePixelRatio || 1;
|
||||
canvas.width = canvasWidth * devicePixelRatio;
|
||||
canvas.height = canvasHeight * devicePixelRatio;
|
||||
|
||||
// canvasContainer = document.getElementById("canvas_container");
|
||||
// console.assert(canvasContainer != null, "Couldn't find canvas container DOM element!");
|
||||
appGlobals.canvas = canvas;
|
||||
return canvas;
|
||||
}
|
||||
|
||||
function CreateGlContext(canvas)
|
||||
{
|
||||
var canvasContextGl = canvas.getContext("webgl2");
|
||||
if (canvasContextGl === null) { console.error("Unable to initialize WebGL render context. Your browser or machine may not support it :("); return null; }
|
||||
// console.dir(canvasContextGl);
|
||||
appGlobals.glContext = canvasContextGl;
|
||||
return canvasContextGl;
|
||||
}
|
||||
|
||||
async function LoadWasmModule(wasmFilePath, initialWasmPageCount)
|
||||
{
|
||||
appGlobals.textDecoder = new TextDecoder("utf-8");
|
||||
|
||||
let wasmEnvironment =
|
||||
{
|
||||
...jsStdFunctions,
|
||||
...jsGlFunctions,
|
||||
};
|
||||
appGlobals.wasmModule = await loadWasmModule(wasmFilePath, wasmEnvironment);
|
||||
|
||||
appGlobals.memDataView = new DataView(new Uint8Array(appGlobals.wasmModule.exports.memory.buffer).buffer);
|
||||
// let heapBaseAddress = appGlobals.wasmModule.exports.__heap_base.value;
|
||||
// console.log("__heap_base = " + heapBaseAddress);
|
||||
|
||||
let memorySize = appGlobals.wasmModule.exports.memory.buffer.byteLength;
|
||||
let numMemoryPagesAfterLoad = memorySize / WASM_MEMORY_PAGE_SIZE;
|
||||
if ((memorySize % WASM_MEMORY_PAGE_SIZE) != 0)
|
||||
{
|
||||
console.warn("memorySize (" + memorySize + ") is not a multiple of WASM_MEMORY_PAGE_SIZE (" + WASM_MEMORY_PAGE_SIZE + ")");
|
||||
numMemoryPagesAfterLoad++;
|
||||
}
|
||||
appGlobals.wasmModule.exports.init_mem(numMemoryPagesAfterLoad);
|
||||
}
|
||||
|
||||
async function MainLoop()
|
||||
{
|
||||
console.log("Initializing WebGL Canvas...");
|
||||
var canvas = AcquireCanvas(600, 400);
|
||||
var glContext = CreateGlContext(canvas);
|
||||
|
||||
console.log("Loading WASM Module...");
|
||||
await LoadWasmModule("app.wasm", 4);
|
||||
appGlobals.wasmModule.exports.App_Initialize();
|
||||
|
||||
console.log("Running!");
|
||||
function renderFrame()
|
||||
{
|
||||
appGlobals.wasmModule.exports.App_UpdateAndRender();
|
||||
window.requestAnimationFrame(renderFrame);
|
||||
}
|
||||
window.requestAnimationFrame(renderFrame);
|
||||
}
|
||||
|
||||
MainLoop();
|
||||
73
data/std_functions.js
Normal file
73
data/std_functions.js
Normal file
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
File: std_functions.c
|
||||
Author: Taylor Robbins
|
||||
Date: 09\01\2025
|
||||
Description:
|
||||
** Contains all the functions that are required as imports by the C standard library implementation in the std folder
|
||||
*/
|
||||
|
||||
import { WASM_MEMORY_PAGE_SIZE, appGlobals } from './globals.js'
|
||||
import { wasmPntrToJsString, wasmPntrAndLengthToJsString } from './wasm_functions.js'
|
||||
|
||||
export function jsStdPrint(level, messageStrPntr, messageLength)
|
||||
{
|
||||
let messageStr = wasmPntrAndLengthToJsString(messageStrPntr, messageLength);
|
||||
if (level == 0) { console.debug(messageStr); }
|
||||
else if (level == 1) { console.info(messageStr); }
|
||||
else if (level == 2) { console.warn(messageStr); }
|
||||
else if (level == 3) { console.error(messageStr); }
|
||||
else { console.log(messageStr); }
|
||||
}
|
||||
|
||||
export function jsStdAbort(messageStrPntr, exitCode)
|
||||
{
|
||||
let messageStr = wasmPntrToJsString(messageStrPntr);
|
||||
let exitStr = "Abort [" + exitCode + "]: " + messageStr;
|
||||
console.error(exitStr);
|
||||
throw new Error(exitStr);
|
||||
}
|
||||
|
||||
export function jsStdAssertFailure(filePathPntr, fileLineNum, funcNamePntr, conditionStrPntr, messageStrPntr)
|
||||
{
|
||||
let filePath = wasmPntrToJsString(filePathPntr);
|
||||
let funcName = wasmPntrToJsString(funcNamePntr);
|
||||
let conditionStr = wasmPntrToJsString(conditionStrPntr);
|
||||
let outputMessage = "";
|
||||
if (messageStrPntr != 0)
|
||||
{
|
||||
let messageStr = wasmPntrToJsString(messageStrPntr);
|
||||
outputMessage = "Assertion failed, " + messageStr + " (" + conditionStr + ") is not true! In " + filePath + ":" + fileLineNum + " " + funcName + "(...)";
|
||||
}
|
||||
else
|
||||
{
|
||||
outputMessage = "Assertion failed! (" + conditionStr + ") is not true! In " + filePath + ":" + fileLineNum + " " + funcName + "(...)";
|
||||
}
|
||||
console.error(outputMessage);
|
||||
throw new Error(outputMessage);
|
||||
}
|
||||
|
||||
export function jsStdDebugBreak()
|
||||
{
|
||||
//TODO: This is not a proper solution, really. Can we somehow notify the debugger in Firefox/Chrome/Safari/etc.?
|
||||
alert("A debug breakpoint has been hit!");
|
||||
}
|
||||
|
||||
//TODO: Can we use these inside the Wasm module rather than calling out to javascript??
|
||||
// __builtin_wasm_memory_size(0); // the number of 64Kb pages we have
|
||||
// __builtin_wasm_memory_grow(0, blocks); // increases amount of pages
|
||||
// __builtin_huge_valf(); // similar to Infinity in JS
|
||||
export function jsStdGrowMemory(numPages)
|
||||
{
|
||||
let currentPageCount = appGlobals.wasmModule.exports.memory.buffer.byteLength / WASM_MEMORY_PAGE_SIZE;
|
||||
// console.log("Memory growing by " + numPages + " pages (" + currentPageCount + " -> " + (currentPageCount + numPages) + ")");
|
||||
appGlobals.wasmModule.exports.memory.grow(numPages);
|
||||
appGlobals.memDataView = new DataView(new Uint8Array(appGlobals.wasmModule.exports.memory.buffer).buffer);
|
||||
}
|
||||
|
||||
export let jsStdFunctions = {
|
||||
jsStdPrint: jsStdPrint,
|
||||
jsStdAbort: jsStdAbort,
|
||||
jsStdAssertFailure: jsStdAssertFailure,
|
||||
jsStdDebugBreak: jsStdDebugBreak,
|
||||
jsStdGrowMemory: jsStdGrowMemory,
|
||||
};
|
||||
42
data/wasm_functions.js
Normal file
42
data/wasm_functions.js
Normal file
@@ -0,0 +1,42 @@
|
||||
|
||||
import { appGlobals } from './globals.js'
|
||||
|
||||
export async function loadWasmModule(filePath, environment)
|
||||
{
|
||||
let result = null;
|
||||
try
|
||||
{
|
||||
const fetchPromise = fetch(filePath);
|
||||
const wasmModule = await WebAssembly.instantiateStreaming(
|
||||
fetchPromise,
|
||||
{ env: environment }
|
||||
);
|
||||
result = wasmModule.instance;
|
||||
}
|
||||
catch (exception)
|
||||
{
|
||||
console.error("Failed to load WASM module from \"" + filePath + "\":", exception);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
//TODO: We should do some performance measurements of wasmPntrToJsString vs wasmPntrAndLengthToJsString!
|
||||
export function wasmPntrToJsString(ptr)
|
||||
{
|
||||
let cIndex = ptr;
|
||||
while (cIndex < appGlobals.memDataView.byteLength)
|
||||
{
|
||||
let byteValue = appGlobals.memDataView.getUint8(cIndex, true);
|
||||
if (byteValue == 0) { break; }
|
||||
cIndex++;
|
||||
}
|
||||
return appGlobals.textDecoder.decode(
|
||||
appGlobals.memDataView.buffer.slice(ptr, cIndex)
|
||||
);
|
||||
}
|
||||
export function wasmPntrAndLengthToJsString(ptr, length)
|
||||
{
|
||||
return appGlobals.textDecoder.decode(
|
||||
appGlobals.memDataView.buffer.slice(ptr, ptr + length)
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user