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

造輪子利器:AST與前端編譯

開發(fā) 前端
為了補充這些缺少的部分,接下來移動到下一個單詞,生成token,并且將其轉(zhuǎn)換成子節(jié)點,添加進現(xiàn)有的ast中,然后重復(fù)這個 移動&生成 的遞歸的過程。

本文為來自 字節(jié)教育-成人與創(chuàng)新前端團隊 成員的文章,已授權(quán) ELab 發(fā)布。

簡介

在計算機科學中,抽象語法樹是源代碼語法結(jié)構(gòu)的一種抽象表示。它以樹狀的形式表現(xiàn)編程語言的語法結(jié)構(gòu),樹上的每個節(jié)點都表示源代碼中的一種結(jié)構(gòu)。之所以說語法是“抽象”的,是因為這里的語法并不會表示出真實語法中出現(xiàn)的每個細節(jié)。

——維基百科

在前端基建中,ast可以說是必不可少的。對ast進行操作,其實就相當于對源代碼進行操作。

ast的應(yīng)用包括:

  1. 開發(fā)輔助:eslint、prettier、ts檢查
  2. 代碼變更:壓縮、混淆、css modules
  3. 代碼轉(zhuǎn)換:jsx、vue、ts轉(zhuǎn)換為js

ast的生成

通過詞法分析和語法分析,可以得出一顆ast。

  1. 詞法分析

詞法分析的過程是將代碼喂給有限狀態(tài)機,結(jié)果是將代碼單詞轉(zhuǎn)換為令牌(token),一個token包含的信息包括其的種類、屬性值等。

例如將 ??const a = 1 + 1?? 轉(zhuǎn)換為token的話,結(jié)果大概如下

[
{type: 關(guān)鍵字, value: const},
{type: 標識符, value: a},
{type: 賦值操作符, value: =},
{type: 常數(shù), value: 1},
{type: 運算符, value: +},
{type: 常數(shù), value: 1},
]
  1. 語法分析

面對一串代碼,先通過詞法分析,獲得第一個token,為其建立一個ast節(jié)點,此時的ast節(jié)點的屬性以及子節(jié)點都不完整。

為了補充這些缺少的部分,接下來移動到下一個單詞,生成token,并且將其轉(zhuǎn)換成子節(jié)點,添加進現(xiàn)有的ast中,然后重復(fù)這個 移動&生成 的遞歸的過程。

  • 讓我們來看看const a = 1是怎么變成一顆ast的。
  1. 讀取const,生成一個VariableDeclaration節(jié)點
  2. 讀取a,新建VariableDeclarator節(jié)點
  3. 讀取=
  4. 讀取1,新建NumericLiteral節(jié)點
  5. 將NumericLiteral賦值給VariableDeclarator的init屬性
  6. 將VariableDeclarator賦值給VariableDeclaration的declaration屬性

前端編譯

隨著前端技術(shù)和理念的不斷進步,涌現(xiàn)了各種新奇的代碼以及帶來了新的項目組織方式。

但在這些新技術(shù)中,有許多代碼不能在瀏覽器中直接執(zhí)行,比如typescript、jsx等,這種情況下我們的項目就需要通過編譯、打包,將其轉(zhuǎn)換為可以直接在瀏覽器中執(zhí)行的代碼。

以webpack為例,打包工具作用就是基于代碼的import、export、require構(gòu)建依賴樹,將其做成一個或多個bundles。它解決的是模塊化的問題,但它自帶的能力只能支持javascript以及json文件,而平時我們遇到的ts、jsx、vue文件,則需要先經(jīng)過編譯工具的編譯。例如如果我們想用webpack對含有ts文件的項目進行打包,進行如下配置。

// webpack.config.js
const path = require('path');

module.exports = {
// ...
module: {
rules: [{
test: /.ts$/,
use: 'babel-loader',
options: {
presets: [
'@babel/typescript'
]
}
}],
},
};

配置的含義則是:當webpack解析到.ts文件時,先使用babel-loader進行轉(zhuǎn)換,再進行打包。

操作ast進行代碼編譯

?編譯工具?

常見的編譯工具有這幾種

  1. babel:目前最主流的編譯工具,使用javascript編寫。
  2. esbuild:使用Go語言開發(fā)的打包工具(也包含了編譯功能), 被Vite用于開發(fā)環(huán)境的編譯。
  3. swc:使用rust編寫的編譯工具。

在對外提供直接操作ast的能力上,babel和swc使用的是訪問者模式,插件編寫上有較多的共通之處,最大的區(qū)別就是語言不同。esbuild沒有對外提供直接操作ast的能力,但是可以通過接入其他的編譯工具達到操作ast的效果。

編譯過程

代碼編譯的過程分為三步,接(parse)、化(transform)、發(fā)(generate)

parse的過程則是上文中提到的,將代碼從字符串轉(zhuǎn)化為樹狀結(jié)構(gòu)的ast。

transform則是對ast節(jié)點進行遍歷,遍歷的過程中對ast進行修改。

generate則是將被修改過的ast,重新生成為代碼。

編譯插件

一般我們提起babel,就會想到是用來將新標準的js轉(zhuǎn)化為兼容性更高的舊標準js。

如果babel默認的編譯效果不能滿足我們的需求,那我們要如何插手編譯過程,將ast修改成我們想要的ast呢。此時就需要用到babel plugin,也就是babel插件。

就如同上文中的配置

const path = require('path');

module.exports = {
module: {
rules: [{
test: /.ts$/,
use: 'babel-loader',
options: {
presets: [
// presets也就是已經(jīng)配置好的插件集合,也就是“預(yù)設(shè)”
'@babel/preset-typescript'
]
}
}],
},
};

除了以上將typescript轉(zhuǎn)換為javscript的插件外,日常中我們還會用到許多其他的插件/預(yù)設(shè),例如

  • @babel/react 轉(zhuǎn)換react文件
  • react-refresh/babel 熱刷新
  • babel-plugin-react-css-modules css模塊化 避免樣式污染
  • istanbul 收集代碼覆蓋率
  • ......

Hello plugin!

babel在將代碼轉(zhuǎn)換為ast后,會對ast進行遍歷,在遍歷時,會應(yīng)用插件所提供的訪問者對相應(yīng)的ast節(jié)點進行訪問,以達到修改ast的目的。

我們在編寫插件時,首先我們需要知道我們想要訪問的ast節(jié)點對應(yīng)的類型是什么。假如我們要對函數(shù)類型的ast節(jié)點進行修改,先來看看這一段代碼經(jīng)過babel的轉(zhuǎn)換以后會生成什么樣的ast。

https://astexplorer.net/

function a() {};
const b = function() {
}
const c = () => {};

ast:(刪除部分結(jié)構(gòu)后)

 [
{
"type": "FunctionDeclaration",
"id": {
"type": "Identifier",

"name": "a"
}
},
{
"type": "VariableDeclaration",
"declarations": [
{
"type": "VariableDeclarator",
"id": {
"type": "Identifier",
"name": "b"
},
"init": {
"type": "FunctionExpression",
}
}
],
"kind": "const"
},
{
"type": "VariableDeclaration",
"declarations": [
{
"type": "VariableDeclarator",
"id": {
"type": "Identifier",
"name": "c"
},
"init": {
"type": "ArrowFunctionExpression",
}
}
],
"kind": "const"
}
]

新建my-plugin.js,在其中編寫如下代碼,對外暴露出訪問者,babel在遍歷到對應(yīng)節(jié)點時會調(diào)用相應(yīng)的訪問者。

// my-plugin.js
module.exports = () => ({
visitor: {
// 對一種ast節(jié)點進行訪問
FunctionDeclaration: {
enter: enterFunction,
// 在babel對ast進行深度優(yōu)先遍歷時,
// 我們有enter和exit兩次機會訪問同一個ast節(jié)點。
exit: exitFunction
},
// 對多種ast節(jié)點進行訪問
"FunctionDeclaration|FunctionExpression|ArrowFunctionExpression": {
enter: enterFunction
}
// 使用“別名”進行訪問
Function: enterFunction
}
})

function enterFunction() {
console.log('hello plugin!')
};
function exitFunction() {};

接入插件

// .babelrc
{
"plugins": [
'./my-plugin.js'
]
}

實踐

接下來我們來通過編寫一個完整的babel插件來看看如何對ast進行修改:打印出函數(shù)的執(zhí)行時間

代碼:

async function a() {
function b() {
for (let i = 0; i < 10000000; i += Math.random()) {}
}
b();
await new Promise(resolve => {
setTimeout(resolve, 1000);
})
}

運行效果:

b cost: 219 // 函數(shù)b耗時219毫秒
anonymous cost: 0 // promise中的匿名函數(shù)耗時0毫秒
a cost: 1222 // 函數(shù)a耗時1222毫秒

實現(xiàn)思路:在函數(shù)的第一行,插入一個ast節(jié)點,定義一個變量記錄剛開始執(zhí)行函數(shù)的時間。在函數(shù)的的最后一行,以及return時,打印出當前時間與開始時間的差。

新增&插入節(jié)點

除了手寫一個ast節(jié)點以外我們可以通過兩種babel為我們提供的輔助工具生成ast節(jié)點

@babel/types

一個工具集,可以用來新建、校驗節(jié)點等。

在這里我們需要新建一個 var fnName_start_time = Date.now()的ast節(jié)點。

import * as t from 'babel-types';

function functionEnter(path, state) {
const node = path.node;
const fnName = node.name || node.id?.name || 'anonymous';
// 新建一個變量聲明
const ast = t.variableDeclarator(
// 變量名
t.identifier(`${fnName}_start_time`),
// Date.now()
t.callExpression(
t.memberExpression(
t.identifier('Date'),
t.identifier('now')
),
// 參數(shù)為空
[]
)
);
}

@babel/template

通過模板的方式,可以直接將代碼轉(zhuǎn)換成ast,也可以替換掉模版中的節(jié)點,方便快捷。

import template from "babel-template";

const varName = `${fnName}_start_time`;
// 直接通過代碼生成
const ast = template(`const ${varName} = Date.now()`)();
// 或者
const ast = template('const fnName = Date.now()')({
fnName: t.identifier(varName)
})

在生成了我們想要的ast節(jié)點后,我們可以將其插入到我們現(xiàn)有的節(jié)點中。

function functionEnter(path, state) {
const node = path.node;
const fnName = node.name || node.id?.name || 'anonymous';
const varName = `${fnName}_start_time`;
const start = template(`const ${varName} = Date.now()`)();
const end = template(
`console.log('${fnName} cost:', Date.now() - ${varName})`
)();

if (!node.body) {
return;
}
// 插入到容器中,函數(shù)的第一行添加const fnName_start_time = Date.now()
path.get('body').unshiftContainer('body', start);
path.get('body').pushContainer('body', end);
}

module.exports = () => ({
visitor: {
Function: enterFunction
}
})

主動遍歷&停止遍歷&狀態(tài)

雖然我們在函數(shù)的第一行和最后一行添加了相應(yīng)的代碼,但是還是不能完整的實現(xiàn)我們需要的功能——如果函數(shù)在執(zhí)行最后一行之前進行了return,則不能打印出耗時數(shù)據(jù)。

找出該函數(shù)進行return的ast節(jié)點,在return之前,先把函數(shù)的耗時打印出來。

function a() {
if (Math.random() > 0.5) {
// 需要逮出來的return
return 'a';
}
function b() {
// 需要跳過的return
return 'b';
}
}

通過主動遍歷的方法,我們把returnStatement的訪問者放到Function的訪問者中。

當我們進行主動遍歷時,需要跳過子節(jié)點中的函數(shù)節(jié)點的遍歷,因為我們的目的只是在遍歷函數(shù)a節(jié)點時,訪問其return,而不想去修改子函數(shù)節(jié)點的return。

function functionEnter(path, state) {
// 主動遍歷
path.traverse({
// 訪問遍歷到子函數(shù),則跳過子函數(shù)及其的子節(jié)點遍歷
Function(innerPath) {
innerPath.skip();
},
// 訪問類型為ReturnStatement的子節(jié)點
ReturnStatement: returnEnter
// 傳遞狀態(tài)
}, { fnName })
}

function returnEnter(path, state) {
// 讀取狀態(tài)
const { fnName } = state;

// 代碼為resutn xxx; 新建 const fnName_result = xxx 的節(jié)點
const resultVar = t.identifier(`${fnName}_result`);
const returnResult = template(`const RESULT_VAR = RESULT`)({
RESULT_VAR: resultVar,
RESULT: path.node.argument || t.identifier('undefined')
})

// 插入兄弟節(jié)點
path.insertBefore(returnResult);

// 修改return xxx為
// return (console.log('耗時'), fnName_result)
const varName = `${fnName}_start_time`;
const end = template(
`console.log('${fnName} cost:', Date.now() - ${varName})`
)();
const ast = t.sequenceExpression([
end.expression,
resultVar
]);
path.node.argument = ast;
}

最終效果

// 原代碼
function a() {
function b() {
for (let i = 0; i < 10000000; i += Math.random()) {}
function c() {
for (let i = 0; i < 10000000; i += Math.random()) {}
}
return c();
}
b();
for (let i = 0; i < 10000000; i += Math.random()) {}
}
// 經(jīng)過babel編譯的代碼
function a() {
var a_start_time = Date.now();
function b() {
var b_start_time = Date.now();
for (var i = 0; i < 10000000; i += Math.random()) {}
function c() {
var c_start_time = Date.now();
for (var _i = 0; _i < 10000000; _i += Math.random()) {}
console.log('c cost:', Date.now() - c_start_time);
}
var b_result = c();
return console.log('b cost:', Date.now() - b_start_time), b_result;
console.log('b cost:', Date.now() - b_start_time);
}
b();
for (var i = 0; i < 10000000; i += Math.random()) {}
console.log('a cost:', Date.now() - a_start_time);
}
// 運行后控制臺打印結(jié)果
c cost: 290
b cost: 603
a cost: 895
責任編輯:武曉燕 來源: ELab團隊
相關(guān)推薦

2024-05-30 07:07:00

Virtual虛擬 DOM前端

2015-08-06 10:14:15

造輪子facebook

2023-02-06 17:27:48

2024-07-01 08:01:45

API網(wǎng)關(guān)接口

2021-08-03 10:43:17

AI 數(shù)據(jù)人工智能

2023-09-21 11:03:31

開發(fā)輪子工具

2020-09-08 08:45:39

jupyter插件代碼

2024-09-30 05:38:48

2021-01-11 11:36:23

鴻蒙HarmonyOSApp開發(fā)

2024-05-14 08:11:56

ReactuseState造輪子

2020-09-19 09:47:05

AI 數(shù)據(jù)人工智能

2021-10-08 23:07:02

工具AST編譯

2024-07-12 09:35:38

前端工具檢驗

2022-02-14 08:58:00

架構(gòu)

2022-04-27 20:02:22

Dubbo注冊中心開發(fā)

2025-06-26 01:25:00

2012-05-24 10:09:52

ibmdw

2023-09-25 06:37:19

前端開發(fā)工具

2021-03-15 07:57:02

SpringBoot 腳手架系統(tǒng)

2022-05-13 09:16:49

Python代碼
點贊
收藏

51CTO技術(shù)棧公眾號

欧美偷拍一区二区| 欧美成人精品三级网站| 国产精品天天看天天狠| 欧美性xxxxxxxxx| 视频一区二区在线观看| 99久久精品日本一区二区免费| 欧美精选一区| 亚洲人成亚洲人成在线观看| 中文字幕一区二区在线观看视频 | 国产精品午夜在线观看| 91九色综合久久| 天天综合网久久综合网| 国产精品久久久久久久免费观看| 亚洲成人激情图| 色综合色综合色综合色综合| 17videosex性欧美| 国产精品乱码久久久久久| 国产乱码精品一区二区三区不卡| 国语对白做受69按摩| 欧美激情日韩| 在线观看精品国产视频| 第四色在线视频| 国产成人久久精品一区二区三区| 欧美日韩一区免费| 777久久精品一区二区三区无码 | 亚洲视频分类| 欧美一区二区三区在线| 日日碰狠狠丁香久燥| 女同视频在线观看| 国产精品欧美一级免费| 久久国产精品高清| 午夜精品久久久久久久99老熟妇| 日本va欧美va欧美va精品| 色综合导航网站| 手机在线中文字幕| 欧美日韩国产免费观看视频| 日韩免费视频一区| 女同激情久久av久久| 日韩影片中文字幕| 欧美性高潮在线| 可以在线看的av网站| av网址在线看| 中文字幕亚洲欧美在线不卡| 色噜噜狠狠色综合网| 暖暖视频在线免费观看| 99精品国产99久久久久久白柏 | 亚洲另类av| 亚洲成人精品在线| 久久国产免费视频| 日韩不卡在线视频| 欧美一级高清片在线观看| 奇米视频7777| 在线欧美激情| 欧美一区二区三区电影| 欧洲美女亚洲激情| www.久久热| 欧美一级高清片| 苍井空张开腿实干12次| av综合网址| 精品成人佐山爱一区二区| 国产吃瓜黑料一区二区| 成人免费在线电影网| 精品美女一区二区| 免费黄色三级网站| 天天躁日日躁狠狠躁欧美巨大小说| 亚洲第一精品福利| 粉嫩av懂色av蜜臀av分享| 欧美顶级毛片在线播放| 日韩精品中文字幕久久臀| 一区二区三区免费在线观看视频 | 国产成人免费视频网站高清观看视频| 亚洲va码欧洲m码| 国产福利视频导航| 成人国产精品免费观看视频| 黄色国产精品一区二区三区| 亚洲欧洲综合在线| 国产午夜精品一区二区三区视频 | 99re视频在线观看| 免费av网站观看| 久久影视一区二区| 亚洲福利av在线| 成人午夜在线影视| 亚洲丰满少妇videoshd| 日韩欧美精品在线观看视频| 99re久久| 精品久久久久久久一区二区蜜臀| 国产精品无码在线| 精品日本12videosex| 久久国产一区二区三区| 激情五月婷婷小说| 久久亚洲风情| 91一区二区三区| 黄色av网站免费在线观看| 久久久久一区二区三区四区| 中文字幕中文字幕一区三区| ririsao久久精品一区| 色综合网色综合| 99视频在线观看视频| 免费看成人人体视频| 综合av色偷偷网| 免费一级特黄特色大片| 青青草精品视频| 国产成人女人毛片视频在线| h网站在线免费观看| 一区二区三区国产精品| mm1313亚洲国产精品无码试看| 福利一区三区| 国产午夜精品视频| 久久精品www人人爽人人| 日韩av中文在线观看| 国产传媒欧美日韩| 日韩在线观看www| 欧美日韩国产精品一区二区不卡中文| 999在线观看| 欧美天堂影院| 欧美多人爱爱视频网站| 国产91av在线播放| 成人av网址在线| 一区二区高清视频| 韩日毛片在线观看| 日韩女优电影在线观看| 亚洲区一区二区三| 久久这里有精品15一区二区三区| 99re在线| www.欧美日本韩国| 欧美老女人在线| 国产美女免费网站| 在线亚洲国产精品网站| 国产精品v欧美精品∨日韩| 在线免费黄色| 欧美日韩午夜影院| 国产在线综合视频| 国产精品主播| 久久综合入口| 午夜激情电影在线播放| 亚洲精品v欧美精品v日韩精品| 日本在线一级片| 狠狠色丁香久久婷婷综合_中| 日韩理论片在线观看| 成人一区福利| 亚洲欧美日韩直播| 亚洲婷婷综合网| 91丨九色丨蝌蚪富婆spa| 久久国产精品网| xvideos.蜜桃一区二区| 欧美日韩第一视频| 亚洲成人第一区| 一个色在线综合| 国产大尺度视频| 亚洲美女毛片| 国产在线精品一区二区三区》| brazzers在线观看| 亚洲福利视频二区| 亚洲 欧美 日韩 综合| 播五月开心婷婷综合| 青青青青草视频| 国产厕拍一区| 欧美在线激情网| 国产爆初菊在线观看免费视频网站 | 最新一区二区三区| 国产精品996| 日韩精品在线观看av| 国产精品色呦| 日韩69视频在线观看| 福利在线午夜| 欧美高清激情brazzers| 欧美黄色一区二区三区| 成人aaaa免费全部观看| 欧美亚洲精品一区二区| 国内精品久久久久久久影视简单| 国产精品久久久久久影视| 欧美成人二区| 亚洲的天堂在线中文字幕| www.国产一区二区| 亚洲欧美影音先锋| 无码人妻一区二区三区在线| 亚洲资源av| 一个色的综合| а√中文在线天堂精品| 欧美一区二三区| 视频免费一区| 精品国产伦一区二区三区免费| 国语对白永久免费| 亚洲视频在线观看一区| 亚洲色图欧美日韩| 日韩成人伦理电影在线观看| 日韩video| 亚瑟一区二区三区四区| 成人字幕网zmw| 亚洲精品永久免费视频| 国产性猛交xxxx免费看久久| 99国产精品久久久久久久成人 | 大型av综合网站| 国产成人精品免高潮在线观看| 超碰在线免费公开| 亚洲精品日韩丝袜精品| 国产伦理一区二区| 黑人巨大精品欧美一区免费视频| 亚洲人与黑人屁股眼交| 337p粉嫩大胆色噜噜噜噜亚洲| 手机在线国产视频| 久久一二三四| 国产精品一线二线三线| 欧美r级电影| 欧美日韩亚洲一区二区三区在线观看| 精品欧美视频| 国产精品免费网站| 免费h视频在线观看| 久久久极品av| 国产乱视频在线观看| 337p日本欧洲亚洲大胆色噜噜| 在线视频免费观看一区| 欧美性猛交xxxxx免费看| 69av视频在线| ●精品国产综合乱码久久久久| 51调教丨国产调教视频| 国产xxx精品视频大全| 激情五月俺来也| 久久久久在线| 欧美视频在线观看网站| 欧美aⅴ99久久黑人专区| 亚洲美女搞黄| 国产影视精品一区二区三区| 国产午夜精品在线| 亚洲一级大片| 成人激情av在线| 精品福利在线| 国产精品wwwwww| 超碰国产一区| 欧美亚洲视频在线观看| www.51av欧美视频| 久久久久久噜噜噜久久久精品| a毛片在线看免费观看| 久久精彩免费视频| 日本中文字幕伦在线观看| 一本色道久久88精品综合| 男女av在线| 亚洲欧美中文日韩在线v日本| 日韩一区二区三区在线观看视频| 欧美一级片免费看| 精品人妻无码一区二区色欲产成人| 欧美日韩精品一区二区三区四区 | 精品日韩在线一区| 精品国产乱码一区二区三| 欧美丰满嫩嫩电影| 国产乱人乱偷精品视频a人人澡| 欧美日韩精品福利| 国产又粗又长视频| 777色狠狠一区二区三区| 97视频免费在线| 日韩一区二区免费视频| www.色亚洲| 精品国产乱码久久久久久浪潮| 国产成人自拍一区| 亚洲第一综合天堂另类专| 婷婷色在线观看| 日韩www在线| 久久综合九色综合久| 中文字幕欧美精品日韩中文字幕| 求av网址在线观看| 久久国产精品99国产精| 蜜臀av在线| 51精品在线观看| 亚洲伦乱视频| 91久热免费在线视频| 精品中文在线| 久草热久草热线频97精品| 蜜桃一区二区三区| 亚洲电影网站| 国产综合婷婷| 精品久久久久久久免费人妻| 青青草国产成人av片免费| 日本在线视频播放| 99久久精品免费观看| 亚洲国产无码精品| 国产精品国产三级国产a| 九九热精彩视频| 色一区在线观看| 91亚洲国产成人久久精品麻豆| 日韩免费观看高清完整版| 手机在线精品视频| 最新国产精品拍自在线播放| av大片在线| 日韩免费在线看| 精品一区91| 欧美日韩在线精品| 综合激情视频| 妞干网在线免费视频| 国产一区二区剧情av在线| 菠萝菠萝蜜网站| 亚洲素人一区二区| 51国产偷自视频区视频| 欧美精品第一页| 深夜福利视频在线观看| 日韩视频免费大全中文字幕| 美女的胸无遮挡在线观看| 成人av色在线观看| 亚洲免费福利一区| 三年中国中文在线观看免费播放 | 亚洲国产成人va在线观看麻豆| 高清成人在线观看| 在线看片中文字幕| 五月综合激情日本mⅴ| 国产伦精品一区二区三区免.费 | 9a蜜桃久久久久久免费| 欧美日韩国产免费观看视频| 久久久性生活视频| 国内成+人亚洲+欧美+综合在线 | 五月婷婷六月色| 久久综合免费视频影院| gogo亚洲高清大胆美女人体| 动漫3d精品一区二区三区 | 亚洲欧洲一二区| 欧美高清性xxxxhd| 黄色在线一区| 国产精品中文久久久久久| 国产亚洲精品7777| 国产精品男女视频| 亚洲电影中文字幕| 欧美xxxx做受欧美88bbw| 91精品国产综合久久久久久久久| 亚洲国产精品嫩草影院久久av| 欧美中日韩在线| 久久se精品一区精品二区| 久久久久久国产精品无码| 五月婷婷综合激情| 亚洲精华国产精华精华液网站| 久久精品91久久香蕉加勒比 | 欧美撒尿777hd撒尿| 欧美女同网站| 青青草原成人在线视频| 老司机精品视频在线播放| 欧洲精品在线播放| 国产凹凸在线观看一区二区| 懂色av懂色av粉嫩av| 4438x亚洲最大成人网| 米奇精品一区二区三区| 国产精品网红直播| 久久国产精品成人免费观看的软件| 亚洲 中文字幕 日韩 无码| 91麻豆国产福利精品| 亚洲一区欧美在线| 亚洲国产精品成人一区二区| 波多野结衣精品| 国产伦一区二区三区色一情| 综合亚洲视频| 无码人妻一区二区三区一| 亚洲国产一区二区在线播放| 亚洲国产日韩在线观看| 国内精品久久久久久影视8| 国产66精品| 国产三区在线视频| 国产丝袜在线精品| 羞羞色院91蜜桃| 久久精品免费播放| 一区二区日韩| av免费看网址| 91丨九色porny丨蝌蚪| 高潮毛片又色又爽免费 | 免费看电影在线| 国产精品一区二区不卡视频| 99riav国产精品| 精品人妻互换一区二区三区| 欧洲一区二区av| 男人影院在线观看| 成人国产一区二区| 一区二区三区国产盗摄| 91精品人妻一区二区三区蜜桃欧美 | 一区二区三区| 黄色一级片在线看| 久久亚洲私人国产精品va媚药| 中文字幕视频免费观看| 欧美xxxx做受欧美| 牲欧美videos精品| 网站一区二区三区| 亚洲乱码中文字幕综合| 人妻无码中文字幕| 国产成人精品久久二区二区91| 午夜激情久久| 日本美女视频网站| 色婷婷av一区二区三区之一色屋| 在线观看免费黄视频| 国产不卡一区二区三区在线观看| 久久精品女人天堂| 日日噜噜夜夜狠狠久久波多野| 精品国产乱码久久久久久老虎| 欧美不卡高清一区二区三区| 97精品国产97久久久久久粉红| 91啪亚洲精品| 一本色道久久综合无码人妻| 久久久久免费精品国产| 精品视频黄色| 午夜影院福利社| 欧美在线一区二区| 都市激情久久综合| 亚洲一区3d动漫同人无遮挡| av不卡在线观看| 国产又粗又大又爽| 日本久久久久久久久久久| 久久中文视频|