Skip to content

Commit 89fa964

Browse files
committed
first commit
0 parents  commit 89fa964

23 files changed

+772
-0
lines changed

.cspell.json

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
{
2+
"$schema": "https://raw.githubusercontent.com/streetsidesoftware/cspell/main/cspell.schema.json",
3+
"version": "0.2",
4+
"language": "en",
5+
"languageId": "typescript,javascript",
6+
"dictionaries": [
7+
"powershell",
8+
"typescript",
9+
"node"
10+
],
11+
"allowCompoundWords": true,
12+
"useGitignore": true,
13+
"ignorePaths": [
14+
".gitignore",
15+
"*.d.ts"
16+
],
17+
"words": [
18+
"arrayify",
19+
"bpvm",
20+
"lcov",
21+
"zhengxs"
22+
]
23+
}

.editorconfig

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# EditorConfig is awesome: https://EditorConfig.org
2+
3+
root = true
4+
5+
[*]
6+
charset = utf-8
7+
indent_size = 2
8+
indent_style = space
9+
indent_size = 2
10+
tab_width = 2
11+
continuation_indent_size = 4 # IntelliJ family IDEs
12+
insert_final_newline = true
13+
trim_trailing_whitespace = true
14+
15+
[*.md]
16+
trim_trailing_whitespace = false
17+
18+
[Makefile]
19+
indent_size = 4
20+
indent_style = tab

.gitattributes

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
pnpm-lock.yaml merge=text
2+
shrinkwrap.yaml merge=binary
3+
npm-shrinkwrap.json merge=binary
4+
yarn.lock merge=binary
5+
6+
*.json linguist-language=JSON-with-Comments
7+
8+
* text=auto eol=lf

.gitignore

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
.DS_store
2+
.history
3+
4+
node_modules
5+
6+
# git features
7+
.mailmap
8+
9+
# local env files
10+
.env.local
11+
.env.*.local
12+
13+
# Log files
14+
npm-debug.log*
15+
yarn-debug.log*
16+
yarn-error.log*
17+
pnpm-debug.log*
18+
19+
# Editor directories and files
20+
.idea
21+
# .vscode
22+
*.suo
23+
*.ntvs*
24+
*.njsproj
25+
*.sln
26+
*.sw?
27+
28+
# build artifacts
29+
dist/
30+
dist-types/
31+
32+
yarn.lock
33+
pnpm-lock.yaml
34+
package-lock.json

.node-version

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
22

.prettierrc

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
{
2+
"semi": true,
3+
"singleQuote": true,
4+
"overrides": [
5+
{
6+
"files": ".prettierrc",
7+
"options": {
8+
"parser": "json"
9+
}
10+
}
11+
]
12+
}

.vscode/launch.json

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
{
2+
// 使用 IntelliSense 了解相关属性。
3+
// 悬停以查看现有属性的描述。
4+
// 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387
5+
"version": "0.2.0",
6+
"configurations": [
7+
{
8+
"name": "Run Files",
9+
"type": "node",
10+
"request": "launch",
11+
"program": "${file}",
12+
"runtimeArgs": ["--no-warnings"],
13+
"runtimeExecutable": "tsx",
14+
"console": "integratedTerminal",
15+
"internalConsoleOptions": "neverOpen",
16+
"skipFiles": ["<node_internals>/**", "${workspaceFolder}/node_modules/**"]
17+
},
18+
{
19+
"name": "Watch Files",
20+
"type": "node",
21+
"request": "launch",
22+
"program": "${file}",
23+
"runtimeArgs": ["--no-warnings", "--watch"],
24+
"runtimeExecutable": "tsx",
25+
"console": "integratedTerminal",
26+
"internalConsoleOptions": "neverOpen",
27+
"skipFiles": ["<node_internals>/**", "${workspaceFolder}/node_modules/**"]
28+
}
29+
]
30+
}

LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2025 zhengxs2018
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

README.md

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
# bpvm
2+
3+
一个基于 Proxy 的浏览器沙箱,确保动态运行的代码,不会污染全局环境。
4+
5+
## 安装
6+
7+
```sh
8+
$ pnpm add bpvm
9+
```
10+
11+
### 使用
12+
13+
```ts
14+
import { runInNewContext } from 'bpvm'
15+
16+
window.globalVar = 3
17+
18+
const context = {
19+
globalVar: 1,
20+
}
21+
22+
runInNewContext('globalVar *= 2, context')
23+
24+
console.log(context)
25+
// Prints: { globalVar: 2 }
26+
27+
console.log(window.globalVar)
28+
// Prints: 3
29+
```
30+
31+
## 本地启动
32+
33+
1. 使用 **vscode** 打开项目
34+
2. 进入到子模块的 `samples` 目录
35+
3. 打开需要运行的示例文件
36+
4. 点击侧边栏的 **运行和调试** 按钮
37+
5. 运行 `Run Files`
38+
39+
## License
40+
41+
MIT

package.json

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
{
2+
"name": "bpvm",
3+
"version": "0.2.0",
4+
"description": "A browser sandbox based on Proxy",
5+
"keywords": [
6+
"sandbox",
7+
"proxy",
8+
"browser",
9+
"vm"
10+
],
11+
"homepage": "https://github.com/FrontEndDev-org/bpvm#readme",
12+
"repository": {
13+
"type": "git",
14+
"url": "https://github.com/FrontEndDev-org/bpvm.git"
15+
},
16+
"author": "zhengxs2018",
17+
"license": "MIT",
18+
"sideEffects": false,
19+
"type": "module",
20+
"main": "./dist/index.js",
21+
"types": "./dist-types/index.d.ts",
22+
"files": [
23+
"dist",
24+
"dist-types"
25+
],
26+
"publishConfig": {
27+
"directory": "package"
28+
},
29+
"clean-publish": {
30+
"withoutPublish": true,
31+
"tempDir": "package",
32+
"fields": [
33+
"engines",
34+
"publishConfig"
35+
]
36+
},
37+
"packageManager": "[email protected]",
38+
"engines": {
39+
"node": ">=22.0.0"
40+
},
41+
"scripts": {
42+
"build": "vite build",
43+
"watch": "vite build --mode development --watch",
44+
"format": "prettier src samples --write --log-level warn",
45+
"clean:bundle": "rimraf dist dist-types",
46+
"prepublishOnly": "pnpm build && clean-publish",
47+
"postpublish": "rimraf ./package"
48+
},
49+
"devDependencies": {
50+
"@types/node": "^22.15.14",
51+
"clean-publish": "^5.2.0",
52+
"husky": "^9.1.7",
53+
"lint-staged": "^15.5.2",
54+
"prettier": "^3.5.3",
55+
"rimraf": "^6.0.1",
56+
"tsx": "^4.19.4",
57+
"typescript": "^5.8.3",
58+
"vite": "^6.3.5",
59+
"vite-plugin-checker": "^0.9.3",
60+
"vite-plugin-dts": "^4.5.3",
61+
"vite-plugin-externalize-deps": "^0.9.0"
62+
}
63+
}

samples/globalVar.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import './polyfill.js';
2+
import { runInNewContext } from '../src/index.js';
3+
4+
(window as any).globalVar = 3;
5+
6+
const context = {
7+
globalVar: 1,
8+
};
9+
10+
runInNewContext(`globalVar *= 2`, context);
11+
12+
console.log(context);
13+
// Prints: { globalVar: 2 }
14+
15+
console.log((window as any).globalVar);
16+
// Prints: 3

samples/module.ts

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import './polyfill.js';
2+
import { ModuleScript } from '../src/index.js';
3+
import { isNil } from '../src/util.js';
4+
5+
type Extension = {
6+
activate: () => void;
7+
};
8+
9+
const code = `
10+
const { isNil } = require('shared')
11+
12+
const msg = 'hello,module'
13+
14+
15+
exports.activate = function () {
16+
console.log('环境变量', process.env.NODE_ENV)
17+
console.log('全局变量', abc)
18+
console.log('函数调用', isNil(null), isNil(1))
19+
console.log('当前上下文变量', msg)
20+
}`;
21+
22+
const vm = new ModuleScript<Extension>(code, {
23+
env: {
24+
NODE_ENV: 'development',
25+
},
26+
module: {
27+
alias: {
28+
shared: { isNil },
29+
},
30+
},
31+
scopes: ['abc'],
32+
});
33+
34+
const exports = vm.getExports({
35+
abc: '123',
36+
});
37+
38+
exports.activate();
39+
//=> Prints:
40+
//=> 环境变量 development
41+
//=> 全局变量 123
42+
//=> 函数调用 false false
43+
//=> 当前上下文变量 hello,module

samples/polyfill.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
// @ts-expect-error mock browser global
2+
global.window = {};

samples/script.ts

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import './polyfill.js';
2+
import { createContext, Script } from '../src/index.js';
3+
4+
const code = `
5+
const msg = 'hello,script'
6+
7+
window.print = function () {
8+
console.log('环境变量', process.env.NODE_ENV)
9+
console.log('全局变量', abc)
10+
console.log('当前上下文变量', msg)
11+
}`;
12+
13+
const vm = new Script(code, {
14+
scopes: ['process', 'abc'],
15+
});
16+
17+
const context = createContext<{
18+
print: () => void;
19+
}>({
20+
process: {
21+
env: {
22+
NODE_ENV: 'development',
23+
},
24+
},
25+
abc: '123',
26+
});
27+
28+
vm.runInContext(context);
29+
30+
context.print();
31+
//=> Prints:
32+
//=> 环境变量 development
33+
//=> 全局变量 123
34+
//=> 当前上下文变量 hello,script

samples/sum.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import './polyfill.js';
2+
import { runInNewContext } from '../src/index.js';
3+
4+
const result = runInNewContext(
5+
'a + 5',
6+
{ a: 100 },
7+
{
8+
returnValue: true,
9+
},
10+
);
11+
12+
console.log(result);

0 commit comments

Comments
 (0)