@nine-lab/nine-mu 0.1.339 β 0.1.340
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/nine-mu.js +50 -15
- package/dist/nine-mu.js.map +1 -1
- package/dist/nine-mu.umd.js +1 -1
- package/dist/nine-mu.umd.js.map +1 -1
- package/package.json +1 -1
- package/src/components/exception/ExceptionHook.js +48 -17
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
// src/components/exception/ExceptionHook.js
|
|
2
2
|
import { nine } from '@nine-lab/nine-util';
|
|
3
|
+
import { trace } from '@nopeer';
|
|
3
4
|
|
|
4
5
|
export class ExceptionHook extends HTMLElement {
|
|
5
|
-
// π‘ λΉκ³΅κ° μΈμ€ν΄μ€ νλ μ μ
|
|
6
6
|
#lastPath = window.location.pathname;
|
|
7
7
|
#hasError = false;
|
|
8
8
|
#cssPath = "/css/nine-exception-hook.css";
|
|
@@ -10,15 +10,15 @@ export class ExceptionHook extends HTMLElement {
|
|
|
10
10
|
|
|
11
11
|
constructor() {
|
|
12
12
|
super();
|
|
13
|
-
// Shadow DOM(open λͺ¨λ) νμ±ν
|
|
14
13
|
this.attachShadow({ mode: 'open' });
|
|
14
|
+
trace.log("π [nine-exception-hook] μΈμ€ν΄μ€ μμ±λ¨");
|
|
15
15
|
}
|
|
16
16
|
|
|
17
17
|
connectedCallback() {
|
|
18
|
+
trace.log("π [nine-exception-hook] DOMμ λ§μ΄νΈλ¨. μ΄λ²€νΈ 리μ€λ λ°μΈλ© μμ");
|
|
18
19
|
this.#renderer();
|
|
19
20
|
this.#injectShadowStylesheet();
|
|
20
21
|
|
|
21
|
-
// π― 리μ‘νΈ λ° κ°λ° μ€λ²λ μ΄μ stopPropagationμ μ°ννκΈ° μν μ΄μ€ μ€λνΌ κ°λ
|
|
22
22
|
this.#setupGlobalSniffer();
|
|
23
23
|
|
|
24
24
|
window.addEventListener('unhandledrejection', this.#handlePromiseError, true);
|
|
@@ -27,36 +27,42 @@ export class ExceptionHook extends HTMLElement {
|
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
disconnectedCallback() {
|
|
30
|
+
trace.log("π [nine-exception-hook] DOMμμ μΈλ§μ΄νΈλ¨. 리μ€λ ν΄μ ");
|
|
30
31
|
window.removeEventListener('error', this.#handleRuntimeError, true);
|
|
31
32
|
window.removeEventListener('unhandledrejection', this.#handlePromiseError, true);
|
|
32
33
|
window.removeEventListener('popstate', this.#handleLocationChange);
|
|
33
34
|
document.removeEventListener('click', this.#handleLocationChange, true);
|
|
34
35
|
|
|
35
|
-
// π― μμ onerror νΈλ€λ¬ 볡ꡬ
|
|
36
36
|
if (window.onerror === this.#handleRuntimeError || this.#oldOnError) {
|
|
37
37
|
window.onerror = this.#oldOnError;
|
|
38
|
+
trace.log("π [nine-exception-hook] window.onerror 볡ꡬ μλ£");
|
|
38
39
|
}
|
|
39
40
|
}
|
|
40
41
|
|
|
41
42
|
#setupGlobalSniffer() {
|
|
42
|
-
// νμ€ μΊ‘μ²λ§ 리μ€λ λ±λ‘
|
|
43
43
|
window.addEventListener('error', this.#handleRuntimeError, true);
|
|
44
|
+
trace.log("π [nine-exception-hook] window.addEventListener('error') λ±λ‘ μλ£");
|
|
44
45
|
|
|
45
|
-
// π― [μΉνΈν€] ν νλ μμν¬κ° μ΄λ²€νΈλ₯Ό μΌμΌλ 무쑰건 μ€νλλ μμ hook κ°λ‘μ±κΈ°
|
|
46
46
|
this.#oldOnError = window.onerror;
|
|
47
47
|
window.onerror = (message, source, lineno, colno, error) => {
|
|
48
|
+
trace.log("π¨ [nine-exception-hook] μμ window.onerror ν¬μ°©!!", { message, source, lineno, error });
|
|
49
|
+
|
|
48
50
|
if (!this.#hasError) {
|
|
51
|
+
trace.log("π― [nine-exception-hook] νμ¬ μλ¬ μν μμ -> μλ¬ λ³΄λ μΆλ ₯ μλ");
|
|
49
52
|
const errorMessage = error?.message || message || "μ μ μλ λ°νμ μμΈ";
|
|
50
53
|
const errorStack = error?.stack || `${source}:${lineno}:${colno}`;
|
|
51
54
|
this.#renderError(errorMessage, errorStack);
|
|
55
|
+
} else {
|
|
56
|
+
trace.log("β οΈ [nine-exception-hook] μ΄λ―Έ μλ¬ νλ©΄μ΄ νμ±νλμ΄ μμ΄ μμ onerror ν¨μ€");
|
|
52
57
|
}
|
|
53
58
|
|
|
54
|
-
// κΈ°μ‘΄μ λ±λ‘λμ΄ μλ λ€λ₯Έ onerror μμ§(Vite, λΈλΌμ°μ λ±)μ΄ μμΌλ©΄ κ·Έλλ‘ μ€νλλλ‘ μμ
|
|
55
59
|
if (this.#oldOnError) {
|
|
60
|
+
trace.log("π [nine-exception-hook] κΈ°μ‘΄μ λ±λ‘λμ΄ μλ λ€λ₯Έ onerror μμ§μΌλ‘ μμ");
|
|
56
61
|
return this.#oldOnError(message, source, lineno, colno, error);
|
|
57
62
|
}
|
|
58
63
|
return false;
|
|
59
64
|
};
|
|
65
|
+
trace.log("π [nine-exception-hook] μμ window.onerror κ°λ‘μ±κΈ°(Chaining) μλ£");
|
|
60
66
|
}
|
|
61
67
|
|
|
62
68
|
#renderer = () => {
|
|
@@ -85,33 +91,47 @@ export class ExceptionHook extends HTMLElement {
|
|
|
85
91
|
}
|
|
86
92
|
|
|
87
93
|
#handleRuntimeError = (event) => {
|
|
88
|
-
|
|
94
|
+
trace.log("π¨ [nine-exception-hook] window.addEventListener('error') 리μ€λ ν¬μ°©!!", event);
|
|
95
|
+
|
|
96
|
+
if (this.#hasError) {
|
|
97
|
+
trace.log("β οΈ [nine-exception-hook] μ΄λ―Έ μλ¬ νλ©΄μ΄ νμ±νλμ΄ μμ΄ μ΄λ²€νΈ 리μ€λ ν¨μ€");
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
89
100
|
|
|
90
|
-
// π― event.errorκ° nullμ΄κ±°λ μ μ€λλλΌλ messageλ₯Ό ν΅ν΄ μλ¬λ₯Ό 무쑰건 ν¬μ°©ν©λλ€.
|
|
91
101
|
const errorMessage = event.error?.message || event.message || String(event);
|
|
92
102
|
const errorStack = event.error?.stack || "No stack trace available";
|
|
93
103
|
|
|
94
|
-
// λΈλΌμ°μ λ΄λΆ μ€ν¬λ¦½νΈ λ‘λ© μλ¬ μμΈ μ²λ¦¬ ν κ°μ°¨μμ΄ λ°μΈλ©
|
|
95
104
|
if (errorMessage && errorMessage !== "Script error.") {
|
|
105
|
+
trace.log("π― [nine-exception-hook] μ μμ μΈ μλ¬ λ©μμ§ νμΈ -> μλ¬ λ³΄λ μΆλ ₯ μλ", { errorMessage });
|
|
96
106
|
this.#renderError(errorMessage, errorStack);
|
|
107
|
+
} else {
|
|
108
|
+
trace.log("β οΈ [nine-exception-hook] 'Script error.' μ΄κ±°λ λΉ λ©μμ§λΌ 무μλ¨");
|
|
97
109
|
}
|
|
98
110
|
}
|
|
99
111
|
|
|
100
112
|
#handlePromiseError = (event) => {
|
|
113
|
+
trace.log("π¨ [nine-exception-hook] unhandledrejection (Promise μλ¬) ν¬μ°©!!", event);
|
|
114
|
+
|
|
101
115
|
if (this.#hasError) return;
|
|
102
116
|
|
|
103
|
-
// λΉλκΈ° λΉμ μ λ°νμ κ±°λΆ(ex. null.data μ½κΈ° μλ¬) μΊμΉ
|
|
104
117
|
const reason = event.reason;
|
|
105
118
|
const errorMessage = reason?.message || String(reason || "Unhandled Promise Rejection");
|
|
106
119
|
const errorStack = reason?.stack || "No stack trace available";
|
|
107
120
|
|
|
121
|
+
trace.log("π― [nine-exception-hook] Promise κ±°λΆ νμΈ -> μλ¬ λ³΄λ μΆλ ₯ μλ");
|
|
108
122
|
this.#renderError(errorMessage, errorStack);
|
|
109
123
|
}
|
|
110
124
|
|
|
111
125
|
#handleLocationChange = () => {
|
|
112
126
|
setTimeout(() => {
|
|
127
|
+
trace.log("π [nine-exception-hook] μ£Όμ μ΄λ κ°μ§ 체ν¬", {
|
|
128
|
+
hasError: this.#hasError,
|
|
129
|
+
lastPath: this.#lastPath,
|
|
130
|
+
currentPath: window.location.pathname
|
|
131
|
+
});
|
|
132
|
+
|
|
113
133
|
if (this.#hasError && this.#lastPath !== window.location.pathname) {
|
|
114
|
-
|
|
134
|
+
trace.log("β¨ [nine-exception-hook] Shadow DOM λ΄λΆ μμΈ μ²μ λ° μ μ 볡ꡬ");
|
|
115
135
|
this.#lastPath = window.location.pathname;
|
|
116
136
|
this.#hasError = false;
|
|
117
137
|
|
|
@@ -125,6 +145,7 @@ export class ExceptionHook extends HTMLElement {
|
|
|
125
145
|
}
|
|
126
146
|
|
|
127
147
|
#sendToAiAction = async (errorMessage, errorStack) => {
|
|
148
|
+
trace.log("π [nine-exception-hook] AI μμ μμ² λ²νΌ ν΄λ¦λ¨");
|
|
128
149
|
const btn = this.shadowRoot.querySelector('.nine-ai-btn');
|
|
129
150
|
const footer = this.shadowRoot.querySelector('.nine-error-footer');
|
|
130
151
|
if (!btn) return;
|
|
@@ -135,6 +156,7 @@ export class ExceptionHook extends HTMLElement {
|
|
|
135
156
|
|
|
136
157
|
try {
|
|
137
158
|
if (window.triggerAutoRecovery) {
|
|
159
|
+
trace.log("π‘ [nine-exception-hook] window.triggerAutoRecovery νΈμΆ μ€ν");
|
|
138
160
|
await window.triggerAutoRecovery({
|
|
139
161
|
message: errorMessage,
|
|
140
162
|
stack: errorStack || "No stack trace available",
|
|
@@ -147,7 +169,7 @@ export class ExceptionHook extends HTMLElement {
|
|
|
147
169
|
throw new Error("window.triggerAutoRecovery κ΄μ ν μμ§μ΄ λ‘λλμ§ μμμ΅λλ€.");
|
|
148
170
|
}
|
|
149
171
|
} catch (err) {
|
|
150
|
-
|
|
172
|
+
trace.error("β AI μ μ‘ μ€ν¨:", err);
|
|
151
173
|
btn.disabled = false;
|
|
152
174
|
btn.innerText = "β μ¬μ μ‘ μλ";
|
|
153
175
|
footer.innerHTML = `<span style="color: #E53E3E;">β οΈ μ μ‘ μ€ν¨: ${err.message}</span>`;
|
|
@@ -155,14 +177,21 @@ export class ExceptionHook extends HTMLElement {
|
|
|
155
177
|
}
|
|
156
178
|
|
|
157
179
|
#renderError(errorMessage, errorStack) {
|
|
158
|
-
|
|
159
|
-
this.#hasError = true;
|
|
180
|
+
trace.log("π¨ [nine-exception-hook] #renderError() μ€ν μμ. UI μ ν μ§ν");
|
|
160
181
|
|
|
161
182
|
const coreContainer = this.shadowRoot.querySelector('.nine-hook-core');
|
|
162
|
-
if (coreContainer)
|
|
183
|
+
if (coreContainer) {
|
|
184
|
+
coreContainer.style.display = 'none';
|
|
185
|
+
trace.log("π¨ [nine-exception-hook] <slot> λ³Έλ¬Έ μμ 컨ν
μ΄λ μ¨κΉ (display: none)");
|
|
186
|
+
} else {
|
|
187
|
+
trace.error("β [nine-exception-hook] .nine-hook-core μ리먼νΈλ₯Ό μ°Ύμ μ μμ΅λλ€.");
|
|
188
|
+
}
|
|
163
189
|
|
|
164
190
|
const exceptionBoard = this.shadowRoot.querySelector('.nine-exception-board');
|
|
165
|
-
if (!exceptionBoard)
|
|
191
|
+
if (!exceptionBoard) {
|
|
192
|
+
trace.error("β [nine-exception-hook] .nine-exception-board μ리먼νΈλ₯Ό μ°Ύμ μ μμ΅λλ€.");
|
|
193
|
+
return;
|
|
194
|
+
}
|
|
166
195
|
|
|
167
196
|
const errorHTML = `
|
|
168
197
|
<div class="nine-error-container">
|
|
@@ -180,10 +209,12 @@ export class ExceptionHook extends HTMLElement {
|
|
|
180
209
|
`;
|
|
181
210
|
|
|
182
211
|
exceptionBoard.innerHTML = errorHTML;
|
|
212
|
+
trace.log("π¨ [nine-exception-hook] Shadow DOMμ μλ¬ UI μ½μ
μλ£");
|
|
183
213
|
|
|
184
214
|
const aiBtn = this.shadowRoot.querySelector('.nine-ai-btn');
|
|
185
215
|
if (aiBtn) {
|
|
186
216
|
aiBtn.addEventListener('click', () => this.#sendToAiAction(errorMessage, errorStack));
|
|
217
|
+
trace.log("π¨ [nine-exception-hook] AI μμ² λ²νΌ μ΄λ²€νΈ 리μ€λ λ°μΈλ© μ±κ³΅");
|
|
187
218
|
}
|
|
188
219
|
}
|
|
189
220
|
}
|