Merge V8 5.3.332.45.  DO NOT MERGE

Test: Manual

FPIIM-449

Change-Id: Id3254828b068abdea3cb10442e0172a8c9a98e03
(cherry picked from commit 13e2dadd00298019ed862f2b2fc5068bba730bcf)
diff --git a/test/cctest/test-usecounters.cc b/test/cctest/test-usecounters.cc
new file mode 100644
index 0000000..8d4628c
--- /dev/null
+++ b/test/cctest/test-usecounters.cc
@@ -0,0 +1,73 @@
+// Copyright 2016 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.
+
+#include "src/v8.h"
+
+#include "test/cctest/cctest.h"
+
+namespace {
+
+int* global_use_counts = NULL;
+
+void MockUseCounterCallback(v8::Isolate* isolate,
+                            v8::Isolate::UseCounterFeature feature) {
+  ++global_use_counts[feature];
+}
+}
+
+TEST(DefineGetterSetterThrowUseCount) {
+  v8::Isolate* isolate = CcTest::isolate();
+  v8::HandleScope scope(isolate);
+  LocalContext env;
+  int use_counts[v8::Isolate::kUseCounterFeatureCount] = {};
+  global_use_counts = use_counts;
+  CcTest::isolate()->SetUseCounterCallback(MockUseCounterCallback);
+
+  // __defineGetter__ and __defineSetter__ do not increment
+  // kDefineGetterOrSetterWouldThrow on success
+  CompileRun(
+      "var a = {};"
+      "Object.defineProperty(a, 'b', { value: 0, configurable: true });"
+      "a.__defineGetter__('b', ()=>{});");
+  CHECK_EQ(0, use_counts[v8::Isolate::kDefineGetterOrSetterWouldThrow]);
+  CompileRun(
+      "var a = {};"
+      "Object.defineProperty(a, 'b', { value: 0, configurable: true });"
+      "a.__defineSetter__('b', ()=>{});");
+  CHECK_EQ(0, use_counts[v8::Isolate::kDefineGetterOrSetterWouldThrow]);
+
+  // __defineGetter__ and __defineSetter__ do not increment
+  // kDefineGetterOrSetterWouldThrow on other errors
+  v8::Local<v8::Value> resultProxyThrow = CompileRun(
+      "var exception;"
+      "try {"
+      "var a = new Proxy({}, { defineProperty: ()=>{throw new Error;} });"
+      "a.__defineGetter__('b', ()=>{});"
+      "} catch (e) { exception = e; }"
+      "exception");
+  CHECK_EQ(0, use_counts[v8::Isolate::kDefineGetterOrSetterWouldThrow]);
+  CHECK(resultProxyThrow->IsObject());
+  resultProxyThrow = CompileRun(
+      "var exception;"
+      "try {"
+      "var a = new Proxy({}, { defineProperty: ()=>{throw new Error;} });"
+      "a.__defineSetter__('b', ()=>{});"
+      "} catch (e) { exception = e; }"
+      "exception");
+  CHECK_EQ(0, use_counts[v8::Isolate::kDefineGetterOrSetterWouldThrow]);
+  CHECK(resultProxyThrow->IsObject());
+
+  // __defineGetter__ and __defineSetter__ increment
+  // kDefineGetterOrSetterWouldThrow when they would throw per spec (B.2.2.2)
+  CompileRun(
+      "var a = {};"
+      "Object.defineProperty(a, 'b', { value: 0, configurable: false });"
+      "a.__defineGetter__('b', ()=>{});");
+  CHECK_EQ(1, use_counts[v8::Isolate::kDefineGetterOrSetterWouldThrow]);
+  CompileRun(
+      "var a = {};"
+      "Object.defineProperty(a, 'b', { value: 0, configurable: false });"
+      "a.__defineSetter__('b', ()=>{});");
+  CHECK_EQ(2, use_counts[v8::Isolate::kDefineGetterOrSetterWouldThrow]);
+}