Left: | ||
Right: |
LEFT | RIGHT |
---|---|
1 // Copyright (C) 2011 Google Inc. | 1 // Copyright (C) 2011 Google Inc. |
2 // | 2 // |
3 // Licensed under the Apache License, Version 2.0 (the "License"); | 3 // Licensed under the Apache License, Version 2.0 (the "License"); |
4 // you may not use this file except in compliance with 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 | 5 // You may obtain a copy of the License at |
6 // | 6 // |
7 // https://www.apache.org/licenses/LICENSE-2.0 | 7 // https://www.apache.org/licenses/LICENSE-2.0 |
8 // | 8 // |
9 // Unless required by applicable law or agreed to in writing, software | 9 // Unless required by applicable law or agreed to in writing, software |
10 // distributed under the License is distributed on an "AS IS" BASIS, | 10 // distributed under the License is distributed on an "AS IS" BASIS, |
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
12 // See the License for the specific language governing permissions and | 12 // See the License for the specific language governing permissions and |
13 // limitations under the License. | 13 // limitations under the License. |
14 | 14 |
15 /** | 15 /** |
16 * @fileoverview Monkey patch almost ES5 platforms into a closer | 16 * @fileoverview Monkey patch almost ES5 platforms into a closer |
17 * emulation of full <a href= | 17 * emulation of full <a href= |
18 * "https://code.google.com/p/es-lab/wiki/SecureableES5">Secureable | 18 * "https://code.google.com/p/es-lab/wiki/SecureableES5">Secureable |
19 * ES5</a>. | 19 * ES5</a>. |
20 * | 20 * |
21 * <p>Assumes only ES3, but only proceeds to do useful repairs when | 21 * <p>Assumes only ES3, but only proceeds to do useful repairs when |
22 * the platform is close enough to ES5 to be worth attempting | 22 * the platform is close enough to ES5 to be worth attempting |
23 * repairs. Compatible with almost-ES5, ES5, ES5-strict, and | 23 * repairs. Compatible with almost-ES5, ES5, ES5-strict, and |
24 * anticipated ES6. | 24 * anticipated ES6. |
25 * | 25 * |
26 * <p>Ignore the "...requires ___global_test_function___" below. We | 26 * <p>Ignore the "...requires ___global_test_function___" below. We |
27 * create it, use it, and delete it all within this module. But we | 27 * create it, use it, and delete it all within this module. But we |
28 * need to lie to the linter since it can't tell. Likewise ignore the | 28 * need to lie to the linter since it can't tell. |
29 * "...requires NonexistentGlobal", since we need the attempt to | |
30 * access it to create a ReferenceError. Therefore, we actually | |
31 * require its absence, but the linter doesn't know that. | |
kpreid2
2015/02/17 19:23:07
Given that you've pointed out precedent for using
MarkM
2015/02/17 22:29:15
That worked. See reply below.
| |
32 * | 29 * |
33 * //requires ses.mitigateSrcGotchas | 30 * //requires ses.mitigateSrcGotchas |
34 * //provides ses.ok, ses.okToLoad, ses.getMaxSeverity | 31 * //provides ses.ok, ses.okToLoad, ses.getMaxSeverity |
35 * //provides ses.is, ses.makeDelayedTamperProof | 32 * //provides ses.is, ses.makeDelayedTamperProof |
36 * //provides ses.makeCallerHarmless, ses.makeArgumentsHarmless | 33 * //provides ses.makeCallerHarmless, ses.makeArgumentsHarmless |
37 * //provides ses.noFuncPoison | 34 * //provides ses.noFuncPoison |
38 * //provides ses.verifyStrictFunctionBody | 35 * //provides ses.verifyStrictFunctionBody |
39 * | 36 * |
40 * @author Mark S. Miller | 37 * @author Mark S. Miller |
41 * @requires ___global_test_function___, ___global_valueOf_function___ | 38 * @requires ___global_test_function___, ___global_valueOf_function___ |
42 * @requires JSON, eval, this | 39 * @requires JSON, eval, this |
43 * @requires navigator, document, DOMException | 40 * @requires navigator, document, DOMException |
44 * @requires NonexistentGlobal | |
45 * @overrides ses, repairES5Module | 41 * @overrides ses, repairES5Module |
46 * @overrides RegExp, WeakMap, Object, parseInt | 42 * @overrides RegExp, WeakMap, Object, parseInt |
47 */ | 43 */ |
48 var RegExp; | 44 var RegExp; |
49 var ses; | 45 var ses; |
50 | 46 |
51 /** | 47 /** |
52 * <p>Qualifying platforms generally include all JavaScript platforms | 48 * <p>Qualifying platforms generally include all JavaScript platforms |
53 * shown on <a href="http://kangax.github.com/es5-compat-table/" | 49 * shown on <a href="http://kangax.github.com/es5-compat-table/" |
54 * >ECMAScript 5 compatibility table</a> that implement {@code | 50 * >ECMAScript 5 compatibility table</a> that implement {@code |
(...skipping 3133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3188 } else { | 3184 } else { |
3189 return 'Unexpected result of setting a function\'s prototype ' + | 3185 return 'Unexpected result of setting a function\'s prototype ' + |
3190 'with defineProperty: ' + typeof bar.prototype; | 3186 'with defineProperty: ' + typeof bar.prototype; |
3191 } | 3187 } |
3192 } | 3188 } |
3193 | 3189 |
3194 /** | 3190 /** |
3195 * Tests for https://bugzilla.mozilla.org/show_bug.cgi?id=1125389 | 3191 * Tests for https://bugzilla.mozilla.org/show_bug.cgi?id=1125389 |
3196 * which is a Firefox specific bug that enables one to extend | 3192 * which is a Firefox specific bug that enables one to extend |
3197 * objects that were supposedly made non-extensible. | 3193 * objects that were supposedly made non-extensible. |
3198 * | |
3199 * <p>We use ReferenceError rather than the more traditional | |
3200 * TypeError below (by changing the right side of the assignment to, | |
3201 * for example 1) since doing so no longer provokes the bug on FF35. | |
3202 */ | 3194 */ |
3203 function test_NON_EXTENSIBLES_EXTENSIBLE() { | 3195 function test_NON_EXTENSIBLES_EXTENSIBLE() { |
3196 var someVar = 33; | |
3197 var a = void 0; | |
3204 function Obj() { | 3198 function Obj() { |
3205 this.x = 0; | 3199 this.x = 0; |
3206 Object.preventExtensions(this); | 3200 Object.preventExtensions(this); |
3207 } | 3201 } |
3208 var i = 0; | 3202 var i = 0; |
3209 function test() { | 3203 function test() { |
3210 var A = new Obj(); | 3204 var A = new Obj(); |
3205 a = A; | |
3211 while (i < 2000) { | 3206 while (i < 2000) { |
3212 i++; | 3207 i++; |
3213 if (Object.isExtensible(A)) { | 3208 if (Object.isExtensible(A)) { |
3214 return; | 3209 return; |
3215 } | 3210 } |
3216 } | 3211 } |
3217 A.length1 = NonexistentGlobal; | 3212 A.length1 = someVar; |
kpreid2
2015/02/17 19:23:07
Will this also provoke the bug if we use an actual
MarkM
2015/02/17 22:29:15
Good intuition and good news:
Not only does an ex
| |
3218 } | 3213 } |
3219 try { | 3214 try { |
3220 test(); | 3215 test(); |
3221 } catch (e) { | 3216 } catch (e) { |
3222 if (e instanceof ReferenceError && i === 2000) { | 3217 if (e instanceof TypeError && i === 2000) { |
3223 return false; | 3218 return false; |
3224 } else { | 3219 } else { |
3225 return 'Unexpected error: ' + e; | 3220 return 'Unexpected error: ' + e; |
3226 } | 3221 } |
3222 } | |
3223 try { | |
3224 a.randomProperty = someVar; | |
3225 a.length1 = someVar; | |
3226 } catch (e2) { | |
3227 return 'Extending failed: ' + e2; | |
3228 } | |
3229 if (a.randomProperty !== someVar || a.length1 !== someVar) { | |
3230 return 'Did not extend correctly: ' + a; | |
3227 } | 3231 } |
3228 return true; | 3232 return true; |
3229 } | 3233 } |
3230 | 3234 |
3231 ////////////////////// Repairs ///////////////////// | 3235 ////////////////////// Repairs ///////////////////// |
3232 // | 3236 // |
3233 // Each repair_NAME function exists primarily to repair the problem | 3237 // Each repair_NAME function exists primarily to repair the problem |
3234 // indicated by the corresponding test_NAME function. But other test | 3238 // indicated by the corresponding test_NAME function. But other test |
3235 // failures can still trigger a given repair. | 3239 // failures can still trigger a given repair. |
3236 | 3240 |
(...skipping 661 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3898 * need not be unguessage, but only resistent to accidental | 3902 * need not be unguessage, but only resistent to accidental |
3899 * collision. If the WeakMap installation repair happens on top of | 3903 * collision. If the WeakMap installation repair happens on top of |
3900 * this one, they should compose fine. | 3904 * this one, they should compose fine. |
3901 */ | 3905 */ |
3902 function repair_NON_EXTENSIBLES_EXTENSIBLE() { | 3906 function repair_NON_EXTENSIBLES_EXTENSIBLE() { |
3903 var hop = Object.prototype.hasOwnProperty; | 3907 var hop = Object.prototype.hasOwnProperty; |
3904 var gopn = Object.getOwnPropertyNames; | 3908 var gopn = Object.getOwnPropertyNames; |
3905 var defProp = Object.defineProperty; | 3909 var defProp = Object.defineProperty; |
3906 var isExtensible = Object.isExtensible; | 3910 var isExtensible = Object.isExtensible; |
3907 | 3911 |
3908 var BOGUS_NAME = '___j9d04gcuzydmfgvi___'; | 3912 var DUMMY_NAME = '___j9d04gcuzydmfgvi___'; |
3909 | 3913 |
3910 function isNotBogusName(name) { return name !== BOGUS_NAME; } | 3914 function isNotDummyName(name) { return name !== DUMMY_NAME; } |
3915 | |
3916 // For all calls to Object.defineProperty (defProp) to redefine an | |
3917 // existing property, keep in mind that omitting some attributes, | |
3918 // like writable:, enumerable:, or configurable:, means that the | |
3919 // current setting of these attributes should be preseved, rather | |
3920 // than defaulting to false. | |
3921 | |
3922 // Note that the use of .filter as an array instance method below | |
3923 // only works in SES under the immutable primordials | |
3924 // assumption. For example, it would not work in CES (Confined | |
3925 // EcmaScript). | |
3911 | 3926 |
3912 defProp(Object, 'getOwnPropertyNames', { | 3927 defProp(Object, 'getOwnPropertyNames', { |
kpreid2
2015/02/17 19:23:07
All property descriptors should be configurable:tr
MarkM
2015/02/17 22:29:15
Added comment both here and in WeakMap.js explaini
| |
3913 value: function nonBogusGetOwnPropertyNames(obj) { | 3928 value: function nonDummyGetOwnPropertyNames(obj) { |
3914 return gopn(obj).filter(isNotBogusName); | 3929 return gopn(obj).filter(isNotDummyName); |
kpreid2
2015/02/17 19:23:07
Worth noting that this is not sound in a writable-
MarkM
2015/02/17 22:29:15
Done.
| |
3915 } | 3930 } |
3916 }); | 3931 }); |
3917 if ('getPropertyNames' in Object) { | 3932 if ('getPropertyNames' in Object) { |
3918 var originalGetPropertyNames = Object.getPropertyNames; | 3933 var originalGetPropertyNames = Object.getPropertyNames; |
3919 defProp(Object, 'getPropertyNames', { | 3934 defProp(Object, 'getPropertyNames', { |
3920 value: function nonBogusGetPropertyNames(obj) { | 3935 value: function nonDummyGetPropertyNames(obj) { |
3921 return originalGetPropertyNames(obj).filter(isNotBogusName); | 3936 return originalGetPropertyNames(obj).filter(isNotDummyName); |
3922 } | 3937 } |
3923 }); | 3938 }); |
3924 } | 3939 } |
3925 | 3940 |
3926 function makeBogus(obj) { | 3941 function addDummyProperty(obj) { |
kpreid2
2015/02/17 19:23:07
Unhelpful function name, sounds constructorish. Ho
MarkM
2015/02/17 22:29:15
Done.
| |
3927 if (obj !== Object(obj)) { return; } | 3942 if (obj !== Object(obj)) { return; } |
3928 if (!Object.isExtensible(obj)) { return; } | 3943 if (!Object.isExtensible(obj)) { return; } |
3929 defProp(obj, BOGUS_NAME, { | 3944 defProp(obj, DUMMY_NAME, { |
3930 value: 'BOGUS', | 3945 value: 'DUMMY', |
3931 writable: false, | 3946 writable: false, |
3932 enumerable: false, | 3947 enumerable: false, |
3933 configurable: false | 3948 configurable: false |
3934 }); | 3949 }); |
3935 } | 3950 } |
3936 | 3951 |
3937 var oldFreeze = Object.freeze; | 3952 var oldFreeze = Object.freeze; |
3938 defProp(Object, 'freeze', { | 3953 defProp(Object, 'freeze', { |
3939 value: function bogosifyingFreeze(obj) { | 3954 value: function bogosifyingFreeze(obj) { |
3940 makeBogus(obj); | 3955 addDummyProperty(obj); |
3941 return oldFreeze(obj); | 3956 return oldFreeze(obj); |
3942 } | 3957 } |
3943 }); | 3958 }); |
3944 | 3959 |
3945 var oldSeal = Object.seal; | 3960 var oldSeal = Object.seal; |
3946 defProp(Object, 'seal', { | 3961 defProp(Object, 'seal', { |
3947 value: function bogosifyingSeal(obj) { | 3962 value: function bogosifyingSeal(obj) { |
3948 makeBogus(obj); | 3963 addDummyProperty(obj); |
3949 return oldSeal(obj); | 3964 return oldSeal(obj); |
3950 } | 3965 } |
3951 }); | 3966 }); |
3952 | 3967 |
3953 var oldPreventExtensions = Object.preventExtensions; | 3968 var oldPreventExtensions = Object.preventExtensions; |
3954 defProp(Object, 'preventExtensions', { | 3969 defProp(Object, 'preventExtensions', { |
3955 value: function bogosifyingPreventExtensions(obj) { | 3970 value: function bogosifyingPreventExtensions(obj) { |
3956 makeBogus(obj); | 3971 addDummyProperty(obj); |
3957 return oldPreventExtensions(obj); | 3972 return oldPreventExtensions(obj); |
3958 } | 3973 } |
3959 }); | 3974 }); |
3960 } | 3975 } |
3961 | 3976 |
3962 ////////////////////// Generic tests/repairs ///////////////////// | 3977 ////////////////////// Generic tests/repairs ///////////////////// |
3963 // | 3978 // |
3964 // These are tests and repairs which follow a pattern, such that it is | 3979 // These are tests and repairs which follow a pattern, such that it is |
3965 // more practical to define them programmatically. | 3980 // more practical to define them programmatically. |
3966 | 3981 |
(...skipping 1336 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5303 ses.es5ProblemReports = indexedReports; | 5318 ses.es5ProblemReports = indexedReports; |
5304 } catch (err) { | 5319 } catch (err) { |
5305 ses._repairer.updateMaxSeverity(ses.severities.NOT_SUPPORTED); | 5320 ses._repairer.updateMaxSeverity(ses.severities.NOT_SUPPORTED); |
5306 var during = ses._repairer.wasDoing(); | 5321 var during = ses._repairer.wasDoing(); |
5307 logger.error('ES5 Repair ' + during + 'failed with: ', err); | 5322 logger.error('ES5 Repair ' + during + 'failed with: ', err); |
5308 } | 5323 } |
5309 | 5324 |
5310 logger.reportMax(); | 5325 logger.reportMax(); |
5311 | 5326 |
5312 })(this); | 5327 })(this); |
LEFT | RIGHT |