Socket
Socket
Sign inDemoInstall

ses

Package Overview
Dependencies
Maintainers
3
Versions
103
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

ses - npm Package Compare versions

Comparing version 0.1.2 to 0.1.3

src/bundle/nat.js

231

demo/demo-start.js

@@ -23,8 +23,13 @@ console.log('starting');

function delayMS(count, value) {
// return a Promise that fires (with 'value') 'count' milliseconds in the
// future
return new Promise((resolve, reject) => window.setTimeout(resolve, count, value));
function delayMS(count) {
// busywait for 'count' milliseconds
const target = Date.now() + count;
while (Date.now() < target) {
}
}
function refreshUI() {
return new Promise((resolve, reject) => window.setTimeout(resolve, 0, undefined));
}
const attackerGuess = document.getElementById('guess');

@@ -35,10 +40,33 @@ function setAttackerGuess(text) {

function launch() {
document.getElementById("guess-box").className = "code-box launched";
function setLaunch(status) {
if (status) {
document.getElementById("guess-box").className = "code-box launched";
} else {
document.getElementById("guess-box").className = "code-box";
}
}
function log(...args) {
// TODO: can console.log be coerced into throwing an exception, or
// returning any other primal-realm objects? If so, the attacker could
// use their log() access to corrupt the primal realm and escape.
console.log(...args);
}
// two approaches:
// * force in-order delivery:
// maintain queue of (delay, resolver) pairs
// when guess() is called: compute delay, build promise, append (delay,resolver)
// - if queue was empty, call setTimeout(queue[0].delay)
// - then return promise
// when setTimeout fires: pop queue, fire resolver on next turn
// - if queue is non-empty, start new timer for queue[0].delay
// * better: don't give UI queue access to attacker
// attacker provides stateful object with go() method
// framework calls go(guess_func)
// attacker can use Promises and call guess_func(guess)
// guess_func returns synchronously (after busywait)
// limit attacker to some finite number of calls per go()
// framework updates UI (with setTimeout(0)), then calls go() again
// build the SES Realm and evaluate the defender inside

@@ -53,3 +81,3 @@ const options = {};

const defenderSrc = buildDefenderSrc();
const d = r.evaluate(defenderSrc, { getRandomValues, setMacguffinText, delayMS, setAttackerGuess, launch, log });
const d = r.evaluate(defenderSrc, { getRandomValues, setMacguffinText, delayMS, refreshUI, setAttackerGuess, setLaunch, log });

@@ -64,3 +92,6 @@ // now create the form that lets the user submit attacker code

console.log('executing attacker code:', code);
d.submitProgram(code);
d.stopAttacker();
// wait a moment to make sure the running program notices the stop request
const wait = new Promise((resolve, reject) => window.setTimeout(resolve, 10, undefined));
wait.then(() => d.submitProgram(code));
});

@@ -99,92 +130,74 @@ aStop.addEventListener('click', function stop(event) {

// actually use these values.
let guess, checkEnabled, log;
let guess, log;
function allZeros() {
guess('0000000000');
function* allZeros() {
guess('0000000000');
}
}
function counter() {
let i = 0;
function submitNext(correct) {
if (correct || !checkEnabled()) {
return;
}
let guessedCode = i.toString(36).toUpperCase();
while (guessedCode.length < 10) {
guessedCode = '0' + guessedCode;
}
i += 1;
guess(guessedCode).then(submitNext);
function *counter() {
for (let i = 0; true; i++) {
let guessedCode = i.toString(36).toUpperCase();
while (guessedCode.length < 10) {
guessedCode = '0' + guessedCode;
}
guess(guessedCode);
yield;
};
}
submitNext(false);
}
function timing() {
function checkOneGuess(guessedCode) {
let start = Date.now();
return guess(guessedCode).then(correct => {
let elapsed = Date.now() - start;
return { elapsed, correct };
});
}
function toChar(c) {
return c.toString(36).toUpperCase();
}
function fastestChar(delays) {
return Array.from(delays.keys()
).reduce((a, b) => delays.get(a) > delays.get(b) ? a : b);
}
function *timing() {
function toChar(c) {
return c.toString(36).toUpperCase();
}
let known = '';
let c = 0;
let delays;
function fastestChar(delays) {
const pairs = Array.from(delays.entries());
pairs.sort((a,b) => b[1] - a[1]);
return pairs[0][0];
}
function reset() {
known = '';
c = 0;
}
function insert(into, offset, char) {
return into.slice(0, offset) + char + into.slice(offset+1, into.length);
}
function checkNext() {
if (c === 0) {
delays = new Map();
function buildCode(base, offset, c) {
// keep the first 'offset' chars of base, set [offset] to c, fill the
// rest with random-looking junk to make the demo look cool
// (random-looking, not truly random, because we're deterministic)
let code = insert(base, offset, toChar(c));
for (let off2 = offset+1; off2 < 10; off2++) {
code = insert(code, off2, toChar((off2*3 + c*7) % 36));
}
return code;
}
const guessCharacter = toChar(c);
let guessedCode = known + guessCharacter;
while (guessedCode.length < 10) {
guessedCode = guessedCode + '0';
}
return checkOneGuess(guessedCode).then(o => {
const { elapsed, correct } = o;
if (correct || !checkEnabled()) {
return true;
}
//log(`delay(${guessedCode}) was ${elapsed}`);
delays.set(guessCharacter, elapsed);
c += 1;
if (c === 36) {
const next = fastestChar(delays);
log(`Adding ${known} + ${next}`);
known = known + next;
if (known.length === 10) {
// if we're right, we never actually reach here, since we guessed
// correctly earlier, and a correct guess disables the attacker
log(`I think the code is ${known}`);
return guess(known).then(correct => {
if (correct) {
log(`I was right, muahaha`);
return true;
}
log('we must have measured the timings wrong, try again');
reset();
return checkNext();
});
let base = '0000000000';
while (true) {
for (let offset = 0; offset < 10; offset++) {
const delays = new Map();
for (let c = 0; c < 36; c++) {
const guessedCode = buildCode(base, offset, c);
const start = Date.now();
guess(guessedCode);
const elapsed = Date.now() - start;
delays.set(toChar(c), elapsed);
yield; // allow UI to refresh
// if our guess was right, then on the last character
// (offset===9) we never actually reach here, since we guessed
// correctly earlier, and when the attacker guesses correctly,
// the defender stops calling go()
}
c = 0;
log(delays);
const nextChar = fastestChar(delays);
base = insert(base, offset, nextChar);
log(`Setting code[${offset}]=${nextChar} -> ${base}`);
}
return checkNext();
});
log('we must have measured the timings wrong, try again');
}
}
checkNext();
}

@@ -198,4 +211,4 @@

// actually use these values.
let getRandomValues, setMacguffinText, delayMS, setAttackerGuess, launch, log;
let SES, def;
let getRandomValues, setMacguffinText, delayMS, setAttackerGuess, setLaunch, log;
let SES, def, refreshUI;

@@ -228,32 +241,54 @@ // this is stringified and loaded in the SES realm, with several endowments

function attackerLog(...args) {
log(...args);
}
function guess(guessedCode) {
// To demonstrate how deterministic attacker code cannot sense covert
// channels, we provide a pretty obvious covert channel.
// channels, we provide a pretty obvious covert channel: we compare one
// character at a time, and busy-wait a long time between characters.
// The time we take indicates how many leading characters they got
// right, enabling a linear-time guessing attack.
guessedCode = `${guessedCode}`; // force into a String
setAttackerGuess(guessedCode);
let delay = 0;
for (let i=0; i < 10; i++) {
if (secretCode.slice(i, i+1) !== guessedCode.slice(i, i+1)) {
return delayMS(delay, false);
return false;
}
delay += 10;
delayMS(10);
}
// they guessed correctly
enableAttacker = false;
launch();
return delayMS(delay, true);
setLaunch(true);
return true;
}
function checkEnabled() {
return enableAttacker;
}
function submitProgram(program) {
// the attacker's code will be submitted here. We expect it to be a
// generator function, starting with 'function*' and ending with the
// closing curly brace
function attackerLog(...args) {
log(...args);
}
program = `(${program})`; // turn it into an expression
function submitProgram(program) {
// the attacker's code will be submitted here
enableAttacker = true;
SES.confine(program, { guess, checkEnabled, log: attackerLog });
setLaunch(false);
const attacker = SES.confine(program, { guess: guess, log: attackerLog });
const attackGen = attacker(); // build the generator
function nextGuess() {
if (!enableAttacker) {
return; // attacker was interrupted, so don't ask
}
// give the attacker another chance to run
if (attackGen.next().done) {
return; // attacker gave up, so stop asking
}
if (!enableAttacker) {
return; // attacker was correct, so stop asking
}
// now let the UI refresh before we call attacker again
refreshUI().then(nextGuess);
}
nextGuess();
}

@@ -260,0 +295,0 @@

@@ -8,4 +8,233 @@ # SES Demo

For local testing, run a web server and serve the entire git tree (the demo
accesses the generated `ROOT/dist/ses-shim.js` file, so serving just this
`demo/` directory is not enough). Re-run `npm run-script build` after any
changes to the source code to rebuild `ses-shim.js`.
accesses the generated ``ROOT/dist/ses-shim.js`` file, so serving just this
``demo/`` directory is not enough). Re-run ``npm run-script build`` after any
changes to the source code to rebuild ``ses-shim.js``.
## Would You Like To Play A Game?
Remember the scene from [WarGames](https://www.imdb.com/title/tt0086567/)
where the computer is trying to guess the launch codes? Here, you get to play
the computer.
## Attacker
You provide the attacker's program by pasting its source code into the box
and pressing the Execute button. The attack program is confined in an SES
environment (shared with the defender), which means it is limited to
``strict`` mode and has access to the usual ECMAScript primordials (Object,
String, Array, Math, Map, Date (but see below), and so on). But it does not
have access to platform objects (``window``, ``document``, or ``XHR`` on a
web browser, or ``require`` on Node.js).
In addition to the primordials, the attacker's program gets access to two
endowments: ``guess(code)`` and ``log(message)``. These are provided by the
defender.
This source code must evaluate to a generator function (starting with
`function*` and ending with a closing curly brace), which will be called once
to produce a generator. That generator will be iterated again and again until
it exits or the secret code is guessed correctly.
```js
function* guessZeros() {
guess('0000000000');
}
```
The attacker uses ``guess()`` to try and guess the launch code. This guess is
displayed on the bottom panel. When the guess matches the code on the top
panel, the attacker wins and the game is over. The codes are ten characters
long, and each character is a capital letter from A to Z, or a digit from 0
to 9. There are ``36**10`` possibilities (about three quadrillion, or about
``2**51``, which also happens to be roughly how many ants are alive on Earth
at any given moment). It takes at least a few milliseconds to check each one,
so brute-force guessing would take thousands of years to try all possible
combinations.
We use a generator function, rather than an ordinary function, as a
concession to make the demo look more interesting. In a more realistic setup,
the attacker code would do all its work during its singular evaluation (it
could make as many calls to guess() as it liked), with something like this:
```js
for (let i = 0; true; i++) {
let guessedCode = i.toString(36).toUpperCase();
while (guessedCode.length < 10) {
guessedCode = '0' + guessedCode; // pad to 10 characters
}
guess(guessedCode);
}
```
But in a single-threaded browser context, that wouldn't give the framework an
opportunity to update the UI. In addition, the web browser would pop a "this
script is taking too long" dialog box after maybe 15 seconds of constant
execution, since it is effectively stuck in an infinite loop.
By using a generator, we can update the UI once per iteration. Thus the
attack function should call ``guess()`` once, then yield from the generator,
then loop back around if it wants to make more guesses. The above program
should be rewritten like this:
```js
function* counter() {
for (let i = 0; true; i++) {
let guessedCode = i.toString(36).toUpperCase();
while (guessedCode.length < 10) {
guessedCode = '0' + guessedCode; // pad to 10 characters
}
guess(guessedCode);
yield;
}
```
Despite this quirk, the attacker's program is still essentially being
evaluated as purely transformational code: the way we load the attacker isn't
quite as important as the way we allow it to call ``guess()``.
## Defender
The defender in this game has slightly more power than the attacker: it is
SES-confined as well, but it gets additional endowments from the setup code.
One of these is a form of ``getRandomValues`` so it can select a random
target code: SES programs are normally denied access to non-determinism, so
it would have no way of choosing a different code on each pageload. A few
more endowments provide control over the DOM: ``setMacguffinText`` sets the
target code in the top box, ``setAttackerGuess`` sets the guessed code in the
bottom box, ``setLaunch`` changes the CSS class of the bottom box to change
the text color when the guess is correct. Note that, for this demo, none of
these endowments are particularly defensive: the defender code could use them
to break out of the SES sandbox.
``refreshUI`` returns a Promise that resolves after a ``setTimeout(0)``. This
yields control back to the browser's UI event queue, giving it a chance to
repaint the screen with the updated codes. ``log`` simply delivers its
arguments to the browser's usual ``console.log``.
``delayMS`` performs a busy-wait for the given number of milliseconds by
polling ``Date.now`` until it reaches some target value.
We use ``delayMS()`` to introduce an egregious timing-channel vulnerability
into the defender's ``guess()`` function: it checks the attacker's guess one
character at a time, waiting a full 10ms between each test, and returns
immediately upon the first incorrect failure. If the attacker can measure how
long ``guess()`` takes to run, they can mount a classic timing-oracle attack
which runs in linear (rather than exponential) time. A safer form of
``guess()`` would do a constant-time comparison (for which the most practical
approach is to just hash both sides and compare the hashes). Our vulnerable
``guess()`` looks like this:
```js
function guess(guessedCode) {
guessedCode = `${guessedCode}`; // force into a String
setAttackerGuess(guessedCode);
for (let i=0; i < 10; i++) {
if (secretCode.slice(i, i+1) !== guessedCode.slice(i, i+1)) {
return false;
}
delayMS(10);
}
// they guessed correctly
enableAttacker = false;
setLaunch(true);
return true;
}
```
The defender creates the ``guess()`` function, then provides it (and ``log``)
as endowments to the attacker. It invokes ``SES.confine`` to evaluate the
attacker's code with the endowments as the second argument:
```js
function attackerLog(...args) {
log(...args);
}
const attacker = SES.confine(program, { guess: guess, log: attackerLog });
```
The defender then invokes the attacker in a loop, using ``refreshUI()`` to
delay each pass until the UI had a chance to be updated, with something like
this:
```js
program = `(${program})`; // turn it into an expression
const attacker = SES.confine(program, { guess: guess, log: attackerLog });
const attackGen = attacker(); // build the generator
function nextGuess() {
// give the attacker another chance to run
if (attackGen.next().done) {
return; // attacker gave up, so stop asking
}
// now let the UI refresh before we call attacker again
refreshUI().then(nextGuess);
}
nextGuess();
```
(some additional lines exist to stop the loop if/when the attacker gets the
code right).
## Taming Date.now
The SES environment normally replaces ``Date.now()`` with a function that
only returns ``NaN``. But this can be disabled by setting a configuration
option named ``dateNowTrap`` to ``false``.
(Note that this API is still in flux, and we might change it in the future.
One interesting option might be to set ``Date.now`` to return a constant,
pre-selected value, enabling more code to run mostly-correctly, while still
limiting its use as an attack vector)
SES replaces the ``new Date()`` constructor with a tamed version that acts as
if you wrote ``new Date(NaN)``. It does not currently have an option to
change this behavior, but that will probably change too.
By prohibiting access to a clock, we can prevent the attacker code from
sensing timing-based covert channel. Fully-deterministic execution cannot
sense any covert channel, since the output must be a strict function of the
declared input, and the covert channel is (by definition) not part of the
input arguments.
However we must be careful to not inadvertently provide access to a clock.
[Fantastic Timers and Where to Find
Them](https://gruss.cc/files/fantastictimers.pdf) (by Schwarz, Maurice,
Gruss, and Mangard) enumerates a variety of surprising clocks that might be
available to Javascript code. They all depend upon forms of non-determinism,
such as:
* shared-state mutability: a ``WebWorker`` writes sequential integers to a
shared ``ArrayBuffer`` as fast as it can, while a second thread simply
reads from that location when desired
* platform-provided UI features: initiate a CSS animation and monitor its
progress
* message-passing: two separate frames exchange ``postMessage`` calls and
compare their arrival order with ones sent to themselves
* explicit platform features: the ``performance.now()`` call offers
microsecond-level timing
SES omits all platform features, which removes all the timers listed in this
paper. However it is easy to accidentally reintroduce some through
endowments. For example you might give the confined code the ability to send
messages to a remote system (which itself has access to a clock). When
multiple sources send messages to a common recipient, those messages will be
interleaved in some nondeterminisic fashion that depends upon the arrival
times: that ordering can also be used as a clock.
The demo page has two flavors: by changing the URL slightly, the attacker can
be allowed or denied access to ``Date.now()``. This makes it easy to
demonstrate the success or failure of a timing-based attack.
The first version of this demo implemented ``delayMS()`` with a Promise that
resolved at some point in the future (via a ``setTimeout()`` callback). In
that version, ``guess()`` returned a Promise. Richard Gibson exploited this
in a [clever attack](https://github.com/Agoric/SES/issues/8) that submitted
multiple guesses in parallel and sensed the order of their resolution: it
didn't reveal exactly how long ``guess()`` took, but knowing which guess took
the longest was enough to mount the attack. We thought we were only using
``setTimeout()`` for internal purposes, but by exposing a function that used
it, we accidentally gave the attacker code enough tools to build a clock of
their own.
The lesson is to be careful when building endowments, especially if you build
them from powerful components that live outside the SES environment.
{
"name": "ses",
"version": "0.1.2",
"version": "0.1.3",
"description": "Secure ECMAScript",

@@ -5,0 +5,0 @@ "main": "src/index.js",

@@ -20,3 +20,3 @@ # Secure EcmaScript (SES)

flavors of confined EcmaScript execution. And visit
https://cdn.rawgit.com/Agoric/SES/0.1.0/demo/ for a demo.
https://rawgit.com/Agoric/SES/master/demo/ for a demo.

@@ -23,0 +23,0 @@ Derived from the Caja project, https://github.com/google/caja/wiki/SES .

@@ -24,2 +24,3 @@ // Copyright (C) 2018 Agoric

r.global.def = b.def;
r.global.Nat = b.Nat;

@@ -108,2 +109,4 @@ b.deepFreezePrimordials(r.global);

() => parentRealm.evaluate(code, endowments));
global.SES.confineExpr = (code, endowments) => callAndWrapError(
() => parentRealm.evaluate(`(${code})`, endowments));
}

@@ -21,6 +21,7 @@ // Copyright (C) 2018 Agoric

import { def } from './def.js';
import { Nat } from './nat.js';
export { createSESWithRealmConstructor, createSESInThisRealm,
deepFreezePrimordials, removeProperties, tamePrimordials, getAnonIntrinsics,
def
def, Nat
};

@@ -109,2 +109,3 @@ // Copyright (C) 2011 Google Inc.

var t = true;
var j = true; // included in the Jessie runtime
var TypedArrayWhitelist; // defined and used below

@@ -208,8 +209,8 @@

constFunc: t,
Nat: t,
def: t,
Nat: j,
def: j,
is: t,
compileExpr: t,
confine: t,
confine: j,
compileModule: t, // experimental

@@ -249,5 +250,5 @@ compileProgram: t, // Cannot be implemented in just ES5.1.

// 18.1
Infinity: t,
NaN: t,
undefined: t,
Infinity: j,
NaN: j,
undefined: j,

@@ -266,3 +267,3 @@ // 18.2

// 19 Fundamental Objects

@@ -276,3 +277,3 @@

entries: t, // ES-Harmony
freeze: t,
freeze: j,
getOwnPropertyDescriptor: t,

@@ -283,3 +284,3 @@ getOwnPropertyDescriptors: t, // proposed ES-Harmony

getPrototypeOf: t,
is: t, // ES-Harmony
is: j, // ES-Harmony
isExtensible: t,

@@ -289,4 +290,4 @@ isFrozen: t,

keys: t,
preventExtensions: t,
seal: t,
preventExtensions: j,
seal: j,
setPrototypeOf: t, // ES-Harmony

@@ -319,3 +320,3 @@ values: t, // ES-Harmony

},
Function: { // 19.2

@@ -339,7 +340,7 @@ length: t,

},
Boolean: { // 19.3
prototype: t
},
Symbol: { // 19.4 all ES-Harmony

@@ -399,12 +400,12 @@ asyncIterator: t, // proposed? ES-Harmony

// 20 Numbers and Dates
Number: { // 20.1
EPSILON: t, // ES-Harmony
isFinite: t, // ES-Harmony
isFinite: j, // ES-Harmony
isInteger: t, // ES-Harmony
isNaN: t, // ES-Harmony
isSafeInteger: t, // ES-Harmony
MAX_SAFE_INTEGER: t, // ES-Harmony
isNaN: j, // ES-Harmony
isSafeInteger: j, // ES-Harmony
MAX_SAFE_INTEGER: j, // ES-Harmony
MAX_VALUE: t,
MIN_SAFE_INTEGER: t, // ES-Harmony
MIN_SAFE_INTEGER: j, // ES-Harmony
MIN_VALUE: t,

@@ -424,12 +425,12 @@ NaN: t,

Math: { // 20.2
E: t,
LN10: t,
LN2: t,
E: j,
LN10: j,
LN2: j,
LOG10E: t,
LOG2E: t,
PI: t,
PI: j,
SQRT1_2: t,
SQRT2: t,
abs: t,
abs: j,
acos: t,

@@ -443,3 +444,3 @@ acosh: t, // ES-Harmony

cbrt: t, // ES-Harmony
ceil: t,
ceil: j,
clz32: t, // ES-Harmony

@@ -450,22 +451,22 @@ cos: t,

expm1: t, // ES-Harmony
floor: t,
floor: j,
fround: t, // ES-Harmony
hypot: t, // ES-Harmony
imul: t, // ES-Harmony
log: t,
log: j,
log1p: t, // ES-Harmony
log10: t, // ES-Harmony
log2: t, // ES-Harmony
max: t,
min: t,
pow: t,
log10: j, // ES-Harmony
log2: j, // ES-Harmony
max: j,
min: j,
pow: j,
random: t, // questionable
round: t,
round: j,
sign: t, // ES-Harmony
sin: t,
sinh: t, // ES-Harmony
sqrt: t,
sqrt: j,
tan: t,
tanh: t, // ES-Harmony
trunc: t // ES-Harmony
trunc: j // ES-Harmony
},

@@ -533,5 +534,5 @@

String: { // 21.2
fromCharCode: t,
fromCharCode: j,
fromCodePoint: t, // ES-Harmony
raw: t, // ES-Harmony
raw: j, // ES-Harmony
prototype: {

@@ -542,6 +543,6 @@ charAt: t,

concat: t,
endsWith: t, // ES-Harmony
endsWith: j, // ES-Harmony
includes: t, // ES-Harmony
indexOf: t,
lastIndexOf: t,
indexOf: j,
lastIndexOf: j,
localeCompare: t,

@@ -555,5 +556,5 @@ match: t,

search: t,
slice: t,
slice: j,
split: t,
startsWith: t, // ES-Harmony
startsWith: j, // ES-Harmony
substring: t,

@@ -569,18 +570,18 @@ toLocaleLowerCase: t,

anchor: t,
big: t,
blink: t,
bold: t,
fixed: t,
fontcolor: t,
fontsize: t,
italics: t,
link: t,
small: t,
strike: t,
sub: t,
sup: t,
big: t,
blink: t,
bold: t,
fixed: t,
fontcolor: t,
fontsize: t,
italics: t,
link: t,
small: t,
strike: t,
sub: t,
sup: t,
trimLeft: t, // non-standard
trimRight: t, // non-standard
// 21.1.4 instances

@@ -604,3 +605,3 @@ length: '*'

sticky: 'maybeAccessor',
test: t,
test: t,
unicode: 'maybeAccessor', // ES-Harmony

@@ -619,5 +620,5 @@ dotAll: 'maybeAccessor', // proposed ES-Harmony

Array: { // 22.1
from: t,
from: j,
isArray: t,
of: t, // ES-Harmony?
of: j, // ES-Harmony?
prototype: {

@@ -629,23 +630,23 @@ concat: t,

fill: t, // ES-Harmony
filter: t,
filter: j,
find: t, // ES-Harmony
findIndex: t, // ES-Harmony
forEach: t,
forEach: j,
includes: t, // ES-Harmony
indexOf: t,
indexOf: j,
join: t,
keys: t, // ES-Harmony
lastIndexOf: t,
map: t,
pop: t,
push: t,
reduce: t,
reduceRight: t,
lastIndexOf: j,
map: j,
pop: j,
push: j,
reduce: j,
reduceRight: j,
reverse: t,
shift: t,
slice: t,
shift: j,
slice: j,
some: t,
sort: t,
splice: t,
unshift: t,
unshift: j,
values: t, // ES-Harmony

@@ -663,3 +664,3 @@

// TODO: Not yet organized according to spec order
Int8Array: TypedArrayWhitelist,

@@ -680,12 +681,12 @@ Uint8Array: TypedArrayWhitelist,

prototype: {
clear: t,
delete: t,
entries: t,
forEach: t,
get: t,
has: t,
keys: t,
set: t,
clear: j,
delete: j,
entries: j,
forEach: j,
get: j,
has: j,
keys: j,
set: j,
size: 'maybeAccessor',
values: t
values: j
}

@@ -696,21 +697,21 @@ },

prototype: {
add: t,
clear: t,
delete: t,
entries: t,
forEach: t,
has: t,
keys: t,
add: j,
clear: j,
delete: j,
entries: j,
forEach: j,
has: j,
keys: j,
size: 'maybeAccessor',
values: t
values: j
}
},
WeakMap: { // 23.3
prototype: {
// Note: coordinate this list with maintenance of repairES5.js
delete: t,
get: t,
has: t,
set: t
delete: j,
get: j,
has: j,
set: j
}

@@ -721,5 +722,5 @@ },

prototype: {
add: t,
delete: t,
has: t
add: j,
delete: j,
has: j
}

@@ -773,4 +774,4 @@ },

JSON: { // 24.5
parse: t,
stringify: t
parse: j,
stringify: j
},

@@ -782,9 +783,9 @@

Promise: { // 25.4
all: t,
race: t,
reject: t,
resolve: t,
all: j,
race: j,
reject: j,
resolve: j,
prototype: {
catch: t,
then: t,
then: j,
finally: t, // proposed ES-Harmony

@@ -850,3 +851,3 @@

},
Proxy: { // 26.2

@@ -865,3 +866,3 @@ revocable: t

// Other
StringMap: { // A specialized approximation of ES-Harmony's Map.

@@ -868,0 +869,0 @@ prototype: {} // Technically, the methods should be on the prototype,

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc