Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Sourcemaps Lookup Laravel Package

spatie/sourcemaps-lookup

Fast, memory-efficient Source Map v3 lookup for PHP. Resolve JavaScript stack frames to original source file, line/column, symbol name, and enclosing scope. Optimized for the read path and high-volume error symbolicating from uploaded sourcemaps.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps

  1. Installation:

    composer require spatie/sourcemaps-lookup
    
  2. First Use Case: Load a source map and resolve a stack trace position:

    use Spatie\SourcemapsLookup\SourceMapLookup;
    
    $map = SourceMapLookup::fromFile(public_path('js/bundle.js.map'));
    $position = $map->lookup(42, 17); // Line 42, column 17 in the generated JS
    
    if ($position) {
        echo "Original: {$position->sourceFileName}:{$position->sourceLine}";
    }
    
  3. Where to Look First:

    • README.md for core methods (lookup, scopeAt, sourceContent).
    • Benchmarks to understand performance tradeoffs.
    • Exceptions for error handling patterns.

Implementation Patterns

Core Workflow: Stack Trace Resolution

  1. Load Maps Efficiently: Cache maps by URL to avoid redundant parsing:

    $mapCache = [];
    foreach ($stackFrames as $frame) {
        $mapCache[$frame['sourceMapUrl']] ??= SourceMapLookup::fromJson($frame['sourceMap']);
        $position = $mapCache[$frame['sourceMapUrl']]->lookup($frame['line'], $frame['column']);
    }
    
  2. Resolve Positions with Context: Combine lookup with scopeAt for function names and sourceLines for code snippets:

    $position = $map->lookup($line, $column);
    $scope = $map->scopeAt($line, $column);
    
    $snippet = $map->sourceLines(
        $position->sourceFileIndex,
        $position->sourceLine - 5,
        $position->sourceLine + 5
    );
    
  3. Handle Edge Cases:

    • No mapping: Check for null from lookup().
    • Third-party code: Use isIgnored() to filter vendor/framework frames:
      if ($position && !$map->isIgnored($position->sourceFileName)) {
          // Render user code
      }
      

Integration with Laravel

  1. Service Provider Setup: Register a singleton for global map caching:

    $this->app->singleton('sourcemap', function () {
        return new SourceMapLookupCache();
    });
    
  2. Middleware for Error Pages: Attach resolved positions to exceptions:

    public function handle($request, Throwable $exception)
    {
        $map = SourceMapLookup::fromFile(storage_path('app/public/js/bundle.js.map'));
        $position = $map->lookup($exception->getLine(), $exception->getColumn());
    
        $exception->setOriginalSource($position);
        return parent::handle($request, $exception);
    }
    
  3. Blade Directives for Debugging: Create a @sourcemap directive to render stack traces with original sources:

    Blade::directive('sourcemap', function ($expression) {
        return "<?php echo resolve('sourcemap')->render($expression); ?>";
    });
    

Gotchas and Tips

Pitfalls

  1. Lazy Parsing Overhead:

    • The first lookup() on a line parses all preceding segments. For bulk lookups, pre-warm critical lines:
      $map->lookup(1, 0); // Force-parse line 1 to avoid cold-start delays
      
  2. Source Root Resolution:

    • sourceFileName is resolved with sourceRoot but not further resolved to absolute paths. Handle path joining manually if needed:
      $absolutePath = rtrim($map->sourceRoot, '/') . '/' . $position->sourceFileName;
      
  3. Scope Resolution Limitations:

  4. Memory Usage:

    • Large maps (e.g., 6MB+) may spike memory during parsing. Use sourceLines() instead of sourceContent() for snippets to avoid loading entire files.

Debugging Tips

  1. Validate Source Maps: Use try-catch to handle malformed maps:

    try {
        $map = SourceMapLookup::fromJson($json);
    } catch (InvalidSourceMap $e) {
        Log::error("Invalid source map: " . $e->getMessage());
        return null;
    }
    
  2. Inspect Mappings: Log raw mappings for debugging:

    $map = SourceMapLookup::fromArray($data);
    Log::debug('Sources:', $map->sourceNames());
    
  3. Performance Profiling:

    • Use memory_get_usage() to monitor spikes during bulk lookups.
    • Profile findGenerated() separately—it builds a full reverse index on first call.

Extension Points

  1. Custom Position Resolvers: Extend Spatie\SourcemapsLookup\Position or create a decorator to add metadata (e.g., Git blame info):

    class EnhancedPosition extends Position {
        public function gitBlame(): ?string {
            // Integrate with a Git service
        }
    }
    
  2. Source Content Caching: Cache sourcesContent in Laravel’s cache:

    $content = Cache::remember(
        "sourcemap:{$map->hash()}:{$position->sourceFileIndex}",
        now()->addHours(1),
        fn() => $map->sourceContent($position->sourceFileIndex)
    );
    
  3. Reverse Lookup Optimization: For frequent findGenerated() calls, pre-compute the reverse index in a Laravel job:

    ReverseIndex::dispatch($map->toArray())->onQueue('high');
    
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
craftcms/url-validator
directorytree/privacy-filter-classifier
directorytree/privacy-filter
datacore/hub-sdk
develia/commons
cuci/prototurk-sdk
cuci/prototurk-sdk-symfony
develia/geo-bundle
dreamzy/livewire-charts
touchestate-sdk/php-sdk
22h/doctrine-garbage-collection-bundle
agtp/agtp-php
agtp/mod-php
splash/sonata-admin
splash/metadata
splash/openapi
splash/scopes
splash/toolkit
testo/output-teamcity
testo/bridge-symfony