javascriptdom

Manually/Artificially throwing a DOMException with JavaScript


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.)


Solution

  • In 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