From 2460d7b6ef5bfa90f63d656be051d4a1b257e5dd Mon Sep 17 00:00:00 2001 From: upstream Date: Fri, 4 Sep 2026 05:12:29 +0200 Subject: [PATCH] Upstream lukeed/klona state of the touched files before fb0cab4de3 --- src/full.js | 53 +++++++++++++++++++++++++++++ src/index.js | 81 ++++++++++++++++++++++++++++++++++++++++++++ src/json.js | 28 +++++++++++++++ src/lite.js | 51 ++++++++++++++++++++++++++++ test/full.js | 28 +++++++++++++++ test/index.js | 24 +++++++++++++ test/json.js | 14 ++++++++ test/lite.js | 19 +++++++++++ test/suites/index.js | 24 +++++++++++++ 9 files changed, 322 insertions(+) create mode 100644 src/full.js create mode 100644 src/index.js create mode 100644 src/json.js create mode 100644 src/lite.js create mode 100644 test/full.js create mode 100644 test/index.js create mode 100644 test/json.js create mode 100644 test/lite.js create mode 100644 test/suites/index.js diff --git a/src/full.js b/src/full.js new file mode 100644 index 0000000..b5f86c3 --- /dev/null +++ b/src/full.js @@ -0,0 +1,53 @@ +function set(obj, key, val) { + if (typeof val.value === 'object') val.value = klona(val.value); + if (!val.enumerable || val.get || val.set || !val.configurable || !val.writable || key === '__proto__') { + Object.defineProperty(obj, key, val); + } else obj[key] = val.value; +} + +export function klona(x) { + if (typeof x !== 'object') return x; + + var i=0, k, list, tmp, str=Object.prototype.toString.call(x); + + if (str === '[object Object]') { + tmp = Object.create(x.__proto__ || null); + } else if (str === '[object Array]') { + tmp = Array(x.length); + } else if (str === '[object Set]') { + tmp = new Set; + x.forEach(function (val) { + tmp.add(klona(val)); + }); + } else if (str === '[object Map]') { + tmp = new Map; + x.forEach(function (val, key) { + tmp.set(klona(key), klona(val)); + }); + } else if (str === '[object Date]') { + tmp = new Date(+x); + } else if (str === '[object RegExp]') { + tmp = new RegExp(x.source, x.flags); + } else if (str === '[object DataView]') { + tmp = new x.constructor( klona(x.buffer) ); + } else if (str === '[object ArrayBuffer]') { + tmp = x.slice(0); + } else if (str.slice(-6) === 'Array]') { + // ArrayBuffer.isView(x) + // ~> `new` bcuz `Buffer.slice` => ref + tmp = new x.constructor(x); + } + + if (tmp) { + for (list=Object.getOwnPropertySymbols(x); i < list.length; i++) { + set(tmp, list[i], Object.getOwnPropertyDescriptor(x, list[i])); + } + + for (i=0, list=Object.getOwnPropertyNames(x); i < list.length; i++) { + if (Object.hasOwnProperty.call(tmp, k=list[i]) && tmp[k] === x[k]) continue; + set(tmp, k, Object.getOwnPropertyDescriptor(x, k)); + } + } + + return tmp || x; +} diff --git a/src/index.js b/src/index.js new file mode 100644 index 0000000..4b866ba --- /dev/null +++ b/src/index.js @@ -0,0 +1,81 @@ +export function klona(x) { + if (typeof x !== 'object') return x; + + var k, tmp, str=Object.prototype.toString.call(x); + + if (str === '[object Object]') { + if (x.constructor !== Object && typeof x.constructor === 'function') { + tmp = new x.constructor(); + for (k in x) { + if (x.hasOwnProperty(k) && tmp[k] !== x[k]) { + tmp[k] = klona(x[k]); + } + } + } else { + tmp = {}; // null + for (k in x) { + if (k === '__proto__') { + Object.defineProperty(tmp, k, { + value: klona(x[k]), + configurable: true, + enumerable: true, + writable: true, + }); + } else { + tmp[k] = klona(x[k]); + } + } + } + return tmp; + } + + if (str === '[object Array]') { + k = x.length; + for (tmp=Array(k); k--;) { + tmp[k] = klona(x[k]); + } + return tmp; + } + + if (str === '[object Set]') { + tmp = new Set; + x.forEach(function (val) { + tmp.add(klona(val)); + }); + return tmp; + } + + if (str === '[object Map]') { + tmp = new Map; + x.forEach(function (val, key) { + tmp.set(klona(key), klona(val)); + }); + return tmp; + } + + if (str === '[object Date]') { + return new Date(+x); + } + + if (str === '[object RegExp]') { + tmp = new RegExp(x.source, x.flags); + tmp.lastIndex = x.lastIndex; + return tmp; + } + + if (str === '[object DataView]') { + return new x.constructor( klona(x.buffer) ); + } + + if (str === '[object ArrayBuffer]') { + return x.slice(0); + } + + // ArrayBuffer.isView(x) + // ~> `new` bcuz `Buffer.slice` => ref + if (str.slice(-6) === 'Array]') { + return new x.constructor(x); + } + + return x; +} diff --git a/src/json.js b/src/json.js new file mode 100644 index 0000000..eae543d --- /dev/null +++ b/src/json.js @@ -0,0 +1,28 @@ +export function klona(val) { + var k, out, tmp; + + if (Array.isArray(val)) { + out = Array(k=val.length); + while (k--) out[k] = (tmp=val[k]) && typeof tmp === 'object' ? klona(tmp) : tmp; + return out; + } + + if (Object.prototype.toString.call(val) === '[object Object]') { + out = {}; // null + for (k in val) { + if (k === '__proto__') { + Object.defineProperty(out, k, { + value: klona(val[k]), + configurable: true, + enumerable: true, + writable: true, + }); + } else { + out[k] = (tmp=val[k]) && typeof tmp === 'object' ? klona(tmp) : tmp; + } + } + return out; + } + + return val; +} diff --git a/src/lite.js b/src/lite.js new file mode 100644 index 0000000..bbd342e --- /dev/null +++ b/src/lite.js @@ -0,0 +1,51 @@ +export function klona(x) { + if (typeof x !== 'object') return x; + + var k, tmp, str=Object.prototype.toString.call(x); + + if (str === '[object Object]') { + if (x.constructor !== Object && typeof x.constructor === 'function') { + tmp = new x.constructor(); + for (k in x) { + if (x.hasOwnProperty(k) && tmp[k] !== x[k]) { + tmp[k] = klona(x[k]); + } + } + } else { + tmp = {}; // null + for (k in x) { + if (k === '__proto__') { + Object.defineProperty(tmp, k, { + value: klona(x[k]), + configurable: true, + enumerable: true, + writable: true, + }); + } else { + tmp[k] = klona(x[k]); + } + } + } + return tmp; + } + + if (str === '[object Array]') { + k = x.length; + for (tmp=Array(k); k--;) { + tmp[k] = klona(x[k]); + } + return tmp; + } + + if (str === '[object Date]') { + return new Date(+x); + } + + if (str === '[object RegExp]') { + tmp = new RegExp(x.source, x.flags); + tmp.lastIndex = x.lastIndex; + return tmp; + } + + return x; +} diff --git a/test/full.js b/test/full.js new file mode 100644 index 0000000..816a9b7 --- /dev/null +++ b/test/full.js @@ -0,0 +1,28 @@ +import * as suites from './suites'; +import { klona } from '../src/full'; + +suites.API(klona); + +suites.Strings(klona); +suites.Booleans(klona); +suites.Numbers(klona); +suites.Nully(klona); + +suites.Dates(klona); +suites.RegExps(klona); + +suites.Objects(klona); +suites.Arrays(klona); + +suites.Functions(klona); +suites.Pollutions(klona); +suites.Classes(klona); + +suites.Maps(klona); +suites.Sets(klona); + +suites.TypedArrays(klona); + +suites.Symbols(klona); +suites.Descriptors(klona); +suites.Dicts(klona); diff --git a/test/index.js b/test/index.js new file mode 100644 index 0000000..46470d4 --- /dev/null +++ b/test/index.js @@ -0,0 +1,24 @@ +import * as suites from './suites'; +import { klona } from '../src/index'; + +suites.API(klona); + +suites.Strings(klona); +suites.Booleans(klona); +suites.Numbers(klona); +suites.Nully(klona); + +suites.Dates(klona); +suites.RegExps(klona); + +suites.Objects(klona); +suites.Arrays(klona); + +suites.Functions(klona); +suites.Pollutions(klona); +suites.Classes(klona); + +suites.Maps(klona); +suites.Sets(klona); + +suites.TypedArrays(klona); diff --git a/test/json.js b/test/json.js new file mode 100644 index 0000000..d32a942 --- /dev/null +++ b/test/json.js @@ -0,0 +1,14 @@ +import * as suites from './suites'; +import { klona } from '../src/json'; + +suites.API(klona); + +suites.Strings(klona); +suites.Booleans(klona); +suites.Numbers(klona); +suites.Nully(klona); + +suites.Objects(klona); +suites.Arrays(klona); + +suites.Pollutions(klona); diff --git a/test/lite.js b/test/lite.js new file mode 100644 index 0000000..a406dc3 --- /dev/null +++ b/test/lite.js @@ -0,0 +1,19 @@ +import * as suites from './suites'; +import { klona } from '../src/lite'; + +suites.API(klona); + +suites.Strings(klona); +suites.Booleans(klona); +suites.Numbers(klona); +suites.Nully(klona); + +suites.Dates(klona); +suites.RegExps(klona); + +suites.Objects(klona); +suites.Arrays(klona); + +suites.Functions(klona); +suites.Pollutions(klona); +suites.Classes(klona); diff --git a/test/suites/index.js b/test/suites/index.js new file mode 100644 index 0000000..7d5ccfc --- /dev/null +++ b/test/suites/index.js @@ -0,0 +1,24 @@ +export { default as API } from './api'; + +export { default as Numbers } from './number'; +export { default as Booleans } from './boolean'; +export { default as Strings } from './string'; +export { default as Nully } from './nullish'; + +export { default as Maps } from './map'; +export { default as Sets } from './set'; + +export { default as TypedArrays } from './typedarray'; +export { default as Descriptors } from './descriptor'; +export { default as Symbols } from './symbol'; + +export { default as Dates } from './date'; +export { default as RegExps } from './regexp'; + +export { default as Dicts } from './dictionary'; +export { default as Objects } from './object'; +export { default as Arrays } from './array'; + +export { default as Functions } from './function'; +export { default as Pollutions } from './pollution'; +export { default as Classes } from './class';