Skip to content

Commit 2bf57d1

Browse files
committed
tracked tests passing
1 parent 029cc2e commit 2bf57d1

File tree

6 files changed

+91
-21
lines changed

6 files changed

+91
-21
lines changed

babel.config.mjs

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,17 @@ export default {
1717
allowDeclareFields: true,
1818
},
1919
],
20-
['@babel/plugin-proposal-decorators', { version: '2023-11' }],
21-
// [
22-
// 'module:decorator-transforms',
23-
// {
24-
// runEarly: true,
25-
// runtime: { import: 'decorator-transforms/runtime' },
26-
// },
27-
// ],
20+
...(process.env.VITE_STABLE_DECORATORS
21+
? [['@babel/plugin-proposal-decorators', { version: '2023-11' }]]
22+
: [
23+
[
24+
'module:decorator-transforms',
25+
{
26+
runEarly: true,
27+
runtime: { import: 'decorator-transforms/runtime' },
28+
},
29+
],
30+
]),
2831
[
2932
'babel-plugin-ember-template-compilation',
3033
{

packages/@ember/-internals/metal/lib/computed.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ import {
4040
notifyPropertyChange,
4141
PROPERTY_DID_CHANGE,
4242
} from './property_events';
43+
import { isModernDecoratorArgs } from './decorator-util';
4344

4445
export type ComputedPropertyGetterFunction = (this: any, key: string) => unknown;
4546
export type ComputedPropertySetterFunction = (
@@ -884,6 +885,11 @@ export function computed(callback: ComputedPropertyCallback): ComputedDecorator;
884885
export function computed(
885886
...args: ElementDescriptor | string[] | ComputedDecoratorKeysAndConfig
886887
): ComputedDecorator | DecoratorPropertyDescriptor | void {
888+
if (isModernDecoratorArgs(args)) {
889+
console.log(`ignoring computed on ${args[1].kind} ${args[1].name?.toString()}`);
890+
return;
891+
}
892+
887893
assert(
888894
`@computed can only be used directly as a native decorator. If you're using tracked in classic classes, add parenthesis to call it like a function: computed()`,
889895
!(isElementDescriptor(args.slice(0, 3)) && args.length === 5 && (args[4] as unknown) === true)

packages/@ember/-internals/metal/lib/decorator.ts

Lines changed: 32 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,11 @@ import type { Meta } from '@ember/-internals/meta';
22
import { meta as metaFor, peekMeta } from '@ember/-internals/meta';
33
import { assert } from '@ember/debug';
44
import { DEBUG } from '@glimmer/env';
5+
import {
6+
type Decorator,
7+
identifyModernDecoratorArgs,
8+
isModernDecoratorArgs,
9+
} from './decorator-util';
510

611
export type DecoratorPropertyDescriptor = (PropertyDescriptor & { initializer?: any }) | undefined;
712

@@ -113,13 +118,23 @@ export function makeComputedDecorator(
113118
desc: ComputedDescriptor,
114119
DecoratorClass: { prototype: object }
115120
): ExtendedMethodDecorator {
116-
let decorator = function COMPUTED_DECORATOR(
117-
target: object,
118-
key: string,
119-
propertyDesc?: DecoratorPropertyDescriptor,
120-
maybeMeta?: Meta,
121-
isClassicDecorator?: boolean
122-
): DecoratorPropertyDescriptor {
121+
let decorator = function COMPUTED_DECORATOR(...args: unknown[]): DecoratorPropertyDescriptor {
122+
if (isModernDecoratorArgs(args)) {
123+
return computedDecorator2023(
124+
args,
125+
desc,
126+
DecoratorClass
127+
) as unknown as DecoratorPropertyDescriptor;
128+
}
129+
130+
let [target, key, propertyDesc, maybeMeta, isClassicDecorator] = args as [
131+
object,
132+
string,
133+
DecoratorPropertyDescriptor | undefined,
134+
Meta | undefined,
135+
boolean | undefined
136+
];
137+
123138
assert(
124139
`Only one computed property decorator can be applied to a class field or accessor, but '${key}' was decorated twice. You may have added the decorator to both a getter and setter, which is unnecessary.`,
125140
isClassicDecorator ||
@@ -148,6 +163,16 @@ export function makeComputedDecorator(
148163
return decorator;
149164
}
150165

166+
function computedDecorator2023(
167+
args: Paramters<Decorator>,
168+
desc: ComputedDescriptor,
169+
DecoratorClass: { prototype: object }
170+
) {
171+
let dec = identifyModernDecoratorArgs(args);
172+
console.log(`ignoring modern decorator on ${dec.kind} ${dec.context.name?.toString()}`);
173+
return;
174+
}
175+
151176
/////////////
152177

153178
const DECORATOR_DESCRIPTOR_MAP: WeakMap<ExtendedMethodDecorator, ComputedDescriptor | true> =

packages/@ember/-internals/metal/lib/tracked.ts

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import { CHAIN_PASS_THROUGH } from './chain-tags';
88
import type { ExtendedMethodDecorator, DecoratorPropertyDescriptor } from './decorator';
99
import { COMPUTED_SETTERS, isElementDescriptor, setClassicDecorator } from './decorator';
1010
import { SELF_TAG } from './tags';
11+
import { Decorator, identifyModernDecoratorArgs, isModernDecoratorArgs } from './decorator-util';
1112

1213
/**
1314
@decorator
@@ -82,6 +83,11 @@ export function tracked(
8283
desc: DecoratorPropertyDescriptor
8384
): DecoratorPropertyDescriptor;
8485
export function tracked(...args: any[]): ExtendedMethodDecorator | DecoratorPropertyDescriptor {
86+
if (isModernDecoratorArgs(args)) {
87+
// TODO: cast is a lie, keeping the public types unchanged for now
88+
return tracked2023(args) as unknown as DecoratorPropertyDescriptor;
89+
}
90+
8591
assert(
8692
`@tracked can only be used directly as a native decorator. If you're using tracked in classic classes, add parenthesis to call it like a function: tracked()`,
8793
!(isElementDescriptor(args.slice(0, 3)) && args.length === 5 && args[4] === true)
@@ -200,3 +206,25 @@ export class TrackedDescriptor {
200206
this._set.call(obj, value);
201207
}
202208
}
209+
210+
function tracked2023(args: Parameters<Decorator>) {
211+
const dec = identifyModernDecoratorArgs(args);
212+
switch (dec.kind) {
213+
case 'field':
214+
dec.context.addInitializer(function (this: any) {
215+
let initial = this[dec.context.name];
216+
Object.defineProperty(
217+
this,
218+
dec.context.name,
219+
descriptorForField([
220+
this,
221+
dec.context.name as string,
222+
{ initializer: () => initial },
223+
]) as any
224+
);
225+
});
226+
return;
227+
default:
228+
throw new Error(`unimplemented: tracked on ${dec.kind} ${dec.context.name?.toString()}`);
229+
}
230+
}

packages/@ember/-internals/metal/tests/tracked/validation_test.js

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,11 @@ moduleFor(
5454
let tag = track(() => obj.first);
5555
let snapshot = valueForTag(tag);
5656

57-
assert.equal(obj.first, 'first: second', 'The value initializes correctly');
57+
let expectedInitialValue = import.meta.env.VITE_STABLE_DECORATORS
58+
? 'first: undefined'
59+
: 'first: second';
60+
61+
assert.equal(obj.first, expectedInitialValue, 'The value initializes correctly');
5862
assert.equal(validateTag(tag, snapshot), true);
5963

6064
snapshot = valueForTag(tag);
@@ -65,7 +69,7 @@ moduleFor(
6569
// See: https://github.com/glimmerjs/glimmer-vm/pull/1018
6670
// assert.equal(validate(tag, snapshot), true);
6771

68-
assert.equal(obj.first, 'first: second', 'The value stays the same once initialized');
72+
assert.equal(obj.first, expectedInitialValue, 'The value stays the same once initialized');
6973
snapshot = valueForTag(tag);
7074

7175
assert.equal(validateTag(tag, snapshot), true);

rollup.config.mjs

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -247,10 +247,14 @@ export function hiddenDependencies() {
247247
'module'
248248
).path,
249249
...walkGlimmerDeps(['@glimmer/compiler']),
250-
// 'decorator-transforms/runtime': resolve(
251-
// findFromProject('decorator-transforms').root,
252-
// 'dist/runtime.js'
253-
// ),
250+
...(process.env.VITE_STABLE_DECORATORS
251+
? {}
252+
: {
253+
'decorator-transforms/runtime': resolve(
254+
findFromProject('decorator-transforms').root,
255+
'dist/runtime.js'
256+
),
257+
}),
254258
};
255259
}
256260

0 commit comments

Comments
 (0)