-
Notifications
You must be signed in to change notification settings - Fork 3
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Objects with null prototypes lose type information #3
Comments
Similar issue: Object.setPrototypeOf(new Number(-0), Array.prototype) expected: |
For the first problem, I don't think it is possible to find the name of an object's class after its prototype is set to For the second issue, we can get type with const n = new Number(-0);
Object.setPrototypeOf(n, Array.prototype);
console.log(Object.prototype.toString.call(n));
// [object Number] The reason why we don't get expected output Function isBoxedPrimitive(val) {
return isNumberObject(val) ||
isStringObject(val) ||
isBooleanObject(val) ||
isBigIntObject(val) ||
isSymbolObject(val);
} The problem is that function checkBox(cls) {
return (val) => {
if (!constructorNamed(val, cls.name)) {
return false;
}
try {
cls.prototype.valueOf.call(val);
} catch {
return false;
}
return true;
};
}
const isNumberObject = checkBox(Number); The problem is that function constructorNamed(val, ...name) {
// Pass in names rather than types, in case SharedArrayBuffer (e.g.) isn't
// in your browser
for (const n of name) {
const typ = globalThis[n];
if (typ) {
if (val instanceof typ) {
return true;
}
}
}
// instanceOf doesn't work across vm boundaries, so check the whole
// inheritance chain
while (val) {
if (typeof val !== 'object') {
return false;
}
if (name.indexOf(getConstructorName(val)) >= 0) {
return true;
}
val = Object.getPrototypeOf(val);
}
return false;
} Checking with getConstructorName(val) {
if (!val || typeof val !== 'object') {
throw new Error('Invalid object');
}
if (val.constructor && val.constructor.name) {
return val.constructor.name;
}
const str = Object.prototype.toString.call(val);
// e.g. [object Boolean]
const m = str.match(/^\[object ([^\]]+)\]/);
if (m) {
return m[1];
}
return 'Object';
} And finally, the problem is that getConstructorName(val) {
if (!val || typeof val !== 'object') {
throw new Error('Invalid object');
}
const str = Object.prototype.toString.call(val);
// e.g. [object Boolean]
const m = str.match(/^\[object ([^\]]+)\]/);
if (m && m[1] !== 'Object') {
return m[1];
}
if (val.constructor && val.constructor.name) {
return val.constructor.name;
}
return 'Object';
} This will fix the problem of getting correct type for primitive values with changed prototype and I don't see how it could break functionality for any other values, but I have only checked it on few examples. |
Can you submit a patch for this, please? Make sure to add yourself to a "contributors" section in package.json as well. Thank you! |
Code like this:
expected:
[Foo: null prototype] {}
actual:
[Object: null prototype] {}
The text was updated successfully, but these errors were encountered: