diff options
author | Bert Belder <bertbelder@gmail.com> | 2018-10-07 23:48:06 +0200 |
---|---|---|
committer | Bert Belder <bertbelder@gmail.com> | 2018-10-08 18:19:32 +0200 |
commit | e742af10aa67dc90a68fcb60b8e70733fd753e68 (patch) | |
tree | bc9d7360c5a8cb94e93f9dabf5749b94addc0c18 /libdeno/binding.cc | |
parent | d86e5d2605c68606c8073d1b563d3389ea93c112 (diff) |
Abide by the rules when passing Isolate between c and rust
Ensure that at most one mutable Isolate reference exists at a time.
`deno_execute()` and `deno_respond()` now borrow a reference to the rust-side
isolate from the caller. When we need a reference to the isolate while one of
these functions is on the stack, `deno_get_data()` can be used to borrow back
that reference.
Diffstat (limited to 'libdeno/binding.cc')
-rw-r--r-- | libdeno/binding.cc | 31 |
1 files changed, 27 insertions, 4 deletions
diff --git a/libdeno/binding.cc b/libdeno/binding.cc index 7bc1a0397..55a78069e 100644 --- a/libdeno/binding.cc +++ b/libdeno/binding.cc @@ -401,6 +401,24 @@ void AddIsolate(Deno* d, v8::Isolate* isolate) { d->isolate->SetData(0, d); } +class UserDataScope { + Deno* deno; + void* prev_data; + void* data; // Not necessary; only for sanity checking. + + public: + UserDataScope(Deno* deno_, void* data_) : deno(deno_), data(data_) { + CHECK(deno->user_data == nullptr || deno->user_data == data_); + prev_data = deno->user_data; + deno->user_data = data; + } + + ~UserDataScope() { + CHECK(deno->user_data == data); + deno->user_data = prev_data; + } +}; + } // namespace deno extern "C" { @@ -413,7 +431,10 @@ void deno_init() { v8::V8::Initialize(); } -void* deno_get_data(Deno* d) { return d->user_data; } +void* deno_get_data(const Deno* d) { + CHECK(d->user_data != nullptr); + return d->user_data; +} const char* deno_v8_version() { return v8::V8::GetVersion(); } @@ -423,7 +444,9 @@ void deno_set_v8_flags(int* argc, char** argv) { const char* deno_last_exception(Deno* d) { return d->last_exception.c_str(); } -int deno_execute(Deno* d, const char* js_filename, const char* js_source) { +int deno_execute(Deno* d, void* user_data, const char* js_filename, + const char* js_source) { + deno::UserDataScope user_data_scope(d, user_data); auto* isolate = d->isolate; v8::Locker locker(isolate); v8::Isolate::Scope isolate_scope(isolate); @@ -432,7 +455,7 @@ int deno_execute(Deno* d, const char* js_filename, const char* js_source) { return deno::Execute(context, js_filename, js_source) ? 1 : 0; } -int deno_respond(Deno* d, int32_t req_id, deno_buf buf) { +int deno_respond(Deno* d, void* user_data, int32_t req_id, deno_buf buf) { if (d->currentArgs != nullptr) { // Synchronous response. auto ab = deno::ImportBuf(d->isolate, buf); @@ -442,7 +465,7 @@ int deno_respond(Deno* d, int32_t req_id, deno_buf buf) { } // Asynchronous response. - + deno::UserDataScope user_data_scope(d, user_data); v8::Locker locker(d->isolate); v8::Isolate::Scope isolate_scope(d->isolate); v8::HandleScope handle_scope(d->isolate); |