diff --git a/v8js_v8inspector_class.cc b/v8js_v8inspector_class.cc index 8647129..628ebc4 100644 --- a/v8js_v8inspector_class.cc +++ b/v8js_v8inspector_class.cc @@ -18,6 +18,10 @@ #include "v8js_exceptions.h" #include "v8js_v8inspector_class.h" +#include + +#include + extern "C" { // #include "ext/date/php_date.h" @@ -39,18 +43,157 @@ static zend_object_handlers v8js_v8inspector_handlers; +#define kInspectorClientIndex 2 + +class InspectorFrontend final : public v8_inspector::V8Inspector::Channel { + public: + explicit InspectorFrontend(v8::Local context) { + isolate_ = context->GetIsolate(); + // context_.Reset(isolate_, context); + } + ~InspectorFrontend() override = default; + + private: + void sendResponse( + int callId, + std::unique_ptr message) override { + Send(message->string()); + } + void sendNotification( + std::unique_ptr message) override { + Send(message->string()); + } + void flushProtocolNotifications() override {} + + + void Send(const v8_inspector::StringView& string) { + v8::Isolate::AllowJavascriptExecutionScope allow_script(isolate_); + v8::HandleScope handle_scope(isolate_); + int length = static_cast(string.length()); + // DCHECK_LT(length, v8::String::kMaxLength); + v8::Local message = + (string.is8Bit() + ? v8::String::NewFromOneByte( + isolate_, + reinterpret_cast(string.characters8()), + v8::NewStringType::kNormal, length) + : v8::String::NewFromTwoByte( + isolate_, + reinterpret_cast(string.characters16()), + v8::NewStringType::kNormal, length)) + .ToLocalChecked(); + + v8::String::Utf8Value str(isolate_, message); + const char *cstr = ToCString(str); + // RETVAL_STRINGL(cstr, str.length()); + std::cout << cstr << std::endl; + } + + v8::Isolate* isolate_; + // Global context_; +}; + + +class InspectorClient : public v8_inspector::V8InspectorClient { + public: + InspectorClient(v8::Local context) { + isolate_ = context->GetIsolate(); + channel_.reset(new InspectorFrontend(context)); + inspector_ = v8_inspector::V8Inspector::create(isolate_, this); + session_ = + inspector_->connect(1, channel_.get(), v8_inspector::StringView()); + context->SetAlignedPointerInEmbedderData(kInspectorClientIndex, this); + inspector_->contextCreated(v8_inspector::V8ContextInfo( + context, kContextGroupId, v8_inspector::StringView())); + + /* Local function = + FunctionTemplate::New(isolate_, SendInspectorMessage) + ->GetFunction(context) + .ToLocalChecked(); + Local function_name = String::NewFromUtf8Literal( + isolate_, "send", NewStringType::kInternalized); + CHECK(context->Global()->Set(context, function_name, function).FromJust()); */ + + context_.Reset(isolate_, context); + } + + /* void runMessageLoopOnPause(int contextGroupId) override { + v8::Isolate::AllowJavascriptExecutionScope allow_script(isolate_); + v8::HandleScope handle_scope(isolate_); + Local callback_name = v8::String::NewFromUtf8Literal( + isolate_, "handleInspectorMessage", NewStringType::kInternalized); + Local context = context_.Get(isolate_); + Local callback = + context->Global()->Get(context, callback_name).ToLocalChecked(); + if (!callback->IsFunction()) return; + + v8::TryCatch try_catch(isolate_); + try_catch.SetVerbose(true); + is_paused = true; + + while (is_paused) { + USE(Local::Cast(callback)->Call(context, Undefined(isolate_), 0, + {})); + if (try_catch.HasCaught()) { + is_paused = false; + } + } + } + + void quitMessageLoopOnPause() override { is_paused = false; } */ + + private: + static v8_inspector::V8InspectorSession* GetSession(v8::Local context) { + InspectorClient* inspector_client = static_cast( + context->GetAlignedPointerFromEmbedderData(kInspectorClientIndex)); + return inspector_client->session_.get(); + } + + /* Local ensureDefaultContextInGroup(int group_id) override { + DCHECK(isolate_); + DCHECK_EQ(kContextGroupId, group_id); + return context_.Get(isolate_); + } */ + + /* static void SendInspectorMessage( + const v8::FunctionCallbackInfo& args) { + Isolate* isolate = args.GetIsolate(); + v8::HandleScope handle_scope(isolate); + Local context = isolate->GetCurrentContext(); + args.GetReturnValue().Set(Undefined(isolate)); + Local message = args[0]->ToString(context).ToLocalChecked(); + v8_inspector::V8InspectorSession* session = + InspectorClient::GetSession(context); + int length = message->Length(); + std::unique_ptr buffer(new uint16_t[length]); + message->Write(isolate, buffer.get(), 0, length); + v8_inspector::StringView message_view(buffer.get(), length); + { + v8::SealHandleScope seal_handle_scope(isolate); + session->dispatchProtocolMessage(message_view); + } + args.GetReturnValue().Set(True(isolate)); + } */ + + static const int kContextGroupId = 1; + + std::unique_ptr inspector_; + std::unique_ptr session_; + std::unique_ptr channel_; + // bool is_paused = false; + v8::Global context_; + v8::Isolate* isolate_; +}; + + + static void v8js_v8inspector_free_storage(zend_object *object) /* {{{ */ { v8js_v8inspector *c = v8js_v8inspector_fetch_object(object); - // TODO need to clean up? + delete c->client; zend_object_std_dtor(&c->std); - - /* if(c->ctx) { - c->v8obj.Reset(); - c->ctx->v8js_v8inspectors.remove(c); - } */ } /* }}} */ @@ -103,7 +246,11 @@ PHP_METHOD(V8Inspector, __wakeup) void v8js_v8inspector_create(zval *res, v8js_ctx *ctx) /* {{{ */ { object_init_ex(res, php_ce_v8inspector); - // v8js_v8inspector *inspector = Z_V8JS_V8INSPECTOR_OBJ_P(res); + v8js_v8inspector *inspector = Z_V8JS_V8INSPECTOR_OBJ_P(res); + + V8JS_CTX_PROLOGUE(ctx); + inspector->client = new InspectorClient(v8_context); + } /* }}} */ diff --git a/v8js_v8inspector_class.h b/v8js_v8inspector_class.h index b66db4c..9d83119 100644 --- a/v8js_v8inspector_class.h +++ b/v8js_v8inspector_class.h @@ -13,10 +13,11 @@ #ifndef V8JS_V8INSPECTOR_CLASS_H #define V8JS_V8INSPECTOR_CLASS_H +class InspectorClient; + /* {{{ Object container */ struct v8js_v8inspector { - // TODO add inspector class handle - // v8::Persistent v8obj; + InspectorClient *client; zend_object std; }; /* }}} */