https://bugs.webkit.org/show_bug.cgi?id=143923
Reviewed by Darin Adler.
Builtin functions defined by builtins/*.js accidentally have [[Construct]].
According to the spec, these functions except for explicitly defined as a constructor do not have [[Construct]].
This patch fixes it. When the JS function used for a construction is builtin function, throw not a constructor error.
Ideally, returning ConstructTypeNone in JSFunction::getConstructData is enough.
However, to avoid calling getConstructData (it involves indirect call of function pointer of getConstructData), some places do not check ConstructType.
In these places, they only check the target function is JSFunction because previously JSFunction always has [[Construct]].
So in this patch, we check `isBuiltinFunction()` in those places.
* dfg/DFGByteCodeParser.cpp:
(JSC::DFG::ByteCodeParser::inliningCost):
* jit/JITOperations.cpp:
* llint/LLIntSlowPaths.cpp:
(JSC::LLInt::setUpCall):
* runtime/JSFunction.cpp:
(JSC::JSFunction::getConstructData):
* tests/stress/builtin-function-is-construct-type-none.js: Added.
(shouldThrow):
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@182995
268f45cc-cd09-0410-ab3c-
d52691b4dbfc
2015-04-19 Yusuke Suzuki <utatane.tea@gmail.com>
+ Make Builtin functions non constructible
+ https://bugs.webkit.org/show_bug.cgi?id=143923
+
+ Reviewed by Darin Adler.
+
+ Builtin functions defined by builtins/*.js accidentally have [[Construct]].
+ According to the spec, these functions except for explicitly defined as a constructor do not have [[Construct]].
+ This patch fixes it. When the JS function used for a construction is builtin function, throw not a constructor error.
+
+ Ideally, returning ConstructTypeNone in JSFunction::getConstructData is enough.
+ However, to avoid calling getConstructData (it involves indirect call of function pointer of getConstructData), some places do not check ConstructType.
+ In these places, they only check the target function is JSFunction because previously JSFunction always has [[Construct]].
+ So in this patch, we check `isBuiltinFunction()` in those places.
+
+ * dfg/DFGByteCodeParser.cpp:
+ (JSC::DFG::ByteCodeParser::inliningCost):
+ * jit/JITOperations.cpp:
+ * llint/LLIntSlowPaths.cpp:
+ (JSC::LLInt::setUpCall):
+ * runtime/JSFunction.cpp:
+ (JSC::JSFunction::getConstructData):
+ * tests/stress/builtin-function-is-construct-type-none.js: Added.
+ (shouldThrow):
+
+2015-04-19 Yusuke Suzuki <utatane.tea@gmail.com>
+
[ES6] Implement WeakSet
https://bugs.webkit.org/show_bug.cgi?id=142408
}
// Do we have a code block, and does the code block's size match the heuristics/requirements for
- // being an inline candidate? We might not have a code block if code was thrown away or if we
- // simply hadn't actually made this call yet. We could still theoretically attempt to inline it
- // if we had a static proof of what was being called; this might happen for example if you call a
- // global function, where watchpointing gives us static information. Overall, it's a rare case
- // because we expect that any hot callees would have already been compiled.
+ // being an inline candidate? We might not have a code block (1) if code was thrown away,
+ // (2) if we simply hadn't actually made this call yet or (3) code is a builtin function and
+ // specialization kind is construct. In the former 2 cases, we could still theoretically attempt
+ // to inline it if we had a static proof of what was being called; this might happen for example
+ // if you call a global function, where watchpointing gives us static information. Overall,
+ // it's a rare case because we expect that any hot callees would have already been compiled.
CodeBlock* codeBlock = executable->baselineCodeBlockFor(kind);
if (!codeBlock) {
if (verbose)
codePtr = executable->entrypointFor(*vm, kind, MustCheckArity, registers);
else {
FunctionExecutable* functionExecutable = static_cast<FunctionExecutable*>(executable);
+
+ if (!isCall(kind) && functionExecutable->isBuiltinFunction()) {
+ exec->vm().throwException(exec, createNotAConstructorError(exec, callee));
+ return reinterpret_cast<char*>(vm->getCTIStub(throwExceptionFromCallSlowPathGenerator).code().executableAddress());
+ }
+
JSObject* error = functionExecutable->prepareForExecution(execCallee, callee, scope, kind);
if (error) {
throwStackOverflowError(exec);
ExecutableBase* executable = function->executable();
if (UNLIKELY(!executable->hasJITCodeFor(kind))) {
FunctionExecutable* functionExecutable = static_cast<FunctionExecutable*>(executable);
+
+ if (!isCall(kind) && functionExecutable->isBuiltinFunction()) {
+ exec->vm().throwException(exec, createNotAConstructorError(exec, function));
+ return reinterpret_cast<char*>(vm->getCTIStub(throwExceptionFromCallSlowPathGenerator).code().executableAddress());
+ }
+
JSObject* error = functionExecutable->prepareForExecution(execCallee, function, scope, kind);
if (error) {
exec->vm().throwException(exec, error);
codePtr = executable->entrypointFor(vm, kind, MustCheckArity, RegisterPreservationNotRequired);
else {
FunctionExecutable* functionExecutable = static_cast<FunctionExecutable*>(executable);
+
+ if (!isCall(kind) && functionExecutable->isBuiltinFunction())
+ LLINT_CALL_THROW(exec, createNotAConstructorError(exec, callee));
+
JSObject* error = functionExecutable->prepareForExecution(execCallee, callee, scope, kind);
if (error)
LLINT_CALL_THROW(exec, error);
ConstructType JSFunction::getConstructData(JSCell* cell, ConstructData& constructData)
{
JSFunction* thisObject = jsCast<JSFunction*>(cell);
+
+ if (thisObject->isBuiltinFunction())
+ return ConstructTypeNone;
+
if (thisObject->isHostFunction()) {
constructData.native.function = thisObject->nativeConstructor();
return ConstructTypeHost;
--- /dev/null
+function shouldThrow(func, message) {
+ var error = null;
+ try {
+ func();
+ } catch (e) {
+ error = e;
+ }
+ if (!error)
+ throw new Error("not thrown.");
+ if (String(error) !== message)
+ throw new Error("bad error: " + String(error));
+}
+
+for (var i = 0; i < 10000; ++i) {
+ shouldThrow(function () {
+ new Array.prototype.forEach(function () { });
+ }, "TypeError: function is not a constructor (evaluating 'new Array.prototype.forEach(function () { })')");
+}