The Nashorn Javascript engine (part of Java 8) reports some exceptions, esp. regarding method binding errors like arity or type mismatches, as a NativeTypeError-instance, which does not have a cause relation to get any exception and is therefore very opaque to me (I'd like to report as much as possible back to the script user).
Is there a documented method to get root causes or further information from a NativeTypeError-instance?
ECMAScript standard only defines name and message properties on Error objects like TypeError, ReferenceError etc.
Nashorn defines certain extension properties such as "lineNumber", "columnNumber", "fileName" (for the source where exception was thrown from) and "stack" to access stack trace. Also "printStackTrace", "getStackTrace" functions are supported via Error.prototype extensions.
See also:
https://wiki.openjdk.java.net/display/Nashorn/Nashorn+extensions#Nashornextensions-ExtensionsofErrorobjects,Error.prototypeandErrorconstructor
Answering my own question: the semantics of NativeTypeError are described in the ECMAScript standard (ECMA-262, sec. 15.11.7). Instances of NativeTypeError expose a public field message, which is of type Object, but is most likely a String for all circumstances I've encountered it.
Related
In an Error, the property stack is optional. However, when I throw a new Error('myError') or when I have a generic error thrown during the execution of my script, I always get the stack. According to the browser, the stack is not the same but I is not undefined.
I was wondering in which case it was possible to have an undefined stack?
The stack property is not defined by the JavaScript specification (yet). So a compliant JavaScript implementation could well not have a stack property on Error instances. Most do nowadays (certainly the big three: V8, SpiderMonkey, and JavaSciptCore), but it's not standardized (yet), so they don't have to.
In an Error, the property stack is optional.
I'm guessing you're referring to TypeScript's type information for Error:
interface Error {
stack?: string | undefined;
}
Since most JavaScript engines do provide a stack property of type string even though it's not defined by the specification, making it optional with the type string | undefined is a pragmatic choice (the TypeScript project team are notoriously pragmatic). So rather than leave it out entirely, they acknowledge the common practice.
I was wondering in which case it was possible to have an undefined stack?
I think it's unlikely you'd have an undefined stack on an Error instance on implementations that support it (more likely "" if no stack information is available, but I don't recall seeing a blank stack). That said, there's likely a reason TYpeScript's types define it as stack?: string | undefined and not stack?: string.
const myError = new Error("bug");
myError.propertyIsEnumerable("message") //false
myError.propertyIsEnumerable("stack") //false
The implications of this are that when you for loop this kind of object, you won't fetch these fields, which I find strange.
What was the reasoning behind that?
The reason that I can think of is to maintain the behaviour of Object.keys. If you see the initial specs, the error part not very detailed. the error specs are
This specification specifies the last possible moment an error occurs. A given implementation may generate errors
sooner (e.g. at compile-time). Doing so may cause differences in behavior among implementations. Notably, if runtime
errors become catchable in future versions, a given error would not be catchable if an implementation generates the
error at compile-time rather than runtime.
An ECMAScript compiler should detect errors at compile time in all code presented to it, even code that detailed
analysis might prove to be “dead” (never executed). A programmer should not rely on the trick of placing code within
an if (false) statement, for example, to try to suppress compile-time error detection.
In general, if a compiler can prove that a construct cannot execute without error under any circumstances, then it may
issue a compile-time error even though the construct might neverbe executed at all.
You can see the first specs at https://www.ecma-international.org/publications/files/ECMA-ST-ARCH/ECMA-262,%201st%20edition,%20June%201997.pdf
Here, it reads, "Therefore, this interface can be obtained by using binding-specific casting methods on an instance of the Node interface."
What does it mean that the interface can be "obtained" by "using the binding-specific casting methods?"
What are "binding specific casting methods?"
I understand that the word "binding" here is referring to a language binding. And, that "casting methods" are specific to the binding. But, it still isn't clear to me what the sentence means.
Practically, I would like to create an instance of an Object that inherits from EventTarget.prototype, and call EventTarget.prototype's addEventListener on it.
I understand that that is not possible. It is discussed here. I think the reason it is not possible may be related to this question.
IDL language bindings.
The link in the post is to a DOM2 specification of an "EventTarget" interface, written in IDL ("Interface Definition Language"). As a definition language, IDL describes what must be provided in a an interface written in a real language such as JavaScript, Java, MicoSoft Visual Basic for applications, or C++ for example.
"this interface can be obtained by using binding-specific casting methods on an instance of the Node interface."
is a technical way of saying "use the methods and properties documented for the language you are using, on a DOM node, rather than the exact wording of the specification provided here. The most binding we are most familiar with in web pages is, of course, for JavaScript. "Casting methods" may refer to how the implementation would automatically perform conversions between programming language and the DOM as required - e.g. converting JavaScript numbers to and from integer representations in some DOM attributes.
EventTargetPrototype
In Firefox this in object in the prototype chain of DOM nodes containing addEventListener and associated functions. Again it Firefox you can access it as
Object.getPrototypeOf( Node.prototype))
and then create an object prototyped on it, using
Object.create(Object.getPrototypeOf( Node.prototype))
This didn't work for dispatching events however. It seems additional support ( perhaps the Node interface as well?) is required. Using a HTMLSpanElement for the target "node object" worked in Firefox for dispatching and listening to an event without adding it to the DOM:
let a = document.createElement("SPAN");
a.addEventListener( "custom", function() {console.log("wow");}, false);
a.dispatchEvent( new CustomEvent("custom"));
Would I use this in production code? Definitely not. Except if thousands had tested it before me, in every browser type I might wish to support!
Could the following code ever throw an error?
var canvas = document.createElement("canvas");
var ctx = canvas.getContext("somethingwrong");
In chromium, it does just return null.
How would it be if the the requested rendering context is known to a browser? (Like "webgl" or "experimental-webgl") Is there the possibility of an error exception? In chromium I could not provoke this behavior.
In other words: Do I need to wrap this code in a try/catch in a library that checks cleanly for a rendering context?
Is there maybe a way to objectify this? E.g. by a web service that tries a code snipped in different browsers and lists their possibly differing results.
Returning null is the expected behavior if the requested context is not available, or if the canvas has already been assigned to a different type of context:
Returns null if the given context ID is not supported, if the canvas
has already been initialized with the other context type (e.g. trying
to get a "2d" context after getting a "webgl" context).
There are special cases where an exception can be thrown related to proxy scenarios (ibid):
Throws an InvalidStateError exception if the setContext() or
transferControlToProxy() methods have been used.
In addition to that, even though a browser may support a certain type of context there is no guarantee that the object can be created if the system resources such as memory are low in which case null would be returned.
Here is an overview of what will be returned in different (common) scenarios.
So unless you are using proxy transfers (which is not exactly widely supported at this time) you do not need to use try-catch with getContext().
Tip: in the future canvas will get a property probablySupportsContext() which can be used before getContext(). This will do these tests and return false if conditions are not met (supported context, already in use with different context type, low resources etc.):
var supported = canvas . probablySupportsContext(contextId [, ... ] )
Returns false if calling getContext() with the same arguments would
definitely return null, and true otherwise.
Update Just wanted to elaborate on a special case - for vendor specific extensions it is in theory possible to get an exception thrown depending on that very specific extension and how it defines its behavior. But these are and should not be considered part of the standard and since they are experimental in most cases, a risk and non-standard behavior is implied.
What type of object should be thrown in JavaScript?
I see a lot of examples which throw a plain old string and there seems to be a semi-standard Error type. Should I prefer one over the other?
The Error object and specific error objects such as TypeError are fully standardized in the ECMAScript specification. There are, however, common non-standard properties of these objects available in most browsers.
You can throw whatever you like, so long as your error handling code knows what to do with the objects you throw, but there are advantages to using Error objects:
Consistency with handling errors thrown by native code, such as having a message property, so you don't have to write different code to handle native errors and your own errors;
Error objects in Mozilla and other browsers have very useful non-standard properties, such as fileName, lineNumber and stack. You only get these on Error objects and they can be very useful for debugging.