isolate_);
if (!bindee.is_null() && bindee->IsJSFunction() &&
- !JSFunction::cast(*bindee)->IsNative()) {
+ !JSFunction::cast(*bindee)->IsFromNativeScript()) {
Handle<JSFunction> bindee_function(JSFunction::cast(*bindee));
Debug::FloodWithOneShot(bindee_function);
}
frames_it.Advance();
}
// Skip builtin functions on the stack.
- while (!frames_it.done() && frames_it.frame()->function()->IsNative()) {
+ while (!frames_it.done() &&
+ frames_it.frame()->function()->IsFromNativeScript()) {
frames_it.Advance();
}
// Step out: If there is a JavaScript caller frame, we need to
Handle<JSFunction> js_function(JSFunction::cast(fun));
if (js_function->shared()->bound()) {
Debug::FloodBoundFunctionWithOneShot(js_function);
- } else if (!js_function->IsNative()) {
+ } else if (!js_function->IsFromNativeScript()) {
// Don't step into builtins.
// It will also compile target function if it's not compiled yet.
FloodWithOneShot(js_function);
if (function->shared()->bound()) {
// Handle Function.prototype.bind
Debug::FloodBoundFunctionWithOneShot(function);
- } else if (!function->IsNative()) {
+ } else if (!function->IsFromNativeScript()) {
// Don't allow step into functions in the native context.
if (function->shared()->code() ==
isolate->builtins()->builtin(Builtins::kFunctionApply) ||
// function.
if (!holder.is_null() && holder->IsJSFunction()) {
Handle<JSFunction> js_function = Handle<JSFunction>::cast(holder);
- if (!js_function->IsNative()) {
+ if (!js_function->IsFromNativeScript()) {
Debug::FloodWithOneShot(js_function);
} else if (js_function->shared()->bound()) {
// Handle Function.prototype.bind
if (!shared->allows_lazy_compilation()) continue;
if (!shared->script()->IsScript()) continue;
- if (function->IsNative()) continue;
+ if (function->IsFromNativeScript()) continue;
if (shared->code()->gc_metadata() == active_code_marker) continue;
if (shared->is_generator()) {
// call to this function is encountered it is skipped. The seen_caller
// in/out parameter is used to remember if the caller has been seen
// yet.
-static bool IsVisibleInStackTrace(StackFrame* raw_frame,
+static bool IsVisibleInStackTrace(JSFunction* fun,
Object* caller,
+ Object* receiver,
bool* seen_caller) {
- // Only display JS frames.
- if (!raw_frame->is_java_script()) return false;
- JavaScriptFrame* frame = JavaScriptFrame::cast(raw_frame);
- JSFunction* fun = frame->function();
if ((fun == caller) && !(*seen_caller)) {
*seen_caller = true;
return false;
// The --builtins-in-stack-traces command line flag allows including
// internal call sites in the stack trace for debugging purposes.
if (!FLAG_builtins_in_stack_traces) {
- if (frame->receiver()->IsJSBuiltinsObject() ||
- (fun->IsBuiltin() && !fun->shared()->native())) {
+ if (receiver->IsJSBuiltinsObject()) return false;
+ if (fun->IsBuiltin()) {
+ return fun->shared()->native();
+ } else if (fun->IsFromNativeScript() || fun->IsFromExtensionScript()) {
return false;
}
}
int frames_seen = 0;
int sloppy_frames = 0;
bool encountered_strict_function = false;
- for (StackFrameIterator iter(this);
+ for (JavaScriptFrameIterator iter(this);
!iter.done() && frames_seen < limit;
iter.Advance()) {
- StackFrame* raw_frame = iter.frame();
- if (IsVisibleInStackTrace(raw_frame, *caller, &seen_caller)) {
- JavaScriptFrame* frame = JavaScriptFrame::cast(raw_frame);
- // Set initial size to the maximum inlining level + 1 for the outermost
- // function.
- List<FrameSummary> frames(FLAG_max_inlining_levels + 1);
- frame->Summarize(&frames);
- for (int i = frames.length() - 1; i >= 0; i--) {
- Handle<JSFunction> fun = frames[i].function();
- // Filter out frames from other security contexts.
- if (!this->context()->HasSameSecurityTokenAs(fun->context())) continue;
- if (cursor + 4 > elements->length()) {
- int new_capacity = JSObject::NewElementsCapacity(elements->length());
- Handle<FixedArray> new_elements =
- factory()->NewFixedArrayWithHoles(new_capacity);
- for (int i = 0; i < cursor; i++) {
- new_elements->set(i, elements->get(i));
- }
- elements = new_elements;
+ JavaScriptFrame* frame = iter.frame();
+ // Set initial size to the maximum inlining level + 1 for the outermost
+ // function.
+ List<FrameSummary> frames(FLAG_max_inlining_levels + 1);
+ frame->Summarize(&frames);
+ for (int i = frames.length() - 1; i >= 0; i--) {
+ Handle<JSFunction> fun = frames[i].function();
+ Handle<Object> recv = frames[i].receiver();
+ // Filter out internal frames that we do not want to show.
+ if (!IsVisibleInStackTrace(*fun, *caller, *recv, &seen_caller)) continue;
+ // Filter out frames from other security contexts.
+ if (!this->context()->HasSameSecurityTokenAs(fun->context())) continue;
+ if (cursor + 4 > elements->length()) {
+ int new_capacity = JSObject::NewElementsCapacity(elements->length());
+ Handle<FixedArray> new_elements =
+ factory()->NewFixedArrayWithHoles(new_capacity);
+ for (int i = 0; i < cursor; i++) {
+ new_elements->set(i, elements->get(i));
}
- ASSERT(cursor + 4 <= elements->length());
-
- Handle<Object> recv = frames[i].receiver();
- Handle<Code> code = frames[i].code();
- Handle<Smi> offset(Smi::FromInt(frames[i].offset()), this);
- // The stack trace API should not expose receivers and function
- // objects on frames deeper than the top-most one with a strict
- // mode function. The number of sloppy frames is stored as
- // first element in the result array.
- if (!encountered_strict_function) {
- if (fun->shared()->strict_mode() == STRICT) {
- encountered_strict_function = true;
- } else {
- sloppy_frames++;
- }
+ elements = new_elements;
+ }
+ ASSERT(cursor + 4 <= elements->length());
+
+
+ Handle<Code> code = frames[i].code();
+ Handle<Smi> offset(Smi::FromInt(frames[i].offset()), this);
+ // The stack trace API should not expose receivers and function
+ // objects on frames deeper than the top-most one with a strict
+ // mode function. The number of sloppy frames is stored as
+ // first element in the result array.
+ if (!encountered_strict_function) {
+ if (fun->shared()->strict_mode() == STRICT) {
+ encountered_strict_function = true;
+ } else {
+ sloppy_frames++;
}
- elements->set(cursor++, *recv);
- elements->set(cursor++, *fun);
- elements->set(cursor++, *code);
- elements->set(cursor++, *offset);
}
+ elements->set(cursor++, *recv);
+ elements->set(cursor++, *fun);
+ elements->set(cursor++, *code);
+ elements->set(cursor++, *offset);
frames_seen++;
}
}
}
+static const char* kStackTraceFromExtensionSource =
+ "function foo() {"
+ " throw new Error();"
+ "}"
+ "function bar() {"
+ " foo();"
+ "}";
+
+
+TEST(StackTraceInExtension) {
+ v8::HandleScope handle_scope(CcTest::isolate());
+ v8::RegisterExtension(new Extension("stacktracetest",
+ kStackTraceFromExtensionSource));
+ const char* extension_names[] = { "stacktracetest" };
+ v8::ExtensionConfiguration extensions(1, extension_names);
+ v8::Handle<Context> context =
+ Context::New(CcTest::isolate(), &extensions);
+ Context::Scope lock(context);
+ CompileRun("function user() { bar(); }"
+ "var error;"
+ "try{ user(); } catch (e) { error = e; }");
+ CHECK_EQ(-1, CompileRun("error.stack.indexOf('foo')")->Int32Value());
+ CHECK_EQ(-1, CompileRun("error.stack.indexOf('bar')")->Int32Value());
+ CHECK_NE(-1, CompileRun("error.stack.indexOf('user')")->Int32Value());
+}
+
+
TEST(NullExtensions) {
v8::HandleScope handle_scope(CcTest::isolate());
v8::RegisterExtension(new Extension("nulltest", NULL));