Skip to content

Instantly share code, notes, and snippets.

@abhi-bit
Created September 23, 2016 10:40
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save abhi-bit/505538ac45d4b11014c3681e3bb74a2b to your computer and use it in GitHub Desktop.
Save abhi-bit/505538ac45d4b11014c3681e3bb74a2b to your computer and use it in GitHub Desktop.
Allocation failed - Javascript heap out of memory
#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