npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

browser-code-runner

v1.0.5

Published

A unified API for executing different programming language code in the browser

Downloads

38

Readme

Browser Code Runner

A unified API to execute different programming languages in the browser using web workers. This package provides a seamless way to run JavaScript, Python, and Lua code directly in the browser without blocking the main thread.

✨ What's New in v1.0.2

  • 🚀 Full Python Support: Python execution now works out-of-the-box with Pyodide
  • 🎯 Full Lua Support: Lua execution now works out-of-the-box with Fengari
  • 🔧 Self-Contained: No need to manually load libraries - everything is handled automatically
  • ⚡ Dynamic Loading: Libraries are loaded only when needed and cached for performance
  • 🛡️ Better Error Handling: Comprehensive error messages and fallback mechanisms

Features

  • 🚀 Web Worker Support: All code execution runs in separate threads to keep your main thread responsive
  • 🐍 Python Support: Execute Python code using Pyodide (CPython compiled to WebAssembly) - Now fully working!
  • 🔧 JavaScript Support: Execute JavaScript/TypeScript code in a sandboxed environment
  • 🎯 Lua Support: Execute Lua code using Fengari (Lua VM in JavaScript) - Now fully working!
  • ⏱️ Timeout Protection: Configurable timeouts to prevent infinite loops
  • 📦 TypeScript Support: Full TypeScript definitions included
  • 🧪 Comprehensive Testing: Thorough test coverage for all features
  • 🔄 Automatic Library Loading: Pyodide and Fengari are loaded automatically when needed
  • 💾 Smart Caching: Libraries are cached after first use for faster subsequent executions

Installation

npm install browser-code-runner

Quick Start

import { runCode } from 'browser-code-runner';

// Execute Python code (now works out-of-the-box!)
const pythonResult = await runCode({
  language: 'python',
  code: 'print("Hello from Python!")\nprint("2 + 2 =", 2 + 2)',
  timeout: 5000
});

console.log(pythonResult.stdout); // "Hello from Python!\n2 + 2 = 4\n"

// Execute Lua code (now works out-of-the-box!)
const luaResult = await runCode({
  language: 'lua',
  code: 'print("Hello from Lua!")\nprint("2 + 2 =", 2 + 2)',
  timeout: 3000
});

console.log(luaResult.stdout); // "Hello from Lua!\n2 + 2 = 4\n"

// Execute JavaScript code (always worked)
const jsResult = await runCode({
  language: 'javascript',
  code: 'console.log("Hello from JavaScript!")\nconsole.log("2 + 2 =", 2 + 2)',
  timeout: 2000
});

console.log(jsResult.stdout); // "Hello from JavaScript!\n2 + 2 = 4\n"

🎮 Try the Demo

Experience the Browser Code Runner in action with our interactive demo:

  • 🌐 Live Demo: View Demo
  • 📱 Mobile Responsive: Works perfectly on all devices
  • 🎨 Monaco Editor: Professional code editing experience
  • 🚀 Real-time Execution: See results immediately
  • 🐍 Python Support: Full Python execution with Pyodide
  • 🎯 Lua Support: Full Lua execution with Fengari

Run locally:

npm install
npm run demo

Supported Languages

Phase 1 (Fully Supported ✅)

  1. JavaScript/TypeScript

    • Runs natively in the browser
    • Sandboxed execution environment
    • Full access to JavaScript APIs
    • Status: ✅ Fully Working
  2. Python

    • Powered by Pyodide (CPython → WebAssembly)
    • Status: ✅ Fully Working (v1.0.2+)
    • Automatically loads Pyodide when needed
    • Full Python standard library support
    • Cached after first use for performance
  3. Lua

    • Powered by Fengari (Lua VM in JavaScript)
    • Status: ✅ Fully Working (v1.0.2+)
    • Automatically loads Fengari when needed
    • Lightweight and fast execution
    • Cached after first use for performance

🚀 Implementation Guide

Basic Usage

The simplest way to use the package is with the runCode function:

import { runCode } from 'browser-code-runner';

// All languages work the same way
const result = await runCode({
  language: 'javascript' | 'python' | 'lua',
  code: 'your code here',
  timeout: 5000 // optional, default: 5000ms
});

Advanced Usage

For more control, use the CodeRunner class:

import { createCodeRunner } from 'browser-code-runner';

const runner = createCodeRunner();

try {
  const result = await runner.runCode({
    language: 'python',
    code: 'print("Hello World")',
    timeout: 10000
  });
  
  console.log('Output:', result.stdout);
  console.log('Errors:', result.stderr);
  console.log('Exit Code:', result.exitCode);
  console.log('Execution Time:', result.timeMs + 'ms');
} finally {
  // Always clean up resources
  runner.terminate();
}

Error Handling

import { runCode } from 'browser-code-runner';

try {
  const result = await runCode({
    language: 'python',
    code: 'print("Hello")\nundefined_variable', // This will cause an error
    timeout: 5000
  });
  
  if (result.exitCode !== 0) {
    console.error('Execution failed:', result.stderr);
  } else {
    console.log('Success:', result.stdout);
  }
} catch (error) {
  if (error.message.includes('timed out')) {
    console.error('Code execution timed out');
  } else if (error.message.includes('Failed to load')) {
    console.error('Library loading failed:', error.message);
  } else {
    console.error('Unexpected error:', error.message);
  }
}

📚 Language-Specific Examples

Python Examples

Basic Python

const result = await runCode({
  language: 'python',
  code: `
    print("Hello from Python!")
    print("2 + 2 =", 2 + 2)
    
    # Lists and loops
    numbers = [1, 2, 3, 4, 5]
    for num in numbers:
        print(f"Number: {num}")
    
    # Functions
    def greet(name):
        return f"Hello, {name}!"
    
    print(greet("World"))
  `,
  timeout: 8000 // Python needs more time for library loading
});

Python with Libraries

const result = await runCode({
  language: 'python',
  code: `
    import math
    import random
    from datetime import datetime
    
    # Generate random data
    data = [random.randint(1, 100) for _ in range(10)]
    print("Random data:", data)
    
    # Calculate statistics
    mean = sum(data) / len(data)
    print(f"Mean: {mean:.2f}")
    print(f"Square root of 16: {math.sqrt(16)}")
    
    # Current time
    print(f"Current time: {datetime.now()}")
  `,
  timeout: 10000
});

Lua Examples

Basic Lua

const result = await runCode({
  language: 'lua',
  code: `
    print("Hello from Lua!")
    print("2 + 2 =", 2 + 2)
    
    -- Tables and loops
    local numbers = {1, 2, 3, 4, 5}
    for i, num in ipairs(numbers) do
        print("Number:", num)
    end
    
    -- Functions
    local function greet(name)
        return "Hello, " .. name .. "!"
    end
    
    print(greet("World"))
  `,
  timeout: 5000
});

Advanced Lua

const result = await runCode({
  language: 'lua',
  code: `
    -- Fibonacci with memoization
    local memo = {}
    function fibonacci(n)
        if memo[n] then
            return memo[n]
        end
        
        if n <= 1 then
            memo[n] = n
            return n
        end
        
        memo[n] = fibonacci(n-1) + fibonacci(n-2)
        return memo[n]
    end
    
    -- Calculate first 10 Fibonacci numbers
    for i = 0, 10 do
        print("fib(" .. i .. ") = " .. fibonacci(i))
    end
  `,
  timeout: 6000
});

JavaScript Examples

Basic JavaScript

const result = await runCode({
  language: 'javascript',
  code: `
    console.log("Hello from JavaScript!");
    console.log("2 + 2 =", 2 + 2);
    
    // Arrays and loops
    const numbers = [1, 2, 3, 4, 5];
    numbers.forEach(num => console.log("Number:", num));
    
    // Functions
    function greet(name) {
        return \`Hello, \${name}!\`;
    }
    
    console.log(greet("World"));
  `,
  timeout: 3000
});

Advanced JavaScript

const result = await runCode({
  language: 'javascript',
  code: `
    // Classes and async operations
    class Calculator {
        constructor() {
            this.history = [];
        }
        
        add(a, b) {
            const result = a + b;
            this.history.push(\`\${a} + \${b} = \${result}\`);
            return result;
        }
        
        getHistory() {
            return this.history;
        }
    }
    
    const calc = new Calculator();
    console.log("5 + 3 =", calc.add(5, 3));
    console.log("History:", calc.getHistory());
    
    // Async operations
    async function fetchData() {
        const promise = Promise.resolve("Data fetched successfully!");
        const result = await promise;
        console.log(result);
    }
    
    fetchData();
  `,
  timeout: 4000
});

🔧 API Reference

runCode(options: RunCodeOptions): Promise<RunCodeResult>

The main function to execute code in any supported language.

Parameters

interface RunCodeOptions {
  language: 'javascript' | 'python' | 'lua';
  code: string;
  stdin?: string;
  timeout?: number; // Default: 5000ms
}

Returns

interface RunCodeResult {
  stdout: string;
  stderr: string;
  exitCode: number; // 0 for success, non-zero for errors
  timeMs: number;   // Execution time in milliseconds
}

createCodeRunner(workerUrl?: string): CodeRunner

Create a new CodeRunner instance for advanced usage.

CodeRunner Class

Advanced API for managing multiple code executions.

const runner = createCodeRunner();

// Execute code
const result = await runner.runCode({
  language: 'javascript',
  code: 'console.log("Hello World");'
});

// Clean up resources
runner.terminate();

🚨 Troubleshooting

Common Issues

1. Python/Lua Execution Fails

Problem: Getting "Failed to load Pyodide/Fengari" errors Solution:

  • Ensure you have a stable internet connection (libraries are loaded from CDN)
  • Check if your browser supports WebAssembly
  • Try increasing the timeout value

2. Code Execution Times Out

Problem: Code runs but times out before completion Solution:

  • Increase the timeout parameter
  • For Python: Use timeout: 8000 or higher
  • For Lua: Use timeout: 5000 or higher
  • For JavaScript: Use timeout: 3000 or higher

3. Worker Not Found

Problem: "Worker script not found" error Solution:

  • Ensure the worker file is accessible
  • Check if you're using a custom worker URL
  • Verify the package is properly built

4. Library Loading Issues

Problem: Pyodide or Fengari fails to load Solution:

  • Check browser console for network errors
  • Ensure CDN access is not blocked
  • Try refreshing the page and retrying

Performance Tips

  1. Set Appropriate Timeouts:

    • JavaScript: 2000-5000ms
    • Python: 8000-15000ms (first run), 3000-8000ms (subsequent)
    • Lua: 5000-10000ms (first run), 2000-5000ms (subsequent)
  2. Library Caching:

    • First execution of Python/Lua will be slower due to library loading
    • Subsequent executions will be much faster
    • Libraries are cached in the worker
  3. Code Optimization:

    • Avoid infinite loops
    • Use appropriate data structures
    • Consider memory usage for large operations

Performance Considerations

Web Workers

  • All code execution runs in separate threads
  • Main thread remains responsive during execution
  • Automatic cleanup of worker resources

Caching

  • Python (Pyodide): ~7-10 MB initial download, cached after first use
  • Lua (Fengari): ~1 MB, very lightweight
  • JavaScript: No additional downloads required

Timeouts

  • Default timeout: 5000ms (5 seconds)
  • Recommended timeouts:
    • JavaScript: 2000-5000ms
    • Python: 8000-15000ms
    • Lua: 5000-10000ms
  • Automatic cleanup on timeout

Browser Compatibility

  • Modern Browsers: Chrome 80+, Firefox 75+, Safari 13+, Edge 80+
  • Web Worker Support: Required
  • ES2020 Features: Required
  • WebAssembly: Required for Python support
  • Network Access: Required for library loading (CDN)

Development

Setup

git clone <repository-url>
cd browser-code-runner
npm install

Build

npm run build        # Build TypeScript + worker
npm run build:vite   # Build ES/UMD bundles
npm run build:all    # Full build for publishing

Test

npm test
npm run test:watch

Lint

npm run lint
npm run lint:fix

Format

npm run format

Demo

npm run demo        # Build + copy worker + serve demo

Contributing

  1. Fork the repository
  2. Create a feature branch
  3. Make your changes
  4. Add tests for new functionality
  5. Ensure all tests pass
  6. Submit a pull request

License

MIT License - see LICENSE file for details.

Roadmap

Phase 2 (Future)

  • C/C++ support via Emscripten
  • Ruby support via Opal or WASM MRI builds
  • Go support via WebAssembly
  • Rust support via WebAssembly

Phase 3 (Future)

  • Real-time collaboration features
  • Code sharing and execution
  • Advanced debugging capabilities
  • Performance profiling

Support

Acknowledgments