mirror of
https://github.com/RGBCube/serenity
synced 2025-05-31 06:38:10 +00:00
LibJS: Simplify and normalize publicly-exposed Object functions
Previously, the Object class had many different types of functions for each action. For example: get_by_index, get(PropertyName), get(FlyString). This is a bit verbose, so these methods have been shortened to simply use the PropertyName structure. The methods then internally call _by_index if necessary. Note that the _by_index have been made private to enforce this change. Secondly, a clear distinction has been made between "putting" and "defining" an object property. "Putting" should mean modifying a (potentially) already existing property. This is akin to doing "a.b = 'foo'". This implies two things about put operations: - They will search the prototype chain for setters and call them, if necessary. - If no property exists with a particular key, the put operation should create a new property with the default attributes (configurable, writable, and enumerable). In contrast, "defining" a property should completely overwrite any existing value without calling setters (if that property is configurable, of course). Thus, all of the many JS objects have had any "put" calls changed to "define_property" calls. Additionally, "put_native_function" and "put_native_property" have had their "put" replaced with "define". Finally, "put_own_property" has been made private, as all necessary functionality should be exposed with the put and define_property methods.
This commit is contained in:
parent
59a32f29b0
commit
dd08c992e8
45 changed files with 501 additions and 417 deletions
|
@ -1282,20 +1282,20 @@ Value ObjectExpression::execute(Interpreter& interpreter) const
|
||||||
for (size_t i = 0; i < elements.size(); ++i) {
|
for (size_t i = 0; i < elements.size(); ++i) {
|
||||||
auto element = elements.at(i);
|
auto element = elements.at(i);
|
||||||
if (!element.is_empty())
|
if (!element.is_empty())
|
||||||
object->put_by_index(i, element);
|
object->define_property(i, element);
|
||||||
}
|
}
|
||||||
} else if (key_result.is_object()) {
|
} else if (key_result.is_object()) {
|
||||||
auto& obj_to_spread = key_result.as_object();
|
auto& obj_to_spread = key_result.as_object();
|
||||||
|
|
||||||
for (auto& it : obj_to_spread.shape().property_table_ordered()) {
|
for (auto& it : obj_to_spread.shape().property_table_ordered()) {
|
||||||
if (it.value.attributes & Attribute::Enumerable)
|
if (it.value.attributes & Attribute::Enumerable)
|
||||||
object->put(it.key, obj_to_spread.get(it.key));
|
object->define_property(it.key, obj_to_spread.get(it.key));
|
||||||
}
|
}
|
||||||
} else if (key_result.is_string()) {
|
} else if (key_result.is_string()) {
|
||||||
auto& str_to_spread = key_result.as_string().string();
|
auto& str_to_spread = key_result.as_string().string();
|
||||||
|
|
||||||
for (size_t i = 0; i < str_to_spread.length(); i++) {
|
for (size_t i = 0; i < str_to_spread.length(); i++) {
|
||||||
object->put_by_index(i, js_string(interpreter, str_to_spread.substring(i, 1)));
|
object->define_property(i, js_string(interpreter, str_to_spread.substring(i, 1)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1329,14 +1329,14 @@ Value ObjectExpression::execute(Interpreter& interpreter) const
|
||||||
}
|
}
|
||||||
if (!accessor) {
|
if (!accessor) {
|
||||||
accessor = Accessor::create(interpreter, nullptr, nullptr);
|
accessor = Accessor::create(interpreter, nullptr, nullptr);
|
||||||
object->put_own_property(*object, key, Attribute::Configurable | Attribute::Enumerable, accessor, Object::PutOwnPropertyMode::DefineProperty);
|
object->define_property(key, accessor, Attribute::Configurable | Attribute::Enumerable);
|
||||||
}
|
}
|
||||||
if (property.type() == ObjectProperty::Type::Getter)
|
if (property.type() == ObjectProperty::Type::Getter)
|
||||||
accessor->set_getter(&value.as_function());
|
accessor->set_getter(&value.as_function());
|
||||||
else
|
else
|
||||||
accessor->set_setter(&value.as_function());
|
accessor->set_setter(&value.as_function());
|
||||||
} else {
|
} else {
|
||||||
object->put(key, value);
|
object->define_property(key, value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return object;
|
return object;
|
||||||
|
@ -1354,7 +1354,7 @@ PropertyName MemberExpression::computed_property_name(Interpreter& interpreter)
|
||||||
{
|
{
|
||||||
if (!is_computed()) {
|
if (!is_computed()) {
|
||||||
ASSERT(m_property->is_identifier());
|
ASSERT(m_property->is_identifier());
|
||||||
return PropertyName(static_cast<const Identifier&>(*m_property).string());
|
return static_cast<const Identifier&>(*m_property).string();
|
||||||
}
|
}
|
||||||
auto index = m_property->execute(interpreter);
|
auto index = m_property->execute(interpreter);
|
||||||
if (interpreter.exception())
|
if (interpreter.exception())
|
||||||
|
@ -1363,12 +1363,12 @@ PropertyName MemberExpression::computed_property_name(Interpreter& interpreter)
|
||||||
ASSERT(!index.is_empty());
|
ASSERT(!index.is_empty());
|
||||||
|
|
||||||
if (index.is_integer() && index.as_i32() >= 0)
|
if (index.is_integer() && index.as_i32() >= 0)
|
||||||
return PropertyName(index.as_i32());
|
return index.as_i32();
|
||||||
|
|
||||||
auto index_string = index.to_string(interpreter);
|
auto index_string = index.to_string(interpreter);
|
||||||
if (interpreter.exception())
|
if (interpreter.exception())
|
||||||
return {};
|
return {};
|
||||||
return PropertyName(index_string);
|
return index_string;
|
||||||
}
|
}
|
||||||
|
|
||||||
String MemberExpression::to_string_approximation() const
|
String MemberExpression::to_string_approximation() const
|
||||||
|
@ -1537,7 +1537,7 @@ Value TaggedTemplateLiteral::execute(Interpreter& interpreter) const
|
||||||
return {};
|
return {};
|
||||||
raw_strings->elements().append(value);
|
raw_strings->elements().append(value);
|
||||||
}
|
}
|
||||||
strings->put("raw", raw_strings, 0);
|
strings->define_property("raw", raw_strings, 0);
|
||||||
|
|
||||||
return interpreter.call(tag_function, js_undefined(), move(arguments));
|
return interpreter.call(tag_function, js_undefined(), move(arguments));
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,7 +42,7 @@ Array* Array::create(GlobalObject& global_object)
|
||||||
Array::Array(Object& prototype)
|
Array::Array(Object& prototype)
|
||||||
: Object(&prototype)
|
: Object(&prototype)
|
||||||
{
|
{
|
||||||
put_native_property("length", length_getter, length_setter, Attribute::Writable);
|
define_native_property("length", length_getter, length_setter, Attribute::Writable);
|
||||||
}
|
}
|
||||||
|
|
||||||
Array::~Array()
|
Array::~Array()
|
||||||
|
|
|
@ -39,12 +39,12 @@ namespace JS {
|
||||||
ArrayConstructor::ArrayConstructor()
|
ArrayConstructor::ArrayConstructor()
|
||||||
: NativeFunction("Array", *interpreter().global_object().function_prototype())
|
: NativeFunction("Array", *interpreter().global_object().function_prototype())
|
||||||
{
|
{
|
||||||
put("prototype", interpreter().global_object().array_prototype(), 0);
|
define_property("prototype", interpreter().global_object().array_prototype(), 0);
|
||||||
put("length", Value(1), Attribute::Configurable);
|
define_property("length", Value(1), Attribute::Configurable);
|
||||||
|
|
||||||
u8 attr = Attribute::Writable | Attribute::Configurable;
|
u8 attr = Attribute::Writable | Attribute::Configurable;
|
||||||
put_native_function("isArray", is_array, 1, attr);
|
define_native_function("isArray", is_array, 1, attr);
|
||||||
put_native_function("of", of, 0, attr);
|
define_native_function("of", of, 0, attr);
|
||||||
}
|
}
|
||||||
|
|
||||||
ArrayConstructor::~ArrayConstructor()
|
ArrayConstructor::~ArrayConstructor()
|
||||||
|
|
|
@ -46,30 +46,30 @@ ArrayPrototype::ArrayPrototype()
|
||||||
{
|
{
|
||||||
u8 attr = Attribute::Writable | Attribute::Configurable;
|
u8 attr = Attribute::Writable | Attribute::Configurable;
|
||||||
|
|
||||||
put_native_function("filter", filter, 1, attr);
|
define_native_function("filter", filter, 1, attr);
|
||||||
put_native_function("forEach", for_each, 1, attr);
|
define_native_function("forEach", for_each, 1, attr);
|
||||||
put_native_function("map", map, 1, attr);
|
define_native_function("map", map, 1, attr);
|
||||||
put_native_function("pop", pop, 0, attr);
|
define_native_function("pop", pop, 0, attr);
|
||||||
put_native_function("push", push, 1, attr);
|
define_native_function("push", push, 1, attr);
|
||||||
put_native_function("shift", shift, 0, attr);
|
define_native_function("shift", shift, 0, attr);
|
||||||
put_native_function("toString", to_string, 0, attr);
|
define_native_function("toString", to_string, 0, attr);
|
||||||
put_native_function("unshift", unshift, 1, attr);
|
define_native_function("unshift", unshift, 1, attr);
|
||||||
put_native_function("join", join, 1, attr);
|
define_native_function("join", join, 1, attr);
|
||||||
put_native_function("concat", concat, 1, attr);
|
define_native_function("concat", concat, 1, attr);
|
||||||
put_native_function("slice", slice, 2, attr);
|
define_native_function("slice", slice, 2, attr);
|
||||||
put_native_function("indexOf", index_of, 1, attr);
|
define_native_function("indexOf", index_of, 1, attr);
|
||||||
put_native_function("reduce", reduce, 1, attr);
|
define_native_function("reduce", reduce, 1, attr);
|
||||||
put_native_function("reduceRight", reduce_right, 1, attr);
|
define_native_function("reduceRight", reduce_right, 1, attr);
|
||||||
put_native_function("reverse", reverse, 0, attr);
|
define_native_function("reverse", reverse, 0, attr);
|
||||||
put_native_function("lastIndexOf", last_index_of, 1, attr);
|
define_native_function("lastIndexOf", last_index_of, 1, attr);
|
||||||
put_native_function("includes", includes, 1, attr);
|
define_native_function("includes", includes, 1, attr);
|
||||||
put_native_function("find", find, 1, attr);
|
define_native_function("find", find, 1, attr);
|
||||||
put_native_function("findIndex", find_index, 1, attr);
|
define_native_function("findIndex", find_index, 1, attr);
|
||||||
put_native_function("some", some, 1, attr);
|
define_native_function("some", some, 1, attr);
|
||||||
put_native_function("every", every, 1, attr);
|
define_native_function("every", every, 1, attr);
|
||||||
put_native_function("splice", splice, 2, attr);
|
define_native_function("splice", splice, 2, attr);
|
||||||
put_native_function("fill", fill, 1, attr);
|
define_native_function("fill", fill, 1, attr);
|
||||||
put("length", Value(0), Attribute::Configurable);
|
define_property("length", Value(0), Attribute::Configurable);
|
||||||
}
|
}
|
||||||
|
|
||||||
ArrayPrototype::~ArrayPrototype()
|
ArrayPrototype::~ArrayPrototype()
|
||||||
|
@ -115,7 +115,7 @@ static void for_each_item(Interpreter& interpreter, const String& name, AK::Func
|
||||||
auto this_value = interpreter.argument(1);
|
auto this_value = interpreter.argument(1);
|
||||||
|
|
||||||
for (size_t i = 0; i < initial_length; ++i) {
|
for (size_t i = 0; i < initial_length; ++i) {
|
||||||
auto value = this_object->get_by_index(i);
|
auto value = this_object->get(i);
|
||||||
if (interpreter.exception())
|
if (interpreter.exception())
|
||||||
return;
|
return;
|
||||||
if (value.is_empty()) {
|
if (value.is_empty()) {
|
||||||
|
@ -193,7 +193,7 @@ Value ArrayPrototype::push(Interpreter& interpreter)
|
||||||
if (new_length > MAX_ARRAY_LIKE_INDEX)
|
if (new_length > MAX_ARRAY_LIKE_INDEX)
|
||||||
return interpreter.throw_exception<TypeError>("Maximum array size exceeded");
|
return interpreter.throw_exception<TypeError>("Maximum array size exceeded");
|
||||||
for (size_t i = 0; i < argument_count; ++i)
|
for (size_t i = 0; i < argument_count; ++i)
|
||||||
this_object->put_by_index(length + i, interpreter.argument(i));
|
this_object->put(length + i, interpreter.argument(i));
|
||||||
auto new_length_value = Value((i32)new_length);
|
auto new_length_value = Value((i32)new_length);
|
||||||
this_object->put("length", new_length_value);
|
this_object->put("length", new_length_value);
|
||||||
if (interpreter.exception())
|
if (interpreter.exception())
|
||||||
|
@ -228,10 +228,10 @@ Value ArrayPrototype::pop(Interpreter& interpreter)
|
||||||
return js_undefined();
|
return js_undefined();
|
||||||
}
|
}
|
||||||
auto index = length - 1;
|
auto index = length - 1;
|
||||||
auto element = this_object->get_by_index(index).value_or(js_undefined());
|
auto element = this_object->get(index).value_or(js_undefined());
|
||||||
if (interpreter.exception())
|
if (interpreter.exception())
|
||||||
return {};
|
return {};
|
||||||
this_object->delete_property(PropertyName(index));
|
this_object->delete_property(index);
|
||||||
this_object->put("length", Value((i32)index));
|
this_object->put("length", Value((i32)index));
|
||||||
if (interpreter.exception())
|
if (interpreter.exception())
|
||||||
return {};
|
return {};
|
||||||
|
@ -279,7 +279,7 @@ Value ArrayPrototype::join(Interpreter& interpreter)
|
||||||
for (size_t i = 0; i < length; ++i) {
|
for (size_t i = 0; i < length; ++i) {
|
||||||
if (i > 0)
|
if (i > 0)
|
||||||
builder.append(separator);
|
builder.append(separator);
|
||||||
auto value = this_object->get_by_index(i).value_or(js_undefined());
|
auto value = this_object->get(i).value_or(js_undefined());
|
||||||
if (interpreter.exception())
|
if (interpreter.exception())
|
||||||
return {};
|
return {};
|
||||||
if (value.is_undefined() || value.is_null())
|
if (value.is_undefined() || value.is_null())
|
||||||
|
@ -379,7 +379,7 @@ Value ArrayPrototype::index_of(Interpreter& interpreter)
|
||||||
}
|
}
|
||||||
auto search_element = interpreter.argument(0);
|
auto search_element = interpreter.argument(0);
|
||||||
for (i32 i = from_index; i < length; ++i) {
|
for (i32 i = from_index; i < length; ++i) {
|
||||||
auto element = this_object->get_by_index(i);
|
auto element = this_object->get(i);
|
||||||
if (interpreter.exception())
|
if (interpreter.exception())
|
||||||
return {};
|
return {};
|
||||||
if (strict_eq(interpreter, element, search_element))
|
if (strict_eq(interpreter, element, search_element))
|
||||||
|
@ -410,7 +410,7 @@ Value ArrayPrototype::reduce(Interpreter& interpreter)
|
||||||
} else {
|
} else {
|
||||||
bool start_found = false;
|
bool start_found = false;
|
||||||
while (!start_found && start < initial_length) {
|
while (!start_found && start < initial_length) {
|
||||||
auto value = this_object->get_by_index(start);
|
auto value = this_object->get(start);
|
||||||
if (interpreter.exception())
|
if (interpreter.exception())
|
||||||
return {};
|
return {};
|
||||||
start_found = !value.is_empty();
|
start_found = !value.is_empty();
|
||||||
|
@ -427,7 +427,7 @@ Value ArrayPrototype::reduce(Interpreter& interpreter)
|
||||||
auto this_value = js_undefined();
|
auto this_value = js_undefined();
|
||||||
|
|
||||||
for (size_t i = start; i < initial_length; ++i) {
|
for (size_t i = start; i < initial_length; ++i) {
|
||||||
auto value = this_object->get_by_index(i);
|
auto value = this_object->get(i);
|
||||||
if (interpreter.exception())
|
if (interpreter.exception())
|
||||||
return {};
|
return {};
|
||||||
if (value.is_empty())
|
if (value.is_empty())
|
||||||
|
@ -469,7 +469,7 @@ Value ArrayPrototype::reduce_right(Interpreter& interpreter)
|
||||||
} else {
|
} else {
|
||||||
bool start_found = false;
|
bool start_found = false;
|
||||||
while (!start_found && start >= 0) {
|
while (!start_found && start >= 0) {
|
||||||
auto value = this_object->get_by_index(start);
|
auto value = this_object->get(start);
|
||||||
if (interpreter.exception())
|
if (interpreter.exception())
|
||||||
return {};
|
return {};
|
||||||
start_found = !value.is_empty();
|
start_found = !value.is_empty();
|
||||||
|
@ -486,7 +486,7 @@ Value ArrayPrototype::reduce_right(Interpreter& interpreter)
|
||||||
auto this_value = js_undefined();
|
auto this_value = js_undefined();
|
||||||
|
|
||||||
for (int i = start; i >= 0; --i) {
|
for (int i = start; i >= 0; --i) {
|
||||||
auto value = this_object->get_by_index(i);
|
auto value = this_object->get(i);
|
||||||
if (interpreter.exception())
|
if (interpreter.exception())
|
||||||
return {};
|
return {};
|
||||||
if (value.is_empty())
|
if (value.is_empty())
|
||||||
|
@ -548,7 +548,7 @@ Value ArrayPrototype::last_index_of(Interpreter& interpreter)
|
||||||
}
|
}
|
||||||
auto search_element = interpreter.argument(0);
|
auto search_element = interpreter.argument(0);
|
||||||
for (i32 i = from_index; i >= 0; --i) {
|
for (i32 i = from_index; i >= 0; --i) {
|
||||||
auto element = this_object->get_by_index(i);
|
auto element = this_object->get(i);
|
||||||
if (interpreter.exception())
|
if (interpreter.exception())
|
||||||
return {};
|
return {};
|
||||||
if (strict_eq(interpreter, element, search_element))
|
if (strict_eq(interpreter, element, search_element))
|
||||||
|
@ -579,7 +579,7 @@ Value ArrayPrototype::includes(Interpreter& interpreter)
|
||||||
}
|
}
|
||||||
auto value_to_find = interpreter.argument(0);
|
auto value_to_find = interpreter.argument(0);
|
||||||
for (i32 i = from_index; i < length; ++i) {
|
for (i32 i = from_index; i < length; ++i) {
|
||||||
auto element = this_object->get_by_index(i).value_or(js_undefined());
|
auto element = this_object->get(i).value_or(js_undefined());
|
||||||
if (interpreter.exception())
|
if (interpreter.exception())
|
||||||
return {};
|
return {};
|
||||||
if (same_value_zero(interpreter, element, value_to_find))
|
if (same_value_zero(interpreter, element, value_to_find))
|
||||||
|
@ -687,7 +687,7 @@ Value ArrayPrototype::splice(Interpreter& interpreter)
|
||||||
auto removed_elements = Array::create(interpreter.global_object());
|
auto removed_elements = Array::create(interpreter.global_object());
|
||||||
|
|
||||||
for (size_t i = 0; i < actual_delete_count; ++i) {
|
for (size_t i = 0; i < actual_delete_count; ++i) {
|
||||||
auto value = this_object->get_by_index(actual_start + i);
|
auto value = this_object->get(actual_start + i);
|
||||||
if (interpreter.exception())
|
if (interpreter.exception())
|
||||||
return {};
|
return {};
|
||||||
|
|
||||||
|
@ -696,43 +696,43 @@ Value ArrayPrototype::splice(Interpreter& interpreter)
|
||||||
|
|
||||||
if (insert_count < actual_delete_count) {
|
if (insert_count < actual_delete_count) {
|
||||||
for (size_t i = actual_start; i < initial_length - actual_delete_count; ++i) {
|
for (size_t i = actual_start; i < initial_length - actual_delete_count; ++i) {
|
||||||
auto from = this_object->get_by_index(i + actual_delete_count);
|
auto from = this_object->get(i + actual_delete_count);
|
||||||
if (interpreter.exception())
|
if (interpreter.exception())
|
||||||
return {};
|
return {};
|
||||||
|
|
||||||
auto to = i + insert_count;
|
auto to = i + insert_count;
|
||||||
|
|
||||||
if (!from.is_empty()) {
|
if (!from.is_empty()) {
|
||||||
this_object->put_by_index(to, from);
|
this_object->put(to, from);
|
||||||
if (interpreter.exception())
|
if (interpreter.exception())
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
this_object->delete_property(PropertyName(to));
|
this_object->delete_property(to);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (size_t i = initial_length; i > new_length; --i)
|
for (size_t i = initial_length; i > new_length; --i)
|
||||||
this_object->delete_property(PropertyName(i - 1));
|
this_object->delete_property(i - 1);
|
||||||
} else if (insert_count > actual_delete_count) {
|
} else if (insert_count > actual_delete_count) {
|
||||||
for (size_t i = initial_length - actual_delete_count; i > actual_start; --i) {
|
for (size_t i = initial_length - actual_delete_count; i > actual_start; --i) {
|
||||||
auto from = this_object->get_by_index(i + actual_delete_count - 1);
|
auto from = this_object->get(i + actual_delete_count - 1);
|
||||||
if (interpreter.exception())
|
if (interpreter.exception())
|
||||||
return {};
|
return {};
|
||||||
|
|
||||||
auto to = i + insert_count - 1;
|
auto to = i + insert_count - 1;
|
||||||
|
|
||||||
if (!from.is_empty()) {
|
if (!from.is_empty()) {
|
||||||
this_object->put_by_index(to, from);
|
this_object->put(to, from);
|
||||||
if (interpreter.exception())
|
if (interpreter.exception())
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
this_object->delete_property(PropertyName(to));
|
this_object->delete_property(to);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (size_t i = 0; i < insert_count; ++i) {
|
for (size_t i = 0; i < insert_count; ++i) {
|
||||||
this_object->put_by_index(actual_start + i, interpreter.argument(i + 2));
|
this_object->put(actual_start + i, interpreter.argument(i + 2));
|
||||||
if (interpreter.exception())
|
if (interpreter.exception())
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
@ -782,7 +782,7 @@ Value ArrayPrototype::fill(Interpreter& interpreter)
|
||||||
to = min(relative_end, length);
|
to = min(relative_end, length);
|
||||||
|
|
||||||
for (size_t i = from; i < to; i++) {
|
for (size_t i = from; i < to; i++) {
|
||||||
this_object->put_by_index(i, interpreter.argument(0));
|
this_object->put(i, interpreter.argument(0));
|
||||||
if (interpreter.exception())
|
if (interpreter.exception())
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,8 +36,8 @@ namespace JS {
|
||||||
BooleanConstructor::BooleanConstructor()
|
BooleanConstructor::BooleanConstructor()
|
||||||
: NativeFunction("Boolean", *interpreter().global_object().function_prototype())
|
: NativeFunction("Boolean", *interpreter().global_object().function_prototype())
|
||||||
{
|
{
|
||||||
put("prototype", Value(interpreter().global_object().boolean_prototype()), 0);
|
define_property("prototype", Value(interpreter().global_object().boolean_prototype()), 0);
|
||||||
put("length", Value(1), Attribute::Configurable);
|
define_property("length", Value(1), Attribute::Configurable);
|
||||||
}
|
}
|
||||||
|
|
||||||
BooleanConstructor::~BooleanConstructor()
|
BooleanConstructor::~BooleanConstructor()
|
||||||
|
|
|
@ -35,8 +35,8 @@ namespace JS {
|
||||||
BooleanPrototype::BooleanPrototype()
|
BooleanPrototype::BooleanPrototype()
|
||||||
: BooleanObject(false, *interpreter().global_object().object_prototype())
|
: BooleanObject(false, *interpreter().global_object().object_prototype())
|
||||||
{
|
{
|
||||||
put_native_function("toString", to_string, 0, Attribute::Writable | Attribute::Configurable);
|
define_native_function("toString", to_string, 0, Attribute::Writable | Attribute::Configurable);
|
||||||
put_native_function("valueOf", value_of, 0, Attribute::Writable | Attribute::Configurable);
|
define_native_function("valueOf", value_of, 0, Attribute::Writable | Attribute::Configurable);
|
||||||
}
|
}
|
||||||
|
|
||||||
BooleanPrototype::~BooleanPrototype() { }
|
BooleanPrototype::~BooleanPrototype() { }
|
||||||
|
|
|
@ -36,7 +36,7 @@ BoundFunction::BoundFunction(Function& target_function, Value bound_this, Vector
|
||||||
, m_constructor_prototype(constructor_prototype)
|
, m_constructor_prototype(constructor_prototype)
|
||||||
, m_name(String::format("bound %s", target_function.name().characters()))
|
, m_name(String::format("bound %s", target_function.name().characters()))
|
||||||
{
|
{
|
||||||
put("length", Value(length), Attribute::Configurable);
|
define_property("length", Value(length), Attribute::Configurable);
|
||||||
}
|
}
|
||||||
|
|
||||||
BoundFunction::~BoundFunction()
|
BoundFunction::~BoundFunction()
|
||||||
|
|
|
@ -38,15 +38,15 @@ namespace JS {
|
||||||
ConsoleObject::ConsoleObject()
|
ConsoleObject::ConsoleObject()
|
||||||
: Object(interpreter().global_object().object_prototype())
|
: Object(interpreter().global_object().object_prototype())
|
||||||
{
|
{
|
||||||
put_native_function("log", log);
|
define_native_function("log", log);
|
||||||
put_native_function("debug", debug);
|
define_native_function("debug", debug);
|
||||||
put_native_function("info", info);
|
define_native_function("info", info);
|
||||||
put_native_function("warn", warn);
|
define_native_function("warn", warn);
|
||||||
put_native_function("error", error);
|
define_native_function("error", error);
|
||||||
put_native_function("trace", trace);
|
define_native_function("trace", trace);
|
||||||
put_native_function("count", count);
|
define_native_function("count", count);
|
||||||
put_native_function("countReset", count_reset);
|
define_native_function("countReset", count_reset);
|
||||||
put_native_function("clear", clear);
|
define_native_function("clear", clear);
|
||||||
}
|
}
|
||||||
|
|
||||||
ConsoleObject::~ConsoleObject()
|
ConsoleObject::~ConsoleObject()
|
||||||
|
|
|
@ -37,10 +37,10 @@ namespace JS {
|
||||||
DateConstructor::DateConstructor()
|
DateConstructor::DateConstructor()
|
||||||
: NativeFunction("Date", *interpreter().global_object().function_prototype())
|
: NativeFunction("Date", *interpreter().global_object().function_prototype())
|
||||||
{
|
{
|
||||||
put("prototype", interpreter().global_object().date_prototype(), 0);
|
define_property("prototype", interpreter().global_object().date_prototype(), 0);
|
||||||
put("length", Value(7), Attribute::Configurable);
|
define_property("length", Value(7), Attribute::Configurable);
|
||||||
|
|
||||||
put_native_function("now", now, 0, Attribute::Writable | Attribute::Configurable);
|
define_native_function("now", now, 0, Attribute::Writable | Attribute::Configurable);
|
||||||
}
|
}
|
||||||
|
|
||||||
DateConstructor::~DateConstructor()
|
DateConstructor::~DateConstructor()
|
||||||
|
|
|
@ -52,18 +52,18 @@ DatePrototype::DatePrototype()
|
||||||
: Object(interpreter().global_object().object_prototype())
|
: Object(interpreter().global_object().object_prototype())
|
||||||
{
|
{
|
||||||
u8 attr = Attribute::Writable | Attribute::Configurable;
|
u8 attr = Attribute::Writable | Attribute::Configurable;
|
||||||
put_native_function("getDate", get_date, 0, attr);
|
define_native_function("getDate", get_date, 0, attr);
|
||||||
put_native_function("getDay", get_day, 0, attr);
|
define_native_function("getDay", get_day, 0, attr);
|
||||||
put_native_function("getFullYear", get_full_year, 0, attr);
|
define_native_function("getFullYear", get_full_year, 0, attr);
|
||||||
put_native_function("getHours", get_hours, 0, attr);
|
define_native_function("getHours", get_hours, 0, attr);
|
||||||
put_native_function("getMilliseconds", get_milliseconds, 0, attr);
|
define_native_function("getMilliseconds", get_milliseconds, 0, attr);
|
||||||
put_native_function("getMinutes", get_minutes, 0, attr);
|
define_native_function("getMinutes", get_minutes, 0, attr);
|
||||||
put_native_function("getMonth", get_month, 0, attr);
|
define_native_function("getMonth", get_month, 0, attr);
|
||||||
put_native_function("getSeconds", get_seconds, 0, attr);
|
define_native_function("getSeconds", get_seconds, 0, attr);
|
||||||
put_native_function("getTime", get_time, 0, attr);
|
define_native_function("getTime", get_time, 0, attr);
|
||||||
put_native_function("toDateString", to_date_string, 0, attr);
|
define_native_function("toDateString", to_date_string, 0, attr);
|
||||||
put_native_function("toTimeString", to_time_string, 0, attr);
|
define_native_function("toTimeString", to_time_string, 0, attr);
|
||||||
put_native_function("toString", to_string, 0, attr);
|
define_native_function("toString", to_string, 0, attr);
|
||||||
}
|
}
|
||||||
|
|
||||||
DatePrototype::~DatePrototype()
|
DatePrototype::~DatePrototype()
|
||||||
|
|
|
@ -34,8 +34,8 @@ namespace JS {
|
||||||
ErrorConstructor::ErrorConstructor()
|
ErrorConstructor::ErrorConstructor()
|
||||||
: NativeFunction("Error", *interpreter().global_object().function_prototype())
|
: NativeFunction("Error", *interpreter().global_object().function_prototype())
|
||||||
{
|
{
|
||||||
put("prototype", interpreter().global_object().error_prototype(), 0);
|
define_property("prototype", interpreter().global_object().error_prototype(), 0);
|
||||||
put("length", Value(1), Attribute::Configurable);
|
define_property("length", Value(1), Attribute::Configurable);
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorConstructor::~ErrorConstructor()
|
ErrorConstructor::~ErrorConstructor()
|
||||||
|
@ -62,8 +62,8 @@ Value ErrorConstructor::construct(Interpreter& interpreter)
|
||||||
ConstructorName::ConstructorName() \
|
ConstructorName::ConstructorName() \
|
||||||
: NativeFunction(*interpreter().global_object().function_prototype()) \
|
: NativeFunction(*interpreter().global_object().function_prototype()) \
|
||||||
{ \
|
{ \
|
||||||
put("prototype", interpreter().global_object().snake_name##_prototype(), 0); \
|
define_property("prototype", interpreter().global_object().snake_name##_prototype(), 0); \
|
||||||
put("length", Value(1), Attribute::Configurable); \
|
define_property("length", Value(1), Attribute::Configurable); \
|
||||||
} \
|
} \
|
||||||
ConstructorName::~ConstructorName() { } \
|
ConstructorName::~ConstructorName() { } \
|
||||||
Value ConstructorName::call(Interpreter& interpreter) \
|
Value ConstructorName::call(Interpreter& interpreter) \
|
||||||
|
|
|
@ -39,9 +39,9 @@ ErrorPrototype::ErrorPrototype()
|
||||||
: Object(interpreter().global_object().object_prototype())
|
: Object(interpreter().global_object().object_prototype())
|
||||||
{
|
{
|
||||||
u8 attr = Attribute::Writable | Attribute::Configurable;
|
u8 attr = Attribute::Writable | Attribute::Configurable;
|
||||||
put_native_property("name", name_getter, name_setter, attr);
|
define_native_property("name", name_getter, name_setter, attr);
|
||||||
put_native_property("message", message_getter, nullptr, attr);
|
define_native_property("message", message_getter, nullptr, attr);
|
||||||
put_native_function("toString", to_string, 0, attr);
|
define_native_function("toString", to_string, 0, attr);
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorPrototype::~ErrorPrototype()
|
ErrorPrototype::~ErrorPrototype()
|
||||||
|
|
|
@ -38,8 +38,8 @@ namespace JS {
|
||||||
FunctionConstructor::FunctionConstructor()
|
FunctionConstructor::FunctionConstructor()
|
||||||
: NativeFunction("Function", *interpreter().global_object().function_prototype())
|
: NativeFunction("Function", *interpreter().global_object().function_prototype())
|
||||||
{
|
{
|
||||||
put("prototype", interpreter().global_object().function_prototype(), 0);
|
define_property("prototype", interpreter().global_object().function_prototype(), 0);
|
||||||
put("length", Value(1), Attribute::Configurable);
|
define_property("length", Value(1), Attribute::Configurable);
|
||||||
}
|
}
|
||||||
|
|
||||||
FunctionConstructor::~FunctionConstructor()
|
FunctionConstructor::~FunctionConstructor()
|
||||||
|
|
|
@ -46,12 +46,12 @@ FunctionPrototype::FunctionPrototype()
|
||||||
void FunctionPrototype::initialize()
|
void FunctionPrototype::initialize()
|
||||||
{
|
{
|
||||||
u8 attr = Attribute::Writable | Attribute::Configurable;
|
u8 attr = Attribute::Writable | Attribute::Configurable;
|
||||||
put_native_function("apply", apply, 2, attr);
|
define_native_function("apply", apply, 2, attr);
|
||||||
put_native_function("bind", bind, 1, attr);
|
define_native_function("bind", bind, 1, attr);
|
||||||
put_native_function("call", call, 1, attr);
|
define_native_function("call", call, 1, attr);
|
||||||
put_native_function("toString", to_string, 0, attr);
|
define_native_function("toString", to_string, 0, attr);
|
||||||
put("length", Value(0), Attribute::Configurable);
|
define_property("length", Value(0), Attribute::Configurable);
|
||||||
put("name", js_string(heap(), ""), Attribute::Configurable);
|
define_property("name", js_string(heap(), ""), Attribute::Configurable);
|
||||||
}
|
}
|
||||||
|
|
||||||
FunctionPrototype::~FunctionPrototype()
|
FunctionPrototype::~FunctionPrototype()
|
||||||
|
@ -80,7 +80,7 @@ Value FunctionPrototype::apply(Interpreter& interpreter)
|
||||||
return {};
|
return {};
|
||||||
MarkedValueList arguments(interpreter.heap());
|
MarkedValueList arguments(interpreter.heap());
|
||||||
for (size_t i = 0; i < length; ++i) {
|
for (size_t i = 0; i < length; ++i) {
|
||||||
auto element = arg_array.as_object().get(String::number(i));
|
auto element = arg_array.as_object().get(i);
|
||||||
if (interpreter.exception())
|
if (interpreter.exception())
|
||||||
return {};
|
return {};
|
||||||
arguments.append(element.value_or(js_undefined()));
|
arguments.append(element.value_or(js_undefined()));
|
||||||
|
|
|
@ -82,19 +82,19 @@ void GlobalObject::initialize()
|
||||||
#undef __JS_ENUMERATE
|
#undef __JS_ENUMERATE
|
||||||
|
|
||||||
u8 attr = Attribute::Writable | Attribute::Configurable;
|
u8 attr = Attribute::Writable | Attribute::Configurable;
|
||||||
put_native_function("gc", gc, 0, attr);
|
define_native_function("gc", gc, 0, attr);
|
||||||
put_native_function("isNaN", is_nan, 1, attr);
|
define_native_function("isNaN", is_nan, 1, attr);
|
||||||
put_native_function("isFinite", is_finite, 1, attr);
|
define_native_function("isFinite", is_finite, 1, attr);
|
||||||
put_native_function("parseFloat", parse_float, 1, attr);
|
define_native_function("parseFloat", parse_float, 1, attr);
|
||||||
|
|
||||||
put("NaN", js_nan(), 0);
|
define_property("NaN", js_nan(), 0);
|
||||||
put("Infinity", js_infinity(), 0);
|
define_property("Infinity", js_infinity(), 0);
|
||||||
put("undefined", js_undefined(), 0);
|
define_property("undefined", js_undefined(), 0);
|
||||||
|
|
||||||
put("globalThis", this, attr);
|
define_property("globalThis", this, attr);
|
||||||
put("console", heap().allocate<ConsoleObject>(), attr);
|
define_property("console", heap().allocate<ConsoleObject>(), attr);
|
||||||
put("Math", heap().allocate<MathObject>(), attr);
|
define_property("Math", heap().allocate<MathObject>(), attr);
|
||||||
put("Reflect", heap().allocate<ReflectObject>(), attr);
|
define_property("Reflect", heap().allocate<ReflectObject>(), attr);
|
||||||
|
|
||||||
add_constructor("Array", m_array_constructor, *m_array_prototype);
|
add_constructor("Array", m_array_constructor, *m_array_prototype);
|
||||||
add_constructor("Boolean", m_boolean_constructor, *m_boolean_prototype);
|
add_constructor("Boolean", m_boolean_constructor, *m_boolean_prototype);
|
||||||
|
|
|
@ -73,9 +73,9 @@ template<typename ConstructorType>
|
||||||
inline void GlobalObject::add_constructor(const FlyString& property_name, ConstructorType*& constructor, Object& prototype)
|
inline void GlobalObject::add_constructor(const FlyString& property_name, ConstructorType*& constructor, Object& prototype)
|
||||||
{
|
{
|
||||||
constructor = heap().allocate<ConstructorType>();
|
constructor = heap().allocate<ConstructorType>();
|
||||||
constructor->put("name", js_string(heap(), property_name), Attribute::Configurable);
|
constructor->define_property("name", js_string(heap(), property_name), Attribute::Configurable);
|
||||||
prototype.put("constructor", constructor, Attribute::Writable | Attribute::Configurable);
|
prototype.define_property("constructor", constructor, Attribute::Writable | Attribute::Configurable);
|
||||||
put(property_name, constructor, Attribute::Writable | Attribute::Configurable);
|
define_property(property_name, constructor, Attribute::Writable | Attribute::Configurable);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,32 +38,32 @@ MathObject::MathObject()
|
||||||
: Object(interpreter().global_object().object_prototype())
|
: Object(interpreter().global_object().object_prototype())
|
||||||
{
|
{
|
||||||
u8 attr = Attribute::Writable | Attribute::Configurable;
|
u8 attr = Attribute::Writable | Attribute::Configurable;
|
||||||
put_native_function("abs", abs, 1, attr);
|
define_native_function("abs", abs, 1, attr);
|
||||||
put_native_function("random", random, 0, attr);
|
define_native_function("random", random, 0, attr);
|
||||||
put_native_function("sqrt", sqrt, 1, attr);
|
define_native_function("sqrt", sqrt, 1, attr);
|
||||||
put_native_function("floor", floor, 1, attr);
|
define_native_function("floor", floor, 1, attr);
|
||||||
put_native_function("ceil", ceil, 1, attr);
|
define_native_function("ceil", ceil, 1, attr);
|
||||||
put_native_function("round", round, 1, attr);
|
define_native_function("round", round, 1, attr);
|
||||||
put_native_function("max", max, 2, attr);
|
define_native_function("max", max, 2, attr);
|
||||||
put_native_function("min", min, 2, attr);
|
define_native_function("min", min, 2, attr);
|
||||||
put_native_function("trunc", trunc, 1, attr);
|
define_native_function("trunc", trunc, 1, attr);
|
||||||
put_native_function("sin", sin, 1, attr);
|
define_native_function("sin", sin, 1, attr);
|
||||||
put_native_function("cos", cos, 1, attr);
|
define_native_function("cos", cos, 1, attr);
|
||||||
put_native_function("tan", tan, 1, attr);
|
define_native_function("tan", tan, 1, attr);
|
||||||
put_native_function("pow", pow, 2, attr);
|
define_native_function("pow", pow, 2, attr);
|
||||||
put_native_function("exp", exp, 1, attr);
|
define_native_function("exp", exp, 1, attr);
|
||||||
put_native_function("expm1", expm1, 1, attr);
|
define_native_function("expm1", expm1, 1, attr);
|
||||||
put_native_function("sign", sign, 1, attr);
|
define_native_function("sign", sign, 1, attr);
|
||||||
put_native_function("clz32", clz32, 1, attr);
|
define_native_function("clz32", clz32, 1, attr);
|
||||||
|
|
||||||
put("E", Value(M_E), 0);
|
define_property("E", Value(M_E), 0);
|
||||||
put("LN2", Value(M_LN2), 0);
|
define_property("LN2", Value(M_LN2), 0);
|
||||||
put("LN10", Value(M_LN10), 0);
|
define_property("LN10", Value(M_LN10), 0);
|
||||||
put("LOG2E", Value(log2(M_E)), 0);
|
define_property("LOG2E", Value(log2(M_E)), 0);
|
||||||
put("LOG10E", Value(log10(M_E)), 0);
|
define_property("LOG10E", Value(log10(M_E)), 0);
|
||||||
put("PI", Value(M_PI), 0);
|
define_property("PI", Value(M_PI), 0);
|
||||||
put("SQRT1_2", Value(M_SQRT1_2), 0);
|
define_property("SQRT1_2", Value(M_SQRT1_2), 0);
|
||||||
put("SQRT2", Value(M_SQRT2), 0);
|
define_property("SQRT2", Value(M_SQRT2), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
MathObject::~MathObject()
|
MathObject::~MathObject()
|
||||||
|
|
|
@ -41,19 +41,19 @@ NumberConstructor::NumberConstructor()
|
||||||
: NativeFunction("Number", *interpreter().global_object().function_prototype())
|
: NativeFunction("Number", *interpreter().global_object().function_prototype())
|
||||||
{
|
{
|
||||||
u8 attr = Attribute::Writable | Attribute::Configurable;
|
u8 attr = Attribute::Writable | Attribute::Configurable;
|
||||||
put_native_function("isFinite", is_finite, 1, attr);
|
define_native_function("isFinite", is_finite, 1, attr);
|
||||||
put_native_function("isInteger", is_integer, 1, attr);
|
define_native_function("isInteger", is_integer, 1, attr);
|
||||||
put_native_function("isNaN", is_nan, 1, attr);
|
define_native_function("isNaN", is_nan, 1, attr);
|
||||||
put_native_function("isSafeInteger", is_safe_integer, 1, attr);
|
define_native_function("isSafeInteger", is_safe_integer, 1, attr);
|
||||||
put("parseFloat", interpreter().global_object().get("parseFloat"));
|
define_property("parseFloat", interpreter().global_object().get("parseFloat"));
|
||||||
put("prototype", interpreter().global_object().number_prototype(), 0);
|
define_property("prototype", interpreter().global_object().number_prototype(), 0);
|
||||||
put("length", Value(1), Attribute::Configurable);
|
define_property("length", Value(1), Attribute::Configurable);
|
||||||
put("EPSILON", Value(EPSILON), 0);
|
define_property("EPSILON", Value(EPSILON), 0);
|
||||||
put("MAX_SAFE_INTEGER", Value(MAX_SAFE_INTEGER), 0);
|
define_property("MAX_SAFE_INTEGER", Value(MAX_SAFE_INTEGER), 0);
|
||||||
put("MIN_SAFE_INTEGER", Value(MIN_SAFE_INTEGER), 0);
|
define_property("MIN_SAFE_INTEGER", Value(MIN_SAFE_INTEGER), 0);
|
||||||
put("NEGATIVE_INFINITY", js_negative_infinity(), 0);
|
define_property("NEGATIVE_INFINITY", js_negative_infinity(), 0);
|
||||||
put("POSITIVE_INFINITY", js_infinity(), 0);
|
define_property("POSITIVE_INFINITY", js_infinity(), 0);
|
||||||
put("NaN", js_nan(), 0);
|
define_property("NaN", js_nan(), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
NumberConstructor::~NumberConstructor()
|
NumberConstructor::~NumberConstructor()
|
||||||
|
|
|
@ -89,13 +89,21 @@ bool Object::has_prototype(const Object* prototype) const
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Value Object::get_own_property(const Object& this_object, const FlyString& property_name) const
|
Value Object::get_own_property(const Object& this_object, PropertyName property_name) const
|
||||||
{
|
{
|
||||||
auto metadata = shape().lookup(property_name);
|
Value value_here;
|
||||||
if (!metadata.has_value())
|
|
||||||
return {};
|
if (property_name.is_number()) {
|
||||||
|
if (static_cast<size_t>(property_name.as_number()) >= m_elements.size())
|
||||||
|
return {};
|
||||||
|
value_here = m_elements[property_name.as_number()];
|
||||||
|
} else {
|
||||||
|
auto metadata = shape().lookup(property_name.as_string());
|
||||||
|
if (!metadata.has_value())
|
||||||
|
return {};
|
||||||
|
value_here = m_storage[metadata.value().offset];
|
||||||
|
}
|
||||||
|
|
||||||
auto value_here = m_storage[metadata.value().offset];
|
|
||||||
ASSERT(!value_here.is_empty());
|
ASSERT(!value_here.is_empty());
|
||||||
if (value_here.is_accessor()) {
|
if (value_here.is_accessor()) {
|
||||||
return value_here.as_accessor().call_getter(Value(const_cast<Object*>(this)));
|
return value_here.as_accessor().call_getter(Value(const_cast<Object*>(this)));
|
||||||
|
@ -122,14 +130,14 @@ Value Object::get_own_properties(const Object& this_object, GetOwnPropertyMode k
|
||||||
|
|
||||||
for (size_t i = 0; i < str.length(); ++i) {
|
for (size_t i = 0; i < str.length(); ++i) {
|
||||||
if (kind == GetOwnPropertyMode::Key) {
|
if (kind == GetOwnPropertyMode::Key) {
|
||||||
properties_array->put_by_index(i, js_string(interpreter(), String::number(i)));
|
properties_array->define_property(i, js_string(interpreter(), String::number(i)));
|
||||||
} else if (kind == GetOwnPropertyMode::Value) {
|
} else if (kind == GetOwnPropertyMode::Value) {
|
||||||
properties_array->put_by_index(i, js_string(interpreter(), String::format("%c", str[i])));
|
properties_array->define_property(i, js_string(interpreter(), String::format("%c", str[i])));
|
||||||
} else {
|
} else {
|
||||||
auto* entry_array = Array::create(interpreter().global_object());
|
auto* entry_array = Array::create(interpreter().global_object());
|
||||||
entry_array->put_by_index(0, js_string(interpreter(), String::number(i)));
|
entry_array->define_property(0, js_string(interpreter(), String::number(i)));
|
||||||
entry_array->put_by_index(1, js_string(interpreter(), String::format("%c", str[i])));
|
entry_array->define_property(1, js_string(interpreter(), String::format("%c", str[i])));
|
||||||
properties_array->put_by_index(i, entry_array);
|
properties_array->define_property(i, entry_array);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -175,24 +183,36 @@ Value Object::get_own_properties(const Object& this_object, GetOwnPropertyMode k
|
||||||
return properties_array;
|
return properties_array;
|
||||||
}
|
}
|
||||||
|
|
||||||
Value Object::get_own_property_descriptor(const FlyString& property_name) const
|
Value Object::get_own_property_descriptor(PropertyName property_name) const
|
||||||
{
|
{
|
||||||
auto metadata = shape().lookup(property_name);
|
Value value;
|
||||||
if (!metadata.has_value())
|
u8 attributes;
|
||||||
return js_undefined();
|
|
||||||
auto value = get(property_name);
|
if (property_name.is_number()) {
|
||||||
if (interpreter().exception())
|
if (static_cast<size_t>(property_name.as_number()) >= m_elements.size())
|
||||||
return {};
|
return {};
|
||||||
|
value = m_elements[property_name.as_number()];
|
||||||
|
attributes = default_attributes;
|
||||||
|
} else {
|
||||||
|
auto metadata = shape().lookup(property_name.as_string());
|
||||||
|
if (!metadata.has_value())
|
||||||
|
return js_undefined();
|
||||||
|
value = get(property_name);
|
||||||
|
if (interpreter().exception())
|
||||||
|
return {};
|
||||||
|
attributes = metadata.value().attributes;
|
||||||
|
}
|
||||||
|
|
||||||
auto* descriptor = Object::create_empty(interpreter(), interpreter().global_object());
|
auto* descriptor = Object::create_empty(interpreter(), interpreter().global_object());
|
||||||
descriptor->put("enumerable", Value((metadata.value().attributes & Attribute::Enumerable) != 0));
|
descriptor->define_property("enumerable", Value((attributes & Attribute::Enumerable) != 0));
|
||||||
descriptor->put("configurable", Value((metadata.value().attributes & Attribute::Configurable) != 0));
|
descriptor->define_property("configurable", Value((attributes & Attribute::Configurable) != 0));
|
||||||
if (value.is_accessor()) {
|
if (value.is_accessor()) {
|
||||||
auto& pair = value.as_accessor();
|
auto& pair = value.as_accessor();
|
||||||
descriptor->put("get", pair.getter());
|
descriptor->define_property("get", pair.getter());
|
||||||
descriptor->put("set", pair.setter());
|
descriptor->define_property("set", pair.setter());
|
||||||
} else {
|
} else {
|
||||||
descriptor->put("value", value.value_or(js_undefined()));
|
descriptor->define_property("value", value.value_or(js_undefined()));
|
||||||
descriptor->put("writable", Value((metadata.value().attributes & Attribute::Writable) != 0));
|
descriptor->define_property("writable", Value((attributes & Attribute::Writable) != 0));
|
||||||
}
|
}
|
||||||
return descriptor;
|
return descriptor;
|
||||||
}
|
}
|
||||||
|
@ -249,7 +269,7 @@ bool Object::define_property(const FlyString& property_name, const Object& descr
|
||||||
<< "getter=" << getter.to_string_without_side_effects() << ", "
|
<< "getter=" << getter.to_string_without_side_effects() << ", "
|
||||||
<< "setter=" << setter.to_string_without_side_effects() << "}";
|
<< "setter=" << setter.to_string_without_side_effects() << "}";
|
||||||
|
|
||||||
return put_own_property(*this, property_name, attributes, Accessor::create(interpreter(), getter_function, setter_function), PutOwnPropertyMode::DefineProperty, throw_exceptions);
|
return define_property(property_name, Accessor::create(interpreter(), getter_function, setter_function), attributes, throw_exceptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto value = descriptor.get("value");
|
auto value = descriptor.get("value");
|
||||||
|
@ -263,10 +283,21 @@ bool Object::define_property(const FlyString& property_name, const Object& descr
|
||||||
dbg() << "Defining new property " << property_name << " with data descriptor { attributes=" << attributes
|
dbg() << "Defining new property " << property_name << " with data descriptor { attributes=" << attributes
|
||||||
<< ", value=" << (value.is_empty() ? "<empty>" : value.to_string_without_side_effects()) << " }";
|
<< ", value=" << (value.is_empty() ? "<empty>" : value.to_string_without_side_effects()) << " }";
|
||||||
|
|
||||||
return put_own_property(*this, property_name, attributes, value, PutOwnPropertyMode::DefineProperty, throw_exceptions);
|
return define_property(property_name, value, attributes, throw_exceptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Object::put_own_property(Object& this_object, const FlyString& property_name, u8 attributes, Value value, PutOwnPropertyMode mode, bool throw_exceptions)
|
bool Object::define_property(PropertyName property_name, Value value, u8 attributes, bool throw_exceptions)
|
||||||
|
{
|
||||||
|
if (property_name.is_number())
|
||||||
|
return put_own_property_by_index(*this, property_name.as_number(), value, attributes, PutOwnPropertyMode::DefineProperty, throw_exceptions);
|
||||||
|
bool ok;
|
||||||
|
i32 property_index = property_name.as_string().to_int(ok);
|
||||||
|
if (ok && property_index >= 0)
|
||||||
|
return put_own_property_by_index(*this, property_index, value, attributes, PutOwnPropertyMode::DefineProperty, throw_exceptions);
|
||||||
|
return put_own_property(*this, property_name.as_string(), value, attributes, PutOwnPropertyMode::DefineProperty, throw_exceptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Object::put_own_property(Object& this_object, const FlyString& property_name, Value value, u8 attributes, PutOwnPropertyMode mode, bool throw_exceptions)
|
||||||
{
|
{
|
||||||
ASSERT(!(mode == PutOwnPropertyMode::Put && value.is_accessor()));
|
ASSERT(!(mode == PutOwnPropertyMode::Put && value.is_accessor()));
|
||||||
|
|
||||||
|
@ -338,6 +369,53 @@ bool Object::put_own_property(Object& this_object, const FlyString& property_nam
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Object::put_own_property_by_index(Object& this_object, u32 property_index, Value value, u8 attributes, PutOwnPropertyMode mode, bool throw_exceptions)
|
||||||
|
{
|
||||||
|
ASSERT(!(mode == PutOwnPropertyMode::Put && value.is_accessor()));
|
||||||
|
|
||||||
|
if (value.is_accessor()) {
|
||||||
|
auto& accessor = value.as_accessor();
|
||||||
|
if (accessor.getter())
|
||||||
|
attributes |= Attribute::HasGet;
|
||||||
|
if (accessor.setter())
|
||||||
|
attributes |= Attribute::HasSet;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto new_property = property_index >= m_elements.size();
|
||||||
|
auto existing_property = new_property ? Value() : m_elements[property_index];
|
||||||
|
auto existing_attributes = default_attributes;
|
||||||
|
|
||||||
|
if (!new_property && mode == PutOwnPropertyMode::DefineProperty && !(existing_attributes & Attribute::Configurable) && attributes != existing_attributes) {
|
||||||
|
dbg() << "Disallow reconfig of non-configurable property";
|
||||||
|
if (throw_exceptions)
|
||||||
|
interpreter().throw_exception<TypeError>(String::format("Cannot change attributes of non-configurable property %d", property_index));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto value_here = existing_property;
|
||||||
|
if (!new_property && mode == PutOwnPropertyMode::Put && !value_here.is_accessor() && !(existing_attributes & Attribute::Writable)) {
|
||||||
|
dbg() << "Disallow write to non-writable property";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value.is_empty())
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (value_here.is_object() && value_here.as_object().is_native_property()) {
|
||||||
|
auto& native_property = static_cast<NativeProperty&>(value_here.as_object());
|
||||||
|
auto& interpreter = const_cast<Object*>(this)->interpreter();
|
||||||
|
auto& call_frame = interpreter.push_call_frame();
|
||||||
|
call_frame.this_value = &this_object;
|
||||||
|
native_property.set(interpreter, value);
|
||||||
|
interpreter.pop_call_frame();
|
||||||
|
} else {
|
||||||
|
if (new_property)
|
||||||
|
m_elements.resize(property_index + 1);
|
||||||
|
m_elements[property_index] = value;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
Value Object::delete_property(PropertyName property_name)
|
Value Object::delete_property(PropertyName property_name)
|
||||||
{
|
{
|
||||||
ASSERT(property_name.is_valid());
|
ASSERT(property_name.is_valid());
|
||||||
|
@ -371,16 +449,13 @@ void Object::ensure_shape_is_unique()
|
||||||
m_shape = m_shape->create_unique_clone();
|
m_shape = m_shape->create_unique_clone();
|
||||||
}
|
}
|
||||||
|
|
||||||
Value Object::get_by_index(i32 property_index) const
|
Value Object::get_by_index(u32 property_index) const
|
||||||
{
|
{
|
||||||
if (property_index < 0)
|
|
||||||
return get(String::number(property_index));
|
|
||||||
|
|
||||||
const Object* object = this;
|
const Object* object = this;
|
||||||
while (object) {
|
while (object) {
|
||||||
if (is_string_object()) {
|
if (is_string_object()) {
|
||||||
auto& string = static_cast<const StringObject*>(this)->primitive_string().string();
|
auto& string = static_cast<const StringObject*>(this)->primitive_string().string();
|
||||||
if (property_index < (i32)string.length())
|
if (property_index < string.length())
|
||||||
return js_string(heap(), string.substring(property_index, 1));
|
return js_string(heap(), string.substring(property_index, 1));
|
||||||
return js_undefined();
|
return js_undefined();
|
||||||
}
|
}
|
||||||
|
@ -395,10 +470,14 @@ Value Object::get_by_index(i32 property_index) const
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
Value Object::get(const FlyString& property_name) const
|
Value Object::get(PropertyName property_name) const
|
||||||
{
|
{
|
||||||
|
if (property_name.is_number())
|
||||||
|
return get_by_index(property_name.as_number());
|
||||||
|
|
||||||
|
auto property_string = property_name.to_string();
|
||||||
bool ok;
|
bool ok;
|
||||||
i32 property_index = property_name.to_int(ok);
|
i32 property_index = property_string.to_int(ok);
|
||||||
if (ok && property_index >= 0)
|
if (ok && property_index >= 0)
|
||||||
return get_by_index(property_index);
|
return get_by_index(property_index);
|
||||||
|
|
||||||
|
@ -412,18 +491,9 @@ Value Object::get(const FlyString& property_name) const
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
Value Object::get(PropertyName property_name) const
|
bool Object::put_by_index(u32 property_index, Value value)
|
||||||
{
|
|
||||||
if (property_name.is_number())
|
|
||||||
return get_by_index(property_name.as_number());
|
|
||||||
return get(property_name.as_string());
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Object::put_by_index(i32 property_index, Value value, u8 attributes)
|
|
||||||
{
|
{
|
||||||
ASSERT(!value.is_empty());
|
ASSERT(!value.is_empty());
|
||||||
if (property_index < 0)
|
|
||||||
return put(String::number(property_index), value, attributes);
|
|
||||||
// FIXME: Implement some kind of sparse storage for arrays with huge indices.
|
// FIXME: Implement some kind of sparse storage for arrays with huge indices.
|
||||||
// Also: Take attributes into account here
|
// Also: Take attributes into account here
|
||||||
if (static_cast<size_t>(property_index) >= m_elements.size())
|
if (static_cast<size_t>(property_index) >= m_elements.size())
|
||||||
|
@ -432,19 +502,24 @@ bool Object::put_by_index(i32 property_index, Value value, u8 attributes)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Object::put(const FlyString& property_name, Value value, u8 attributes)
|
bool Object::put(PropertyName property_name, Value value)
|
||||||
{
|
{
|
||||||
|
if (property_name.is_number())
|
||||||
|
return put_by_index(property_name.as_number(), value);
|
||||||
|
|
||||||
ASSERT(!value.is_empty());
|
ASSERT(!value.is_empty());
|
||||||
|
|
||||||
|
auto property_string = property_name.to_string();
|
||||||
bool ok;
|
bool ok;
|
||||||
i32 property_index = property_name.to_int(ok);
|
i32 property_index = property_string.to_int(ok);
|
||||||
if (ok && property_index >= 0)
|
if (ok && property_index >= 0)
|
||||||
return put_by_index(property_index, value, attributes);
|
return put_by_index(property_index, value);
|
||||||
|
|
||||||
// If there's a setter in the prototype chain, we go to the setter.
|
// If there's a setter in the prototype chain, we go to the setter.
|
||||||
// Otherwise, it goes in the own property storage.
|
// Otherwise, it goes in the own property storage.
|
||||||
Object* object = this;
|
Object* object = this;
|
||||||
while (object) {
|
while (object) {
|
||||||
auto metadata = object->shape().lookup(property_name);
|
auto metadata = object->shape().lookup(property_string);
|
||||||
if (metadata.has_value()) {
|
if (metadata.has_value()) {
|
||||||
auto value_here = object->m_storage[metadata.value().offset];
|
auto value_here = object->m_storage[metadata.value().offset];
|
||||||
if (value_here.is_accessor()) {
|
if (value_here.is_accessor()) {
|
||||||
|
@ -463,27 +538,20 @@ bool Object::put(const FlyString& property_name, Value value, u8 attributes)
|
||||||
}
|
}
|
||||||
object = object->prototype();
|
object = object->prototype();
|
||||||
}
|
}
|
||||||
return put_own_property(*this, property_name, attributes, value, PutOwnPropertyMode::Put);
|
return put_own_property(*this, property_string, value, default_attributes, PutOwnPropertyMode::Put);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Object::put(PropertyName property_name, Value value, u8 attributes)
|
bool Object::define_native_function(const FlyString& property_name, AK::Function<Value(Interpreter&)> native_function, i32 length, u8 attribute)
|
||||||
{
|
|
||||||
if (property_name.is_number())
|
|
||||||
return put_by_index(property_name.as_number(), value, attributes);
|
|
||||||
return put(property_name.as_string(), value, attributes);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Object::put_native_function(const FlyString& property_name, AK::Function<Value(Interpreter&)> native_function, i32 length, u8 attributes)
|
|
||||||
{
|
{
|
||||||
auto* function = NativeFunction::create(interpreter(), interpreter().global_object(), property_name, move(native_function));
|
auto* function = NativeFunction::create(interpreter(), interpreter().global_object(), property_name, move(native_function));
|
||||||
function->put("length", Value(length), Attribute::Configurable);
|
function->define_property("length", Value(length), Attribute::Configurable);
|
||||||
function->put("name", js_string(heap(), property_name), Attribute::Configurable);
|
function->define_property("name", js_string(heap(), property_name), Attribute::Configurable);
|
||||||
return put(property_name, function, attributes);
|
return define_property(property_name, function, attribute);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Object::put_native_property(const FlyString& property_name, AK::Function<Value(Interpreter&)> getter, AK::Function<void(Interpreter&, Value)> setter, u8 attributes)
|
bool Object::define_native_property(const FlyString& property_name, AK::Function<Value(Interpreter&)> getter, AK::Function<void(Interpreter&, Value)> setter, u8 attribute)
|
||||||
{
|
{
|
||||||
return put(property_name, heap().allocate<NativeProperty>(move(getter), move(setter)), attributes);
|
return define_property(property_name, heap().allocate<NativeProperty>(move(getter), move(setter)), attribute);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Object::visit_children(Cell::Visitor& visitor)
|
void Object::visit_children(Cell::Visitor& visitor)
|
||||||
|
@ -498,7 +566,7 @@ void Object::visit_children(Cell::Visitor& visitor)
|
||||||
visitor.visit(value);
|
visitor.visit(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Object::has_property(const FlyString& property_name) const
|
bool Object::has_property(PropertyName property_name) const
|
||||||
{
|
{
|
||||||
const Object* object = this;
|
const Object* object = this;
|
||||||
while (object) {
|
while (object) {
|
||||||
|
@ -509,18 +577,25 @@ bool Object::has_property(const FlyString& property_name) const
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Object::has_own_property(const FlyString& property_name) const
|
bool Object::has_own_property(PropertyName property_name) const
|
||||||
{
|
{
|
||||||
bool ok;
|
auto has_indexed_property = [&](u32 index) -> bool {
|
||||||
i32 property_index = property_name.to_int(ok);
|
|
||||||
if (ok && property_index >= 0) {
|
|
||||||
if (is_string_object())
|
if (is_string_object())
|
||||||
return property_index < (i32) static_cast<const StringObject*>(this)->primitive_string().string().length();
|
return index < static_cast<const StringObject*>(this)->primitive_string().string().length();
|
||||||
if (static_cast<size_t>(property_index) >= m_elements.size())
|
if (static_cast<size_t>(index) >= m_elements.size())
|
||||||
return false;
|
return false;
|
||||||
return !m_elements[property_index].is_empty();
|
return !m_elements[index].is_empty();
|
||||||
}
|
};
|
||||||
return shape().lookup(property_name).has_value();
|
|
||||||
|
if (property_name.is_number())
|
||||||
|
return has_indexed_property(property_name.as_number());
|
||||||
|
|
||||||
|
bool ok;
|
||||||
|
i32 property_index = property_name.as_string().to_int(ok);
|
||||||
|
if (ok && property_index >= 0)
|
||||||
|
return has_indexed_property(property_index);
|
||||||
|
|
||||||
|
return shape().lookup(property_name.as_string()).has_value();
|
||||||
}
|
}
|
||||||
|
|
||||||
Value Object::to_primitive(PreferredType preferred_type) const
|
Value Object::to_primitive(PreferredType preferred_type) const
|
||||||
|
|
|
@ -60,25 +60,24 @@ public:
|
||||||
Shape& shape() { return *m_shape; }
|
Shape& shape() { return *m_shape; }
|
||||||
const Shape& shape() const { return *m_shape; }
|
const Shape& shape() const { return *m_shape; }
|
||||||
|
|
||||||
Value delete_property(PropertyName);
|
|
||||||
|
|
||||||
virtual Value get_by_index(i32 property_index) const;
|
|
||||||
Value get(const FlyString& property_name) const;
|
|
||||||
Value get(PropertyName) const;
|
Value get(PropertyName) const;
|
||||||
|
|
||||||
virtual bool put_by_index(i32 property_index, Value, u8 attributes = default_attributes);
|
bool has_property(PropertyName) const;
|
||||||
bool put(const FlyString& property_name, Value, u8 attributes = default_attributes);
|
bool has_own_property(PropertyName) const;
|
||||||
bool put(PropertyName, Value, u8 attributes = default_attributes);
|
|
||||||
|
|
||||||
Value get_own_property(const Object& this_object, const FlyString& property_name) const;
|
bool put(PropertyName, Value);
|
||||||
Value get_own_properties(const Object& this_object, GetOwnPropertyMode, u8 attributes = Attribute::Configurable | Attribute::Enumerable | Attribute::Writable) const;
|
|
||||||
Value get_own_property_descriptor(const FlyString& property_name) const;
|
Value get_own_property(const Object& this_object, PropertyName) const;
|
||||||
|
Value get_own_properties(const Object& this_object, GetOwnPropertyMode, u8 attributes = default_attributes) const;
|
||||||
|
Value get_own_property_descriptor(PropertyName) const;
|
||||||
|
|
||||||
bool define_property(const FlyString& property_name, const Object& descriptor, bool throw_exceptions = true);
|
bool define_property(const FlyString& property_name, const Object& descriptor, bool throw_exceptions = true);
|
||||||
bool put_own_property(Object& this_object, const FlyString& property_name, u8 attributes, Value, PutOwnPropertyMode, bool throw_exceptions = true);
|
bool define_property(PropertyName, Value value, u8 attributes = default_attributes, bool throw_exceptions = true);
|
||||||
|
|
||||||
bool put_native_function(const FlyString& property_name, AK::Function<Value(Interpreter&)>, i32 length = 0, u8 attribute = default_attributes);
|
bool define_native_function(const FlyString& property_name, AK::Function<Value(Interpreter&)>, i32 length = 0, u8 attribute = default_attributes);
|
||||||
bool put_native_property(const FlyString& property_name, AK::Function<Value(Interpreter&)> getter, AK::Function<void(Interpreter&, Value)> setter, u8 attribute = default_attributes);
|
bool define_native_property(const FlyString& property_name, AK::Function<Value(Interpreter&)> getter, AK::Function<void(Interpreter&, Value)> setter, u8 attribute = default_attributes);
|
||||||
|
|
||||||
|
Value delete_property(PropertyName);
|
||||||
|
|
||||||
virtual bool is_array() const { return false; }
|
virtual bool is_array() const { return false; }
|
||||||
virtual bool is_boolean() const { return false; }
|
virtual bool is_boolean() const { return false; }
|
||||||
|
@ -99,9 +98,6 @@ public:
|
||||||
void set_prototype(Object*);
|
void set_prototype(Object*);
|
||||||
bool has_prototype(const Object* prototype) const;
|
bool has_prototype(const Object* prototype) const;
|
||||||
|
|
||||||
bool has_property(const FlyString& property_name) const;
|
|
||||||
bool has_own_property(const FlyString& property_name) const;
|
|
||||||
|
|
||||||
enum class PreferredType {
|
enum class PreferredType {
|
||||||
Default,
|
Default,
|
||||||
String,
|
String,
|
||||||
|
@ -118,6 +114,11 @@ public:
|
||||||
Vector<Value>& elements() { return m_elements; }
|
Vector<Value>& elements() { return m_elements; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
virtual Value get_by_index(u32 property_index) const;
|
||||||
|
virtual bool put_by_index(u32 property_index, Value);
|
||||||
|
bool put_own_property(Object& this_object, const FlyString& property_name, Value, u8 attributes, PutOwnPropertyMode = PutOwnPropertyMode::Put, bool throw_exceptions = true);
|
||||||
|
bool put_own_property_by_index(Object& this_object, u32 property_index, Value, u8 attributes, PutOwnPropertyMode = PutOwnPropertyMode::Put, bool throw_exceptions = true);
|
||||||
|
|
||||||
void set_shape(Shape&);
|
void set_shape(Shape&);
|
||||||
void ensure_shape_is_unique();
|
void ensure_shape_is_unique();
|
||||||
|
|
||||||
|
|
|
@ -38,19 +38,19 @@ namespace JS {
|
||||||
ObjectConstructor::ObjectConstructor()
|
ObjectConstructor::ObjectConstructor()
|
||||||
: NativeFunction("Object", *interpreter().global_object().function_prototype())
|
: NativeFunction("Object", *interpreter().global_object().function_prototype())
|
||||||
{
|
{
|
||||||
put("prototype", interpreter().global_object().object_prototype(), 0);
|
define_property("prototype", interpreter().global_object().object_prototype(), 0);
|
||||||
put("length", Value(1), Attribute::Configurable);
|
define_property("length", Value(1), Attribute::Configurable);
|
||||||
|
|
||||||
u8 attr = Attribute::Writable | Attribute::Configurable;
|
u8 attr = Attribute::Writable | Attribute::Configurable;
|
||||||
put_native_function("defineProperty", define_property, 3, attr);
|
define_native_function("defineProperty", define_property_, 3, attr);
|
||||||
put_native_function("is", is, 2, attr);
|
define_native_function("is", is, 2, attr);
|
||||||
put_native_function("getOwnPropertyDescriptor", get_own_property_descriptor, 2, attr);
|
define_native_function("getOwnPropertyDescriptor", get_own_property_descriptor, 2, attr);
|
||||||
put_native_function("getOwnPropertyNames", get_own_property_names, 1, attr);
|
define_native_function("getOwnPropertyNames", get_own_property_names, 1, attr);
|
||||||
put_native_function("getPrototypeOf", get_prototype_of, 1, attr);
|
define_native_function("getPrototypeOf", get_prototype_of, 1, attr);
|
||||||
put_native_function("setPrototypeOf", set_prototype_of, 2, attr);
|
define_native_function("setPrototypeOf", set_prototype_of, 2, attr);
|
||||||
put_native_function("keys", keys, 1, attr);
|
define_native_function("keys", keys, 1, attr);
|
||||||
put_native_function("values", values, 1, attr);
|
define_native_function("values", values, 1, attr);
|
||||||
put_native_function("entries", entries, 1, attr);
|
define_native_function("entries", entries, 1, attr);
|
||||||
}
|
}
|
||||||
|
|
||||||
ObjectConstructor::~ObjectConstructor()
|
ObjectConstructor::~ObjectConstructor()
|
||||||
|
@ -118,7 +118,7 @@ Value ObjectConstructor::get_own_property_descriptor(Interpreter& interpreter)
|
||||||
return object->get_own_property_descriptor(property_key);
|
return object->get_own_property_descriptor(property_key);
|
||||||
}
|
}
|
||||||
|
|
||||||
Value ObjectConstructor::define_property(Interpreter& interpreter)
|
Value ObjectConstructor::define_property_(Interpreter& interpreter)
|
||||||
{
|
{
|
||||||
if (!interpreter.argument(0).is_object())
|
if (!interpreter.argument(0).is_object())
|
||||||
return interpreter.throw_exception<TypeError>("Object argument is not an object");
|
return interpreter.throw_exception<TypeError>("Object argument is not an object");
|
||||||
|
|
|
@ -42,7 +42,7 @@ private:
|
||||||
virtual bool has_constructor() const override { return true; }
|
virtual bool has_constructor() const override { return true; }
|
||||||
virtual const char* class_name() const override { return "ObjectConstructor"; }
|
virtual const char* class_name() const override { return "ObjectConstructor"; }
|
||||||
|
|
||||||
static Value define_property(Interpreter&);
|
static Value define_property_(Interpreter&);
|
||||||
static Value is(Interpreter&);
|
static Value is(Interpreter&);
|
||||||
static Value get_own_property_descriptor(Interpreter&);
|
static Value get_own_property_descriptor(Interpreter&);
|
||||||
static Value get_own_property_names(Interpreter&);
|
static Value get_own_property_names(Interpreter&);
|
||||||
|
|
|
@ -43,9 +43,9 @@ void ObjectPrototype::initialize()
|
||||||
// This must be called after the constructor has returned, so that the below code
|
// This must be called after the constructor has returned, so that the below code
|
||||||
// can find the ObjectPrototype through normal paths.
|
// can find the ObjectPrototype through normal paths.
|
||||||
u8 attr = Attribute::Writable | Attribute::Configurable;
|
u8 attr = Attribute::Writable | Attribute::Configurable;
|
||||||
put_native_function("hasOwnProperty", has_own_property, 1, attr);
|
define_native_function("hasOwnProperty", has_own_property, 1, attr);
|
||||||
put_native_function("toString", to_string, 0, attr);
|
define_native_function("toString", to_string, 0, attr);
|
||||||
put_native_function("valueOf", value_of, 0, attr);
|
define_native_function("valueOf", value_of, 0, attr);
|
||||||
}
|
}
|
||||||
|
|
||||||
ObjectPrototype::~ObjectPrototype()
|
ObjectPrototype::~ObjectPrototype()
|
||||||
|
|
|
@ -40,14 +40,26 @@ public:
|
||||||
|
|
||||||
PropertyName() {}
|
PropertyName() {}
|
||||||
|
|
||||||
explicit PropertyName(i32 index)
|
PropertyName(i32 index)
|
||||||
: m_type(Type::Number)
|
: m_type(Type::Number)
|
||||||
, m_number(index)
|
, m_number(index)
|
||||||
{
|
{
|
||||||
ASSERT(m_number >= 0);
|
ASSERT(index >= 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
explicit PropertyName(const FlyString& string)
|
PropertyName(const char* chars)
|
||||||
|
: m_type(Type::String)
|
||||||
|
, m_string(FlyString(chars))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
PropertyName(const String& string)
|
||||||
|
: m_type(Type::String)
|
||||||
|
, m_string(FlyString(string))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
PropertyName(const FlyString& string)
|
||||||
: m_type(Type::String)
|
: m_type(Type::String)
|
||||||
, m_string(string)
|
, m_string(string)
|
||||||
{
|
{
|
||||||
|
@ -70,7 +82,7 @@ public:
|
||||||
private:
|
private:
|
||||||
Type m_type { Type::Invalid };
|
Type m_type { Type::Invalid };
|
||||||
FlyString m_string;
|
FlyString m_string;
|
||||||
i32 m_number { 0 };
|
u32 m_number { 0 };
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -79,19 +79,19 @@ ReflectObject::ReflectObject()
|
||||||
: Object(interpreter().global_object().object_prototype())
|
: Object(interpreter().global_object().object_prototype())
|
||||||
{
|
{
|
||||||
u8 attr = Attribute::Writable | Attribute::Configurable;
|
u8 attr = Attribute::Writable | Attribute::Configurable;
|
||||||
put_native_function("apply", apply, 3, attr);
|
define_native_function("apply", apply, 3, attr);
|
||||||
put_native_function("construct", construct, 2, attr);
|
define_native_function("construct", construct, 2, attr);
|
||||||
put_native_function("defineProperty", define_property, 3, attr);
|
define_native_function("defineProperty", define_property, 3, attr);
|
||||||
put_native_function("deleteProperty", delete_property, 2, attr);
|
define_native_function("deleteProperty", delete_property, 2, attr);
|
||||||
put_native_function("get", get, 2, attr);
|
define_native_function("get", get, 2, attr);
|
||||||
put_native_function("getOwnPropertyDescriptor", get_own_property_descriptor, 2, attr);
|
define_native_function("getOwnPropertyDescriptor", get_own_property_descriptor, 2, attr);
|
||||||
put_native_function("getPrototypeOf", get_prototype_of, 1, attr);
|
define_native_function("getPrototypeOf", get_prototype_of, 1, attr);
|
||||||
put_native_function("has", has, 2, attr);
|
define_native_function("has", has, 2, attr);
|
||||||
put_native_function("isExtensible", is_extensible, 1, attr);
|
define_native_function("isExtensible", is_extensible, 1, attr);
|
||||||
put_native_function("ownKeys", own_keys, 1, attr);
|
define_native_function("ownKeys", own_keys, 1, attr);
|
||||||
put_native_function("preventExtensions", prevent_extensions, 1, attr);
|
define_native_function("preventExtensions", prevent_extensions, 1, attr);
|
||||||
put_native_function("set", set, 3, attr);
|
define_native_function("set", set, 3, attr);
|
||||||
put_native_function("setPrototypeOf", set_prototype_of, 2, attr);
|
define_native_function("setPrototypeOf", set_prototype_of, 2, attr);
|
||||||
}
|
}
|
||||||
|
|
||||||
ReflectObject::~ReflectObject()
|
ReflectObject::~ReflectObject()
|
||||||
|
|
|
@ -60,9 +60,9 @@ ScriptFunction::ScriptFunction(const FlyString& name, const Statement& body, Vec
|
||||||
, m_parent_environment(parent_environment)
|
, m_parent_environment(parent_environment)
|
||||||
, m_function_length(m_function_length)
|
, m_function_length(m_function_length)
|
||||||
{
|
{
|
||||||
put("prototype", Object::create_empty(interpreter(), interpreter().global_object()), 0);
|
define_property("prototype", Object::create_empty(interpreter(), interpreter().global_object()), 0);
|
||||||
put_native_property("length", length_getter, nullptr, Attribute::Configurable);
|
define_native_property("length", length_getter, nullptr, Attribute::Configurable);
|
||||||
put_native_property("name", name_getter, nullptr, Attribute::Configurable);
|
define_native_property("name", name_getter, nullptr, Attribute::Configurable);
|
||||||
}
|
}
|
||||||
|
|
||||||
ScriptFunction::~ScriptFunction()
|
ScriptFunction::~ScriptFunction()
|
||||||
|
|
|
@ -37,10 +37,10 @@ namespace JS {
|
||||||
StringConstructor::StringConstructor()
|
StringConstructor::StringConstructor()
|
||||||
: NativeFunction("String", *interpreter().global_object().function_prototype())
|
: NativeFunction("String", *interpreter().global_object().function_prototype())
|
||||||
{
|
{
|
||||||
put("prototype", interpreter().global_object().string_prototype(), 0);
|
define_property("prototype", interpreter().global_object().string_prototype(), 0);
|
||||||
put("length", Value(1), Attribute::Configurable);
|
define_property("length", Value(1), Attribute::Configurable);
|
||||||
|
|
||||||
put_native_function("raw", raw, 0, Attribute::Writable | Attribute::Configurable);
|
define_native_function("raw", raw, 0, Attribute::Writable | Attribute::Configurable);
|
||||||
}
|
}
|
||||||
|
|
||||||
StringConstructor::~StringConstructor()
|
StringConstructor::~StringConstructor()
|
||||||
|
|
|
@ -64,24 +64,24 @@ StringPrototype::StringPrototype()
|
||||||
{
|
{
|
||||||
u8 attr = Attribute::Writable | Attribute::Configurable;
|
u8 attr = Attribute::Writable | Attribute::Configurable;
|
||||||
|
|
||||||
put_native_property("length", length_getter, nullptr, 0);
|
define_native_property("length", length_getter, nullptr, 0);
|
||||||
put_native_function("charAt", char_at, 1, attr);
|
define_native_function("charAt", char_at, 1, attr);
|
||||||
put_native_function("repeat", repeat, 1, attr);
|
define_native_function("repeat", repeat, 1, attr);
|
||||||
put_native_function("startsWith", starts_with, 1, attr);
|
define_native_function("startsWith", starts_with, 1, attr);
|
||||||
put_native_function("indexOf", index_of, 1, attr);
|
define_native_function("indexOf", index_of, 1, attr);
|
||||||
put_native_function("toLowerCase", to_lowercase, 0, attr);
|
define_native_function("toLowerCase", to_lowercase, 0, attr);
|
||||||
put_native_function("toUpperCase", to_uppercase, 0, attr);
|
define_native_function("toUpperCase", to_uppercase, 0, attr);
|
||||||
put_native_function("toString", to_string, 0, attr);
|
define_native_function("toString", to_string, 0, attr);
|
||||||
put_native_function("padStart", pad_start, 1, attr);
|
define_native_function("padStart", pad_start, 1, attr);
|
||||||
put_native_function("padEnd", pad_end, 1, attr);
|
define_native_function("padEnd", pad_end, 1, attr);
|
||||||
put_native_function("trim", trim, 0, attr);
|
define_native_function("trim", trim, 0, attr);
|
||||||
put_native_function("trimStart", trim_start, 0, attr);
|
define_native_function("trimStart", trim_start, 0, attr);
|
||||||
put_native_function("trimEnd", trim_end, 0, attr);
|
define_native_function("trimEnd", trim_end, 0, attr);
|
||||||
put_native_function("concat", concat, 1, attr);
|
define_native_function("concat", concat, 1, attr);
|
||||||
put_native_function("substring", substring, 2, attr);
|
define_native_function("substring", substring, 2, attr);
|
||||||
put_native_function("includes", includes, 1, attr);
|
define_native_function("includes", includes, 1, attr);
|
||||||
put_native_function("slice", slice, 2, attr);
|
define_native_function("slice", slice, 2, attr);
|
||||||
put_native_function("lastIndexOf", last_index_of, 1, attr);
|
define_native_function("lastIndexOf", last_index_of, 1, attr);
|
||||||
}
|
}
|
||||||
|
|
||||||
StringPrototype::~StringPrototype()
|
StringPrototype::~StringPrototype()
|
||||||
|
|
|
@ -35,27 +35,27 @@ namespace JS {
|
||||||
SymbolConstructor::SymbolConstructor()
|
SymbolConstructor::SymbolConstructor()
|
||||||
: NativeFunction("Symbol", *interpreter().global_object().function_prototype())
|
: NativeFunction("Symbol", *interpreter().global_object().function_prototype())
|
||||||
{
|
{
|
||||||
put("prototype", interpreter().global_object().symbol_prototype(), 0);
|
define_property("prototype", interpreter().global_object().symbol_prototype(), 0);
|
||||||
put("length", Value(0), Attribute::Configurable);
|
define_property("length", Value(0), Attribute::Configurable);
|
||||||
|
|
||||||
put_native_function("for", for_, 1, Attribute::Writable | Attribute::Configurable);
|
define_native_function("for", for_, 1, Attribute::Writable | Attribute::Configurable);
|
||||||
put_native_function("keyFor", key_for, 1, Attribute::Writable | Attribute::Configurable);
|
define_native_function("keyFor", key_for, 1, Attribute::Writable | Attribute::Configurable);
|
||||||
|
|
||||||
SymbolObject::initialize_well_known_symbols(interpreter());
|
SymbolObject::initialize_well_known_symbols(interpreter());
|
||||||
|
|
||||||
put("iterator", SymbolObject::well_known_iterator(), 0);
|
define_property("iterator", SymbolObject::well_known_iterator(), 0);
|
||||||
put("asyncIterator", SymbolObject::well_known_async_terator(), 0);
|
define_property("asyncIterator", SymbolObject::well_known_async_terator(), 0);
|
||||||
put("match", SymbolObject::well_known_match(), 0);
|
define_property("match", SymbolObject::well_known_match(), 0);
|
||||||
put("matchAll", SymbolObject::well_known_match_all(), 0);
|
define_property("matchAll", SymbolObject::well_known_match_all(), 0);
|
||||||
put("replace", SymbolObject::well_known_replace(), 0);
|
define_property("replace", SymbolObject::well_known_replace(), 0);
|
||||||
put("search", SymbolObject::well_known_search(), 0);
|
define_property("search", SymbolObject::well_known_search(), 0);
|
||||||
put("split", SymbolObject::well_known_split(), 0);
|
define_property("split", SymbolObject::well_known_split(), 0);
|
||||||
put("hasInstance", SymbolObject::well_known_has_instance(), 0);
|
define_property("hasInstance", SymbolObject::well_known_has_instance(), 0);
|
||||||
put("isConcatSpreadable", SymbolObject::well_known_is_concat_spreadable(), 0);
|
define_property("isConcatSpreadable", SymbolObject::well_known_is_concat_spreadable(), 0);
|
||||||
put("unscopables", SymbolObject::well_known_unscopables(), 0);
|
define_property("unscopables", SymbolObject::well_known_unscopables(), 0);
|
||||||
put("species", SymbolObject::well_known_species(), 0);
|
define_property("species", SymbolObject::well_known_species(), 0);
|
||||||
put("toPrimitive", SymbolObject::well_known_to_primtive(), 0);
|
define_property("toPrimitive", SymbolObject::well_known_to_primtive(), 0);
|
||||||
put("toStringTag", SymbolObject::well_known_to_string_tag(), 0);
|
define_property("toStringTag", SymbolObject::well_known_to_string_tag(), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
SymbolConstructor::~SymbolConstructor()
|
SymbolConstructor::~SymbolConstructor()
|
||||||
|
|
|
@ -42,10 +42,10 @@ namespace JS {
|
||||||
SymbolPrototype::SymbolPrototype()
|
SymbolPrototype::SymbolPrototype()
|
||||||
: Object(interpreter().global_object().object_prototype())
|
: Object(interpreter().global_object().object_prototype())
|
||||||
{
|
{
|
||||||
put_native_property("description", description_getter, nullptr, Attribute::Configurable);
|
define_native_property("description", description_getter, nullptr, Attribute::Configurable);
|
||||||
|
|
||||||
put_native_function("toString", to_string, 0, Attribute::Writable | Attribute::Configurable);
|
define_native_function("toString", to_string, 0, Attribute::Writable | Attribute::Configurable);
|
||||||
put_native_function("valueOf", value_of, 0, Attribute::Writable | Attribute::Configurable);
|
define_native_function("valueOf", value_of, 0, Attribute::Writable | Attribute::Configurable);
|
||||||
}
|
}
|
||||||
|
|
||||||
SymbolPrototype::~SymbolPrototype()
|
SymbolPrototype::~SymbolPrototype()
|
||||||
|
|
|
@ -32,19 +32,17 @@
|
||||||
|
|
||||||
namespace JS {
|
namespace JS {
|
||||||
|
|
||||||
Uint8ClampedArray* Uint8ClampedArray::create(GlobalObject& global_object, i32 length)
|
Uint8ClampedArray* Uint8ClampedArray::create(GlobalObject& global_object, u32 length)
|
||||||
{
|
{
|
||||||
ASSERT(length >= 0);
|
|
||||||
auto& interpreter = global_object.interpreter();
|
auto& interpreter = global_object.interpreter();
|
||||||
return interpreter.heap().allocate<Uint8ClampedArray>(length, *global_object.array_prototype());
|
return interpreter.heap().allocate<Uint8ClampedArray>(length, *global_object.array_prototype());
|
||||||
}
|
}
|
||||||
|
|
||||||
Uint8ClampedArray::Uint8ClampedArray(i32 length, Object& prototype)
|
Uint8ClampedArray::Uint8ClampedArray(u32 length, Object& prototype)
|
||||||
: Object(&prototype)
|
: Object(&prototype)
|
||||||
, m_length(length)
|
, m_length(length)
|
||||||
{
|
{
|
||||||
ASSERT(m_length >= 0);
|
define_native_property("length", length_getter, nullptr);
|
||||||
put_native_property("length", length_getter, nullptr);
|
|
||||||
m_data = new u8[m_length];
|
m_data = new u8[m_length];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -65,10 +63,9 @@ Value Uint8ClampedArray::length_getter(Interpreter& interpreter)
|
||||||
return Value(static_cast<const Uint8ClampedArray*>(this_object)->length());
|
return Value(static_cast<const Uint8ClampedArray*>(this_object)->length());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Uint8ClampedArray::put_by_index(i32 property_index, Value value, u8)
|
bool Uint8ClampedArray::put_by_index(u32 property_index, Value value)
|
||||||
{
|
{
|
||||||
// FIXME: Use attributes
|
// FIXME: Use attributes
|
||||||
ASSERT(property_index >= 0);
|
|
||||||
ASSERT(property_index < m_length);
|
ASSERT(property_index < m_length);
|
||||||
auto number = value.to_i32(interpreter());
|
auto number = value.to_i32(interpreter());
|
||||||
if (interpreter().exception())
|
if (interpreter().exception())
|
||||||
|
@ -77,9 +74,8 @@ bool Uint8ClampedArray::put_by_index(i32 property_index, Value value, u8)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
Value Uint8ClampedArray::get_by_index(i32 property_index) const
|
Value Uint8ClampedArray::get_by_index(u32 property_index) const
|
||||||
{
|
{
|
||||||
ASSERT(property_index >= 0);
|
|
||||||
ASSERT(property_index < m_length);
|
ASSERT(property_index < m_length);
|
||||||
return Value((i32)m_data[property_index]);
|
return Value((i32)m_data[property_index]);
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,15 +32,15 @@ namespace JS {
|
||||||
|
|
||||||
class Uint8ClampedArray final : public Object {
|
class Uint8ClampedArray final : public Object {
|
||||||
public:
|
public:
|
||||||
static Uint8ClampedArray* create(GlobalObject&, i32 length);
|
static Uint8ClampedArray* create(GlobalObject&, u32 length);
|
||||||
|
|
||||||
Uint8ClampedArray(i32 length, Object& prototype);
|
Uint8ClampedArray(u32 length, Object& prototype);
|
||||||
virtual ~Uint8ClampedArray() override;
|
virtual ~Uint8ClampedArray() override;
|
||||||
|
|
||||||
i32 length() const { return m_length; }
|
i32 length() const { return m_length; }
|
||||||
|
|
||||||
virtual bool put_by_index(i32 property_index, Value value, u8 attribute = default_attributes) override;
|
virtual bool put_by_index(u32 property_index, Value value) override;
|
||||||
virtual Value get_by_index(i32 property_index) const override;
|
virtual Value get_by_index(u32 property_index) const override;
|
||||||
|
|
||||||
u8* data() { return m_data; }
|
u8* data() { return m_data; }
|
||||||
const u8* data() const { return m_data; }
|
const u8* data() const { return m_data; }
|
||||||
|
@ -52,7 +52,7 @@ private:
|
||||||
static Value length_getter(Interpreter&);
|
static Value length_getter(Interpreter&);
|
||||||
|
|
||||||
u8* m_data { nullptr };
|
u8* m_data { nullptr };
|
||||||
i32 m_length { 0 };
|
u32 m_length { 0 };
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,25 +51,25 @@ CanvasRenderingContext2DWrapper::CanvasRenderingContext2DWrapper(CanvasRendering
|
||||||
: Wrapper(*interpreter().global_object().object_prototype())
|
: Wrapper(*interpreter().global_object().object_prototype())
|
||||||
, m_impl(impl)
|
, m_impl(impl)
|
||||||
{
|
{
|
||||||
put_native_function("fillRect", fill_rect, 4);
|
define_native_function("fillRect", fill_rect, 4);
|
||||||
put_native_function("scale", scale, 2);
|
define_native_function("scale", scale, 2);
|
||||||
put_native_function("translate", translate, 2);
|
define_native_function("translate", translate, 2);
|
||||||
put_native_function("strokeRect", stroke_rect, 4);
|
define_native_function("strokeRect", stroke_rect, 4);
|
||||||
put_native_function("drawImage", draw_image, 3);
|
define_native_function("drawImage", draw_image, 3);
|
||||||
put_native_function("beginPath", begin_path, 0);
|
define_native_function("beginPath", begin_path, 0);
|
||||||
put_native_function("closePath", close_path, 0);
|
define_native_function("closePath", close_path, 0);
|
||||||
put_native_function("stroke", stroke, 0);
|
define_native_function("stroke", stroke, 0);
|
||||||
put_native_function("fill", fill, 0);
|
define_native_function("fill", fill, 0);
|
||||||
put_native_function("moveTo", move_to, 2);
|
define_native_function("moveTo", move_to, 2);
|
||||||
put_native_function("lineTo", line_to, 2);
|
define_native_function("lineTo", line_to, 2);
|
||||||
put_native_function("quadraticCurveTo", quadratic_curve_to, 4);
|
define_native_function("quadraticCurveTo", quadratic_curve_to, 4);
|
||||||
put_native_function("createImageData", create_image_data, 1);
|
define_native_function("createImageData", create_image_data, 1);
|
||||||
put_native_function("putImageData", put_image_data, 3);
|
define_native_function("putImageData", put_image_data, 3);
|
||||||
|
|
||||||
put_native_property("fillStyle", fill_style_getter, fill_style_setter);
|
define_native_property("fillStyle", fill_style_getter, fill_style_setter);
|
||||||
put_native_property("strokeStyle", stroke_style_getter, stroke_style_setter);
|
define_native_property("strokeStyle", stroke_style_getter, stroke_style_setter);
|
||||||
put_native_property("lineWidth", line_width_getter, line_width_setter);
|
define_native_property("lineWidth", line_width_getter, line_width_setter);
|
||||||
put_native_property("canvas", canvas_getter, nullptr);
|
define_native_property("canvas", canvas_getter, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
CanvasRenderingContext2DWrapper::~CanvasRenderingContext2DWrapper()
|
CanvasRenderingContext2DWrapper::~CanvasRenderingContext2DWrapper()
|
||||||
|
|
|
@ -40,9 +40,9 @@ namespace Bindings {
|
||||||
DocumentWrapper::DocumentWrapper(Document& document)
|
DocumentWrapper::DocumentWrapper(Document& document)
|
||||||
: NodeWrapper(document)
|
: NodeWrapper(document)
|
||||||
{
|
{
|
||||||
put_native_function("getElementById", get_element_by_id, 1);
|
define_native_function("getElementById", get_element_by_id, 1);
|
||||||
put_native_function("querySelector", query_selector, 1);
|
define_native_function("querySelector", query_selector, 1);
|
||||||
put_native_function("querySelectorAll", query_selector_all, 1);
|
define_native_function("querySelectorAll", query_selector_all, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
DocumentWrapper::~DocumentWrapper()
|
DocumentWrapper::~DocumentWrapper()
|
||||||
|
|
|
@ -40,12 +40,12 @@ namespace Bindings {
|
||||||
ElementWrapper::ElementWrapper(Element& element)
|
ElementWrapper::ElementWrapper(Element& element)
|
||||||
: NodeWrapper(element)
|
: NodeWrapper(element)
|
||||||
{
|
{
|
||||||
put_native_property("innerHTML", inner_html_getter, inner_html_setter);
|
define_native_property("innerHTML", inner_html_getter, inner_html_setter);
|
||||||
put_native_property("id", id_getter, id_setter);
|
define_native_property("id", id_getter, id_setter);
|
||||||
|
|
||||||
u8 attributes = JS::Attribute::Configurable | JS::Attribute::Enumerable | JS::Attribute::Writable;
|
u8 attributes = JS::Attribute::Configurable | JS::Attribute::Enumerable | JS::Attribute::Writable;
|
||||||
put_native_function("getAttribute", get_attribute, 1, attributes);
|
define_native_function("getAttribute", get_attribute, 1, attributes);
|
||||||
put_native_function("setAttribute", set_attribute, 2, attributes);
|
define_native_function("setAttribute", set_attribute, 2, attributes);
|
||||||
}
|
}
|
||||||
|
|
||||||
ElementWrapper::~ElementWrapper()
|
ElementWrapper::~ElementWrapper()
|
||||||
|
|
|
@ -42,7 +42,7 @@ EventTargetWrapper::EventTargetWrapper(EventTarget& impl)
|
||||||
: Wrapper(*interpreter().global_object().object_prototype())
|
: Wrapper(*interpreter().global_object().object_prototype())
|
||||||
, m_impl(impl)
|
, m_impl(impl)
|
||||||
{
|
{
|
||||||
put_native_function("addEventListener", add_event_listener, 2);
|
define_native_function("addEventListener", add_event_listener, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
EventTargetWrapper::~EventTargetWrapper()
|
EventTargetWrapper::~EventTargetWrapper()
|
||||||
|
|
|
@ -40,10 +40,10 @@ namespace Bindings {
|
||||||
HTMLCanvasElementWrapper::HTMLCanvasElementWrapper(HTMLCanvasElement& element)
|
HTMLCanvasElementWrapper::HTMLCanvasElementWrapper(HTMLCanvasElement& element)
|
||||||
: ElementWrapper(element)
|
: ElementWrapper(element)
|
||||||
{
|
{
|
||||||
put_native_function("getContext", get_context, 1);
|
define_native_function("getContext", get_context, 1);
|
||||||
|
|
||||||
put_native_property("width", width_getter, nullptr);
|
define_native_property("width", width_getter, nullptr);
|
||||||
put_native_property("height", height_getter, nullptr);
|
define_native_property("height", height_getter, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
HTMLCanvasElementWrapper::~HTMLCanvasElementWrapper()
|
HTMLCanvasElementWrapper::~HTMLCanvasElementWrapper()
|
||||||
|
|
|
@ -44,9 +44,9 @@ ImageDataWrapper::ImageDataWrapper(ImageData& impl)
|
||||||
: Wrapper(*interpreter().global_object().object_prototype())
|
: Wrapper(*interpreter().global_object().object_prototype())
|
||||||
, m_impl(impl)
|
, m_impl(impl)
|
||||||
{
|
{
|
||||||
put_native_property("width", width_getter, nullptr);
|
define_native_property("width", width_getter, nullptr);
|
||||||
put_native_property("height", height_getter, nullptr);
|
define_native_property("height", height_getter, nullptr);
|
||||||
put_native_property("data", data_getter, nullptr);
|
define_native_property("data", data_getter, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
ImageDataWrapper::~ImageDataWrapper()
|
ImageDataWrapper::~ImageDataWrapper()
|
||||||
|
|
|
@ -39,15 +39,15 @@ LocationObject::LocationObject()
|
||||||
: Object(interpreter().global_object().object_prototype())
|
: Object(interpreter().global_object().object_prototype())
|
||||||
{
|
{
|
||||||
u8 attr = JS::Attribute::Writable | JS::Attribute::Enumerable;
|
u8 attr = JS::Attribute::Writable | JS::Attribute::Enumerable;
|
||||||
put_native_property("href", href_getter, href_setter, attr);
|
define_native_property("href", href_getter, href_setter, attr);
|
||||||
put_native_property("host", host_getter, nullptr, attr);
|
define_native_property("host", host_getter, nullptr, attr);
|
||||||
put_native_property("hostname", hostname_getter, nullptr, attr);
|
define_native_property("hostname", hostname_getter, nullptr, attr);
|
||||||
put_native_property("pathname", pathname_getter, nullptr, attr);
|
define_native_property("pathname", pathname_getter, nullptr, attr);
|
||||||
put_native_property("hash", hash_getter, nullptr, attr);
|
define_native_property("hash", hash_getter, nullptr, attr);
|
||||||
put_native_property("search", search_getter, nullptr, attr);
|
define_native_property("search", search_getter, nullptr, attr);
|
||||||
put_native_property("protocol", protocol_getter, nullptr, attr);
|
define_native_property("protocol", protocol_getter, nullptr, attr);
|
||||||
|
|
||||||
put_native_function("reload", reload, JS::Attribute::Enumerable);
|
define_native_function("reload", reload, JS::Attribute::Enumerable);
|
||||||
}
|
}
|
||||||
|
|
||||||
LocationObject::~LocationObject()
|
LocationObject::~LocationObject()
|
||||||
|
|
|
@ -37,8 +37,8 @@ namespace Bindings {
|
||||||
MouseEventWrapper::MouseEventWrapper(MouseEvent& event)
|
MouseEventWrapper::MouseEventWrapper(MouseEvent& event)
|
||||||
: EventWrapper(event)
|
: EventWrapper(event)
|
||||||
{
|
{
|
||||||
put_native_property("offsetX", offset_x_getter, nullptr);
|
define_native_property("offsetX", offset_x_getter, nullptr);
|
||||||
put_native_property("offsetY", offset_y_getter, nullptr);
|
define_native_property("offsetY", offset_y_getter, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
MouseEventWrapper::~MouseEventWrapper()
|
MouseEventWrapper::~MouseEventWrapper()
|
||||||
|
|
|
@ -40,15 +40,15 @@ NavigatorObject::NavigatorObject()
|
||||||
auto* languages = JS::Array::create(interpreter().global_object());
|
auto* languages = JS::Array::create(interpreter().global_object());
|
||||||
languages->elements().append(js_string(heap(), "en-US"));
|
languages->elements().append(js_string(heap(), "en-US"));
|
||||||
|
|
||||||
put("appCodeName", js_string(heap(), "Mozilla"));
|
define_property("appCodeName", js_string(heap(), "Mozilla"));
|
||||||
put("appName", js_string(heap(), "Netscape"));
|
define_property("appName", js_string(heap(), "Netscape"));
|
||||||
put("appVersion", js_string(heap(), "4.0"));
|
define_property("appVersion", js_string(heap(), "4.0"));
|
||||||
put("language", languages->elements().first());
|
define_property("language", languages->elements().first());
|
||||||
put("languages", languages);
|
define_property("languages", languages);
|
||||||
put("platform", js_string(heap(), "SerenityOS"));
|
define_property("platform", js_string(heap(), "SerenityOS"));
|
||||||
put("product", js_string(heap(), "Gecko"));
|
define_property("product", js_string(heap(), "Gecko"));
|
||||||
|
|
||||||
put_native_property("userAgent", user_agent_getter, nullptr);
|
define_native_property("userAgent", user_agent_getter, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
NavigatorObject::~NavigatorObject()
|
NavigatorObject::~NavigatorObject()
|
||||||
|
|
|
@ -51,21 +51,21 @@ void WindowObject::initialize()
|
||||||
{
|
{
|
||||||
GlobalObject::initialize();
|
GlobalObject::initialize();
|
||||||
|
|
||||||
put("window", this, JS::Attribute::Enumerable);
|
define_property("window", this, JS::Attribute::Enumerable);
|
||||||
put_native_property("document", document_getter, document_setter, JS::Attribute::Enumerable);
|
define_native_property("document", document_getter, document_setter, JS::Attribute::Enumerable);
|
||||||
put_native_function("alert", alert);
|
define_native_function("alert", alert);
|
||||||
put_native_function("confirm", confirm);
|
define_native_function("confirm", confirm);
|
||||||
put_native_function("setInterval", set_interval, 1);
|
define_native_function("setInterval", set_interval, 1);
|
||||||
put_native_function("setTimeout", set_timeout, 1);
|
define_native_function("setTimeout", set_timeout, 1);
|
||||||
put_native_function("requestAnimationFrame", request_animation_frame, 1);
|
define_native_function("requestAnimationFrame", request_animation_frame, 1);
|
||||||
put_native_function("cancelAnimationFrame", cancel_animation_frame, 1);
|
define_native_function("cancelAnimationFrame", cancel_animation_frame, 1);
|
||||||
|
|
||||||
put("navigator", heap().allocate<NavigatorObject>(), JS::Attribute::Enumerable | JS::Attribute::Configurable);
|
define_property("navigator", heap().allocate<NavigatorObject>(), JS::Attribute::Enumerable | JS::Attribute::Configurable);
|
||||||
put("location", heap().allocate<LocationObject>(), JS::Attribute::Enumerable | JS::Attribute::Configurable);
|
define_property("location", heap().allocate<LocationObject>(), JS::Attribute::Enumerable | JS::Attribute::Configurable);
|
||||||
|
|
||||||
m_xhr_prototype = heap().allocate<XMLHttpRequestPrototype>();
|
m_xhr_prototype = heap().allocate<XMLHttpRequestPrototype>();
|
||||||
m_xhr_constructor = heap().allocate<XMLHttpRequestConstructor>();
|
m_xhr_constructor = heap().allocate<XMLHttpRequestConstructor>();
|
||||||
m_xhr_constructor->put("prototype", m_xhr_prototype, 0);
|
m_xhr_constructor->define_property("prototype", m_xhr_prototype, 0);
|
||||||
add_constructor("XMLHttpRequest", m_xhr_constructor, *m_xhr_prototype);
|
add_constructor("XMLHttpRequest", m_xhr_constructor, *m_xhr_prototype);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -39,13 +39,13 @@ namespace Bindings {
|
||||||
XMLHttpRequestConstructor::XMLHttpRequestConstructor()
|
XMLHttpRequestConstructor::XMLHttpRequestConstructor()
|
||||||
: NativeFunction(*interpreter().global_object().function_prototype())
|
: NativeFunction(*interpreter().global_object().function_prototype())
|
||||||
{
|
{
|
||||||
put("length", JS::Value(1), JS::Attribute::Configurable);
|
define_property("length", JS::Value(1), JS::Attribute::Configurable);
|
||||||
|
|
||||||
put("UNSENT", JS::Value((i32)XMLHttpRequest::ReadyState::Unsent), JS::Attribute::Enumerable);
|
define_property("UNSENT", JS::Value((i32)XMLHttpRequest::ReadyState::Unsent), JS::Attribute::Enumerable);
|
||||||
put("OPENED", JS::Value((i32)XMLHttpRequest::ReadyState::Opened), JS::Attribute::Enumerable);
|
define_property("OPENED", JS::Value((i32)XMLHttpRequest::ReadyState::Opened), JS::Attribute::Enumerable);
|
||||||
put("HEADERS_RECEIVED", JS::Value((i32)XMLHttpRequest::ReadyState::HeadersReceived), JS::Attribute::Enumerable);
|
define_property("HEADERS_RECEIVED", JS::Value((i32)XMLHttpRequest::ReadyState::HeadersReceived), JS::Attribute::Enumerable);
|
||||||
put("LOADING", JS::Value((i32)XMLHttpRequest::ReadyState::Loading), JS::Attribute::Enumerable);
|
define_property("LOADING", JS::Value((i32)XMLHttpRequest::ReadyState::Loading), JS::Attribute::Enumerable);
|
||||||
put("DONE", JS::Value((i32)XMLHttpRequest::ReadyState::Done), JS::Attribute::Enumerable);
|
define_property("DONE", JS::Value((i32)XMLHttpRequest::ReadyState::Done), JS::Attribute::Enumerable);
|
||||||
}
|
}
|
||||||
|
|
||||||
XMLHttpRequestConstructor::~XMLHttpRequestConstructor()
|
XMLHttpRequestConstructor::~XMLHttpRequestConstructor()
|
||||||
|
|
|
@ -38,16 +38,16 @@ namespace Bindings {
|
||||||
XMLHttpRequestPrototype::XMLHttpRequestPrototype()
|
XMLHttpRequestPrototype::XMLHttpRequestPrototype()
|
||||||
: Object(interpreter().global_object().object_prototype())
|
: Object(interpreter().global_object().object_prototype())
|
||||||
{
|
{
|
||||||
put_native_function("open", open, 2);
|
define_native_function("open", open, 2);
|
||||||
put_native_function("send", send, 0);
|
define_native_function("send", send, 0);
|
||||||
put_native_property("readyState", ready_state_getter, nullptr, JS::Attribute::Enumerable | JS::Attribute::Configurable);
|
define_native_property("readyState", ready_state_getter, nullptr, JS::Attribute::Enumerable | JS::Attribute::Configurable);
|
||||||
put_native_property("responseText", response_text_getter, nullptr, JS::Attribute::Enumerable | JS::Attribute::Configurable);
|
define_native_property("responseText", response_text_getter, nullptr, JS::Attribute::Enumerable | JS::Attribute::Configurable);
|
||||||
|
|
||||||
put("UNSENT", JS::Value((i32)XMLHttpRequest::ReadyState::Unsent), JS::Attribute::Enumerable);
|
define_property("UNSENT", JS::Value((i32)XMLHttpRequest::ReadyState::Unsent), JS::Attribute::Enumerable);
|
||||||
put("OPENED", JS::Value((i32)XMLHttpRequest::ReadyState::Opened), JS::Attribute::Enumerable);
|
define_property("OPENED", JS::Value((i32)XMLHttpRequest::ReadyState::Opened), JS::Attribute::Enumerable);
|
||||||
put("HEADERS_RECEIVED", JS::Value((i32)XMLHttpRequest::ReadyState::HeadersReceived), JS::Attribute::Enumerable);
|
define_property("HEADERS_RECEIVED", JS::Value((i32)XMLHttpRequest::ReadyState::HeadersReceived), JS::Attribute::Enumerable);
|
||||||
put("LOADING", JS::Value((i32)XMLHttpRequest::ReadyState::Loading), JS::Attribute::Enumerable);
|
define_property("LOADING", JS::Value((i32)XMLHttpRequest::ReadyState::Loading), JS::Attribute::Enumerable);
|
||||||
put("DONE", JS::Value((i32)XMLHttpRequest::ReadyState::Done), JS::Attribute::Enumerable);
|
define_property("DONE", JS::Value((i32)XMLHttpRequest::ReadyState::Done), JS::Attribute::Enumerable);
|
||||||
}
|
}
|
||||||
|
|
||||||
XMLHttpRequestPrototype::~XMLHttpRequestPrototype()
|
XMLHttpRequestPrototype::~XMLHttpRequestPrototype()
|
||||||
|
|
|
@ -313,10 +313,10 @@ ReplObject::ReplObject()
|
||||||
void ReplObject::initialize()
|
void ReplObject::initialize()
|
||||||
{
|
{
|
||||||
GlobalObject::initialize();
|
GlobalObject::initialize();
|
||||||
put_native_function("exit", exit_interpreter);
|
define_native_function("exit", exit_interpreter);
|
||||||
put_native_function("help", repl_help);
|
define_native_function("help", repl_help);
|
||||||
put_native_function("load", load_file, 1);
|
define_native_function("load", load_file, 1);
|
||||||
put_native_function("save", save_to_file, 1);
|
define_native_function("save", save_to_file, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
ReplObject::~ReplObject()
|
ReplObject::~ReplObject()
|
||||||
|
@ -391,7 +391,7 @@ void repl(JS::Interpreter& interpreter)
|
||||||
|
|
||||||
void enable_test_mode(JS::Interpreter& interpreter)
|
void enable_test_mode(JS::Interpreter& interpreter)
|
||||||
{
|
{
|
||||||
interpreter.global_object().put_native_function("load", ReplObject::load_file);
|
interpreter.global_object().define_native_function("load", ReplObject::load_file);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Function<void()> interrupt_interpreter;
|
static Function<void()> interrupt_interpreter;
|
||||||
|
@ -751,7 +751,7 @@ int main(int argc, char** argv)
|
||||||
case CompleteProperty: {
|
case CompleteProperty: {
|
||||||
auto maybe_variable = interpreter->get_variable(variable_name);
|
auto maybe_variable = interpreter->get_variable(variable_name);
|
||||||
if (maybe_variable.is_empty()) {
|
if (maybe_variable.is_empty()) {
|
||||||
maybe_variable = interpreter->global_object().get(variable_name);
|
maybe_variable = interpreter->global_object().get(FlyString(variable_name));
|
||||||
if (maybe_variable.is_empty())
|
if (maybe_variable.is_empty())
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue