Files
easemob-sdk-test/scripts/easemob-polyfill.js
zyh fd549c6e3d feat: 初始化环信 SDK 测试项目
- 添加项目配置文档 (AGENTS.md)
- 创建 package.json,包含环信 SDK 及测试依赖
- 添加环信 polyfill 工具模块
- 添加双用户消息互发测试脚本
- 添加 polyfill 测试脚本

Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Happy <yesreply@happy.engineering>
2026-03-29 23:14:09 +00:00

138 lines
4.9 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* 环信 SDK Node.js Polyfill 工具模块
*
* 提供 easemob-websdk 在 Node.js 下运行所需的浏览器 API 模拟。
*
* 用法:
* const { applyManualPolyfill, applyHappyDomPolyfill, printGlobalState } = require('./easemob-polyfill');
* applyManualPolyfill();
*/
// ──────────────────────────────────────────
// 手动 Polyfill逐项注入缺失的浏览器 API
// ──────────────────────────────────────────
function applyManualPolyfill() {
// window → globalThis关键让 typeof window === 'object'SDK 据此判断浏览器环境)
if (typeof globalThis.window === 'undefined') {
globalThis.window = globalThis;
console.log(' + window = globalThis');
}
// self → globalThis
if (typeof globalThis.self === 'undefined') {
globalThis.self = globalThis;
console.log(' + self = globalThis');
}
// WebSocket → ws
if (typeof globalThis.WebSocket === 'undefined') {
try {
const wsModule = require('ws');
globalThis.WebSocket = wsModule.WebSocket || wsModule;
console.log(' + WebSocket = ws (Node.js)');
} catch {
console.warn(' ! ws 包未安装,跳过 WebSocket polyfill');
}
}
// localStorage → 内存 Map
if (typeof globalThis.localStorage === 'undefined') {
const store = new Map();
globalThis.localStorage = {
getItem: (key) => store.get(key) ?? null,
setItem: (key, value) => { store.set(key, String(value)); },
removeItem: (key) => { store.delete(key); },
clear: () => { store.clear(); },
get length() { return store.size; },
key: (_index) => null,
};
console.log(' + localStorage = in-memory Map');
}
// XMLHttpRequest 由调用方按需注入xhr2 / xmlhttprequest此处不再自动注入
// navigator 基本模拟
if (typeof globalThis.navigator === 'undefined') {
globalThis.navigator = {
userAgent: 'Node.js',
platform: process.platform,
appName: 'Node.js',
appVersion: process.version,
language: 'zh-CN',
};
console.log(' + navigator = basic mock');
}
}
// ──────────────────────────────────────────
// happy-dom Polyfill注入完整浏览器环境
// ──────────────────────────────────────────
async function applyHappyDomPolyfill() {
let happyDOM;
try {
happyDOM = require('happy-dom');
} catch {
console.error(' ✗ happy-dom 未安装');
console.error(' 请运行: npm install happy-dom --save-dev');
process.exit(1);
}
// happy-dom v20+ uses Browser + BrowserContext API
if (happyDOM.Browser && happyDOM.BrowserContext) {
const browser = new happyDOM.Browser();
const page = browser.newPage('https://a1.easemob.com');
const window = page.mainFrame.window;
const document = window.document;
globalThis.window = window;
globalThis.document = document;
globalThis.self = window;
globalThis.navigator = window.navigator;
globalThis.localStorage = window.localStorage;
globalThis.XMLHttpRequest = window.XMLHttpRequest;
globalThis.WebSocket = window.WebSocket;
globalThis.fetch = window.fetch.bind(window);
globalThis.Headers = window.Headers;
globalThis.Request = window.Request;
globalThis.Response = window.Response;
console.log(' + happy-dom Browser + BrowserContext ✓');
console.log(` + page URL: ${window.location.href}`);
return;
}
// 旧版 GlobalRegistrator API (happy-dom < v15)
const Registrator = happyDOM.GlobalRegistrator;
if (Registrator && Registrator.register) {
await Registrator.register();
console.log(' + happy-dom GlobalRegistrator.register() ✓');
return;
}
console.error(' ✗ happy-dom 版本不兼容,无法注入全局 API');
console.error(' 当前版本:', require('happy-dom/package.json').version);
process.exit(1);
}
// ──────────────────────────────────────────
// 打印当前全局 API 状态
// ──────────────────────────────────────────
function printGlobalState() {
const apis = [
'self', 'WebSocket', 'localStorage', 'XMLHttpRequest',
'navigator', 'fetch', 'window', 'document',
];
console.log('\n 全局 API 状态:');
for (const api of apis) {
const exists = typeof globalThis[api] !== 'undefined';
const type = typeof globalThis[api];
console.log(` ${exists ? '✓' : '✗'} ${api}: ${exists ? type : 'undefined'}`);
}
}
module.exports = {
applyManualPolyfill,
applyHappyDomPolyfill,
printGlobalState,
};