Skip to content

Commit 5722f5d

Browse files
committed
Added InjectedScriptHost.cc
1 parent ba1174f commit 5722f5d

File tree

5 files changed

+347
-295
lines changed

5 files changed

+347
-295
lines changed

binding.gyp

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,24 @@
11
{
2+
'variables': {
3+
'node_next': '<!(node -e "console.log(process.versions.modules > 45)")'
4+
},
25
'targets': [
36
{
47
'target_name': 'debug',
58
'win_delay_load_hook': 'true',
69
'sources': [
7-
'src/debug.cc',
10+
'src/debug.cc'
811
],
912
'include_dirs' : [
1013
"<!(node -e \"require('nan')\")"
14+
],
15+
'conditions' : [
16+
['node_next=="true"', {
17+
'sources': [
18+
'src/InjectedScriptHost.cc'
19+
],
20+
'defines': ['NODE_NEXT=true']
21+
}]
1122
]
1223
},
1324
{

src/InjectedScriptHost.cc

Lines changed: 263 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,263 @@
1+
#include <v8-debug.h>
2+
3+
#include "InjectedScriptHost.h"
4+
#include "tools.h"
5+
6+
using v8::Isolate;
7+
using v8::Handle;
8+
using v8::Local;
9+
using v8::Value;
10+
using v8::Boolean;
11+
using v8::Number;
12+
using v8::Integer;
13+
using v8::String;
14+
using v8::Object;
15+
using v8::Array;
16+
using v8::Message;
17+
using v8::Function;
18+
using Nan::To;
19+
using Nan::New;
20+
using Nan::Get;
21+
using Nan::Set;
22+
using Nan::ForceSet;
23+
using Nan::SetMethod;
24+
using Nan::EscapableHandleScope;
25+
using Nan::Undefined;
26+
using Nan::TryCatch;
27+
using Nan::ThrowError;
28+
using Nan::ThrowTypeError;
29+
using Nan::MaybeLocal;
30+
using Nan::EmptyString;
31+
using Nan::Utf8String;
32+
33+
namespace nodex {
34+
void InjectedScriptHost::Initialize(Handle<Object> target) {
35+
Local<Object> injectedScriptHost = New<Object>();
36+
SetMethod(injectedScriptHost, "eval", Eval);
37+
SetMethod(injectedScriptHost, "evaluateWithExceptionDetails", EvaluateWithExceptionDetails);
38+
SetMethod(injectedScriptHost, "setNonEnumProperty", SetNonEnumProperty);
39+
SetMethod(injectedScriptHost, "subtype", Subtype);
40+
SetMethod(injectedScriptHost, "internalConstructorName", InternalConstructorName);
41+
SetMethod(injectedScriptHost, "functionDetailsWithoutScopes", FunctionDetailsWithoutScopes);
42+
SetMethod(injectedScriptHost, "callFunction", CallFunction);
43+
44+
SET(target, "InjectedScriptHost", injectedScriptHost);
45+
}
46+
47+
Handle<Object> InjectedScriptHost::createExceptionDetails(Handle<Message> message) {
48+
EscapableHandleScope scope;
49+
50+
Local<Object> exceptionDetails = New<Object>();
51+
SET(exceptionDetails, "text", message->Get());
52+
53+
SET(exceptionDetails, "url", message->GetScriptOrigin().ResourceName());
54+
SET(exceptionDetails, "scriptId", New<Integer>((int32_t)message->GetScriptOrigin().ScriptID()->Value()));
55+
SET(exceptionDetails, "line", New<Integer>(message->GetLineNumber()));
56+
SET(exceptionDetails, "column", New<Number>(message->GetStartColumn()));
57+
58+
if (!message->GetStackTrace().IsEmpty())
59+
SET(exceptionDetails, "stackTrace", message->GetStackTrace()->AsArray());
60+
else
61+
SET(exceptionDetails, "stackTrace", Undefined());
62+
63+
return scope.Escape(exceptionDetails);
64+
};
65+
66+
NAN_METHOD(InjectedScriptHost::EvaluateWithExceptionDetails) {
67+
if (info.Length() < 1)
68+
return ThrowError("One argument expected.");
69+
70+
Local<Object> wrappedResult = New<Object>();
71+
Local<String> expression = CHK(To<String>(info[0]));
72+
if (expression.IsEmpty())
73+
return ThrowTypeError("The argument must be a string.");
74+
75+
TryCatch tryCatch;
76+
MaybeLocal<Value> result;
77+
RUNSCRIPT(expression, result);
78+
79+
if (tryCatch.HasCaught()) {
80+
SET(wrappedResult, "result", tryCatch.Exception());
81+
SET(wrappedResult, "exceptionDetails", createExceptionDetails(tryCatch.Message()));
82+
} else {
83+
SET(wrappedResult, "result", CHK(result));
84+
SET(wrappedResult, "exceptionDetails", Undefined());
85+
}
86+
87+
RETURN(wrappedResult);
88+
};
89+
90+
NAN_METHOD(InjectedScriptHost::SetNonEnumProperty) {
91+
if (info.Length() < 3)
92+
return ThrowError("Three arguments expected.");
93+
if (!info[0]->IsObject())
94+
return ThrowTypeError("Argument 0 must be an object.");
95+
if (!info[1]->IsString())
96+
return ThrowTypeError("Argument 1 must be a string.");
97+
98+
Local<Object> object = CHK(To<Object>(info[0]));
99+
ForceSet(object, info[1], info[2], v8::DontEnum);
100+
101+
RETURN(Undefined());
102+
};
103+
104+
NAN_METHOD(InjectedScriptHost::Subtype) {
105+
if (info.Length() < 1)
106+
return ThrowError("One argument expected.");
107+
108+
Local<Value> value = info[0];
109+
if (value->IsArray() || value->IsTypedArray() || value->IsArgumentsObject())
110+
RETURN(CHK(New("array")));
111+
112+
if (value->IsDate())
113+
RETURN(CHK(New("date")));
114+
115+
if (value->IsRegExp())
116+
RETURN(CHK(New("regexp")));
117+
118+
if (value->IsMap() || value->IsWeakMap())
119+
RETURN(CHK(New("map")));
120+
121+
if (value->IsSet() || value->IsWeakSet())
122+
RETURN(CHK(New("set")));
123+
124+
if (value->IsMapIterator() || value->IsSetIterator())
125+
RETURN(CHK(New("iterator")));
126+
127+
if (value->IsGeneratorObject())
128+
RETURN(CHK(New("generator")));
129+
130+
if (value->IsNativeError())
131+
RETURN(CHK(New("error")));
132+
133+
RETURN(Undefined());
134+
};
135+
136+
Local<String> InjectedScriptHost::functionDisplayName(Handle<Function> function) {
137+
EscapableHandleScope scope;
138+
139+
Local<String> value = CHK(To<String>(function->GetDisplayName()));
140+
if (value->Length())
141+
return scope.Escape(value);
142+
143+
value = CHK(To<String>(function->GetName()));
144+
if (value->Length())
145+
return scope.Escape(value);
146+
147+
value = CHK(To<String>(function->GetInferredName()));
148+
if (value->Length())
149+
return scope.Escape(value);
150+
151+
return scope.Escape(EmptyString());
152+
};
153+
154+
NAN_METHOD(InjectedScriptHost::InternalConstructorName) {
155+
if (info.Length() < 1)
156+
return ThrowError("One argument expected.");
157+
if (!info[0]->IsObject())
158+
return ThrowTypeError("The argument must be an object.");
159+
160+
Local<Object> object = CHK(To<Object>(info[0]));
161+
Local<String> result = object->GetConstructorName();
162+
163+
const char* result_type;
164+
if (result.IsEmpty() || result->IsNull() || result->IsUndefined())
165+
result_type = "";
166+
else
167+
result_type = *Utf8String(info[0]);
168+
169+
if (!result.IsEmpty() && strcmp(result_type, "Object") == 0) {
170+
Local<String> constructorSymbol = CHK(New("constructor"));
171+
if (object->HasRealNamedProperty(constructorSymbol) && !object->HasRealNamedCallbackProperty(constructorSymbol)) {
172+
TryCatch tryCatch;
173+
Local<Value> constructor = object->GetRealNamedProperty(constructorSymbol);
174+
if (!constructor.IsEmpty() && constructor->IsFunction()) {
175+
Local<String> constructorName = functionDisplayName(Handle<Function>::Cast(constructor));
176+
if (!constructorName.IsEmpty() && !tryCatch.HasCaught())
177+
result = constructorName;
178+
}
179+
}
180+
if (strcmp(result_type, "Object") == 0 && object->IsFunction())
181+
result = CHK(New("Function"));
182+
}
183+
184+
RETURN(result);
185+
}
186+
187+
NAN_METHOD(InjectedScriptHost::FunctionDetailsWithoutScopes) {
188+
if (info.Length() < 1)
189+
return ThrowError("One argument expected.");
190+
191+
if (!info[0]->IsFunction())
192+
return ThrowTypeError("The argument must be a function.");
193+
194+
Local<Function> function = Local<Function>::Cast(info[0]);
195+
int32_t lineNumber = function->GetScriptLineNumber();
196+
int32_t columnNumber = function->GetScriptColumnNumber();
197+
198+
Local<Object> location = New<Object>();
199+
SET(location, "lineNumber", New(lineNumber));
200+
SET(location, "columnNumber", New(columnNumber));
201+
SET(location, "scriptId", CHK(To<String>(New(function->ScriptId()))));
202+
203+
Local<Object> result = New<Object>();
204+
SET(result, "location", location);
205+
206+
Handle<String> name = functionDisplayName(function);
207+
SET(result, "functionName", name.IsEmpty() ? EmptyString() : name);
208+
209+
SET(result, "isGenerator", New<Boolean>(function->IsGeneratorFunction()));
210+
211+
RETURN(result);
212+
}
213+
214+
NAN_METHOD(InjectedScriptHost::CallFunction) {
215+
if (info.Length() < 2 || info.Length() > 3)
216+
return ThrowError("Two or three arguments expected.");
217+
if (!info[0]->IsFunction())
218+
return ThrowTypeError("Argument 0 must be a function.");
219+
220+
Handle<Function> function = Handle<Function>::Cast(info[0]);
221+
Handle<Value> receiver = info[1];
222+
223+
TryCatch tryCatch;
224+
MaybeLocal<Value> result;
225+
226+
if (info.Length() < 3 || info[2]->IsUndefined()) {
227+
result = function->Call(receiver, 0, NULL);
228+
MAYBE_RETHROW();
229+
RETURN(CHK(result));
230+
}
231+
232+
if (!info[2]->IsArray())
233+
return ThrowTypeError("Argument 2 must be an array.");
234+
235+
Handle<Array> arguments = Handle<Array>::Cast(info[2]);
236+
int argc = arguments->Length();
237+
Handle<Value> *argv = new Handle<Value>[argc];
238+
for (int i = 0; i < argc; ++i)
239+
argv[i] = CHK(Get(arguments, i));
240+
241+
result = function->Call(receiver, argc, argv);
242+
delete [] argv;
243+
244+
MAYBE_RETHROW();
245+
RETURN(CHK(result));
246+
};
247+
248+
NAN_METHOD(InjectedScriptHost::Eval) {
249+
if (info.Length() < 1)
250+
return ThrowError("One argument expected.");
251+
252+
Local<String> expression = info[0]->ToString();
253+
if (expression.IsEmpty())
254+
return ThrowTypeError("The argument must be a string.");
255+
256+
TryCatch tryCatch;
257+
MaybeLocal<Value> result;
258+
RUNSCRIPT(expression, result);
259+
MAYBE_RETHROW();
260+
261+
RETURN(CHK(result));
262+
};
263+
}

src/InjectedScriptHost.h

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
#ifndef X_INJECTED_SCRIPT_HOST_
2+
#define X_INJECTED_SCRIPT_HOST_
3+
4+
#include <nan.h>
5+
6+
namespace nodex {
7+
8+
class InjectedScriptHost {
9+
public:
10+
static void Initialize(v8::Handle<v8::Object> target);
11+
static NAN_METHOD(Eval);
12+
static NAN_METHOD(EvaluateWithExceptionDetails);
13+
static NAN_METHOD(SetNonEnumProperty);
14+
static NAN_METHOD(Subtype);
15+
static NAN_METHOD(InternalConstructorName);
16+
static NAN_METHOD(FunctionDetailsWithoutScopes);
17+
static NAN_METHOD(CallFunction);
18+
/*
19+
static v8::Local<v8::Value> New(const v8::CpuProfile* node);
20+
static Nan::Persistent<v8::Array> profiles;
21+
*/
22+
private:
23+
static v8::Handle<v8::Object> createExceptionDetails(v8::Handle<v8::Message> message);
24+
static v8::Local<v8::String> functionDisplayName(v8::Handle<v8::Function> function);
25+
26+
/*
27+
static NAN_METHOD(Delete);
28+
static void Initialize();
29+
static Nan::Persistent<v8::ObjectTemplate> profile_template_;
30+
static uint32_t uid_counter;
31+
*/
32+
};
33+
34+
} //namespace nodex
35+
#endif // X_INJECTED_SCRIPT_HOST_

0 commit comments

Comments
 (0)