Created
December 16, 2023 09:04
-
-
Save nyteshade/d540ea79443028466292ac9b32669f9c to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
globalThis.Descriptor = class Descriptor { | |
static base(enumerable = true, configurable = true) { | |
return { enumerable, configurable } | |
} | |
static data(value, writable = true, { configurable, writable } = this.base()) { | |
return { value, enumerable, configurable, writable } | |
} | |
static accessor( getter, setter, store, { configurable, writable } = this.base()) { | |
if (Object.isObject(store)) { | |
// controversial | |
const injectStore = (fn) => { | |
let source = String(fn) | |
source = source.replace(/(?:get|set)(\s*)(\w+)?\((.*?)\)/, 'function$1$2($3)') | |
source = source.replace(/^(.*?)\{/, ) | |
} | |
} | |
} | |
} | |
Object.defineProperties(Function, { | |
isClass: { | |
value(value) { | |
return String(value).includes('class') | |
}, | |
configurable: true, | |
enumerable: true, | |
writable: true, | |
} | |
}) | |
Object.defineProperties(Object, { | |
isObject: { | |
value(value, falseIfIsArray = false) { | |
if ((Array.isArray(value) && falseIfIsArray) || value instanceof Function) { | |
return false | |
} | |
return ((value !== null && typeof(value) === 'object') || value instanceof Object) | |
}, | |
configurable: true, | |
enumerable: true, | |
writable: true, | |
}, | |
copy: { | |
value(...sources) { | |
const prototype = Object.getPrototypeOf(sources?.[0] ?? {}) | |
const target = Object.create(prototype) | |
return Object.copyTo(target, ...sources) | |
}, | |
configurable: true, | |
enumerable: true, | |
writable: true, | |
}, | |
copyTo: { | |
value(target, ...sources) { | |
if (!Object.isObject(target)) { | |
return null | |
} | |
sources.forEach(source => { | |
if (!source) { | |
return | |
} | |
const isArray = a => Array.isArray(a?.value) | |
const isObject = o => Object.isObject(o?.value) | |
const isRegExp = r => | |
const arrayClone = a => (a?.map(element => { | |
if (Object.isObject(element)) return Object.copy(element) | |
if (Array.isArray(element)) return arrayClone(element) | |
}) ?? null) | |
const descriptors = (Object.descriptors(source) | |
.reduce((accumulator, [key, descriptor]) => { | |
if (isArray(descriptor)) { | |
accumulator[key] = { ...descriptor, value: arrayClone(descriptor.value) } | |
} | |
else if (isObject(descriptor)) { | |
accumulator[key] = { ...descriptor, value: Object.copy(descriptor.value) } | |
} | |
else { | |
accumulator[key] = descriptor | |
} | |
return accumulator | |
}, {}) | |
) | |
Object.defineProperties(target, descriptors) | |
}) | |
return target | |
} | |
}, | |
descriptors: { | |
value(object, asObject = false, includeThis = false) { | |
const isClass = (value) => String(value?.constructor).includes('class') | |
function transform(value, isProto = false) { | |
const keys = Reflect.ownKeys(value) | |
return keys.reduce((accumulator, key) => { | |
const descriptor = Object.getOwnPropertyDescriptor(value, key) | |
if (asObject) { | |
accumulator[key] = descriptor | |
if (includeThis) { | |
accumulator[`${String(key)}:this`] = value | |
accumulator[`${String(key)}:isPrototype`] = isProto | |
} | |
} | |
else { | |
const entry = [key, descriptor] | |
if (includeThis) { | |
entry.push(value) | |
entry.push(isProto) | |
} | |
accumulator.push(entry) | |
} | |
return accumulator | |
}, asObject ? {} : []) | |
} | |
let descriptors = asObject ? {} : [] | |
if (isClass(object) && object?.constructor?.prototype) { | |
const prototype = object.constructor.prototype | |
if (asObject) | |
descriptors = { ...descriptors, ...transform(prototype, true) } | |
else | |
descriptors = descriptors.concat(transform(prototype, true)) | |
} | |
if (asObject) | |
descriptors = { ...descriptors, ...transform(object) } | |
else | |
descriptors = descriptors.concat(transform(object)) | |
return descriptors | |
}, | |
enumerable: true, | |
configurable: true, | |
writable: true, | |
} | |
}) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment