File size: 4,257 Bytes
26d82c6
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
"use strict";
Object.defineProperty(exports, "__esModule", {
    value: true
});
Object.defineProperty(exports, "installProcessErrorHandlers", {
    enumerable: true,
    get: function() {
        return installProcessErrorHandlers;
    }
});
const _ispostpone = require("../lib/router-utils/is-postpone");
let _global = globalThis;
function installProcessErrorHandlers(shouldRemoveUncaughtErrorAndRejectionListeners) {
    if (_global.nextInitializedProcessErrorHandlers) return;
    _global.nextInitializedProcessErrorHandlers = true;
    // The conventional wisdom of Node.js and other runtimes is to treat
    // unhandled errors as fatal and exit the process.
    //
    // But Next.js is not a generic JS runtime — it's a specialized runtime for
    // React Server Components.
    //
    // Many unhandled rejections are due to the late-awaiting pattern for
    // prefetching data. In Next.js it's OK to call an async function without
    // immediately awaiting it, to start the request as soon as possible
    // without blocking unncessarily on the result. These can end up
    // triggering an "unhandledRejection" if it later turns out that the
    // data is not needed to render the page. Example:
    //
    //     const promise = fetchData()
    //     const shouldShow = await checkCondition()
    //     if (shouldShow) {
    //       return <Component promise={promise} />
    //     }
    //
    // In this example, `fetchData` is called immediately to start the request
    // as soon as possible, but if `shouldShow` is false, then it will be
    // discarded without unwrapping its result. If it errors, it will trigger
    // an "unhandledRejection" event.
    //
    // Ideally, we would suppress these rejections completely without warning,
    // because we don't consider them real errors. (TODO: Currently we do warn.)
    //
    // But regardless of whether we do or don't warn, we definitely shouldn't
    // crash the entire process.
    //
    // Even a "legit" unhandled error unrelated to prefetching shouldn't
    // prevent the rest of the page from rendering.
    //
    // So, we're going to intentionally override the default error handling
    // behavior of the outer JS runtime to be more forgiving
    // Remove any existing "unhandledRejection" and "uncaughtException" handlers.
    // This is gated behind an experimental flag until we've considered the impact
    // in various deployment environments. It's possible this may always need to
    // be configurable.
    if (shouldRemoveUncaughtErrorAndRejectionListeners) {
        process.removeAllListeners('uncaughtException');
        process.removeAllListeners('unhandledRejection');
    }
    // Install a new handler to prevent the process from crashing.
    process.on('unhandledRejection', (reason)=>{
        if ((0, _ispostpone.isPostpone)(reason)) {
            // React postpones that are unhandled might end up logged here but they're
            // not really errors. They're just part of rendering.
            return;
        }
        // Immediately log the error.
        // TODO: Ideally, if we knew that this error was triggered by application
        // code, we would suppress it entirely without logging. We can't reliably
        // detect all of these, but when cacheComponents is enabled, we could suppress
        // at least some of them by waiting to log the error until after all in-
        // progress renders have completed. Then, only log errors for which there
        // was not a corresponding "rejectionHandled" event.
        console.error(reason);
    });
    process.on('rejectionHandled', ()=>{
    // TODO: See note in the unhandledRejection handler above. In the future,
    // we may use the "rejectionHandled" event to de-queue an error from
    // being logged.
    });
    // Unhandled exceptions are errors triggered by non-async functions, so this
    // is unrelated to the late-awaiting pattern. However, for similar reasons,
    // we still shouldn't crash the process. Just log it.
    process.on('uncaughtException', (reason)=>{
        if ((0, _ispostpone.isPostpone)(reason)) {
            return;
        }
        console.error(reason);
    });
}

//# sourceMappingURL=process-error-handlers.js.map