SharedArrayBuffer is not defined

Uncaught ReferenceError: SharedArrayBuffer is not defined


这个错误通常是因为浏览器的安全策略限制导致的。


SharedArrayBuffer 错误原因

SharedArrayBuffer 需要特殊的浏览器安全设置才能使用,主要是因为安全漏洞(如 Spectre 攻击)的原因,现代浏览器默认禁用了它。


跨源隔离(Cross-Origin Isolation)

要在浏览器中使用 SharedArrayBuffer,必须启用跨源隔离。这需要在服务器响应头中设置以下两个头部:

Cross-Origin-Embedder-Policy: require-corp

Cross-Origin-Opener-Policy: same-origin


或更宽松的配置

Cross-Origin-Opener-Policy: same-origin

Cross-Origin-Embedder-Policy: same-origin


使用本地服务器而非文件协议

不要直接双击 HTML 文件打开(file:// 协议),而是使用本地服务器。


本地开发时的快速解决方案

第一步:Chrome 浏览器 禁用 Web 安全

启动 Chrome 时添加以下标志:

bash

bash 复制代码
chrome --disable-web-security --user-data-dir=/tmp/chrome-test

Windows系统上启动 Chrome 并添加标志的方法:

方法1:使用 CMD 命令行(最简单)
  1. Win + R,输入 cmd,回车

  2. 在 CMD 中输入:


cmd

复制代码
"C:\Program Files\Google\Chrome\Application\chrome.exe" --disable-web-security --user-data-dir="C:\temp\chrome-test"

方法2:在 PowerShell 中正确的语法

powershell

复制代码
& "C:\Program Files\Google\Chrome\Application\chrome.exe" "--disable-web-security" "--user-data-dir=C:\temp\chrome-test"

或者:

powershell

复制代码
Start-Process "C:\Program Files\Google\Chrome\Application\chrome.exe" -ArgumentList "--disable-web-security", "--user-data-dir=C:\temp\chrome-test"

验证是否成功

启动后,你应该看到 Chrome 顶部的警告横幅:

text

复制代码
您使用的是不受支持的命令行标记:--disable-web-security。稳定性和安全性会有所下降。


后续页面打开都在这个新弹出的窗口中进行测试


其他方式:创建快捷方式

  1. 右键点击 Chrome 快捷方式,选择"属性"

  2. 在"目标"字段的末尾添加:

    复制代码
    --disable-web-security --user-data-dir="C:\temp\chrome-test"
  3. 完整的目标路径应该类似:

    复制代码
    "C:\Program Files\Google\Chrome\Application\chrome.exe" --disable-web-security --user-data-dir="C:\temp\chrome-test"
  4. 点击"应用",然后双击此快捷方式启动


或者使用 Chrome 扩展程序(推荐,但可能无法获取)

安装这些扩展可以绕过 CORS 限制:

  1. Allow CORS: Access-Control-Allow-Origin

    • Chrome Web Store 链接:https://chrome.google.com/webstore/detail/allow-cors-access-control/lhobafahddgcelffkeicbaginigeejlf

    • 安装后,点击图标开启/关闭

  2. Moesif CORS

    • 功能更强大,可以自定义配置

    • 链接:https://chrome.google.com/webstore/detail/moesif-origin-cors-change/digfbfaphojjndkpccljibejjbppifbc


HTTPS要求

请注意,大多数浏览器要求使用HTTPS才能启用SharedArrayBuffer(localhost除外)。


即使禁用了 Web 安全,SharedArrayBuffer 仍然需要特定的 HTTP 头部才能启用。

浏览器的警告横幅只是禁用了 CORS,但没有设置必要的 COOP/COEP 头部。


第二步:必须设置正确的响应头(使用本地服务器并设置头部)

1、使用 Node.js + Express

javascript

javascript 复制代码
// server.js
const express = require('express');
const app = express();
const path = require('path');

// 设置必需的头部
app.use((req, res, next) => {
    res.setHeader('Cross-Origin-Opener-Policy', 'same-origin');
    res.setHeader('Cross-Origin-Embedder-Policy', 'require-corp');
    res.setHeader('Access-Control-Allow-Origin', '*');
    next();
});

app.use(express.static('.'));

app.listen(8080, () => {
    console.log('Server running at http://localhost:8080/');
    console.log('Headers set: COOP=same-origin, COEP=require-corp');
});

运行:

bash

复制代码
node server.js

安装 Express

bash 复制代码
# 临时使用淘宝镜像安装
npm install -g express --registry=https://registry.npmmirror.com

# 或者设置永久使用淘宝镜像
npm config set registry https://registry.npmmirror.com

# 验证配置
npm config get registry

2、使用纯 Node.js(无需额外安装 Express)

创建 server.js

javascript

javascript 复制代码
const http = require('http');
const fs = require('fs');
const path = require('path');

const server = http.createServer((req, res) => {
    console.log(`${req.method} ${req.url}`);
    
    // 设置必需的头部
    res.setHeader('Cross-Origin-Opener-Policy', 'same-origin');
    res.setHeader('Cross-Origin-Embedder-Policy', 'require-corp');
    res.setHeader('Access-Control-Allow-Origin', '*');
    res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');
    res.setHeader('Access-Control-Allow-Headers', 'Content-Type');
    
    // 处理 OPTIONS 预检请求
    if (req.method === 'OPTIONS') {
        res.writeHead(200);
        res.end();
        return;
    }
    
    // 确定请求的文件路径
    let filePath = '.' + req.url;
    if (filePath === './') {
        filePath = './worker.html'; // 默认加载你的 HTML 文件
    }
    
    // 获取文件扩展名
    const extname = path.extname(filePath);
    let contentType = 'text/html';
    
    // 根据扩展名设置 Content-Type
    switch (extname) {
        case '.js':
            contentType = 'text/javascript';
            break;
        case '.css':
            contentType = 'text/css';
            break;
        case '.json':
            contentType = 'application/json';
            break;
        case '.png':
            contentType = 'image/png';
            break;
        case '.jpg':
            contentType = 'image/jpg';
            break;
        case '.wasm':
            contentType = 'application/wasm';
            break;
    }
    
    // 读取文件
    fs.readFile(filePath, (error, content) => {
        if (error) {
            if (error.code === 'ENOENT') {
                // 文件不存在
                fs.readFile('./404.html', (err, notFoundContent) => {
                    if (err) {
                        res.writeHead(404, { 'Content-Type': 'text/plain' });
                        res.end('404 Not Found\n');
                    } else {
                        res.writeHead(404, { 'Content-Type': 'text/html' });
                        res.end(notFoundContent, 'utf-8');
                    }
                });
            } else {
                // 服务器错误
                res.writeHead(500);
                res.end('Server Error: ' + error.code);
            }
        } else {
            // 成功响应
            res.writeHead(200, { 
                'Content-Type': contentType,
                'Content-Length': content.length
            });
            res.end(content, 'utf-8');
        }
    });
});

const port = 8080;
server.listen(port, () => {
    console.log(`Server running at http://localhost:${port}`);
    console.log('Required headers are set:');
    console.log('  Cross-Origin-Opener-Policy: same-origin');
    console.log('  Cross-Origin-Embedder-Policy: require-corp');
    console.log('  Access-Control-Allow-Origin: *');
    console.log('\nOpen your browser to: http://localhost:8080/worker.html');
});

3、使用 Python(最简单,无需网络)

如果你安装了 Python3(WSL Ubuntu 通常自带):

bash

bash 复制代码
#!/usr/bin/env python3
"""
SharedArrayBuffer 专用服务器
确保设置正确的响应头
"""

import http.server
import socketserver
import os
import sys

def main(port=8000):
    """启动带正确头部的服务器"""
    
    class SABHandler(http.server.SimpleHTTPRequestHandler):
        """SharedArrayBuffer 专用处理器"""
        
        def end_headers(self):
            # 必须的三个头部
            self.send_header('Cross-Origin-Opener-Policy', 'same-origin')
            self.send_header('Cross-Origin-Embedder-Policy', 'require-corp')
            self.send_header('Access-Control-Allow-Origin', '*')
            super().end_headers()
        
        def log_message(self, format, *args):
            # 简化日志,只显示重要请求
            path = self.path
            if path.endswith('.html') or path == '/' or 'worker' in path:
                print(f'📦 {path}')
    
    # 确保在当前目录
    script_dir = os.path.dirname(os.path.abspath(__file__))
    os.chdir(script_dir)
    
    print('\n' + '='*60)
    print('🎯 SHAREDARRAYBUFFER 开发服务器')
    print('='*60)
    print(f'📡 服务器地址: http://localhost:{port}')
    print(f'📁 服务目录: {os.getcwd()}')
    print('\n🔧 已配置的响应头:')
    print('   ✓ Cross-Origin-Opener-Policy: same-origin')
    print('   ✓ Cross-Origin-Embedder-Policy: require-corp')
    print('   ✓ Access-Control-Allow-Origin: *')
    
    # 列出HTML文件
    html_files = [f for f in os.listdir('.') if f.lower().endswith('.html')]
    if html_files:
        print('\n📄 可访问的页面:')
        for html in sorted(html_files):
            print(f'   → http://localhost:{port}/{html}')
    
    print('\n💡 使用说明:')
    print('   1. 访问上面的任一链接')
    print('   2. 按 F12 查看 Network → Headers 确认头部')
    print('   3. SharedArrayBuffer 现在应该可用了')
    print('   4. 按 Ctrl+C 停止服务器')
    print('='*60 + '\n')
    
    try:
        with socketserver.TCPServer(("", port), SABHandler) as httpd:
            httpd.serve_forever()
    except OSError as e:
        if 'Address already in use' in str(e):
            print(f'❌ 端口 {port} 已被占用!')
            print(f'   请使用其他端口: python3 server.py 8080')
            return 1
        raise
    except KeyboardInterrupt:
        print('\n👋 服务器已停止')
        return 0

if __name__ == '__main__':
    # 使用命令行参数指定端口,或默认8000
    port = int(sys.argv[1]) if len(sys.argv) > 1 else 8000
    sys.exit(main(port))

验证是否成功

访问页面,按 F12 打开开发者工具,查看:

  1. Network 标签 → 点击你的文件 → 查看 Response Headers

  2. 应该能看到:

    • Cross-Origin-Opener-Policy: same-origin

    • Cross-Origin-Embedder-Policy: require-corp



建议方案

使用 Python 方案最简单,因为:

  1. WSL Ubuntu 自带 Python3

  2. 无需安装任何额外包

  3. 自动设置所需头部

项目根目录直接运行:

bash 复制代码
python3 server.py

彻底清理所有端口占用


复制代码
Press Ctrl+C to stop the server

在终端中项目根目录运行以下清理命令:


注意:可能需要输入密码


bash 复制代码
# 强力清理所有可能的端口占用
echo "🧹 清理所有可能冲突的进程..."
sudo pkill -f "python.*http.server" 2>/dev/null || true
sudo pkill -f "node.*server" 2>/dev/null || true
sudo pkill -f "http-server" 2>/dev/null || true

# 释放所有相关端口
for port in 3000 3001 3002 8000 8001 8002 8080 8081 8082 8888 5000; do
    sudo fuser -k ${port}/tcp 2>/dev/null || true
done

echo "✅ 清理完成"

检测支持

在使用 SharedArrayBuffer 之前,最好先检测浏览器是否支持:

javascript 复制代码
// 检查 SharedArrayBuffer 是否可用
if (typeof SharedArrayBuffer === 'undefined') {
    // 降级方案:使用普通 ArrayBuffer
    console.warn('SharedArrayBuffer is not available. Using fallback.');
    
    // 创建一个简单的模拟(功能有限)
    window.SharedArrayBuffer = ArrayBuffer;
    
    // 或者根据你的需求调整代码逻辑
    // 例如:使用 worker.postMessage 替代共享内存
}

完整示例

下面是一个使用 SharedArrayBuffer 的完整示例(需要适当的安全头部):

javascript 复制代码
// 在代码中检测支持情况
function isSharedArrayBufferSupported() {
    try {
        if (typeof SharedArrayBuffer !== 'function') {
            return false;
        }
        
        // 测试是否可以实际创建
        const sab = new SharedArrayBuffer(1);
        return sab instanceof SharedArrayBuffer;
    } catch (e) {
        return false;
    }
}

if (!isSharedArrayBufferSupported()) {
    // 提供降级方案或错误提示
    console.error('SharedArrayBuffer is not supported in this environment');
    // 提示用户更新浏览器或使用支持的浏览器
}
相关推荐
QC七哥1 个月前
使用wrangler发布cf的workers项目
workers·站点部署·wrangler
武穆逸仙2 年前
基于Cloudflare/CloudDNS/GitHub使用免费域名部署NewBing的AI服务
人工智能·cloudflare·bingai·workers