Commit 1348bdfa authored by ap@apple.com's avatar ap@apple.com

Reviewed by Geoffrey Garen.

        https://bugs.webkit.org/show_bug.cgi?id=33057
        REGRESSION(r49365): typeof(xhr.responseText) != "string" in Windows

        <rdar://problem/7296920> REGRESSION: WebKit fails to start PeaceKeeper benchmark

        Test: fast/js/webcore-string-comparison.html

        In r49365, some code was moved from JSString.cpp to JSString.h, and as a result, WebCore
        got a way to directly instantiate JSStrings over DLL borders. Since vftable for JSString was
        not exported, objects created from WebCore got a different vptr, and JavaScriptCore
        optimizations that relied on vptr of all JSString objects being equal failed.

        * config.h: Added a JS_EXPORTCLASS macro for exporting classes. It's currently the same as
        JS_EXPORTDATA, but it clearly needed a new name.

        * runtime/InitializeThreading.cpp:
        (JSC::initializeThreadingOnce):
        * runtime/JSGlobalData.cpp:
        (JSC::JSGlobalData::storeVPtrs):
        (JSC::JSGlobalData::JSGlobalData):
        (JSC::JSGlobalData::createNonDefault):
        (JSC::JSGlobalData::create):
        (JSC::JSGlobalData::sharedInstance):
        * runtime/JSGlobalData.h:
        Store vptrs just once, no need to repeatedly pick and copy them. This makes it possible to
        assert vptr correctness in object destructors (which don't have access to JSGlobalData,
        and even Heap::heap(this) will fail for fake objects created from storeVPtrs()).

        * runtime/JSArray.cpp: (JSC::JSArray::~JSArray): Assert that vptr is what we expect it to be.
        It's important to assert in destructor, because MSVC changes the vptr after constructor
        is invoked.
        * runtime/JSByteArray.cpp: (JSC::JSByteArray::~JSByteArray): Ditto.
        * runtime/JSByteArray.h: Ditto.
        * runtime/JSFunction.h: Ditto.
        * runtime/JSFunction.cpp: (JSC::JSFunction::~JSFunction): Ditto.

        * runtime/JSCell.h: (JSC::JSCell::setVPtr): Added a method to substitute vptr for another
        one.

        * runtime/JSString.h: Export JSString class together with its vftable, and tell other
        libraries tp import it. This is needed on platforms that have a separate JavaScriptCore
        dynamic library - and on Mac, we already did the export via JavaScriptCore.exp.
        (JSC::JSString::~JSString): Assert tha vptr is what we expect it to be.
        (JSC::fixupVPtr): Store a previously saved primary vftable pointer (do nothing if building
        JavaScriptCore itself).
        (JSC::jsSingleCharacterString): Call fixupVPtr in case this is call across DLL boundary.
        (JSC::jsSingleCharacterSubstring): Ditto.
        (JSC::jsNontrivialString): Ditto.
        (JSC::jsString): Ditto.
        (JSC::jsSubstring): Ditto.
        (JSC::jsOwnedString): Ditto.

        * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def: Export the new static
        JSGlobalData members that are used in WebCore via inline functions.



git-svn-id: http://svn.webkit.org/repository/webkit/trunk@52956 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent 836a6b30
2010-01-07 Alexey Proskuryakov <ap@apple.com>
Reviewed by Geoffrey Garen.
https://bugs.webkit.org/show_bug.cgi?id=33057
REGRESSION(r49365): typeof(xhr.responseText) != "string" in Windows
<rdar://problem/7296920> REGRESSION: WebKit fails to start PeaceKeeper benchmark
Test: fast/js/webcore-string-comparison.html
In r49365, some code was moved from JSString.cpp to JSString.h, and as a result, WebCore
got a way to directly instantiate JSStrings over DLL borders. Since vftable for JSString was
not exported, objects created from WebCore got a different vptr, and JavaScriptCore
optimizations that relied on vptr of all JSString objects being equal failed.
* config.h: Added a JS_EXPORTCLASS macro for exporting classes. It's currently the same as
JS_EXPORTDATA, but it clearly needed a new name.
* runtime/InitializeThreading.cpp:
(JSC::initializeThreadingOnce):
* runtime/JSGlobalData.cpp:
(JSC::JSGlobalData::storeVPtrs):
(JSC::JSGlobalData::JSGlobalData):
(JSC::JSGlobalData::createNonDefault):
(JSC::JSGlobalData::create):
(JSC::JSGlobalData::sharedInstance):
* runtime/JSGlobalData.h:
Store vptrs just once, no need to repeatedly pick and copy them. This makes it possible to
assert vptr correctness in object destructors (which don't have access to JSGlobalData,
and even Heap::heap(this) will fail for fake objects created from storeVPtrs()).
* runtime/JSArray.cpp: (JSC::JSArray::~JSArray): Assert that vptr is what we expect it to be.
It's important to assert in destructor, because MSVC changes the vptr after constructor
is invoked.
* runtime/JSByteArray.cpp: (JSC::JSByteArray::~JSByteArray): Ditto.
* runtime/JSByteArray.h: Ditto.
* runtime/JSFunction.h: Ditto.
* runtime/JSFunction.cpp: (JSC::JSFunction::~JSFunction): Ditto.
* runtime/JSCell.h: (JSC::JSCell::setVPtr): Added a method to substitute vptr for another
one.
* runtime/JSString.h: Export JSString class together with its vftable, and tell other
libraries tp import it. This is needed on platforms that have a separate JavaScriptCore
dynamic library - and on Mac, we already did the export via JavaScriptCore.exp.
(JSC::JSString::~JSString): Assert tha vptr is what we expect it to be.
(JSC::fixupVPtr): Store a previously saved primary vftable pointer (do nothing if building
JavaScriptCore itself).
(JSC::jsSingleCharacterString): Call fixupVPtr in case this is call across DLL boundary.
(JSC::jsSingleCharacterSubstring): Ditto.
(JSC::jsNontrivialString): Ditto.
(JSC::jsString): Ditto.
(JSC::jsSubstring): Ditto.
(JSC::jsOwnedString): Ditto.
* JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def: Export the new static
JSGlobalData members that are used in WebCore via inline functions.
2010-01-07 Geoffrey Garen <ggaren@apple.com>
Reviewed by Sam Weinig.
......
......@@ -180,12 +180,14 @@ EXPORTS
?isHostFunctionNonInline@JSFunction@JSC@@ABE_NXZ
?isMainThread@WTF@@YA_NXZ
?isVariableObject@JSVariableObject@JSC@@UBE_NXZ
?jsArrayVPtr@JSGlobalData@JSC@@2PAXA
?jsNumberCell@JSC@@YA?AVJSValue@1@PAVExecState@1@N@Z
?jsOwnedString@JSC@@YAPAVJSString@1@PAVJSGlobalData@1@ABVUString@1@@Z
?jsRegExpCompile@@YAPAUJSRegExp@@PB_WHW4JSRegExpIgnoreCaseOption@@W4JSRegExpMultilineOption@@PAIPAPBD@Z
?jsRegExpExecute@@YAHPBUJSRegExp@@PB_WHHPAHH@Z
?jsRegExpFree@@YAXPAUJSRegExp@@@Z
?jsString@JSC@@YAPAVJSString@1@PAVJSGlobalData@1@ABVUString@1@@Z
?jsStringVPtr@JSGlobalData@JSC@@2PAXA
?lock@JSLock@JSC@@SAXW4JSLockBehavior@2@@Z
?lock@Mutex@WTF@@QAEXXZ
?lockAtomicallyInitializedStaticMutex@WTF@@YAXXZ
......
......@@ -31,8 +31,10 @@
#else
#define JS_EXPORTDATA __declspec(dllimport)
#endif
#define JS_EXPORTCLASS JS_EXPORTDATA
#else
#define JS_EXPORTDATA
#define JS_EXPORTCLASS
#endif
#if OS(WINDOWS)
......
......@@ -49,6 +49,7 @@ static void initializeThreadingOnce()
{
WTF::initializeThreading();
initializeUString();
JSGlobalData::storeVPtrs();
#if ENABLE(JSC_MULTIPLE_THREADS)
s_dtoaP5Mutex = new Mutex;
initializeDates();
......
......@@ -185,6 +185,7 @@ JSArray::JSArray(NonNullPassRefPtr<Structure> structure, const ArgList& list)
JSArray::~JSArray()
{
ASSERT(vptr() == JSGlobalData::jsArrayVPtr);
checkConsistency(DestructorConsistencyCheck);
delete m_storage->m_sparseValueMap;
......
......@@ -42,7 +42,15 @@ JSByteArray::JSByteArray(ExecState* exec, NonNullPassRefPtr<Structure> structure
{
putDirect(exec->globalData().propertyNames->length, jsNumber(exec, m_storage->length()), ReadOnly | DontDelete);
}
#if !ASSERT_DISABLED
JSByteArray::~JSByteArray()
{
ASSERT(vptr() == JSGlobalData::jsByteArrayVPtr);
}
#endif
PassRefPtr<Structure> JSByteArray::createStructure(JSValue prototype)
{
PassRefPtr<Structure> result = Structure::create(prototype, TypeInfo(ObjectType, StructureFlags));
......
......@@ -33,7 +33,7 @@
namespace JSC {
class JSByteArray : public JSObject {
friend struct VPtrSet;
friend class JSGlobalData;
public:
bool canAccessIndex(unsigned i) { return i < m_storage->length(); }
JSValue getIndex(ExecState* exec, unsigned i)
......@@ -91,6 +91,10 @@ namespace JSC {
WTF::ByteArray* storage() const { return m_storage.get(); }
#if !ASSERT_DISABLED
virtual ~JSByteArray();
#endif
protected:
static const unsigned StructureFlags = OverridesGetOwnPropertySlot | OverridesGetPropertyNames | JSObject::StructureFlags;
......
......@@ -43,7 +43,7 @@ namespace JSC {
friend class JSValue;
friend class JSAPIValueWrapper;
friend class JSZombie;
friend struct VPtrSet;
friend class JSGlobalData;
private:
explicit JSCell(Structure*);
......@@ -111,6 +111,7 @@ namespace JSC {
virtual JSString* toThisJSString(ExecState*);
virtual JSValue getJSNumber();
void* vptr() { return *reinterpret_cast<void**>(this); }
void setVPtr(void* vptr) { *reinterpret_cast<void**>(this) = vptr; }
private:
// Base implementation; for non-object classes implements getPropertySlot.
......
......@@ -81,6 +81,8 @@ JSFunction::JSFunction(ExecState* exec, NonNullPassRefPtr<FunctionExecutable> ex
JSFunction::~JSFunction()
{
ASSERT(vptr() == JSGlobalData::jsFunctionVPtr);
// JIT code for other functions may have had calls linked directly to the code for this function; these links
// are based on a check for the this pointer value for this JSFunction - which will no longer be valid once
// this memory is freed and may be reused (potentially for another, different JSFunction).
......
......@@ -36,7 +36,7 @@ namespace JSC {
class JSFunction : public InternalFunction {
friend class JIT;
friend struct VPtrSet;
friend class JSGlobalData;
typedef InternalFunction Base;
......
......@@ -71,42 +71,38 @@ extern JSC_CONST_HASHTABLE HashTable regExpTable;
extern JSC_CONST_HASHTABLE HashTable regExpConstructorTable;
extern JSC_CONST_HASHTABLE HashTable stringTable;
struct VPtrSet {
VPtrSet();
void* JSGlobalData::jsArrayVPtr;
void* JSGlobalData::jsByteArrayVPtr;
void* JSGlobalData::jsStringVPtr;
void* JSGlobalData::jsFunctionVPtr;
void* jsArrayVPtr;
void* jsByteArrayVPtr;
void* jsStringVPtr;
void* jsFunctionVPtr;
};
VPtrSet::VPtrSet()
void JSGlobalData::storeVPtrs()
{
CollectorCell cell;
void* storage = &cell;
COMPILE_ASSERT(sizeof(JSArray) <= sizeof(CollectorCell), sizeof_JSArray_must_be_less_than_CollectorCell);
JSCell* jsArray = new (storage) JSArray(JSArray::createStructure(jsNull()));
jsArrayVPtr = jsArray->vptr();
JSGlobalData::jsArrayVPtr = jsArray->vptr();
jsArray->~JSCell();
COMPILE_ASSERT(sizeof(JSByteArray) <= sizeof(CollectorCell), sizeof_JSByteArray_must_be_less_than_CollectorCell);
JSCell* jsByteArray = new (storage) JSByteArray(JSByteArray::VPtrStealingHack);
jsByteArrayVPtr = jsByteArray->vptr();
JSGlobalData::jsByteArrayVPtr = jsByteArray->vptr();
jsByteArray->~JSCell();
COMPILE_ASSERT(sizeof(JSString) <= sizeof(CollectorCell), sizeof_JSString_must_be_less_than_CollectorCell);
JSCell* jsString = new (storage) JSString(JSString::VPtrStealingHack);
jsStringVPtr = jsString->vptr();
JSGlobalData::jsStringVPtr = jsString->vptr();
jsString->~JSCell();
COMPILE_ASSERT(sizeof(JSFunction) <= sizeof(CollectorCell), sizeof_JSFunction_must_be_less_than_CollectorCell);
JSCell* jsFunction = new (storage) JSFunction(JSFunction::createStructure(jsNull()));
jsFunctionVPtr = jsFunction->vptr();
JSGlobalData::jsFunctionVPtr = jsFunction->vptr();
jsFunction->~JSCell();
}
JSGlobalData::JSGlobalData(bool isShared, const VPtrSet& vptrSet)
JSGlobalData::JSGlobalData(bool isShared)
: isSharedInstance(isShared)
, clientData(0)
, arrayTable(fastNew<HashTable>(JSC::arrayTable))
......@@ -130,10 +126,6 @@ JSGlobalData::JSGlobalData(bool isShared, const VPtrSet& vptrSet)
#if USE(JSVALUE32)
, numberStructure(JSNumberCell::createStructure(jsNull()))
#endif
, jsArrayVPtr(vptrSet.jsArrayVPtr)
, jsByteArrayVPtr(vptrSet.jsByteArrayVPtr)
, jsStringVPtr(vptrSet.jsStringVPtr)
, jsFunctionVPtr(vptrSet.jsFunctionVPtr)
, identifierTable(createIdentifierTable())
, propertyNames(new CommonIdentifiers(this))
, emptyList(new MarkedArgumentBuffer)
......@@ -149,7 +141,7 @@ JSGlobalData::JSGlobalData(bool isShared, const VPtrSet& vptrSet)
, dynamicGlobalObject(0)
, functionCodeBlockBeingReparsed(0)
, firstStringifierToMark(0)
, markStack(vptrSet.jsArrayVPtr)
, markStack(jsArrayVPtr)
, cachedUTCOffset(NaN)
, weakRandom(static_cast<int>(currentTime()))
#ifndef NDEBUG
......@@ -204,12 +196,12 @@ JSGlobalData::~JSGlobalData()
PassRefPtr<JSGlobalData> JSGlobalData::createNonDefault()
{
return adoptRef(new JSGlobalData(false, VPtrSet()));
return adoptRef(new JSGlobalData(false));
}
PassRefPtr<JSGlobalData> JSGlobalData::create()
{
JSGlobalData* globalData = new JSGlobalData(false, VPtrSet());
JSGlobalData* globalData = new JSGlobalData(false);
setDefaultIdentifierTable(globalData->identifierTable);
setCurrentIdentifierTable(globalData->identifierTable);
return adoptRef(globalData);
......@@ -232,7 +224,7 @@ JSGlobalData& JSGlobalData::sharedInstance()
{
JSGlobalData*& instance = sharedInstanceInternal();
if (!instance) {
instance = new JSGlobalData(true, VPtrSet());
instance = new JSGlobalData(true);
#if ENABLE(JSC_MULTIPLE_THREADS)
instance->makeUsableFromMultipleThreads();
#endif
......
......@@ -62,7 +62,6 @@ namespace JSC {
struct HashTable;
struct Instruction;
struct VPtrSet;
struct DSTOffsetCache {
DSTOffsetCache()
......@@ -130,10 +129,11 @@ namespace JSC {
RefPtr<Structure> numberStructure;
#endif
void* jsArrayVPtr;
void* jsByteArrayVPtr;
void* jsStringVPtr;
void* jsFunctionVPtr;
static void storeVPtrs();
static JS_EXPORTDATA void* jsArrayVPtr;
static JS_EXPORTDATA void* jsByteArrayVPtr;
static JS_EXPORTDATA void* jsStringVPtr;
static JS_EXPORTDATA void* jsFunctionVPtr;
IdentifierTable* identifierTable;
CommonIdentifiers* propertyNames;
......@@ -194,7 +194,7 @@ namespace JSC {
void stopSampling();
void dumpSampleData(ExecState* exec);
private:
JSGlobalData(bool isShared, const VPtrSet&);
JSGlobalData(bool isShared);
static JSGlobalData*& sharedInstanceInternal();
void createNativeThunk();
};
......
......@@ -59,10 +59,10 @@ namespace JSC {
JSString* jsOwnedString(JSGlobalData*, const UString&);
JSString* jsOwnedString(ExecState*, const UString&);
class JSString : public JSCell {
class JS_EXPORTCLASS JSString : public JSCell {
public:
friend class JIT;
friend struct VPtrSet;
friend class JSGlobalData;
// A Rope is a string composed of a set of substrings.
class Rope : public RefCounted<Rope> {
......@@ -247,6 +247,7 @@ namespace JSC {
~JSString()
{
ASSERT(vptr() == JSGlobalData::jsStringVPtr);
for (unsigned i = 0; i < m_ropeLength; ++i)
m_fibers[i].deref();
}
......@@ -350,6 +351,16 @@ namespace JSC {
JSString* asString(JSValue);
// When an object is created from a different DLL, MSVC changes vptr to a "local" one right after invoking a constructor,
// see <http://groups.google.com/group/microsoft.public.vc.language/msg/55cdcefeaf770212>.
// This breaks isJSString(), and we don't need that hack anyway, so we change vptr back to primary one.
// The below function must be called by any inline function that invokes a JSString constructor.
#if COMPILER(MSVC) && !defined(BUILDING_JavaScriptCore)
inline JSString* fixupVPtr(JSGlobalData* globalData, JSString* string) { string->setVPtr(globalData->jsStringVPtr); return string; }
#else
inline JSString* fixupVPtr(JSGlobalData*, JSString* string) { return string; }
#endif
inline JSString* asString(JSValue value)
{
ASSERT(asCell(value)->isString());
......@@ -365,7 +376,7 @@ namespace JSC {
{
if (c <= 0xFF)
return globalData->smallStrings.singleCharacterString(globalData, c);
return new (globalData) JSString(globalData, UString(&c, 1));
return fixupVPtr(globalData, new (globalData) JSString(globalData, UString(&c, 1)));
}
inline JSString* jsSingleCharacterSubstring(JSGlobalData* globalData, const UString& s, unsigned offset)
......@@ -374,7 +385,7 @@ namespace JSC {
UChar c = s.data()[offset];
if (c <= 0xFF)
return globalData->smallStrings.singleCharacterString(globalData, c);
return new (globalData) JSString(globalData, UString(UString::Rep::create(s.rep(), offset, 1)));
return fixupVPtr(globalData, new (globalData) JSString(globalData, UString(UString::Rep::create(s.rep(), offset, 1))));
}
inline JSString* jsNontrivialString(JSGlobalData* globalData, const char* s)
......@@ -382,13 +393,13 @@ namespace JSC {
ASSERT(s);
ASSERT(s[0]);
ASSERT(s[1]);
return new (globalData) JSString(globalData, s);
return fixupVPtr(globalData, new (globalData) JSString(globalData, s));
}
inline JSString* jsNontrivialString(JSGlobalData* globalData, const UString& s)
{
ASSERT(s.size() > 1);
return new (globalData) JSString(globalData, s);
return fixupVPtr(globalData, new (globalData) JSString(globalData, s));
}
inline JSString* JSString::getIndex(ExecState* exec, unsigned i)
......@@ -407,7 +418,7 @@ namespace JSC {
if (c <= 0xFF)
return globalData->smallStrings.singleCharacterString(globalData, c);
}
return new (globalData) JSString(globalData, s);
return fixupVPtr(globalData, new (globalData) JSString(globalData, s));
}
inline JSString* jsSubstring(JSGlobalData* globalData, const UString& s, unsigned offset, unsigned length)
......@@ -422,7 +433,7 @@ namespace JSC {
if (c <= 0xFF)
return globalData->smallStrings.singleCharacterString(globalData, c);
}
return new (globalData) JSString(globalData, UString(UString::Rep::create(s.rep(), offset, length)), JSString::HasOtherOwner);
return fixupVPtr(globalData, new (globalData) JSString(globalData, UString(UString::Rep::create(s.rep(), offset, length)), JSString::HasOtherOwner));
}
inline JSString* jsOwnedString(JSGlobalData* globalData, const UString& s)
......@@ -435,7 +446,7 @@ namespace JSC {
if (c <= 0xFF)
return globalData->smallStrings.singleCharacterString(globalData, c);
}
return new (globalData) JSString(globalData, s, JSString::HasOtherOwner);
return fixupVPtr(globalData, new (globalData) JSString(globalData, s, JSString::HasOtherOwner));
}
inline JSString* jsEmptyString(ExecState* exec) { return jsEmptyString(&exec->globalData()); }
......
2010-01-07 Alexey Proskuryakov <ap@apple.com>
Reviewed by Geoffrey Garen.
https://bugs.webkit.org/show_bug.cgi?id=33057
REGRESSION(r49365): typeof(xhr.responseText) != "string" in Windows
<rdar://problem/7296920> REGRESSION: WebKit fails to start PeaceKeeper benchmark
* fast/js/script-tests/webcore-string-comparison.js: Added.
* fast/js/webcore-string-comparison-expected.txt: Added.
* fast/js/webcore-string-comparison.html: Added.
2010-01-07 Simon Fraser <simon.fraser@apple.com>
Reviewed by Kevin Decker, Darin Adler.
description('Test for <a href="https://bugs.webkit.org/show_bug.cgi?id=33057">bug 33057</a>: typeof(xhr.responseText) != "string" on Windows.</p>');
var r = new XMLHttpRequest;
r.open("GET", "webcore-string-comparison.html", false);
r.send();
shouldBe('typeof(r.responseText) == "string"', 'true');
shouldBe('typeof(r.responseText) === "string"', 'true');
shouldBe('typeof(r.responseText) != "string"', 'false');
shouldBe('typeof(r.responseText) !== "string"', 'false');
shouldBe('"" + typeof(r.responseText)', '"string"');
shouldBe('typeof(r.responseText) + ""', '"string"');
shouldBe('String(typeof(r.responseText))', '"string"');
shouldBe('String(typeof(r.responseText))', 'typeof(r.responseText)');
successfullyParsed = true;
Test for bug 33057: typeof(xhr.responseText) != "string" on Windows.
On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
PASS typeof(r.responseText) == "string" is true
PASS typeof(r.responseText) === "string" is true
PASS typeof(r.responseText) != "string" is false
PASS typeof(r.responseText) !== "string" is false
PASS "" + typeof(r.responseText) is "string"
PASS typeof(r.responseText) + "" is "string"
PASS String(typeof(r.responseText)) is "string"
PASS String(typeof(r.responseText)) is typeof(r.responseText)
PASS successfullyParsed is true
TEST COMPLETE
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
<html>
<head>
<link rel="stylesheet" href="resources/js-test-style.css">
<script src="resources/js-test-pre.js"></script>
</head>
<body>
<p id="description"></p>
<div id="console"></div>
<script src="script-tests/webcore-string-comparison.js"></script>
<script src="resources/js-test-post.js"></script>
</body>
</html>
2010-01-07 Alexey Proskuryakov <ap@apple.com>
Reviewed by Geoffrey Garen.
https://bugs.webkit.org/show_bug.cgi?id=33057
REGRESSION(r49365): typeof(xhr.responseText) != "string" in Windows
<rdar://problem/7296920> REGRESSION: WebKit fails to start PeaceKeeper benchmark
* config.h: Define JS_EXPORTCLASS. I'm not sure why this isn't done in JSC globally for all
possible clients, but keeping the current design for now.
2010-01-07 Brent Fulgham <bfulgham@webkit.org>
Reviewed by Jon Honeycutt.
......@@ -36,8 +36,10 @@
#else
#define WEBKIT_EXPORTDATA __declspec(dllimport)
#endif
#define JS_EXPORTCLASS JS_EXPORTDATA
#else
#define JS_EXPORTDATA
#define JS_EXPORTCLASS
#define WEBKIT_EXPORTDATA
#endif
......
2010-01-07 Alexey Proskuryakov <ap@apple.com>
Reviewed by Geoffrey Garen.
https://bugs.webkit.org/show_bug.cgi?id=33057
REGRESSION(r49365): typeof(xhr.responseText) != "string" in Windows
<rdar://problem/7296920> REGRESSION: WebKit fails to start PeaceKeeper benchmark
* WebCoreSupport/WebInspectorClientCF.cpp: Define JS_EXPORTCLASS. I'm not sure why this
isn't done in JSC globally for all possible clients, but keeping the current design for now.
2009-12-03 Pavel Feldman <pfeldman@dhcp-172-28-174-220.spb.corp.google.com>
Reviewed by Timothy Hatcher.
......
......@@ -43,8 +43,10 @@
#else
#define JS_EXPORTDATA __declspec(dllimport)
#endif
#define JS_EXPORTCLASS JS_EXPORTDATA
#else
#define JS_EXPORTDATA
#define JS_EXPORTCLASS
#endif
#include "WebInspectorClient.h"
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment