View Javadoc
1   /*
2    * Copyright (c) 2002-2026 Gargoyle Software Inc.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    * https://www.apache.org/licenses/LICENSE-2.0
8    *
9    * Unless required by applicable law or agreed to in writing, software
10   * distributed under the License is distributed on an "AS IS" BASIS,
11   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12   * See the License for the specific language governing permissions and
13   * limitations under the License.
14   */
15  package org.htmlunit.javascript.host.dom;
16  
17  import static org.htmlunit.javascript.configuration.SupportedBrowser.FF;
18  import static org.htmlunit.javascript.configuration.SupportedBrowser.FF_ESR;
19  
20  import java.util.Arrays;
21  import java.util.List;
22  
23  import org.htmlunit.javascript.HtmlUnitScriptable;
24  import org.htmlunit.javascript.JavaScriptEngine;
25  import org.htmlunit.javascript.configuration.JsxClass;
26  import org.htmlunit.javascript.configuration.JsxConstant;
27  import org.htmlunit.javascript.configuration.JsxConstructor;
28  import org.htmlunit.javascript.configuration.JsxGetter;
29  
30  /**
31   * Exception for DOM manipulations.
32   *
33   * @see <a href="https://developer.mozilla.org/en-US/docs/Web/API/DOMException">MDN Documentation</a>
34   * @see <a href="http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html#ID-17189187">
35   *     DOM-Level-2-Core</a>
36   * @author Marc Guillemot
37   * @author Frank Danek
38   * @author Ahmed Ashour
39   * @author Ronald Brill
40   */
41  @JsxClass
42  public class DOMException extends HtmlUnitScriptable {
43  
44      /** If the specified range of text does not fit into a DOMString. */
45      @JsxConstant
46      public static final int DOMSTRING_SIZE_ERR = org.w3c.dom.DOMException.DOMSTRING_SIZE_ERR;
47  
48      /** If any node is inserted somewhere it doesn't belong. */
49      @JsxConstant
50      public static final int HIERARCHY_REQUEST_ERR = org.w3c.dom.DOMException.HIERARCHY_REQUEST_ERR;
51  
52      /** If index or size is negative, or greater than the allowed value. */
53      @JsxConstant
54      public static final int INDEX_SIZE_ERR = org.w3c.dom.DOMException.INDEX_SIZE_ERR;
55  
56      /** If an attempt is made to add an attribute that is already in use elsewhere. */
57      @JsxConstant
58      public static final int INUSE_ATTRIBUTE_ERR = org.w3c.dom.DOMException.INUSE_ATTRIBUTE_ERR;
59  
60      /** If a parameter or an operation is not supported by the underlying object. */
61      @JsxConstant
62      public static final int INVALID_ACCESS_ERR = org.w3c.dom.DOMException.INVALID_ACCESS_ERR;
63  
64      /** If an invalid or illegal character is specified, such as in a name. */
65      @JsxConstant
66      public static final int INVALID_CHARACTER_ERR = org.w3c.dom.DOMException.INVALID_CHARACTER_ERR;
67  
68      /** If an attempt is made to modify the type of the underlying object. */
69      @JsxConstant
70      public static final int INVALID_MODIFICATION_ERR = org.w3c.dom.DOMException.INVALID_MODIFICATION_ERR;
71  
72      /** If an attempt is made to use an object that is not, or is no longer, usable. */
73      @JsxConstant
74      public static final int INVALID_STATE_ERR = org.w3c.dom.DOMException.INVALID_STATE_ERR;
75  
76      /** If an attempt is made to create or change an object in a way which is incorrect with regard to namespaces. */
77      @JsxConstant
78      public static final int NAMESPACE_ERR = org.w3c.dom.DOMException.NAMESPACE_ERR;
79  
80      /** If data is specified for a node which does not support data. */
81      @JsxConstant
82      public static final int NO_DATA_ALLOWED_ERR = org.w3c.dom.DOMException.NO_DATA_ALLOWED_ERR;
83  
84      /** If an attempt is made to modify an object where modifications are not allowed. */
85      @JsxConstant
86      public static final int NO_MODIFICATION_ALLOWED_ERR = org.w3c.dom.DOMException.NO_MODIFICATION_ALLOWED_ERR;
87  
88      /** If an attempt is made to reference a node in a context where it does not exist. */
89      @JsxConstant
90      public static final int NOT_FOUND_ERR = org.w3c.dom.DOMException.NOT_FOUND_ERR;
91  
92      /** If the implementation does not support the requested type of object or operation. */
93      @JsxConstant
94      public static final int NOT_SUPPORTED_ERR = org.w3c.dom.DOMException.NOT_SUPPORTED_ERR;
95  
96      /** If an invalid or illegal string is specified. */
97      @JsxConstant
98      public static final int SYNTAX_ERR = org.w3c.dom.DOMException.SYNTAX_ERR;
99  
100     /** If a node is used in a different document than the one that created it (that doesn't support it). */
101     @JsxConstant
102     public static final int WRONG_DOCUMENT_ERR = org.w3c.dom.DOMException.WRONG_DOCUMENT_ERR;
103 
104     /** If a call to a method would make the {@code Node} invalid with respect to "partial validity". */
105     @JsxConstant
106     public static final int VALIDATION_ERR = org.w3c.dom.DOMException.VALIDATION_ERR;
107 
108     /** If the type of object is incompatible with the expected type of the parameter. */
109     @JsxConstant
110     public static final int TYPE_MISMATCH_ERR = org.w3c.dom.DOMException.TYPE_MISMATCH_ERR;
111 
112     /** Security error. */
113     @JsxConstant
114     public static final int SECURITY_ERR = 18;
115 
116     /** Network error. */
117     @JsxConstant
118     public static final int NETWORK_ERR = 19;
119 
120     /** Abort error. */
121     @JsxConstant
122     public static final int ABORT_ERR = 20;
123 
124     /** URL mismatch error. */
125     @JsxConstant
126     public static final int URL_MISMATCH_ERR = 21;
127 
128     /** Quota exceeded error. */
129     @JsxConstant
130     public static final int QUOTA_EXCEEDED_ERR = 22;
131 
132     /** Timeout error. */
133     @JsxConstant
134     public static final int TIMEOUT_ERR = 23;
135 
136     /** Invalid node type error. */
137     @JsxConstant
138     public static final int INVALID_NODE_TYPE_ERR = 24;
139 
140     /** Data clone error. */
141     @JsxConstant
142     public static final int DATA_CLONE_ERR = 25;
143 
144     // The following ids are HtmlUnit internal. The names have no legacy code,
145     // so they are not exposed to JavaScript and the code property returns 0.
146 
147     /** Encoding error. */
148     public static final int ENCODING_ERR = 26;
149 
150     /** Not readable error. */
151     public static final int NOT_READABLE_ERR = 27;
152 
153     /** Unknown error. */
154     public static final int UNKNOWN_ERR = 28;
155 
156     /** Constraint error. */
157     public static final int CONSTRAINT_ERR = 29;
158 
159     /** Data error. */
160     public static final int DATA_ERR = 30;
161 
162     /** Transaction inactive error. */
163     public static final int TRANSACTION_INACTIVE_ERR = 31;
164 
165     /** Read only error. */
166     public static final int READ_ONLY_ERR = 32;
167 
168     /** Version error. */
169     public static final int VERSION_ERR = 33;
170 
171     /** Operation error. */
172     public static final int OPERATION_ERR = 34;
173 
174     /** Not allowed error. */
175     public static final int NOT_ALLOWED_ERR = 35;
176 
177     /** Opt out error. */
178     public static final int OPT_OUT_ERR = 36;
179 
180     private static final List<String> COMMON_ERROR_NAMES = Arrays.asList(
181         "IndexSizeError",
182         "DOMStringSizeError",
183         "HierarchyRequestError",
184         "WrongDocumentError",
185         "InvalidCharacterError",
186         "NoDataAllowedError",
187         "NoModificationAllowedError",
188         "NotFoundError",
189         "NotSupportedError",
190         "InUseAttributeError",
191         "InvalidStateError",
192         "SyntaxError",
193         "InvalidModificationError",
194         "NamespaceError",
195         "InvalidAccessError",
196         "ValidationError",
197         "TypeMismatchError",
198         "SecurityError",
199         "NetworkError",
200         "AbortError",
201         "URLMismatchError",
202         "QuotaExceededError",
203         "TimeoutError",
204         "InvalidNodeTypeError",
205         "DataCloneError",
206         "EncodingError",
207         "NotReadableError",
208         "UnknownError",
209         "ConstraintError",
210         "DataError",
211         "TransactionInactiveError",
212         "ReadOnlyError",
213         "VersionError",
214         "OperationError",
215         "NotAllowedError",
216         "OptOutError");
217 
218     private int code_;
219     private String name_;
220     private String message_;
221     private int lineNumber_;
222     private String fileName_;
223 
224     /**
225      * Default constructor used to build the prototype.
226      */
227     public DOMException() {
228         super();
229     }
230 
231     /**
232      * Constructor.
233      * @param message the exception message
234      * @param error the error code (one of the constants from the class)
235      */
236     public DOMException(final String message, final int error) {
237         message_ = message;
238         code_ = toLegacyCode(error);
239         name_ = COMMON_ERROR_NAMES.get(error - 1);
240     }
241 
242     /**
243      * JavaScript constructor.
244      * @param message a description of the exception. If not present, the empty string '' is used
245      * @param error If the specified name is a standard error name,
246      *        then getting the code property of the DOMException object will return the
247      *        code number corresponding to the specified name.
248      *        If not present, the string 'Error' is used.
249      */
250     @JsxConstructor
251     public void jsConstructor(final String message, final Object error) {
252         message_ = message;
253 
254         if (error == null) {
255             code_ = 0;
256             name_ = null;
257             return;
258         }
259 
260         if (JavaScriptEngine.isUndefined(error)) {
261             code_ = 0;
262             name_ = "Error";
263             return;
264         }
265 
266         name_ = JavaScriptEngine.toString(error);
267 
268         final int idx = COMMON_ERROR_NAMES.indexOf(name_);
269         if (idx != -1) {
270             code_ = toLegacyCode(idx + 1);
271             return;
272         }
273 
274         code_ = 0;
275     }
276 
277     private static int toLegacyCode(final int error) {
278         return error > DATA_CLONE_ERR ? 0 : error;
279     }
280 
281     /**
282      * Gets the exception code.
283      * @return the exception code
284      */
285     @JsxGetter
286     public Object getCode() {
287         if (code_ == -1) {
288             return JavaScriptEngine.UNDEFINED;
289         }
290         return code_;
291     }
292 
293     /**
294      * Gets the exception name.
295      * @return the exception name
296      */
297     @JsxGetter
298     public String getName() {
299         return name_;
300     }
301 
302     /**
303      * Gets the exception message.
304      * @return the exception message
305      */
306     @JsxGetter
307     public Object getMessage() {
308         if (message_ == null) {
309             return JavaScriptEngine.UNDEFINED;
310         }
311         return message_;
312     }
313 
314     /**
315      * Gets the line at which the exception occurred.
316      * @return the line of the exception
317      */
318     @JsxGetter({FF, FF_ESR})
319     public Object getLineNumber() {
320         if (lineNumber_ == -1) {
321             return JavaScriptEngine.UNDEFINED;
322         }
323         return lineNumber_;
324     }
325 
326     /**
327      * Gets the name of the file in which the exception occurred.
328      * @return the name of the source file
329      */
330     @JsxGetter({FF, FF_ESR})
331     public Object getFilename() {
332         if (fileName_ == null) {
333             return JavaScriptEngine.UNDEFINED;
334         }
335         return fileName_;
336     }
337 
338     /**
339      * Sets the location in JavaScript source where this exception occurred.
340      * @param fileName the name of the source file
341      * @param lineNumber the line number
342      */
343     public void setLocation(final String fileName, final int lineNumber) {
344         fileName_ = fileName;
345         lineNumber_ = lineNumber;
346     }
347 }