Bug 1074571 - Make the delete operator trigger TDZ. (r=Waldo)
authorShu-yu Guo <shu@rfrn.org>
Tue, 30 Sep 2014 15:18:30 -0700
changeset 208069 da1b3063095cf09a81901b0cd9e2aecbc7d9180e
parent 208068 f624db42fc488fac10a993f88e2bff43e9d551e1
child 208070 b37f591b400e4ce5a1a37bf0d9d18f9c605641d7
push id27575
push usercbook@mozilla.com
push dateWed, 01 Oct 2014 12:52:17 +0000
treeherdermozilla-central@fe0afc101ad2 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersWaldo
bugs1074571
milestone35.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1074571 - Make the delete operator trigger TDZ. (r=Waldo)
js/src/jit-test/tests/basic/letTDZDelete.js
js/src/vm/Interpreter.cpp
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/basic/letTDZDelete.js
@@ -0,0 +1,23 @@
+function assertThrowsReferenceError(f) {
+  var e = null;
+  try {
+    f();
+  } catch (ex) {
+    e = ex;
+  }
+  assertEq(e instanceof ReferenceError, true);
+}
+
+assertThrowsReferenceError(function () { delete x; let x; });
+
+// FIXME do this unconditionally once bug 611388 lands.
+function constIsLexical() {
+  try {
+    (function () { z++; const z; })();
+    return false;
+  } catch (e) {
+    return true;
+  }
+}
+if (constIsLexical())
+  assertThrowsReferenceError(function () { delete x; const x; });
--- a/js/src/vm/Interpreter.cpp
+++ b/js/src/vm/Interpreter.cpp
@@ -3551,17 +3551,17 @@ js::GetScopeName(JSContext *cx, HandleOb
         if (AtomToPrintableString(cx, name, &printable))
             js_ReportIsNotDefined(cx, printable.ptr());
         return false;
     }
 
     if (!JSObject::getProperty(cx, obj, obj, name, vp))
         return false;
 
-    // See note in NameOperation.
+    // See note in FetchName.
     return CheckUninitializedLexical(cx, name, vp);
 }
 
 /*
  * Alternate form for NAME opcodes followed immediately by a TYPEOF,
  * which do not report an exception on (typeof foo == "undefined") tests.
  */
 bool
@@ -3576,17 +3576,17 @@ js::GetScopeNameForTypeOf(JSContext *cx,
     if (!shape) {
         vp.set(UndefinedValue());
         return true;
     }
 
     if (!JSObject::getProperty(cx, obj, obj, name, vp))
         return false;
 
-    // See note in NameOperation.
+    // See note in FetchName.
     return CheckUninitializedLexical(cx, name, vp);
 }
 
 JSObject *
 js::Lambda(JSContext *cx, HandleFunction fun, HandleObject parent)
 {
     MOZ_ASSERT(!fun->isArrow());
 
@@ -3861,16 +3861,23 @@ js::DeleteNameOperation(JSContext *cx, H
         return false;
 
     if (!scope) {
         // Return true for non-existent names.
         res.setBoolean(true);
         return true;
     }
 
+    // NAME operations are the slow paths already, so unconditionally check
+    // for uninitialized lets.
+    if (pobj == scope && IsUninitializedLexicalSlot(scope, shape)) {
+        ReportUninitializedLexical(cx, name);
+        return false;
+    }
+
     bool succeeded;
     RootedId id(cx, NameToId(name));
     if (!JSObject::deleteGeneric(cx, scope, id, &succeeded))
         return false;
     res.setBoolean(succeeded);
     return true;
 }