Skip to content

Commit f75b9dd

Browse files
committed
Add class Scope
1 parent dd00b85 commit f75b9dd

File tree

3 files changed

+37
-34
lines changed

3 files changed

+37
-34
lines changed

fluent/src/bundle.js

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import {resolveComplexPattern} from "./resolver.js";
22
import FluentResource from "./resource.js";
33
import { FluentNone } from "./types.js";
4+
import Scope from "./scope.js";
45

56
/**
67
* Message bundles are single-language stores of translations. They are
@@ -222,7 +223,7 @@ export default class FluentBundle {
222223
}
223224

224225
// Resolve a complex pattern.
225-
let scope = this._createScope(args, errors);
226+
let scope = new Scope(this, errors, args);
226227
try {
227228
let value = resolveComplexPattern(scope, pattern);
228229
return value.toString(scope);
@@ -235,17 +236,6 @@ export default class FluentBundle {
235236
}
236237
}
237238

238-
_createScope(args, errors) {
239-
return {
240-
args,
241-
errors,
242-
bundle: this,
243-
dirty: new WeakSet(),
244-
// TermReferences are resolved in a new scope.
245-
insideTermReference: false,
246-
};
247-
}
248-
249239
_memoizeIntlObject(ctor, opts) {
250240
const cache = this._intls.get(ctor) || {};
251241
const id = JSON.stringify(opts);

fluent/src/resolver.js

Lines changed: 12 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -47,16 +47,6 @@ const FSI = "\u2068";
4747
const PDI = "\u2069";
4848

4949

50-
// Helper: Report an error.
51-
function report(scope, error) {
52-
if (scope.errors) {
53-
scope.errors.push(error);
54-
} else {
55-
throw error;
56-
}
57-
}
58-
59-
6050
// Helper: match a variant key to the given selector.
6151
function match(bundle, selector, key) {
6252
if (key === selector) {
@@ -89,7 +79,7 @@ function getDefault(scope, variants, star) {
8979
return resolvePattern(scope, variants[star].value);
9080
}
9181

92-
report(scope, new RangeError("No default"));
82+
scope.reportError(new RangeError("No default"));
9383
return new FluentNone();
9484
}
9585

@@ -137,7 +127,7 @@ function resolveExpression(scope, expr) {
137127
function VariableReference(scope, {name}) {
138128
if (!scope.args || !scope.args.hasOwnProperty(name)) {
139129
if (scope.insideTermReference === false) {
140-
report(scope, new ReferenceError(`Unknown variable: ${name}`));
130+
scope.reportError(new ReferenceError(`Unknown variable: ${name}`));
141131
}
142132
return new FluentNone(`$${name}`);
143133
}
@@ -160,7 +150,7 @@ function VariableReference(scope, {name}) {
160150
return new FluentDateTime(arg);
161151
}
162152
default:
163-
report(scope,
153+
scope.reportError(
164154
new TypeError(`Unsupported variable type: ${name}, ${typeof arg}`)
165155
);
166156
return new FluentNone(`$${name}`);
@@ -171,7 +161,7 @@ function VariableReference(scope, {name}) {
171161
function MessageReference(scope, {name, attr}) {
172162
const message = scope.bundle._messages.get(name);
173163
if (!message) {
174-
report(scope, new ReferenceError(`Unknown message: ${name}`));
164+
scope.reportError(new ReferenceError(`Unknown message: ${name}`));
175165
return new FluentNone(name);
176166
}
177167

@@ -180,15 +170,15 @@ function MessageReference(scope, {name, attr}) {
180170
if (attribute) {
181171
return resolvePattern(scope, attribute);
182172
}
183-
report(scope, new ReferenceError(`Unknown attribute: ${attr}`));
173+
scope.reportError(new ReferenceError(`Unknown attribute: ${attr}`));
184174
return new FluentNone(`${name}.${attr}`);
185175
}
186176

187177
if (message.value) {
188178
return resolvePattern(scope, message.value);
189179
}
190180

191-
report(scope, new ReferenceError(`No value: ${name}`));
181+
scope.reportError(new ReferenceError(`No value: ${name}`));
192182
return new FluentNone(name);
193183
}
194184

@@ -197,20 +187,20 @@ function TermReference(scope, {name, attr, args}) {
197187
const id = `-${name}`;
198188
const term = scope.bundle._terms.get(id);
199189
if (!term) {
200-
report(scope, new ReferenceError(`Unknown term: ${id}`));
190+
scope.reportError(new ReferenceError(`Unknown term: ${id}`));
201191
return new FluentNone(id);
202192
}
203193

204194
// Every TermReference has its own args.
205195
const [, keyargs] = getArguments(scope, args);
206-
const local = {...scope, args: keyargs, insideTermReference: true};
196+
const local = scope.clone(keyargs);
207197

208198
if (attr) {
209199
const attribute = term.attributes[attr];
210200
if (attribute) {
211201
return resolvePattern(local, attribute);
212202
}
213-
report(scope, new ReferenceError(`Unknown attribute: ${attr}`));
203+
scope.reportError(new ReferenceError(`Unknown attribute: ${attr}`));
214204
return new FluentNone(`${id}.${attr}`);
215205
}
216206

@@ -223,12 +213,12 @@ function FunctionReference(scope, {name, args}) {
223213
// the `FluentBundle` constructor.
224214
const func = scope.bundle._functions[name] || builtins[name];
225215
if (!func) {
226-
report(scope, new ReferenceError(`Unknown function: ${name}()`));
216+
scope.reportError(new ReferenceError(`Unknown function: ${name}()`));
227217
return new FluentNone(`${name}()`);
228218
}
229219

230220
if (typeof func !== "function") {
231-
report(scope, new TypeError(`Function ${name}() is not callable`));
221+
scope.reportError(new TypeError(`Function ${name}() is not callable`));
232222
return new FluentNone(`${name}()`);
233223
}
234224

@@ -261,7 +251,7 @@ function SelectExpression(scope, {selector, variants, star}) {
261251
// Resolve a pattern (a complex string with placeables).
262252
export function resolveComplexPattern(scope, ptn) {
263253
if (scope.dirty.has(ptn)) {
264-
report(scope, new RangeError("Cyclic reference"));
254+
scope.reportError(new RangeError("Cyclic reference"));
265255
return new FluentNone();
266256
}
267257

fluent/src/scope.js

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
export default class Scope {
2+
constructor(bundle, errors, args,
3+
insideTermReference = false, dirty = new WeakSet()
4+
) {
5+
this.bundle = bundle;
6+
this.errors = errors;
7+
this.args = args;
8+
this.dirty = dirty;
9+
// TermReferences are resolved in a new scope.
10+
this.insideTermReference = insideTermReference;
11+
}
12+
13+
clone(args) {
14+
return new Scope(this.bundle, this.errors, args, true, this.dirty);
15+
}
16+
17+
reportError(error) {
18+
if (!this.errors) {
19+
throw error;
20+
}
21+
this.errors.push(error);
22+
}
23+
}

0 commit comments

Comments
 (0)