### parseOpts Option Example Source: https://github.com/humansecurity/flast/blob/main/_autodocs/configuration.md Example demonstrating the use of the 'parseOpts' option in generateFlatAST. ```javascript import {generateFlatAST} from 'flast'; // Parse with JSX support const ast = generateFlatAST(code, { parseOpts: { sourceType: 'module', ecmaVersion: 2020, comment: true, tokens: true, ecmaFeatures: { jsx: true } } }); ``` -------------------------------- ### Minimal Reproduction Example Source: https://github.com/humansecurity/flast/blob/main/_autodocs/troubleshooting.md An example demonstrating how to create a minimal reproduction case for debugging FLAST issues, including generating an AST, marking nodes, and applying changes. ```javascript import {generateFlatAST, Arborist, logger} from 'flast'; logger.setLogLevelDebug(); const minimalCode = 'const x = 42;'; try { const ast = generateFlatAST(minimalCode); console.log('AST length:', ast.length); const arb = new Arborist(minimalCode); const lit = arb.ast[0].typeMap.Literal[0]; arb.markNode(lit, {type: 'Literal', value: 100, raw: '100'}); const applied = arb.applyChanges(); console.log('Result:', arb.script); } catch (e) { console.error('Error:', e); } ``` -------------------------------- ### detailed Option Example Source: https://github.com/humansecurity/flast/blob/main/_autodocs/configuration.md Example demonstrating the use of the 'detailed' option in generateFlatAST. ```javascript import {generateFlatAST} from 'flast'; // With scope analysis const ast1 = generateFlatAST(code, {detailed: true}); const scopes = ast1[0].allScopes; // Available // Without scope analysis const ast2 = generateFlatAST(code, {detailed: false}); const scopes = ast2[0].allScopes; // undefined ``` -------------------------------- ### Compact Output Example Source: https://github.com/humansecurity/flast/blob/main/_autodocs/configuration.md Illustrates how to generate code with minimized whitespace. ```javascript import {generateFlatAST, generateCode} from 'flast'; const code = ' function add(a, b) { return a + b; } '; const ast = generateFlatAST(code); // Compact output const compact = generateCode(ast[0], { format: {compact: true} }); // Result: function add(a,b){return a+b} ``` -------------------------------- ### log Example Source: https://github.com/humansecurity/flast/blob/main/_autodocs/api-reference/logger.md Example of logging standard messages after setting the log level. ```javascript logger.setLogLevelLog(); logger.log('Transformation completed'); logger.log('[+] Applied 5 changes'); ``` -------------------------------- ### setLogLevel Example Source: https://github.com/humansecurity/flast/blob/main/_autodocs/api-reference/logger.md Example of setting the log level to DEBUG. ```javascript logger.setLogLevel(logger.logLevels.DEBUG); ``` -------------------------------- ### Install flast using npm Source: https://github.com/humansecurity/flast/blob/main/README.md Installs the flast package via npm. ```bash npm install flast ``` -------------------------------- ### Constructor Example Source: https://github.com/humansecurity/flast/blob/main/_autodocs/api-reference/Arborist.md Demonstrates creating an Arborist instance from source code or a pre-generated AST. ```javascript import {Arborist} from 'flast'; // From source code const arb1 = new Arborist('const x = 42;'); // From pre-generated AST import {generateFlatAST} from 'flast'; const ast = generateFlatAST('const x = 42;'); const arb2 = new Arborist(ast); ``` -------------------------------- ### applyChanges Example Source: https://github.com/humansecurity/flast/blob/main/_autodocs/api-reference/Arborist.md Illustrates applying multiple changes and observing the result. ```javascript const arb = new Arborist('const x = 1; const y = 2;'); // Mark multiple changes const declarators = arb.ast[0].typeMap.VariableDeclarator; arb.markNode(declarators[0]); // Delete first arb.markNode(declarators[1], { type: 'VariableDeclarator', id: {type: 'Identifier', name: 'z'}, init: {type: 'Literal', value: 3, raw: '3'} }); const applied = arb.applyChanges(); console.log(applied); // 2 (two changes applied) console.log(arb.script); // "const z = 3;" ``` -------------------------------- ### setLogLevelNone Example Source: https://github.com/humansecurity/flast/blob/main/_autodocs/api-reference/logger.md Example of disabling all logging. ```javascript logger.setLogLevelNone(); logger.debug('This will not be logged'); logger.log('This will not be logged'); ``` -------------------------------- ### Configuration Re-Exports Example Source: https://github.com/humansecurity/flast/blob/main/_autodocs/exports.md Example demonstrating how to use `generateFlatAST` with custom options, where configuration objects are documented in parameter descriptions rather than being directly re-exported. ```javascript import {generateFlatAST} from 'flast'; // Default options (not exported separately) const opts = { detailed: true, includeSrc: true, alternateSourceTypeOnFailure: true, parseOpts: { sourceType: 'module', comment: true, tokens: true, }, }; const ast = generateFlatAST(code, opts); ``` -------------------------------- ### Example 1: Numeric Calculation Simplification Source: https://github.com/humansecurity/flast/blob/main/README.md An example demonstrating how to simplify constant numeric expressions in JavaScript code by replacing them with their computed values using the `applyIteratively` function. ```js import {applyIteratively} from 'flast'; function simplifyNumericExpressions(arb) { const binaryNodes = arb.ast[0].typeMap.BinaryExpression || []; for (let i = 0; i < binaryNodes.length; i++) { const n = binaryNodes[i]; if (n.left.type === 'Literal' && typeof n.left.value === 'number' && n.right.type === 'Literal' && typeof n.right.value === 'number') { let result; switch (n.operator) { case '+': result = n.left.value + n.right.value; break; case '-': result = n.left.value - n.right.value; break; case '*': result = n.left.value * n.right.value; break; case '/': result = n.left.value / n.right.value; break; default: continue; } arb.markNode(n, {type: 'Literal', value: result, raw: String(result)}); } } return arb; } const script = 'let x = 5 * 3 + 1;'; const result = applyIteratively(script, [simplifyNumericExpressions]); console.log(result); // let x = 16; ``` -------------------------------- ### setLogLevelDebug Example Source: https://github.com/humansecurity/flast/blob/main/_autodocs/api-reference/logger.md Example of enabling all logging, including debug messages. ```javascript logger.setLogLevelDebug(); // Now see detailed debug output ``` -------------------------------- ### includeSrc Option Example Source: https://github.com/humansecurity/flast/blob/main/_autodocs/configuration.md Example demonstrating the use of the 'includeSrc' option in generateFlatAST. ```javascript import {generateFlatAST} from 'flast'; const code = 'const x = 42;'; const ast1 = generateFlatAST(code, {includeSrc: true}); console.log(ast1[0].childNodes[0].src); // "const x = 42;" const ast2 = generateFlatAST(code, {includeSrc: false}); console.log(ast2[0].childNodes[0].src); // undefined ``` -------------------------------- ### Complete Workflow Example Source: https://github.com/humansecurity/flast/blob/main/_autodocs/api-reference/Arborist.md A comprehensive example showing how to use Arborist to find, delete, and rename functions within a code string, and then apply these changes. ```javascript import {Arborist} from 'flast'; const code = ` function add(a, b) { return a + b; } function multiply(a, b) { return a * b; } `; const arb = new Arborist(code); // Find all function declarations const functions = arb.ast[0].typeMap.FunctionDeclaration; // Delete the first function arb.markNode(functions[0]); // Rename the second function const secondFunc = functions[1]; arb.markNode(secondFunc.id, { type: 'Identifier', name: 'product' }); // Apply changes const changes = arb.applyChanges(); console.log(`Applied ${changes} changes`); console.log(arb.script); // Output: // function product(a, b) { // return a * b; // } ``` -------------------------------- ### Combining Format Options Source: https://github.com/humansecurity/flast/blob/main/_autodocs/configuration.md An example showing how to combine multiple formatting options like indentation, quotes, and compactness. ```javascript import {generateFlatAST, generateCode} from 'flast'; const ast = generateFlatAST(code); // Compact, single quotes, tabs const output = generateCode(ast[0], { format: { indent: {style: '\t'}, quotes: 'single', compact: true, }, comment: false }); ``` -------------------------------- ### generateRootNode Usage Examples Source: https://github.com/humansecurity/flast/blob/main/_autodocs/api-reference/parsingUtilities.md Provides examples of safe parsing with fallback and parsing with source code access. ```javascript import {generateRootNode} from 'flast'; // Safe parsing with fallback const root = generateRootNode('const x = 42;'); if (root) { console.log(root.type); // 'Program' console.log(root.body); // Program body } else { console.log('Parse failed'); } // Parsing with source code access const root2 = generateRootNode(code, { includeSrc: true, parseOpts: { sourceType: 'module', ecmaVersion: 'latest' } }); ``` -------------------------------- ### error Example Source: https://github.com/humansecurity/flast/blob/main/_autodocs/api-reference/logger.md Example of logging error messages. ```javascript logger.error('Failed to parse: Unexpected token'); logger.error(`[-] Unable to apply changes: ${error.message}`); ``` -------------------------------- ### Node Navigation Example Source: https://github.com/humansecurity/flast/blob/main/_autodocs/index.md Illustrates how to navigate the AST using parent and child links. ```javascript node.parentNode; // Parent in tree node.childNodes; // Direct children node.parentKey; // Property name in parent node.src; // Original source code (if includeSrc: true) ``` -------------------------------- ### debug Example Source: https://github.com/humansecurity/flast/blob/main/_autodocs/api-reference/logger.md Example of logging debug messages after setting the log level. ```javascript logger.setLogLevelDebug(); logger.debug('Parsing code...'); logger.debug('AST generated with 150 nodes'); ``` -------------------------------- ### setLogLevelLog Example Source: https://github.com/humansecurity/flast/blob/main/_autodocs/api-reference/logger.md Example of enabling log and error messages, disabling debug. ```javascript logger.setLogLevelLog(); logger.debug('Hidden'); // Not logged logger.log('Visible'); // Logged logger.error('Visible'); // Logged ``` -------------------------------- ### alternateSourceTypeOnFailure Option Example Source: https://github.com/humansecurity/flast/blob/main/_autodocs/configuration.md Example demonstrating the use of the 'alternateSourceTypeOnFailure' option in generateFlatAST. ```javascript import {generateFlatAST} from 'flast'; // Code with strict mode would normally fail as module const code = "'use strict'; const x = 42;'; // With fallback (default) const ast1 = generateFlatAST(code); // Succeeds // Without fallback const ast2 = generateFlatAST(code, {alternateSourceTypeOnFailure: false}); // May fail depending on parser behavior ``` -------------------------------- ### Empty AST Returned Source: https://github.com/humansecurity/flast/blob/main/_autodocs/troubleshooting.md Example of how to enable debug logging and check for an empty AST. ```javascript import {generateFlatAST, logger} from 'flast'; logger.setLogLevelDebug(); // Enable debug output const ast = generateFlatAST(code); if (ast.length === 0) { console.log('Parse failed - check logs above'); // Manually check code with a linter or parser } ``` -------------------------------- ### Complete Parsing Workflow Examples Source: https://github.com/humansecurity/flast/blob/main/_autodocs/api-reference/parsingUtilities.md Illustrates three methods for parsing code and extracting a flat AST, from low-level to high-level, highlighting the recommended approach. ```javascript import { parseCode, generateRootNode, extractNodesFromRoot, generateFlatAST } from 'flast'; const code = 'const x = 42;'; // Method 1: Low-level (for advanced use) const root1 = parseCode(code); // May throw const ast1 = extractNodesFromRoot(root1, { detailed: true, includeSrc: true }); // Method 2: Mid-level (with error handling) const root2 = generateRootNode(code); // Doesn't throw if (root2) { const ast2 = extractNodesFromRoot(root2, { detailed: true, includeSrc: true }); } // Method 3: High-level (recommended) const ast3 = generateFlatAST(code, { detailed: true, includeSrc: true }); // All three produce equivalent results console.log(ast1.length === ast3.length); // true ``` -------------------------------- ### Debugging applyIteratively Performance Source: https://github.com/humansecurity/flast/blob/main/_autodocs/troubleshooting.md Example demonstrating how to lower the iteration limit and check transform functions for infinite loops or inefficiencies when applyIteratively is slow. ```javascript import {applyIteratively, logger} from 'flast'; logger.setLogLevelLog(); // See what's happening const result = applyIteratively(code, [transform], 10); // Lower limit // If still slow, check your transform function function transform(arb) { // Inefficient: iterates all 10,000 nodes for (let i = 0; i < arb.ast.length; i++) { // ... } return arb; } // Better: only iterate relevant types function transform(arb) { const targets = arb.ast[0].typeMap.Identifier || []; for (let i = 0; i < targets.length; i++) { // ... } return arb; } ``` -------------------------------- ### Check Versions Source: https://github.com/humansecurity/flast/blob/main/_autodocs/troubleshooting.md Code snippets to check the Node.js version and the installed FLAST version. ```javascript // Check Node.js version (must be 18+) console.log(process.version); // Check flast version (see package.json or package-lock.json) import {version} from 'flast/package.json'; console.log('flast:', version); ``` -------------------------------- ### markNode Example Source: https://github.com/humansecurity/flast/blob/main/_autodocs/api-reference/Arborist.md Shows how to mark nodes for deletion or replacement. ```javascript import {Arborist} from 'flast'; const arb = new Arborist('const x = 42; const y = 100;'); // Mark for deletion const varDeclarators = arb.ast[0].typeMap.VariableDeclarator; arb.markNode(varDeclarators[0]); // Delete the entire "const x = 42;" statement // Mark for replacement const literals = arb.ast[0].typeMap.Literal; arb.markNode(literals[0], { type: 'Literal', value: 99, raw: '99' }); console.log(arb.getNumberOfChanges()); // 2 arb.applyChanges(); // Apply all changes at once console.log(arb.script); ``` -------------------------------- ### parseCode Usage Examples Source: https://github.com/humansecurity/flast/blob/main/_autodocs/api-reference/parsingUtilities.md Demonstrates basic parsing with parseCode and parsing with custom espree options. ```javascript import {parseCode} from 'flast'; // Basic parsing const ast = parseCode('const x = 42;'); console.log(ast.type); // 'Program' console.log(ast.body.length); // 1 // With custom espree options const ast2 = parseCode(code, { sourceType: 'script', ecmaVersion: 2020 }); ``` -------------------------------- ### Debugging applyIteratively Errors Source: https://github.com/humansecurity/flast/blob/main/_autodocs/troubleshooting.md Example showing how to increase log level to DEBUG to see full error stacks and how to use try-catch within transformation functions to handle errors gracefully. ```javascript import {applyIteratively, logger} from 'flast'; logger.setLogLevelDebug(); // See full error stack function badTransform(arb) { throw new Error('Oops'); } const result = applyIteratively(code, [badTransform]); // Error logged, but function continues // To find issue: use debugger function betterTransform(arb) { try { // risky code } catch (e) { console.error('Detailed error:', e); throw; // Re-throw if needed } return arb; } ``` -------------------------------- ### Optimizing Memory Usage Source: https://github.com/humansecurity/flast/blob/main/_autodocs/troubleshooting.md Example showing how to reduce memory consumption by disabling scope analysis and source closure storage during AST generation. ```javascript import {generateFlatAST} from 'flast'; // Disable unnecessary features const ast = generateFlatAST(largeCode, { detailed: false, // Skip scope analysis (major savings) includeSrc: false // Skip source closures }); ``` -------------------------------- ### Complete Real-World Example Source: https://github.com/humansecurity/flast/blob/main/_autodocs/api-reference/treeModifier.md A comprehensive example demonstrating the use of treeModifier for removing debugger statements, replacing console.log, and removing unused imports. ```javascript import {treeModifier, applyIteratively} from 'flast'; // Remove all debugger statements const removeDebugger = treeModifier( n => n.type === 'DebuggerStatement', (n, arb) => arb.markNode(n) ); // Replace console.log with custom logger const replaceConsoleLog = treeModifier( n => n.type === 'Identifier' && n.name === 'console', (n, arb) => arb.markNode(n, { type: 'Identifier', name: 'logger' }) ); // Remove unused imports const removeUnusedImports = treeModifier( n => n.type === 'ImportDeclaration' && n.specifiers.every(s => { const imported = s.imported || s.local; return !imported.references || imported.references.length === 0; }), (n, arb) => arb.markNode(n) ); const code = ` import unused from 'unused'; debugger; console.log('test'); `; const result = applyIteratively(code, [ removeDebugger, replaceConsoleLog, removeUnusedImports ]); ``` -------------------------------- ### Internal Usage Example Source: https://github.com/humansecurity/flast/blob/main/_autodocs/api-reference/logger.md Shows how `applyIteratively` uses the logger for progress and debugging output. ```javascript import {applyIteratively, logger} from 'flast'; logger.setLogLevelDebug(); const result = applyIteratively(code, [myTransform]); // Output: // [!] Running myTransform... // [+] myTransform applying 5 new changes! // [!] Running myTransform completed in 0.023 seconds // [+] ==> Iteration #1 completed in 0.024 seconds with 5 changes (42 nodes) ``` -------------------------------- ### Optimizing Parsing Performance Source: https://github.com/humansecurity/flast/blob/main/_autodocs/troubleshooting.md Example demonstrating how to speed up parsing of large files by disabling detailed scope analysis and comment/token processing. ```javascript import {generateFlatAST} from 'flast'; // Optimize parsing const ast = generateFlatAST(largeCode, { detailed: false, // 3-5x faster parseOpts: { comment: false, // Faster parsing tokens: false // Not needed for most uses } }); ``` -------------------------------- ### Changes Don't Apply Source: https://github.com/humansecurity/flast/blob/main/_autodocs/troubleshooting.md Example of marking a node for replacement and applying changes using Arborist. ```javascript import {Arborist} from 'flast'; const arb = new Arborist(code); const node = arb.ast[0].typeMap.Literal[0]; // Mark for replacement arb.markNode(node, { type: 'Literal', value: 42, raw: '42' }); console.log(arb.getNumberOfChanges()); // Should be > 0 const applied = arb.applyChanges(); if (applied === 0) { console.log('Changes reverted - likely invalid code'); } ``` -------------------------------- ### Clone the flast repository Source: https://github.com/humansecurity/flast/blob/main/README.md Clones the flast repository and installs its dependencies. ```bash git clone git@github.com:HumanSecurity/flast.git cd flast npm install ``` -------------------------------- ### Type Map Example Source: https://github.com/humansecurity/flast/blob/main/_autodocs/index.md Demonstrates the usage of the typeMap Proxy for fast type-based lookups. ```javascript const identifiers = ast[0].typeMap.Identifier; // Fast const unknown = ast[0].typeMap.NonExistent; // [] (not undefined) ``` -------------------------------- ### Basic flast usage example Source: https://github.com/humansecurity/flast/blob/main/README.md Demonstrates basic usage of flast by replacing string literals in a JavaScript code snippet. It shows how to initialize Arborist, mark nodes for replacement, and apply changes. ```js import {Arborist} from 'flast'; const replacements = {'Hello': 'General', 'there!': 'Kenobi'}; const arb = new Arborist(`console.log('Hello' + ' ' + 'there!');`); // This is equivalent to: // const ast = generateFlatAST(`console.log('Hello' + ' ' + 'there!');`); // const arb = new Arborist(ast); // Since the Arborist accepts either code as a string or a flat AST object. for (let i = 0; i < arb.ast.length; i++) { const n = arb.ast[i]; if (n.type === 'Literal' && replacements[n.value]) { arb.markNode(n, { type: 'Literal', value: replacements[n.value], raw: `'${replacements[n.value]}', }); } } arb.applyChanges(); console.log(arb.script); // console.log('General' + ' ' + 'Kenobi'); ``` -------------------------------- ### Multi-Pass Simplification Source: https://github.com/humansecurity/flast/blob/main/_autodocs/api-reference/applyIteratively.md This example shows a multi-pass simplification process involving simplifying numeric expressions and removing dead code. ```javascript import {applyIteratively} from 'flast'; // Pass 1: Simplify numeric expressions function simplifyNumbers(arb) { const binaries = arb.ast[0].typeMap.BinaryExpression || []; for (let i = 0; i < binaries.length; i++) { const n = binaries[i]; if (n.left.type === 'Literal' && typeof n.left.value === 'number' && n.right.type === 'Literal' && typeof n.right.value === 'number') { let result; switch (n.operator) { case '+': result = n.left.value + n.right.value; break; case '-': result = n.left.value - n.right.value; break; case '*': result = n.left.value * n.right.value; break; case '/': result = n.left.value / n.right.value; break; default: continue; } arb.markNode(n, {type: 'Literal', value: result, raw: String(result)}); } } return arb; } // Pass 2: Remove dead code (unused constants) function removeDeadCode(arb) { const varDecls = arb.ast[0].typeMap.VariableDeclarator || []; for (let i = 0; i < varDecls.length; i++) { const n = varDecls[i]; if (!n.references || n.references.length === 0) { arb.markNode(n); } } return arb; } const code = " let unused = 5 + 3; let x = 2 * 4; console.log(x); "; const result = applyIteratively(code, [simplifyNumbers, removeDeadCode]); // Output: 2 iterations // Pass 1: Simplifies 5+3 to 8 and 2*4 to 8 // Pass 2: Removes unused = 8 ``` -------------------------------- ### Collect Logs for Analysis Source: https://github.com/humansecurity/flast/blob/main/_autodocs/api-reference/logger.md Example of collecting logs in memory for later analysis. ```javascript import {generateFlatAST, logger} from 'flast'; const collectedLogs = []; logger.setLogFunc(msg => collectedLogs.push(msg)); logger.setLogLevelLog(); const ast = generateFlatAST(code); console.log('Collected logs:', collectedLogs); ``` -------------------------------- ### Redirect to a file Source: https://github.com/humansecurity/flast/blob/main/_autodocs/api-reference/logger.md Example of redirecting logger output to a file using a write stream. ```javascript // Redirect to a file const fs = require('fs'); const logStream = fs.createWriteStream('debug.log'); logger.setLogFunc(msg => logStream.write(msg + '\n')); // Or collect logs in memory const logs = []; logger.setLogFunc(msg => logs.push(msg)); ``` -------------------------------- ### Basic Iterative Transformation Source: https://github.com/humansecurity/flast/blob/main/_autodocs/api-reference/applyIteratively.md This example demonstrates a basic iterative transformation where string literals 'foo' are replaced with 'bar'. ```javascript import {applyIteratively} from 'flast'; // Transformation function: replace string literals "foo" with "bar" function replaceFoo(arb) { const literals = arb.ast[0].typeMap.Literal || []; for (let i = 0; i < literals.length; i++) { const n = literals[i]; if (n.value === 'foo') { arb.markNode(n, { type: 'Literal', value: 'bar', raw: "'bar'" }); } } return arb; } const code = "const x = 'foo'; const y = 'foo';"; const result = applyIteratively(code, [replaceFoo]); console.log(result); // "const x = 'bar'; const y = 'bar';" ``` -------------------------------- ### Scope Analysis Example Source: https://github.com/humansecurity/flast/blob/main/_autodocs/index.md Shows how to access scope information when detailed parsing is enabled. ```javascript node.scope; // The scope object node.scopeId; // Scope identifier node.lineage; // Array of ancestor scopeIds node.declNode; // For references: declaration node node.references; // For declarations: reference nodes ``` -------------------------------- ### Iteration Pattern Example Source: https://github.com/humansecurity/flast/blob/main/_autodocs/index.md Outlines the standard workflow for performing transformations using flast. ```javascript 1. **Mark**: Use `arb.markNode()` to queue changes 2. **Apply**: Call `arb.applyChanges()` to validate and apply 3. **Regenerate**: Code is automatically regenerated 4. **Repeat**: Use `applyIteratively()` to run multiple passes ``` -------------------------------- ### Parse and Inspect Source: https://github.com/humansecurity/flast/blob/main/_autodocs/index.md Example of parsing JavaScript code and inspecting the generated AST. ```javascript import {generateFlatAST} from 'flast'; const code = 'const x = 42;'; const ast = generateFlatAST(code); // All nodes in single array console.log(ast.length); // Total nodes // Fast type-based lookup const identifiers = ast[0].typeMap.Identifier; const literals = ast[0].typeMap.Literal; // Access scope information if (ast[0].allScopes) { for (const scopeId in ast[0].allScopes) { console.log(`Scope ${scopeId}`); } } ``` -------------------------------- ### Integration with External Services Source: https://github.com/humansecurity/flast/blob/main/_autodocs/api-reference/logger.md Example of integrating logger with an external service for log aggregation. ```javascript import {logger} from 'flast'; // Send logs to monitoring service logger.setLogFunc(async msg => { await fetch('https://logs.example.com/api', { method: 'POST', body: JSON.stringify({level: 'info', message: msg}) }); }); logger.setLogLevelDebug(); ``` -------------------------------- ### Updating AST and Type Maps Source: https://github.com/humansecurity/flast/blob/main/_autodocs/troubleshooting.md Example illustrating the correct way to modify nodes and ensure the type map is updated by obtaining fresh references after applying changes. ```javascript import {Arborist} from 'flast'; const arb = new Arborist(code); // Get type map reference BEFORE modifications const literals = arb.ast[0].typeMap.Literal; // Modify nodes for (let i = 0; i < literals.length; i++) { arb.markNode(literals[i], {type: 'Identifier', name: 'x'}); } // Don't use old literals reference anymore! arb.applyChanges(); // After applying, get fresh reference const newLiterals = arb.ast[0].typeMap.Literal; // Fresh! ``` -------------------------------- ### Basic Parsing Source: https://github.com/humansecurity/flast/blob/main/_autodocs/api-reference/generateFlatAST.md A basic example demonstrating how to import and use generateFlatAST to parse a simple JavaScript code string. ```javascript import {generateFlatAST} from 'flast'; const code = 'const x = 42; console.log(x);'; const ast = generateFlatAST(code); console.log(ast.length); // Total number of nodes console.log(ast[0].type); // 'Program' console.log(ast[0].typeMap.Identifier.length); // 2 identifiers (x, console, x) ``` -------------------------------- ### Logging and Debugging Source: https://github.com/humansecurity/flast/blob/main/_autodocs/index.md Example of how to import and use the logger utility to control log levels and redirect output. ```javascript import { logger } from 'flast'; logger.setLogLevelDebug(); // Enable debug output logger.setLogLevelLog(); // Standard operational messages logger.setLogLevelError(); // Only errors logger.setLogLevelNone(); // Silent (default) logger.setLogFunc(customFunction); // Redirect output ``` -------------------------------- ### Simple Transformation Source: https://github.com/humansecurity/flast/blob/main/_autodocs/index.md Example of using Arborist to mark and apply simple AST modifications. ```javascript import {Arborist} from 'flast'; const arb = new Arborist('const x = 42;'); // Mark changes const literal = arb.ast[0].typeMap.Literal[0]; arb.markNode(literal, { type: 'Literal', value: 100, raw: '100' }); // Apply all at once arb.applyChanges(); console.log(arb.script); // "const x = 100;" ``` -------------------------------- ### Conditional Logging for Production Source: https://github.com/humansecurity/flast/blob/main/_autodocs/api-reference/logger.md A best practice example for conditionally enabling debug logging based on an environment variable. ```javascript if (process.env.DEBUG) { logger.setLogLevelDebug(); } else { logger.setLogLevelNone(); } ``` -------------------------------- ### Consistent Node Type Checking Source: https://github.com/humansecurity/flast/blob/main/_autodocs/troubleshooting.md Example of creating helper functions (type guards) for reliably checking node types within the AST. ```javascript import {generateFlatAST} from 'flast'; const ast = generateFlatAST(code); function isIdentifier(node) { return node && node.type === 'Identifier'; } function isBinaryOp(node) { return node && node.type === 'BinaryExpression'; } // Use type guards consistently const identifiers = ast[0].typeMap.Identifier; for (let i = 0; i < identifiers.length; i++) { console.assert(isIdentifier(identifiers[i])); } ``` -------------------------------- ### Iterating by Type Source: https://github.com/humansecurity/flast/blob/main/_autodocs/api-reference/generateFlatAST.md An example showing how to efficiently iterate over specific node types, like Identifiers, using the typeMap. ```javascript const ast = generateFlatAST('let a = 1; let b = 2;'); // Efficient: only iterate identifiers const identifiers = ast[0].typeMap.Identifier; for (let i = 0; i < identifiers.length; i++) { console.log(identifiers[i].name); } ``` -------------------------------- ### generateRootNode Fallback Example Source: https://github.com/humansecurity/flast/blob/main/_autodocs/api-reference/parsingUtilities.md Shows generateRootNode retrying with 'script' mode when 'module' mode fails and alternateSourceTypeOnFailure is true. ```javascript const code = "var x = 1;"; // Valid in script mode const root = generateRootNode(code, { alternateSourceTypeOnFailure: true }); // Succeeds: first fails as module, retries as script ``` -------------------------------- ### Validating Generated Code Syntax Source: https://github.com/humansecurity/flast/blob/main/_autodocs/troubleshooting.md Example of how to verify that the JavaScript code generated by `generateCode` is syntactically valid by attempting to create a new Function from it. ```javascript import {generateFlatAST, generateCode} from 'flast'; const ast = generateFlatAST(originalCode); // ... modifications ... const generated = generateCode(ast[0]); // Verify generated code is valid try { new Function(generated); // Throws on syntax error console.log('Generated code is valid'); } catch (e) { console.log('Generated code has error:', e.message); // Check your modifications for invalid structures } ``` -------------------------------- ### setLogLevelError Example Source: https://github.com/humansecurity/flast/blob/main/_autodocs/api-reference/logger.md Example of enabling only error messages. ```javascript logger.setLogLevelError(); logger.debug('Hidden'); // Not logged logger.log('Hidden'); // Not logged logger.error('Visible'); // Logged ``` -------------------------------- ### declNode is undefined Source: https://github.com/humansecurity/flast/blob/main/_autodocs/troubleshooting.md Example of enabling detailed scope analysis and checking node types to resolve 'declNode is undefined'. ```javascript // Ensure scope analysis enabled const ast = generateFlatAST(code, {detailed: true}); // Check node type const id = ast[0].typeMap.Identifier[0]; if (id.parentKey === 'id') { console.log('This is a declaration, check .references instead'); } else if (id.declNode) { console.log('This is a reference to:', id.declNode.id.name); } ``` -------------------------------- ### Custom Parser Options Source: https://github.com/humansecurity/flast/blob/main/_autodocs/api-reference/generateFlatAST.md An example of how to pass custom options to the underlying espree parser for extended syntax support. ```javascript // Parse TypeScript-like syntax extensions const ast = generateFlatAST(code, { parseOpts: { sourceType: 'module', ecmaVersion: 'latest', ecmaFeatures: { jsx: true } } }); ``` -------------------------------- ### AST Array Structure Example Source: https://github.com/humansecurity/flast/blob/main/_autodocs/ast-structure.md Illustrates the flat AST array structure where each node has a unique index. ```javascript ast[0] // Program (root) ast[1] // First child of root ast[2] // Another node // ... ast[n] // Last node ``` -------------------------------- ### generateRootNode Source Code Closure Example Source: https://github.com/humansecurity/flast/blob/main/_autodocs/api-reference/parsingUtilities.md Demonstrates attaching a source code closure for lazy source retrieval with includeSrc: true. ```javascript const root = generateRootNode(code, {includeSrc: true}); // root.srcClosure is a function that returns source slices on demand ``` -------------------------------- ### Iterate over relevant node types for performance Source: https://github.com/humansecurity/flast/blob/main/README.md Example demonstrating how to iterate over specific node types (Identifiers and VariableDeclarators) for better performance, rather than the entire AST. ```js const relevantNodes = [ ...ast[0].typeMap.Identifier, ...ast[0].typeMap.VariableDeclarator, ]; for (let i = 0; i < relevantNodes.length; i++) { const n = relevantNodes[i]; // ... process n ... } ``` -------------------------------- ### Recommended Configuration: Development (debugging) Source: https://github.com/humansecurity/flast/blob/main/_autodocs/configuration.md Configuration settings optimized for development and debugging, enabling detailed AST information and comments. ```javascript generateFlatAST(code, { detailed: true, includeSrc: true, alternateSourceTypeOnFailure: true, parseOpts: {comment: true, tokens: true} }); generateCode(root, { format: {compact: false}, comment: true }); ``` -------------------------------- ### Indentation Styles Source: https://github.com/humansecurity/flast/blob/main/_autodocs/configuration.md Demonstrates how to configure different indentation styles (spaces and tabs) for code generation. ```javascript import {generateFlatAST, generateCode} from 'flast'; const code = 'const obj = { a: 1, b: { c: 2 } };'; const ast = generateFlatAST(code); // With 2 spaces (default) const output1 = generateCode(ast[0], { format: {indent: {style: ' '}} }); // With tabs const output2 = generateCode(ast[0], { format: {indent: {style: '\t'}} }); // With 4 spaces const output3 = generateCode(ast[0], { format: {indent: {style: ' '}} }); ``` -------------------------------- ### Recommended Configuration: Production (performance) Source: https://github.com/humansecurity/flast/blob/main/_autodocs/configuration.md Configuration settings for production environments, prioritizing performance by disabling detailed AST information and comments. ```javascript generateFlatAST(code, { detailed: false, includeSrc: false, parseOpts: {comment: false, tokens: false} }); generateCode(root, { format: {compact: true}, comment: false }); ``` -------------------------------- ### Example: Optimized Multi-Pass Source: https://github.com/humansecurity/flast/blob/main/_autodocs/api-reference/applyIteratively.md An example of an optimized transformation function `efficientTransform` that leverages `typeMap` to process only relevant node types (Literals and BinaryExpressions), improving performance by avoiding iteration over unnecessary nodes. ```javascript import {applyIteratively} from 'flast'; function efficientTransform(arb) { // Only process relevant nodes const targets = [ ...arb.ast[0].typeMap.Literal, ...arb.ast[0].typeMap.BinaryExpression, ]; for (let i = 0; i < targets.length; i++) { // Process only what matters } return arb; } const result = applyIteratively(code, [efficientTransform], 50); ``` -------------------------------- ### Node Deletion Source: https://github.com/humansecurity/flast/blob/main/_autodocs/api-reference/treeModifier.md Example of using treeModifier to remove all console.log calls from the code. ```javascript import {treeModifier, applyIteratively} from 'flast'; // Remove all console.log calls const removeConsoleLogs = treeModifier( n => n.type === 'CallExpression' && n.callee.type === 'MemberExpression' && n.callee.object.name === 'console' && n.callee.property.name === 'log', (n, arb) => arb.markNode(n.parent) // Mark parent ExpressionStatement ); const code = 'console.log("hello"); const x = 42; console.log(x);'; const result = applyIteratively(code, [removeConsoleLogs]); console.log(result); // "const x = 42;" ``` -------------------------------- ### Recommended Configuration: Minification Source: https://github.com/humansecurity/flast/blob/main/_autodocs/configuration.md Configuration optimized for minifying code, including compact output, specific quote styles, and disabling comments. ```javascript generateCode(root, { format: { indent: {style: ''}, quotes: 'single', compact: true, escapeless: false }, comment: false }); ``` -------------------------------- ### Enable Verbose Logging Source: https://github.com/humansecurity/flast/blob/main/_autodocs/troubleshooting.md Demonstrates how to enable debug-level logging in FLAST, including setting the log level and redirecting logs to a file. ```javascript import {logger} from 'flast'; // Levels: DEBUG (1) < LOG (2) < ERROR (3) < NONE (9e10) logger.setLogLevelDebug(); // Most verbose // Or specific level logger.setLogLevel(logger.logLevels.DEBUG); // Redirect to file const fs = require('fs'); const stream = fs.createWriteStream('debug.log'); logger.setLogFunc(msg => stream.write(msg + '\n')); ``` -------------------------------- ### Conditional Modification Source: https://github.com/humansecurity/flast/blob/main/_autodocs/api-reference/treeModifier.md Example of using treeModifier to double all numeric literals less than 100. ```javascript import {treeModifier, applyIteratively} from 'flast'; // Double all numeric literals less than 100 const doubleSmallNumbers = treeModifier( n => n.type === 'Literal' && typeof n.value === 'number' && n.value < 100, (n, arb) => arb.markNode(n, { type: 'Literal', value: n.value * 2, raw: String(n.value * 2) }) ); const code = 'const x = 50; const y = 200;'; const result = applyIteratively(code, [doubleSmallNumbers]); console.log(result); // "const x = 100; const y = 200;" ``` -------------------------------- ### Generating Code with Source Maps Source: https://github.com/humansecurity/flast/blob/main/_autodocs/troubleshooting.md Demonstrates how to generate code with source maps, both as a separate map object and embedded within the code as a trailing comment. ```javascript import {generateCode} from 'flast'; // With source map const {code, map} = generateCode(root, { sourceMap: true, sourceMapWithCode: false }); // With embedded source map const code = generateCode(root, { sourceMapWithCode: true }); // Source map is in trailing comment ``` -------------------------------- ### Boilerplate Reduction Example Source: https://github.com/humansecurity/flast/blob/main/_autodocs/api-reference/treeModifier.md Compares a manual transformation function with one created using treeModifier. ```javascript function myTransform(arb) { for (let i = 0; i < arb.ast.length; i++) { const n = arb.ast[i]; if (filterCondition(n)) { // Modify n } } return arb; } const myTransform = treeModifier( n => filterCondition(n), n => { /* Modify n */ } ); ``` -------------------------------- ### Logging and Debugging Source: https://github.com/humansecurity/flast/blob/main/_autodocs/api-reference/applyIteratively.md Illustrates how to enable debug logging for `applyIteratively` using the `logger` utility, providing insights into the transformation process, including function execution times and changes made per iteration. ```javascript import {applyIteratively} from 'flast'; import {logger} from 'flast'; // Enable debug logging logger.setLogLevelDebug(); // Run transformation const result = applyIteratively(code, [myTransform]); // Output shows: // - Each function name as it runs // - Time taken by each function // - Number of changes per iteration // - Total nodes in AST ``` -------------------------------- ### Multi-Pass Transformation Source: https://github.com/humansecurity/flast/blob/main/_autodocs/index.md Example of using applyIteratively and treeModifier for multi-pass AST transformations. ```javascript import {applyIteratively, treeModifier} from 'flast'; const replaceFoo = treeModifier( n => n.type === 'Literal' && n.value === 'foo', (n, arb) => arb.markNode(n, { type: 'Literal', value: 'bar', raw: "'bar'" }) ); const code = "const x = 'foo'; const y = 'foo';"; const result = applyIteratively(code, [replaceFoo]); // Result: both 'foo' replaced with 'bar' ``` -------------------------------- ### Custom Logging with Timestamps Source: https://github.com/humansecurity/flast/blob/main/_autodocs/api-reference/logger.md Illustrates how to implement custom logging with timestamps. ```javascript import {logger} from 'flast'; logger.setLogFunc(msg => { const timestamp = new Date().toISOString(); console.log(`[${timestamp}] ${msg}`); }); logger.setLogLevelLog(); ``` -------------------------------- ### Migration Notes: From Direct File Imports Source: https://github.com/humansecurity/flast/blob/main/_autodocs/exports.md Illustrates the migration from older direct file import patterns to the recommended main entry point import. ```javascript import {generateFlatAST} from 'flast/src/flast.js'; // Old approach import {generateFlatAST} from 'flast'; // New approach (same functionality) ``` -------------------------------- ### Safe Modifications Example Source: https://github.com/humansecurity/flast/blob/main/_autodocs/index.md Demonstrates the Arborist's mechanism for safe AST modifications. ```javascript arb.markNode(node, replacement); // Queue change arb.applyChanges(); // Apply & validate // If code breaks, changes are reverted automatically ``` -------------------------------- ### Recommended Configuration: Code Analysis Source: https://github.com/humansecurity/flast/blob/main/_autodocs/configuration.md Configuration for code analysis tasks, enabling detailed AST information and comments for deeper inspection. ```javascript generateFlatAST(code, { detailed: true, includeSrc: true, parseOpts: {comment: true, tokens: true} }); // Detailed scope info needed for analysis ``` -------------------------------- ### Basic AST Generation and Traversal Source: https://github.com/humansecurity/flast/blob/main/_autodocs/types.md Demonstrates how to generate a flat AST and access its root node and child nodes. ```javascript import {generateFlatAST} from 'flast'; const ast = generateFlatAST('const x = 42;'); const rootNode = ast[0]; console.log(rootNode.type); // 'Program' console.log(rootNode.nodeId); // 0 console.log(rootNode.childNodes.length); // > 0 // Access nodes by type const identifiers = rootNode.typeMap.Identifier; for (let i = 0; i < identifiers.length; i++) { const id = identifiers[i]; console.log(id.name); // 'x' console.log(id.src); // 'x' console.log(id.parentNode.type); // Parent type } ``` -------------------------------- ### Merge Comments Example Source: https://github.com/humansecurity/flast/blob/main/_autodocs/api-reference/Arborist.md Illustrates how to use the static `mergeComments` method to transfer comments between AST nodes. ```javascript import {Arborist} from 'flast'; const arb = new Arborist( '\n // Comment\n const x = 42;' ); const declarator = arb.ast[0].typeMap.VariableDeclarator[0]; const literal = declarator.init; // Merge trailing comments from literal to declarator Arborist.mergeComments(declarator, literal, 'trailingComments'); ``` -------------------------------- ### Simple Node Replacement Source: https://github.com/humansecurity/flast/blob/main/_autodocs/api-reference/treeModifier.md Example of using treeModifier to replace all occurrences of the string literal 'foo' with 'bar'. ```javascript import {treeModifier, applyIteratively} from 'flast'; // Replace all string literals "foo" with "bar" const replaceFoo = treeModifier( n => n.type === 'Literal' && n.value === 'foo', (n, arb) => arb.markNode(n, { type: 'Literal', value: 'bar', raw: "'bar'" }) ); const code = "const x = 'foo'; const y = 'foo';"; const result = applyIteratively(code, [replaceFoo]); console.log(result); // "const x = 'bar'; const y = 'bar';" ``` -------------------------------- ### Quote Style Configuration Source: https://github.com/humansecurity/flast/blob/main/_autodocs/configuration.md Shows how to enforce single or double quotes, or use the original style from the source code. ```javascript import {generateFlatAST, generateCode} from 'flast'; const code = "const x = 'hello';"; const ast = generateFlatAST(code); // Use double quotes const output = generateCode(ast[0], { format: {quotes: 'double'} }); // Result: const x = "hello"; ``` -------------------------------- ### Debug a Single Transformation Source: https://github.com/humansecurity/flast/blob/main/_autodocs/troubleshooting.md Shows how to debug a single transformation by manually stepping through the process, marking nodes for replacement, and applying changes. ```javascript import {Arborist, logger} from 'flast'; logger.setLogLevelDebug(); const arb = new Arborist(code); // Manually step through transformation const targets = arb.ast[0].typeMap.Literal; for (let i = 0; i < targets.length; i++) { const n = targets[i]; console.log(`Processing literal: ${n.value}`); if (someCondition(n)) { console.log(` -> Marking for replacement`); arb.markNode(n, replacement); } } console.log(`Total changes: ${arb.getNumberOfChanges()}`); const applied = arb.applyChanges(); console.log(`Applied: ${applied}`); ``` -------------------------------- ### Disable Scope Analysis Source: https://github.com/humansecurity/flast/blob/main/_autodocs/api-reference/generateFlatAST.md Example of how to disable detailed scope analysis for performance by setting `detailed: false` in the options. ```javascript // Parse without scope/reference analysis const ast = generateFlatAST(code, { detailed: false }); // ast[0].allScopes will not exist // Nodes will not have scope, lineage, declNode, or references ``` -------------------------------- ### Cannot Delete Required Node Source: https://github.com/humansecurity/flast/blob/main/_autodocs/troubleshooting.md Example demonstrating how Arborist handles attempts to delete nodes that are syntactically required. ```javascript import {Arborist} from 'flast'; const arb = new Arborist(` function f() { const x = 1; } `); // Get the variable declaration const varDecl = arb.ast[0].typeMap.VariableDeclaration[0]; arb.markNode(varDecl); // Try to delete arb.applyChanges(); // This may succeed - Arborist handles finding the right node to remove ``` -------------------------------- ### Main Entry Point Source: https://github.com/humansecurity/flast/blob/main/_autodocs/exports.md All exports can be imported from the main package. ```javascript import { // Parsing generateFlatAST, generateCode, generateRootNode, parseCode, extractNodesFromRoot, mapIdentifierRelations, // Modification Arborist, // Utilities applyIteratively, treeModifier, logger, // Types ASTNode, ASTScope, } from 'flast'; ``` -------------------------------- ### ASTAllScopes Usage Source: https://github.com/humansecurity/flast/blob/main/_autodocs/types.md Illustrates how to access and utilize the `allScopes` map to find scopes by ID or type. ```javascript import {generateFlatAST} from 'flast'; const ast = generateFlatAST(code, {detailed: true}); const allScopes = ast[0].allScopes; // Access scope by ID const scope0 = allScopes[0]; console.log(scope0.type); // Usually 'global' // Find all function scopes for (const scopeId in allScopes) { const scope = allScopes[scopeId]; if (scope.type === 'function') { console.log(`Function scope: ${scope.block.id?.name}`); } } ``` -------------------------------- ### Function Error Handling Source: https://github.com/humansecurity/flast/blob/main/_autodocs/index.md Example of how errors in transformation functions are caught by applyIteratively. Errors are logged but do not stop the iteration. ```javascript logger.setLogLevelError(); // See errors in iteration const result = applyIteratively(code, [transform]); // Errors logged but don't stop iteration ``` -------------------------------- ### Named Function for Logging Source: https://github.com/humansecurity/flast/blob/main/_autodocs/api-reference/treeModifier.md Example of creating a named transformation function using the optional funcName parameter for better debug output. ```javascript import {treeModifier, applyIteratively, logger} from 'flast'; logger.setLogLevelDebug(); // Create named function for better debug output const renameVariables = treeModifier( n => n.type === 'Identifier' && n.name === 'temp', (n, arb) => arb.markNode(n, { type: 'Identifier', name: 'temporary' }), 'renameVariables' // Function name for logging ); const code = 'let temp = 42;'; applyIteratively(code, [renameVariables]); // Output includes: "[!] Running renameVariables..." ```