diff --git a/JSTests/stress/attribute-custom-accessor.js b/JSTests/stress/attribute-custom-accessor.js new file mode 100644 index 0000000000000..268025cff0943 --- /dev/null +++ b/JSTests/stress/attribute-custom-accessor.js @@ -0,0 +1,87 @@ +async function asyncSleep(ms) { + return new Promise(resolve => { + setTimeout(() => { + resolve(); + }, ms); + }); +} + +function reifyAllStaticProperties(object) { + Object.assign({}, object); +} + +function setHasBeenDictionary(object) { + for (let i = 0; i < 100; i++) { + object.b = 1; + delete object.b; + } + + for (const x in Object.create(object)) { + + } +} + +function watchToJSONForReplacements(object) { + JSON.stringify(Object.create(object)); +} + +async function watchLastMatchForReplacements(object) { + const tmp = Object.create(object); + function getLastMatch() { + return tmp.lastMatch; + } + + for (let i = 0; i < 2000; i++) { + try { + getLastMatch(); + } catch { + + } + } + + await asyncSleep(500); +} + +const target = { + toJSON: (() => { + const object = {}; + for (let i = 0; i < 10; i++) { + object['a' + i] = 1; + } + + object.lastMatch = 0x8888; + + return object; + })() +}; + +function opt() { + return target.toJSON.lastMatch; +} + +async function main() { + setHasBeenDictionary(target); + + reifyAllStaticProperties(RegExp); + await watchLastMatchForReplacements(RegExp); + + for (let i = 0; i < 2000; i++) { + opt(); + } + + await asyncSleep(200); + + target.toJSON = RegExp; + target.b = 1; + + watchToJSONForReplacements(target); + + await asyncSleep(1000); + + const custom_getter_setter = opt(); + describe(custom_getter_setter); + + custom_getter_setter.x = 1; +} + +main(); diff --git a/Source/JavaScriptCore/bytecode/PropertyCondition.cpp b/Source/JavaScriptCore/bytecode/PropertyCondition.cpp index 502e15db389e5..028a54299f323 100644 --- a/Source/JavaScriptCore/bytecode/PropertyCondition.cpp +++ b/Source/JavaScriptCore/bytecode/PropertyCondition.cpp @@ -498,9 +498,11 @@ bool PropertyCondition::isValidValueForAttributes(JSValue value, unsigned attrib { if (!value) return false; - bool attributesClaimAccessor = !!(attributes & PropertyAttribute::Accessor); - bool valueClaimsAccessor = !!jsDynamicCast(value); - return attributesClaimAccessor == valueClaimsAccessor; + if (value.inherits()) + return attributes & PropertyAttribute::Accessor; + if (value.inherits()) + return attributes & PropertyAttribute::CustomAccessorOrValue; + return !(attributes & PropertyAttribute::AccessorOrCustomAccessorOrValue); } bool PropertyCondition::isValidValueForPresence(JSValue value) const