日本综合一区二区|亚洲中文天堂综合|日韩欧美自拍一区|男女精品天堂一区|欧美自拍第6页亚洲成人精品一区|亚洲黄色天堂一区二区成人|超碰91偷拍第一页|日韩av夜夜嗨中文字幕|久久蜜综合视频官网|精美人妻一区二区三区

RELATEED CONSULTING
相關(guān)咨詢(xún)
選擇下列產(chǎn)品馬上在線(xiàn)溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問(wèn)題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營(yíng)銷(xiāo)解決方案
比Eval和Iframe更強(qiáng)的新一代JavaScript沙箱!

JavaScript 的運(yùn)行環(huán)境

領(lǐng)域(realm),這個(gè)詞比較抽象,其實(shí)就代表了一個(gè) JavaScript 獨(dú)立的運(yùn)行環(huán)境,里面有獨(dú)立的變量作用域。

創(chuàng)新互聯(lián)公司長(zhǎng)期為近千家客戶(hù)提供的網(wǎng)站建設(shè)服務(wù),團(tuán)隊(duì)從業(yè)經(jīng)驗(yàn)10年,關(guān)注不同地域、不同群體,并針對(duì)不同對(duì)象提供差異化的產(chǎn)品和服務(wù);打造開(kāi)放共贏平臺(tái),與合作伙伴共同營(yíng)造健康的互聯(lián)網(wǎng)生態(tài)環(huán)境。為慶安企業(yè)提供專(zhuān)業(yè)的網(wǎng)站制作、成都網(wǎng)站制作,慶安網(wǎng)站改版等技術(shù)服務(wù)。擁有十余年豐富建站經(jīng)驗(yàn)和眾多成功案例,為您定制開(kāi)發(fā)。

比如下面的代碼:




每個(gè) iframe 都有一個(gè)獨(dú)立的運(yùn)行環(huán)境,document 的全局對(duì)象不同于 iframe 的全局對(duì)象,類(lèi)似的,全局對(duì)象上的 Array 肯定也不同。

ShadowRealm API

ShadowRealm API 是一個(gè)新的 JavaScript 提案,它允許一個(gè) JS 運(yùn)行時(shí)創(chuàng)建多個(gè)高度隔離的 JS 運(yùn)行環(huán)境(realm),每個(gè) realm 具有獨(dú)立的全局對(duì)象和內(nèi)建對(duì)象。

ShadowRealm 具有下面的類(lèi)型簽名:

declare class ShadowRealm {
constructor();
evaluate(sourceText: string): PrimitiveValueOrCallable;
importValue(specifier: string, bindingName: string): Promise;
}

每個(gè) ShadowRealm 實(shí)例都有自己獨(dú)立的運(yùn)行環(huán)境,它提供了兩種方法讓我們來(lái)執(zhí)行運(yùn)行環(huán)境中的代碼:

  • .evaluate():同步執(zhí)行代碼字符串,類(lèi)似 eval()。
  • .importValue():返回一個(gè) Promise 對(duì)象,異步執(zhí)行代碼字符串。

shadowRealm.evaluate()

.evaluate() 的類(lèi)型簽名:

evaluate(sourceText: string): PrimitiveValueOrCallable;

.evaluate() 的工作原理很像 eval():

const sr = new ShadowRealm();
console.assert(
sr.evaluate(`'ab' + 'cd'`) === 'abcd'
);

但是與 eval() 不同的是,代碼是在 .evaluate() 的獨(dú)立運(yùn)行環(huán)境中執(zhí)行的:

globalThis.realm = 'incubator realm';

const sr = new ShadowRealm();
sr.evaluate(`globalThis.realm = 'ConardLi realm'`);
console.assert(
sr.evaluate(`globalThis.realm`) === 'ConardLi realm'
);

如果 .evaluate() 返回一個(gè)函數(shù),為了方便在外部調(diào)用這個(gè)函數(shù)會(huì)被包裝,然后在 ShadowRealm 中運(yùn)行:

globalThis.realm = 'incubator realm';

const sr = new ShadowRealm();
sr.evaluate(`globalThis.realm = 'ConardLi realm'`);

const wrappedFunc = sr.evaluate(`() => globalThis.realm`);
console.assert(wrappedFunc() === 'ConardLi realm');

每當(dāng)一個(gè)值傳入 ShadowRealm 時(shí),它必須是原始類(lèi)型或者可以被調(diào)用的。否則會(huì)拋出異常:

> new ShadowRealm().evaluate('[]')
TypeError: value passing between realms must be callable or primitive

shadowRealm.importValue()

.importValue() 的類(lèi)型簽名:

importValue(specifier: string, bindingName: string): Promise;

你可以直接導(dǎo)入一個(gè)外部的模塊,異步執(zhí)行并返回一個(gè) Promise,用法:

// main.js
const sr = new ShadowRealm();
const wrappedSum = await sr.importValue('./my-module.js', 'sum');
console.assert(wrappedSum('hi', ' ', 'folks', '!') === 'hi ConardLi!');

// my-module.js
export function sum(...values) {
return values.reduce((prev, value) => prev + value);
}

與 .evaluate() 一樣,傳入 ShadowRealms 的值(包括參數(shù)和跨環(huán)境函數(shù)調(diào)用的結(jié)果)必須是原始的或可調(diào)用的。

ShadowRealms 可以用來(lái)做什么?

  • 在 Web IDE 或 Web 繪圖應(yīng)用等程序中運(yùn)行插件等第三方代碼。
  • 在 ShadowRealms 中創(chuàng)建一個(gè)編程環(huán)境,運(yùn)行用戶(hù)代碼。
  • 服務(wù)器可以在 ShadowRealms 中運(yùn)行第三方代碼。
  • 在 ShadowRealms 中可以運(yùn)行測(cè)試,這樣外部的JS執(zhí)行環(huán)境不會(huì)受到影響,并且每個(gè)套件都可以在新環(huán)境中啟動(dòng)(這有助于提高可復(fù)用性)。
  • 網(wǎng)頁(yè)抓取(從網(wǎng)頁(yè)中提取數(shù)據(jù))和網(wǎng)頁(yè)應(yīng)用測(cè)試等可以在 ShadowRealms 中運(yùn)行。

與其他方案對(duì)比

eval()和Function

ShadowRealms 與 eval() 和 Function 很像,但比它們倆都好一點(diǎn):我們可以創(chuàng)建新的JS運(yùn)行環(huán)境并在其中執(zhí)行代碼,這可以保護(hù)外部的JS運(yùn)行環(huán)境不受代碼執(zhí)行的操作的影響。

Web Workers

Web Worker 是一個(gè)比 ShadowRealms 更強(qiáng)大的隔離機(jī)制。其中的代碼運(yùn)行在獨(dú)立的進(jìn)程中,通信是異步的。

但是,當(dāng)我們想要做一些更輕量級(jí)的操作時(shí),ShadowRealms 是一個(gè)很好的選擇。它的算法可以同步計(jì)算,更便捷,而且全局?jǐn)?shù)據(jù)管理更自由。

iframe

前面我們已經(jīng)提到了,每個(gè) iframe 都有自己的運(yùn)行環(huán)境,我們可以在里面同步執(zhí)行代碼。




與 ShadowRealms 相比,還是有以下缺點(diǎn):

  • 只能在瀏覽器中使用 iframe;
  • 需要向 DOM 添加一個(gè) iframe 以對(duì)其進(jìn)行初始化;
  • 每個(gè) iframe 環(huán)境都包含完整的 DOM,這在一些場(chǎng)景下限制了自定義的靈活度;
  • 默認(rèn)情況下,對(duì)象是可以跨環(huán)境的,這意味著需要額外的工作來(lái)確保代碼安全。

Node.js 上的 vm 模塊

Node.js 的 vm 模塊與 ShadowRealm API 類(lèi)似,但具有更多功能:緩存 JavaScript 引擎、攔截 import() 等等。但它唯一的缺點(diǎn)就是不能跨平臺(tái),只能在 Node.js 環(huán)境下使用。

用法示例:在 ShadowRealms 中運(yùn)行測(cè)試

下面我們來(lái)看個(gè)在 ShadowRealms 中運(yùn)行測(cè)試的小 Demo,測(cè)試庫(kù)收集通過(guò) test() 指定的測(cè)試,并允許我們通過(guò) runTests() 運(yùn)行它們:

// test-lib.js
const testDescs = [];

export function test(description, callback) {
testDescs.push({description, callback});
}

export function runTests() {
const testResults = [];
for (const testDesc of testDescs) {
try {
testDesc.callback();
testResults.push(`${testDesc.description}: OK\n`);
} catch (err) {
testResults.push(`${testDesc.description}: ${err}\n`);
}
}
return testResults.join('');
}

使用庫(kù)來(lái)指定測(cè)試:

// my-test.js
import {test} from './test-lib.js';
import * as assert from './assertions.js';

test('succeeds', () => {
assert.equal(3, 3);
});

test('fails', () => {
assert.equal(1, 3);
});

export default true;

在下一個(gè)示例中,我們動(dòng)態(tài)加載 my-test.js 模塊來(lái)收集然后運(yùn)行測(cè)試。

唉,目前還沒(méi)有辦法在不導(dǎo)入任何東西的情況下加載模塊。

這就是為什么在前面示例的最后一行中有一個(gè)默認(rèn)導(dǎo)出。我們使用 ShadowRealm .importvalue() 方法導(dǎo)入 default export 。

// test-runner.js
async function runTestModule(moduleSpecifier) {
const sr = new ShadowRealm();
await sr.importValue(moduleSpecifier, 'default');
const runTests = await sr.importValue('./test-lib.js', 'runTests');
const result = runTests();
console.log(result);
}
await runTestModule('./my-test.js');

在 ShadowRealms 中運(yùn)行 Web 應(yīng)用

jsdom 庫(kù)創(chuàng)建了一個(gè)封裝的瀏覽器環(huán)境,可以用來(lái)測(cè)試 Web 應(yīng)用、從 HTML 中提取數(shù)據(jù)等。它目前使用的是 Node.js vm 模塊,未來(lái)可能會(huì)更新為使用 ShadowRealms(后者的好處是可以跨平臺(tái),而 vm 目前只支持 Node.js)。


網(wǎng)站標(biāo)題:比Eval和Iframe更強(qiáng)的新一代JavaScript沙箱!
URL標(biāo)題:http://www.dlmjj.cn/article/dphidei.html