typia
Version:
Superfast runtime validators with only one line
200 lines • 7.92 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports._plainCloneAny = void 0;
const _plainCloneAny = (value) => cloneMain(value);
exports._plainCloneAny = _plainCloneAny;
const NOT_NATIVE = Symbol("not-native");
const objectToString = Object.prototype.toString;
const getter = (prototype, key) => Object.getOwnPropertyDescriptor(prototype, key).get;
const read = (accessor, value) => Reflect.apply(accessor, value, []);
const tryRead = (accessor, value) => {
if (accessor === undefined)
return { success: false };
try {
return { success: true, value: read(accessor, value) };
}
catch (_a) {
return { success: false };
}
};
const arrayBufferByteLength = getter(ArrayBuffer.prototype, "byteLength");
const sharedArrayBufferByteLength = typeof SharedArrayBuffer === "undefined"
? undefined
: getter(SharedArrayBuffer.prototype, "byteLength");
const dataViewBuffer = getter(DataView.prototype, "buffer");
const dataViewByteLength = getter(DataView.prototype, "byteLength");
const dataViewByteOffset = getter(DataView.prototype, "byteOffset");
const typedArrayName = getter(Object.getPrototypeOf(Uint8Array.prototype), Symbol.toStringTag);
const blobSize = typeof Blob === "undefined" ? undefined : getter(Blob.prototype, "size");
const blobType = typeof Blob === "undefined" ? undefined : getter(Blob.prototype, "type");
const fileName = typeof File === "undefined" ? undefined : getter(File.prototype, "name");
const fileLastModified = typeof File === "undefined"
? undefined
: getter(File.prototype, "lastModified");
const regexpSource = getter(RegExp.prototype, "source");
const regexpFlags = getter(RegExp.prototype, "flags");
const nativeTag = (value) => {
let tagged;
try {
tagged = Symbol.toStringTag in value;
}
catch (_a) {
return undefined;
}
if (!tagged)
try {
return objectToString.call(value);
}
catch (_b) {
return undefined;
}
const date = tryRead(Date.prototype.getTime, value);
if (date.success)
return "[object Date]";
const typed = tryRead(typedArrayName, value);
if (typed.success && typed.value !== undefined)
return `[object ${typed.value}]`;
if (tryRead(arrayBufferByteLength, value).success)
return "[object ArrayBuffer]";
if (tryRead(sharedArrayBufferByteLength, value).success)
return "[object SharedArrayBuffer]";
if (tryRead(dataViewBuffer, value).success)
return "[object DataView]";
if (tryRead(fileName, value).success)
return "[object File]";
if (tryRead(blobSize, value).success)
return "[object Blob]";
if (tryRead(regexpSource, value).success)
return "[object RegExp]";
return undefined;
};
const cloneMain = (value) => {
if (value === undefined)
return undefined;
else if (typeof value === "object")
if (value === null)
return null;
else if (Array.isArray(value))
return value.map(cloneMain);
else {
const native = cloneNative(value);
if (native !== NOT_NATIVE)
return native;
else if (value instanceof Set)
return new Set([...value].map(cloneMain));
else if (value instanceof Map)
return new Map([...value].map(([k, v]) => [cloneMain(k), cloneMain(v)]));
else if (value instanceof WeakSet || value instanceof WeakMap)
throw new Error("WeakSet and WeakMap are not supported");
else {
const primitive = value.valueOf();
if (primitive !== value)
return cloneMain(primitive);
return Object.fromEntries(Object.entries(value)
.map(([k, v]) => [k, cloneMain(v)])
.filter(([, v]) => v !== undefined));
}
}
else if (typeof value === "function")
return undefined;
return value;
};
const cloneNative = (value) => {
const tag = nativeTag(value);
switch (tag) {
case "[object Date]": {
const time = tryRead(Date.prototype.getTime, value);
return time.success ? new Date(time.value) : NOT_NATIVE;
}
case "[object Uint8Array]":
return new Uint8Array(value);
case "[object Uint8ClampedArray]":
return new Uint8ClampedArray(value);
case "[object Uint16Array]":
return new Uint16Array(value);
case "[object Uint32Array]":
return new Uint32Array(value);
case "[object BigUint64Array]":
return new BigUint64Array(value);
case "[object Int8Array]":
return new Int8Array(value);
case "[object Int16Array]":
return new Int16Array(value);
case "[object Int32Array]":
return new Int32Array(value);
case "[object BigInt64Array]":
return new BigInt64Array(value);
case "[object Float32Array]":
return new Float32Array(value);
case "[object Float64Array]":
return new Float64Array(value);
case "[object ArrayBuffer]": {
const byteLength = tryRead(arrayBufferByteLength, value);
return byteLength.success
? cloneBufferRange(value, 0, byteLength.value, false)
: NOT_NATIVE;
}
case "[object SharedArrayBuffer]": {
const byteLength = tryRead(sharedArrayBufferByteLength, value);
return byteLength.success
? cloneBufferRange(value, 0, byteLength.value, true)
: NOT_NATIVE;
}
case "[object DataView]": {
const buffer = tryRead(dataViewBuffer, value);
if (!buffer.success)
return NOT_NATIVE;
const byteOffset = read(dataViewByteOffset, value);
const byteLength = read(dataViewByteLength, value);
return new DataView(cloneBufferRange(buffer.value, byteOffset, byteLength));
}
case "[object File]": {
const size = tryRead(blobSize, value);
if (typeof File === "undefined" ||
!size.success ||
blobType === undefined ||
fileName === undefined ||
fileLastModified === undefined)
return NOT_NATIVE;
return new File([value], read(fileName, value), {
type: read(blobType, value),
lastModified: read(fileLastModified, value),
});
}
case "[object Blob]": {
const size = tryRead(blobSize, value);
if (typeof Blob === "undefined" ||
!size.success ||
blobType === undefined)
return NOT_NATIVE;
return new Blob([value], {
type: read(blobType, value),
});
}
case "[object RegExp]": {
const source = tryRead(regexpSource, value);
return source.success
? new RegExp(source.value, read(regexpFlags, value))
: NOT_NATIVE;
}
default:
return NOT_NATIVE;
}
};
const cloneBufferRange = (input, byteOffset, byteLength, shared) => {
if (shared === undefined)
shared = tryRead(sharedArrayBufferByteLength, input).success;
let output;
if (shared) {
if (typeof SharedArrayBuffer === "undefined")
throw new TypeError("SharedArrayBuffer is not available");
output = new SharedArrayBuffer(byteLength);
}
else {
read(arrayBufferByteLength, input);
output = new ArrayBuffer(byteLength);
}
new Uint8Array(output).set(new Uint8Array(input, byteOffset, byteLength));
return output;
};
//# sourceMappingURL=_plainCloneAny.js.map