linvail
Version:
Provenancial Equality for JavaScript
636 lines (634 loc) • 20 kB
JavaScript
import {
atExternal,
atInternal,
closeIterator,
fromInternalDescriptor,
getInternalDescriptorValue,
getLength,
toInternalDefineDescriptor,
toPrototype,
toInternalReferenceSloppy,
toInternalReferenceStrict,
toPropertyKey,
void_oracle,
} from "./helper.mjs";
import {
applyInternal,
defineInternalPropertyDescriptor,
getInternalOwnPropertyDescriptor,
getInternalPropertyValue,
listInternalOwnPropertyKey,
setInternalPropertyValue,
} from "../reflect.mjs";
import {
wrapStandardPrimitive,
wrapValue,
wrapReference,
} from "../region/core.mjs";
import {
createEmptyArray,
createEmptyObject,
createFullArray,
} from "../region/create.mjs";
/**
* @type {Record<
* (
* | "global.Object"
* | `global.Object.${keyof typeof Object}`
* ),
* import("../oracle.d.ts").Oracle
* >}
*/
export const object_oracle_record = {
"global.Object": {
construct: (region, input, new_target) => {
const {
"global.Object": Object,
"global.Object.prototype": object_prototype,
} = region;
if (new_target.inner === Object) {
const internal = atInternal(region, input, 0);
if (internal.inner == null) {
return createEmptyObject(region, object_prototype);
}
if (internal.type === "primitive") {
return wrapReference(region, Object(internal.inner));
} else {
return internal;
}
} else {
const prototype = getInternalPropertyValue(
region,
new_target,
"prototype",
new_target,
);
if (prototype.type === "primitive") {
// BREAKAGE: it should be the Object.prototype from the new_targets' realm
return createEmptyObject(region, object_prototype);
} else {
return createEmptyObject(region, prototype.inner);
}
}
},
apply: (region, _that, input) => {
const {
"global.Object": Object,
"global.Object.prototype": object_prototype,
} = region;
const internal = atInternal(region, input, 0);
if (internal.inner == null) {
return createEmptyObject(region, object_prototype);
}
if (internal.type === "primitive") {
return wrapReference(region, Object(internal.inner));
} else {
return internal;
}
},
},
"global.Object.prototype": void_oracle, // not a function
"global.Object.assign": {
construct: null,
apply: (region, _that, input) => {
const { "global.TypeError": TypeError } = region;
const target = toInternalReferenceSloppy(
region,
atInternal(region, input, 0),
);
for (let index = 1; index < input.length; index++) {
const original_source = atInternal(region, input, index);
if (original_source.inner != null) {
const source = toInternalReferenceSloppy(region, original_source);
const keys = listInternalOwnPropertyKey(region, source);
for (let index = 0; index < keys.length; index++) {
const key = keys[index];
const descriptor = getInternalOwnPropertyDescriptor(
region,
source,
key,
);
if (descriptor && descriptor.enumerable) {
if (
!setInternalPropertyValue(
region,
target,
key,
getInternalPropertyValue(region, source, key, source),
target,
)
) {
throw new TypeError("Cannot set property at Object.assign");
}
}
}
}
}
return target;
},
},
"global.Object.create": {
construct: null,
apply: (region, _that, input) => {
const { "global.undefined": undefined } = region;
const prototype = toPrototype(region, atInternal(region, input, 0));
const raw_property_record = atInternal(region, input, 1);
if (raw_property_record.inner === undefined) {
return createEmptyObject(region, prototype);
} else {
const properties = toInternalReferenceSloppy(
region,
raw_property_record,
);
const target = createEmptyObject(region, prototype);
const keys = listInternalOwnPropertyKey(region, properties);
const { length } = keys;
for (let index = 0; index < length; index++) {
const key = keys[index];
const descriptor = getInternalOwnPropertyDescriptor(
region,
properties,
key,
);
if (descriptor && descriptor.enumerable) {
defineInternalPropertyDescriptor(
region,
target,
key,
toInternalDefineDescriptor(
region,
getInternalDescriptorValue(region, descriptor, properties),
),
);
}
}
return target;
}
},
},
"global.Object.defineProperties": {
construct: null,
apply: (region, _that, input) => {
const { "global.TypeError": TypeError } = region;
const target = toInternalReferenceStrict(
region,
atInternal(region, input, 0),
);
const descriptors = toInternalReferenceSloppy(
region,
atInternal(region, input, 1),
);
const keys = listInternalOwnPropertyKey(region, descriptors);
for (let index = 0; index < keys.length; index++) {
const key = keys[index];
const descriptor = getInternalOwnPropertyDescriptor(
region,
descriptors,
key,
);
if (descriptor && descriptor.enumerable) {
if (
!defineInternalPropertyDescriptor(
region,
target,
key,
toInternalDefineDescriptor(
region,
getInternalPropertyValue(region, descriptors, key, descriptors),
),
)
) {
throw new TypeError(
"Failed to define property at Object.defineProperties",
);
}
}
}
return target;
},
},
"global.Object.defineProperty": {
construct: null,
apply: (region, _that, input) => {
const { "global.TypeError": TypeError } = region;
const target = toInternalReferenceStrict(
region,
atInternal(region, input, 0),
);
const key = toPropertyKey(region, atExternal(region, input, 1));
const descriptor = toInternalDefineDescriptor(
region,
atInternal(region, input, 2),
);
if (!defineInternalPropertyDescriptor(region, target, key, descriptor)) {
throw new TypeError(
"Failed to define property at Object.defineProperty",
);
}
return target;
},
},
"global.Object.entries": {
construct: null,
apply: (region, _that, input) => {
const { "global.Reflect.defineProperty": defineProperty } = region;
const target = toInternalReferenceSloppy(
region,
atInternal(region, input, 0),
);
const keys = listInternalOwnPropertyKey(region, target);
const entries = createEmptyArray(region, 0);
let length = 0;
for (let index = 0; index < keys.length; index++) {
const key = keys[index];
if (typeof key === "string") {
const descriptor = getInternalOwnPropertyDescriptor(
region,
target,
key,
);
if (descriptor && descriptor.enumerable) {
defineProperty(entries.plain, length, {
__proto__: null,
value: createFullArray(region, [
wrapStandardPrimitive(region, key),
getInternalPropertyValue(region, target, key, target),
]),
writable: true,
enumerable: true,
configurable: true,
});
length++;
}
}
}
return entries;
},
},
"global.Object.freeze": void_oracle, // no benefit
"global.Object.fromEntries": {
construct: null,
apply: (region, _that, input) => {
const {
"global.TypeError": TypeError,
"global.Symbol.iterator": iterator_symbol,
"global.Object.prototype": object_prototype,
"global.Reflect.defineProperty": defineProperty,
} = region;
const entries = toInternalReferenceSloppy(
region,
atInternal(region, input, 0),
);
const object = createEmptyObject(region, object_prototype);
const iterator = toInternalReferenceStrict(
region,
applyInternal(
region,
toInternalReferenceStrict(
region,
getInternalPropertyValue(region, entries, iterator_symbol, entries),
),
entries,
[],
),
);
const next = toInternalReferenceStrict(
region,
getInternalPropertyValue(region, iterator, "next", iterator),
);
let done = false;
while (!done) {
const step = toInternalReferenceStrict(
region,
applyInternal(region, next, iterator, []),
);
done = !!getInternalPropertyValue(region, step, "done", step).inner;
if (!done) {
const original_entry = getInternalPropertyValue(
region,
step,
"value",
step,
);
if (original_entry.type === "primitive") {
closeIterator(region, iterator);
throw new TypeError(
"Iterator result should be an object at Object.fromEntries",
);
}
const entry = toInternalReferenceStrict(
region,
getInternalPropertyValue(region, step, "value", step),
);
let key, val;
try {
const entry0 = getInternalPropertyValue(region, entry, 0, entry);
const entry1 = getInternalPropertyValue(region, entry, 1, entry);
key = toPropertyKey(region, entry0.inner);
val = entry1;
} catch (error) {
closeIterator(region, iterator);
throw error;
}
if (
!defineProperty(object.plain, key, {
__proto__: null,
value: val,
writable: true,
enumerable: true,
configurable: true,
})
) {
throw new TypeError("Cannot define property at Object.fromEntries");
}
}
}
return object;
},
},
"global.Object.getOwnPropertyDescriptor": {
construct: null,
apply: (region, _that, input) => {
const target = toInternalReferenceSloppy(
region,
atInternal(region, input, 0),
);
const key = toPropertyKey(region, atExternal(region, input, 1));
const descriptor = getInternalOwnPropertyDescriptor(region, target, key);
return descriptor
? fromInternalDescriptor(region, descriptor)
: wrapStandardPrimitive(region, descriptor);
},
},
"global.Object.getOwnPropertyDescriptors": {
construct: null,
apply: (region, _that, input) => {
const { "global.Object.prototype": object_prototype } = region;
const target = toInternalReferenceSloppy(
region,
atInternal(region, input, 0),
);
const keys = listInternalOwnPropertyKey(region, target);
const descriptors = createEmptyObject(region, object_prototype);
for (let index = 0; index < keys.length; index++) {
const key = keys[index];
const descriptor = getInternalOwnPropertyDescriptor(
region,
target,
key,
);
if (descriptor) {
defineInternalPropertyDescriptor(region, descriptors, key, {
__proto__: null,
value: fromInternalDescriptor(region, descriptor),
writable: true,
enumerable: true,
configurable: true,
});
}
}
return descriptors;
},
},
"global.Object.getOwnPropertyNames": {
construct: null,
apply: (region, _that, input) => {
const { "global.Reflect.defineProperty": defineProperty } = region;
const target = toInternalReferenceSloppy(
region,
atInternal(region, input, 0),
);
const keys = listInternalOwnPropertyKey(region, target);
const strings = createEmptyArray(region, 0);
let length = 0;
for (let index = 0; index < keys.length; index++) {
const key = keys[index];
if (typeof key === "string") {
defineProperty(strings.plain, length, {
__proto__: null,
value: wrapStandardPrimitive(region, key),
writable: true,
enumerable: true,
configurable: true,
});
length++;
}
}
return strings;
},
},
"global.Object.getOwnPropertySymbols": {
construct: null,
apply: (region, _that, input) => {
const { "global.Reflect.defineProperty": defineProperty } = region;
const target = toInternalReferenceSloppy(
region,
atInternal(region, input, 0),
);
const keys = listInternalOwnPropertyKey(region, target);
const strings = createEmptyArray(region, 0);
let length = 0;
for (let index = 0; index < keys.length; index++) {
const key = keys[index];
if (typeof key === "symbol") {
defineProperty(strings.plain, length, {
__proto__: null,
value: wrapValue(region, key),
writable: true,
enumerable: true,
configurable: true,
});
length++;
}
}
return strings;
},
},
"global.Object.getPrototypeOf": void_oracle, // no benefit
"global.Object.groupBy": {
construct: null,
apply: (region, _that, input) => {
const {
"global.undefined": undefined,
"global.Reflect.defineProperty": defineProperty,
"global.Symbol.iterator": iterator_symbol,
"global.TypeError": TypeError,
} = region;
const items = toInternalReferenceSloppy(
region,
atInternal(region, input, 0),
);
const callback = toInternalReferenceSloppy(
region,
atInternal(region, input, 1),
);
if (typeof callback.inner !== "function") {
throw new TypeError("Callback is not a function at Object.groupBy");
}
const result = createEmptyObject(region, null);
const iterator = toInternalReferenceStrict(
region,
applyInternal(
region,
toInternalReferenceStrict(
region,
getInternalPropertyValue(region, items, iterator_symbol, items),
),
items,
[],
),
);
const next = toInternalReferenceStrict(
region,
getInternalPropertyValue(region, iterator, "next", iterator),
);
let done = false;
/**
* @type {{
* [key in PropertyKey]?:
* import("../domain.d.ts").HostReferenceWrapper<"array">
* }}
*/
const groups = /** @type {any} */ ({ __proto__: null });
let index = 0;
while (!done) {
const step = toInternalReferenceStrict(
region,
applyInternal(region, next, iterator, []),
);
done = !!getInternalPropertyValue(region, step, "done", step).inner;
if (!done) {
const item = getInternalPropertyValue(region, step, "value", step);
const key = toPropertyKey(
region,
applyInternal(
region,
callback,
wrapStandardPrimitive(region, undefined),
[item, wrapStandardPrimitive(region, index++)],
).inner,
);
let group = groups[key];
if (!group) {
group = createEmptyArray(region, 0);
groups[key] = group;
if (
!defineProperty(result.plain, key, {
__proto__: null,
value: group,
writable: true,
enumerable: true,
configurable: true,
})
) {
throw new TypeError("Cannot define group at Object.groupBy");
}
}
const length = getLength(region, group);
if (
!defineProperty(group.plain, length, {
__proto__: null,
value: item,
writable: true,
enumerable: true,
configurable: true,
})
) {
throw new TypeError("Cannot set group index at Object.groupBy");
}
}
}
return result;
},
},
"global.Object.hasOwn": void_oracle, // no benefit
"global.Object.is": void_oracle, // no benefit
"global.Object.isExtensible": void_oracle, // no benefit
"global.Object.isFrozen": void_oracle, // no benefit
"global.Object.isSealed": void_oracle, // no benefit
"global.Object.keys": {
construct: null,
apply: (region, _that, input) => {
const {
"global.TypeError": TypeError,
"global.Reflect.defineProperty": defineProperty,
} = region;
const target = toInternalReferenceSloppy(
region,
atInternal(region, input, 0),
);
const keys = listInternalOwnPropertyKey(region, target);
const result = createEmptyArray(region, 0);
let length = 0;
for (let index = 0; index < keys.length; index++) {
const key = keys[index];
if (typeof key === "string") {
const descriptor = getInternalOwnPropertyDescriptor(
region,
target,
key,
);
if (descriptor && descriptor.enumerable) {
if (
!defineProperty(result.plain, length, {
__proto__: null,
value: wrapStandardPrimitive(region, key),
writable: true,
enumerable: true,
configurable: true,
})
) {
throw new TypeError("Cannot define property at Object.keys");
}
length++;
}
}
}
return result;
},
},
"global.Object.preventExtensions": void_oracle, // no benefit
"global.Object.seal": void_oracle, // no benefit
"global.Object.setPrototypeOf": void_oracle, // no benefit
"global.Object.values": {
construct: null,
apply: (region, _that, input) => {
const {
"global.TypeError": TypeError,
"global.Reflect.defineProperty": defineProperty,
} = region;
const target = toInternalReferenceSloppy(
region,
atInternal(region, input, 0),
);
const keys = listInternalOwnPropertyKey(region, target);
const result = createEmptyArray(region, 0);
let length = 0;
for (let index = 0; index < keys.length; index++) {
const key = keys[index];
if (typeof key === "string") {
const descriptor = getInternalOwnPropertyDescriptor(
region,
target,
key,
);
if (descriptor && descriptor.enumerable) {
if (
!defineProperty(result.plain, length, {
__proto__: null,
value: getInternalPropertyValue(region, target, key, target),
writable: true,
enumerable: true,
configurable: true,
})
) {
throw new TypeError("Cannot define property at Object.values");
}
length++;
}
}
}
return result;
},
},
};