ember-legacy-class-transform
Version:
The default blueprint for ember-cli addons.
239 lines • 6.73 kB
JavaScript
import { dict, EMPTY_ARRAY } from '@glimmer/util';
import { combineTagged } from '@glimmer/reference';
import { PrimitiveReference, UNDEFINED_REFERENCE } from '../references';
export class Arguments {
constructor() {
this.stack = null;
this.positional = new PositionalArguments();
this.named = new NamedArguments();
}
empty() {
this.setup(null, true);
return this;
}
setup(stack, synthetic) {
this.stack = stack;
let names = stack.fromTop(0);
let namedCount = names.length;
let positionalCount = stack.fromTop(namedCount + 1);
let start = positionalCount + namedCount + 2;
let positional = this.positional;
positional.setup(stack, start, positionalCount);
let named = this.named;
named.setup(stack, namedCount, names, synthetic);
}
get tag() {
return combineTagged([this.positional, this.named]);
}
get length() {
return this.positional.length + this.named.length;
}
at(pos) {
return this.positional.at(pos);
}
get(name) {
return this.named.get(name);
}
capture() {
return {
tag: this.tag,
length: this.length,
positional: this.positional.capture(),
named: this.named.capture()
};
}
clear() {
let { stack, length } = this;
stack.pop(length + 2);
}
}
class PositionalArguments {
constructor() {
this.length = 0;
this.stack = null;
this.start = 0;
this._tag = null;
this._references = null;
}
setup(stack, start, length) {
this.stack = stack;
this.start = start;
this.length = length;
this._tag = null;
this._references = null;
}
get tag() {
let tag = this._tag;
if (!tag) {
tag = this._tag = combineTagged(this.references);
}
return tag;
}
at(position) {
let { start, length } = this;
if (position < 0 || position >= length) {
return UNDEFINED_REFERENCE;
}
// stack: pos1, pos2, pos3, named1, named2
// start: 4 (top - 4)
//
// at(0) === pos1 === top - start
// at(1) === pos2 === top - (start - 1)
// at(2) === pos3 === top - (start - 2)
let fromTop = start - position - 1;
return this.stack.fromTop(fromTop);
}
capture() {
return new CapturedPositionalArguments(this.tag, this.references);
}
get references() {
let references = this._references;
if (!references) {
let { length } = this;
references = this._references = new Array(length);
for (let i = 0; i < length; i++) {
references[i] = this.at(i);
}
}
return references;
}
}
class CapturedPositionalArguments {
constructor(tag, references, length = references.length) {
this.tag = tag;
this.references = references;
this.length = length;
}
at(position) {
return this.references[position];
}
value() {
return this.references.map(this.valueOf);
}
get(name) {
let { references, length } = this;
if (name === 'length') {
return PrimitiveReference.create(length);
} else {
let idx = parseInt(name, 10);
if (idx < 0 || idx >= length) {
return UNDEFINED_REFERENCE;
} else {
return references[idx];
}
}
}
valueOf(reference) {
return reference.value();
}
}
class NamedArguments {
constructor() {
this.length = 0;
this._tag = null;
this._references = null;
this._names = null;
this._realNames = EMPTY_ARRAY;
}
setup(stack, length, names, synthetic) {
this.stack = stack;
this.length = length;
this._tag = null;
this._references = null;
if (synthetic) {
this._names = names;
this._realNames = EMPTY_ARRAY;
} else {
this._names = null;
this._realNames = names;
}
}
get tag() {
return combineTagged(this.references);
}
get names() {
let names = this._names;
if (!names) {
names = this._names = this._realNames.map(this.sliceName);
}
return names;
}
has(name) {
return this.names.indexOf(name) !== -1;
}
get(name) {
let { names, length } = this;
let idx = names.indexOf(name);
if (idx === -1) {
return UNDEFINED_REFERENCE;
}
// stack: pos1, pos2, pos3, named1, named2
// start: 4 (top - 4)
// namedDict: { named1: 1, named2: 0 };
//
// get('named1') === named1 === top - (start - 1)
// get('named2') === named2 === top - start
let fromTop = length - idx;
return this.stack.fromTop(fromTop);
}
capture() {
return new CapturedNamedArguments(this.tag, this.names, this.references);
}
get references() {
let references = this._references;
if (!references) {
let { names, length } = this;
references = this._references = [];
for (let i = 0; i < length; i++) {
references[i] = this.get(names[i]);
}
}
return references;
}
sliceName(name) {
return name.slice(1);
}
}
class CapturedNamedArguments {
constructor(tag, names, references) {
this.tag = tag;
this.names = names;
this.references = references;
this.length = names.length;
this._map = null;
}
get map() {
let map = this._map;
if (!map) {
let { names, references } = this;
map = this._map = dict();
for (let i = 0; i < names.length; i++) {
let name = names[i];
map[name] = references[i];
}
}
return map;
}
has(name) {
return this.names.indexOf(name) !== -1;
}
get(name) {
let { names, references } = this;
let idx = names.indexOf(name);
if (idx === -1) {
return UNDEFINED_REFERENCE;
} else {
return references[idx];
}
}
value() {
let { names, references } = this;
let out = dict();
for (let i = 0; i < names.length; i++) {
let name = names[i];
out[name] = references[i].value();
}
return out;
}
}
export default new Arguments();