}
+Object* CallIC::TryCallAsFunction(Object* object) {
+ HandleScope scope;
+ Handle<Object> target(object);
+ Handle<Object> delegate = Execution::GetFunctionDelegate(target);
+
+ if (delegate->IsJSFunction()) {
+ // Patch the receiver and use the delegate as the function to
+ // invoke. This is used for invoking objects as if they were
+ // functions.
+ const int argc = this->target()->arguments_count();
+ StackFrameLocator locator;
+ JavaScriptFrame* frame = locator.FindJavaScriptFrame(0);
+ int index = frame->ComputeExpressionsCount() - (argc + 1);
+ frame->SetExpression(index, *target);
+ }
+
+ return *delegate;
+}
+
+
Object* CallIC::LoadFunction(State state,
Handle<Object> object,
Handle<String> name) {
return TypeError("non_object_property_call", object, name);
}
+ Object* result = Heap::the_hole_value();
+
+ // Check if the name is trivially convertible to an index and get
+ // the element if so.
+ uint32_t index;
+ if (name->AsArrayIndex(&index)) {
+ result = object->GetElement(index);
+ if (result->IsJSFunction()) return result;
+
+ // Try to find a suitable function delegate for the object at hand.
+ result = TryCallAsFunction(result);
+ if (result->IsJSFunction()) return result;
+
+ // Otherwise, it will fail in the lookup step.
+ }
+
// Lookup the property in the object.
LookupResult lookup;
object->Lookup(*name, &lookup);
- Object* result = Heap::the_hole_value();
-
if (!lookup.IsValid()) {
// If the object does not have the requested property, check which
// exception we need to throw.
}
// Try to find a suitable function delegate for the object at hand.
- HandleScope scope;
- Handle<Object> target(result);
- Handle<Object> delegate = Execution::GetFunctionDelegate(target);
-
- if (delegate->IsJSFunction()) {
- // Patch the receiver and use the delegate as the function to
- // invoke. This is used for invoking objects as if they were
- // functions.
- const int argc = this->target()->arguments_count();
- StackFrameLocator locator;
- JavaScriptFrame* frame = locator.FindJavaScriptFrame(0);
- int index = frame->ComputeExpressionsCount() - (argc + 1);
- frame->SetExpression(index, *target);
- return *delegate;
- } else {
- return TypeError("property_not_function", object, name);
- }
+ result = TryCallAsFunction(result);
+ return result->IsJSFunction() ?
+ result : TypeError("property_not_function", object, name);
}
Handle<Object> object,
Handle<String> name);
+ // Returns a JSFunction if the object can be called as a function,
+ // and patches the stack to be ready for the call.
+ // Otherwise, it returns the undefined value.
+ Object* TryCallAsFunction(Object* object);
+
static void Clear(Address address, Code* target);
friend class IC;
};
CHECK(!try_catch.HasCaught());
CHECK_EQ(49, value->Int32Value());
+ // test special case of call as function
+ value = Script::Compile(v8_str("[obj]['0'](45)"))->Run();
+ CHECK(!try_catch.HasCaught());
+ CHECK_EQ(45, value->Int32Value());
+
value = Script::Compile(v8_str("obj.call = Function.prototype.call;"
"obj.call(null, 87)"))->Run();
CHECK(!try_catch.HasCaught());
--- /dev/null
+// Copyright 2008 Google Inc. All Rights Reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Flags: --call_regexp
+var callbacks = [ function() {return 'foo'}, "nonobject", /abc/ ];
+assertEquals('foo', callbacks['0']());
+assertThrows("callbacks['1']()");
+assertEquals('abc', callbacks['2']("abcdefg"));