| OLD | NEW |
| 1 // Copyright 2006-2008 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2008 the V8 project authors. All rights reserved. |
| 2 | 2 |
| 3 #include <stdlib.h> | 3 #include <stdlib.h> |
| 4 | 4 |
| 5 #include "v8.h" | 5 #include "v8.h" |
| 6 | 6 |
| 7 #include "execution.h" | 7 #include "execution.h" |
| 8 #include "factory.h" | 8 #include "factory.h" |
| 9 #include "macro-assembler.h" | 9 #include "macro-assembler.h" |
| 10 #include "global-handles.h" | 10 #include "global-handles.h" |
| (...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 207 | 207 |
| 208 { | 208 { |
| 209 v8::HandleScope inner_scope; | 209 v8::HandleScope inner_scope; |
| 210 // Allocate a function and keep it in global object's property. | 210 // Allocate a function and keep it in global object's property. |
| 211 Handle<JSFunction> function = | 211 Handle<JSFunction> function = |
| 212 FACTORY->NewFunction(name, FACTORY->undefined_value()); | 212 FACTORY->NewFunction(name, FACTORY->undefined_value()); |
| 213 Handle<Map> initial_map = | 213 Handle<Map> initial_map = |
| 214 FACTORY->NewMap(JS_OBJECT_TYPE, JSObject::kHeaderSize); | 214 FACTORY->NewMap(JS_OBJECT_TYPE, JSObject::kHeaderSize); |
| 215 function->set_initial_map(*initial_map); | 215 function->set_initial_map(*initial_map); |
| 216 Isolate::Current()->context()->global()->SetProperty( | 216 Isolate::Current()->context()->global()->SetProperty( |
| 217 *name, *function, NONE)->ToObjectChecked(); | 217 *name, *function, NONE, kNonStrictMode)->ToObjectChecked(); |
| 218 // Allocate an object. Unrooted after leaving the scope. | 218 // Allocate an object. Unrooted after leaving the scope. |
| 219 Handle<JSObject> obj = FACTORY->NewJSObject(function); | 219 Handle<JSObject> obj = FACTORY->NewJSObject(function); |
| 220 obj->SetProperty(*prop_name, Smi::FromInt(23), NONE)->ToObjectChecked(); | 220 obj->SetProperty( |
| 221 obj->SetProperty(*prop_namex, Smi::FromInt(24), NONE)->ToObjectChecked(); | 221 *prop_name, Smi::FromInt(23), NONE, kNonStrictMode)->ToObjectChecked(); |
| 222 obj->SetProperty( |
| 223 *prop_namex, Smi::FromInt(24), NONE, kNonStrictMode)->ToObjectChecked(); |
| 222 | 224 |
| 223 CHECK_EQ(Smi::FromInt(23), obj->GetProperty(*prop_name)); | 225 CHECK_EQ(Smi::FromInt(23), obj->GetProperty(*prop_name)); |
| 224 CHECK_EQ(Smi::FromInt(24), obj->GetProperty(*prop_namex)); | 226 CHECK_EQ(Smi::FromInt(24), obj->GetProperty(*prop_namex)); |
| 225 } | 227 } |
| 226 | 228 |
| 227 HEAP->CollectGarbage(NEW_SPACE); | 229 HEAP->CollectGarbage(NEW_SPACE); |
| 228 | 230 |
| 229 // Function should be alive. | 231 // Function should be alive. |
| 230 CHECK(Isolate::Current()->context()->global()->HasLocalProperty(*name)); | 232 CHECK(Isolate::Current()->context()->global()->HasLocalProperty(*name)); |
| 231 // Check function is retained. | 233 // Check function is retained. |
| 232 Object* func_value = Isolate::Current()->context()->global()-> | 234 Object* func_value = Isolate::Current()->context()->global()-> |
| 233 GetProperty(*name)->ToObjectChecked(); | 235 GetProperty(*name)->ToObjectChecked(); |
| 234 CHECK(func_value->IsJSFunction()); | 236 CHECK(func_value->IsJSFunction()); |
| 235 Handle<JSFunction> function(JSFunction::cast(func_value)); | 237 Handle<JSFunction> function(JSFunction::cast(func_value)); |
| 236 | 238 |
| 237 { | 239 { |
| 238 HandleScope inner_scope; | 240 HandleScope inner_scope; |
| 239 // Allocate another object, make it reachable from global. | 241 // Allocate another object, make it reachable from global. |
| 240 Handle<JSObject> obj = FACTORY->NewJSObject(function); | 242 Handle<JSObject> obj = FACTORY->NewJSObject(function); |
| 241 Isolate::Current()->context()->global()-> | 243 Isolate::Current()->context()->global()->SetProperty( |
| 242 SetProperty(*obj_name, *obj, NONE)->ToObjectChecked(); | 244 *obj_name, *obj, NONE, kNonStrictMode)->ToObjectChecked(); |
| 243 obj->SetProperty(*prop_name, Smi::FromInt(23), NONE)->ToObjectChecked(); | 245 obj->SetProperty( |
| 246 *prop_name, Smi::FromInt(23), NONE, kNonStrictMode)->ToObjectChecked(); |
| 244 } | 247 } |
| 245 | 248 |
| 246 // After gc, it should survive. | 249 // After gc, it should survive. |
| 247 HEAP->CollectGarbage(NEW_SPACE); | 250 HEAP->CollectGarbage(NEW_SPACE); |
| 248 | 251 |
| 249 CHECK(Isolate::Current()->context()->global()->HasLocalProperty(*obj_name)); | 252 CHECK(Isolate::Current()->context()->global()->HasLocalProperty(*obj_name)); |
| 250 CHECK(Isolate::Current()->context()->global()-> | 253 CHECK(Isolate::Current()->context()->global()-> |
| 251 GetProperty(*obj_name)->ToObjectChecked()->IsJSObject()); | 254 GetProperty(*obj_name)->ToObjectChecked()->IsJSObject()); |
| 252 Object* obj = Isolate::Current()->context()->global()-> | 255 Object* obj = Isolate::Current()->context()->global()-> |
| 253 GetProperty(*obj_name)->ToObjectChecked(); | 256 GetProperty(*obj_name)->ToObjectChecked(); |
| (...skipping 282 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 536 v8::HandleScope sc; | 539 v8::HandleScope sc; |
| 537 Handle<String> name = FACTORY->LookupAsciiSymbol("theFunction"); | 540 Handle<String> name = FACTORY->LookupAsciiSymbol("theFunction"); |
| 538 Handle<JSFunction> function = | 541 Handle<JSFunction> function = |
| 539 FACTORY->NewFunction(name, FACTORY->undefined_value()); | 542 FACTORY->NewFunction(name, FACTORY->undefined_value()); |
| 540 Handle<Map> initial_map = | 543 Handle<Map> initial_map = |
| 541 FACTORY->NewMap(JS_OBJECT_TYPE, JSObject::kHeaderSize); | 544 FACTORY->NewMap(JS_OBJECT_TYPE, JSObject::kHeaderSize); |
| 542 function->set_initial_map(*initial_map); | 545 function->set_initial_map(*initial_map); |
| 543 | 546 |
| 544 Handle<String> prop_name = FACTORY->LookupAsciiSymbol("theSlot"); | 547 Handle<String> prop_name = FACTORY->LookupAsciiSymbol("theSlot"); |
| 545 Handle<JSObject> obj = FACTORY->NewJSObject(function); | 548 Handle<JSObject> obj = FACTORY->NewJSObject(function); |
| 546 obj->SetProperty(*prop_name, Smi::FromInt(23), NONE)->ToObjectChecked(); | 549 obj->SetProperty( |
| 550 *prop_name, Smi::FromInt(23), NONE, kNonStrictMode)->ToObjectChecked(); |
| 547 CHECK_EQ(Smi::FromInt(23), obj->GetProperty(*prop_name)); | 551 CHECK_EQ(Smi::FromInt(23), obj->GetProperty(*prop_name)); |
| 548 // Check that we can add properties to function objects. | 552 // Check that we can add properties to function objects. |
| 549 function->SetProperty(*prop_name, | 553 function->SetProperty( |
| 550 Smi::FromInt(24), | 554 *prop_name, Smi::FromInt(24), NONE, kNonStrictMode)->ToObjectChecked(); |
| 551 NONE)->ToObjectChecked(); | |
| 552 CHECK_EQ(Smi::FromInt(24), function->GetProperty(*prop_name)); | 555 CHECK_EQ(Smi::FromInt(24), function->GetProperty(*prop_name)); |
| 553 } | 556 } |
| 554 | 557 |
| 555 | 558 |
| 556 TEST(ObjectProperties) { | 559 TEST(ObjectProperties) { |
| 557 InitializeVM(); | 560 InitializeVM(); |
| 558 | 561 |
| 559 v8::HandleScope sc; | 562 v8::HandleScope sc; |
| 560 String* object_symbol = String::cast(HEAP->Object_symbol()); | 563 String* object_symbol = String::cast(HEAP->Object_symbol()); |
| 561 Object* raw_object = Isolate::Current()->context()->global()-> | 564 Object* raw_object = Isolate::Current()->context()->global()-> |
| 562 GetProperty(object_symbol)->ToObjectChecked(); | 565 GetProperty(object_symbol)->ToObjectChecked(); |
| 563 JSFunction* object_function = JSFunction::cast(raw_object); | 566 JSFunction* object_function = JSFunction::cast(raw_object); |
| 564 Handle<JSFunction> constructor(object_function); | 567 Handle<JSFunction> constructor(object_function); |
| 565 Handle<JSObject> obj = FACTORY->NewJSObject(constructor); | 568 Handle<JSObject> obj = FACTORY->NewJSObject(constructor); |
| 566 Handle<String> first = FACTORY->LookupAsciiSymbol("first"); | 569 Handle<String> first = FACTORY->LookupAsciiSymbol("first"); |
| 567 Handle<String> second = FACTORY->LookupAsciiSymbol("second"); | 570 Handle<String> second = FACTORY->LookupAsciiSymbol("second"); |
| 568 | 571 |
| 569 // check for empty | 572 // check for empty |
| 570 CHECK(!obj->HasLocalProperty(*first)); | 573 CHECK(!obj->HasLocalProperty(*first)); |
| 571 | 574 |
| 572 // add first | 575 // add first |
| 573 obj->SetProperty(*first, Smi::FromInt(1), NONE)->ToObjectChecked(); | 576 obj->SetProperty( |
| 577 *first, Smi::FromInt(1), NONE, kNonStrictMode)->ToObjectChecked(); |
| 574 CHECK(obj->HasLocalProperty(*first)); | 578 CHECK(obj->HasLocalProperty(*first)); |
| 575 | 579 |
| 576 // delete first | 580 // delete first |
| 577 CHECK(obj->DeleteProperty(*first, JSObject::NORMAL_DELETION)); | 581 CHECK(obj->DeleteProperty(*first, JSObject::NORMAL_DELETION)); |
| 578 CHECK(!obj->HasLocalProperty(*first)); | 582 CHECK(!obj->HasLocalProperty(*first)); |
| 579 | 583 |
| 580 // add first and then second | 584 // add first and then second |
| 581 obj->SetProperty(*first, Smi::FromInt(1), NONE)->ToObjectChecked(); | 585 obj->SetProperty( |
| 582 obj->SetProperty(*second, Smi::FromInt(2), NONE)->ToObjectChecked(); | 586 *first, Smi::FromInt(1), NONE, kNonStrictMode)->ToObjectChecked(); |
| 587 obj->SetProperty( |
| 588 *second, Smi::FromInt(2), NONE, kNonStrictMode)->ToObjectChecked(); |
| 583 CHECK(obj->HasLocalProperty(*first)); | 589 CHECK(obj->HasLocalProperty(*first)); |
| 584 CHECK(obj->HasLocalProperty(*second)); | 590 CHECK(obj->HasLocalProperty(*second)); |
| 585 | 591 |
| 586 // delete first and then second | 592 // delete first and then second |
| 587 CHECK(obj->DeleteProperty(*first, JSObject::NORMAL_DELETION)); | 593 CHECK(obj->DeleteProperty(*first, JSObject::NORMAL_DELETION)); |
| 588 CHECK(obj->HasLocalProperty(*second)); | 594 CHECK(obj->HasLocalProperty(*second)); |
| 589 CHECK(obj->DeleteProperty(*second, JSObject::NORMAL_DELETION)); | 595 CHECK(obj->DeleteProperty(*second, JSObject::NORMAL_DELETION)); |
| 590 CHECK(!obj->HasLocalProperty(*first)); | 596 CHECK(!obj->HasLocalProperty(*first)); |
| 591 CHECK(!obj->HasLocalProperty(*second)); | 597 CHECK(!obj->HasLocalProperty(*second)); |
| 592 | 598 |
| 593 // add first and then second | 599 // add first and then second |
| 594 obj->SetProperty(*first, Smi::FromInt(1), NONE)->ToObjectChecked(); | 600 obj->SetProperty( |
| 595 obj->SetProperty(*second, Smi::FromInt(2), NONE)->ToObjectChecked(); | 601 *first, Smi::FromInt(1), NONE, kNonStrictMode)->ToObjectChecked(); |
| 602 obj->SetProperty( |
| 603 *second, Smi::FromInt(2), NONE, kNonStrictMode)->ToObjectChecked(); |
| 596 CHECK(obj->HasLocalProperty(*first)); | 604 CHECK(obj->HasLocalProperty(*first)); |
| 597 CHECK(obj->HasLocalProperty(*second)); | 605 CHECK(obj->HasLocalProperty(*second)); |
| 598 | 606 |
| 599 // delete second and then first | 607 // delete second and then first |
| 600 CHECK(obj->DeleteProperty(*second, JSObject::NORMAL_DELETION)); | 608 CHECK(obj->DeleteProperty(*second, JSObject::NORMAL_DELETION)); |
| 601 CHECK(obj->HasLocalProperty(*first)); | 609 CHECK(obj->HasLocalProperty(*first)); |
| 602 CHECK(obj->DeleteProperty(*first, JSObject::NORMAL_DELETION)); | 610 CHECK(obj->DeleteProperty(*first, JSObject::NORMAL_DELETION)); |
| 603 CHECK(!obj->HasLocalProperty(*first)); | 611 CHECK(!obj->HasLocalProperty(*first)); |
| 604 CHECK(!obj->HasLocalProperty(*second)); | 612 CHECK(!obj->HasLocalProperty(*second)); |
| 605 | 613 |
| 606 // check string and symbol match | 614 // check string and symbol match |
| 607 static const char* string1 = "fisk"; | 615 static const char* string1 = "fisk"; |
| 608 Handle<String> s1 = FACTORY->NewStringFromAscii(CStrVector(string1)); | 616 Handle<String> s1 = FACTORY->NewStringFromAscii(CStrVector(string1)); |
| 609 obj->SetProperty(*s1, Smi::FromInt(1), NONE)->ToObjectChecked(); | 617 obj->SetProperty( |
| 618 *s1, Smi::FromInt(1), NONE, kNonStrictMode)->ToObjectChecked(); |
| 610 Handle<String> s1_symbol = FACTORY->LookupAsciiSymbol(string1); | 619 Handle<String> s1_symbol = FACTORY->LookupAsciiSymbol(string1); |
| 611 CHECK(obj->HasLocalProperty(*s1_symbol)); | 620 CHECK(obj->HasLocalProperty(*s1_symbol)); |
| 612 | 621 |
| 613 // check symbol and string match | 622 // check symbol and string match |
| 614 static const char* string2 = "fugl"; | 623 static const char* string2 = "fugl"; |
| 615 Handle<String> s2_symbol = FACTORY->LookupAsciiSymbol(string2); | 624 Handle<String> s2_symbol = FACTORY->LookupAsciiSymbol(string2); |
| 616 obj->SetProperty(*s2_symbol, Smi::FromInt(1), NONE)->ToObjectChecked(); | 625 obj->SetProperty( |
| 626 *s2_symbol, Smi::FromInt(1), NONE, kNonStrictMode)->ToObjectChecked(); |
| 617 Handle<String> s2 = FACTORY->NewStringFromAscii(CStrVector(string2)); | 627 Handle<String> s2 = FACTORY->NewStringFromAscii(CStrVector(string2)); |
| 618 CHECK(obj->HasLocalProperty(*s2)); | 628 CHECK(obj->HasLocalProperty(*s2)); |
| 619 } | 629 } |
| 620 | 630 |
| 621 | 631 |
| 622 TEST(JSObjectMaps) { | 632 TEST(JSObjectMaps) { |
| 623 InitializeVM(); | 633 InitializeVM(); |
| 624 | 634 |
| 625 v8::HandleScope sc; | 635 v8::HandleScope sc; |
| 626 Handle<String> name = FACTORY->LookupAsciiSymbol("theFunction"); | 636 Handle<String> name = FACTORY->LookupAsciiSymbol("theFunction"); |
| 627 Handle<JSFunction> function = | 637 Handle<JSFunction> function = |
| 628 FACTORY->NewFunction(name, FACTORY->undefined_value()); | 638 FACTORY->NewFunction(name, FACTORY->undefined_value()); |
| 629 Handle<Map> initial_map = | 639 Handle<Map> initial_map = |
| 630 FACTORY->NewMap(JS_OBJECT_TYPE, JSObject::kHeaderSize); | 640 FACTORY->NewMap(JS_OBJECT_TYPE, JSObject::kHeaderSize); |
| 631 function->set_initial_map(*initial_map); | 641 function->set_initial_map(*initial_map); |
| 632 | 642 |
| 633 Handle<String> prop_name = FACTORY->LookupAsciiSymbol("theSlot"); | 643 Handle<String> prop_name = FACTORY->LookupAsciiSymbol("theSlot"); |
| 634 Handle<JSObject> obj = FACTORY->NewJSObject(function); | 644 Handle<JSObject> obj = FACTORY->NewJSObject(function); |
| 635 | 645 |
| 636 // Set a propery | 646 // Set a propery |
| 637 obj->SetProperty(*prop_name, Smi::FromInt(23), NONE)->ToObjectChecked(); | 647 obj->SetProperty( |
| 648 *prop_name, Smi::FromInt(23), NONE, kNonStrictMode)->ToObjectChecked(); |
| 638 CHECK_EQ(Smi::FromInt(23), obj->GetProperty(*prop_name)); | 649 CHECK_EQ(Smi::FromInt(23), obj->GetProperty(*prop_name)); |
| 639 | 650 |
| 640 // Check the map has changed | 651 // Check the map has changed |
| 641 CHECK(*initial_map != obj->map()); | 652 CHECK(*initial_map != obj->map()); |
| 642 } | 653 } |
| 643 | 654 |
| 644 | 655 |
| 645 TEST(JSArray) { | 656 TEST(JSArray) { |
| 646 InitializeVM(); | 657 InitializeVM(); |
| 647 | 658 |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 694 v8::HandleScope sc; | 705 v8::HandleScope sc; |
| 695 String* object_symbol = String::cast(HEAP->Object_symbol()); | 706 String* object_symbol = String::cast(HEAP->Object_symbol()); |
| 696 Object* raw_object = Isolate::Current()->context()->global()-> | 707 Object* raw_object = Isolate::Current()->context()->global()-> |
| 697 GetProperty(object_symbol)->ToObjectChecked(); | 708 GetProperty(object_symbol)->ToObjectChecked(); |
| 698 JSFunction* object_function = JSFunction::cast(raw_object); | 709 JSFunction* object_function = JSFunction::cast(raw_object); |
| 699 Handle<JSFunction> constructor(object_function); | 710 Handle<JSFunction> constructor(object_function); |
| 700 Handle<JSObject> obj = FACTORY->NewJSObject(constructor); | 711 Handle<JSObject> obj = FACTORY->NewJSObject(constructor); |
| 701 Handle<String> first = FACTORY->LookupAsciiSymbol("first"); | 712 Handle<String> first = FACTORY->LookupAsciiSymbol("first"); |
| 702 Handle<String> second = FACTORY->LookupAsciiSymbol("second"); | 713 Handle<String> second = FACTORY->LookupAsciiSymbol("second"); |
| 703 | 714 |
| 704 obj->SetProperty(*first, Smi::FromInt(1), NONE)->ToObjectChecked(); | 715 obj->SetProperty( |
| 705 obj->SetProperty(*second, Smi::FromInt(2), NONE)->ToObjectChecked(); | 716 *first, Smi::FromInt(1), NONE, kNonStrictMode)->ToObjectChecked(); |
| 717 obj->SetProperty( |
| 718 *second, Smi::FromInt(2), NONE, kNonStrictMode)->ToObjectChecked(); |
| 706 | 719 |
| 707 Object* ok = obj->SetElement(0, *first)->ToObjectChecked(); | 720 Object* ok = obj->SetElement(0, *first)->ToObjectChecked(); |
| 708 | 721 |
| 709 ok = obj->SetElement(1, *second)->ToObjectChecked(); | 722 ok = obj->SetElement(1, *second)->ToObjectChecked(); |
| 710 | 723 |
| 711 // Make the clone. | 724 // Make the clone. |
| 712 Handle<JSObject> clone = Copy(obj); | 725 Handle<JSObject> clone = Copy(obj); |
| 713 CHECK(!clone.is_identical_to(obj)); | 726 CHECK(!clone.is_identical_to(obj)); |
| 714 | 727 |
| 715 CHECK_EQ(obj->GetElement(0), clone->GetElement(0)); | 728 CHECK_EQ(obj->GetElement(0), clone->GetElement(0)); |
| 716 CHECK_EQ(obj->GetElement(1), clone->GetElement(1)); | 729 CHECK_EQ(obj->GetElement(1), clone->GetElement(1)); |
| 717 | 730 |
| 718 CHECK_EQ(obj->GetProperty(*first), clone->GetProperty(*first)); | 731 CHECK_EQ(obj->GetProperty(*first), clone->GetProperty(*first)); |
| 719 CHECK_EQ(obj->GetProperty(*second), clone->GetProperty(*second)); | 732 CHECK_EQ(obj->GetProperty(*second), clone->GetProperty(*second)); |
| 720 | 733 |
| 721 // Flip the values. | 734 // Flip the values. |
| 722 clone->SetProperty(*first, Smi::FromInt(2), NONE)->ToObjectChecked(); | 735 clone->SetProperty( |
| 723 clone->SetProperty(*second, Smi::FromInt(1), NONE)->ToObjectChecked(); | 736 *first, Smi::FromInt(2), NONE, kNonStrictMode)->ToObjectChecked(); |
| 737 clone->SetProperty( |
| 738 *second, Smi::FromInt(1), NONE, kNonStrictMode)->ToObjectChecked(); |
| 724 | 739 |
| 725 ok = clone->SetElement(0, *second)->ToObjectChecked(); | 740 ok = clone->SetElement(0, *second)->ToObjectChecked(); |
| 726 ok = clone->SetElement(1, *first)->ToObjectChecked(); | 741 ok = clone->SetElement(1, *first)->ToObjectChecked(); |
| 727 | 742 |
| 728 CHECK_EQ(obj->GetElement(1), clone->GetElement(0)); | 743 CHECK_EQ(obj->GetElement(1), clone->GetElement(0)); |
| 729 CHECK_EQ(obj->GetElement(0), clone->GetElement(1)); | 744 CHECK_EQ(obj->GetElement(0), clone->GetElement(1)); |
| 730 | 745 |
| 731 CHECK_EQ(obj->GetProperty(*second), clone->GetProperty(*first)); | 746 CHECK_EQ(obj->GetProperty(*second), clone->GetProperty(*first)); |
| 732 CHECK_EQ(obj->GetProperty(*first), clone->GetProperty(*second)); | 747 CHECK_EQ(obj->GetProperty(*first), clone->GetProperty(*second)); |
| 733 } | 748 } |
| (...skipping 569 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1303 CHECK(helper.b_found()); | 1318 CHECK(helper.b_found()); |
| 1304 } | 1319 } |
| 1305 // ...but is now unreachable. | 1320 // ...but is now unreachable. |
| 1306 { | 1321 { |
| 1307 HeapIteratorTestHelper helper(a_saved, *b); | 1322 HeapIteratorTestHelper helper(a_saved, *b); |
| 1308 helper.IterateHeap(HeapIterator::kFilterUnreachable); | 1323 helper.IterateHeap(HeapIterator::kFilterUnreachable); |
| 1309 CHECK(!helper.a_found()); | 1324 CHECK(!helper.a_found()); |
| 1310 CHECK(helper.b_found()); | 1325 CHECK(helper.b_found()); |
| 1311 } | 1326 } |
| 1312 } | 1327 } |
| OLD | NEW |