Skip to content

Commit

Permalink
fix(ast): correctly resolves access keyed on primitve (#1662)
Browse files Browse the repository at this point in the history
closes #1617
  • Loading branch information
bigopon committed Jan 30, 2023
1 parent 5f3a88d commit 0eae2ce
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 3 deletions.
33 changes: 33 additions & 0 deletions packages/__tests__/2-runtime/ast.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -480,6 +480,39 @@ describe('AccessKeyedExpression', function () {
assert.strictEqual(binding.calls.length, 2, 'binding.calls.length');
});

describe('returns the right value when accessing keyed on primitive', function () {

it('returns string when accessing string character', function () {
const value = astEvaluate(
new AccessKeyedExpression(new PrimitiveLiteralExpression('a'), new PrimitiveLiteralExpression(0)),
null,
null,
null
);
assert.strictEqual(value, 'a');
});

it('returns undefined when accessing keyed on null/undefined', function () {
const value = astEvaluate(
new AccessKeyedExpression(PrimitiveLiteralExpression.$null, new PrimitiveLiteralExpression(0)),
null,
null,
null
);
assert.strictEqual(value, undefined);
});

it('returns prototype method when accessing keyed on primitive', function () {
const value = astEvaluate(
new AccessKeyedExpression(new PrimitiveLiteralExpression(0), new PrimitiveLiteralExpression('toFixed')),
null,
null,
null
);
assert.strictEqual(value, Number.prototype.toFixed);
});
});

describe('does not attempt to observe property when object is primitive', function () {
const objects: [string, any][] = [
[` null`, null],
Expand Down
2 changes: 1 addition & 1 deletion packages/runtime-html/src/observation/observation-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ const removeListener = (target: EventTarget, name: string, handler: EventListene
/** @internal */
export const mixinNodeObserverUseConfig =
<T extends INodeObserver & EventListenerObject & ISubscriberCollection & { _el: INode; _config: INodeObserverConfigBase; _listened: boolean; _start(): void; _stop?(): void }>(target: Constructable<T>) => {
let event: string;
const prototype = target.prototype;
defineHiddenProp(prototype, 'subscribe', function (this: T, subscriber: ISubscriber) {
if (this.subs.add(subscriber) && this.subs.count === 1) {
Expand Down Expand Up @@ -46,7 +47,6 @@ export const mixinNodeObserverUseConfig =
}
});
};
let event: string;

export const mixinNoopSubscribable = (target: Constructable) => {
defineHiddenProp(target.prototype, 'subscribe', noop);
Expand Down
6 changes: 4 additions & 2 deletions packages/runtime/src/binding/ast.eval.ts
Original file line number Diff line number Diff line change
Expand Up @@ -171,14 +171,16 @@ export function astEvaluate(ast: IsExpressionOrStatement, s: Scope, e: IAstEvalu
}
case ExpressionKind.AccessKeyed: {
const instance = astEvaluate(ast.object, s, e, c) as IIndexable;
const key = astEvaluate(ast.key, s, e, c) as string;
if (isObject(instance)) {
const key = astEvaluate(ast.key, s, e, c) as string;
if (c !== null) {
c.observe(instance, key);
}
return instance[key];
}
return void 0;
return instance == null
? void 0
: instance[key];
}
case ExpressionKind.TaggedTemplate: {
const results = ast.expressions.map(expr => astEvaluate(expr, s, e, c));
Expand Down

0 comments on commit 0eae2ce

Please sign in to comment.