OLD | NEW |
| (Empty) |
1 /* | |
2 * Copyright (c) 2010 Google Inc. All rights reserved. | |
3 * | |
4 * Redistribution and use in source and binary forms, with or without | |
5 * modification, are permitted provided that the following conditions are | |
6 * met: | |
7 * | |
8 * * Redistributions of source code must retain the above copyright | |
9 * notice, this list of conditions and the following disclaimer. | |
10 * * Redistributions in binary form must reproduce the above | |
11 * copyright notice, this list of conditions and the following disclaimer | |
12 * in the documentation and/or other materials provided with the | |
13 * distribution. | |
14 * * Neither the name of Google Inc. nor the names of its | |
15 * contributors may be used to endorse or promote products derived from | |
16 * this software without specific prior written permission. | |
17 * | |
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | |
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | |
22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
29 */ | |
30 | |
31 #include "sky/engine/config.h" | |
32 #include "sky/engine/core/inspector/ScriptArguments.h" | |
33 | |
34 #include "sky/engine/bindings/core/v8/ScriptValue.h" | |
35 #include "sky/engine/bindings/core/v8/V8Binding.h" | |
36 #include "sky/engine/wtf/text/StringBuilder.h" | |
37 #include "v8/include/v8.h" | |
38 | |
39 namespace blink { | |
40 | |
41 namespace { | |
42 | |
43 static const unsigned maxArrayItemsLimit = 10000; | |
44 static const unsigned maxStackDepthLimit = 32; | |
45 | |
46 class V8ValueStringBuilder { | |
47 public: | |
48 static String toString(v8::Handle<v8::Value> value, v8::Isolate* isolate) | |
49 { | |
50 V8ValueStringBuilder builder(isolate); | |
51 if (!builder.append(value)) | |
52 return String(); | |
53 return builder.toString(); | |
54 } | |
55 | |
56 private: | |
57 enum { | |
58 IgnoreNull = 1 << 0, | |
59 IgnoreUndefined = 1 << 1, | |
60 }; | |
61 | |
62 V8ValueStringBuilder(v8::Isolate* isolate) | |
63 : m_arrayLimit(maxArrayItemsLimit) | |
64 , m_isolate(isolate) | |
65 { | |
66 } | |
67 | |
68 bool append(v8::Handle<v8::Value> value, unsigned ignoreOptions = 0) | |
69 { | |
70 if (value.IsEmpty()) | |
71 return true; | |
72 if ((ignoreOptions & IgnoreNull) && value->IsNull()) | |
73 return true; | |
74 if ((ignoreOptions & IgnoreUndefined) && value->IsUndefined()) | |
75 return true; | |
76 if (value->IsString()) | |
77 return append(v8::Handle<v8::String>::Cast(value)); | |
78 if (value->IsStringObject()) | |
79 return append(v8::Handle<v8::StringObject>::Cast(value)->ValueOf()); | |
80 if (value->IsSymbol()) | |
81 return append(v8::Handle<v8::Symbol>::Cast(value)); | |
82 if (value->IsSymbolObject()) | |
83 return append(v8::Handle<v8::SymbolObject>::Cast(value)->ValueOf()); | |
84 if (value->IsNumberObject()) { | |
85 m_builder.appendNumber(v8::Handle<v8::NumberObject>::Cast(value)->Va
lueOf()); | |
86 return true; | |
87 } | |
88 if (value->IsBooleanObject()) { | |
89 m_builder.append(v8::Handle<v8::BooleanObject>::Cast(value)->ValueOf
() ? "true" : "false"); | |
90 return true; | |
91 } | |
92 if (value->IsArray()) | |
93 return append(v8::Handle<v8::Array>::Cast(value)); | |
94 if (toDOMWindow(value, m_isolate)) { | |
95 m_builder.append("[object Window]"); | |
96 return true; | |
97 } | |
98 if (value->IsObject() | |
99 && !value->IsDate() | |
100 && !value->IsFunction() | |
101 && !value->IsNativeError() | |
102 && !value->IsRegExp()) | |
103 return append(v8::Handle<v8::Object>::Cast(value)->ObjectProtoToStri
ng()); | |
104 return append(value->ToString()); | |
105 } | |
106 | |
107 bool append(v8::Handle<v8::Array> array) | |
108 { | |
109 if (m_visitedArrays.contains(array)) | |
110 return true; | |
111 uint32_t length = array->Length(); | |
112 if (length > m_arrayLimit) | |
113 return false; | |
114 if (m_visitedArrays.size() > maxStackDepthLimit) | |
115 return false; | |
116 | |
117 bool result = true; | |
118 m_arrayLimit -= length; | |
119 m_visitedArrays.append(array); | |
120 for (uint32_t i = 0; i < length; ++i) { | |
121 if (i) | |
122 m_builder.append(','); | |
123 if (!append(array->Get(i), IgnoreNull | IgnoreUndefined)) { | |
124 result = false; | |
125 break; | |
126 } | |
127 } | |
128 m_visitedArrays.removeLast(); | |
129 return result; | |
130 } | |
131 | |
132 bool append(v8::Handle<v8::Symbol> symbol) | |
133 { | |
134 m_builder.appendLiteral("Symbol("); | |
135 bool result = append(symbol->Name(), IgnoreUndefined); | |
136 m_builder.append(')'); | |
137 return result; | |
138 } | |
139 | |
140 bool append(v8::Handle<v8::String> string) | |
141 { | |
142 if (m_tryCatch.HasCaught()) | |
143 return false; | |
144 if (!string.IsEmpty()) | |
145 m_builder.append(toCoreString(string)); | |
146 return true; | |
147 } | |
148 | |
149 String toString() | |
150 { | |
151 if (m_tryCatch.HasCaught()) | |
152 return String(); | |
153 return m_builder.toString(); | |
154 } | |
155 | |
156 uint32_t m_arrayLimit; | |
157 v8::Isolate* m_isolate; | |
158 StringBuilder m_builder; | |
159 Vector<v8::Handle<v8::Array> > m_visitedArrays; | |
160 v8::TryCatch m_tryCatch; | |
161 }; | |
162 | |
163 } // namespace | |
164 | |
165 DEFINE_EMPTY_DESTRUCTOR_WILL_BE_REMOVED(ScriptArguments) | |
166 | |
167 PassRefPtr<ScriptArguments> ScriptArguments::create(ScriptState* scriptState, Ve
ctor<ScriptValue>& arguments) | |
168 { | |
169 return adoptRef(new ScriptArguments(scriptState, arguments)); | |
170 } | |
171 | |
172 ScriptArguments::ScriptArguments(ScriptState* scriptState, Vector<ScriptValue>&
arguments) | |
173 : m_scriptState(scriptState) | |
174 { | |
175 m_arguments.swap(arguments); | |
176 } | |
177 | |
178 const ScriptValue &ScriptArguments::argumentAt(size_t index) const | |
179 { | |
180 ASSERT(m_arguments.size() > index); | |
181 return m_arguments[index]; | |
182 } | |
183 | |
184 bool ScriptArguments::getFirstArgumentAsString(String& result, bool checkForNull
OrUndefined) | |
185 { | |
186 if (!argumentCount()) | |
187 return false; | |
188 | |
189 const ScriptValue& value = argumentAt(0); | |
190 ScriptState::Scope scope(m_scriptState.get()); | |
191 if (checkForNullOrUndefined && (value.isNull() || value.isUndefined())) | |
192 return false; | |
193 | |
194 result = V8ValueStringBuilder::toString(value.v8Value(), value.isolate()); | |
195 return true; | |
196 } | |
197 | |
198 } // namespace blink | |
OLD | NEW |