@@ -5988,6 +5988,240 @@ log('Same module, different instances: ' + (inst1 !== inst2));
59885988log('Same compiled module: ' + (wasmModule === wasmModule));` ,
59895989 } ,
59905990
5991+ 'rich-name-section' : {
5992+ label : 'Rich Name Section' ,
5993+ group : 'Debug' ,
5994+ description : 'Build a module with function names, local names, and global names — then inspect them.' ,
5995+ target : 'mvp' ,
5996+ features : [ ] ,
5997+ imports : [ 'ModuleBuilder' , 'ValueType' , 'BinaryReader' ] ,
5998+ code : `// Rich Name Section — inspect debug names embedded in a WASM binary
5999+ const mod = new ModuleBuilder('mathLib');
6000+
6001+ mod.defineFunction('add', [ValueType.Int32],
6002+ [ValueType.Int32, ValueType.Int32], (f, a) => {
6003+ a.get_local(f.getParameter(0));
6004+ a.get_local(f.getParameter(1));
6005+ a.add_i32();
6006+ }).withExport();
6007+
6008+ mod.defineFunction('multiply', [ValueType.Int32],
6009+ [ValueType.Int32, ValueType.Int32], (f, a) => {
6010+ a.get_local(f.getParameter(0));
6011+ a.get_local(f.getParameter(1));
6012+ a.mul_i32();
6013+ }).withExport();
6014+
6015+ mod.defineFunction('square', [ValueType.Int32],
6016+ [ValueType.Int32], (f, a) => {
6017+ a.get_local(f.getParameter(0));
6018+ a.get_local(f.getParameter(0));
6019+ a.mul_i32();
6020+ }).withExport();
6021+
6022+ // Build and read back the name section
6023+ const bytes = mod.toBytes();
6024+ const reader = new BinaryReader(bytes);
6025+ const info = reader.read();
6026+
6027+ log('=== Name Section Contents ===');
6028+ log('');
6029+ log('Module name: ' + (info.nameSection?.moduleName || '(none)'));
6030+ log('');
6031+
6032+ if (info.nameSection?.functionNames) {
6033+ log('Function names (' + info.nameSection.functionNames.size + '):');
6034+ for (const [idx, name] of info.nameSection.functionNames) {
6035+ log(' func ' + idx + ' = "' + name + '"');
6036+ }
6037+ } else {
6038+ log('No function names found.');
6039+ }
6040+ log('');
6041+
6042+ log('Exports:');
6043+ for (const exp of info.exports) {
6044+ const kindNames = ['func', 'table', 'memory', 'global', 'tag'];
6045+ log(' "' + exp.name + '" -> ' + (kindNames[exp.kind] || 'unknown') + ' ' + exp.index);
6046+ }
6047+ log('');
6048+ log('Types:');
6049+ for (let i = 0; i < info.types.length; i++) {
6050+ const t = info.types[i];
6051+ if (t.kind === 'func') {
6052+ const params = t.parameterTypes.map(() => 'i32').join(', ');
6053+ const returns = t.returnTypes.map(() => 'i32').join(', ');
6054+ log(' type ' + i + ': (' + params + ') -> (' + returns + ')');
6055+ }
6056+ }
6057+ log('');
6058+ log('Click "Explore" on the WAT card to inspect in the explorer!');` ,
6059+ } ,
6060+
6061+ 'disassembler-usage' : {
6062+ label : 'Disassembler' ,
6063+ group : 'Debug' ,
6064+ description : 'Build a module and use TextModuleWriter to get the WAT.' ,
6065+ target : 'mvp' ,
6066+ features : [ ] ,
6067+ imports : [ 'ModuleBuilder' , 'ValueType' , 'TextModuleWriter' ] ,
6068+ code : `// Disassembler — build a module and convert to WAT
6069+ const mod = new ModuleBuilder('demo');
6070+
6071+ mod.defineFunction('add', [ValueType.Int32],
6072+ [ValueType.Int32, ValueType.Int32], (f, a) => {
6073+ a.get_local(f.getParameter(0));
6074+ a.get_local(f.getParameter(1));
6075+ a.add_i32();
6076+ }).withExport();
6077+
6078+ mod.defineFunction('max', [ValueType.Int32],
6079+ [ValueType.Int32, ValueType.Int32], (f, a) => {
6080+ const x = f.getParameter(0);
6081+ const y = f.getParameter(1);
6082+ a.get_local(x);
6083+ a.get_local(y);
6084+ a.gt_i32();
6085+ a.if(ValueType.Int32);
6086+ a.get_local(x);
6087+ a.else();
6088+ a.get_local(y);
6089+ a.end();
6090+ }).withExport();
6091+
6092+ // Get full WAT via TextModuleWriter
6093+ const wat = mod.toString();
6094+ log('Full WAT:');
6095+ log(wat);
6096+
6097+ // Get binary and inspect
6098+ const bytes = mod.toBytes();
6099+ log('');
6100+ log('Binary size: ' + bytes.length + ' bytes');
6101+ log('Magic: 0x' + Array.from(bytes.slice(0, 4)).map(b => b.toString(16).padStart(2, '0')).join(''));
6102+ log('Version: ' + (bytes[4] | (bytes[5] << 8) | (bytes[6] << 16) | (bytes[7] << 24)));
6103+ log('');
6104+ log('Click "Explore" on the WAT card to inspect the binary structure!');` ,
6105+ } ,
6106+
6107+ 'binary-structure' : {
6108+ label : 'Binary Structure' ,
6109+ group : 'Debug' ,
6110+ description : 'Build a module and inspect its raw binary structure section by section.' ,
6111+ target : 'mvp' ,
6112+ features : [ ] ,
6113+ imports : [ 'ModuleBuilder' , 'ValueType' , 'BinaryReader' ] ,
6114+ code : `// Binary Structure — inspect the section layout of a WASM binary
6115+ const mod = new ModuleBuilder('sections');
6116+
6117+ mod.defineMemory(1, 4);
6118+ mod.defineGlobal(ValueType.Int32, true, 0);
6119+
6120+ mod.defineFunction('store', [],
6121+ [ValueType.Int32, ValueType.Int32], (f, a) => {
6122+ a.get_local(f.getParameter(0));
6123+ a.get_local(f.getParameter(1));
6124+ a.store_i32();
6125+ }).withExport();
6126+
6127+ mod.defineFunction('load', [ValueType.Int32],
6128+ [ValueType.Int32], (f, a) => {
6129+ a.get_local(f.getParameter(0));
6130+ a.load_i32();
6131+ }).withExport();
6132+
6133+ const bytes = mod.toBytes();
6134+ const reader = new BinaryReader(bytes);
6135+ const info = reader.read();
6136+
6137+ const sectionNames = {
6138+ 1: 'Type', 2: 'Import', 3: 'Function', 4: 'Table', 5: 'Memory',
6139+ 6: 'Global', 7: 'Export', 8: 'Start', 9: 'Element', 10: 'Code',
6140+ 11: 'Data', 12: 'DataCount', 0: 'Custom',
6141+ };
6142+
6143+ log('Module version: ' + info.version);
6144+ log('Total size: ' + bytes.length + ' bytes');
6145+ log('');
6146+ log('Types: ' + info.types.length);
6147+ log('Functions: ' + info.functions.length);
6148+ log('Memories: ' + info.memories.length);
6149+ log('Globals: ' + info.globals.length);
6150+ log('Exports: ' + info.exports.length);
6151+ log('');
6152+
6153+ // Parse sections manually
6154+ let offset = 8;
6155+ while (offset < bytes.length) {
6156+ const sectionId = bytes[offset];
6157+ let sizeOffset = offset + 1;
6158+ let sectionSize = 0;
6159+ let shift = 0;
6160+ while (sizeOffset < bytes.length) {
6161+ const byte = bytes[sizeOffset++];
6162+ sectionSize |= (byte & 0x7f) << shift;
6163+ shift += 7;
6164+ if (!(byte & 0x80)) break;
6165+ }
6166+ const name = sectionNames[sectionId] || 'Unknown(' + sectionId + ')';
6167+ log(name + ' section: offset 0x' + offset.toString(16) + ', ' + sectionSize + ' bytes');
6168+ offset = sizeOffset + sectionSize;
6169+ }` ,
6170+ } ,
6171+
6172+ 'custom-metadata' : {
6173+ label : 'Structured Custom Section' ,
6174+ group : 'Debug' ,
6175+ description : 'Embed structured metadata in a custom section and read it back.' ,
6176+ target : 'mvp' ,
6177+ features : [ ] ,
6178+ imports : [ 'ModuleBuilder' , 'ValueType' , 'BinaryReader' ] ,
6179+ code : `// Structured Custom Section — embed and read back build metadata
6180+ const mod = new ModuleBuilder('app');
6181+
6182+ mod.defineFunction('main', [], [], (f, a) => {
6183+ a.nop();
6184+ }).withExport();
6185+
6186+ // Embed build metadata as a custom section
6187+ const metadata = {
6188+ buildTime: new Date().toISOString(),
6189+ compiler: 'webasmjs playground',
6190+ version: '1.0.0',
6191+ features: ['debug-names', 'custom-sections'],
6192+ };
6193+
6194+ const jsonStr = JSON.stringify(metadata);
6195+ const encoder = new TextEncoder();
6196+ const metadataBytes = encoder.encode(jsonStr);
6197+ mod.defineCustomSection('build-metadata', metadataBytes);
6198+
6199+ // Also add a producers-style section
6200+ const producerStr = 'webasmjs;1.0.0';
6201+ mod.defineCustomSection('source-info', encoder.encode(producerStr));
6202+
6203+ const bytes = mod.toBytes();
6204+ const reader = new BinaryReader(bytes);
6205+ const info = reader.read();
6206+
6207+ log('Custom sections found: ' + info.customSections.length);
6208+ log('');
6209+ for (const section of info.customSections) {
6210+ if (section.name === 'name') { continue; }
6211+ log('Section: "' + section.name + '" (' + section.data.length + ' bytes)');
6212+ const decoder = new TextDecoder();
6213+ const content = decoder.decode(section.data);
6214+ try {
6215+ const parsed = JSON.parse(content);
6216+ log(' ' + JSON.stringify(parsed, null, 2));
6217+ } catch {
6218+ log(' ' + content);
6219+ }
6220+ log('');
6221+ }
6222+ log('Click "Explore" to see the custom sections in the explorer!');` ,
6223+ } ,
6224+
59916225 // ─── Imports ───
59926226
59936227 'import-memory' : {
0 commit comments