Censor .caller if it is a strict function instead of throwing.
authorrossberg@chromium.org <rossberg@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Fri, 23 Nov 2012 15:47:58 +0000 (15:47 +0000)
committerrossberg@chromium.org <rossberg@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Fri, 23 Nov 2012 15:47:58 +0000 (15:47 +0000)
For details, see:

http://www.mail-archive.com/es-discuss@mozilla.org/msg19322.html
https://bugs.ecmascript.org/show_bug.cgi?id=310

R=mstarzinger@chromium.org
BUG=

Review URL: https://codereview.chromium.org/11417140

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

src/accessors.cc
test/mjsunit/strict-mode.js

index 855ddb2..a30bfd5 100644 (file)
@@ -649,19 +649,6 @@ const AccessorDescriptor Accessors::FunctionArguments = {
 //
 
 
-static MaybeObject* CheckNonStrictCallerOrThrow(
-    Isolate* isolate,
-    JSFunction* caller) {
-  DisableAssertNoAllocation enable_allocation;
-  if (!caller->shared()->is_classic_mode()) {
-    return isolate->Throw(
-        *isolate->factory()->NewTypeError("strict_caller",
-                                          HandleVector<Object>(NULL, 0)));
-  }
-  return caller;
-}
-
-
 class FrameFunctionIterator {
  public:
   FrameFunctionIterator(Isolate* isolate, const AssertNoAllocation& promise)
@@ -748,7 +735,14 @@ MaybeObject* Accessors::FunctionGetCaller(Object* object, void*) {
   if (caller->shared()->bound()) {
     return isolate->heap()->null_value();
   }
-  return CheckNonStrictCallerOrThrow(isolate, caller);
+  // Censor if the caller is not a classic mode function.
+  // Change from ES5, which used to throw, see:
+  // https://bugs.ecmascript.org/show_bug.cgi?id=310
+  if (!caller->shared()->is_classic_mode()) {
+    return isolate->heap()->null_value();
+  }
+
+  return caller;
 }
 
 
index e13ada4..5fb404a 100644 (file)
@@ -1141,9 +1141,9 @@ function CheckPillDescriptor(func, name) {
 
   function strict() {
     "use strict";
-    return_my_caller();
+    return return_my_caller();
   }
-  assertThrows(strict, TypeError);
+  assertSame(null, strict());
 
   function non_strict() {
     return return_my_caller();
@@ -1155,32 +1155,57 @@ function CheckPillDescriptor(func, name) {
 (function TestNonStrictFunctionCallerPill() {
   function strict(n) {
     "use strict";
-    non_strict(n);
+    return non_strict(n);
   }
 
   function recurse(n, then) {
     if (n > 0) {
-      recurse(n - 1, then);
+      return recurse(n - 1, then);
     } else {
       return then();
     }
   }
 
   function non_strict(n) {
-    recurse(n, function() { non_strict.caller; });
+    return recurse(n, function() { return non_strict.caller; });
   }
 
   function test(n) {
-    try {
-      recurse(n, function() { strict(n); });
-    } catch(e) {
-      return e instanceof TypeError;
+    return recurse(n, function() { return strict(n); });
+  }
+
+  for (var i = 0; i < 10; i ++) {
+    assertSame(null, test(i));
+  }
+})();
+
+
+(function TestNonStrictFunctionCallerDescriptorPill() {
+  function strict(n) {
+    "use strict";
+    return non_strict(n);
+  }
+
+  function recurse(n, then) {
+    if (n > 0) {
+      return recurse(n - 1, then);
+    } else {
+      return then();
     }
-    return false;
+  }
+
+  function non_strict(n) {
+    return recurse(n, function() {
+      return Object.getOwnPropertyDescriptor(non_strict, "caller").value;
+    });
+  }
+
+  function test(n) {
+    return recurse(n, function() { return strict(n); });
   }
 
   for (var i = 0; i < 10; i ++) {
-    assertEquals(test(i), true);
+    assertSame(null, test(i));
   }
 })();