diff --git a/index.bs b/index.bs index 437ba2155..782cc867e 100644 --- a/index.bs +++ b/index.bs @@ -5069,21 +5069,23 @@ No [=extended attributes=] are applicable to dictionaries.

Exceptions

-An exception is a type of object that -represents an error and which can be thrown or treated as a first -class value by implementations. Web IDL does not allow exceptions -to be defined, but instead has a number of pre-defined exceptions -that specifications can reference and throw in their definition of -operations, attributes, and so on. Exceptions have an -error name, -a {{DOMString}}, -which is the type of error the exception represents, and a -message, which is an optional, -user agent-defined value that provides human readable details of the error. - -There are two kinds of exceptions available to be thrown from specifications. -The first is a simple exception, which -is identified by one of the following types: +An exception is a type of object that represents an error and +which can be thrown or treated as a first class value by implementations. Web IDL has a number of +pre-defined exceptions that specifications can reference and throw in their definition of +operations, attributes, and so on. Custom exception types can also be defined, as [=interfaces=] +that [=interface/inherit=] from {{DOMException}}. + +In addition to their type, which is either one of the [=simple exceptions=], {{DOMException}}, or a +derived interface of {{DOMException}}, all exceptions have a +message, which is an +[=implementation-defined=] [=string=] that provides human readable details of the error. +{{DOMException}} instances also have an +error name [=string=], which +provides a general category for the exception. {{DOMException}} derived interfaces will +have other properties, as defined in their specifications. + +A simple exception is identified by one of the +following types: * EvalError * RangeError @@ -5091,74 +5093,101 @@ is identified by one of the following types: * TypeError * URIError -These correspond to all of the ECMAScript [=ECMAScript/error objects=] -(apart from {{ECMAScript/SyntaxError}} and {{ECMAScript/Error}}, -which are deliberately omitted as they are reserved for use -by the ECMAScript parser and by authors, respectively). -The meaning of each [=simple exception=] matches -its corresponding error object in the -ECMAScript specification. - -The second kind of exception is a {{DOMException}}, -which is an exception that encapsulates a name and an optional integer code, -for compatibility with historically defined exceptions in the DOM. - -For [=simple exceptions=], the [=error name=] is the type of the exception. -For a {{DOMException}}, the [=error name=] must be one of the names -listed in the [=error names table=] below. -The table also indicates the {{DOMException}}'s integer code for that error name, -if it has one. - -Note: As {{DOMException}} is an [=interface type=], it can be used as a type in IDL. -This allows for example an [=operation=] -to be declared to have a {{DOMException}} -[=return type=]. - -[=Simple exceptions=] can be created -by providing their [=error name=]. -A {{DOMException}} can be [=created=] -by providing its [=error name=] followed by {{DOMException}}. -Exceptions can also be thrown, by providing the -same details required to [=created|create=] one. +These correspond to all of the ECMAScript [=ECMAScript/error objects=] (apart from +{{ECMAScript/SyntaxError}} and {{ECMAScript/Error}}, which are deliberately omitted as they are +reserved for use by the ECMAScript parser and by authors, respectively). The meaning of each +[=simple exception=] matches its corresponding error object in the ECMAScript specification. -The resulting behavior from creating and throwing an exception is language binding-specific. +The second kind of exception is a {{DOMException}}, which provides further +programmatically-introspectable detail on the error that occurred by giving an [=exception/error +name=]. Such [=exception/error names=] are drawn from the [=error names table=] below. + +

As {{DOMException}} is an [=interface type=], it can be used as a type in IDL. This +allows for example an [=operation=] to be declared to have a {{DOMException}} [=return type=]. This +is generally a bad pattern, however, as exceptions are meant to be thrown and not returned. -Note: See [[#es-creating-throwing-exceptions]] for details on what creating and throwing an exception -entails in the ECMAScript language binding. +The final kind of exception is a derived interface of {{DOMException}}. These are more complicated, +and thus described in the dedicated section [[#idl-DOMException-derived-interfaces]]. -

+[=Simple exceptions=] can be +created by providing their +type name. A {{DOMException}} can be [=exception/created=] by providing its [=error name=] followed +by {{DOMException}}. Exceptions can also be +thrown, by providing the same details +required to [=exception/create=] one. In both cases, the caller may provide additional information +about what the exception indicates, which is useful when constructing the exception's +[=exception/message=]. - Here is are some examples of wording to use to create and throw exceptions. - To throw a new [=simple exception=] named {{TypeError}}: +
+

Here is are some examples of wording to use to create and throw exceptions. + To throw a new [=simple exception=] whose type is {{TypeError}}:

- [=exception/Throw=] a {{TypeError}}. +

[=exception/Throw=] a {{TypeError}}.

- To throw a new {{DOMException}} with [=error name=] "{{NotAllowedError!!exception}}": +

To throw a new {{DOMException}} with [=error name=] "{{NotAllowedError}}":

- [=exception/Throw=] a "{{NotAllowedError!!exception}}" {{DOMException}}. +

[=exception/Throw=] an "{{NotAllowedError}}" {{DOMException}}.

- To create a new {{DOMException}} with [=error name=] "{{SyntaxError!!exception}}": +

To create a new {{DOMException}} with [=error name=] "{{SyntaxError}}":

- Let object be a newly [=created=] "{{SyntaxError!!exception}}" {{DOMException}}. +

Let object be a newly [=exception/created=] "{{SyntaxError}}" + {{DOMException}}. +

+ +

To [=reject=] a promise with a new {{DOMException}} with [=error name=] "{{OperationError}}": + +

+ [=Reject=] p with an "{{OperationError}}" {{DOMException}}.
+
+

An example of including additional information used to construct the [=exception/message=] + would be: -

Error names

+
+ [=exception/Throw=] a "{{SyntaxError}}" {{DOMException}} indicating that the given value + had disallowed trailing spaces. +
-The error names table below lists all the allowed error names -for {{DOMException}}, a description, and legacy code values. +

Such additional context is most helpful to implementers when it is not immediately obvious + why the exception is being thrown, e.g., because there are many different steps in the algorithm + which throw a "{{SyntaxError}}" {{DOMException}}. In contrast, if your specification throws a + "{{NotAllowedError}}" {{DOMException}} immediately after checking if the user has provided + permission to use a given feature, it's fairly obvious what sort of [=exception/message=] the + implementation should construct, and so specifying it is not necessary. +

-

- The {{DOMException}} names marked as deprecated are kept for legacy purposes but their usage is discouraged. -

+The resulting behavior from creating and throwing an exception is language binding-specific. + +

See [[#es-creating-throwing-exceptions]] for details on what creating and throwing an +exception entails in the ECMAScript language binding. + + +

Base {{DOMException}} error names

+ +The error names table below lists all the allowed error +names for instances of the base {{DOMException}} interface, along with a description of what such +error names mean, and legacy numeric error code values. + +

Interfaces [=interface/inheriting=] from {{DOMException}}, in the manner described +in [[#idl-DOMException-derived-interfaces]], will have their own names, not listed in this table. -Note: If an error name is not listed here, please file a bug as indicated at the top of this specification and it will be addressed shortly. Thanks! +When [=exception/creating=] or [=exception/throwing=] a {{DOMException}}, specifications must use +one of these names. If a specification author believes none of these names are a good fit for their +case, they must +file an issue +to discuss adding a new name to the shared namespace, so that the community can coordinate such +efforts. Note that adding new use-case-specific names is only important if you believe web +developers will discriminate multiple error conditions arising from a single API. + +

The {{DOMException}} names marked as deprecated are kept for legacy purposes, but +their usage is discouraged. Note: Don't confuse the "{{SyntaxError!!exception}}" {{DOMException}} defined here with ECMAScript's {{ECMAScript/SyntaxError}}. @@ -5342,6 +5371,94 @@ over just using {{SyntaxError!!exception}} to refer to the {{DOMException}}. [[D +

{{DOMException}} derived interfaces

+ +When an exception needs to carry additional programmatically-introspectable information, beyond just +its [=error name=], specification authors can create an [=interface=] which [=interface/inherits=] +from {{DOMException}}. Such interfaces need to follow certain rules, in order to have a predictable +shape for developers. Specifically: + +* The [=identifier=] of the [=interface=] must end with Error, and must not be any + of the names in the [=error names table=]. +* The [=interface=] must have a [=constructor operation=] which sets the instance's + [=DOMException/name=] to the interface's [=identifier=]. +* Their [=constructor operation=] must take as its first parameter an [=optional=] {{DOMString}} + named |message| defaulting to the empty string, and must set the instance's + [=DOMException/message=] to |message|. +* Their [=constructor operation=] should take as its second parameter a [=dictionary=] containing + the additional information that needs to be exposed. +* They should have [=read only=] [=attributes=], whose names are the same as the members of the + constructor dictionary, which return the values accepted by the constructor operation. +* They should be [=serializable objects=], whose [=serialization steps=] and + [=deserialization steps=] preserve the additional information. + +

These requirements mean that the inherited {{DOMException/code}} property of these +interfaces will always return 0. + +

+ The definition for a {{DOMException}} derived interface which carries along an additional + "hardware error code", for interfacing with a hypothetical Widget hardware device, could look + something like this: + +
+        [Exposed=Window]
+        interface WidgetError : DOMException {
+          constructor(optional DOMString message = "", WidgetErrorOptions options);
+
+          readonly attribute unsigned long long hardwareErrorCode;
+        };
+
+        dictionary WidgetErrorOptions {
+            required [EnforceRange] unsigned long long hardwareErrorCode;
+        };
+    
+ + Every WidgetError instance has a hardware error code, + a number. + +
+ The new WidgetError(|message|, |options|) constructor steps are: + + 1. Set [=this=]'s [=DOMException/name=] to "WidgetError". + 1. Set [=this=]'s [=DOMException/message=] to |message|. + 1. Set [=this=]'s [=WidgetError/hardware error code=] to + |options|["hardwareErrorCode"]. +
+ +
+ The hardwareErrorCode getter steps are to return [=this=]'s + [=WidgetError/hardware error code=]. +
+ + WidgetError objects are [=serializable objects=]. + +
+ Their [=serialization steps=], given |value| and |serialized|, are: + + 1. Run the {{DOMException}} [=serialization steps=] given |value| and |serialized|. + 1. Set |serialized|.\[[HardwareErrorCode]] to |value|'s [=WidgetError/hardware error code=]. +
+ +
+ Their [=deserialization steps=], given |value| and |serialized|, are: + + 1. Run the {{DOMException}} [=deserialization steps=] given |value| and |serialized|. + 1. Set |value|'s [=WidgetError/hardware error code=] to |serialized|.\[[HardwareErrorCode]]. +
+
+ +To [=exception/create=] or [=exception/throw=] a {{DOMException}} derived interface, supply its +[=interface=] [=identifier=] as well as the additional information needed to construct it. + +
+

To throw an instance of the WidgetError exemplified + above: + +

+

[=exception/Throw=] a WidgetError whose [=WidgetError/hardware error code=] + is 42. +

+

Enumerations

@@ -14367,39 +14484,61 @@ A {{DOMException}} is represented by a

Creating and throwing exceptions

-
+
+ To create a [=simple exception=] of type |T|: - To create a [=simple exception=] or {{DOMException}} |E|, with a string giving the - [=error name=] |N| for the {{DOMException}} case and optionally a string giving a user - agent-defined message |M|: + 1. Let |message| be an [=implementation-defined=] message appropriate for the exceptional + situation. The calling specification may contain information to to help implementations + construct this message. - 1. If |M| was not specified, let |M| be undefined. - 1. Let |args| be a list of ECMAScript values determined based on the type of |E|: -
- : |E| is {{DOMException}} - :: |args| is «|M|, |N|». - : |E| is a [=simple exception=] - :: |args| is «|M|». -
- 1. Let |X| be an object determined based on the type of |E|: -
- : |E| is {{DOMException}} - :: |X| is the {{DOMException}} [=interface object=] - from the [=current realm=]. - : |E| is a [=simple exception=] - :: |X| is the [=constructor=] for the corresponding ECMAScript error - from the [=current realm=]. -
- 1. Return [=!=] Construct(|X|, |args|). + Implementations need to be cautious not to leak sensitive or secured information when + constructing this message, e.g., by including the [=Document/URL=] of a cross-origin frame, + or information which could identify the user. + + 1. Let |args| be « |message| ». + + 1. Let |constructor| be [=current realm=].\[[Intrinsics]].[[%|T|%]]. + + 1. Return [=!=] [$Construct$](|constructor|, |args|).
-
+
+ To create a {{DOMException}} given [=error name=] |name|: + + 1. Let |ex| be a [=new=] {{DOMException}} created in the [=current realm=]. + + 1. Set |ex|'s [=DOMException/name=] to |name|. + + 1. Set |ex|'s [=DOMException/message=] to an [=implementation-defined=] message appropriate for + the exceptional situation. The calling specification may contain information to to help + implementations construct this message. + + 1. Return |ex|. +
- To [=exception/throw=] a [=simple exception=] or {{DOMException}}, with a string giving the - [=error name=] for the {{DOMException}} case and optionally a string giving a user - agent-defined message: +
+ To create a {{DOMException}} derived interface given the [=interface=] [=identifier=] |type| + and additional initialization instructions: + + 1. Let |ex| be a [=new=] instance of the [=interface=] identified by |type|, created in the + [=current realm=]. + + 1. Set |ex|'s [=DOMException/name=] to |type|. + + 1. Set |ex|'s [=DOMException/message=] to an [=implementation-defined=] message appropriate for + the exceptional situation. The calling specification may contain information to to help + implementations construct this message. + + 1. Initialize |ex|'s additionally as described by the caller. + + 1. Return |ex|. +
+ +
+ To [=exception/throw=] an [=exception=]: - 1. Let |O| be the result of [=created|creating an exception=] with the same arguments. + 1. Let |O| be the result of [=exception/create|creating an exception=] with the same + arguments. 1. Throw |O|.