294dbf49bc
This patch ports over the spec defined operation `GetOption` from JavaScript to C++: https://tc39.github.io/ecma402/#sec-getoption The JS implementation will be deleted once all it's users are migrated. Refactors LocaleConstructor to use this method which fixes some test262 tests. The test262 test status file is updated to reflect this. Bug: v8:5751, v8:7684 Cq-Include-Trybots: luci.v8.try:v8_linux_noi18n_rel_ng Change-Id: Ief5eae9b69dcea50062825163ca7658ed20bd0cf Reviewed-on: https://chromium-review.googlesource.com/1094201 Commit-Queue: Sathya Gunasekaran <gsathya@chromium.org> Reviewed-by: Jakob Gruber <jgruber@chromium.org> Cr-Commit-Position: refs/heads/master@{#53652}
198 lines
7.5 KiB
C++
198 lines
7.5 KiB
C++
// 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.
|
|
|
|
#ifdef V8_INTL_SUPPORT
|
|
|
|
#include "src/builtins/builtins-intl.h"
|
|
#include "src/lookup.h"
|
|
#include "src/objects-inl.h"
|
|
#include "test/cctest/cctest.h"
|
|
|
|
namespace v8 {
|
|
namespace internal {
|
|
|
|
// This operator overloading enables CHECK_EQ to be used with
|
|
// std::vector<NumberFormatSpan>
|
|
bool operator==(const NumberFormatSpan& lhs, const NumberFormatSpan& rhs) {
|
|
return memcmp(&lhs, &rhs, sizeof(lhs)) == 0;
|
|
}
|
|
template <typename _CharT, typename _Traits, typename T>
|
|
std::basic_ostream<_CharT, _Traits>& operator<<(
|
|
std::basic_ostream<_CharT, _Traits>& self, const std::vector<T>& v) {
|
|
self << "[";
|
|
for (auto it = v.begin(); it < v.end();) {
|
|
self << *it;
|
|
it++;
|
|
if (it < v.end()) self << ", ";
|
|
}
|
|
return self << "]";
|
|
}
|
|
template <typename _CharT, typename _Traits>
|
|
std::basic_ostream<_CharT, _Traits>& operator<<(
|
|
std::basic_ostream<_CharT, _Traits>& self, const NumberFormatSpan& part) {
|
|
return self << "{" << part.field_id << "," << part.begin_pos << ","
|
|
<< part.end_pos << "}";
|
|
}
|
|
|
|
void test_flatten_regions_to_parts(
|
|
const std::vector<NumberFormatSpan>& regions,
|
|
const std::vector<NumberFormatSpan>& expected_parts) {
|
|
std::vector<NumberFormatSpan> mutable_regions = regions;
|
|
std::vector<NumberFormatSpan> parts = FlattenRegionsToParts(&mutable_regions);
|
|
CHECK_EQ(expected_parts, parts);
|
|
}
|
|
|
|
TEST(FlattenRegionsToParts) {
|
|
test_flatten_regions_to_parts(
|
|
std::vector<NumberFormatSpan>{
|
|
NumberFormatSpan(-1, 0, 10), NumberFormatSpan(1, 2, 8),
|
|
NumberFormatSpan(2, 2, 4), NumberFormatSpan(3, 6, 8),
|
|
},
|
|
std::vector<NumberFormatSpan>{
|
|
NumberFormatSpan(-1, 0, 2), NumberFormatSpan(2, 2, 4),
|
|
NumberFormatSpan(1, 4, 6), NumberFormatSpan(3, 6, 8),
|
|
NumberFormatSpan(-1, 8, 10),
|
|
});
|
|
test_flatten_regions_to_parts(
|
|
std::vector<NumberFormatSpan>{
|
|
NumberFormatSpan(0, 0, 1),
|
|
},
|
|
std::vector<NumberFormatSpan>{
|
|
NumberFormatSpan(0, 0, 1),
|
|
});
|
|
test_flatten_regions_to_parts(
|
|
std::vector<NumberFormatSpan>{
|
|
NumberFormatSpan(-1, 0, 1), NumberFormatSpan(0, 0, 1),
|
|
},
|
|
std::vector<NumberFormatSpan>{
|
|
NumberFormatSpan(0, 0, 1),
|
|
});
|
|
test_flatten_regions_to_parts(
|
|
std::vector<NumberFormatSpan>{
|
|
NumberFormatSpan(0, 0, 1), NumberFormatSpan(-1, 0, 1),
|
|
},
|
|
std::vector<NumberFormatSpan>{
|
|
NumberFormatSpan(0, 0, 1),
|
|
});
|
|
test_flatten_regions_to_parts(
|
|
std::vector<NumberFormatSpan>{
|
|
NumberFormatSpan(-1, 0, 10), NumberFormatSpan(1, 0, 1),
|
|
NumberFormatSpan(2, 0, 2), NumberFormatSpan(3, 0, 3),
|
|
NumberFormatSpan(4, 0, 4), NumberFormatSpan(5, 0, 5),
|
|
NumberFormatSpan(15, 5, 10), NumberFormatSpan(16, 6, 10),
|
|
NumberFormatSpan(17, 7, 10), NumberFormatSpan(18, 8, 10),
|
|
NumberFormatSpan(19, 9, 10),
|
|
},
|
|
std::vector<NumberFormatSpan>{
|
|
NumberFormatSpan(1, 0, 1), NumberFormatSpan(2, 1, 2),
|
|
NumberFormatSpan(3, 2, 3), NumberFormatSpan(4, 3, 4),
|
|
NumberFormatSpan(5, 4, 5), NumberFormatSpan(15, 5, 6),
|
|
NumberFormatSpan(16, 6, 7), NumberFormatSpan(17, 7, 8),
|
|
NumberFormatSpan(18, 8, 9), NumberFormatSpan(19, 9, 10),
|
|
});
|
|
|
|
// : 4
|
|
// : 22 33 3
|
|
// : 11111 22
|
|
// input regions: 0000000 111
|
|
// : ------------
|
|
// output parts: 0221340--231
|
|
test_flatten_regions_to_parts(
|
|
std::vector<NumberFormatSpan>{
|
|
NumberFormatSpan(-1, 0, 12), NumberFormatSpan(0, 0, 7),
|
|
NumberFormatSpan(1, 9, 12), NumberFormatSpan(1, 1, 6),
|
|
NumberFormatSpan(2, 9, 11), NumberFormatSpan(2, 1, 3),
|
|
NumberFormatSpan(3, 10, 11), NumberFormatSpan(3, 4, 6),
|
|
NumberFormatSpan(4, 5, 6),
|
|
},
|
|
std::vector<NumberFormatSpan>{
|
|
NumberFormatSpan(0, 0, 1), NumberFormatSpan(2, 1, 3),
|
|
NumberFormatSpan(1, 3, 4), NumberFormatSpan(3, 4, 5),
|
|
NumberFormatSpan(4, 5, 6), NumberFormatSpan(0, 6, 7),
|
|
NumberFormatSpan(-1, 7, 9), NumberFormatSpan(2, 9, 10),
|
|
NumberFormatSpan(3, 10, 11), NumberFormatSpan(1, 11, 12),
|
|
});
|
|
}
|
|
|
|
TEST(GetOptions) {
|
|
LocalContext env;
|
|
Isolate* isolate = CcTest::i_isolate();
|
|
v8::Isolate* v8_isolate = env->GetIsolate();
|
|
v8::HandleScope handle_scope(v8_isolate);
|
|
|
|
Handle<JSObject> options = isolate->factory()->NewJSObjectWithNullProto();
|
|
Handle<String> key = isolate->factory()->NewStringFromAsciiChecked("foo");
|
|
Handle<String> service =
|
|
isolate->factory()->NewStringFromAsciiChecked("service");
|
|
Handle<Object> undefined = isolate->factory()->undefined_value();
|
|
Handle<FixedArray> empty_fixed_array =
|
|
isolate->factory()->empty_fixed_array();
|
|
|
|
// No value found
|
|
Handle<Object> result =
|
|
Object::GetOption(isolate, options, key, Object::OptionType::String,
|
|
empty_fixed_array, undefined, service)
|
|
.ToHandleChecked();
|
|
CHECK(result->IsUndefined(isolate));
|
|
|
|
// Value found
|
|
v8::internal::LookupIterator it(options, key);
|
|
CHECK(Object::SetProperty(&it, Handle<Smi>(Smi::FromInt(42), isolate),
|
|
LanguageMode::kStrict,
|
|
AllocationMemento::MAY_BE_STORE_FROM_KEYED)
|
|
.FromJust());
|
|
result = Object::GetOption(isolate, options, key, Object::OptionType::String,
|
|
empty_fixed_array, undefined, service)
|
|
.ToHandleChecked();
|
|
CHECK(result->IsString());
|
|
Handle<String> expected_str =
|
|
isolate->factory()->NewStringFromAsciiChecked("42");
|
|
CHECK(String::Equals(expected_str, Handle<String>::cast(result)));
|
|
|
|
result = Object::GetOption(isolate, options, key, Object::OptionType::Boolean,
|
|
empty_fixed_array, undefined, service)
|
|
.ToHandleChecked();
|
|
CHECK(result->IsBoolean());
|
|
CHECK(result->IsTrue(isolate));
|
|
|
|
// No expected value in values array
|
|
Handle<FixedArray> values = isolate->factory()->NewFixedArray(1);
|
|
{
|
|
CHECK(!Object::GetOption(isolate, options, key, Object::OptionType::String,
|
|
values, undefined, service)
|
|
.ToHandle(&result));
|
|
CHECK(isolate->has_pending_exception());
|
|
isolate->clear_pending_exception();
|
|
}
|
|
|
|
// Add expected value to values array
|
|
values->set(0, *expected_str);
|
|
result = Object::GetOption(isolate, options, key, Object::OptionType::String,
|
|
values, undefined, service)
|
|
.ToHandleChecked();
|
|
CHECK(result->IsString());
|
|
CHECK(String::Equals(expected_str, Handle<String>::cast(result)));
|
|
|
|
// Test boolean values
|
|
CHECK(Object::SetProperty(&it, isolate->factory()->ToBoolean(false),
|
|
LanguageMode::kStrict,
|
|
AllocationMemento::MAY_BE_STORE_FROM_KEYED)
|
|
.FromJust());
|
|
result = Object::GetOption(isolate, options, key, Object::OptionType::String,
|
|
empty_fixed_array, undefined, service)
|
|
.ToHandleChecked();
|
|
CHECK(result->IsString());
|
|
|
|
result = Object::GetOption(isolate, options, key, Object::OptionType::Boolean,
|
|
empty_fixed_array, undefined, service)
|
|
.ToHandleChecked();
|
|
CHECK(result->IsBoolean());
|
|
CHECK(result->IsFalse(isolate));
|
|
}
|
|
|
|
} // namespace internal
|
|
} // namespace v8
|
|
|
|
#endif // V8_INTL_SUPPORT
|