2021SC@SDUSC
Scope.h
#pragma once
#include <string>
#include <unordered_map>
#include "base/unicode_string_view.h"
#include "core/base/common.h"
#include "core/base/task.h"
#include "core/base/uri_loader.h"
#include "core/engine.h"
#include "core/napi/js_native_api.h"
#include "core/napi/js_native_api_types.h"
#include "core/task/worker_task_runner.h"
class JavaScriptTaskRunner;
class ModuleBase;
class Scope;
class ScopeWrapper {
public:
explicit ScopeWrapper(std::shared_ptr<Scope> scope) : scope_(scope) {}
public:
std::weak_ptr<Scope> scope_;
};
class Scope {
public:
using unicode_string_view = tdf::base::unicode_string_view;
using RegisterMap = hippy::base::RegisterMap;
using CtxValue = hippy::napi::CtxValue;
using Ctx = hippy::napi::Ctx;
using UriLoader = hippy::base::UriLoader;
using FunctionData = hippy::napi::FunctionData;
using BindingData = hippy::napi::BindingData;
using Encoding = hippy::napi::Encoding;
Scope(Engine* engine,
std::string name,
std::unique_ptr<RegisterMap> map);
~Scope();
void WillExit();
inline std::shared_ptr<Ctx> GetContext() { return context_; }
inline std::unique_ptr<RegisterMap>& GetRegisterMap() { return map_; }
ModuleBase* GetModuleClass(const unicode_string_view& moduleName);
void AddModuleClass(const unicode_string_view& name,
std::unique_ptr<ModuleBase> module);
std::shared_ptr<CtxValue> GetModuleValue(
const unicode_string_view& moduleName);
void AddModuleValue(const unicode_string_view& name,
const std::shared_ptr<CtxValue>& value);
void SaveFunctionData(std::unique_ptr<FunctionData> data);
inline void SaveBindingData(std::unique_ptr<BindingData> data) {
binding_data_ = std::move(data);
}
inline const std::unique_ptr<BindingData>& GetBindingData() {
return binding_data_;
}
void RunJS(const unicode_string_view& js,
const unicode_string_view& name,
bool is_copy = true);
std::shared_ptr<CtxValue> RunJSSync(const unicode_string_view& data,
const unicode_string_view& name,
bool is_copy = true);
inline std::shared_ptr<JavaScriptTaskRunner> GetTaskRunner() {
return engine_->GetJSRunner();
}
inline std::shared_ptr<WorkerTaskRunner> GetWorkerTaskRunner() {
return engine_->GetWorkerTaskRunner();
}
inline void AddTask(std::unique_ptr<hippy::base::Task> task) {
std::shared_ptr<JavaScriptTaskRunner> runner = engine_->GetJSRunner();
if (runner) {
runner->PostTask(std::move(task));
}
}
inline void SetUriLoader(std::shared_ptr<UriLoader> loader) {
loader_ = loader;
}
inline std::shared_ptr<UriLoader> GetUriLoader() { return loader_; }
private:
friend class Engine;
void Initialized();
private:
Engine* engine_;
std::shared_ptr<Ctx> context_;
std::string name_;
std::unique_ptr<RegisterMap> map_;
std::unordered_map<unicode_string_view, std::shared_ptr<CtxValue>>
module_value_map_;
std::unordered_map<unicode_string_view, std::unique_ptr<ModuleBase>>
module_class_map_;
std::vector<std::unique_ptr<FunctionData>> function_data_;
std::unique_ptr<BindingData> binding_data_;
std::unique_ptr<ScopeWrapper> wrapper_;
std::shared_ptr<UriLoader> loader_;
};
C++类的scope简析:
首先来说说 名字的域 (或者说是C++语言里面的那些名字标识符的可见范围)
在程序的任意代码位置上,每一个被使用到的名字或者标识符指代一个实体,比如变量名,函数名,类型名等等。然而 同一个名字可以被重复使用用来指代不同代码作用域里的不同实体。
域指的是程序的某部分,在程序的这个部分里面,一个名字有它的特定含义。在C++里,不同的域是通过 用 { } 这个 括号来隔开的。
同一个名字可以指代在不同域里面的名字。那么名字的可见范围是从它的声明开始到 声明这个名字的域的结束位置为止。
每一个类拥有它自己的一个新scope。如果在类的scope 范围外,通常的数据成员或者函数成员可以通过 使用成员访问操作符作用在该类的 对象,引用,或者指针上来达到访问的目的。当要访问类的类型成员,可以使用域操作符。 不管使用哪种操作符,跟在操作符后面的那个名字一样的标识符必须是该类的成员。 比如如下:
Screen::pos ht = 24, wd = 80; // use the pos type defined by Screen
Screen scr(ht, wd, ' ')
Screen *p = &scr;
char c = scr.get(); // fetches the get member from the object scr
c = p->get(); // fetches the get member from the object to which p points
正因为每一个类定义一个它自己全新的域,所以在类的定义(或者说作用域之外)如果想要定义该类的一个成员函数,必须要加上类名和函数名字,因为在类的域外,成员的名字是被隐藏了的。
只要类名被编译器识别到了,剩下的定义--包括参数列表和函数体--都在类的作用域里面。因此可以不需要类名就可以引用其他的类成员。
class Window_mgr
{
public:
using ScreenIndex = std::vector<Screen>::size_type;
void clear(ScreenIndex);
private:
std::vector<Screen> screens{Screen(24, 80, ' ')};
};
void Window_mgr::clear(ScreenIndex i)
{
Screen &s = screens[i];
s.contents = string(s.height * s.width, ' ');
}
像上面的clear 成员函数用到了Window_mgr域内定义的类型 ScreenIndex, 因为编译器是在知道了当前处于 Window_mgr 类域里面后才发现clear 成员函数的参数列表的,因此不需要多此一举说明 要使有 Window_mgr类里面定义的 ScreenIndex 类型。同理 screens 的使用也是同一个道理。
然而,由于成员函数的返回类型是出现在成员函数名的前面的,所以当成员函数是在类外面定义的时候,任何的返回值类型同样也是在类之外的域。 这样的话,返回值类型必须要声明该类型是哪个域的。
class Window_mgr
{
public:
ScreenIndex addScreen(const Screen&);
};
Window_mgr::ScreenIndex Window_mgr::addScreen(const Screen &s)
{
}
从上面的addScreen 函数的例子可以看到,由于返回值类型出现在类名之前,那么就不再 该类的作用域里,所以为了使用该类定义的类型,就必须加上 Window_mgr 用来指代使用的是该类的自定义类型。