OLD | NEW |
1 /* | 1 /* |
2 * This file is part of Adblock Plus <http://adblockplus.org/>, | 2 * This file is part of Adblock Plus <http://adblockplus.org/>, |
3 * Copyright (C) 2006-2014 Eyeo GmbH | 3 * Copyright (C) 2006-2014 Eyeo GmbH |
4 * | 4 * |
5 * Adblock Plus is free software: you can redistribute it and/or modify | 5 * Adblock Plus is free software: you can redistribute it and/or modify |
6 * it under the terms of the GNU General Public License version 3 as | 6 * it under the terms of the GNU General Public License version 3 as |
7 * published by the Free Software Foundation. | 7 * published by the Free Software Foundation. |
8 * | 8 * |
9 * Adblock Plus is distributed in the hope that it will be useful, | 9 * Adblock Plus is distributed in the hope that it will be useful, |
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of | 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
(...skipping 379 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
390 let type5 = type1.extend({}, { | 390 let type5 = type1.extend({}, { |
391 destructor: function(super_) | 391 destructor: function(super_) |
392 { | 392 { |
393 this.retain(); | 393 this.retain(); |
394 this.release(); | 394 this.release(); |
395 } | 395 } |
396 }); | 396 }); |
397 type5(0).release(); | 397 type5(0).release(); |
398 ok(true, "Temporarily retaining reference in destructor is allowed"); | 398 ok(true, "Temporarily retaining reference in destructor is allowed"); |
399 }); | 399 }); |
| 400 |
| 401 test("Property watchers", function() |
| 402 { |
| 403 let {ObjectType, uint8, int32} = require("typedObjects"); |
| 404 |
| 405 let watched = null; |
| 406 let type1 = new ObjectType({ |
| 407 foo: uint8, |
| 408 bar: int32 |
| 409 }, { |
| 410 constructor: function(foo, bar) |
| 411 { |
| 412 this.foo = foo; |
| 413 this.bar = bar; |
| 414 }, |
| 415 |
| 416 watch: { |
| 417 foo: function(value) |
| 418 { |
| 419 watched = [this, "foo", this.foo, value]; |
| 420 return value + 1; |
| 421 }, |
| 422 bar: function(value) |
| 423 { |
| 424 watched = [this, "bar", this.bar, value]; |
| 425 return value + 2; |
| 426 } |
| 427 } |
| 428 }); |
| 429 |
| 430 let obj1 = type1(1, 2); |
| 431 |
| 432 obj1.foo = 5; |
| 433 deepEqual(watched, [obj1, "foo", 2, 5], "Watcher called for first property")
; |
| 434 equal(obj1.foo, 6, "Value returned by the watcher applied"); |
| 435 |
| 436 obj1.bar += 4; |
| 437 deepEqual(watched, [obj1, "bar", 4, 8], "Watcher called for second property"
); |
| 438 equal(obj1.bar, 10, "Value returned by the watcher applied"); |
| 439 |
| 440 let type2 = type1.extend({}, { |
| 441 watch: { |
| 442 bar: function(value) |
| 443 { |
| 444 watched = [this, "barOverridden", this.bar, value]; |
| 445 return value; |
| 446 } |
| 447 } |
| 448 }); |
| 449 |
| 450 let obj2 = type2(3, 4); |
| 451 |
| 452 obj2.foo = 8; |
| 453 deepEqual(watched, [obj2, "foo", 4, 8], "Watchers are inherited"); |
| 454 equal(obj2.foo, 9, "Value returned by the watcher applied"); |
| 455 |
| 456 obj2.bar = 10; |
| 457 deepEqual(watched, [obj2, "barOverridden", 4, 10], "Watchers can be overridd
en"); |
| 458 equal(obj2.bar, 10, "Value returned by the watcher applied"); |
| 459 }); |
| 460 |
| 461 test("Arrays of primitive types", function() |
| 462 { |
| 463 let {ObjectType, uint32} = require("typedObjects"); |
| 464 |
| 465 let arrayDestroyed = false; |
| 466 let uint32Array = uint32.Array({ |
| 467 customProp: uint32, |
| 468 setCustomProp: function(customProp) |
| 469 { |
| 470 this.customProp = customProp; |
| 471 } |
| 472 }, { |
| 473 constructor: function(length) |
| 474 { |
| 475 this.length = length; |
| 476 }, |
| 477 destructor: function() |
| 478 { |
| 479 arrayDestroyed = true; |
| 480 } |
| 481 }); |
| 482 ok(uint32Array, "Array type created"); |
| 483 |
| 484 let array1 = uint32Array(3); |
| 485 ok(array1, "Array created"); |
| 486 equal(array1.length, 3, "Constructor set length to 3"); |
| 487 equal(array1.size, 4, "Array size was set accordingly"); |
| 488 |
| 489 // Custom properties/methods |
| 490 equal(typeof array1.customProp, "number", "Custom array property created"); |
| 491 equal(typeof array1.setCustomProp, "function", "Custom array method created"
); |
| 492 |
| 493 array1.setCustomProp(12); |
| 494 equal(array1.customProp, 12, "Method could set custom property"); |
| 495 |
| 496 // Setting/reading array elements |
| 497 for (var i = 0; i < 3; i++) |
| 498 array1.set(i, i * 2); |
| 499 for (var i = 0; i < 3; i++) |
| 500 equal(array1.get(i), i * 2, "Array element value persisted"); |
| 501 |
| 502 // Array length changes |
| 503 array1.length = 5; |
| 504 equal(array1.length, 5, "Length increased to 5"); |
| 505 equal(array1.size, 8, "Array size adjusted accordingly"); |
| 506 for (var i = 0; i < 3; i++) |
| 507 equal(array1.get(i), i * 2, "Array element value survived length increase"
); |
| 508 |
| 509 array1.length = 2; |
| 510 equal(array1.length, 2, "Length reduced to 2"); |
| 511 equal(array1.size, 8, "Array size unchanged after length reduction"); |
| 512 for (var i = 0; i < 2; i++) |
| 513 equal(array1.get(i), i * 2, "Value of remaining elements survived length d
ecrease"); |
| 514 |
| 515 // Out of bounds read/writes |
| 516 throws(() => array1.get(-1), "Getting with negative element index throws"); |
| 517 throws(() => array1.get(2), "Getting with too large element index throws"); |
| 518 throws(() => array1.set(-1, 12), "Setting with negative element index throws
"); |
| 519 throws(() => array1.set(2, 12), "Setting with too large element index throws
"); |
| 520 |
| 521 // Using array as a property type |
| 522 let type1 = ObjectType({ |
| 523 foo: uint32Array |
| 524 }); |
| 525 let obj1 = type1(); |
| 526 obj1.foo = array1; |
| 527 ok(array1.equals(obj1.foo), "Array assigned to object property correctly"); |
| 528 |
| 529 ok(!arrayDestroyed, "Array not destroyed at this point"); |
| 530 array1.release(); |
| 531 ok(!arrayDestroyed, "Array not destroyed after releasing if referenced in an
object"); |
| 532 |
| 533 obj1.release(); |
| 534 ok(arrayDestroyed, "Array destroyed after releasing object holding a referen
ce to it"); |
| 535 }); |
| 536 |
| 537 test("Arrays of objects", function() |
| 538 { |
| 539 let {ObjectType, uint8} = require("typedObjects"); |
| 540 |
| 541 let destroyed = []; |
| 542 let arrayDestroyed = false; |
| 543 let type1 = ObjectType({ |
| 544 foo: uint8 |
| 545 }, { |
| 546 constructor: function(foo) |
| 547 { |
| 548 this.foo = foo; |
| 549 }, |
| 550 destructor: function() |
| 551 { |
| 552 destroyed.push(this.foo); |
| 553 } |
| 554 }); |
| 555 |
| 556 let type1Array = type1.Array(null, { |
| 557 destructor: function() |
| 558 { |
| 559 arrayDestroyed = true; |
| 560 } |
| 561 }); |
| 562 ok(type1Array, "Array type created"); |
| 563 |
| 564 let array1 = type1Array(); |
| 565 ok(array1, "Array created"); |
| 566 |
| 567 equal(array1.length, 0, "Default array length"); |
| 568 equal(array1.size, 0, "Default array size"); |
| 569 |
| 570 throws(() => array1.get(0), "Getting element of empty array throws"); |
| 571 throws(() => array1.set(0, null), "Setting element of empty array throws"); |
| 572 |
| 573 array1.length = 1; |
| 574 equal(array1.length, 1, "Array length set to 1"); |
| 575 equal(array1.size, 1, "Array size adjusted accordingly"); |
| 576 |
| 577 let obj1 = type1(1); |
| 578 array1.set(0, obj1); |
| 579 obj1.release(); |
| 580 |
| 581 ok(obj1.equals(array1.get(0)), "Array element persisted"); |
| 582 throws(() => array1.get(-1), "Getting with negative element index throws"); |
| 583 throws(() => array1.get(1), "Getting with too large element index throws"); |
| 584 throws(() => array1.set(-1, null), "Setting with negative element index thro
ws"); |
| 585 throws(() => array1.set(1, null), "Setting with too large element index thro
ws"); |
| 586 |
| 587 array1.length = 3; |
| 588 equal(array1.length, 3, "Array length set to 3"); |
| 589 equal(array1.size, 4, "Array size adjusted accordingly"); |
| 590 |
| 591 ok(obj1.equals(array1.get(0)), "Array element survived resizing"); |
| 592 equal(array1.get(1), null, "Uninitialized array element is null"); |
| 593 equal(array1.get(2), null, "Uninitialized array element is null"); |
| 594 |
| 595 let obj2 = type1(2); |
| 596 array1.set(2, obj2); |
| 597 obj2.release(); |
| 598 |
| 599 ok(obj1.equals(array1.get(0)), "Array element unchanged after setting anothe
r element"); |
| 600 equal(array1.get(1), null, "Uninitialized array element is null"); |
| 601 ok(obj2.equals(array1.get(2)), "Array element persisted"); |
| 602 |
| 603 deepEqual(destroyed, [], "No objects destroyed at this point"); |
| 604 |
| 605 array1.set(0, null); |
| 606 deepEqual(destroyed, [1], "Object destroyed after being unset in array"); |
| 607 |
| 608 array1.set(1, array1.get(2)); |
| 609 array1.set(2, null); |
| 610 deepEqual(destroyed, [1], "Object not destroyed after being unset in array i
f still set on another element"); |
| 611 |
| 612 array1.length = 1; |
| 613 equal(array1.length, 1, "Array length reduced"); |
| 614 equal(array1.size, 4, "Array size unchanged after length reduction"); |
| 615 deepEqual(destroyed, [1, 2], "Object destroyed after removed implicitly by r
educing length"); |
| 616 |
| 617 ok(!arrayDestroyed, "Array not destroyed at this point"); |
| 618 array1.release(); |
| 619 ok(arrayDestroyed, "Array destroyed after releasing"); |
| 620 }); |
| 621 |
| 622 test("Array memory allocation", function() |
| 623 { |
| 624 let {uint32} = require("typedObjects"); |
| 625 |
| 626 let uint32Array = uint32.Array(null, { |
| 627 arrayBufferSize: 8, |
| 628 constructor: function(length) |
| 629 { |
| 630 this.length = length; |
| 631 } |
| 632 }); |
| 633 |
| 634 let array1 = uint32Array(0); |
| 635 equal(array1.arrayBufferIndex, -1, "No buffer allocated for zero-size arrays
"); |
| 636 |
| 637 array1.length = 3; |
| 638 equal(array1.arrayBufferIndex, 0, "First array allocated in first buffer"); |
| 639 equal(array1.arrayByteOffset, 0, "First array allocated at zero byte offset"
); |
| 640 |
| 641 let array2 = uint32Array(4); |
| 642 equal(array2.arrayBufferIndex, 0, "Second array allocated in first buffer"); |
| 643 equal(array2.arrayByteOffset, 16, "Second array allocated at next available
byte offset"); |
| 644 |
| 645 let array3 = uint32Array(4); |
| 646 equal(array3.arrayBufferIndex, 1, "Third array allocated in new buffer"); |
| 647 equal(array3.arrayByteOffset, 0, "Third array allocated at zero byte offset"
); |
| 648 |
| 649 let array4 = uint32Array(2); |
| 650 equal(array4.arrayBufferIndex, 2, "Array with different size allocated in ne
w buffer"); |
| 651 equal(array4.arrayByteOffset, 0, "Array with different size allocated at zer
o offset"); |
| 652 |
| 653 array2.release(); |
| 654 array2 = uint32Array(3); |
| 655 equal(array2.arrayBufferIndex, 0, "After releasing an array new array is all
ocated in same buffer"); |
| 656 equal(array2.arrayByteOffset, 16, "After releasing an array new array is all
ocated at same byte offset"); |
| 657 |
| 658 array1.length = 0; |
| 659 array1.size = 0; |
| 660 equal(array1.arrayBufferIndex, -1, "Setting array size to zero releases its
buffer"); |
| 661 |
| 662 array4.length = 4; |
| 663 equal(array4.arrayBufferIndex, 0, "Increasing array size moves it to a diffe
rent buffer"); |
| 664 equal(array4.arrayByteOffset, 0, "Increasing array size moves makes it reuse
the spot from a released array buffer"); |
| 665 |
| 666 let array5 = uint32Array(9); |
| 667 equal(array5.arrayBufferIndex, 3, "Large array gets its own buffer"); |
| 668 equal(array5.arrayByteOffset, 0, "Large array is allocated at zero offset"); |
| 669 |
| 670 let array6 = uint32Array(9); |
| 671 equal(array6.arrayBufferIndex, 4, "Second large array gets its own buffer"); |
| 672 equal(array6.arrayByteOffset, 0, "Second large array is allocated at zero of
fset"); |
| 673 |
| 674 array5.release(); |
| 675 array5 = uint32Array(9); |
| 676 equal(array5.arrayBufferIndex, 5, "Buffer indexes for large arrays aren't re
used"); |
| 677 equal(array5.arrayByteOffset, 0, "Large array is allocated at zero offset"); |
| 678 |
| 679 for (let array of [array1, array2, array3, array4]) |
| 680 array.release(); |
| 681 }); |
400 })(); | 682 })(); |
OLD | NEW |