summaryrefslogtreecommitdiff
path: root/Userland
diff options
context:
space:
mode:
authordavidot <davidot@serenityos.org>2021-11-15 01:48:55 +0100
committerLinus Groh <mail@linusgroh.de>2021-11-21 21:46:39 +0000
commit5d0f666f22db855fb6ecede5e6a570ba66efbec5 (patch)
treeebad032de01afaa1f2e1be9114590217bc1c63d3 /Userland
parentde46a2cff1411519a71bfb04490ce9b805e2c09b (diff)
downloadserenity-5d0f666f22db855fb6ecede5e6a570ba66efbec5.zip
LibJS: Don't set a prototype property on async functions
This is now as defined in the spec. However since we execute async functions in bytecode by transforming it to a generator function it must have a prototype for the GeneratorObject. We check whether it is an async function and in that case use the hardcoded generator object prototype. This also ensures that user code cannot override this property thus preventing exposing internal implementation details.
Diffstat (limited to 'Userland')
-rw-r--r--Userland/Libraries/LibJS/Runtime/ECMAScriptFunctionObject.cpp3
-rw-r--r--Userland/Libraries/LibJS/Runtime/ECMAScriptFunctionObject.h2
-rw-r--r--Userland/Libraries/LibJS/Runtime/GeneratorObject.cpp10
3 files changed, 13 insertions, 2 deletions
diff --git a/Userland/Libraries/LibJS/Runtime/ECMAScriptFunctionObject.cpp b/Userland/Libraries/LibJS/Runtime/ECMAScriptFunctionObject.cpp
index 2a638dc0bf..3c4ae45323 100644
--- a/Userland/Libraries/LibJS/Runtime/ECMAScriptFunctionObject.cpp
+++ b/Userland/Libraries/LibJS/Runtime/ECMAScriptFunctionObject.cpp
@@ -101,10 +101,11 @@ void ECMAScriptFunctionObject::initialize(GlobalObject& global_object)
MUST(prototype->define_property_or_throw(vm.names.constructor, { .value = this, .writable = true, .enumerable = false, .configurable = true }));
break;
case FunctionKind::Generator:
- case FunctionKind::Async:
// prototype is "g1.prototype" in figure-2 (https://tc39.es/ecma262/img/figure-2.png)
prototype = global_object.generator_object_prototype();
break;
+ case FunctionKind::Async:
+ break;
}
define_direct_property(vm.names.prototype, prototype, Attribute::Writable);
}
diff --git a/Userland/Libraries/LibJS/Runtime/ECMAScriptFunctionObject.h b/Userland/Libraries/LibJS/Runtime/ECMAScriptFunctionObject.h
index 0868ebc55b..21ea05bc59 100644
--- a/Userland/Libraries/LibJS/Runtime/ECMAScriptFunctionObject.h
+++ b/Userland/Libraries/LibJS/Runtime/ECMAScriptFunctionObject.h
@@ -75,6 +75,8 @@ public:
// Equivalent to absence of [[Construct]]
virtual bool has_constructor() const override { return m_kind == FunctionKind::Regular && !m_is_arrow_function; }
+ FunctionKind kind() const { return m_kind; }
+
protected:
virtual bool is_strict_mode() const final { return m_strict; }
diff --git a/Userland/Libraries/LibJS/Runtime/GeneratorObject.cpp b/Userland/Libraries/LibJS/Runtime/GeneratorObject.cpp
index e145f9422c..7f37c6d084 100644
--- a/Userland/Libraries/LibJS/Runtime/GeneratorObject.cpp
+++ b/Userland/Libraries/LibJS/Runtime/GeneratorObject.cpp
@@ -16,7 +16,15 @@ namespace JS {
ThrowCompletionOr<GeneratorObject*> GeneratorObject::create(GlobalObject& global_object, Value initial_value, ECMAScriptFunctionObject* generating_function, ExecutionContext execution_context, Bytecode::RegisterWindow frame)
{
// This is "g1.prototype" in figure-2 (https://tc39.es/ecma262/img/figure-2.png)
- auto generating_function_prototype = TRY(generating_function->get(global_object.vm().names.prototype));
+ Value generating_function_prototype;
+ if (generating_function->kind() == FunctionKind::Async) {
+ // We implement async functions by transforming them to generator function in the bytecode
+ // interpreter. However an async function does not have a prototype and should not be
+ // changed thus we hardcode the prototype.
+ generating_function_prototype = global_object.generator_object_prototype();
+ } else {
+ generating_function_prototype = TRY(generating_function->get(global_object.vm().names.prototype));
+ }
auto* generating_function_prototype_object = TRY(generating_function_prototype.to_object(global_object));
auto object = global_object.heap().allocate<GeneratorObject>(global_object, global_object, *generating_function_prototype_object, move(execution_context));
object->m_generating_function = generating_function;