Visitar URL original
fix(core): don't use plain objects as maps for jsaction data · angular/angular@d7d5401 · GitHub
Skip to content

Commit d7d5401

Browse files
arturovtthePunderWoman
authored andcommitted
fix(core): don't use plain objects as maps for jsaction data
The parsed jsaction action map, the parser cache keyed by the raw jsaction attribute value, and the fallback in getDefaulted were all plain {} objects. Looking up a key that was never explicitly set but happens to match an inherited Object.prototype member (toString, constructor, hasOwnProperty, ...) resolves to that inherited value instead of undefined, and callers only check `!== undefined` to decide whether there's a real action or cache entry. Use Object.create(null) instead, which has no prototype to accidentally collide with. (cherry picked from commit 8d8859c)
1 parent fc1a44a commit d7d5401

2 files changed

Lines changed: 7 additions & 4 deletions

File tree

‎packages/core/primitives/event-dispatch/src/action_resolver.ts‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@ import * as eventLib from './event';
1919
* Since maps from event to action are immutable we can use a single map
2020
* to represent the empty map.
2121
*/
22-
const EMPTY_ACTION_MAP: {[key: string]: string} = {};
22+
// tslint:disable-next-line:no-toplevel-property-access
23+
const EMPTY_ACTION_MAP: {[key: string]: string} = /* @__PURE__ */ Object.create(null);
2324

2425
/**
2526
* This regular expression matches a semicolon.
@@ -258,7 +259,7 @@ export class ActionResolver {
258259
} else {
259260
actionMap = cache.getParsed(jsactionAttribute);
260261
if (!actionMap) {
261-
actionMap = {};
262+
actionMap = Object.create(null) as {[key: string]: string | undefined};
262263
const values = jsactionAttribute.split(REGEXP_SEMICOLON);
263264
for (let idx = 0; idx < values.length; idx++) {
264265
const value = values[idx];

‎packages/core/primitives/event-dispatch/src/cache.ts‎

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,9 @@ import {Property} from './property';
1111
/**
1212
* Map from jsaction annotation to a parsed map from event name to action name.
1313
*/
14-
const parseCache: {[key: string]: {[key: string]: string | undefined}} = {};
14+
// tslint:disable-next-line:no-toplevel-property-access
15+
const parseCache: {[key: string]: {[key: string]: string | undefined}} =
16+
/* @__PURE__ */ Object.create(null);
1517

1618
/**
1719
* Reads the jsaction parser cache from the given DOM Element.
@@ -25,7 +27,7 @@ export function get(element: Element): {[key: string]: string | undefined} | und
2527
* creates an empty one.
2628
*/
2729
export function getDefaulted(element: Element): {[key: string]: string | undefined} {
28-
const cache = get(element) ?? {};
30+
const cache = get(element) ?? Object.create(null);
2931
set(element, cache);
3032
return cache;
3133
}

0 commit comments

Comments
 (0)