1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 |
|
10 |
|
11 |
|
12 |
|
13 |
|
14 |
|
15 |
|
16 |
|
17 | import { isPromise } from './util_base';
|
18 |
|
19 | const TENSORFLOWJS_FLAGS_PREFIX = 'tfjsflags';
|
20 |
|
21 |
|
22 |
|
23 |
|
24 |
|
25 |
|
26 |
|
27 | export class Environment {
|
28 |
|
29 | constructor(global) {
|
30 | this.global = global;
|
31 | this.flags = {};
|
32 | this.flagRegistry = {};
|
33 | this.urlFlags = {};
|
34 |
|
35 | this.getQueryParams = getQueryParams;
|
36 | this.populateURLFlags();
|
37 | }
|
38 | setPlatform(platformName, platform) {
|
39 | if (this.platform != null) {
|
40 | console.warn(`Platform ${this.platformName} has already been set. ` +
|
41 | `Overwriting the platform with ${platform}.`);
|
42 | }
|
43 | this.platformName = platformName;
|
44 | this.platform = platform;
|
45 | }
|
46 | registerFlag(flagName, evaluationFn, setHook) {
|
47 | this.flagRegistry[flagName] = { evaluationFn, setHook };
|
48 |
|
49 |
|
50 | if (this.urlFlags[flagName] != null) {
|
51 | const flagValue = this.urlFlags[flagName];
|
52 | console.warn(`Setting feature override from URL ${flagName}: ${flagValue}.`);
|
53 | this.set(flagName, flagValue);
|
54 | }
|
55 | }
|
56 | async getAsync(flagName) {
|
57 | if (flagName in this.flags) {
|
58 | return this.flags[flagName];
|
59 | }
|
60 | this.flags[flagName] = await this.evaluateFlag(flagName);
|
61 | return this.flags[flagName];
|
62 | }
|
63 | get(flagName) {
|
64 | if (flagName in this.flags) {
|
65 | return this.flags[flagName];
|
66 | }
|
67 | const flagValue = this.evaluateFlag(flagName);
|
68 | if (isPromise(flagValue)) {
|
69 | throw new Error(`Flag ${flagName} cannot be synchronously evaluated. ` +
|
70 | `Please use getAsync() instead.`);
|
71 | }
|
72 | this.flags[flagName] = flagValue;
|
73 | return this.flags[flagName];
|
74 | }
|
75 | getNumber(flagName) {
|
76 | return this.get(flagName);
|
77 | }
|
78 | getBool(flagName) {
|
79 | return this.get(flagName);
|
80 | }
|
81 | getFlags() {
|
82 | return this.flags;
|
83 | }
|
84 |
|
85 | get features() {
|
86 | return this.flags;
|
87 | }
|
88 | set(flagName, value) {
|
89 | if (this.flagRegistry[flagName] == null) {
|
90 | throw new Error(`Cannot set flag ${flagName} as it has not been registered.`);
|
91 | }
|
92 | this.flags[flagName] = value;
|
93 | if (this.flagRegistry[flagName].setHook != null) {
|
94 | this.flagRegistry[flagName].setHook(value);
|
95 | }
|
96 | }
|
97 | evaluateFlag(flagName) {
|
98 | if (this.flagRegistry[flagName] == null) {
|
99 | throw new Error(`Cannot evaluate flag '${flagName}': no evaluation function found.`);
|
100 | }
|
101 | return this.flagRegistry[flagName].evaluationFn();
|
102 | }
|
103 | setFlags(flags) {
|
104 | this.flags = Object.assign({}, flags);
|
105 | }
|
106 | reset() {
|
107 | this.flags = {};
|
108 | this.urlFlags = {};
|
109 | this.populateURLFlags();
|
110 | }
|
111 | populateURLFlags() {
|
112 | if (typeof this.global === 'undefined' ||
|
113 | typeof this.global.location === 'undefined' ||
|
114 | typeof this.global.location.search === 'undefined') {
|
115 | return;
|
116 | }
|
117 | const urlParams = this.getQueryParams(this.global.location.search);
|
118 | if (TENSORFLOWJS_FLAGS_PREFIX in urlParams) {
|
119 | const keyValues = urlParams[TENSORFLOWJS_FLAGS_PREFIX].split(',');
|
120 | keyValues.forEach(keyValue => {
|
121 | const [key, value] = keyValue.split(':');
|
122 | this.urlFlags[key] = parseValue(key, value);
|
123 | });
|
124 | }
|
125 | }
|
126 | }
|
127 | export function getQueryParams(queryString) {
|
128 | const params = {};
|
129 | queryString.replace(/[?&]([^=?&]+)(?:=([^&]*))?/g, (s, ...t) => {
|
130 | decodeParam(params, t[0], t[1]);
|
131 | return t.join('=');
|
132 | });
|
133 | return params;
|
134 | }
|
135 | function decodeParam(params, name, value) {
|
136 | params[decodeURIComponent(name)] = decodeURIComponent(value || '');
|
137 | }
|
138 | function parseValue(flagName, value) {
|
139 | value = value.toLowerCase();
|
140 | if (value === 'true' || value === 'false') {
|
141 | return value === 'true';
|
142 | }
|
143 | else if (`${+value}` === value) {
|
144 | return +value;
|
145 | }
|
146 | throw new Error(`Could not parse value flag value ${value} for flag ${flagName}.`);
|
147 | }
|
148 |
|
149 |
|
150 |
|
151 |
|
152 |
|
153 |
|
154 |
|
155 |
|
156 | export function env() {
|
157 | return ENV;
|
158 | }
|
159 | export let ENV = null;
|
160 | export function setEnvironmentGlobal(environment) {
|
161 | ENV = environment;
|
162 | }
|
163 |
|
\ | No newline at end of file |