精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

揭秘:支付寶小程序 V8 Worker 技術演進

開發 開發工具
本文分享支付寶小程序 V8 Worker 相關工作沉淀和總結,包括技術演進、基礎架構、基礎功能、以及 JS 引擎能力輸出,以及一些優化方案等。歡迎同學們共同探討,指正。

本文分享支付寶小程序 V8 Worker 相關工作沉淀和總結,包括技術演進、基礎架構、基礎功能、以及 JS 引擎能力輸出,以及一些優化方案等。歡迎同學們共同探討,指正。

從 Service Worker 到 V8 Worker

本節簡要介紹支付寶小程序從 Service Worker 到 V8 Worker 的技術演進過程。

眾所周知,支付寶小程序源碼打包完成之后主要分為兩部分:

  • 第一部分負責小程序的視圖展示,打包產物為 index.js,我們稱為 Render 部分
  • 第二部分負責小程序的業務邏輯、視圖更新等,打包產物為 index.worker.js,我們稱為 Worker 部分

同時,前端框架 APPX 也分為 Render 部分(af-appx.min.js)和 Worker 部分(af-appx.worker.min.js):

  • Render部分(index.js 和 af-appx.min.js)運行在 UCWebView 或 SystemWebView 上
  • Worker 部分(index.worker.js 和 af-appx.worker.min.js)運行于 Service Worker[1] 上

Service Worker

Service Worker 由瀏覽器內核提供,設計目的是用于充當 Web 應用程序與瀏覽器之間的代理服務器;Service Worker 運行在獨立的 worker 上下文,因此它不能訪問 DOM。相對于驅動應用的主 JavaScript 線程,它運行在其他線程中,所以不會造成阻塞。

??

??

 

但是有一個問題是 Service Worker 的啟動和 Render 部分的啟動是串行的,必須是在 WebView 啟動之后,由 Render 部分的 JS 發起。這對小程序來說就是較大的性能瓶頸。

??

??

 

WebView Worker

為了解決 Worker 和 Render 串行初始化和執行帶來的性能問題,小程序團隊嘗試過使用 WebView 來執行 Worker。也就是在啟動小程序的時候同時 new 出兩個 WebView,一個 WebView 用來渲染 Render 部分,另一個 WebView 專門用來執行 Worker 部分的 JS 腳本。但是專門使用一個 WebView 來執行 Worker 部分的 JS 腳本,無疑是”大材小用“,使用一個 WebView 的資源消耗必然是較高的。

??

??

 

V8 Worker

Service Worker 的串行初始化會影響小程序啟動性能,WebView Worker 來運行小程序 Worker 代碼又不夠輕量,使用專有 JS 引擎來做 Worker 部分的工作乃是最優選擇,因此 V8 Worker 應運而生。

下圖是小程序 V8 Worker 的基本結構,本文后面繼續詳細描述。

??

??

 

利用 V8 引擎運行 Worker 主要有以下一些優勢:

  • 能夠解決 Render 和 Worker 串行初始化和運行的問題,WebView 和 V8 引擎可并行初始化、可并行執行 Render 和 Worker 部分的 JS 腳本
  • 能夠提供 JS 安全運行環境,隔離框架 JS 和業務 JS
  • 易于給小程序注入 JS 對象,綁定 JSAPI
  • 能夠支持更豐富的數據類型,如 ArrayBuffer 等
  • 能夠擴展 Worker 能力,提供小程序插件、多線程 Worker 等功能
  • 能夠充分利用 V8 引擎的能力做性能優化,如 V8 CodeCache 等
  • 能夠給小程序以外的業務提供 JS 引擎能力,如 V8 Native 插件
  • 能夠自定義 JS 引擎運行參數

??

??

 

V8 Worker 基礎架構

本節主要介紹了支付寶小程序的 V8 Worker 工程結構、基于 V8 Worker 的小程序架構;同時如果對 V8 引擎不是很熟悉,這里給出了 V8 的簡要介紹和學習資料鏈接。

V8 簡介與入門

在介紹 V8 Worker 之前,先簡要了解下 V8 引擎[2]本身。如果對 V8 很熟的大牛請自行跳過。

V8 是 Google 的開源項目,是一個高性能 JavaScript 和 WebAssembly 引擎,應用于用于 Chrome 瀏覽器、Node.js 等項目。學習 V8 的門檻還是比較高,這里只給出了閱讀本文所需要知道的 V8 基本概念,以及官方的嵌入式 V8 的 HelloWorld 代碼,同時給出一些學習鏈接。

嵌入式 V8 基本概念

1 Isolate (隔離)

Isolate 和操作系統中進程的概念有些類似。進程是完全相互隔離的,一個進程里有多個線程,同時各個進程之間并不相互共享資源。Isolate 也是一樣,Isolate1 和 Isolate2 兩個擁有各自堆棧的虛擬機實例,且相互完全隔離。

2 Contexts (上下文)

在 V8 中,一個 context 就是一個執行環境, 它使得可以在一個 V8 實例中運行相互隔離且無關的 JavaScript 代碼。你必須為你將要執行的 JavaScript 代碼顯式的指定一個 context。

之所以這樣是因為 JavaScript 提供了一些內建的工具函數和對象,他們可以被 JS 代碼所修改。比如,如果兩個完全無關的 JS 函數都在用同樣的方式修改一個 global 對象,很可能就會出現一個意外的結果。

3 Handle(句柄)與 垃圾回收

Handle 提供了一個 JS 對象在堆內存中的地址的引用。V8 垃圾回收器將回收一個已無法被訪問到的對象占用的堆內存空間。垃圾回收過程中,回收器通常會將對象在堆內存中進行移動. 當回收器移動對象的同時,也會將所有相應的 Handle 更新為新的地址。

當一個對象在 JavaScript 中無法被訪問到,并且也沒有任何 Handle 引用它,則這個對象將被當作 "垃圾" 對待。回收器將不斷將所有判定為 "垃圾" 的對象從堆內存中移除。V8 的垃圾回收機制是其性能的關鍵所在。

Local Handles 保存在一個棧結構中,當棧的析構函數(destructor)被調用時將同時被銷毀。這些 handle 的生命周期取決于 handle scope(當一個函數被調用的時候,對應的 handle scope 將被創建)。當一個 handle scope 被銷毀時,如果在它當中的 handle 所引用的對象已無法再被 JavaScript 訪問,或者沒有其他的 handle 指向它,那么這些對象都將在 scope 的銷毀過程中被垃圾回收器回收。入門指南中的例子使用的就是這種 Handle。

Persistent handle 是一個堆內存上分配的 JavaScript 對象的引用,這點和 local handle 一樣。但它有兩個自己的特點,是對于它們所關聯的引用的生命周期管理方面。當你希望持有一個對象的引用,并且超出該函數調用的時期或范圍時,或者是該引用的生命周期與 C++ 的作用域不一致時,就需要使用 persistent handle 了。例如 Google Chrome 就是使用 persistent handle 引用 DOM 節點。Persistent handle 支持弱引用,即 PersistentBase::SetWeak,它可以在其引用的對象只剩下弱引用的時候,由垃圾回收器出發一個回調。

4 Templates(模板)

在一個 context 中,template 是 JavaScript 函數和對象的一個模型。你可以使用 template 來將 C++ 函數和數據結構封裝在一個 JavaScript 對象中,這樣它就可以被 JS 代碼操作。例如,Chrome 使用 template 將 C++ DOM 節點封裝成 JS 對象,并且將函數安裝在 global 命名空間中。你可以創建一個 template 集合, 在每個創建的 context 中你都可以重復使用它們。你可以按照你的需求,創建任意多的 template。然而在任意一個 context 中,任意 template 都只能擁有一個實例。

在 JS 中,函數和對象之間有很強的二元性。在 C++ 或 Java 中創建一種新的對象類型通常要定義一個類。而在 JS 中你卻要創建一個函數, 并以函數為構造器生成對象實例。JS 對象的內部結構和功能很大程度上是由構造它的函數決定的。這些也反映在 V8 的 template 的設計中, 因此 V8 有兩種類型的 template:

1)FunctionTemplate

一個 Function Template 就是一個 JS 函數的模型. 我們可以在我們指定的 context 下通過調用 template 的 GetFunction 方法來創建一個 JS 函數的實例. 你也可以將一個 C++ 回調與一個當 JS 函數實例執行時被調用的 function template 關聯起來。

2)ObjectTemplate

每一個 Function Template 都與一個 Object Template 相關聯。它用來配置以該函數作為構造器而創建的對象。

5 Accessors (存取器)

存取器是一個當對象屬性被 JS 代碼訪問的時候計算并返回一個值的 C++ 回調。存取器是通過 Object Template 的 SetAccessor 方法進行配置的。該方法接收屬性的名稱和與其相關聯的回調函數,分別在 JS 讀取和寫入該屬性時觸發。

存取器的復雜性源于你所操作的數據的訪問方式:

  • 訪問靜態全局變量
  • 訪問動態變量

6 Interceptors(攔截器)

我們可以設置一個回調,讓它在對應對象的任意屬性被訪問時都會被調用。這就是 Interceptor。考慮到效率,分為兩種不同的 interceptor:

  • 屬性名攔截器:當通過字符串形式的屬性名訪問時調用。比如在瀏覽器中使用document.theFormName.elementName 進行訪問。
  • 屬性索引攔截器:當通過屬性的下標/索引訪問時調用。比如在瀏覽器中使用document.forms.elements[0] 進行訪問。

7 Security Model(安全模型)

在 V8 中,同源被定義為相同的 context。默認情況下,是無法訪問別的 context 的。如果一定要這樣做,需要使用安全令牌或安全回調。安全令牌可以是任意值,但通常來說是個唯一的規范字符串。當建立一個 context 時,我們可以通過 SetSecurityToken 來指定一個安全令牌, 否則 V8 將自動為該 context 生成一個。

學習資料

官方文檔 [4]

  • Ignition: An Interpreter for V8 [5]
  • Ignition: Jump-starting an Interpreter for V8 [6]
  • V8: Hooking up the Ignition to the Turbofan [7]
  • V8 Code Caching [8]

基于 V8 Worker 的小程序架構

本小節詳細講述 V8 Worker 的小程序架構,分別描述了 Render 部分和 V8 Worker 的 JSAPI 流程細節,以及 Render 和 Worker 直接如何通信。

??

??

 

單 V8 Context 結構

如上圖所示,在 V8 Worker 的初期,一個小程序占用一個 V8 Isolate,一個 V8 Isolate 只創建一個 V8 Context。也就是小程序的前端框架 APPX 的代碼 appx.worker.min.js 和小程序的業務代碼 index.worker.js 運行于同一個 V8 Isolate 上的同一個 V8 Context 上。這樣的設計就會存在 JS 安全性問題,業務 JS 代碼可以通過拼接冒名的形式訪問到為 APPX 注入的內部 JS 對象和內部 JSAPI,在同一個 V8 Context 中,是無法隔離開業務 JS 代碼和 APPX 框架 JS 代碼的運行環境的。后面我們會介紹如何解決這個安全問題。

Render 部分 JSAPI 流程

如上圖所示,Render 和 Nebula 直接的雙向通行是分別通過 Console.log 和 WebView 的 loadUrl[9] 接口進行的。

容器到 Render

容器要加載運行 Render 部分的 JS 腳本,都是通過 WebView 的 loadUrl 進行;WebView 在運行 Render 部分的 JS 腳本(af-appx.min.js 和 index.js)之前,需要提前注入 APPX 框架需要用到的全局 JS 對象,如 window.AlipayJSBridge[10] 等,供 JSAPI 調用使用。

Render 到容器

Render 側到容器的 JSAPI 的調用,本質上是通過 Console.log[11] Web API 實現。

Worker 部分 JSAPI 流程

Worker 到容器

類似于 Render 部分,在初始化 V8 Worker 時,也需要在 V8 Worker 環境中注入 AlipayJSBridge 這個全局 JS 對象,AlipayJSBridge 的定義在 workerjs_v8_origin.js [12]中,workerjs_v8_origin.js[13] 已提前在 V8 Worker 中加載。

AlipayJSBridge = { 
//xxxxx
call: function (func, param, callback) {
nativeFlushQueue(func, viewId, JSON.stringify(msg), extraData);
}
//xxxxx
}

同時,我們已經在 V8 Worker 環境中提前注入了 nativeFlushQueue API,同時綁定了這個 API 的 JAVA 側回調:

mV8Runtime.registerJavaMethod(new AsyncJsapiCallback(this), "__nativeFlushQueue__");

這樣 Worker 部分 JSAPI 通過 AlipayJSBridge.call() 調用,最終會回調到容器側的AsyncJsapiCallback() 。

容器到 Worker

JSAPI 在容器側處理完成之后,如果有返回結果,將會返回到 Worker。

Render 和 Worker 通信

基于容器總線的消息通道

以 Render 到 Worker 發送消息為例,流程大致為:

  • Render 側發送 postMessage 消息,此時消息需要經過一次序列化轉成字符串。
  • WebChromeClient onConsoleMessage 攔截到消息,反序列化成 JSONObject 并發送到容器總線 bridge.sendToNative(event) 。
  • 容器總線進行事件分發。
  • worker 插件攔截到 postMessage 事件,并發送到 worker。
  • V8Worker 將消息反序列化成 string,并轉成 JS 數據類型,傳到 Worker 所在的 V8Context。
  • workerjs_v8_origin.js 中_invokeJS 函數被調用,至此,Worker 已收到來自 Render 的消息。

基于 MessageChannel 的消息通道

可以看出,基于容器總線的消息通道,一個消息從 Render 到 Worker 中間需要經過多次的序列化和反序列化,這是非常耗時的操作;不僅在小程序啟動過程中影響小程序啟動速度,小程序的滑動等交互事件都會有大量的 Worker 和 Render 之間的消息傳遞,所以也會影響幀率。

于是,基于 MessageChannel 的消息通道應運而生。

MessageChannel 允許我們創建一個新的消息通道,并通過它的兩個 messagePort 屬性發送數據。如下圖所示,MessageChannel 會創建一個管道,管道的兩端分別代表一個 messagePort,都能夠通過 portMessage 向對方發送數據,通過 onmessage 來接受對方發送過來的數據。利用 MessageChannel 的特性,render 和 worker 之間的通信可以不通過 Nebula 總線,這樣減少了消息的序列化和反序列化。

??

??

 

V8 Worker 接入 JSI

背景

??

??

 

隨著支付寶端以及整個集團使用V8引擎的業務越來越多,對 V8 引擎的升級維護工作就越來越復雜和重要。每個業務可能使用不同的接口,升級 V8 引擎時都需要重新適配。同時,剛才前文也提到了,目前 V8 引擎由 UCWebView 內核提供,使用 V8 需要重新進行拷貝。

如何解決這些問題呢?"計算機科學領域的任何問題都可以通過增加一個間接的中間層來解決",于是就誕生了 JSI(JavaScript Interface)。

JSI 簡介

JSI(JavaScript Interface)是對 JavaScript 引擎(V8、JSC 等)進行封裝,給業務方提供基礎的、完整的、穩定的、與具體 JS引擎無關的、向后兼容的 Java API 和 Native API。

??

??

 

JSI 帶來的優勢有:

與具體 JavaScript 引擎無關的、各平臺通用 JSI API

實現了 Inspector、Code Cache、JS Timer 等通用的功能,能讓業務方更加集中精力地關注于業務方面的開發,縮短開發周期

JSI 負責處理 JS 引擎版本兼容性問題,接入業務無感知

JSI 直接使用 UC 內核中的 libwebviewuc.so,不需要進行 V8 拷貝

JSI 采用支付寶和 UC 共建的形式,JSI 接入層下沉到 Ariver 工程,通過 Ariver 輸出到集團各業務

基于 JSI 的 V8 Worker

下圖是基于 JSI 的 V8 Worker 工程結構。對比基于 J2V8[14] 的 V8 Worker 發現,小程序、小游戲、Cube 等業務只需要通過 JSI 的 Java 接口去加載 V8 引擎即可,JSI 中使用 U4 Linker 加載 libwebviewuc.so,可復用 UC WebView SDK 中的 libwebviewuc.so,且無需拷貝,解決了與 UC WebView 在同一個進程中共存時 libwebviewuc.so 全局變量沖突的問題。JSI 同時提供了 Java 和 C++ 兩種封裝 API,方便業務方接入。

JSI 接入文檔詳細介紹了如何快速通過 JSI 來使用 JS 引擎:

  • Java 和 Native 側的初始化
  • 創建 JSEngine(對應于 v8::isolate)
  • 創建 JSContext(對應于 v8::Context)
  • 如何通過 Java/C++ 接口注入 JS 對象(全局常量、全局函數、全局訪問器)
  • 如何執行 JS 腳本
  • Trace 分析、Timer 等

??

??

 

V8 Worker 如何解決 JS 安全問題

前文已經介紹,采用單 V8 Isolate 單 V8 Context 結構的 V8 Worker 會存在 JS 安全問題,無法隔離業務 JS 和前端框架 JS 的運行環境。下面就介紹多 Context 隔離的 V8 Worker 和多 Isolate 隔離多線程 Worker。

多 Context 隔離

下圖描述了多 V8 Context 隔離架構的 V8 Worker。對于同一個小程序,在同一個 V8 Isolate 下,分別為小程序前端框架腳本(af-appx.worker.minjs)、小程序業務腳本(index.worker.js)和小程序插件[15]腳本(plugin/index.worker.js)創建單獨 APPX Context、Biz Context、Plugin Context(jsi::JSContext 就對應于 v8::Context)。同一個小程序可能會存在多個小程序插件,對于每一個插件都會分配一個單獨 V8 Context 運行環境。

如 V8 Context 安全模型[16]所描述,同源即被定義為 Context,默認情況下不同的 Context 是不能相互訪問的,除非通過 SetSecurityToken 設定安全令牌。正式利用了這一特性,我們將前端框架、小程序業務和小程序插件的 JS 運行環境進行了安全隔離。

??

??

 

多 Isolate 隔離的多線程 Worker

在小程序中,對于一些異步處理的任務,可以放置于后臺 Worker 線程去運行,待運行結束后,再把結果返回到小程序主線程,這就是多線程 Worker。

??

??

 

上圖描述了多線程 Worker 的設計框架。小程序 Worker 主線程運行于單獨的 V8 Isolate 上,同時,業務 JS、APPX 框架 JS、插件 JS 會運行屬于各自的 V8 Context 上。同時對于每一個 Worker 任務,都會單獨起一個 Worker 線程,創建單獨的 V8 Isolate 和 V8 Context 實例。每一個 Worker 任務和小程序主線程中的任務都是相互線程隔離的、Isolate 隔離的。

Isolate 隔離意味著 V8 堆的隔離,因此 Worker 主線程和后臺 Worker 線程,是無法直接傳遞數據的。Worker 主線程和后臺 Worker 線程要想實現數據傳遞,則需要進行序列化和反序列化(Serialize 和 Deserialize)。序列化即將數據從源 V8 堆上拷貝至 C++ 堆上,反序列化即將數據從 C++ 堆上拷貝至目標 V8 堆上。Worker 主線程和后臺 Worker 線程通過序列化和反序列化的接口 postMessage 和 onMessage 來進行數據傳遞。

JS 引擎能力輸出

支付寶中一些其他業務如(Native GCanas)想要在 C++ 層獲得 JS 引擎能力,同時不想自己費力去重新接入 JS 引擎。這時需要 V8 Worker 具備將小程序的 JS 運行環境對外輸出的能力。V8 Native 插件是其中一個方案。

V8 Native 插件

下圖描述了 V8 Native 插件的框架。設計思路如下:

在 V8 Worker 中增加一層 C++ 插件代碼,定義 Native 插件的接口,加載業務的動態鏈接庫并管理插件。

將小程序 JS 運行環境(基于 JSI 的 C++ 接口,jsi::JSEngine、jsi::JSContext)通過插件接口暴露給插件業務方,業務方即可獲得小程序JS運行環境,方便添加自定義的 JS 對象,綁定自定義 JSAPI。

  • V8 Worker 將小程序生命周期事件,通過插件接口通知給業務方。
  • 同時給插件業務暴露 PostTask 接口,允許插件業務將任務放到小程序的 JS 線程去執行。

插件業務通過接入 V8 Native 插件將獲得如下能力:

  • 獲得小程序生命周期事件
  • 獲得小程序 JS 執行環境
  • 在小程序 JS 線程執行任務
  • 訪問小程序的 JS 對象,JSAPI
  • 注入自定義 JS 對象,綁定自定義的 C++ 實現 JSAPI

由于插件業務能夠直接獲得小程序 JS 的執行環境,因此插件業務必須可信的,否則會帶來安全問題;所以在 V8 Worker java 層需要對插件進行白名單管理和開關控制。

??

??

 

V8 Worker 性能優化

并行初始化

V8 Worker 最初引入的原因就是為了解決小程序 Render 和 Worker 串行初始化和執行的問題。前文已經介紹,這里不再贅述。

Code Caching

??

??

 

上圖是 V8 code caching 的原理。因為 JS 是 JIT 語言,所以 V8 運行 JS 時需要先解析和編譯,因此 JS 的執行效率一直都是個問題。V8 code caching 的原理是,第一次運行 JS 腳本的時候同時會生成該 JS 腳本的字節碼緩存,并保存在本地磁盤,第二次再運行同一個腳本的時候,V8 可以利用第一次保存的字節碼緩存重建 Compile 結果,這樣就不需要重新 CompileCode。這樣第二次利用 Code Cache 之后,執行這個腳本將會更快。

V8 Code caching 分為兩種:

  • Lazy Code caching:只將跑過的熱函數生成 code caching
  • Eager Code caching:將整個JS腳本都生成 code caching

Eager Code caching 生成的緩存將會更全,熱點函數命中率也會更高。同時體積將會更大,因此第二次從磁盤加載緩存時耗時也會更多。V8 官方宣稱 Eager Code caching會比 Lazy Code caching 減少 20%-40% 的 parse 和 compile 的時間。實際上我們通過實驗發現 Eager Code caching 并不比 UC 目前的 Lazy Code caching 有更好的效果。原因是緩存的體積對性能影響巨大。但是通過 Trace 分析,使用 Eager Code caching 和沒有使用 cache 相比,JS 執行時間還是有較大的提升。

??

??

 

相關鏈接

[1]https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API[2]https://v8.dev/docs[3]https://chromium.googlesource.com/v8/v8/+/branch-heads/6.8/samples/hello-world.cc

[4]https://v8.dev/docs

[5]https://docs.google.com/presentation/d/1OqjVqRhtwlKeKfvMdX6HaCIu9wpZsrzqpIVIwQSuiXQ/edit#slide=id.ge4ef702cb_2_67

[6]https://docs.google.com/presentation/d/1HgDDXBYqCJNasBKBDf9szap1j4q4wnSHhOYpaNy5mHU/edit#slide=id.g1357e6d1a4_0_58

[7]https://docs.google.com/presentation/d/1HgDDXBYqCJNasBKBDf9szap1j4q4wnSHhOYpaNy5mHU/edit#slide=id.g1357e6d1a4_0_58

[8]https://v8.dev/blog/code-caching

[9]https://developer.android.com/reference/android/webkit/WebView#loadUrl(java.lang.String)

[10]https://codesearch.alipay.com/source/xref/Android_wallet_master/android-phone-nebula-git/nebula/js/h5_bridge.js?r=78c30345[11]https://developer.mozilla.org/en-US/docs/Web/API/Console/log[12]https://codesearch.alipay.com/source/xref/Android_wallet_master/android-ariver/js/workerjs_v8_origin.js?r=b59d7f92[13]https://codesearch.alipay.com/source/xref/Android_wallet_master/android-ariver/js/workerjs_v8_origin.js?r=b59d7f92[14]https://github.com/eclipsesource/J2V8[15]https://opendocs.alipay.com/mini/plugin/plugin-introduction[16]https://v8.dev/docs/embed#security-model

 

責任編輯:武曉燕 來源: 51CTO專欄
相關推薦

2019-11-13 09:46:08

技術研發指標

2017-09-28 14:48:46

支付寶深度學習xNN

2012-11-21 17:37:46

Oracle技術嘉年華

2020-09-02 12:15:27

支付寶交警移動應用

2019-02-27 09:45:53

小程序開發者支付寶

2021-01-25 14:13:26

iOS支付寶支付

2021-09-09 15:30:28

鴻蒙HarmonyOS應用

2025-09-08 01:55:00

2014-11-17 10:52:56

支付寶去阿里化

2025-01-17 07:48:45

支付寶程序員技術圈

2022-01-07 10:28:49

支付寶體驗科技

2020-07-14 16:18:55

支付寶微信小程序

2009-09-17 12:15:28

互聯網

2017-11-21 17:21:42

WOT峰會

2018-03-27 12:02:31

央行支付寶紅包

2011-04-21 11:27:42

Firefox支付寶

2013-10-31 11:24:53

支付寶漏洞支付寶漏洞

2017-12-18 18:23:09

支付寶掃碼賺錢支付寶套路

2009-12-14 16:31:00

Linux安裝支付寶
點贊
收藏

51CTO技術棧公眾號

亚洲第一网站男人都懂| 亚洲精品综合在线| 国产精品成人播放| 成人午夜免费影院| 2021年精品国产福利在线| 偷拍一区二区三区| 午夜精品区一区二区三| www.热久久| 日韩和欧美一区二区三区| 操日韩av在线电影| 性少妇bbw张开| 精品视频在线观看免费观看 | 国产一区二区三区在线观看免费 | 黄瓜视频成人app免费| 中文字幕日韩av资源站| 美女主播视频一区| va婷婷在线免费观看| 销魂美女一区二区三区视频在线| 爱福利视频一区| 欧美 变态 另类 人妖| 国产精品一区免费在线| 色琪琪一区二区三区亚洲区| 九九久久九九久久| 日本视频在线| 久久久高清一区二区三区| 国产精品18毛片一区二区| 亚洲性在线观看| 欧美亚洲一区| 久久久人成影片一区二区三区| 国产又粗又黄又猛| 一道在线中文一区二区三区| 精品av久久707| 一区二区久久精品| 日韩毛片免费视频一级特黄| 91福利在线观看| 99爱视频在线| 国产亚洲成av人片在线观看| 亚洲欧美视频在线观看视频| 日韩av不卡在线播放| 欧美77777| 成人黄色在线视频| yy111111少妇影院日韩夜片| 97在线播放免费观看| 捆绑调教美女网站视频一区| 国产aⅴ夜夜欢一区二区三区| 色播视频在线播放| 一本色道久久综合| 久久久久亚洲精品成人网小说| 欧美片一区二区| 国产精品a级| 欧美日本在线视频中文字字幕| fc2ppv在线播放| 97欧美在线视频| 精品国产拍在线观看| 潮喷失禁大喷水aⅴ无码| 久久av影视| 亚洲天堂男人天堂女人天堂| 人妻aⅴ无码一区二区三区| 香蕉久久精品| 亚洲片av在线| 国产7777777| 99精品在线| 久久五月天色综合| 久草资源在线视频| 亚洲性色视频| 日av在线播放中文不卡| 久久国产香蕉视频| 黄页网站大全一区二区| av资源站久久亚洲| 天天干天天操av| 久久亚洲免费视频| 尤物一区二区三区| 四季久久免费一区二区三区四区| 亚洲一区中文在线| 18岁网站在线观看| av久久网站| 日韩欧美中文字幕精品| 欧美日韩人妻精品一区在线| 国产欧美一区| 久久亚洲精品国产亚洲老地址| 欧美又粗又大又长| 香蕉精品999视频一区二区| 国产精品久久久久一区二区| 国产高清精品软件丝瓜软件| 成人午夜碰碰视频| 日韩妆和欧美的一区二区| 国产精品久久麻豆| 午夜精品一区在线观看| 黄色片在线免费| 视频成人永久免费视频| 日韩精品免费在线视频观看| 久久嫩草捆绑紧缚| 亚洲一区二区三区高清不卡| 国产欧美日韩精品丝袜高跟鞋| 午夜久久久久久久久久| 久久久久国产精品麻豆| 性生活免费观看视频| 欧美久久天堂| 欧美精品一二三| 精品人妻一区二区三区香蕉 | 亚洲性视频在线| 亚洲男人的天堂在线播放| 顶臀精品视频www| 久久久久久一区二区| 99re在线国产| 888av在线| 欧美午夜xxx| 性色av浪潮av| 精品视频免费在线观看| 午夜精品美女自拍福到在线| 国产一区二区三区黄片| 久久久久国产一区二区三区四区| 国产亚洲精品久久久久久久| 国产精品99久久久久久董美香| 亚洲国产一区二区三区在线观看| 三级全黄做爰视频| 手机精品视频在线观看| 国产日韩欧美一区二区| 天堂8中文在线| 欧美剧情片在线观看| a毛片毛片av永久免费| 精品动漫一区| 91视频99| av免费在线网站| 欧美男人的天堂一二区| 精品无码国产污污污免费网站| 亚洲久色影视| 亚洲综合社区网| 久草资源在线| 欧美男人的天堂一二区| 97在线观看免费视频| 亚洲欧美成人综合| 国产亚洲精品自在久久| 国产高清在线a视频大全| 91精品国产乱码久久蜜臀| 99国产精品免费| 日韩 欧美一区二区三区| 欧美自拍资源在线| 三级成人黄色影院| 亚洲欧美色图片| www.色国产| 久久精品一二三| 噼里啪啦国语在线观看免费版高清版| 香蕉久久夜色精品国产使用方法| 久久久久久999| 成人免费视频国产| 亚洲v日本v欧美v久久精品| 国内精品免费视频| 好吊日精品视频| 国产精华一区| 日韩激情电影| 亚洲人成电影网站色xx| 欧美一级做a爰片免费视频| 欧美激情一区二区三区全黄| 男人女人黄一级| 久久福利影院| 5566av亚洲| 白浆在线视频| 亚洲偷熟乱区亚洲香蕉av| 亚洲中文一区二区三区| 亚洲欧美日韩在线不卡| 国产大学生av| 亚洲欧美日韩一区在线观看| 日韩一区二区电影在线观看| 高清久久精品| 国自产精品手机在线观看视频| 三级在线电影| 欧美色偷偷大香| 国产精品九九九九九九| 9i在线看片成人免费| 免费看黄色一级大片| 亚洲国产精品久久久天堂| 国产伦精品一区二区三区照片91| 在线中文字幕播放| 久久久国产一区二区三区| 老熟妇高潮一区二区高清视频| 色悠悠久久综合| 182在线观看视频| 99久久精品久久久久久清纯| 国产成人综合一区| 午夜国产精品视频免费体验区| 久久国产手机看片| 青青久久精品| 欧美日韩国产va另类| 神马电影在线观看| 欧美肥妇毛茸茸| 在线观看国产亚洲| 18成人在线视频| 粉嫩av蜜桃av蜜臀av| 精品一区二区三区影院在线午夜| 18禁网站免费无遮挡无码中文| 你微笑时很美电视剧整集高清不卡| 国产精品视频网站| 国产传媒在线观看| www.欧美免费| 日韩美女一级视频| 日韩欧美一级精品久久| 天天爱天天做天天爽| 亚洲一区二区在线免费观看视频| 日本激情小视频| 成人午夜激情视频| 蜜桃福利午夜精品一区| 亚洲欧美日韩综合国产aⅴ| 久久久久久成人| 91社区国产高清| 久久久国产高清| 亚洲欧美自拍偷拍| 国产肉体xxxx裸体784大胆| 欧美aaaaa成人免费观看视频| 日韩成人三级视频| 久久一区二区三区电影| 快播亚洲色图| 91久久精品无嫩草影院 | 欧美爱爱视频网站| 免费成人结看片| 国产精品国产精品国产专区不卡| 欧美aaa级| 日本中文字幕不卡免费| 91精品国产黑色瑜伽裤| 久久综合色88| av网站大全在线观看| 亚洲人线精品午夜| 香蕉视频黄色片| 精品欧美乱码久久久久久 | 中文字幕 在线观看| 欧美精品videosex极品1| 黄a在线观看| 一本大道久久加勒比香蕉| 久久久久国产精品嫩草影院| 亚洲国产精品久久91精品| 亚洲成人久久精品| 欧美一级日韩不卡播放免费| 国产精品爽爽久久| 在线91免费看| 国产免费不卡av| 制服丝袜av成人在线看| 91午夜交换视频| 欧美高清视频在线高清观看mv色露露十八| 成人免费一级片| 欧美午夜宅男影院| 中文字幕第2页| 欧美日韩免费一区二区三区| 一区二区视频免费观看| 欧美日韩一区二区三区在线看| 成人h动漫精品一区二区下载| 色综合视频在线观看| 手机看片久久久| 91久久久免费一区二区| 无码人妻熟妇av又粗又大| 欧美又粗又大又爽| 亚洲天堂999| 欧美精品xxxxbbbb| 不卡av中文字幕| 亚洲福利小视频| 欧美一区二区三区少妇| 国产亚洲一区二区精品| 性开放的欧美大片| 久久成人国产精品| 黄视频在线免费看| 51精品国产黑色丝袜高跟鞋| 欧美一区久久久| 国产美女高潮久久白浆| 亚洲电影一区| 精品久久蜜桃| 日韩久久视频| 三级在线免费观看| 1024日韩| 亚洲性生活网站| 狠狠色综合日日| 一级黄色免费视频| 久久久精品人体av艺术| 激情无码人妻又粗又大| 亚洲国产成人tv| 一级片视频在线观看| 欧美日韩精品欧美日韩精品一综合| 国产高潮在线观看| 日韩高清欧美高清| 婷婷成人激情| 91精品国产高清久久久久久久久| 最新日韩三级| 2022国产精品| 免费精品国产| 欧美日韩亚洲国产成人| 日韩午夜高潮| 黄色一级片免费的| 99视频在线精品| 日本激情视频一区二区三区| 午夜精品久久久久久久久久 | 日韩区国产区| 欧美视频二区| 久久久久免费精品| 国产成人午夜99999| 久久精品视频18| 一区二区三区四区五区视频在线观看| 久久99国产综合精品免费| 7777女厕盗摄久久久| 天堂91在线| 欧美另类99xxxxx| 欧美日韩尤物久久| 国产一区二区三区免费不卡| 999国产精品视频| 无码精品国产一区二区三区免费| 国产精品综合av一区二区国产馆| 亚洲成人网在线播放| 一区二区三区 在线观看视频| 丰满人妻老熟妇伦人精品| 精品日产卡一卡二卡麻豆| av电影在线观看一区二区三区| 国内精品久久久久久久| 懂色av色香蕉一区二区蜜桃| 奇米888一区二区三区| 亚洲国产日本| 免费看91视频| 一区精品在线播放| 中文字幕免费高清在线观看| 亚洲男人天堂2023| 国产黄大片在线观看| 99国产视频| 中文字幕亚洲综合久久五月天色无吗''| 黄色片一级视频| 91免费看片在线观看| 日本少妇性生活| 欧美变态tickling挠脚心| 国产黄色在线网站| 国产精品综合不卡av| 精品日本12videosex| 超碰网在线观看| 26uuu国产日韩综合| 人人干人人干人人干| 精品国产不卡一区二区三区| 手机在线免费观看av| 亚洲va国产va天堂va久久| 婷婷综合激情| 午夜av中文字幕| 亚洲欧美经典视频| 国产熟女一区二区三区四区| www.亚洲成人| 在线成人免费| 国产盗摄视频在线观看| 国产中文字幕一区| 久久久精品视频免费观看| 欧美一区二区三区的| 亚洲www色| 国产精品免费一区二区三区观看 | 国产视频在线视频| 国产丝袜美腿一区二区三区| 精品久久久久久久久久久久久久久久久久| 精品小视频在线| 深夜视频一区二区| 一本久道久久综合狠狠爱亚洲精品| 久久综合综合久久综合| 欧美做爰爽爽爽爽爽爽| 日韩视频一区二区在线观看| 男女视频在线| 狠狠色综合网站久久久久久久| 国产欧美大片| 亚洲精品国产一区黑色丝袜| 欧美性一区二区| 国产成人无吗| 国产一区二区三区四区五区加勒比| 国产毛片一区| 国产精品久久久久久成人| 欧美一区二区三区免费| 好看的中文字幕在线播放| 国产在线精品一区二区三区| 老牛国产精品一区的观看方式| 国产精品综合激情| 日韩欧美中文字幕公布| 国产99在线| 亚洲精品第一区二区三区| 国产精品一级在线| 成人午夜视频精品一区| 在线播放日韩精品| 久久影院一区二区三区| 男女超爽视频免费播放| 国产日韩精品一区| 亚洲大尺度网站| 国产精品成人va在线观看| 91精品婷婷色在线观看| 30一40一50老女人毛片| 欧美精品一级二级三级| 国产精品yjizz视频网| 亚洲啪啪av| 成人国产精品免费观看| 最近中文字幕在线视频| 久久久久久久久综合| 国内精品久久久久久久影视简单| 久久精品国产99久久99久久久| 欧美日韩免费区域视频在线观看| 亚洲1卡2卡3卡4卡乱码精品| 国产精品久久亚洲| 日本aⅴ精品一区二区三区| 国产无遮挡免费视频| 日韩在线免费高清视频| 神马久久影院| 无人码人妻一区二区三区免费| 色国产精品一区在线观看| 日韩电影免费观看| 午夜精品福利一区二区| 91免费版在线|