📄 test-decls.cc.svn-base
字号:
// Copyright 2007-2008 the V8 project authors. All rights reserved.// Redistribution and use in source and binary forms, with or without// modification, are permitted provided that the following conditions are// met://// * Redistributions of source code must retain the above copyright// notice, this list of conditions and the following disclaimer.// * Redistributions in binary form must reproduce the above// copyright notice, this list of conditions and the following// disclaimer in the documentation and/or other materials provided// with the distribution.// * Neither the name of Google Inc. nor the names of its// contributors may be used to endorse or promote products derived// from this software without specific prior written permission.//// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.#include <stdlib.h>#include "v8.h"#include "heap.h"#include "cctest.h"using namespace v8;enum Expectations { EXPECT_RESULT, EXPECT_EXCEPTION};// A DeclarationContext holds a reference to a v8::Context and keeps// track of various declaration related counters to make it easier to// track if global declarations in the presence of interceptors behave// the right way.class DeclarationContext { public: DeclarationContext(); virtual ~DeclarationContext() { if (is_initialized_) { context_->Exit(); context_.Dispose(); } } void Check(const char* source, int get, int set, int has, Expectations expectations, v8::Handle<Value> value = Local<Value>()); int get_count() const { return get_count_; } int set_count() const { return set_count_; } int has_count() const { return has_count_; } protected: virtual v8::Handle<Value> Get(Local<String> key); virtual v8::Handle<Value> Set(Local<String> key, Local<Value> value); virtual v8::Handle<Boolean> Has(Local<String> key); void InitializeIfNeeded(); // Get the holder for the interceptor. Default to the instance template // but may be overwritten. virtual Local<ObjectTemplate> GetHolder(Local<FunctionTemplate> function) { return function->InstanceTemplate(); } // The handlers are called as static functions that forward // to the instance specific virtual methods. static v8::Handle<Value> HandleGet(Local<String> key, const AccessorInfo& info); static v8::Handle<Value> HandleSet(Local<String> key, Local<Value> value, const AccessorInfo& info); static v8::Handle<Boolean> HandleHas(Local<String> key, const AccessorInfo& info); private: bool is_initialized_; Persistent<Context> context_; Local<String> property_; int get_count_; int set_count_; int has_count_; static DeclarationContext* GetInstance(const AccessorInfo& info);};DeclarationContext::DeclarationContext() : is_initialized_(false), get_count_(0), set_count_(0), has_count_(0) { // Do nothing.}void DeclarationContext::InitializeIfNeeded() { if (is_initialized_) return; HandleScope scope; Local<FunctionTemplate> function = FunctionTemplate::New(); Local<Value> data = Integer::New(reinterpret_cast<intptr_t>(this)); GetHolder(function)->SetNamedPropertyHandler(&HandleGet, &HandleSet, &HandleHas, 0, 0, data); context_ = Context::New(0, function->InstanceTemplate(), Local<Value>()); context_->Enter(); is_initialized_ = true;}void DeclarationContext::Check(const char* source, int get, int set, int has, Expectations expectations, v8::Handle<Value> value) { InitializeIfNeeded(); // A retry after a GC may pollute the counts, so perform gc now // to avoid that. v8::internal::Heap::CollectGarbage(0, v8::internal::NEW_SPACE); HandleScope scope; TryCatch catcher; catcher.SetVerbose(true); Local<Value> result = Script::Compile(String::New(source))->Run(); CHECK_EQ(get, get_count()); CHECK_EQ(set, set_count()); CHECK_EQ(has, has_count()); if (expectations == EXPECT_RESULT) { CHECK(!catcher.HasCaught()); if (!value.IsEmpty()) { CHECK_EQ(value, result); } } else { CHECK(expectations == EXPECT_EXCEPTION); CHECK(catcher.HasCaught()); if (!value.IsEmpty()) { CHECK_EQ(value, catcher.Exception()); } }}v8::Handle<Value> DeclarationContext::HandleGet(Local<String> key, const AccessorInfo& info) { DeclarationContext* context = GetInstance(info); context->get_count_++; return context->Get(key);}v8::Handle<Value> DeclarationContext::HandleSet(Local<String> key, Local<Value> value, const AccessorInfo& info) { DeclarationContext* context = GetInstance(info); context->set_count_++; return context->Set(key, value);}v8::Handle<Boolean> DeclarationContext::HandleHas(Local<String> key, const AccessorInfo& info) { DeclarationContext* context = GetInstance(info); context->has_count_++; return context->Has(key);}DeclarationContext* DeclarationContext::GetInstance(const AccessorInfo& info) { Local<Value> data = info.Data(); return reinterpret_cast<DeclarationContext*>(Int32::Cast(*data)->Value());}v8::Handle<Value> DeclarationContext::Get(Local<String> key) { return v8::Handle<Value>();}v8::Handle<Value> DeclarationContext::Set(Local<String> key, Local<Value> value) { return v8::Handle<Value>();}v8::Handle<Boolean> DeclarationContext::Has(Local<String> key) { return v8::Handle<Boolean>();}// Test global declaration of a property the interceptor doesn't know// about and doesn't handle.TEST(Unknown) { HandleScope scope; { DeclarationContext context; context.Check("var x; x", 1, // access 1, // declaration 2, // declaration + initialization EXPECT_RESULT, Undefined()); } { DeclarationContext context; context.Check("var x = 0; x", 1, // access 2, // declaration + initialization 2, // declaration + initialization EXPECT_RESULT, Number::New(0)); } { DeclarationContext context; context.Check("function x() { }; x", 1, // access 1, // declaration 0, EXPECT_RESULT); } { DeclarationContext context; context.Check("const x; x", 1, // access 2, // declaration + initialization 2, // declaration + initialization EXPECT_RESULT, Undefined()); } { DeclarationContext context; context.Check("const x = 0; x", 1, // access 2, // declaration + initialization 2, // declaration + initialization EXPECT_RESULT, Undefined()); // SB 0 - BUG 1213579 }}class PresentPropertyContext: public DeclarationContext { protected: virtual v8::Handle<Boolean> Has(Local<String> key) { return True(); }};TEST(Present) { HandleScope scope; { PresentPropertyContext context; context.Check("var x; x", 1, // access 0, 2, // declaration + initialization EXPECT_EXCEPTION); // x is not defined! } { PresentPropertyContext context; context.Check("var x = 0; x", 1, // access 1, // initialization 2, // declaration + initialization EXPECT_RESULT, Number::New(0)); } { PresentPropertyContext context; context.Check("function x() { }; x", 1, // access 1, // declaration 0, EXPECT_RESULT); } { PresentPropertyContext context; context.Check("const x; x", 0, 0, 1, // (re-)declaration EXPECT_EXCEPTION); // x has already been declared! } { PresentPropertyContext context; context.Check("const x = 0; x", 0, 0,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -