Line data Source code
1 : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /* vim: set ts=8 sts=4 et sw=4 tw=99: */
3 : /* This Source Code Form is subject to the terms of the Mozilla Public
4 : * License, v. 2.0. If a copy of the MPL was not distributed with this
5 : * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 :
7 : /*
8 : * nsScriptErrorWithStack implementation.
9 : * a main-thread-only, cycle-collected subclass of nsScriptErrorBase
10 : * that can store a SavedFrame stack trace object.
11 : */
12 :
13 : #include "nsScriptError.h"
14 : #include "MainThreadUtils.h"
15 : #include "mozilla/Assertions.h"
16 : #include "mozilla/dom/ScriptSettings.h"
17 : #include "nsGlobalWindow.h"
18 : #include "nsCycleCollectionParticipant.h"
19 :
20 : using namespace mozilla::dom;
21 :
22 : namespace {
23 :
24 : static nsCString
25 0 : FormatStackString(JSContext* cx, HandleObject aStack) {
26 0 : JS::RootedString formattedStack(cx);
27 :
28 0 : if (!JS::BuildStackString(cx, aStack, &formattedStack)) {
29 0 : return nsCString();
30 : }
31 :
32 0 : nsAutoJSString stackJSString;
33 0 : if (!stackJSString.init(cx, formattedStack)) {
34 0 : return nsCString();
35 : }
36 :
37 0 : return NS_ConvertUTF16toUTF8(stackJSString.get());
38 : }
39 :
40 : }
41 :
42 :
43 : NS_IMPL_CYCLE_COLLECTION_CLASS(nsScriptErrorWithStack)
44 :
45 0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsScriptErrorWithStack)
46 0 : tmp->mStack = nullptr;
47 0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_END
48 :
49 0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsScriptErrorWithStack)
50 0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
51 :
52 0 : NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(nsScriptErrorWithStack)
53 0 : NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mStack)
54 0 : NS_IMPL_CYCLE_COLLECTION_TRACE_END
55 :
56 0 : NS_IMPL_CYCLE_COLLECTING_ADDREF(nsScriptErrorWithStack)
57 0 : NS_IMPL_CYCLE_COLLECTING_RELEASE(nsScriptErrorWithStack)
58 :
59 0 : NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsScriptErrorWithStack)
60 0 : NS_INTERFACE_MAP_ENTRY(nsISupports)
61 0 : NS_INTERFACE_MAP_ENTRY(nsIConsoleMessage)
62 0 : NS_INTERFACE_MAP_ENTRY(nsIScriptError)
63 0 : NS_INTERFACE_MAP_END
64 :
65 0 : nsScriptErrorWithStack::nsScriptErrorWithStack(JS::HandleObject aStack)
66 0 : : mStack(aStack)
67 : {
68 0 : MOZ_ASSERT(NS_IsMainThread(), "You can't use this class on workers.");
69 0 : mozilla::HoldJSObjects(this);
70 0 : }
71 :
72 0 : nsScriptErrorWithStack::~nsScriptErrorWithStack() {
73 0 : mozilla::DropJSObjects(this);
74 0 : }
75 :
76 : NS_IMETHODIMP
77 0 : nsScriptErrorWithStack::Init(const nsAString& message,
78 : const nsAString& sourceName,
79 : const nsAString& sourceLine,
80 : uint32_t lineNumber,
81 : uint32_t columnNumber,
82 : uint32_t flags,
83 : const char* category)
84 : {
85 0 : MOZ_CRASH("nsScriptErrorWithStack requires to be initialized with a document, by using InitWithWindowID");
86 : }
87 :
88 : NS_IMETHODIMP
89 0 : nsScriptErrorWithStack::GetStack(JS::MutableHandleValue aStack) {
90 0 : aStack.setObjectOrNull(mStack);
91 0 : return NS_OK;
92 : }
93 :
94 : NS_IMETHODIMP
95 0 : nsScriptErrorWithStack::ToString(nsACString& /*UTF8*/ aResult)
96 : {
97 0 : MOZ_ASSERT(NS_IsMainThread());
98 :
99 0 : nsCString message;
100 0 : nsresult rv = nsScriptErrorBase::ToString(message);
101 0 : NS_ENSURE_SUCCESS(rv, rv);
102 :
103 0 : if (!mStack) {
104 0 : aResult.Assign(message);
105 0 : return NS_OK;
106 : }
107 :
108 0 : AutoJSAPI jsapi;
109 0 : if (!jsapi.Init(mStack)) {
110 0 : return NS_ERROR_FAILURE;
111 : }
112 :
113 0 : JSContext* cx = jsapi.cx();
114 0 : RootedObject stack(cx, mStack);
115 0 : nsCString stackString = FormatStackString(cx, stack);
116 0 : nsCString combined = message + NS_LITERAL_CSTRING("\n") + stackString;
117 0 : aResult.Assign(combined);
118 :
119 0 : return NS_OK;
120 : }
|