{"id":23562069,"url":"https://github.com/lddubeau/last-resort","last_synced_at":"2025-05-16T02:33:43.320Z","repository":{"id":10764469,"uuid":"66889329","full_name":"lddubeau/last-resort","owner":"lddubeau","description":"A simple library to take care of global errors in browsers.","archived":false,"fork":false,"pushed_at":"2023-01-04T21:37:38.000Z","size":1618,"stargazers_count":2,"open_issues_count":16,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-04-21T10:54:09.915Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mpl-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/lddubeau.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2016-08-29T23:50:03.000Z","updated_at":"2020-05-21T03:33:46.000Z","dependencies_parsed_at":"2023-01-11T17:56:42.556Z","dependency_job_id":null,"html_url":"https://github.com/lddubeau/last-resort","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lddubeau%2Flast-resort","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lddubeau%2Flast-resort/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lddubeau%2Flast-resort/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lddubeau%2Flast-resort/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/lddubeau","download_url":"https://codeload.github.com/lddubeau/last-resort/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254455721,"owners_count":22074042,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-12-26T16:14:49.899Z","updated_at":"2025-05-16T02:33:43.302Z","avatar_url":"https://github.com/lddubeau.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"Last Resort aims to help your application catch unhandled exceptions and\nunhandled rejected promises in the browser.\n\nPlatforms Supported\n===================\n\n[![Browser Stack](https://www.browserstack.com/images/mail/browserstack-logo-footer.png)](https://www.browserstack.com)\n\nLast Resort is tested using\n[BrowserStack](https://www.browserstack.com). BrowserStack provides this service\nfor free under their program for supporting open-source software.\n\nLast Resort is supported on:\n\n* Desktop: Chrome, Firefox, Edge, IE11, IE10, IE9, Opera, and Safari (on El\nCapitan, Yosemite, Mavericks).\n\n* Mobile: iOS 9.3 down to 6. Android 4.4. Presumably later versions of Android\n  are also fine, although we've not been able to test them.\n\nWe test against the latest versions offered by the vendors of these browsers on\ntheir respective platforms.\n\nBorderline cases:\n\n* The suite runs on IE9 but it does not perform a thorough check of the values\n  obtained from the events generated by the browser. There are a few quirks\n  there.\n\nIf you see a platform you think should be tested but isn't, then chances are\nthat Browser Stack is not providing support for it, or is not providing stable\nsupport for it. You should inspect the ``karma.conf.js`` file to see platforms\nthat have been commented out. If you can get these platforms to work, you are\nwelcome to put in a pull request.\n\nNot supported, and unlikely to be supported, ever:\n\n* Android versions less than 4.4.\n\n* iOS versions less than 6.\n\n**IMPORTANT IMPORTANT IMPORTANT: Last Resort depends on\n``\u003cglobal\u003e.addEventListener(\"unhandledrejection\", ...)`` being supported in your\nenvironment in order to trap unhandled rejections.** If your platform does not\nsupport this, then Last Resort will not be able to trap unhandled\nrejections. [This\npage](https://developer.mozilla.org/en-US/docs/Web/API/PromiseRejectionEvent)\nsuggests that only Chrome 49 and over supports it natively. On browsers that do\nnot support it natively, you must use a promise library that provides support\nfor ``unhandledrejection``\nevents. [Bluebird](https://github.com/petkaantonov/bluebird/) is one such\nlibrary. It is actually the library used for testing Last Resort's handling of\nunhandled rejections.\n\n**Note on using Last Resort in workers**. Last Resort, when used with Bluebird,\nis able to trap unhandledrejection in workers. However, it has to use\n`self.onunhandledrejection`` rather than ``self.addEventListener``. This is\nbecause a lot of platforms (including **all** Microsoft browsers) do not\nactually allow using ``self.addEventListener`` to listen for custom\nexceptions. See [this\ncomment](https://github.com/petkaantonov/bluebird/pull/1213#issuecomment-243168274)\nfor details.\n\nLoading Last Resort\n===================\n\nLast Resort can be loaded in the following ways:\n\n1. In a `script` element. In this case it will be available as `LastResort` on\n   the `window` object in which it has been loaded.\n\n2. As an AMD module. It will export the same thing as what `LastResort` contains\n   in the scenario above. You may name the module whatever you want, so long as\n   you define a path for it in your `paths` configuration.\n\n3. As a CommonJS module. It will export the same as the thing as the earlier\n   options.\n\n4. In a `script` element and then as an AMD or CommonJS module. This is not a\n   common way to load scripts but Last Resort supports it. When it is loaded by\n   `script`, it creates `LastResort` like in the first scenario above. When it\n   is then loaded again as a module, it checks whether `LastResort` already\n   exists in the global space, and returns *that* if it exists, rather than\n   create a new module. If `LastResort` does not exist, then it will initialize\n   itself from scratch. Note that, when loaded first through `script` and then\n   as a module, `LastResort` will still be present in the global space if it had\n   only been loaded through `script`.\n\nWhy this 4th method? This is supported in order to allow loading Last Resort as\nearly as possible, while still allowing it to be referenced as a module, and not\nforcing modules that need to use it to refer to a global. Ideally, Last Resort\nshould be loaded before any other code so that it can report errors as early as\npossible. In one project in which it is used, it is loaded with a `script`\nelement, then we register an absolutely bare error handler that uses `alert` to\nreport to the user, then more substantial scripts are loaded, including an AMD\nmodule that provides a Bootstrap-based dialog in case of error. This module\nloads Last Resort as an AMD module and replaces the initial barebones error\nhandler with its more sophisticated one.\n\nUsing Last Resort\n=================\n\nLast Resort listens to these two events:\n\n* ``error``, which is emitted when a thrown exception is not caught by any code.\n\n* ``unhandledrejection``, which is emitted when a rejected promise is not\n  handled by any code.\n\nIn the following when we say \"the events\" we are referring to these two events.\n\nLast Resort exports these items:\n\n* ``install(context, options)`` installs Last Resort to intercept the events on\n  ``context``. The parameter ``context`` is often ``window`` but could be the\n  global context of a worker too (``self``). It returns an instance of\n  ``OnError`` this instance is what is now handling the events.\n\n  The ``options`` parameter is a plain object holding possible options:\n\n  + ``force`` when set to ``true`` will force the installation of Last Resort on\n     the ``context`` even if it was already installed previously. Otherwise an\n     exception is raised. If ``force`` is used and Last Resort was previously\n     installed, the previous installation will be automatically uninstalled.\n\n  + ``noUnhandledRejection`` when set to ``true`` will **NOT** install a handler\n     to catch unhandled rejections.\n\n* The ``OnError`` class, which has the following methods:\n\n  + ``register(fn)`` registers the function ``fn`` to handle the events. ``fn``\n     will be called with the event objects generated for the ``error`` and\n     ``unhandledrejection`` events. It should be prepared to examine the event\n     to determine what happened exactly. **Until ``register(fn)`` is called, the\n     ``OnError`` instance does not do anything when an event is emitted.**\n\n  + ``uninstall()`` uninstalls the ``OnError``\n\n* ``isInstalled(context)`` returns ``true`` if ``install(context)`` was\n  ever called. ``false`` otherwise.\n\n* ``wasTriggered()`` returns ``true`` if any event was raised in any context.\n\nBy default, the registered function is called both when an uncaught exception\nhappens and when an unhandled Promise rejection happens. So it has to be ready\nto examine its arguments and determine how to process that information depending\non the types and number of the arguments passed.\n\nWhen the registered function is called, Last Resort calls ``uninstall`` on the\n``OnError` object that bears the registered function. This prevents infinite\nrecursion if it happens that the registered function causes new errors. It is up\nto the developer of the registered function to ensure that this function does\nnot screw things up while it is running. It *could* call ``LastResort.install``\nanew if desired and register its own specialized handler. Or it could do its own\nerror handling.\n\nSome old browsers bypass ``onerror`` handlers attached to ``iframe`` elements\nand instead go straight for the one on the root window. It is up to your\napplication to decide whether it needs to support these old browsers and use\nLast Resort appropriately (e.g. detect the issue and install on the root window\ninstead of installing on an ``iframe``).\n\nExample\n=======\n\nHere is a super simple example:\n\n    import * as lr from \"last-resort\";\n\n    const onerror: lr.OnError = lr.install(window);\n\n    function handle(ev: Event): void {\n        // tslint:disable-next-line:no-console\n        console.log(ev);\n    }\n\n    onerror.register(handle);\n\nThis example just dumps the error to the console.\n\nDeveloping Last Resort\n======================\n\nIf you produce a pull request run ``gulp test`` first to make sure it is\nclean. If you add features, do add tests for them.\n\n\u003c!--\n#  LocalWords:  BrowserStack El Capitan iOS addEventListener issuecomment fn\n#  LocalWords:  unhandledrejection onunhandledrejection LastResort CommonJS\n#  LocalWords:  barebones OnError noUnhandledRejection isInstalled onerror\n#  LocalWords:  wasTriggered iframe\n--\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flddubeau%2Flast-resort","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flddubeau%2Flast-resort","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flddubeau%2Flast-resort/lists"}