test-preparser.cc 37.5 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/api-inl.h"
6
#include "src/ast/ast.h"
7
#include "src/codegen/compiler.h"
8
#include "src/objects/objects-inl.h"
9 10
#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

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

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

      // Let declarations and assignments.
140 141 142 143 144 145 146
      {"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; }"},
147 148

      // Const declarations.
149 150 151
      {"const var1 = 5;"},
      {"if (true) { const var1 = 5; }"},
      {"const var1 = 5; function f() { var1; }"},
152

153 154
      // Functions.
      {"function f1() { let var2; }"},
155 156 157 158 159 160
      {"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; };"},
161

162
      {"function *f1() { let var2; }"},
163 164
      {"let var1 = function *f1() { let var2; };"},
      {"let var1 = function*() { let var2; };"},
165 166

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

170
      // Redeclarations.
171 172 173 174 175 176 177 178
      {"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; }"},
179 180

      // Shadowing declarations.
181 182 183
      {"var var1; if (true) { var var1; }"},
      {"var var1; if (true) { let var1; }"},
      {"let var1; if (true) { let var1; }"},
184

185 186
      {"var var1; if (true) { const var1 = 0; }"},
      {"const var1 = 0; if (true) { const var1 = 0; }"},
187

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

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

202 203
      {"this;"},
      {"if (true) { this; }"},
204
      {"() => { this; };"},
205 206

      // Variable called "arguments"
207 208
      {"var arguments;", SKIP_STRICT},
      {"var arguments; arguments = 5;", SKIP_STRICT},
209
      {"if (true) { var arguments; }", SKIP_STRICT, PreciseMaybeAssigned::NO},
210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227
      {"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},
228 229

      // Destructuring declarations.
230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255
      {"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]};"},
256 257

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

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

      // Evals.
273 274 275 276 277 278
      {"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(''); }"},
279 280

      // Standard for loops.
281 282 283 284 285 286 287
      {"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; } }"},
288 289

      // For of loops
290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313
      {"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; } }"},
314 315

      // For in loops
316 317 318 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
      {"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; } }"},
345

346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361
      // 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; } }"},

362 363 364 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
      // 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; } }"},

397
      // Loops without declarations
398 399 400 401 402 403 404 405
      {"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; } "
406
       "}"},
407 408 409
      {"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; } }"},
410

411
      // Block functions (potentially sloppy).
412
      {"if (true) { function f1() {} }"},
413
      {"if (true) { function f1() {} function f1() {} }", SKIP_STRICT},
414
      {"if (true) { if (true) { function f1() {} } }"},
415 416
      {"if (true) { if (true) { function f1() {} function f1() {} } }",
       SKIP_STRICT},
417 418 419 420 421
      {"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; } "
422
       "}",
423
       SKIP_STRICT},
424
      {"if (true) { function f1() {} function f1() {} } function foo() { f1; "
425
       "}",
426
       SKIP_STRICT},
427 428
      {"if (true) { if (true) { function f1() {} } function foo() { f1; } }"},
      {"if (true) { if (true) { function f1() {} function f1() {} } function "
429
       "foo() { f1; } }",
430
       SKIP_STRICT},
431 432
      {"if (true) { function f1() {} f1 = 3; function foo() { f1; } }"},
      {"if (true) { function f1() {} f1 = 3; } function foo() { f1; }"},
433

434 435
      {"var f1 = 1; if (true) { function f1() {} }"},
      {"var f1 = 1; if (true) { function f1() {} } function foo() { f1; }"},
436

437 438
      {"if (true) { function f1() {} function f2() { f1(); } }"},

439 440 441
      {"if (true) { function *f1() {} }"},
      {"if (true) { async function f1() {} }"},

442 443 444
      // (Potentially sloppy) block function shadowing a catch variable.
      {"try { } catch(var1) { if (true) { function var1() {} } }"},

445 446 447 448 449 450 451
      // Simple parameters.
      {"var1", ""},
      {"var1", "var1;"},
      {"var1", "var1 = 9;"},
      {"var1", "function f1() { var1; }"},
      {"var1", "function f1() { var1 = 9; }"},

452 453 454 455 456 457 458 459 460 461
      {"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; }"},

462
      // Duplicate parameters.
463 464 465 466 467 468 469
      {"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)},
470 471 472

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

474
      // Rest parameter.
475 476 477 478 479 480 481 482 483 484 485
      {"...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},
486

487
      // Default parameters.
488 489 490 491
      {"var1 = 3", "", SKIP_STRICT_FUNCTION, PreciseMaybeAssigned::NO},
      {"var1, var2 = var1", "", SKIP_STRICT_FUNCTION, PreciseMaybeAssigned::NO},
      {"var1, var2 = 4, ...var3", "", SKIP_STRICT_FUNCTION,
       PreciseMaybeAssigned::NO},
492 493 494

      // Destructuring parameters. Because of the search space explosion, we
      // cannot test all interesting cases. Let's try to test a relevant subset.
495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511
      {"[]", "", 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},

512 513 514 515
      {"[var1]", "() => { var1; };", SKIP_STRICT_FUNCTION},
      {"{name1: var1}", "() => { var1; };", SKIP_STRICT_FUNCTION},
      {"{name1: var1}", "() => { name1; };", SKIP_STRICT_FUNCTION},
      {"{var1}", "() => { var1; };", SKIP_STRICT_FUNCTION},
516 517 518 519 520

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

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

      // Nesting destructuring.
529 530
      {"[var1, [var2, var3], {var4, name5: [var5, var6]}]", "",
       SKIP_STRICT_FUNCTION},
531 532

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

537
      // Complicated cases from bugs.
538
      {"var1 = {} = {}", "", SKIP_STRICT_FUNCTION, PreciseMaybeAssigned::NO},
539

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

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

      // Default parameters inside destruring parameters.
557 558 559 560
      {"[var1 = 4, var2 = var1]", "", SKIP_STRICT_FUNCTION,
       PreciseMaybeAssigned::NO},
      {"{var1 = 4, var2 = var1}", "", SKIP_STRICT_FUNCTION,
       PreciseMaybeAssigned::NO},
561 562

      // Locals shadowing parameters.
563
      {"var1, var2", "var var1 = 16; () => { var1 = 17; };"},
564 565

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

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

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

586 587
      // Sloppy eval in arrow function parameter list which is inside another
      // arrow function parameter list.
588
      {"var1, var2 = (var3, var4 = eval(''), var5) => { let var6; }, var7",
589 590 591 592
       "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},
593 594 595 596 597 598 599

      // 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; } }"},
600 601 602 603 604

      {"try { } catch({var1, var2}) { function f() { var1 = 3; } }"},
      {"try { } catch([var1, var2]) { function f() { var1 = 3; } }"},
      {"try { } catch({}) { }"},
      {"try { } catch([]) { }"},
605 606 607 608

      // Shadowing the catch variable
      {"try { } catch(var1) { var var1 = 3; }"},
      {"try { } catch(var1) { var var1 = 3; function f() { var1 = 3; } }"},
609 610 611

      // Classes
      {"class MyClass {}"},
612 613 614 615 616 617 618
      {"var1 = class MyClass {};"},
      {"var var1 = class MyClass {};"},
      {"let var1 = class MyClass {};"},
      {"const var1 = class MyClass {};"},
      {"var var1 = class {};"},
      {"let var1 = class {};"},
      {"const var1 = class {};"},
619

620 621 622 623 624 625
      {"class MyClass { constructor() {} }"},
      {"class MyClass { constructor() { var var1; } }"},
      {"class MyClass { constructor() { var var1 = 11; } }"},
      {"class MyClass { constructor() { var var1; function foo() { var1 = 11; "
       "} } }"},

626 627 628 629 630 631 632 633 634 635
      {"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; } } "
       "}"},
636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657

      {"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; } } }"},
658

659 660 661 662 663
      {"class X { ['bar'] = 1; }; new X;"},
      {"class X { static ['foo'] = 2; }; new X;"},
      {"class X { ['bar'] = 1; static ['foo'] = 2; }; new X;"},
      {"class X { #x = 1 }; new X;"},
      {"function t() { return class { #x = 1 }; } new t();"},
664 665
  };

666 667 668 669 670 671
  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)) {
672 673
        continue;
      }
674
      if (outer.arrow && (inner.skip & SKIP_ARROW)) continue;
675

676
      const char* code = outer.code;
677
      int code_len = Utf8LengthHelper(code);
678

679 680
      int params_len = Utf8LengthHelper(inner.params);
      int source_len = Utf8LengthHelper(inner.source);
681
      int len = code_len + params_len + source_len;
682

683
      i::ScopedVector<char> program(len + 1);
684
      i::SNPrintF(program, code, inner.params, inner.source);
685

686 687
      i::HandleScope scope(isolate);

688
      i::Handle<i::String> source =
689
          factory->InternalizeUtf8String(program.begin());
690 691 692
      source->PrintOn(stdout);
      printf("\n");

693
      // Compile and run the script to get a pointer to the lazy function.
694
      v8::Local<v8::Value> v = CompileRun(program.begin());
695 696
      i::Handle<i::Object> o = v8::Utils::OpenHandle(*v);
      i::Handle<i::JSFunction> f = i::Handle<i::JSFunction>::cast(o);
697
      i::Handle<i::SharedFunctionInfo> shared = i::handle(f->shared(), isolate);
698

699 700
      if (inner.bailout == Bailout::BAILOUT_IF_OUTER_SLOPPY &&
          !outer.strict_outer) {
701
        CHECK(!shared->HasUncompiledDataWithPreparseData());
702 703
        continue;
      }
704

705 706
      CHECK(shared->HasUncompiledDataWithPreparseData());
      i::Handle<i::PreparseData> produced_data_on_heap(
707
          shared->uncompiled_data_with_preparse_data().preparse_data(),
708
          isolate);
709

710 711 712 713
      i::UnoptimizedCompileFlags flags =
          i::UnoptimizedCompileFlags::ForFunctionCompile(isolate, *shared);
      flags.set_is_lazy_compile(true);

714
      // Parse the lazy function using the scope data.
715 716
      i::UnoptimizedCompileState using_scope_state(isolate);
      i::ParseInfo using_scope_data(isolate, flags, &using_scope_state);
717 718
      using_scope_data.set_consumed_preparse_data(
          i::ConsumedPreparseData::For(isolate, produced_data_on_heap));
719 720
      CHECK(i::parsing::ParseFunction(&using_scope_data, shared, isolate,
                                      i::parsing::ReportStatisticsMode::kYes));
721 722 723 724 725 726 727 728

      // 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));

      // Parse the lazy function again eagerly to produce baseline data.
729 730
      i::UnoptimizedCompileState not_using_scope_state(isolate);
      i::ParseInfo not_using_scope_data(isolate, flags, &not_using_scope_state);
731 732
      CHECK(i::parsing::ParseFunction(&not_using_scope_data, shared, isolate,
                                      i::parsing::ReportStatisticsMode::kYes));
733 734 735 736 737 738 739 740 741 742

      // 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));

      // Verify that scope allocation gave the same results when parsing w/ the
      // scope data (and skipping functions), and when parsing without.
743
      i::ScopeTestHelper::CompareScopes(
744
          scope_without_skipped_functions, scope_with_skipped_functions,
745
          inner.precise_maybe_assigned == PreciseMaybeAssigned::YES);
746
    }
747 748
  }
}
749 750 751 752 753 754 755 756 757 758 759 760 761

// 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);
762
  i::UnoptimizedCompileState state(isolate);
763 764
  i::UnoptimizedCompileFlags flags =
      i::UnoptimizedCompileFlags::ForScriptCompile(isolate, *script);
765
  i::ParseInfo info(isolate, flags, &state);
766 767 768

  // 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.
769 770
  i::parsing::ParseProgram(&info, script, isolate,
                           i::parsing::ReportStatisticsMode::kYes);
771
}
772 773 774 775 776 777 778

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

  i::Zone zone(isolate->allocator(), ZONE_NAME);
779 780 781
  std::vector<uint8_t> buffer;
  i::PreparseDataBuilder::ByteData bytes;
  bytes.Start(&buffer);
782 783 784 785 786 787 788 789

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

790
  // Write some data.
791
#ifdef DEBUG
792
  bytes.WriteUint32(1983);  // This will be overwritten.
793 794 795 796
#else
  bytes.WriteVarint32(1983);
#endif
  bytes.WriteVarint32(2147483647);
797 798
  bytes.WriteUint8(4);
  bytes.WriteUint8(255);
799
  bytes.WriteVarint32(0);
800
  bytes.WriteUint8(0);
801
#ifdef DEBUG
802 803
  bytes.SaveCurrentSizeAtFirstUint32();
  int saved_size = 21;
804 805
  CHECK_EQ(buffer.size(), kBufferSize);
  CHECK_EQ(bytes.length(), saved_size);
806
#endif
807
  bytes.WriteUint8(100);
808 809 810 811 812 813 814 815
  // 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);
816 817 818 819 820 821 822 823

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

  // End with a lonely quarter.
824 825 826
  bytes.WriteQuarter(0);
  bytes.WriteQuarter(1);
  bytes.WriteQuarter(2);
827 828
  bytes.WriteVarint32(0xff);

829 830
  // End with a lonely quarter.
  bytes.WriteQuarter(2);
831

832
  CHECK_EQ(buffer.size(), 64);
833
#ifdef DEBUG
834
  const int kDataSize = 42;
835
#else
836
  const int kDataSize = 21;
837
#endif
838 839
  CHECK_EQ(bytes.length(), kDataSize);
  CHECK_EQ(buffer.size(), kBufferSize);
840 841 842 843 844 845 846 847

  // 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);
848
  CHECK_EQ(copied_buffer.size(), kBufferSize);
849

850
  {
851
    // Serialize as a ZoneConsumedPreparseData, and read back data.
852
    i::ZonePreparseData* data_in_zone = bytes.CopyToZone(&zone, 0);
853
    i::ZoneConsumedPreparseData::ByteData bytes_for_reading;
854
    i::ZoneVectorWrapper wrapper(data_in_zone->byte_data());
855
    i::ZoneConsumedPreparseData::ByteData::ReadingScope reading_scope(
856
        &bytes_for_reading, wrapper);
857

858 859 860
    CHECK_EQ(wrapper.data_length(), kDataSize);

    for (int i = 0; i < kDataSize; i++) {
861 862 863
      CHECK_EQ(copied_buffer.at(i), wrapper.get(i));
    }

864
#ifdef DEBUG
865
    CHECK_EQ(bytes_for_reading.ReadUint32(), saved_size);
866
#else
867
    CHECK_EQ(bytes_for_reading.ReadVarint32(), 1983);
868
#endif
869
    CHECK_EQ(bytes_for_reading.ReadVarint32(), 2147483647);
870 871
    CHECK_EQ(bytes_for_reading.ReadUint8(), 4);
    CHECK_EQ(bytes_for_reading.ReadUint8(), 255);
872
    CHECK_EQ(bytes_for_reading.ReadVarint32(), 0);
873 874
    CHECK_EQ(bytes_for_reading.ReadUint8(), 0);
    CHECK_EQ(bytes_for_reading.ReadUint8(), 100);
875

876 877 878 879 880 881
    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);
882

883 884 885
    CHECK_EQ(bytes_for_reading.ReadQuarter(), 0);
    CHECK_EQ(bytes_for_reading.ReadQuarter(), 1);
    CHECK_EQ(bytes_for_reading.ReadQuarter(), 2);
886 887 888 889 890 891 892 893
    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);

894
    CHECK_EQ(bytes_for_reading.ReadQuarter(), 2);
895 896
    // We should have consumed all data at this point.
    CHECK(!bytes_for_reading.HasRemainingBytes(1));
897 898 899
  }

  {
900
    // Serialize as an OnHeapConsumedPreparseData, and read back data.
901
    i::Handle<i::PreparseData> data_on_heap = bytes.CopyToHeap(isolate, 0);
902
    CHECK_EQ(data_on_heap->data_length(), kDataSize);
903
    CHECK_EQ(data_on_heap->children_length(), 0);
904 905
    i::OnHeapConsumedPreparseData::ByteData bytes_for_reading;
    i::OnHeapConsumedPreparseData::ByteData::ReadingScope reading_scope(
906 907
        &bytes_for_reading, *data_on_heap);

908
    for (int i = 0; i < kDataSize; i++) {
909 910 911
      CHECK_EQ(copied_buffer[i], data_on_heap->get(i));
    }

912
#ifdef DEBUG
913
    CHECK_EQ(bytes_for_reading.ReadUint32(), saved_size);
914
#else
915
    CHECK_EQ(bytes_for_reading.ReadVarint32(), 1983);
916
#endif
917
    CHECK_EQ(bytes_for_reading.ReadVarint32(), 2147483647);
918 919
    CHECK_EQ(bytes_for_reading.ReadUint8(), 4);
    CHECK_EQ(bytes_for_reading.ReadUint8(), 255);
920
    CHECK_EQ(bytes_for_reading.ReadVarint32(), 0);
921 922
    CHECK_EQ(bytes_for_reading.ReadUint8(), 0);
    CHECK_EQ(bytes_for_reading.ReadUint8(), 100);
923

924 925 926 927 928 929
    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);
930

931 932 933
    CHECK_EQ(bytes_for_reading.ReadQuarter(), 0);
    CHECK_EQ(bytes_for_reading.ReadQuarter(), 1);
    CHECK_EQ(bytes_for_reading.ReadQuarter(), 2);
934 935 936 937 938 939 940 941
    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);

942
    CHECK_EQ(bytes_for_reading.ReadQuarter(), 2);
943 944
    // We should have consumed all data at this point.
    CHECK(!bytes_for_reading.HasRemainingBytes(1));
945
  }
946
}