Files
node/src/sharedarraybuffer_metadata.cc
Joyee Cheung 28a3e280ec src: add proper MemoryInfoName to wrappers
- Use camel case names for memory retainers inherited from AsyncWrap
  instead of their provider names (which are all in upper case)
- Assign class names to wraps so that they appear in the heap snapshot
  as nodes with class names as node names. Previously some nodes are
  named with reference names, which are supposed to be edge names
  instead.

PR-URL: https://github.com/nodejs/node/pull/21939
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: Gus Caplan <me@gus.host>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Tobias Nießen <tniessen@tnie.de>
2018-07-27 15:51:19 +08:00

136 lines
4.0 KiB
C++

#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
// SABLiftimePartner* pointer.
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();
}
void MemoryInfo(MemoryTracker* tracker) const override {
tracker->TrackThis(this);
}
ADD_MEMORY_INFO_NAME(SABLifetimePartner)
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