Skip to content

Commit ddcb1c5

Browse files
authored
Use Object.prototype.hasOwnProperty.call (#441)
1 parent 70d6520 commit ddcb1c5

File tree

2 files changed

+245
-3
lines changed

2 files changed

+245
-3
lines changed

fluent-bundle/src/resolver.js

+6-3
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ function getDefault(scope, variants, star) {
7878
// Helper: resolve arguments to a call expression.
7979
function getArguments(scope, args) {
8080
const positional = [];
81-
const named = {};
81+
const named = Object.create(null);
8282

8383
for (const arg of args) {
8484
if (arg.type === "narg") {
@@ -120,12 +120,15 @@ function VariableReference(scope, {name}) {
120120
let arg;
121121
if (scope.params) {
122122
// We're inside a TermReference. It's OK to reference undefined parameters.
123-
if (scope.params.hasOwnProperty(name)) {
123+
if (Object.prototype.hasOwnProperty.call(scope.params, name)) {
124124
arg = scope.params[name];
125125
} else {
126126
return new FluentNone(`$${name}`);
127127
}
128-
} else if (scope.args && scope.args.hasOwnProperty(name)) {
128+
} else if (
129+
scope.args
130+
&& Object.prototype.hasOwnProperty.call(scope.args, name)
131+
) {
129132
// We're in the top-level Pattern or inside a MessageReference. Missing
130133
// variables references produce ReferenceErrors.
131134
arg = scope.args[name];
+239
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,239 @@
1+
'use strict';
2+
3+
import assert from 'assert';
4+
import ftl from "@fluent/dedent";
5+
6+
import FluentBundle from '../src/bundle';
7+
import FluentResource from '../src/resource';
8+
9+
suite('Interesting Object properties', function() {
10+
let bundle, errs;
11+
12+
setup(function() {
13+
errs = [];
14+
});
15+
16+
suite('Object.prototype.constructor', function(){
17+
suiteSetup(function() {
18+
bundle = new FluentBundle('en-US', { useIsolating: false });
19+
bundle.addResource(new FluentResource(ftl`
20+
test = {$constructor}
21+
`));
22+
});
23+
24+
test('empty args literal', function() {
25+
const msg = bundle.getMessage('test');
26+
const val = bundle.formatPattern(msg.value, {}, errs);
27+
assert.strictEqual(val, '{$constructor}');
28+
assert.strictEqual(errs.length, 1);
29+
assert(errs[0] instanceof ReferenceError); // unknown variable
30+
});
31+
32+
test('empty args with null prototype', function() {
33+
const msg = bundle.getMessage('test');
34+
const val = bundle.formatPattern(msg.value, Object.create(null), errs);
35+
assert.strictEqual(val, '{$constructor}');
36+
assert.strictEqual(errs.length, 1);
37+
assert(errs[0] instanceof ReferenceError); // unknown variable
38+
});
39+
40+
test('own property', function() {
41+
const msg = bundle.getMessage('test');
42+
const val = bundle.formatPattern(msg.value, {constructor: 1}, errs);
43+
assert.strictEqual(val, '1');
44+
assert.strictEqual(errs.length, 0);
45+
});
46+
});
47+
48+
suite('Object.prototype.hasOwnProperty', function(){
49+
suiteSetup(function() {
50+
bundle = new FluentBundle('en-US', { useIsolating: false });
51+
bundle.addResource(new FluentResource(ftl`
52+
test = {$hasOwnProperty}
53+
`));
54+
});
55+
56+
test('empty args literal', function() {
57+
const msg = bundle.getMessage('test');
58+
const val = bundle.formatPattern(msg.value, {}, errs);
59+
assert.strictEqual(val, '{$hasOwnProperty}');
60+
assert.strictEqual(errs.length, 1);
61+
assert(errs[0] instanceof ReferenceError); // unknown variable
62+
});
63+
64+
test('empty args with null prototype', function() {
65+
const msg = bundle.getMessage('test');
66+
const val = bundle.formatPattern(msg.value, Object.create(null), errs);
67+
assert.strictEqual(val, '{$hasOwnProperty}');
68+
assert.strictEqual(errs.length, 1);
69+
assert(errs[0] instanceof ReferenceError); // unknown variable
70+
});
71+
72+
test('own property', function() {
73+
const msg = bundle.getMessage('test');
74+
const val = bundle.formatPattern(msg.value, {hasOwnProperty: 1}, errs);
75+
assert.strictEqual(val, '1');
76+
assert.strictEqual(errs.length, 0);
77+
});
78+
});
79+
80+
suite('Object.prototype.isPrototypeOf', function(){
81+
suiteSetup(function() {
82+
bundle = new FluentBundle('en-US', { useIsolating: false });
83+
bundle.addResource(new FluentResource(ftl`
84+
test = {$isPrototypeOf}
85+
`));
86+
});
87+
88+
test('empty args literal', function() {
89+
const msg = bundle.getMessage('test');
90+
const val = bundle.formatPattern(msg.value, {}, errs);
91+
assert.strictEqual(val, '{$isPrototypeOf}');
92+
assert.strictEqual(errs.length, 1);
93+
assert(errs[0] instanceof ReferenceError); // unknown variable
94+
});
95+
96+
test('empty args with null prototype', function() {
97+
const msg = bundle.getMessage('test');
98+
const val = bundle.formatPattern(msg.value, Object.create(null), errs);
99+
assert.strictEqual(val, '{$isPrototypeOf}');
100+
assert.strictEqual(errs.length, 1);
101+
assert(errs[0] instanceof ReferenceError); // unknown variable
102+
});
103+
104+
test('own property', function() {
105+
const msg = bundle.getMessage('test');
106+
const val = bundle.formatPattern(msg.value, {isPrototypeOf: 1}, errs);
107+
assert.strictEqual(val, '1');
108+
assert.strictEqual(errs.length, 0);
109+
});
110+
});
111+
112+
suite('Object.prototype.propertyIsEnumerable', function(){
113+
suiteSetup(function() {
114+
bundle = new FluentBundle('en-US', { useIsolating: false });
115+
bundle.addResource(new FluentResource(ftl`
116+
test = {$propertyIsEnumerable}
117+
`));
118+
});
119+
120+
test('empty args literal', function() {
121+
const msg = bundle.getMessage('test');
122+
const val = bundle.formatPattern(msg.value, {}, errs);
123+
assert.strictEqual(val, '{$propertyIsEnumerable}');
124+
assert.strictEqual(errs.length, 1);
125+
assert(errs[0] instanceof ReferenceError); // unknown variable
126+
});
127+
128+
test('empty args with null prototype', function() {
129+
const msg = bundle.getMessage('test');
130+
const val = bundle.formatPattern(msg.value, Object.create(null), errs);
131+
assert.strictEqual(val, '{$propertyIsEnumerable}');
132+
assert.strictEqual(errs.length, 1);
133+
assert(errs[0] instanceof ReferenceError); // unknown variable
134+
});
135+
136+
test('own property', function() {
137+
const msg = bundle.getMessage('test');
138+
const val = bundle.formatPattern(msg.value, {propertyIsEnumerable: 1}, errs);
139+
assert.strictEqual(val, '1');
140+
assert.strictEqual(errs.length, 0);
141+
});
142+
});
143+
144+
suite('Object.prototype.toLocaleString', function(){
145+
suiteSetup(function() {
146+
bundle = new FluentBundle('en-US', { useIsolating: false });
147+
bundle.addResource(new FluentResource(ftl`
148+
test = {$toLocaleString}
149+
`));
150+
});
151+
152+
test('empty args literal', function() {
153+
const msg = bundle.getMessage('test');
154+
const val = bundle.formatPattern(msg.value, {}, errs);
155+
assert.strictEqual(val, '{$toLocaleString}');
156+
assert.strictEqual(errs.length, 1);
157+
assert(errs[0] instanceof ReferenceError); // unknown variable
158+
});
159+
160+
test('empty args with null prototype', function() {
161+
const msg = bundle.getMessage('test');
162+
const val = bundle.formatPattern(msg.value, Object.create(null), errs);
163+
assert.strictEqual(val, '{$toLocaleString}');
164+
assert.strictEqual(errs.length, 1);
165+
assert(errs[0] instanceof ReferenceError); // unknown variable
166+
});
167+
168+
test('own property', function() {
169+
const msg = bundle.getMessage('test');
170+
const val = bundle.formatPattern(msg.value, {toLocaleString: 1}, errs);
171+
assert.strictEqual(val, '1');
172+
assert.strictEqual(errs.length, 0);
173+
});
174+
});
175+
176+
suite('Object.prototype.toString', function(){
177+
suiteSetup(function() {
178+
bundle = new FluentBundle('en-US', { useIsolating: false });
179+
bundle.addResource(new FluentResource(ftl`
180+
test = {$toString}
181+
`));
182+
});
183+
184+
test('empty args literal', function() {
185+
const msg = bundle.getMessage('test');
186+
const val = bundle.formatPattern(msg.value, {}, errs);
187+
assert.strictEqual(val, '{$toString}');
188+
assert.strictEqual(errs.length, 1);
189+
assert(errs[0] instanceof ReferenceError); // unknown variable
190+
});
191+
192+
test('empty args with null prototype', function() {
193+
const msg = bundle.getMessage('test');
194+
const val = bundle.formatPattern(msg.value, Object.create(null), errs);
195+
assert.strictEqual(val, '{$toString}');
196+
assert.strictEqual(errs.length, 1);
197+
assert(errs[0] instanceof ReferenceError); // unknown variable
198+
});
199+
200+
test('own property', function() {
201+
const msg = bundle.getMessage('test');
202+
const val = bundle.formatPattern(msg.value, {toString: 1}, errs);
203+
assert.strictEqual(val, '1');
204+
assert.strictEqual(errs.length, 0);
205+
});
206+
});
207+
208+
suite('Object.prototype.valueOf', function(){
209+
suiteSetup(function() {
210+
bundle = new FluentBundle('en-US', { useIsolating: false });
211+
bundle.addResource(new FluentResource(ftl`
212+
test = {$valueOf}
213+
`));
214+
});
215+
216+
test('empty args literal', function() {
217+
const msg = bundle.getMessage('test');
218+
const val = bundle.formatPattern(msg.value, {}, errs);
219+
assert.strictEqual(val, '{$valueOf}');
220+
assert.strictEqual(errs.length, 1);
221+
assert(errs[0] instanceof ReferenceError); // unknown variable
222+
});
223+
224+
test('empty args with null property', function() {
225+
const msg = bundle.getMessage('test');
226+
const val = bundle.formatPattern(msg.value, Object.create(null), errs);
227+
assert.strictEqual(val, '{$valueOf}');
228+
assert.strictEqual(errs.length, 1);
229+
assert(errs[0] instanceof ReferenceError); // unknown variable
230+
});
231+
232+
test('own property', function() {
233+
const msg = bundle.getMessage('test');
234+
const val = bundle.formatPattern(msg.value, {valueOf: 1}, errs);
235+
assert.strictEqual(val, '1');
236+
assert.strictEqual(errs.length, 0);
237+
});
238+
});
239+
});

0 commit comments

Comments
 (0)