-
Notifications
You must be signed in to change notification settings - Fork 1.3k
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
Normative: specify for-in enumeration order in more cases #1791
Merged
+135
−1
Conversation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
bakkot
added
normative change
Affects behavior required to correctly evaluate some ECMAScript source text
pending stage 4
This proposal has not yet achieved stage 4, but may otherwise be ready to merge.
has test262 tests
proposal
This is related to a specific proposal, and will be closed/merged when the proposal reaches stage 4.
labels
Nov 23, 2019
ljharb
added
needs test262 tests
The proposal should specify how to test an implementation. Ideally via github.com/tc39/test262
and removed
has test262 tests
labels
Nov 23, 2019
("has tests" applies after the test262 tests are merged) |
ljharb
approved these changes
Nov 23, 2019
bakkot
commented
Nov 27, 2019
syg
approved these changes
Nov 28, 2019
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Editor review: lgtm with nits and wordsmithing.
Addressed comments; thanks for the feedback. |
ljharb
added
has stage 4
This PR represents a proposal that has achieved stage 4, and is ready to merge.
and removed
pending stage 4
This proposal has not yet achieved stage 4, but may otherwise be ready to merge.
labels
Dec 4, 2019
ljharb
added
has test262 tests
and removed
needs test262 tests
The proposal should specify how to test an implementation. Ideally via github.com/tc39/test262
labels
Dec 18, 2019
jmdyck
reviewed
Jan 2, 2020
spec.html
Outdated
<emu-note> | ||
<p>The following is an informative definition of an ECMAScript generator function that conforms to these rules:</p> | ||
<p>Hosts are not required to implement the algorithm in <emu-xref href="#sec-%foriniteratorprototype%.next"></emu-xref> directly. They may choose any implementation whose behavior will not deviate from that algorithm unless one of the constraints in the previous paragraph is violated.</p> | ||
<p>The following is an informative definition of an ECMAScript generator function that conforms to these rules:</ins></p> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Suggested change
<p>The following is an informative definition of an ECMAScript generator function that conforms to these rules:</ins></p> | |
<p>The following is an informative definition of an ECMAScript generator function that conforms to these rules:</p> |
ljharb
force-pushed
the
proposal-for-in-order
branch
from
January 2, 2020 23:51
f57c931
to
1bed13a
Compare
ljharb
added a commit
that referenced
this pull request
Jan 3, 2020
This correction was noted here: #1791 (comment) but omitted in the PR merge.
2 tasks
bertogg
pushed a commit
to Igalia/webkit
that referenced
this pull request
Dec 16, 2020
… from for-in https://bugs.webkit.org/show_bug.cgi?id=38970 Reviewed by Keith Miller. JSTests: * stress/arguments-bizarre-behaviour-disable-enumerability.js: * stress/for-in-redefine-enumerable.js: Added. * stress/for-in-shadow-non-enumerable.js: Added. * test262/expectations.yaml: Mark 4 test cases as passing. Source/JavaScriptCore: While for/in was initially specified with notion of "shadowing", it wasn't clarified until ES5 that [[Enumerable]] attributes are ignored when determining if a property has already been processed. Recently, for/in spec was expanded [1] to pin down common case enumeration as it's currently implemented by V8 and SpiderMonkey. Since keeping track of DontEnum properties is a massive slowdown for uncached runs (with any data structure used), this patch simply adds [[Enumerable]] check to has_{indexed,structure,generic}_property bytecode ops and does renaming chores. Common code is now shared between HasIndexedProperty (emitted for `0 in arr`) and HasEnumerableIndexedProperty DFG nodes via passing different slow path ops rather than having OpInfo with PropertySlot::InternalMethodType, which is a nice refactor. While this change aligns common case for/in enumeration with the spec and other engines, it also introduces a few observable discrepancies from V8 and SpiderMonkey, which are permitted by the spec [2]: a) properties that have been redefined as DontEnum within loop body are skipped, which matches the spec [3] and seems like expected behavior; b) "shadowing" is broken if a DontEnum property of already visited object is added / deleted / redefined within loop body, which (pretty much) never happens. This patch introduces a new invariant: all properties getOwn*PropertyNames() returns in DontEnumPropertiesMode::Exclude should be reported as [[Enumerable]] by getOwnPropertySlot(). JSCallbackObject and RuntimeArray are fixed to follow it. for/in and Object.keys microbenchmarks are neutral. This change does not affect JSPropertyNameEnumerator caching, nor fast paths of its bytecodes. [1]: tc39/ecma262#1791 [2]: https://tc39.es/ecma262/#sec-enumerate-object-properties (last paragraph) [3]: https://tc39.es/ecma262/#sec-%foriniteratorprototype%.next (step 7.b.iii) * API/JSCallbackObjectFunctions.h: (JSC::JSCallbackObject<Parent>::getOwnPropertySlot): * API/tests/testapi.c: * API/tests/testapiScripts/testapi.js: * bytecode/BytecodeList.rb: * bytecode/BytecodeUseDef.cpp: (JSC::computeUsesForBytecodeIndexImpl): (JSC::computeDefsForBytecodeIndexImpl): * bytecode/CodeBlock.cpp: (JSC::CodeBlock::finishCreation): * bytecode/Opcode.h: * bytecompiler/BytecodeGenerator.cpp: (JSC::BytecodeGenerator::emitHasEnumerableIndexedProperty): (JSC::BytecodeGenerator::emitHasEnumerableStructureProperty): (JSC::BytecodeGenerator::emitHasEnumerableProperty): (JSC::BytecodeGenerator::emitHasGenericProperty): Deleted. (JSC::BytecodeGenerator::emitHasIndexedProperty): Deleted. (JSC::BytecodeGenerator::emitHasStructureProperty): Deleted. * bytecompiler/BytecodeGenerator.h: * bytecompiler/NodesCodegen.cpp: (JSC::ForInNode::emitBytecode): * dfg/DFGAbstractInterpreterInlines.h: (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects): * dfg/DFGByteCodeParser.cpp: (JSC::DFG::ByteCodeParser::parseBlock): * dfg/DFGCapabilities.cpp: (JSC::DFG::capabilityLevel): * dfg/DFGClobberize.h: (JSC::DFG::clobberize): * dfg/DFGDoesGC.cpp: (JSC::DFG::doesGC): * dfg/DFGFixupPhase.cpp: (JSC::DFG::FixupPhase::fixupNode): (JSC::DFG::FixupPhase::convertToHasIndexedProperty): * dfg/DFGNode.h: (JSC::DFG::Node::hasArrayMode): (JSC::DFG::Node::hasInternalMethodType const): Deleted. (JSC::DFG::Node::internalMethodType const): Deleted. (JSC::DFG::Node::setInternalMethodType): Deleted. * dfg/DFGNodeType.h: * dfg/DFGOperations.cpp: (JSC::DFG::JSC_DEFINE_JIT_OPERATION): * dfg/DFGOperations.h: * dfg/DFGPredictionPropagationPhase.cpp: * dfg/DFGSSALoweringPhase.cpp: (JSC::DFG::SSALoweringPhase::handleNode): * dfg/DFGSafeToExecute.h: (JSC::DFG::safeToExecute): * dfg/DFGSpeculativeJIT.cpp: (JSC::DFG::SpeculativeJIT::compileHasEnumerableProperty): (JSC::DFG::SpeculativeJIT::compileHasEnumerableStructureProperty): (JSC::DFG::SpeculativeJIT::compileHasIndexedProperty): (JSC::DFG::SpeculativeJIT::compileHasGenericProperty): Deleted. (JSC::DFG::SpeculativeJIT::compileHasStructureProperty): Deleted. * dfg/DFGSpeculativeJIT.h: * dfg/DFGSpeculativeJIT32_64.cpp: (JSC::DFG::SpeculativeJIT::compile): * dfg/DFGSpeculativeJIT64.cpp: (JSC::DFG::SpeculativeJIT::compile): * ftl/FTLCapabilities.cpp: (JSC::FTL::canCompile): * ftl/FTLLowerDFGToB3.cpp: (JSC::FTL::DFG::LowerDFGToB3::compileNode): (JSC::FTL::DFG::LowerDFGToB3::compileHasIndexedProperty): (JSC::FTL::DFG::LowerDFGToB3::compileHasEnumerableProperty): (JSC::FTL::DFG::LowerDFGToB3::compileHasEnumerableStructureProperty): (JSC::FTL::DFG::LowerDFGToB3::compileHasGenericProperty): Deleted. (JSC::FTL::DFG::LowerDFGToB3::compileHasStructureProperty): Deleted. * jit/JIT.cpp: (JSC::JIT::privateCompileMainPass): (JSC::JIT::privateCompileSlowCases): * jit/JIT.h: * jit/JITOpcodes.cpp: (JSC::JIT::emit_op_has_enumerable_structure_property): (JSC::JIT::emit_op_has_enumerable_indexed_property): (JSC::JIT::emitSlow_op_has_enumerable_indexed_property): (JSC::JIT::emit_op_has_structure_property): Deleted. (JSC::JIT::emit_op_has_indexed_property): Deleted. (JSC::JIT::emitSlow_op_has_indexed_property): Deleted. * jit/JITOpcodes32_64.cpp: (JSC::JIT::emit_op_has_enumerable_structure_property): (JSC::JIT::emit_op_has_enumerable_indexed_property): (JSC::JIT::emitSlow_op_has_enumerable_indexed_property): (JSC::JIT::emit_op_has_structure_property): Deleted. (JSC::JIT::emit_op_has_indexed_property): Deleted. (JSC::JIT::emitSlow_op_has_indexed_property): Deleted. * jit/JITOperations.cpp: (JSC::JSC_DEFINE_JIT_OPERATION): * jit/JITOperations.h: * llint/LowLevelInterpreter.asm: * llint/LowLevelInterpreter64.asm: * runtime/CommonSlowPaths.cpp: (JSC::JSC_DEFINE_COMMON_SLOW_PATH): * runtime/CommonSlowPaths.h: * runtime/JSObject.cpp: (JSC::JSObject::hasProperty const): (JSC::JSObject::hasEnumerableProperty const): (JSC::JSObject::hasPropertyGeneric const): Deleted. * runtime/JSObject.h: Source/WebCore: Report RuntimeArray indices as [[Enumerable]]. Test: platform/mac/fast/dom/wrapper-classes-objc.html * bridge/runtime_array.cpp: (JSC::RuntimeArray::getOwnPropertySlot): (JSC::RuntimeArray::getOwnPropertySlotByIndex): LayoutTests: * platform/mac/fast/dom/wrapper-classes-objc-expected.txt: * platform/mac/fast/dom/wrapper-classes-objc.html: git-svn-id: http://svn.webkit.org/repository/webkit/trunk@270874 268f45cc-cd09-0410-ab3c-d52691b4dbfc
ryanhaddad
pushed a commit
to WebKit/WebKit
that referenced
this pull request
Dec 22, 2020
… from for-in https://bugs.webkit.org/show_bug.cgi?id=38970 Reviewed by Keith Miller. JSTests: * stress/arguments-bizarre-behaviour-disable-enumerability.js: * stress/for-in-redefine-enumerable.js: Added. * stress/for-in-shadow-non-enumerable.js: Added. * test262/expectations.yaml: Mark 4 test cases as passing. Source/JavaScriptCore: While for/in was initially specified with notion of "shadowing", it wasn't clarified until ES5 that [[Enumerable]] attributes are ignored when determining if a property has already been processed. Recently, for/in spec was expanded [1] to pin down common case enumeration as it's currently implemented by V8 and SpiderMonkey. Since keeping track of DontEnum properties is a massive slowdown for uncached runs (with any data structure used), this patch simply adds [[Enumerable]] check to has_{indexed,structure,generic}_property bytecode ops and does renaming chores. Common code is now shared between HasIndexedProperty (emitted for `0 in arr`) and HasEnumerableIndexedProperty DFG nodes via passing different slow path ops rather than having OpInfo with PropertySlot::InternalMethodType, which is a nice refactor. While this change aligns common case for/in enumeration with the spec and other engines, it also introduces a few observable discrepancies from V8 and SpiderMonkey, which are permitted by the spec [2]: a) properties that have been redefined as DontEnum within loop body are skipped, which matches the spec [3] and seems like expected behavior; b) "shadowing" is broken if a DontEnum property of already visited object is added / deleted / redefined within loop body, which (pretty much) never happens. This patch introduces a new invariant: all properties getOwn*PropertyNames() returns in DontEnumPropertiesMode::Exclude should be reported as [[Enumerable]] by getOwnPropertySlot(). JSCallbackObject and RuntimeArray are fixed to follow it. for/in and Object.keys microbenchmarks are neutral. This change does not affect JSPropertyNameEnumerator caching, nor fast paths of its bytecodes. [1]: tc39/ecma262#1791 [2]: https://tc39.es/ecma262/#sec-enumerate-object-properties (last paragraph) [3]: https://tc39.es/ecma262/#sec-%foriniteratorprototype%.next (step 7.b.iii) * API/JSCallbackObjectFunctions.h: (JSC::JSCallbackObject<Parent>::getOwnPropertySlot): * API/tests/testapi.c: * API/tests/testapiScripts/testapi.js: * bytecode/BytecodeList.rb: * bytecode/BytecodeUseDef.cpp: (JSC::computeUsesForBytecodeIndexImpl): (JSC::computeDefsForBytecodeIndexImpl): * bytecode/CodeBlock.cpp: (JSC::CodeBlock::finishCreation): * bytecode/Opcode.h: * bytecompiler/BytecodeGenerator.cpp: (JSC::BytecodeGenerator::emitHasEnumerableIndexedProperty): (JSC::BytecodeGenerator::emitHasEnumerableStructureProperty): (JSC::BytecodeGenerator::emitHasEnumerableProperty): (JSC::BytecodeGenerator::emitHasGenericProperty): Deleted. (JSC::BytecodeGenerator::emitHasIndexedProperty): Deleted. (JSC::BytecodeGenerator::emitHasStructureProperty): Deleted. * bytecompiler/BytecodeGenerator.h: * bytecompiler/NodesCodegen.cpp: (JSC::ForInNode::emitBytecode): * dfg/DFGAbstractInterpreterInlines.h: (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects): * dfg/DFGByteCodeParser.cpp: (JSC::DFG::ByteCodeParser::parseBlock): * dfg/DFGCapabilities.cpp: (JSC::DFG::capabilityLevel): * dfg/DFGClobberize.h: (JSC::DFG::clobberize): * dfg/DFGDoesGC.cpp: (JSC::DFG::doesGC): * dfg/DFGFixupPhase.cpp: (JSC::DFG::FixupPhase::fixupNode): (JSC::DFG::FixupPhase::convertToHasIndexedProperty): * dfg/DFGNode.h: (JSC::DFG::Node::hasArrayMode): (JSC::DFG::Node::hasInternalMethodType const): Deleted. (JSC::DFG::Node::internalMethodType const): Deleted. (JSC::DFG::Node::setInternalMethodType): Deleted. * dfg/DFGNodeType.h: * dfg/DFGOperations.cpp: (JSC::DFG::JSC_DEFINE_JIT_OPERATION): * dfg/DFGOperations.h: * dfg/DFGPredictionPropagationPhase.cpp: * dfg/DFGSSALoweringPhase.cpp: (JSC::DFG::SSALoweringPhase::handleNode): * dfg/DFGSafeToExecute.h: (JSC::DFG::safeToExecute): * dfg/DFGSpeculativeJIT.cpp: (JSC::DFG::SpeculativeJIT::compileHasEnumerableProperty): (JSC::DFG::SpeculativeJIT::compileHasEnumerableStructureProperty): (JSC::DFG::SpeculativeJIT::compileHasIndexedProperty): (JSC::DFG::SpeculativeJIT::compileHasGenericProperty): Deleted. (JSC::DFG::SpeculativeJIT::compileHasStructureProperty): Deleted. * dfg/DFGSpeculativeJIT.h: * dfg/DFGSpeculativeJIT32_64.cpp: (JSC::DFG::SpeculativeJIT::compile): * dfg/DFGSpeculativeJIT64.cpp: (JSC::DFG::SpeculativeJIT::compile): * ftl/FTLCapabilities.cpp: (JSC::FTL::canCompile): * ftl/FTLLowerDFGToB3.cpp: (JSC::FTL::DFG::LowerDFGToB3::compileNode): (JSC::FTL::DFG::LowerDFGToB3::compileHasIndexedProperty): (JSC::FTL::DFG::LowerDFGToB3::compileHasEnumerableProperty): (JSC::FTL::DFG::LowerDFGToB3::compileHasEnumerableStructureProperty): (JSC::FTL::DFG::LowerDFGToB3::compileHasGenericProperty): Deleted. (JSC::FTL::DFG::LowerDFGToB3::compileHasStructureProperty): Deleted. * jit/JIT.cpp: (JSC::JIT::privateCompileMainPass): (JSC::JIT::privateCompileSlowCases): * jit/JIT.h: * jit/JITOpcodes.cpp: (JSC::JIT::emit_op_has_enumerable_structure_property): (JSC::JIT::emit_op_has_enumerable_indexed_property): (JSC::JIT::emitSlow_op_has_enumerable_indexed_property): (JSC::JIT::emit_op_has_structure_property): Deleted. (JSC::JIT::emit_op_has_indexed_property): Deleted. (JSC::JIT::emitSlow_op_has_indexed_property): Deleted. * jit/JITOpcodes32_64.cpp: (JSC::JIT::emit_op_has_enumerable_structure_property): (JSC::JIT::emit_op_has_enumerable_indexed_property): (JSC::JIT::emitSlow_op_has_enumerable_indexed_property): (JSC::JIT::emit_op_has_structure_property): Deleted. (JSC::JIT::emit_op_has_indexed_property): Deleted. (JSC::JIT::emitSlow_op_has_indexed_property): Deleted. * jit/JITOperations.cpp: (JSC::JSC_DEFINE_JIT_OPERATION): * jit/JITOperations.h: * llint/LowLevelInterpreter.asm: * llint/LowLevelInterpreter64.asm: * runtime/CommonSlowPaths.cpp: (JSC::JSC_DEFINE_COMMON_SLOW_PATH): * runtime/CommonSlowPaths.h: * runtime/JSObject.cpp: (JSC::JSObject::hasProperty const): (JSC::JSObject::hasEnumerableProperty const): (JSC::JSObject::hasPropertyGeneric const): Deleted. * runtime/JSObject.h: Source/WebCore: Report RuntimeArray indices as [[Enumerable]]. Test: platform/mac/fast/dom/wrapper-classes-objc.html * bridge/runtime_array.cpp: (JSC::RuntimeArray::getOwnPropertySlot): (JSC::RuntimeArray::getOwnPropertySlotByIndex): LayoutTests: * platform/mac/fast/dom/wrapper-classes-objc-expected.txt: * platform/mac/fast/dom/wrapper-classes-objc.html: Canonical link: https://commits.webkit.org/232510@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@270874 268f45cc-cd09-0410-ab3c-d52691b4dbfc
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Labels
editorial change
has stage 4
This PR represents a proposal that has achieved stage 4, and is ready to merge.
has test262 tests
normative change
Affects behavior required to correctly evaluate some ECMAScript source text
proposal
This is related to a specific proposal, and will be closed/merged when the proposal reaches stage 4.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
This PR implements the for-in-order proposal, currently at stage 3.
I intend to request stage 4 at the December 2019 meeting.
Here is the PR adding tests to test262.