# lib/goog/string/const.js

1 | // Copyright 2013 The Closure Library Authors. All Rights Reserved.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS-IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | goog.provide('goog.string.Const');
16 |
17 | goog.require('goog.asserts');
18 | goog.require('goog.string.TypedString');
19 |
20 |
21 |
22 | /**
23 | * Wrapper for compile-time-constant strings.
24 | *
25 | * Const is a wrapper for strings that can only be created from program
26 | * constants (i.e., string literals). This property relies on a custom Closure
27 | * compiler check that {@code goog.string.Const.from} is only invoked on
28 | * compile-time-constant expressions.
29 | *
30 | * Const is useful in APIs whose correct and secure use requires that certain
31 | * arguments are not attacker controlled: Compile-time constants are inherently
32 | * under the control of the application and not under control of external
33 | * attackers, and hence are safe to use in such contexts.
34 | *
35 | * Instances of this type must be created via its factory method
36 | * {@code goog.string.Const.from} and not by invoking its constructor. The
37 | * constructor intentionally takes no parameters and the type is immutable;
38 | * hence only a default instance corresponding to the empty string can be
39 | * obtained via constructor invocation.
40 | *
41 | * @see goog.string.Const#from
42 | * @constructor
43 | * @final
44 | * @struct
45 | * @implements {goog.string.TypedString}
46 | */
47 | goog.string.Const = function() {
48 | /**
49 | * The wrapped value of this Const object. The field has a purposely ugly
50 | * name to make (non-compiled) code that attempts to directly access this
51 | * field stand out.
52 | * @private {string}
53 | */
54 | this.stringConstValueWithSecurityContract__googStringSecurityPrivate_ = '';
55 |
56 | /**
57 | * A type marker used to implement additional run-time type checking.
58 | * @see goog.string.Const#unwrap
59 | * @const
60 | * @private
61 | */
62 | this.STRING_CONST_TYPE_MARKER__GOOG_STRING_SECURITY_PRIVATE_ =
63 | goog.string.Const.TYPE_MARKER_;
64 | };
65 |
66 |
67 | /**
68 | * @override
69 | * @const
70 | */
71 | goog.string.Const.prototype.implementsGoogStringTypedString = true;
72 |
73 |
74 | /**
75 | * Returns this Const's value a string.
76 | *
77 | * IMPORTANT: In code where it is security-relevant that an object's type is
78 | * indeed {@code goog.string.Const}, use {@code goog.string.Const.unwrap}
79 | * instead of this method.
80 | *
81 | * @see goog.string.Const#unwrap
82 | * @override
83 | */
84 | goog.string.Const.prototype.getTypedStringValue = function() {
85 | return this.stringConstValueWithSecurityContract__googStringSecurityPrivate_;
86 | };
87 |
88 |
89 | /**
90 | * Returns a debug-string representation of this value.
91 | *
92 | * To obtain the actual string value wrapped inside an object of this type,
93 | * use {@code goog.string.Const.unwrap}.
94 | *
95 | * @see goog.string.Const#unwrap
96 | * @override
97 | */
98 | goog.string.Const.prototype.toString = function() {
99 | return 'Const{' +
100 | this.stringConstValueWithSecurityContract__googStringSecurityPrivate_ +
101 | '}';
102 | };
103 |
104 |
105 | /**
106 | * Performs a runtime check that the provided object is indeed an instance
107 | * of {@code goog.string.Const}, and returns its value.
108 | * @param {!goog.string.Const} stringConst The object to extract from.
109 | * @return {string} The Const object's contained string, unless the run-time
110 | * type check fails. In that case, {@code unwrap} returns an innocuous
111 | * string, or, if assertions are enabled, throws
112 | * {@code goog.asserts.AssertionError}.
113 | */
114 | goog.string.Const.unwrap = function(stringConst) {
115 | // Perform additional run-time type-checking to ensure that stringConst is
116 | // indeed an instance of the expected type. This provides some additional
117 | // protection against security bugs due to application code that disables type
118 | // checks.
119 | if (stringConst instanceof goog.string.Const &&
120 | stringConst.constructor === goog.string.Const &&
121 | stringConst.STRING_CONST_TYPE_MARKER__GOOG_STRING_SECURITY_PRIVATE_ ===
122 | goog.string.Const.TYPE_MARKER_) {
123 | return stringConst.
124 | stringConstValueWithSecurityContract__googStringSecurityPrivate_;
125 | } else {
126 | goog.asserts.fail('expected object of type Const, got \'' +
127 | stringConst + '\'');
128 | return 'type_error:Const';
129 | }
130 | };
131 |
132 |
133 | /**
134 | * Creates a Const object from a compile-time constant string.
135 | *
136 | * It is illegal to invoke this function on an expression whose
137 | * compile-time-contant value cannot be determined by the Closure compiler.
138 | *
139 | * Correct invocations include,
140 | * <pre>
141 | * var s = goog.string.Const.from('hello');
142 | * var t = goog.string.Const.from('hello' + 'world');
143 | * </pre>
144 | *
145 | * In contrast, the following are illegal:
146 | * <pre>
147 | * var s = goog.string.Const.from(getHello());
148 | * var t = goog.string.Const.from('hello' + world);
149 | * </pre>
150 | *
151 | * TODO(xtof): Compile-time checks that this function is only called
152 | * with compile-time constant expressions.
153 | *
154 | * @param {string} s A constant string from which to create a Const.
155 | * @return {!goog.string.Const} A Const object initialized to stringConst.
156 | */
157 | goog.string.Const.from = function(s) {
158 | return goog.string.Const.create__googStringSecurityPrivate_(s);
159 | };
160 |
161 |
162 | /**
163 | * Type marker for the Const type, used to implement additional run-time
164 | * type checking.
165 | * @const {!Object}
166 | * @private
167 | */
168 | goog.string.Const.TYPE_MARKER_ = {};
169 |
170 |
171 | /**
172 | * Utility method to create Const instances.
173 | * @param {string} s The string to initialize the Const object with.
174 | * @return {!goog.string.Const} The initialized Const object.
175 | * @private
176 | */
177 | goog.string.Const.create__googStringSecurityPrivate_ = function(s) {
178 | var stringConst = new goog.string.Const();
179 | stringConst.stringConstValueWithSecurityContract__googStringSecurityPrivate_ =
180 | s;
181 | return stringConst;
182 | };