Iterator.cpp (3396B)
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim:set ts=2 sw=2 sts=2 et cindent: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #include "js/Iterator.h" 8 9 #include "js/Conversions.h" 10 #include "vm/Interpreter.h" 11 #include "vm/JSAtomState.h" 12 #include "vm/JSContext.h" 13 #include "vm/ObjectOperations.h" 14 #include "vm/SelfHosting.h" 15 #include "vm/StringType.h" 16 #include "vm/JSContext-inl.h" // JSContext::check 17 #include "vm/JSObject-inl.h" 18 19 using namespace js; 20 21 namespace JS { 22 23 // https://tc39.es/ecma262/#sec-getiterator 24 // GetIterator(obj [, hint [, method]]) 25 JSObject* GetIteratorObject(JSContext* cx, HandleValue obj, bool isAsync) { 26 cx->check(obj); 27 28 FixedInvokeArgs<3> args(cx); 29 args[0].set(obj); 30 args[1].setBoolean(isAsync); 31 args[2].setUndefined(); // method 32 33 RootedValue rval(cx); 34 if (!CallSelfHostedFunction(cx, cx->names().GetIterator, UndefinedHandleValue, 35 args, &rval)) { 36 return nullptr; 37 } 38 39 MOZ_ASSERT(rval.isObject()); 40 return &rval.toObject(); 41 } 42 43 // https://tc39.es/ecma262/#sec-iteratornext 44 bool IteratorNext(JSContext* cx, HandleObject iteratorRecord, 45 MutableHandleValue result) { 46 cx->check(iteratorRecord); 47 48 FixedInvokeArgs<1> args(cx); 49 args[0].setObject(*iteratorRecord); 50 return CallSelfHostedFunction(cx, cx->names().IteratorNext, 51 UndefinedHandleValue, args, result); 52 } 53 54 // https://tc39.es/ecma262/#sec-iteratorcomplete 55 bool IteratorComplete(JSContext* cx, HandleObject iterResult, bool* done) { 56 cx->check(iterResult); 57 58 RootedValue doneV(cx); 59 if (!GetProperty(cx, iterResult, iterResult, cx->names().done, &doneV)) { 60 return false; 61 } 62 63 *done = ToBoolean(doneV); 64 return true; 65 } 66 67 // https://tc39.es/ecma262/#sec-iteratorvalue 68 bool IteratorValue(JSContext* cx, HandleObject iterResult, 69 MutableHandleValue value) { 70 cx->check(iterResult); 71 return GetProperty(cx, iterResult, iterResult, cx->names().value, value); 72 } 73 74 bool GetIteratorRecordIterator(JSContext* cx, HandleObject iteratorRecord, 75 MutableHandleValue iterator) { 76 cx->check(iteratorRecord); 77 return GetProperty(cx, iteratorRecord, iteratorRecord, cx->names().iterator, 78 iterator); 79 } 80 81 // https://tc39.es/ecma262/#sec-getmethod 82 static bool GetMethod(JSContext* cx, HandleValue v, Handle<PropertyName*> name, 83 MutableHandleValue result) { 84 // Step 1. Let func be ? GetV(V, P). 85 RootedValue func(cx); 86 if (!GetProperty(cx, v, name, &func)) { 87 return false; 88 } 89 90 // Step 2. If func is either undefined or null, return undefined. 91 if (func.isNullOrUndefined()) { 92 result.setUndefined(); 93 return true; 94 } 95 96 // Step 3. If IsCallable(func) is false, throw a TypeError exception. 97 if (!IsCallable(func)) { 98 return ReportIsNotFunction(cx, func, -1); 99 } 100 101 // Step 4. Return func. 102 result.set(func); 103 return true; 104 } 105 106 bool GetReturnMethod(JSContext* cx, HandleValue iterator, 107 MutableHandleValue result) { 108 cx->check(iterator); 109 // Step 2. Let returnMethod be GetMethod(iterator, "return"). 110 return GetMethod(cx, iterator, cx->names().return_, result); 111 } 112 113 } // namespace JS