+2014-04-08 Oliver Hunt <oliver@apple.com>
+
+ Rewrite Function.bind as a builtin
+ https://bugs.webkit.org/show_bug.cgi?id=131083
+
+ Reviewed by Geoffrey Garen.
+
+ Testing.
+
+ * js/dom/function-bind-expected.txt:
+ * js/regress/function-bind-expected.txt: Added.
+ * js/regress/function-bind.html: Added.
+ * js/regress/script-tests/function-bind.js: Added.
+ (foo):
+
2014-04-13 Youenn Fablet <youenn.fablet@crf.canon.fr>
[GStreamer] No CORS support for media elements
On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
-PASS new (decodeURI.bind())() threw exception TypeError: function is not a constructor (evaluating 'new (decodeURI.bind())()').
+PASS new (decodeURI.bind())() threw exception TypeError: function is not a constructor.
PASS (new (String.bind())('foo')).toString() is 'foo'
PASS result is "[object Window] -> x:1, y:2"
PASS result is "'a' -> x:'b', y:1"
PASS "prototype" in F is true
PASS "prototype" in G is false
PASS "prototype" in H is false
-PASS Function.bind.call(undefined) threw exception TypeError: Type error.
+PASS Function.bind.call(undefined) threw exception TypeError: Cannot bind non-function object..
PASS abcAt(1) is "b"
-PASS new abcAt(1) threw exception TypeError: function is not a constructor (evaluating 'new abcAt(1)').
+PASS new abcAt(1) threw exception TypeError: function is not a constructor.
PASS boundFunctionPrototypeAccessed is false
PASS Function.bind.length is 1
PASS successfullyParsed is true
--- /dev/null
+JSRegress/function-bind
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS no exception thrown
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
--- /dev/null
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<script src="../../resources/js-test-pre.js"></script>
+</head>
+<body>
+<script src="../../resources/regress-pre.js"></script>
+<script src="script-tests/function-bind.js"></script>
+<script src="../../resources/regress-post.js"></script>
+<script src="../../resources/js-test-post.js"></script>
+</body>
+</html>
--- /dev/null
+function foo(a,b) {
+ return a ^ b + arguments.length;
+}
+
+var g0 = foo.bind({});
+var g1 = foo.bind({}, 1);
+var g2 = foo.bind({}, 1, 2);
+var g3 = foo.bind({}, 1, 2, 3);
+var start = new Date;
+
+var result = 0;
+for (var i = 0; i < 100000; ++i) {
+ result *= 3;
+ result += g0(i, result);
+ result += g1();
+ result += g1(i);
+ result += g1(i, result);
+ result += g2();
+ result += g2(i);
+ result += g2(i, result);
+ result += g3();
+ result += g3(i);
+ result += g3(i, result);
+ result |= 0;
+}
+print((new Date - start))
+if (result != 1596499010)
+ throw "Bad result: " + result;
JSCallbackConstructor* constructor = JSCallbackConstructor::create(exec, exec->lexicalGlobalObject(), exec->lexicalGlobalObject()->callbackConstructorStructure(), jsClass, callAsConstructor);
constructor->putDirect(exec->vm(), exec->propertyNames().prototype, jsPrototype, DontEnum | DontDelete | ReadOnly);
+ constructor->putDirect(exec->vm(), exec->propertyNames().prototypeForHasInstancePrivateName, jsPrototype, DontEnum | DontDelete | ReadOnly);
return toRef(constructor);
}
static bool parseScript(VM* vm, const SourceCode& source, ParserError& error)
{
- return JSC::parse<JSC::ProgramNode>(vm, source, 0, Identifier(), JSParseNormal, JSParseProgramCode, error);
+ return JSC::parse<JSC::ProgramNode>(vm, source, 0, Identifier(), JSParseNormal, JSParseProgramCode, JSNotFunctionKind, error);
}
extern "C" {
runtime/JSArrayBufferPrototype.cpp
runtime/JSArrayBufferView.cpp
runtime/JSArrayIterator.cpp
- runtime/JSBoundFunction.cpp
runtime/JSCJSValue.cpp
runtime/JSCell.cpp
runtime/JSConsole.cpp
+2014-04-08 Oliver Hunt <oliver@apple.com>
+
+ Rewrite Function.bind as a builtin
+ https://bugs.webkit.org/show_bug.cgi?id=131083
+
+ Reviewed by Geoffrey Garen.
+
+ This change removes the existing function.bind implementation
+ entirely so JSBoundFunction is no more.
+
+ Instead we just return a regular JS closure with a few
+ private properties hanging off it that allow us to perform
+ the necessary bound function fakery. While most of this is
+ simple, a couple of key changes:
+
+ - The parser and lexer now directly track whether they're
+ parsing code for call or construct and convert the private
+ name @IsConstructor into TRUETOK or FALSETOK as appropriate.
+ This automatically gives us the ability to vary behaviour
+ from within the builtin. It also leaves a lot of headroom
+ for trivial future improvements.
+ - The instanceof operator now uses the prototypeForHasInstance
+ private name, and we have a helper function to ensure that
+ all objects that need to can update their magical 'prototype'
+ property pair correctly.
+
+ * API/JSScriptRef.cpp:
+ (parseScript):
+ * JavaScriptCore.xcodeproj/project.pbxproj:
+ * builtins/BuiltinExecutables.cpp:
+ (JSC::BuiltinExecutables::createBuiltinExecutable):
+ * builtins/Function.prototype.js:
+ (bind.bindingFunction):
+ (bind.else.bindingFunction):
+ (bind):
+ * bytecode/UnlinkedCodeBlock.cpp:
+ (JSC::generateFunctionCodeBlock):
+ * bytecompiler/NodesCodegen.cpp:
+ (JSC::InstanceOfNode::emitBytecode):
+ * interpreter/Interpreter.cpp:
+ * parser/Lexer.cpp:
+ (JSC::Lexer<T>::Lexer):
+ (JSC::Lexer<LChar>::parseIdentifier):
+ (JSC::Lexer<UChar>::parseIdentifier):
+ * parser/Lexer.h:
+ * parser/Parser.cpp:
+ (JSC::Parser<LexerType>::Parser):
+ (JSC::Parser<LexerType>::parseInner):
+ * parser/Parser.h:
+ (JSC::parse):
+ * parser/ParserModes.h:
+ * runtime/CodeCache.cpp:
+ (JSC::CodeCache::getGlobalCodeBlock):
+ (JSC::CodeCache::getFunctionExecutableFromGlobalCode):
+ * runtime/CommonIdentifiers.h:
+ * runtime/Completion.cpp:
+ (JSC::checkSyntax):
+ * runtime/Executable.cpp:
+ (JSC::ProgramExecutable::checkSyntax):
+ * runtime/FunctionPrototype.cpp:
+ (JSC::FunctionPrototype::addFunctionProperties):
+ (JSC::functionProtoFuncBind): Deleted.
+ * runtime/JSBoundFunction.cpp: Removed.
+ * runtime/JSBoundFunction.h: Removed.
+ * runtime/JSFunction.cpp:
+ (JSC::RetrieveCallerFunctionFunctor::RetrieveCallerFunctionFunctor):
+ (JSC::RetrieveCallerFunctionFunctor::operator()):
+ (JSC::retrieveCallerFunction):
+ (JSC::JSFunction::getOwnPropertySlot):
+ (JSC::JSFunction::defineOwnProperty):
+ * runtime/JSGlobalObject.cpp:
+ (JSC::JSGlobalObject::reset):
+ * runtime/JSGlobalObjectFunctions.cpp:
+ (JSC::globalFuncSetTypeErrorAccessor):
+ * runtime/JSGlobalObjectFunctions.h:
+ * runtime/JSObject.h:
+ (JSC::JSObject::inlineGetOwnPropertySlot):
+
2014-04-12 Filip Pizlo <fpizlo@apple.com>
Math.fround() should be an intrinsic
<ClCompile Include="..\runtime\JSArrayBufferConstructor.cpp" />
<ClCompile Include="..\runtime\JSArrayBufferPrototype.cpp" />
<ClCompile Include="..\runtime\JSArrayBufferView.cpp" />
- <ClCompile Include="..\runtime\JSBoundFunction.cpp" />
<ClCompile Include="..\runtime\JSCJSValue.cpp" />
<ClCompile Include="..\runtime\JSCell.cpp" />
<ClCompile Include="..\runtime\JSConsole.cpp" />
<ClInclude Include="..\runtime\JSArrayBufferView.h" />
<ClInclude Include="..\runtime\JSArrayBufferViewInlines.h" />
<ClInclude Include="..\runtime\JSArrayIterator.h" />
- <ClInclude Include="..\runtime\JSBoundFunction.h" />
<ClInclude Include="..\runtime\JSCInlines.h" />
<ClInclude Include="..\runtime\JSCJSValue.h" />
<ClInclude Include="..\runtime\JSCJSValueInlines.h" />
<ClCompile Include="..\runtime\JSArray.cpp">
<Filter>runtime</Filter>
</ClCompile>
- <ClCompile Include="..\runtime\JSBoundFunction.cpp">
- <Filter>runtime</Filter>
- </ClCompile>
<ClCompile Include="..\runtime\JSCell.cpp">
<Filter>runtime</Filter>
</ClCompile>
<ClInclude Include="..\runtime\JSArray.h">
<Filter>runtime</Filter>
</ClInclude>
- <ClInclude Include="..\runtime\JSBoundFunction.h">
- <Filter>runtime</Filter>
- </ClInclude>
<ClInclude Include="..\runtime\JSCell.h">
<Filter>runtime</Filter>
</ClInclude>
86F3EEBD168CDE930077B92A /* ObjCCallbackFunction.h in Headers */ = {isa = PBXBuildFile; fileRef = 86F3EEB9168CCF750077B92A /* ObjCCallbackFunction.h */; };
86F3EEBE168CDE930077B92A /* ObjCCallbackFunction.mm in Sources */ = {isa = PBXBuildFile; fileRef = 86F3EEBA168CCF750077B92A /* ObjCCallbackFunction.mm */; };
86F3EEBF168CDE930077B92A /* ObjcRuntimeExtras.h in Headers */ = {isa = PBXBuildFile; fileRef = 86F3EEB616855A5B0077B92A /* ObjcRuntimeExtras.h */; };
- 86FA9E91142BBB2E001773B7 /* JSBoundFunction.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 86FA9E8F142BBB2D001773B7 /* JSBoundFunction.cpp */; };
- 86FA9E92142BBB2E001773B7 /* JSBoundFunction.h in Headers */ = {isa = PBXBuildFile; fileRef = 86FA9E90142BBB2E001773B7 /* JSBoundFunction.h */; };
90213E3D123A40C200D422F3 /* MemoryStatistics.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 90213E3B123A40C200D422F3 /* MemoryStatistics.cpp */; };
90213E3E123A40C200D422F3 /* MemoryStatistics.h in Headers */ = {isa = PBXBuildFile; fileRef = 90213E3C123A40C200D422F3 /* MemoryStatistics.h */; settings = {ATTRIBUTES = (Private, ); }; };
93052C340FB792190048FDC3 /* ParserArena.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 93052C320FB792190048FDC3 /* ParserArena.cpp */; };
86F75EFB151C062F007C9BA3 /* RegExpCachedResult.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RegExpCachedResult.cpp; sourceTree = "<group>"; };
86F75EFC151C062F007C9BA3 /* RegExpCachedResult.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RegExpCachedResult.h; sourceTree = "<group>"; };
86F75EFD151C062F007C9BA3 /* RegExpMatchesArray.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RegExpMatchesArray.cpp; sourceTree = "<group>"; };
- 86FA9E8F142BBB2D001773B7 /* JSBoundFunction.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSBoundFunction.cpp; sourceTree = "<group>"; };
- 86FA9E90142BBB2E001773B7 /* JSBoundFunction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSBoundFunction.h; sourceTree = "<group>"; };
90213E3B123A40C200D422F3 /* MemoryStatistics.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MemoryStatistics.cpp; sourceTree = "<group>"; };
90213E3C123A40C200D422F3 /* MemoryStatistics.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MemoryStatistics.h; sourceTree = "<group>"; };
93052C320FB792190048FDC3 /* ParserArena.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ParserArena.cpp; sourceTree = "<group>"; };
0F2B66BC17B6B5AB00A7AE3F /* JSArrayBufferViewInlines.h */,
A7BDAEC417F4EA1400F6140C /* JSArrayIterator.cpp */,
A7BDAEC517F4EA1400F6140C /* JSArrayIterator.h */,
- 86FA9E8F142BBB2D001773B7 /* JSBoundFunction.cpp */,
- 86FA9E90142BBB2E001773B7 /* JSBoundFunction.h */,
BC7F8FBA0E19D1EF008632C0 /* JSCell.cpp */,
BC1167D80E19BCC9008066DD /* JSCell.h */,
0F97496F1687ADE200A4FF6A /* JSCellInlines.h */,
A7BDAECB17F4EA1400F6140C /* JSArrayIterator.h in Headers */,
BC18C4180E16F5CD00B34460 /* JSBase.h in Headers */,
140D17D70E8AD4A9000CD17D /* JSBasePrivate.h in Headers */,
- 86FA9E92142BBB2E001773B7 /* JSBoundFunction.h in Headers */,
BC18C4190E16F5CD00B34460 /* JSCallbackConstructor.h in Headers */,
BC18C41A0E16F5CD00B34460 /* JSCallbackFunction.h in Headers */,
BC18C41B0E16F5CD00B34460 /* JSCallbackObject.h in Headers */,
0F2B66E817B6B5AB00A7AE3F /* JSArrayBufferView.cpp in Sources */,
A7BDAECA17F4EA1400F6140C /* JSArrayIterator.cpp in Sources */,
1421359B0A677F4F00A8195E /* JSBase.cpp in Sources */,
- 86FA9E91142BBB2E001773B7 /* JSBoundFunction.cpp in Sources */,
1440F8AF0A508D200005F061 /* JSCallbackConstructor.cpp in Sources */,
1440F8920A508B100005F061 /* JSCallbackFunction.cpp in Sources */,
14ABDF600A437FEF00ECCA01 /* JSCallbackObject.cpp in Sources */,
{
JSTextPosition positionBeforeLastNewline;
ParserError error;
- RefPtr<ProgramNode> program = parse<ProgramNode>(&m_vm, source, 0, Identifier(), JSParseBuiltin, JSParseProgramCode, error, &positionBeforeLastNewline);
+ RefPtr<ProgramNode> program = parse<ProgramNode>(&m_vm, source, 0, Identifier(), JSParseBuiltin, JSParseProgramCode, JSNotFunctionKind, error, &positionBeforeLastNewline);
if (!program) {
dataLog("Fatal error compiling builtin function '", name.string(), "': ", error.m_message);
RELEASE_ASSERT(body);
for (const auto& closedVariable : program->closedVariables()) {
if (closedVariable == m_vm.propertyNames->arguments.impl())
- continue;
+ continue;
if (closedVariable == m_vm.propertyNames->undefinedKeyword.impl())
continue;
"use strict";
return this.@apply(thisValue, argumentValues);
}
+
+function bind(thisValue /*, optional arguments */)
+{
+ "use strict";
+ var boundFunction = this;
+ if (typeof boundFunction !== "function")
+ throw new @TypeError("Cannot bind non-function object.");
+ var bindingFunction;
+ var oversizedCall = undefined;
+ if (arguments.length <= 1) {
+ bindingFunction = function () {
+ if (@IsConstructor)
+ return new boundFunction(...arguments);
+ return boundFunction.@apply(thisValue, arguments);
+ }
+ } else {
+ var length = arguments.length;
+ switch (length - 1 /* skip thisValue */) {
+ case 1: {
+ var boundParameter = arguments[1];
+ bindingFunction = function () {
+ var argumentLength = arguments.length;
+ if (!argumentLength) {
+ if (@IsConstructor)
+ return new boundFunction(boundParameter);
+ return boundFunction.@call(thisValue, boundParameter);
+ }
+ if (argumentLength == 1) {
+ if (@IsConstructor)
+ return new boundFunction(boundParameter, arguments[0]);
+ return boundFunction.@call(thisValue, boundParameter, arguments[0]);
+ }
+ if (argumentLength == 2) {
+ if (@IsConstructor)
+ return new boundFunction(boundParameter, arguments[0], arguments[1]);
+ return boundFunction.@call(thisValue, boundParameter, arguments[0], arguments[1]);
+ }
+ if (argumentLength == 3) {
+ if (@IsConstructor)
+ return new boundFunction(boundParameter, arguments[0], arguments[1], arguments[2]);
+ return boundFunction.@call(thisValue, boundParameter, arguments[0], arguments[1], arguments[2]);
+ }
+ var completeArguments = [boundParameter, ...arguments];
+ if (!oversizedCall) {
+ oversizedCall = function (isConstruct, boundFunction, thisValue, completeArguments) {
+ if (isConstruct)
+ return new boundFunction(...completeArguments);
+ return boundFunction.@apply(thisValue, completeArguments);
+ }
+ }
+ return oversizedCall(@IsConstructor, boundFunction, thisValue, completeArguments);
+ }
+ break;
+ }
+ case 2: {
+ var boundParameter1 = arguments[1];
+ var boundParameter2 = arguments[2];
+ bindingFunction = function () {
+ if (!arguments.length) {
+ if (@IsConstructor)
+ return new boundFunction(boundParameter1, boundParameter2);
+ return boundFunction.@call(thisValue, boundParameter1, boundParameter2);
+ }
+ if (arguments.length == 1) {
+ if (@IsConstructor)
+ return new boundFunction(boundParameter1, boundParameter2, arguments[0]);
+ return boundFunction.@call(thisValue, boundParameter1, boundParameter2, arguments[0]);
+ }
+ if (arguments.length == 2) {
+ if (@IsConstructor)
+ return new boundFunction(boundParameter1, boundParameter2, arguments[0], arguments[1]);
+ return boundFunction.@call(thisValue, boundParameter1, boundParameter2, arguments[0], arguments[1]);
+ }
+ if (arguments.length == 3) {
+ if (@IsConstructor)
+ return new boundFunction(boundParameter1, boundParameter2, arguments[0], arguments[1], arguments[2]);
+ return boundFunction.@call(thisValue, boundParameter1, boundParameter2, arguments[0], arguments[1], arguments[2]);
+ }
+ var completeArguments = [boundParameter1, boundParameter2, ...arguments];
+ if (!oversizedCall) {
+ oversizedCall = function (isConstruct, boundFunction, thisValue, completeArguments) {
+ if (isConstruct)
+ return new boundFunction(...completeArguments);
+ return boundFunction.@apply(thisValue, completeArguments);
+ }
+ }
+ return oversizedCall(@IsConstructor, boundFunction, thisValue, completeArguments);
+ }
+ break;
+ }
+ case 3: {
+ var boundParameter1 = arguments[1];
+ var boundParameter2 = arguments[2];
+ var boundParameter3 = arguments[3];
+ bindingFunction = function () {
+ if (!arguments.length) {
+ if (@IsConstructor)
+ return new boundFunction(boundParameter1, boundParameter2, boundParameter3);
+ return boundFunction.@call(thisValue, boundParameter1, boundParameter2, boundParameter3);
+ }
+ if (arguments.length == 1) {
+ if (@IsConstructor)
+ return new boundFunction(boundParameter1, boundParameter2, boundParameter3, arguments[0]);
+ return boundFunction.@call(thisValue, boundParameter1, boundParameter2, boundParameter3, arguments[0]);
+ }
+ if (arguments.length == 2) {
+ if (@IsConstructor)
+ return new boundFunction(boundParameter1, boundParameter2, boundParameter3, arguments[0], arguments[1]);
+ return boundFunction.@call(thisValue, boundParameter1, boundParameter2, boundParameter3, arguments[0], arguments[1]);
+ }
+ if (arguments.length == 3) {
+ if (@IsConstructor)
+ return new boundFunction(boundParameter1, boundParameter2, boundParameter3, arguments[0], arguments[1], arguments[2]);
+ return boundFunction.@call(thisValue, boundParameter1, boundParameter2, boundParameter3, arguments[0], arguments[1], arguments[2]);
+ }
+ var completeArguments = [boundParameter1, boundParameter2, boundParameter3, ...arguments];
+ if (!oversizedCall) {
+ oversizedCall = function (isConstruct, boundFunction, thisValue, completeArguments) {
+ if (isConstruct)
+ return new boundFunction(...completeArguments);
+ return boundFunction.@apply(thisValue, completeArguments);
+ }
+ }
+ return oversizedCall(@IsConstructor, boundFunction, thisValue, completeArguments);
+ }
+ break;
+ }
+ default:
+ var boundParameters = [];
+ for (var i = 1; i < length; i++)
+ boundParameters[i - 1] = arguments[i];
+
+ bindingFunction = function () {
+ if (!arguments.length) {
+ if (@IsConstructor)
+ return new boundFunction(...boundParameters);
+ return boundFunction.@apply(thisValue, boundParameters);
+ }
+
+ var completeArguments = [];
+ var localBoundParameters = boundParameters;
+ var boundLength = localBoundParameters.length;
+ for (var i = 0; i < boundLength; i++)
+ completeArguments[i] = localBoundParameters[i];
+ for (var i = 0; i < arguments.length; i++)
+ completeArguments[i + boundLength] = arguments[i];
+ if (@IsConstructor)
+ return new boundFunction(...completeArguments);
+ else
+ return boundFunction.@apply(thisValue, completeArguments);
+ }
+ }
+ }
+ bindingFunction.@boundFunctionName = this.name;
+ bindingFunction.@boundFunction = boundFunction.@boundFunction || boundFunction;
+ var boundLength = boundFunction.length - (arguments.length - 1);
+ if (boundLength < 0)
+ boundLength = 0;
+ bindingFunction.@boundFunctionLength = boundLength;
+ @SetTypeErrorAccessor(bindingFunction, "arguments");
+ @SetTypeErrorAccessor(bindingFunction, "caller");
+ return bindingFunction;
+}
static UnlinkedFunctionCodeBlock* generateFunctionCodeBlock(VM& vm, UnlinkedFunctionExecutable* executable, const SourceCode& source, CodeSpecializationKind kind, DebuggerMode debuggerMode, ProfilerMode profilerMode, UnlinkedFunctionKind functionKind, ParserError& error)
{
- RefPtr<FunctionBodyNode> body = parse<FunctionBodyNode>(&vm, source, executable->parameters(), executable->name(), executable->toStrictness(), JSParseFunctionCode, error);
+ RefPtr<FunctionBodyNode> body = parse<FunctionBodyNode>(&vm, source, executable->parameters(), executable->name(), executable->toStrictness(), JSParseFunctionCode, kind == CodeForConstruct ? JSFunctionIsConstructorKind : JSFunctionIsFunctionKind, error);
if (!body) {
ASSERT(error.m_type != ParserError::ErrorNone);
generator.emitCheckHasInstance(dstReg.get(), src1.get(), src2.get(), target.get());
generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
- generator.emitGetById(prototype.get(), src2.get(), generator.vm()->propertyNames->prototype);
+ generator.emitGetById(prototype.get(), src2.get(), generator.vm()->propertyNames->prototypeForHasInstancePrivateName);
generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
RegisterID* result = generator.emitInstanceOf(dstReg.get(), src1.get(), prototype.get());
void IfElseNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
{
generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
-
+ bool constantBranch = false;
+ if (m_condition->getBooleanConstant(constantBranch)) {
+ if (constantBranch)
+ generator.emitNode(dst, m_ifBlock);
+ else if (m_elseBlock)
+ generator.emitNode(dst, m_elseBlock);
+ return;
+ }
RefPtr<Label> beforeThen = generator.newLabel();
RefPtr<Label> beforeElse = generator.newLabel();
RefPtr<Label> afterElse = generator.newLabel();
#include "GetterSetter.h"
#include "JSActivation.h"
#include "JSArray.h"
-#include "JSBoundFunction.h"
#include "JSNameScope.h"
#include "JSNotAnObject.h"
#include "JSPropertyNameIterator.h"
};
template <typename T>
-Lexer<T>::Lexer(VM* vm, JSParserStrictness strictness)
+Lexer<T>::Lexer(VM* vm, JSParserStrictness strictness, JSFunctionKind functionKind)
: m_isReparsing(false)
, m_vm(vm)
, m_parsingBuiltinFunction(strictness == JSParseBuiltin)
+ , m_functionKind(functionKind)
{
}
ident = m_vm->propertyNames->getPrivateName(*ident);
else if (*ident == m_vm->propertyNames->undefinedKeyword)
tokenData->ident = &m_vm->propertyNames->undefinedPrivateName;
+
if (!ident)
return INVALID_PRIVATE_NAME_ERRORTOK;
+
+ if (*ident == m_vm->propertyNames->IsConstructorPrivateName)
+ return m_functionKind == JSFunctionIsConstructorKind ? TRUETOKEN : FALSETOKEN;
+
}
tokenData->ident = ident;
} else
ident = m_vm->propertyNames->getPrivateName(*ident);
else if (*ident == m_vm->propertyNames->undefinedKeyword)
tokenData->ident = &m_vm->propertyNames->undefinedPrivateName;
+ if (m_functionKind == JSFunctionIsConstructorKind) {
+ if (*ident == m_vm->propertyNames->IsConstructorPrivateName)
+ return TRUETOKEN;
+ return FALSETOKEN;
+ }
if (!ident)
return INVALID_PRIVATE_NAME_ERRORTOK;
}
WTF_MAKE_FAST_ALLOCATED;
public:
- Lexer(VM*, JSParserStrictness);
+ Lexer(VM*, JSParserStrictness, JSFunctionKind);
~Lexer();
// Character manipulation functions.
VM* m_vm;
bool m_parsingBuiltinFunction;
+ JSFunctionKind m_functionKind;
};
template <>
virtual bool isSubtract() const { return false; }
virtual bool isBoolean() const { return false; }
virtual bool isSpreadExpression() const { return false; }
+ virtual bool getBooleanConstant(bool&) const { return false; }
virtual void emitBytecodeInConditionContext(BytecodeGenerator&, Label*, Label*, FallThroughMode);
NullNode(const JSTokenLocation&);
private:
+
+ bool getBooleanConstant(bool& value) const override
+ {
+ value = false;
+ return true;
+ }
+
virtual bool isNull() const override { return true; }
virtual JSValue jsValue(BytecodeGenerator&) const override { return jsNull(); }
};
public:
BooleanNode(const JSTokenLocation&, bool value);
bool value() { return m_value; }
-
+
private:
+ bool getBooleanConstant(bool& value) const override
+ {
+ value = m_value;
+ return true;
+ }
+
virtual bool isBoolean() const override { return true; }
virtual JSValue jsValue(BytecodeGenerator&) const override { return jsBoolean(m_value); }
void setValue(double value) { m_value = value; }
private:
+ bool getBooleanConstant(bool& value) const override
+ {
+ value = (bool)m_value;
+ return true;
+ }
virtual bool isNumber() const override { return true; }
virtual JSValue jsValue(BytecodeGenerator&) const override { return jsNumber(m_value); }
}
template <typename LexerType>
-Parser<LexerType>::Parser(VM* vm, const SourceCode& source, FunctionParameters* parameters, const Identifier& name, JSParserStrictness strictness, JSParserMode parserMode)
+Parser<LexerType>::Parser(VM* vm, const SourceCode& source, FunctionParameters* parameters, const Identifier& name, JSParserStrictness strictness, JSParserMode parserMode, JSFunctionKind functionKind)
: m_vm(vm)
, m_source(&source)
, m_hasStackOverflow(false)
, m_sourceElements(0)
, m_parsingBuiltin(strictness == JSParseBuiltin)
{
- m_lexer = adoptPtr(new LexerType(vm, strictness));
+ m_lexer = adoptPtr(new LexerType(vm, strictness, functionKind));
m_arena = m_vm->parserArena.get();
m_lexer->setCode(source, m_arena);
m_token.m_location.line = source.firstLine();
Vector<RefPtr<StringImpl>> closedVariables;
if (m_parsingBuiltin) {
- RELEASE_ASSERT(!capturedVariables.size());
IdentifierSet usedVariables;
scope->getUsedVariables(usedVariables);
for (const auto& variable : usedVariables) {
continue;
closedVariables.append(variable);
}
+ if (!capturedVariables.isEmpty()) {
+ for (const auto& capturedVariable : capturedVariables) {
+ if (scope->hasDeclaredVariable(Identifier(m_vm, capturedVariable.get())))
+ continue;
+
+ if (scope->hasDeclaredParameter(Identifier(m_vm, capturedVariable.get())))
+ continue;
+ RELEASE_ASSERT_NOT_REACHED();
+ }
+ }
}
didFinishParsing(sourceElements, context.varDeclarations(), context.funcDeclarations(), features,
context.numConstants(), capturedVariables, std::move(closedVariables));
WTF_MAKE_FAST_ALLOCATED;
public:
- Parser(VM*, const SourceCode&, FunctionParameters*, const Identifier&, JSParserStrictness, JSParserMode);
+ Parser(VM*, const SourceCode&, FunctionParameters*, const Identifier&, JSParserStrictness, JSParserMode, JSFunctionKind);
~Parser();
template <class ParsedNode>
}
template <class ParsedNode>
-PassRefPtr<ParsedNode> parse(VM* vm, const SourceCode& source, FunctionParameters* parameters, const Identifier& name, JSParserStrictness strictness, JSParserMode parserMode, ParserError& error, JSTextPosition* positionBeforeLastNewline = 0)
+PassRefPtr<ParsedNode> parse(VM* vm, const SourceCode& source, FunctionParameters* parameters, const Identifier& name, JSParserStrictness strictness, JSParserMode parserMode, JSFunctionKind functionKind, ParserError& error, JSTextPosition* positionBeforeLastNewline = 0)
{
SamplingRegion samplingRegion("Parsing");
ASSERT(!source.provider()->source().isNull());
if (source.provider()->source().is8Bit()) {
- Parser<Lexer<LChar>> parser(vm, source, parameters, name, strictness, parserMode);
+ Parser<Lexer<LChar>> parser(vm, source, parameters, name, strictness, parserMode, functionKind);
RefPtr<ParsedNode> result = parser.parse<ParsedNode>(error);
if (positionBeforeLastNewline)
*positionBeforeLastNewline = parser.positionBeforeLastNewline();
}
return result.release();
}
- Parser<Lexer<UChar>> parser(vm, source, parameters, name, strictness, parserMode);
+ Parser<Lexer<UChar>> parser(vm, source, parameters, name, strictness, parserMode, functionKind);
RefPtr<ParsedNode> result = parser.parse<ParsedNode>(error);
if (positionBeforeLastNewline)
*positionBeforeLastNewline = parser.positionBeforeLastNewline();
enum JSParserStrictness { JSParseNormal, JSParseBuiltin, JSParseStrict };
enum JSParserMode { JSParseProgramCode, JSParseFunctionCode };
-
+enum JSFunctionKind { JSNotFunctionKind, JSFunctionIsFunctionKind, JSFunctionIsConstructorKind };
+
enum ProfilerMode { ProfilerOff, ProfilerOn };
enum DebuggerMode { DebuggerOff, DebuggerOn };
void ArgumentsIteratorConstructor::finishCreation(VM& vm, ArgumentsIteratorPrototype* prototype)
{
Base::finishCreation(vm);
- putDirectWithoutTransition(vm, vm.propertyNames->prototype, prototype, DontEnum | DontDelete | ReadOnly);
+ putDirectPrototypePropertyWithoutTransitions(vm, prototype, DontEnum | DontDelete | ReadOnly);
}
}
void ArrayConstructor::finishCreation(VM& vm, ArrayPrototype* arrayPrototype)
{
Base::finishCreation(vm, arrayPrototype->classInfo()->className);
- putDirectWithoutTransition(vm, vm.propertyNames->prototype, arrayPrototype, DontEnum | DontDelete | ReadOnly);
+ putDirectPrototypePropertyWithoutTransitions(vm, arrayPrototype, DontEnum | DontDelete | ReadOnly);
putDirectWithoutTransition(vm, vm.propertyNames->length, jsNumber(1), ReadOnly | DontEnum | DontDelete);
}
void BooleanConstructor::finishCreation(VM& vm, BooleanPrototype* booleanPrototype)
{
Base::finishCreation(vm, booleanPrototype->classInfo()->className);
- putDirectWithoutTransition(vm, vm.propertyNames->prototype, booleanPrototype, DontEnum | DontDelete | ReadOnly);
+ putDirectPrototypePropertyWithoutTransitions(vm, booleanPrototype, DontEnum | DontDelete | ReadOnly);
// no. of arguments for constructor
putDirectWithoutTransition(vm, vm.propertyNames->length, jsNumber(1), ReadOnly | DontDelete | DontEnum);
}
typedef typename CacheTypes<UnlinkedCodeBlockType>::RootNode RootNode;
- RefPtr<RootNode> rootNode = parse<RootNode>(&vm, source, 0, Identifier(), strictness, JSParseProgramCode, error);
+ RefPtr<RootNode> rootNode = parse<RootNode>(&vm, source, 0, Identifier(), strictness, JSParseProgramCode, JSNotFunctionKind, error);
if (!rootNode) {
m_sourceCode.remove(addResult.iterator);
return 0;
return jsCast<UnlinkedFunctionExecutable*>(addResult.iterator->value.cell.get());
JSTextPosition positionBeforeLastNewline;
- RefPtr<ProgramNode> program = parse<ProgramNode>(&vm, source, 0, Identifier(), JSParseNormal, JSParseProgramCode, error, &positionBeforeLastNewline);
+ RefPtr<ProgramNode> program = parse<ProgramNode>(&vm, source, 0, Identifier(), JSParseNormal, JSParseProgramCode, JSNotFunctionKind, error, &positionBeforeLastNewline);
if (!program) {
RELEASE_ASSERT(error.m_type != ParserError::ErrorNone);
m_sourceCode.remove(addResult.iterator);
macro(Object) \
macro(TypeError) \
macro(undefined) \
- macro(BuiltinLog)
+ macro(BuiltinLog) \
+ macro(IsConstructor) \
+ macro(boundFunctionName) \
+ macro(boundFunctionParameters) \
+ macro(boundFunction) \
+ macro(boundFunctionLength) \
+ macro(prototypeForHasInstance) \
+ macro(SetTypeErrorAccessor)
namespace JSC {
{
JSLockHolder lock(vm);
RELEASE_ASSERT(vm.atomicStringTable() == wtfThreadData().atomicStringTable());
- RefPtr<ProgramNode> programNode = parse<ProgramNode>(&vm, source, 0, Identifier(), JSParseNormal, JSParseProgramCode, error);
+ RefPtr<ProgramNode> programNode = parse<ProgramNode>(&vm, source, 0, Identifier(), JSParseNormal, JSParseProgramCode, JSNotFunctionKind, error);
return programNode;
}
void DateConstructor::finishCreation(VM& vm, DatePrototype* datePrototype)
{
Base::finishCreation(vm, datePrototype->classInfo()->className);
- putDirectWithoutTransition(vm, vm.propertyNames->prototype, datePrototype, DontEnum | DontDelete | ReadOnly);
+ putDirectPrototypePropertyWithoutTransitions(vm, datePrototype, DontEnum | DontDelete | ReadOnly);
putDirectWithoutTransition(vm, vm.propertyNames->length, jsNumber(7), ReadOnly | DontEnum | DontDelete);
}
{
Base::finishCreation(vm, errorPrototype->classInfo()->className);
// ECMA 15.11.3.1 Error.prototype
- putDirectWithoutTransition(vm, vm.propertyNames->prototype, errorPrototype, DontEnum | DontDelete | ReadOnly);
+ putDirectPrototypePropertyWithoutTransitions(vm, errorPrototype, DontEnum | DontDelete | ReadOnly);
putDirectWithoutTransition(vm, vm.propertyNames->length, jsNumber(1), DontDelete | ReadOnly | DontEnum);
}
ParserError error;
VM* vm = &exec->vm();
JSGlobalObject* lexicalGlobalObject = exec->lexicalGlobalObject();
- RefPtr<ProgramNode> programNode = parse<ProgramNode>(vm, m_source, 0, Identifier(), JSParseNormal, ProgramNode::isFunctionNode ? JSParseFunctionCode : JSParseProgramCode, error);
+ RefPtr<ProgramNode> programNode = parse<ProgramNode>(vm, m_source, 0, Identifier(), JSParseNormal, ProgramNode::isFunctionNode ? JSParseFunctionCode : JSParseProgramCode, JSNotFunctionKind, error);
if (programNode)
return 0;
ASSERT(error.m_type != ParserError::ErrorNone);
void FunctionConstructor::finishCreation(VM& vm, FunctionPrototype* functionPrototype)
{
Base::finishCreation(vm, functionPrototype->classInfo()->className);
- putDirectWithoutTransition(vm, vm.propertyNames->prototype, functionPrototype, DontEnum | DontDelete | ReadOnly);
+ putDirectPrototypePropertyWithoutTransitions(vm, functionPrototype, DontEnum | DontDelete | ReadOnly);
// Number of arguments for constructor
putDirectWithoutTransition(vm, vm.propertyNames->length, jsNumber(1), ReadOnly | DontDelete | DontEnum);
#include "BuiltinExecutables.h"
#include "BuiltinNames.h"
#include "JSArray.h"
-#include "JSBoundFunction.h"
#include "JSFunction.h"
#include "JSString.h"
#include "JSStringBuilder.h"
const ClassInfo FunctionPrototype::s_info = { "Function", &Base::s_info, 0, 0, CREATE_METHOD_TABLE(FunctionPrototype) };
static EncodedJSValue JSC_HOST_CALL functionProtoFuncToString(ExecState*);
-static EncodedJSValue JSC_HOST_CALL functionProtoFuncBind(ExecState*);
FunctionPrototype::FunctionPrototype(VM& vm, Structure* structure)
: InternalFunction(vm, structure)
*applyFunction = putDirectBuiltinFunctionWithoutTransition(vm, globalObject, vm.propertyNames->builtinNames().applyPublicName(), functionPrototypeApplyCodeGenerator(vm), DontEnum);
*callFunction = putDirectBuiltinFunctionWithoutTransition(vm, globalObject, vm.propertyNames->builtinNames().callPublicName(), functionPrototypeCallCodeGenerator(vm), DontEnum);
-
- JSFunction* bindFunction = JSFunction::create(vm, globalObject, 1, vm.propertyNames->bind.string(), functionProtoFuncBind);
- putDirectWithoutTransition(vm, vm.propertyNames->bind, bindFunction, DontEnum);
+
+ putDirectBuiltinFunctionWithoutTransition(vm, globalObject, vm.propertyNames->builtinNames().bindPublicName(), functionPrototypeBindCodeGenerator(vm), DontEnum);
}
static EncodedJSValue JSC_HOST_CALL callFunctionPrototype(ExecState*)
return throwVMTypeError(exec);
}
-// 15.3.4.5 Function.prototype.bind (thisArg [, arg1 [, arg2, ...]])
-EncodedJSValue JSC_HOST_CALL functionProtoFuncBind(ExecState* exec)
-{
- JSGlobalObject* globalObject = exec->callee()->globalObject();
-
- // Let Target be the this value.
- JSValue target = exec->thisValue();
-
- // If IsCallable(Target) is false, throw a TypeError exception.
- CallData callData;
- CallType callType = getCallData(target, callData);
- if (callType == CallTypeNone)
- return throwVMTypeError(exec);
- // Primitive values are not callable.
- ASSERT(target.isObject());
- JSObject* targetObject = asObject(target);
- VM& vm = exec->vm();
-
- // Let A be a new (possibly empty) internal list of all of the argument values provided after thisArg (arg1, arg2 etc), in order.
- size_t numBoundArgs = exec->argumentCount() > 1 ? exec->argumentCount() - 1 : 0;
- JSArray* boundArgs = JSArray::tryCreateUninitialized(vm, globalObject->arrayStructureForIndexingTypeDuringAllocation(ArrayWithUndecided), numBoundArgs);
- if (!boundArgs)
- return JSValue::encode(throwOutOfMemoryError(exec));
-
- for (size_t i = 0; i < numBoundArgs; ++i)
- boundArgs->initializeIndex(vm, i, exec->argument(i + 1));
-
- // If the [[Class]] internal property of Target is "Function", then ...
- // Else set the length own property of F to 0.
- unsigned length = 0;
- if (targetObject->inherits(JSFunction::info())) {
- ASSERT(target.get(exec, exec->propertyNames().length).isNumber());
- // a. Let L be the length property of Target minus the length of A.
- // b. Set the length own property of F to either 0 or L, whichever is larger.
- unsigned targetLength = (unsigned)target.get(exec, exec->propertyNames().length).asNumber();
- if (targetLength > numBoundArgs)
- length = targetLength - numBoundArgs;
- }
-
- JSString* name = target.get(exec, exec->propertyNames().name).toString(exec);
- return JSValue::encode(JSBoundFunction::create(vm, globalObject, targetObject, exec->argument(0), boundArgs, length, name->value(exec)));
-}
-
} // namespace JSC
void JSArrayBufferConstructor::finishCreation(VM& vm, JSArrayBufferPrototype* prototype)
{
Base::finishCreation(vm, "ArrayBuffer");
- putDirectWithoutTransition(vm, vm.propertyNames->prototype, prototype, DontEnum | DontDelete | ReadOnly);
+ putDirectPrototypePropertyWithoutTransitions(vm, prototype, DontEnum | DontDelete | ReadOnly);
putDirectWithoutTransition(vm, vm.propertyNames->length, jsNumber(1), DontEnum | DontDelete | ReadOnly);
JSGlobalObject* globalObject = this->globalObject();
+++ /dev/null
-/*
- * Copyright (C) 2011 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-#include "JSBoundFunction.h"
-
-#include "GetterSetter.h"
-#include "JSGlobalObject.h"
-#include "JSCInlines.h"
-
-namespace JSC {
-
-const ClassInfo JSBoundFunction::s_info = { "Function", &Base::s_info, 0, 0, CREATE_METHOD_TABLE(JSBoundFunction) };
-
-EncodedJSValue JSC_HOST_CALL boundFunctionCall(ExecState* exec)
-{
- JSBoundFunction* boundFunction = jsCast<JSBoundFunction*>(exec->callee());
-
- ASSERT(isJSArray(boundFunction->boundArgs())); // Currently this is true!
- JSArray* boundArgs = asArray(boundFunction->boundArgs());
-
- MarkedArgumentBuffer args;
- for (unsigned i = 0; i < boundArgs->length(); ++i)
- args.append(boundArgs->getIndexQuickly(i));
- for (unsigned i = 0; i < exec->argumentCount(); ++i)
- args.append(exec->uncheckedArgument(i));
-
- JSObject* targetFunction = boundFunction->targetFunction();
- CallData callData;
- CallType callType = getCallData(targetFunction, callData);
- ASSERT(callType != CallTypeNone);
- return JSValue::encode(call(exec, targetFunction, callType, callData, boundFunction->boundThis(), args));
-}
-
-EncodedJSValue JSC_HOST_CALL boundFunctionConstruct(ExecState* exec)
-{
- JSBoundFunction* boundFunction = jsCast<JSBoundFunction*>(exec->callee());
-
- ASSERT(isJSArray(boundFunction->boundArgs())); // Currently this is true!
- JSArray* boundArgs = asArray(boundFunction->boundArgs());
-
- MarkedArgumentBuffer args;
- for (unsigned i = 0; i < boundArgs->length(); ++i)
- args.append(boundArgs->getIndexQuickly(i));
- for (unsigned i = 0; i < exec->argumentCount(); ++i)
- args.append(exec->uncheckedArgument(i));
-
- JSObject* targetFunction = boundFunction->targetFunction();
- ConstructData constructData;
- ConstructType constructType = getConstructData(targetFunction, constructData);
- ASSERT(constructType != ConstructTypeNone);
- return JSValue::encode(construct(exec, targetFunction, constructType, constructData, args));
-}
-
-JSBoundFunction* JSBoundFunction::create(VM& vm, JSGlobalObject* globalObject, JSObject* targetFunction, JSValue boundThis, JSValue boundArgs, int length, const String& name)
-{
- ConstructData constructData;
- ConstructType constructType = JSC::getConstructData(targetFunction, constructData);
- bool canConstruct = constructType != ConstructTypeNone;
- NativeExecutable* executable = vm.getHostFunction(boundFunctionCall, canConstruct ? boundFunctionConstruct : callHostFunctionAsConstructor);
- JSBoundFunction* function = new (NotNull, allocateCell<JSBoundFunction>(vm.heap)) JSBoundFunction(vm, globalObject, globalObject->boundFunctionStructure(), targetFunction, boundThis, boundArgs);
-
- function->finishCreation(vm, executable, length, name);
- return function;
-}
-
-void JSBoundFunction::destroy(JSCell* cell)
-{
- static_cast<JSBoundFunction*>(cell)->JSBoundFunction::~JSBoundFunction();
-}
-
-bool JSBoundFunction::customHasInstance(JSObject* object, ExecState* exec, JSValue value)
-{
- return jsCast<JSBoundFunction*>(object)->m_targetFunction->hasInstance(exec, value);
-}
-
-JSBoundFunction::JSBoundFunction(VM& vm, JSGlobalObject* globalObject, Structure* structure, JSObject* targetFunction, JSValue boundThis, JSValue boundArgs)
- : Base(vm, globalObject, structure)
- , m_targetFunction(vm, this, targetFunction)
- , m_boundThis(vm, this, boundThis)
- , m_boundArgs(vm, this, boundArgs)
-{
-}
-
-void JSBoundFunction::finishCreation(VM& vm, NativeExecutable* executable, int length, const String& name)
-{
- Base::finishCreation(vm, executable, length, name);
- ASSERT(inherits(info()));
-
- putDirectNonIndexAccessor(vm, vm.propertyNames->arguments, globalObject()->throwTypeErrorGetterSetter(vm), DontDelete | DontEnum | Accessor);
- putDirectNonIndexAccessor(vm, vm.propertyNames->caller, globalObject()->throwTypeErrorGetterSetter(vm), DontDelete | DontEnum | Accessor);
-}
-
-void JSBoundFunction::visitChildren(JSCell* cell, SlotVisitor& visitor)
-{
- JSBoundFunction* thisObject = jsCast<JSBoundFunction*>(cell);
- ASSERT_GC_OBJECT_INHERITS(thisObject, info());
- COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
- ASSERT(thisObject->structure()->typeInfo().overridesVisitChildren());
- Base::visitChildren(thisObject, visitor);
-
- visitor.append(&thisObject->m_targetFunction);
- visitor.append(&thisObject->m_boundThis);
- visitor.append(&thisObject->m_boundArgs);
-}
-
-} // namespace JSC
+++ /dev/null
-/*
- * Copyright (C) 2011 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef JSBoundFunction_h
-#define JSBoundFunction_h
-
-#include "JSFunction.h"
-
-namespace JSC {
-
-EncodedJSValue JSC_HOST_CALL boundFunctionCall(ExecState*);
-EncodedJSValue JSC_HOST_CALL boundFunctionConstruct(ExecState*);
-
-class JSBoundFunction : public JSFunction {
-public:
- typedef JSFunction Base;
-
- static JSBoundFunction* create(VM&, JSGlobalObject*, JSObject* targetFunction, JSValue boundThis, JSValue boundArgs, int, const String&);
-
- static void destroy(JSCell*);
-
- static bool customHasInstance(JSObject*, ExecState*, JSValue);
-
- JSObject* targetFunction() { return m_targetFunction.get(); }
- JSValue boundThis() { return m_boundThis.get(); }
- JSValue boundArgs() { return m_boundArgs.get(); }
-
- static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
- {
- ASSERT(globalObject);
- return Structure::create(vm, globalObject, prototype, TypeInfo(JSFunctionType, StructureFlags), info());
- }
-
- DECLARE_INFO;
-
-protected:
- const static unsigned StructureFlags = OverridesHasInstance | OverridesVisitChildren | Base::StructureFlags;
-
- static void visitChildren(JSCell*, SlotVisitor&);
-
-private:
- JSBoundFunction(VM&, JSGlobalObject*, Structure*, JSObject* targetFunction, JSValue boundThis, JSValue boundArgs);
-
- void finishCreation(VM&, NativeExecutable*, int, const String&);
-
- WriteBarrier<JSObject> m_targetFunction;
- WriteBarrier<Unknown> m_boundThis;
- WriteBarrier<Unknown> m_boundArgs;
-};
-
-} // namespace JSC
-
-#endif // JSFunction_h
#include "FunctionPrototype.h"
#include "GetterSetter.h"
#include "JSArray.h"
-#include "JSBoundFunction.h"
#include "JSFunctionInlines.h"
#include "JSGlobalObject.h"
#include "JSNameScope.h"
class RetrieveCallerFunctionFunctor {
public:
- RetrieveCallerFunctionFunctor(JSFunction* functionObj)
- : m_targetCallee(jsDynamicCast<JSObject*>(functionObj))
+ RetrieveCallerFunctionFunctor(ExecState* exec, JSFunction* functionObj)
+ : m_exec(exec)
+ , m_targetCallee(jsDynamicCast<JSObject*>(functionObj))
, m_hasFoundFrame(false)
, m_hasSkippedToCallerFrame(false)
, m_result(jsNull())
{
JSObject* callee = visitor->callee();
- if (callee && callee->inherits(JSBoundFunction::info()))
+ if (callee && callee->hasOwnProperty(m_exec, m_exec->propertyNames().boundFunctionNamePrivateName))
return StackVisitor::Continue;
if (!m_hasFoundFrame && (callee != m_targetCallee))
}
private:
+ ExecState* m_exec;
JSObject* m_targetCallee;
bool m_hasFoundFrame;
bool m_hasSkippedToCallerFrame;
static JSValue retrieveCallerFunction(ExecState* exec, JSFunction* functionObj)
{
- RetrieveCallerFunctionFunctor functor(functionObj);
+ RetrieveCallerFunctionFunctor functor(exec, functionObj);
exec->iterate(functor);
return functor.result();
}
bool JSFunction::getOwnPropertySlot(JSObject* object, ExecState* exec, PropertyName propertyName, PropertySlot& slot)
{
JSFunction* thisObject = jsCast<JSFunction*>(object);
- if (thisObject->isHostOrBuiltinFunction())
+ if (thisObject->isHostFunction())
return Base::getOwnPropertySlot(thisObject, exec, propertyName, slot);
-
- if (propertyName == exec->propertyNames().prototype) {
+ if (thisObject->isBuiltinFunction()) {
+ if (propertyName == exec->propertyNames().caller) {
+ if (thisObject->jsExecutable()->isStrictMode()) {
+ bool result = Base::getOwnPropertySlot(thisObject, exec, propertyName, slot);
+ if (!result) {
+ thisObject->putDirectAccessor(exec, propertyName, thisObject->globalObject()->throwTypeErrorGetterSetter(exec->vm()), DontDelete | DontEnum | Accessor);
+ result = Base::getOwnPropertySlot(thisObject, exec, propertyName, slot);
+ ASSERT(result);
+ }
+ return result;
+ }
+ slot.setCacheableCustom(thisObject, ReadOnly | DontEnum | DontDelete, callerGetter);
+ return true;
+ }
+ if (propertyName == exec->propertyNames().prototypeForHasInstancePrivateName) {
+ PropertySlot boundFunctionSlot(thisObject);
+ if (Base::getOwnPropertySlot(thisObject, exec, exec->propertyNames().boundFunctionPrivateName, boundFunctionSlot)) {
+ JSValue boundFunction = boundFunctionSlot.getValue(exec, exec->propertyNames().boundFunctionPrivateName);
+ PropertySlot boundPrototypeSlot(asObject(boundFunction));
+ if (asObject(boundFunction)->getPropertySlot(exec, propertyName, boundPrototypeSlot)) {
+ slot.setValue(boundPrototypeSlot.slotBase(), boundPrototypeSlot.attributes(), boundPrototypeSlot.getValue(exec, propertyName));
+ return true;
+ }
+ }
+ }
+ if (propertyName == exec->propertyNames().name) {
+ PropertySlot nameSlot(thisObject);
+ if (Base::getOwnPropertySlot(thisObject, exec, exec->vm().propertyNames->boundFunctionNamePrivateName, nameSlot)) {
+ slot.setValue(thisObject, DontEnum | DontDelete | ReadOnly, nameSlot.getValue(exec, exec->vm().propertyNames->boundFunctionNamePrivateName));
+ return true;
+ }
+ }
+ if (propertyName == exec->propertyNames().length) {
+ PropertySlot lengthSlot(thisObject);
+ if (Base::getOwnPropertySlot(thisObject, exec, exec->vm().propertyNames->boundFunctionLengthPrivateName, lengthSlot)) {
+ slot.setValue(thisObject, DontEnum | DontDelete | ReadOnly, lengthSlot.getValue(exec, exec->vm().propertyNames->boundFunctionLengthPrivateName));
+ return true;
+ }
+ }
+
+ return Base::getOwnPropertySlot(thisObject, exec, propertyName, slot);
+ }
+
+ if (propertyName == exec->propertyNames().prototype || propertyName == exec->propertyNames().prototypeForHasInstancePrivateName) {
VM& vm = exec->vm();
unsigned attributes;
PropertyOffset offset = thisObject->getDirectOffset(vm, propertyName, attributes);
if (!isValidOffset(offset)) {
JSObject* prototype = constructEmptyObject(exec);
prototype->putDirect(vm, exec->propertyNames().constructor, thisObject, DontEnum);
- thisObject->putDirect(vm, exec->propertyNames().prototype, prototype, DontDelete | DontEnum);
+ thisObject->putDirectPrototypeProperty(vm, prototype, DontDelete | DontEnum);
offset = thisObject->getDirectOffset(vm, exec->propertyNames().prototype, attributes);
ASSERT(isValidOffset(offset));
}
void JSFunction::getOwnNonIndexPropertyNames(JSObject* object, ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode)
{
JSFunction* thisObject = jsCast<JSFunction*>(object);
- if (!thisObject->isHostOrBuiltinFunction() && (mode == IncludeDontEnumProperties)) {
- VM& vm = exec->vm();
- // Make sure prototype has been reified.
- PropertySlot slot(thisObject);
- thisObject->methodTable(vm)->getOwnPropertySlot(thisObject, exec, vm.propertyNames->prototype, slot);
+ if (mode == IncludeDontEnumProperties) {
+ bool shouldIncludeJSFunctionProperties = !thisObject->isHostOrBuiltinFunction();
+ if (!shouldIncludeJSFunctionProperties && thisObject->isBuiltinFunction()) {
+ PropertySlot boundFunctionSlot(thisObject);
+ shouldIncludeJSFunctionProperties = Base::getOwnPropertySlot(thisObject, exec, exec->propertyNames().boundFunctionPrivateName, boundFunctionSlot);
+ }
+ if (shouldIncludeJSFunctionProperties) {
+ VM& vm = exec->vm();
+ // Make sure prototype has been reified.
+ PropertySlot slot(thisObject);
+ thisObject->methodTable(vm)->getOwnPropertySlot(thisObject, exec, vm.propertyNames->prototype, slot);
- propertyNames.add(vm.propertyNames->arguments);
- propertyNames.add(vm.propertyNames->caller);
- propertyNames.add(vm.propertyNames->length);
- propertyNames.add(vm.propertyNames->name);
+ propertyNames.add(vm.propertyNames->arguments);
+ propertyNames.add(vm.propertyNames->caller);
+ propertyNames.add(vm.propertyNames->length);
+ propertyNames.add(vm.propertyNames->name);
+ }
}
Base::getOwnNonIndexPropertyNames(thisObject, exec, propertyNames, mode);
}
thisObject->m_allocationProfile.clear();
thisObject->m_allocationProfileWatchpoint.fireAll();
// Don't allow this to be cached, since a [[Put]] must clear m_allocationProfile.
- PutPropertySlot dontCache(thisObject);
- Base::put(thisObject, exec, propertyName, value, dontCache);
+ PutPropertySlot dontCachePrototype(thisObject);
+ Base::put(thisObject, exec, propertyName, value, dontCachePrototype);
+ PutPropertySlot dontCachePrototypeForHasInstance(thisObject);
+ Base::put(thisObject, exec, exec->propertyNames().prototypeForHasInstancePrivateName, value, dontCachePrototypeForHasInstance);
return;
}
if (thisObject->jsExecutable()->isStrictMode() && (propertyName == exec->propertyNames().arguments || propertyName == exec->propertyNames().caller)) {
thisObject->methodTable(exec->vm())->getOwnPropertySlot(thisObject, exec, propertyName, slot);
thisObject->m_allocationProfile.clear();
thisObject->m_allocationProfileWatchpoint.fireAll();
- return Base::defineOwnProperty(object, exec, propertyName, descriptor, throwException);
+ if (!Base::defineOwnProperty(object, exec, propertyName, descriptor, throwException))
+ return false;
+ Base::defineOwnProperty(object, exec, exec->propertyNames().prototypeForHasInstancePrivateName, descriptor, throwException);
+ return true;
}
bool valueCheck;
void JSGenericTypedArrayViewConstructor<ViewClass>::finishCreation(VM& vm, JSObject* prototype, const String& name)
{
Base::finishCreation(vm, name);
- putDirectWithoutTransition(vm, vm.propertyNames->prototype, prototype, DontEnum | DontDelete | ReadOnly);
+ putDirectPrototypePropertyWithoutTransitions(vm, prototype, DontEnum | DontDelete | ReadOnly);
putDirectWithoutTransition(vm, vm.propertyNames->length, jsNumber(3), DontEnum | DontDelete | ReadOnly);
putDirectWithoutTransition(vm, vm.propertyNames->BYTES_PER_ELEMENT, jsNumber(ViewClass::elementSize), DontEnum | ReadOnly | DontDelete);
}
#include "JSArrayBufferConstructor.h"
#include "JSArrayBufferPrototype.h"
#include "JSArrayIterator.h"
-#include "JSBoundFunction.h"
#include "JSCInlines.h"
#include "JSCallbackConstructor.h"
#include "JSCallbackFunction.h"
m_functionPrototype.set(vm, this, FunctionPrototype::create(vm, FunctionPrototype::createStructure(vm, this, jsNull()))); // The real prototype will be set once ObjectPrototype is created.
m_functionStructure.set(vm, this, JSFunction::createStructure(vm, this, m_functionPrototype.get()));
- m_boundFunctionStructure.set(vm, this, JSBoundFunction::createStructure(vm, this, m_functionPrototype.get()));
m_namedFunctionStructure.set(vm, this, Structure::addPropertyTransition(vm, m_functionStructure.get(), vm.propertyNames->name, DontDelete | ReadOnly | DontEnum, 0, m_functionNameOffset));
m_internalFunctionStructure.set(vm, this, InternalFunction::createStructure(vm, this, m_functionPrototype.get()));
JSFunction* callFunction = 0;
}
JSFunction* builtinLog = JSFunction::create(vm, this, 1, vm.propertyNames->emptyIdentifier.string(), globalFuncBuiltinLog);
+ JSFunction* setTypeErrorAccessor = JSFunction::create(vm, this, 2, vm.propertyNames->emptyIdentifier.string(), globalFuncSetTypeErrorAccessor);
GlobalPropertyInfo staticGlobals[] = {
GlobalPropertyInfo(vm.propertyNames->NaN, jsNaN(), DontEnum | DontDelete | ReadOnly),
GlobalPropertyInfo(vm.propertyNames->Infinity, jsNumber(std::numeric_limits<double>::infinity()), DontEnum | DontDelete | ReadOnly),
GlobalPropertyInfo(vm.propertyNames->undefinedPrivateName, jsUndefined(), DontEnum | DontDelete | ReadOnly),
GlobalPropertyInfo(vm.propertyNames->ObjectPrivateName, objectConstructor, DontEnum | DontDelete | ReadOnly),
GlobalPropertyInfo(vm.propertyNames->TypeErrorPrivateName, m_typeErrorConstructor.get(), DontEnum | DontDelete | ReadOnly),
- GlobalPropertyInfo(vm.propertyNames->BuiltinLogPrivateName, builtinLog, DontEnum | DontDelete | ReadOnly)
+ GlobalPropertyInfo(vm.propertyNames->BuiltinLogPrivateName, builtinLog, DontEnum | DontDelete | ReadOnly),
+ GlobalPropertyInfo(vm.propertyNames->SetTypeErrorAccessorPrivateName, setTypeErrorAccessor, DontEnum | DontDelete | ReadOnly)
};
addStaticGlobals(staticGlobals, WTF_ARRAY_LENGTH(staticGlobals));
#include "JSGlobalObjectFunctions.h"
#include "CallFrame.h"
+#include "GetterSetter.h"
#include "Interpreter.h"
#include "JSFunction.h"
#include "JSGlobalObject.h"
return JSValue::encode(jsUndefined());
}
+
+EncodedJSValue JSC_HOST_CALL globalFuncSetTypeErrorAccessor(ExecState* exec)
+{
+ JSObject* target = jsDynamicCast<JSObject*>(exec->argument(0));
+ JSValue propertyName = exec->argument(1);
+
+ // Setting __proto__ of a primitive should have no effect.
+ if (!target || !propertyName.isString())
+ return JSValue::encode(jsUndefined());
+ VM& vm = exec->vm();
+ Identifier property(exec, asString(propertyName)->getString(exec));
+ target->putDirectNonIndexAccessor(vm, vm.propertyNames->arguments, target->globalObject()->throwTypeErrorGetterSetter(vm), DontDelete | DontEnum | Accessor);
+ return JSValue::encode(jsUndefined());
+}
+
} // namespace JSC
EncodedJSValue JSC_HOST_CALL globalFuncProtoSetter(ExecState*);
EncodedJSValue JSC_HOST_CALL globalFuncBuiltinLog(ExecState*);
+EncodedJSValue JSC_HOST_CALL globalFuncSetTypeErrorAccessor(ExecState*);
+
static const double mantissaOverflowLowerBound = 9007199254740992.0;
double parseIntOverflow(const LChar*, unsigned length, int radix);
bool isStrWhiteSpace(UChar);
{
return exec->vm().throwException(exec, createTypeError(exec, message));
}
-
+
+void JSObject::putDirectPrototypeProperty(VM& vm, JSValue value, int attributes)
+{
+ putDirect(vm, vm.propertyNames->prototype, value, attributes);
+ putDirect(vm, vm.propertyNames->prototypeForHasInstancePrivateName, value, attributes);
+}
+
+void JSObject::putDirectPrototypePropertyWithoutTransitions(VM& vm, JSValue value, int attributes)
+{
+ putDirectWithoutTransition(vm, vm.propertyNames->prototype, value, attributes);
+ putDirectWithoutTransition(vm, vm.propertyNames->prototypeForHasInstancePrivateName, value, attributes);
+}
+
} // namespace JSC
}
}
+ JS_EXPORT_PRIVATE void putDirectPrototypeProperty(VM&, JSValue, int);
+ void putDirectPrototypePropertyWithoutTransitions(VM&, JSValue, int);
+
private:
friend class LLIntOffsetsExtractor;
void JSPromiseConstructor::finishCreation(VM& vm, JSPromisePrototype* promisePrototype)
{
Base::finishCreation(vm, "Promise");
- putDirectWithoutTransition(vm, vm.propertyNames->prototype, promisePrototype, DontEnum | DontDelete | ReadOnly);
+ putDirectPrototypePropertyWithoutTransitions(vm, promisePrototype, DontEnum | DontDelete | ReadOnly);
putDirectWithoutTransition(vm, vm.propertyNames->length, jsNumber(1), ReadOnly | DontEnum | DontDelete);
}
void MapConstructor::finishCreation(VM& vm, MapPrototype* mapPrototype)
{
Base::finishCreation(vm, mapPrototype->classInfo()->className);
- putDirectWithoutTransition(vm, vm.propertyNames->prototype, mapPrototype, DontEnum | DontDelete | ReadOnly);
+ putDirectPrototypePropertyWithoutTransitions(vm, mapPrototype, DontEnum | DontDelete | ReadOnly);
putDirectWithoutTransition(vm, vm.propertyNames->length, jsNumber(0), ReadOnly | DontEnum | DontDelete);
}
void MapIteratorConstructor::finishCreation(VM& vm, MapIteratorPrototype* prototype)
{
Base::finishCreation(vm);
- putDirectWithoutTransition(vm, vm.propertyNames->prototype, prototype, DontEnum | DontDelete | ReadOnly);
+ putDirectPrototypePropertyWithoutTransitions(vm, prototype, DontEnum | DontDelete | ReadOnly);
}
}
void NameConstructor::finishCreation(VM& vm, NamePrototype* prototype)
{
Base::finishCreation(vm, prototype->classInfo()->className);
- putDirectWithoutTransition(vm, vm.propertyNames->prototype, prototype, DontEnum | DontDelete | ReadOnly);
+ putDirectPrototypePropertyWithoutTransitions(vm, prototype, DontEnum | DontDelete | ReadOnly);
putDirectWithoutTransition(vm, vm.propertyNames->length, jsNumber(1), DontDelete | ReadOnly | DontEnum);
}
NativeErrorPrototype* prototype = NativeErrorPrototype::create(vm, globalObject, prototypeStructure, name, this);
putDirect(vm, vm.propertyNames->length, jsNumber(1), DontDelete | ReadOnly | DontEnum); // ECMA 15.11.7.5
- putDirect(vm, vm.propertyNames->prototype, prototype, DontDelete | ReadOnly | DontEnum);
+ putDirectPrototypeProperty(vm, prototype, DontDelete | ReadOnly | DontEnum);
m_errorStructure.set(vm, this, ErrorInstance::createStructure(vm, globalObject, prototype));
ASSERT(m_errorStructure);
ASSERT(m_errorStructure->isObject());
ASSERT(inherits(info()));
// Number.Prototype
- putDirectWithoutTransition(vm, vm.propertyNames->prototype, numberPrototype, DontEnum | DontDelete | ReadOnly);
+ putDirectPrototypePropertyWithoutTransitions(vm, numberPrototype, DontEnum | DontDelete | ReadOnly);
// no. of arguments for constructor
putDirectWithoutTransition(vm, vm.propertyNames->length, jsNumber(1), ReadOnly | DontEnum | DontDelete);
{
Base::finishCreation(vm, Identifier(&vm, "Object").string());
// ECMA 15.2.3.1
- putDirectWithoutTransition(vm, vm.propertyNames->prototype, objectPrototype, DontEnum | DontDelete | ReadOnly);
+ putDirectPrototypePropertyWithoutTransitions(vm, objectPrototype, DontEnum | DontDelete | ReadOnly);
// no. of arguments for constructor
putDirectWithoutTransition(vm, vm.propertyNames->length, jsNumber(1), ReadOnly | DontEnum | DontDelete);
}
ASSERT(inherits(info()));
// ECMA 15.10.5.1 RegExp.prototype
- putDirectWithoutTransition(vm, vm.propertyNames->prototype, regExpPrototype, DontEnum | DontDelete | ReadOnly);
+ putDirectPrototypePropertyWithoutTransitions(vm, regExpPrototype, DontEnum | DontDelete | ReadOnly);
// no. of arguments for constructor
putDirectWithoutTransition(vm, vm.propertyNames->length, jsNumber(2), ReadOnly | DontDelete | DontEnum);
void SetConstructor::finishCreation(VM& vm, SetPrototype* setPrototype)
{
Base::finishCreation(vm, setPrototype->classInfo()->className);
- putDirectWithoutTransition(vm, vm.propertyNames->prototype, setPrototype, DontEnum | DontDelete | ReadOnly);
+ putDirectPrototypePropertyWithoutTransitions(vm, setPrototype, DontEnum | DontDelete | ReadOnly);
putDirectWithoutTransition(vm, vm.propertyNames->length, jsNumber(0), ReadOnly | DontEnum | DontDelete);
}
void SetIteratorConstructor::finishCreation(VM& vm, SetIteratorPrototype* prototype)
{
Base::finishCreation(vm);
- putDirectWithoutTransition(vm, vm.propertyNames->prototype, prototype, DontEnum | DontDelete | ReadOnly);
+ putDirectPrototypePropertyWithoutTransitions(vm, prototype, DontEnum | DontDelete | ReadOnly);
}
}
void StringConstructor::finishCreation(VM& vm, StringPrototype* stringPrototype)
{
Base::finishCreation(vm, stringPrototype->classInfo()->className);
- putDirectWithoutTransition(vm, vm.propertyNames->prototype, stringPrototype, ReadOnly | DontEnum | DontDelete);
+ putDirectPrototypePropertyWithoutTransitions(vm, stringPrototype, ReadOnly | DontEnum | DontDelete);
putDirectWithoutTransition(vm, vm.propertyNames->length, jsNumber(1), ReadOnly | DontEnum | DontDelete);
}
void WeakMapConstructor::finishCreation(VM& vm, WeakMapPrototype* prototype)
{
Base::finishCreation(vm, prototype->classInfo()->className);
- putDirectWithoutTransition(vm, vm.propertyNames->prototype, prototype, DontEnum | DontDelete | ReadOnly);
+ putDirectPrototypePropertyWithoutTransitions(vm, prototype, DontEnum | DontDelete | ReadOnly);
putDirectWithoutTransition(vm, vm.propertyNames->length, jsNumber(0), ReadOnly | DontEnum | DontDelete);
}
+2014-04-08 Oliver Hunt <oliver@apple.com>
+
+ Rewrite Function.bind as a builtin
+ https://bugs.webkit.org/show_bug.cgi?id=131083
+
+ Reviewed by Geoffrey Garen.
+
+ Switch WebCore to use the helper functions when defining the
+ prototype properties on DOM constructors, and update bindings
+ tests accordingly.
+
+ * bindings/js/JSImageConstructor.cpp:
+ (WebCore::JSImageConstructor::finishCreation):
+ * bindings/scripts/CodeGeneratorJS.pm:
+ (GenerateConstructorHelperMethods):
+ * bindings/scripts/test/JS/JSTestActiveDOMObject.cpp:
+ (WebCore::JSTestActiveDOMObjectConstructor::finishCreation):
+ * bindings/scripts/test/JS/JSTestCustomNamedGetter.cpp:
+ (WebCore::JSTestCustomNamedGetterConstructor::finishCreation):
+ * bindings/scripts/test/JS/JSTestEventConstructor.cpp:
+ (WebCore::JSTestEventConstructorConstructor::finishCreation):
+ * bindings/scripts/test/JS/JSTestEventTarget.cpp:
+ (WebCore::JSTestEventTargetConstructor::finishCreation):
+ * bindings/scripts/test/JS/JSTestException.cpp:
+ (WebCore::JSTestExceptionConstructor::finishCreation):
+ * bindings/scripts/test/JS/JSTestGenerateIsReachable.cpp:
+ (WebCore::JSTestGenerateIsReachableConstructor::finishCreation):
+ * bindings/scripts/test/JS/JSTestInterface.cpp:
+ (WebCore::JSTestInterfaceConstructor::finishCreation):
+ * bindings/scripts/test/JS/JSTestMediaQueryListListener.cpp:
+ (WebCore::JSTestMediaQueryListListenerConstructor::finishCreation):
+ * bindings/scripts/test/JS/JSTestNamedConstructor.cpp:
+ (WebCore::JSTestNamedConstructorConstructor::finishCreation):
+ (WebCore::JSTestNamedConstructorNamedConstructor::finishCreation):
+ * bindings/scripts/test/JS/JSTestNode.cpp:
+ (WebCore::JSTestNodeConstructor::finishCreation):
+ * bindings/scripts/test/JS/JSTestObj.cpp:
+ (WebCore::JSTestObjConstructor::finishCreation):
+ * bindings/scripts/test/JS/JSTestOverloadedConstructors.cpp:
+ (WebCore::JSTestOverloadedConstructorsConstructor::finishCreation):
+ * bindings/scripts/test/JS/JSTestSerializedScriptValueInterface.cpp:
+ (WebCore::JSTestSerializedScriptValueInterfaceConstructor::finishCreation):
+ * bindings/scripts/test/JS/JSTestTypedefs.cpp:
+ (WebCore::JSTestTypedefsConstructor::finishCreation):
+ * bindings/scripts/test/JS/JSattribute.cpp:
+ (WebCore::JSattributeConstructor::finishCreation):
+ * bindings/scripts/test/JS/JSreadonly.cpp:
+ (WebCore::JSreadonlyConstructor::finishCreation):
+
2014-04-13 Simon Fraser <simon.fraser@apple.com>
[iOS WK2] Hook up scrolling tree nodes when coming out of the page cache
/*
* Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
- * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2010 Apple Inc. All rights reserved.
+ * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2010, 2014 Apple Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
{
Base::finishCreation(globalObject);
ASSERT(inherits(info()));
- putDirect(vm, vm.propertyNames->prototype, JSHTMLImageElementPrototype::self(vm, globalObject), None);
+ putDirectPrototypeProperty(vm, JSHTMLImageElementPrototype::self(vm, globalObject), None);
}
static EncodedJSValue JSC_HOST_CALL constructImage(ExecState* exec)
if (IsDOMGlobalObject($interface)) {
push(@$outputArray, " Base::finishCreation(vm);\n");
push(@$outputArray, " ASSERT(inherits(info()));\n");
- push(@$outputArray, " putDirect(vm, vm.propertyNames->prototype, globalObject->prototype(), DontDelete | ReadOnly);\n");
+ push(@$outputArray, " putDirectPrototypeProperty(vm, globalObject->prototype(), DontDelete | ReadOnly);\n");
} elsif ($generatingNamedConstructor) {
push(@$outputArray, " Base::finishCreation(globalObject);\n");
push(@$outputArray, " ASSERT(inherits(info()));\n");
- push(@$outputArray, " putDirect(vm, vm.propertyNames->prototype, ${className}Prototype::self(vm, globalObject), None);\n");
+ push(@$outputArray, " putDirectPrototypeProperty(vm, ${className}Prototype::self(vm, globalObject), None);\n");
} else {
push(@$outputArray, " Base::finishCreation(vm);\n");
push(@$outputArray, " ASSERT(inherits(info()));\n");
- push(@$outputArray, " putDirect(vm, vm.propertyNames->prototype, ${protoClassName}::self(vm, globalObject), DontDelete | ReadOnly);\n");
+ push(@$outputArray, " putDirectPrototypeProperty(vm, ${protoClassName}::self(vm, globalObject), DontDelete | ReadOnly);\n");
}
push(@$outputArray, " putDirect(vm, vm.propertyNames->length, jsNumber(${leastConstructorLength}), ReadOnly | DontDelete | DontEnum);\n") if defined $leastConstructorLength;
push(@$outputArray, "}\n\n");
{
Base::finishCreation(vm);
ASSERT(inherits(info()));
- putDirect(vm, vm.propertyNames->prototype, JSTestActiveDOMObjectPrototype::self(vm, globalObject), DontDelete | ReadOnly);
+ putDirectPrototypeProperty(vm, JSTestActiveDOMObjectPrototype::self(vm, globalObject), DontDelete | ReadOnly);
putDirect(vm, vm.propertyNames->length, jsNumber(0), ReadOnly | DontDelete | DontEnum);
}
{
Base::finishCreation(vm);
ASSERT(inherits(info()));
- putDirect(vm, vm.propertyNames->prototype, JSTestCustomNamedGetterPrototype::self(vm, globalObject), DontDelete | ReadOnly);
+ putDirectPrototypeProperty(vm, JSTestCustomNamedGetterPrototype::self(vm, globalObject), DontDelete | ReadOnly);
putDirect(vm, vm.propertyNames->length, jsNumber(0), ReadOnly | DontDelete | DontEnum);
}
{
Base::finishCreation(vm);
ASSERT(inherits(info()));
- putDirect(vm, vm.propertyNames->prototype, JSTestEventConstructorPrototype::self(vm, globalObject), DontDelete | ReadOnly);
+ putDirectPrototypeProperty(vm, JSTestEventConstructorPrototype::self(vm, globalObject), DontDelete | ReadOnly);
putDirect(vm, vm.propertyNames->length, jsNumber(1), ReadOnly | DontDelete | DontEnum);
}
{
Base::finishCreation(vm);
ASSERT(inherits(info()));
- putDirect(vm, vm.propertyNames->prototype, JSTestEventTargetPrototype::self(vm, globalObject), DontDelete | ReadOnly);
+ putDirectPrototypeProperty(vm, JSTestEventTargetPrototype::self(vm, globalObject), DontDelete | ReadOnly);
putDirect(vm, vm.propertyNames->length, jsNumber(0), ReadOnly | DontDelete | DontEnum);
}
{
Base::finishCreation(vm);
ASSERT(inherits(info()));
- putDirect(vm, vm.propertyNames->prototype, JSTestExceptionPrototype::self(vm, globalObject), DontDelete | ReadOnly);
+ putDirectPrototypeProperty(vm, JSTestExceptionPrototype::self(vm, globalObject), DontDelete | ReadOnly);
putDirect(vm, vm.propertyNames->length, jsNumber(0), ReadOnly | DontDelete | DontEnum);
}
{
Base::finishCreation(vm);
ASSERT(inherits(info()));
- putDirect(vm, vm.propertyNames->prototype, JSTestGenerateIsReachablePrototype::self(vm, globalObject), DontDelete | ReadOnly);
+ putDirectPrototypeProperty(vm, JSTestGenerateIsReachablePrototype::self(vm, globalObject), DontDelete | ReadOnly);
putDirect(vm, vm.propertyNames->length, jsNumber(0), ReadOnly | DontDelete | DontEnum);
}
{
Base::finishCreation(vm);
ASSERT(inherits(info()));
- putDirect(vm, vm.propertyNames->prototype, JSTestInterfacePrototype::self(vm, globalObject), DontDelete | ReadOnly);
+ putDirectPrototypeProperty(vm, JSTestInterfacePrototype::self(vm, globalObject), DontDelete | ReadOnly);
putDirect(vm, vm.propertyNames->length, jsNumber(1), ReadOnly | DontDelete | DontEnum);
}
{
Base::finishCreation(vm);
ASSERT(inherits(info()));
- putDirect(vm, vm.propertyNames->prototype, JSTestMediaQueryListListenerPrototype::self(vm, globalObject), DontDelete | ReadOnly);
+ putDirectPrototypeProperty(vm, JSTestMediaQueryListListenerPrototype::self(vm, globalObject), DontDelete | ReadOnly);
putDirect(vm, vm.propertyNames->length, jsNumber(0), ReadOnly | DontDelete | DontEnum);
}
{
Base::finishCreation(vm);
ASSERT(inherits(info()));
- putDirect(vm, vm.propertyNames->prototype, JSTestNamedConstructorPrototype::self(vm, globalObject), DontDelete | ReadOnly);
+ putDirectPrototypeProperty(vm, JSTestNamedConstructorPrototype::self(vm, globalObject), DontDelete | ReadOnly);
putDirect(vm, vm.propertyNames->length, jsNumber(0), ReadOnly | DontDelete | DontEnum);
}
{
Base::finishCreation(globalObject);
ASSERT(inherits(info()));
- putDirect(vm, vm.propertyNames->prototype, JSTestNamedConstructorPrototype::self(vm, globalObject), None);
+ putDirectPrototypeProperty(vm, JSTestNamedConstructorPrototype::self(vm, globalObject), None);
putDirect(vm, vm.propertyNames->length, jsNumber(0), ReadOnly | DontDelete | DontEnum);
}
{
Base::finishCreation(vm);
ASSERT(inherits(info()));
- putDirect(vm, vm.propertyNames->prototype, JSTestNodePrototype::self(vm, globalObject), DontDelete | ReadOnly);
+ putDirectPrototypeProperty(vm, JSTestNodePrototype::self(vm, globalObject), DontDelete | ReadOnly);
putDirect(vm, vm.propertyNames->length, jsNumber(0), ReadOnly | DontDelete | DontEnum);
}
{
Base::finishCreation(vm);
ASSERT(inherits(info()));
- putDirect(vm, vm.propertyNames->prototype, JSTestObjPrototype::self(vm, globalObject), DontDelete | ReadOnly);
+ putDirectPrototypeProperty(vm, JSTestObjPrototype::self(vm, globalObject), DontDelete | ReadOnly);
putDirect(vm, vm.propertyNames->length, jsNumber(1), ReadOnly | DontDelete | DontEnum);
}
{
Base::finishCreation(vm);
ASSERT(inherits(info()));
- putDirect(vm, vm.propertyNames->prototype, JSTestOverloadedConstructorsPrototype::self(vm, globalObject), DontDelete | ReadOnly);
+ putDirectPrototypeProperty(vm, JSTestOverloadedConstructorsPrototype::self(vm, globalObject), DontDelete | ReadOnly);
putDirect(vm, vm.propertyNames->length, jsNumber(1), ReadOnly | DontDelete | DontEnum);
}
{
Base::finishCreation(vm);
ASSERT(inherits(info()));
- putDirect(vm, vm.propertyNames->prototype, JSTestSerializedScriptValueInterfacePrototype::self(vm, globalObject), DontDelete | ReadOnly);
+ putDirectPrototypeProperty(vm, JSTestSerializedScriptValueInterfacePrototype::self(vm, globalObject), DontDelete | ReadOnly);
putDirect(vm, vm.propertyNames->length, jsNumber(0), ReadOnly | DontDelete | DontEnum);
}
{
Base::finishCreation(vm);
ASSERT(inherits(info()));
- putDirect(vm, vm.propertyNames->prototype, JSTestTypedefsPrototype::self(vm, globalObject), DontDelete | ReadOnly);
+ putDirectPrototypeProperty(vm, JSTestTypedefsPrototype::self(vm, globalObject), DontDelete | ReadOnly);
putDirect(vm, vm.propertyNames->length, jsNumber(2), ReadOnly | DontDelete | DontEnum);
}
{
Base::finishCreation(vm);
ASSERT(inherits(info()));
- putDirect(vm, vm.propertyNames->prototype, JSattributePrototype::self(vm, globalObject), DontDelete | ReadOnly);
+ putDirectPrototypeProperty(vm, JSattributePrototype::self(vm, globalObject), DontDelete | ReadOnly);
putDirect(vm, vm.propertyNames->length, jsNumber(0), ReadOnly | DontDelete | DontEnum);
}
{
Base::finishCreation(vm);
ASSERT(inherits(info()));
- putDirect(vm, vm.propertyNames->prototype, JSreadonlyPrototype::self(vm, globalObject), DontDelete | ReadOnly);
+ putDirectPrototypeProperty(vm, JSreadonlyPrototype::self(vm, globalObject), DontDelete | ReadOnly);
putDirect(vm, vm.propertyNames->length, jsNumber(0), ReadOnly | DontDelete | DontEnum);
}