Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .vscode/dictionaries/code-entities.txt
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ adlm
advertisementreceived
afrc
afterscriptexecute
aioquic
alaw
allowdirs
allowevents
Expand Down Expand Up @@ -950,6 +951,7 @@ workon
WORKON_HOME
writingsuggestions
wtai
wtransport
x-abiword
X-cept-Encoding
x-ms-aria-flowfrom
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ Returns the extension's version from the [`version`](/en-US/docs/Mozilla/Add-ons
## Syntax

```js-nolint
let extensionVersion = await browser.runtime.getVersion()
let extensionVersion = browser.runtime.getVersion()
```

### Parameters
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,7 @@ In addition to the standard DOM APIs, content scripts can use these WebExtension
- {{WebExtAPIRef("runtime.getDocumentId()","getDocumentId()")}}
- {{WebExtAPIRef("runtime.getFrameId()","getFrameId()")}}
- [`getManifest()`](/en-US/docs/Mozilla/Add-ons/WebExtensions/API/runtime/getManifest)
- {{WebExtAPIRef("runtime.getVersion()","getVersion()")}}
- [`getURL()`](/en-US/docs/Mozilla/Add-ons/WebExtensions/API/runtime/getURL)
- [`onConnect`](/en-US/docs/Mozilla/Add-ons/WebExtensions/API/runtime/onConnect)
- [`onMessage`](/en-US/docs/Mozilla/Add-ons/WebExtensions/API/runtime/onMessage)
Expand Down
2 changes: 2 additions & 0 deletions files/en-us/mozilla/firefox/releases/158/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,8 @@ Firefox 158 is the current [Nightly version of Firefox](https://www.firefox.com/

## Changes for add-on developers

- Adds [`runtime.getVersion()`](/en-US/docs/Mozilla/Add-ons/WebExtensions/API/runtime/getVersion) to return the extension's version as declared in the manifest. ([Firefox bug 1992418](https://bugzil.la/1992418))

<!-- ### Removals -->

<!-- ### Other -->
Expand Down
33 changes: 32 additions & 1 deletion files/en-us/web/api/htmlelement/load_event/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ browser-compat: api.HTMLElement.load_event

{{APIRef("HTML DOM")}}

The **`load`** event fires for elements containing a resource when the resource has successfully loaded. Currently, the list of supported HTML elements are: {{HTMLElement("body")}}, {{HTMLElement("embed")}}, {{HTMLElement("iframe")}}, {{HTMLElement("img")}}, {{HTMLElement("link")}}, {{HTMLElement("object")}}, {{HTMLElement("script")}}, {{HTMLElement("style")}}, and {{HTMLElement("track")}}.
The **`load`** event fires for elements containing a resource when the resource has successfully loaded. Currently, the list of supported HTML elements are: {{HTMLElement("embed")}}, {{HTMLElement("iframe")}}, {{HTMLElement("img")}}, {{HTMLElement("link")}}, {{HTMLElement("object")}}, {{HTMLElement("script")}}, {{HTMLElement("style")}}, and {{HTMLElement("track")}}.

> [!NOTE]
> The `load` event on {{domxref("HTMLBodyElement#event_handlers", "HTMLBodyElement")}} is actually an alias for the {{domxref("Window/load_event", "window.onload")}} event. Therefore, the `load` event will only fire on the `<body>` element once all of the document's resources have loaded or errored. However, for the sake of clarity, it is recommended that the event handler is attached to the `window` object directly rather than on `HTMLBodyElement`.
Expand All @@ -29,6 +29,35 @@ onload = (event) => { }

A generic {{domxref("Event")}}.

## Usage notes

### Handling resources that have already loaded

A resource may finish loading before your script registers a `load` event listener. In that case, the listener will not receive the event that has already fired.

For example, an image in the HTML may load while the browser is still receiving and parsing the rest of the document, before it reaches a subsequent script that registers the listener. The listener can also be registered too late if the script is loaded asynchronously or deferred, or if it waits for {{domxref("Document/DOMContentLoaded_event", "DOMContentLoaded")}} before registering the listener. Server-rendered HTML using frameworks such as React or Vue can have the same issue because event handlers written in JSX or templates are compiled into JavaScript calls, not HTML event handler attributes.

There are some ways to ensure that the event handler is registered as soon as possible, before the resource loads. For example, you can use an [HTML event handler attribute](/en-US/docs/Web/HTML/Reference/Attributes#event_handler_attributes) if you don't mind its undesirable aspects, or you can dynamically create the whole element in JavaScript and make sure the event listener is attached before starting the load (such as by assigning to `src` for images).

Alternatively, when registering the event handler, you can check if the resource has already loaded—and if so, immediately trigger the handler. For an image, you can check its {{domxref("HTMLImageElement.complete", "complete")}} and {{domxref("HTMLImageElement.naturalWidth", "naturalWidth")}} properties after registering the listener. `complete` checks that the request completed; `naturalWidth > 0` ensures that an actual image was loaded.

```js
const image = document.getElementById("image");
let handled = false;

function handleLoaded() {
if (handled) return;
handled = true;
// Use the loaded image here.
}

image.addEventListener("load", handleLoaded, { once: true });

if (image.complete && image.naturalWidth > 0) {
handleLoaded();
}
```

## Examples

This example prints to the screen whenever the {{HtmlElement("img")}} element successfully loads its resource.
Expand Down Expand Up @@ -62,6 +91,8 @@ function reload() {

### Result

The example's `<img>` element contains an `src` attribute in the markup, so the image may load before the `load` event listener attaches. Clicking "reload" is guaranteed to trigger the event listener.

{{EmbedLiveSample("Example", "100%", "200")}}

## Specifications
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,16 +22,59 @@ Service workers are enabled by default in all modern browsers. To run code using

## Basic architecture

With service workers, the following steps are generally observed for basic setup:
With service workers, the following steps are generally observed for initial installation and for replacing an existing service worker. The diagrams show an example that populates versioned caches during installation and removes old caches during activation.

### Initial installation

In this example, two pages are already open before the first service worker is registered. One of the pages calls [`serviceWorkerContainer.register()`](/en-US/docs/Web/API/ServiceWorkerContainer/register), which initiates the process.

1. The service worker code is fetched and then registered. If successful, the service worker is executed in a [`ServiceWorkerGlobalScope`](/en-US/docs/Web/API/ServiceWorkerGlobalScope); this is basically a special kind of worker context, running off the main script execution thread, with no DOM access. The service worker is now ready to process events.

![Registration of the first service worker, showing its parsed state, scope, and two open, uncontrolled clients.](sw-registration.svg)

1. The service worker code is fetched and then registered using [`serviceWorkerContainer.register()`](/en-US/docs/Web/API/ServiceWorkerContainer/register). If successful, the service worker is executed in a [`ServiceWorkerGlobalScope`](/en-US/docs/Web/API/ServiceWorkerGlobalScope); this is basically a special kind of worker context, running off the main script execution thread, with no DOM access. The service worker is now ready to process events.
2. Installation takes place. An `install` event is always the first one sent to a service worker (this can be used to start the process of populating an IndexedDB, and caching site assets). During this step, the application is preparing to make everything available for use offline.
3. When the `install` handler completes, the service worker is considered installed. At this point a previous version of the service worker may be active and controlling open pages. Because we don't want two different versions of the same service worker running at the same time, the new version is not yet active.
4. Once all pages controlled by the old version of the service worker have closed, it's safe to retire the old version, and the newly installed service worker receives an `activate` event. The primary use of `activate` is to clean up resources used in previous versions of the service worker. The new service worker can call [`skipWaiting()`](/en-US/docs/Web/API/ServiceWorkerGlobalScope/skipWaiting) to ask to be activated immediately without waiting for open pages to be closed. The new service worker will then receive `activate` immediately, and will take over any open pages.
5. After activation, the service worker will now control pages, but only those that were opened after the `register()` is successful. In other words, documents will have to be reloaded to actually be controlled, because a document starts life with or without a service worker and maintains that for its lifetime. To override this default behavior and adopt open pages, a service worker can call [`clients.claim()`](/en-US/docs/Web/API/Clients/claim).
6. Whenever a new version of a service worker is fetched, this cycle happens again and the remains of the previous version are cleaned during the new version's activation.

![lifecycle diagram](sw-lifecycle.svg)
![The install event populates a cache while the same two clients remain open.](sw-installation.svg)

3. When installation completes successfully, the service worker is considered installed.

![The service worker is installed, with a populated cache, but does not yet control clients.](sw-installed.svg)

4. Because this is the first service worker, it receives an `activate` event without waiting for open pages to close. The `activate` handler can finish setting up the service worker.

![The activate event finishes setup while the same two existing clients remain open.](sw-activation.svg)

5. After activation, the service worker will control pages opened within its scope. Existing documents will have to be reloaded to actually be controlled, because a document starts life with or without a service worker and maintains that for its lifetime. To override this default behavior and adopt open pages, a service worker can call [`clients.claim()`](/en-US/docs/Web/API/Clients/claim).

![A new client opens and is controlled by the activated service worker, while the two existing clients remain open and uncontrolled.](sw-activated.svg)

### Replacing an existing service worker

This independent example starts with one open client controlled by version 1. It illustrates the default waiting behavior when replacing an existing service worker.

1. Whenever a new version of a service worker is fetched, this cycle happens again. The previous version remains active and continues to control its clients.

![The open client calls register(), and version 2 is parsed while version 1 remains activated and controls the client.](sw-replacement-fetched.svg)

2. Installation takes place for the new version. Its `install` handler can populate a new cache while the old version continues to use its existing cache.

![Version 2 receives the install event and populates a new cache while version 1 continues to control the same client.](sw-replacement-installation.svg)

3. When installation completes successfully, the new version waits while the old version is still controlling clients. The new version is not yet active.

![Version 2 is installed and waiting, with its new cache ready, while version 1 still controls the open client.](sw-replacement-waiting.svg)

4. Once all pages controlled by the old version of the service worker have closed and the old version has finished handling pending events, it's safe to retire the old version, and the newly installed service worker receives an `activate` event. The primary use of `activate` is to clean up resources used in previous versions of the service worker, such as the old cache in this example.

The new service worker can call [`skipWaiting()`](/en-US/docs/Web/API/ServiceWorkerGlobalScope/skipWaiting) to ask to be activated without waiting for open pages to be closed. It then takes over the pages controlled by the old version.

![The client controlled by version 1 closes. Version 1 is retired, and version 2 receives activate and deletes the old cache.](sw-replacement-activation.svg)

5. After activation, newly opened pages within the registration's scope are controlled by the new version.

![A new client opens and is controlled by version 2, which uses its new cache.](sw-replacement-activated.svg)

### Service worker events

Here is a summary of the available service worker events:

Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Loading