返回顶部
首页 > 资讯 > 前端开发 > JavaScript >详解vue3沙箱机制
  • 771
分享到

详解vue3沙箱机制

2024-04-02 19:04:59 771人浏览 安东尼
摘要

目录前言浏览器编译版本本地预编译版本总结参考前言 vue3 沙箱主要分两种 浏览器编译版本,浏览器版本是使用with语法加上proxy代理拦截 本地预编译版本,通

前言

vue3 沙箱主要分两种

  1. 浏览器编译版本,浏览器版本是使用with语法加上proxy代理拦截
  2. 本地预编译版本,通过在模版预编译阶段转换阶段,使用转换插件transfORMExpression将非白名单标识符挂在在组件代理对象下

浏览器编译版本

render 函数编译结果


<div>{{test}}</div>
<div>{{Math.floor(1)}}</div>

to


const _Vue = Vue;

return function render(_ctx, _cache, $props, $setup, $data, $options) {
  with (_ctx) {
    const {
      toDisplayString: _toDisplayString,
      createVnode: _createVNode,
      Fragment: _Fragment,
      openBlock: _openBlock,
      createBlock: _createBlock,
    } = _Vue;

    return (
      _openBlock(),
      _createBlock(
        _Fragment,
        null,
        [
          _createVNode("div", null, _toDisplayString(test), 1 ),
          _createVNode(
            "div",
            null,
            _toDisplayString(Math.floor(1)),
            1 
          ),
        ],
        64 
      )
    );
  }
};

从上面的代码,我们能发现,变量标识符没有增加前缀,只是用with语法包裹了一下,延长作用域链,那么是如何做到 js 沙箱拦截的呢?例如变量test,理论上说,当前作用域链没有test变量,变量会从上一层作用域查找,直到查找到全局作用域,但是,实际上只会在_ctx上查找,原理很简单,_ctx是一个代理对象,那么我们如何使用Proxy做拦截,示例代码如下:


const GLOBALS_WHITE_LISTED =
  "Infinity,undefined,NaN,isFinite,isNaN,parseFloat,parseInt,decodeURI," +
  "decodeURIComponent,encodeURI,encodeURIComponent,Math,Number,Date,Array," +
  "Object,Boolean,String,RegExp,Map,Set,JSON,Intl,BigInt";

const isGloballyWhitelisted = (key) => {
  return GLOBALS_WHITE_LISTED.split(",").includes(key);
};

const hasOwn = (obj, key) => {
  return Object.prototype.hasOwnProperty.call(obj, key);
};

const origin = {};
const _ctx = new Proxy(origin, {
  get(target, key, reciever) {
    if (hasOwn(target, key)) {
      Reflect.get(target, key, reciever);
    } else {
      console.warn(
        `Property ${JSON.stringify(key)} was accessed during render ` +
          `but is not defined on instance.`
      );
    }
  },
  has(target, key) {
    // 如果是 全局对象 返回false,不触发get 拦截,从上一层作用域查找变量
    // 如果不是 全局对象 返回true,触发get 拦截
    return !isGloballyWhitelisted(key);
  },
});

代码很简单,为什么这么简单的代码就能做到拦截?
因为 with 语句会触发 has 拦截,当 has 返回 true,就会 触发代理对象 get 拦截,如果返回 false, 则代理对象 get 拦截不会触发,变量不在当前代理对象查找,直接查找更上一层作用域

本地预编译版本


<div>{{test}}</div>
<div>{{Math.floor(1)}}</div>

to


import {
  toDisplayString as _toDisplayString,
  createVNode as _createVNode,
  Fragment as _Fragment,
  openBlock as _openBlock,
  createBlock as _createBlock,
} from "vue";

export function render(_ctx, _cache, $props, $setup, $data, $options) {
  return (
    _openBlock(),
    _createBlock(
      _Fragment,
      null,
      [
        _createVNode("div", null, _toDisplayString(_ctx.a), 1 ),
        _createVNode(
          "div",
          null,
          _toDisplayString(Math.floor(1)),
          1 
        ),
      ],
      64 
    )
  );
}

从上面的代码我们可以发现,非白名单标识符都添加了_ctx 变量前缀,那么是如何做到的呢?当本地编译 template 时,处于转换阶段时会对 变量表达式节点NodeTypes.SIMPLE_EXPRESSION进行添加前缀处理,示例代码如下:


const GLOBALS_WHITE_LISTED =
  "Infinity,undefined,NaN,isFinite,isNaN,parseFloat,parseInt,decodeURI," +
  "decodeURIComponent,encodeURI,encodeURIComponent,Math,Number,Date,Array," +
  "Object,Boolean,String,RegExp,Map,Set,JSON,Intl,BigInt";

const isGloballyWhitelisted = (key) => {
  return GLOBALS_WHITE_LISTED.split(",").includes(key);
};
const isLiteralWhitelisted = (key)=>{
  return 'true,false,null,this'.split(',').includes(key)
}
export function processExpression(
  node
) {
  const rewriteIdentifier = (raw) => {
    return `_ctx.${raw}`
  }
  const rawExp = node.content
  if (isSimpleIdentifier(rawExp)) {
    const isAllowedGlobal = isGloballyWhitelisted(rawExp)
    const isLiteral = isLiteralWhitelisted(rawExp)
    if (!isAllowedGlobal && !isLiteral) {
      node.content = rewriteIdentifier(rawExp)
    }
    return node
  }

当然上面的代码只是简化版本,原版插件还做了精确到了__props $setup,减短变量查询路径,提高性能,还有通过babel编译复杂表达式比如:箭头函数。

总结

整个 vue3 js 沙箱机制就解释结束了,当初浏览器编译版本困扰了我很久,因为不知道 has 可以拦截 with 语句变量查询

参考

Proxy handler.has
说说 JS 中的沙箱
动手写 js 沙箱

 到此这篇关于详解vue3 沙箱机制的文章就介绍到这了,更多相关vue3 沙箱机制内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

--结束END--

本文标题: 详解vue3沙箱机制

本文链接: https://lsjlt.com/news/123675.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • 详解vue3沙箱机制
    目录前言浏览器编译版本本地预编译版本总结参考前言 vue3 沙箱主要分两种 浏览器编译版本,浏览器版本是使用with语法加上proxy代理拦截 本地预编译版本,通...
    99+
    2024-04-02
  • 详解vue3的沙箱机制
    目录前言浏览器编译版本本地预编译版本总结前言 vue3 沙箱主要分两种 浏览器编译版本,浏览器版本是使用with语法加上proxy代理拦截 本地预编译版本,通过在...
    99+
    2024-04-02
  • vue3的沙箱机制是什么
    今天就跟大家聊聊有关vue3的沙箱机制是什么,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。vue3 沙箱主要分两种浏览器编译版本,浏览器版本是使用with语法加上proxy代理拦截本...
    99+
    2023-06-14
  • android沙箱机制是什么
    Android沙箱机制是一种安全机制,用于隔离不同应用程序之间的访问权限,确保应用程序只能访问其被授权的资源和数据。它通过将每个应用...
    99+
    2023-08-26
    android
  • docker怎么使用沙箱机制
    Docker使用了Linux内核提供的沙箱机制来隔离应用程序的运行环境。下面是使用Docker的沙箱机制的步骤:1. 安装Docke...
    99+
    2023-09-20
    docker
  • android沙箱机制怎么应用
    Android沙箱机制是指将每个应用程序都限制在自己的运行环境中,不能访问其他应用程序的资源和数据。应用程序之间相互隔离,提高了系统...
    99+
    2023-09-20
    android
  • 详解Android应用沙盒机制
    目录前言一、Android应用DAC沙盒二、Android应用权限三、应用信息的存储四、应用权限的映射五、应用的SELinux标签六、Android应用MAC沙盒前言 Androi...
    99+
    2024-04-02
  • quickjs 封装 JavaScript 沙箱详情
    目录1、场景2、简化底层 api2.1自动调用 dispose 2.2 提供更好的创建 vm 值的方法3、实现 console/setTimeout/setInterval 等常见 ...
    99+
    2024-04-02
  • WebWorker 封装 JavaScript 沙箱详情
    目录1、场景2、实现 IJavaScriptShadowbox2.1 主线程的实现2.2 web worker 线程的实现3、使用 WebWorkerShadowbox/WebWor...
    99+
    2024-04-02
  • Java应用程序的安全沙箱机制是什么
    这篇“Java应用程序的安全沙箱机制是什么”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“Java应用程序的安全沙箱机制是什么...
    99+
    2023-06-03
  • Qiankun原理详解JS沙箱是如何做隔离
    目录前言复习一下沙箱SanpshotSandboxLegacySandboxProxySandbox隔离原理XXX is undefined总结前言 相信大家也知道 qiankun ...
    99+
    2024-04-02
  • 如何解决Flex安全沙箱问题
    这篇文章主要为大家展示了“如何解决Flex安全沙箱问题”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“如何解决Flex安全沙箱问题”这篇文章吧。Flex安全沙箱问题的解决关于Flex安全沙箱问题的...
    99+
    2023-06-17
  • Flex如何解决安全沙箱问题
    这篇文章将为大家详细讲解有关Flex如何解决安全沙箱问题,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。跨域文件读取方法一:在目标服务器上布署crossdomain.xml文件(我用的此方法很管用,放上就没...
    99+
    2023-06-17
  • PythonPyecharts绘制箱线图详解
    本篇博客只是单纯的记录一下自己学习Boxplot,没有过多的解释,官网:》》Boxplot import seaborn as sns import numpy as np impo...
    99+
    2024-04-02
  • 举例详解iOS开发过程中的沙盒机制与文件
    iOS沙盒机制  iOS应用程序只能在为该改程序创建的文件系统中读取文件,不可以去其它地方访问,此区域被成为沙盒,所以所有的非代码文件都要保存在此,例如图像,图标,声音,映...
    99+
    2022-05-18
    iOS
  • 微前端qiankun沙箱实现源码解读
    目录前言LegacySandbox单实例沙箱ProxySandbox多实例沙箱SapshotSandbox 快照沙箱结束语前言 上篇我们介绍了微前端实现沙箱的几种方式,没看过的可以下...
    99+
    2024-04-02
  • Java--装箱和拆箱详解
    目录装箱拆箱==null总结装箱 八大基本类型都有一个与之对应的类: 基本类型 类 ...
    99+
    2024-04-02
  • Python Matplotlib绘制箱线图boxplot()函数详解
    目录箱线图boxplot()函数还提供了丰富的自定义选项箱线图通常用在多组数据比较时补充:plt.boxplot()函数绘制箱图、常用方法实战常用方法总结 箱线图 箱线图一...
    99+
    2024-04-02
  • 深度解析 Vue3 的响应式机制
    目录什么是响应式响应式原理定制响应式数据Vueuse 工具包什么是响应式 响应式一直都是 Vue 的特色功能之一;与之相比,JavaScript 里面的变量,是没...
    99+
    2024-04-02
  • Flex跨域访问沙箱问题的解决方案是什么
    Flex跨域访问沙箱问题的解决方案是什么,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。当Flex访问WebService服务时,在本地能够正常访问,当部署到we...
    99+
    2023-06-17
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作