Skip to content

Instantly share code, notes, and snippets.

@devsnek
Created June 30, 2020 21:42
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save devsnek/45cfb143ecca5861c210de2338444642 to your computer and use it in GitHub Desktop.
Save devsnek/45cfb143ecca5861c210de2338444642 to your computer and use it in GitHub Desktop.
diff --git a/src/intrinsics/ArrayPrototype.mjs b/src/intrinsics/ArrayPrototype.mjs
index f6be4d6..c0f658f 100644
--- a/src/intrinsics/ArrayPrototype.mjs
+++ b/src/intrinsics/ArrayPrototype.mjs
@@ -563,6 +563,7 @@ export function BootstrapArrayPrototype(realmRec) {
);
proto.DefineOwnProperty(wellKnownSymbols.iterator, proto.GetOwnProperty(new Value('values')));
+ proto.DefineOwnProperty(wellKnownSymbols.slice, proto.GetOwnProperty(new Value('slice')));
{
const unscopableList = OrdinaryObjectCreate(Value.null);
diff --git a/src/intrinsics/StringPrototype.mjs b/src/intrinsics/StringPrototype.mjs
index 1d43716..cf3afb7 100644
--- a/src/intrinsics/StringPrototype.mjs
+++ b/src/intrinsics/StringPrototype.mjs
@@ -718,5 +718,7 @@ export function BootstrapStringPrototype(realmRec) {
[wellKnownSymbols.iterator, StringProto_iterator, 0],
]);
+ X(proto.DefineOwnProperty(wellKnownSymbols.slice, proto.GetOwnProperty(new Value('slice'))));
+
realmRec.Intrinsics['%String.prototype%'] = proto;
}
diff --git a/src/parser/ExpressionParser.mjs b/src/parser/ExpressionParser.mjs
index 176289b..4a1b7fe 100644
--- a/src/parser/ExpressionParser.mjs
+++ b/src/parser/ExpressionParser.mjs
@@ -436,9 +436,21 @@ export class ExpressionParser extends FunctionParser {
this.next();
node.MemberExpression = result;
node.IdentifierName = null;
- node.Expression = this.parseExpression();
- result = this.finishNode(node, 'MemberExpression');
+ if (this.eat(Token.COLON)) {
+ node.Expression_b = this.parseAssignmentExpression();
+ } else {
+ const expression = this.parseExpression();
+ if (expression.type !== 'CommaOperator' && this.eat(Token.COLON)) {
+ node.Expression_a = expression;
+ if (!this.test(Token.RBRACK)) {
+ node.Expression_b = this.parseAssignmentExpression();
+ }
+ } else {
+ node.Expression = expression;
+ }
+ }
this.expect(Token.RBRACK);
+ result = this.finishNode(node, 'MemberExpression');
break;
}
case Token.PERIOD:
diff --git a/src/runtime-semantics/MemberExpression.mjs b/src/runtime-semantics/MemberExpression.mjs
index 26c1c1b..857508f 100644
--- a/src/runtime-semantics/MemberExpression.mjs
+++ b/src/runtime-semantics/MemberExpression.mjs
@@ -1,4 +1,10 @@
-import { GetValue } from '../abstract-ops/all.mjs';
+import { Value, wellKnownSymbols } from '../value.mjs';
+import {
+ GetValue,
+ Call,
+ GetMethod,
+ ToObject,
+} from '../abstract-ops/all.mjs';
import { Evaluate } from '../evaluator.mjs';
import { Q } from '../completion.mjs';
import { OutOfRange } from '../helpers.mjs';
@@ -40,12 +46,33 @@ function* Evaluate_MemberExpression_IdentifierName({ strict, MemberExpression, I
// CallExpression :
// CallExpression `[` Expression `]`
// CallExpression `.` IdentifierName
-export function Evaluate_MemberExpression(MemberExpression) {
+export function* Evaluate_MemberExpression(MemberExpression) {
switch (true) {
+ case !!MemberExpression.Expression_a || !!MemberExpression.Expression_b: {
+ const baseReference = yield* Evaluate(MemberExpression.MemberExpression);
+ const baseValue = Q(GetValue(baseReference));
+ let start;
+ if (MemberExpression.Expression_a) {
+ const startRef = yield* Evaluate(MemberExpression.Expression_a);
+ start = Q(GetValue(startRef));
+ } else {
+ start = new Value(0);
+ }
+ let end;
+ if (MemberExpression.Expression_b) {
+ const endRef = yield* Evaluate(MemberExpression.Expression_b);
+ end = Q(GetValue(endRef));
+ } else {
+ end = Value.undefined;
+ }
+ const base = Q(ToObject(baseValue));
+ const method = Q(GetMethod(base, wellKnownSymbols.slice));
+ return Q(Call(method, base, [start, end]));
+ }
case !!MemberExpression.Expression:
- return Evaluate_MemberExpression_Expression(MemberExpression);
+ return yield* Evaluate_MemberExpression_Expression(MemberExpression);
case !!MemberExpression.IdentifierName:
- return Evaluate_MemberExpression_IdentifierName(MemberExpression);
+ return yield* Evaluate_MemberExpression_IdentifierName(MemberExpression);
default:
throw new OutOfRange('Evaluate_MemberExpression', MemberExpression);
}
diff --git a/src/value.mjs b/src/value.mjs
index e06cb63..6d1fffc 100644
--- a/src/value.mjs
+++ b/src/value.mjs
@@ -628,6 +628,7 @@ for (const name of [
'matchAll',
'replace',
'search',
+ 'slice',
'species',
'split',
'toPrimitive',
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment