Changeset 197815 in webkit
- Timestamp:
- Mar 8, 2016, 4:01:09 PM (9 years ago)
- Location:
- trunk
- Files:
-
- 3 added
- 21 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r197811 r197815 1 2016-03-08 Mark Lam <mark.lam@apple.com> 2 3 Implement Function.name support for getters/setters and inferring name of function properties. 4 https://bugs.webkit.org/show_bug.cgi?id=154865 5 6 Reviewed by Geoffrey Garen. 7 8 * js/function-toString-vs-name-expected.txt: Added. 9 * js/function-toString-vs-name.html: Added. 10 * js/script-tests/function-toString-vs-name.js: Added. 11 1 12 2016-03-08 Myles C. Maxfield <mmaxfield@apple.com> 2 13 -
trunk/LayoutTests/inspector/model/remote-object-get-properties-expected.txt
r196648 r197815 221 221 EXPRESSION: window.boundFunction 222 222 type: function 223 description: function () {223 description: function unboundFunction() { 224 224 [native code] 225 225 } -
trunk/LayoutTests/platform/mac/http/tests/media/media-source/SourceBuffer-abort-readyState-expected.txt
r196033 r197815 5 5 step@http://127.0.0.1:8000/w3c/resources/testharness.js:1160:30 6 6 isTypeSupported@http://127.0.0.1:8000/media/media-source/SourceBuffer-abort-readyState.html:19:18 7 boundisTypeSupported@[native code]7 isTypeSupported@[native code] 8 8 http://127.0.0.1:8000/media/media-source/SourceBuffer-abort-readyState.html:42:36 9 9 step@http://127.0.0.1:8000/w3c/resources/testharness.js:1160:30 -
trunk/LayoutTests/platform/mac/http/tests/media/media-source/SourceBuffer-abort-removed-expected.txt
r196033 r197815 5 5 step@http://127.0.0.1:8000/w3c/resources/testharness.js:1160:30 6 6 isTypeSupported@http://127.0.0.1:8000/media/media-source/SourceBuffer-abort-removed.html:18:18 7 boundisTypeSupported@[native code]7 isTypeSupported@[native code] 8 8 http://127.0.0.1:8000/media/media-source/SourceBuffer-abort-removed.html:28:36 9 9 step@http://127.0.0.1:8000/w3c/resources/testharness.js:1160:30 -
trunk/LayoutTests/platform/mac/http/tests/media/media-source/SourceBuffer-abort-updating-expected.txt
r196033 r197815 5 5 step@http://127.0.0.1:8000/w3c/resources/testharness.js:1160:30 6 6 isTypeSupported@http://127.0.0.1:8000/media/media-source/SourceBuffer-abort-updating.html:32:18 7 boundisTypeSupported@[native code]7 isTypeSupported@[native code] 8 8 http://127.0.0.1:8000/media/media-source/SourceBuffer-abort-updating.html:42:36 9 9 step@http://127.0.0.1:8000/w3c/resources/testharness.js:1160:30 -
trunk/LayoutTests/platform/mac/http/tests/media/media-source/mediasource-sourcebuffer-mode-expected.txt
r196033 r197815 9 9 http://127.0.0.1:8000/media/media-source/mediasource-sourcebuffer-mode.html:114:32 10 10 handleWaitCallback_@http://127.0.0.1:8000/media/media-source/mediasource-util.js:97:17 11 bound@[native code]11 handleWaitCallback_@[native code] 12 12 step@http://127.0.0.1:8000/w3c/resources/testharness.js:1160:30 13 13 http://127.0.0.1:8000/w3c/resources/testharness.js:1189:33) -
trunk/Source/JavaScriptCore/ChangeLog
r197803 r197815 1 2016-03-08 Mark Lam <mark.lam@apple.com> 2 3 Implement Function.name support for getters/setters and inferring name of function properties. 4 https://bugs.webkit.org/show_bug.cgi?id=154865 5 6 Reviewed by Geoffrey Garen. 7 8 1. toString() no longer uses the value of Function.name as the name of the 9 function in the returned string, because ... 10 11 i. Function.name is supposed to be configurable. Hence, it can be made 12 writable and can be set to any JSValue, or deleted. 13 ii. Function.prototype.toString() is supposed to produce a string that can be 14 eval'ed. Hence, for JS functions, the function name in the produced 15 string must be a legal function name (and not some arbitrary value set in 16 Function.name). For example, while a number is a legal value for 17 Function.name, it is not legal as the function name in the toString() 18 string. 19 20 Instead, we'll always use the original name from the JS source that the 21 function was parsed from. 22 23 2. JSFunction::name() now always return the original name, not the value of 24 the Function.name property. As a result, it also no longer needs an 25 ExecState* arg. 26 27 If the original name is an empty string, JSFunction::name() will use the 28 inferred name. 29 30 3. For JS functions, the original name can be attained from their 31 FunctionExecutable object. 32 33 For host/native functions (which do not have a FunctionExecutable), we get the 34 "original" name from its NativeExecutable. 35 36 4. The m_hostFunctionStubMap now keys its NativeExecutable pointers using the 37 original name, in addition to the native function and constructor pointers. 38 39 This is needed because we want a different NativeExecutable for functions with 40 a different name (to satisfy (3) above). 41 42 5. Changed JSBoundFunction to store the name of its bound function in its 43 NativeExecutable. This will later be used to generate the toString() string. 44 It's Function.name value is eagerly initialized at construction time. 45 46 6. Function.name for getters/setters are now prefixed with "get"/"set". 47 This was done both for the JSBoundSlotBaseFunctions and JS definable get/set 48 functions. 49 50 7. Added InternalFunction::m_originalName so that we can use it to generate the 51 toString() string. We're storing it as a JSString instead of a WTF::String 52 only because we want InternalFunction to be continue to be trivially 53 destructible. 54 55 * inspector/JSInjectedScriptHost.cpp: 56 (Inspector::JSInjectedScriptHost::functionDetails): 57 * jit/JITThunks.cpp: 58 (JSC::JITThunks::finalize): 59 (JSC::JITThunks::hostFunctionStub): 60 * jit/JITThunks.h: 61 * runtime/Executable.h: 62 * runtime/FunctionPrototype.cpp: 63 (JSC::functionProtoFuncToString): 64 * runtime/InternalFunction.cpp: 65 (JSC::InternalFunction::finishCreation): 66 (JSC::InternalFunction::visitChildren): 67 (JSC::InternalFunction::name): 68 (JSC::InternalFunction::displayName): 69 * runtime/InternalFunction.h: 70 * runtime/JSBoundFunction.cpp: 71 (JSC::JSBoundFunction::create): 72 (JSC::JSBoundFunction::visitChildren): 73 (JSC::JSBoundFunction::toStringName): Deleted. 74 * runtime/JSBoundFunction.h: 75 (JSC::JSBoundFunction::boundThis): 76 (JSC::JSBoundFunction::boundArgs): 77 (JSC::JSBoundFunction::createStructure): 78 * runtime/JSBoundSlotBaseFunction.cpp: 79 (JSC::boundSlotBaseFunctionCall): 80 (JSC::JSBoundSlotBaseFunction::create): 81 * runtime/JSFunction.cpp: 82 (JSC::JSFunction::initializeRareData): 83 (JSC::JSFunction::name): 84 (JSC::JSFunction::displayName): 85 (JSC::JSFunction::calculatedDisplayName): 86 (JSC::JSFunction::reifyName): 87 * runtime/JSFunction.h: 88 * tests/es6.yaml: 89 1 90 2016-03-08 Commit Queue <commit-queue@webkit.org> 2 91 -
trunk/Source/JavaScriptCore/inspector/JSInjectedScriptHost.cpp
r197539 r197815 204 204 result->putDirect(exec->vm(), Identifier::fromString(exec, "location"), location); 205 205 206 String name = function->name( exec);206 String name = function->name(); 207 207 if (!name.isEmpty()) 208 208 result->putDirect(exec->vm(), Identifier::fromString(exec, "name"), jsString(exec, name)); -
trunk/Source/JavaScriptCore/jit/JITThunks.cpp
r195000 r197815 80 80 { 81 81 auto* nativeExecutable = jsCast<NativeExecutable*>(handle.get().asCell()); 82 weakRemove(*m_hostFunctionStubMap, std::make_ pair(nativeExecutable->function(), nativeExecutable->constructor()), nativeExecutable);82 weakRemove(*m_hostFunctionStubMap, std::make_tuple(nativeExecutable->function(), nativeExecutable->constructor(), nativeExecutable->name()), nativeExecutable); 83 83 } 84 84 … … 87 87 ASSERT(!isCompilationThread()); 88 88 89 if (NativeExecutable* nativeExecutable = m_hostFunctionStubMap->get(std::make_ pair(function, constructor)))89 if (NativeExecutable* nativeExecutable = m_hostFunctionStubMap->get(std::make_tuple(function, constructor, name))) 90 90 return nativeExecutable; 91 91 … … 96 96 adoptRef(new NativeJITCode(MacroAssemblerCodeRef::createSelfManagedCodeRef(ctiNativeConstruct(vm)), JITCode::HostCallThunk)), 97 97 constructor, NoIntrinsic, name); 98 weakAdd(*m_hostFunctionStubMap, std::make_ pair(function, constructor), Weak<NativeExecutable>(nativeExecutable, this));98 weakAdd(*m_hostFunctionStubMap, std::make_tuple(function, constructor, name), Weak<NativeExecutable>(nativeExecutable, this)); 99 99 return nativeExecutable; 100 100 } … … 105 105 ASSERT(vm->canUseJIT()); 106 106 107 if (NativeExecutable* nativeExecutable = m_hostFunctionStubMap->get(std::make_ pair(function, &callHostFunctionAsConstructor)))107 if (NativeExecutable* nativeExecutable = m_hostFunctionStubMap->get(std::make_tuple(function, &callHostFunctionAsConstructor, name))) 108 108 return nativeExecutable; 109 109 … … 118 118 119 119 NativeExecutable* nativeExecutable = NativeExecutable::create(*vm, forCall, function, forConstruct, callHostFunctionAsConstructor, intrinsic, name); 120 weakAdd(*m_hostFunctionStubMap, std::make_ pair(function, &callHostFunctionAsConstructor), Weak<NativeExecutable>(nativeExecutable, this));120 weakAdd(*m_hostFunctionStubMap, std::make_tuple(function, &callHostFunctionAsConstructor, name), Weak<NativeExecutable>(nativeExecutable, this)); 121 121 return nativeExecutable; 122 122 } -
trunk/Source/JavaScriptCore/jit/JITThunks.h
r195000 r197815 37 37 #include "WeakHandleOwner.h" 38 38 #include "WeakInlines.h" 39 #include <tuple> 39 40 #include <wtf/HashMap.h> 40 41 #include <wtf/RefPtr.h> … … 68 69 typedef HashMap<ThunkGenerator, MacroAssemblerCodeRef> CTIStubMap; 69 70 CTIStubMap m_ctiStubMap; 70 typedef HashMap<std::pair<NativeFunction, NativeFunction>, Weak<NativeExecutable>> HostFunctionStubMap; 71 72 typedef std::tuple<NativeFunction, NativeFunction, String> HostFunctionKey; 73 74 struct HostFunctionHash { 75 static unsigned hash(const HostFunctionKey& key) 76 { 77 unsigned hash = WTF::pairIntHash(hashPointer(std::get<0>(key)), hashPointer(std::get<1>(key))); 78 if (!std::get<2>(key).isNull()) 79 hash = WTF::pairIntHash(hash, DefaultHash<String>::Hash::hash(std::get<2>(key))); 80 return hash; 81 } 82 static bool equal(const HostFunctionKey& a, const HostFunctionKey& b) 83 { 84 return (std::get<0>(a) == std::get<0>(b)) && (std::get<1>(a) == std::get<1>(b)) && (std::get<2>(a) == std::get<2>(b)); 85 } 86 static const bool safeToCompareToEmptyOrDeleted = true; 87 88 private: 89 static inline unsigned hashPointer(NativeFunction p) 90 { 91 return DefaultHash<NativeFunction>::Hash::hash(p); 92 } 93 }; 94 95 struct HostFunctionHashTrait : WTF::GenericHashTraits<HostFunctionKey> { 96 static const bool emptyValueIsZero = true; 97 static EmptyValueType emptyValue() { return std::make_tuple(nullptr, nullptr, String()); } 98 99 static void constructDeletedValue(HostFunctionKey& slot) { std::get<0>(slot) = reinterpret_cast<NativeFunction>(-1); } 100 static bool isDeletedValue(const HostFunctionKey& value) { return std::get<0>(value) == reinterpret_cast<NativeFunction>(-1); } 101 }; 102 103 typedef HashMap<HostFunctionKey, Weak<NativeExecutable>, HostFunctionHash, HostFunctionHashTrait> HostFunctionStubMap; 71 104 std::unique_ptr<HostFunctionStubMap> m_hostFunctionStubMap; 72 105 Lock m_lock; -
trunk/Source/JavaScriptCore/runtime/Executable.h
r197308 r197815 664 664 ConstructAbility constructAbility() const { return m_unlinkedExecutable->constructAbility(); } 665 665 bool isArrowFunction() const { return parseMode() == SourceParseMode::ArrowFunctionMode; } 666 bool isGetter() const { return parseMode() == SourceParseMode::GetterMode; } 667 bool isSetter() const { return parseMode() == SourceParseMode::SetterMode; } 666 668 DerivedContextType derivedContextType() const { return m_unlinkedExecutable->derivedContextType(); } 667 669 bool isClassConstructorFunction() const { return m_unlinkedExecutable->isClassConstructorFunction(); } 668 670 const Identifier& name() { return m_unlinkedExecutable->name(); } 669 671 const Identifier& inferredName() { return m_unlinkedExecutable->inferredName(); } 672 // FIXME: ecmaName() needs to be reimplement to be based on ES6 rules of determining the inferred 673 // Function.name from non-computed names. https://bugs.webkit.org/show_bug.cgi?id=155203 674 const Identifier& ecmaName() { return inferredName(); } 670 675 size_t parameterCount() const { return m_unlinkedExecutable->parameterCount(); } // Excluding 'this'! 671 676 SourceParseMode parseMode() const { return m_unlinkedExecutable->parseMode(); } -
trunk/Source/JavaScriptCore/runtime/FunctionPrototype.cpp
r197648 r197815 86 86 if (thisValue.inherits(JSFunction::info())) { 87 87 JSFunction* function = jsCast<JSFunction*>(thisValue); 88 if (function->isHostOrBuiltinFunction()) { 89 String name; 90 if (JSBoundFunction* boundFunction = jsDynamicCast<JSBoundFunction*>(function)) 91 name = boundFunction->toStringName(exec); 92 else 93 name = function->name(exec); 94 return JSValue::encode(jsMakeNontrivialString(exec, "function ", name, "() {\n [native code]\n}")); 95 } 88 if (function->isHostOrBuiltinFunction()) 89 return JSValue::encode(jsMakeNontrivialString(exec, "function ", function->name(), "() {\n [native code]\n}")); 96 90 97 91 FunctionExecutable* executable = function->jsExecutable(); … … 102 96 executable->parametersStartOffset(), 103 97 executable->parametersStartOffset() + executable->source().length()); 104 return JSValue::encode(jsMakeNontrivialString(exec, functionHeader, function->name( exec), source));98 return JSValue::encode(jsMakeNontrivialString(exec, functionHeader, function->name(), source)); 105 99 } 106 100 … … 168 162 } 169 163 170 JSString* name = target.get(exec, exec->propertyNames().name).toString(exec); 164 JSValue nameProp = target.get(exec, exec->propertyNames().name); 165 JSString* name = nameProp.isString() ? nameProp.toString(exec) : jsEmptyString(exec); 171 166 return JSValue::encode(JSBoundFunction::create(vm, exec, globalObject, targetObject, exec->argument(0), boundArgs, length, name->value(exec))); 172 167 } -
trunk/Source/JavaScriptCore/runtime/InternalFunction.cpp
r197614 r197815 45 45 ASSERT(inherits(info())); 46 46 ASSERT(methodTable()->getCallData != InternalFunction::info()->methodTable.getCallData); 47 putDirect(vm, vm.propertyNames->name, jsString(&vm, name), DontDelete | ReadOnly | DontEnum); 47 JSString* nameString = jsString(&vm, name); 48 m_originalName.set(vm, this, nameString); 49 putDirect(vm, vm.propertyNames->name, nameString, ReadOnly | DontEnum); 48 50 } 49 51 50 const String& InternalFunction::name(ExecState* exec)52 void InternalFunction::visitChildren(JSCell* cell, SlotVisitor& visitor) 51 53 { 52 return asString(getDirect(exec->vm(), exec->vm().propertyNames->name))->tryGetValue(); 54 InternalFunction* thisObject = jsCast<InternalFunction*>(cell); 55 ASSERT_GC_OBJECT_INHERITS(thisObject, info()); 56 Base::visitChildren(thisObject, visitor); 57 58 visitor.append(&thisObject->m_originalName); 59 } 60 61 const String& InternalFunction::name(ExecState*) 62 { 63 const String& name = m_originalName->tryGetValue(); 64 ASSERT(name); // m_originalName was built from a String, and hence, there is no rope to resolve. 65 return name; 53 66 } 54 67 -
trunk/Source/JavaScriptCore/runtime/InternalFunction.h
r194869 r197815 39 39 DECLARE_EXPORT_INFO; 40 40 41 JS_EXPORT_PRIVATE static void visitChildren(JSCell*, SlotVisitor&); 42 41 43 JS_EXPORT_PRIVATE const String& name(ExecState*); 42 44 const String displayName(ExecState*); … … 56 58 57 59 static CallType getCallData(JSCell*, CallData&); 60 WriteBarrier<JSString> m_originalName; 58 61 }; 59 62 -
trunk/Source/JavaScriptCore/runtime/JSBoundFunction.cpp
r197648 r197815 125 125 ConstructType constructType = JSC::getConstructData(targetFunction, constructData); 126 126 bool canConstruct = constructType != ConstructType::None; 127 NativeExecutable* executable = vm.getHostFunction(boundFunctionCall, canConstruct ? boundFunctionConstruct : callHostFunctionAsConstructor, ASCIILiteral("Function.prototype.bind result"));127 NativeExecutable* executable = vm.getHostFunction(boundFunctionCall, canConstruct ? boundFunctionConstruct : callHostFunctionAsConstructor, name); 128 128 Structure* structure = getBoundFunctionStructure(vm, exec, globalObject, targetFunction); 129 129 if (UNLIKELY(vm.exception())) … … 168 168 } 169 169 170 String JSBoundFunction::toStringName(ExecState* exec)171 {172 return m_targetFunction->get(exec, exec->vm().propertyNames->name).toWTFString(exec);173 }174 175 170 } // namespace JSC -
trunk/Source/JavaScriptCore/runtime/JSBoundFunction.h
r197648 r197815 41 41 const static unsigned StructureFlags = ~ImplementsDefaultHasInstance & Base::StructureFlags; 42 42 43 static JSBoundFunction* create(VM&, ExecState*, JSGlobalObject*, JSObject* targetFunction, JSValue boundThis, JSValue boundArgs, int, const String& );43 static JSBoundFunction* create(VM&, ExecState*, JSGlobalObject*, JSObject* targetFunction, JSValue boundThis, JSValue boundArgs, int, const String& name); 44 44 45 45 static bool customHasInstance(JSObject*, ExecState*, JSValue); … … 49 49 JSValue boundArgs() { return m_boundArgs.get(); } 50 50 51 String toStringName(ExecState*); 52 53 static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype) 51 static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype) 54 52 { 55 53 ASSERT(globalObject); … … 65 63 JSBoundFunction(VM&, JSGlobalObject*, Structure*, JSObject* targetFunction, JSValue boundThis, JSValue boundArgs); 66 64 67 void finishCreation(VM&, NativeExecutable*, int , const String&);65 void finishCreation(VM&, NativeExecutable*, int length, const String& name); 68 66 69 67 WriteBarrier<JSObject> m_targetFunction; -
trunk/Source/JavaScriptCore/runtime/JSBoundSlotBaseFunction.cpp
r196331 r197815 51 51 return JSValue::encode(jsUndefined()); 52 52 53 const String& name = boundSlotBaseFunction->name( exec);53 const String& name = boundSlotBaseFunction->name(); 54 54 return getter(exec, JSValue::encode(exec->thisValue()), PropertyName(Identifier::fromString(exec, name))); 55 55 } … … 68 68 69 69 // Can't do this during initialization because getHostFunction might do a GC allocation. 70 function->finishCreation(vm, executable, boundSlotBase, getterSetter, name); 70 String prefix = (type == Type::Getter) ? "get " : "set "; 71 function->finishCreation(vm, executable, boundSlotBase, getterSetter, makeString(prefix, name)); 71 72 return function; 72 73 } -
trunk/Source/JavaScriptCore/runtime/JSCJSValue.cpp
r197794 r197815 208 208 return; 209 209 210 if (shouldThrow && !exec->hadException()) 210 211 if (shouldThrow) 211 212 throwTypeError(exec, StrictModeReadonlyPropertyWriteError); -
trunk/Source/JavaScriptCore/runtime/JSFunction.cpp
r197794 r197815 178 178 } 179 179 180 String JSFunction::name(ExecState* exec) 181 { 182 return get(exec, exec->vm().propertyNames->name).toWTFString(exec); 180 String JSFunction::name() 181 { 182 if (isHostFunction()) { 183 NativeExecutable* executable = jsCast<NativeExecutable*>(this->executable()); 184 return executable->name(); 185 } 186 return jsExecutable()->name().string(); 183 187 } 184 188 … … 200 204 return explicitName; 201 205 202 const String actualName = name( exec);206 const String actualName = name(); 203 207 if (!actualName.isEmpty() || isHostOrBuiltinFunction()) 204 208 return actualName; … … 590 594 ASSERT(!isHostFunction()); 591 595 unsigned initialAttributes = DontEnum | ReadOnly; 592 const Identifier& identifier = exec->propertyNames().name; 593 putDirect(vm, identifier, jsString(exec, jsExecutable()->name().string()), initialAttributes); 594 596 const Identifier& propID = exec->propertyNames().name; 597 598 const Identifier& nameID = jsExecutable()->name(); 599 String name = nameID.string(); 600 if (name.isEmpty()) 601 name = jsExecutable()->ecmaName().string(); 602 603 if (jsExecutable()->isGetter()) 604 name = makeString("get ", name); 605 else if (jsExecutable()->isSetter()) 606 name = makeString("set ", name); 607 608 putDirect(vm, propID, jsString(exec, name), initialAttributes); 595 609 rareData->setHasReifiedName(); 596 610 } -
trunk/Source/JavaScriptCore/runtime/JSFunction.h
r197205 r197815 82 82 static JSFunction* createBuiltinFunction(VM&, FunctionExecutable*, JSGlobalObject*, const String& name); 83 83 84 JS_EXPORT_PRIVATE String name( ExecState*);84 JS_EXPORT_PRIVATE String name(); 85 85 JS_EXPORT_PRIVATE String displayName(ExecState*); 86 86 const String calculatedDisplayName(ExecState*); -
trunk/Source/JavaScriptCore/tests/es6.yaml
r197732 r197815 792 792 cmd: runES6 :normal 793 793 - path: es6/function_name_property_accessor_properties.js 794 cmd: runES6 : fail794 cmd: runES6 :normal 795 795 - path: es6/function_name_property_bound_functions.js 796 796 cmd: runES6 :normal … … 812 812 cmd: runES6 :fail 813 813 - path: es6/function_name_property_variables_function.js 814 cmd: runES6 : fail814 cmd: runES6 :normal 815 815 - path: es6/generators_%GeneratorPrototype%.constructor.js 816 816 cmd: runES6 :normal
Note:
See TracChangeset
for help on using the changeset viewer.