Changeset 226012 in webkit


Ignore:
Timestamp:
Dec 17, 2017 12:57:35 PM (6 years ago)
Author:
mark.lam@apple.com
Message:

Hollow out stub implementation of InspectorBackendDispatcher::sendResponse().
https://bugs.webkit.org/show_bug.cgi?id=180901
<rdar://problem/36087649>

Reviewed by Darin Adler.

We only need to keep a deprecated implementation of InspectorValues,
InspectorObjects, and InspectorBackendDispatcher::sendResponse() around so that
older versions of Safari can link against and run with a build of the latest code
in WebKit trunk. Older versions of System Safari used InspectorValues (via
WebInspector.framework) for two things:

  1. Augmented JSContexts SPIs (via WebInspector.framework).
  2. maybe WebDriver.

Neither of these are used when running SafariForWebKitDevelopment. Since neither
are used, we can stub out the symbols (InspectorValues, InspectorObjects,
InspectorBackendDispatcher::sendResponse) to do nothing, and
SafariForWebKitDevelopment will still continue to launch with trunk WebKit, and
run without any observable bad behavior.

  • JavaScriptCore.xcodeproj/project.pbxproj:
  • SourcesCocoa.txt:
  • inspector/InspectorBackendDispatcher.cpp:
  • inspector/InspectorBackendDispatcher.h:
  • inspector/cocoa/DeprecatedInspectorValues.cpp:

(Inspector::InspectorValue::null):
(Inspector::InspectorValue::create):
(Inspector::InspectorValue::asValue):
(Inspector::InspectorValue::asObject):
(Inspector::InspectorValue::asArray):
(Inspector::InspectorValue::parseJSON):
(Inspector::InspectorValue::toJSONString const):
(Inspector::InspectorValue::asBoolean const):
(Inspector::InspectorValue::asDouble const):
(Inspector::InspectorValue::asInteger const):
(Inspector::InspectorValue::asString const):
(Inspector::InspectorValue::writeJSON const):
(Inspector::InspectorValue::memoryCost const):
(Inspector::InspectorObjectBase::openAccessors):
(Inspector::InspectorObjectBase::memoryCost const):
(Inspector::InspectorObjectBase::getBoolean const):
(Inspector::InspectorObjectBase::getString const):
(Inspector::InspectorObjectBase::getObject const):
(Inspector::InspectorObjectBase::getArray const):
(Inspector::InspectorObjectBase::getValue const):
(Inspector::InspectorObjectBase::remove):
(Inspector::InspectorObject::create):
(Inspector::InspectorArrayBase::get const):
(Inspector::InspectorArrayBase::memoryCost const):
(Inspector::InspectorArray::create):
(Inspector::BackendDispatcher::sendResponse):
(Inspector::InspectorObjectBase::~InspectorObjectBase): Deleted.
(Inspector::InspectorObjectBase::asObject): Deleted.
(Inspector::InspectorObjectBase::writeJSON const): Deleted.
(Inspector::InspectorObjectBase::InspectorObjectBase): Deleted.
(Inspector::InspectorArrayBase::~InspectorArrayBase): Deleted.
(Inspector::InspectorArrayBase::asArray): Deleted.
(Inspector::InspectorArrayBase::writeJSON const): Deleted.
(Inspector::InspectorArrayBase::InspectorArrayBase): Deleted.

  • inspector/cocoa/DeprecatedInspectorValues.h: Removed.
Location:
trunk/Source/JavaScriptCore
Files:
1 deleted
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/ChangeLog

    r226011 r226012  
     12017-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
    1652017-12-17  Yusuke Suzuki  <utatane.tea@gmail.com>
    266
  • trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj

    r225913 r226012  
    12151215                981ED82328234D91BAECCADE /* MachineContext.h in Headers */ = {isa = PBXBuildFile; fileRef = 28806E21155E478A93FA7B02 /* MachineContext.h */; settings = {ATTRIBUTES = (Private, ); }; };
    12161216                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 */; };
    12181217                992F56B71E4E84B20035953B /* RemoteInspectorXPCConnection.h in Headers */ = {isa = PBXBuildFile; fileRef = 992F56B11E4E84790035953B /* RemoteInspectorXPCConnection.h */; settings = {ATTRIBUTES = (Private, ); }; };
    12191218                9959E92B1BD17FA4001AA413 /* cssmin.py in Headers */ = {isa = PBXBuildFile; fileRef = 9959E9271BD17FA0001AA413 /* cssmin.py */; settings = {ATTRIBUTES = (Private, ); }; };
     
    17161715                E49DC16C12EF294E00184A1F /* SourceProviderCache.h in Headers */ = {isa = PBXBuildFile; fileRef = E49DC15112EF272200184A1F /* SourceProviderCache.h */; settings = {ATTRIBUTES = (Private, ); }; };
    17171716                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 */; };
    17181718                FE0D4A061AB8DD0A002F54BF /* ExecutionTimeLimitTest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FE0D4A041AB8DD0A002F54BF /* ExecutionTimeLimitTest.cpp */; };
    17191719                FE0D4A091ABA2437002F54BF /* GlobalContextWithFinalizerTest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FE0D4A071ABA2437002F54BF /* GlobalContextWithFinalizerTest.cpp */; };
     
    38163816                992ABCF51BEA94CA006403A0 /* RemoteAutomationTarget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RemoteAutomationTarget.cpp; sourceTree = "<group>"; };
    38173817                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>"; };
    38193818                992D6A111FBD491D000245F4 /* DeprecatedInspectorValues.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DeprecatedInspectorValues.cpp; sourceTree = "<group>"; };
    38203819                992F56B01E4E84790035953B /* RemoteInspectorCocoa.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = RemoteInspectorCocoa.mm; sourceTree = "<group>"; };
     
    76317630                        children = (
    76327631                                992D6A111FBD491D000245F4 /* DeprecatedInspectorValues.cpp */,
    7633                                 992D6A101FBD491C000245F4 /* DeprecatedInspectorValues.h */,
    76347632                        );
    76357633                        path = cocoa;
     
    83568354                                473DA4A4764C45FE871B0485 /* DefinePropertyAttributes.h in Headers */,
    83578355                                0FBB73BB1DEF8645002C009E /* DeleteAllCodeEffort.h in Headers */,
    8358                                 992D6A131FBD492E000245F4 /* DeprecatedInspectorValues.h in Headers */,
    83598356                                0F96303C1D4192CD005609D9 /* DestructionMode.h in Headers */,
    83608357                                A77A423E17A0BBFD00A8DB81 /* DFGAbstractHeap.h in Headers */,
     
    88708867                                FE2B0B731FD9EF700075DA5F /* JSCPoison.h in Headers */,
    88718868                                FE2B0B691FD227E00075DA5F /* JSCPoisonedPtr.h in Headers */,
    8872                                 A72028B81797601E0098028C /* JSCTestRunnerUtils.h in Headers */,
     8869                                A72028B81797601E0098028C /* JSCTestRunnerUtils.h in Headers */,
    88738870                                72AAF7CE1D0D31B3005E60BE /* JSCustomGetterSetterFunction.h in Headers */,
    88748871                                0F2B66EC17B6B5AB00A7AE3F /* JSDataView.h in Headers */,
     
    1010710104                                536B31381F71C5990037FC33 /* UnifiedSource95.cpp in Sources */,
    1010810105                                536B312F1F71C5990037FC33 /* UnifiedSource96.cpp in Sources */,
     10106                                FE05FAFD1FE4CEDA00093230 /* DeprecatedInspectorValues.cpp in Sources */,
    1010910107                                536B31361F71C5990037FC33 /* UnifiedSource97.cpp in Sources */,
    1011010108                                536B316A1F71C5990037FC33 /* UnifiedSource98.cpp in Sources */,
  • trunk/Source/JavaScriptCore/SourcesCocoa.txt

    r225231 r226012  
    3232API/ObjCCallbackFunction.mm
    3333
    34 inspector/cocoa/DeprecatedInspectorValues.cpp
    35 
    3634inspector/remote/RemoteAutomationTarget.cpp
    3735inspector/remote/RemoteControllableTarget.cpp
  • trunk/Source/JavaScriptCore/inspector/InspectorBackendDispatcher.cpp

    r225231 r226012  
    11/*
    2  * Copyright (C) 2013, 2015 Apple Inc. All Rights Reserved.
     2 * Copyright (C) 2013-2017 Apple Inc. All Rights Reserved.
    33 * Copyright (C) 2011 The Chromium Authors. All rights reserved.
    44 *
     
    3434#include <wtf/text/WTFString.h>
    3535
    36 #if PLATFORM(COCOA)
    37 #include "DeprecatedInspectorValues.h"
    38 #endif
    39 
    4036namespace Inspector {
    4137
     
    189185    }
    190186}
    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)
    206187
    207188// 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  
    11/*
    2  * Copyright (C) 2013, 2015 Apple Inc. All Rights Reserved.
     2 * Copyright (C) 2013-2017 Apple Inc. All Rights Reserved.
    33 * Copyright (C) 2011 The Chromium Authors. All rights reserved.
    44 *
     
    3838
    3939class BackendDispatcher;
    40 
    41 #if PLATFORM(COCOA)
    42 class InspectorObject;
    43 #endif
    4440
    4541typedef String ErrorString;
     
    9490    // then this alternate method with a dummy parameter can be removed in favor of the one without it.
    9591    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 #endif
    100 
    10192    void sendResponse(long requestId, RefPtr<JSON::Object>&& result);
    10293    void sendPendingErrors();
  • trunk/Source/JavaScriptCore/inspector/cocoa/DeprecatedInspectorValues.cpp

    r225231 r226012  
    11/*
    2  * Copyright (C) 2010 Google Inc. All rights reserved.
     2 * Copyright (C) 2009-2010 Google Inc. All rights reserved.
    33 * Copyright (C) 2014 University of Washington. All rights reserved.
    44 * Copyright (C) 2017 Apple Inc. All rights reserved.
     
    3232
    3333#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
     37namespace WTF {
     38
     39class StringBuilder;
     40
     41class String { };
     42template<typename T> class Ref { };
     43template<typename T> class RefPtr { };
     44
     45} // namespace WTF
     46
     47using WTF::Ref;
     48using WTF::RefPtr;
     49using WTF::String;
     50using WTF::StringBuilder;
    3951
    4052namespace 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;
     53class InspectorArray;
     54class InspectorArrayBase;
     55class InspectorObject;
     56class InspectorObjectBase;
     57class InspectorValue;
    7458}
    7559
    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 }
     60namespace Inspector {
     61
     62class JS_EXPORT_PRIVATE InspectorValue {
     63public:
     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
     109Ref<InspectorValue> InspectorValue::null() { return { }; }
     110Ref<InspectorValue> InspectorValue::create(bool) { return { }; }
     111Ref<InspectorValue> InspectorValue::create(int) { return { }; }
     112Ref<InspectorValue> InspectorValue::create(double) { return { }; }
     113Ref<InspectorValue> InspectorValue::create(const String&) { return { }; }
     114Ref<InspectorValue> InspectorValue::create(const char*) { return { }; }
     115
     116bool InspectorValue::asValue(RefPtr<Inspector::InspectorValue> &) { return true; }
     117bool InspectorValue::asObject(RefPtr<InspectorObject>&) { return false; }
     118bool InspectorValue::asArray(RefPtr<InspectorArray>&) { return false; }
     119
     120bool InspectorValue::parseJSON(const String&, RefPtr<InspectorValue>&) { return false; }
     121String InspectorValue::toJSONString() const { return { }; }
     122
     123bool InspectorValue::asBoolean(bool&) const { return false; }
     124bool InspectorValue::asDouble(double&) const { return false; }
     125bool InspectorValue::asDouble(float&) const { return false; }
     126
     127bool InspectorValue::asInteger(int&) const { return false; }
     128bool InspectorValue::asInteger(unsigned&) const { return false; }
     129bool InspectorValue::asInteger(long&) const { return false; }
     130bool InspectorValue::asInteger(long long&) const { return false; }
     131bool InspectorValue::asInteger(unsigned long&) const { return false; }
     132bool InspectorValue::asInteger(unsigned long long&) const { return false; }
     133
     134bool InspectorValue::asString(String&) const { return false; }
     135void InspectorValue::writeJSON(StringBuilder&) const { }
     136size_t InspectorValue::memoryCost() const { return 0; }
     137
     138
     139class JS_EXPORT_PRIVATE InspectorObjectBase : public InspectorValue {
     140public:
     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
     154InspectorObject* InspectorObjectBase::openAccessors() { return nullptr; }
     155size_t InspectorObjectBase::memoryCost() const { return 0; }
     156
     157bool InspectorObjectBase::getBoolean(const String&, bool&) const { return false; }
     158bool InspectorObjectBase::getString(const String&, String&) const { return false; }
     159bool InspectorObjectBase::getObject(const String&, RefPtr<InspectorObject>&) const { return false; }
     160bool InspectorObjectBase::getArray(const String&, RefPtr<InspectorArray>&) const { return false; }
     161bool InspectorObjectBase::getValue(const String&, RefPtr<InspectorValue>&) const { return false; }
     162void InspectorObjectBase::remove(const String&) { }
     163
     164
     165class InspectorObject : public InspectorObjectBase {
     166public:
     167    static JS_EXPORT_PRIVATE Ref<InspectorObject> create();
     168};
     169
     170Ref<InspectorObject> InspectorObject::create() { return { }; }
     171
     172
     173class JS_EXPORT_PRIVATE InspectorArrayBase : public InspectorValue {
     174public:
     175    RefPtr<InspectorValue> get(size_t index) const;
     176
     177    size_t memoryCost() const final;
     178};
     179
     180RefPtr<InspectorValue> InspectorArrayBase::get(size_t) const { return { }; }
     181size_t InspectorArrayBase::memoryCost() const { return 0; }
     182
     183
     184class InspectorArray : public InspectorArrayBase {
     185public:
     186    static JS_EXPORT_PRIVATE Ref<InspectorArray> create();
     187};
     188
     189Ref<InspectorArray> InspectorArray::create() { return { }; }
     190
     191
     192class JS_EXPORT_PRIVATE BackendDispatcher {
     193public:
     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>.
     199void BackendDispatcher::sendResponse(long, RefPtr<InspectorObject>&&) { }
    850200
    851201} // namespace Inspector
Note: See TracChangeset for help on using the changeset viewer.