-
Notifications
You must be signed in to change notification settings - Fork 371
/
JavaScriptException.java
195 lines (172 loc) · 5.39 KB
/
JavaScriptException.java
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
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
/*
* Copyright 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.google.gwt.core.client;
import com.google.gwt.core.client.impl.JavaScriptExceptionBase;
/**
* Any JavaScript exceptions occurring within JSNI methods are wrapped as this
* class when caught in Java code. The wrapping does not occur until the
* exception passes out of JSNI into Java. Before that, the thrown object
* remains a native JavaScript exception object, and can be caught in JSNI as
* normal.
* <p>
* The return value of {@link #getStackTrace()} may vary between browsers due to
* variations in the underlying error-reporting capabilities. When possible, the
* stack trace will be the stack trace of the underlying error object. If it is
* not possible to accurately report a stack trace, a zero-length array will be
* returned. In those cases where the underlying stack trace cannot be
* determined, {@link #fillInStackTrace()} can be called in the associated catch
* block to create a stack trace corresponding to the location where the
* JavaScriptException object was created.
*
* <pre>
* try {
* nativeMethod();
* } catch (JavaScriptException e) {
* if (e.getStackTrace().length == 0) {
* e.fillInStackTrace();
* }
* }
* </pre>
*/
public final class JavaScriptException extends JavaScriptExceptionBase {
private static final Object NOT_SET = new Object();
private static String getExceptionDescription(Object e) {
if (e instanceof JavaScriptObject) {
return getExceptionDescription0((JavaScriptObject) e);
} else {
return e + "";
}
}
private static native String getExceptionDescription0(JavaScriptObject e) /*-{
return (e == null) ? null : e.message;
}-*/;
private static String getExceptionName(Object e) {
if (e == null) {
return "null";
} else if (e instanceof JavaScriptObject) {
return getExceptionName0((JavaScriptObject) e);
} else if (e instanceof String) {
return "String";
} else {
return e.getClass().getName();
}
}
private static native String getExceptionName0(JavaScriptObject e) /*-{
return (e == null) ? null : e.name;
}-*/;
/**
* The original description of the JavaScript exception this class wraps,
* initialized as <code>e.message</code>.
*/
private String description = "";
/**
* The underlying exception this class wraps.
*/
private final Object e;
/**
* A constructed message describing this exception.
*/
private String message;
/**
* The original type name of the JavaScript exception this class wraps,
* initialized as <code>e.name</code>.
*/
private String name;
/**
* @param e the object caught in JavaScript that triggered the exception
*/
public JavaScriptException(Object e) {
this(e, "");
}
/**
* @param e the object caught in JavaScript that triggered the exception
* @param description to include in getMessage(), e.g. at the top of a stack
* trace
*/
public JavaScriptException(Object e, String description) {
super(e);
this.e = e;
this.description = description;
}
public JavaScriptException(String name, String description) {
super(null);
this.message = "JavaScript " + name + " exception: " + description;
this.name = name;
this.description = description;
this.e = NOT_SET;
}
/**
* Used for testing instantiations.
*
* @param message the detail message
*/
protected JavaScriptException(String message) {
super(null);
this.message = this.description = message;
this.e = NOT_SET;
fillInStackTrace();
}
/**
* Returns {@code true} if a thrown object is not set for the exception.
*/
public boolean isThrownSet() {
return e != NOT_SET;
}
/**
* Returns the original thrown object from javascript; may be {@code null}.
*/
public Object getThrown() {
return e == NOT_SET ? null : e;
}
/**
* Returns the original JavaScript message of the exception; may be
* <code>null</code>.
*/
public String getDescription() {
ensureInit();
return description;
}
/**
* Returns the original JavaScript the exception; may be <code>null</code>.
*
* @deprecated deprecated in favor for {@link #getThrown()} and {@link #isThrownSet()}
*/
@Deprecated
public JavaScriptObject getException() {
return (e instanceof JavaScriptObject) ? (JavaScriptObject) e : null;
}
@Override
public String getMessage() {
ensureInit();
return message;
}
/**
* Returns the original JavaScript type name of the exception; may be
* <code>null</code>.
*/
public String getName() {
ensureInit();
return name;
}
private void ensureInit() {
if (message == null) {
Object exception = getThrown();
name = getExceptionName(exception);
description = description + ": " + getExceptionDescription(exception);
message = "(" + name + ") " + description;
}
}
}