diff options
Diffstat (limited to 'js/src/vm/Iterator.cpp')
-rw-r--r-- | js/src/vm/Iterator.cpp | 113 |
1 files changed, 113 insertions, 0 deletions
diff --git a/js/src/vm/Iterator.cpp b/js/src/vm/Iterator.cpp new file mode 100644 index 0000000000..ce7189c495 --- /dev/null +++ b/js/src/vm/Iterator.cpp @@ -0,0 +1,113 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim:set ts=2 sw=2 sts=2 et cindent: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "js/Iterator.h" + +#include "js/Conversions.h" +#include "vm/Interpreter.h" +#include "vm/JSAtomState.h" +#include "vm/JSContext.h" +#include "vm/ObjectOperations.h" +#include "vm/SelfHosting.h" +#include "vm/StringType.h" +#include "vm/JSContext-inl.h" // JSContext::check +#include "vm/JSObject-inl.h" + +using namespace js; + +namespace JS { + +// https://tc39.es/ecma262/#sec-getiterator +// GetIterator(obj [, hint [, method]]) +JSObject* GetIteratorObject(JSContext* cx, HandleValue obj, bool isAsync) { + cx->check(obj); + + FixedInvokeArgs<3> args(cx); + args[0].set(obj); + args[1].setBoolean(isAsync); + args[2].setUndefined(); // method + + RootedValue rval(cx); + if (!CallSelfHostedFunction(cx, cx->names().GetIterator, UndefinedHandleValue, + args, &rval)) { + return nullptr; + } + + MOZ_ASSERT(rval.isObject()); + return &rval.toObject(); +} + +// https://tc39.es/ecma262/#sec-iteratornext +bool IteratorNext(JSContext* cx, HandleObject iteratorRecord, + MutableHandleValue result) { + cx->check(iteratorRecord); + + FixedInvokeArgs<1> args(cx); + args[0].setObject(*iteratorRecord); + return CallSelfHostedFunction(cx, cx->names().IteratorNext, + UndefinedHandleValue, args, result); +} + +// https://tc39.es/ecma262/#sec-iteratorcomplete +bool IteratorComplete(JSContext* cx, HandleObject iterResult, bool* done) { + cx->check(iterResult); + + RootedValue doneV(cx); + if (!GetProperty(cx, iterResult, iterResult, cx->names().done, &doneV)) { + return false; + } + + *done = ToBoolean(doneV); + return true; +} + +// https://tc39.es/ecma262/#sec-iteratorvalue +bool IteratorValue(JSContext* cx, HandleObject iterResult, + MutableHandleValue value) { + cx->check(iterResult); + return GetProperty(cx, iterResult, iterResult, cx->names().value, value); +} + +bool GetIteratorRecordIterator(JSContext* cx, HandleObject iteratorRecord, + MutableHandleValue iterator) { + cx->check(iteratorRecord); + return GetProperty(cx, iteratorRecord, iteratorRecord, cx->names().iterator, + iterator); +} + +// https://tc39.es/ecma262/#sec-getmethod +static bool GetMethod(JSContext* cx, HandleValue v, Handle<PropertyName*> name, + MutableHandleValue result) { + // Step 1. Let func be ? GetV(V, P). + RootedValue func(cx); + if (!GetProperty(cx, v, name, &func)) { + return false; + } + + // Step 2. If func is either undefined or null, return undefined. + if (func.isNullOrUndefined()) { + result.setUndefined(); + return true; + } + + // Step 3. If IsCallable(func) is false, throw a TypeError exception. + if (!IsCallable(func)) { + return ReportIsNotFunction(cx, func, -1); + } + + // Step 4. Return func. + result.set(func); + return true; +} + +bool GetReturnMethod(JSContext* cx, HandleValue iterator, + MutableHandleValue result) { + cx->check(iterator); + // Step 2. Let returnMethod be GetMethod(iterator, "return"). + return GetMethod(cx, iterator, cx->names().return_, result); +} + +} // namespace JS |