├── .editorconfig ├── .eslintrc.yml ├── .github ├── CONTRIBUTING.md ├── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md └── workflows │ └── ci.yml ├── .gitignore ├── .npmignore ├── CHANGELOG.md ├── LICENSE ├── README.md ├── bower.json ├── component.json ├── dist ├── stack-generator.js ├── stack-generator.min.js └── stack-generator.min.js.map ├── karma.conf.ci.js ├── karma.conf.js ├── package-lock.json ├── package.json ├── spec ├── fixtures │ └── a.js ├── spec-helper.js └── stack-generator-spec.js ├── stack-generator.d.ts └── stack-generator.js /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig helps developers define and maintain consistent 2 | # coding styles between different editors and IDEs 3 | # editorconfig.org 4 | 5 | root = true 6 | 7 | [*] 8 | end_of_line = lf 9 | charset = utf-8 10 | trim_trailing_whitespace = true 11 | insert_final_newline = true 12 | 13 | [*.{js,json}] 14 | indent_style = space 15 | indent_size = 4 16 | 17 | [.{jshintrc,jscsrc}] 18 | indent_style = space 19 | indent_size = 4 20 | 21 | [*.{yml,yaml}] 22 | indent_style = space 23 | indent_size = 2 24 | 25 | [*.md] 26 | trim_trailing_whitespace = false 27 | -------------------------------------------------------------------------------- /.eslintrc.yml: -------------------------------------------------------------------------------- 1 | env: 2 | browser: true 3 | commonjs: true 4 | node: true 5 | extends: 'eslint:recommended' 6 | globals: 7 | afterEach: false 8 | define: false 9 | describe: false 10 | expect: false 11 | it: false 12 | something_bad: false 13 | StackGenerator: false 14 | parserOptions: 15 | ecmaVersion: 5 16 | ignorePatterns: 17 | - 'coverage/**' 18 | - 'dist/**' 19 | - '**/*.ts' 20 | rules: 21 | indent: 22 | - error 23 | - 4 24 | linebreak-style: 25 | - error 26 | - unix 27 | quotes: 28 | - error 29 | - single 30 | semi: 31 | - error 32 | - always 33 | no-console: 34 | - error 35 | - allow: 36 | - error 37 | -------------------------------------------------------------------------------- /.github/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | ## Submitting bugs 2 | Please include the following information to help us reproduce and fix: 3 | 4 | * What you did 5 | * What you expected to happen 6 | * What actually happened 7 | * Browser and version 8 | * Example code that reproduces the problem (if possible) 9 | * *(l33t mode)* A failing test 10 | 11 | ## Making contributions 12 | Want to be listed as a *Contributor*? Make a pull request with: 13 | 14 | * Unit and/or functional tests that validate changes you're making. 15 | * Run unit tests in the latest IE, Firefox, Chrome, Safari and Opera and make sure they pass. 16 | * Rebase your changes onto origin/HEAD if you can do so cleanly. 17 | * If submitting additional functionality, provide an example of how to use it. 18 | * Please keep code style consistent with surrounding code. 19 | 20 | ## Dev Setup 21 | * Make sure you have [NodeJS v16.x](https://nodejs.org/) installed 22 | * Run `npm ci` from the project directory 23 | 24 | ## Linting 25 | * Run `npm run lint` to run ESLint 26 | 27 | ## Testing 28 | * (Local) Run `npm test`. Make sure [Karma Local Config](karma.conf.js) has the browsers you want 29 | * (Any browser, remotely) If you have a [Sauce Labs](https://saucelabs.com) account, you can run `npm run test-ci` 30 | Make sure the target browser is enabled in [Karma CI Config](karma.conf.ci.js) 31 | Otherwise, GitHub Actions will run all browsers if you submit a Pull Request. 32 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: a:bug 6 | assignees: '' 7 | 8 | --- 9 | 10 | 11 | 12 | ## Expected Behavior 13 | 14 | 15 | 16 | ## Current Behavior 17 | 18 | 19 | 20 | ## Steps to Reproduce (for bugs) 21 | 22 | 23 | 24 | ## Context 25 | 26 | 27 | 28 | ## Your Environment 29 | 30 | * Package version: 31 | * Browser name and version: 32 | * OS version (desktop or mobile): 33 | * Link to your project: 34 | 35 | ## Possible Solution 36 | 37 | 38 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: a:feature 6 | assignees: '' 7 | 8 | --- 9 | 10 | 11 | 12 | ## Expected Behavior 13 | 14 | 15 | 16 | ## Context 17 | 18 | 19 | 20 | ## Possible Solution 21 | 22 | 23 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: Continuous Integration 2 | on: [push] 3 | 4 | jobs: 5 | tests: 6 | runs-on: ubuntu-latest 7 | environment: sauce 8 | permissions: read-all 9 | env: 10 | SAUCE_USERNAME: ${{ secrets.SAUCE_USERNAME }} 11 | SAUCE_ACCESS_KEY: ${{ secrets.SAUCE_ACCESS_KEY }} 12 | SAUCE_TUNNEL_ID: github-action-tunnel 13 | steps: 14 | - name: Setup sauce connect 15 | uses: saucelabs/sauce-connect-action@v2 16 | with: 17 | username: ${{ secrets.SAUCE_USERNAME }} 18 | accessKey: ${{ secrets.SAUCE_ACCESS_KEY }} 19 | tunnelIdentifier: github-action-tunnel 20 | scVersion: 4.7.1 21 | - name: Checkout 22 | uses: actions/checkout@v2 23 | - uses: actions/setup-node@v2 24 | with: 25 | node-version: 16 26 | - name: Cache dependencies 27 | uses: actions/cache@v2 28 | with: 29 | path: ~/.npm 30 | key: npm-${{ hashFiles('package-lock.json') }} 31 | restore-keys: npm- 32 | - name: Install packages 33 | run: npm ci 34 | - name: Lint code 35 | run: npm run lint 36 | - name: Run browser tests in Saucelabs 37 | run: npm run test-ci 38 | timeout-minutes: 5 39 | - name: Install lcov 40 | run: | 41 | sudo apt update 42 | sudo apt install lcov 43 | - name: Merge lcov reports 44 | run: find coverage -name lcov.info -exec echo -a \"{}\" \; | xargs lcov -o coverage/lcov.info 45 | - name: Coveralls 46 | uses: coverallsapp/github-action@master 47 | with: 48 | github-token: ${{ secrets.github_token }} 49 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.seed 2 | *.log 3 | *.out 4 | *.pid 5 | *.gz 6 | 7 | pids 8 | logs 9 | results 10 | 11 | bower_components 12 | node_modules 13 | build 14 | coverage 15 | 16 | .idea 17 | .coveralls.yml 18 | dist 19 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | build/ 3 | coverage/ 4 | spec/ 5 | *.log 6 | .coveralls.yml 7 | .editorconfig 8 | .idea 9 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## v2.0.0 2 | * Upgrade `stackframe` dependency to 1.x. Stackframes are constructed and accessed differently. See the [stackframe CHANGELOG](https://github.com/stacktracejs/stackframe/blob/master/CHANGELOG.md#v10x) for details. 3 | 4 | ## v1.0.3 5 | * Fix edge case when parsing arguments with Firefox 6 | 7 | ## v1.0.2 8 | * Name functions such that they can can be filtered out by stacktrace.js 9 | 10 | ## v1.0.1 11 | * Provide standard distribution (minified and unminified). 12 | 13 | ## v1.0.0 14 | * Add `getArgs()` and `setArgs(args)` methods 15 | 16 | ## v0.1.0 17 | * Initial port from stacktrace.js 18 | 19 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2017 Eric Wendelin and other contributors 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of 4 | this software and associated documentation files (the "Software"), to deal in 5 | the Software without restriction, including without limitation the rights to 6 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 7 | of the Software, and to permit persons to whom the Software is furnished to do 8 | so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | SOFTWARE. 20 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | stack-generator 2 | =============== 3 | [![Build Status](https://img.shields.io/github/workflow/status/stacktracejs/stack-generator/Continuous%20Integration/master?logo=github&style=flat-square)](https://github.com/stacktracejs/stack-generator/actions?query=workflow%3AContinuous+Integration+branch%3Amaster) 4 | [![Coverage Status](https://img.shields.io/coveralls/stacktracejs/stack-generator.svg?style=flat-square)](https://coveralls.io/r/stacktracejs/stack-generator?branch=master) 5 | [![GitHub license](https://img.shields.io/github/license/stacktracejs/stack-generator.svg?style=flat-square)](https://opensource.org/licenses/MIT) 6 | [![dependencies](https://img.shields.io/badge/dependencies-1-green.svg?style=flat-square)](https://github.com/stacktracejs/stack-generator/releases) 7 | [![module format](https://img.shields.io/badge/module%20format-umd-lightgrey.svg?style=flat-square&colorB=ff69b4)](https://github.com/stacktracejs/stack-generator/releases) 8 | [![code of conduct](https://img.shields.io/badge/code%20of-conduct-lightgrey.svg?style=flat-square&colorB=ff69b4)](http://todogroup.org/opencodeofconduct/#stacktrace.js/me@eriwen.com) 9 | 10 | Generate artificial stacktrace by walking `arguments.callee.caller` chain. **Works everywhere except [strict-mode](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Strict_mode)**. 11 | 12 | ## Usage 13 | ``` 14 | StackGenerator.backtrace() 15 | 16 | => [StackFrame({functionName: 'foo', args: []}), StackFrame(..), StackFrame(..)] 17 | ``` 18 | 19 | ## Installation 20 | ``` 21 | npm install stack-generator 22 | bower install stack-generator 23 | https://raw.githubusercontent.com/stacktracejs/stack-generator/master/dist/stack-generator.min.js 24 | ``` 25 | 26 | ## Browser Support 27 | [![Sauce Test Status](https://saucelabs.com/browser-matrix/stacktracejs.svg)](https://saucelabs.com/u/stacktracejs) 28 | 29 | ## Contributing 30 | Want to be listed as a *Contributor*? Start with the [Contributing Guide](CONTRIBUTING.md)! 31 | -------------------------------------------------------------------------------- /bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "stack-generator", 3 | "main": "./dist/stack-generator.js", 4 | "homepage": "https://github.com/stacktracejs/stack-generator.js", 5 | "authors": [ 6 | "Eric Wendelin (http://www.eriwen.com)", 7 | "Victor Homyakov (https://github.com/victor-homyakov)" 8 | ], 9 | "description": "Generate artificial backtrace by walking arguments.callee.caller chain", 10 | "dependencies": { 11 | "stackframe": "~1.0.3" 12 | }, 13 | "moduleType": [ 14 | "amd", 15 | "globals", 16 | "node" 17 | ], 18 | "keywords": [ 19 | "stacktrace", 20 | "stack-trace", 21 | "backtrace", 22 | "cross-browser", 23 | "framework-agnostic", 24 | "error", 25 | "debugger" 26 | ], 27 | "license": "MIT", 28 | "ignore": [ 29 | "**/.*", 30 | "node_modules", 31 | "spec" 32 | ] 33 | } 34 | -------------------------------------------------------------------------------- /component.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "stack-generator", 3 | "repository": "stacktracejs/stack-generator", 4 | "description": "Generate artificial backtrace by walking arguments.callee.caller chain", 5 | "version": "2.0.0", 6 | "keywords": [ 7 | "stacktrace", 8 | "error" 9 | ], 10 | "main": "stack-generator.js", 11 | "scripts": [ 12 | "stack-generator.js" 13 | ], 14 | "dependencies": { 15 | "stacktracejs/stackframe": "1.0.2" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /dist/stack-generator.js: -------------------------------------------------------------------------------- 1 | (function(root, factory) { 2 | 'use strict'; 3 | // Universal Module Definition (UMD) to support AMD, CommonJS/Node.js, Rhino, and browsers. 4 | 5 | /* istanbul ignore next */ 6 | if (typeof define === 'function' && define.amd) { 7 | define('stack-generator', ['stackframe'], factory); 8 | } else if (typeof exports === 'object') { 9 | module.exports = factory(require('stackframe')); 10 | } else { 11 | root.StackGenerator = factory(root.StackFrame); 12 | } 13 | }(this, function(StackFrame) { 14 | return { 15 | backtrace: function StackGenerator$$backtrace(opts) { 16 | var stack = []; 17 | var maxStackSize = 10; 18 | 19 | if (typeof opts === 'object' && typeof opts.maxStackSize === 'number') { 20 | maxStackSize = opts.maxStackSize; 21 | } 22 | 23 | var curr = arguments.callee; 24 | while (curr && stack.length < maxStackSize && curr['arguments']) { 25 | // Allow V8 optimizations 26 | var args = new Array(curr['arguments'].length); 27 | for (var i = 0; i < args.length; ++i) { 28 | args[i] = curr['arguments'][i]; 29 | } 30 | if (/function(?:\s+([\w$]+))+\s*\(/.test(curr.toString())) { 31 | stack.push(new StackFrame({functionName: RegExp.$1 || undefined, args: args})); 32 | } else { 33 | stack.push(new StackFrame({args: args})); 34 | } 35 | 36 | try { 37 | curr = curr.caller; 38 | } catch (e) { 39 | break; 40 | } 41 | } 42 | return stack; 43 | } 44 | }; 45 | })); 46 | -------------------------------------------------------------------------------- /dist/stack-generator.min.js: -------------------------------------------------------------------------------- 1 | !function(t,e){"use strict";"function"==typeof define&&define.amd?define("stackframe",[],e):"object"==typeof exports?module.exports=e():t.StackFrame=e()}(this,function(){"use strict";function t(t){return t.charAt(0).toUpperCase()+t.substring(1)}function e(t){return function(){return this[t]}}var r=["isConstructor","isEval","isNative","isToplevel"],n=["columnNumber","lineNumber"],i=["fileName","functionName","source"],o=r.concat(n,i,["args"],["evalOrigin"]);function a(e){if(e)for(var r=0;r (https://www.eriwen.com)", 6 | "Victor Homyakov (https://github.com/victor-homyakov)", 7 | "Oliver Salzburg (https://github.com/oliversalzburg)", 8 | "Ben Gourley (https://github.com/bengourley)" 9 | ], 10 | "version": "2.0.10", 11 | "license": "MIT", 12 | "keywords": [ 13 | "stacktrace", 14 | "error" 15 | ], 16 | "homepage": "https://www.stacktracejs.com", 17 | "repository": { 18 | "type": "git", 19 | "url": "git://github.com/stacktracejs/stack-generator.git" 20 | }, 21 | "dependencies": { 22 | "stackframe": "^1.3.4" 23 | }, 24 | "devDependencies": { 25 | "eslint": "^8.17.0", 26 | "jasmine": "^4.1.0", 27 | "jasmine-core": "^4.1.1", 28 | "karma": "^6.3.20", 29 | "karma-chrome-launcher": "^3.1.1", 30 | "karma-coverage": "^2.2.0", 31 | "karma-coveralls": "^2.1.0", 32 | "karma-firefox-launcher": "^2.1.2", 33 | "karma-ie-launcher": "^1.0.0", 34 | "karma-jasmine": "^4.0.2", 35 | "karma-opera-launcher": "^1.0.0", 36 | "karma-phantomjs-launcher": "^1.0.4", 37 | "karma-safari-launcher": "^1.0.0", 38 | "karma-sauce-launcher": "^4.3.6", 39 | "karma-spec-reporter": "^0.0.34", 40 | "uglify-es": "^3.3.9" 41 | }, 42 | "bugs": { 43 | "url": "https://github.com/stacktracejs/stack-generator/issues" 44 | }, 45 | "main": "./stack-generator.js", 46 | "typings": "./stack-generator.d.js", 47 | "files": [ 48 | "LICENSE", 49 | "README.md", 50 | "stack-generator.js", 51 | "stack-generator.d.ts", 52 | "dist/" 53 | ], 54 | "scripts": { 55 | "lint": "eslint --fix stack-generator.js spec/", 56 | "test": "karma start karma.conf.js --single-run", 57 | "test-pr": "karma start karma.conf.js --single-run --browsers Firefox,Chrome_No_Sandbox", 58 | "test-ci": "karma start karma.conf.ci.js --single-run", 59 | "prepare": "cp stack-generator.js dist/ && uglifyjs node_modules/stackframe/stackframe.js stack-generator.js -o dist/stack-generator.min.js --compress --mangle --source-map \"url=stack-generator.min.js.map\"" 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /spec/fixtures/a.js: -------------------------------------------------------------------------------- 1 | function a () { 2 | something_bad(); 3 | } 4 | 5 | a(); 6 | -------------------------------------------------------------------------------- /spec/spec-helper.js: -------------------------------------------------------------------------------- 1 | // Polyfill for old browsers 2 | // See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/isArray 3 | if (!Array.isArray) { 4 | Array.isArray = function(arg) { 5 | return Object.prototype.toString.call(arg) === '[object Array]'; 6 | }; 7 | } 8 | -------------------------------------------------------------------------------- /spec/stack-generator-spec.js: -------------------------------------------------------------------------------- 1 | describe('StackGenerator', function() { 2 | describe('#backtrace', function() { 3 | afterEach(function () { 4 | window.onerror = null; 5 | }); 6 | 7 | it('should generate backtrace for function declarations', function() { 8 | var stackFrames = null; 9 | 10 | function foo() { 11 | bar('arg1', 42); 12 | } 13 | 14 | function bar() { 15 | stackFrames = StackGenerator.backtrace(); 16 | } 17 | 18 | foo(); 19 | 20 | expect(stackFrames).toBeTruthy(); 21 | expect(stackFrames[0].functionName).toBe('StackGenerator$$backtrace'); 22 | expect(stackFrames[0].args).toEqual([]); 23 | expect(stackFrames[1].functionName).toBe('bar'); 24 | expect(stackFrames[1].args).toEqual(['arg1', 42]); 25 | expect(stackFrames[2].functionName).toBe('foo'); 26 | expect(stackFrames[2].args).toEqual([]); 27 | }); 28 | 29 | it('should generate backtrace for named function expressions', function() { 30 | var stackFrames = null; 31 | var foo = function foo() { 32 | bar(); 33 | }; 34 | var bar = function bar() { 35 | stackFrames = StackGenerator.backtrace(); 36 | }; 37 | foo(); 38 | 39 | expect(stackFrames).toBeTruthy(); 40 | expect(stackFrames[0].functionName).toBe('StackGenerator$$backtrace'); 41 | expect(stackFrames[0].args).toEqual([]); 42 | expect(stackFrames[1].functionName).toBe('bar'); 43 | expect(stackFrames[1].args).toEqual([]); 44 | expect(stackFrames[2].functionName).toBe('foo'); 45 | expect(stackFrames[2].args).toEqual([]); 46 | }); 47 | 48 | it('should limit stack size given a max stack size', function() { 49 | var stackFrames = null; 50 | var foo = function foo() { 51 | bar(); 52 | }; 53 | var bar = function() { 54 | stackFrames = StackGenerator.backtrace({maxStackSize: 2}); 55 | }; 56 | foo(); 57 | 58 | expect(stackFrames).toBeTruthy(); 59 | expect(stackFrames.length).toBe(2); 60 | }); 61 | 62 | it('should stop and not throw error when encountering a call to eval', function() { 63 | var stackFrames = null; 64 | var foo = function foo() { 65 | eval('stackFrames = StackGenerator.backtrace({maxStackSize: 2});'); 66 | }; 67 | foo(); 68 | 69 | expect(stackFrames).toBeTruthy(); 70 | expect(stackFrames[0].functionName).toBe('StackGenerator$$backtrace'); 71 | }); 72 | 73 | it('should stop and not throw error when entering a strict-mode context', function() { 74 | 'use strict'; 75 | 76 | function _isStrictMode() { 77 | return (eval('var __temp = null'), (typeof __temp === 'undefined')); 78 | } 79 | 80 | var stackFrames = null; 81 | var foo = function() { 82 | bar(); 83 | }; 84 | var bar = function bar() { 85 | stackFrames = StackGenerator.backtrace({maxStackSize: 25}); 86 | }; 87 | foo(); 88 | 89 | expect(stackFrames).toBeTruthy(); 90 | if (_isStrictMode()) { 91 | expect(stackFrames.length).toBe(1); 92 | } 93 | expect(stackFrames[0].functionName).toBe('StackGenerator$$backtrace'); 94 | }); 95 | 96 | it('should handle "null" callees', function(done) { 97 | var errored = false; 98 | window.onerror = function () { 99 | try { 100 | StackGenerator.backtrace(); 101 | } catch (e) { 102 | errored = true; 103 | } 104 | expect(errored).toBe(false); 105 | done(); 106 | }; 107 | var script = document.createElement('script'); 108 | script.src = '/base/spec/fixtures/a.js'; 109 | window.document.body.appendChild(script); 110 | }); 111 | }); 112 | }); 113 | -------------------------------------------------------------------------------- /stack-generator.d.ts: -------------------------------------------------------------------------------- 1 | // Type definitions for StackGenerator v2.0 2 | // Project: https://github.com/stacktracejs/stack-generator 3 | // Definitions by: Eric Wendelin 4 | // Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped 5 | 6 | import StackFrame = require("stackframe"); 7 | 8 | declare namespace StackGenerator { 9 | export type {StackFrame}; 10 | 11 | interface StackGeneratorOptions { 12 | /** Maximum number of StackFrames to return. Default is 10 */ 13 | maxStackSize: number 14 | } 15 | 16 | /** 17 | * Generate artificial backtrace by walking arguments.callee.caller chain. 18 | * 19 | * @param {Object} opts object 20 | * @return {Array} of StackFrames 21 | */ 22 | export function backtrace(opts: StackGeneratorOptions): StackFrame[]; 23 | } 24 | 25 | export = StackGenerator; 26 | -------------------------------------------------------------------------------- /stack-generator.js: -------------------------------------------------------------------------------- 1 | (function(root, factory) { 2 | 'use strict'; 3 | // Universal Module Definition (UMD) to support AMD, CommonJS/Node.js, Rhino, and browsers. 4 | 5 | /* istanbul ignore next */ 6 | if (typeof define === 'function' && define.amd) { 7 | define('stack-generator', ['stackframe'], factory); 8 | } else if (typeof exports === 'object') { 9 | module.exports = factory(require('stackframe')); 10 | } else { 11 | root.StackGenerator = factory(root.StackFrame); 12 | } 13 | }(this, function(StackFrame) { 14 | return { 15 | backtrace: function StackGenerator$$backtrace(opts) { 16 | var stack = []; 17 | var maxStackSize = 10; 18 | 19 | if (typeof opts === 'object' && typeof opts.maxStackSize === 'number') { 20 | maxStackSize = opts.maxStackSize; 21 | } 22 | 23 | var curr = arguments.callee; 24 | while (curr && stack.length < maxStackSize && curr['arguments']) { 25 | // Allow V8 optimizations 26 | var args = new Array(curr['arguments'].length); 27 | for (var i = 0; i < args.length; ++i) { 28 | args[i] = curr['arguments'][i]; 29 | } 30 | if (/function(?:\s+([\w$]+))+\s*\(/.test(curr.toString())) { 31 | stack.push(new StackFrame({functionName: RegExp.$1 || undefined, args: args})); 32 | } else { 33 | stack.push(new StackFrame({args: args})); 34 | } 35 | 36 | try { 37 | curr = curr.caller; 38 | } catch (e) { 39 | break; 40 | } 41 | } 42 | return stack; 43 | } 44 | }; 45 | })); 46 | --------------------------------------------------------------------------------