kFunctionName = 1 << 3,
kIsEval = 1 << 4,
kIsConstructor = 1 << 5,
+ kScriptNameOrSourceURL = 1 << 6,
kOverview = kLineNumber | kColumnOffset | kScriptName | kFunctionName,
- kDetailed = kOverview | kIsEval | kIsConstructor
+ kDetailed = kOverview | kIsEval | kIsConstructor | kScriptNameOrSourceURL
};
/**
Local<String> GetScriptName() const;
/**
+ * Returns the name of the resource that contains the script for the
+ * function for this StackFrame or sourceURL value if the script name
+ * is undefined and its source ends with //@ sourceURL=... string.
+ */
+ Local<String> GetScriptNameOrSourceURL() const;
+
+ /**
* Returns the name of the function associated with this stack frame.
*/
Local<String> GetFunctionName() const;
}
+Local<String> StackFrame::GetScriptNameOrSourceURL() const {
+ if (IsDeadCheck("v8::StackFrame::GetScriptNameOrSourceURL()")) {
+ return Local<String>();
+ }
+ ENTER_V8;
+ HandleScope scope;
+ i::Handle<i::JSObject> self = Utils::OpenHandle(this);
+ i::Handle<i::Object> name = GetProperty(self, "scriptNameOrSourceURL");
+ if (!name->IsString()) {
+ return Local<String>();
+ }
+ return scope.Close(Local<String>::Cast(Utils::ToLocal(name)));
+}
+
+
Local<String> StackFrame::GetFunctionName() const {
if (IsDeadCheck("v8::StackFrame::GetFunctionName()")) return Local<String>();
ENTER_V8;
SetProperty(stackFrame, script_key, script_name, NONE);
}
+ if (options & StackTrace::kScriptNameOrSourceURL) {
+ Handle<Object> script_name(script->name());
+ Handle<String> method_name =
+ Factory::LookupAsciiSymbol("nameOrSourceURL");
+ Handle<JSValue> script_wrapper = GetScriptWrapper(Handle<Script>(script));
+ Handle<Object> property = GetProperty(script_wrapper, method_name);
+ ASSERT(property->IsJSFunction());
+ Handle<JSFunction> method = Handle<JSFunction>::cast(property);
+ bool caught_exception;
+ Handle<Object> result = Execution::TryCall(method, script_wrapper, 0,
+ NULL, &caught_exception);
+ if (caught_exception) {
+ result = Factory::undefined_value();
+ }
+ Handle<String> script_name_or_source_url_key =
+ Factory::LookupAsciiSymbol("scriptNameOrSourceURL");
+ SetProperty(stackFrame, script_name_or_source_url_key, result, NONE);
+ }
+
if (options & StackTrace::kFunctionName) {
Handle<Object> fun_name(fun->shared()->name());
if (fun_name->ToBoolean()->IsFalse()) {
}
+v8::Handle<Value> AnalyzeStackOfEvalWithSourceURL(const v8::Arguments& args) {
+ v8::HandleScope scope;
+ v8::Handle<v8::StackTrace> stackTrace =
+ v8::StackTrace::CurrentStackTrace(10, v8::StackTrace::kDetailed);
+ CHECK_EQ(5, stackTrace->GetFrameCount());
+ v8::Handle<v8::String> url = v8_str("eval_url");
+ for (int i = 0; i < 3; i++) {
+ v8::Handle<v8::String> name =
+ stackTrace->GetFrame(i)->GetScriptNameOrSourceURL();
+ CHECK(!name.IsEmpty());
+ CHECK_EQ(url, name);
+ }
+ return v8::Undefined();
+}
+
+
+TEST(SourceURLInStackTrace) {
+ v8::HandleScope scope;
+ Local<ObjectTemplate> templ = ObjectTemplate::New();
+ templ->Set(v8_str("AnalyzeStackOfEvalWithSourceURL"),
+ v8::FunctionTemplate::New(AnalyzeStackOfEvalWithSourceURL));
+ LocalContext context(0, templ);
+
+ const char *source =
+ "function outer() {\n"
+ "function bar() {\n"
+ " AnalyzeStackOfEvalWithSourceURL();\n"
+ "}\n"
+ "function foo() {\n"
+ "\n"
+ " bar();\n"
+ "}\n"
+ "foo();\n"
+ "}\n"
+ "eval('(' + outer +')()//@ sourceURL=eval_url');";
+ CHECK(CompileRun(source)->IsUndefined());
+}
+
+
// Test that idle notification can be handled and eventually returns true.
THREADED_TEST(IdleNotification) {
bool rv = false;