summaryrefslogtreecommitdiff
path: root/platform
diff options
context:
space:
mode:
authorJohn Firebaugh <john.firebaugh@gmail.com>2015-11-20 16:09:58 -0800
committerJohn Firebaugh <john.firebaugh@gmail.com>2015-11-20 16:33:46 -0800
commitc4c3a19d85991b3c2703e7b6561d8c1a3fed3543 (patch)
tree93b548f7fa3875ee149455a2d41ecd7027b3e547 /platform
parent8a0bce780847546c161670420e4d0f1e3a6cbdca (diff)
downloadqtlocation-mapboxgl-c4c3a19d85991b3c2703e7b6561d8c1a3fed3543.tar.gz
[node] Allow GC in spite of reference loops through the request method
The following produces a reference cycle: var map = new mbgl.Map({ request: function () { ... } }); map has a reference to the request function, which has a reference to its closure, which has a reference to map. Storing a the map options in an internal field, rather than a Persistent, allows V8 to collect the reference cycle when none of its members have other references.
Diffstat (limited to 'platform')
-rw-r--r--platform/node/src/node_file_source.cpp38
-rw-r--r--platform/node/src/node_file_source.hpp25
-rw-r--r--platform/node/src/node_map.cpp33
-rw-r--r--platform/node/src/node_map.hpp9
-rw-r--r--platform/node/src/node_request.cpp1
5 files changed, 35 insertions, 71 deletions
diff --git a/platform/node/src/node_file_source.cpp b/platform/node/src/node_file_source.cpp
deleted file mode 100644
index 5d7973f851..0000000000
--- a/platform/node/src/node_file_source.cpp
+++ /dev/null
@@ -1,38 +0,0 @@
-#include "node_file_source.hpp"
-#include "node_request.hpp"
-#include "node_mapbox_gl_native.hpp"
-
-namespace node_mbgl {
-
-class NodeFileSourceRequest : public mbgl::FileRequest {
-public:
- std::unique_ptr<mbgl::WorkRequest> workRequest;
-};
-
-NodeFileSource::NodeFileSource(v8::Local<v8::Object> options_) {
- options.Reset(options_);
-}
-
-NodeFileSource::~NodeFileSource() {
- options.Reset();
-}
-
-std::unique_ptr<mbgl::FileRequest> NodeFileSource::request(const mbgl::Resource& resource, Callback callback) {
- auto req = std::make_unique<NodeFileSourceRequest>();
-
- // This function can be called from any thread. Make sure we're executing the
- // JS implementation in the node event loop.
- req->workRequest = NodeRunLoop().invokeWithCallback([this] (mbgl::Resource res, Callback cb) {
- Nan::HandleScope scope;
-
- auto requestHandle = NodeRequest::Create(res, cb)->ToObject();
- auto callbackHandle = Nan::GetFunction(Nan::New<v8::FunctionTemplate>(NodeRequest::Respond, requestHandle)).ToLocalChecked();
-
- v8::Local<v8::Value> argv[] = { requestHandle, callbackHandle };
- Nan::MakeCallback(Nan::New(options), "request", 2, argv);
- }, callback, resource);
-
- return std::move(req);
-}
-
-}
diff --git a/platform/node/src/node_file_source.hpp b/platform/node/src/node_file_source.hpp
deleted file mode 100644
index 2ce673fb50..0000000000
--- a/platform/node/src/node_file_source.hpp
+++ /dev/null
@@ -1,25 +0,0 @@
-#pragma once
-
-#include <mbgl/storage/file_source.hpp>
-
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wunused-parameter"
-#pragma GCC diagnostic ignored "-Wshadow"
-#pragma GCC diagnostic ignored "-Wnested-anon-types"
-#include <nan.h>
-#pragma GCC diagnostic pop
-
-namespace node_mbgl {
-
-class NodeFileSource : public mbgl::FileSource {
-public:
- NodeFileSource(v8::Local<v8::Object>);
- ~NodeFileSource();
-
- std::unique_ptr<mbgl::FileRequest> request(const mbgl::Resource&, Callback);
-
-private:
- Nan::Persistent<v8::Object> options;
-};
-
-}
diff --git a/platform/node/src/node_map.cpp b/platform/node/src/node_map.cpp
index 6e9230287e..99fbb919e4 100644
--- a/platform/node/src/node_map.cpp
+++ b/platform/node/src/node_map.cpp
@@ -1,8 +1,11 @@
#include "node_map.hpp"
+#include "node_request.hpp"
+#include "node_mapbox_gl_native.hpp"
#include <mbgl/platform/default/headless_display.hpp>
#include <mbgl/map/still_image.hpp>
#include <mbgl/util/exception.hpp>
+#include <mbgl/util/work_request.hpp>
#include <unistd.h>
@@ -42,7 +45,7 @@ const static char* releasedMessage() {
NAN_MODULE_INIT(NodeMap::Init) {
v8::Local<v8::FunctionTemplate> tpl = Nan::New<v8::FunctionTemplate>(New);
- tpl->InstanceTemplate()->SetInternalFieldCount(1);
+ tpl->InstanceTemplate()->SetInternalFieldCount(2);
tpl->SetClassName(Nan::New("Map").ToLocalChecked());
Nan::SetPrototypeMethod(tpl, "load", Load);
@@ -124,6 +127,8 @@ NAN_METHOD(NodeMap::New) {
return Nan::ThrowError("Options object 'ratio' property must be a number");
}
+ info.This()->SetInternalField(1, options);
+
try {
auto nodeMap = new NodeMap(options);
nodeMap->Wrap(info.This());
@@ -427,8 +432,7 @@ NodeMap::NodeMap(v8::Local<v8::Object> options) :
Nan::HandleScope scope;
return Nan::Has(options, Nan::New("ratio").ToLocalChecked()).FromJust() ? Nan::Get(options, Nan::New("ratio").ToLocalChecked()).ToLocalChecked()->NumberValue() : 1.0;
}()),
- fs(options),
- map(std::make_unique<mbgl::Map>(view, fs, mbgl::MapMode::Still)),
+ map(std::make_unique<mbgl::Map>(view, *this, mbgl::MapMode::Still)),
async(new uv_async_t) {
async->data = this;
@@ -444,4 +448,27 @@ NodeMap::~NodeMap() {
if (valid) release();
}
+class NodeFileSourceRequest : public mbgl::FileRequest {
+public:
+ std::unique_ptr<mbgl::WorkRequest> workRequest;
+};
+
+std::unique_ptr<mbgl::FileRequest> NodeMap::request(const mbgl::Resource& resource, Callback cb1) {
+ auto req = std::make_unique<NodeFileSourceRequest>();
+
+ // This function can be called from any thread. Make sure we're executing the
+ // JS implementation in the node event loop.
+ req->workRequest = NodeRunLoop().invokeWithCallback([this] (mbgl::Resource res, Callback cb2) {
+ Nan::HandleScope scope;
+
+ auto requestHandle = NodeRequest::Create(res, cb2)->ToObject();
+ auto callbackHandle = Nan::GetFunction(Nan::New<v8::FunctionTemplate>(NodeRequest::Respond, requestHandle)).ToLocalChecked();
+
+ v8::Local<v8::Value> argv[] = { requestHandle, callbackHandle };
+ Nan::MakeCallback(handle()->GetInternalField(1)->ToObject(), "request", 2, argv);
+ }, cb1, resource);
+
+ return std::move(req);
+}
+
}
diff --git a/platform/node/src/node_map.hpp b/platform/node/src/node_map.hpp
index 91cada17d1..f610408d3f 100644
--- a/platform/node/src/node_map.hpp
+++ b/platform/node/src/node_map.hpp
@@ -1,8 +1,7 @@
#pragma once
-#include "node_file_source.hpp"
-
#include <mbgl/map/map.hpp>
+#include <mbgl/storage/file_source.hpp>
#include <mbgl/platform/default/headless_view.hpp>
#pragma GCC diagnostic push
@@ -16,7 +15,8 @@
namespace node_mbgl {
-class NodeMap : public Nan::ObjectWrap {
+class NodeMap : public Nan::ObjectWrap,
+ public mbgl::FileSource {
public:
struct RenderOptions;
class RenderWorker;
@@ -43,8 +43,9 @@ public:
NodeMap(v8::Local<v8::Object>);
~NodeMap();
+ std::unique_ptr<mbgl::FileRequest> request(const mbgl::Resource&, Callback);
+
mbgl::HeadlessView view;
- NodeFileSource fs;
std::unique_ptr<mbgl::Map> map;
std::exception_ptr error;
diff --git a/platform/node/src/node_request.cpp b/platform/node/src/node_request.cpp
index e08e4ffd17..4575d42a7a 100644
--- a/platform/node/src/node_request.cpp
+++ b/platform/node/src/node_request.cpp
@@ -1,5 +1,4 @@
#include "node_request.hpp"
-#include "node_file_source.hpp"
#include <mbgl/storage/response.hpp>
#include <cmath>