Created
September 23, 2016 10:40
-
-
Save abhi-bit/505538ac45d4b11014c3681e3bb74a2b to your computer and use it in GitHub Desktop.
Allocation failed - Javascript heap out of memory
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <cassert> | |
#include <cstdio> | |
#include <cstring> | |
#include <fstream> | |
#include <iostream> | |
#include <map> | |
#include <string> | |
#include <vector> | |
#include <include/v8.h> | |
#include <include/libplatform/libplatform.h> | |
using namespace std; | |
using namespace v8; | |
class HTTPResponse { | |
public: | |
HTTPResponse(Isolate* isolate); | |
~HTTPResponse(); | |
Local<Object> WrapHTTPResponseMap(); | |
Isolate* GetIsolate() { return isolate_; } | |
Global<ObjectTemplate> http_response_map_template_; | |
map<string, string> http_response; | |
private: | |
static Local<ObjectTemplate> MakeHTTPResponseMapTemplate(Isolate* isolate); | |
static void HTTPResponseGet(Local<Name> name, | |
const PropertyCallbackInfo<Value>& info); | |
Isolate* isolate_; | |
}; | |
class HTTPBody { | |
public: | |
HTTPBody(Isolate* isolate); | |
~HTTPBody(); | |
Local<Object> WrapHTTPBodyMap(); | |
Isolate* GetIsolate() { return isolate_; } | |
map<string, string> http_body; | |
private: | |
static void HTTPBodySet(Local<Name> name, Local<Value> value, | |
const PropertyCallbackInfo<Value>& info); | |
Isolate* isolate_; | |
}; | |
// ================================================================ | |
map<string, string>* UnwrapMap(Local<Object> obj) { | |
Local<External> field = Local<External>::Cast(obj->GetInternalField(0)); | |
void* ptr = field->Value(); | |
return static_cast<map<string, string>*>(ptr); | |
} | |
string ObjectToString(Local<Value> value) { | |
String::Utf8Value utf8_value(value); | |
return string(*utf8_value); | |
} | |
string ToString(Isolate* isolate, Handle<Value> object) { | |
HandleScope handle_scope(isolate); | |
Local<Context> context = isolate->GetCurrentContext(); | |
Local<Object> global = context->Global(); | |
Local<Object> JSON = global->Get(String::NewFromUtf8(isolate, "JSON"))->ToObject(); | |
Local<Function> JSON_stringify = | |
Local<Function>::Cast(JSON->Get( | |
String::NewFromUtf8(isolate, "stringify"))); | |
Local<Value> result; | |
Local<Value> args[1]; | |
args[0] = { object }; | |
result = JSON_stringify->Call(context->Global(), 1, args); | |
return ObjectToString(result); | |
} | |
// ================================================================ | |
HTTPBody::HTTPBody(Isolate* isolate) { | |
isolate_ = isolate; | |
} | |
HTTPBody::~HTTPBody() { } | |
void HTTPBody::HTTPBodySet(Local<Name> name, Local<Value> value_obj, | |
const PropertyCallbackInfo<Value>& info) { | |
if (name->IsSymbol()) return; | |
string key = ObjectToString(Local<String>::Cast(name)); | |
string value = ToString(info.GetIsolate(), value_obj); | |
map<string, string>* body = UnwrapMap(info.Holder()); | |
(*body)[key] = value; | |
std::cout << "key: " << key << " value: " << value << std::endl; | |
info.GetReturnValue().Set(value_obj); | |
} | |
Local<Object> HTTPBody::WrapHTTPBodyMap() { | |
EscapableHandleScope handle_scope(GetIsolate()); | |
Local<FunctionTemplate> body_map_template = FunctionTemplate::New(GetIsolate()); | |
body_map_template->InstanceTemplate()->SetHandler( | |
NamedPropertyHandlerConfiguration(NULL, HTTPBodySet)); | |
body_map_template->InstanceTemplate()->SetInternalFieldCount(1); | |
Local<Object> result = body_map_template->GetFunction()->NewInstance(); | |
Local<External> map_ptr = External::New(GetIsolate(), &http_body); | |
result->SetInternalField(0, map_ptr); | |
return handle_scope.Escape(result); | |
} | |
HTTPResponse::HTTPResponse(Isolate* isolate) { | |
isolate_ = isolate; | |
} | |
HTTPResponse::~HTTPResponse() { } | |
void HTTPResponse::HTTPResponseGet(Local<Name> name, | |
const PropertyCallbackInfo<Value>& info) { | |
if (name->IsSymbol()) return; | |
string key = ObjectToString(Local<String>::Cast(name)); | |
HTTPBody* body = new HTTPBody(info.GetIsolate()); | |
Local<Object> body_map = body->WrapHTTPBodyMap(); | |
info.GetReturnValue().Set(body_map); | |
} | |
Local<ObjectTemplate> HTTPResponse::MakeHTTPResponseMapTemplate( | |
Isolate* isolate) { | |
EscapableHandleScope handle_scope(isolate); | |
Local<ObjectTemplate> result = ObjectTemplate::New(isolate); | |
result->SetInternalFieldCount(2); | |
result->SetHandler(NamedPropertyHandlerConfiguration(HTTPResponseGet)); | |
return handle_scope.Escape(result); | |
} | |
Local<Object> HTTPResponse::WrapHTTPResponseMap() { | |
EscapableHandleScope handle_scope(GetIsolate()); | |
if (http_response_map_template_.IsEmpty()) { | |
Local<ObjectTemplate> raw_template = MakeHTTPResponseMapTemplate(GetIsolate()); | |
http_response_map_template_.Reset(GetIsolate(), raw_template); | |
} | |
Local<ObjectTemplate> templ = | |
Local<ObjectTemplate>::New(GetIsolate(), http_response_map_template_); | |
Local<Object> result = | |
templ->NewInstance(GetIsolate()->GetCurrentContext()).ToLocalChecked(); | |
Local<External> map_ptr = External::New(GetIsolate(), &http_response); | |
Local<External> isolate_ptr = External::New(GetIsolate(), isolate_); | |
result->SetInternalField(0, map_ptr); | |
result->SetInternalField(1, isolate_ptr); | |
return handle_scope.Escape(result); | |
} | |
class ArrayBufferAllocator : public v8::ArrayBuffer::Allocator { | |
public: | |
virtual void* Allocate(size_t length) { | |
void* data = AllocateUninitialized(length); | |
return data == NULL ? data : memset(data, 0, length); | |
} | |
virtual void* AllocateUninitialized(size_t length) { return malloc(length); } | |
virtual void Free(void* data, size_t) { free(data); } | |
}; | |
const char* js_function = | |
"function OnHTTPGet(req, res) {" | |
" res.body.query_result = 100;" | |
" res.body.row_count = 1;" | |
"}"; | |
int main(int argc, char* argv[]) { | |
V8::InitializeICU(); | |
V8::InitializeExternalStartupData(argv[0]); | |
Platform* platform = platform::CreateDefaultPlatform(); | |
V8::InitializePlatform(platform); | |
V8::Initialize(); | |
ArrayBufferAllocator allocator; | |
Isolate::CreateParams create_params; | |
create_params.array_buffer_allocator = &allocator; | |
Isolate* isolate = Isolate::New(create_params); | |
{ | |
Isolate::Scope isolate_scope(isolate); | |
HandleScope handle_scope(isolate); | |
Local<Context> context = Context::New(isolate); | |
Context::Scope context_scope(context); | |
Local<String> source = | |
String::NewFromUtf8(isolate, js_function, NewStringType::kNormal) | |
.ToLocalChecked(); | |
Local<Script> script = Script::Compile(context, source).ToLocalChecked(); | |
Local<Value> result = script->Run(context).ToLocalChecked(); | |
const char* http_req = "{\"path\": \"/root\"}"; | |
HTTPResponse* response = new HTTPResponse(isolate); | |
Handle<Value> args[2]; | |
args[0] = JSON::Parse(String::NewFromUtf8(isolate, http_req)); | |
args[1] = response->WrapHTTPResponseMap(); | |
Local<String> on_http_get = | |
String::NewFromUtf8(isolate, "OnHTTPGet", NewStringType::kNormal) | |
.ToLocalChecked(); | |
Local<Value> on_http_get_val; | |
if(!context->Global()->Get(context, on_http_get).ToLocal(&on_http_get_val)) | |
cout << "Failed to grab OnHTTPGet function " << endl; | |
if(on_http_get_val->IsFunction()) | |
cout << "Yes it's a function" << endl; | |
Local<Function> on_http_get_fun = Local<Function>::Cast(on_http_get_val); | |
while(true) { | |
on_http_get_fun->Call(context->Global(), 2, args); | |
} | |
} | |
isolate->Dispose(); | |
V8::Dispose(); | |
V8::ShutdownPlatform(); | |
delete platform; | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment