Commit 6c9b264e authored by barraclough@apple.com's avatar barraclough@apple.com

Add support for private names

https://bugs.webkit.org/show_bug.cgi?id=86509

Reviewed by Oliver Hunt.

The spec isn't final, but we can start adding support to allow property maps
to contain keys that aren't identifiers.

Source/JavaScriptCore: 

* API/JSCallbackObjectFunctions.h:
(JSC::::getOwnPropertySlot):
(JSC::::put):
(JSC::::deleteProperty):
(JSC::::getStaticValue):
(JSC::::staticFunctionGetter):
(JSC::::callbackGetter):
    - Only expose public named properties over the JSC API.
* CMakeLists.txt:
* DerivedSources.make:
* DerivedSources.pri:
* GNUmakefile.list.am:
* JavaScriptCore.gypi:
* JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj:
* JavaScriptCore.xcodeproj/project.pbxproj:
* Target.pri:
    - Added new files to build system.
* dfg/DFGOperations.cpp:
(JSC::DFG::operationPutByValInternal):
    - Added support for property access with name objects.
* interpreter/CallFrame.h:
(JSC::ExecState::privateNamePrototypeTable):
    - Added hash table for NamePrototype
* interpreter/Interpreter.cpp:
(JSC::Interpreter::privateExecute):
    - Added support for property access with name objects.
* jit/JITStubs.cpp:
(JSC::DEFINE_STUB_FUNCTION):
    - Added support for property access with name objects.
* llint/LLIntSlowPaths.cpp:
(JSC::LLInt::getByVal):
(JSC::LLInt::LLINT_SLOW_PATH_DECL):
* runtime/CommonSlowPaths.h:
(JSC::CommonSlowPaths::opIn):
* runtime/JSActivation.cpp:
(JSC::JSActivation::symbolTableGet):
(JSC::JSActivation::symbolTablePut):
(JSC::JSActivation::symbolTablePutWithAttributes):
    - Added support for property access with name objects.
* runtime/JSGlobalData.cpp:
(JSC):
(JSC::JSGlobalData::JSGlobalData):
(JSC::JSGlobalData::~JSGlobalData):
* runtime/JSGlobalData.h:
(JSGlobalData):
    - Added hash table for NamePrototype
* runtime/JSGlobalObject.cpp:
(JSC::JSGlobalObject::reset):
* runtime/JSGlobalObject.h:
(JSGlobalObject):
(JSC::JSGlobalObject::privateNameStructure):
(JSC::JSGlobalObject::symbolTableHasProperty):
    - Added new global properties.
* runtime/JSType.h:
* runtime/JSTypeInfo.h:
(JSC::TypeInfo::isName):
    - Added type for NameInstances, for fast isName check.
* runtime/JSVariableObject.cpp:
(JSC::JSVariableObject::deleteProperty):
(JSC::JSVariableObject::symbolTableGet):
* runtime/JSVariableObject.h:
(JSC::JSVariableObject::symbolTableGet):
(JSC::JSVariableObject::symbolTablePut):
(JSC::JSVariableObject::symbolTablePutWithAttributes):
    - symbol table lookup should take a PropertyName.
* runtime/Lookup.cpp:
(JSC::setUpStaticFunctionSlot):
* runtime/Lookup.h:
(JSC::HashTable::entry):
    - entry lookup should take a PropertyName.
* runtime/NameConstructor.cpp: Added.
(JSC):
(JSC::NameConstructor::NameConstructor):
(JSC::NameConstructor::finishCreation):
(JSC::constructPrivateName):
(JSC::NameConstructor::getConstructData):
(JSC::NameConstructor::getCallData):
* runtime/NameConstructor.h: Added.
(JSC):
(NameConstructor):
(JSC::NameConstructor::create):
(JSC::NameConstructor::createStructure):
    - Added constructor.
* runtime/NameInstance.cpp: Added.
(JSC):
(JSC::NameInstance::NameInstance):
(JSC::NameInstance::destroy):
* runtime/NameInstance.h: Added.
(JSC):
(NameInstance):
(JSC::NameInstance::createStructure):
(JSC::NameInstance::create):
(JSC::NameInstance::privateName):
(JSC::NameInstance::nameString):
(JSC::NameInstance::finishCreation):
(JSC::isName):
    - Added instance.
* runtime/NamePrototype.cpp: Added.
(JSC):
(JSC::NamePrototype::NamePrototype):
(JSC::NamePrototype::finishCreation):
(JSC::NamePrototype::getOwnPropertySlot):
(JSC::NamePrototype::getOwnPropertyDescriptor):
(JSC::privateNameProtoFuncToString):
* runtime/NamePrototype.h: Added.
(JSC):
(NamePrototype):
(JSC::NamePrototype::create):
(JSC::NamePrototype::createStructure):
    - Added prototype.
* runtime/PrivateName.h: Added.
(JSC):
(PrivateName):
(JSC::PrivateName::PrivateName):
(JSC::PrivateName::uid):
    - A private name object holds a StringImpl that can be used as a unique key in a property map.
* runtime/PropertyMapHashTable.h:
(JSC::PropertyTable::find):
(JSC::PropertyTable::findWithString):
    - Strings should only match keys in the table that are identifiers.
* runtime/PropertyName.h:
(JSC::PropertyName::PropertyName):
(PropertyName):
(JSC::PropertyName::uid):
(JSC::PropertyName::publicName):
(JSC::PropertyName::asIndex):
(JSC::operator==):
(JSC::operator!=):
    - replaced impl() & ustring() with uid() [to get the raw impl] and publicName() [impl or null, if not an identifier].
* runtime/Structure.cpp:
(JSC::Structure::despecifyDictionaryFunction):
(JSC::Structure::addPropertyTransitionToExistingStructure):
(JSC::Structure::addPropertyTransition):
(JSC::Structure::attributeChangeTransition):
(JSC::Structure::get):
(JSC::Structure::despecifyFunction):
(JSC::Structure::putSpecificValue):
(JSC::Structure::remove):
(JSC::Structure::getPropertyNamesFromStructure):
* runtime/Structure.h:
(JSC::Structure::get):
    - call uid() to get a PropertyName raw impl, for use as a key.

Source/WebCore: 

Test: fast/js/names.html

* bindings/js/JSCSSStyleDeclarationCustom.cpp:
(WebCore::cssPropertyIDForJSCSSPropertyName):
* bindings/js/JSDOMBinding.cpp:
(WebCore::findAtomicString):
(WebCore::objectToStringFunctionGetter):
* bindings/js/JSDOMBinding.h:
(WebCore::propertyNameToString):
(WebCore::propertyNameToAtomicString):
* bindings/js/JSDOMWindowCustom.cpp:
(WebCore::nonCachingStaticFunctionGetter):
* bindings/js/JSHistoryCustom.cpp:
(WebCore::nonCachingStaticBackFunctionGetter):
(WebCore::nonCachingStaticForwardFunctionGetter):
(WebCore::nonCachingStaticGoFunctionGetter):
* bindings/js/JSLocationCustom.cpp:
(WebCore::nonCachingStaticReplaceFunctionGetter):
(WebCore::nonCachingStaticReloadFunctionGetter):
(WebCore::nonCachingStaticAssignFunctionGetter):
* bridge/c/c_class.cpp:
(JSC::Bindings::CClass::methodsNamed):
(JSC::Bindings::CClass::fieldNamed):
* bridge/c/c_instance.cpp:
(JSC::Bindings::CInstance::getMethod):
* bridge/jni/jsc/JavaClassJSC.cpp:
(JavaClass::methodsNamed):
(JavaClass::fieldNamed):
* bridge/jni/jsc/JavaInstanceJSC.cpp:
* bridge/objc/objc_class.mm:
(JSC::Bindings::ObjcClass::methodsNamed):
(JSC::Bindings::ObjcClass::fieldNamed):
(JSC::Bindings::ObjcClass::fallbackObject):
* bridge/objc/objc_instance.mm:
(ObjcInstance::setValueOfUndefinedField):
(ObjcInstance::getValueOfUndefinedField):
    - Removed PropertyName::impl(), call publicName() to get the string associated with a name.

Source/WebKit/mac: 

* Plugins/Hosted/ProxyInstance.mm:
(WebKit::ProxyClass::methodsNamed):
(WebKit::ProxyClass::fieldNamed):
(WebKit::ProxyInstance::getMethod):
(WebKit::ProxyInstance::methodsNamed):
(WebKit::ProxyInstance::fieldNamed):
    - Removed PropertyName::impl(), call publicName() to get the string associated with a name.

Source/WebKit2: 

* WebProcess/Plugins/Netscape/JSNPObject.cpp:
(WebKit::npIdentifierFromIdentifier):
(WebKit::JSNPObject::methodGetter):
    - Removed PropertyName::impl(), call publicName() to get the string associated with a name.

Source/WTF: 

* wtf/text/StringImpl.h:
(WTF::StringImpl::StringImpl):
(StringImpl):
(WTF::StringImpl::createEmptyUnique):
(WTF::StringImpl::isEmptyUnique):
    - Allow empty string impls to be allocated, which can be used as unique keys.

LayoutTests: 

* fast/js/names-expected.txt: Added.
* fast/js/names.html: Added.
* fast/js/script-tests/names.js: Added.
    - Added test cases.



git-svn-id: http://svn.webkit.org/repository/webkit/trunk@117859 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent 339a5dde
2012-05-15 Gavin Barraclough <barraclough@apple.com>
Add support for private names
https://bugs.webkit.org/show_bug.cgi?id=86509
Reviewed by Oliver Hunt.
The spec isn't final, but we can start adding support to allow property maps
to contain keys that aren't identifiers.
* fast/js/names-expected.txt: Added.
* fast/js/names.html: Added.
* fast/js/script-tests/names.js: Added.
- Added test cases.
2012-05-21 Emil A Eklund <eae@chromium.org>
Fix bug in paintNinePieceImage exposed by subpixel change
This tests an early experimental implementation of ES6-esque private names.
On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
PASS prop in o is false
PASS 'prop' in o is false
PASS Object.getOwnPropertyNames(o).length is 0
PASS forIn(o) is []
PASS prop in o is true
PASS 'prop' in o is false
PASS Object.getOwnPropertyNames(o).length is 0
PASS forIn(o) is []
PASS o[prop] is 42
PASS o['prop'] is 101
PASS Object.getOwnPropertyNames(o).length is 1
PASS forIn(o) is ["prop"]
PASS prop in o is false
PASS 'prop' in o is true
PASS Object.getOwnPropertyNames(o).length is 1
PASS forIn(o) is ["prop"]
PASS successfullyParsed is true
TEST COMPLETE
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
<html>
<head>
<script src="resources/js-test-pre.js"></script>
</head>
<body>
<script src="script-tests/names.js"></script>
<script src="resources/js-test-post.js"></script>
</body>
</html>
description(
"This tests an early experimental implementation of ES6-esque private names."
);
function forIn(o)
{
var a = [];
for (x in o)
a.push(x);
return a;
}
var prop = Name("prop");
var o = {};
shouldBeFalse("prop in o");
shouldBeFalse("'prop' in o");
shouldBe("Object.getOwnPropertyNames(o).length", '0');
shouldBe("forIn(o)", '[]');
o[prop] = 42;
shouldBeTrue("prop in o");
shouldBeFalse("'prop' in o");
shouldBe("Object.getOwnPropertyNames(o).length", '0');
shouldBe("forIn(o)", '[]');
o['prop'] = 101;
shouldBe("o[prop]", '42');
shouldBe("o['prop']", '101');
shouldBe("Object.getOwnPropertyNames(o).length", '1');
shouldBe("forIn(o)", '["prop"]');
delete o[prop];
shouldBeFalse("prop in o");
shouldBeTrue("'prop' in o");
shouldBe("Object.getOwnPropertyNames(o).length", '1');
shouldBe("forIn(o)", '["prop"]');
successfullyParsed = true;
......@@ -1436,6 +1436,9 @@ BUGWK80335 : fast/js/mozilla/strict/15.4.4.13.html = TEXT
// V8 should implement the length property of constructors
BUGWK78657 : fast/js/constructor-length.html = FAIL
// This is JSC-only, preliminary implementation of a ES6 feature - doesn't exist in V8 (yet)
BUGWK86509 SKIP WONTFIX : fast/js/names.html = FAIL
// Linux pixeltest failure: The text suggests that the radios should not
// overlap, but it's very close and quite different from the Windows version
BUGCR10350 LINUX : fast/replaced/width100percent-radio.html = FAIL
......
......@@ -129,54 +129,56 @@ bool JSCallbackObject<Parent>::getOwnPropertySlot(JSCell* cell, ExecState* exec,
JSObjectRef thisRef = toRef(thisObject);
RefPtr<OpaqueJSString> propertyNameRef;
for (JSClassRef jsClass = thisObject->classRef(); jsClass; jsClass = jsClass->parentClass) {
// optional optimization to bypass getProperty in cases when we only need to know if the property exists
if (JSObjectHasPropertyCallback hasProperty = jsClass->hasProperty) {
if (!propertyNameRef)
propertyNameRef = OpaqueJSString::create(propertyName.ustring());
APICallbackShim callbackShim(exec);
if (hasProperty(ctx, thisRef, propertyNameRef.get())) {
slot.setCustom(thisObject, callbackGetter);
return true;
}
} else if (JSObjectGetPropertyCallback getProperty = jsClass->getProperty) {
if (!propertyNameRef)
propertyNameRef = OpaqueJSString::create(propertyName.ustring());
JSValueRef exception = 0;
JSValueRef value;
{
if (StringImpl* name = propertyName.publicName()) {
for (JSClassRef jsClass = thisObject->classRef(); jsClass; jsClass = jsClass->parentClass) {
// optional optimization to bypass getProperty in cases when we only need to know if the property exists
if (JSObjectHasPropertyCallback hasProperty = jsClass->hasProperty) {
if (!propertyNameRef)
propertyNameRef = OpaqueJSString::create(name);
APICallbackShim callbackShim(exec);
value = getProperty(ctx, thisRef, propertyNameRef.get(), &exception);
}
if (exception) {
throwError(exec, toJS(exec, exception));
slot.setValue(jsUndefined());
return true;
}
if (value) {
slot.setValue(toJS(exec, value));
return true;
}
}
if (OpaqueJSClassStaticValuesTable* staticValues = jsClass->staticValues(exec)) {
if (staticValues->contains(propertyName.impl())) {
JSValue value = thisObject->getStaticValue(exec, propertyName);
if (hasProperty(ctx, thisRef, propertyNameRef.get())) {
slot.setCustom(thisObject, callbackGetter);
return true;
}
} else if (JSObjectGetPropertyCallback getProperty = jsClass->getProperty) {
if (!propertyNameRef)
propertyNameRef = OpaqueJSString::create(name);
JSValueRef exception = 0;
JSValueRef value;
{
APICallbackShim callbackShim(exec);
value = getProperty(ctx, thisRef, propertyNameRef.get(), &exception);
}
if (exception) {
throwError(exec, toJS(exec, exception));
slot.setValue(jsUndefined());
return true;
}
if (value) {
slot.setValue(value);
slot.setValue(toJS(exec, value));
return true;
}
}
}
if (OpaqueJSClassStaticFunctionsTable* staticFunctions = jsClass->staticFunctions(exec)) {
if (staticFunctions->contains(propertyName.impl())) {
slot.setCustom(thisObject, staticFunctionGetter);
return true;
if (OpaqueJSClassStaticValuesTable* staticValues = jsClass->staticValues(exec)) {
if (staticValues->contains(name)) {
JSValue value = thisObject->getStaticValue(exec, propertyName);
if (value) {
slot.setValue(value);
return true;
}
}
}
if (OpaqueJSClassStaticFunctionsTable* staticFunctions = jsClass->staticFunctions(exec)) {
if (staticFunctions->contains(name)) {
slot.setCustom(thisObject, staticFunctionGetter);
return true;
}
}
}
}
return Parent::getOwnPropertySlot(thisObject, exec, propertyName, slot);
}
......@@ -233,53 +235,55 @@ void JSCallbackObject<Parent>::put(JSCell* cell, ExecState* exec, PropertyName p
RefPtr<OpaqueJSString> propertyNameRef;
JSValueRef valueRef = toRef(exec, value);
for (JSClassRef jsClass = thisObject->classRef(); jsClass; jsClass = jsClass->parentClass) {
if (JSObjectSetPropertyCallback setProperty = jsClass->setProperty) {
if (!propertyNameRef)
propertyNameRef = OpaqueJSString::create(propertyName.ustring());
JSValueRef exception = 0;
bool result;
{
APICallbackShim callbackShim(exec);
result = setProperty(ctx, thisRef, propertyNameRef.get(), valueRef, &exception);
}
if (exception)
throwError(exec, toJS(exec, exception));
if (result || exception)
return;
}
if (OpaqueJSClassStaticValuesTable* staticValues = jsClass->staticValues(exec)) {
if (StaticValueEntry* entry = staticValues->get(propertyName.impl())) {
if (entry->attributes & kJSPropertyAttributeReadOnly)
if (StringImpl* name = propertyName.publicName()) {
for (JSClassRef jsClass = thisObject->classRef(); jsClass; jsClass = jsClass->parentClass) {
if (JSObjectSetPropertyCallback setProperty = jsClass->setProperty) {
if (!propertyNameRef)
propertyNameRef = OpaqueJSString::create(name);
JSValueRef exception = 0;
bool result;
{
APICallbackShim callbackShim(exec);
result = setProperty(ctx, thisRef, propertyNameRef.get(), valueRef, &exception);
}
if (exception)
throwError(exec, toJS(exec, exception));
if (result || exception)
return;
if (JSObjectSetPropertyCallback setProperty = entry->setProperty) {
if (!propertyNameRef)
propertyNameRef = OpaqueJSString::create(propertyName.ustring());
JSValueRef exception = 0;
bool result;
{
APICallbackShim callbackShim(exec);
result = setProperty(ctx, thisRef, propertyNameRef.get(), valueRef, &exception);
}
if (exception)
throwError(exec, toJS(exec, exception));
if (result || exception)
}
if (OpaqueJSClassStaticValuesTable* staticValues = jsClass->staticValues(exec)) {
if (StaticValueEntry* entry = staticValues->get(name)) {
if (entry->attributes & kJSPropertyAttributeReadOnly)
return;
if (JSObjectSetPropertyCallback setProperty = entry->setProperty) {
if (!propertyNameRef)
propertyNameRef = OpaqueJSString::create(name);
JSValueRef exception = 0;
bool result;
{
APICallbackShim callbackShim(exec);
result = setProperty(ctx, thisRef, propertyNameRef.get(), valueRef, &exception);
}
if (exception)
throwError(exec, toJS(exec, exception));
if (result || exception)
return;
}
}
}
}
if (OpaqueJSClassStaticFunctionsTable* staticFunctions = jsClass->staticFunctions(exec)) {
if (StaticFunctionEntry* entry = staticFunctions->get(propertyName.impl())) {
if (entry->attributes & kJSPropertyAttributeReadOnly)
if (OpaqueJSClassStaticFunctionsTable* staticFunctions = jsClass->staticFunctions(exec)) {
if (StaticFunctionEntry* entry = staticFunctions->get(name)) {
if (entry->attributes & kJSPropertyAttributeReadOnly)
return;
thisObject->JSCallbackObject<Parent>::putDirect(exec->globalData(), propertyName, value); // put as override property
return;
thisObject->JSCallbackObject<Parent>::putDirect(exec->globalData(), propertyName, value); // put as override property
return;
}
}
}
}
return Parent::put(thisObject, exec, propertyName, value, slot);
}
......@@ -291,39 +295,41 @@ bool JSCallbackObject<Parent>::deleteProperty(JSCell* cell, ExecState* exec, Pro
JSObjectRef thisRef = toRef(thisObject);
RefPtr<OpaqueJSString> propertyNameRef;
for (JSClassRef jsClass = thisObject->classRef(); jsClass; jsClass = jsClass->parentClass) {
if (JSObjectDeletePropertyCallback deleteProperty = jsClass->deleteProperty) {
if (!propertyNameRef)
propertyNameRef = OpaqueJSString::create(propertyName.ustring());
JSValueRef exception = 0;
bool result;
{
APICallbackShim callbackShim(exec);
result = deleteProperty(ctx, thisRef, propertyNameRef.get(), &exception);
if (StringImpl* name = propertyName.publicName()) {
for (JSClassRef jsClass = thisObject->classRef(); jsClass; jsClass = jsClass->parentClass) {
if (JSObjectDeletePropertyCallback deleteProperty = jsClass->deleteProperty) {
if (!propertyNameRef)
propertyNameRef = OpaqueJSString::create(name);
JSValueRef exception = 0;
bool result;
{
APICallbackShim callbackShim(exec);
result = deleteProperty(ctx, thisRef, propertyNameRef.get(), &exception);
}
if (exception)
throwError(exec, toJS(exec, exception));
if (result || exception)
return true;
}
if (exception)
throwError(exec, toJS(exec, exception));
if (result || exception)
return true;
}
if (OpaqueJSClassStaticValuesTable* staticValues = jsClass->staticValues(exec)) {
if (StaticValueEntry* entry = staticValues->get(propertyName.impl())) {
if (entry->attributes & kJSPropertyAttributeDontDelete)
return false;
return true;
if (OpaqueJSClassStaticValuesTable* staticValues = jsClass->staticValues(exec)) {
if (StaticValueEntry* entry = staticValues->get(name)) {
if (entry->attributes & kJSPropertyAttributeDontDelete)
return false;
return true;
}
}
}
if (OpaqueJSClassStaticFunctionsTable* staticFunctions = jsClass->staticFunctions(exec)) {
if (StaticFunctionEntry* entry = staticFunctions->get(propertyName.impl())) {
if (entry->attributes & kJSPropertyAttributeDontDelete)
return false;
return true;
if (OpaqueJSClassStaticFunctionsTable* staticFunctions = jsClass->staticFunctions(exec)) {
if (StaticFunctionEntry* entry = staticFunctions->get(name)) {
if (entry->attributes & kJSPropertyAttributeDontDelete)
return false;
return true;
}
}
}
}
return Parent::deleteProperty(thisObject, exec, propertyName);
}
......@@ -509,25 +515,30 @@ JSValue JSCallbackObject<Parent>::getStaticValue(ExecState* exec, PropertyName p
JSObjectRef thisRef = toRef(this);
RefPtr<OpaqueJSString> propertyNameRef;
for (JSClassRef jsClass = classRef(); jsClass; jsClass = jsClass->parentClass)
if (OpaqueJSClassStaticValuesTable* staticValues = jsClass->staticValues(exec))
if (StaticValueEntry* entry = staticValues->get(propertyName.impl()))
if (JSObjectGetPropertyCallback getProperty = entry->getProperty) {
if (!propertyNameRef)
propertyNameRef = OpaqueJSString::create(propertyName.ustring());
JSValueRef exception = 0;
JSValueRef value;
{
APICallbackShim callbackShim(exec);
value = getProperty(toRef(exec), thisRef, propertyNameRef.get(), &exception);
}
if (exception) {
throwError(exec, toJS(exec, exception));
return jsUndefined();
if (StringImpl* name = propertyName.publicName()) {
for (JSClassRef jsClass = classRef(); jsClass; jsClass = jsClass->parentClass) {
if (OpaqueJSClassStaticValuesTable* staticValues = jsClass->staticValues(exec)) {
if (StaticValueEntry* entry = staticValues->get(name)) {
if (JSObjectGetPropertyCallback getProperty = entry->getProperty) {
if (!propertyNameRef)
propertyNameRef = OpaqueJSString::create(name);
JSValueRef exception = 0;
JSValueRef value;
{
APICallbackShim callbackShim(exec);
value = getProperty(toRef(exec), thisRef, propertyNameRef.get(), &exception);
}
if (exception) {
throwError(exec, toJS(exec, exception));
return jsUndefined();
}
if (value)
return toJS(exec, value);
}
if (value)
return toJS(exec, value);
}
}
}
}
return JSValue();
}
......@@ -542,19 +553,21 @@ JSValue JSCallbackObject<Parent>::staticFunctionGetter(ExecState* exec, JSValue
if (Parent::getOwnPropertySlot(thisObj, exec, propertyName, slot2))
return slot2.getValue(exec, propertyName);
for (JSClassRef jsClass = thisObj->classRef(); jsClass; jsClass = jsClass->parentClass) {
if (OpaqueJSClassStaticFunctionsTable* staticFunctions = jsClass->staticFunctions(exec)) {
if (StaticFunctionEntry* entry = staticFunctions->get(propertyName.impl())) {
if (JSObjectCallAsFunctionCallback callAsFunction = entry->callAsFunction) {
JSObject* o = JSCallbackFunction::create(exec, thisObj->globalObject(), callAsFunction, propertyName.ustring());
thisObj->putDirect(exec->globalData(), propertyName, o, entry->attributes);
return o;
if (StringImpl* name = propertyName.publicName()) {
for (JSClassRef jsClass = thisObj->classRef(); jsClass; jsClass = jsClass->parentClass) {
if (OpaqueJSClassStaticFunctionsTable* staticFunctions = jsClass->staticFunctions(exec)) {
if (StaticFunctionEntry* entry = staticFunctions->get(name)) {
if (JSObjectCallAsFunctionCallback callAsFunction = entry->callAsFunction) {
JSObject* o = JSCallbackFunction::create(exec, thisObj->globalObject(), callAsFunction, name);
thisObj->putDirect(exec->globalData(), propertyName, o, entry->attributes);
return o;
}
}
}
}
}
return throwError(exec, createReferenceError(exec, "Static function property defined with NULL callAsFunction callback."));
}
......@@ -566,24 +579,27 @@ JSValue JSCallbackObject<Parent>::callbackGetter(ExecState* exec, JSValue slotPa
JSObjectRef thisRef = toRef(thisObj);
RefPtr<OpaqueJSString> propertyNameRef;
for (JSClassRef jsClass = thisObj->classRef(); jsClass; jsClass = jsClass->parentClass)
if (JSObjectGetPropertyCallback getProperty = jsClass->getProperty) {
if (!propertyNameRef)
propertyNameRef = OpaqueJSString::create(propertyName.ustring());
JSValueRef exception = 0;
JSValueRef value;
{
APICallbackShim callbackShim(exec);
value = getProperty(toRef(exec), thisRef, propertyNameRef.get(), &exception);
}
if (exception) {
throwError(exec, toJS(exec, exception));
return jsUndefined();
if (StringImpl* name = propertyName.publicName()) {
for (JSClassRef jsClass = thisObj->classRef(); jsClass; jsClass = jsClass->parentClass) {
if (JSObjectGetPropertyCallback getProperty = jsClass->getProperty) {
if (!propertyNameRef)
propertyNameRef = OpaqueJSString::create(name);
JSValueRef exception = 0;
JSValueRef value;
{
APICallbackShim callbackShim(exec);
value = getProperty(toRef(exec), thisRef, propertyNameRef.get(), &exception);
}
if (exception) {
throwError(exec, toJS(exec, exception));
return jsUndefined();
}
if (value)
return toJS(exec, value);
}
if (value)
return toJS(exec, value);
}
}
return throwError(exec, createReferenceError(exec, "hasProperty callback returned true for a property that doesn't exist."));
}
......
......@@ -192,6 +192,12 @@ SET(JavaScriptCore_SOURCES
runtime/LiteralParser.cpp
runtime/Lookup.cpp
runtime/MathObject.cpp
runtime/NameConstructor.cpp
runtime/NameConstructor.h
runtime/NameInstance.cpp
runtime/NameInstance.h
runtime/NamePrototype.cpp
runtime/NamePrototype.h
runtime/NativeErrorConstructor.cpp
runtime/NativeErrorPrototype.cpp
runtime/NumberConstructor.cpp
......@@ -243,6 +249,7 @@ SET(JavaScriptCore_LUT_FILES
runtime/JSGlobalObject.cpp
runtime/JSONObject.cpp
runtime/MathObject.cpp
runtime/NamePrototype.cpp
runtime/NumberConstructor.cpp
runtime/NumberPrototype.cpp
runtime/ObjectConstructor.cpp
......
2012-05-15 Gavin Barraclough <barraclough@apple.com>
Add support for private names
https://bugs.webkit.org/show_bug.cgi?id=86509
Reviewed by Oliver Hunt.
The spec isn't final, but we can start adding support to allow property maps
to contain keys that aren't identifiers.
* API/JSCallbackObjectFunctions.h:
(JSC::::getOwnPropertySlot):
(JSC::::put):
(JSC::::deleteProperty):
(JSC::::getStaticValue):
(JSC::::staticFunctionGetter):
(JSC::::callbackGetter):
- Only expose public named properties over the JSC API.
* CMakeLists.txt:
* DerivedSources.make:
* DerivedSources.pri:
* GNUmakefile.list.am:
* JavaScriptCore.gypi:
* JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj:
* JavaScriptCore.xcodeproj/project.pbxproj:
* Target.pri:
- Added new files to build system.
* dfg/DFGOperations.cpp:
(JSC::DFG::operationPutByValInternal):
- Added support for property access with name objects.
* interpreter/CallFrame.h:
(JSC::ExecState::privateNamePrototypeTable):
- Added hash table for NamePrototype
* interpreter/Interpreter.cpp:
(JSC::Interpreter::privateExecute):
- Added support for property access with name objects.
* jit/JITStubs.cpp:
(JSC::DEFINE_STUB_FUNCTION):
- Added support for property access with name objects.
* llint/LLIntSlowPaths.cpp:
(JSC::LLInt::getByVal):
(JSC::LLInt::LLINT_SLOW_PATH_DECL):
* runtime/CommonSlowPaths.h:
(JSC::CommonSlowPaths::opIn):
* runtime/JSActivation.cpp:
(JSC::JSActivation::symbolTableGet):
(JSC::JSActivation::symbolTablePut):
(JSC::JSActivation::symbolTablePutWithAttributes):
- Added support for property access with name objects.
* runtime/JSGlobalData.cpp:
(JSC):
(JSC::JSGlobalData::JSGlobalData):
(JSC::JSGlobalData::~JSGlobalData):
* runtime/JSGlobalData.h:
(JSGlobalData):
- Added hash table for NamePrototype
* runtime/JSGlobalObject.cpp:
(JSC::JSGlobalObject::reset):
* runtime/JSGlobalObject.h:
(JSGlobalObject):
(JSC::JSGlobalObject::privateNameStructure):
(JSC::JSGlobalObject::symbolTableHasProperty):
- Added new global properties.
* runtime/JSType.h:
* runtime/JSTypeInfo.h:
(JSC::TypeInfo::isName):
- Added type for NameInstances, for fast isName check.