Is it possible to manually throw a DOMException error in pure JavaScript? Documentation I've read suggests it should be relatively easy to construct (at least in Java.)
However, in Chrome, following code returns TypeError: Illegal constructor
:
// DOM SYNTAX_ERR (12)
var myDOMException = new DOMException(12,"I'm sorry Dave, I'm afraid I can't do that.");
Regrettably, this is what I expected after reading the W3 docs, which don't appear to specify a constructor at all. (As an aside, while I'm not particularly 'au fait' with IDL, I would have assumed their variant would support specification of constructors.)
Frustratingly, the DOMException class lurks tantalisingly in the global scope. How can I use it? Can I use it?
Update
Since I wrote this, I've made a couple of discoveries - namely:
var myDOMException = DOMException.constructor(12,"Error Message");
var myDOMException2 = DOMException.constructor.call(DOMException,DOMException.SYNTAX_ERR,"Error Message");
Looks like it worked!
...not so fast.
$> myDOMException instanceof DOMException
false
$> myDOMException2 instanceof DOMException
false
And possibly even more offputting:
$> myDOMException.constructor
function Number() {
[native code]
}
As always, any assistance would be greatly appreciated.
Update #2
Just to clarify my reasons for returning a DOMException object as opposed to a more generic Error - I'm trying to implement the WHATWG's Timed Text Track spec in pure JavaScript. There are a number of instances where a proper solution would be required to return a DOMException object, specifically one with a code of 12 (SYNTAX_ERR.)
Is it possible to manually throw a DOMException error in pure JavaScript? Documentation I've read suggests it should be relatively easy to construct (at least in Java.)
However, in Chrome, following code returns TypeError: Illegal constructor
:
// DOM SYNTAX_ERR (12)
var myDOMException = new DOMException(12,"I'm sorry Dave, I'm afraid I can't do that.");
Regrettably, this is what I expected after reading the W3 docs, which don't appear to specify a constructor at all. (As an aside, while I'm not particularly 'au fait' with IDL, I would have assumed their variant would support specification of constructors.)
Frustratingly, the DOMException class lurks tantalisingly in the global scope. How can I use it? Can I use it?
Update
Since I wrote this, I've made a couple of discoveries - namely:
var myDOMException = DOMException.constructor(12,"Error Message");
var myDOMException2 = DOMException.constructor.call(DOMException,DOMException.SYNTAX_ERR,"Error Message");
Looks like it worked!
...not so fast.
$> myDOMException instanceof DOMException
false
$> myDOMException2 instanceof DOMException
false
And possibly even more offputting:
$> myDOMException.constructor
function Number() {
[native code]
}
As always, any assistance would be greatly appreciated.
Update #2
Just to clarify my reasons for returning a DOMException object as opposed to a more generic Error - I'm trying to implement the WHATWG's Timed Text Track spec in pure JavaScript. There are a number of instances where a proper solution would be required to return a DOMException object, specifically one with a code of 12 (SYNTAX_ERR.)
Share Improve this question edited Feb 27, 2011 at 23:55 Christopher asked Feb 27, 2011 at 23:09 ChristopherChristopher 5344 silver badges11 bronze badges 7- 4 Java and JavaScript are like car and carpet (to quote this answer). So that documentation is irrelevant. – Matthew Flaschen Commented Feb 27, 2011 at 23:14
- I was more interested in it as a DOM implementation, not as a 'similar to JavaScript' language, which I'm well aware it's not (name aside.) – Christopher Commented Feb 27, 2011 at 23:21
- If you would elaborate on why you want to be able to throw such a thing, you might get some interesting suggestions. – Pointy Commented Feb 27, 2011 at 23:27
- @Pointy Thanks - see my revised question above. – Christopher Commented Feb 27, 2011 at 23:37
- Internal objects do lots of weird things and break tons of rules. The reason calling DOMException.constructor works is because the proto for a DOMException isn't a function as normal constructors are, it's an object, even though the object signature is a function (don't ask me why). Also, normally, the constructor property will always be functions, because anything you instantiate is a function. The place you want to find the proper constructor for an object is within prototype.constructor, which will almost always point back at the object that contains the prototype, unless you override it. – TimE Commented Dec 4, 2012 at 11:47
3 Answers
Reset to default 12In Firefox, at least, DOMException
is not a function. It is an object that defines several constants.
typeof DOMException === 'object' // true (not 'function')
It could be used like this:
try {
throw DOMException;
} catch(e) {
if (e === DOMException)
console.log("caught DOMException")
}
This works if you're trying to signal a DOMException
but don't need an actual instance of DOMException
.
Ugly, ugly hack (that basically works)
If you absolutely need an instance of DOMException
that has the SYNTAX_ERR
code, you could perform an action that causes one to be created and throw
that:
function createSyntaxException() {
try {
// will cause a DOMException
document.querySelectorAll("div:foo");
} catch(e) {
return e;
}
}
throw createSyntaxException();
The details of the thrown exception won't match your specific situation, of course, but the resulting object will have the correct code and pass instanceof
checks.
var e = createSyntaxException();
console.log(e instanceof DOMException); // true
console.log(e.code === e.SYNTAX_ERR); // true
You could mitigate the details issue by subclassing DOMException
and adding getters/setters for each of its (read-only) properties.
function DOMExceptionCustom() {
var message;
this.__defineGetter__("message", function(){
return message;
});
this.__defineSetter__("message", function(val){
message = val;
});
}
// subclass DOMException
DOMExceptionCustom.prototype = createSyntaxException();
var err = new DOMExceptionCustom();
err.message = "my custom message";
The resulting object has the desired properties:
console.log(err.code === err.SYNTAX_ERR); // true
console.log(err.message); // "my custom message"
console.log(err instanceof DOMExceptionCustom); // true
console.log(err instanceof DOMException); // true
Here is my crack at it. Solution based on ECMAScript 5 and WebIDL. I've discussed this with the W3C/ECMAScript join task force that are working on WebIDL. They said it's basically impossible to do because it relies on internal platform behaviour... but here is something that may be close enough.
function CustomDOMException(code, message) {
//throw on missing code
if (typeof code !== "number") {
throw TypeError("Wrong argument");
}
//we need the codes, to get the "name" property.
var consts = {
1: "INDEX_SIZE_ERR",
3: "HIERARCHY_REQUEST_ERR",
4: "WRONG_DOCUMENT_ERR",
5: "INVALID_CHARACTER_ERR",
7: "NO_MODIFICATION_ALLOWED_ERR",
8: "NOT_FOUND_ERR",
9: "NOT_SUPPORTED_ERR",
11: "INVALID_STATE_ERR",
12: "SYNTAX_ERR",
13: "INVALID_MODIFICATION_ERR",
14: "NAMESPACE_ERR",
15: "INVALID_ACCESS_ERR",
17: "TYPE_MISMATCH_ERR",
18: "SECURITY_ERR",
19: "NETWORK_ERR",
20: "ABORT_ERR",
21: "URL_MISMATCH_ERR",
22: "QUOTA_EXCEEDED_ERR",
23: "TIMEOUT_ERR",
24: "INVALID_NODE_TYPE_ERR",
25: "DATA_CLONE_ERR"
}
if ((code in consts) === false) {
throw TypeError("Unknown exception code: " + code);
}
//props for adding properties
var props = {};
//generate an exception object
var newException;
try {
//force an exception to be generated;
document.removeChild({})
} catch (e) {
//use it as the prototype
newException = Object.create(Object.getPrototypeOf(e));
}
//get the name of the exception type
var name = consts[code];
//add the properties
var props = {value: null, writable: true, enumerable: false, Configurable: true};
//name
props.value = name;
Object.defineProperty(newException, "name", props);
props.value = code;
Object.defineProperty(newException, "code", props);
props.value = message;
Object.defineProperty(newException, "message", props);
//Make sure it "stringifies" properly
var finalMessage;
var obj = this;
if (typeof message === "function") {
finalMessage = function() {
return message.call(newException)
}
} else {
finalMessage = function() {
return name + ": DOM Exception " + code;
}
}
props.value = function() {
return finalMessage.call(newException)
}
Object.defineProperty(newException, "toString", props);
return newException;
}
And some tests:
// Throws SYNTAX_ERR
console.log(new CustomDOMException(12));
// Custom message
console.log(new CustomDOMException(1, "ERROR!"));
// Custom message
console.log(new CustomDOMException(1, function() {
return "Custom Err:" + this.name + " : " + Date.now()
}));
// Throws TypeError
try {
new CustomDOMException(2)
} catch (e) {
console.log(e);
}
// Throws TypeError
try {
new CustomDOMException()
} catch (e) {
console.log(e);
}
// Throws TypeError
try {
new CustomDOMException("Wee!")
} catch (e) {
console.log(e);
}
//Check the inheritance chain
var ext = new CustomDOMException(17);
var isInstance = ext instanceof DOMException;
console.log("instanceof DOMException: " + isInstance)
Although it is an old question,
I have found out the correct way to do it. So I share it here.
error.code
is meaningful but cannot be used for error construction.error.code
will automatically match theerror.name
e.g.TimeoutError
,AbortError
,TypeError
, etc.
As you want to error to have the error.code = DOMException.SYNTAX_ERR (12)
, you can use document.querySelector('a::b')
to create that error and find out its error name.
Then you can have
throw new DOMException("I'm sorry Dave, I'm afraid I can't do that.", "SyntaxError")
You can also change DOMException
to MyOwnError
.
class MyOwnError extends DOMException{
constructor(msg){
super(msg, 'SyntaxError');
}
}
throw new MyOwnError("I'm sorry Dave, I'm afraid I can't do that.", "SyntaxError")
class MyOwnError extends DOMException {
constructor(msg) {
super(msg, 'SyntaxError');
}
}
const err = new MyOwnError("Oops...")
console.log(err.code === err.SYNTAX_ERR); // true
console.log(err.message); // "my custom message"
console.log(err instanceof MyOwnError); // true
console.log(err instanceof DOMException); // true
throw err