Changeset 226012 in webkit
- Timestamp:
- Dec 17, 2017 12:57:35 PM (6 years ago)
- Location:
- trunk/Source/JavaScriptCore
- Files:
-
- 1 deleted
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/JavaScriptCore/ChangeLog
r226011 r226012 1 2017-12-17 Mark Lam <mark.lam@apple.com> 2 3 Hollow out stub implementation of InspectorBackendDispatcher::sendResponse(). 4 https://bugs.webkit.org/show_bug.cgi?id=180901 5 <rdar://problem/36087649> 6 7 Reviewed by Darin Adler. 8 9 We only need to keep a deprecated implementation of InspectorValues, 10 InspectorObjects, and InspectorBackendDispatcher::sendResponse() around so that 11 older versions of Safari can link against and run with a build of the latest code 12 in WebKit trunk. Older versions of System Safari used InspectorValues (via 13 WebInspector.framework) for two things: 14 15 1. Augmented JSContexts SPIs (via WebInspector.framework). 16 2. maybe WebDriver. 17 18 Neither of these are used when running SafariForWebKitDevelopment. Since neither 19 are used, we can stub out the symbols (InspectorValues, InspectorObjects, 20 InspectorBackendDispatcher::sendResponse) to do nothing, and 21 SafariForWebKitDevelopment will still continue to launch with trunk WebKit, and 22 run without any observable bad behavior. 23 24 * JavaScriptCore.xcodeproj/project.pbxproj: 25 * SourcesCocoa.txt: 26 * inspector/InspectorBackendDispatcher.cpp: 27 * inspector/InspectorBackendDispatcher.h: 28 * inspector/cocoa/DeprecatedInspectorValues.cpp: 29 (Inspector::InspectorValue::null): 30 (Inspector::InspectorValue::create): 31 (Inspector::InspectorValue::asValue): 32 (Inspector::InspectorValue::asObject): 33 (Inspector::InspectorValue::asArray): 34 (Inspector::InspectorValue::parseJSON): 35 (Inspector::InspectorValue::toJSONString const): 36 (Inspector::InspectorValue::asBoolean const): 37 (Inspector::InspectorValue::asDouble const): 38 (Inspector::InspectorValue::asInteger const): 39 (Inspector::InspectorValue::asString const): 40 (Inspector::InspectorValue::writeJSON const): 41 (Inspector::InspectorValue::memoryCost const): 42 (Inspector::InspectorObjectBase::openAccessors): 43 (Inspector::InspectorObjectBase::memoryCost const): 44 (Inspector::InspectorObjectBase::getBoolean const): 45 (Inspector::InspectorObjectBase::getString const): 46 (Inspector::InspectorObjectBase::getObject const): 47 (Inspector::InspectorObjectBase::getArray const): 48 (Inspector::InspectorObjectBase::getValue const): 49 (Inspector::InspectorObjectBase::remove): 50 (Inspector::InspectorObject::create): 51 (Inspector::InspectorArrayBase::get const): 52 (Inspector::InspectorArrayBase::memoryCost const): 53 (Inspector::InspectorArray::create): 54 (Inspector::BackendDispatcher::sendResponse): 55 (Inspector::InspectorObjectBase::~InspectorObjectBase): Deleted. 56 (Inspector::InspectorObjectBase::asObject): Deleted. 57 (Inspector::InspectorObjectBase::writeJSON const): Deleted. 58 (Inspector::InspectorObjectBase::InspectorObjectBase): Deleted. 59 (Inspector::InspectorArrayBase::~InspectorArrayBase): Deleted. 60 (Inspector::InspectorArrayBase::asArray): Deleted. 61 (Inspector::InspectorArrayBase::writeJSON const): Deleted. 62 (Inspector::InspectorArrayBase::InspectorArrayBase): Deleted. 63 * inspector/cocoa/DeprecatedInspectorValues.h: Removed. 64 1 65 2017-12-17 Yusuke Suzuki <utatane.tea@gmail.com> 2 66 -
trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
r225913 r226012 1215 1215 981ED82328234D91BAECCADE /* MachineContext.h in Headers */ = {isa = PBXBuildFile; fileRef = 28806E21155E478A93FA7B02 /* MachineContext.h */; settings = {ATTRIBUTES = (Private, ); }; }; 1216 1216 990DA67F1C8E316A00295159 /* generate_objc_protocol_type_conversions_implementation.py in Headers */ = {isa = PBXBuildFile; fileRef = 990DA67E1C8E311D00295159 /* generate_objc_protocol_type_conversions_implementation.py */; settings = {ATTRIBUTES = (Private, ); }; }; 1217 992D6A131FBD492E000245F4 /* DeprecatedInspectorValues.h in Headers */ = {isa = PBXBuildFile; fileRef = 992D6A101FBD491C000245F4 /* DeprecatedInspectorValues.h */; };1218 1217 992F56B71E4E84B20035953B /* RemoteInspectorXPCConnection.h in Headers */ = {isa = PBXBuildFile; fileRef = 992F56B11E4E84790035953B /* RemoteInspectorXPCConnection.h */; settings = {ATTRIBUTES = (Private, ); }; }; 1219 1218 9959E92B1BD17FA4001AA413 /* cssmin.py in Headers */ = {isa = PBXBuildFile; fileRef = 9959E9271BD17FA0001AA413 /* cssmin.py */; settings = {ATTRIBUTES = (Private, ); }; }; … … 1716 1715 E49DC16C12EF294E00184A1F /* SourceProviderCache.h in Headers */ = {isa = PBXBuildFile; fileRef = E49DC15112EF272200184A1F /* SourceProviderCache.h */; settings = {ATTRIBUTES = (Private, ); }; }; 1717 1716 E49DC16D12EF295300184A1F /* SourceProviderCacheItem.h in Headers */ = {isa = PBXBuildFile; fileRef = E49DC14912EF261A00184A1F /* SourceProviderCacheItem.h */; settings = {ATTRIBUTES = (Private, ); }; }; 1717 FE05FAFD1FE4CEDA00093230 /* DeprecatedInspectorValues.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 992D6A111FBD491D000245F4 /* DeprecatedInspectorValues.cpp */; }; 1718 1718 FE0D4A061AB8DD0A002F54BF /* ExecutionTimeLimitTest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FE0D4A041AB8DD0A002F54BF /* ExecutionTimeLimitTest.cpp */; }; 1719 1719 FE0D4A091ABA2437002F54BF /* GlobalContextWithFinalizerTest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FE0D4A071ABA2437002F54BF /* GlobalContextWithFinalizerTest.cpp */; }; … … 3816 3816 992ABCF51BEA94CA006403A0 /* RemoteAutomationTarget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RemoteAutomationTarget.cpp; sourceTree = "<group>"; }; 3817 3817 992ABCF61BEA94CA006403A0 /* RemoteAutomationTarget.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RemoteAutomationTarget.h; sourceTree = "<group>"; }; 3818 992D6A101FBD491C000245F4 /* DeprecatedInspectorValues.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DeprecatedInspectorValues.h; sourceTree = "<group>"; };3819 3818 992D6A111FBD491D000245F4 /* DeprecatedInspectorValues.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DeprecatedInspectorValues.cpp; sourceTree = "<group>"; }; 3820 3819 992F56B01E4E84790035953B /* RemoteInspectorCocoa.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = RemoteInspectorCocoa.mm; sourceTree = "<group>"; }; … … 7631 7630 children = ( 7632 7631 992D6A111FBD491D000245F4 /* DeprecatedInspectorValues.cpp */, 7633 992D6A101FBD491C000245F4 /* DeprecatedInspectorValues.h */,7634 7632 ); 7635 7633 path = cocoa; … … 8356 8354 473DA4A4764C45FE871B0485 /* DefinePropertyAttributes.h in Headers */, 8357 8355 0FBB73BB1DEF8645002C009E /* DeleteAllCodeEffort.h in Headers */, 8358 992D6A131FBD492E000245F4 /* DeprecatedInspectorValues.h in Headers */,8359 8356 0F96303C1D4192CD005609D9 /* DestructionMode.h in Headers */, 8360 8357 A77A423E17A0BBFD00A8DB81 /* DFGAbstractHeap.h in Headers */, … … 8870 8867 FE2B0B731FD9EF700075DA5F /* JSCPoison.h in Headers */, 8871 8868 FE2B0B691FD227E00075DA5F /* JSCPoisonedPtr.h in Headers */, 8872 8869 A72028B81797601E0098028C /* JSCTestRunnerUtils.h in Headers */, 8873 8870 72AAF7CE1D0D31B3005E60BE /* JSCustomGetterSetterFunction.h in Headers */, 8874 8871 0F2B66EC17B6B5AB00A7AE3F /* JSDataView.h in Headers */, … … 10107 10104 536B31381F71C5990037FC33 /* UnifiedSource95.cpp in Sources */, 10108 10105 536B312F1F71C5990037FC33 /* UnifiedSource96.cpp in Sources */, 10106 FE05FAFD1FE4CEDA00093230 /* DeprecatedInspectorValues.cpp in Sources */, 10109 10107 536B31361F71C5990037FC33 /* UnifiedSource97.cpp in Sources */, 10110 10108 536B316A1F71C5990037FC33 /* UnifiedSource98.cpp in Sources */, -
trunk/Source/JavaScriptCore/SourcesCocoa.txt
r225231 r226012 32 32 API/ObjCCallbackFunction.mm 33 33 34 inspector/cocoa/DeprecatedInspectorValues.cpp35 36 34 inspector/remote/RemoteAutomationTarget.cpp 37 35 inspector/remote/RemoteControllableTarget.cpp -
trunk/Source/JavaScriptCore/inspector/InspectorBackendDispatcher.cpp
r225231 r226012 1 1 /* 2 * Copyright (C) 2013 , 2015Apple Inc. All Rights Reserved.2 * Copyright (C) 2013-2017 Apple Inc. All Rights Reserved. 3 3 * Copyright (C) 2011 The Chromium Authors. All rights reserved. 4 4 * … … 34 34 #include <wtf/text/WTFString.h> 35 35 36 #if PLATFORM(COCOA)37 #include "DeprecatedInspectorValues.h"38 #endif39 40 36 namespace Inspector { 41 37 … … 189 185 } 190 186 } 191 192 #if PLATFORM(COCOA)193 // COMPATIBILITY: remove this when no longer needed by system WebInspector.framework <http://webkit.org/b/179847>.194 void BackendDispatcher::sendResponse(long requestId, RefPtr<InspectorObject>&& result)195 {196 ASSERT(!m_protocolErrors.size());197 198 // The JSON-RPC 2.0 specification requires that the "error" member have the value 'null'199 // if no error occurred during an invocation, but we do not include it at all.200 Ref<InspectorObject> responseMessage = InspectorObject::create();201 responseMessage->setObject(ASCIILiteral("result"), WTFMove(result));202 responseMessage->setInteger(ASCIILiteral("id"), requestId);203 m_frontendRouter->sendResponse(responseMessage->toJSONString());204 }205 #endif // PLATFORM(COCOA)206 187 207 188 // FIXME: remove this function when legacy InspectorObject symbols are no longer needed <http://webkit.org/b/179847>. -
trunk/Source/JavaScriptCore/inspector/InspectorBackendDispatcher.h
r225231 r226012 1 1 /* 2 * Copyright (C) 2013 , 2015Apple Inc. All Rights Reserved.2 * Copyright (C) 2013-2017 Apple Inc. All Rights Reserved. 3 3 * Copyright (C) 2011 The Chromium Authors. All rights reserved. 4 4 * … … 38 38 39 39 class BackendDispatcher; 40 41 #if PLATFORM(COCOA)42 class InspectorObject;43 #endif44 40 45 41 typedef String ErrorString; … … 94 90 // then this alternate method with a dummy parameter can be removed in favor of the one without it. 95 91 void sendResponse(long requestId, RefPtr<JSON::Object>&& result, bool unused); 96 #if PLATFORM(COCOA)97 // COMPATIBILITY: remove this when no longer needed by system WebInspector.framework.98 void sendResponse(long requestId, RefPtr<InspectorObject>&& result);99 #endif100 101 92 void sendResponse(long requestId, RefPtr<JSON::Object>&& result); 102 93 void sendPendingErrors(); -
trunk/Source/JavaScriptCore/inspector/cocoa/DeprecatedInspectorValues.cpp
r225231 r226012 1 1 /* 2 * Copyright (C) 20 10 Google Inc. All rights reserved.2 * Copyright (C) 2009-2010 Google Inc. All rights reserved. 3 3 * Copyright (C) 2014 University of Washington. All rights reserved. 4 4 * Copyright (C) 2017 Apple Inc. All rights reserved. … … 32 32 33 33 #include "config.h" 34 #include "DeprecatedInspectorValues.h" 35 36 #include <wtf/DecimalNumber.h> 37 #include <wtf/dtoa.h> 38 #include <wtf/text/StringBuilder.h> 34 35 #include "JSExportMacros.h" 36 37 namespace WTF { 38 39 class StringBuilder; 40 41 class String { }; 42 template<typename T> class Ref { }; 43 template<typename T> class RefPtr { }; 44 45 } // namespace WTF 46 47 using WTF::Ref; 48 using WTF::RefPtr; 49 using WTF::String; 50 using WTF::StringBuilder; 39 51 40 52 namespace Inspector { 41 42 namespace { 43 44 static const int stackLimit = 1000; 45 46 enum Token { 47 OBJECT_BEGIN, 48 OBJECT_END, 49 ARRAY_BEGIN, 50 ARRAY_END, 51 STRING, 52 NUMBER, 53 BOOL_TRUE, 54 BOOL_FALSE, 55 NULL_TOKEN, 56 LIST_SEPARATOR, 57 OBJECT_PAIR_SEPARATOR, 58 INVALID_TOKEN, 59 }; 60 61 const char* const nullString = "null"; 62 const char* const trueString = "true"; 63 const char* const falseString = "false"; 64 65 bool parseConstToken(const UChar* start, const UChar* end, const UChar** tokenEnd, const char* token) 66 { 67 while (start < end && *token != '\0' && *start++ == *token++) { } 68 69 if (*token != '\0') 70 return false; 71 72 *tokenEnd = start; 73 return true; 53 class InspectorArray; 54 class InspectorArrayBase; 55 class InspectorObject; 56 class InspectorObjectBase; 57 class InspectorValue; 74 58 } 75 59 76 bool readInt(const UChar* start, const UChar* end, const UChar** tokenEnd, bool canHaveLeadingZeros) 77 { 78 if (start == end) 79 return false; 80 81 bool haveLeadingZero = '0' == *start; 82 int length = 0; 83 while (start < end && '0' <= *start && *start <= '9') { 84 ++start; 85 ++length; 86 } 87 88 if (!length) 89 return false; 90 91 if (!canHaveLeadingZeros && length > 1 && haveLeadingZero) 92 return false; 93 94 *tokenEnd = start; 95 return true; 96 } 97 98 bool parseNumberToken(const UChar* start, const UChar* end, const UChar** tokenEnd) 99 { 100 // We just grab the number here. We validate the size in DecodeNumber. 101 // According to RFC4627, a valid number is: [minus] int [frac] [exp] 102 if (start == end) 103 return false; 104 105 UChar c = *start; 106 if ('-' == c) 107 ++start; 108 109 if (!readInt(start, end, &start, false)) 110 return false; 111 112 if (start == end) { 113 *tokenEnd = start; 114 return true; 115 } 116 117 // Optional fraction part 118 c = *start; 119 if ('.' == c) { 120 ++start; 121 if (!readInt(start, end, &start, true)) 122 return false; 123 if (start == end) { 124 *tokenEnd = start; 125 return true; 126 } 127 c = *start; 128 } 129 130 // Optional exponent part 131 if ('e' == c || 'E' == c) { 132 ++start; 133 if (start == end) 134 return false; 135 c = *start; 136 if ('-' == c || '+' == c) { 137 ++start; 138 if (start == end) 139 return false; 140 } 141 if (!readInt(start, end, &start, true)) 142 return false; 143 } 144 145 *tokenEnd = start; 146 return true; 147 } 148 149 bool readHexDigits(const UChar* start, const UChar* end, const UChar** tokenEnd, int digits) 150 { 151 if (end - start < digits) 152 return false; 153 154 for (int i = 0; i < digits; ++i) { 155 if (!isASCIIHexDigit(*start++)) 156 return false; 157 } 158 159 *tokenEnd = start; 160 return true; 161 } 162 163 bool parseStringToken(const UChar* start, const UChar* end, const UChar** tokenEnd) 164 { 165 while (start < end) { 166 UChar c = *start++; 167 if ('\\' == c) { 168 c = *start++; 169 // Make sure the escaped char is valid. 170 switch (c) { 171 case 'x': 172 if (!readHexDigits(start, end, &start, 2)) 173 return false; 174 break; 175 case 'u': 176 if (!readHexDigits(start, end, &start, 4)) 177 return false; 178 break; 179 case '\\': 180 case '/': 181 case 'b': 182 case 'f': 183 case 'n': 184 case 'r': 185 case 't': 186 case 'v': 187 case '"': 188 break; 189 default: 190 return false; 191 } 192 } else if ('"' == c) { 193 *tokenEnd = start; 194 return true; 195 } 196 } 197 198 return false; 199 } 200 201 Token parseToken(const UChar* start, const UChar* end, const UChar** tokenStart, const UChar** tokenEnd) 202 { 203 while (start < end && isSpaceOrNewline(*start)) 204 ++start; 205 206 if (start == end) 207 return INVALID_TOKEN; 208 209 *tokenStart = start; 210 211 switch (*start) { 212 case 'n': 213 if (parseConstToken(start, end, tokenEnd, nullString)) 214 return NULL_TOKEN; 215 break; 216 case 't': 217 if (parseConstToken(start, end, tokenEnd, trueString)) 218 return BOOL_TRUE; 219 break; 220 case 'f': 221 if (parseConstToken(start, end, tokenEnd, falseString)) 222 return BOOL_FALSE; 223 break; 224 case '[': 225 *tokenEnd = start + 1; 226 return ARRAY_BEGIN; 227 case ']': 228 *tokenEnd = start + 1; 229 return ARRAY_END; 230 case ',': 231 *tokenEnd = start + 1; 232 return LIST_SEPARATOR; 233 case '{': 234 *tokenEnd = start + 1; 235 return OBJECT_BEGIN; 236 case '}': 237 *tokenEnd = start + 1; 238 return OBJECT_END; 239 case ':': 240 *tokenEnd = start + 1; 241 return OBJECT_PAIR_SEPARATOR; 242 case '0': 243 case '1': 244 case '2': 245 case '3': 246 case '4': 247 case '5': 248 case '6': 249 case '7': 250 case '8': 251 case '9': 252 case '-': 253 if (parseNumberToken(start, end, tokenEnd)) 254 return NUMBER; 255 break; 256 case '"': 257 if (parseStringToken(start + 1, end, tokenEnd)) 258 return STRING; 259 break; 260 } 261 262 return INVALID_TOKEN; 263 } 264 265 bool decodeString(const UChar* start, const UChar* end, StringBuilder& output) 266 { 267 while (start < end) { 268 UChar c = *start++; 269 if ('\\' != c) { 270 output.append(c); 271 continue; 272 } 273 c = *start++; 274 switch (c) { 275 case '"': 276 case '/': 277 case '\\': 278 break; 279 case 'b': 280 c = '\b'; 281 break; 282 case 'f': 283 c = '\f'; 284 break; 285 case 'n': 286 c = '\n'; 287 break; 288 case 'r': 289 c = '\r'; 290 break; 291 case 't': 292 c = '\t'; 293 break; 294 case 'v': 295 c = '\v'; 296 break; 297 case 'x': 298 c = toASCIIHexValue(start[0], start[1]); 299 start += 2; 300 break; 301 case 'u': 302 c = toASCIIHexValue(start[0], start[1]) << 8 | toASCIIHexValue(start[2], start[3]); 303 start += 4; 304 break; 305 default: 306 return false; 307 } 308 output.append(c); 309 } 310 311 return true; 312 } 313 314 bool decodeString(const UChar* start, const UChar* end, String& output) 315 { 316 if (start == end) { 317 output = emptyString(); 318 return true; 319 } 320 321 if (start > end) 322 return false; 323 324 StringBuilder buffer; 325 buffer.reserveCapacity(end - start); 326 if (!decodeString(start, end, buffer)) 327 return false; 328 329 output = buffer.toString(); 330 return true; 331 } 332 333 RefPtr<InspectorValue> buildValue(const UChar* start, const UChar* end, const UChar** valueTokenEnd, int depth) 334 { 335 if (depth > stackLimit) 336 return nullptr; 337 338 RefPtr<InspectorValue> result; 339 const UChar* tokenStart; 340 const UChar* tokenEnd; 341 Token token = parseToken(start, end, &tokenStart, &tokenEnd); 342 switch (token) { 343 case INVALID_TOKEN: 344 return nullptr; 345 case NULL_TOKEN: 346 result = InspectorValue::null(); 347 break; 348 case BOOL_TRUE: 349 result = InspectorValue::create(true); 350 break; 351 case BOOL_FALSE: 352 result = InspectorValue::create(false); 353 break; 354 case NUMBER: { 355 bool ok; 356 double value = charactersToDouble(tokenStart, tokenEnd - tokenStart, &ok); 357 if (!ok) 358 return nullptr; 359 result = InspectorValue::create(value); 360 break; 361 } 362 case STRING: { 363 String value; 364 bool ok = decodeString(tokenStart + 1, tokenEnd - 1, value); 365 if (!ok) 366 return nullptr; 367 result = InspectorValue::create(value); 368 break; 369 } 370 case ARRAY_BEGIN: { 371 Ref<InspectorArray> array = InspectorArray::create(); 372 start = tokenEnd; 373 token = parseToken(start, end, &tokenStart, &tokenEnd); 374 while (token != ARRAY_END) { 375 RefPtr<InspectorValue> arrayNode = buildValue(start, end, &tokenEnd, depth + 1); 376 if (!arrayNode) 377 return nullptr; 378 array->pushValue(WTFMove(arrayNode)); 379 380 // After a list value, we expect a comma or the end of the list. 381 start = tokenEnd; 382 token = parseToken(start, end, &tokenStart, &tokenEnd); 383 if (token == LIST_SEPARATOR) { 384 start = tokenEnd; 385 token = parseToken(start, end, &tokenStart, &tokenEnd); 386 if (token == ARRAY_END) 387 return nullptr; 388 } else if (token != ARRAY_END) { 389 // Unexpected value after list value. Bail out. 390 return nullptr; 391 } 392 } 393 if (token != ARRAY_END) 394 return nullptr; 395 result = WTFMove(array); 396 break; 397 } 398 case OBJECT_BEGIN: { 399 Ref<InspectorObject> object = InspectorObject::create(); 400 start = tokenEnd; 401 token = parseToken(start, end, &tokenStart, &tokenEnd); 402 while (token != OBJECT_END) { 403 if (token != STRING) 404 return nullptr; 405 String key; 406 if (!decodeString(tokenStart + 1, tokenEnd - 1, key)) 407 return nullptr; 408 start = tokenEnd; 409 410 token = parseToken(start, end, &tokenStart, &tokenEnd); 411 if (token != OBJECT_PAIR_SEPARATOR) 412 return nullptr; 413 start = tokenEnd; 414 415 RefPtr<InspectorValue> value = buildValue(start, end, &tokenEnd, depth + 1); 416 if (!value) 417 return nullptr; 418 object->setValue(key, WTFMove(value)); 419 start = tokenEnd; 420 421 // After a key/value pair, we expect a comma or the end of the 422 // object. 423 token = parseToken(start, end, &tokenStart, &tokenEnd); 424 if (token == LIST_SEPARATOR) { 425 start = tokenEnd; 426 token = parseToken(start, end, &tokenStart, &tokenEnd); 427 if (token == OBJECT_END) 428 return nullptr; 429 } else if (token != OBJECT_END) { 430 // Unexpected value after last object value. Bail out. 431 return nullptr; 432 } 433 } 434 if (token != OBJECT_END) 435 return nullptr; 436 result = WTFMove(object); 437 break; 438 } 439 440 default: 441 // We got a token that's not a value. 442 return nullptr; 443 } 444 *valueTokenEnd = tokenEnd; 445 return result; 446 } 447 448 inline bool escapeChar(UChar c, StringBuilder& dst) 449 { 450 switch (c) { 451 case '\b': dst.appendLiteral("\\b"); break; 452 case '\f': dst.appendLiteral("\\f"); break; 453 case '\n': dst.appendLiteral("\\n"); break; 454 case '\r': dst.appendLiteral("\\r"); break; 455 case '\t': dst.appendLiteral("\\t"); break; 456 case '\\': dst.appendLiteral("\\\\"); break; 457 case '"': dst.appendLiteral("\\\""); break; 458 default: 459 return false; 460 } 461 return true; 462 } 463 464 inline void doubleQuoteString(const String& str, StringBuilder& dst) 465 { 466 dst.append('"'); 467 for (unsigned i = 0; i < str.length(); ++i) { 468 UChar c = str[i]; 469 if (!escapeChar(c, dst)) { 470 if (c < 32 || c > 126 || c == '<' || c == '>') { 471 // 1. Escaping <, > to prevent script execution. 472 // 2. Technically, we could also pass through c > 126 as UTF8, but this 473 // is also optional. It would also be a pain to implement here. 474 dst.append(String::format("\\u%04X", c)); 475 } else 476 dst.append(c); 477 } 478 } 479 dst.append('"'); 480 } 481 482 } // anonymous namespace 483 484 Ref<InspectorValue> InspectorValue::null() 485 { 486 return adoptRef(*new InspectorValue); 487 } 488 489 Ref<InspectorValue> InspectorValue::create(bool value) 490 { 491 return adoptRef(*new InspectorValue(value)); 492 } 493 494 Ref<InspectorValue> InspectorValue::create(int value) 495 { 496 return adoptRef(*new InspectorValue(value)); 497 } 498 499 Ref<InspectorValue> InspectorValue::create(double value) 500 { 501 return adoptRef(*new InspectorValue(value)); 502 } 503 504 Ref<InspectorValue> InspectorValue::create(const String& value) 505 { 506 return adoptRef(*new InspectorValue(value)); 507 } 508 509 Ref<InspectorValue> InspectorValue::create(const char* value) 510 { 511 return adoptRef(*new InspectorValue(value)); 512 } 513 514 bool InspectorValue::asValue(RefPtr<Inspector::InspectorValue> & value) 515 { 516 value = this; 517 return true; 518 } 519 520 bool InspectorValue::asObject(RefPtr<InspectorObject>&) 521 { 522 return false; 523 } 524 525 bool InspectorValue::asArray(RefPtr<InspectorArray>&) 526 { 527 return false; 528 } 529 530 bool InspectorValue::parseJSON(const String& jsonInput, RefPtr<InspectorValue>& output) 531 { 532 // FIXME: This whole file should just use StringView instead of UChar/length and avoid upconverting. 533 auto characters = StringView(jsonInput).upconvertedCharacters(); 534 const UChar* start = characters; 535 const UChar* end = start + jsonInput.length(); 536 const UChar* tokenEnd; 537 auto result = buildValue(start, end, &tokenEnd, 0); 538 if (!result || tokenEnd != end) 539 return false; 540 541 output = WTFMove(result); 542 return true; 543 } 544 545 String InspectorValue::toJSONString() const 546 { 547 StringBuilder result; 548 result.reserveCapacity(512); 549 writeJSON(result); 550 return result.toString(); 551 } 552 553 bool InspectorValue::asBoolean(bool& output) const 554 { 555 if (type() != Type::Boolean) 556 return false; 557 558 output = m_value.boolean; 559 return true; 560 } 561 562 bool InspectorValue::asDouble(double& output) const 563 { 564 if (type() != Type::Double) 565 return false; 566 567 output = m_value.number; 568 return true; 569 } 570 571 bool InspectorValue::asDouble(float& output) const 572 { 573 if (type() != Type::Double) 574 return false; 575 576 output = static_cast<float>(m_value.number); 577 return true; 578 } 579 580 bool InspectorValue::asInteger(int& output) const 581 { 582 if (type() != Type::Integer && type() != Type::Double) 583 return false; 584 585 output = static_cast<int>(m_value.number); 586 return true; 587 } 588 589 bool InspectorValue::asInteger(unsigned& output) const 590 { 591 if (type() != Type::Integer && type() != Type::Double) 592 return false; 593 594 output = static_cast<unsigned>(m_value.number); 595 return true; 596 } 597 598 bool InspectorValue::asInteger(long& output) const 599 { 600 if (type() != Type::Integer && type() != Type::Double) 601 return false; 602 603 output = static_cast<long>(m_value.number); 604 return true; 605 } 606 607 bool InspectorValue::asInteger(long long& output) const 608 { 609 if (type() != Type::Integer && type() != Type::Double) 610 return false; 611 612 output = static_cast<long long>(m_value.number); 613 return true; 614 } 615 616 bool InspectorValue::asInteger(unsigned long& output) const 617 { 618 if (type() != Type::Integer && type() != Type::Double) 619 return false; 620 621 output = static_cast<unsigned long>(m_value.number); 622 return true; 623 } 624 625 bool InspectorValue::asInteger(unsigned long long& output) const 626 { 627 if (type() != Type::Integer && type() != Type::Double) 628 return false; 629 630 output = static_cast<unsigned long long>(m_value.number); 631 return true; 632 } 633 634 bool InspectorValue::asString(String& output) const 635 { 636 if (type() != Type::String) 637 return false; 638 639 output = m_value.string; 640 return true; 641 } 642 643 void InspectorValue::writeJSON(StringBuilder& output) const 644 { 645 switch (m_type) { 646 case Type::Null: 647 output.appendLiteral("null"); 648 break; 649 case Type::Boolean: 650 if (m_value.boolean) 651 output.appendLiteral("true"); 652 else 653 output.appendLiteral("false"); 654 break; 655 case Type::String: 656 doubleQuoteString(m_value.string, output); 657 break; 658 case Type::Double: 659 case Type::Integer: { 660 NumberToLStringBuffer buffer; 661 if (!std::isfinite(m_value.number)) { 662 output.appendLiteral("null"); 663 return; 664 } 665 DecimalNumber decimal = m_value.number; 666 unsigned length = 0; 667 if (decimal.bufferLengthForStringDecimal() > WTF::NumberToStringBufferLength) { 668 // Not enough room for decimal. Use exponential format. 669 if (decimal.bufferLengthForStringExponential() > WTF::NumberToStringBufferLength) { 670 // Fallback for an abnormal case if it's too little even for exponential. 671 output.appendLiteral("NaN"); 672 return; 673 } 674 length = decimal.toStringExponential(buffer, WTF::NumberToStringBufferLength); 675 } else 676 length = decimal.toStringDecimal(buffer, WTF::NumberToStringBufferLength); 677 output.append(buffer, length); 678 break; 679 } 680 default: 681 ASSERT_NOT_REACHED(); 682 } 683 } 684 685 size_t InspectorValue::memoryCost() const 686 { 687 size_t memoryCost = sizeof(this); 688 if (m_type == Type::String && m_value.string) 689 memoryCost += m_value.string->sizeInBytes(); 690 return memoryCost; 691 } 692 693 InspectorObjectBase::~InspectorObjectBase() 694 { 695 } 696 697 bool InspectorObjectBase::asObject(RefPtr<InspectorObject>& output) 698 { 699 COMPILE_ASSERT(sizeof(InspectorObject) == sizeof(InspectorObjectBase), cannot_cast); 700 701 output = static_cast<InspectorObject*>(this); 702 return true; 703 } 704 705 InspectorObject* InspectorObjectBase::openAccessors() 706 { 707 COMPILE_ASSERT(sizeof(InspectorObject) == sizeof(InspectorObjectBase), cannot_cast); 708 709 return static_cast<InspectorObject*>(this); 710 } 711 712 size_t InspectorObjectBase::memoryCost() const 713 { 714 size_t memoryCost = InspectorValue::memoryCost(); 715 for (const auto& entry : m_map) { 716 memoryCost += entry.key.sizeInBytes(); 717 if (entry.value) 718 memoryCost += entry.value->memoryCost(); 719 } 720 return memoryCost; 721 } 722 723 bool InspectorObjectBase::getBoolean(const String& name, bool& output) const 724 { 725 RefPtr<InspectorValue> value; 726 if (!getValue(name, value)) 727 return false; 728 729 return value->asBoolean(output); 730 } 731 732 bool InspectorObjectBase::getString(const String& name, String& output) const 733 { 734 RefPtr<InspectorValue> value; 735 if (!getValue(name, value)) 736 return false; 737 738 return value->asString(output); 739 } 740 741 bool InspectorObjectBase::getObject(const String& name, RefPtr<InspectorObject>& output) const 742 { 743 RefPtr<InspectorValue> value; 744 if (!getValue(name, value)) 745 return false; 746 747 return value->asObject(output); 748 } 749 750 bool InspectorObjectBase::getArray(const String& name, RefPtr<InspectorArray>& output) const 751 { 752 RefPtr<InspectorValue> value; 753 if (!getValue(name, value)) 754 return false; 755 756 return value->asArray(output); 757 } 758 759 bool InspectorObjectBase::getValue(const String& name, RefPtr<InspectorValue>& output) const 760 { 761 Dictionary::const_iterator findResult = m_map.find(name); 762 if (findResult == m_map.end()) 763 return false; 764 765 output = findResult->value; 766 return true; 767 } 768 769 void InspectorObjectBase::remove(const String& name) 770 { 771 m_map.remove(name); 772 m_order.removeFirst(name); 773 } 774 775 void InspectorObjectBase::writeJSON(StringBuilder& output) const 776 { 777 output.append('{'); 778 for (size_t i = 0; i < m_order.size(); ++i) { 779 auto findResult = m_map.find(m_order[i]); 780 ASSERT(findResult != m_map.end()); 781 if (i) 782 output.append(','); 783 doubleQuoteString(findResult->key, output); 784 output.append(':'); 785 findResult->value->writeJSON(output); 786 } 787 output.append('}'); 788 } 789 790 InspectorObjectBase::InspectorObjectBase() 791 : Inspector::InspectorValue(Type::Object) 792 , m_map() 793 , m_order() 794 { 795 } 796 797 InspectorArrayBase::~InspectorArrayBase() 798 { 799 } 800 801 bool InspectorArrayBase::asArray(RefPtr<InspectorArray>& output) 802 { 803 COMPILE_ASSERT(sizeof(InspectorArrayBase) == sizeof(InspectorArray), cannot_cast); 804 output = static_cast<InspectorArray*>(this); 805 return true; 806 } 807 808 void InspectorArrayBase::writeJSON(StringBuilder& output) const 809 { 810 output.append('['); 811 for (Vector<RefPtr<InspectorValue>>::const_iterator it = m_map.begin(); it != m_map.end(); ++it) { 812 if (it != m_map.begin()) 813 output.append(','); 814 (*it)->writeJSON(output); 815 } 816 output.append(']'); 817 } 818 819 InspectorArrayBase::InspectorArrayBase() 820 : InspectorValue(Type::Array) 821 , m_map() 822 { 823 } 824 825 RefPtr<InspectorValue> InspectorArrayBase::get(size_t index) const 826 { 827 ASSERT_WITH_SECURITY_IMPLICATION(index < m_map.size()); 828 return m_map[index]; 829 } 830 831 Ref<InspectorObject> InspectorObject::create() 832 { 833 return adoptRef(*new InspectorObject); 834 } 835 836 Ref<InspectorArray> InspectorArray::create() 837 { 838 return adoptRef(*new InspectorArray); 839 } 840 841 size_t InspectorArrayBase::memoryCost() const 842 { 843 size_t memoryCost = InspectorValue::memoryCost(); 844 for (const auto& item : m_map) { 845 if (item) 846 memoryCost += item->memoryCost(); 847 } 848 return memoryCost; 849 } 60 namespace Inspector { 61 62 class JS_EXPORT_PRIVATE InspectorValue { 63 public: 64 virtual ~InspectorValue() { } 65 66 static Ref<InspectorValue> null(); 67 static Ref<InspectorValue> create(bool); 68 static Ref<InspectorValue> create(int); 69 static Ref<InspectorValue> create(double); 70 static Ref<InspectorValue> create(const String&); 71 static Ref<InspectorValue> create(const char*); 72 73 enum class Type { 74 Null = 0, 75 Boolean, 76 Double, 77 Integer, 78 String, 79 Object, 80 Array, 81 }; 82 83 Type type() const { return Type::Null; } 84 bool isNull() const { return true; } 85 86 bool asBoolean(bool&) const; 87 bool asInteger(int&) const; 88 bool asInteger(unsigned&) const; 89 bool asInteger(long&) const; 90 bool asInteger(long long&) const; 91 bool asInteger(unsigned long&) const; 92 bool asInteger(unsigned long long&) const; 93 bool asDouble(double&) const; 94 bool asDouble(float&) const; 95 bool asString(String&) const; 96 bool asValue(RefPtr<InspectorValue>&); 97 98 virtual bool asObject(RefPtr<InspectorObject>&); 99 virtual bool asArray(RefPtr<InspectorArray>&); 100 101 static bool parseJSON(const String&, RefPtr<InspectorValue>&); 102 103 String toJSONString() const; 104 virtual void writeJSON(StringBuilder&) const; 105 106 virtual size_t memoryCost() const; 107 }; 108 109 Ref<InspectorValue> InspectorValue::null() { return { }; } 110 Ref<InspectorValue> InspectorValue::create(bool) { return { }; } 111 Ref<InspectorValue> InspectorValue::create(int) { return { }; } 112 Ref<InspectorValue> InspectorValue::create(double) { return { }; } 113 Ref<InspectorValue> InspectorValue::create(const String&) { return { }; } 114 Ref<InspectorValue> InspectorValue::create(const char*) { return { }; } 115 116 bool InspectorValue::asValue(RefPtr<Inspector::InspectorValue> &) { return true; } 117 bool InspectorValue::asObject(RefPtr<InspectorObject>&) { return false; } 118 bool InspectorValue::asArray(RefPtr<InspectorArray>&) { return false; } 119 120 bool InspectorValue::parseJSON(const String&, RefPtr<InspectorValue>&) { return false; } 121 String InspectorValue::toJSONString() const { return { }; } 122 123 bool InspectorValue::asBoolean(bool&) const { return false; } 124 bool InspectorValue::asDouble(double&) const { return false; } 125 bool InspectorValue::asDouble(float&) const { return false; } 126 127 bool InspectorValue::asInteger(int&) const { return false; } 128 bool InspectorValue::asInteger(unsigned&) const { return false; } 129 bool InspectorValue::asInteger(long&) const { return false; } 130 bool InspectorValue::asInteger(long long&) const { return false; } 131 bool InspectorValue::asInteger(unsigned long&) const { return false; } 132 bool InspectorValue::asInteger(unsigned long long&) const { return false; } 133 134 bool InspectorValue::asString(String&) const { return false; } 135 void InspectorValue::writeJSON(StringBuilder&) const { } 136 size_t InspectorValue::memoryCost() const { return 0; } 137 138 139 class JS_EXPORT_PRIVATE InspectorObjectBase : public InspectorValue { 140 public: 141 InspectorObject* openAccessors(); 142 143 size_t memoryCost() const final; 144 145 bool getBoolean(const String& name, bool& output) const; 146 bool getString(const String& name, String& output) const; 147 bool getObject(const String& name, RefPtr<InspectorObject>&) const; 148 bool getArray(const String& name, RefPtr<InspectorArray>&) const; 149 bool getValue(const String& name, RefPtr<InspectorValue>&) const; 150 151 void remove(const String&); 152 }; 153 154 InspectorObject* InspectorObjectBase::openAccessors() { return nullptr; } 155 size_t InspectorObjectBase::memoryCost() const { return 0; } 156 157 bool InspectorObjectBase::getBoolean(const String&, bool&) const { return false; } 158 bool InspectorObjectBase::getString(const String&, String&) const { return false; } 159 bool InspectorObjectBase::getObject(const String&, RefPtr<InspectorObject>&) const { return false; } 160 bool InspectorObjectBase::getArray(const String&, RefPtr<InspectorArray>&) const { return false; } 161 bool InspectorObjectBase::getValue(const String&, RefPtr<InspectorValue>&) const { return false; } 162 void InspectorObjectBase::remove(const String&) { } 163 164 165 class InspectorObject : public InspectorObjectBase { 166 public: 167 static JS_EXPORT_PRIVATE Ref<InspectorObject> create(); 168 }; 169 170 Ref<InspectorObject> InspectorObject::create() { return { }; } 171 172 173 class JS_EXPORT_PRIVATE InspectorArrayBase : public InspectorValue { 174 public: 175 RefPtr<InspectorValue> get(size_t index) const; 176 177 size_t memoryCost() const final; 178 }; 179 180 RefPtr<InspectorValue> InspectorArrayBase::get(size_t) const { return { }; } 181 size_t InspectorArrayBase::memoryCost() const { return 0; } 182 183 184 class InspectorArray : public InspectorArrayBase { 185 public: 186 static JS_EXPORT_PRIVATE Ref<InspectorArray> create(); 187 }; 188 189 Ref<InspectorArray> InspectorArray::create() { return { }; } 190 191 192 class JS_EXPORT_PRIVATE BackendDispatcher { 193 public: 194 // COMPATIBILITY: remove this when no longer needed by system WebInspector.framework. 195 void sendResponse(long requestId, RefPtr<InspectorObject>&& result); 196 }; 197 198 // COMPATIBILITY: remove this when no longer needed by system WebInspector.framework <http://webkit.org/b/179847>. 199 void BackendDispatcher::sendResponse(long, RefPtr<InspectorObject>&&) { } 850 200 851 201 } // namespace Inspector
Note: See TracChangeset
for help on using the changeset viewer.