import { BUILTIN_UTILS_SOURCE } from "./builtin-utils.js";
class WorkerPool {
    workers = [];
    availableWorkers = [];
    maxSize;
    isInitialized = false;
    constructor(maxSize = 2){
        this.maxSize = maxSize;
    }
    async initialize() {
        if (this.isInitialized) return;
        for(let i = 0; i < this.maxSize; i++)try {
            const worker = await this.createSecureWorker();
            this.workers.push(worker);
            this.availableWorkers.push(worker);
        } catch (error) {
            this.workers.forEach((w)=>w.terminate());
            this.workers = [];
            this.availableWorkers = [];
            throw new Error(`Failed to initialize Worker pool: ${error instanceof Error ? error.message : String(error)}`);
        }
        this.isInitialized = true;
    }
    createSecureWorker() {
        const libraryLoadCode = `// 内置工具库（lodash/Ramda 兼容 API）\n${BUILTIN_UTILS_SOURCE}`;
        const workerCode = `
      // ============================================
      // 阶段 1: 立即执行安全加固 (IIFE)
      // ============================================
      (function initSecureSandbox() {
        'use strict';
        
        // 1.1 保存必要的原生引用（在被删除前）
        const nativeImportScripts = self.importScripts;
        const nativePostMessage = self.postMessage.bind(self);
        
        // 1.2 立即删除危险 API
        delete self.importScripts;
        delete self.fetch;
        delete self.XMLHttpRequest;
        delete self.WebSocket;
        
        // 1.3 冻结关键原型链（防止污染和篡改）
        Object.freeze(Object.prototype);
        Object.freeze(Array.prototype);
        Object.freeze(Function.prototype);
        Object.freeze(String.prototype);
        Object.freeze(Number.prototype);
        Object.freeze(Boolean.prototype);
        
        // ============================================
        // 阶段 2: 加载工具库
        // ============================================
        try {
          ${libraryLoadCode}
        } catch (error) {
          nativePostMessage({ 
            initError: 'Failed to load utility library: ' + error.message 
          });
          return;
        }
        
        // 验证库是否加载成功
        const utilityLib = self._;
        if (!utilityLib) {
          nativePostMessage({ 
            initError: 'Builtin utility library (_ or R) not found after loading' 
          });
          return;
        }
        
        // ============================================
        // 阶段 3: 创建安全上下文
        // ============================================
        const createSafeContext = (lib) => {
          const allowedGlobals = {
            // 工具库
            _: lib,
            R: lib,
            
            // 基础类型构造函数（只读）
            Array: Array,
            Object: Object,
            String: String,
            Number: Number,
            Boolean: Boolean,
            Date: Date,
            
            // 数学和工具
            Math: Math,
            JSON: JSON,
            
            // 类型检查
            parseInt: parseInt,
            parseFloat: parseFloat,
            isNaN: isNaN,
            isFinite: isFinite,
            
            // 错误类型（用于调试）
            Error: Error,
            TypeError: TypeError,
            RangeError: RangeError,
            
            // 只读的数据引用
            data: null,
          };
          
          // 使用 Proxy 严格控制访问
          return new Proxy(allowedGlobals, {
            get(target, prop) {
              if (prop === Symbol.unscopables) {
                return undefined;
              }
              
              if (prop in target) {
                return target[prop];
              }
              
              // 拒绝访问任何未定义的属性
              throw new ReferenceError(
                \`'\${String(prop)}' is not defined. \\n\` +
                \`Only these globals are available: \${Object.keys(allowedGlobals).join(', ')}\`
              );
            },
            
            set(target, prop, value) {
              // 只允许设置 data 属性（用于传递执行数据）
              if (prop === 'data') {
                target[prop] = value;
                return true;
              }
              
              // 拒绝设置其他属性
              throw new TypeError(
                \`Cannot set property '\${String(prop)}' on global context\`
              );
            },
            
            has(target, prop) {
              return prop in target;
            },
            
            // 防止 getOwnPropertyDescriptor 等元编程操作
            getOwnPropertyDescriptor(target, prop) {
              if (prop in target) {
                return Object.getOwnPropertyDescriptor(target, prop);
              }
              return undefined;
            }
          });
        };
        
        const safeContext = createSafeContext(utilityLib);
        
        // ============================================
        // 阶段 4: 代码执行引擎
        // ============================================
        const executeUserCodeSafely = (code, data, timeout) => {
          // 设置超时保护（内层防御）
          let timeoutId = null;
          let isTimedOut = false;
          
          if (timeout > 0) {
            timeoutId = setTimeout(() => {
              isTimedOut = true;
            }, timeout);
          }
          
          try {
            // 超时检查函数
            // ⚠️ 注意：这只能防御"合作式"的代码（包含 I/O、迭代、递归）
            // 对于纯计算死循环（while(true){}），只有外层 worker.terminate() 能终止
            const checkTimeout = () => {
              if (isTimedOut) {
                throw new Error(\`Execution timeout (exceeded \${timeout}ms)\`);
              }
            };
            
            // 更新安全上下文中的数据
            safeContext.data = data;
            
            // 提取安全上下文的所有变量名和值
            const contextKeys = Object.keys(safeContext);
            const contextValues = contextKeys.map(key => safeContext[key]);
            
            // 显式遮蔽 Worker 全局对象中的危险变量（设为 undefined）
            const shadowedGlobals = [
              'self',           // Worker 全局对象本身
              'postMessage',    // 通信通道（防止滥用）
              'close',          // Worker 终止方法
              'importScripts',  // 动态加载脚本（已删除，但显式遮蔽更安全）
              'addEventListener', // 事件监听器
              'removeEventListener',
              'dispatchEvent',
              'onmessage',      // 消息处理器
              'onerror',        // 错误处理器
              'onmessageerror',
              'setTimeout',     // ⚠️ 遮蔽定时器，防止资源泄漏
              'clearTimeout',
              'setInterval',    // ⚠️ 防止用户创建大量定时器
              'clearInterval',
            ];
            
            // 包装用户代码：在严格模式下执行，通过参数注入变量
            const wrappedCode = \`
              "use strict";
              // 用户代码在这里执行，可以直接访问注入的变量（_, R, data, Math, etc.）
              \${code}
            \`;
            
            // 创建函数：参数是上下文变量名 + checkTimeout + 遮蔽的全局变量名
            const userFunction = new Function(
              ...contextKeys,        // 安全上下文变量
              'checkTimeout',        // 超时检查函数（用户可选调用）
              ...shadowedGlobals,    // 显式遮蔽的危险全局变量
              wrappedCode
            );
            
            // 执行并获取结果
            const result = userFunction(
              ...contextValues,                          // 安全上下文的值
              checkTimeout,                              // 超时检查函数
              ...shadowedGlobals.map(() => undefined)   // 所有危险全局变量设为 undefined
            );
            
            // 清除超时
            if (timeoutId) {
              clearTimeout(timeoutId);
            }
            
            // 验证返回值（只检查危险类型，不限制结构）
            const validateResultType = (result) => {
              const type = typeof result
              
              // 禁止返回函数、Symbol
              if (type === 'function' || type === 'symbol') {
                throw new TypeError(
                  \`Code must not return \${type}. Returned types must be serializable.\`
                );
              }
              
              // 禁止返回 Promise
              if (result && typeof result.then === 'function') {
                throw new TypeError(
                  \`Code must not return a Promise. Async operations are not allowed.\`
                );
              }
              
              // 如果是数组，检查元素的危险类型
              if (Array.isArray(result)) {
                for (let i = 0; i < result.length; i++) {
                  const item = result[i];
                  const itemType = typeof item;
                  
                  if (itemType === 'function' || itemType === 'symbol') {
                    throw new TypeError(
                      \`Array element at index \${i} has forbidden type: \${itemType}\`
                    );
                  }
                  
                  if (item && typeof item.then === 'function') {
                    throw new TypeError(
                      \`Array element at index \${i} is a Promise. Async operations are not allowed.\`
                    );
                  }
                }
              }
            };
            
            validateResultType(result);
            
            return result;
            
          } catch (error) {
            throw error;
          } finally {
            // 清理数据引用（防止内存泄漏）
            safeContext.data = null;
          }
        };
        
        // ============================================
        // 阶段 5: 消息处理
        // ============================================
        self.onmessage = function(event) {
          // ⚠️ 防御性检查：确保消息格式正确
          if (!event || !event.data) {
            nativePostMessage({ 
              taskId: 'unknown',
              success: false,
              error: 'Invalid message format: event.data is null or undefined'
            });
            return;
          }
          
          const { code, data, timeout, taskId } = event.data;
          
          // 验证必需字段
          if (!taskId) {
            nativePostMessage({ 
              taskId: 'unknown',
              success: false,
              error: 'Invalid message: taskId is required'
            });
            return;
          }
          
          try {
            const result = executeUserCodeSafely(code, data, timeout);
            
            nativePostMessage({ 
              taskId,
              success: true,
              result: result 
            });
            
          } catch (error) {
            nativePostMessage({ 
              taskId,
              success: false,
              error: error.message || String(error),
              errorType: error.constructor.name
            });
          }
        };
        
        // 错误捕获
        self.onerror = function(event) {
          nativePostMessage({ 
            globalError: event.message || 'Unknown worker error'
          });
        };
        
        // 发送初始化成功消息
        nativePostMessage({ initialized: true });
        
      })(); // 立即执行
    `;
        const blob = new Blob([
            workerCode
        ], {
            type: "application/javascript"
        });
        const blobURL = URL.createObjectURL(blob);
        const worker = new Worker(blobURL);
        URL.revokeObjectURL(blobURL);
        return new Promise((resolve, reject)=>{
            let isSettled = false;
            const cleanup = ()=>{
                if (!isSettled) {
                    isSettled = true;
                    worker.onmessage = null;
                    worker.onerror = null;
                }
            };
            const timeout = setTimeout(()=>{
                cleanup();
                worker.terminate();
                reject(new Error('Worker initialization timeout'));
            }, 10000);
            worker.onmessage = (e)=>{
                if (e.data.initialized) {
                    clearTimeout(timeout);
                    cleanup();
                    resolve(worker);
                } else if (e.data.initError) {
                    clearTimeout(timeout);
                    cleanup();
                    worker.terminate();
                    reject(new Error(e.data.initError));
                }
            };
            worker.onerror = (errorEvent)=>{
                clearTimeout(timeout);
                cleanup();
                worker.terminate();
                const errorMessage = errorEvent.message || errorEvent.error?.message || 'Unknown worker initialization error';
                reject(new Error(`Worker initialization failed: ${errorMessage}`));
            };
        });
    }
    async acquire() {
        if (!this.isInitialized) await this.initialize();
        if (0 === this.availableWorkers.length) try {
            const tempWorker = await this.createSecureWorker();
            return tempWorker;
        } catch (error) {
            throw new Error(`Failed to create temporary Worker: ${error instanceof Error ? error.message : String(error)}`);
        }
        return this.availableWorkers.pop();
    }
    release(worker) {
        if (this.workers.includes(worker)) this.availableWorkers.push(worker);
        else worker.terminate();
    }
    terminate() {
        this.workers.forEach((worker)=>worker.terminate());
        this.workers = [];
        this.availableWorkers = [];
        this.isInitialized = false;
    }
}
let globalWorkerPool = null;
let poolInitPromise = null;
let poolConfig = {
    poolSize: 2
};
function getOrCreateWorkerPool() {
    if (globalWorkerPool) return Promise.resolve(globalWorkerPool);
    if (poolInitPromise) return poolInitPromise;
    poolInitPromise = (async ()=>{
        try {
            const pool = new WorkerPool(poolConfig.poolSize);
            await pool.initialize();
            globalWorkerPool = pool;
            return pool;
        } catch (error) {
            poolInitPromise = null;
            throw error;
        }
    })();
    return poolInitPromise;
}
async function initializeWorkerPool(options = {}) {
    poolConfig = {
        poolSize: options.poolSize ?? 2
    };
    await getOrCreateWorkerPool();
}
function terminateWorkerPool() {
    if (globalWorkerPool) {
        globalWorkerPool.terminate();
        globalWorkerPool = null;
    }
    poolInitPromise = null;
}
function validateCodeSafety(code) {
    if (!code || 0 === code.trim().length) throw new Error('Code cannot be empty');
    if (code.length > 50000) throw new Error('Code is too long (max 50KB)');
    if (!/\breturn\b/.test(code)) throw new Error('Code must contain a return statement');
    const forbiddenPatterns = [
        {
            pattern: /\beval\b/gi,
            description: 'eval()'
        },
        {
            pattern: /\bFunction\s*\(/gi,
            description: 'Function constructor'
        },
        {
            pattern: /\bnew\s+Function\b/gi,
            description: 'new Function()'
        },
        {
            pattern: /\bimportScripts\b/gi,
            description: 'importScripts()'
        },
        {
            pattern: /\bfetch\b/gi,
            description: 'fetch()'
        },
        {
            pattern: /\bXMLHttpRequest\b/gi,
            description: 'XMLHttpRequest'
        },
        {
            pattern: /\bWebSocket\b/gi,
            description: 'WebSocket'
        },
        {
            pattern: /\blocalStorage\b/gi,
            description: 'localStorage'
        },
        {
            pattern: /\bsessionStorage\b/gi,
            description: 'sessionStorage'
        },
        {
            pattern: /\bindexedDB\b/gi,
            description: 'indexedDB'
        },
        {
            pattern: /\bwindow\b/gi,
            description: 'window'
        },
        {
            pattern: /\bdocument\b/gi,
            description: 'document'
        },
        {
            pattern: /\bnavigator\b/gi,
            description: 'navigator'
        },
        {
            pattern: /\blocation\b/gi,
            description: 'location'
        },
        {
            pattern: /\brequire\b/gi,
            description: 'require()'
        },
        {
            pattern: /\bimport\s+/gi,
            description: 'import statement'
        },
        {
            pattern: /\bexport\s+/gi,
            description: 'export statement'
        },
        {
            pattern: /\bconstructor\b/gi,
            description: 'constructor access'
        },
        {
            pattern: /\[['"]constructor['"]\]/gi,
            description: 'constructor via bracket notation'
        },
        {
            pattern: /\['constructor'\]/gi,
            description: 'constructor string access'
        },
        {
            pattern: /\b__proto__\b/gi,
            description: '__proto__'
        },
        {
            pattern: /\bprototype\b/gi,
            description: 'prototype manipulation'
        },
        {
            pattern: /Object\.setPrototypeOf/gi,
            description: 'Object.setPrototypeOf()'
        },
        {
            pattern: /Object\.getPrototypeOf/gi,
            description: 'Object.getPrototypeOf()'
        },
        {
            pattern: /Object\.create\s*\(\s*null\s*\)/gi,
            description: 'Object.create(null)'
        },
        {
            pattern: /\bReflect\./gi,
            description: 'Reflect API'
        },
        {
            pattern: /\bProxy\b/gi,
            description: 'Proxy constructor'
        },
        {
            pattern: /\bglobal\b/gi,
            description: 'global object'
        },
        {
            pattern: /\bglobalThis\b/gi,
            description: 'globalThis'
        },
        {
            pattern: /\bself\s*\[/gi,
            description: 'self[] access'
        },
        {
            pattern: /\bthis\s*\.\s*constructor/gi,
            description: 'this.constructor'
        },
        {
            pattern: /\basync\s+function/gi,
            description: 'async function'
        },
        {
            pattern: /\bawait\b/gi,
            description: 'await keyword'
        },
        {
            pattern: /\bnew\s+Promise\b/gi,
            description: 'new Promise()'
        },
        {
            pattern: /\.then\s*\(/gi,
            description: 'Promise.then()'
        },
        {
            pattern: /\bfunction\s*\*/gi,
            description: 'generator function'
        },
        {
            pattern: /\byield\b/gi,
            description: 'yield keyword'
        },
        {
            pattern: /\.apply\s*\(/gi,
            description: 'Function.apply()'
        },
        {
            pattern: /\.call\s*\(/gi,
            description: 'Function.call()'
        },
        {
            pattern: /\.bind\s*\(/gi,
            description: 'Function.bind()'
        },
        {
            pattern: /\bWorker\b/gi,
            description: 'Worker constructor'
        },
        {
            pattern: /\bSharedWorker\b/gi,
            description: 'SharedWorker'
        },
        {
            pattern: /\bServiceWorker\b/gi,
            description: 'ServiceWorker'
        }
    ];
    for (const { pattern, description } of forbiddenPatterns)if (pattern.test(code)) throw new Error(`Security violation: Code contains forbidden pattern "${description}". For AI-generated code, please regenerate without this pattern.`);
    const suspiciousPatterns = [
        /['"]con['"] *\+ *['"]structor['"]/gi,
        /['"]ev['"] *\+ *['"]al['"]/gi,
        /['"]__pro['"] *\+ *['"]to__['"]/gi,
        /\b(self|window|global)\s*\[\s*['"][a-z]+['"]\s*\+\s*['"][a-z]+['"]\s*\]/gi
    ];
    for (const pattern of suspiciousPatterns)if (pattern.test(code)) throw new Error('Security violation: Code contains suspicious string concatenation that may bypass security checks.');
    const aiCodeWarnings = [
        {
            pattern: /\[['"][a-z_$]+['"]\]/gi,
            count: 0,
            threshold: 10,
            description: 'excessive bracket notation'
        },
        {
            pattern: /\s*\+\s*['"]/gi,
            count: 0,
            threshold: 5,
            description: 'excessive string concatenation'
        }
    ];
    for (const warning of aiCodeWarnings){
        const matches = code.match(warning.pattern);
        if (matches && matches.length > warning.threshold) throw new Error(`Security warning: Code contains ${matches.length} instances of ${warning.description}, which is unusual for AI-generated code. Please regenerate.`);
    }
}
async function executeFilterCode(options) {
    const { code, data, timeout = 2000 } = options;
    if ("u" < typeof Worker) return {
        success: false,
        data: [],
        error: 'Web Worker is not supported in this environment'
    };
    try {
        validateCodeSafety(code);
        if (!Array.isArray(data)) throw new Error('Input data must be an array');
        if (data.length > 100000) console.warn(`[vseed] Large dataset detected: ${data.length} items. Consider pagination for better performance.`);
        const dataSize = JSON.stringify(data).length;
        if (dataSize > 10485760) throw new Error(`Input data is too large (${(dataSize / 1024 / 1024).toFixed(1)}MB). Maximum allowed is 10MB.`);
        const pool = await getOrCreateWorkerPool();
        const worker = await pool.acquire();
        const taskId = `task_${Date.now()}_${Math.random().toString(36).substring(7)}`;
        let shouldReleaseWorker = true;
        try {
            const result = await new Promise((resolve, reject)=>{
                let isSettled = false;
                const cleanup = ()=>{
                    if (!isSettled) {
                        isSettled = true;
                        worker.removeEventListener('message', messageHandler);
                        worker.removeEventListener('error', errorHandler);
                    }
                };
                const outerTimeoutId = setTimeout(()=>{
                    cleanup();
                    shouldReleaseWorker = false;
                    worker.terminate();
                    reject(new Error(`Execution timeout (exceeded ${timeout}ms) - outer guard`));
                }, timeout + 1000);
                const messageHandler = (e)=>{
                    if (e.data.taskId !== taskId) return;
                    clearTimeout(outerTimeoutId);
                    cleanup();
                    if (e.data.success) resolve(e.data.result);
                    else reject(new Error(`Execution failed: ${e.data.error}${e.data.errorType ? ` (${e.data.errorType})` : ''}`));
                };
                const errorHandler = (errorEvent)=>{
                    clearTimeout(outerTimeoutId);
                    cleanup();
                    shouldReleaseWorker = false;
                    worker.terminate();
                    const errorMessage = errorEvent.message || errorEvent.error?.message || 'Unknown worker error';
                    reject(new Error(`Worker error: ${errorMessage}`));
                };
                worker.addEventListener('message', messageHandler);
                worker.addEventListener('error', errorHandler);
                worker.postMessage({
                    taskId,
                    code,
                    data,
                    timeout
                });
            });
            return {
                success: true,
                data: result
            };
        } finally{
            if (shouldReleaseWorker && globalWorkerPool) globalWorkerPool.release(worker);
        }
    } catch (error) {
        return {
            success: false,
            data: [],
            error: error instanceof Error ? error.message : String(error)
        };
    }
}
export { executeFilterCode, initializeWorkerPool, terminateWorkerPool, validateCodeSafety };

//# sourceMappingURL=execute.js.map