2013-04-25 13:46:04 +00:00
|
|
|
// Copyright (c) 2013 GitHub, Inc. All rights reserved.
|
|
|
|
// Copyright (c) 2012 Intel Corp. All rights reserved.
|
|
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
|
|
// found in the LICENSE file.
|
|
|
|
|
2014-03-16 00:30:26 +00:00
|
|
|
#include "atom/common/api/atom_api_id_weak_map.h"
|
2013-04-25 13:46:04 +00:00
|
|
|
|
2013-12-11 07:48:19 +00:00
|
|
|
#include <algorithm>
|
|
|
|
|
2013-07-29 11:14:35 +00:00
|
|
|
#include "base/logging.h"
|
2014-03-16 00:30:26 +00:00
|
|
|
#include "atom/common/v8/native_type_conversions.h"
|
|
|
|
#include "atom/common/v8/node_common.h"
|
2013-07-29 11:14:35 +00:00
|
|
|
|
2013-04-25 13:46:04 +00:00
|
|
|
namespace atom {
|
|
|
|
|
|
|
|
namespace api {
|
|
|
|
|
|
|
|
IDWeakMap::IDWeakMap()
|
2013-04-27 08:54:17 +00:00
|
|
|
: next_id_(0) {
|
2013-04-25 13:46:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
IDWeakMap::~IDWeakMap() {
|
|
|
|
}
|
|
|
|
|
|
|
|
bool IDWeakMap::Has(int key) const {
|
|
|
|
return map_.find(key) != map_.end();
|
|
|
|
}
|
|
|
|
|
2013-12-11 07:48:19 +00:00
|
|
|
void IDWeakMap::Erase(int key) {
|
|
|
|
if (Has(key))
|
|
|
|
map_.erase(key);
|
|
|
|
else
|
2013-07-29 11:14:35 +00:00
|
|
|
LOG(WARNING) << "Object with key " << key << " is being GCed for twice.";
|
2013-04-25 13:46:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int IDWeakMap::GetNextID() {
|
2013-04-27 08:54:17 +00:00
|
|
|
return ++next_id_;
|
2013-04-25 13:46:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// static
|
|
|
|
void IDWeakMap::WeakCallback(v8::Isolate* isolate,
|
2013-12-11 07:48:19 +00:00
|
|
|
v8::Persistent<v8::Object>* value,
|
|
|
|
IDWeakMap* self) {
|
|
|
|
v8::HandleScope handle_scope(isolate);
|
|
|
|
v8::Local<v8::Object> local = v8::Local<v8::Object>::New(isolate, *value);
|
|
|
|
self->Erase(
|
|
|
|
FromV8Value(local->GetHiddenValue(v8::String::New("IDWeakMapKey"))));
|
2013-04-25 13:46:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// static
|
2013-12-11 07:48:19 +00:00
|
|
|
void IDWeakMap::New(const v8::FunctionCallbackInfo<v8::Value>& args) {
|
|
|
|
(new IDWeakMap)->Wrap(args.This());
|
2013-04-25 13:46:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// static
|
2013-12-11 07:48:19 +00:00
|
|
|
void IDWeakMap::Add(const v8::FunctionCallbackInfo<v8::Value>& args) {
|
2013-04-25 13:46:04 +00:00
|
|
|
if (!args[0]->IsObject())
|
|
|
|
return node::ThrowTypeError("Bad argument");
|
|
|
|
|
2013-12-11 07:48:19 +00:00
|
|
|
IDWeakMap* self = Unwrap<IDWeakMap>(args.This());
|
2013-04-25 13:46:04 +00:00
|
|
|
|
2013-12-11 07:48:19 +00:00
|
|
|
int key = self->GetNextID();
|
|
|
|
v8::Local<v8::Object> v8_value = args[0]->ToObject();
|
|
|
|
v8_value->SetHiddenValue(v8::String::New("IDWeakMapKey"), ToV8Value(key));
|
2013-04-25 13:46:04 +00:00
|
|
|
|
2013-12-11 16:10:09 +00:00
|
|
|
self->map_[key] = new RefCountedPersistent<v8::Object>(v8_value);
|
|
|
|
self->map_[key]->MakeWeak(self, WeakCallback);
|
2013-04-25 13:46:04 +00:00
|
|
|
|
2013-12-11 07:48:19 +00:00
|
|
|
args.GetReturnValue().Set(key);
|
2013-04-25 13:46:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// static
|
2013-12-11 07:48:19 +00:00
|
|
|
void IDWeakMap::Get(const v8::FunctionCallbackInfo<v8::Value>& args) {
|
|
|
|
int key;
|
|
|
|
if (!FromV8Arguments(args, &key))
|
2013-04-25 13:46:04 +00:00
|
|
|
return node::ThrowTypeError("Bad argument");
|
|
|
|
|
2013-12-11 07:48:19 +00:00
|
|
|
IDWeakMap* self = Unwrap<IDWeakMap>(args.This());
|
|
|
|
if (!self->Has(key))
|
2013-04-25 13:46:04 +00:00
|
|
|
return node::ThrowError("Invalid key");
|
|
|
|
|
2013-12-11 07:48:19 +00:00
|
|
|
args.GetReturnValue().Set(self->map_[key]->NewHandle());
|
2013-04-25 13:46:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// static
|
2013-12-11 07:48:19 +00:00
|
|
|
void IDWeakMap::Has(const v8::FunctionCallbackInfo<v8::Value>& args) {
|
|
|
|
int key;
|
|
|
|
if (!FromV8Arguments(args, &key))
|
2013-04-25 13:46:04 +00:00
|
|
|
return node::ThrowTypeError("Bad argument");
|
|
|
|
|
2013-12-11 07:48:19 +00:00
|
|
|
IDWeakMap* self = Unwrap<IDWeakMap>(args.This());
|
|
|
|
args.GetReturnValue().Set(self->Has(key));
|
2013-04-25 13:46:04 +00:00
|
|
|
}
|
|
|
|
|
2013-04-27 08:54:17 +00:00
|
|
|
// static
|
2013-12-11 07:48:19 +00:00
|
|
|
void IDWeakMap::Keys(const v8::FunctionCallbackInfo<v8::Value>& args) {
|
|
|
|
IDWeakMap* self = Unwrap<IDWeakMap>(args.This());
|
2013-04-27 08:54:17 +00:00
|
|
|
|
2013-12-11 07:48:19 +00:00
|
|
|
v8::Local<v8::Array> keys = v8::Array::New(self->map_.size());
|
2013-04-27 08:54:17 +00:00
|
|
|
|
|
|
|
int i = 0;
|
2013-12-11 07:48:19 +00:00
|
|
|
for (auto el = self->map_.begin(); el != self->map_.end(); ++el) {
|
|
|
|
keys->Set(i, ToV8Value(el->first));
|
2013-04-27 08:54:17 +00:00
|
|
|
++i;
|
|
|
|
}
|
|
|
|
|
2013-12-11 07:48:19 +00:00
|
|
|
args.GetReturnValue().Set(keys);
|
2013-04-27 08:54:17 +00:00
|
|
|
}
|
|
|
|
|
2013-04-25 13:46:04 +00:00
|
|
|
// static
|
2013-12-11 07:48:19 +00:00
|
|
|
void IDWeakMap::Remove(const v8::FunctionCallbackInfo<v8::Value>& args) {
|
|
|
|
int key;
|
|
|
|
if (!FromV8Arguments(args, &key))
|
2013-04-25 13:46:04 +00:00
|
|
|
return node::ThrowTypeError("Bad argument");
|
|
|
|
|
2013-12-11 07:48:19 +00:00
|
|
|
IDWeakMap* self = Unwrap<IDWeakMap>(args.This());
|
|
|
|
if (!self->Has(key))
|
2013-04-25 13:46:04 +00:00
|
|
|
return node::ThrowError("Invalid key");
|
|
|
|
|
2013-12-11 07:48:19 +00:00
|
|
|
self->Erase(key);
|
2013-04-25 13:46:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// static
|
|
|
|
void IDWeakMap::Initialize(v8::Handle<v8::Object> target) {
|
2013-12-11 07:48:19 +00:00
|
|
|
v8::Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(New);
|
2013-04-25 13:46:04 +00:00
|
|
|
t->InstanceTemplate()->SetInternalFieldCount(1);
|
|
|
|
t->SetClassName(v8::String::NewSymbol("IDWeakMap"));
|
|
|
|
|
|
|
|
NODE_SET_PROTOTYPE_METHOD(t, "add", Add);
|
|
|
|
NODE_SET_PROTOTYPE_METHOD(t, "get", Get);
|
|
|
|
NODE_SET_PROTOTYPE_METHOD(t, "has", Has);
|
2013-04-27 08:54:17 +00:00
|
|
|
NODE_SET_PROTOTYPE_METHOD(t, "keys", Keys);
|
2013-04-25 13:46:04 +00:00
|
|
|
NODE_SET_PROTOTYPE_METHOD(t, "remove", Remove);
|
|
|
|
|
|
|
|
target->Set(v8::String::NewSymbol("IDWeakMap"), t->GetFunction());
|
|
|
|
}
|
|
|
|
|
|
|
|
} // namespace api
|
|
|
|
|
|
|
|
} // namespace atom
|
|
|
|
|
|
|
|
NODE_MODULE(atom_common_id_weak_map, atom::api::IDWeakMap::Initialize)
|