| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1360,6 +1360,24 @@ The externally maintained libraries used by Node.js are: | |||
| 1360 | 1360 | OR OTHER DEALINGS IN THE SOFTWARE. | |
| 1361 | 1361 | """ | |
| 1362 | 1362 | ||
| 1363 | + - caja, located at lib/internal/freeze_intrinsics.js, is licensed as follows: | ||
| 1364 | + """ | ||
| 1365 | + Adapted from SES/Caja - Copyright (C) 2011 Google Inc. | ||
| 1366 | + Copyright (C) 2018 Agoric | ||
| 1367 | + | ||
| 1368 | + Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 1369 | + you may not use this file except in compliance with the License. | ||
| 1370 | + You may obtain a copy of the License at | ||
| 1371 | + | ||
| 1372 | + http://www.apache.org/licenses/LICENSE-2.0 | ||
| 1373 | + | ||
| 1374 | + Unless required by applicable law or agreed to in writing, software | ||
| 1375 | + distributed under the License is distributed on an "AS IS" BASIS, | ||
| 1376 | + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 1377 | + See the License for the specific language governing permissions and | ||
| 1378 | + limitations under the License. | ||
| 1379 | + """ | ||
| 1380 | + | ||
| 1363 | 1381 | - brotli, located at deps/brotli, is licensed as follows: | |
| 1364 | 1382 | """ | |
| 1365 | 1383 | Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors. | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -177,6 +177,25 @@ added: v6.0.0 | |||
| 177 | 177 | Force FIPS-compliant crypto on startup. (Cannot be disabled from script code.) | |
| 178 | 178 | (Same requirements as `--enable-fips`.) | |
| 179 | 179 | ||
| 180 | + ### `--frozen-intrinsics` | ||
| 181 | + <!-- YAML | ||
| 182 | + added: REPLACEME | ||
| 183 | + --> | ||
| 184 | + | ||
| 185 | + > Stability: 1 - Experimental | ||
| 186 | + | ||
| 187 | + Enable experimental frozen intrinsics like `Array` and `Object`. | ||
| 188 | + | ||
| 189 | + Support is currently only provided for the root context and no guarantees are | ||
| 190 | + currently provided that `global.Array` is indeed the default intrinsic | ||
| 191 | + reference. | ||
| 192 | + | ||
| 193 | + **Code breakage is highly likely with this flag**, especially since limited | ||
| 194 | + support for subclassing builtins is provided currently due to ECMA-262 bug | ||
| 195 | + https://github.com/tc39/ecma262/pull/1320. | ||
| 196 | + | ||
| 197 | + Both of the above may change in future updates, which will be breaking changes. | ||
| 198 | + | ||
| 180 | 199 | ### `--http-parser=library` | |
| 181 | 200 | <!-- YAML | |
| 182 | 201 | added: v11.4.0 | |
@@ -671,6 +690,7 @@ Node.js options that are allowed are: | |||
| 671 | 690 | - `--experimental-report` | |
| 672 | 691 | - `--experimental-vm-modules` | |
| 673 | 692 | - `--force-fips` | |
| 693 | + - `--frozen-intrinsics` | ||
| 674 | 694 | - `--icu-data-dir` | |
| 675 | 695 | - `--inspect` | |
| 676 | 696 | - `--inspect-brk` | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -144,6 +144,9 @@ Force FIPS-compliant crypto on startup | |||
| 144 | 144 | Same requirements as | |
| 145 | 145 | .Fl -enable-fips . | |
| 146 | 146 | . | |
| 147 | + .It Fl -frozen-intrinsics | ||
| 148 | + Enable experimental frozen intrinsics support. | ||
| 149 | + . | ||
| 147 | 150 | .It Fl -http-parser Ns = Ns Ar library | |
| 148 | 151 | Chooses an HTTP parser library. Available values are | |
| 149 | 152 | .Sy llhttp | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -31,6 +31,7 @@ function prepareMainThreadExecution() { | |||
| 31 | 31 | initializeClusterIPC(); | |
| 32 | 32 | ||
| 33 | 33 | initializeDeprecations(); | |
| 34 | + initializeFrozenIntrinsics(); | ||
| 34 | 35 | initializeESMLoader(); | |
| 35 | 36 | loadPreloadModules(); | |
| 36 | 37 | } | |
@@ -230,6 +231,14 @@ function initializeESMLoader() { | |||
| 230 | 231 | } | |
| 231 | 232 | } | |
| 232 | 233 | ||
| 234 | + function initializeFrozenIntrinsics() { | ||
| 235 | + if (getOptionValue('--frozen-intrinsics')) { | ||
| 236 | + process.emitWarning('The --frozen-intrinsics flag is experimental', | ||
| 237 | + 'ExperimentalWarning'); | ||
| 238 | + require('internal/freeze_intrinsics')(); | ||
| 239 | + } | ||
| 240 | + } | ||
| 241 | + | ||
| 233 | 242 | function loadPreloadModules() { | |
| 234 | 243 | // For user code, we preload modules if `-r` is passed | |
| 235 | 244 | const preloadModules = getOptionValue('--require'); | |
@@ -245,6 +254,7 @@ module.exports = { | |||
| 245 | 254 | prepareMainThreadExecution, | |
| 246 | 255 | initializeDeprecations, | |
| 247 | 256 | initializeESMLoader, | |
| 257 | + initializeFrozenIntrinsics, | ||
| 248 | 258 | loadPreloadModules, | |
| 249 | 259 | setupTraceCategoryState, | |
| 250 | 260 | initializeReport | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,244 @@ | |||
| 1 | + // Adapted from SES/Caja - Copyright (C) 2011 Google Inc. | ||
| 2 | + // Copyright (C) 2018 Agoric | ||
| 3 | + | ||
| 4 | + // Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 5 | + // you may not use this file except in compliance with the License. | ||
| 6 | + // You may obtain a copy of the License at | ||
| 7 | + // | ||
| 8 | + // http://www.apache.org/licenses/LICENSE-2.0 | ||
| 9 | + // | ||
| 10 | + // Unless required by applicable law or agreed to in writing, software | ||
| 11 | + // distributed under the License is distributed on an "AS IS" BASIS, | ||
| 12 | + // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 13 | + // See the License for the specific language governing permissions and | ||
| 14 | + // limitations under the License. | ||
| 15 | + // SPDX-License-Identifier: MIT | ||
| 16 | + | ||
| 17 | + // based upon: | ||
| 18 | + // https://github.com/google/caja/blob/master/src/com/google/caja/ses/startSES.js | ||
| 19 | + // https://github.com/google/caja/blob/master/src/com/google/caja/ses/repairES5.js | ||
| 20 | + // https://github.com/tc39/proposal-frozen-realms/blob/91ac390e3451da92b5c27e354b39e52b7636a437/shim/src/deep-freeze.js | ||
| 21 | + | ||
| 22 | + /* global WebAssembly, SharedArrayBuffer, console */ | ||
| 23 | + 'use strict'; | ||
| 24 | + module.exports = function() { | ||
| 25 | + | ||
| 26 | + const intrinsics = [ | ||
| 27 | + // Anonymous Intrinsics | ||
| 28 | + // ThrowTypeError | ||
| 29 | + Object.getOwnPropertyDescriptor(Function.prototype, 'caller').get, | ||
| 30 | + // IteratorPrototype | ||
| 31 | + Object.getPrototypeOf( | ||
| 32 | + Object.getPrototypeOf(new Array()[Symbol.iterator]()) | ||
| 33 | + ), | ||
| 34 | + // ArrayIteratorPrototype | ||
| 35 | + Object.getPrototypeOf(new Array()[Symbol.iterator]()), | ||
| 36 | + // StringIteratorPrototype | ||
| 37 | + Object.getPrototypeOf(new String()[Symbol.iterator]()), | ||
| 38 | + // MapIteratorPrototype | ||
| 39 | + Object.getPrototypeOf(new Map()[Symbol.iterator]()), | ||
| 40 | + // SetIteratorPrototype | ||
| 41 | + Object.getPrototypeOf(new Set()[Symbol.iterator]()), | ||
| 42 | + // GeneratorFunction | ||
| 43 | + Object.getPrototypeOf(function* () {}), | ||
| 44 | + // AsyncFunction | ||
| 45 | + Object.getPrototypeOf(async function() {}), | ||
| 46 | + // AsyncGeneratorFunction | ||
| 47 | + Object.getPrototypeOf(async function* () {}), | ||
| 48 | + // TypedArray | ||
| 49 | + Object.getPrototypeOf(Uint8Array), | ||
| 50 | + | ||
| 51 | + // 18 The Global Object | ||
| 52 | + eval, | ||
| 53 | + isFinite, | ||
| 54 | + isNaN, | ||
| 55 | + parseFloat, | ||
| 56 | + parseInt, | ||
| 57 | + decodeURI, | ||
| 58 | + decodeURIComponent, | ||
| 59 | + encodeURI, | ||
| 60 | + encodeURIComponent, | ||
| 61 | + | ||
| 62 | + // 19 Fundamental Objects | ||
| 63 | + Object, // 19.1 | ||
| 64 | + Function, // 19.2 | ||
| 65 | + Boolean, // 19.3 | ||
| 66 | + Symbol, // 19.4 | ||
| 67 | + | ||
| 68 | + // Disabled pending stack trace mutation handling | ||
| 69 | + // Error, // 19.5 | ||
| 70 | + // EvalError, | ||
| 71 | + // RangeError, | ||
| 72 | + // ReferenceError, | ||
| 73 | + // SyntaxError, | ||
| 74 | + // TypeError, | ||
| 75 | + // URIError, | ||
| 76 | + | ||
| 77 | + // 20 Numbers and Dates | ||
| 78 | + Number, // 20.1 | ||
| 79 | + Math, // 20.2 | ||
| 80 | + Date, // 20.3 | ||
| 81 | + | ||
| 82 | + // 21 Text Processing | ||
| 83 | + String, // 21.1 | ||
| 84 | + RegExp, // 21.2 | ||
| 85 | + | ||
| 86 | + // 22 Indexed Collections | ||
| 87 | + Array, // 22.1 | ||
| 88 | + | ||
| 89 | + Int8Array, | ||
| 90 | + Uint8Array, | ||
| 91 | + Uint8ClampedArray, | ||
| 92 | + Int16Array, | ||
| 93 | + Uint16Array, | ||
| 94 | + Int32Array, | ||
| 95 | + Uint32Array, | ||
| 96 | + Float32Array, | ||
| 97 | + Float64Array, | ||
| 98 | + BigInt64Array, | ||
| 99 | + BigUint64Array, | ||
| 100 | + | ||
| 101 | + // 23 Keyed Collections | ||
| 102 | + Map, // 23.1 | ||
| 103 | + Set, // 23.2 | ||
| 104 | + WeakMap, // 23.3 | ||
| 105 | + WeakSet, // 23.4 | ||
| 106 | + | ||
| 107 | + // 24 Structured Data | ||
| 108 | + ArrayBuffer, // 24.1 | ||
| 109 | + DataView, // 24.3 | ||
| 110 | + JSON, // 24.5 | ||
| 111 | + Promise, // 25.4 | ||
| 112 | + | ||
| 113 | + // 26 Reflection | ||
| 114 | + Reflect, // 26.1 | ||
| 115 | + Proxy, // 26.2 | ||
| 116 | + | ||
| 117 | + // B.2.1 | ||
| 118 | + escape, | ||
| 119 | + unescape, | ||
| 120 | + | ||
| 121 | + // Web compatibility | ||
| 122 | + clearImmediate, | ||
| 123 | + clearInterval, | ||
| 124 | + clearTimeout, | ||
| 125 | + decodeURI, | ||
| 126 | + decodeURIComponent, | ||
| 127 | + encodeURI, | ||
| 128 | + encodeURIComponent, | ||
| 129 | + setImmediate, | ||
| 130 | + setInterval, | ||
| 131 | + setTimeout, | ||
| 132 | + | ||
| 133 | + // Other APIs | ||
| 134 | + console, | ||
| 135 | + BigInt, | ||
| 136 | + Atomics, | ||
| 137 | + WebAssembly, | ||
| 138 | + SharedArrayBuffer | ||
| 139 | + ]; | ||
| 140 | + | ||
| 141 | + if (typeof Intl !== 'undefined') | ||
| 142 | + intrinsics.push(Intl); | ||
| 143 | + | ||
| 144 | + intrinsics.forEach(deepFreeze); | ||
| 145 | + | ||
| 146 | + function deepFreeze(root) { | ||
| 147 | + | ||
| 148 | + const { freeze, getOwnPropertyDescriptors, getPrototypeOf } = Object; | ||
| 149 | + const { ownKeys } = Reflect; | ||
| 150 | + | ||
| 151 | + // Objects that are deeply frozen. | ||
| 152 | + // It turns out that Error is reachable from WebAssembly so it is | ||
| 153 | + // explicitly added here to ensure it is not frozen | ||
| 154 | + const frozenSet = new WeakSet([Error, Error.prototype]); | ||
| 155 | + | ||
| 156 | + /** | ||
| 157 | + * "innerDeepFreeze()" acts like "Object.freeze()", except that: | ||
| 158 | + * | ||
| 159 | + * To deepFreeze an object is to freeze it and all objects transitively | ||
| 160 | + * reachable from it via transitive reflective property and prototype | ||
| 161 | + * traversal. | ||
| 162 | + */ | ||
| 163 | + function innerDeepFreeze(node) { | ||
| 164 | + // Objects that we have frozen in this round. | ||
| 165 | + const freezingSet = new Set(); | ||
| 166 | + | ||
| 167 | + // If val is something we should be freezing but aren't yet, | ||
| 168 | + // add it to freezingSet. | ||
| 169 | + function enqueue(val) { | ||
| 170 | + if (Object(val) !== val) { | ||
| 171 | + // ignore primitives | ||
| 172 | + return; | ||
| 173 | + } | ||
| 174 | + const type = typeof val; | ||
| 175 | + if (type !== 'object' && type !== 'function') { | ||
| 176 | + // NB: handle for any new cases in future | ||
| 177 | + } | ||
| 178 | + if (frozenSet.has(val) || freezingSet.has(val)) { | ||
| 179 | + // todo use uncurried form | ||
| 180 | + // Ignore if already frozen or freezing | ||
| 181 | + return; | ||
| 182 | + } | ||
| 183 | + freezingSet.add(val); // todo use uncurried form | ||
| 184 | + } | ||
| 185 | + | ||
| 186 | + function doFreeze(obj) { | ||
| 187 | + // Immediately freeze the object to ensure reactive | ||
| 188 | + // objects such as proxies won't add properties | ||
| 189 | + // during traversal, before they get frozen. | ||
| 190 | + | ||
| 191 | + // Object are verified before being enqueued, | ||
| 192 | + // therefore this is a valid candidate. | ||
| 193 | + // Throws if this fails (strict mode). | ||
| 194 | + freeze(obj); | ||
| 195 | + | ||
| 196 | + // We rely upon certain commitments of Object.freeze and proxies here | ||
| 197 | + | ||
| 198 | + // Get stable/immutable outbound links before a Proxy has a chance to do | ||
| 199 | + // something sneaky. | ||
| 200 | + const proto = getPrototypeOf(obj); | ||
| 201 | + const descs = getOwnPropertyDescriptors(obj); | ||
| 202 | + enqueue(proto); | ||
| 203 | + ownKeys(descs).forEach((name) => { | ||
| 204 | + // todo uncurried form | ||
| 205 | + // todo: getOwnPropertyDescriptors is guaranteed to return well-formed | ||
| 206 | + // descriptors, but they still inherit from Object.prototype. If | ||
| 207 | + // someone has poisoned Object.prototype to add 'value' or 'get' | ||
| 208 | + // properties, then a simple 'if ("value" in desc)' or 'desc.value' | ||
| 209 | + // test could be confused. We use hasOwnProperty to be sure about | ||
| 210 | + // whether 'value' is present or not, which tells us for sure that | ||
| 211 | + // this is a data property. | ||
| 212 | + const desc = descs[name]; | ||
| 213 | + if ('value' in desc) { | ||
| 214 | + // todo uncurried form | ||
| 215 | + enqueue(desc.value); | ||
| 216 | + } else { | ||
| 217 | + enqueue(desc.get); | ||
| 218 | + enqueue(desc.set); | ||
| 219 | + } | ||
| 220 | + }); | ||
| 221 | + } | ||
| 222 | + | ||
| 223 | + function dequeue() { | ||
| 224 | + // New values added before forEach() has finished will be visited. | ||
| 225 | + freezingSet.forEach(doFreeze); // todo curried forEach | ||
| 226 | + } | ||
| 227 | + | ||
| 228 | + function commit() { | ||
| 229 | + // todo curried forEach | ||
| 230 | + // we capture the real WeakSet.prototype.add above, in case someone | ||
| 231 | + // changes it. The two-argument form of forEach passes the second | ||
| 232 | + // argument as the 'this' binding, so we add to the correct set. | ||
| 233 | + freezingSet.forEach(frozenSet.add, frozenSet); | ||
| 234 | + } | ||
| 235 | + | ||
| 236 | + enqueue(node); | ||
| 237 | + dequeue(); | ||
| 238 | + commit(); | ||
| 239 | + } | ||
| 240 | + | ||
| 241 | + innerDeepFreeze(root); | ||
| 242 | + return root; | ||
| 243 | + } | ||
| 244 | + }; | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -6,6 +6,7 @@ | |||
| 6 | 6 | const { | |
| 7 | 7 | initializeDeprecations, | |
| 8 | 8 | initializeESMLoader, | |
| 9 | + initializeFrozenIntrinsics, | ||
| 9 | 10 | initializeReport, | |
| 10 | 11 | loadPreloadModules, | |
| 11 | 12 | setupTraceCategoryState | |
@@ -81,6 +82,7 @@ port.on('message', (message) => { | |||
| 81 | 82 | require('internal/process/policy').setup(manifestSrc, manifestURL); | |
| 82 | 83 | } | |
| 83 | 84 | initializeDeprecations(); | |
| 85 | + initializeFrozenIntrinsics(); | ||
| 84 | 86 | initializeESMLoader(); | |
| 85 | 87 | loadPreloadModules(); | |
| 86 | 88 | publicWorker.parentPort = publicPort; | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -123,6 +123,7 @@ | |||
| 123 | 123 | 'lib/internal/error-serdes.js', | |
| 124 | 124 | 'lib/internal/fixed_queue.js', | |
| 125 | 125 | 'lib/internal/freelist.js', | |
| 126 | + 'lib/internal/freeze_intrinsics.js', | ||
| 126 | 127 | 'lib/internal/fs/promises.js', | |
| 127 | 128 | 'lib/internal/fs/read_file_context.js', | |
| 128 | 129 | 'lib/internal/fs/streams.js', | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -187,6 +187,10 @@ EnvironmentOptionsParser::EnvironmentOptionsParser() { | |||
| 187 | 187 | kAllowedInEnvironment); | |
| 188 | 188 | #endif // NODE_REPORT | |
| 189 | 189 | AddOption("--expose-internals", "", &EnvironmentOptions::expose_internals); | |
| 190 | + AddOption("--frozen-intrinsics", | ||
| 191 | + "experimental frozen intrinsics support", | ||
| 192 | + &EnvironmentOptions::frozen_intrinsics, | ||
| 193 | + kAllowedInEnvironment); | ||
| 190 | 194 | AddOption("--http-parser", | |
| 191 | 195 | "Select which HTTP parser to use; either 'legacy' or 'llhttp' " | |
| 192 | 196 | #ifdef NODE_EXPERIMENTAL_HTTP_DEFAULT | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -100,6 +100,7 @@ class EnvironmentOptions : public Options { | |||
| 100 | 100 | bool experimental_repl_await = false; | |
| 101 | 101 | bool experimental_vm_modules = false; | |
| 102 | 102 | bool expose_internals = false; | |
| 103 | + bool frozen_intrinsics = false; | ||
| 103 | 104 | std::string http_parser = | |
| 104 | 105 | #ifdef NODE_EXPERIMENTAL_HTTP_DEFAULT | |
| 105 | 106 | "llhttp"; | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,10 @@ | |||
| 1 | + // Flags: --frozen-intrinsics | ||
| 2 | + 'use strict'; | ||
| 3 | + require('../common'); | ||
| 4 | + const assert = require('assert'); | ||
| 5 | + | ||
| 6 | + try { | ||
| 7 | + Object.defineProperty = 'asdf'; | ||
| 8 | + assert(false); | ||
| 9 | + } catch { | ||
| 10 | + } | ||
| Back | FazBrowse Home | New Git URL |
0 commit comments