Skip to content

Instantly share code, notes, and snippets.

@devsnek devsnek/step.diff
Created Jan 27, 2019

Embed
What would you like to do?
diff --git a/.eslintrc.js b/.eslintrc.js
index fee700a..37d2a52 100644
--- a/.eslintrc.js
+++ b/.eslintrc.js
@@ -29,6 +29,8 @@ module.exports = {
'no-restricted-syntax': 'off',
'no-use-before-define': 'off',
'no-continue': 'off',
+ 'no-extra-parens': 'error',
+ 'require-yield': 'off',
'import/no-cycle': 'off',
'import/prefer-default-export': 'off',
'import/no-unresolved': 'off',
diff --git a/bin/engine262.js b/bin/engine262.js
index 31d8bb2..23a94f7 100755
--- a/bin/engine262.js
+++ b/bin/engine262.js
@@ -70,6 +70,18 @@ function createRealm() {
return realm;
}
+function runToCompletion(it) {
+ if (!it.next) {
+ return it;
+ }
+ while (true) {
+ const { done, value } = it.next();
+ if (done) {
+ return value;
+ }
+ }
+}
+
if (process.argv[2]) {
const realm = createRealm();
const source = fs.readFileSync(process.argv[2], 'utf8');
@@ -85,7 +97,7 @@ if (process.argv[2]) {
}
}
} else {
- result = realm.evaluateScript(source);
+ result = runToCompletion(realm.evaluateScript(source));
}
if (result instanceof AbruptCompletion) {
const inspected = inspect(result, realm);
@@ -99,7 +111,7 @@ if (process.argv[2]) {
repl.start({
prompt: '> ',
eval: (cmd, context, filename, callback) => {
- const result = realm.evaluateScript(cmd);
+ const result = runToCompletion(realm.evaluateScript(cmd));
callback(null, result);
},
completer: () => [],
diff --git a/src/abstract-ops/arguments-operations.mjs b/src/abstract-ops/arguments-operations.mjs
index 6bbb73e..f0ec3b8 100644
--- a/src/abstract-ops/arguments-operations.mjs
+++ b/src/abstract-ops/arguments-operations.mjs
@@ -21,11 +21,11 @@ import { X } from '../completion.mjs';
// 9.4.4 #sec-arguments-exotic-objects
// 9.4.4.6 #sec-createunmappedargumentsobject
-export function CreateUnmappedArgumentsObject(argumentsList) {
+export function* CreateUnmappedArgumentsObject(argumentsList) {
const len = argumentsList.length;
const obj = ObjectCreate(surroundingAgent.intrinsic('%ObjectPrototype%'), ['ParameterMap']);
obj.ParameterMap = Value.undefined;
- DefinePropertyOrThrow(obj, new Value('length'), Descriptor({
+ yield* DefinePropertyOrThrow(obj, new Value('length'), Descriptor({
Value: new Value(len),
Writable: Value.true,
Enumerable: Value.false,
@@ -34,17 +34,17 @@ export function CreateUnmappedArgumentsObject(argumentsList) {
let index = 0;
while (index < len) {
const val = argumentsList[index];
- const idxStr = X(ToString(new Value(index)));
- X(CreateDataProperty(obj, idxStr, val));
+ const idxStr = X(yield* ToString(new Value(index)));
+ X(yield* CreateDataProperty(obj, idxStr, val));
index += 1;
}
- X(DefinePropertyOrThrow(obj, wellKnownSymbols.iterator, Descriptor({
+ X(yield* DefinePropertyOrThrow(obj, wellKnownSymbols.iterator, Descriptor({
Value: surroundingAgent.intrinsic('%ArrayProto_values%'),
Writable: Value.true,
Enumerable: Value.false,
Configurable: Value.true,
})));
- X(DefinePropertyOrThrow(obj, new Value('callee'), Descriptor({
+ X(yield* DefinePropertyOrThrow(obj, new Value('callee'), Descriptor({
Get: surroundingAgent.intrinsic('%ThrowTypeError%'),
Set: surroundingAgent.intrinsic('%ThrowTypeError%'),
Enumerable: Value.false,
@@ -53,11 +53,11 @@ export function CreateUnmappedArgumentsObject(argumentsList) {
return obj;
}
-function ArgGetterSteps() {
+function* ArgGetterSteps() {
const f = this;
const name = f.Name;
const env = f.Env;
- return env.GetBindingValue(name, Value.false);
+ return yield* env.GetBindingValue(name, Value.false);
}
// 9.4.4.7.1 #sec-makearggetter
@@ -69,26 +69,26 @@ function MakeArgGetter(name, env) {
return getter;
}
-function ArgSetterSteps([value]) {
+function* ArgSetterSteps([value]) {
Assert(value !== undefined);
const f = this;
const name = f.Name;
const env = f.Env;
- return env.SetMutableBinding(name, value, Value.false);
+ return yield* env.SetMutableBinding(name, value, Value.false);
}
// 9.4.4.7.2 #sec-makeargsetter
-function MakeArgSetter(name, env) {
+function* MakeArgSetter(name, env) {
const steps = ArgSetterSteps;
const setter = CreateBuiltinFunction(steps, ['Name', 'Env']);
- SetFunctionLength(setter, new Value(1));
+ yield* SetFunctionLength(setter, new Value(1));
setter.Name = name;
setter.Env = env;
return setter;
}
// 9.4.4.7 #sec-createmappedargumentsobject
-export function CreateMappedArgumentsObject(func, formals, argumentsList, env) {
+export function* CreateMappedArgumentsObject(func, formals, argumentsList, env) {
// Assert: formals does not contain a rest parameter, any binding
// patterns, or any initializers. It may contain duplicate identifiers.
const len = argumentsList.length;
@@ -102,11 +102,11 @@ export function CreateMappedArgumentsObject(func, formals, argumentsList, env) {
let index = 0;
while (index < len) {
const val = argumentsList[index];
- const idxStr = X(ToString(new Value(index)));
- X(CreateDataProperty(obj, idxStr, val));
+ const idxStr = X(yield* ToString(new Value(index)));
+ X(yield* CreateDataProperty(obj, idxStr, val));
index += 1;
}
- X(DefinePropertyOrThrow(obj, new Value('length'), Descriptor({
+ X(yield* DefinePropertyOrThrow(obj, new Value('length'), Descriptor({
Value: new Value(len),
Writable: Value.true,
Enumerable: Value.false,
@@ -121,7 +121,7 @@ export function CreateMappedArgumentsObject(func, formals, argumentsList, env) {
if (index < len) {
const g = MakeArgGetter(name, env);
const p = MakeArgSetter(name, env);
- X(map.DefineOwnProperty(X(ToString(new Value(index))), Descriptor({
+ X(yield* map.DefineOwnProperty(X(yield* ToString(new Value(index))), Descriptor({
Set: p,
Get: g,
Enumerable: Value.false,
@@ -131,13 +131,13 @@ export function CreateMappedArgumentsObject(func, formals, argumentsList, env) {
}
index -= 1;
}
- X(DefinePropertyOrThrow(obj, wellKnownSymbols.iterator, Descriptor({
+ X(yield* DefinePropertyOrThrow(obj, wellKnownSymbols.iterator, Descriptor({
Value: surroundingAgent.intrinsic('%ArrayProto_values%'),
Writable: Value.true,
Enumerable: Value.false,
Configurable: Value.true,
})));
- X(DefinePropertyOrThrow(obj, new Value('callee'), Descriptor({
+ X(yield* DefinePropertyOrThrow(obj, new Value('callee'), Descriptor({
Value: func,
Writable: Value.true,
Enumerable: Value.false,
diff --git a/src/abstract-ops/array-objects.mjs b/src/abstract-ops/array-objects.mjs
index 58626e4..99b7e95 100644
--- a/src/abstract-ops/array-objects.mjs
+++ b/src/abstract-ops/array-objects.mjs
@@ -34,7 +34,7 @@ import { msg } from '../helpers.mjs';
// 22.1 #sec-array-objects
// 9.4.2.2 #sec-arraycreate
-export function ArrayCreate(length, proto) {
+export function* ArrayCreate(length, proto) {
Assert(length.numberValue() >= 0);
if (Object.is(length.numberValue(), -0)) {
length = new Value(0);
@@ -53,7 +53,7 @@ export function ArrayCreate(length, proto) {
A.Prototype = proto;
A.Extensible = Value.true;
- X(OrdinaryDefineOwnProperty(A, new Value('length'), Descriptor({
+ X(yield* OrdinaryDefineOwnProperty(A, new Value('length'), Descriptor({
Value: length,
Writable: Value.true,
Enumerable: Value.false,
@@ -64,19 +64,19 @@ export function ArrayCreate(length, proto) {
}
// 9.4.2.3 #sec-arrayspeciescreate
-export function ArraySpeciesCreate(originalArray, length) {
+export function* ArraySpeciesCreate(originalArray, length) {
Assert(Type(length) === 'Number' && Number.isInteger(length.numberValue()) && length.numberValue() >= 0);
if (Object.is(length.numberValue(), -0)) {
length = new Value(+0);
}
const isArray = Q(IsArray(originalArray));
if (isArray === Value.false) {
- return Q(ArrayCreate(length));
+ return Q(yield* ArrayCreate(length));
}
- let C = Q(Get(originalArray, new Value('constructor')));
+ let C = Q(yield* Get(originalArray, new Value('constructor')));
if (IsConstructor(C) === Value.true) {
const thisRealm = surroundingAgent.currentRealmRecord;
- const realmC = Q(GetFunctionRealm(C));
+ const realmC = Q(yield* GetFunctionRealm(C));
if (thisRealm !== realmC) {
if (SameValue(C, realmC.Intrinsics['%Array%']) === Value.true) {
C = Value.undefined;
@@ -84,37 +84,37 @@ export function ArraySpeciesCreate(originalArray, length) {
}
}
if (Type(C) === 'Object') {
- C = Q(Get(C, wellKnownSymbols.species));
+ C = Q(yield* Get(C, wellKnownSymbols.species));
if (C === Value.null) {
C = Value.undefined;
}
}
if (C === Value.undefined) {
- return Q(ArrayCreate(length));
+ return Q(yield* ArrayCreate(length));
}
if (IsConstructor(C) === Value.false) {
return surroundingAgent.Throw('TypeError', msg('NotAConstructor', C));
}
- return Q(Construct(C, [length]));
+ return Q(yield* Construct(C, [length]));
}
// 9.4.2.4 #sec-arraysetlength
-export function ArraySetLength(A, Desc) {
+export function* ArraySetLength(A, Desc) {
if (Desc.Value === undefined) {
- return OrdinaryDefineOwnProperty(A, new Value('length'), Desc);
+ return yield* OrdinaryDefineOwnProperty(A, new Value('length'), Desc);
}
const newLenDesc = Descriptor({ ...Desc });
- const newLen = Q(ToUint32(Desc.Value)).numberValue();
- const numberLen = Q(ToNumber(Desc.Value)).numberValue();
+ const newLen = Q(yield* ToUint32(Desc.Value)).numberValue();
+ const numberLen = Q(yield* ToNumber(Desc.Value)).numberValue();
if (newLen !== numberLen) {
return surroundingAgent.Throw('RangeError', 'Invalid array length');
}
newLenDesc.Value = new Value(newLen);
- const oldLenDesc = OrdinaryGetOwnProperty(A, new Value('length'));
+ const oldLenDesc = yield* OrdinaryGetOwnProperty(A, new Value('length'));
Assert(Type(oldLenDesc) !== 'Undefined' && !IsAccessorDescriptor(oldLenDesc));
let oldLen = oldLenDesc.Value.numberValue();
if (newLen >= oldLen) {
- return OrdinaryDefineOwnProperty(A, new Value('length'), newLenDesc);
+ return yield* OrdinaryDefineOwnProperty(A, new Value('length'), newLenDesc);
}
if (oldLenDesc.Writable === Value.false) {
return Value.false;
@@ -126,35 +126,35 @@ export function ArraySetLength(A, Desc) {
newWritable = false;
newLenDesc.Writable = Value.true;
}
- const succeeded = X(OrdinaryDefineOwnProperty(A, new Value('length'), newLenDesc));
+ const succeeded = X(yield* OrdinaryDefineOwnProperty(A, new Value('length'), newLenDesc));
if (succeeded === Value.false) {
return Value.false;
}
while (newLen < oldLen) {
oldLen -= 1;
- const idxToDelete = X(ToString(new Value(oldLen)));
- const deleteSucceeded = X(A.Delete(idxToDelete));
+ const idxToDelete = X(yield* ToString(new Value(oldLen)));
+ const deleteSucceeded = X(yield* A.Delete(idxToDelete));
if (deleteSucceeded === Value.false) {
newLenDesc.Value = new Value(oldLen + 1);
if (newWritable === false) {
newLenDesc.Writable = Value.false;
}
- X(OrdinaryDefineOwnProperty(A, new Value('length'), newLenDesc));
+ X(yield* OrdinaryDefineOwnProperty(A, new Value('length'), newLenDesc));
return Value.false;
}
}
if (newWritable === false) {
- OrdinaryDefineOwnProperty(A, new Value('length'), Descriptor({ Writable: Value.false }));
+ yield* OrdinaryDefineOwnProperty(A, new Value('length'), Descriptor({ Writable: Value.false }));
}
return Value.true;
}
// 22.1.3.1.1 #sec-isconcatspreadable
-export function IsConcatSpreadable(O) {
+export function* IsConcatSpreadable(O) {
if (Type(O) !== 'Object') {
return Value.false;
}
- const spreadable = Q(Get(O, wellKnownSymbols.isConcatSpreadable));
+ const spreadable = Q(yield* Get(O, wellKnownSymbols.isConcatSpreadable));
if (spreadable !== Value.undefined) {
return ToBoolean(spreadable);
}
@@ -162,7 +162,7 @@ export function IsConcatSpreadable(O) {
}
// 22.1.3.25.1 #sec-sortcompare
-export function SortCompare(x, y, comparefn) {
+export function* SortCompare(x, y, comparefn) {
if (x === Value.undefined && y === Value.undefined) {
return new Value(+0);
}
@@ -173,20 +173,20 @@ export function SortCompare(x, y, comparefn) {
return new Value(-1);
}
if (comparefn !== Value.undefined) {
- const callRes = Q(Call(comparefn, Value.undefined, [x, y]));
- const v = Q(ToNumber(callRes));
+ const callRes = Q(yield* Call(comparefn, Value.undefined, [x, y]));
+ const v = Q(yield* ToNumber(callRes));
if (v.isNaN()) {
return new Value(+0);
}
return v;
}
- const xString = Q(ToString(x));
- const yString = Q(ToString(y));
- const xSmaller = AbstractRelationalComparison(xString, yString);
+ const xString = Q(yield* ToString(x));
+ const yString = Q(yield* ToString(y));
+ const xSmaller = yield* AbstractRelationalComparison(xString, yString);
if (xSmaller === Value.true) {
return new Value(-1);
}
- const ySmaller = AbstractRelationalComparison(yString, xString);
+ const ySmaller = yield* AbstractRelationalComparison(yString, xString);
if (ySmaller === Value.true) {
return new Value(1);
}
diff --git a/src/abstract-ops/arraybuffer-objects.mjs b/src/abstract-ops/arraybuffer-objects.mjs
index d02dddc..36340dc 100644
--- a/src/abstract-ops/arraybuffer-objects.mjs
+++ b/src/abstract-ops/arraybuffer-objects.mjs
@@ -2,8 +2,8 @@ import {
Assert,
CreateByteDataBlock,
CopyDataBlockBytes,
- IsConstructor,
OrdinaryCreateFromConstructor,
+ IsConstructor,
SameValue,
numericTypeInfo,
} from './all.mjs';
@@ -18,8 +18,12 @@ import { Value, Type } from '../value.mjs';
// 24.2 #sec-sharedarraybuffer-objects
// 24.1.1.1 #sec-allocatearraybuffer
-export function AllocateArrayBuffer(constructor, byteLength) {
- const obj = Q(OrdinaryCreateFromConstructor(constructor, '%ArrayBufferPrototype%', ['ArrayBufferData', 'ArrayBufferByteLength', 'ArrayBufferDetachKey']));
+export function* AllocateArrayBuffer(constructor, byteLength) {
+ const obj = Q(yield* OrdinaryCreateFromConstructor(
+ constructor,
+ '%ArrayBufferPrototype%',
+ ['ArrayBufferData', 'ArrayBufferByteLength', 'ArrayBufferDetachKey'],
+ ));
Assert(byteLength.numberValue() >= 0);
Assert(Number.isInteger(byteLength.numberValue()));
const block = Q(CreateByteDataBlock(byteLength));
@@ -38,7 +42,7 @@ export function IsDetachedBuffer(arrayBuffer) {
}
// 24.1.1.3 #sec-detacharraybuffer
-export function DetachArrayBuffer(arrayBuffer, key) {
+export function* DetachArrayBuffer(arrayBuffer, key) {
Assert(Type(arrayBuffer) === 'Object' && 'ArrayBufferData' in arrayBuffer && 'ArrayBufferByteLength' in arrayBuffer && 'ArrayBufferDetachKey' in arrayBuffer);
Assert(IsSharedArrayBuffer(arrayBuffer) === Value.false);
if (key === undefined) {
@@ -53,16 +57,16 @@ export function DetachArrayBuffer(arrayBuffer, key) {
}
// 24.1.1.4 #sec-clonearraybuffer
-export function CloneArrayBuffer(srcBuffer, srcByteOffset, srcLength, cloneConstructor) {
+export function* CloneArrayBuffer(srcBuffer, srcByteOffset, srcLength, cloneConstructor) {
Assert(Type(srcBuffer) === 'Object' && 'ArrayBufferData' in srcBuffer);
Assert(IsConstructor(cloneConstructor) === Value.true);
- const targetBuffer = Q(AllocateArrayBuffer(cloneConstructor, srcLength));
+ const targetBuffer = Q(yield* AllocateArrayBuffer(cloneConstructor, srcLength));
if (IsDetachedBuffer(srcBuffer)) {
return surroundingAgent.Throw('TypeError', msg('BufferDetached'));
}
const srcBlock = srcBuffer.ArrayBufferData;
const targetBlock = targetBuffer.ArrayBufferData;
- CopyDataBlockBytes(targetBlock, new Value(0), srcBlock, srcByteOffset, srcLength);
+ yield* CopyDataBlockBytes(targetBlock, new Value(0), srcBlock, srcByteOffset, srcLength);
return targetBuffer;
}
@@ -110,7 +114,7 @@ const float64NaNLE = Object.freeze([0, 0, 0, 0, 0, 0, 248, 127]);
const float64NaNBE = Object.freeze([127, 248, 0, 0, 0, 0, 0, 0]);
// 24.1.1.7 #sec-numbertorawbytes
-export function NumberToRawBytes(type, value, isLittleEndian) {
+export function* NumberToRawBytes(type, value, isLittleEndian) {
Assert(Type(isLittleEndian) === 'Boolean');
isLittleEndian = isLittleEndian === Value.true;
let rawBytes;
@@ -133,7 +137,7 @@ export function NumberToRawBytes(type, value, isLittleEndian) {
const info = numericTypeInfo.get(type);
const n = info.ElementSize;
const convOp = info.ConversionOperation;
- const intValue = X(convOp(value)).numberValue();
+ const intValue = X(yield* convOp(value)).numberValue();
const dataViewType = type === 'Uint8C' ? 'Uint8' : type;
throwawayDataView[`set${dataViewType}`](0, intValue, isLittleEndian);
rawBytes = [...throwawayArray.subarray(0, n)];
@@ -142,7 +146,7 @@ export function NumberToRawBytes(type, value, isLittleEndian) {
}
// 24.1.1.8 #sec-setvalueinbuffer
-export function SetValueInBuffer(arrayBuffer, byteIndex, type, value, isTypedArray, order, isLittleEndian) {
+export function* SetValueInBuffer(arrayBuffer, byteIndex, type, value, isTypedArray, order, isLittleEndian) {
byteIndex = byteIndex.numberValue();
Assert(!IsDetachedBuffer(arrayBuffer));
const info = numericTypeInfo.get(type);
@@ -155,7 +159,7 @@ export function SetValueInBuffer(arrayBuffer, byteIndex, type, value, isTypedArr
if (isLittleEndian === undefined) {
isLittleEndian = surroundingAgent.LittleEndian;
}
- const rawBytes = NumberToRawBytes(type, value, isLittleEndian);
+ const rawBytes = yield* NumberToRawBytes(type, value, isLittleEndian);
// if (IsSharedArrayBuffer(arrayBuffer) === Value.true) {
//
// } else {
diff --git a/src/abstract-ops/async-function-operations.mjs b/src/abstract-ops/async-function-operations.mjs
index 2d764a5..1f1a30e 100644
--- a/src/abstract-ops/async-function-operations.mjs
+++ b/src/abstract-ops/async-function-operations.mjs
@@ -10,7 +10,7 @@ import { resume } from '../helpers.mjs';
// 25.7 #sec-async-function-objects
// 25.7.5.1 #sec-async-functions-abstract-operations-async-function-start
-export function AsyncFunctionStart(promiseCapability, asyncFunctionBody, isExpression) {
+export function* AsyncFunctionStart(promiseCapability, asyncFunctionBody, isExpression) {
const runningContext = surroundingAgent.runningExecutionContext;
const asyncContext = runningContext.copy();
asyncContext.codeEvaluationState = (function* resumer() {
@@ -20,13 +20,13 @@ export function AsyncFunctionStart(promiseCapability, asyncFunctionBody, isExpre
surroundingAgent.executionContextStack.pop(asyncContext);
// https://github.com/tc39/ecma262/pull/1406
if (result.Type === 'throw') {
- X(Call(promiseCapability.Reject, Value.undefined, [result.Value]));
+ X(yield* Call(promiseCapability.Reject, Value.undefined, [result.Value]));
} else if (result.Type === 'normal' && isExpression === false) {
- X(Call(promiseCapability.Resolve, Value.undefined, [Value.undefined]));
+ X(yield* Call(promiseCapability.Resolve, Value.undefined, [Value.undefined]));
} else {
Assert(result.Type === (isExpression ? 'normal' : 'return'));
Assert(result.Value !== undefined);
- X(Call(promiseCapability.Resolve, Value.undefined, [result.Value]));
+ X(yield* Call(promiseCapability.Resolve, Value.undefined, [result.Value]));
}
return Value.undefined;
}());
diff --git a/src/abstract-ops/async-generator-objects.mjs b/src/abstract-ops/async-generator-objects.mjs
index 24e31b9..1cb5126 100644
--- a/src/abstract-ops/async-generator-objects.mjs
+++ b/src/abstract-ops/async-generator-objects.mjs
@@ -48,10 +48,10 @@ export function AsyncGeneratorStart(generator, generatorBody) {
} else {
resultValue = result.Value;
if (result.Type !== 'return') {
- return X(AsyncGeneratorReject(generator, resultValue));
+ return X(yield* AsyncGeneratorReject(generator, resultValue));
}
}
- return X(AsyncGeneratorResolve(generator, resultValue, Value.true));
+ return X(yield* AsyncGeneratorResolve(generator, resultValue, Value.true));
}());
generator.AsyncGeneratorContext = genContext;
generator.AsyncGeneratorState = 'suspendedStart';
@@ -60,46 +60,46 @@ export function AsyncGeneratorStart(generator, generatorBody) {
}
// 25.5.3.3 #sec-asyncgeneratorresolve
-function AsyncGeneratorResolve(generator, value, done) {
+function* AsyncGeneratorResolve(generator, value, done) {
// Assert: generator is an AsyncGenerator instance.
const queue = generator.AsyncGeneratorQueue;
Assert(queue.length > 0);
const next = queue.shift();
const promiseCapability = next.Capability;
- const iteratorResult = X(CreateIterResultObject(value, done));
- X(Call(promiseCapability.Resolve, Value.undefined, [iteratorResult]));
- X(AsyncGeneratorResumeNext(generator));
+ const iteratorResult = X(yield* CreateIterResultObject(value, done));
+ X(yield* Call(promiseCapability.Resolve, Value.undefined, [iteratorResult]));
+ X(yield* AsyncGeneratorResumeNext(generator));
return Value.undefined;
}
// 25.5.3.4 #sec-asyncgeneratorreject
-function AsyncGeneratorReject(generator, exception) {
+function* AsyncGeneratorReject(generator, exception) {
// Assert: generator is an AsyncGenerator instance.
const queue = generator.AsyncGeneratorQueue;
Assert(queue.length > 0);
const next = queue.shift();
const promiseCapability = next.Capability;
- X(Call(promiseCapability.Reject, Value.undefined, [exception]));
- X(AsyncGeneratorResumeNext(generator));
+ X(yield* Call(promiseCapability.Reject, Value.undefined, [exception]));
+ X(yield* AsyncGeneratorResumeNext(generator));
return Value.undefined;
}
// 25.5.3.5.1 #async-generator-resume-next-return-processor-fulfilled
-function AsyncGeneratorResumeNextReturnProcessorFulfilledFunctions([value = Value.undefined]) {
+function* AsyncGeneratorResumeNextReturnProcessorFulfilledFunctions([value = Value.undefined]) {
const F = surroundingAgent.activeFunctionObject;
F.Generator.AsyncGeneratorState = 'completed';
- return X(AsyncGeneratorResolve(F.Generator, value, Value.true));
+ return X(yield* AsyncGeneratorResolve(F.Generator, value, Value.true));
}
// 25.5.3.5.2 #async-generator-resume-next-return-processor-rejected
-function AsyncGeneratorResumeNextReturnProcessorRejectedFunctions([reason = Value.undefined]) {
+function* AsyncGeneratorResumeNextReturnProcessorRejectedFunctions([reason = Value.undefined]) {
const F = surroundingAgent.activeFunctionObject;
F.Generator.AsyncGeneratorState = 'completed';
- return X(AsyncGeneratorReject(F.Generator, reason));
+ return X(yield* AsyncGeneratorReject(F.Generator, reason));
}
// 25.5.3.5 #sec-asyncgeneratorresumenext
-function AsyncGeneratorResumeNext(generator) {
+function* AsyncGeneratorResumeNext(generator) {
// Assert: generator is an AsyncGenerator instance.
let state = generator.AsyncGeneratorState;
Assert(state !== 'executing');
@@ -121,19 +121,19 @@ function AsyncGeneratorResumeNext(generator) {
if (state === 'completed') {
if (completion.Type === 'return') {
generator.AsyncGeneratorState = 'awaiting-return';
- const promiseCapability = X(NewPromiseCapability(surroundingAgent.intrinsic('%Promise%')));
- X(Call(promiseCapability.Resolve, Value.undefined, [completion.Value]));
+ const promiseCapability = X(yield* NewPromiseCapability(surroundingAgent.intrinsic('%Promise%')));
+ X(yield* Call(promiseCapability.Resolve, Value.undefined, [completion.Value]));
const stepsFulfilled = AsyncGeneratorResumeNextReturnProcessorFulfilledFunctions;
const onFulfilled = CreateBuiltinFunction(stepsFulfilled, ['Generator']);
onFulfilled.Generator = generator;
const stepsRejected = AsyncGeneratorResumeNextReturnProcessorRejectedFunctions;
const onRejected = CreateBuiltinFunction(stepsRejected, ['Generator']);
onRejected.Generator = generator;
- X(PerformPromiseThen(promiseCapability.Promise, onFulfilled, onRejected));
+ X(yield* PerformPromiseThen(promiseCapability.Promise, onFulfilled, onRejected));
return Value.undefined;
} else {
Assert(completion.Type === 'throw');
- X(AsyncGeneratorReject(generator, completion.Value));
+ X(yield* AsyncGeneratorReject(generator, completion.Value));
return Value.undefined;
}
}
@@ -153,12 +153,12 @@ function AsyncGeneratorResumeNext(generator) {
}
// 25.5.3.6 #sec-asyncgeneratorenqueue
-export function AsyncGeneratorEnqueue(generator, completion) {
+export function* AsyncGeneratorEnqueue(generator, completion) {
Assert(completion instanceof Completion);
- const promiseCapability = X(NewPromiseCapability(surroundingAgent.intrinsic('%Promise%')));
+ const promiseCapability = X(yield* NewPromiseCapability(surroundingAgent.intrinsic('%Promise%')));
if (Type(generator) !== 'Object' || !('AsyncGeneratorState' in generator)) {
const badGeneratorError = surroundingAgent.Throw('TypeError', msg('NotAnTypeObject', 'AsyncGenerator', generator)).Value;
- X(Call(promiseCapability.Reject, Value.undefined, [badGeneratorError]));
+ X(yield* Call(promiseCapability.Reject, Value.undefined, [badGeneratorError]));
return promiseCapability.Promise;
}
const queue = generator.AsyncGeneratorQueue;
@@ -166,7 +166,7 @@ export function AsyncGeneratorEnqueue(generator, completion) {
queue.push(request);
const state = generator.AsyncGeneratorState;
if (state !== 'executing') {
- X(AsyncGeneratorResumeNext(generator));
+ X(yield* AsyncGeneratorResumeNext(generator));
}
return promiseCapability.Promise;
}
diff --git a/src/abstract-ops/dataview-objects.mjs b/src/abstract-ops/dataview-objects.mjs
index 269d860..71bed06 100644
--- a/src/abstract-ops/dataview-objects.mjs
+++ b/src/abstract-ops/dataview-objects.mjs
@@ -17,12 +17,12 @@ import { Type, Value } from '../value.mjs';
// 24.3 #sec-dataview-objects
// 24.3.1.1 #sec-getviewvalue
-export function GetViewValue(view, requestIndex, isLittleEndian, type) {
+export function* GetViewValue(view, requestIndex, isLittleEndian, type) {
if (Type(view) !== 'Object' || !('DataView' in view)) {
return surroundingAgent.Throw('TypeError', msg('NotATypeObject', 'DataView', view));
}
Assert('ViewedArrayBuffer' in view);
- const getIndex = Q(ToIndex(requestIndex)).numberValue();
+ const getIndex = Q(yield* ToIndex(requestIndex)).numberValue();
isLittleEndian = X(ToBoolean(isLittleEndian));
const buffer = view.ViewedArrayBuffer;
if (IsDetachedBuffer(buffer)) {
@@ -39,13 +39,13 @@ export function GetViewValue(view, requestIndex, isLittleEndian, type) {
}
// 24.3.1.2 #sec-setviewvalue
-export function SetViewValue(view, requestIndex, isLittleEndian, type, value) {
+export function* SetViewValue(view, requestIndex, isLittleEndian, type, value) {
if (Type(view) !== 'Object' || !('DataView' in view)) {
return surroundingAgent.Throw('TypeError', msg('NotATypeObject', 'DataView', view));
}
Assert('ViewedArrayBuffer' in view);
- const getIndex = Q(ToIndex(requestIndex)).numberValue();
- const numberValue = Q(ToNumber(value));
+ const getIndex = Q(yield* ToIndex(requestIndex)).numberValue();
+ const numberValue = Q(yield* ToNumber(value));
isLittleEndian = X(ToBoolean(isLittleEndian));
const buffer = view.ViewedArrayBuffer;
if (IsDetachedBuffer(buffer)) {
@@ -58,5 +58,5 @@ export function SetViewValue(view, requestIndex, isLittleEndian, type, value) {
return surroundingAgent.Throw('RangeError', msg('DataViewOOB'));
}
const bufferIndex = new Value(getIndex + viewOffset);
- return SetValueInBuffer(buffer, bufferIndex, type, numberValue, false, 'Unordered', isLittleEndian);
+ return yield* SetValueInBuffer(buffer, bufferIndex, type, numberValue, false, 'Unordered', isLittleEndian);
}
diff --git a/src/abstract-ops/date-objects.mjs b/src/abstract-ops/date-objects.mjs
index f8d94c7..bd8191e 100644
--- a/src/abstract-ops/date-objects.mjs
+++ b/src/abstract-ops/date-objects.mjs
@@ -185,14 +185,14 @@ export const msPerMinute = msPerSecond * SecondsPerMinute;
export const msPerHour = msPerMinute * MinutesPerHour;
// 20.3.1.11 #sec-maketime
-export function MakeTime(hour, min, sec, ms) {
+export function* MakeTime(hour, min, sec, ms) {
if (!Number.isFinite(hour.numberValue()) || !Number.isFinite(min.numberValue()) || !Number.isFinite(sec.numberValue()) || !Number.isFinite(ms.numberValue())) {
return new Value(NaN);
}
- const h = X(ToInteger(hour)).numberValue();
- const m = X(ToInteger(min)).numberValue();
- const s = X(ToInteger(sec)).numberValue();
- const milli = X(ToInteger(ms)).numberValue();
+ const h = X(yield* ToInteger(hour)).numberValue();
+ const m = X(yield* ToInteger(min)).numberValue();
+ const s = X(yield* ToInteger(sec)).numberValue();
+ const milli = X(yield* ToInteger(ms)).numberValue();
const t = h * msPerHour + m * msPerMinute + s * msPerSecond + milli;
return new Value(t);
}
@@ -200,13 +200,13 @@ export function MakeTime(hour, min, sec, ms) {
const daysWithinYearToEndOfMonth = [0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365];
// 20.3.1.12 #sec-makeday
-export function MakeDay(year, month, date) {
+export function* MakeDay(year, month, date) {
if (!Number.isFinite(year.numberValue()) || !Number.isFinite(month.numberValue()) || !Number.isFinite(date.numberValue())) {
return new Value(NaN);
}
- const y = X(ToInteger(year)).numberValue();
- const m = X(ToInteger(month)).numberValue();
- const dt = X(ToInteger(date)).numberValue();
+ const y = X(yield* ToInteger(year)).numberValue();
+ const m = X(yield* ToInteger(month)).numberValue();
+ const dt = X(yield* ToInteger(date)).numberValue();
const ym = y + Math.floor(m / 12);
const mn = mod(m, 12);
const ymday = DayFromYear(new Value(ym + (mn > 1 ? 1 : 0))).numberValue() - 365 * (mn > 1 ? 1 : 0) + daysWithinYearToEndOfMonth[mn];
@@ -223,14 +223,14 @@ export function MakeDate(day, time) {
}
// 20.3.1.14 #sec-timeclip
-export function TimeClip(time) {
+export function* TimeClip(time) {
if (!Number.isFinite(time.numberValue())) {
return new Value(NaN);
}
if (Math.abs(time.numberValue()) > 8.64e15) {
return new Value(NaN);
}
- let clippedTime = X(ToInteger(time)).numberValue();
+ let clippedTime = X(yield* ToInteger(time)).numberValue();
if (Object.is(clippedTime, -0)) {
clippedTime = 0;
}
diff --git a/src/abstract-ops/function-operations.mjs b/src/abstract-ops/function-operations.mjs
index 5b89b87..df59fad 100644
--- a/src/abstract-ops/function-operations.mjs
+++ b/src/abstract-ops/function-operations.mjs
@@ -46,7 +46,7 @@ import {
GlobalEnvironmentRecord,
NewFunctionEnvironment,
} from '../environment.mjs';
-import { unwind, OutOfRange } from '../helpers.mjs';
+import { OutOfRange } from '../helpers.mjs';
// This file covers abstract operations defined in
// 9.2 #sec-ecmascript-function-objects
@@ -72,7 +72,7 @@ function PrepareForOrdinaryCall(F, newTarget) {
}
// 9.2.1.2 #sec-ordinarycallbindthis
-function OrdinaryCallBindThis(F, calleeContext, thisArgument) {
+function* OrdinaryCallBindThis(F, calleeContext, thisArgument) {
const thisMode = F.ThisMode;
if (thisMode === 'lexical') {
return new NormalCompletion(Value.undefined);
@@ -89,7 +89,7 @@ function OrdinaryCallBindThis(F, calleeContext, thisArgument) {
Assert(globalEnvRec instanceof GlobalEnvironmentRecord);
thisValue = globalEnvRec.GlobalThisValue;
} else {
- thisValue = X(ToObject(thisArgument));
+ thisValue = X(yield* ToObject(thisArgument));
// NOTE: ToObject produces wrapper objects using calleeRealm.
}
}
@@ -131,7 +131,7 @@ export function* OrdinaryCallEvaluateBody(F, argumentsList) {
}
// 9.2.1 #sec-ecmascript-function-objects-call-thisargument-argumentslist
-function FunctionCallSlot(thisArgument, argumentsList) {
+function* FunctionCallSlot(thisArgument, argumentsList) {
const F = this;
Assert(F instanceof FunctionValue);
@@ -141,8 +141,8 @@ function FunctionCallSlot(thisArgument, argumentsList) {
// const callerContext = surroundingAgent.runningExecutionContext;
const calleeContext = PrepareForOrdinaryCall(F, Value.undefined);
Assert(surroundingAgent.runningExecutionContext === calleeContext);
- OrdinaryCallBindThis(F, calleeContext, thisArgument);
- const result = EnsureCompletion(unwind(OrdinaryCallEvaluateBody(F, argumentsList)));
+ yield* OrdinaryCallBindThis(F, calleeContext, thisArgument);
+ const result = EnsureCompletion(yield* OrdinaryCallEvaluateBody(F, argumentsList));
// Remove calleeContext from the execution context stack and
// restore callerContext as the running execution context.
surroundingAgent.executionContextStack.pop(calleeContext);
@@ -154,7 +154,7 @@ function FunctionCallSlot(thisArgument, argumentsList) {
}
// 9.2.2 #sec-ecmascript-function-objects-construct-argumentslist-newtarget
-function FunctionConstructSlot(argumentsList, newTarget) {
+function* FunctionConstructSlot(argumentsList, newTarget) {
const F = this;
Assert(F instanceof FunctionValue);
@@ -163,16 +163,16 @@ function FunctionConstructSlot(argumentsList, newTarget) {
const kind = F.ConstructorKind;
let thisArgument;
if (kind === 'base') {
- thisArgument = Q(OrdinaryCreateFromConstructor(newTarget, '%ObjectPrototype%'));
+ thisArgument = Q(yield* OrdinaryCreateFromConstructor(newTarget, '%ObjectPrototype%'));
}
const calleeContext = PrepareForOrdinaryCall(F, newTarget);
Assert(surroundingAgent.runningExecutionContext === calleeContext);
if (kind === 'base') {
- OrdinaryCallBindThis(F, calleeContext, thisArgument);
+ yield* OrdinaryCallBindThis(F, calleeContext, thisArgument);
}
const constructorEnv = calleeContext.LexicalEnvironment;
const envRec = constructorEnv.EnvironmentRecord;
- const result = EnsureCompletion(unwind(OrdinaryCallEvaluateBody(F, argumentsList)));
+ const result = EnsureCompletion(yield* OrdinaryCallEvaluateBody(F, argumentsList));
// Remove calleeContext from the execution context stack and
// restore callerContext as the running execution context.
surroundingAgent.executionContextStack.pop(calleeContext);
@@ -233,7 +233,7 @@ export function FunctionAllocate(functionPrototype, strict, functionKind) {
}
// 9.2.4 #sec-functioninitialize
-export function FunctionInitialize(F, kind, ParameterList, Body, Scope) {
+export function* FunctionInitialize(F, kind, ParameterList, Body, Scope) {
let len;
switch (kind) {
case 'Normal':
@@ -248,7 +248,7 @@ export function FunctionInitialize(F, kind, ParameterList, Body, Scope) {
default:
throw new OutOfRange('FunctionInitialize kind', kind);
}
- X(SetFunctionLength(F, new Value(len)));
+ X(yield* SetFunctionLength(F, new Value(len)));
const Strict = F.Strict;
F.Environment = Scope;
F.FormalParameters = ParameterList;
@@ -268,54 +268,54 @@ export function FunctionInitialize(F, kind, ParameterList, Body, Scope) {
// Instead of taking in a {Async}Function/Concise/GeneratorBody for Body, we
// instead take in the entire function node as Body and save it in
// ECMAScriptCode as such.
-export function FunctionCreate(kind, ParameterList, Body, Scope, Strict, prototype) {
+export function* FunctionCreate(kind, ParameterList, Body, Scope, Strict, prototype) {
if (prototype === undefined) {
prototype = surroundingAgent.intrinsic('%FunctionPrototype%');
}
const allocKind = kind === 'Normal' ? 'normal' : 'non-constructor';
const F = FunctionAllocate(prototype, Strict, allocKind);
- return FunctionInitialize(F, kind, ParameterList, Body, Scope);
+ return yield* FunctionInitialize(F, kind, ParameterList, Body, Scope);
}
// 9.2.6 #sec-generatorfunctioncreate
-export function GeneratorFunctionCreate(kind, ParameterList, Body, Scope, Strict) {
+export function* GeneratorFunctionCreate(kind, ParameterList, Body, Scope, Strict) {
const functionPrototype = surroundingAgent.intrinsic('%Generator%');
const F = FunctionAllocate(functionPrototype, Strict, 'generator');
- return FunctionInitialize(F, kind, ParameterList, Body, Scope);
+ return yield* FunctionInitialize(F, kind, ParameterList, Body, Scope);
}
// 9.2.7 #sec-asyncgeneratorfunctioncreate
-export function AsyncGeneratorFunctionCreate(kind, ParameterList, Body, Scope, Strict) {
+export function* AsyncGeneratorFunctionCreate(kind, ParameterList, Body, Scope, Strict) {
const functionPrototype = surroundingAgent.intrinsic('%AsyncGenerator%');
const F = X(FunctionAllocate(functionPrototype, Strict, 'generator'));
- return X(FunctionInitialize(F, kind, ParameterList, Body, Scope));
+ return X(yield* FunctionInitialize(F, kind, ParameterList, Body, Scope));
}
// 9.2.8 #sec-async-functions-abstract-operations-async-function-create
-export function AsyncFunctionCreate(kind, parameters, body, Scope, Strict) {
+export function* AsyncFunctionCreate(kind, parameters, body, Scope, Strict) {
const functionPrototype = surroundingAgent.intrinsic('%AsyncFunctionPrototype%');
const F = X(FunctionAllocate(functionPrototype, Strict, 'async'));
- return X(FunctionInitialize(F, kind, parameters, body, Scope));
+ return X(yield* FunctionInitialize(F, kind, parameters, body, Scope));
}
// 9.2.10 #sec-makeconstructor
-export function MakeConstructor(F, writablePrototype, prototype) {
+export function* MakeConstructor(F, writablePrototype, prototype) {
Assert(F instanceof FunctionValue);
Assert(IsConstructor(F) === Value.true);
- Assert(X(IsExtensible(F)) === Value.true && X(HasOwnProperty(F, new Value('prototype'))) === Value.false);
+ Assert(X(yield* IsExtensible(F)) === Value.true && X(yield* HasOwnProperty(F, new Value('prototype'))) === Value.false);
if (writablePrototype === undefined) {
writablePrototype = true;
}
if (prototype === undefined) {
prototype = ObjectCreate(surroundingAgent.intrinsic('%ObjectPrototype%'));
- X(DefinePropertyOrThrow(prototype, new Value('constructor'), Descriptor({
+ X(yield* DefinePropertyOrThrow(prototype, new Value('constructor'), Descriptor({
Value: F,
Writable: writablePrototype ? Value.true : Value.false,
Enumerable: Value.false,
Configurable: Value.true,
})));
}
- X(DefinePropertyOrThrow(F, new Value('prototype'), Descriptor({
+ X(yield* DefinePropertyOrThrow(F, new Value('prototype'), Descriptor({
Value: prototype,
Writable: writablePrototype ? Value.true : Value.false,
Enumerable: Value.false,
@@ -341,8 +341,8 @@ export function MakeMethod(F, homeObject) {
}
// 9.2.13 #sec-setfunctionname
-export function SetFunctionName(F, name, prefix) {
- Assert(IsExtensible(F) === Value.true && HasOwnProperty(F, new Value('name')) === Value.false);
+export function* SetFunctionName(F, name, prefix) {
+ Assert((yield* IsExtensible(F)) === Value.true && (yield* HasOwnProperty(F, new Value('name'))) === Value.false);
Assert(Type(name) === 'Symbol' || Type(name) === 'String');
Assert(!prefix || Type(prefix) === 'String');
if (Type(name) === 'Symbol') {
@@ -356,7 +356,7 @@ export function SetFunctionName(F, name, prefix) {
if (prefix !== undefined) {
name = new Value(`${prefix.stringValue()} ${name.stringValue()}`);
}
- return X(DefinePropertyOrThrow(F, new Value('name'), Descriptor({
+ return X(yield* DefinePropertyOrThrow(F, new Value('name'), Descriptor({
Value: name,
Writable: Value.false,
Enumerable: Value.false,
@@ -365,11 +365,11 @@ export function SetFunctionName(F, name, prefix) {
}
// 9.2.14 #sec-setfunctionlength
-export function SetFunctionLength(F, length) {
- Assert(IsExtensible(F) === Value.true && HasOwnProperty(F, new Value('length')) === Value.false);
+export function* SetFunctionLength(F, length) {
+ Assert((yield* IsExtensible(F)) === Value.true && (yield* HasOwnProperty(F, new Value('length'))) === Value.false);
Assert(Type(length) === 'Number');
- Assert(length.numberValue() >= 0 && X(ToInteger(length)).numberValue() === length.numberValue());
- return X(DefinePropertyOrThrow(F, new Value('length'), Descriptor({
+ Assert(length.numberValue() >= 0 && X(yield* ToInteger(length)).numberValue() === length.numberValue());
+ return X(yield* DefinePropertyOrThrow(F, new Value('length'), Descriptor({
Value: length,
Writable: Value.false,
Enumerable: Value.false,
diff --git a/src/abstract-ops/generator-operations.mjs b/src/abstract-ops/generator-operations.mjs
index c5bac8b..6720c9b 100644
--- a/src/abstract-ops/generator-operations.mjs
+++ b/src/abstract-ops/generator-operations.mjs
@@ -36,7 +36,7 @@ export function GeneratorStart(generator, generatorBody) {
Assert(result.Type === 'throw');
return Completion(result);
}
- return X(CreateIterResultObject(resultValue, Value.true));
+ return X(yield* CreateIterResultObject(resultValue, Value.true));
}());
generator.GeneratorContext = genContext;
generator.GeneratorState = 'suspendedStart';
@@ -60,10 +60,10 @@ export function GeneratorValidate(generator) {
}
// 25.4.3.3 #sec-generatorresume
-export function GeneratorResume(generator, value) {
- const state = Q(GeneratorValidate(generator));
+export function* GeneratorResume(generator, value) {
+ const state = Q(yield* GeneratorValidate(generator));
if (state === 'completed') {
- return X(CreateIterResultObject(Value.undefined, Value.true));
+ return X(yield* CreateIterResultObject(Value.undefined, Value.true));
}
Assert(state === 'suspendedStart' || state === 'suspendedYield');
const genContext = generator.GeneratorContext;
@@ -79,9 +79,9 @@ export function GeneratorResume(generator, value) {
}
// 25.4.3.4 #sec-generatorresumeabrupt
-export function GeneratorResumeAbrupt(generator, abruptCompletion) {
+export function* GeneratorResumeAbrupt(generator, abruptCompletion) {
Assert(abruptCompletion instanceof AbruptCompletion);
- let state = Q(GeneratorValidate(generator));
+ let state = Q(yield* GeneratorValidate(generator));
if (state === 'suspendedStart') {
generator.GeneratorState = 'completed';
generator.GeneratorContext = null;
@@ -89,7 +89,7 @@ export function GeneratorResumeAbrupt(generator, abruptCompletion) {
}
if (state === 'completed') {
if (abruptCompletion.Type === 'return') {
- return X(CreateIterResultObject(abruptCompletion.Value, Value.true));
+ return X(yield* CreateIterResultObject(abruptCompletion.Value, Value.true));
}
return Completion(abruptCompletion);
}
diff --git a/src/abstract-ops/iterator-operations.mjs b/src/abstract-ops/iterator-operations.mjs
index 30038ae..4dbf339 100644
--- a/src/abstract-ops/iterator-operations.mjs
+++ b/src/abstract-ops/iterator-operations.mjs
@@ -31,29 +31,29 @@ import {
// 25.1 #sec-iteration
// 7.4.1 #sec-getiterator
-export function GetIterator(obj, hint, method) {
+export function* GetIterator(obj, hint, method) {
if (!hint) {
hint = 'sync';
}
Assert(hint === 'sync' || hint === 'async');
if (!method) {
if (hint === 'async') {
- method = Q(GetMethod(obj, wellKnownSymbols.asyncIterator));
+ method = Q(yield* GetMethod(obj, wellKnownSymbols.asyncIterator));
if (method === Value.undefined) {
- const syncMethod = Q(GetMethod(obj, wellKnownSymbols.iterator));
- const syncIteratorRecord = Q(GetIterator(obj, 'sync', syncMethod));
- return Q(CreateAsyncFromSyncIterator(syncIteratorRecord));
+ const syncMethod = Q(yield* GetMethod(obj, wellKnownSymbols.iterator));
+ const syncIteratorRecord = Q(yield* GetIterator(obj, 'sync', syncMethod));
+ return Q(yield* CreateAsyncFromSyncIterator(syncIteratorRecord));
}
} else {
- method = Q(GetMethod(obj, wellKnownSymbols.iterator));
+ method = Q(yield* GetMethod(obj, wellKnownSymbols.iterator));
}
}
- const iterator = Q(Call(method, obj));
+ const iterator = Q(yield* Call(method, obj));
if (Type(iterator) !== 'Object') {
// TODO: throw with an error message
return surroundingAgent.Throw('TypeError');
}
- const nextMethod = Q(GetV(iterator, new Value('next')));
+ const nextMethod = Q(yield* GetV(iterator, new Value('next')));
const iteratorRecord = {
Iterator: iterator,
NextMethod: nextMethod,
@@ -63,12 +63,12 @@ export function GetIterator(obj, hint, method) {
}
// 7.4.2 #sec-iteratornext
-export function IteratorNext(iteratorRecord, value) {
+export function* IteratorNext(iteratorRecord, value) {
let result;
if (!value) {
- result = Q(Call(iteratorRecord.NextMethod, iteratorRecord.Iterator, []));
+ result = Q(yield* Call(iteratorRecord.NextMethod, iteratorRecord.Iterator, []));
} else {
- result = Q(Call(iteratorRecord.NextMethod, iteratorRecord.Iterator, [value]));
+ result = Q(yield* Call(iteratorRecord.NextMethod, iteratorRecord.Iterator, [value]));
}
if (Type(result) !== 'Object') {
// TODO: throw with an error message
@@ -78,21 +78,21 @@ export function IteratorNext(iteratorRecord, value) {
}
// 7.4.3 #sec-iteratorcomplete
-export function IteratorComplete(iterResult) {
+export function* IteratorComplete(iterResult) {
Assert(Type(iterResult) === 'Object');
- return EnsureCompletion(ToBoolean(Q(Get(iterResult, new Value('done')))));
+ return EnsureCompletion(ToBoolean(Q(yield* Get(iterResult, new Value('done')))));
}
// 7.4.4 #sec-iteratorvalue
-export function IteratorValue(iterResult) {
+export function* IteratorValue(iterResult) {
Assert(Type(iterResult) === 'Object');
- return EnsureCompletion(Q(Get(iterResult, new Value('value'))));
+ return EnsureCompletion(Q(yield* Get(iterResult, new Value('value'))));
}
// 7.4.5 #sec-iteratorstep
-export function IteratorStep(iteratorRecord) {
- const result = Q(IteratorNext(iteratorRecord));
- const done = Q(IteratorComplete(result));
+export function* IteratorStep(iteratorRecord) {
+ const result = Q(yield* IteratorNext(iteratorRecord));
+ const done = Q(yield* IteratorComplete(result));
if (done === Value.true) {
return EnsureCompletion(Value.false);
}
@@ -100,17 +100,17 @@ export function IteratorStep(iteratorRecord) {
}
// 7.4.6 #sec-iteratorclose
-export function IteratorClose(iteratorRecord, completion) {
+export function* IteratorClose(iteratorRecord, completion) {
// TODO: completion should be a Completion Record so this should not be necessary
completion = EnsureCompletion(completion);
Assert(Type(iteratorRecord.Iterator) === 'Object');
Assert(completion instanceof Completion);
const iterator = iteratorRecord.Iterator;
- const ret = Q(GetMethod(iterator, new Value('return')));
+ const ret = Q(yield* GetMethod(iterator, new Value('return')));
if (ret === Value.undefined) {
return Completion(completion);
}
- const innerResult = EnsureCompletion(Call(ret, iterator, []));
+ const innerResult = EnsureCompletion(yield* Call(ret, iterator, []));
if (completion.Type === 'throw') {
return Completion(completion);
}
@@ -129,11 +129,11 @@ export function* AsyncIteratorClose(iteratorRecord, completion) {
Assert(Type(iteratorRecord.Iterator) === 'Object');
Assert(completion instanceof Completion);
const iterator = iteratorRecord.Iterator;
- const ret = Q(GetMethod(iterator, new Value('return')));
+ const ret = Q(yield* GetMethod(iterator, new Value('return')));
if (ret === Value.undefined) {
return Completion(completion);
}
- let innerResult = EnsureCompletion(Call(ret, iterator, []));
+ let innerResult = EnsureCompletion(yield* Call(ret, iterator, []));
if (innerResult.Type === 'normal') {
innerResult = EnsureCompletion(yield* Await(innerResult.Value));
}
@@ -151,16 +151,16 @@ export function* AsyncIteratorClose(iteratorRecord, completion) {
}
// 7.4.8 #sec-createiterresultobject
-export function CreateIterResultObject(value, done) {
+export function* CreateIterResultObject(value, done) {
Assert(Type(done) === 'Boolean');
const obj = ObjectCreate(surroundingAgent.intrinsic('%ObjectPrototype%'));
- X(CreateDataProperty(obj, new Value('value'), value));
- X(CreateDataProperty(obj, new Value('done'), done));
+ X(yield* CreateDataProperty(obj, new Value('value'), value));
+ X(yield* CreateDataProperty(obj, new Value('done'), done));
return obj;
}
// 7.4.9 #sec-createlistiteratorRecord
-export function CreateListIteratorRecord(list) {
+export function* CreateListIteratorRecord(list) {
const iterator = ObjectCreate(surroundingAgent.intrinsic('%IteratorPrototype%'), [
'IteratedList',
'ListIteratorNextIndex',
@@ -177,7 +177,7 @@ export function CreateListIteratorRecord(list) {
}
// 7.4.9.1 #sec-listiterator-next
-function ListIteratorNextSteps(args, { thisValue }) {
+function* ListIteratorNextSteps(args, { thisValue }) {
const O = thisValue;
Assert(Type(O) === 'Object');
Assert('IteratedList' in O);
@@ -185,39 +185,44 @@ function ListIteratorNextSteps(args, { thisValue }) {
const index = O.ListIteratorNextIndex;
const len = list.length;
if (index >= len) {
- return CreateIterResultObject(Value.undefined, Value.true);
+ return yield* CreateIterResultObject(Value.undefined, Value.true);
}
O.ListIteratorNextIndex += 1;
- return CreateIterResultObject(list[index], Value.false);
+ return yield* CreateIterResultObject(list[index], Value.false);
}
// 25.1.4.1 #sec-createasyncfromsynciterator
-export function CreateAsyncFromSyncIterator(syncIteratorRecord) {
+export function* CreateAsyncFromSyncIterator(syncIteratorRecord) {
const asyncIterator = X(ObjectCreate(surroundingAgent.intrinsic('%AsyncFromSyncIteratorPrototype%'), [
'SyncIteratorRecord',
]));
asyncIterator.SyncIteratorRecord = syncIteratorRecord;
- return Q(GetIterator(asyncIterator, 'async'));
+ return Q(yield* GetIterator(asyncIterator, 'async'));
}
// 25.1.4.2.5 #sec-async-from-sync-iterator-value-unwrap-functions
-function AsyncFromSyncIteratorValueUnwrapFunctions([value = Value.undefined]) {
+function* AsyncFromSyncIteratorValueUnwrapFunctions([value = Value.undefined]) {
const F = this;
- return X(CreateIterResultObject(value, F.Done));
+ return X(yield* CreateIterResultObject(value, F.Done));
}
// 25.1.4.4 #sec-async-from-sync-iterator-continuation
-export function AsyncFromSyncIteratorContinuation(result, promiseCapability) {
- const done = IteratorComplete(result);
+export function* AsyncFromSyncIteratorContinuation(result, promiseCapability) {
+ const done = yield* IteratorComplete(result);
IfAbruptRejectPromise(done, promiseCapability);
- const value = IteratorValue(result);
+ const value = yield* IteratorValue(result);
IfAbruptRejectPromise(value, promiseCapability);
- const valueWrapperCapability = X(NewPromiseCapability(surroundingAgent.intrinsic('%Promise%')));
- X(Call(valueWrapperCapability.Resolve, Value.undefined, [value]));
+ const valueWrapperCapability = X(yield* NewPromiseCapability(surroundingAgent.intrinsic('%Promise%')));
+ X(yield* Call(valueWrapperCapability.Resolve, Value.undefined, [value]));
const steps = AsyncFromSyncIteratorValueUnwrapFunctions;
const onFulfilled = CreateBuiltinFunction(steps, ['Done']);
onFulfilled.Done = done;
- X(PerformPromiseThen(valueWrapperCapability.Promise, onFulfilled, Value.undefined, promiseCapability));
+ X(yield* PerformPromiseThen(
+ valueWrapperCapability.Promise,
+ onFulfilled,
+ Value.undefined,
+ promiseCapability,
+ ));
return promiseCapability.Promise;
}
diff --git a/src/abstract-ops/module-records.mjs b/src/abstract-ops/module-records.mjs
index 2a1415e..477af70 100644
--- a/src/abstract-ops/module-records.mjs
+++ b/src/abstract-ops/module-records.mjs
@@ -31,7 +31,7 @@ import {
import { msg } from '../helpers.mjs';
// 15.2.1.16.4.1 #sec-innermoduleinstantiation
-export function InnerModuleInstantiation(module, stack, index) {
+export function* InnerModuleInstantiation(module, stack, index) {
if (!(module instanceof SourceTextModuleRecord)) {
Q(module.Instantiate());
return index;
@@ -47,7 +47,7 @@ export function InnerModuleInstantiation(module, stack, index) {
stack.push(module);
for (const required of module.RequestedModules) {
const requiredModule = Q(HostResolveImportedModule(module, required));
- index = Q(InnerModuleInstantiation(requiredModule, stack, index));
+ index = Q(yield* InnerModuleInstantiation(requiredModule, stack, index));
Assert(requiredModule.Status === 'instantiating' || requiredModule.Status === 'instantiated' || requiredModule.Status === 'evaluated');
if (stack.includes(requiredModule)) {
Assert(requiredModule.Status === 'instantiating');
@@ -57,7 +57,7 @@ export function InnerModuleInstantiation(module, stack, index) {
module.DFSAncestorIndex = Math.min(module.DFSAncestorIndex, requiredModule.DFSAncestorIndex);
}
}
- Q(ModuleDeclarationEnvironmentSetup(module));
+ Q(yield* ModuleDeclarationEnvironmentSetup(module));
Assert(stack.indexOf(module) === stack.lastIndexOf(module));
Assert(module.DFSAncestorIndex <= module.DFSIndex);
if (module.DFSAncestorIndex === module.DFSIndex) {
@@ -74,7 +74,7 @@ export function InnerModuleInstantiation(module, stack, index) {
}
// 15.2.1.16.4.2 #sec-moduledeclarationenvironmentsetup
-export function ModuleDeclarationEnvironmentSetup(module) {
+export function* ModuleDeclarationEnvironmentSetup(module) {
for (const e of module.IndirectExportEntries) {
const resolution = Q(module.ResolveExport(e.ExportName, []));
if (resolution === null || resolution === 'ambiguous') {
@@ -91,7 +91,7 @@ export function ModuleDeclarationEnvironmentSetup(module) {
for (const ie of module.ImportEntries) {
const importedModule = X(HostResolveImportedModule(module, ie.ModuleRequest));
if (ie.ImportName === new Value('*')) {
- const namespace = Q(GetModuleNamespace(importedModule));
+ const namespace = Q(yield* GetModuleNamespace(importedModule));
X(envRec.CreateImmutableBinding(ie.LocalName, Value.true));
envRec.InitializeBinding(ie.LocalName, namespace);
} else {
@@ -133,7 +133,7 @@ export function ModuleDeclarationEnvironmentSetup(module) {
}
// 15.2.1.18 #sec-getmodulenamespace
-export function GetModuleNamespace(module) {
+export function* GetModuleNamespace(module) {
Assert(module instanceof ModuleRecord);
Assert(module.Status !== 'uninstantiated');
let namespace = module.Namespace;
@@ -146,13 +146,13 @@ export function GetModuleNamespace(module) {
unambiguousNames.push(name);
}
}
- namespace = ModuleNamespaceCreate(module, unambiguousNames);
+ namespace = yield* ModuleNamespaceCreate(module, unambiguousNames);
}
return namespace;
}
// 15.2.1.16.5.1 #sec-innermoduleevaluation
-export function InnerModuleEvaluation(module, stack, index) {
+export function* InnerModuleEvaluation(module, stack, index) {
if (!(module instanceof SourceTextModuleRecord)) {
Q(module.Evaluate());
return index;
@@ -175,7 +175,7 @@ export function InnerModuleEvaluation(module, stack, index) {
stack.push(module);
for (const required of module.RequestedModules) {
const requiredModule = X(HostResolveImportedModule(module, required));
- index = Q(InnerModuleEvaluation(requiredModule, stack, index));
+ index = Q(yield* InnerModuleEvaluation(requiredModule, stack, index));
Assert(requiredModule.Status === 'evaluating' || requiredModule.Status === 'evaluated');
if (stack.includes(requiredModule)) {
Assert(requiredModule.Status === 'evaluating');
@@ -185,7 +185,7 @@ export function InnerModuleEvaluation(module, stack, index) {
module.DFSAncestorIndex = Math.min(module.DFSAncestorIndex, requiredModule.DFSAncestorIndex);
}
}
- Q(ModuleExecution(module));
+ Q(yield* ModuleExecution(module));
Assert(stack.indexOf(module) === stack.lastIndexOf(module));
Assert(module.DFSAncestorIndex <= module.DFSIndex);
if (module.DFSAncestorIndex === module.DFSIndex) {
diff --git a/src/abstract-ops/object-operations.mjs b/src/abstract-ops/object-operations.mjs
index 90a985f..26a2fe4 100644
--- a/src/abstract-ops/object-operations.mjs
+++ b/src/abstract-ops/object-operations.mjs
@@ -35,26 +35,26 @@ import { msg } from '../helpers.mjs';
// 7.3 #sec-operations-on-objects
// 7.3.1 #sec-get-o-p
-export function Get(O, P) {
+export function* Get(O, P) {
Assert(Type(O) === 'Object');
Assert(IsPropertyKey(P));
// TODO: This should just return Q(O.Get(P, O))
- return new NormalCompletion(Q(O.Get(P, O)));
+ return new NormalCompletion(Q(yield* O.Get(P, O)));
}
// 7.3.2 #sec-getv
-export function GetV(V, P) {
+export function* GetV(V, P) {
Assert(IsPropertyKey(P));
- const O = Q(ToObject(V));
- return Q(O.Get(P, V));
+ const O = Q(yield* ToObject(V));
+ return Q(yield* O.Get(P, V));
}
// 7.3.3 #sec-set-o-p-v-throw
-export function Set(O, P, V, Throw) {
+export function* Set(O, P, V, Throw) {
Assert(Type(O) === 'Object');
Assert(IsPropertyKey(P));
Assert(Type(Throw) === 'Boolean');
- const success = Q(O.Set(P, V, O));
+ const success = Q(yield* O.Set(P, V, O));
if (success === Value.false && Throw === Value.true) {
return surroundingAgent.Throw('TypeError', msg('CannotSetProperty', P, O));
}
@@ -62,7 +62,7 @@ export function Set(O, P, V, Throw) {
}
// 7.3.4 #sec-createdataproperty
-export function CreateDataProperty(O, P, V) {
+export function* CreateDataProperty(O, P, V) {
Assert(Type(O) === 'Object');
Assert(IsPropertyKey(P));
@@ -72,11 +72,11 @@ export function CreateDataProperty(O, P, V) {
Enumerable: Value.true,
Configurable: Value.true,
});
- return Q(O.DefineOwnProperty(P, newDesc));
+ return Q(yield* O.DefineOwnProperty(P, newDesc));
}
// 7.3.5 #sec-createmethodproperty
-export function CreateMethodProperty(O, P, V) {
+export function* CreateMethodProperty(O, P, V) {
Assert(Type(O) === 'Object');
Assert(IsPropertyKey(P));
@@ -86,14 +86,14 @@ export function CreateMethodProperty(O, P, V) {
Enumerable: Value.false,
Configurable: Value.true,
});
- return Q(O.DefineOwnProperty(P, newDesc));
+ return Q(yield* O.DefineOwnProperty(P, newDesc));
}
// 7.3.6 #sec-createdatapropertyorthrow
-export function CreateDataPropertyOrThrow(O, P, V) {
+export function* CreateDataPropertyOrThrow(O, P, V) {
Assert(Type(O) === 'Object');
Assert(IsPropertyKey(P));
- const success = Q(CreateDataProperty(O, P, V));
+ const success = Q(yield* CreateDataProperty(O, P, V));
if (success === Value.false) {
// TODO: throw with an error message
return surroundingAgent.Throw('TypeError');
@@ -102,10 +102,10 @@ export function CreateDataPropertyOrThrow(O, P, V) {
}
// 7.3.7 #sec-definepropertyorthrow
-export function DefinePropertyOrThrow(O, P, desc) {
+export function* DefinePropertyOrThrow(O, P, desc) {
Assert(Type(O) === 'Object');
Assert(IsPropertyKey(P));
- const success = Q(O.DefineOwnProperty(P, desc));
+ const success = Q(yield* O.DefineOwnProperty(P, desc));
if (success === Value.false) {
// TODO: throw with an error message
return surroundingAgent.Throw('TypeError');
@@ -114,10 +114,10 @@ export function DefinePropertyOrThrow(O, P, desc) {
}
// 7.3.8 #sec-deletepropertyorthrow
-export function DeletePropertyOrThrow(O, P) {
+export function* DeletePropertyOrThrow(O, P) {
Assert(Type(O) === 'Object');
Assert(IsPropertyKey(P));
- const success = Q(O.Delete(P));
+ const success = Q(yield* O.Delete(P));
if (success === Value.false) {
// TODO: throw with an error message
return surroundingAgent.Throw('TypeError');
@@ -126,9 +126,9 @@ export function DeletePropertyOrThrow(O, P) {
}
// 7.3.9 #sec-getmethod
-export function GetMethod(V, P) {
+export function* GetMethod(V, P) {
Assert(IsPropertyKey(P));
- const func = Q(GetV(V, P));
+ const func = Q(yield* GetV(V, P));
if (func === Value.null || func === Value.undefined) {
return Value.undefined;
}
@@ -139,17 +139,17 @@ export function GetMethod(V, P) {
}
// 7.3.10 #sec-hasproperty
-export function HasProperty(O, P) {
+export function* HasProperty(O, P) {
Assert(Type(O) === 'Object');
Assert(IsPropertyKey(P));
- return Q(O.HasProperty(P));
+ return Q(yield* O.HasProperty(P));
}
// 7.3.11 #sec-hasownproperty
-export function HasOwnProperty(O, P) {
+export function* HasOwnProperty(O, P) {
Assert(Type(O) === 'Object');
Assert(IsPropertyKey(P));
- const desc = Q(O.GetOwnProperty(P));
+ const desc = Q(yield* O.GetOwnProperty(P));
if (desc === Value.undefined) {
return Value.false;
}
@@ -157,7 +157,7 @@ export function HasOwnProperty(O, P) {
}
// 7.3.12 #sec-call
-export function Call(F, V, argumentsList) {
+export function* Call(F, V, argumentsList) {
if (!argumentsList) {
argumentsList = [];
}
@@ -167,11 +167,11 @@ export function Call(F, V, argumentsList) {
return surroundingAgent.Throw('TypeError', msg('NotAFunction', F));
}
- return Q(F.Call(V, argumentsList));
+ return Q(yield* F.Call(V, argumentsList));
}
// 7.3.13 #sec-construct
-export function Construct(F, argumentsList, newTarget) {
+export function* Construct(F, argumentsList, newTarget) {
if (!newTarget) {
newTarget = F;
}
@@ -180,33 +180,33 @@ export function Construct(F, argumentsList, newTarget) {
}
Assert(IsConstructor(F) === Value.true);
Assert(IsConstructor(newTarget) === Value.true);
- return Q(F.Construct(argumentsList, newTarget));
+ return Q(yield* F.Construct(argumentsList, newTarget));
}
// 7.3.14 #sec-setintegritylevel
-export function SetIntegrityLevel(O, level) {
+export function* SetIntegrityLevel(O, level) {
Assert(Type(O) === 'Object');
Assert(level === 'sealed' || level === 'frozen');
- const status = Q(O.PreventExtensions());
+ const status = Q(yield* O.PreventExtensions());
if (status === Value.false) {
return Value.false;
}
- const keys = Q(O.OwnPropertyKeys());
+ const keys = Q(yield* O.OwnPropertyKeys());
if (level === 'sealed') {
for (const k of keys) {
- Q(DefinePropertyOrThrow(O, k, Descriptor({ Configurable: Value.false })));
+ Q(yield* DefinePropertyOrThrow(O, k, Descriptor({ Configurable: Value.false })));
}
} else if (level === 'frozen') {
for (const k of keys) {
- const currentDesc = Q(O.GetOwnProperty(k));
+ const currentDesc = Q(yield* O.GetOwnProperty(k));
if (currentDesc !== Value.undefined) {
let desc;
- if (IsAccessorDescriptor(currentDesc) === true) {
+ if ((yield* IsAccessorDescriptor(currentDesc)) === true) {
desc = Descriptor({ Configurable: Value.false });
} else {
desc = Descriptor({ Configurable: Value.false, Writable: Value.false });
}
- Q(DefinePropertyOrThrow(O, k, desc));
+ Q(yield* DefinePropertyOrThrow(O, k, desc));
}
}
}
@@ -214,21 +214,21 @@ export function SetIntegrityLevel(O, level) {
}
// 7.3.15 #sec-testintegritylevel
-export function TestIntegrityLevel(O, level) {
+export function* TestIntegrityLevel(O, level) {
Assert(Type(O) === 'Object');
Assert(level === 'sealed' || level === 'frozen');
const status = Q(IsExtensible(O));
if (status === Value.true) {
return Value.false;
}
- const keys = Q(O.OwnPropertyKeys());
+ const keys = Q(yield* O.OwnPropertyKeys());
for (const k of keys) {
- const currentDesc = Q(O.GetOwnProperty(k));
+ const currentDesc = Q(yield* O.GetOwnProperty(k));
if (currentDesc !== Value.undefined) {
if (currentDesc.Configurable === Value.true) {
return Value.false;
}
- if (level === 'frozen' && IsDataDescriptor(currentDesc)) {
+ if (level === 'frozen' && (yield* IsDataDescriptor(currentDesc))) {
if (currentDesc.Writable === Value.true) {
return Value.false;
}
@@ -239,13 +239,13 @@ export function TestIntegrityLevel(O, level) {
}
// 7.3.16 #sec-createarrayfromlist
-export function CreateArrayFromList(elements) {
+export function* CreateArrayFromList(elements) {
Assert(elements.every((e) => e instanceof Value));
- const array = X(ArrayCreate(new Value(0)));
+ const array = X(yield* ArrayCreate(new Value(0)));
let n = 0;
for (const e of elements) {
- const nStr = X(ToString(new Value(n)));
- const status = X(CreateDataProperty(array, nStr, e));
+ const nStr = X(yield* ToString(new Value(n)));
+ const status = X(yield* CreateDataProperty(array, nStr, e));
Assert(status === Value.true);
n += 1;
}
@@ -253,7 +253,7 @@ export function CreateArrayFromList(elements) {
}
// 7.3.17 #sec-createlistfromarraylike
-export function CreateListFromArrayLike(obj, elementTypes) {
+export function* CreateListFromArrayLike(obj, elementTypes) {
if (!elementTypes) {
elementTypes = ['Undefined', 'Null', 'Boolean', 'String', 'Symbol', 'Number', 'Object'];
}
@@ -261,13 +261,13 @@ export function CreateListFromArrayLike(obj, elementTypes) {
// TODO: throw with an error message
return surroundingAgent.Throw('TypeError');
}
- const lenProp = Q(Get(obj, new Value('length')));
- const len = Q(ToLength(lenProp)).numberValue();
+ const lenProp = Q(yield* Get(obj, new Value('length')));
+ const len = Q(yield* ToLength(lenProp)).numberValue();
const list = [];
let index = 0;
while (index < len) {
- const indexName = X(ToString(new Value(index)));
- const next = Q(Get(obj, indexName));
+ const indexName = X(yield* ToString(new Value(index)));
+ const next = Q(yield* Get(obj, indexName));
if (!elementTypes.includes(Type(next))) {
// TODO: throw with an error message
return surroundingAgent.Throw('TypeError');
@@ -279,34 +279,34 @@ export function CreateListFromArrayLike(obj, elementTypes) {
}
// 7.3.18 #sec-invoke
-export function Invoke(V, P, argumentsList) {
+export function* Invoke(V, P, argumentsList) {
Assert(IsPropertyKey(P));
if (!argumentsList) {
argumentsList = [];
}
- const func = Q(GetV(V, P));
- return Q(Call(func, V, argumentsList));
+ const func = Q(yield* GetV(V, P));
+ return Q(yield* Call(func, V, argumentsList));
}
// 7.3.19 #sec-ordinaryhasinstance
-export function OrdinaryHasInstance(C, O) {
+export function* OrdinaryHasInstance(C, O) {
if (IsCallable(C) === Value.false) {
return Value.false;
}
if ('BoundTargetFunction' in C) {
const BC = C.BoundTargetFunction;
- return Q(InstanceofOperator(O, BC));
+ return Q(yield* InstanceofOperator(O, BC));
}
if (Type(O) !== 'Object') {
return Value.false;
}
- const P = Q(Get(C, new Value('prototype')));
+ const P = Q(yield* Get(C, new Value('prototype')));
if (Type(P) !== 'Object') {
// TODO: throw with an error message
return surroundingAgent.Throw('TypeError');
}
while (true) {
- O = Q(O.GetPrototypeOf());
+ O = Q(yield* O.GetPrototypeOf());
if (O === Value.null) {
return Value.false;
}
@@ -317,9 +317,9 @@ export function OrdinaryHasInstance(C, O) {
}
// 7.3.20 #sec-speciesconstructor
-export function SpeciesConstructor(O, defaultConstructor) {
+export function* SpeciesConstructor(O, defaultConstructor) {
Assert(Type(O) === 'Object');
- const C = Q(Get(O, new Value('constructor')));
+ const C = Q(yield* Get(O, new Value('constructor')));
if (C === Value.undefined) {
return defaultConstructor;
}
@@ -327,7 +327,7 @@ export function SpeciesConstructor(O, defaultConstructor) {
// TODO: throw with an error message
return surroundingAgent.Throw('TypeError');
}
- const S = Q(Get(C, wellKnownSymbols.species));
+ const S = Q(yield* Get(C, wellKnownSymbols.species));
if (S === Value.undefined || S === Value.null) {
return defaultConstructor;
}
@@ -339,23 +339,23 @@ export function SpeciesConstructor(O, defaultConstructor) {
}
// 7.3.21 #sec-enumerableownpropertynames
-export function EnumerableOwnPropertyNames(O, kind) {
+export function* EnumerableOwnPropertyNames(O, kind) {
Assert(Type(O) === 'Object');
- const ownKeys = Q(O.OwnPropertyKeys());
+ const ownKeys = Q(yield* O.OwnPropertyKeys());
const properties = [];
for (const key of ownKeys) {
if (Type(key) === 'String') {
- const desc = Q(O.GetOwnProperty(key));
+ const desc = Q(yield* O.GetOwnProperty(key));
if (desc !== Value.undefined && desc.Enumerable === Value.true) {
if (kind === 'key') {
properties.push(key);
} else {
- const value = Q(Get(O, key));
+ const value = Q(yield* Get(O, key));
if (kind === 'value') {
properties.push(value);
} else {
Assert(kind === 'key+value');
- const entry = CreateArrayFromList([key, value]);
+ const entry = yield* CreateArrayFromList([key, value]);
properties.push(entry);
}
}
@@ -369,7 +369,7 @@ export function EnumerableOwnPropertyNames(O, kind) {
}
// 7.3.22 #sec-getfunctionrealm
-export function GetFunctionRealm(obj) {
+export function* GetFunctionRealm(obj) {
Assert(IsCallable(obj) === Value.true);
if ('Realm' in obj) {
return obj.Realm;
@@ -377,7 +377,7 @@ export function GetFunctionRealm(obj) {
if ('BoundTargetFunction' in obj) {
const target = obj.BoundTargetFunction;
- return Q(GetFunctionRealm(target));
+ return Q(yield* GetFunctionRealm(target));
}
if (obj instanceof ProxyExoticObjectValue) {
@@ -385,21 +385,21 @@ export function GetFunctionRealm(obj) {
return surroundingAgent.Throw('TypeError', msg('ProxyRevoked', 'GetFunctionRealm'));
}
const proxyTarget = obj.ProxyTarget;
- return Q(GetFunctionRealm(proxyTarget));
+ return Q(yield* GetFunctionRealm(proxyTarget));
}
return surroundingAgent.currentRealmRecord;
}
// 7.3.23 #sec-copydataproperties
-export function CopyDataProperties(target, source, excludedItems) {
+export function* CopyDataProperties(target, source, excludedItems) {
Assert(Type(target) === 'Object');
Assert(excludedItems.every((i) => IsPropertyKey(i)));
if (source === Value.undefined || source === Value.null) {
return target;
}
- const from = X(ToObject(source));
- const keys = Q(from.OwnPropertyKeys());
+ const from = X(yield* ToObject(source));
+ const keys = Q(yield* from.OwnPropertyKeys());
for (const nextKey of keys) {
let excluded = false;
for (const e of excludedItems) {
@@ -410,8 +410,8 @@ export function CopyDataProperties(target, source, excludedItems) {
if (excluded === false) {
const desc = Q(from.GetOwnProperty(nextKey));
if (desc !== Value.undefined && desc.Enumerable === Value.true) {
- const propValue = Q(Get(from, nextKey));
- X(CreateDataProperty(target, nextKey, propValue));
+ const propValue = Q(yield* Get(from, nextKey));
+ X(yield* CreateDataProperty(target, nextKey, propValue));
}
}
}
diff --git a/src/abstract-ops/objects.mjs b/src/abstract-ops/objects.mjs
index 74dcec6..2229ad1 100644
--- a/src/abstract-ops/objects.mjs
+++ b/src/abstract-ops/objects.mjs
@@ -32,12 +32,12 @@ import {
import { Q, X } from '../completion.mjs';
// 9.1.1.1 OrdinaryGetPrototypeOf
-export function OrdinaryGetPrototypeOf(O) {
+export function* OrdinaryGetPrototypeOf(O) {
return O.Prototype;
}
// 9.1.2.1 OrdinarySetPrototypeOf
-export function OrdinarySetPrototypeOf(O, V) {
+export function* OrdinarySetPrototypeOf(O, V) {
Assert(Type(V) === 'Object' || Type(V) === 'Null');
const extensible = O.Extensible;
@@ -77,7 +77,7 @@ export function OrdinaryPreventExtensions(O) {
}
// 9.1.5.1 OrdinaryGetOwnProperty
-export function OrdinaryGetOwnProperty(O, P) {
+export function* OrdinaryGetOwnProperty(O, P) {
Assert(IsPropertyKey(P));
if (!O.properties.has(P)) {
@@ -102,9 +102,9 @@ export function OrdinaryGetOwnProperty(O, P) {
}
// 9.1.6.1 OrdinaryDefineOwnProperty
-export function OrdinaryDefineOwnProperty(O, P, Desc) {
- const current = Q(O.GetOwnProperty(P));
- const extensible = Q(IsExtensible(O));
+export function* OrdinaryDefineOwnProperty(O, P, Desc) {
+ const current = Q(yield* O.GetOwnProperty(P));
+ const extensible = Q(yield* IsExtensible(O));
return ValidateAndApplyPropertyDescriptor(O, P, extensible, Desc, current);
}
@@ -229,31 +229,31 @@ export function ValidateAndApplyPropertyDescriptor(O, P, extensible, Desc, curre
}
// 9.1.7.1 OrdinaryHasProperty
-export function OrdinaryHasProperty(O, P) {
+export function* OrdinaryHasProperty(O, P) {
Assert(IsPropertyKey(P));
- const hasOwn = Q(O.GetOwnProperty(P));
+ const hasOwn = Q(yield* O.GetOwnProperty(P));
if (Type(hasOwn) !== 'Undefined') {
return Value.true;
}
- const parent = Q(O.GetPrototypeOf());
+ const parent = Q(yield* O.GetPrototypeOf());
if (Type(parent) !== 'Null') {
- return Q(parent.HasProperty(P));
+ return Q(yield* parent.HasProperty(P));
}
return Value.false;
}
// 9.1.8.1
-export function OrdinaryGet(O, P, Receiver) {
+export function* OrdinaryGet(O, P, Receiver) {
Assert(IsPropertyKey(P));
- const desc = Q(O.GetOwnProperty(P));
+ const desc = Q(yield* O.GetOwnProperty(P));
if (Type(desc) === 'Undefined') {
- const parent = Q(O.GetPrototypeOf());
+ const parent = Q(yield* O.GetPrototypeOf());
if (Type(parent) === 'Null') {
return Value.undefined;
}
- return Q(parent.Get(P, Receiver));
+ return Q(yield* parent.Get(P, Receiver));
}
if (IsDataDescriptor(desc)) {
return desc.Value;
@@ -263,24 +263,24 @@ export function OrdinaryGet(O, P, Receiver) {
if (Type(getter) === 'Undefined') {
return Value.undefined;
}
- return Q(Call(getter, Receiver));
+ return Q(yield* Call(getter, Receiver));
}
// 9.1.9.1 OrdinarySet
-export function OrdinarySet(O, P, V, Receiver) {
+export function* OrdinarySet(O, P, V, Receiver) {
Assert(IsPropertyKey(P));
- const ownDesc = Q(O.GetOwnProperty(P));
- return OrdinarySetWithOwnDescriptor(O, P, V, Receiver, ownDesc);
+ const ownDesc = Q(yield* O.GetOwnProperty(P));
+ return yield* OrdinarySetWithOwnDescriptor(O, P, V, Receiver, ownDesc);
}
// 9.1.9.2 OrdinarySetWithOwnDescriptor
-export function OrdinarySetWithOwnDescriptor(O, P, V, Receiver, ownDesc) {
+export function* OrdinarySetWithOwnDescriptor(O, P, V, Receiver, ownDesc) {
Assert(IsPropertyKey(P));
if (Type(ownDesc) === 'Undefined') {
- const parent = Q(O.GetPrototypeOf());
+ const parent = Q(yield* O.GetPrototypeOf());
if (Type(parent) !== 'Null') {
- return Q(parent.Set(P, V, Receiver));
+ return Q(yield* parent.Set(P, V, Receiver));
}
ownDesc = Descriptor({
Value: Value.undefined,
@@ -298,7 +298,7 @@ export function OrdinarySetWithOwnDescriptor(O, P, V, Receiver, ownDesc) {
return Value.false;
}
- const existingDescriptor = Q(Receiver.GetOwnProperty(P));
+ const existingDescriptor = Q(yield* Receiver.GetOwnProperty(P));
if (Type(existingDescriptor) !== 'Undefined') {
if (IsAccessorDescriptor(existingDescriptor)) {
return Value.false;
@@ -307,9 +307,9 @@ export function OrdinarySetWithOwnDescriptor(O, P, V, Receiver, ownDesc) {
return Value.false;
}
const valueDesc = Descriptor({ Value: V });
- return Q(Receiver.DefineOwnProperty(P, valueDesc));
+ return Q(yield* Receiver.DefineOwnProperty(P, valueDesc));
}
- return CreateDataProperty(Receiver, P, V);
+ return yield* CreateDataProperty(Receiver, P, V);
}
Assert(IsAccessorDescriptor(ownDesc));
@@ -317,14 +317,14 @@ export function OrdinarySetWithOwnDescriptor(O, P, V, Receiver, ownDesc) {
if (setter === undefined || Type(setter) === 'Undefined') {
return Value.false;
}
- Q(Call(setter, Receiver, [V]));
+ Q(yield* Call(setter, Receiver, [V]));
return Value.true;
}
// 9.1.10.1 OrdinaryDelete
-export function OrdinaryDelete(O, P) {
+export function* OrdinaryDelete(O, P) {
Assert(IsPropertyKey(P));
- const desc = Q(O.GetOwnProperty(P));
+ const desc = Q(yield* O.GetOwnProperty(P));
if (Type(desc) === 'Undefined') {
return Value.true;
}
@@ -336,13 +336,13 @@ export function OrdinaryDelete(O, P) {
}
// 9.1.11.1
-export function OrdinaryOwnPropertyKeys(O) {
+export function* OrdinaryOwnPropertyKeys(O) {
const keys = [];
// For each own property key P of O that is an array index, in ascending numeric index order, do
// Add P as the last element of keys.
for (const P of O.properties.keys()) {
- if (isArrayIndex(P)) {
+ if (yield* isArrayIndex(P)) {
keys.push(P);
}
}
@@ -352,7 +352,7 @@ export function OrdinaryOwnPropertyKeys(O) {
// P is not an array index, in ascending chronological order of property creation, do
// Add P as the last element of keys.
for (const P of O.properties.keys()) {
- if (Type(P) === 'String' && isArrayIndex(P) === false) {
+ if (Type(P) === 'String' && (yield* isArrayIndex(P)) === false) {
keys.push(P);
}
}
@@ -393,21 +393,21 @@ export function ObjectCreate(proto, internalSlotsList) {
}
// 9.1.13 OrdinaryCreateFromConstructor
-export function OrdinaryCreateFromConstructor(constructor, intrinsicDefaultProto, internalSlotsList) {
+export function* OrdinaryCreateFromConstructor(constructor, intrinsicDefaultProto, internalSlotsList) {
// Assert: intrinsicDefaultProto is a String value that
// is this specification's name of an intrinsic object.
- const proto = Q(GetPrototypeFromConstructor(constructor, intrinsicDefaultProto));
+ const proto = Q(yield* GetPrototypeFromConstructor(constructor, intrinsicDefaultProto));
return ObjectCreate(proto, internalSlotsList);
}
// 9.1.14 GetPrototypeFromConstructor
-export function GetPrototypeFromConstructor(constructor, intrinsicDefaultProto) {
+export function* GetPrototypeFromConstructor(constructor, intrinsicDefaultProto) {
// Assert: intrinsicDefaultProto is a String value that
// is this specification's name of an intrinsic object.
Assert(IsCallable(constructor) === Value.true);
- let proto = Q(Get(constructor, new Value('prototype')));
+ let proto = Q(yield* Get(constructor, new Value('prototype')));
if (Type(proto) !== 'Object') {
- const realm = Q(GetFunctionRealm(constructor));
+ const realm = Q(yield* GetFunctionRealm(constructor));
proto = realm.Intrinsics[intrinsicDefaultProto];
}
return proto;
@@ -430,7 +430,7 @@ export function IntegerIndexedObjectCreate(prototype, internalSlotsList) {
}
// 9.4.5.8 #sec-integerindexedelementget
-export function IntegerIndexedElementGet(O, index) {
+export function* IntegerIndexedElementGet(O, index) {
Assert(Type(index) === 'Number');
Assert(O instanceof ObjectValue
&& 'ViewedArrayBuffer' in O
@@ -463,14 +463,14 @@ export function IntegerIndexedElementGet(O, index) {
}
// 9.4.5.9 #sec-integerindexedelementset
-export function IntegerIndexedElementSet(O, index, value) {
+export function* IntegerIndexedElementSet(O, index, value) {
Assert(Type(index) === 'Number');
Assert(O instanceof ObjectValue
&& 'ViewedArrayBuffer' in O
&& 'ArrayLength' in O
&& 'ByteOffset' in O
&& 'TypedArrayName' in O);
- const numValue = Q(ToNumber(value));
+ const numValue = Q(yield* ToNumber(value));
const buffer = O.ViewedArrayBuffer;
if (IsDetachedBuffer(buffer)) {
return surroundingAgent.Throw('TypeError', 'Attempt to access detached ArrayBuffer');
@@ -492,6 +492,6 @@ export function IntegerIndexedElementSet(O, index, value) {
ElementType: elementType,
} = typedArrayInfo.get(arrayTypeName);
const indexedPosition = new Value((index.numberValue() * elementSize) + offset.numberValue());
- X(SetValueInBuffer(buffer, indexedPosition, elementType, numValue, true, 'Unordered'));
+ X(yield* SetValueInBuffer(buffer, indexedPosition, elementType, numValue, true, 'Unordered'));
return Value.true;
}
diff --git a/src/abstract-ops/promise-operations.mjs b/src/abstract-ops/promise-operations.mjs
index ecd8449..edaa215 100644
--- a/src/abstract-ops/promise-operations.mjs
+++ b/src/abstract-ops/promise-operations.mjs
@@ -52,16 +52,16 @@ export class PromiseReactionRecord {
}
// 25.6.1.3 #sec-createresolvingfunctions
-export function CreateResolvingFunctions(promise) {
+export function* CreateResolvingFunctions(promise) {
const alreadyResolved = { Value: false };
const stepsResolve = PromiseResolveFunctions;
const resolve = CreateBuiltinFunction(stepsResolve, ['Promise', 'AlreadyResolved']);
- SetFunctionLength(resolve, new Value(1));
+ yield* SetFunctionLength(resolve, new Value(1));
resolve.Promise = promise;
resolve.AlreadyResolved = alreadyResolved;
const stepsReject = PromiseRejectFunctions;
const reject = CreateBuiltinFunction(stepsReject, ['Promise', 'AlreadyResolved']);
- SetFunctionLength(reject, new Value(1));
+ yield* SetFunctionLength(reject, new Value(1));
reject.Promise = promise;
reject.AlreadyResolved = alreadyResolved;
return {
@@ -71,7 +71,7 @@ export function CreateResolvingFunctions(promise) {
}
// 25.6.1.3.1 #sec-promise-reject-functions
-function PromiseRejectFunctions([reason = Value.undefined]) {
+function* PromiseRejectFunctions([reason = Value.undefined]) {
const F = this;
Assert('Promise' in F && Type(F.Promise) === 'Object');
@@ -85,7 +85,7 @@ function PromiseRejectFunctions([reason = Value.undefined]) {
}
// 25.6.1.3.2 #sec-promise-resolve-functions
-function PromiseResolveFunctions([resolution = Value.undefined]) {
+function* PromiseResolveFunctions([resolution = Value.undefined]) {
const F = this;
Assert('Promise' in F && Type(F.Promise) === 'Object');
@@ -103,7 +103,7 @@ function PromiseResolveFunctions([resolution = Value.undefined]) {
return FulfillPromise(promise, resolution);
}
- const then = Get(resolution, new Value('then'));
+ const then = yield* Get(resolution, new Value('then'));
if (then instanceof AbruptCompletion) {
return RejectPromise(promise, then.Value);
}
@@ -127,16 +127,16 @@ function FulfillPromise(promise, value) {
}
// 25.6.1.5 #sec-newpromisecapability
-export function NewPromiseCapability(C) {
+export function* NewPromiseCapability(C) {
if (IsConstructor(C) === Value.false) {
return surroundingAgent.Throw('TypeError', msg('NotAConstructor', C));
}
const promiseCapability = new PromiseCapabilityRecord();
const steps = GetCapabilitiesExecutorFunctions;
const executor = CreateBuiltinFunction(steps, ['Capability']);
- SetFunctionLength(executor, new Value(2));
+ yield* SetFunctionLength(executor, new Value(2));
executor.Capability = promiseCapability;
- const promise = Q(Construct(C, [executor]));
+ const promise = Q(yield* Construct(C, [executor]));
if (IsCallable(promiseCapability.Resolve) === Value.false) {
return surroundingAgent.Throw('TypeError', msg('PromiseResolveFunction', promiseCapability.Resolve));
}
@@ -148,7 +148,7 @@ export function NewPromiseCapability(C) {
}
// 25.6.1.5.1 #sec-getcapabilitiesexecutor-functions
-function GetCapabilitiesExecutorFunctions([resolve = Value.undefined, reject = Value.undefined]) {
+function* GetCapabilitiesExecutorFunctions([resolve = Value.undefined, reject = Value.undefined]) {
const F = this;
const promiseCapability = F.Capability;
@@ -186,7 +186,7 @@ function TriggerPromiseReactions(reactions, argument) {
}
// 25.6.2.1 #sec-promisereactionjob
-export function PromiseReactionJob(reaction, argument) {
+export function* PromiseReactionJob(reaction, argument) {
Assert(reaction instanceof PromiseReactionRecord);
const promiseCapability = reaction.Capability;
const type = reaction.Type;
@@ -200,7 +200,7 @@ export function PromiseReactionJob(reaction, argument) {
handlerResult = new ThrowCompletion(argument);
}
} else {
- handlerResult = Call(handler, Value.undefined, [argument]);
+ handlerResult = yield* Call(handler, Value.undefined, [argument]);
}
if (promiseCapability === Value.undefined) {
Assert(!(handlerResult instanceof AbruptCompletion));
@@ -208,42 +208,46 @@ export function PromiseReactionJob(reaction, argument) {
}
let status;
if (handlerResult instanceof AbruptCompletion) {
- status = Call(promiseCapability.Reject, Value.undefined, [handlerResult.Value]);
+ status = yield* Call(promiseCapability.Reject, Value.undefined, [handlerResult.Value]);
} else {
- status = Call(promiseCapability.Resolve, Value.undefined, [EnsureCompletion(handlerResult).Value]);
+ status = yield* Call(
+ promiseCapability.Resolve,
+ Value.undefined,
+ [EnsureCompletion(handlerResult).Value],
+ );
}
return status;
}
// 25.6.2.2 #sec-promiseresolvethenablejob
-function PromiseResolveThenableJob(promiseToResolve, thenable, then) {
- const resolvingFunctions = CreateResolvingFunctions(promiseToResolve);
- const thenCallResult = Call(then, thenable, [
+function* PromiseResolveThenableJob(promiseToResolve, thenable, then) {
+ const resolvingFunctions = yield* CreateResolvingFunctions(promiseToResolve);
+ const thenCallResult = yield* Call(then, thenable, [
resolvingFunctions.Resolve, resolvingFunctions.Reject,
]);
if (thenCallResult instanceof AbruptCompletion) {
- const status = Call(resolvingFunctions.Reject, Value.undefined, [thenCallResult.Value]);
+ const status = yield* Call(resolvingFunctions.Reject, Value.undefined, [thenCallResult.Value]);
return status;
}
return thenCallResult;
}
// 25.6.4.5.1 #sec-promise-resolve
-export function PromiseResolve(C, x) {
+export function* PromiseResolve(C, x) {
Assert(Type(C) === 'Object');
if (IsPromise(x) === Value.true) {
- const xConstructor = Q(Get(x, new Value('constructor')));
+ const xConstructor = Q(yield* Get(x, new Value('constructor')));
if (SameValue(xConstructor, C) === Value.true) {
return x;
}
}
- const promiseCapability = Q(NewPromiseCapability(C));
- Q(Call(promiseCapability.Resolve, Value.undefined, [x]));
+ const promiseCapability = Q(yield* NewPromiseCapability(C));
+ Q(yield* Call(promiseCapability.Resolve, Value.undefined, [x]));
return promiseCapability.Promise;
}
// 25.6.5.4.1 #sec-performpromisethen
-export function PerformPromiseThen(promise, onFulfilled, onRejected, resultCapability) {
+export function* PerformPromiseThen(promise, onFulfilled, onRejected, resultCapability) {
Assert(IsPromise(promise) === Value.true);
if (resultCapability) {
Assert(resultCapability instanceof PromiseCapabilityRecord);
diff --git a/src/abstract-ops/reference-operations.mjs b/src/abstract-ops/reference-operations.mjs
index bd2ea52..051adf5 100644
--- a/src/abstract-ops/reference-operations.mjs
+++ b/src/abstract-ops/reference-operations.mjs
@@ -66,7 +66,7 @@ export function IsSuperReference(V) {
}
// 6.2.4.8 #sec-getvalue
-export function GetValue(V) {
+export function* GetValue(V) {
ReturnIfAbrupt(V);
if (Type(V) !== 'Reference') {
return V;
@@ -78,16 +78,16 @@ export function GetValue(V) {
if (IsPropertyReference(V) === Value.true) {
if (HasPrimitiveBase(V) === Value.true) {
Assert(base !== Value.undefined && base !== Value.null);
- base = X(ToObject(base));
+ base = X(yield* ToObject(base));
}
- return Q(base.Get(GetReferencedName(V), GetThisValue(V)));
+ return Q(yield* base.Get(GetReferencedName(V), GetThisValue(V)));
} else {
- return Q(base.GetBindingValue(GetReferencedName(V), IsStrictReference(V)));
+ return Q(yield* base.GetBindingValue(GetReferencedName(V), IsStrictReference(V)));
}
}
// 6.2.4.9 #sec-putvalue
-export function PutValue(V, W) {
+export function* PutValue(V, W) {
ReturnIfAbrupt(V);
ReturnIfAbrupt(W);
if (Type(V) !== 'Reference') {
@@ -99,19 +99,19 @@ export function PutValue(V, W) {
return surroundingAgent.Throw('ReferenceError', msg('NotDefined', GetReferencedName(V)));
}
const globalObj = GetGlobalObject();
- return Q(Set(globalObj, GetReferencedName(V), W, Value.false));
+ return Q(yield* Set(globalObj, GetReferencedName(V), W, Value.false));
} else if (IsPropertyReference(V) === Value.true) {
if (HasPrimitiveBase(V) === Value.true) {
Assert(Type(base) !== 'Undefined' && Type(base) !== 'Null');
- base = X(ToObject(base));
+ base = X(yield* ToObject(base));
}
- const succeeded = Q(base.Set(GetReferencedName(V), W, GetThisValue(V)));
+ const succeeded = Q(yield* base.Set(GetReferencedName(V), W, GetThisValue(V)));
if (succeeded === Value.false && IsStrictReference(V) === Value.true) {
return surroundingAgent.Throw('TypeError', msg('CannotSetProperty', GetReferencedName(V), base));
}
return new NormalCompletion(Value.undefined);
} else {
- return Q(base.SetMutableBinding(GetReferencedName(V), W, IsStrictReference(V)));
+ return Q(yield* base.SetMutableBinding(GetReferencedName(V), W, IsStrictReference(V)));
}
}
diff --git a/src/abstract-ops/regexp-objects.mjs b/src/abstract-ops/regexp-objects.mjs
index db7263e..f27bcaa 100644
--- a/src/abstract-ops/regexp-objects.mjs
+++ b/src/abstract-ops/regexp-objects.mjs
@@ -15,9 +15,13 @@ import { Q, X } from '../completion.mjs';
import { msg } from '../helpers.mjs';
// 21.2.3.2.1 #sec-regexpalloc
-export function RegExpAlloc(newTarget) {
- const obj = Q(OrdinaryCreateFromConstructor(newTarget, '%RegExpPrototype%', ['RegExpMatcher', 'OriginalSource', 'OriginalFlags']));
- X(DefinePropertyOrThrow(obj, new Value('lastIndex'), Descriptor({
+export function* RegExpAlloc(newTarget) {
+ const obj = Q(yield* OrdinaryCreateFromConstructor(
+ newTarget,
+ '%RegExpPrototype%',
+ ['RegExpMatcher', 'OriginalSource', 'OriginalFlags'],
+ ));
+ X(yield* DefinePropertyOrThrow(obj, new Value('lastIndex'), Descriptor({
Writable: Value.true,
Enumerable: Value.false,
Configurable: Value.false,
@@ -26,19 +30,19 @@ export function RegExpAlloc(newTarget) {
}
// 21.2.3.2.2 #sec-regexpinitialize
-export function RegExpInitialize(obj, pattern, flags) {
+export function* RegExpInitialize(obj, pattern, flags) {
let P;
if (pattern === Value.undefined) {
P = new Value('');
} else {
- P = Q(ToString(pattern));
+ P = Q(yield* ToString(pattern));
}
let F;
if (flags === Value.undefined) {
F = new Value('');
} else {
- F = Q(ToString(flags));
+ F = Q(yield* ToString(flags));
}
const f = F.stringValue();
@@ -67,7 +71,7 @@ export function RegExpInitialize(obj, pattern, flags) {
obj.OriginalFlags = F;
obj.RegExpMatcher = getMatcher(P, F);
- Q(Set(obj, new Value('lastIndex'), new Value(0), Value.true));
+ Q(yield* Set(obj, new Value('lastIndex'), new Value(0), Value.true));
return obj;
}
@@ -102,9 +106,9 @@ function getMatcher(P, F) {
}
// 21.2.3.2.3 #sec-regexpcreate
-export function RegExpCreate(P, F) {
- const obj = Q(RegExpAlloc(surroundingAgent.intrinsic('%RegExp%')));
- return Q(RegExpInitialize(obj, P, F));
+export function* RegExpCreate(P, F) {
+ const obj = Q(yield* RegExpAlloc(surroundingAgent.intrinsic('%RegExp%')));
+ return Q(yield* RegExpInitialize(obj, P, F));
}
// 21.2.3.2.4 #sec-escaperegexppattern
diff --git a/src/abstract-ops/spec-types.mjs b/src/abstract-ops/spec-types.mjs
index ba6808e..efff2af 100644
--- a/src/abstract-ops/spec-types.mjs
+++ b/src/abstract-ops/spec-types.mjs
@@ -57,71 +57,71 @@ export function IsGenericDescriptor(Desc) {
}
// 6.2.5.4 #sec-frompropertydescriptor
-export function FromPropertyDescriptor(Desc) {
+export function* FromPropertyDescriptor(Desc) {
if (Type(Desc) === 'Undefined') {
return Value.undefined;
}
const obj = ObjectCreate(surroundingAgent.intrinsic('%ObjectPrototype%'));
if (Desc.Value !== undefined) {
- X(CreateDataProperty(obj, new Value('value'), Desc.Value));
+ X(yield* CreateDataProperty(obj, new Value('value'), Desc.Value));
}
if (Desc.Writable !== undefined) {
- X(CreateDataProperty(obj, new Value('writable'), Desc.Writable));
+ X(yield* CreateDataProperty(obj, new Value('writable'), Desc.Writable));
}
if (Desc.Get !== undefined) {
- X(CreateDataProperty(obj, new Value('get'), Desc.Get));
+ X(yield* CreateDataProperty(obj, new Value('get'), Desc.Get));
}
if (Desc.Set !== undefined) {
- X(CreateDataProperty(obj, new Value('set'), Desc.Set));
+ X(yield* CreateDataProperty(obj, new Value('set'), Desc.Set));
}
if (Desc.Enumerable !== undefined) {
- X(CreateDataProperty(obj, new Value('enumerable'), Desc.Enumerable));
+ X(yield* CreateDataProperty(obj, new Value('enumerable'), Desc.Enumerable));
}
if (Desc.Configurable !== undefined) {
- X(CreateDataProperty(obj, new Value('configurable'), Desc.Configurable));
+ X(yield* CreateDataProperty(obj, new Value('configurable'), Desc.Configurable));
}
// Assert: All of the above CreateDataProperty operations return true.
return obj;
}
// 6.2.5.5 #sec-topropertydescriptor
-export function ToPropertyDescriptor(Obj) {
+export function* ToPropertyDescriptor(Obj) {
if (Type(Obj) !== 'Object') {
return surroundingAgent.Throw('TypeError', msg('NotAnObject', Obj));
}
const desc = Descriptor({});
- const hasEnumerable = Q(HasProperty(Obj, new Value('enumerable')));
+ const hasEnumerable = Q(yield* HasProperty(Obj, new Value('enumerable')));
if (hasEnumerable === Value.true) {
- const enumerable = ToBoolean(Q(Get(Obj, new Value('enumerable'))));
+ const enumerable = ToBoolean(Q(yield* Get(Obj, new Value('enumerable'))));
desc.Enumerable = enumerable;
}
- const hasConfigurable = Q(HasProperty(Obj, new Value('configurable')));
+ const hasConfigurable = Q(yield* HasProperty(Obj, new Value('configurable')));
if (hasConfigurable === Value.true) {
- const conf = ToBoolean(Q(Get(Obj, new Value('configurable'))));
+ const conf = ToBoolean(Q(yield* Get(Obj, new Value('configurable'))));
desc.Configurable = conf;
}
- const hasValue = Q(HasProperty(Obj, new Value('value')));
+ const hasValue = Q(yield* HasProperty(Obj, new Value('value')));
if (hasValue === Value.true) {
- const value = Q(Get(Obj, new Value('value')));
+ const value = Q(yield* Get(Obj, new Value('value')));
desc.Value = value;
}
- const hasWritable = Q(HasProperty(Obj, new Value('writable')));
+ const hasWritable = Q(yield* HasProperty(Obj, new Value('writable')));
if (hasWritable === Value.true) {
- const writable = ToBoolean(Q(Get(Obj, new Value('writable'))));
+ const writable = ToBoolean(Q(yield* Get(Obj, new Value('writable'))));
desc.Writable = writable;
}
- const hasGet = Q(HasProperty(Obj, new Value('get')));
+ const hasGet = Q(yield* HasProperty(Obj, new Value('get')));
if (hasGet === Value.true) {
- const getter = Q(Get(Obj, new Value('get')));
+ const getter = Q(yield* Get(Obj, new Value('get')));
if (IsCallable(getter) === Value.false && Type(getter) !== 'Undefined') {
return surroundingAgent.Throw('TypeError', msg('NotAFunction', getter));
}
desc.Get = getter;
}
- const hasSet = Q(HasProperty(Obj, new Value('set')));
+ const hasSet = Q(yield* HasProperty(Obj, new Value('set')));
if (hasSet === Value.true) {
- const setter = Q(Get(Obj, new Value('set')));
+ const setter = Q(yield* Get(Obj, new Value('set')));
if (IsCallable(setter) === Value.false && Type(setter) !== 'Undefined') {
return surroundingAgent.Throw('TypeError', msg('NotAFunction', setter));
}
@@ -136,7 +136,7 @@ export function ToPropertyDescriptor(Obj) {
}
// 6.2.5.6 #sec-completepropertydescriptor
-export function CompletePropertyDescriptor(Desc) {
+export function* CompletePropertyDescriptor(Desc) {
Assert(Type(Desc) === 'Descriptor');
const like = Descriptor({
Value: Value.undefined,
@@ -146,7 +146,7 @@ export function CompletePropertyDescriptor(Desc) {
Enumerable: false,
Configurable: false,
});
- if (IsGenericDescriptor(Desc) || IsDataDescriptor(Desc)) {
+ if ((yield* IsGenericDescriptor(Desc)) || (yield* IsDataDescriptor(Desc))) {
if (Desc.Value === undefined) {
Desc.Value = like.Value;
}
diff --git a/src/abstract-ops/string-objects.mjs b/src/abstract-ops/string-objects.mjs
index e583421..5947ebf 100644
--- a/src/abstract-ops/string-objects.mjs
+++ b/src/abstract-ops/string-objects.mjs
@@ -14,14 +14,14 @@ import {
import { X } from '../completion.mjs';
// 9.4.3.4 #sec-stringcreate
-export function StringCreate(value, prototype) {
+export function* StringCreate(value, prototype) {
Assert(Type(value) === 'String');
const S = new StringExoticObjectValue();
S.StringData = value;
S.Prototype = prototype;
S.Extensible = Value.true;
const length = new Value(value.stringValue().length);
- X(DefinePropertyOrThrow(S, new Value('length'), Descriptor({
+ X(yield* DefinePropertyOrThrow(S, new Value('length'), Descriptor({
Value: length,
Writable: Value.false,
Enumerable: Value.false,
@@ -30,13 +30,13 @@ export function StringCreate(value, prototype) {
return S;
}
-export function StringGetOwnProperty(S, P) {
+export function* StringGetOwnProperty(S, P) {
Assert(Type(S) === 'Object' && 'StringData' in S);
Assert(IsPropertyKey(P));
if (Type(P) !== 'String') {
return Value.undefined;
}
- const index = X(CanonicalNumericIndexString(P));
+ const index = X(yield* CanonicalNumericIndexString(P));
if (Type(index) === 'Undefined') {
return Value.undefined;
}
diff --git a/src/abstract-ops/testing-comparison.mjs b/src/abstract-ops/testing-comparison.mjs
index 1d1189b..9bdb8b0 100644
--- a/src/abstract-ops/testing-comparison.mjs
+++ b/src/abstract-ops/testing-comparison.mjs
@@ -21,11 +21,11 @@ import { Q, X } from '../completion.mjs';
import { OutOfRange, msg } from '../helpers.mjs';
// 6.1.7 #integer-index
-export function isIntegerIndex(V) {
+export function* isIntegerIndex(V) {
if (Type(V) !== 'String') {
return false;
}
- const numeric = X(CanonicalNumericIndexString(V));
+ const numeric = X(yield* CanonicalNumericIndexString(V));
if (numeric === Value.undefined) {
return false;
}
@@ -36,11 +36,11 @@ export function isIntegerIndex(V) {
}
// 6.1.7 #array-index
-export function isArrayIndex(V) {
+export function* isArrayIndex(V) {
if (Type(V) !== 'String') {
return false;
}
- const numeric = X(CanonicalNumericIndexString(V));
+ const numeric = X(yield* CanonicalNumericIndexString(V));
if (numeric === Value.undefined) {
return false;
}
@@ -110,7 +110,7 @@ export function IsConstructor(argument) {
}
// 7.2.5 IsExtensible
-export function IsExtensible(O) {
+export function* IsExtensible(O) {
Assert(Type(O) === 'Object');
return O.IsExtensible();
}
@@ -141,11 +141,11 @@ export function IsPropertyKey(argument) {
}
// 7.2.8 IsRegExp
-export function IsRegExp(argument) {
+export function* IsRegExp(argument) {
if (Type(argument) !== 'Object') {
return Value.false;
}
- const matcher = Q(Get(argument, wellKnownSymbols.match));
+ const matcher = Q(yield* Get(argument, wellKnownSymbols.match));
if (matcher !== Value.undefined) {
return ToBoolean(matcher);
}
@@ -249,21 +249,21 @@ export function SameValueNonNumber(x, y) {
}
// 7.2.13 #sec-abstract-relational-comparison
-export function AbstractRelationalComparison(x, y, LeftFirst = true) {
+export function* AbstractRelationalComparison(x, y, LeftFirst = true) {
let px;
let py;
if (LeftFirst === true) {
- px = Q(ToPrimitive(x, 'Number'));
- py = Q(ToPrimitive(y, 'Number'));
+ px = Q(yield* ToPrimitive(x, 'Number'));
+ py = Q(yield* ToPrimitive(y, 'Number'));
} else {
- py = Q(ToPrimitive(y, 'Number'));
- px = Q(ToPrimitive(x, 'Number'));
+ py = Q(yield* ToPrimitive(y, 'Number'));
+ px = Q(yield* ToPrimitive(x, 'Number'));
}
if (Type(px) === 'String' && Type(py) === 'String') {
- if (IsStringPrefix(py, px)) {
+ if (yield* IsStringPrefix(py, px)) {
return Value.false;
}
- if (IsStringPrefix(px, py)) {
+ if (yield* IsStringPrefix(px, py)) {
return Value.true;
}
let k = 0;
@@ -281,8 +281,8 @@ export function AbstractRelationalComparison(x, y, LeftFirst = true) {
return Value.false;
}
} else {
- const nx = Q(ToNumber(px));
- const ny = Q(ToNumber(py));
+ const nx = Q(yield* ToNumber(px));
+ const ny = Q(yield* ToNumber(py));
if (nx.isNaN()) {
return Value.undefined;
}
@@ -312,9 +312,9 @@ export function AbstractRelationalComparison(x, y, LeftFirst = true) {
}
// 7.2.14 #sec-abstract-equality-comparison
-export function AbstractEqualityComparison(x, y) {
+export function* AbstractEqualityComparison(x, y) {
if (Type(x) === Type(y)) {
- return StrictEqualityComparison(x, y);
+ return yield* StrictEqualityComparison(x, y);
}
if (x === Value.null && y === Value.undefined) {
return Value.true;
@@ -323,22 +323,22 @@ export function AbstractEqualityComparison(x, y) {
return Value.true;
}
if (Type(x) === 'Number' && Type(y) === 'String') {
- return AbstractEqualityComparison(x, X(ToNumber(y)));
+ return yield* AbstractEqualityComparison(x, X(yield* ToNumber(y)));
}
if (Type(x) === 'String' && Type(y) === 'Number') {
- return AbstractEqualityComparison(X(ToNumber(x)), y);
+ return yield* AbstractEqualityComparison(X(yield* ToNumber(x)), y);
}
if (Type(x) === 'Boolean') {
- return AbstractEqualityComparison(X(ToNumber(x)), y);
+ return yield* AbstractEqualityComparison(X(yield* ToNumber(x)), y);
}
if (Type(y) === 'Boolean') {
- return AbstractEqualityComparison(x, X(ToNumber(y)));
+ return yield* AbstractEqualityComparison(x, X(yield* ToNumber(y)));
}
if (['String', 'Number', 'Symbol'].includes(Type(x)) && Type(y) === 'Object') {
- return AbstractEqualityComparison(x, Q(ToPrimitive(y)));
+ return yield* AbstractEqualityComparison(x, Q(yield* ToPrimitive(y)));
}
if (Type(x) === 'Object' && ['String', 'Number', 'Symbol'].includes(Type(y))) {
- return AbstractEqualityComparison(Q(ToPrimitive(x)), y);
+ return yield* AbstractEqualityComparison(Q(yield* ToPrimitive(x)), y);
}
return Value.false;
}
@@ -373,9 +373,7 @@ export function StrictEqualityComparison(x, y) {
// 9.1.6.2 #sec-iscompatiblepropertydescriptor
export function IsCompatiblePropertyDescriptor(Extensible, Desc, Current) {
- return ValidateAndApplyPropertyDescriptor(
- Value.undefined, Value.undefined, Extensible, Desc, Current,
- );
+ return ValidateAndApplyPropertyDescriptor(Value.undefined, Value.undefined, Extensible, Desc, Current);
}
// 25.6.1.6 #sec-ispromise
diff --git a/src/abstract-ops/type-conversion.mjs b/src/abstract-ops/type-conversion.mjs
index d02ff11..a2e5373 100644
--- a/src/abstract-ops/type-conversion.mjs
+++ b/src/abstract-ops/type-conversion.mjs
@@ -22,7 +22,7 @@ import { Q, X } from '../completion.mjs';
import { OutOfRange, msg } from '../helpers.mjs';
// 7.1.1 #sec-toprimitive
-export function ToPrimitive(input, PreferredType) {
+export function* ToPrimitive(input, PreferredType) {
Assert(input instanceof Value);
if (Type(input) === 'Object') {
let hint;
@@ -34,9 +34,9 @@ export function ToPrimitive(input, PreferredType) {
Assert(PreferredType === 'Number');
hint = new Value('number');
}
- const exoticToPrim = Q(GetMethod(input, wellKnownSymbols.toPrimitive));
+ const exoticToPrim = Q(yield* GetMethod(input, wellKnownSymbols.toPrimitive));
if (exoticToPrim !== Value.undefined) {
- const result = Q(Call(exoticToPrim, input, [hint]));
+ const result = Q(yield* Call(exoticToPrim, input, [hint]));
if (Type(result) !== 'Object') {
return result;
}
@@ -45,13 +45,13 @@ export function ToPrimitive(input, PreferredType) {
if (hint.stringValue() === 'default') {
hint = new Value('number');
}
- return Q(OrdinaryToPrimitive(input, hint));
+ return Q(yield* OrdinaryToPrimitive(input, hint));
}
return input;
}
// 7.1.1.1 #sec-ordinarytoprimitive
-export function OrdinaryToPrimitive(O, hint) {
+export function* OrdinaryToPrimitive(O, hint) {
Assert(Type(O) === 'Object');
Assert(Type(hint) === 'String' && (hint.stringValue() === 'string' || hint.stringValue() === 'number'));
let methodNames;
@@ -61,9 +61,9 @@ export function OrdinaryToPrimitive(O, hint) {
methodNames = [new Value('valueOf'), new Value('toString')];
}
for (const name of methodNames) {
- const method = Q(Get(O, name));
+ const method = Q(yield* Get(O, name));
if (IsCallable(method) === Value.true) {
- const result = Q(Call(method, O));
+ const result = Q(yield* Call(method, O));
if (Type(result) !== 'Object') {
return result;
}
@@ -102,7 +102,7 @@ export function ToBoolean(argument) {
}
// 7.1.3 #sec-tonumber
-export function ToNumber(argument) {
+export function* ToNumber(argument) {
const type = Type(argument);
switch (type) {
case 'Undefined':
@@ -121,8 +121,8 @@ export function ToNumber(argument) {
case 'Symbol':
return surroundingAgent.Throw('TypeError', msg('CannotConvertSymbol', 'number'));
case 'Object': {
- const primValue = Q(ToPrimitive(argument, 'Number'));
- return Q(ToNumber(primValue));
+ const primValue = Q(yield* ToPrimitive(argument, 'Number'));
+ return Q(yield* ToNumber(primValue));
}
default:
throw new OutOfRange('ToNumber', { type, argument });
@@ -136,8 +136,8 @@ const mod = (n, m) => {
};
// 7.1.4 #sec-tointeger
-export function ToInteger(argument) {
- const number = Q(ToNumber(argument)).numberValue();
+export function* ToInteger(argument) {
+ const number = Q(yield* ToNumber(argument)).numberValue();
if (Number.isNaN(number)) {
return new Value(0);
}
@@ -149,8 +149,8 @@ export function ToInteger(argument) {
}
// 7.1.5 #sec-toint32
-export function ToInt32(argument) {
- const number = Q(ToNumber(argument)).numberValue();
+export function* ToInt32(argument) {
+ const number = Q(yield* ToNumber(argument)).numberValue();
if (Number.isNaN(number) || number === 0 || !Number.isFinite(number)) {
return new Value(0);
}
@@ -163,8 +163,8 @@ export function ToInt32(argument) {
}
// 7.1.6 #sec-touint32
-export function ToUint32(argument) {
- const number = Q(ToNumber(argument)).numberValue();
+export function* ToUint32(argument) {
+ const number = Q(yield* ToNumber(argument)).numberValue();
if (Number.isNaN(number) || number === 0 || !Number.isFinite(number)) {
return new Value(0);
}
@@ -174,8 +174,8 @@ export function ToUint32(argument) {
}
// 7.1.7 #sec-toint16
-export function ToInt16(argument) {
- const number = Q(ToNumber(argument)).numberValue();
+export function* ToInt16(argument) {
+ const number = Q(yield* ToNumber(argument)).numberValue();
if (Number.isNaN(number) || number === 0 || !Number.isFinite(number)) {
return new Value(0);
}
@@ -188,8 +188,8 @@ export function ToInt16(argument) {
}
// 7.1.8 #sec-touint16
-export function ToUint16(argument) {
- const number = Q(ToNumber(argument)).numberValue();
+export function* ToUint16(argument) {
+ const number = Q(yield* ToNumber(argument)).numberValue();
if (Number.isNaN(number) || number === 0 || !Number.isFinite(number)) {
return new Value(0);
}
@@ -199,8 +199,8 @@ export function ToUint16(argument) {
}
// 7.1.9 #sec-toint8
-export function ToInt8(argument) {
- const number = Q(ToNumber(argument)).numberValue();
+export function* ToInt8(argument) {
+ const number = Q(yield* ToNumber(argument)).numberValue();
if (Number.isNaN(number) || number === 0 || !Number.isFinite(number)) {
return new Value(0);
}
@@ -213,8 +213,8 @@ export function ToInt8(argument) {
}
// 7.1.10 #sec-touint8
-export function ToUint8(argument) {
- const number = Q(ToNumber(argument)).numberValue();
+export function* ToUint8(argument) {
+ const number = Q(yield* ToNumber(argument)).numberValue();
if (Number.isNaN(number) || number === 0 || !Number.isFinite(number)) {
return new Value(0);
}
@@ -224,8 +224,8 @@ export function ToUint8(argument) {
}
// 7.1.11 #sec-touint8clamp
-export function ToUint8Clamp(argument) {
- const number = Q(ToNumber(argument)).numberValue();
+export function* ToUint8Clamp(argument) {
+ const number = Q(yield* ToNumber(argument)).numberValue();
if (Number.isNaN(number)) {
return new Value(0);
}
@@ -249,7 +249,7 @@ export function ToUint8Clamp(argument) {
}
// 7.1.12 #sec-tostring
-export function ToString(argument) {
+export function* ToString(argument) {
const type = Type(argument);
switch (type) {
case 'Undefined':
@@ -259,14 +259,14 @@ export function ToString(argument) {
case 'Boolean':
return new Value(argument === Value.true ? 'true' : 'false');
case 'Number':
- return NumberToString(argument);
+ return yield* NumberToString(argument);
case 'String':
return argument;
case 'Symbol':
return surroundingAgent.Throw('TypeError', msg('CannotConvertSymbol', 'string'));
case 'Object': {
- const primValue = Q(ToPrimitive(argument, 'String'));
- return Q(ToString(primValue));
+ const primValue = Q(yield* ToPrimitive(argument, 'String'));
+ return Q(yield* ToString(primValue));
}
default:
throw new OutOfRange('ToString', { type, argument });
@@ -274,7 +274,7 @@ export function ToString(argument) {
}
// 7.1.12.1 #sec-tostring-applied-to-the-number-type
-export function NumberToString(m) {
+export function* NumberToString(m) {
if (m.isNaN()) {
return new Value('NaN');
}
@@ -283,7 +283,7 @@ export function NumberToString(m) {
return new Value('0');
}
if (mVal < 0) {
- const str = X(NumberToString(new Value(-mVal))).stringValue();
+ const str = X(yield* NumberToString(new Value(-mVal))).stringValue();
return new Value(`-${str}`);
}
if (m.isInfinity()) {
@@ -294,7 +294,7 @@ export function NumberToString(m) {
}
// 7.1.13 #sec-toobject
-export function ToObject(argument) {
+export function* ToObject(argument) {
const type = Type(argument);
switch (type) {
case 'Undefined':
@@ -312,7 +312,7 @@ export function ToObject(argument) {
return obj;
}
case 'String':
- return StringCreate(argument, surroundingAgent.intrinsic('%StringPrototype%'));
+ return yield* StringCreate(argument, surroundingAgent.intrinsic('%StringPrototype%'));
case 'Symbol': {
const obj = ObjectCreate(surroundingAgent.intrinsic('%SymbolPrototype%'));
obj.SymbolData = argument;
@@ -326,17 +326,17 @@ export function ToObject(argument) {
}
// 7.1.14 #sec-topropertykey
-export function ToPropertyKey(argument) {
- const key = Q(ToPrimitive(argument, 'String'));
+export function* ToPropertyKey(argument) {
+ const key = Q(yield* ToPrimitive(argument, 'String'));
if (Type(key) === 'Symbol') {
return key;
}
- return X(ToString(key));
+ return X(yield* ToString(key));
}
// 7.1.15 #sec-tolength
-export function ToLength(argument) {
- const len = Q(ToInteger(argument));
+export function* ToLength(argument) {
+ const len = Q(yield* ToInteger(argument));
if (len.numberValue() <= 0) {
return new Value(0);
}
@@ -344,29 +344,29 @@ export function ToLength(argument) {
}
// 7.1.16 #sec-canonicalnumericindexstring
-export function CanonicalNumericIndexString(argument) {
+export function* CanonicalNumericIndexString(argument) {
Assert(Type(argument) === 'String');
if (argument.stringValue() === '-0') {
return new Value(-0);
}
- const n = X(ToNumber(argument));
- if (SameValue(X(ToString(n)), argument) === Value.false) {
+ const n = X(yield* ToNumber(argument));
+ if (SameValue(X(yield* ToString(n)), argument) === Value.false) {
return Value.undefined;
}
return n;
}
// 7.1.17 #sec-toindex
-export function ToIndex(value) {
+export function* ToIndex(value) {
let index;
if (Type(value) === 'Undefined') {
index = new Value(0);
} else {
- const integerIndex = Q(ToInteger(value));
+ const integerIndex = Q(yield* ToInteger(value));
if (integerIndex.numberValue() < 0) {
return surroundingAgent.Throw('RangeError', msg('NegativeIndex'));
}
- index = X(ToLength(integerIndex));
+ index = X(yield* ToLength(integerIndex));
if (SameValueZero(integerIndex, index) === Value.false) {
return surroundingAgent.Throw('RangeError', msg('OutOfRange', 'Index'));
}
diff --git a/src/abstract-ops/typedarray-objects.mjs b/src/abstract-ops/typedarray-objects.mjs
index e8b00a2..624c359 100644
--- a/src/abstract-ops/typedarray-objects.mjs
+++ b/src/abstract-ops/typedarray-objects.mjs
@@ -52,14 +52,14 @@ export const typedArrayInfo = new Map([
export const numericTypeInfo = new Map([...typedArrayInfo.values()].map((info) => [info.ElementType, info]));
// 22.2.2.1.1 #sec-iterabletolist
-export function IterableToList(items, method) {
- const iteratorRecord = Q(GetIterator(items, 'sync', method));
+export function* IterableToList(items, method) {
+ const iteratorRecord = Q(yield* GetIterator(items, 'sync', method));
const values = [];
let next = Value.true;
while (next !== Value.false) {
- next = Q(IteratorStep(iteratorRecord));
+ next = Q(yield* IteratorStep(iteratorRecord));
if (next !== Value.false) {
- const nextValue = Q(IteratorValue(next));
+ const nextValue = Q(yield* IteratorValue(next));
values.push(nextValue);
}
}
@@ -80,9 +80,12 @@ export function ValidateTypedArray(O) {
}
// 22.2.4.2.1 #sec-allocatetypedarray
-export function AllocateTypedArray(constructorName, newTarget, defaultProto, length) {
- const proto = Q(GetPrototypeFromConstructor(newTarget, defaultProto));
- const obj = IntegerIndexedObjectCreate(proto, ['ViewedArrayBuffer', 'TypedArrayName', 'ByteLength', 'ByteOffset', 'ArrayLength']);
+export function* AllocateTypedArray(constructorName, newTarget, defaultProto, length) {
+ const proto = Q(yield* GetPrototypeFromConstructor(newTarget, defaultProto));
+ const obj = IntegerIndexedObjectCreate(
+ proto,
+ ['ViewedArrayBuffer', 'TypedArrayName', 'ByteLength', 'ByteOffset', 'ArrayLength'],
+ );
Assert(obj.ViewedArrayBuffer === Value.undefined);
obj.TypedArrayName = constructorName;
if (length === undefined) {
@@ -90,20 +93,20 @@ export function AllocateTypedArray(constructorName, newTarget, defaultProto, len
obj.ByteOffset = new Value(0);
obj.ArrayLength = new Value(0);
} else {
- Q(AllocateTypedArrayBuffer(obj, length));
+ Q(yield* AllocateTypedArrayBuffer(obj, length));
}
return obj;
}
// 22.2.4.2.2 #sec-allocatetypedarraybuffer
-export function AllocateTypedArrayBuffer(O, length) {
+export function* AllocateTypedArrayBuffer(O, length) {
Assert(Type(O) === 'Object' && 'ViewedArrayBuffer' in O);
Assert(O.ViewedArrayBuffer === Value.undefined);
Assert(length.numberValue() >= 0);
const constructorName = O.TypedArrayName.stringValue();
const elementSize = typedArrayInfo.get(constructorName).ElementSize;
const byteLength = new Value(elementSize * length.numberValue());
- const data = Q(AllocateArrayBuffer(surroundingAgent.intrinsic('%ArrayBuffer%'), byteLength));
+ const data = Q(yield* AllocateArrayBuffer(surroundingAgent.intrinsic('%ArrayBuffer%'), byteLength));
O.ViewedArrayBuffer = data;
O.ByteLength = byteLength;
O.ByteOffset = new Value(0);
@@ -112,8 +115,8 @@ export function AllocateTypedArrayBuffer(O, length) {
}
// 22.2.4.6 #typedarray-create
-export function TypedArrayCreate(constructor, argumentList) {
- const newTypedArray = Q(Construct(constructor, argumentList));
+export function* TypedArrayCreate(constructor, argumentList) {
+ const newTypedArray = Q(yield* Construct(constructor, argumentList));
Q(ValidateTypedArray(newTypedArray));
if (argumentList.length === 1 && Type(argumentList[0]) === 'Number') {
if (newTypedArray.ArrayLength.numberValue() < argumentList[0].numberValue()) {
@@ -124,10 +127,10 @@ export function TypedArrayCreate(constructor, argumentList) {
}
// 22.2.4.7 #typedarray-species-create
-export function TypedArraySpeciesCreate(exemplar, argumentList) {
+export function* TypedArraySpeciesCreate(exemplar, argumentList) {
Assert(Type(exemplar) === 'Object' && 'TypedArrayName' in exemplar);
const intrinsicName = typedArrayInfo.get(exemplar.TypedArrayName.stringValue()).Intrinsic;
const defaultConstructor = surroundingAgent.intrinsic(intrinsicName);
- const constructor = Q(SpeciesConstructor(exemplar, defaultConstructor));
- return Q(TypedArrayCreate(constructor, argumentList));
+ const constructor = Q(yield* SpeciesConstructor(exemplar, defaultConstructor));
+ return Q(yield* TypedArrayCreate(constructor, argumentList));
}
diff --git a/src/api.mjs b/src/api.mjs
index 42d1488..61bd25e 100644
--- a/src/api.mjs
+++ b/src/api.mjs
@@ -26,10 +26,10 @@ import {
NormalCompletion,
Q, X,
ThrowCompletion,
- EnsureCompletion,
+ // EnsureCompletion,
} from './completion.mjs';
import * as AbstractOps from './abstract-ops/all.mjs';
-import { OutOfRange } from './helpers.mjs';
+import { OutOfRange, unwind } from './helpers.mjs';
export const Abstract = { ...AbstractOps, Type };
const {
@@ -116,11 +116,11 @@ class APIRealm {
}
// END ScriptEvaluationJob
- const res = Q(ScriptEvaluation(s));
+ return ScriptEvaluation(s);
- runJobQueue();
+ // runJobQueue();
- return EnsureCompletion(res);
+ // return EnsureCompletion(res);
});
}
@@ -257,7 +257,7 @@ export {
const getObjectTag = (value, wrap) => {
try {
- const s = X(AbstractOps.Get(value, wellKnownSymbols.toStringTag)).stringValue();
+ const s = X(unwind(AbstractOps.Get(value, wellKnownSymbols.toStringTag))).stringValue();
if (wrap) {
return `[${s}] `;
}
@@ -279,12 +279,12 @@ export function inspect(v, realm = surroundingAgent.currentRealmRecord, compact
try {
const objectToString = realm.Intrinsics['%ObjProto_toString%'];
if (toString.nativeFunction === objectToString.nativeFunction) {
- return X(AbstractOps.Call(toString, value, [])).stringValue();
+ return X(unwind(AbstractOps.Call(toString, value, []))).stringValue();
} else {
const tag = getObjectTag(value, false) || 'Unknown';
- const ctor = X(AbstractOps.Get(value, new Value('constructor')));
+ const ctor = X(unwind(AbstractOps.Get(value, new Value('constructor'))));
if (Type(ctor) === 'Object') {
- const ctorName = X(AbstractOps.Get(ctor, new Value('name'))).stringValue();
+ const ctorName = X(unwind(AbstractOps.Get(ctor, new Value('name')))).stringValue();
if (ctorName !== '') {
return `#<${ctorName}>`;
}
@@ -292,7 +292,7 @@ export function inspect(v, realm = surroundingAgent.currentRealmRecord, compact
}
return `[object ${tag}]`;
}
- } catch (e) {
+ } catch {
return '[object Unknown]';
}
};
@@ -323,7 +323,7 @@ export function inspect(v, realm = surroundingAgent.currentRealmRecord, compact
inspected.add(value);
if ('Call' in value) {
const name = value.properties.get(new Value('name'));
- if (name !== undefined) {
+ if (name !== undefined && name.Value && name.Value.stringValue && name.Value.stringValue()) {
return `[Function: ${name.Value.stringValue()}]`;
}
return '[Function]';
@@ -338,11 +338,11 @@ export function inspect(v, realm = surroundingAgent.currentRealmRecord, compact
}`;
}
const errorToString = realm.Intrinsics['%ErrorPrototype%'].properties.get(new Value('toString')).Value;
- const toString = Q(AbstractOps.Get(value, new Value('toString')));
+ const toString = Q(unwind(AbstractOps.Get(value, new Value('toString'))));
if (toString.nativeFunction === errorToString.nativeFunction) {
- let e = Q(AbstractOps.Get(value, new Value('stack')));
+ let e = Q(unwind(AbstractOps.Get(value, new Value('stack'))));
if (!e.stringValue) {
- e = X(AbstractOps.Call(toString, value));
+ e = X(unwind(AbstractOps.Call(toString, value)));
}
return e.stringValue();
}
@@ -363,7 +363,7 @@ export function inspect(v, realm = surroundingAgent.currentRealmRecord, compact
}
try {
const tag = getObjectTag(value, true);
- const keys = X(value.OwnPropertyKeys());
+ const keys = X(unwind(value.OwnPropertyKeys()));
if (keys.length === 0) {
return `${tag}{}`;
}
@@ -372,7 +372,7 @@ export function inspect(v, realm = surroundingAgent.currentRealmRecord, compact
if (keys.length > 5) {
indent += 1;
for (const key of keys) {
- const C = X(value.GetOwnProperty(key));
+ const C = X(unwind(value.GetOwnProperty(key)));
out = `${out}\n${' '.repeat(indent)}${innerInspect(key, false)}: ${innerInspect(C.Value)},`;
}
indent -= 1;
@@ -381,13 +381,13 @@ export function inspect(v, realm = surroundingAgent.currentRealmRecord, compact
const oc = compact;
compact = true;
for (const key of keys) {
- const C = X(value.GetOwnProperty(key));
+ const C = X(unwind(value.GetOwnProperty(key)));
out = `${out} ${innerInspect(key, false)}: ${innerInspect(C.Value)},`;
}
compact = oc;
return `${out.slice(0, -1)} ${isArray ? ']' : '}'}`;
}
- } catch (e) {
+ } catch {
return compactObject(toString);
}
}
diff --git a/src/completion.mjs b/src/completion.mjs
index 3b0703d..adeda84 100644
--- a/src/completion.mjs
+++ b/src/completion.mjs
@@ -22,6 +22,12 @@ export function Completion(type, value, target) {
return type;
}
+function __DELETE_ME__(v) {
+ if (v && v.next && v.return) {
+ throw new Error('HECK YOU');
+ }
+}
+
// 6.2.3.2 #sec-normalcompletion
export class NormalCompletion {
constructor(value) {
@@ -35,6 +41,7 @@ export class NormalCompletion {
export class AbruptCompletion {
static [Symbol.hasInstance](v) {
+ __DELETE_ME__(v);
return v instanceof Completion && v.Type !== 'normal';
}
}
@@ -116,6 +123,7 @@ export function IfAbruptRejectPromise() {
}
export function EnsureCompletion(val) {
+ __DELETE_ME__(val);
if (val instanceof Completion) {
return val;
}
@@ -149,16 +157,16 @@ function AwaitRejectedFunctions([reason]) {
export function* Await(value) {
const asyncContext = surroundingAgent.runningExecutionContext;
- const promise = Q(PromiseResolve(surroundingAgent.intrinsic('%Promise%'), value));
+ const promise = Q(yield* PromiseResolve(surroundingAgent.intrinsic('%Promise%'), value));
const stepsFulfilled = AwaitFulfilledFunctions;
const onFulfilled = CreateBuiltinFunction(stepsFulfilled, ['AsyncContext']);
- X(SetFunctionLength(onFulfilled, new Value(1)));
+ X(yield* SetFunctionLength(onFulfilled, new Value(1)));
onFulfilled.AsyncContext = asyncContext;
const stepsRejected = AwaitRejectedFunctions;
const onRejected = CreateBuiltinFunction(stepsRejected, ['AsyncContext']);
- X(SetFunctionLength(onRejected, new Value(1)));
+ X(yield* SetFunctionLength(onRejected, new Value(1)));
onRejected.AsyncContext = asyncContext;
- X(PerformPromiseThen(promise, onFulfilled, onRejected));
+ X(yield* PerformPromiseThen(promise, onFulfilled, onRejected));
surroundingAgent.executionContextStack.pop(asyncContext);
const completion = yield Value.undefined;
return completion;
diff --git a/src/engine.mjs b/src/engine.mjs
index 4f164c1..b9db24a 100644
--- a/src/engine.mjs
+++ b/src/engine.mjs
@@ -15,7 +15,7 @@ import {
import { Construct, Assert } from './abstract-ops/all.mjs';
import { GlobalDeclarationInstantiation } from './runtime-semantics/all.mjs';
import { Evaluate_Script } from './evaluator.mjs';
-import { msg } from './helpers.mjs';
+import { msg, unwind } from './helpers.mjs';
export class Agent {
constructor(options = {}) {
@@ -62,7 +62,7 @@ export class Agent {
Throw(type, message) {
const cons = this.currentRealmRecord.Intrinsics[`%${type}%`];
- const error = Construct(cons, message ? [new Value(message)] : []);
+ const error = unwind(Construct(cons, message ? [new Value(message)] : []));
error.hostTrace = new Error().stack;
return new ThrowCompletion(error);
}
@@ -168,7 +168,7 @@ export function AgentSignifier() {
}
// 15.1.10 #sec-runtime-semantics-scriptevaluation
-export function ScriptEvaluation(scriptRecord) {
+export function* ScriptEvaluation(scriptRecord) {
const globalEnv = scriptRecord.Realm.GlobalEnv;
const scriptCtx = new ExecutionContext();
scriptCtx.Function = Value.null;
@@ -180,9 +180,9 @@ export function ScriptEvaluation(scriptRecord) {
// Suspend runningExecutionContext
surroundingAgent.executionContextStack.push(scriptCtx);
const scriptBody = scriptRecord.ECMAScriptCode.body;
- let result = EnsureCompletion(GlobalDeclarationInstantiation(scriptBody, globalEnv));
+ let result = EnsureCompletion(yield* GlobalDeclarationInstantiation(scriptBody, globalEnv));
if (result.Type === 'normal') {
- result = Evaluate_Script(scriptBody, globalEnv);
+ result = yield* Evaluate_Script(scriptBody, globalEnv);
}
if (result.Type === 'normal' && !result.Value) {
result = new NormalCompletion(Value.undefined);
diff --git a/src/environment.mjs b/src/environment.mjs
index af8f8a8..2c27da9 100644
--- a/src/environment.mjs
+++ b/src/environment.mjs
@@ -39,7 +39,7 @@ export class DeclarativeEnvironmentRecord extends EnvironmentRecord {
this.bindings = new Map();
}
- HasBinding(N) {
+ * HasBinding(N) {
Assert(IsPropertyKey(N));
if (this.bindings.has(N)) {
return Value.true;
@@ -47,7 +47,7 @@ export class DeclarativeEnvironmentRecord extends EnvironmentRecord {
return Value.false;
}
- CreateMutableBinding(N, D) {
+ * CreateMutableBinding(N, D) {
Assert(IsPropertyKey(N));
this.bindings.set(N, {
indirect: false,
@@ -59,7 +59,7 @@ export class DeclarativeEnvironmentRecord extends EnvironmentRecord {
});
}
- CreateImmutableBinding(N, S) {
+ * CreateImmutableBinding(N, S) {
Assert(IsPropertyKey(N));
this.bindings.set(N, {
indirect: false,
@@ -71,7 +71,7 @@ export class DeclarativeEnvironmentRecord extends EnvironmentRecord {
});
}
- InitializeBinding(N, V) {
+ * InitializeBinding(N, V) {
Assert(IsPropertyKey(N));
const binding = this.bindings.get(N);
Assert(binding !== undefined);
@@ -79,15 +79,15 @@ export class DeclarativeEnvironmentRecord extends EnvironmentRecord {
binding.initialized = true;
}
- SetMutableBinding(N, V, S) {
+ * SetMutableBinding(N, V, S) {
Assert(IsPropertyKey(N));
const envRec = this;
if (!this.bindings.has(N)) {
if (S === Value.true) {
return surroundingAgent.Throw('ReferenceError', msg('NotDefined', N));
}
- envRec.CreateMutableBinding(N, true);
- envRec.InitializeBinding(N, V);
+ yield* envRec.CreateMutableBinding(N, true);
+ yield* envRec.InitializeBinding(N, V);
return new NormalCompletion(undefined);
}
@@ -107,7 +107,7 @@ export class DeclarativeEnvironmentRecord extends EnvironmentRecord {
return new NormalCompletion(undefined);
}
- GetBindingValue(N) {
+ * GetBindingValue(N) {
Assert(IsPropertyKey(N));
const binding = this.bindings.get(N);
if (binding.initialized === false) {
@@ -150,12 +150,12 @@ export class ObjectEnvironmentRecord extends EnvironmentRecord {
}
// 8.1.1.2.1 #sec-object-environment-records-hasbinding-n
- HasBinding(N) {
+ * HasBinding(N) {
Assert(IsPropertyKey(N));
const envRec = this;
const bindings = envRec.bindingObject;
- const foundBinding = Q(HasProperty(bindings, N));
+ const foundBinding = Q(yield* HasProperty(bindings, N));
if (foundBinding === Value.false) {
return Value.false;
}
@@ -166,7 +166,7 @@ export class ObjectEnvironmentRecord extends EnvironmentRecord {
const unscopables = Q(Get(bindings, wellKnownSymbols.unscopables));
if (Type(unscopables) === 'Object') {
- const blocked = ToBoolean(Q(Get(unscopables, N)));
+ const blocked = ToBoolean(Q(yield* Get(unscopables, N)));
if (blocked === Value.true) {
return Value.false;
}
@@ -176,11 +176,11 @@ export class ObjectEnvironmentRecord extends EnvironmentRecord {
}
// 8.1.1.2.2 #sec-object-environment-records-createmutablebinding-n-d
- CreateMutableBinding(N, D) {
+ * CreateMutableBinding(N, D) {
Assert(IsPropertyKey(N));
const envRec = this;
const bindings = envRec.bindingObject;
- return Q(DefinePropertyOrThrow(bindings, N, Descriptor({
+ return Q(yield* DefinePropertyOrThrow(bindings, N, Descriptor({
Value: Value.undefined,
Writable: Value.true,
Enumerable: Value.true,
@@ -194,28 +194,28 @@ export class ObjectEnvironmentRecord extends EnvironmentRecord {
}
// 8.1.1.2.4 #sec-object-environment-records-initializebinding-n-v
- InitializeBinding(N, V) {
+ * InitializeBinding(N, V) {
Assert(IsPropertyKey(N));
const envRec = this;
// Record that the binding for N in envRec has been initialized.
// According to the spec this is an unnecessary step for object Environment Records.
- return Q(envRec.SetMutableBinding(N, V, Value.false));
+ return Q(yield* envRec.SetMutableBinding(N, V, Value.false));
}
// 8.1.1.2.5 #sec-object-environment-records-setmutablebinding-n-v-s
- SetMutableBinding(N, V, S) {
+ * SetMutableBinding(N, V, S) {
Assert(IsPropertyKey(N));
const envRec = this;
const bindings = envRec.bindingObject;
- return Q(Set(bindings, N, V, S));
+ return Q(yield* Set(bindings, N, V, S));
}
// 8.1.1.2.6 #sec-object-environment-records-getbindingvalue-n-s
- GetBindingValue(N, S) {
+ * GetBindingValue(N, S) {
Assert(IsPropertyKey(N));
const envRec = this;
const bindings = envRec.bindingObject;
- const value = Q(HasProperty(bindings, N));
+ const value = Q(yield* HasProperty(bindings, N));
if (value === Value.false) {
if (S === Value.false) {
return Value.undefined;
@@ -223,15 +223,15 @@ export class ObjectEnvironmentRecord extends EnvironmentRecord {
return surroundingAgent.Throw('ReferenceError', msg('NotDefined', N));
}
}
- return Q(Get(bindings, N));
+ return Q(yield* Get(bindings, N));
}
// 8.1.1.2.7 #sec-object-environment-records-deletebinding-n
- DeleteBinding(N) {
+ * DeleteBinding(N) {
Assert(IsPropertyKey(N));
const envRec = this;
const bindings = envRec.bindingObject;
- return Q(bindings.Delete(N));
+ return Q(yield* bindings.Delete(N));
}
// 8.1.1.2.8 #sec-object-environment-records-hasthisbinding
@@ -304,14 +304,14 @@ export class FunctionEnvironmentRecord extends DeclarativeEnvironmentRecord {
return envRec.ThisValue;
}
- GetSuperBase() {
+ * GetSuperBase() {
const envRec = this;
const home = envRec.HomeObject;
if (Type(home) === 'Undefined') {
return Value.undefined;
}
Assert(Type(home) === 'Object');
- return Q(home.GetPrototypeOf());
+ return Q(yield* home.GetPrototypeOf());
}
}
@@ -324,82 +324,82 @@ export class GlobalEnvironmentRecord extends EnvironmentRecord {
this.VarNames = undefined;
}
- HasBinding(N) {
+ * HasBinding(N) {
Assert(IsPropertyKey(N));
const envRec = this;
const DclRec = envRec.DeclarativeRecord;
- if (DclRec.HasBinding(N) === Value.true) {
+ if ((yield* DclRec.HasBinding(N)) === Value.true) {
return Value.true;
}
const ObjRec = envRec.ObjectRecord;
- return ObjRec.HasBinding(N);
+ return yield* ObjRec.HasBinding(N);
}
- CreateMutableBinding(N, D) {
+ * CreateMutableBinding(N, D) {
Assert(IsPropertyKey(N));
const envRec = this;
const DclRec = envRec.DeclarativeRecord;
- if (DclRec.HasBinding(N) === Value.true) {
+ if ((yield* DclRec.HasBinding(N)) === Value.true) {
return surroundingAgent.Throw('TypeError', msg('AlreadyDeclared', N));
}
- return DclRec.CreateMutableBinding(N, D);
+ return yield* DclRec.CreateMutableBinding(N, D);
}
- CreateImmutableBinding(N, S) {
+ * CreateImmutableBinding(N, S) {
Assert(IsPropertyKey(N));
const envRec = this;
const DclRec = envRec.DeclarativeRecord;
- if (DclRec.HasBinding(N) === Value.true) {
+ if ((yield* DclRec.HasBinding(N)) === Value.true) {
return surroundingAgent.Throw('TypeError', msg('AlreadyDeclared', N));
}
- return DclRec.CreateImmutableBinding(N, S);
+ return yield* DclRec.CreateImmutableBinding(N, S);
}
- InitializeBinding(N, V) {
+ * InitializeBinding(N, V) {
Assert(IsPropertyKey(N));
const envRec = this;
const DclRec = envRec.DeclarativeRecord;
- if (DclRec.HasBinding(N) === Value.true) {
- return DclRec.InitializeBinding(N, V);
+ if ((yield* DclRec.HasBinding(N)) === Value.true) {
+ return yield* DclRec.InitializeBinding(N, V);
}
const ObjRec = envRec.ObjectRecord;
- return ObjRec.InitializeBinding(N, V);
+ return yield* ObjRec.InitializeBinding(N, V);
}
- SetMutableBinding(N, V, S) {
+ * SetMutableBinding(N, V, S) {
Assert(IsPropertyKey(N));
const envRec = this;
const DclRec = envRec.DeclarativeRecord;
- if (DclRec.HasBinding(N) === Value.true) {
+ if ((yield* DclRec.HasBinding(N)) === Value.true) {
return DclRec.SetMutableBinding(N, V, S);
}
const ObjRec = envRec.ObjectRecord;
- return Q(ObjRec.SetMutableBinding(N, V, S));
+ return Q(yield* ObjRec.SetMutableBinding(N, V, S));
}
- GetBindingValue(N, S) {
+ * GetBindingValue(N, S) {
Assert(IsPropertyKey(N));
const envRec = this;
const DclRec = envRec.DeclarativeRecord;
- if (DclRec.HasBinding(N) === Value.true) {
- return DclRec.GetBindingValue(N, S);
+ if ((yield* DclRec.HasBinding(N)) === Value.true) {
+ return yield* DclRec.GetBindingValue(N, S);
}
const ObjRec = envRec.ObjectRecord;
- return Q(ObjRec.GetBindingValue(N, S));
+ return Q(yield* ObjRec.GetBindingValue(N, S));
}
- DeleteBinding(N) {
+ * DeleteBinding(N) {
Assert(IsPropertyKey(N));
const envRec = this;
const DclRec = this.DeclarativeRecord;
- if (DclRec.HasBinding(N) === Value.true) {
+ if ((yield* DclRec.HasBinding(N)) === Value.true) {
return Q(DclRec.DeleteBinding(N));
}
const ObjRec = envRec.ObjectRecord;
const globalObject = ObjRec.bindingObject;
- const existingProp = Q(HasOwnProperty(globalObject, N));
+ const existingProp = Q(yield* HasOwnProperty(globalObject, N));
if (existingProp === Value.true) {
- const status = Q(ObjRec.DeleteBinding(N));
+ const status = Q(yield* ObjRec.DeleteBinding(N));
if (status === Value.true) {
const varNames = envRec.VarNames;
if (varNames.includes(N)) {
@@ -438,19 +438,19 @@ export class GlobalEnvironmentRecord extends EnvironmentRecord {
return Value.false;
}
- HasLexicalDeclaration(N) {
+ * HasLexicalDeclaration(N) {
Assert(IsPropertyKey(N));
const envRec = this;
const DclRec = envRec.DeclarativeRecord;
return DclRec.HasBinding(N);
}
- HasRestrictedGlobalProperty(N) {
+ * HasRestrictedGlobalProperty(N) {
Assert(IsPropertyKey(N));
const envRec = this;
const ObjRec = envRec.ObjectRecord;
const globalObject = ObjRec.bindingObject;
- const existingProp = Q(globalObject.GetOwnProperty(N));
+ const existingProp = Q(yield* globalObject.GetOwnProperty(N));
if (existingProp === Value.undefined) {
return Value.false;
}
@@ -460,26 +460,26 @@ export class GlobalEnvironmentRecord extends EnvironmentRecord {
return Value.true;
}
- CanDeclareGlobalVar(N) {
+ * CanDeclareGlobalVar(N) {
Assert(IsPropertyKey(N));
const envRec = this;
const ObjRec = envRec.ObjectRecord;
const globalObject = ObjRec.bindingObject;
- const hasProperty = Q(HasOwnProperty(globalObject, N));
+ const hasProperty = Q(yield* HasOwnProperty(globalObject, N));
if (hasProperty === Value.true) {
return Value.true;
}
- return Q(IsExtensible(globalObject));
+ return Q(yield* IsExtensible(globalObject));
}
- CanDeclareGlobalFunction(N) {
+ * CanDeclareGlobalFunction(N) {
Assert(IsPropertyKey(N));
const envRec = this;
const ObjRec = envRec.ObjectRecord;
const globalObject = ObjRec.bindingObject;
- const existingProp = Q(globalObject.GetOwnProperty(N));
+ const existingProp = Q(yield* globalObject.GetOwnProperty(N));
if (Type(existingProp) === 'Undefined') {
- return Q(IsExtensible(globalObject));
+ return Q(yield* IsExtensible(globalObject));
}
if (existingProp.Configurable === Value.true) {
return Value.true;
@@ -492,16 +492,16 @@ export class GlobalEnvironmentRecord extends EnvironmentRecord {
return Value.false;
}
- CreateGlobalVarBinding(N, D) {
+ * CreateGlobalVarBinding(N, D) {
Assert(IsPropertyKey(N));
const envRec = this;
const ObjRec = envRec.ObjectRecord;
const globalObject = ObjRec.bindingObject;
- const hasProperty = Q(HasOwnProperty(globalObject, N));
- const extensible = Q(IsExtensible(globalObject));
+ const hasProperty = Q(yield* HasOwnProperty(globalObject, N));
+ const extensible = Q(yield* IsExtensible(globalObject));
if (hasProperty === Value.false && extensible === Value.true) {
- Q(ObjRec.CreateMutableBinding(N, D));
- Q(ObjRec.InitializeBinding(N, Value.undefined));
+ Q(yield* ObjRec.CreateMutableBinding(N, D));
+ Q(yield* ObjRec.InitializeBinding(N, Value.undefined));
}
const varDeclaredNames = envRec.VarNames;
if (!varDeclaredNames.includes(N)) {
@@ -510,12 +510,12 @@ export class GlobalEnvironmentRecord extends EnvironmentRecord {
return new NormalCompletion(undefined);
}
- CreateGlobalFunctionBinding(N, V, D) {
+ * CreateGlobalFunctionBinding(N, V, D) {
Assert(IsPropertyKey(N));
const envRec = this;
const ObjRec = envRec.ObjectRecord;
const globalObject = ObjRec.bindingObject;
- const existingProp = Q(globalObject.GetOwnProperty(N));
+ const existingProp = Q(yield* globalObject.GetOwnProperty(N));
let desc;
if (Type(existingProp) === 'Undefined' || existingProp.Configurable === Value.true) {
desc = Descriptor({
@@ -529,9 +529,9 @@ export class GlobalEnvironmentRecord extends EnvironmentRecord {
Value: V,
});
}
- Q(DefinePropertyOrThrow(globalObject, N, desc));
+ Q(yield* DefinePropertyOrThrow(globalObject, N, desc));
// Record that the binding for N in ObjRec has been initialized.
- Q(Set(globalObject, N, V, Value.false));
+ Q(yield* Set(globalObject, N, V, Value.false));
const varDeclaredNames = envRec.VarNames;
if (!varDeclaredNames.includes(N)) {
varDeclaredNames.push(N);
@@ -541,7 +541,7 @@ export class GlobalEnvironmentRecord extends EnvironmentRecord {
}
export class ModuleEnvironmentRecord extends DeclarativeEnvironmentRecord {
- GetBindingValue(N, S) {
+ * GetBindingValue(N, S) {
Assert(S === Value.true);
const envRec = this;
Assert(envRec.bindings.has(N));
@@ -553,7 +553,7 @@ export class ModuleEnvironmentRecord extends DeclarativeEnvironmentRecord {
return surroundingAgent.Throw('ReferenceError', 'targetEnv is undefined');
}
const targetER = targetEnv.EnvironmentRecord;
- return Q(targetER.GetBindingValue(N2, Value.true));
+ return Q(yield* targetER.GetBindingValue(N2, Value.true));
}
if (binding.initialized === false) {
return surroundingAgent.Throw('ReferenceError', msg('NotDefined', N));
@@ -573,9 +573,9 @@ export class ModuleEnvironmentRecord extends DeclarativeEnvironmentRecord {
return Value.undefined;
}
- CreateImportBinding(N, M, N2) {
+ * CreateImportBinding(N, M, N2) {
const envRec = this;
- Assert(envRec.HasBinding(N) === Value.false);
+ Assert(yield* envRec.HasBinding(N) === Value.false);
Assert(M instanceof ModuleRecord);
// Assert: When M.[[Environment]] is instantiated it will have a direct binding for N2.
envRec.bindings.set(N, {
@@ -588,7 +588,7 @@ export class ModuleEnvironmentRecord extends DeclarativeEnvironmentRecord {
}
// 8.1.2.1 #sec-getidentifierreference
-export function GetIdentifierReference(lex, name, strict) {
+export function* GetIdentifierReference(lex, name, strict) {
if (Type(lex) === 'Null') {
return new Reference({
BaseValue: Value.undefined,
@@ -597,7 +597,7 @@ export function GetIdentifierReference(lex, name, strict) {
});
}
const envRec = lex.EnvironmentRecord;
- const exists = Q(envRec.HasBinding(name));
+ const exists = Q(yield* envRec.HasBinding(name));
if (exists === Value.true) {
return new Reference({
BaseValue: envRec,
@@ -606,7 +606,7 @@ export function GetIdentifierReference(lex, name, strict) {
});
} else {
const outer = lex.outerEnvironmentReference;
- return GetIdentifierReference(outer, name, strict);
+ return yield* GetIdentifierReference(outer, name, strict);
}
}
diff --git a/src/evaluator.mjs b/src/evaluator.mjs
index 336b72c..4224f6b 100644
--- a/src/evaluator.mjs
+++ b/src/evaluator.mjs
@@ -140,7 +140,7 @@ import {
GetValue,
} from './abstract-ops/all.mjs';
import { surroundingAgent } from './engine.mjs';
-import { unwind, OutOfRange } from './helpers.mjs';
+import { OutOfRange } from './helpers.mjs';
// 13.2.13 #sec-block-runtime-semantics-evaluation
// StatementList : StatementList StatementListItem
@@ -263,7 +263,7 @@ function* Evaluate_StatementListItem(StatementListItem) {
return yield* Evaluate_TryStatement(StatementListItem);
case isDebuggerStatement(StatementListItem):
- return Evaluate_DebuggerStatement(StatementListItem);
+ return yield* Evaluate_DebuggerStatement(StatementListItem);
case isHoistableDeclaration(StatementListItem):
return Evaluate_HoistableDeclaration(StatementListItem);
@@ -285,7 +285,7 @@ export const Evaluate_Statement = Evaluate_StatementListItem;
// ExpressionStatement : Expression `;`
function* Evaluate_ExpressionStatement(ExpressionStatement) {
const exprRef = yield* Evaluate(ExpressionStatement.expression);
- return GetValue(exprRef);
+ return yield* GetValue(exprRef);
}
export function EvaluateBinopValues(operator, lval, rval) {
@@ -332,7 +332,7 @@ function* Inner_Evaluate_Expression(Expression) {
return Evaluate_ThisExpression(Expression);
case isIdentifierReference(Expression):
- return Evaluate_Identifier(Expression);
+ return yield* Evaluate_Identifier(Expression);
case isLiteral(Expression):
return Evaluate_Literal(Expression);
@@ -344,22 +344,22 @@ function* Inner_Evaluate_Expression(Expression) {
return yield* Evaluate_ObjectLiteral(Expression);
case isFunctionExpression(Expression):
- return Evaluate_FunctionExpression(Expression);
+ return yield* Evaluate_FunctionExpression(Expression);
case isClassExpression(Expression):
return yield* Evaluate_ClassExpression(Expression);
case isGeneratorExpression(Expression):
- return Evaluate_GeneratorExpression(Expression);
+ return yield* Evaluate_GeneratorExpression(Expression);
case isAsyncFunctionExpression(Expression):
- return Evaluate_AsyncFunctionExpression(Expression);
+ return yield* Evaluate_AsyncFunctionExpression(Expression);
case isAsyncGeneratorExpression(Expression):
- return Evaluate_AsyncGeneratorExpression(Expression);
+ return yield* Evaluate_AsyncGeneratorExpression(Expression);
case isRegularExpressionLiteral(Expression):
- return Evaluate_RegularExpressionLiteral(Expression);
+ return yield* Evaluate_RegularExpressionLiteral(Expression);
case isTemplateLiteral(Expression):
return yield* Evaluate_TemplateLiteral(Expression);
@@ -430,10 +430,10 @@ function* Inner_Evaluate_Expression(Expression) {
return yield* Evaluate_YieldExpression(Expression);
case isArrowFunction(Expression):
- return Evaluate_ArrowFunction(Expression);
+ return yield* Evaluate_ArrowFunction(Expression);
case isAsyncArrowFunction(Expression):
- return Evaluate_AsyncArrowFunction(Expression);
+ return yield* Evaluate_AsyncArrowFunction(Expression);
case isActualAssignmentExpression(Expression):
return yield* Evaluate_AssignmentExpression(Expression);
@@ -460,7 +460,7 @@ export function Evaluate_Script(Script) {
if (Script.length === 0) {
return new NormalCompletion(Value.undefined);
}
- return unwind(Evaluate_StatementList(Script));
+ return Evaluate_StatementList(Script);
}
// 15.2.1.20 #sec-module-semantics-runtime-semantics-evaluation
@@ -483,7 +483,7 @@ export function Evaluate_Module(Module) {
if (Module.length === 0) {
return new NormalCompletion(Value.undefined);
}
- return unwind(Evaluate_ModuleBody(Module));
+ return Evaluate_ModuleBody(Module);
}
export function* Evaluate(Production) {
@@ -491,6 +491,8 @@ export function* Evaluate(Production) {
surroundingAgent.hostDefinedOptions.onNodeEvaluation(Production, surroundingAgent.currentRealmRecord);
}
+ yield Production;
+
switch (true) {
case isImportDeclaration(Production):
return new NormalCompletion(undefined);
diff --git a/src/helpers.mjs b/src/helpers.mjs
index 087d67e..2ee2c0b 100644
--- a/src/helpers.mjs
+++ b/src/helpers.mjs
@@ -49,7 +49,7 @@ export function captureStack(O) {
let string = '\n at ';
const functionName = e.Function.properties.get(new Value('name'));
if (functionName) {
- string += X(ToString(functionName.Value)).stringValue();
+ string += X(unwind(ToString(functionName.Value))).stringValue();
} else {
string += '<anonymous>';
}
@@ -60,15 +60,15 @@ export function captureStack(O) {
})
.reverse();
- const errorString = X(ToString(O)).stringValue();
+ const errorString = X(unwind(ToString(O))).stringValue();
const trace = `${errorString}${stack.join('')}`;
- X(DefinePropertyOrThrow(O, new Value('stack'), Descriptor({
+ X(unwind(DefinePropertyOrThrow(O, new Value('stack'), Descriptor({
Value: new Value(trace),
Writable: Value.true,
Enumerable: Value.false,
Configurable: Value.false,
- })));
+ }))));
}
function inlineInspect(V) {
diff --git a/src/intrinsics/Array.mjs b/src/intrinsics/Array.mjs
index de90403..943bab5 100644
--- a/src/intrinsics/Array.mjs
+++ b/src/intrinsics/Array.mjs
@@ -38,7 +38,7 @@ import { OutOfRange, msg } from '../helpers.mjs';
import { BootstrapConstructor } from './Bootstrap.mjs';
// 22.1.1 #sec-array-constructor
-function ArrayConstructor(argumentsList, { NewTarget }) {
+function* ArrayConstructor(argumentsList, { NewTarget }) {
const numberOfArgs = argumentsList.length;
if (numberOfArgs === 0) {
// 22.1.1.1 #sec-array-constructor-array
@@ -46,8 +46,8 @@ function ArrayConstructor(argumentsList, { NewTarget }) {
if (Type(NewTarget) === 'Undefined') {
NewTarget = surroundingAgent.activeFunctionObject;
}
- const proto = GetPrototypeFromConstructor(NewTarget, '%ArrayPrototype%');
- return ArrayCreate(new Value(0), proto);
+ const proto = yield* GetPrototypeFromConstructor(NewTarget, '%ArrayPrototype%');
+ return yield* ArrayCreate(new Value(0), proto);
} else if (numberOfArgs === 1) {
// 22.1.1.2 #sec-array-len
const [len] = argumentsList;
@@ -55,20 +55,20 @@ function ArrayConstructor(argumentsList, { NewTarget }) {
if (Type(NewTarget) === 'Undefined') {
NewTarget = surroundingAgent.activeFunctionObject;
}
- const proto = GetPrototypeFromConstructor(NewTarget, '%ArrayPrototype%');
- const array = ArrayCreate(new Value(0), proto);
+ const proto = yield* GetPrototypeFromConstructor(NewTarget, '%ArrayPrototype%');