Revision: 20209
Author:   [email protected]
Date:     Mon Mar 24 16:34:06 2014 UTC
Log:      Add support for per-isolate private symbols

[email protected]
BUG=
LOG=Y

Review URL: https://codereview.chromium.org/196103004
http://code.google.com/p/v8/source/detail?r=20209

Modified:
 /branches/bleeding_edge/include/v8.h
 /branches/bleeding_edge/src/api.cc
 /branches/bleeding_edge/src/array-iterator.js
 /branches/bleeding_edge/src/heap.cc
 /branches/bleeding_edge/src/heap.h
 /branches/bleeding_edge/src/isolate.cc
 /branches/bleeding_edge/src/isolate.h
 /branches/bleeding_edge/src/macros.py
 /branches/bleeding_edge/src/messages.js
 /branches/bleeding_edge/src/promise.js
 /branches/bleeding_edge/src/runtime.cc
 /branches/bleeding_edge/src/runtime.h
 /branches/bleeding_edge/src/symbol.js
 /branches/bleeding_edge/test/cctest/test-api.cc

=======================================
--- /branches/bleeding_edge/include/v8.h        Mon Mar 24 12:13:58 2014 UTC
+++ /branches/bleeding_edge/include/v8.h        Mon Mar 24 16:34:06 2014 UTC
@@ -2001,9 +2001,20 @@
   // Returns the print name string of the symbol, or undefined if none.
   Local<Value> Name() const;

-  // Create a symbol. If data is not NULL, it will be used as a print name.
+ // Create a symbol. If name is not empty, it will be used as the description.
   static Local<Symbol> New(
-      Isolate *isolate, const char* data = NULL, int length = -1);
+      Isolate *isolate, Local<String> name = Local<String>());
+
+  // Access global symbol registry.
+  // Note that symbols created this way are never collected, so
+  // they should only be used for statically fixed properties.
+  // Also, there is only one global name space for the names used as keys.
+  // To minimize the potential for clashes, use qualified names as keys.
+  static Local<Symbol> For(Isolate *isolate, Local<String> name);
+
+  // Retrieve a global symbol. Similar to |For|, but using a separate
+ // registry that is not accessible by (and cannot clash with) JavaScript code.
+  static Local<Symbol> ForApi(Isolate *isolate, Local<String> name);

   V8_INLINE static Symbol* Cast(v8::Value* obj);
  private:
@@ -2022,9 +2033,18 @@
// Returns the print name string of the private symbol, or undefined if none.
   Local<Value> Name() const;

- // Create a private symbol. If data is not NULL, it will be the print name.
-  static Local<Private> New(Isolate *isolate,
-                            Local<String> name = Local<String>());
+ // Create a private symbol. If name is not empty, it will be the description.
+  static Local<Private> New(
+      Isolate *isolate, Local<String> name = Local<String>());
+
+  // Retrieve a global private symbol. If a symbol with this name has not
+  // been retrieved in the same isolate before, it is created.
+  // Note that private symbols created this way are never collected, so
+  // they should only be used for statically fixed properties.
+  // Also, there is only one global name space for the names used as keys.
+  // To minimize the potential for clashes, use qualified names as keys,
+  // e.g., "Class#property".
+  static Local<Private> ForApi(Isolate *isolate, Local<String> name);

  private:
   Private();
=======================================
--- /branches/bleeding_edge/src/api.cc  Mon Mar 24 15:36:15 2014 UTC
+++ /branches/bleeding_edge/src/api.cc  Mon Mar 24 16:34:06 2014 UTC
@@ -6120,25 +6120,55 @@
 }


-Local<Symbol> v8::Symbol::New(Isolate* isolate, const char* data, int length) {
+Local<Symbol> v8::Symbol::New(Isolate* isolate, Local<String> name) {
   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
   EnsureInitializedForIsolate(i_isolate, "v8::Symbol::New()");
   LOG_API(i_isolate, "Symbol::New()");
   ENTER_V8(i_isolate);
   i::Handle<i::Symbol> result = i_isolate->factory()->NewSymbol();
-  if (data != NULL) {
-    if (length == -1) length = i::StrLength(data);
-    i::Handle<i::String> name = i_isolate->factory()->NewStringFromUtf8(
-        i::Vector<const char>(data, length));
-    result->set_name(*name);
-  }
+  if (!name.IsEmpty()) result->set_name(*Utils::OpenHandle(*name));
   return Utils::ToLocal(result);
 }


-Local<Private> v8::Private::New(
-    Isolate* isolate, Local<String> name) {
+Local<Symbol> v8::Symbol::For(Isolate* isolate, Local<String> name) {
   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
+  i::Handle<i::String> i_name = Utils::OpenHandle(*name);
+  i::Handle<i::JSObject> registry = i_isolate->GetSymbolRegistry();
+  i::Handle<i::String> part = i_isolate->factory()->for_string();
+  i::Handle<i::JSObject> symbols =
+ i::Handle<i::JSObject>::cast(i::JSObject::GetProperty(registry, part));
+  i::Handle<i::Object> symbol = i::JSObject::GetProperty(symbols, i_name);
+  if (!symbol->IsSymbol()) {
+    ASSERT(symbol->IsUndefined());
+    symbol = i_isolate->factory()->NewSymbol();
+    i::Handle<i::Symbol>::cast(symbol)->set_name(*i_name);
+    i::JSObject::SetProperty(symbols, i_name, symbol, NONE, i::STRICT);
+  }
+  return Utils::ToLocal(i::Handle<i::Symbol>::cast(symbol));
+}
+
+
+Local<Symbol> v8::Symbol::ForApi(Isolate* isolate, Local<String> name) {
+  i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
+  i::Handle<i::String> i_name = Utils::OpenHandle(*name);
+  i::Handle<i::JSObject> registry = i_isolate->GetSymbolRegistry();
+  i::Handle<i::String> part = i_isolate->factory()->for_api_string();
+  i::Handle<i::JSObject> symbols =
+ i::Handle<i::JSObject>::cast(i::JSObject::GetProperty(registry, part));
+  i::Handle<i::Object> symbol = i::JSObject::GetProperty(symbols, i_name);
+  if (!symbol->IsSymbol()) {
+    ASSERT(symbol->IsUndefined());
+    symbol = i_isolate->factory()->NewSymbol();
+    i::Handle<i::Symbol>::cast(symbol)->set_name(*i_name);
+    i::JSObject::SetProperty(symbols, i_name, symbol, NONE, i::STRICT);
+  }
+  return Utils::ToLocal(i::Handle<i::Symbol>::cast(symbol));
+}
+
+
+Local<Private> v8::Private::New(Isolate* isolate, Local<String> name) {
+  i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
   EnsureInitializedForIsolate(i_isolate, "v8::Private::New()");
   LOG_API(i_isolate, "Private::New()");
   ENTER_V8(i_isolate);
@@ -6147,6 +6177,25 @@
   Local<Symbol> result = Utils::ToLocal(symbol);
   return v8::Handle<Private>(reinterpret_cast<Private*>(*result));
 }
+
+
+Local<Private> v8::Private::ForApi(Isolate* isolate, Local<String> name) {
+  i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
+  i::Handle<i::String> i_name = Utils::OpenHandle(*name);
+  i::Handle<i::JSObject> registry = i_isolate->GetSymbolRegistry();
+  i::Handle<i::String> part = i_isolate->factory()->private_api_string();
+  i::Handle<i::JSObject> privates =
+ i::Handle<i::JSObject>::cast(i::JSObject::GetProperty(registry, part));
+  i::Handle<i::Object> symbol = i::JSObject::GetProperty(privates, i_name);
+  if (!symbol->IsSymbol()) {
+    ASSERT(symbol->IsUndefined());
+    symbol = i_isolate->factory()->NewPrivateSymbol();
+    i::Handle<i::Symbol>::cast(symbol)->set_name(*i_name);
+    i::JSObject::SetProperty(privates, i_name, symbol, NONE, i::STRICT);
+  }
+ Local<Symbol> result = Utils::ToLocal(i::Handle<i::Symbol>::cast(symbol));
+  return v8::Handle<Private>(reinterpret_cast<Private*>(*result));
+}


 Local<Number> v8::Number::New(Isolate* isolate, double value) {
=======================================
--- /branches/bleeding_edge/src/array-iterator.js Wed Nov 13 10:34:06 2013 UTC +++ /branches/bleeding_edge/src/array-iterator.js Mon Mar 24 16:34:06 2014 UTC
@@ -36,9 +36,9 @@
 var ARRAY_ITERATOR_KIND_ENTRIES = 3;
 // The spec draft also has "sparse" but it is never used.

-var iteratorObjectSymbol = NEW_PRIVATE("iterator_object");
-var arrayIteratorNextIndexSymbol = NEW_PRIVATE("iterator_next");
-var arrayIterationKindSymbol = NEW_PRIVATE("iterator_kind");
+var arrayIteratorObjectSymbol = GLOBAL_PRIVATE("ArrayIterator#object");
+var arrayIteratorNextIndexSymbol = GLOBAL_PRIVATE("ArrayIterator#next");
+var arrayIterationKindSymbol = GLOBAL_PRIVATE("ArrayIterator#kind");

 function ArrayIterator() {}

@@ -46,7 +46,7 @@
 function CreateArrayIterator(array, kind) {
   var object = ToObject(array);
   var iterator = new ArrayIterator;
-  SET_PRIVATE(iterator, iteratorObjectSymbol, object);
+  SET_PRIVATE(iterator, arrayIteratorObjectSymbol, object);
   SET_PRIVATE(iterator, arrayIteratorNextIndexSymbol, 0);
   SET_PRIVATE(iterator, arrayIterationKindSymbol, kind);
   return iterator;
@@ -60,7 +60,7 @@
 // 15.4.5.2.2 ArrayIterator.prototype.next( )
 function ArrayIteratorNext() {
   var iterator = ToObject(this);
-  var array = GET_PRIVATE(iterator, iteratorObjectSymbol);
+  var array = GET_PRIVATE(iterator, arrayIteratorObjectSymbol);
   if (!array) {
     throw MakeTypeError('incompatible_method_receiver',
                         ['Array Iterator.prototype.next']);
=======================================
--- /branches/bleeding_edge/src/heap.cc Mon Mar 24 15:36:15 2014 UTC
+++ /branches/bleeding_edge/src/heap.cc Mon Mar 24 16:34:06 2014 UTC
@@ -3288,13 +3288,8 @@
   }
   set_undefined_cell(Cell::cast(obj));

-  // Allocate objects to hold symbol registry.
- { MaybeObject* maybe_obj = AllocateMap(JS_OBJECT_TYPE, JSObject::kHeaderSize);
-    if (!maybe_obj->ToObject(&obj)) return false;
-    maybe_obj = AllocateJSObjectFromMap(Map::cast(obj));
-    if (!maybe_obj->ToObject(&obj)) return false;
-  }
-  set_symbol_registry(JSObject::cast(obj));
+  // The symbol registry is initialized lazily.
+  set_symbol_registry(undefined_value());

   // Allocate object to hold object observation state.
{ MaybeObject* maybe_obj = AllocateMap(JS_OBJECT_TYPE, JSObject::kHeaderSize);
=======================================
--- /branches/bleeding_edge/src/heap.h  Thu Mar 20 16:13:09 2014 UTC
+++ /branches/bleeding_edge/src/heap.h  Mon Mar 24 16:34:06 2014 UTC
@@ -190,7 +190,7 @@
V(Cell, undefined_cell, UndefineCell) \ V(JSObject, observation_state, ObservationState) \ V(Map, external_map, ExternalMap) \ - V(JSObject, symbol_registry, SymbolRegistry) \ + V(Object, symbol_registry, SymbolRegistry) \ V(Symbol, frozen_symbol, FrozenSymbol) \ V(Symbol, nonexistent_symbol, NonExistentSymbol) \ V(Symbol, elements_transition_symbol, ElementsTransitionSymbol) \
@@ -306,6 +306,11 @@
   V(String_string, "String")                                             \
   V(symbol_string, "symbol")                                             \
   V(Symbol_string, "Symbol")                                             \
+  V(for_string, "for")                                                   \
+  V(for_api_string, "for_api")                                           \
+  V(for_intern_string, "for_intern")                                     \
+  V(private_api_string, "private_api")                                   \
+  V(private_intern_string, "private_intern")                             \
   V(Date_string, "Date")                                                 \
   V(this_string, "this")                                                 \
   V(to_string_string, "toString")                                        \
=======================================
--- /branches/bleeding_edge/src/isolate.cc      Mon Mar 24 10:07:15 2014 UTC
+++ /branches/bleeding_edge/src/isolate.cc      Mon Mar 24 16:34:06 2014 UTC
@@ -2296,4 +2296,25 @@
 #undef ISOLATE_FIELD_OFFSET
 #endif

+
+Handle<JSObject> Isolate::GetSymbolRegistry() {
+  if (heap()->symbol_registry()->IsUndefined()) {
+ Handle<Map> map = factory()->NewMap(JS_OBJECT_TYPE, JSObject::kHeaderSize);
+    Handle<JSObject> registry = factory()->NewJSObjectFromMap(map);
+    heap()->set_symbol_registry(*registry);
+
+    static const char* nested[] = {
+      "for", "for_api", "for_intern", "keyFor", "private_api", "private_intern"
+    };
+    for (unsigned i = 0; i < ARRAY_SIZE(nested); ++i) {
+      Handle<String> name = factory()->InternalizeUtf8String(nested[i]);
+      Handle<JSObject> obj = factory()->NewJSObjectFromMap(map);
+      JSObject::NormalizeProperties(obj, KEEP_INOBJECT_PROPERTIES, 8);
+      JSObject::SetProperty(registry, name, obj, NONE, STRICT);
+    }
+  }
+  return Handle<JSObject>::cast(factory()->symbol_registry());
+}
+
+
 } }  // namespace v8::internal
=======================================
--- /branches/bleeding_edge/src/isolate.h       Mon Mar 24 10:07:15 2014 UTC
+++ /branches/bleeding_edge/src/isolate.h       Mon Mar 24 16:34:06 2014 UTC
@@ -1115,6 +1115,9 @@
     }
     return id;
   }
+
+  // Get (and lazily initialize) the registry for per-isolate symbols.
+  Handle<JSObject> GetSymbolRegistry();

  private:
   Isolate();
=======================================
--- /branches/bleeding_edge/src/macros.py       Wed Jan 22 12:15:57 2014 UTC
+++ /branches/bleeding_edge/src/macros.py       Mon Mar 24 16:34:06 2014 UTC
@@ -162,6 +162,7 @@
macro JSON_NUMBER_TO_STRING(arg) = ((%_IsSmi(%IS_VAR(arg)) || arg - arg == 0) ? %_NumberToString(arg) : "null");

 # Private names.
+macro GLOBAL_PRIVATE(name) = (%CreateGlobalPrivateSymbol(name));
 macro NEW_PRIVATE(name) = (%CreatePrivateSymbol(name));
 macro IS_PRIVATE(sym) = (%SymbolIsPrivate(sym));
 macro HAS_PRIVATE(obj, sym) = (sym in obj);
=======================================
--- /branches/bleeding_edge/src/messages.js     Thu Mar 20 16:13:09 2014 UTC
+++ /branches/bleeding_edge/src/messages.js     Mon Mar 24 16:34:06 2014 UTC
@@ -788,11 +788,10 @@
// ----------------------------------------------------------------------------
 // Error implementation

-//TODO(rossberg)
-var CallSiteReceiverKey = NEW_PRIVATE("receiver");
-var CallSiteFunctionKey = NEW_PRIVATE("function");
-var CallSitePositionKey = NEW_PRIVATE("position");
-var CallSiteStrictModeKey = NEW_PRIVATE("strict mode");
+var CallSiteReceiverKey = NEW_PRIVATE("CallSite#receiver");
+var CallSiteFunctionKey = NEW_PRIVATE("CallSite#function");
+var CallSitePositionKey = NEW_PRIVATE("CallSite#position");
+var CallSiteStrictModeKey = NEW_PRIVATE("CallSite#strict_mode");

 function CallSite(receiver, fun, pos, strict_mode) {
   SET_PRIVATE(this, CallSiteReceiverKey, receiver);
=======================================
--- /branches/bleeding_edge/src/promise.js      Wed Mar 19 21:48:30 2014 UTC
+++ /branches/bleeding_edge/src/promise.js      Mon Mar 24 16:34:06 2014 UTC
@@ -42,11 +42,11 @@
 // Core functionality.

 // Status values: 0 = pending, +1 = resolved, -1 = rejected
-var promiseStatus = NEW_PRIVATE("Promise#status");
-var promiseValue = NEW_PRIVATE("Promise#value");
-var promiseOnResolve = NEW_PRIVATE("Promise#onResolve");
-var promiseOnReject = NEW_PRIVATE("Promise#onReject");
-var promiseRaw = NEW_PRIVATE("Promise#raw");
+var promiseStatus = GLOBAL_PRIVATE("Promise#status");
+var promiseValue = GLOBAL_PRIVATE("Promise#value");
+var promiseOnResolve = GLOBAL_PRIVATE("Promise#onResolve");
+var promiseOnReject = GLOBAL_PRIVATE("Promise#onReject");
+var promiseRaw = GLOBAL_PRIVATE("Promise#raw");

 function IsPromise(x) {
   return IS_SPEC_OBJECT(x) && %HasLocalProperty(x, promiseStatus);
=======================================
--- /branches/bleeding_edge/src/runtime.cc      Mon Mar 24 15:36:15 2014 UTC
+++ /branches/bleeding_edge/src/runtime.cc      Mon Mar 24 16:34:06 2014 UTC
@@ -619,6 +619,25 @@
   if (name->IsString()) symbol->set_name(*name);
   return symbol;
 }
+
+
+RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateGlobalPrivateSymbol) {
+  HandleScope scope(isolate);
+  ASSERT(args.length() == 1);
+  CONVERT_ARG_HANDLE_CHECKED(String, name, 0);
+  Handle<JSObject> registry = isolate->GetSymbolRegistry();
+  Handle<String> part = isolate->factory()->private_intern_string();
+  Handle<JSObject> privates =
+      Handle<JSObject>::cast(JSObject::GetProperty(registry, part));
+  Handle<Object> symbol = JSObject::GetProperty(privates, name);
+  if (!symbol->IsSymbol()) {
+    ASSERT(symbol->IsUndefined());
+    symbol = isolate->factory()->NewPrivateSymbol();
+    Handle<Symbol>::cast(symbol)->set_name(*name);
+    JSObject::SetProperty(privates, name, symbol, NONE, STRICT);
+  }
+  return *symbol;
+}


 RUNTIME_FUNCTION(MaybeObject*, Runtime_NewSymbolWrapper) {
@@ -637,9 +656,9 @@


 RUNTIME_FUNCTION(MaybeObject*, Runtime_SymbolRegistry) {
-  SealHandleScope shs(isolate);
+  HandleScope scope(isolate);
   ASSERT(args.length() == 0);
-  return isolate->heap()->symbol_registry();
+  return *isolate->GetSymbolRegistry();
 }


=======================================
--- /branches/bleeding_edge/src/runtime.h       Mon Mar 24 08:22:24 2014 UTC
+++ /branches/bleeding_edge/src/runtime.h       Mon Mar 24 16:34:06 2014 UTC
@@ -311,6 +311,7 @@
   /* Harmony symbols */ \
   F(CreateSymbol, 1, 1) \
   F(CreatePrivateSymbol, 1, 1) \
+  F(CreateGlobalPrivateSymbol, 1, 1) \
   F(NewSymbolWrapper, 1, 1) \
   F(SymbolDescription, 1, 1) \
   F(SymbolRegistry, 0, 1) \
=======================================
--- /branches/bleeding_edge/src/symbol.js       Mon Mar 24 15:45:52 2014 UTC
+++ /branches/bleeding_edge/src/symbol.js       Mon Mar 24 16:34:06 2014 UTC
@@ -61,31 +61,20 @@
   }
   return %_ValueOf(this);
 }
-
-
-function GetSymbolRegistry() {
-  var registry = %SymbolRegistry();
-  if (IS_UNDEFINED(registry.internal)) {
-    registry.internal = {__proto__: null};
-    registry.for = {__proto__: null};
-    registry.keyFor = {__proto__: null};
-  }
-  return registry;
-}


 function InternalSymbol(key) {
-  var registry = GetSymbolRegistry();
-  if (IS_UNDEFINED(registry.internal[key])) {
-    registry.internal[key] = %CreateSymbol(key);
+  var internal_registry = %SymbolRegistry().for_intern;
+  if (IS_UNDEFINED(internal_registry[key])) {
+    internal_registry[key] = %CreateSymbol(key);
   }
-  return registry.internal[key];
+  return internal_registry[key];
 }


 function SymbolFor(key) {
   key = TO_STRING_INLINE(key);
-  var registry = GetSymbolRegistry();
+  var registry = %SymbolRegistry();
   if (IS_UNDEFINED(registry.for[key])) {
     var symbol = %CreateSymbol(key);
     registry.for[key] = symbol;
@@ -96,10 +85,8 @@


 function SymbolKeyFor(symbol) {
-  if (!IS_SYMBOL(symbol)) {
-    throw MakeTypeError("not_a_symbol", [symbol]);
-  }
-  return GetSymbolRegistry().keyFor[symbol];
+  if (!IS_SYMBOL(symbol)) throw MakeTypeError("not_a_symbol", [symbol]);
+  return %SymbolRegistry().keyFor[symbol];
 }


=======================================
--- /branches/bleeding_edge/test/cctest/test-api.cc Mon Mar 24 10:07:15 2014 UTC +++ /branches/bleeding_edge/test/cctest/test-api.cc Mon Mar 24 16:34:06 2014 UTC
@@ -2757,7 +2757,8 @@

   v8::Local<v8::Object> obj = v8::Object::New(isolate);
   v8::Local<v8::Symbol> sym1 = v8::Symbol::New(isolate);
-  v8::Local<v8::Symbol> sym2 = v8::Symbol::New(isolate, "my-symbol");
+  v8::Local<v8::Symbol> sym2 =
+      v8::Symbol::New(isolate, v8_str("my-symbol"));

   CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);

@@ -2775,7 +2776,7 @@
   CHECK(!sym1->StrictEquals(sym2));
   CHECK(!sym2->StrictEquals(sym1));

- CHECK(sym2->Name()->Equals(v8::String::NewFromUtf8(isolate, "my-symbol")));
+  CHECK(sym2->Name()->Equals(v8_str("my-symbol")));

   v8::Local<v8::Value> sym_val = sym2;
   CHECK(sym_val->IsSymbol());
@@ -2845,8 +2846,8 @@

   v8::Local<v8::Object> obj = v8::Object::New(isolate);
   v8::Local<v8::Private> priv1 = v8::Private::New(isolate);
-  v8::Local<v8::Private> priv2 = v8::Private::New(isolate,
-                                                  v8_str("my-private"));
+  v8::Local<v8::Private> priv2 =
+      v8::Private::New(isolate, v8_str("my-private"));

   CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);

@@ -2895,6 +2896,55 @@
   CHECK_EQ(2002, child->GetPrivate(priv1)->Int32Value());
   CHECK_EQ(0, child->GetOwnPropertyNames()->Length());
 }
+
+
+THREADED_TEST(GlobalSymbols) {
+  i::FLAG_harmony_symbols = true;
+
+  LocalContext env;
+  v8::Isolate* isolate = env->GetIsolate();
+  v8::HandleScope scope(isolate);
+
+  v8::Local<String> name = v8_str("my-symbol");
+  v8::Local<v8::Symbol> glob = v8::Symbol::For(isolate, name);
+  v8::Local<v8::Symbol> glob2 = v8::Symbol::For(isolate, name);
+  CHECK(glob2->SameValue(glob));
+
+  v8::Local<v8::Symbol> glob_api = v8::Symbol::ForApi(isolate, name);
+  v8::Local<v8::Symbol> glob_api2 = v8::Symbol::ForApi(isolate, name);
+  CHECK(glob_api2->SameValue(glob_api));
+  CHECK(!glob_api->SameValue(glob));
+
+  v8::Local<v8::Symbol> sym = v8::Symbol::New(isolate, name);
+  CHECK(!sym->SameValue(glob));
+
+  CompileRun("var sym2 = Symbol.for('my-symbol')");
+  v8::Local<Value> sym2 = env->Global()->Get(v8_str("sym2"));
+  CHECK(sym2->SameValue(glob));
+  CHECK(!sym2->SameValue(glob_api));
+}
+
+
+THREADED_TEST(GlobalPrivates) {
+  LocalContext env;
+  v8::Isolate* isolate = env->GetIsolate();
+  v8::HandleScope scope(isolate);
+
+  v8::Local<String> name = v8_str("my-private");
+  v8::Local<v8::Private> glob = v8::Private::ForApi(isolate, name);
+  v8::Local<v8::Object> obj = v8::Object::New(isolate);
+  CHECK(obj->SetPrivate(glob, v8::Integer::New(isolate, 3)));
+
+  v8::Local<v8::Private> glob2 = v8::Private::ForApi(isolate, name);
+  CHECK(obj->HasPrivate(glob2));
+
+  v8::Local<v8::Private> priv = v8::Private::New(isolate, name);
+  CHECK(!obj->HasPrivate(priv));
+
+  CompileRun("var intern = %CreateGlobalPrivateSymbol('my-private')");
+  v8::Local<Value> intern = env->Global()->Get(v8_str("intern"));
+  CHECK(!obj->Has(intern));
+}


 class ScopedArrayBufferContents {
@@ -10189,10 +10239,11 @@
   Local<v8::Object> o2 = t2->GetFunction()->NewInstance();
   CHECK(o2->SetPrototype(o1));

-  v8::Local<v8::Symbol> sym = v8::Symbol::New(context->GetIsolate(), "s1");
+  v8::Local<v8::Symbol> sym =
+      v8::Symbol::New(context->GetIsolate(), v8_str("s1"));
   o1->Set(sym, v8_num(3));
-  o1->SetHiddenValue(v8_str("h1"),
-                     v8::Integer::New(context->GetIsolate(), 2013));
+  o1->SetHiddenValue(
+      v8_str("h1"), v8::Integer::New(context->GetIsolate(), 2013));

   // Call the runtime version of GetLocalPropertyNames() on
   // the natively created object through JavaScript.

--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
--- You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/d/optout.

Reply via email to