test-preparser.cc 38.1 KB
Newer Older
1 2 3 4
// Copyright 2017 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

5
#include "src/api-inl.h"
6 7 8 9 10
#include "src/ast/ast.h"
#include "src/compiler.h"
#include "src/objects-inl.h"
#include "src/parsing/parse-info.h"
#include "src/parsing/parsing.h"
11 12
#include "src/parsing/preparse-data-impl.h"
#include "src/parsing/preparse-data.h"
13 14 15 16 17

#include "test/cctest/cctest.h"
#include "test/cctest/scope-test-helper.h"
#include "test/cctest/unicode-helpers.h"

18 19
namespace {

20
enum SkipTests {
21 22 23 24 25
  DONT_SKIP = 0,
  // Skip if the test function declares itself strict, otherwise don't skip.
  SKIP_STRICT_FUNCTION = 1,
  // Skip if there's a "use strict" directive above the test.
  SKIP_STRICT_OUTER = 1 << 1,
26
  SKIP_ARROW = 1 << 2,
27 28 29
  SKIP_STRICT = SKIP_STRICT_FUNCTION | SKIP_STRICT_OUTER
};

30 31 32 33
enum class PreciseMaybeAssigned { YES, NO };

enum class Bailout { BAILOUT_IF_OUTER_SLOPPY, NO };

34 35
}  // namespace

36 37 38
TEST(PreParserScopeAnalysis) {
  i::Isolate* isolate = CcTest::i_isolate();
  i::Factory* factory = isolate->factory();
39
  LocalContext env;
40

41
  struct Outer {
42
    const char* code;
43 44
    bool strict_outer;
    bool strict_test_function;
45
    bool arrow;
46
  } outers[] = {
47
      // Normal case (test function at the laziness boundary):
48 49 50 51 52
      {"function test(%s) { %s function skippable() { } } test;", false, false,
       false},

      {"var test2 = function test(%s) { %s function skippable() { } }; test2",
       false, false, false},
53

54
      // Arrow functions (they can never be at the laziness boundary):
55 56 57 58 59 60 61 62 63 64 65 66 67 68
      {"function test() { (%s) => { %s }; function skippable() { } } test;",
       false, false, true},

      // Repeat the above mentioned cases with global 'use strict'
      {"'use strict'; function test(%s) { %s function skippable() { } } test;",
       true, false, false},

      {"'use strict'; var test2 = function test(%s) { %s \n"
       "function skippable() { } }; test2",
       true, false, false},

      {"'use strict'; function test() { (%s) => { %s };\n"
       "function skippable() { } } test;",
       true, false, true},
69 70

      // ... and with the test function declaring itself strict:
71 72 73 74 75 76 77 78 79 80
      {"function test(%s) { 'use strict'; %s function skippable() { } } test;",
       false, true, false},

      {"var test2 = function test(%s) { 'use strict'; %s \n"
       "function skippable() { } }; test2",
       false, true, false},

      {"function test() { 'use strict'; (%s) => { %s };\n"
       "function skippable() { } } test;",
       false, true, true},
81

82
      // Methods containing skippable functions.
83 84 85 86 87 88
      {"function get_method() {\n"
       "  class MyClass { test_method(%s) { %s function skippable() { } } }\n"
       "  var o = new MyClass(); return o.test_method;\n"
       "}\n"
       "get_method();",
       true, true, false},
89

90 91 92 93 94
      // Corner case: function expression with name "arguments".
      {"var test = function arguments(%s) { %s function skippable() { } };\n"
       "test;\n",
       false, false, false}

95
      // FIXME(marja): Generators and async functions
96
  };
97

98 99
  struct Inner {
    Inner(const char* s) : source(s) {}  // NOLINT
100
    Inner(const char* s, SkipTests skip) : source(s), skip(skip) {}
101
    Inner(const char* s, SkipTests skip, PreciseMaybeAssigned precise)
102
        : source(s), skip(skip), precise_maybe_assigned(precise) {}
103 104

    Inner(const char* p, const char* s) : params(p), source(s) {}
105 106
    Inner(const char* p, const char* s, SkipTests skip)
        : params(p), source(s), skip(skip) {}
107 108
    Inner(const char* p, const char* s, SkipTests skip,
          PreciseMaybeAssigned precise)
109
        : params(p), source(s), skip(skip), precise_maybe_assigned(precise) {}
110 111
    Inner(const char* p, const char* s, SkipTests skip, Bailout bailout)
        : params(p), source(s), skip(skip), bailout(bailout) {}
112

113 114 115
    Inner(const char* s, std::function<void()> p, std::function<void()> e)
        : source(s), prologue(p), epilogue(e) {}

116
    const char* params = "";
117
    const char* source;
118
    SkipTests skip = DONT_SKIP;
119 120
    PreciseMaybeAssigned precise_maybe_assigned = PreciseMaybeAssigned::YES;
    Bailout bailout = Bailout::NO;
121 122
    std::function<void()> prologue = nullptr;
    std::function<void()> epilogue = nullptr;
123 124
  } inners[] = {
      // Simple cases
125 126 127 128
      {"var1;"},
      {"var1 = 5;"},
      {"if (true) {}"},
      {"function f1() {}"},
129 130
      {"test;"},
      {"test2;"},
131 132

      // Var declarations and assignments.
133 134
      {"var var1;"},
      {"var var1; var1 = 5;"},
135
      {"if (true) { var var1; }", DONT_SKIP, PreciseMaybeAssigned::NO},
136 137 138 139
      {"if (true) { var var1; var1 = 5; }"},
      {"var var1; function f() { var1; }"},
      {"var var1; var1 = 5; function f() { var1; }"},
      {"var var1; function f() { var1 = 5; }"},
140
      {"function f1() { f2(); } function f2() {}"},
141 142

      // Let declarations and assignments.
143 144 145 146 147 148 149
      {"let var1;"},
      {"let var1; var1 = 5;"},
      {"if (true) { let var1; }"},
      {"if (true) { let var1; var1 = 5; }"},
      {"let var1; function f() { var1; }"},
      {"let var1; var1 = 5; function f() { var1; }"},
      {"let var1; function f() { var1 = 5; }"},
150 151

      // Const declarations.
152 153 154
      {"const var1 = 5;"},
      {"if (true) { const var1 = 5; }"},
      {"const var1 = 5; function f() { var1; }"},
155

156 157
      // Functions.
      {"function f1() { let var2; }"},
158 159 160 161 162 163
      {"var var1 = function f1() { let var2; };"},
      {"let var1 = function f1() { let var2; };"},
      {"const var1 = function f1() { let var2; };"},
      {"var var1 = function() { let var2; };"},
      {"let var1 = function() { let var2; };"},
      {"const var1 = function() { let var2; };"},
164

165
      {"function *f1() { let var2; }"},
166 167
      {"let var1 = function *f1() { let var2; };"},
      {"let var1 = function*() { let var2; };"},
168 169

      {"async function f1() { let var2; }"},
170 171
      {"let var1 = async function f1() { let var2; };"},
      {"let var1 = async function() { let var2; };"},
172

173
      // Redeclarations.
174 175 176 177 178 179 180 181
      {"var var1; var var1;"},
      {"var var1; var var1; var1 = 5;"},
      {"var var1; if (true) { var var1; }"},
      {"if (true) { var var1; var var1; }"},
      {"var var1; if (true) { var var1; var1 = 5; }"},
      {"if (true) { var var1; var var1; var1 = 5; }"},
      {"var var1; var var1; function f() { var1; }"},
      {"var var1; var var1; function f() { var1 = 5; }"},
182 183

      // Shadowing declarations.
184 185 186
      {"var var1; if (true) { var var1; }"},
      {"var var1; if (true) { let var1; }"},
      {"let var1; if (true) { let var1; }"},
187

188 189
      {"var var1; if (true) { const var1 = 0; }"},
      {"const var1 = 0; if (true) { const var1 = 0; }"},
190

191 192 193
      // Variables deeper in the subscopes (scopes without variables inbetween).
      {"if (true) { if (true) { function f() { var var1 = 5; } } }"},

194
      // Arguments and this.
195
      {"arguments;"},
196
      {"arguments = 5;", SKIP_STRICT},
197
      {"if (true) { arguments; }"},
198
      {"if (true) { arguments = 5; }", SKIP_STRICT},
199
      {"() => { arguments; };"},
200 201
      {"var1, var2, var3", "arguments;"},
      {"var1, var2, var3", "arguments = 5;", SKIP_STRICT},
202 203
      {"var1, var2, var3", "() => { arguments; };"},
      {"var1, var2, var3", "() => { arguments = 5; };", SKIP_STRICT},
204

205 206
      {"this;"},
      {"if (true) { this; }"},
207
      {"() => { this; };"},
208 209

      // Variable called "arguments"
210 211
      {"var arguments;", SKIP_STRICT},
      {"var arguments; arguments = 5;", SKIP_STRICT},
212
      {"if (true) { var arguments; }", SKIP_STRICT, PreciseMaybeAssigned::NO},
213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230
      {"if (true) { var arguments; arguments = 5; }", SKIP_STRICT},
      {"var arguments; function f() { arguments; }", SKIP_STRICT},
      {"var arguments; arguments = 5; function f() { arguments; }",
       SKIP_STRICT},
      {"var arguments; function f() { arguments = 5; }", SKIP_STRICT},

      {"let arguments;", SKIP_STRICT},
      {"let arguments; arguments = 5;", SKIP_STRICT},
      {"if (true) { let arguments; }", SKIP_STRICT},
      {"if (true) { let arguments; arguments = 5; }", SKIP_STRICT},
      {"let arguments; function f() { arguments; }", SKIP_STRICT},
      {"let arguments; arguments = 5; function f() { arguments; }",
       SKIP_STRICT},
      {"let arguments; function f() { arguments = 5; }", SKIP_STRICT},

      {"const arguments = 5;", SKIP_STRICT},
      {"if (true) { const arguments = 5; }", SKIP_STRICT},
      {"const arguments = 5; function f() { arguments; }", SKIP_STRICT},
231 232

      // Destructuring declarations.
233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258
      {"var [var1, var2] = [1, 2];"},
      {"var [var1, var2, [var3, var4]] = [1, 2, [3, 4]];"},
      {"var [{var1: var2}, {var3: var4}] = [{var1: 1}, {var3: 2}];"},
      {"var [var1, ...var2] = [1, 2, 3];"},

      {"var {var1: var2, var3: var4} = {var1: 1, var3: 2};"},
      {"var {var1: var2, var3: {var4: var5}} = {var1: 1, var3: {var4: 2}};"},
      {"var {var1: var2, var3: [var4, var5]} = {var1: 1, var3: [2, 3]};"},

      {"let [var1, var2] = [1, 2];"},
      {"let [var1, var2, [var3, var4]] = [1, 2, [3, 4]];"},
      {"let [{var1: var2}, {var3: var4}] = [{var1: 1}, {var3: 2}];"},
      {"let [var1, ...var2] = [1, 2, 3];"},

      {"let {var1: var2, var3: var4} = {var1: 1, var3: 2};"},
      {"let {var1: var2, var3: {var4: var5}} = {var1: 1, var3: {var4: 2}};"},
      {"let {var1: var2, var3: [var4, var5]} = {var1: 1, var3: [2, 3]};"},

      {"const [var1, var2] = [1, 2];"},
      {"const [var1, var2, [var3, var4]] = [1, 2, [3, 4]];"},
      {"const [{var1: var2}, {var3: var4}] = [{var1: 1}, {var3: 2}];"},
      {"const [var1, ...var2] = [1, 2, 3];"},

      {"const {var1: var2, var3: var4} = {var1: 1, var3: 2};"},
      {"const {var1: var2, var3: {var4: var5}} = {var1: 1, var3: {var4: 2}};"},
      {"const {var1: var2, var3: [var4, var5]} = {var1: 1, var3: [2, 3]};"},
259 260

      // Referencing the function variable.
261
      {"test;"},
262 263
      {"function f1() { f1; }"},
      {"function f1() { function f2() { f1; } }"},
264 265
      {"function arguments() {}", SKIP_STRICT},
      {"function f1() {} function f1() {}", SKIP_STRICT},
266
      {"var f1; function f1() {}"},
267 268

      // Assigning to the function variable.
269
      {"test = 3;"},
270 271
      {"function f1() { f1 = 3; }"},
      {"function f1() { f1; } f1 = 3;"},
272 273
      {"function arguments() {} arguments = 8;", SKIP_STRICT},
      {"function f1() {} f1 = 3; function f1() {}", SKIP_STRICT},
274 275

      // Evals.
276 277 278 279 280 281
      {"var var1; eval('');"},
      {"var var1; function f1() { eval(''); }"},
      {"let var1; eval('');"},
      {"let var1; function f1() { eval(''); }"},
      {"const var1 = 10; eval('');"},
      {"const var1 = 10; function f1() { eval(''); }"},
282 283

      // Standard for loops.
284 285 286 287 288 289 290
      {"for (var var1 = 0; var1 < 10; ++var1) { }"},
      {"for (let var1 = 0; var1 < 10; ++var1) { }"},
      {"for (const var1 = 0; var1 < 10; ++var1) { }"},

      {"for (var var1 = 0; var1 < 10; ++var1) { function foo() { var1; } }"},
      {"for (let var1 = 0; var1 < 10; ++var1) { function foo() { var1; } }"},
      {"for (const var1 = 0; var1 < 10; ++var1) { function foo() { var1; } }"},
291 292

      // For of loops
293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316
      {"for (var1 of [1, 2]) { }"},
      {"for (var var1 of [1, 2]) { }"},
      {"for (let var1 of [1, 2]) { }"},
      {"for (const var1 of [1, 2]) { }"},

      {"for (var1 of [1, 2]) { var1; }"},
      {"for (var var1 of [1, 2]) { var1; }"},
      {"for (let var1 of [1, 2]) { var1; }"},
      {"for (const var1 of [1, 2]) { var1; }"},

      {"for (var1 of [1, 2]) { var1 = 0; }"},
      {"for (var var1 of [1, 2]) { var1 = 0; }"},
      {"for (let var1 of [1, 2]) { var1 = 0; }"},
      {"for (const var1 of [1, 2]) { var1 = 0; }"},

      {"for (var1 of [1, 2]) { function foo() { var1; } }"},
      {"for (var var1 of [1, 2]) { function foo() { var1; } }"},
      {"for (let var1 of [1, 2]) { function foo() { var1; } }"},
      {"for (const var1 of [1, 2]) { function foo() { var1; } }"},

      {"for (var1 of [1, 2]) { function foo() { var1 = 0; } }"},
      {"for (var var1 of [1, 2]) { function foo() { var1 = 0; } }"},
      {"for (let var1 of [1, 2]) { function foo() { var1 = 0; } }"},
      {"for (const var1 of [1, 2]) { function foo() { var1 = 0; } }"},
317 318

      // For in loops
319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347
      {"for (var1 in {a: 6}) { }"},
      {"for (var var1 in {a: 6}) { }"},
      {"for (let var1 in {a: 6}) { }"},
      {"for (const var1 in {a: 6}) { }"},

      {"for (var1 in {a: 6}) { var1; }"},
      {"for (var var1 in {a: 6}) { var1; }"},
      {"for (let var1 in {a: 6}) { var1; }"},
      {"for (const var1 in {a: 6}) { var1; }"},

      {"for (var1 in {a: 6}) { var1 = 0; }"},
      {"for (var var1 in {a: 6}) { var1 = 0; }"},
      {"for (let var1 in {a: 6}) { var1 = 0; }"},
      {"for (const var1 in {a: 6}) { var1 = 0; }"},

      {"for (var1 in {a: 6}) { function foo() { var1; } }"},
      {"for (var var1 in {a: 6}) { function foo() { var1; } }"},
      {"for (let var1 in {a: 6}) { function foo() { var1; } }"},
      {"for (const var1 in {a: 6}) { function foo() { var1; } }"},

      {"for (var1 in {a: 6}) { function foo() { var1 = 0; } }"},
      {"for (var var1 in {a: 6}) { function foo() { var1 = 0; } }"},
      {"for (let var1 in {a: 6}) { function foo() { var1 = 0; } }"},
      {"for (const var1 in {a: 6}) { function foo() { var1 = 0; } }"},

      {"for (var1 in {a: 6}) { function foo() { var1 = 0; } }"},
      {"for (var var1 in {a: 6}) { function foo() { var1 = 0; } }"},
      {"for (let var1 in {a: 6}) { function foo() { var1 = 0; } }"},
      {"for (const var1 in {a: 6}) { function foo() { var1 = 0; } }"},
348

349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364
      // Destructuring loop variable
      {"for ([var1, var2] of [[1, 1], [2, 2]]) { }"},
      {"for (var [var1, var2] of [[1, 1], [2, 2]]) { }"},
      {"for (let [var1, var2] of [[1, 1], [2, 2]]) { }"},
      {"for (const [var1, var2] of [[1, 1], [2, 2]]) { }"},

      {"for ([var1, var2] of [[1, 1], [2, 2]]) { var2 = 3; }"},
      {"for (var [var1, var2] of [[1, 1], [2, 2]]) { var2 = 3; }"},
      {"for (let [var1, var2] of [[1, 1], [2, 2]]) { var2 = 3; }"},
      {"for (const [var1, var2] of [[1, 1], [2, 2]]) { var2 = 3; }"},

      {"for ([var1, var2] of [[1, 1], [2, 2]]) { () => { var2 = 3; } }"},
      {"for (var [var1, var2] of [[1, 1], [2, 2]]) { () => { var2 = 3; } }"},
      {"for (let [var1, var2] of [[1, 1], [2, 2]]) { () => { var2 = 3; } }"},
      {"for (const [var1, var2] of [[1, 1], [2, 2]]) { () => { var2 = 3; } }"},

365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399
      // Skippable function in loop header
      {"for (let [var1, var2 = function() { }] of [[1]]) { }"},
      {"for (let [var1, var2 = function() { var1; }] of [[1]]) { }"},
      {"for (let [var1, var2 = function() { var2; }] of [[1]]) { }"},
      {"for (let [var1, var2 = function() { var1; var2; }] of [[1]]) { }"},
      {"for (let [var1, var2 = function() { var1 = 0; }] of [[1]]) { }"},
      {"for (let [var1, var2 = function() { var2 = 0; }] of [[1]]) { }"},
      {"for (let [var1, var2 = function() { var1 = 0; var2 = 0; }] of [[1]]) { "
       "}"},

      {"for (let [var1, var2 = function() { }] of [[1]]) { function f() { "
       "var1; } }"},
      {"for (let [var1, var2 = function() { }] of [[1]]) { function f() { "
       "var2; } }"},
      {"for (let [var1, var2 = function() { }] of [[1]]) { function f() { "
       "var1; var2; } }"},
      {"for (let [var1, var2 = function() { }] of [[1]]) { function f() { "
       "var1 = 0; } }"},
      {"for (let [var1, var2 = function() { }] of [[1]]) { function f() { "
       "var2 = 0; } }"},
      {"for (let [var1, var2 = function() { }] of [[1]]) { function f() { "
       "var1 = 0; var2 = 0; } }"},
      {"for (let [var1, var2 = function() { var1; }] of [[1]]) { "
       "function f() { var1; } }"},
      {"for (let [var1, var2 = function() { var1; }] of [[1]]) { "
       "function f() { var2; } }"},
      {"for (let [var1, var2 = function() { var1; }] of [[1]]) { "
       "function f() { var1; var2; } }"},
      {"for (let [var1, var2 = function() { var2; }] of [[1]]) { "
       "function f() { var1; } }"},
      {"for (let [var1, var2 = function() { var2; }] of [[1]]) { "
       "function f() { var2; } }"},
      {"for (let [var1, var2 = function() { var2; }] of [[1]]) { "
       "function f() { var1; var2; } }"},

400
      // Loops without declarations
401 402 403 404 405 406 407 408
      {"var var1 = 0; for ( ; var1 < 2; ++var1) { }"},
      {"var var1 = 0; for ( ; var1 < 2; ++var1) { function foo() { var1; } }"},
      {"var var1 = 0; for ( ; var1 > 2; ) { }"},
      {"var var1 = 0; for ( ; var1 > 2; ) { function foo() { var1; } }"},
      {"var var1 = 0; for ( ; var1 > 2; ) { function foo() { var1 = 6; } }"},

      {"var var1 = 0; for(var1; var1 < 2; ++var1) { }"},
      {"var var1 = 0; for (var1; var1 < 2; ++var1) { function foo() { var1; } "
409
       "}"},
410 411 412
      {"var var1 = 0; for (var1; var1 > 2; ) { }"},
      {"var var1 = 0; for (var1; var1 > 2; ) { function foo() { var1; } }"},
      {"var var1 = 0; for (var1; var1 > 2; ) { function foo() { var1 = 6; } }"},
413

414
      // Block functions (potentially sloppy).
415
      {"if (true) { function f1() {} }"},
416
      {"if (true) { function f1() {} function f1() {} }", SKIP_STRICT},
417
      {"if (true) { if (true) { function f1() {} } }"},
418 419
      {"if (true) { if (true) { function f1() {} function f1() {} } }",
       SKIP_STRICT},
420 421 422 423 424
      {"if (true) { function f1() {} f1 = 3; }"},

      {"if (true) { function f1() {} function foo() { f1; } }"},
      {"if (true) { function f1() {} } function foo() { f1; }"},
      {"if (true) { function f1() {} function f1() {} function foo() { f1; } "
425
       "}",
426
       SKIP_STRICT},
427
      {"if (true) { function f1() {} function f1() {} } function foo() { f1; "
428
       "}",
429
       SKIP_STRICT},
430 431
      {"if (true) { if (true) { function f1() {} } function foo() { f1; } }"},
      {"if (true) { if (true) { function f1() {} function f1() {} } function "
432
       "foo() { f1; } }",
433
       SKIP_STRICT},
434 435
      {"if (true) { function f1() {} f1 = 3; function foo() { f1; } }"},
      {"if (true) { function f1() {} f1 = 3; } function foo() { f1; }"},
436

437 438
      {"var f1 = 1; if (true) { function f1() {} }"},
      {"var f1 = 1; if (true) { function f1() {} } function foo() { f1; }"},
439

440 441
      {"if (true) { function f1() {} function f2() { f1(); } }"},

442 443 444
      {"if (true) { function *f1() {} }"},
      {"if (true) { async function f1() {} }"},

445 446 447
      // (Potentially sloppy) block function shadowing a catch variable.
      {"try { } catch(var1) { if (true) { function var1() {} } }"},

448 449 450 451 452 453 454
      // Simple parameters.
      {"var1", ""},
      {"var1", "var1;"},
      {"var1", "var1 = 9;"},
      {"var1", "function f1() { var1; }"},
      {"var1", "function f1() { var1 = 9; }"},

455 456 457 458 459 460 461 462 463 464
      {"var1, var2", ""},
      {"var1, var2", "var2;"},
      {"var1, var2", "var2 = 9;"},
      {"var1, var2", "function f1() { var2; }"},
      {"var1, var2", "function f1() { var2 = 9; }"},
      {"var1, var2", "var1;"},
      {"var1, var2", "var1 = 9;"},
      {"var1, var2", "function f1() { var1; }"},
      {"var1, var2", "function f1() { var1 = 9; }"},

465
      // Duplicate parameters.
466 467 468 469 470 471 472
      {"var1, var1", "", SkipTests(SKIP_STRICT | SKIP_ARROW)},
      {"var1, var1", "var1;", SkipTests(SKIP_STRICT | SKIP_ARROW)},
      {"var1, var1", "var1 = 9;", SkipTests(SKIP_STRICT | SKIP_ARROW)},
      {"var1, var1", "function f1() { var1; }",
       SkipTests(SKIP_STRICT | SKIP_ARROW)},
      {"var1, var1", "function f1() { var1 = 9; }",
       SkipTests(SKIP_STRICT | SKIP_ARROW)},
473 474 475

      // If the function declares itself strict, non-simple parameters aren't
      // allowed.
476

477
      // Rest parameter.
478 479 480 481 482 483 484 485 486 487 488
      {"...var2", "", SKIP_STRICT_FUNCTION},
      {"...var2", "var2;", SKIP_STRICT_FUNCTION},
      {"...var2", "var2 = 9;", SKIP_STRICT_FUNCTION},
      {"...var2", "function f1() { var2; }", SKIP_STRICT_FUNCTION},
      {"...var2", "function f1() { var2 = 9; }", SKIP_STRICT_FUNCTION},

      {"var1, ...var2", "", SKIP_STRICT_FUNCTION},
      {"var1, ...var2", "var2;", SKIP_STRICT_FUNCTION},
      {"var1, ...var2", "var2 = 9;", SKIP_STRICT_FUNCTION},
      {"var1, ...var2", "function f1() { var2; }", SKIP_STRICT_FUNCTION},
      {"var1, ...var2", "function f1() { var2 = 9; }", SKIP_STRICT_FUNCTION},
489

490
      // Default parameters.
491 492 493 494
      {"var1 = 3", "", SKIP_STRICT_FUNCTION, PreciseMaybeAssigned::NO},
      {"var1, var2 = var1", "", SKIP_STRICT_FUNCTION, PreciseMaybeAssigned::NO},
      {"var1, var2 = 4, ...var3", "", SKIP_STRICT_FUNCTION,
       PreciseMaybeAssigned::NO},
495 496 497

      // Destructuring parameters. Because of the search space explosion, we
      // cannot test all interesting cases. Let's try to test a relevant subset.
498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514
      {"[]", "", SKIP_STRICT_FUNCTION},
      {"{}", "", SKIP_STRICT_FUNCTION},

      {"[var1]", "", SKIP_STRICT_FUNCTION},
      {"{name1: var1}", "", SKIP_STRICT_FUNCTION},
      {"{var1}", "", SKIP_STRICT_FUNCTION},

      {"[var1]", "var1;", SKIP_STRICT_FUNCTION},
      {"{name1: var1}", "var1;", SKIP_STRICT_FUNCTION},
      {"{name1: var1}", "name1;", SKIP_STRICT_FUNCTION},
      {"{var1}", "var1;", SKIP_STRICT_FUNCTION},

      {"[var1]", "var1 = 16;", SKIP_STRICT_FUNCTION},
      {"{name1: var1}", "var1 = 16;", SKIP_STRICT_FUNCTION},
      {"{name1: var1}", "name1 = 16;", SKIP_STRICT_FUNCTION},
      {"{var1}", "var1 = 16;", SKIP_STRICT_FUNCTION},

515 516 517 518
      {"[var1]", "() => { var1; };", SKIP_STRICT_FUNCTION},
      {"{name1: var1}", "() => { var1; };", SKIP_STRICT_FUNCTION},
      {"{name1: var1}", "() => { name1; };", SKIP_STRICT_FUNCTION},
      {"{var1}", "() => { var1; };", SKIP_STRICT_FUNCTION},
519 520 521 522 523

      {"[var1, var2, var3]", "", SKIP_STRICT_FUNCTION},
      {"{name1: var1, name2: var2, name3: var3}", "", SKIP_STRICT_FUNCTION},
      {"{var1, var2, var3}", "", SKIP_STRICT_FUNCTION},

524 525
      {"[var1, var2, var3]", "() => { var2 = 16;};", SKIP_STRICT_FUNCTION},
      {"{name1: var1, name2: var2, name3: var3}", "() => { var2 = 16;};",
526
       SKIP_STRICT_FUNCTION},
527
      {"{name1: var1, name2: var2, name3: var3}", "() => { name2 = 16;};",
528
       SKIP_STRICT_FUNCTION},
529
      {"{var1, var2, var3}", "() => { var2 = 16;};", SKIP_STRICT_FUNCTION},
530 531

      // Nesting destructuring.
532 533
      {"[var1, [var2, var3], {var4, name5: [var5, var6]}]", "",
       SKIP_STRICT_FUNCTION},
534 535

      // Complicated params.
536 537
      {"var1, [var2], var3 = 24, [var4, var5] = [2, 4], var6, {var7}, var8, "
       "{name9: var9, name10: var10}, ...var11",
538
       "", SKIP_STRICT_FUNCTION, PreciseMaybeAssigned::NO},
539

540
      // Complicated cases from bugs.
541
      {"var1 = {} = {}", "", SKIP_STRICT_FUNCTION, PreciseMaybeAssigned::NO},
542

543
      // Destructuring rest. Because we can.
544
      {"var1, ...[var2]", "", SKIP_STRICT_FUNCTION},
545
      {"var1, ...[var2]", "() => { var2; };", SKIP_STRICT_FUNCTION},
546
      {"var1, ...{0: var2}", "", SKIP_STRICT_FUNCTION},
547
      {"var1, ...{0: var2}", "() => { var2; };", SKIP_STRICT_FUNCTION},
548 549 550 551
      {"var1, ...[]", "", SKIP_STRICT_FUNCTION},
      {"var1, ...{}", "", SKIP_STRICT_FUNCTION},
      {"var1, ...[var2, var3]", "", SKIP_STRICT_FUNCTION},
      {"var1, ...{0: var2, 1: var3}", "", SKIP_STRICT_FUNCTION},
552 553

      // Default parameters for destruring parameters.
554 555 556 557
      {"[var1, var2] = [2, 4]", "", SKIP_STRICT_FUNCTION,
       PreciseMaybeAssigned::NO},
      {"{var1, var2} = {var1: 3, var2: 3}", "", SKIP_STRICT_FUNCTION,
       PreciseMaybeAssigned::NO},
558 559

      // Default parameters inside destruring parameters.
560 561 562 563
      {"[var1 = 4, var2 = var1]", "", SKIP_STRICT_FUNCTION,
       PreciseMaybeAssigned::NO},
      {"{var1 = 4, var2 = var1}", "", SKIP_STRICT_FUNCTION,
       PreciseMaybeAssigned::NO},
564 565

      // Locals shadowing parameters.
566
      {"var1, var2", "var var1 = 16; () => { var1 = 17; };"},
567 568

      // Locals shadowing destructuring parameters and the rest parameter.
569
      {"[var1, var2]", "var var1 = 16; () => { var1 = 17; };",
570
       SKIP_STRICT_FUNCTION},
571
      {"{var1, var2}", "var var1 = 16; () => { var1 = 17; };",
572
       SKIP_STRICT_FUNCTION},
573
      {"var1, var2, ...var3", "var var3 = 16; () => { var3 = 17; };",
574
       SKIP_STRICT_FUNCTION},
575
      {"var1, var2 = var1", "var var1 = 16; () => { var1 = 17; };",
576
       SKIP_STRICT_FUNCTION, PreciseMaybeAssigned::NO},
577 578

      // Hoisted sloppy block function shadowing a parameter.
579
      // FIXME(marja): why is maybe_assigned inaccurate?
580 581
      {"var1, var2", "for (;;) { function var1() { } }", DONT_SKIP,
       PreciseMaybeAssigned::NO},
582

583
      // Sloppy eval in default parameter.
584
      {"var1, var2 = eval(''), var3", "let var4 = 0;", SKIP_STRICT_FUNCTION,
585
       Bailout::BAILOUT_IF_OUTER_SLOPPY},
586
      {"var1, var2 = eval(''), var3 = eval('')", "let var4 = 0;",
587
       SKIP_STRICT_FUNCTION, Bailout::BAILOUT_IF_OUTER_SLOPPY},
588

589 590
      // Sloppy eval in arrow function parameter list which is inside another
      // arrow function parameter list.
591
      {"var1, var2 = (var3, var4 = eval(''), var5) => { let var6; }, var7",
592 593 594 595
       "let var8 = 0;", SKIP_STRICT_FUNCTION, Bailout::BAILOUT_IF_OUTER_SLOPPY},

      // Sloppy eval in a function body with non-simple parameters.
      {"var1 = 1, var2 = 2", "eval('');", SKIP_STRICT_FUNCTION},
596 597 598 599 600 601 602

      // Catch variable
      {"try { } catch(var1) { }"},
      {"try { } catch(var1) { var1; }"},
      {"try { } catch(var1) { var1 = 3; }"},
      {"try { } catch(var1) { function f() { var1; } }"},
      {"try { } catch(var1) { function f() { var1 = 3; } }"},
603 604 605 606 607

      {"try { } catch({var1, var2}) { function f() { var1 = 3; } }"},
      {"try { } catch([var1, var2]) { function f() { var1 = 3; } }"},
      {"try { } catch({}) { }"},
      {"try { } catch([]) { }"},
608 609 610 611

      // Shadowing the catch variable
      {"try { } catch(var1) { var var1 = 3; }"},
      {"try { } catch(var1) { var var1 = 3; function f() { var1 = 3; } }"},
612 613 614

      // Classes
      {"class MyClass {}"},
615 616 617 618 619 620 621
      {"var1 = class MyClass {};"},
      {"var var1 = class MyClass {};"},
      {"let var1 = class MyClass {};"},
      {"const var1 = class MyClass {};"},
      {"var var1 = class {};"},
      {"let var1 = class {};"},
      {"const var1 = class {};"},
622

623 624 625 626 627 628
      {"class MyClass { constructor() {} }"},
      {"class MyClass { constructor() { var var1; } }"},
      {"class MyClass { constructor() { var var1 = 11; } }"},
      {"class MyClass { constructor() { var var1; function foo() { var1 = 11; "
       "} } }"},

629 630 631 632 633 634 635 636 637 638
      {"class MyClass { m() {} }"},
      {"class MyClass { m() { var var1; } }"},
      {"class MyClass { m() { var var1 = 11; } }"},
      {"class MyClass { m() { var var1; function foo() { var1 = 11; } } }"},

      {"class MyClass { static m() {} }"},
      {"class MyClass { static m() { var var1; } }"},
      {"class MyClass { static m() { var var1 = 11; } }"},
      {"class MyClass { static m() { var var1; function foo() { var1 = 11; } } "
       "}"},
639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660

      {"class MyBase {} class MyClass extends MyBase {}"},
      {"class MyClass extends MyBase { constructor() {} }"},
      {"class MyClass extends MyBase { constructor() { super(); } }"},
      {"class MyClass extends MyBase { constructor() { var var1; } }"},
      {"class MyClass extends MyBase { constructor() { var var1 = 11; } }"},
      {"class MyClass extends MyBase { constructor() { var var1; function "
       "foo() { var1 = 11; } } }"},

      {"class MyClass extends MyBase { m() {} }"},
      {"class MyClass extends MyBase { m() { super.foo; } }"},
      {"class MyClass extends MyBase { m() { var var1; } }"},
      {"class MyClass extends MyBase { m() { var var1 = 11; } }"},
      {"class MyClass extends MyBase { m() { var var1; function foo() { var1 = "
       "11; } } }"},

      {"class MyClass extends MyBase { static m() {} }"},
      {"class MyClass extends MyBase { static m() { super.foo; } }"},
      {"class MyClass extends MyBase { static m() { var var1; } }"},
      {"class MyClass extends MyBase { static m() { var var1 = 11; } }"},
      {"class MyClass extends MyBase { static m() { var var1; function foo() { "
       "var1 = 11; } } }"},
661 662 663 664 665

      {"class X { ['bar'] = 1; }; new X;",
       [] { i::FLAG_harmony_public_fields = true; },
       [] { i::FLAG_harmony_public_fields = false; }},
      {"class X { static ['foo'] = 2; }; new X;",
666 667 668 669 670 671 672 673
       [] {
         i::FLAG_harmony_public_fields = true;
         i::FLAG_harmony_static_fields = true;
       },
       [] {
         i::FLAG_harmony_public_fields = false;
         i::FLAG_harmony_static_fields = false;
       }},
674
      {"class X { ['bar'] = 1; static ['foo'] = 2; }; new X;",
675 676 677 678 679 680 681 682
       [] {
         i::FLAG_harmony_public_fields = true;
         i::FLAG_harmony_static_fields = true;
       },
       [] {
         i::FLAG_harmony_public_fields = false;
         i::FLAG_harmony_static_fields = false;
       }},
683 684 685 686 687 688
      {"class X { #x = 1 }; new X;",
       [] { i::FLAG_harmony_private_fields = true; },
       [] { i::FLAG_harmony_private_fields = false; }},
      {"function t() { return class { #x = 1 }; } new t();",
       [] { i::FLAG_harmony_private_fields = true; },
       [] { i::FLAG_harmony_private_fields = false; }},
689 690
  };

691 692 693 694 695 696
  for (unsigned i = 0; i < arraysize(outers); ++i) {
    struct Outer outer = outers[i];
    for (unsigned j = 0; j < arraysize(inners); ++j) {
      struct Inner inner = inners[j];
      if (outer.strict_outer && (inner.skip & SKIP_STRICT_OUTER)) continue;
      if (outer.strict_test_function && (inner.skip & SKIP_STRICT_FUNCTION)) {
697 698
        continue;
      }
699
      if (outer.arrow && (inner.skip & SKIP_ARROW)) continue;
700

701
      const char* code = outer.code;
702
      int code_len = Utf8LengthHelper(code);
703

704 705
      int params_len = Utf8LengthHelper(inner.params);
      int source_len = Utf8LengthHelper(inner.source);
706
      int len = code_len + params_len + source_len;
707

708
      if (inner.prologue != nullptr) inner.prologue();
709

710
      i::ScopedVector<char> program(len + 1);
711
      i::SNPrintF(program, code, inner.params, inner.source);
712

713 714
      i::HandleScope scope(isolate);

715
      i::Handle<i::String> source =
716
          factory->InternalizeUtf8String(program.start());
717 718 719
      source->PrintOn(stdout);
      printf("\n");

720 721 722 723
      // Compile and run the script to get a pointer to the lazy function.
      v8::Local<v8::Value> v = CompileRun(program.start());
      i::Handle<i::Object> o = v8::Utils::OpenHandle(*v);
      i::Handle<i::JSFunction> f = i::Handle<i::JSFunction>::cast(o);
724
      i::Handle<i::SharedFunctionInfo> shared = i::handle(f->shared(), isolate);
725

726 727
      if (inner.bailout == Bailout::BAILOUT_IF_OUTER_SLOPPY &&
          !outer.strict_outer) {
728
        CHECK(!shared->HasUncompiledDataWithPreparseData());
729 730
        continue;
      }
731

732 733 734
      CHECK(shared->HasUncompiledDataWithPreparseData());
      i::Handle<i::PreparseData> produced_data_on_heap(
          shared->uncompiled_data_with_preparse_data()->preparse_data(),
735
          isolate);
736 737

      // Parse the lazy function using the scope data.
738
      i::ParseInfo using_scope_data(isolate, shared);
739
      using_scope_data.set_lazy_compile();
740 741
      using_scope_data.set_consumed_preparse_data(
          i::ConsumedPreparseData::For(isolate, produced_data_on_heap));
742 743 744 745 746 747 748 749 750
      CHECK(i::parsing::ParseFunction(&using_scope_data, shared, isolate));

      // Verify that we skipped at least one function inside that scope.
      i::DeclarationScope* scope_with_skipped_functions =
          using_scope_data.literal()->scope();
      CHECK(i::ScopeTestHelper::HasSkippedFunctionInside(
          scope_with_skipped_functions));

      // Do scope allocation (based on the preparsed scope data).
751
      CHECK(i::DeclarationScope::Analyze(&using_scope_data));
752 753

      // Parse the lazy function again eagerly to produce baseline data.
754
      i::ParseInfo not_using_scope_data(isolate, shared);
755 756 757 758 759 760 761 762 763 764 765
      not_using_scope_data.set_lazy_compile();
      CHECK(i::parsing::ParseFunction(&not_using_scope_data, shared, isolate));

      // Verify that we didn't skip anything (there's no preparsed scope data,
      // so we cannot skip).
      i::DeclarationScope* scope_without_skipped_functions =
          not_using_scope_data.literal()->scope();
      CHECK(!i::ScopeTestHelper::HasSkippedFunctionInside(
          scope_without_skipped_functions));

      // Do normal scope allocation.
766
      CHECK(i::DeclarationScope::Analyze(&not_using_scope_data));
767 768 769

      // Verify that scope allocation gave the same results when parsing w/ the
      // scope data (and skipping functions), and when parsing without.
770
      i::ScopeTestHelper::CompareScopes(
771
          scope_without_skipped_functions, scope_with_skipped_functions,
772
          inner.precise_maybe_assigned == PreciseMaybeAssigned::YES);
773

774
      if (inner.epilogue != nullptr) inner.epilogue();
775
    }
776 777
  }
}
778 779 780 781 782 783 784 785 786 787 788 789 790

// Regression test for
// https://bugs.chromium.org/p/chromium/issues/detail?id=753896. Should not
// crash.
TEST(Regress753896) {
  i::Isolate* isolate = CcTest::i_isolate();
  i::Factory* factory = isolate->factory();
  i::HandleScope scope(isolate);
  LocalContext env;

  i::Handle<i::String> source = factory->InternalizeUtf8String(
      "function lazy() { let v = 0; if (true) { var v = 0; } }");
  i::Handle<i::Script> script = factory->NewScript(source);
791
  i::ParseInfo info(isolate, script);
792 793 794 795 796

  // We don't assert that parsing succeeded or that it failed; currently the
  // error is not detected inside lazy functions, but it might be in the future.
  i::parsing::ParseProgram(&info, isolate);
}
797 798 799 800 801 802 803

TEST(ProducingAndConsumingByteData) {
  i::Isolate* isolate = CcTest::i_isolate();
  i::HandleScope scope(isolate);
  LocalContext env;

  i::Zone zone(isolate->allocator(), ZONE_NAME);
804 805 806
  std::vector<uint8_t> buffer;
  i::PreparseDataBuilder::ByteData bytes;
  bytes.Start(&buffer);
807 808 809 810 811 812 813 814

  bytes.Reserve(32);
  bytes.Reserve(32);
  CHECK_EQ(buffer.size(), 32);
  const int kBufferSize = 64;
  bytes.Reserve(kBufferSize);
  CHECK_EQ(buffer.size(), kBufferSize);

815
  // Write some data.
816
#ifdef DEBUG
817
  bytes.WriteUint32(1983);  // This will be overwritten.
818 819 820 821
#else
  bytes.WriteVarint32(1983);
#endif
  bytes.WriteVarint32(2147483647);
822 823
  bytes.WriteUint8(4);
  bytes.WriteUint8(255);
824
  bytes.WriteVarint32(0);
825
  bytes.WriteUint8(0);
826
#ifdef DEBUG
827 828
  bytes.SaveCurrentSizeAtFirstUint32();
  int saved_size = 21;
829 830
  CHECK_EQ(buffer.size(), kBufferSize);
  CHECK_EQ(bytes.length(), saved_size);
831
#endif
832
  bytes.WriteUint8(100);
833 834 835 836 837 838 839 840
  // Write quarter bytes between uint8s and uint32s to verify they're stored
  // correctly.
  bytes.WriteQuarter(3);
  bytes.WriteQuarter(0);
  bytes.WriteQuarter(2);
  bytes.WriteQuarter(1);
  bytes.WriteQuarter(0);
  bytes.WriteUint8(50);
841 842 843 844 845 846 847 848

  bytes.WriteQuarter(0);
  bytes.WriteQuarter(1);
  bytes.WriteQuarter(2);
  bytes.WriteQuarter(3);
  bytes.WriteVarint32(50);

  // End with a lonely quarter.
849 850 851
  bytes.WriteQuarter(0);
  bytes.WriteQuarter(1);
  bytes.WriteQuarter(2);
852 853
  bytes.WriteVarint32(0xff);

854 855
  // End with a lonely quarter.
  bytes.WriteQuarter(2);
856

857
  CHECK_EQ(buffer.size(), 64);
858
#ifdef DEBUG
859
  const int kDataSize = 42;
860
#else
861
  const int kDataSize = 21;
862
#endif
863 864
  CHECK_EQ(bytes.length(), kDataSize);
  CHECK_EQ(buffer.size(), kBufferSize);
865 866 867 868 869 870 871 872

  // Copy buffer for sanity checks later-on.
  std::vector<uint8_t> copied_buffer(buffer);

  // Move the data from the temporary buffer into the zone for later
  // serialization.
  bytes.Finalize(&zone);
  CHECK_EQ(buffer.size(), 0);
873
  CHECK_EQ(copied_buffer.size(), kBufferSize);
874

875
  {
876
    // Serialize as a ZoneConsumedPreparseData, and read back data.
877
    i::ZonePreparseData* data_in_zone = bytes.CopyToZone(&zone, 0);
878
    i::ZoneConsumedPreparseData::ByteData bytes_for_reading;
879
    i::ZoneVectorWrapper wrapper(data_in_zone->byte_data());
880
    i::ZoneConsumedPreparseData::ByteData::ReadingScope reading_scope(
881
        &bytes_for_reading, wrapper);
882

883 884 885
    CHECK_EQ(wrapper.data_length(), kDataSize);

    for (int i = 0; i < kDataSize; i++) {
886 887 888
      CHECK_EQ(copied_buffer.at(i), wrapper.get(i));
    }

889
#ifdef DEBUG
890
    CHECK_EQ(bytes_for_reading.ReadUint32(), saved_size);
891
#else
892
    CHECK_EQ(bytes_for_reading.ReadVarint32(), 1983);
893
#endif
894
    CHECK_EQ(bytes_for_reading.ReadVarint32(), 2147483647);
895 896
    CHECK_EQ(bytes_for_reading.ReadUint8(), 4);
    CHECK_EQ(bytes_for_reading.ReadUint8(), 255);
897
    CHECK_EQ(bytes_for_reading.ReadVarint32(), 0);
898 899
    CHECK_EQ(bytes_for_reading.ReadUint8(), 0);
    CHECK_EQ(bytes_for_reading.ReadUint8(), 100);
900

901 902 903 904 905 906
    CHECK_EQ(bytes_for_reading.ReadQuarter(), 3);
    CHECK_EQ(bytes_for_reading.ReadQuarter(), 0);
    CHECK_EQ(bytes_for_reading.ReadQuarter(), 2);
    CHECK_EQ(bytes_for_reading.ReadQuarter(), 1);
    CHECK_EQ(bytes_for_reading.ReadQuarter(), 0);
    CHECK_EQ(bytes_for_reading.ReadUint8(), 50);
907

908 909 910
    CHECK_EQ(bytes_for_reading.ReadQuarter(), 0);
    CHECK_EQ(bytes_for_reading.ReadQuarter(), 1);
    CHECK_EQ(bytes_for_reading.ReadQuarter(), 2);
911 912 913 914 915 916 917 918
    CHECK_EQ(bytes_for_reading.ReadQuarter(), 3);
    CHECK_EQ(bytes_for_reading.ReadVarint32(), 50);

    CHECK_EQ(bytes_for_reading.ReadQuarter(), 0);
    CHECK_EQ(bytes_for_reading.ReadQuarter(), 1);
    CHECK_EQ(bytes_for_reading.ReadQuarter(), 2);
    CHECK_EQ(bytes_for_reading.ReadVarint32(), 0xff);

919
    CHECK_EQ(bytes_for_reading.ReadQuarter(), 2);
920 921
    // We should have consumed all data at this point.
    CHECK(!bytes_for_reading.HasRemainingBytes(1));
922 923 924
  }

  {
925
    // Serialize as an OnHeapConsumedPreparseData, and read back data.
926
    i::Handle<i::PreparseData> data_on_heap = bytes.CopyToHeap(isolate, 0);
927
    CHECK_EQ(data_on_heap->data_length(), kDataSize);
928
    CHECK_EQ(data_on_heap->children_length(), 0);
929 930
    i::OnHeapConsumedPreparseData::ByteData bytes_for_reading;
    i::OnHeapConsumedPreparseData::ByteData::ReadingScope reading_scope(
931 932
        &bytes_for_reading, *data_on_heap);

933
    for (int i = 0; i < kDataSize; i++) {
934 935 936
      CHECK_EQ(copied_buffer[i], data_on_heap->get(i));
    }

937
#ifdef DEBUG
938
    CHECK_EQ(bytes_for_reading.ReadUint32(), saved_size);
939
#else
940
    CHECK_EQ(bytes_for_reading.ReadVarint32(), 1983);
941
#endif
942
    CHECK_EQ(bytes_for_reading.ReadVarint32(), 2147483647);
943 944
    CHECK_EQ(bytes_for_reading.ReadUint8(), 4);
    CHECK_EQ(bytes_for_reading.ReadUint8(), 255);
945
    CHECK_EQ(bytes_for_reading.ReadVarint32(), 0);
946 947
    CHECK_EQ(bytes_for_reading.ReadUint8(), 0);
    CHECK_EQ(bytes_for_reading.ReadUint8(), 100);
948

949 950 951 952 953 954
    CHECK_EQ(bytes_for_reading.ReadQuarter(), 3);
    CHECK_EQ(bytes_for_reading.ReadQuarter(), 0);
    CHECK_EQ(bytes_for_reading.ReadQuarter(), 2);
    CHECK_EQ(bytes_for_reading.ReadQuarter(), 1);
    CHECK_EQ(bytes_for_reading.ReadQuarter(), 0);
    CHECK_EQ(bytes_for_reading.ReadUint8(), 50);
955

956 957 958
    CHECK_EQ(bytes_for_reading.ReadQuarter(), 0);
    CHECK_EQ(bytes_for_reading.ReadQuarter(), 1);
    CHECK_EQ(bytes_for_reading.ReadQuarter(), 2);
959 960 961 962 963 964 965 966
    CHECK_EQ(bytes_for_reading.ReadQuarter(), 3);
    CHECK_EQ(bytes_for_reading.ReadVarint32(), 50);

    CHECK_EQ(bytes_for_reading.ReadQuarter(), 0);
    CHECK_EQ(bytes_for_reading.ReadQuarter(), 1);
    CHECK_EQ(bytes_for_reading.ReadQuarter(), 2);
    CHECK_EQ(bytes_for_reading.ReadVarint32(), 0xff);

967
    CHECK_EQ(bytes_for_reading.ReadQuarter(), 2);
968 969
    // We should have consumed all data at this point.
    CHECK(!bytes_for_reading.HasRemainingBytes(1));
970
  }
971
}