deps: upgrade V8 to 4.5.103.35
authorAli Ijaz Sheikh <ofrobots@google.com>
Tue, 29 Sep 2015 15:51:07 +0000 (08:51 -0700)
committerRod Vagg <rod@vagg.org>
Fri, 2 Oct 2015 03:39:25 +0000 (13:39 +1000)
Apply the latest fixes from V8 4.5 branch & bring us up to 4.5.103.35:
* Disallow Object.observe calls on access checked objects.
https://github.com/v8/v8/commit/134e541ad149b9732bc4fee6fe6952cf669703a7
* Avoid excessive data copying for ExternalStreamingStream::SetBookmark.
https://github.com/v8/v8/commit/96dddb455daff3d8626bc4e5d7b2898fbab55991

PR-URL: https://github.com/nodejs/node/pull/3117
Reviewed-By: indutny - Fedor Indutny <fedor.indutny@gmail.com>
Reviewed-By: bnoordhuis - Ben Noordhuis <info@bnoordhuis.nl>
Reviewed-By: trevnorris - Trevor Norris <trev.norris@gmail.com>
Reviewed-By: targos - Michaƫl Zasso <mic.besace@gmail.com>
deps/v8/include/v8-version.h
deps/v8/src/messages.h
deps/v8/src/object-observe.js
deps/v8/src/runtime/runtime-object.cc
deps/v8/src/runtime/runtime.h
deps/v8/src/scanner-character-streams.cc
deps/v8/src/scanner-character-streams.h
deps/v8/test/cctest/test-object-observe.cc

index 56ef22b..98dca23 100644 (file)
@@ -11,7 +11,7 @@
 #define V8_MAJOR_VERSION 4
 #define V8_MINOR_VERSION 5
 #define V8_BUILD_NUMBER 103
-#define V8_PATCH_LEVEL 33
+#define V8_PATCH_LEVEL 35
 
 // Use 1 for candidates and 0 otherwise.
 // (Boolean macro values are not supported by all preprocessors.)
index 4072300..5c3e867 100644 (file)
@@ -173,6 +173,7 @@ class CallSite {
   T(ObserveCallbackFrozen,                                                     \
     "Object.observe cannot deliver to a frozen function object")               \
   T(ObserveGlobalProxy, "% cannot be called on the global proxy object")       \
+  T(ObserveAccessChecked, "% cannot be called on access-checked objects")      \
   T(ObserveInvalidAccept,                                                      \
     "Third argument to Object.observe must be an array of strings.")           \
   T(ObserveNonFunction, "Object.% cannot deliver to non-function")             \
index 56859a1..9c49fd3 100644 (file)
@@ -389,6 +389,8 @@ function ObjectObserve(object, callback, acceptList) {
     throw MakeTypeError(kObserveNonObject, "observe", "observe");
   if (%IsJSGlobalProxy(object))
     throw MakeTypeError(kObserveGlobalProxy, "observe");
+  if (%IsAccessCheckNeeded(object))
+    throw MakeTypeError(kObserveAccessChecked, "observe");
   if (!IS_SPEC_FUNCTION(callback))
     throw MakeTypeError(kObserveNonFunction, "observe");
   if (ObjectIsFrozen(callback))
@@ -617,6 +619,8 @@ function ObjectGetNotifier(object) {
     throw MakeTypeError(kObserveNonObject, "getNotifier", "getNotifier");
   if (%IsJSGlobalProxy(object))
     throw MakeTypeError(kObserveGlobalProxy, "getNotifier");
+  if (%IsAccessCheckNeeded(object))
+    throw MakeTypeError(kObserveAccessChecked, "getNotifier");
 
   if (ObjectIsFrozen(object)) return null;
 
index da1ec49..9536ec0 100644 (file)
@@ -1435,5 +1435,13 @@ RUNTIME_FUNCTION(Runtime_DefineSetterPropertyUnchecked) {
                                setter, attrs));
   return isolate->heap()->undefined_value();
 }
+
+
+RUNTIME_FUNCTION(Runtime_IsAccessCheckNeeded) {
+  SealHandleScope shs(isolate);
+  DCHECK_EQ(1, args.length());
+  CONVERT_ARG_CHECKED(Object, object, 0);
+  return isolate->heap()->ToBoolean(object->IsAccessCheckNeeded());
+}
 }  // namespace internal
 }  // namespace v8
index da1ae40..c4f74e7 100644 (file)
@@ -483,7 +483,8 @@ namespace internal {
   F(IsStrong, 1, 1)                                  \
   F(ClassOf, 1, 1)                                   \
   F(DefineGetterPropertyUnchecked, 4, 1)             \
-  F(DefineSetterPropertyUnchecked, 4, 1)
+  F(DefineSetterPropertyUnchecked, 4, 1)             \
+  F(IsAccessCheckNeeded, 1, 1)
 
 
 #define FOR_EACH_INTRINSIC_OBSERVE(F)            \
index 442bc75..eaaa9bc 100644 (file)
@@ -346,6 +346,7 @@ size_t ExternalStreamingStream::FillBuffer(size_t position) {
       current_data_length_ = source_stream_->GetMoreData(&current_data_);
       current_data_offset_ = 0;
       bool data_ends = current_data_length_ == 0;
+      bookmark_data_is_from_current_data_ = false;
 
       // A caveat: a data chunk might end with bytes from an incomplete UTF-8
       // character (the rest of the bytes will be in the next chunk).
@@ -405,6 +406,15 @@ bool ExternalStreamingStream::SetBookmark() {
   // - buffer_[buffer_cursor_ .. buffer_end_]  =>  bookmark_buffer_
   // - current_data_[.._offset_ .. .._length_]  =>  bookmark_data_
   // - utf8_split_char_buffer_* => bookmark_utf8_split...
+  //
+  // To make sure we don't unnecessarily copy data, we also maintain
+  // whether bookmark_data_ contains a copy of the current current_data_
+  // block. This is done with:
+  // - bookmark_data_is_from_current_data_
+  // - bookmark_data_offset_: offset into bookmark_data_
+  //
+  // Note that bookmark_data_is_from_current_data_ must be maintained
+  // whenever current_data_ is updated.
 
   bookmark_ = pos_;
 
@@ -414,10 +424,21 @@ bool ExternalStreamingStream::SetBookmark() {
   CopyCharsUnsigned(bookmark_buffer_.start(), buffer_cursor_, buffer_length);
 
   size_t data_length = current_data_length_ - current_data_offset_;
-  bookmark_data_.Dispose();
-  bookmark_data_ = Vector<uint8_t>::New(static_cast<int>(data_length));
-  CopyBytes(bookmark_data_.start(), current_data_ + current_data_offset_,
-            data_length);
+  size_t bookmark_data_length = static_cast<size_t>(bookmark_data_.length());
+  if (bookmark_data_is_from_current_data_ &&
+      data_length < bookmark_data_length) {
+    // Fast case: bookmark_data_ was previously copied from the current
+    //            data block, and we have enough data for this bookmark.
+    bookmark_data_offset_ = bookmark_data_length - data_length;
+  } else {
+    // Slow case: We need to copy current_data_.
+    bookmark_data_.Dispose();
+    bookmark_data_ = Vector<uint8_t>::New(static_cast<int>(data_length));
+    CopyBytes(bookmark_data_.start(), current_data_ + current_data_offset_,
+              data_length);
+    bookmark_data_is_from_current_data_ = true;
+    bookmark_data_offset_ = 0;
+  }
 
   bookmark_utf8_split_char_buffer_length_ = utf8_split_char_buffer_length_;
   for (size_t i = 0; i < utf8_split_char_buffer_length_; i++) {
@@ -436,12 +457,14 @@ void ExternalStreamingStream::ResetToBookmark() {
 
   // bookmark_data_* => current_data_*
   // (current_data_ assumes ownership of its memory.)
-  uint8_t* data = new uint8_t[bookmark_data_.length()];
   current_data_offset_ = 0;
-  current_data_length_ = bookmark_data_.length();
-  CopyCharsUnsigned(data, bookmark_data_.begin(), bookmark_data_.length());
+  current_data_length_ = bookmark_data_.length() - bookmark_data_offset_;
+  uint8_t* data = new uint8_t[current_data_length_];
+  CopyCharsUnsigned(data, bookmark_data_.begin() + bookmark_data_offset_,
+                    current_data_length_);
   delete[] current_data_;
   current_data_ = data;
+  bookmark_data_is_from_current_data_ = true;
 
   // bookmark_buffer_ needs to be copied to buffer_.
   CopyCharsUnsigned(buffer_, bookmark_buffer_.begin(),
@@ -462,6 +485,7 @@ void ExternalStreamingStream::FlushCurrent() {
   current_data_ = NULL;
   current_data_length_ = 0;
   current_data_offset_ = 0;
+  bookmark_data_is_from_current_data_ = false;
 }
 
 
index 5821657..f3ee204 100644 (file)
@@ -94,6 +94,8 @@ class ExternalStreamingStream : public BufferedUtf16CharacterStream {
         current_data_length_(0),
         utf8_split_char_buffer_length_(0),
         bookmark_(0),
+        bookmark_data_is_from_current_data_(false),
+        bookmark_data_offset_(0),
         bookmark_utf8_split_char_buffer_length_(0) {}
 
   virtual ~ExternalStreamingStream() {
@@ -134,6 +136,8 @@ class ExternalStreamingStream : public BufferedUtf16CharacterStream {
   size_t bookmark_;
   Vector<uint16_t> bookmark_buffer_;
   Vector<uint8_t> bookmark_data_;
+  bool bookmark_data_is_from_current_data_;
+  size_t bookmark_data_offset_;
   uint8_t bookmark_utf8_split_char_buffer_[4];
   size_t bookmark_utf8_split_char_buffer_length_;
 };
index abbf2b7..0295de5 100644 (file)
@@ -885,3 +885,39 @@ TEST(UseCountObjectGetNotifier) {
   CompileRun("Object.getNotifier(obj)");
   CHECK_EQ(1, use_counts[v8::Isolate::kObjectObserve]);
 }
+
+
+static bool NamedAccessCheckAlwaysAllow(Local<v8::Object> global,
+                                        Local<v8::Value> name,
+                                        v8::AccessType type,
+                                        Local<Value> data) {
+  return true;
+}
+
+
+TEST(DisallowObserveAccessCheckedObject) {
+  v8::Isolate* isolate = CcTest::isolate();
+  v8::HandleScope scope(isolate);
+  LocalContext env;
+  v8::Local<v8::ObjectTemplate> object_template =
+      v8::ObjectTemplate::New(isolate);
+  object_template->SetAccessCheckCallbacks(NamedAccessCheckAlwaysAllow, NULL);
+  env->Global()->Set(v8_str("obj"), object_template->NewInstance());
+  v8::TryCatch try_catch(isolate);
+  CompileRun("Object.observe(obj, function(){})");
+  CHECK(try_catch.HasCaught());
+}
+
+
+TEST(DisallowGetNotifierAccessCheckedObject) {
+  v8::Isolate* isolate = CcTest::isolate();
+  v8::HandleScope scope(isolate);
+  LocalContext env;
+  v8::Local<v8::ObjectTemplate> object_template =
+      v8::ObjectTemplate::New(isolate);
+  object_template->SetAccessCheckCallbacks(NamedAccessCheckAlwaysAllow, NULL);
+  env->Global()->Set(v8_str("obj"), object_template->NewInstance());
+  v8::TryCatch try_catch(isolate);
+  CompileRun("Object.getNotifier(obj)");
+  CHECK(try_catch.HasCaught());
+}