Pass undefined to JS builtins when called with implicit receiver.
authorager@chromium.org <ager@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Thu, 26 May 2011 11:07:48 +0000 (11:07 +0000)
committerager@chromium.org <ager@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Thu, 26 May 2011 11:07:48 +0000 (11:07 +0000)
A couple of corner cases have to be treated specially to not break
everything: eval and getter/setter definitions.

R=lrn@chromium.org
BUG=v8:1365
TEST=mjsunit/regress/regress-1365.js

Review URL: http://codereview.chromium.org/7068009

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@8073 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

27 files changed:
src/arm/builtins-arm.cc
src/arm/full-codegen-arm.cc
src/arm/lithium-codegen-arm.cc
src/compiler.cc
src/compiler.h
src/handles.cc
src/heap.cc
src/hydrogen.cc
src/ia32/builtins-ia32.cc
src/ia32/full-codegen-ia32.cc
src/ia32/lithium-codegen-ia32.cc
src/mips/builtins-mips.cc
src/objects-inl.h
src/objects.h
src/runtime.cc
src/runtime.h
src/v8natives.js
src/x64/builtins-x64.cc
src/x64/full-codegen-x64.cc
src/x64/lithium-codegen-x64.cc
test/cctest/test-api.cc
test/mjsunit/regress/regress-1170.js
test/mjsunit/regress/regress-124.js
test/mjsunit/regress/regress-1365.js [new file with mode: 0644]
test/mjsunit/regress/regress-485.js
test/mozilla/mozilla.status
test/sputnik/sputnik.status

index ff30ec7..789541f 100644 (file)
@@ -1255,8 +1255,7 @@ void Builtins::Generate_FunctionCall(MacroAssembler* masm) {
     __ b(ne, &shift_arguments);
 
     // Do not transform the receiver for native (Compilerhints already in r3).
-    __ tst(r3, Operand(1 << (SharedFunctionInfo::kES5Native +
-                             kSmiTagSize)));
+    __ tst(r3, Operand(1 << (SharedFunctionInfo::kNative + kSmiTagSize)));
     __ b(ne, &shift_arguments);
 
     // Compute the receiver in non-strict mode.
@@ -1440,8 +1439,7 @@ void Builtins::Generate_FunctionApply(MacroAssembler* masm) {
   __ b(ne, &push_receiver);
 
   // Do not transform the receiver for strict mode functions.
-  __ tst(r2, Operand(1 << (SharedFunctionInfo::kES5Native +
-                           kSmiTagSize)));
+  __ tst(r2, Operand(1 << (SharedFunctionInfo::kNative + kSmiTagSize)));
   __ b(ne, &push_receiver);
 
   // Compute the receiver in non-strict mode.
index 22846c3..12f2042 100644 (file)
@@ -139,11 +139,11 @@ void FullCodeGenerator::Generate(CompilationInfo* info) {
   }
 #endif
 
-  // Strict mode functions need to replace the receiver with undefined
-  // when called as functions (without an explicit receiver
-  // object). r5 is zero for method calls and non-zero for function
-  // calls.
-  if (info->is_strict_mode()) {
+  // Strict mode functions and builtins need to replace the receiver
+  // with undefined when called as functions (without an explicit
+  // receiver object). r5 is zero for method calls and non-zero for
+  // function calls.
+  if (info->is_strict_mode() || info->is_native()) {
     Label ok;
     __ cmp(r5, Operand(0));
     __ b(eq, &ok);
index 100f4d2..9e1153a 100644 (file)
@@ -146,11 +146,11 @@ bool LCodeGen::GeneratePrologue() {
   // fp: Caller's frame pointer.
   // lr: Caller's pc.
 
-  // Strict mode functions need to replace the receiver with undefined
-  // when called as functions (without an explicit receiver
-  // object). r5 is zero for method calls and non-zero for function
-  // calls.
-  if (info_->is_strict_mode()) {
+  // Strict mode functions and builtins need to replace the receiver
+  // with undefined when called as functions (without an explicit
+  // receiver object). r5 is zero for method calls and non-zero for
+  // function calls.
+  if (info_->is_strict_mode() || info_->is_native()) {
     Label ok;
     __ cmp(r5, Operand(0));
     __ b(eq, &ok);
index a59de17..893f788 100755 (executable)
@@ -508,7 +508,10 @@ Handle<SharedFunctionInfo> Compiler::Compile(Handle<String> source,
     info.MarkAsGlobal();
     info.SetExtension(extension);
     info.SetPreParseData(pre_data);
-    if (natives == NATIVES_CODE) info.MarkAsAllowingNativesSyntax();
+    if (natives == NATIVES_CODE) {
+      info.MarkAsAllowingNativesSyntax();
+      info.MarkAsNative();
+    }
     result = MakeFunctionInfo(&info);
     if (extension == NULL && !result.is_null()) {
       compilation_cache->PutScript(source, result);
@@ -677,6 +680,7 @@ Handle<SharedFunctionInfo> Compiler::BuildFunctionInfo(FunctionLiteral* literal,
   info.SetFunction(literal);
   info.SetScope(literal->scope());
   if (literal->scope()->is_strict_mode()) info.MarkAsStrictMode();
+  if (script->type()->value() == Script::TYPE_NATIVE) info.MarkAsNative();
 
   LiveEditFunctionTracker live_edit_tracker(info.isolate(), literal);
   // Determine if the function can be lazily compiled. This is necessary to
index 4eb33e2..c8ec2e5 100644 (file)
@@ -89,6 +89,12 @@ class CompilationInfo BASE_EMBEDDED {
   bool allows_natives_syntax() const {
     return IsNativesSyntaxAllowed::decode(flags_);
   }
+  void MarkAsNative() {
+    flags_ |= IsNative::encode(true);
+  }
+  bool is_native() const {
+    return IsNative::decode(flags_);
+  }
   void SetFunction(FunctionLiteral* literal) {
     ASSERT(function_ == NULL);
     function_ = literal;
@@ -167,9 +173,11 @@ class CompilationInfo BASE_EMBEDDED {
 
   void Initialize(Mode mode) {
     mode_ = V8::UseCrankshaft() ? mode : NONOPT;
-    if (!shared_info_.is_null() && shared_info_->strict_mode()) {
-      MarkAsStrictMode();
+    if (!shared_info_.is_null()) {
+      if (shared_info_->strict_mode()) MarkAsStrictMode();
+      if (shared_info_->native()) MarkAsNative();
     }
+
   }
 
   void SetMode(Mode mode) {
@@ -191,6 +199,9 @@ class CompilationInfo BASE_EMBEDDED {
   class IsStrictMode: public BitField<bool, 4, 1> {};
   // Native syntax (%-stuff) allowed?
   class IsNativesSyntaxAllowed: public BitField<bool, 5, 1> {};
+  // Is this a function from our natives.
+  class IsNative: public BitField<bool, 6, 1> {};
+
 
   unsigned flags_;
 
index b03b642..ef7133a 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright 2009 the V8 project authors. All rights reserved.
+// Copyright 2011 the V8 project authors. All rights reserved.
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
 // met:
index 0a3b3d3..54359d6 100644 (file)
@@ -2388,7 +2388,7 @@ MaybeObject* Heap::AllocateSharedFunctionInfo(Object* name) {
   share->set_num_literals(0);
   share->set_end_position(0);
   share->set_function_token_position(0);
-  share->set_es5_native(false);
+  share->set_native(false);
   return result;
 }
 
index bd370e4..8d8ef9e 100644 (file)
@@ -5906,10 +5906,11 @@ HEnvironment* HEnvironment::CopyForInlining(
       inner->SetValueAt(i, push);
     }
   }
-  // If the function we are inlining is a strict mode function, pass
-  // undefined as the receiver for function calls (instead of the
-  // global receiver).
-  if (function->strict_mode() && call_kind == CALL_AS_FUNCTION) {
+  // If the function we are inlining is a strict mode function or a
+  // builtin function, pass undefined as the receiver for function
+  // calls (instead of the global receiver).
+  if ((target->shared()->native() || function->strict_mode()) &&
+      call_kind == CALL_AS_FUNCTION) {
     inner->SetValueAt(0, undefined);
   }
   inner->SetValueAt(arity + 1, outer->LookupContext());
index 1c9bfa4..d869f05 100644 (file)
@@ -613,8 +613,8 @@ void Builtins::Generate_FunctionCall(MacroAssembler* masm) {
     __ j(not_equal, &shift_arguments);
 
     // Do not transform the receiver for natives (shared already in ebx).
-    __ test_b(FieldOperand(ebx, SharedFunctionInfo::kES5NativeByteOffset),
-              1 << SharedFunctionInfo::kES5NativeBitWithinByte);
+    __ test_b(FieldOperand(ebx, SharedFunctionInfo::kNativeByteOffset),
+              1 << SharedFunctionInfo::kNativeBitWithinByte);
     __ j(not_equal, &shift_arguments);
 
     // Compute the receiver in non-strict mode.
@@ -777,8 +777,8 @@ void Builtins::Generate_FunctionApply(MacroAssembler* masm) {
   Factory* factory = masm->isolate()->factory();
 
   // Do not transform the receiver for natives (shared already in ecx).
-  __ test_b(FieldOperand(ecx, SharedFunctionInfo::kES5NativeByteOffset),
-            1 << SharedFunctionInfo::kES5NativeBitWithinByte);
+  __ test_b(FieldOperand(ecx, SharedFunctionInfo::kNativeByteOffset),
+            1 << SharedFunctionInfo::kNativeBitWithinByte);
   __ j(not_equal, &push_receiver);
 
   // Compute the receiver in non-strict mode.
index 8b941e9..f479c82 100644 (file)
@@ -131,11 +131,11 @@ void FullCodeGenerator::Generate(CompilationInfo* info) {
   }
 #endif
 
-  // Strict mode functions need to replace the receiver with undefined
-  // when called as functions (without an explicit receiver
-  // object). ecx is zero for method calls and non-zero for function
-  // calls.
-  if (info->is_strict_mode()) {
+  // Strict mode functions and builtins need to replace the receiver
+  // with undefined when called as functions (without an explicit
+  // receiver object). ecx is zero for method calls and non-zero for
+  // function calls.
+  if (info->is_strict_mode() || info->is_native()) {
     Label ok;
     __ test(ecx, Operand(ecx));
     __ j(zero, &ok, Label::kNear);
index 8d2dfd5..177ac74 100644 (file)
@@ -128,11 +128,11 @@ bool LCodeGen::GeneratePrologue() {
   }
 #endif
 
-  // Strict mode functions need to replace the receiver with undefined
-  // when called as functions (without an explicit receiver
-  // object). ecx is zero for method calls and non-zero for function
-  // calls.
-  if (info_->is_strict_mode()) {
+  // Strict mode functions and builtins need to replace the receiver
+  // with undefined when called as functions (without an explicit
+  // receiver object). ecx is zero for method calls and non-zero for
+  // function calls.
+  if (info_->is_strict_mode() || info_->is_native()) {
     Label ok;
     __ test(ecx, Operand(ecx));
     __ j(zero, &ok, Label::kNear);
index e22259d..857fc12 100644 (file)
@@ -1214,8 +1214,7 @@ void Builtins::Generate_FunctionCall(MacroAssembler* masm) {
     __ Branch(&shift_arguments, ne, t0, Operand(zero_reg));
 
     // Do not transform the receiver for native (Compilerhints already in a3).
-    __ And(t0, a3, Operand(1 << (SharedFunctionInfo::kES5Native +
-                                 kSmiTagSize)));
+    __ And(t0, a3, Operand(1 << (SharedFunctionInfo::kNative + kSmiTagSize)));
     __ Branch(&shift_arguments, ne, t0, Operand(zero_reg));
 
     // Compute the receiver in non-strict mode.
@@ -1401,8 +1400,7 @@ void Builtins::Generate_FunctionApply(MacroAssembler* masm) {
   __ Branch(&push_receiver, ne, t0, Operand(zero_reg));
 
   // Do not transform the receiver for native (Compilerhints already in a2).
-  __ And(t0, a2, Operand(1 << (SharedFunctionInfo::kES5Native +
-                               kSmiTagSize)));
+  __ And(t0, a2, Operand(1 << (SharedFunctionInfo::kNative + kSmiTagSize)));
   __ Branch(&push_receiver, ne, t0, Operand(zero_reg));
 
   // Compute the receiver in non-strict mode.
index c8fcd02..22af01e 100644 (file)
@@ -3309,14 +3309,14 @@ void SharedFunctionInfo::set_strict_mode(bool value) {
 }
 
 
-bool SharedFunctionInfo::es5_native() {
-  return BooleanBit::get(compiler_hints(), kES5Native);
+bool SharedFunctionInfo::native() {
+  return BooleanBit::get(compiler_hints(), kNative);
 }
 
 
-void SharedFunctionInfo::set_es5_native(bool value) {
+void SharedFunctionInfo::set_native(bool value) {
   set_compiler_hints(BooleanBit::set(compiler_hints(),
-                                     kES5Native,
+                                     kNative,
                                      value));
 }
 
index 4c0e6ed..3cbbee3 100644 (file)
@@ -4406,12 +4406,12 @@ class SharedFunctionInfo: public HeapObject {
   inline bool strict_mode();
   inline void set_strict_mode(bool value);
 
-  // Indicates whether the function is a native ES5 function.
+  // Indicates whether the function is a native function.
   // These needs special threatment in .call and .apply since
   // null passed as the receiver should not be translated to the
   // global object.
-  inline bool es5_native();
-  inline void set_es5_native(bool value);
+  inline bool native();
+  inline void set_native(bool value);
 
   // Indicates whether or not the code in the shared function support
   // deoptimization.
@@ -4598,7 +4598,7 @@ class SharedFunctionInfo: public HeapObject {
   static const int kCodeAgeMask = 0x7;
   static const int kOptimizationDisabled = 6;
   static const int kStrictModeFunction = 7;
-  static const int kES5Native = 8;
+  static const int kNative = 8;
 
  private:
 #if V8_HOST_ARCH_32_BIT
@@ -4613,26 +4613,26 @@ class SharedFunctionInfo: public HeapObject {
 
  public:
   // Constants for optimizing codegen for strict mode function and
-  // es5 native tests.
+  // native tests.
   // Allows to use byte-widgh instructions.
   static const int kStrictModeBitWithinByte =
       (kStrictModeFunction + kCompilerHintsSmiTagSize) % kBitsPerByte;
 
-  static const int kES5NativeBitWithinByte =
-      (kES5Native + kCompilerHintsSmiTagSize) % kBitsPerByte;
+  static const int kNativeBitWithinByte =
+      (kNative + kCompilerHintsSmiTagSize) % kBitsPerByte;
 
 #if __BYTE_ORDER == __LITTLE_ENDIAN
   static const int kStrictModeByteOffset = kCompilerHintsOffset +
       (kStrictModeFunction + kCompilerHintsSmiTagSize) / kBitsPerByte;
-  static const int kES5NativeByteOffset = kCompilerHintsOffset +
-      (kES5Native + kCompilerHintsSmiTagSize) / kBitsPerByte;
+  static const int kNativeByteOffset = kCompilerHintsOffset +
+      (kNative + kCompilerHintsSmiTagSize) / kBitsPerByte;
 #elif __BYTE_ORDER == __BIG_ENDIAN
   static const int kStrictModeByteOffset = kCompilerHintsOffset +
       (kCompilerHintsSize - 1) -
       ((kStrictModeFunction + kCompilerHintsSmiTagSize) / kBitsPerByte);
-  static const int kES5NativeByteOffset = kCompilerHintsOffset +
+  static const int kNativeByteOffset = kCompilerHintsOffset +
       (kCompilerHintsSize - 1) -
-      ((kES5Native + kCompilerHintsSmiTagSize) / kBitsPerByte);
+      ((kNative + kCompilerHintsSmiTagSize) / kBitsPerByte);
 #else
 #error Unknown byte ordering
 #endif
index 56b7a90..3e8c019 100644 (file)
@@ -4120,10 +4120,10 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_SetProperty) {
 }
 
 
-// Set the ES5 native flag on the function.
+// Set the native flag on the function.
 // This is used to decide if we should transform null and undefined
 // into the global object when doing call and apply.
-RUNTIME_FUNCTION(MaybeObject*, Runtime_SetES5Flag) {
+RUNTIME_FUNCTION(MaybeObject*, Runtime_SetNativeFlag) {
   NoHandleAllocation ha;
   RUNTIME_ASSERT(args.length() == 1);
 
@@ -4131,7 +4131,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_SetES5Flag) {
 
   if (object->IsJSFunction()) {
     JSFunction* func = JSFunction::cast(*object);
-    func->shared()->set_es5_native(true);
+    func->shared()->set_native(true);
   }
   return isolate->heap()->undefined_value();
 }
index d3223d1..5c37c18 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright 2010 the V8 project authors. All rights reserved.
+// Copyright 2011 the V8 project authors. All rights reserved.
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
 // met:
@@ -92,7 +92,7 @@ namespace internal {
   F(CompileForOnStackReplacement, 1, 1) \
   F(SetNewFunctionAttributes, 1, 1) \
   F(AllocateInNewSpace, 1, 1) \
-  F(SetES5Flag, 1, 1) \
+  F(SetNativeFlag, 1, 1) \
   \
   /* Array join support */ \
   F(PushIfAbsent, 2, 1) \
index d22e94d..469059b 100644 (file)
@@ -56,7 +56,7 @@ function InstallFunctions(object, attributes, functions) {
     %FunctionSetName(f, key);
     %FunctionRemovePrototype(f);
     %SetProperty(object, key, f, attributes);
-    %SetES5Flag(f);
+    %SetNativeFlag(f);
   }
   %ToFastProperties(object);
 }
@@ -132,10 +132,19 @@ function GlobalParseFloat(string) {
 function GlobalEval(x) {
   if (!IS_STRING(x)) return x;
 
+  var receiver = this;
   var global_receiver = %GlobalReceiver(global);
-  var this_is_global_receiver = (this === global_receiver);
+
+  if (receiver == null && !IS_UNDETECTABLE(receiver)) {
+    receiver = global_receiver;
+  }
+
+  var this_is_global_receiver = (receiver === global_receiver);
   var global_is_detached = (global === global_receiver);
 
+  // For consistency with JSC we require the global object passed to
+  // eval to be the global object from which 'eval' originated. This
+  // is not mandated by the spec.
   if (!this_is_global_receiver || global_is_detached) {
     throw new $EvalError('The "this" object passed to eval must ' +
                          'be the global object from which eval originated');
@@ -144,7 +153,7 @@ function GlobalEval(x) {
   var f = %CompileString(x);
   if (!IS_FUNCTION(f)) return f;
 
-  return %_CallFunction(this, f);
+  return %_CallFunction(receiver, f);
 }
 
 
@@ -246,8 +255,9 @@ function ObjectPropertyIsEnumerable(V) {
 
 // Extensions for providing property getters and setters.
 function ObjectDefineGetter(name, fun) {
-  if (this == null && !IS_UNDETECTABLE(this)) {
-    throw new $TypeError('Object.prototype.__defineGetter__: this is Null');
+  var receiver = this;
+  if (receiver == null && !IS_UNDETECTABLE(receiver)) {
+    receiver = %GlobalReceiver(global);
   }
   if (!IS_FUNCTION(fun)) {
     throw new $TypeError('Object.prototype.__defineGetter__: Expecting function');
@@ -256,21 +266,23 @@ function ObjectDefineGetter(name, fun) {
   desc.setGet(fun);
   desc.setEnumerable(true);
   desc.setConfigurable(true);
-  DefineOwnProperty(ToObject(this), ToString(name), desc, false);
+  DefineOwnProperty(ToObject(receiver), ToString(name), desc, false);
 }
 
 
 function ObjectLookupGetter(name) {
-  if (this == null && !IS_UNDETECTABLE(this)) {
-    throw new $TypeError('Object.prototype.__lookupGetter__: this is Null');
+  var receiver = this;
+  if (receiver == null && !IS_UNDETECTABLE(receiver)) {
+    receiver = %GlobalReceiver(global);
   }
-  return %LookupAccessor(ToObject(this), ToString(name), GETTER);
+  return %LookupAccessor(ToObject(receiver), ToString(name), GETTER);
 }
 
 
 function ObjectDefineSetter(name, fun) {
-  if (this == null && !IS_UNDETECTABLE(this)) {
-    throw new $TypeError('Object.prototype.__defineSetter__: this is Null');
+  var receiver = this;
+  if (receiver == null && !IS_UNDETECTABLE(receiver)) {
+    receiver = %GlobalReceiver(global);
   }
   if (!IS_FUNCTION(fun)) {
     throw new $TypeError(
@@ -280,15 +292,16 @@ function ObjectDefineSetter(name, fun) {
   desc.setSet(fun);
   desc.setEnumerable(true);
   desc.setConfigurable(true);
-  DefineOwnProperty(ToObject(this), ToString(name), desc, false);
+  DefineOwnProperty(ToObject(receiver), ToString(name), desc, false);
 }
 
 
 function ObjectLookupSetter(name) {
-  if (this == null && !IS_UNDETECTABLE(this)) {
-    throw new $TypeError('Object.prototype.__lookupSetter__: this is Null');
+  var receiver = this;
+  if (receiver == null && !IS_UNDETECTABLE(receiver)) {
+    receiver = %GlobalReceiver(global);
   }
-  return %LookupAccessor(ToObject(this), ToString(name), SETTER);
+  return %LookupAccessor(ToObject(receiver), ToString(name), SETTER);
 }
 
 
index d324d2f..82ee48e 100644 (file)
@@ -673,8 +673,8 @@ void Builtins::Generate_FunctionCall(MacroAssembler* masm) {
 
     // Do not transform the receiver for natives.
     // SharedFunctionInfo is already loaded into rbx.
-    __ testb(FieldOperand(rbx, SharedFunctionInfo::kES5NativeByteOffset),
-             Immediate(1 << SharedFunctionInfo::kES5NativeBitWithinByte));
+    __ testb(FieldOperand(rbx, SharedFunctionInfo::kNativeByteOffset),
+             Immediate(1 << SharedFunctionInfo::kNativeBitWithinByte));
     __ j(not_zero, &shift_arguments);
 
     // Compute the receiver in non-strict mode.
@@ -844,8 +844,8 @@ void Builtins::Generate_FunctionApply(MacroAssembler* masm) {
   __ j(not_equal, &push_receiver);
 
   // Do not transform the receiver for natives.
-  __ testb(FieldOperand(rdx, SharedFunctionInfo::kES5NativeByteOffset),
-           Immediate(1 << SharedFunctionInfo::kES5NativeBitWithinByte));
+  __ testb(FieldOperand(rdx, SharedFunctionInfo::kNativeByteOffset),
+           Immediate(1 << SharedFunctionInfo::kNativeBitWithinByte));
   __ j(not_zero, &push_receiver);
 
   // Compute the receiver in non-strict mode.
index 329fd18..9f8d4ba 100644 (file)
@@ -131,11 +131,11 @@ void FullCodeGenerator::Generate(CompilationInfo* info) {
   }
 #endif
 
-  // Strict mode functions need to replace the receiver with undefined
-  // when called as functions (without an explicit receiver
-  // object). rcx is zero for method calls and non-zero for function
-  // calls.
-  if (info->is_strict_mode()) {
+  // Strict mode functions and builtins need to replace the receiver
+  // with undefined when called as functions (without an explicit
+  // receiver object). rcx is zero for method calls and non-zero for
+  // function calls.
+  if (info->is_strict_mode() || info->is_native()) {
     Label ok;
     __ testq(rcx, rcx);
     __ j(zero, &ok, Label::kNear);
index 97177de..7345529 100644 (file)
@@ -144,7 +144,7 @@ bool LCodeGen::GeneratePrologue() {
   // when called as functions (without an explicit receiver
   // object). rcx is zero for method calls and non-zero for function
   // calls.
-  if (info_->is_strict_mode()) {
+  if (info_->is_strict_mode() || info_->is_native()) {
     Label ok;
     __ testq(rcx, rcx);
     __ j(zero, &ok, Label::kNear);
index 1121210..34d70b6 100644 (file)
@@ -6664,7 +6664,7 @@ THREADED_TEST(ShadowObject) {
   context->Global()->Set(v8_str("__proto__"), o);
 
   Local<Value> value =
-      Script::Compile(v8_str("propertyIsEnumerable(0)"))->Run();
+      Script::Compile(v8_str("this.propertyIsEnumerable(0)"))->Run();
   CHECK(value->IsBoolean());
   CHECK(!value->BooleanValue());
 
index 8a5a9cf..2ed7458 100644 (file)
@@ -30,18 +30,18 @@ var setter_value = 0;
 __proto__.__defineSetter__("a", function(v) { setter_value = v; });
 eval("var a = 1");
 assertEquals(1, setter_value);
-assertFalse(hasOwnProperty("a"));
+assertFalse(this.hasOwnProperty("a"));
 
 eval("with({}) { eval('var a = 2') }");
 assertEquals(2, setter_value);
-assertFalse(hasOwnProperty("a"));
+assertFalse(this.hasOwnProperty("a"));
 
 // Function declarations are treated specially to match Safari. We do
 // not call setters for them.
 eval("function a() {}");
-assertTrue(hasOwnProperty("a"));
+assertTrue(this.hasOwnProperty("a"));
 
-__proto__.__defineSetter__("b", function(v) {   assertUnreachable(); });
+__proto__.__defineSetter__("b", function(v) { assertUnreachable(); });
 try {
   eval("const b = 23");
   assertUnreachable();
@@ -61,6 +61,5 @@ try {
   assertUnreachable();
 } catch(e) {
   assertEquals(42, e);
-  assertFalse(hasOwnProperty("c"));
+  assertFalse(this.hasOwnProperty("c"));
 }
-
index 0b3aae5..e0df6f5 100644 (file)
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 assertEquals("[object global]", this.toString());
-assertEquals("[object global]", toString());
+assertEquals("[object Undefined]", toString());
 
 assertEquals("[object global]", eval("this.toString()"));
-assertEquals("[object global]", eval("toString()"));
+assertEquals("[object Undefined]", eval("toString()"));
 
 assertEquals("[object global]", eval("var f; this.toString()"));
-assertEquals("[object global]", eval("var f; toString()"));
+assertEquals("[object Undefined]", eval("var f; toString()"));
 
 
 function F(f) {
@@ -45,7 +45,7 @@ function F(f) {
   assertEquals("[object global]", eval("var f; this.toString()"));
   assertEquals("[object global]", eval("var f; toString()"));
 
-  assertEquals("[object global]", eval("f()"));
+  assertEquals("[object Undefined]", eval("f()"));
 
   // Receiver should be the arguments object here.
   assertEquals("[object Arguments]", eval("arguments[0]()"));
diff --git a/test/mjsunit/regress/regress-1365.js b/test/mjsunit/regress/regress-1365.js
new file mode 100644 (file)
index 0000000..f19bdd0
--- /dev/null
@@ -0,0 +1,65 @@
+// Copyright 2011 the V8 project authors. 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.
+
+// See: http://code.google.com/p/v8/issues/detail?id=1365
+
+// Check that builtin methods are passed undefined as the receiver
+// when called as functions through variables.
+
+// Flags: --allow-natives-syntax
+
+// Global variable.
+var valueOf = Object.prototype.valueOf;
+var hasOwnProperty = Object.prototype.hasOwnProperty;
+
+function callGlobalValueOf() { valueOf(); }
+function callGlobalHasOwnProperty() { valueOf(); }
+
+assertEquals(Object.prototype, Object.prototype.valueOf());
+assertThrows(callGlobalValueOf);
+assertThrows(callGlobalHasOwnProperty);
+
+%OptimizeFunctionOnNextCall(Object.prototype.valueOf);
+Object.prototype.valueOf();
+
+assertEquals(Object.prototype, Object.prototype.valueOf());
+assertThrows(callGlobalValueOf);
+assertThrows(callGlobalHasOwnProperty);
+
+function CheckExceptionCallLocal() {
+  var valueOf = Object.prototype.valueOf;
+  var hasOwnProperty = Object.prototype.hasOwnProperty;
+  try { valueOf(); assertUnreachable(); } catch(e) { }
+  try { hasOwnProperty(); assertUnreachable(); } catch(e) { }
+}
+CheckExceptionCallLocal();
+
+function CheckExceptionCallParameter(f) {
+  try { f(); assertUnreachable(); } catch(e) { }
+}
+CheckExceptionCallParameter(Object.prototype.valueOf);
+CheckExceptionCallParameter(Object.prototype.hasOwnProperty);
index e5182b3..f26e0eb 100755 (executable)
@@ -34,11 +34,6 @@ var global = this;
 var global2 = (function(){return this;})();
 assertEquals(global, global2, "direct call to local function returns global");
 
-var builtin = Object.prototype.valueOf;  // Builtin function that returns this.
-
-assertEquals(global, builtin(), "Direct call to builtin");
-
-
 // Builtin that depends on value of this to compute result.
 var builtin2 = Object.prototype.toString;
 
index 44b5577..09937f7 100644 (file)
@@ -206,6 +206,10 @@ ecma_3/RegExp/regress-85721: PASS || FAIL if $mode == debug
 # This section is for tests that fail in both V8 and JSC.  Thus they
 # have been determined to be incompatible between Mozilla and V8/JSC.
 
+# Fail because it calls builtins as functions and do not expect the
+# builtin to have undefined as the receiver.
+ecma/String/15.5.4.6-2: FAIL_OK
+
 # Fail because of toLowerCase and toUpperCase conversion.
 ecma/String/15.5.4.11-2: FAIL_OK
 ecma/String/15.5.4.11-5: FAIL_OK
index 472db6e..aeb85b0 100644 (file)
@@ -175,6 +175,23 @@ S11.1.5_A4.2: FAIL_OK
 S9.9_A1: FAIL_OK
 S9.9_A2: FAIL_OK
 
+# Calls builtins without an explicit receiver which means that
+# undefined is passed to the builtin. The tests expect the global
+# object to be passed which was true in ES3 but not in ES5.
+S11.1.1_A2: FAIL_OK
+S15.5.4.4_A1_T3: FAIL_OK
+S15.5.4.5_A1_T3: FAIL_OK
+S15.5.4.6_A1_T3: FAIL_OK
+S15.5.4.7_A1_T3: FAIL_OK
+S15.5.4.8_A1_T3: FAIL_OK
+S15.5.4.9_A1_T3: FAIL_OK
+S15.5.4.10_A1_T3: FAIL_OK
+S15.5.4.11_A1_T3: FAIL_OK
+S15.5.4.12_A1_T3: FAIL_OK
+S15.5.4.13_A1_T3: FAIL_OK
+S15.5.4.14_A1_T3: FAIL_OK
+S15.5.4.15_A1_T3: FAIL_OK
+
 ##################### SKIPPED TESTS #####################
 
 # These tests take a looong time to run in debug mode.