From 8394975ec7da4b7887c042d750b86e5a8584195f Mon Sep 17 00:00:00 2001 From: "rossberg@chromium.org" Date: Tue, 19 Aug 2014 12:08:46 +0000 Subject: [PATCH] Expose well-known Symbols to C++ API. BUG=341423 LOG=Y R=arv@chromium.org, dcarney@chromium.org, rossberg@chromium.org Review URL: https://codereview.chromium.org/483173002 Patch from Yutaka Hirano . git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@23196 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- include/v8.h | 5 ++++ src/api.cc | 60 +++++++++++++++++++++++++---------------- src/heap/heap.h | 1 + test/cctest/test-api.cc | 23 ++++++++++++++++ 4 files changed, 66 insertions(+), 23 deletions(-) diff --git a/include/v8.h b/include/v8.h index ac3c6173ec..e01da1e23f 100644 --- a/include/v8.h +++ b/include/v8.h @@ -1960,7 +1960,12 @@ class V8_EXPORT Symbol : public Primitive { // registry that is not accessible by (and cannot clash with) JavaScript code. static Local ForApi(Isolate *isolate, Local name); + // Well-known symbols + static Local GetIterator(Isolate* isolate); + static Local GetUnscopables(Isolate* isolate); + V8_INLINE static Symbol* Cast(v8::Value* obj); + private: Symbol(); static void CheckCast(v8::Value* obj); diff --git a/src/api.cc b/src/api.cc index 9093f4dd30..35a7e5f438 100644 --- a/src/api.cc +++ b/src/api.cc @@ -6152,43 +6152,57 @@ Local v8::Symbol::New(Isolate* isolate, Local name) { } -Local v8::Symbol::For(Isolate* isolate, Local name) { - i::Isolate* i_isolate = reinterpret_cast(isolate); - i::Handle i_name = Utils::OpenHandle(*name); - i::Handle registry = i_isolate->GetSymbolRegistry(); - i::Handle part = i_isolate->factory()->for_string(); +static i::Handle SymbolFor(i::Isolate* isolate, + i::Handle name, + i::Handle part) { + i::Handle registry = isolate->GetSymbolRegistry(); i::Handle symbols = i::Handle::cast( i::Object::GetPropertyOrElement(registry, part).ToHandleChecked()); i::Handle symbol = - i::Object::GetPropertyOrElement(symbols, i_name).ToHandleChecked(); + i::Object::GetPropertyOrElement(symbols, name).ToHandleChecked(); if (!symbol->IsSymbol()) { DCHECK(symbol->IsUndefined()); - symbol = i_isolate->factory()->NewSymbol(); - i::Handle::cast(symbol)->set_name(*i_name); - i::JSObject::SetProperty(symbols, i_name, symbol, i::STRICT).Assert(); + symbol = isolate->factory()->NewSymbol(); + i::Handle::cast(symbol)->set_name(*name); + i::JSObject::SetProperty(symbols, name, symbol, i::STRICT).Assert(); } - return Utils::ToLocal(i::Handle::cast(symbol)); + return i::Handle::cast(symbol); +} + + +Local v8::Symbol::For(Isolate* isolate, Local name) { + i::Isolate* i_isolate = reinterpret_cast(isolate); + i::Handle i_name = Utils::OpenHandle(*name); + i::Handle part = i_isolate->factory()->for_string(); + return Utils::ToLocal(SymbolFor(i_isolate, i_name, part)); } Local v8::Symbol::ForApi(Isolate* isolate, Local name) { i::Isolate* i_isolate = reinterpret_cast(isolate); i::Handle i_name = Utils::OpenHandle(*name); - i::Handle registry = i_isolate->GetSymbolRegistry(); i::Handle part = i_isolate->factory()->for_api_string(); - i::Handle symbols = - i::Handle::cast( - i::Object::GetPropertyOrElement(registry, part).ToHandleChecked()); - i::Handle symbol = - i::Object::GetPropertyOrElement(symbols, i_name).ToHandleChecked(); - if (!symbol->IsSymbol()) { - DCHECK(symbol->IsUndefined()); - symbol = i_isolate->factory()->NewSymbol(); - i::Handle::cast(symbol)->set_name(*i_name); - i::JSObject::SetProperty(symbols, i_name, symbol, i::STRICT).Assert(); - } - return Utils::ToLocal(i::Handle::cast(symbol)); + return Utils::ToLocal(SymbolFor(i_isolate, i_name, part)); +} + + +static Local GetWellKnownSymbol(Isolate* isolate, const char* name) { + i::Isolate* i_isolate = reinterpret_cast(isolate); + i::Handle i_name = + Utils::OpenHandle(*String::NewFromUtf8(isolate, name)); + i::Handle part = i_isolate->factory()->for_intern_string(); + return Utils::ToLocal(SymbolFor(i_isolate, i_name, part)); +} + + +Local v8::Symbol::GetIterator(Isolate* isolate) { + return GetWellKnownSymbol(isolate, "Symbol.iterator"); +} + + +Local v8::Symbol::GetUnscopables(Isolate* isolate) { + return GetWellKnownSymbol(isolate, "Symbol.unscopables"); } diff --git a/src/heap/heap.h b/src/heap/heap.h index d9d9d1a194..093660a768 100644 --- a/src/heap/heap.h +++ b/src/heap/heap.h @@ -294,6 +294,7 @@ namespace internal { 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") \ diff --git a/test/cctest/test-api.cc b/test/cctest/test-api.cc index f61400706b..a13a6e5f29 100644 --- a/test/cctest/test-api.cc +++ b/test/cctest/test-api.cc @@ -2924,6 +2924,29 @@ THREADED_TEST(GlobalSymbols) { } +static void CheckWellKnownSymbol(v8::Local(*getter)(v8::Isolate*), + const char* name) { + LocalContext env; + v8::Isolate* isolate = env->GetIsolate(); + v8::HandleScope scope(isolate); + + v8::Local symbol = getter(isolate); + std::string script = std::string("var sym = ") + name; + CompileRun(script.c_str()); + v8::Local value = env->Global()->Get(v8_str("sym")); + + CHECK(!value.IsEmpty()); + CHECK(!symbol.IsEmpty()); + CHECK(value->SameValue(symbol)); +} + + +THREADED_TEST(WellKnownSymbols) { + CheckWellKnownSymbol(v8::Symbol::GetIterator, "Symbol.iterator"); + CheckWellKnownSymbol(v8::Symbol::GetUnscopables, "Symbol.unscopables"); +} + + THREADED_TEST(GlobalPrivates) { LocalContext env; v8::Isolate* isolate = env->GetIsolate();