lol转区什么时候开始iOS11区

写给小白的JavaScript引擎指南
字体:[ ] 类型:转载 时间:
有时编写 Web 应用的代码会感觉充满魔力,因为我们只是写了一系列字符,就能在浏览器里看到效果了。但是理解魔法背后的技术,可以帮助你更好地提高编程技巧
关于本文标题,我并不认为参与写或者读本文的人是白痴。但是有时某个话题会让你觉得自己就像个白痴一样,而 JavaScript 引擎就是这些话题之一,至少对于我来说是这样。
有时编写 Web 应用的代码会感觉充满魔力,因为我们只是写了一系列字符,就能在浏览器里看到效果了。但是理解魔法背后的技术,可以帮助你更好地提高编程技巧。至少当你试图解释在 JavaScript 驱动的 web 或移动应用的幕后发生了什么的时候,会觉得自己不那么白痴了。
很多年前,那是我还是个研究生讲师,向一个教授抱怨还没有掌握那些特别难懂的法语语法点,可以教给我的本科学生。我记得当时她说的话:“有时候,学习某个事物的唯一方式就是教授它。”
尝试向工程师解释 NativeScript 是如何通过 JavaScript 引擎在幕后工作、在运行时连接调用原生的 APIs——面对这样一件复杂的工作很容易在一片杂草中迷失方向。事实上,任何 JavaScript 开发者都应该对我们每天使用的这门技术基础的引擎感到好奇。现在我们一起来仔细分析下 JavaScript 引擎到底做了什么,为什么不同的平台使用不同引擎,多年来它们是如何发展的,以及作为开发者我们为什么要关注这些。
首先,一些专业术语
“JavaScript 引擎”通常被称作一种 虚拟机。“虚拟机”是指软件驱动的给定的计算机系统的模拟器。有很多类型的虚拟机,它们根据自己在多大程度上精确地模拟或代替真实的物理机器来分类。
例如,“系统虚拟机”提供了一个可以运行操作系统的完整仿真平台。Mac 用户很熟悉的 Parallels 就是一个允许你在 Mac 上运行 Windows系统虚拟机。
另一方面,“进程虚拟机”不具备全部的功能,能运行一个程序或者进程。Wine 是一个允许你在 Linux 机器上运行 Windows 应用的进程虚拟机,但是并不在 Linux 中提供完整的 Windows 操作系统。
JavaScript 虚拟机是一种进程虚拟机,专门设计来解释和执行的 JavaScript 代码。
注意:要区别在浏览器中排布页面布局的 布局引擎 和解释和执行代码的底层 JavaScript 引擎是非常重要的。在 这里 可以找到一个很好的阐释。
那么,确切来讲,到底什么是 JavaScript 引擎,它做了什么?
JavaScript 引擎的基本工作是把开发人员写的 JavaScript 代码转换成高效、优化的代码,这样就可以通过浏览器进行解释甚至嵌入到应用中。事实上,JavaScriptCore 自称为“优化虚拟机”。
更准确地讲,每个 JavaScript 引擎都实现了一个版本的 ECMAScript,JavaScript 是它的一个分支。随着 ECMAScript 的不断发展,JavaScript 引擎也不断改进。之所以有这么多不同的引擎,是因为它们每个都被设计运行在不同的 web 浏览器、headless 浏览器、或者像 Node.js 那样的运行时环境中。
你也许熟悉 web 浏览器,那什么是 headless 浏览器呢?它是一个没有图形用户界面的 web 浏览器。它们在对 web 产品进行自动化测试时十分有用。一个很棒的例子就是 PhantomJS。那 Node.js 又和 JavaScript 引擎有什么关系?Node.js 是一个异步的、事件驱动的框架,让你在服务器端可以使用 JavaScript。既然他们是驱动 JavaScript 的工具,所以它们也是由 JavaScript 引擎驱动。
按照上述关于虚拟机的定义,把 JavaScript 引擎称作进程虚拟机就很好理解了,因为它的唯一的目的就是读取和编译 JavaScript 代码。这并不意味着它只是个简单的引擎。比如,JavaScriptCore 就有六个“构建模块”可以分析、解释、优化、垃圾回收 JavaScript 代码。
它是如何工作的?
当然,这决定于引擎。吸引我们注意的两个主要的引擎都利用了 NativeScript ,它们分别是 WebKit 的 JavaScriptCore 和 Google 的 V8 引擎。这两个引擎使用不同的方式处理代码。
JavaScriptCore 执行 一系列步骤 来解释和优化脚本:
它进行词法分析,就是将源代码分解成一系列具有明确含义的符号或字符串。
然后用语法分析器分析这些符号,将其构建成语法树。
接着四个 JIT(Just-In-Time)进程开始参与进来,分析和执行解析器所生成的字节码。
什么?简单来说,JavaScript 引擎会加载你的源代码,把它分解成字符串(又叫做分词),再 把这些字符串转换 成编译器可以理解的字节码,然后执行这些字节码。
Google 的 V8 引擎 是用 C++ 编写的,它也能够编译并执行 JavaScript 源代码、处理内存分配和垃圾回收。它被设计成由两个编译器组成,可以把源码直接编译成机器码:
Full-codegen:输出未优化代码的快速编译器
Crankshaft: 输出执行效率高、优化过的代码的慢速编译器
如果 Crankshaft 确定需要优化的代码是由 Full-codegen 生成的未优化代码,它就会取代 Full-codegen,这个过程叫做“crankshafting”。
一旦编译过程中产生了机器代码,引擎就会向浏览器暴露所有的数据类型、操作符、对象、在 ECMA 标准中指定的函数、或任何运行时需要使用的东西,NativeScript 就是如此。
有哪些 JavaScript 引擎?
有一大堆令人眼花缭乱的 JavaScript 引擎可以用来解释、分析和执行你的客户端代码。每个浏览器版本发布时,它的 JavaScript 引擎都可能有所改变或优化以跟上 JavaScript 代码执行技术的状况的变化。
你还没被这些浏览器引擎的名字完全弄糊涂之前,请记住很多市场营销的元素被加入了这些引擎和以它们为基础的浏览器。这篇对 JavaScript 编译 十分有用的分析 中,作者讽刺地指出:“你所不知道的是,编译器大约有 37% 是由市场营销构成的,对编译器进行品牌重塑也是你能做的为数不多的事情之一,智慧的市场营销,故而有了一系列名字:SquirrelFish、Nitro、SFX……”。
在牢记营销对命名和重命名这些引擎的影响的同时,注意到几件在 JavaScript 引擎发展史上的重大事件是很有用的。我为你做了一个便于理解的图表:
Browser, Headless Browser, or Runtime
JavaScript Engine
Spidermonkey
JavaScriptCore
IE and Edge
JavaScriptCore
*JavaScriptCore 被改写为 SquirrelFish,升级版本为 QuirrelFish Extreme,也叫做 Nitro。然而,构成 Webkit 实现基础的 JavaScript 引擎就是 JavaScriptCore(比如 Safari)。
**iOS 开发者应该要知道移动设备的 Safari 使用 Nitro,但是 UIWebView 不包括 JIT 编译,所以体验会慢一些。然而开发人员可以在 iOS8 中使用包含 Nitro 的 WKWebView,使用体验 明显 变快。混合移动应用程序的开发人员应该能松口气了。
*最终 io.js 从 Node.js 分离开的原因之一就是为了支持 V8 版本的引擎。这仍然是一个挑战,正如 这里 讲述的。
我们为什么要关注?
JavaScript 引擎的代码解析和执行过程的目标就是在最短时间内编译出最优化的代码。
最重要的是,这些引擎的演进与我们对发展 web 和 移动平台的不断探究息息相关,让它们尽可能具有高性能,是相辅相成的。为了追踪这种演进,你可以看到各种各样的引擎在基准图中是如何表现的,就好像
总结的。例如,比较 Chrome 在搭载 V8 引擎与 non-Crankshafted 引擎时的表现就很有趣。
任何一个 web 开发者都要意识到,我们努力编写、调试和维护的代码在不同浏览器中执行效果必然有所差异。为什么某段代码在一个浏览器上工作得很慢,但在另一个上却快得多?
同样地,移动开发者,尤其是使用 webview 显示页面内容的混合移动应用开发者,或者那些使用像 NativeScript 这种运行时环境的开发者,想知道是什么引擎在解释执行他们的 JavaScript 代码。移动 web 开发者应该注意到那些小小设备上的浏览器所具备的各种局限性和可能性。作为一个想持续发展的 web、移动或应用程序开发人员,时刻关注 JavaScript 引擎的变化会带给你超值回报。
js 中的基本数据类型 undefined null boolean number string
js 中的一种复杂数据类型 object& 它是所有对象的基础类型
js 和其他语言一样拥有9种基本的控制语句
js 中的函数无需指定返回值,实际上未指定返回值的函数返回的是undefined
js 中的参数可以随意的传递& 注意arguments[] 数组 它可以帮助你
js 中的函数是不能重载的,但是你可以模仿。
您可能感兴趣的文章:
大家感兴趣的内容
12345678910
最近更新的内容
常用在线小工具请教问题:nodejs 编写的addon内 如何通过V8引擎运行JS代码 - CNode技术社区
这家伙很懒,什么个性签名都没有留下。
###run.cpp:
#define BUILDING_NODE_EXTENSION
#include &node.h&
using namespace v8;
Handle&Value& run(const Arguments& args) {
if (args.Length() & 1) {
ThrowException(Exception::TypeError(String::New(&Args Error&)));
return scope.Close(Undefined());
if (!args[0]-&IsString()) {
ThrowException(Exception::TypeError(String::New(&Args Error&)));
return scope.Close(Undefined());
Persistent&Context& context = Context::New();
Context::Scope context_scope(context);
Local&Script& scritp = Script::Compile(args[0]-&ToString());
Local&Value& result = scritp-&Run();
return scope.Close(result);
void Init(Handle&Object& exports) {
exports-&Set(String::NewSymbol(&run&),
FunctionTemplate::New(run)-&GetFunction());
NODE_MODULE(run, Init)
###test.js:
var addons = require('./run.node');
addons.run(&console.log('hello world')&);
使用命令:node test.js
ReferenceError: console is not defined
at &anonymous&:1:1
at Object.&anonymous& (C:\Users\fx\Documents\Visual Studio 2010\Projects\helloworld\Debug\test.js:2:8)
at Module._compile (module.js:456:26)
at Object.Module._extensions..js (module.js:474:10)
at Module.load (module.js:356:32)
at Function.Module._load (module.js:312:12)
at Function.Module.runMain (module.js:497:10)
at startup (node.js:119:16)
at node.js:902:3
也不知道是啥问题,跪求高手现身
可能 原因是console 不是标准的js库,你试试addons.run(&‘Hello’ + ‘, World!’&);看看结果是不是Hello,World
嗯,确实是这样,但是我想实现的功能类似于这里的 module._compile 方法,这个方法能将文件读入后compile成function。
// Native extension for .js
Module._extensions['.js'] = function(module, filename) {
var content = NativeModule.require('fs').readFileSync(filename, 'utf8');
module._compile(stripBOM(content), filename);
CNode 社区为国内最专业的 Node.js 开源技术社区,致力于 Node.js 的技术研究。
服务器赞助商为
,存储赞助商为
,由提供应用性能服务。
新手搭建 Node.js 服务器,推荐使用无需备案的Introduction
hromium and CEF use the&V8
JavaScript Engine&for their internal JavaScript (JS) implementation. Each frame in a browser window has its own JS context that provides scope and security for JS code executing in that frame (see the &Working with Contexts& section for more information).
CEF exposes a large number of JS features for integration in client applications.
All code that interacts with JS must be executed on the UI thread. To execute code on the UI thread with CEF1 use the CefPostTask() function.
#include &include/cef.h&#include &include/cef_runnable.h&// This method will be called on the UI thread.void UIT_InvokeScript(CefRefPtr&CefBrowser& browser){& // Code here.}// This method may be called on any thread.void RunScript(CefRefPtr&CefBrowser& browser){& if (CefCurrentlyOn(TID_UI)) {&&& UIT_InvokeScript(browser);& } else {&&& // Execute on the UI thread.&&& CefPostTask(TID_UI, NewCefRunnableFunction(&UIT_InvokeScript, browser));& }}
With CEF3 WebKit and JS execution run in a separate renderer process. The main thread in a renderer process is identified as TID_RENDERER and all V8 execution must take place on this thread. JS&s
that communicate between the browser and renderer processes should be designed using asynchronous callbacks. See http://www.chromium.org/developers/design-documents/extensions/how-the-extension-system-works/api-pattern-design-doc for an example.
See the comments in cef_v8.h and examples in tests/unittests/v8_unittest.cc and tests/cefclient/cefclient.cpp for additional information beyond what is presented in this document.
ExecuteJavaScript
The simplest way to execute JS from a client application is using the CefFrame::ExecuteJavaScript() function.
CefRefPtr&CefBrowser& browser = ...;CefRefPtr&CefFrame& frame = browser-&GetMainFrame();frame-&ExecuteJavaScript(&alert('ExecuteJavaScript works!');&,&&& frame-&GetURL(), 0);
The above example will cause&alert('ExecuteJavaScript works!');&to be executed in the browser's main frame.
The ExecuteJavaScript() function can be used to interact with functions and variables in the frame's JS context. In order to return values from JS to the client application consider using Window Binding or Extensions.
Window Binding
Window binding allows the client application to attach values to a frame's&window&object. Window bindings are implemented using the CefV8ContextHandler::OnContextCreated() method.
void MyHandler::OnContextCreated(CefRefPtr&CefBrowser& browser,&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& CefRefPtr&CefFrame& frame,&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& CefRefPtr&CefV8Context& context) OVERRIDE{& // Retrieve the context's window object.& CefRefPtr&CefV8Value& object = context-&GetGlobal();& // Create a new V8 string value. See the &Basic JS Types& section below.& CefRefPtr&CefV8Value& str = CefV8Value::CreateString(&My Value!&);& // Add the string to the window object as &window.myval&. See the &JS Objects& section below.& object-&SetValue(&myval&, str, V8_PROPERTY_ATTRIBUTE_NONE);}
JavaScript in the frame can then interact with the window bindings.
&script language=&JavaScript&&alert(window.myval); // Shows an alert box with &My Value!&&/script&
Window bindings are reloaded each time a frame is reloaded giving the client application an opportunity to change the bindings if necessary. For example, different frames may be given access to different features in the client application by modifying the values
that are bound to the window object for that frame.
Extensions
Extensions are like window bindings except they are loaded into the context for every frame and cannot be modified once loaded. Extensions are registered using the CefRegisterExtension() function.
// Define the extension contents.std::string extensionCode =& &&& &if (!test)&& && test = {};&& &(function() {&& && test.myval = 'My Value!';&& &})();&;// Register the extension.CefRegisterExtension(&v8/test&, extensionCode, NULL);
The string represented by&extensionCode&can be any valid JS code. JS in the frame can then interact with the extension code.
&script language=&JavaScript&&alert(test.myval); // Shows an alert box with &My Value!&&/script&
Note that the above example with NULL as the 3rd argument to CefRegisterExtension() is only supported with CEF revision 389 and newer.
Basic JS Types
CEF supports the creation of basic JS data types including undefined, null, bool, int, double, date and string. These types are created using CefV8Value::Create*() static methods. For example, to create a new JS string
value use the CreateString() method.
CefRefPtr&CefV8Value& str = CefV8Value::CreateString(&My Value!&);
Basic value types can be created at any time and are not initially associated with a particular context (see the &Working with Contexts& section for more information).
To test the value type use the Is*() methods.
CefRefPtr&CefV8Value& val = ...;if (val.IsString()) {& // The value is a string.}
To retrieve the value use the Get*Value() methods.
CefString strVal = val.GetStringValue();
Arrays are created using the CefV8Value::CreateArray() static method. Arrays can only be created and used from within a context (see the &Working with Contexts& section for more information).
CefRefPtr&CefV8Value& arr = CefV8Value::CreateArray();
Values are assigned to an array using the SetValue() method variant that takes an index as the first argument.
arr-&SetValue(0, CefV8Value::CreateString(&My String!&));
To test if a CefV8Value is an array use the IsArray() method. To get the length of an array use the GetArrayLength() method. To get a value from an array use the GetValue() variant that takes an index as the first argument.
JS Objects
Objects are created using the CefV8Value::CreateObject() static method. Objects can only be created and used from within a context (see the &Working with Contexts& section for more information).
CefRefPtr&CefV8Value& obj = CefV8Value::CreateObject(NULL, NULL);
Values are assigned to an object using the SetValue() method variant that takes a key string as the first argument.
obj-&SetValue(&myval&, CefV8Value::CreateString(&My String!&));
Objects with Accessors
Objects can optionally have an associated accessor that provides a native implementation for getting and setting values.
CefRefPtr&CefV8Value& obj = CefV8Value::CreateObject(NULL, accessor);
The |accessor| parameter is an implementation of the CefV8Accessor interface that must be provided by the client application.
class MyV8Accessor : public CefV8Accessor{public:& MyV8Accessor() {}& virtual bool Get(const CefString& name,&&&&&&&&&&&&&&&&&& const CefRefPtr&CefV8Value& object,&&&&&&&&&&&&&&&&&& CefRefPtr&CefV8Value&& retval,&&&&&&&&&&&&&&&&&& CefString& exception) OVERRIDE& {&&& if (name == &myval&) {&&&&& // Return the value.&&&&& retval = CefV8Value::CreateString(myval_);&&&&&&&& }&&& // Value does not exist.&&&& }& virtual bool Set(const CefString& name,&&&&&&&&&&&&&&&&&& const CefRefPtr&CefV8Value& object,&&&&&&&&&&&&&&&&&& const CefRefPtr&CefV8Value& value,&&&&&&&&&&&&&&&&&& CefString& exception) OVERRIDE& {&&& if (name == &myval&) {&&&&& if (value.IsString()) {&&&&&&& // Store the value.&&&&&&& myval_ = value.GetStringValue();&&&&& } else {&&&&&&& // Throw an exception.&&&&&&& exception = &Invalid value type&;&&&&& }&&&&&&&& }&&& // Value does not exist.&&&& }& // Variable used for storing the value.& CefString myval_;& // Provide the reference counting implementation for this class.& IMPLEMENT_REFCOUNTING(MyV8Accessor);};
In order for a value to be passed to the accessor it must be set using the SetValue() method variant that accepts AccessControl and PropertyAttribute arguments.
obj-&SetValue(&myval&, V8_ACCESS_CONTROL_DEFAULT, &&& V8_PROPERTY_ATTRIBUTE_NONE);
JS Functions
CEF supports the creation of JS functions with native implementations. Functions are created using the CefV8Value::CreateFunction() static method. Functions can only be created and used from within a context (see the &Working with Contexts& section for more
information).
CefRefPtr&CefV8Value& func = CefV8Value::CreateFunction(&myfunc&, handler);
The |handler| parameter is an implementation of the CefV8Handler interface that must be provided by the client application.
class MyV8Handler : public CefV8Handler{public:& MyV8Handler() {}& virtual bool Execute(const CefString& name,&&&&&&&&&&&&&&&&&&&&&& CefRefPtr&CefV8Value& object,&&&&&&&&&&&&&&&&&&&&&& const CefV8ValueList& arguments,&&&&&&&&&&&&&&&&&&&&&& CefRefPtr&CefV8Value&& retval,&&&&&&&&&&&&&&&&&&&&&& CefString& exception) OVERRIDE& {&&& if (name == &myfunc&) {&&&&& // Return my string value.&&&&& retval = CefV8Value::CreateString(&My Value!&);&&&&&&&& }&&& // Function does not exist.&&&& }& // Provide the reference counting implementation for this class.& IMPLEMENT_REFCOUNTING(MyV8Handler);};
Functions and Window Binding
Functions can be used to create complex window bindings.
void MyHandler::OnContextCreated(CefRefPtr&CefBrowser& browser,&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& CefRefPtr&CefFrame& frame,&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& CefRefPtr&CefV8Context& context) OVERRIDE{& // Retrieve the context's window object.& CefRefPtr&CefV8Value& object = context-&GetGlobal();& // Create an instance of my CefV8Handler object.& CefRefPtr&CefV8Handler& handler = new MyV8Handler();& // Create the &myfunc& function.& CefRefPtr&CefV8Value& func = CefV8Value::CreateFunction(&myfunc&, handler);& // Add the &myfunc& function to the &window& object.& object-&SetValue(&myfunc&, func, V8_PROPERTY_ATTRIBUTE_NONE);}
&script language=&JavaScript&&alert(window.myfunc()); // Shows an alert box with &My Value!&&/script&
Functions and Extensions
Functions can be used to create complex extensions. Note the use of the &native function& forward declaration which is required when using extensions.
// Define the extension contents.std::string extensionCode =& &&& &if (!test)&& && test = {};&& &(function() {&& && test.myfunc = function() {&& &&&& native function myfunc();&& &&&& return myfunc();&& && };&& &})();&;// Create an instance of my CefV8Handler object.CefRefPtr&CefV8Handler& handler = new MyV8Handler();// Register the extension.CefRegisterExtension(&v8/test&, extensionCode, handler);
&script language=&JavaScript&&alert(test.myfunc()); // Shows an alert box with &My Value!&&/script&
Working with Contexts
Each frame in a browser window has its own V8 context. The context defines the scope for all variables, objects and functions defined in that frame. V8 will be inside a context if the current code location has a CefV8Handler, CefV8Accessor or CefJSBindingHandler
callback higher in the call stack.
The OnContextCreated() and OnContextReleased() methods define the complete life span for the V8 context associated with a frame. You should be careful to follow the below rules when using these methods:
1. Do not hold onto or use a V8 context reference past the call to OnContextReleased() for that context.
2. The lifespan of all V8 objects is unspecified (up to the GC). Be careful when maintaining references directly from V8 objects to your own internal implementation objects. In many cases it may be better to use a proxy object that your application associates
with the V8 context and which can be &disconnected& (allowing your internal implementation object to be freed) when OnContextReleased() is called for the context.
If V8 is not currently inside a context, or if you need to retrieve and store a reference to a context, you can use one of two available CefV8Context static methods. GetCurrentContext() returns the context for the frame that is currently executing JS. GetEnteredContext()
returns the context for the frame where JS execution began. For example, if a function in frame1 calls a function in frame2 then the current context will be frame2 and the entered context will be frame1.
Arrays, objects and functions may only be created, modified and, in the case of functions, executed, if V8 is inside a context. If V8 is not inside a context then the application needs to enter a context by calling Enter() and exit the context by calling Exit().
The Enter() and Exit() methods should only be used:
1. When creating a V8 object, function or array outside of an existing context. For example, when creating a JS object in response to a native menu callback.
2. When creating a V8 object, function or array in a context other than the current context. For example, if a call originating from frame1 needs to modify the context of frame2.
Executing Functions
Native code can execute JS functions by using the ExecuteFunction() and ExecuteFunctionWithContext() methods. The ExecuteFunction() method should only be used if V8 is already inside a context as described in the &Working with Contexts& section. The ExecuteFunctionWithContext()
method allows the application to specify the context that will be entered for execution.
Using JS Callbacks
When registering a JS function callback with native code the application should store a reference to both the current context and the JS function in the native code. This could be implemented as follows.
1. Create a &register& function in OnJSBinding().
void MyHandler::OnContextCreated(CefRefPtr&CefBrowser& browser,&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& CefRefPtr&CefFrame& frame,&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& CefRefPtr&CefV8Context& context) OVERRIDE{& // Retrieve the context's window object.& CefRefPtr&CefV8Value& object = context-&GetGlobal();& CefRefPtr&CefV8Handler& handler = new MyV8Handler(this);& object-&SetValue(&register&,&&&&&&&&&&&&&&&&&& CefV8Value::CreateFunction(&register&, handler),&&&&&&&&&&&&&&&&&& V8_PROPERTY_ATTRIBUTE_NONE);}
2. In the MyV8Handler::Execute() implementation for the &register& function keep a reference to both the context and the function.
virtual bool Execute(const CefString& name,&&&&&&&&&&&&&&&&&&&& CefRefPtr&CefV8Value& object,&&&&&&&&&&&&&&&&&&&& const CefV8ValueList& arguments,&&&&&&&&&&&&&&&&&&&& CefRefPtr&CefV8Value&& retval,&&&&&&&&&&&&&&&&&&&& CefString& exception) OVERRIDE{& if (name == &register&) {&&& if (arguments.size() == 1 && arguments[0]-&IsFunction()) {&&&&& callback_func_ = arguments[0];&&&&& callback_context_ = CefV8Context::GetCurrentContext();&&&&&&&& }& }&}
3. Register the JS callback via JavaScript.
&script language=&JavaScript&&function myFunc() {& // do something in JS.}window.register(myFunc);&/script&
4. Execute the JS callback at some later time.
CefV8ValueLCefRefPtr&CefV8Value&CefRefPtr&CefV8Exception&if (callback_func_-&ExecuteFunctionWithContext(callback_context_, NULL, args, retval, exception, false)) {& if (exception.get()) {&&& // Execution threw an exception.& } else {&&& // Execution succeeded.& }}
See the V8Test.Exception test in tests/unittests/v8_unittest.cc for a complete example of using callbacks.
General Usage
Consider the following example from tests/cefclient/cefclient.cpp.
void UIT_InvokeScript(CefRefPtr&CefBrowser& browser){& REQUIRE_UI_THREAD();& CefRefPtr&CefFrame& frame = browser-&GetMainFrame();& CefRefPtr&CefV8Context& v8Context = frame-&GetV8Context();& CefString url = frame-&GetURL();& if (!v8Context.get()) {&&& frame-&ExecuteJavaScript(&alert('Failed to get V8 context!');&, url, 0);& } else if (v8Context-&Enter()) {&&& CefRefPtr&CefV8Value& globalObj = v8Context-&GetGlobal();&&& CefRefPtr&CefV8Value& evalFunc = globalObj-&GetValue(&eval&);&&& CefRefPtr&CefV8Value& arg0 = CefV8Value::CreateString(&1+2&);&&& CefV8ValueL&&& args.push_back(arg0);&&& CefRefPtr&CefV8Value& retV&&& CefRefPtr&CefV8Exception&&&& if (evalFunc-&ExecuteFunctionWithContext(v8Context, globalObj, args, retVal,&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& exception, false)) {&&&&& if (retVal.get()) {&&&&&&& frame-&ExecuteJavaScript(&&&&&&&&&&& std::string(&alert('InvokeScript returns &) +&&&&&&&&&&& retVal-&GetStringValue().ToString() + &!');&,&&&&&&&&&&& url, 0);&&&&& } else {&&&&&&& frame-&ExecuteJavaScript(&&&&&&&&&&& std::string(&alert('InvokeScript returns exception: &) +&&&&&&&&&&& exception-&GetMessage().ToString() + &!');&,&&&&&&&&&&& url, 0);&&&&& }&&& } else {&&&&& frame-&ExecuteJavaScript(&alert('Failed to execute function!');&, url, 0);&&& }&&& v8Context-&Exit();& } else {&&& frame-&ExecuteJavaScript(&alert('Failed to enter into V8 context!');&,&&&&&&& url, 0);& }}
Rethrowing Exceptions
If the&rethrow_exception&argument to ExecuteFunction*() is true any exceptions generated by V8 will be immediately rethrown. If an exception is rethrown any native code needs
to immediately return. Exceptions should only be rethrown if there is a JS call higher in the call stack. For example, consider the following call stacks where &JS& is a JS function and &EF& is a native ExecuteFunction call:
Stack 1: JS1 -& EF1 -& JS2 -& EF2
Stack 2: Native Menu -& EF1 -& JS2 -& EF2
With stack 1 rethrow should be true for both EF1 and EF2. With stack 2 rethrow should false for EF1 and true for EF2.
This can be implemented by having two varieties of call sites for EF in the native code:
1. Only called from a V8 handler. This covers EF 1 and EF2 in stack 1 and EF2 in stack 2. Rethrow is always true.
2. Only called natively. This covers EF1 in stack 2. Rethrow is always false.
Be very careful when rethrowing exceptions. Incorrect usage (for example, calling ExecuteFunction() immediately after exception has been rethrown) may cause your application to crash or malfunction in hard to debug ways.
&&相关文章推荐
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:19807次
排名:千里之外
原创:15篇
转载:39篇
(1)(1)(3)(2)(2)(2)(5)(4)(6)(1)(2)(2)(1)(1)(1)(14)(6)

我要回帖

更多关于 雄安新区什么时候开工 的文章

 

随机推荐