4 of 6 standards met
When calling getFileName from an cjs context, it returns just a path name eg . However when calling the same function in an esm context the return value is a url eg . Normally this would not be a problem if the caller expects it however it it surprising when using the same code from multiple contexts. This can be demonstrated by changing the file extension of any example ( -> )
Overview Thank you for maintaining this excellent package! I've been working on performance optimization for debugging and error tracking tools that heavily rely on stack trace retrieval. While benchmarking various approaches, I identified several optimization opportunities that could benefit users in performance-sensitive scenarios. I recently created an optimized fork that implemented cached handlers and in-place array modifications, achieving ~30% memory reduction. However, during my research, I discovered several additional optimization opportunities that could further improve performance, particularly for high-frequency call scenarios. Proposed Optimizations 1. Configurable Stack Depth Limiting Current Behavior: The package captures the full call stack every time, which may include dozens of frames in deeply nested applications. Optimization: Add an optional parameter to limit stack capture at the V8 level before frame collection. Implementation: Use Case: Performance Impact: ~20-40% faster for limited depth scenarios (based on V8 documentation stating that limiting frames has "noticeable" performance benefits) Reduces memory allocation for CallSite objects that are never used V8 specifically optimizes for smaller stack limits (default is 10 for this reason) 2. Error Object Reuse with Reset Pattern Current Behavior: Creates a new Error object on every call, triggering V8's stack capture mechanism each time. Optimization: Reuse a single Error object and rely on V8's lazy stack regeneration. Implementation: Performance Impact: ~10-15% reduction in object allocation overhead Reduces GC pressure in high-frequency scenarios (thousands of calls/sec) Note: This requires careful testing as V8's stack capture behavior with deleted stacks may vary 3. Conditional Stack Frame Filtering Current Behavior: Returns all stack frames (minus the function itself), even if the caller only needs specific frames. Optimization: Add filtering capabilities to avoid processing frames that will be discarded. Implementation: Use Case: Performance Impact: ~15-25% faster when filtering reduces result set significantly Avoids array allocation and iteration in user code Particularly valuable for debugging tools that always filter (e.g., exclude test framework frames) 4. Lazy CallSite Method Access with Proxy Current Behavior: V8's CallSite methods (like , ) may perform expensive operations, especially which traverses prototype chains. Optimization: Provide an optional "lazy" mode that defers CallSite method calls until actually needed. Implementation: Use Case: Performance Impact: ~30-50% faster when only a subset of CallSite methods are used Particularly valuable for which has known performance issues Eliminates redundant method calls when the same property is accessed multiple times 5. Result Caching with Weak Map Current Behavior: No caching between calls, even if the call stack is identical (common in recursive or iterative scenarios). Optimization: Cache results keyed by stack depth and top frame, with automatic cleanup via WeakMap. Implementation: Performance Impact: ~60-80% faster on cache hits in recursive/iterative scenarios Automatic cleanup via WeakMap prevents memory leaks Particularly valuable for logging/debugging in hot loops Benchmarking Strategy I'm happy to create comprehensive benchmarks comparing: 1. Baseline: Current implementation 2. Depth limiting: vs capturing full stack 3. Error reuse: vs creating new Error objects 4. Filtering: vs post-processing in user code 5. Lazy evaluation: vs eager method calls 6. Caching: vs repeated identical calls Test scenarios would include: Single call (baseline overhead) High-frequency calls (10,000+ per second) Deep stacks (50+ frames) Filtering scenarios (keeping 10-20% of frames) Recursive/iterative patterns Use Cases These optimizations are particularly valuable for: 1. Production logging/APM tools - High-frequency call stack capture in production monitoring 2. Test frameworks - Stack traces for thousands of test cases 3. Debugging utilities - Interactive debugging with real-time stack inspection 4. Error tracking services - Processing thousands of errors per second 5. Development tools - Hot reload scenarios with repeated stack captures Backward Compatibility All optimizations could be opt-in via the parameter, ensuring zero breaking changes: Next Steps I'm happy to: 1. Create detailed benchmarks demonstrating the performance improvements 2. Submit a PR implementing any/all of these optimizations 3. Add TypeScript definitions for the new options 4. Update documentation with performance guidance 5. Create migration examples for common use cases Would you be interested in any of these optimizations? I'm particularly excited about the depth limiting (#1) and filtering (#3) as they seem to offer the best performance-to-complexity ratio while maintaining the package's simplicity. Thank you for considering these suggestions!
Hello, With Node 16 and when "type": "module" is specified in , the function returns the file name with prefix. Example with the reproducible code below: Result: Expected result: Reproducible code:
Repository: sindresorhus/callsites. Description: Get callsites from the V8 stack trace API Stars: 271, Forks: 24. Primary language: JavaScript. Languages: JavaScript (54%), TypeScript (46%). License: MIT. Latest release: v4.2.0 (2y ago). Open PRs: 0, open issues: 0. Last activity: 9mo ago. Community health: 85%. Top contributors: sindresorhus, SamVerschueren, BendingBender, BenBeattieHood, coreyfarrell, Zen-cronic, raphinesse.