209 lines
6.6 KiB
TypeScript
209 lines
6.6 KiB
TypeScript
import { Boolean } from "./boolean.ts";
|
|
import { TypeError } from "./errors.ts";
|
|
import { Number } from "./number.ts";
|
|
import { func, object } from "../primordials.ts";
|
|
import { String } from "./string.ts";
|
|
import { symbols, valueKey } from "../utils.ts";
|
|
import { Symbol } from "./symbol.ts";
|
|
|
|
export const Object = (() => {
|
|
class Object {
|
|
public toString(this: unknown) {
|
|
if (this === undefined) return "[object Undefined]";
|
|
else if (this === null) return "[object Null]";
|
|
else if (typeof this === "object") {
|
|
if (symbols.toStringTag in this) return "[object " + (this as any)[symbols.toStringTag] + "]";
|
|
else if (object.isArray(this)) return "[object Array]";
|
|
else return "[object Object]";
|
|
}
|
|
else if (typeof this === "number" || this instanceof Number) return "[object Number]";
|
|
else if (typeof this === "symbol" || this instanceof Symbol) return "[object Symbol]";
|
|
else if (typeof this === "string" || this instanceof String) return "[object String]";
|
|
else if (typeof this === "boolean" || this instanceof Boolean) return "[object Boolean]";
|
|
else if (typeof this === "function") return "[object Function]";
|
|
}
|
|
public valueOf() {
|
|
return this;
|
|
}
|
|
public hasOwnProperty(key: string) {
|
|
return object.getOwnMember(this, key) != null;
|
|
}
|
|
|
|
public get __proto__() {
|
|
return object.getPrototype(this);
|
|
}
|
|
public set __proto__(val) {
|
|
object.setPrototype(this, val);
|
|
}
|
|
|
|
public constructor (value?: unknown) {
|
|
if (typeof value === 'object' && value !== null) return value as any;
|
|
if (typeof value === 'string') return new String(value) as any;
|
|
if (typeof value === 'number') return new Number(value) as any;
|
|
if (typeof value === 'boolean') return new Boolean(value) as any;
|
|
if (typeof value === 'symbol') {
|
|
const res: Symbol = {} as any;
|
|
object.setPrototype(res, Symbol.prototype);
|
|
res[valueKey] = value;
|
|
return res as any;
|
|
}
|
|
|
|
return {} as any;
|
|
}
|
|
|
|
public static getOwnPropertyDescriptor(obj: object, key: any) {
|
|
return object.getOwnMember(obj, key);
|
|
}
|
|
public static getOwnPropertyNames(obj: object): string[] {
|
|
return object.getMembers(obj, true, false);
|
|
}
|
|
public static getOwnPropertySymbols(obj: object): symbol[] {
|
|
return object.getSymbolMembers(obj, true, false);
|
|
}
|
|
|
|
public static defineProperty(obj: object, key: string | symbol, desc: PropertyDescriptor) {
|
|
if (obj === null || typeof obj !== "function" && typeof obj !== "object") {
|
|
throw new TypeError("Object.defineProperty called on non-object");
|
|
}
|
|
if (desc === null || typeof desc !== "function" && typeof desc !== "object") {
|
|
throw new TypeError("Property description must be an object: " + desc);
|
|
}
|
|
const res: any = {};
|
|
|
|
if ("get" in desc || "set" in desc) {
|
|
if ("get" in desc) {
|
|
const get = desc.get;
|
|
if (get !== undefined && typeof get !== "function") throw new TypeError("Getter must be a function: " + get);
|
|
res.g = get;
|
|
}
|
|
if ("set" in desc) {
|
|
const set = desc.set;
|
|
if (set !== undefined && typeof set !== "function") throw new TypeError("Setter must be a function: " + set);
|
|
res.s = set;
|
|
}
|
|
if ("enumerable" in desc) res.e = !!desc.enumerable;
|
|
if ("configurable" in desc) res.c = !!desc.configurable;
|
|
|
|
if (!object.defineProperty(obj, key, res)) throw new TypeError("Cannot redefine property: " + String(key));
|
|
}
|
|
else {
|
|
if ("enumerable" in desc) res.e = !!desc.enumerable;
|
|
if ("configurable" in desc) res.c = !!desc.configurable;
|
|
if ("writable" in desc) res.w = !!desc.writable;
|
|
if ("value" in desc) res.v = desc.value;
|
|
|
|
if (!object.defineField(obj, key, res)) throw new TypeError("Cannot redefine property: " + String(key));
|
|
}
|
|
|
|
return obj;
|
|
}
|
|
public static defineProperties(obj: object, desc: PropertyDescriptorMap) {
|
|
const keys = object.getMembers(desc, true, true) as ((keyof typeof obj) & string)[];
|
|
const symbols = object.getSymbolMembers(desc, true, true) as ((keyof typeof obj) & symbol)[];
|
|
|
|
for (let i = 0; i < keys.length; i++) {
|
|
Object.defineProperty(obj, keys[i], desc[keys[i]]);
|
|
}
|
|
for (let i = 0; i < symbols.length; i++) {
|
|
Object.defineProperty(obj, symbols[i], desc[symbols[i]]);
|
|
}
|
|
|
|
return obj;
|
|
}
|
|
public static create(proto: object, desc?: PropertyDescriptorMap) {
|
|
let res = object.setPrototype({}, proto);
|
|
if (desc != null) this.defineProperties(res, desc);
|
|
|
|
return res;
|
|
}
|
|
public static assign(target: any) {
|
|
for (let i = 1; i < arguments.length; i++) {
|
|
const obj = arguments[i];
|
|
const keys = object.getMembers(obj, true, false);
|
|
const symbols = object.getSymbolMembers(obj, true, false);
|
|
|
|
for (let j = 0; j < keys.length; j++) {
|
|
target[keys[j]] = obj[keys[j]];
|
|
}
|
|
for (let j = 0; j < symbols.length; j++) {
|
|
target[symbols[j]] = obj[symbols[j]];
|
|
}
|
|
}
|
|
|
|
return target;
|
|
}
|
|
|
|
public static setPrototypeOf(obj: object, proto: object | null) {
|
|
object.setPrototype(obj, proto!);
|
|
}
|
|
public static getPrototypeOf(obj: object) {
|
|
return object.getPrototype(obj) || null;
|
|
}
|
|
|
|
public static keys(obj: any) {
|
|
const res: any[] = [];
|
|
const keys = object.getMembers(obj, true, true);
|
|
const symbols = object.getSymbolMembers(obj, true, true);
|
|
|
|
for (let i = 0; i < keys.length; i++) {
|
|
res[res.length] = keys[i];
|
|
}
|
|
for (let i = 0; i < symbols.length; i++) {
|
|
res[res.length] = symbols[i];
|
|
}
|
|
|
|
return res;
|
|
}
|
|
public static values(obj: any) {
|
|
const res: any[] = [];
|
|
const keys = object.getMembers(obj, true, true);
|
|
const symbols = object.getSymbolMembers(obj, true, true);
|
|
|
|
for (let i = 0; i < keys.length; i++) {
|
|
res[res.length] = obj[keys[i]];
|
|
}
|
|
for (let i = 0; i < symbols.length; i++) {
|
|
res[res.length] = obj[symbols[i]];
|
|
}
|
|
|
|
return res;
|
|
}
|
|
public static entries(obj: any) {
|
|
const res: [any, any][] = [];
|
|
const keys = object.getMembers(obj, true, true);
|
|
const symbols = object.getSymbolMembers(obj, true, true);
|
|
|
|
for (let i = 0; i < keys.length; i++) {
|
|
res[res.length] = [keys[i], obj[keys[i]]];
|
|
}
|
|
for (let i = 0; i < symbols.length; i++) {
|
|
res[res.length] = [symbols[i], obj[symbols[i]]];
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
public static preventExtensions(obj: object) {
|
|
object.preventExt(obj);
|
|
return obj;
|
|
}
|
|
public static seal(obj: object) {
|
|
object.seal(obj);
|
|
return obj;
|
|
}
|
|
public static freeze(obj: object) {
|
|
object.freeze(obj);
|
|
return obj;
|
|
}
|
|
}
|
|
|
|
object.defineProperty(Object.prototype, "__proto__", { e: false });
|
|
object.setPrototype(Object.prototype, undefined);
|
|
|
|
func.setCallable(Object, true);
|
|
func.setConstructable(Object, true);
|
|
|
|
return Object as any as typeof Object & ((value?: unknown) => object);
|
|
})();
|
|
export type Object = InstanceType<typeof Object>;
|