script: Return cached object from CryptoKey.usages getter (#39564)

Create and store a cached object in `CryptoKey` for the `[[usages]]`
internal slot when the key is created or when its `[[usages]]` internal
slot is updated. The getter can then return the cached object as
specified in https://w3c.github.io/webcrypto/#dom-cryptokey-usages,
instead of creating a new object on each call.

Testing: Pass WPT tests that were expected to fail.

Signed-off-by: Kingsley Yung <kingsley@kkoyung.dev>
This commit is contained in:
Kingsley Yung 2025-09-30 11:56:12 +08:00 committed by GitHub
parent 1accf6d5db
commit 34979c8b71
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 21 additions and 13 deletions

View file

@ -61,6 +61,11 @@ pub(crate) struct CryptoKey {
/// <https://w3c.github.io/webcrypto/#dom-cryptokey-usages>
usages: DomRefCell<Vec<KeyUsage>>,
/// Cached object of <https://w3c.github.io/webcrypto/#dom-cryptokey-usages>
#[ignore_malloc_size_of = "Defined in mozjs"]
usages_object: Heap<*mut JSObject>,
#[no_trace]
handle: Handle,
}
@ -80,6 +85,7 @@ impl CryptoKey {
algorithm,
algorithm_object: Heap::default(),
usages: DomRefCell::new(usages),
usages_object: Heap::default(),
handle,
}
}
@ -99,7 +105,7 @@ impl CryptoKey {
Box::new(CryptoKey::new_inherited(
key_type,
extractable,
usages,
usages.clone(),
algorithm,
handle,
)),
@ -109,6 +115,12 @@ impl CryptoKey {
object.algorithm_object.set(algorithm_object.get());
// Create and store a cached object of usages
let cx = GlobalScope::get_cx();
rooted!(in(*cx) let mut usages_object_value: Value);
usages.safe_to_jsval(cx, usages_object_value.handle_mut());
object.usages_object.set(usages_object_value.to_object());
object
}
@ -130,6 +142,12 @@ impl CryptoKey {
pub(crate) fn set_usages(&self, usages: &[KeyUsage]) {
*self.usages.borrow_mut() = usages.to_owned();
// Create and store a cached object of usages
let cx = GlobalScope::get_cx();
rooted!(in(*cx) let mut usages_object_value: Value);
usages.safe_to_jsval(cx, usages_object_value.handle_mut());
self.usages_object.set(usages_object_value.to_object());
}
}
@ -150,10 +168,8 @@ impl CryptoKeyMethods<crate::DomTypeHolder> for CryptoKey {
}
/// <https://w3c.github.io/webcrypto/#dom-cryptokey-usages>
fn Usages(&self, cx: JSContext) -> NonNull<JSObject> {
rooted!(in(*cx) let mut usages: Value);
self.usages.borrow().safe_to_jsval(cx, usages.handle_mut());
NonNull::new(usages.to_object()).unwrap()
fn Usages(&self, _cx: JSContext) -> NonNull<JSObject> {
NonNull::new(self.usages_object.get()).unwrap()
}
}

View file

@ -1,8 +0,0 @@
[crypto_key_cached_slots.https.any.worker.html]
[CryptoKey.usages getter returns cached object]
expected: FAIL
[crypto_key_cached_slots.https.any.html]
[CryptoKey.usages getter returns cached object]
expected: FAIL