All prototypes should call didBecomePrototype()
[WebKit-https.git] / Source / JavaScriptCore / runtime / ErrorConstructor.cpp
1 /*
2  *  Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
3  *  Copyright (C) 2003-2017 Apple Inc. All rights reserved.
4  *
5  *  This library is free software; you can redistribute it and/or
6  *  modify it under the terms of the GNU Lesser General Public
7  *  License as published by the Free Software Foundation; either
8  *  version 2 of the License, or (at your option) any later version.
9  *
10  *  This library is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  *  Lesser General Public License for more details.
14  *
15  *  You should have received a copy of the GNU Lesser General Public
16  *  License along with this library; if not, write to the Free Software
17  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
18  *
19  */
20
21 #include "config.h"
22 #include "ErrorConstructor.h"
23
24 #include "ErrorPrototype.h"
25 #include "Interpreter.h"
26 #include "JSGlobalObject.h"
27 #include "JSString.h"
28 #include "JSCInlines.h"
29
30 namespace JSC {
31
32 STATIC_ASSERT_IS_TRIVIALLY_DESTRUCTIBLE(ErrorConstructor);
33
34 const ClassInfo ErrorConstructor::s_info = { "Function", &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(ErrorConstructor) };
35
36 static EncodedJSValue JSC_HOST_CALL callErrorConstructor(ExecState*);
37 static EncodedJSValue JSC_HOST_CALL constructErrorConstructor(ExecState*);
38
39 ErrorConstructor::ErrorConstructor(VM& vm, Structure* structure)
40     : InternalFunction(vm, structure, callErrorConstructor, constructErrorConstructor)
41 {
42 }
43
44 void ErrorConstructor::finishCreation(VM& vm, ErrorPrototype* errorPrototype)
45 {
46     Base::finishCreation(vm, vm.propertyNames->Error.string(), NameVisibility::Visible, NameAdditionMode::WithoutStructureTransition);
47     // ECMA 15.11.3.1 Error.prototype
48     putDirectWithoutTransition(vm, vm.propertyNames->prototype, errorPrototype, PropertyAttribute::DontEnum | PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly);
49     putDirectWithoutTransition(vm, vm.propertyNames->length, jsNumber(1), PropertyAttribute::DontEnum | PropertyAttribute::ReadOnly);
50     putDirectWithoutTransition(vm, vm.propertyNames->stackTraceLimit, jsNumber(globalObject(vm)->stackTraceLimit().valueOr(Options::defaultErrorStackTraceLimit())), static_cast<unsigned>(PropertyAttribute::None));
51     didBecomePrototype();
52 }
53
54 // ECMA 15.9.3
55
56 EncodedJSValue JSC_HOST_CALL constructErrorConstructor(ExecState* exec)
57 {
58     VM& vm = exec->vm();
59     auto scope = DECLARE_THROW_SCOPE(vm);
60     JSValue message = exec->argument(0);
61     Structure* errorStructure = InternalFunction::createSubclassStructure(exec, exec->newTarget(), jsCast<InternalFunction*>(exec->jsCallee())->globalObject(vm)->errorStructure());
62     RETURN_IF_EXCEPTION(scope, encodedJSValue());
63     RELEASE_AND_RETURN(scope, JSValue::encode(ErrorInstance::create(exec, errorStructure, message, nullptr, TypeNothing, false)));
64 }
65
66 EncodedJSValue JSC_HOST_CALL callErrorConstructor(ExecState* exec)
67 {
68     JSValue message = exec->argument(0);
69     Structure* errorStructure = jsCast<InternalFunction*>(exec->jsCallee())->globalObject(exec->vm())->errorStructure();
70     return JSValue::encode(ErrorInstance::create(exec, errorStructure, message, nullptr, TypeNothing, false));
71 }
72
73 bool ErrorConstructor::put(JSCell* cell, ExecState* exec, PropertyName propertyName, JSValue value, PutPropertySlot& slot)
74 {
75     VM& vm = exec->vm();
76     ErrorConstructor* thisObject = jsCast<ErrorConstructor*>(cell);
77
78     if (propertyName == vm.propertyNames->stackTraceLimit) {
79         if (value.isNumber()) {
80             double effectiveLimit = value.asNumber();
81             effectiveLimit = std::max(0., effectiveLimit);
82             effectiveLimit = std::min(effectiveLimit, static_cast<double>(std::numeric_limits<unsigned>::max()));
83             thisObject->globalObject(vm)->setStackTraceLimit(static_cast<unsigned>(effectiveLimit));
84         } else
85             thisObject->globalObject(vm)->setStackTraceLimit(WTF::nullopt);
86     }
87
88     return Base::put(thisObject, exec, propertyName, value, slot);
89 }
90
91 bool ErrorConstructor::deleteProperty(JSCell* cell, ExecState* exec, PropertyName propertyName)
92 {
93     VM& vm = exec->vm();
94     ErrorConstructor* thisObject = jsCast<ErrorConstructor*>(cell);
95
96     if (propertyName == vm.propertyNames->stackTraceLimit)
97         thisObject->globalObject(vm)->setStackTraceLimit(WTF::nullopt);
98
99     return Base::deleteProperty(thisObject, exec, propertyName);
100 }
101
102 } // namespace JSC