Details may vary depending on the browser, but the idea is the same: any information about the internals of a script, including error stack traces, is hidden. Exactly because it’s from another domain.
Why do we need error details?
There are many services (and we can build our own) that listen for global errors using
window.onerror
, save errors and provide an interface to access and analyze them. That’s great, as we can see real errors, triggered by our users. But if a script comes from another origin, then there’s not much information about errors in it, as we’ve just seen.
Similar cross-origin policy (CORS) is enforced for other types of resources as well.
To allow cross-origin access, the
<script>
tag needs to have the
crossorigin
attribute, plus the remote server must provide special headers.
There are three levels of cross-origin access:
No
crossorigin
attribute
– access prohibited.
crossorigin="anonymous"
– access allowed if the server responds with the header
Access-Control-Allow-Origin
with
*
or our origin. Browser does not send authorization information and cookies to remote server.
crossorigin="use-credentials"
– access allowed if the server sends back the header
Access-Control-Allow-Origin
with our origin and
Access-Control-Allow-Credentials: true
. Browser sends authorization information and cookies to remote server.
You can read more about cross-origin access in the chapter
CORS
. It describes the
fetch
method for network requests, but the policy is exactly the same.
Such thing as “cookies” is out of our current scope, but you can read about them in the chapter
쿠키와 document.cookie
.
In our case, we didn’t have any crossorigin attribute. So the cross-origin access was prohibited. Let’s add it.
We can choose between
"anonymous"
(no cookies sent, one server-side header needed) and
"use-credentials"
(sends cookies too, two server-side headers needed).
If we don’t care about cookies, then
"anonymous"
is the way to go:
<script>
window.onerror = function(message, url, line, col, errorObj) {
alert(`${message}\n${url}, ${line}:${col}`);
</script>
<script crossorigin="anonymous" src="https://cors.javascript.info/article/onload-onerror/crossorigin/error.js"></script>
Now, assuming that the server provides an
Access-Control-Allow-Origin
header, everything’s fine. We have the full error report.
Images
<img>
, external styles, scripts and other resources provide
load
and
error
events to track their loading:
load
triggers on a successful load,
error
triggers on a failed load.
The only exception is
<iframe>
: for historical reasons it always triggers
load
, for any load completion, even if the page is not found.
The
readystatechange
event also works for resources, but is rarely used, because
load/error
events are simpler.