2018-05-13 19:39:32 +02:00
|
|
|
#include "sharedarraybuffer_metadata.h"
|
|
|
|
|
#include "base_object.h"
|
|
|
|
|
#include "base_object-inl.h"
|
|
|
|
|
#include "node_errors.h"
|
|
|
|
|
|
|
|
|
|
using v8::Context;
|
|
|
|
|
using v8::Function;
|
|
|
|
|
using v8::FunctionTemplate;
|
|
|
|
|
using v8::Local;
|
|
|
|
|
using v8::Maybe;
|
|
|
|
|
using v8::MaybeLocal;
|
|
|
|
|
using v8::Nothing;
|
|
|
|
|
using v8::Object;
|
|
|
|
|
using v8::SharedArrayBuffer;
|
|
|
|
|
using v8::Value;
|
|
|
|
|
|
|
|
|
|
namespace node {
|
|
|
|
|
namespace worker {
|
|
|
|
|
|
|
|
|
|
namespace {
|
|
|
|
|
|
|
|
|
|
// Yield a JS constructor for SABLifetimePartner objects in the form of a
|
|
|
|
|
// standard API object, that has a single field for containing the raw
|
2018-10-06 21:09:29 -04:00
|
|
|
// SABLifetimePartner* pointer.
|
2018-05-13 19:39:32 +02:00
|
|
|
Local<Function> GetSABLifetimePartnerConstructor(
|
|
|
|
|
Environment* env, Local<Context> context) {
|
|
|
|
|
Local<FunctionTemplate> templ;
|
|
|
|
|
templ = env->sab_lifetimepartner_constructor_template();
|
|
|
|
|
if (!templ.IsEmpty())
|
|
|
|
|
return templ->GetFunction(context).ToLocalChecked();
|
|
|
|
|
|
|
|
|
|
templ = BaseObject::MakeLazilyInitializedJSTemplate(env);
|
|
|
|
|
templ->SetClassName(FIXED_ONE_BYTE_STRING(env->isolate(),
|
|
|
|
|
"SABLifetimePartner"));
|
|
|
|
|
env->set_sab_lifetimepartner_constructor_template(templ);
|
|
|
|
|
|
|
|
|
|
return GetSABLifetimePartnerConstructor(env, context);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class SABLifetimePartner : public BaseObject {
|
|
|
|
|
public:
|
|
|
|
|
SABLifetimePartner(Environment* env,
|
|
|
|
|
Local<Object> obj,
|
|
|
|
|
SharedArrayBufferMetadataReference r)
|
|
|
|
|
: BaseObject(env, obj),
|
|
|
|
|
reference(r) {
|
|
|
|
|
MakeWeak();
|
|
|
|
|
}
|
|
|
|
|
|
2018-09-23 17:52:09 -04:00
|
|
|
SET_NO_MEMORY_INFO()
|
|
|
|
|
SET_MEMORY_INFO_NAME(SABLifetimePartner)
|
|
|
|
|
SET_SELF_SIZE(SABLifetimePartner)
|
2018-07-22 09:12:19 +08:00
|
|
|
|
2018-05-13 19:39:32 +02:00
|
|
|
SharedArrayBufferMetadataReference reference;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
} // anonymous namespace
|
|
|
|
|
|
|
|
|
|
SharedArrayBufferMetadataReference
|
|
|
|
|
SharedArrayBufferMetadata::ForSharedArrayBuffer(
|
|
|
|
|
Environment* env,
|
|
|
|
|
Local<Context> context,
|
|
|
|
|
Local<SharedArrayBuffer> source) {
|
|
|
|
|
Local<Value> lifetime_partner;
|
|
|
|
|
|
|
|
|
|
if (!source->GetPrivate(context,
|
|
|
|
|
env->sab_lifetimepartner_symbol())
|
|
|
|
|
.ToLocal(&lifetime_partner)) {
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (lifetime_partner->IsObject() &&
|
|
|
|
|
env->sab_lifetimepartner_constructor_template()
|
|
|
|
|
->HasInstance(lifetime_partner)) {
|
|
|
|
|
CHECK(source->IsExternal());
|
|
|
|
|
SABLifetimePartner* partner =
|
|
|
|
|
Unwrap<SABLifetimePartner>(lifetime_partner.As<Object>());
|
|
|
|
|
CHECK_NE(partner, nullptr);
|
|
|
|
|
return partner->reference;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (source->IsExternal()) {
|
|
|
|
|
// If this is an external SharedArrayBuffer but we do not see a lifetime
|
|
|
|
|
// partner object, it was not us who externalized it. In that case, there
|
|
|
|
|
// is no way to serialize it, because it's unclear how the memory
|
|
|
|
|
// is actually owned.
|
|
|
|
|
THROW_ERR_TRANSFERRING_EXTERNALIZED_SHAREDARRAYBUFFER(env);
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
SharedArrayBuffer::Contents contents = source->Externalize();
|
|
|
|
|
SharedArrayBufferMetadataReference r(new SharedArrayBufferMetadata(
|
|
|
|
|
contents.Data(), contents.ByteLength()));
|
|
|
|
|
if (r->AssignToSharedArrayBuffer(env, context, source).IsNothing())
|
|
|
|
|
return nullptr;
|
|
|
|
|
return r;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Maybe<bool> SharedArrayBufferMetadata::AssignToSharedArrayBuffer(
|
|
|
|
|
Environment* env, Local<Context> context,
|
|
|
|
|
Local<SharedArrayBuffer> target) {
|
|
|
|
|
CHECK(target->IsExternal());
|
|
|
|
|
Local<Function> ctor = GetSABLifetimePartnerConstructor(env, context);
|
|
|
|
|
Local<Object> obj;
|
|
|
|
|
if (!ctor->NewInstance(context).ToLocal(&obj))
|
|
|
|
|
return Nothing<bool>();
|
|
|
|
|
|
|
|
|
|
new SABLifetimePartner(env, obj, shared_from_this());
|
|
|
|
|
return target->SetPrivate(context,
|
|
|
|
|
env->sab_lifetimepartner_symbol(),
|
|
|
|
|
obj);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
SharedArrayBufferMetadata::SharedArrayBufferMetadata(void* data, size_t size)
|
|
|
|
|
: data(data), size(size) { }
|
|
|
|
|
|
|
|
|
|
SharedArrayBufferMetadata::~SharedArrayBufferMetadata() {
|
|
|
|
|
free(data);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
MaybeLocal<SharedArrayBuffer> SharedArrayBufferMetadata::GetSharedArrayBuffer(
|
|
|
|
|
Environment* env, Local<Context> context) {
|
|
|
|
|
Local<SharedArrayBuffer> obj =
|
|
|
|
|
SharedArrayBuffer::New(env->isolate(), data, size);
|
|
|
|
|
|
|
|
|
|
if (AssignToSharedArrayBuffer(env, context, obj).IsNothing())
|
|
|
|
|
return MaybeLocal<SharedArrayBuffer>();
|
|
|
|
|
|
|
|
|
|
return obj;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} // namespace worker
|
|
|
|
|
} // namespace node
|