Skip to content

Commit 18debdf

Browse files
authored
Merge pull request #14355 from ef4/refactor-curly-args
Refactoring curly component argument processing
2 parents 8e1374c + 8b691eb commit 18debdf

File tree

2 files changed

+83
-102
lines changed

2 files changed

+83
-102
lines changed

packages/ember-glimmer/lib/syntax/curly-component.js

Lines changed: 7 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,7 @@
1-
import { assign, OWNER } from 'ember-utils';
1+
import { OWNER } from 'ember-utils';
22
import {
33
StatementSyntax,
44
ValueReference,
5-
EvaluatedArgs,
6-
EvaluatedNamedArgs,
7-
EvaluatedPositionalArgs,
85
ComponentDefinition
96
} from 'glimmer-runtime';
107
import {
@@ -28,7 +25,10 @@ import {
2825
import {
2926
setViewElement
3027
} from 'ember-views';
31-
import processArgs from '../utils/process-args';
28+
import {
29+
gatherArgs,
30+
ComponentArgs
31+
} from '../utils/process-args';
3232
import { privatize as P } from 'container';
3333

3434
const DEFAULT_LAYOUT = P`template:components/-default`;
@@ -181,40 +181,14 @@ class CurlyComponentManager {
181181
prepareArgs(definition, args) {
182182
validatePositionalParameters(args.named, args.positional.values, definition.ComponentClass.positionalParams);
183183

184-
if (definition.args) {
185-
let newNamed = args.named.map;
186-
let newPositional = args.positional.values;
187-
188-
let oldNamed = definition.args.named.map;
189-
let oldPositional = definition.args.positional.values;
190-
191-
// Merge positional arrays
192-
let mergedPositional = [];
193-
194-
mergedPositional.push(...oldPositional);
195-
mergedPositional.splice(0, newPositional.length, ...newPositional);
196-
197-
// Merge named maps
198-
let mergedNamed = assign({}, oldNamed, newNamed);
199-
200-
// THOUGHT: It might be nice to have a static method on EvaluatedArgs that
201-
// can merge two sets of args for us.
202-
let mergedArgs = EvaluatedArgs.create(
203-
EvaluatedPositionalArgs.create(mergedPositional),
204-
EvaluatedNamedArgs.create(mergedNamed)
205-
);
206-
207-
return mergedArgs;
208-
}
209-
210-
return args;
184+
return gatherArgs(args, definition);
211185
}
212186

213187
create(environment, definition, args, dynamicScope, callerSelfRef, hasBlock) {
214188
let parentView = dynamicScope.view;
215189

216190
let klass = definition.ComponentClass;
217-
let processedArgs = processArgs(args, klass.positionalParams);
191+
let processedArgs = ComponentArgs.create(args);
218192
let { attrs, props } = processedArgs.value();
219193

220194
aliasIdToElementId(args, props);

packages/ember-glimmer/lib/utils/process-args.js

Lines changed: 76 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,81 @@
1-
import { symbol, EmptyObject } from 'ember-utils';
2-
import { CONSTANT_TAG } from 'glimmer-reference';
1+
import {
2+
assign,
3+
symbol,
4+
EmptyObject
5+
} from 'ember-utils';
6+
import {
7+
CONSTANT_TAG
8+
} from 'glimmer-reference';
39
import { ARGS } from '../component';
410
import { UPDATE } from './references';
511
import { MUTABLE_CELL } from 'ember-views';
612
import { ACTION } from '../helpers/action';
13+
import {
14+
EvaluatedArgs,
15+
EvaluatedPositionalArgs
16+
} from 'glimmer-runtime';
17+
18+
// Maps all variants of positional and dynamically scoped arguments
19+
// into the named arguments. Input `args` and return value are both
20+
// `EvaluatedArgs`.
21+
export function gatherArgs(args, definition) {
22+
let namedMap = gatherNamedMap(args, definition);
23+
let positionalValues = gatherPositionalValues(args, definition);
24+
return mergeArgs(namedMap, positionalValues, definition.ComponentClass);
25+
}
26+
27+
function gatherNamedMap(args, definition) {
28+
let namedMap = args.named.map;
29+
if (definition.args) {
30+
return assign({}, definition.args.named.map, namedMap);
31+
} else {
32+
return namedMap;
33+
}
34+
}
735

8-
export default function processArgs(args, positionalParamsDefinition) {
9-
if (!positionalParamsDefinition || positionalParamsDefinition.length === 0 || args.positional.length === 0) {
10-
return SimpleArgs.create(args);
11-
} else if (typeof positionalParamsDefinition === 'string') {
12-
return RestArgs.create(args, positionalParamsDefinition);
36+
function gatherPositionalValues(args, definition) {
37+
let positionalValues = args.positional.values;
38+
if (definition.args) {
39+
let oldPositional = definition.args.positional.values;
40+
let newPositional = [];
41+
newPositional.push(...oldPositional);
42+
newPositional.splice(0, positionalValues.length, ...positionalValues);
43+
return newPositional;
1344
} else {
14-
return PositionalArgs.create(args, positionalParamsDefinition);
45+
return positionalValues;
46+
}
47+
}
48+
49+
function mergeArgs(namedMap, positionalValues, componentClass) {
50+
let positionalParamsDefinition = componentClass.positionalParams;
51+
52+
if (positionalParamsDefinition && positionalParamsDefinition.length > 0 && positionalValues.length > 0) {
53+
if (typeof positionalParamsDefinition === 'string') {
54+
namedMap = mergeRestArg(namedMap, positionalValues, positionalParamsDefinition);
55+
} else {
56+
namedMap = mergePositionalParams(namedMap, positionalValues, positionalParamsDefinition);
57+
}
1558
}
59+
return EvaluatedArgs.named(namedMap);
1660
}
1761

1862
const EMPTY_ARGS = {
1963
tag: CONSTANT_TAG,
20-
2164
value() {
2265
return { attrs: {}, props: { attrs: {}, [ARGS]: {} } };
2366
}
2467
};
2568

26-
class SimpleArgs {
27-
static create({ named }) {
28-
if (named.keys.length === 0) {
69+
70+
// ComponentArgs takes EvaluatedNamedArgs and converts them into the
71+
// inputs needed by CurlyComponents (attrs and props, with mutable
72+
// cells, etc).
73+
export class ComponentArgs {
74+
static create(args) {
75+
if (args.named.keys.length === 0) {
2976
return EMPTY_ARGS;
3077
} else {
31-
return new SimpleArgs(named);
78+
return new ComponentArgs(args.named);
3279
}
3380
}
3481

@@ -67,6 +114,22 @@ class SimpleArgs {
67114
}
68115
}
69116

117+
function mergeRestArg(namedMap, positionalValues, restArgName) {
118+
let mergedNamed = assign({}, namedMap);
119+
mergedNamed[restArgName] = EvaluatedPositionalArgs.create(positionalValues);
120+
return mergedNamed;
121+
}
122+
123+
function mergePositionalParams(namedMap, values, positionalParamNames) {
124+
let mergedNamed = assign({}, namedMap);
125+
let length = Math.min(values.length, positionalParamNames.length);
126+
for (let i = 0; i < length; i++) {
127+
let name = positionalParamNames[i];
128+
mergedNamed[name] = values[i];
129+
}
130+
return mergedNamed;
131+
}
132+
70133
const REF = symbol('REF');
71134

72135
class MutableCell {
@@ -80,59 +143,3 @@ class MutableCell {
80143
this[REF][UPDATE](val);
81144
}
82145
}
83-
84-
class RestArgs {
85-
static create(args, restArgName) {
86-
return new RestArgs(args, restArgName);
87-
}
88-
89-
constructor(args, restArgName) {
90-
this.tag = args.tag;
91-
this.simpleArgs = SimpleArgs.create(args);
92-
this.positionalArgs = args.positional;
93-
this.restArgName = restArgName;
94-
}
95-
96-
value() {
97-
let { simpleArgs, positionalArgs, restArgName } = this;
98-
99-
let result = simpleArgs.value();
100-
101-
result.props[ARGS] = positionalArgs;
102-
result.attrs[restArgName] = result.props[restArgName] = positionalArgs.value();
103-
104-
return result;
105-
}
106-
}
107-
108-
109-
class PositionalArgs {
110-
static create(args, positionalParamNames) {
111-
if (args.positional.length < positionalParamNames.length) {
112-
positionalParamNames = positionalParamNames.slice(0, args.positional.length);
113-
}
114-
115-
return new PositionalArgs(args, positionalParamNames);
116-
}
117-
118-
constructor(args, positionalParamNames) {
119-
this.tag = args.tag;
120-
this.simpleArgs = SimpleArgs.create(args);
121-
this.positionalArgs = args.positional;
122-
this.positionalParamNames = positionalParamNames;
123-
}
124-
125-
value() {
126-
let { simpleArgs, positionalArgs, positionalParamNames } = this;
127-
128-
let result = simpleArgs.value();
129-
130-
for (let i = 0; i < positionalParamNames.length; i++) {
131-
let name = positionalParamNames[i];
132-
let reference = result.props[ARGS][name] = positionalArgs.at(i);
133-
result.attrs[name] = result.props[name] = reference.value();
134-
}
135-
136-
return result;
137-
}
138-
}

0 commit comments

Comments
 (0)