Bug 1789227 Comment 22 Edit History

Note: The actual edited comment in the bug view page will always show the original commenter’s name and original timestamp.

(In reply to Peter Van der Beken [:peterv] from comment #21)

Thanks for the extensive explanation, that's super helpful!

> So in this case, if you get `window.docshell` and store it in a variable in JS, as soon as that variable goes out of scope the JS object that you got from `window.docshell` will be subject to collection by the GC, potentially destroying the XPCWrappedNative. If you then get `window.docshell` again you'll get a different object in JS, and we'll create a new XPCWrappedNative.

OK. What guarantees are there about when GCs happen that have this result? E.g.:

```lang=js
window.docShell.QueryInterface(Ci.nsILoadContext);
let x = window.docShell.usePrivateBrowsing; // provided by nsILoadContext
```

Can a GC happen between these two lines? For the sync case above, I am not sure about the answer, but I suppose in:

```
async function() {
  ...
  window.docShell.QueryInterface(Ci.nsILoadContext);
  await somePromise;
  let x = window.docShell.usePrivateBrowsing; // provided by nsILoadContext
}
```

There are definitely no guarantees that there hasn't been a GC?

> nsIClassInfo allows us to 'flatten' the interfaces that are returned from classinfo's `interfaces` property onto the XPCWrappedNative's JS object, which means that if you want to access any property from those interfaces they will be exposed through the main XPCWrappedNative without having to call QI on its JS object. This doesn't prevent the XPCWrappedNative from being collected, it just means that after the XPCWrappedNative is destroyed and a new one created all the properties from those interfaces will be present.

Right. I filed 1804665 to do this for docshell.
(In reply to Peter Van der Beken [:peterv] from comment #21)

Thanks for the extensive explanation, that's super helpful!

> So in this case, if you get `window.docshell` and store it in a variable in JS, as soon as that variable goes out of scope the JS object that you got from `window.docshell` will be subject to collection by the GC, potentially destroying the XPCWrappedNative. If you then get `window.docshell` again you'll get a different object in JS, and we'll create a new XPCWrappedNative.

OK. What guarantees are there about when GCs happen that have this result? E.g.:

```lang=js
window.docShell.QueryInterface(Ci.nsILoadContext);
let x = window.docShell.usePrivateBrowsing; // provided by nsILoadContext
```

Can a GC happen between these two lines? For the sync case above, I am not sure about the answer, but I suppose in:

```
async function() {
  ...
  window.docShell.QueryInterface(Ci.nsILoadContext);
  await somePromise;
  let x = window.docShell.usePrivateBrowsing; // provided by nsILoadContext
}
```

There are definitely no guarantees that there hasn't been a GC?

> nsIClassInfo allows us to 'flatten' the interfaces that are returned from classinfo's `interfaces` property onto the XPCWrappedNative's JS object, which means that if you want to access any property from those interfaces they will be exposed through the main XPCWrappedNative without having to call QI on its JS object. This doesn't prevent the XPCWrappedNative from being collected, it just means that after the XPCWrappedNative is destroyed and a new one created all the properties from those interfaces will be present.

Right. I filed bug 1804665 to do this for docshell.
(In reply to Peter Van der Beken [:peterv] from comment #21)

Thanks for the extensive explanation, that's super helpful!

> So in this case, if you get `window.docshell` and store it in a variable in JS, as soon as that variable goes out of scope the JS object that you got from `window.docshell` will be subject to collection by the GC, potentially destroying the XPCWrappedNative. If you then get `window.docshell` again you'll get a different object in JS, and we'll create a new XPCWrappedNative.

OK. What guarantees are there about when GCs happen that have this result? E.g.:

```js
window.docShell.QueryInterface(Ci.nsILoadContext);
let x = window.docShell.usePrivateBrowsing; // provided by nsILoadContext
```

Can a GC happen between these two lines? For the sync case above, I am not sure about the answer, but I suppose in:

```js
async function() {
  ...
  window.docShell.QueryInterface(Ci.nsILoadContext);
  await somePromise;
  let x = window.docShell.usePrivateBrowsing; // provided by nsILoadContext
}
```

There are definitely no guarantees that there hasn't been a GC?

> nsIClassInfo allows us to 'flatten' the interfaces that are returned from classinfo's `interfaces` property onto the XPCWrappedNative's JS object, which means that if you want to access any property from those interfaces they will be exposed through the main XPCWrappedNative without having to call QI on its JS object. This doesn't prevent the XPCWrappedNative from being collected, it just means that after the XPCWrappedNative is destroyed and a new one created all the properties from those interfaces will be present.

Right. I filed bug 1804665 to do this for docshell.

Back to Bug 1789227 Comment 22