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> /// <https://w3c.github.io/webcrypto/#dom-cryptokey-usages>
usages: DomRefCell<Vec<KeyUsage>>, 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] #[no_trace]
handle: Handle, handle: Handle,
} }
@ -80,6 +85,7 @@ impl CryptoKey {
algorithm, algorithm,
algorithm_object: Heap::default(), algorithm_object: Heap::default(),
usages: DomRefCell::new(usages), usages: DomRefCell::new(usages),
usages_object: Heap::default(),
handle, handle,
} }
} }
@ -99,7 +105,7 @@ impl CryptoKey {
Box::new(CryptoKey::new_inherited( Box::new(CryptoKey::new_inherited(
key_type, key_type,
extractable, extractable,
usages, usages.clone(),
algorithm, algorithm,
handle, handle,
)), )),
@ -109,6 +115,12 @@ impl CryptoKey {
object.algorithm_object.set(algorithm_object.get()); 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 object
} }
@ -130,6 +142,12 @@ impl CryptoKey {
pub(crate) fn set_usages(&self, usages: &[KeyUsage]) { pub(crate) fn set_usages(&self, usages: &[KeyUsage]) {
*self.usages.borrow_mut() = usages.to_owned(); *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> /// <https://w3c.github.io/webcrypto/#dom-cryptokey-usages>
fn Usages(&self, cx: JSContext) -> NonNull<JSObject> { fn Usages(&self, _cx: JSContext) -> NonNull<JSObject> {
rooted!(in(*cx) let mut usages: Value); NonNull::new(self.usages_object.get()).unwrap()
self.usages.borrow().safe_to_jsval(cx, usages.handle_mut());
NonNull::new(usages.to_object()).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