reverse-skills-max: initial public release (restored, redacted, hardened)
This commit is contained in:
@@ -0,0 +1,92 @@
|
||||
// Storage 模块模板:按 fixture 注入 localStorage / sessionStorage,并固化原型链、描述符和 native-like 方法。
|
||||
'use strict';
|
||||
|
||||
let protect = null;
|
||||
try { protect = require('./native-protect'); } catch { protect = null; }
|
||||
|
||||
function defineValue(obj, key, value, options = {}) {
|
||||
if (protect && protect.defineValue) return protect.defineValue(obj, key, value, options);
|
||||
Object.defineProperty(obj, key, {
|
||||
value,
|
||||
writable: options.writable ?? false,
|
||||
enumerable: options.enumerable ?? true,
|
||||
configurable: options.configurable ?? true,
|
||||
});
|
||||
return value;
|
||||
}
|
||||
|
||||
function markNativeFunction(fn, name) {
|
||||
if (protect && protect.markNativeFunction) return protect.markNativeFunction(fn, name);
|
||||
return fn;
|
||||
}
|
||||
|
||||
function markObjectToString(obj, tag) {
|
||||
if (protect && protect.markObjectToString) return protect.markObjectToString(obj, tag);
|
||||
try { Object.defineProperty(obj, Symbol.toStringTag, { value: tag, enumerable: false, configurable: true }); } catch {}
|
||||
return obj;
|
||||
}
|
||||
|
||||
function defineNativeGetter(obj, key, impl, options = {}, addon) {
|
||||
if (protect && protect.defineNativeGetter) return protect.defineNativeGetter(obj, key, impl, options, addon);
|
||||
Object.defineProperty(obj, key, { get: impl, enumerable: options.enumerable ?? true, configurable: options.configurable ?? true });
|
||||
return impl;
|
||||
}
|
||||
|
||||
function defineNativeValue(obj, key, impl, options = {}, addon) {
|
||||
if (protect && protect.defineNativeValue) return protect.defineNativeValue(obj, key, impl, options, addon);
|
||||
return defineValue(obj, key, impl, { writable: true, ...options });
|
||||
}
|
||||
|
||||
function createNativeConstructor(name, length, impl, addon) {
|
||||
if (protect && protect.createNativeConstructor) return protect.createNativeConstructor(name, length, impl, addon);
|
||||
function Ctor(...args) { return impl.call(this, new.target ? true : false, ...args); }
|
||||
try { Object.defineProperty(Ctor, 'name', { value: name, configurable: true }); } catch {}
|
||||
return markNativeFunction(Ctor, name);
|
||||
}
|
||||
|
||||
function throwIllegalConstructor(name, addon) {
|
||||
if (protect && protect.throwIllegalConstructor) return protect.throwIllegalConstructor(name, addon);
|
||||
throw new TypeError(`Failed to construct '${name}': Illegal constructor`);
|
||||
}
|
||||
|
||||
function installStorage(globalObject, fixture = {}, options = {}) {
|
||||
const addon = options.addon || null;
|
||||
const request = fixture.request || {};
|
||||
|
||||
const Storage = createNativeConstructor('Storage', 0, function Storage(isNew) {
|
||||
return throwIllegalConstructor('Storage', addon);
|
||||
}, addon);
|
||||
defineValue(Storage.prototype, 'constructor', Storage, { writable: true, enumerable: false, configurable: true });
|
||||
markObjectToString(Storage.prototype, 'Storage');
|
||||
|
||||
defineNativeGetter(Storage.prototype, 'length', function () { return this.__data.size; }, { enumerable: true, configurable: true, name: 'length' }, addon);
|
||||
defineNativeValue(Storage.prototype, 'key', function key(index) { return Array.from(this.__data.keys())[Number(index)] ?? null; }, { enumerable: true, configurable: true, writable: true, name: 'key', length: 1 }, addon);
|
||||
defineNativeValue(Storage.prototype, 'getItem', function getItem(key) { key = String(key); return this.__data.has(key) ? this.__data.get(key) : null; }, { enumerable: true, configurable: true, writable: true, name: 'getItem', length: 1 }, addon);
|
||||
defineNativeValue(Storage.prototype, 'setItem', function setItem(key, value) { this.__data.set(String(key), String(value)); }, { enumerable: true, configurable: true, writable: true, name: 'setItem', length: 2 }, addon);
|
||||
defineNativeValue(Storage.prototype, 'removeItem', function removeItem(key) { this.__data.delete(String(key)); }, { enumerable: true, configurable: true, writable: true, name: 'removeItem', length: 1 }, addon);
|
||||
defineNativeValue(Storage.prototype, 'clear', function clear() { this.__data.clear(); }, { enumerable: true, configurable: true, writable: true, name: 'clear', length: 0 }, addon);
|
||||
|
||||
function createStorage(initial = {}) {
|
||||
const data = new Map(Object.entries(initial).map(([k, v]) => [String(k), String(v)]));
|
||||
const storage = Object.create(Storage.prototype);
|
||||
defineValue(storage, '__data', data, { enumerable: false, configurable: false, writable: false });
|
||||
markObjectToString(storage, 'Storage');
|
||||
return storage;
|
||||
}
|
||||
|
||||
const localStorage = createStorage(request.localStorage || fixture.localStorage || {});
|
||||
const sessionStorage = createStorage(request.sessionStorage || fixture.sessionStorage || {});
|
||||
|
||||
defineValue(globalObject, 'Storage', Storage, { writable: true, enumerable: false, configurable: true });
|
||||
defineValue(globalObject, 'localStorage', localStorage, { writable: false, enumerable: true, configurable: true });
|
||||
defineValue(globalObject, 'sessionStorage', sessionStorage, { writable: false, enumerable: true, configurable: true });
|
||||
|
||||
return { Storage, localStorage, sessionStorage, createStorage };
|
||||
}
|
||||
|
||||
function createStorage(initial = {}, options = {}) {
|
||||
const context = {};
|
||||
return installStorage(context, { localStorage: initial }, options).localStorage;
|
||||
}
|
||||
|
||||
module.exports = { createStorage, installStorage };
|
||||
Reference in New Issue
Block a user