Generator.js (2855B)
1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 5 function GeneratorNext(val) { 6 // The IsSuspendedGenerator call below is not necessary for correctness. 7 // It's a performance optimization to check for the common case with a 8 // single call. It's also inlined in Baseline. 9 10 if (!IsSuspendedGenerator(this)) { 11 if (!IsObject(this) || !IsGeneratorObject(this)) { 12 return callFunction( 13 CallGeneratorMethodIfWrapped, 14 this, 15 val, 16 "GeneratorNext" 17 ); 18 } 19 20 if (GeneratorObjectIsClosed(this)) { 21 return { value: undefined, done: true }; 22 } 23 24 if (GeneratorIsRunning(this)) { 25 ThrowTypeError(JSMSG_NESTING_GENERATOR); 26 } 27 } 28 29 try { 30 return resumeGenerator(this, val, "next"); 31 } catch (e) { 32 if (!GeneratorObjectIsClosed(this)) { 33 GeneratorSetClosed(this); 34 } 35 throw e; 36 } 37 } 38 39 function GeneratorThrow(val) { 40 if (!IsSuspendedGenerator(this)) { 41 if (!IsObject(this) || !IsGeneratorObject(this)) { 42 return callFunction( 43 CallGeneratorMethodIfWrapped, 44 this, 45 val, 46 "GeneratorThrow" 47 ); 48 } 49 50 if (GeneratorObjectIsClosed(this)) { 51 throw val; 52 } 53 54 if (GeneratorIsRunning(this)) { 55 ThrowTypeError(JSMSG_NESTING_GENERATOR); 56 } 57 } 58 59 try { 60 return resumeGenerator(this, val, "throw"); 61 } catch (e) { 62 if (!GeneratorObjectIsClosed(this)) { 63 GeneratorSetClosed(this); 64 } 65 throw e; 66 } 67 } 68 69 function GeneratorReturn(val) { 70 if (!IsSuspendedGenerator(this)) { 71 if (!IsObject(this) || !IsGeneratorObject(this)) { 72 return callFunction( 73 CallGeneratorMethodIfWrapped, 74 this, 75 val, 76 "GeneratorReturn" 77 ); 78 } 79 80 if (GeneratorObjectIsClosed(this)) { 81 return { value: val, done: true }; 82 } 83 84 if (GeneratorIsRunning(this)) { 85 ThrowTypeError(JSMSG_NESTING_GENERATOR); 86 } 87 } 88 89 try { 90 var rval = { value: val, done: true }; 91 return resumeGenerator(this, rval, "return"); 92 } catch (e) { 93 if (!GeneratorObjectIsClosed(this)) { 94 GeneratorSetClosed(this); 95 } 96 throw e; 97 } 98 } 99 100 function InterpretGeneratorResume(gen, val, kind) { 101 // If we want to resume a generator in the interpreter, the script containing 102 // the resumeGenerator/JSOp::Resume also has to run in the interpreter. The 103 // forceInterpreter() call below compiles to a bytecode op that prevents us 104 // from JITing this script. 105 forceInterpreter(); 106 if (kind === "next") { 107 return resumeGenerator(gen, val, "next"); 108 } 109 if (kind === "throw") { 110 return resumeGenerator(gen, val, "throw"); 111 } 112 assert(kind === "return", "Invalid resume kind"); 113 return resumeGenerator(gen, val, "return"); 114 }