}
+bool CheckMethodName(Handle<JSObject> obj, Handle<Name> name,
+ Handle<JSFunction> fun,
+ LookupIterator::Configuration config) {
+ LookupIterator iter(obj, name, config);
+ if (iter.state() == LookupIterator::DATA) {
+ return iter.GetDataValue().is_identical_to(fun);
+ } else if (iter.state() == LookupIterator::ACCESSOR) {
+ Handle<Object> accessors = iter.GetAccessors();
+ if (accessors->IsAccessorPair()) {
+ Handle<AccessorPair> pair = Handle<AccessorPair>::cast(accessors);
+ return pair->getter() == *fun || pair->setter() == *fun;
+ }
+ }
+ return false;
+}
+
+
+Handle<Object> CallSite::GetMethodName(Isolate* isolate) {
+ MaybeHandle<JSReceiver> maybe = Object::ToObject(isolate, receiver_);
+ Handle<JSReceiver> receiver;
+ if (!maybe.ToHandle(&receiver) || !receiver->IsJSObject()) {
+ return isolate->factory()->null_value();
+ }
+
+ Handle<JSObject> obj = Handle<JSObject>::cast(receiver);
+ Handle<Object> function_name(fun_->shared()->name(), isolate);
+ if (function_name->IsName()) {
+ Handle<Name> name = Handle<Name>::cast(function_name);
+ if (CheckMethodName(obj, name, fun_,
+ LookupIterator::PROTOTYPE_CHAIN_SKIP_INTERCEPTOR))
+ return name;
+ }
+
+ HandleScope outer_scope(isolate);
+ Handle<Object> result;
+ for (PrototypeIterator iter(isolate, obj,
+ PrototypeIterator::START_AT_RECEIVER);
+ !iter.IsAtEnd(); iter.Advance()) {
+ Handle<Object> current = PrototypeIterator::GetCurrent(iter);
+ if (!current->IsJSObject()) break;
+ Handle<JSObject> current_obj = Handle<JSObject>::cast(current);
+ if (current_obj->IsAccessCheckNeeded()) break;
+ Handle<FixedArray> keys = JSObject::GetEnumPropertyKeys(current_obj, false);
+ for (int i = 0; i < keys->length(); i++) {
+ HandleScope inner_scope(isolate);
+ if (!keys->get(i)->IsName()) continue;
+ Handle<Name> name_key(Name::cast(keys->get(i)), isolate);
+ if (!CheckMethodName(current_obj, name_key, fun_,
+ LookupIterator::OWN_SKIP_INTERCEPTOR))
+ continue;
+ // Return null in case of duplicates to avoid confusion.
+ if (!result.is_null()) return isolate->factory()->null_value();
+ result = inner_scope.CloseAndEscape(name_key);
+ }
+ }
+
+ if (!result.is_null()) return outer_scope.CloseAndEscape(result);
+ return isolate->factory()->null_value();
+}
+
+
int CallSite::GetLineNumber(Isolate* isolate) {
if (pos_ >= 0) {
Handle<Object> script_obj(fun_->shared()->script(), isolate);
}
+bool CallSite::IsConstructor(Isolate* isolate) {
+ if (!receiver_->IsJSObject()) return false;
+ Handle<Object> constructor =
+ JSObject::GetDataProperty(Handle<JSObject>::cast(receiver_),
+ isolate->factory()->constructor_string());
+ return constructor.is_identical_to(fun_);
+}
+
+
MaybeHandle<String> MessageTemplate::FormatMessage(int template_index,
Handle<String> arg0,
Handle<String> arg1,
Handle<Object> GetFileName(Isolate* isolate);
Handle<Object> GetFunctionName(Isolate* isolate);
Handle<Object> GetScriptNameOrSourceUrl(Isolate* isolate);
+ Handle<Object> GetMethodName(Isolate* isolate);
// Return 1-based line number, including line offset.
int GetLineNumber(Isolate* isolate);
// Return 1-based column number, including column offset if first line.
bool IsNative(Isolate* isolate);
bool IsToplevel(Isolate* isolate);
bool IsEval(Isolate* isolate);
+ bool IsConstructor(Isolate* isolate);
private:
Handle<Object> receiver_;
// this function.
var receiver = GET_PRIVATE(this, CallSiteReceiverKey);
var fun = GET_PRIVATE(this, CallSiteFunctionKey);
- var ownName = fun.name;
- if (ownName && receiver &&
- (%_CallFunction(receiver, ownName, $objectLookupGetter) === fun ||
- %_CallFunction(receiver, ownName, $objectLookupSetter) === fun ||
- (IS_OBJECT(receiver) && %GetDataProperty(receiver, ownName) === fun))) {
- // To handle DontEnum properties we guess that the method has
- // the same name as the function.
- return ownName;
- }
- var name = null;
- for (var prop in receiver) {
- if (%_CallFunction(receiver, prop, $objectLookupGetter) === fun ||
- %_CallFunction(receiver, prop, $objectLookupSetter) === fun ||
- (IS_OBJECT(receiver) && %GetDataProperty(receiver, prop) === fun)) {
- // If we find more than one match bail out to avoid confusion.
- if (name) {
- return null;
- }
- name = prop;
- }
- }
- if (name) {
- return name;
- }
- return null;
+ var pos = GET_PRIVATE(this, CallSitePositionKey);
+ return %CallSiteGetMethodNameRT(receiver, fun, pos);
}
function CallSiteGetFileName() {
function CallSiteIsConstructor() {
var receiver = GET_PRIVATE(this, CallSiteReceiverKey);
- var constructor = (receiver != null && IS_OBJECT(receiver))
- ? %GetDataProperty(receiver, "constructor") : null;
- if (!constructor) return false;
- return GET_PRIVATE(this, CallSiteFunctionKey) === constructor;
+ var fun = GET_PRIVATE(this, CallSiteFunctionKey);
+ var pos = GET_PRIVATE(this, CallSitePositionKey);
+ return %CallSiteIsConstructorRT(receiver, fun, pos);
}
function CallSiteToString() {
}
-static Handle<FixedArray> GetEnumPropertyKeys(Handle<JSObject> object,
- bool cache_result) {
+Handle<FixedArray> JSObject::GetEnumPropertyKeys(Handle<JSObject> object,
+ bool cache_result) {
Isolate* isolate = object->GetIsolate();
if (object->HasFastProperties()) {
int own_property_count = object->map()->EnumLength();
ASSIGN_RETURN_ON_EXCEPTION(
isolate, content,
FixedArray::UnionOfKeys(
- content, GetEnumPropertyKeys(current, cache_enum_keys)),
+ content, JSObject::GetEnumPropertyKeys(current, cache_enum_keys)),
FixedArray);
DCHECK(ContainsOnlyValidKeys(content));
// Returns the number of enumerable elements.
int GetEnumElementKeys(FixedArray* storage);
+ static Handle<FixedArray> GetEnumPropertyKeys(Handle<JSObject> object,
+ bool cache_result);
+
// Returns a new map with all transitions dropped from the object's current
// map and the ElementsKind set.
static Handle<Map> GetElementsTransitionMap(Handle<JSObject> object,
CALLSITE_GET(GetFileName, ReturnDereferencedHandle)
CALLSITE_GET(GetFunctionName, ReturnDereferencedHandle)
CALLSITE_GET(GetScriptNameOrSourceUrl, ReturnDereferencedHandle)
+CALLSITE_GET(GetMethodName, ReturnDereferencedHandle)
CALLSITE_GET(GetLineNumber, ReturnPositiveSmiOrNull)
CALLSITE_GET(GetColumnNumber, ReturnPositiveSmiOrNull)
CALLSITE_GET(IsNative, ReturnBoolean)
CALLSITE_GET(IsToplevel, ReturnBoolean)
CALLSITE_GET(IsEval, ReturnBoolean)
+CALLSITE_GET(IsConstructor, ReturnBoolean)
#undef CALLSITE_GET
F(CallSiteGetFileNameRT, 3, 1) \
F(CallSiteGetFunctionNameRT, 3, 1) \
F(CallSiteGetScriptNameOrSourceUrlRT, 3, 1) \
+ F(CallSiteGetMethodNameRT, 3, 1) \
F(CallSiteGetLineNumberRT, 3, 1) \
F(CallSiteGetColumnNumberRT, 3, 1) \
F(CallSiteIsNativeRT, 3, 1) \
F(CallSiteIsToplevelRT, 3, 1) \
F(CallSiteIsEvalRT, 3, 1) \
+ F(CallSiteIsConstructorRT, 3, 1) \
F(IS_VAR, 1, 1) \
F(GetFromCache, 2, 1) \
F(IncrementStatsCounter, 1, 1) \
--- /dev/null
+// Copyright 2015 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+var o = { f: function() { throw new Error(); } };
+o.g1 = function() { o.f() }
+o.g2 = o.g1;
+o.h = function() { o.g1() }
+
+Error.prepareStackTrace = function(e, frames) { return frames; }
+
+try {
+ o.h();
+} catch (e) {
+ var frames = e.stack;
+ assertEquals("f", frames[0].getMethodName());
+ assertEquals(null, frames[1].getMethodName());
+ assertEquals("h", frames[2].getMethodName());
+ assertEquals(null, frames[3].getMethodName());
+}