Skip to content

Commit

Permalink
Refactor js.enterContextScope() to JSG_WITHIN_CONTEXT_SCOPE macro
Browse files Browse the repository at this point in the history
Helps to eliminate repetitive boilerplate in multiple locations.
  • Loading branch information
jasnell committed Jan 24, 2024
1 parent f4f29e8 commit 1bcae22
Show file tree
Hide file tree
Showing 6 changed files with 292 additions and 334 deletions.
31 changes: 14 additions & 17 deletions src/workerd/api/actor-state-test.c++
Original file line number Diff line number Diff line change
Expand Up @@ -33,16 +33,15 @@ JSG_DECLARE_ISOLATE_TYPE(ActorStateIsolate, ActorStateContext);
KJ_TEST("v8 serialization version tag hasn't changed") {
jsg::test::Evaluator<ActorStateContext, ActorStateIsolate> e(v8System);
e.getIsolate().runInLockScope([&](ActorStateIsolate::Lock& isolateLock) {
isolateLock.withinHandleScope([&] {
auto v8Context = isolateLock.newContext<ActorStateContext>().getHandle(isolateLock);
auto contextScope = isolateLock.enterContextScope(v8Context);

JSG_WITHIN_CONTEXT_SCOPE(isolateLock,
isolateLock.newContext<ActorStateContext>().getHandle(isolateLock),
[&](jsg::Lock& js) {
auto buf = serializeV8Value(isolateLock, isolateLock.boolean(true));

// Confirm that a version header is appropriately written and that it contains the expected
// current version. When the version increases, we need to write a v8 patch that allows it to
// continue writing data at the old version so that we can do a rolling upgrade without any
// bugs caused by old processes failing to read data written by new ones.
// current version. When the version increases, we need to write a v8 patch that allows it
// to continue writing data at the old version so that we can do a rolling upgrade without
// any bugs caused by old processes failing to read data written by new ones.
KJ_EXPECT(buf[0] == 0xFF);
KJ_EXPECT(buf[1] == 0x0F); // v8 serializer version

Expand All @@ -61,10 +60,9 @@ KJ_TEST("v8 serialization version tag hasn't changed") {
KJ_TEST("we support deserializing up to v15") {
jsg::test::Evaluator<ActorStateContext, ActorStateIsolate> e(v8System);
e.getIsolate().runInLockScope([&](ActorStateIsolate::Lock& isolateLock) {
isolateLock.withinHandleScope([&] {
auto v8Context = isolateLock.newContext<ActorStateContext>().getHandle(isolateLock);
auto contextScope = isolateLock.enterContextScope(v8Context);

JSG_WITHIN_CONTEXT_SCOPE(isolateLock,
isolateLock.newContext<ActorStateContext>().getHandle(isolateLock),
[&](jsg::Lock& js) {
kj::Vector<kj::StringPtr> testCases;
testCases.add("54");
testCases.add("FF0D54");
Expand Down Expand Up @@ -105,12 +103,11 @@ KJ_TEST("wire format version does not change deserialization behavior on real da

jsg::test::Evaluator<ActorStateContext, ActorStateIsolate> e(v8System);
e.getIsolate().runInLockScope([&](ActorStateIsolate::Lock& isolateLock) {
isolateLock.withinHandleScope([&] {
auto v8Context = isolateLock.newContext<ActorStateContext>().getHandle(isolateLock);
auto contextScope = isolateLock.enterContextScope(v8Context);

// Read in data line by line and verify that it round trips (serializes and then deserializes)
// back to the exact same data as the input.
JSG_WITHIN_CONTEXT_SCOPE(isolateLock,
isolateLock.newContext<ActorStateContext>().getHandle(isolateLock),
[&](jsg::Lock& js) {
// Read in data line by line and verify that it round trips (serializes and
// then deserializes) back to the exact same data as the input.
std::string hexStr;
const auto key = "some-key"_kj;
while (std::getline(file, hexStr)) {
Expand Down
124 changes: 61 additions & 63 deletions src/workerd/api/crypto-impl-aes-test.c++
Original file line number Diff line number Diff line change
Expand Up @@ -93,84 +93,82 @@ KJ_TEST("AES-CTR key wrap") {
// Basic test that let me repro an issue where using an AES key that's not AES-KW would fail to
// wrap if it didn't have "encrypt" in its usages when created.

jsg::test::Evaluator<CryptoContext, CryptoIsolate> e(v8System);
e.getIsolate().runInLockScope([&](CryptoIsolate::Lock& isolateLock) {
auto isolate = isolateLock.v8Isolate;

isolateLock.withinHandleScope([&] {
auto context = isolateLock.newContext<CryptoContext>().getHandle(isolateLock);
auto contextScope = isolateLock.enterContextScope(context);

jsg::Lock& js = isolateLock;

SubtleCrypto subtle;

auto wrappingKey = [&] {
auto keyMaterial = kj::heapArray<kj::byte>(
{0x52, 0x4b, 0x67, 0x25, 0xe3, 0x56, 0xaa, 0xce, 0x7e, 0x76, 0x9b,
0x48, 0x92, 0x55, 0x49, 0x06, 0x12, 0x5e, 0xf5, 0xae, 0xce, 0x39,
0xde, 0xc2, 0x5b, 0x27, 0x33, 0x4e, 0x6e, 0x52, 0x32, 0x4e});

SubtleCrypto::ImportKeyAlgorithm algorithm = {
.name = kj::str("AES-CTR"),
};
bool extractable = false;

return subtle.importKeySync(jsg::Lock::from(isolate),
"raw", kj::mv(keyMaterial), kj::mv(algorithm), extractable,
{kj::str("wrapKey"), kj::str("unwrapKey")});
}();

const auto unwrappedKeyMaterial = kj::heapArray<kj::byte>(
{0x52, 0x4b, 0x67, 0x25, 0xe3, 0x56, 0xaa, 0xce, 0x7e, 0x76, 0x9b,
0x48, 0x92, 0x55, 0x49, 0x06, 0x12, 0x5e, 0xf5, 0xae, 0xce, 0x39,
0xde, 0xc2, 0x5b, 0x27, 0x33, 0x4e, 0x6e, 0x52, 0x32, 0x4e});
SubtleCrypto::ImportKeyAlgorithm importAlgorithm;
importAlgorithm.length = 256;
importAlgorithm.name = kj::str("AES-CBC");
const jsg::TypeHandler<SubtleCrypto::JsonWebKey>* jwkHandler = nullptr;
// Not testing JWK here, so valid value isn't needed.

static constexpr kj::byte RAW_KEY_DATA[] = {
0x52, 0x4b, 0x67, 0x25, 0xe3, 0x56, 0xaa, 0xce,
0x7e, 0x76, 0x9b, 0x48, 0x92, 0x55, 0x49, 0x06,
0x12, 0x5e, 0xf5, 0xae, 0xce, 0x39, 0xde, 0xc2,
0x5b, 0x27, 0x33, 0x4e, 0x6e, 0x52, 0x32, 0x4e
};

static constexpr kj::ArrayPtr<const kj::byte> KEY_DATA(RAW_KEY_DATA, 32);

SubtleCrypto subtle;

static constexpr auto getWrappingKey = [](jsg::Lock& js, SubtleCrypto& subtle) {
return subtle.importKeySync(js, "raw",
kj::heapArray<kj::byte>(KEY_DATA),
SubtleCrypto::ImportKeyAlgorithm {
.name = kj::str("AES-CTR")
},
false /* extractable */,
{ kj::str("wrapKey"), kj::str("unwrapKey") });
};

static constexpr auto getEnc = [] {
return SubtleCrypto::EncryptAlgorithm {
.name = kj::str("AES-CTR"),
.counter = kj::arr<uint8_t>(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16),
.length = 5,
};
};

const jsg::TypeHandler<SubtleCrypto::JsonWebKey>* jwkHandler = nullptr;
// Not testing JWK here, so valid value isn't needed.
static constexpr auto getImportKeyAlg = [] {
return SubtleCrypto::ImportKeyAlgorithm {
.name = kj::str("AES-CBC"),
.length = 256,
};
};

bool completed = false;
jsg::test::Evaluator<CryptoContext, CryptoIsolate> e(v8System);
bool completed = false;

e.getIsolate().runInLockScope([&](CryptoIsolate::Lock& isolateLock) {
JSG_WITHIN_CONTEXT_SCOPE(isolateLock,
isolateLock.newContext<CryptoContext>().getHandle(isolateLock),
[&](jsg::Lock& js) {
auto wrappingKey = getWrappingKey(js, subtle);
subtle.importKey(
jsg::Lock::from(isolate),
kj::str("raw"),
kj::heapArray(unwrappedKeyMaterial.asPtr()),
kj::mv(importAlgorithm),
js, kj::str("raw"),
kj::heapArray(KEY_DATA),
getImportKeyAlg(),
true, kj::arr(kj::str("decrypt")))
.then(js, [&] (jsg::Lock&, jsg::Ref<CryptoKey> toWrap) {
SubtleCrypto::EncryptAlgorithm enc;
enc.name = kj::str("AES-CTR");
enc.counter = kj::arr<uint8_t>(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16);
enc.length = 5;
return subtle.wrapKey(isolateLock, kj::str("raw"), *toWrap, *wrappingKey,
kj::mv(enc), *jwkHandler);
return subtle.wrapKey(
js, kj::str("raw"), *toWrap, *wrappingKey,
getEnc(), *jwkHandler);
}).then(js, [&] (jsg::Lock&, kj::Array<kj::byte> wrapped) {
SubtleCrypto::EncryptAlgorithm enc;
enc.name = kj::str("AES-CTR");
enc.counter = kj::arr<uint8_t>(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16);
enc.length = 5;

SubtleCrypto::ImportKeyAlgorithm importAlgorithm;
importAlgorithm.length = 256;
importAlgorithm.name = kj::str("AES-CBC");

return subtle.unwrapKey(isolateLock, kj::str("raw"), kj::mv(wrapped), *wrappingKey,
kj::mv(enc), kj::mv(importAlgorithm), true,
kj::arr(kj::str("encrypt")), *jwkHandler);
return subtle.unwrapKey(js,
kj::str("raw"),
kj::mv(wrapped),
*wrappingKey,
getEnc(),
getImportKeyAlg(),
true, kj::arr(kj::str("encrypt")), *jwkHandler);
}).then(js, [&] (jsg::Lock& js, jsg::Ref<CryptoKey> unwrapped) {
return subtle.exportKey(js, kj::str("raw"), *unwrapped);
}).then(js, [&] (jsg::Lock&, api::SubtleCrypto::ExportKeyData roundTrippedKeyMaterial) {
KJ_ASSERT(roundTrippedKeyMaterial.get<kj::Array<kj::byte>>() == unwrappedKeyMaterial);
KJ_ASSERT(roundTrippedKeyMaterial.get<kj::Array<kj::byte>>() == KEY_DATA);
completed = true;
});

e.runMicrotasks(isolateLock);
KJ_ASSERT(completed, "Microtasks did not run fully.");
js.runMicrotasks();
});
});

KJ_ASSERT(completed, "Microtasks did not run fully.");
}
#if __clang__ && __has_feature(undefined_behavior_sanitizer)
#pragma clang attribute pop // __attribute__((no_sanitize("null"))
Expand Down
6 changes: 2 additions & 4 deletions src/workerd/io/hibernation-manager.c++
Original file line number Diff line number Diff line change
Expand Up @@ -209,16 +209,14 @@ void HibernationManagerImpl::setTimerChannel(TimerChannel& timerChannel) {
}

void HibernationManagerImpl::hibernateWebSockets(Worker::Lock& lock) {
jsg::Lock& js(lock);
js.withinHandleScope([&] {
js.enterContextScope(lock.getContext());
JSG_WITHIN_CONTEXT_SCOPE(lock, lock.getContext(), [&](jsg::Lock& js) {
for (auto& ws : allWs) {
KJ_IF_SOME(active, ws->activeOrPackage.tryGet<jsg::Ref<api::WebSocket>>()) {
// Transfers ownership of properties from api::WebSocket to HibernatableWebSocket via the
// HibernationPackage.
ws->activeOrPackage.init<api::WebSocket::HibernationPackage>(
active.get()->buildPackageForHibernation());
}
} else {} // Here to quash compiler warning
}
});
}
Expand Down
Loading

0 comments on commit 1bcae22

Please sign in to comment.