Conversation
|
I've completed writing the tests, now I just need to actually get them to run properly and debug any issues (could be typos, etc). |
|
https://github.com/babel/babel-test262-runner/ could be useful to run the tests and check if they have any problem. |
|
Yes, I've been using that repo for testing in general. The previous commit for fields (a3b4282) was passing, at that point I kinda had all the details figured out for the overall structure so I scaffolded out all of the tests themselves and made sure I had written all of the ones we needed. Next is just running them again to see if they work and fixing issues. I'm sure there are minor issues, definitely, but could also be some larger ones. @nicolo-ribaudo one quick question, the generators in |
f72b125 to
aa99427
Compare
|
This PR is now ready for review. There are some tests that are failing against the Babel test runner that I can't figure out:
I believe that's it though. The tests should cover the bulk of decorator behavior, there may be some small gaps but we can address those in followups, this is already a massive PR and I don't want to continue adding to it. |
|
@pzuraq We discussed this in yesterday's test262 meeting. We plan to start reviewing it after tackling one other large PR that's been waiting longer. In the meantime, would you mind splitting the commit on this branch into two commits, one with any hand-written changes and one with autogenerated changes? We'll focus on the former. |
|
Ok, sounds good! I can get that done likely by the end of the month or early next month. |
aa99427 to
15f73b9
Compare
|
@pzuraq I went ahead and investigated which tests were autogenerated — it looks like they all are! 😄 A few of them don't have corresponding templates in
|
|
@ptomato ah those files were mistakenly added actually, they were work in progress files as I was working out the way the generator system worked. Removing them and rebasing now. |
15f73b9 to
afe395a
Compare
|
The diff is quite big, I didn't read all, but it will good to add this case to tests if missing. class A {
@decorators[0]
method() {}
} |
|
|
||
| var C = class { | ||
| @pushOrd(1, 3, 6) | ||
| @pushOrd(0, 4, 5) |
There was a problem hiding this comment.
According to https://arai-a.github.io/ecma262-compare/?pr=2417&id=sec-initializefieldoraccessor the extraInitializers run in the order they were added by https://arai-a.github.io/ecma262-compare/?pr=2417&id=sec-createaddinitializerfunction to the context. So according to the spec this should be 0,1,4,3,5,6.
At least unless I am missing something. The polyfill claims that it should 1,2,3,4,5,6.
There was a problem hiding this comment.
The ordering here is correct. There are 3 phases:
- Decorator application
- Field initialization
- Extra initializers
Phase two reverses the ordering of application from outermost -> innermost, because logically we are "setting" the field. The initial value is first created and then set, then the outer decorator gets the initial value and gets to mutate it, then the inner decorator gets the value, then it is set on the internal storage slot.
There is an issue on the decorators repo discussing this, and it was discussed at a Plenary because the change was made in stage 3 so needed consensus to merge.
There was a problem hiding this comment.
Right, application is inside out. So we first apply @pushOrd(0, 4, 5), then @pushOrd(1, 3, 6). According to https://arai-a.github.io/ecma262-compare/?pr=2417&id=sec-applydecoratorsanddefinemethod the extraInitializers are shared between all decorators of the same method. So the first one to run pushes a () => ord.push(4) and the second one () => ord.push(3) to the same extraInitializers list. And that is also the final order we are supposed to run them. So according to the spec I think this example should create 0,1,4,3,5,6.
There was a problem hiding this comment.
Sorry, I got confused. The 5,6 are the extra initializers.
So 3,4 are the normal initializers. And what you are saying is that they are supposed to run outside in. I guess that part I have not found in the spec yet.
There was a problem hiding this comment.
Ah, got it. 15.7.6 ApplyDecoratorsToElementDefinition [...] 8. If IsCallable(initializer) is true, prepend initializer to elementRecord.[[Initializers]].
There was a problem hiding this comment.
However considering that the [[Initializers]] field comes from ClassFieldDefinitionEvaluation which already adds the actual initializer to that list, wouldn't the prepending cause the original initializer to run last?
I.e., I think according to the current spec text we are supposed to see 0,1,3,4,2,5,6.
There was a problem hiding this comment.
This prepends the initialzer to the [[Initializers]] list:
l. If kind is field, then
i. If IsCallable(newValue) is true, prepend newValue to elementRecord.[[Initializers]].
Then we have initialization
- Assert: elementRecord.[[Kind]] is field or accessor.
- If elementRecord has a [[BackingStorageKey]] field, let fieldName be elementRecord.[[BackingStorageKey]].
- Else, let fieldName be elementRecord.[[Key]].
- Let initValue be undefined.
- For each element initializer of elementRecord.[[Initializers]], do
a. Set initValue to ? Call(initializer, receiver, « initValue »).- If fieldName is a Private Name, then
a. Perform ? PrivateFieldAdd(receiver, fieldName, initValue).- Else,
a. Assert: IsPropertyKey(fieldName) is true.
b. Perform ? CreateDataPropertyOrThrow(receiver, fieldName, initValue).- For each element initializer of elementRecord.[[ExtraInitializers]], do
a. Perform ? Call(initializer, receiver).- Return unused.
Note that [[Initializers]] is used before [[ExtraInitializers]], which holds actual initializers added by addInitializers to an element definition. Only Fields and Accessors have [[Initializers]].
There was a problem hiding this comment.
Agreed. But my new worry is that when we call prepend newValue to elementRecord.[[Initializers]], that list already contains the initializer CreateFieldInitializerFunction(this, #element, ord.push(2)) from ClassFieldDefinitionEvaluation. This means prepending the initializers from the decorators will move the actual initializer to the end of the [[Initializers]] list. Resulting in 0,1,3,4,2,5,6.
There was a problem hiding this comment.
hmm, yes ok, you are correct. The prepended decorators are in the correct order, but the original initializer does need to be the first item in the list. This was likely introduced when the order was reversed, when initializers we appended to the list this behavior would have made sense.
There was a problem hiding this comment.
Ok, I created an issue to track this tc39/proposal-decorators#569
|
|
||
| assert(C !== originalClass, 'values are not the same'); | ||
| assert(C instanceof originalClass, 'value is instance of class'); | ||
| assert.sameValue(new C(), 123); |
There was a problem hiding this comment.
Shouldn't this fail with a TypeError if the 'construct' trap returns a non-object?
There was a problem hiding this comment.
ah I see, sorry I was confused (still waking up).
Yes, this should error because construct needs to return an object, that's Proxy's behavior. Test should be updated to do that.
I don't have bandwidth to work on this at the moment but happy to take PRs to the branch or give access.
There was a problem hiding this comment.
I don't have time to work on the tests either. I just stumble upon these issues since I am evaluating the coherence of spec vs. proposed V8 patch vs. babel.
There was a problem hiding this comment.
(btw. the line 32 fails too because of the proxy)
There was a problem hiding this comment.
(it's still very helpful to get these comments, as we can probably find somebody else from the community to take over this PR)
| } | ||
| } | ||
|
|
||
| assert.throws(TypeError, evaluate); |
There was a problem hiding this comment.
Something is wrong here as we are not actually decorating a class as the description suggests.
This PR is still a WIP, I will be trying to wrap it up tomorrow. Took me a while to get best way to combine templates and cases to have as wide coverage as possible without having to write out every permutation manually.