]>
Commit | Line | Data |
---|---|---|
81345200 A |
1 | /* |
2 | * Copyright (C) 2014 Apple Inc. All rights reserved. | |
3 | * | |
4 | * Redistribution and use in source and binary forms, with or without | |
5 | * modification, are permitted provided that the following conditions | |
6 | * are met: | |
7 | * 1. Redistributions of source code must retain the above copyright | |
8 | * notice, this list of conditions and the following disclaimer. | |
9 | * 2. Redistributions in binary form must reproduce the above copyright | |
10 | * notice, this list of conditions and the following disclaimer in the | |
11 | * documentation and/or other materials provided with the distribution. | |
12 | * | |
13 | * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY | |
14 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
15 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
16 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR | |
17 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | |
18 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | |
19 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | |
20 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY | |
21 | * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
22 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
23 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
24 | */ | |
25 | ||
26 | ||
27 | #include "config.h" | |
28 | #include "BuiltinExecutables.h" | |
29 | ||
30 | #include "BuiltinNames.h" | |
31 | #include "Executable.h" | |
32 | #include "JSCInlines.h" | |
33 | #include "Parser.h" | |
ed1e77d3 | 34 | #include <wtf/NeverDestroyed.h> |
81345200 A |
35 | |
36 | namespace JSC { | |
37 | ||
38 | BuiltinExecutables::BuiltinExecutables(VM& vm) | |
39 | : m_vm(vm) | |
40 | #define INITIALIZE_BUILTIN_SOURCE_MEMBERS(name, functionName, length) , m_##name##Source(makeSource(StringImpl::createFromLiteral(s_##name, length))) | |
41 | JSC_FOREACH_BUILTIN(INITIALIZE_BUILTIN_SOURCE_MEMBERS) | |
42 | #undef EXPOSE_BUILTIN_STRINGS | |
43 | { | |
44 | } | |
45 | ||
ed1e77d3 A |
46 | UnlinkedFunctionExecutable* BuiltinExecutables::createDefaultConstructor(ConstructorKind constructorKind, const Identifier& name) |
47 | { | |
48 | static NeverDestroyed<const String> baseConstructorCode(ASCIILiteral("(function () { })")); | |
49 | static NeverDestroyed<const String> derivedConstructorCode(ASCIILiteral("(function () { super(...arguments); })")); | |
50 | ||
51 | switch (constructorKind) { | |
52 | case ConstructorKind::None: | |
53 | break; | |
54 | case ConstructorKind::Base: | |
55 | return createExecutableInternal(makeSource(baseConstructorCode), name, constructorKind); | |
56 | case ConstructorKind::Derived: | |
57 | return createExecutableInternal(makeSource(derivedConstructorCode), name, constructorKind); | |
58 | } | |
59 | ASSERT_NOT_REACHED(); | |
60 | return nullptr; | |
61 | } | |
62 | ||
63 | UnlinkedFunctionExecutable* BuiltinExecutables::createExecutableInternal(const SourceCode& source, const Identifier& name, ConstructorKind constructorKind) | |
81345200 A |
64 | { |
65 | JSTextPosition positionBeforeLastNewline; | |
66 | ParserError error; | |
ed1e77d3 A |
67 | bool isParsingDefaultConstructor = constructorKind != ConstructorKind::None; |
68 | JSParserBuiltinMode builtinMode = isParsingDefaultConstructor ? JSParserBuiltinMode::NotBuiltin : JSParserBuiltinMode::Builtin; | |
69 | UnlinkedFunctionKind kind = isParsingDefaultConstructor ? UnlinkedNormalFunction : UnlinkedBuiltinFunction; | |
70 | RefPtr<SourceProvider> sourceOverride = isParsingDefaultConstructor ? source.provider() : nullptr; | |
71 | std::unique_ptr<ProgramNode> program = parse<ProgramNode>( | |
72 | &m_vm, source, 0, Identifier(), builtinMode, | |
73 | JSParserStrictMode::NotStrict, | |
74 | JSParserCodeType::Program, | |
75 | error, &positionBeforeLastNewline, constructorKind); | |
81345200 A |
76 | |
77 | if (!program) { | |
ed1e77d3 | 78 | dataLog("Fatal error compiling builtin function '", name.string(), "': ", error.message()); |
81345200 A |
79 | CRASH(); |
80 | } | |
81 | ||
82 | StatementNode* exprStatement = program->singleStatement(); | |
83 | RELEASE_ASSERT(exprStatement); | |
84 | RELEASE_ASSERT(exprStatement->isExprStatement()); | |
85 | ExpressionNode* funcExpr = static_cast<ExprStatementNode*>(exprStatement)->expr(); | |
86 | RELEASE_ASSERT(funcExpr); | |
87 | RELEASE_ASSERT(funcExpr->isFuncExprNode()); | |
88 | FunctionBodyNode* body = static_cast<FuncExprNode*>(funcExpr)->body(); | |
89 | RELEASE_ASSERT(!program->hasCapturedVariables()); | |
90 | ||
91 | body->setEndPosition(positionBeforeLastNewline); | |
92 | RELEASE_ASSERT(body); | |
93 | RELEASE_ASSERT(body->ident().isNull()); | |
94 | ||
95 | // This function assumes an input string that would result in a single anonymous function expression. | |
96 | body->setEndPosition(positionBeforeLastNewline); | |
97 | RELEASE_ASSERT(body); | |
98 | for (const auto& closedVariable : program->closedVariables()) { | |
99 | if (closedVariable == m_vm.propertyNames->arguments.impl()) | |
ed1e77d3 | 100 | continue; |
81345200 A |
101 | |
102 | if (closedVariable == m_vm.propertyNames->undefinedKeyword.impl()) | |
103 | continue; | |
81345200 A |
104 | } |
105 | body->overrideName(name); | |
ed1e77d3 | 106 | UnlinkedFunctionExecutable* functionExecutable = UnlinkedFunctionExecutable::create(&m_vm, source, body, kind, WTF::move(sourceOverride)); |
81345200 A |
107 | functionExecutable->m_nameValue.set(m_vm, functionExecutable, jsString(&m_vm, name.string())); |
108 | return functionExecutable; | |
109 | } | |
110 | ||
ed1e77d3 A |
111 | void BuiltinExecutables::finalize(Handle<Unknown>, void* context) |
112 | { | |
113 | static_cast<Weak<UnlinkedFunctionExecutable>*>(context)->clear(); | |
114 | } | |
115 | ||
81345200 A |
116 | #define DEFINE_BUILTIN_EXECUTABLES(name, functionName, length) \ |
117 | UnlinkedFunctionExecutable* BuiltinExecutables::name##Executable() \ | |
118 | {\ | |
119 | if (!m_##name##Executable)\ | |
ed1e77d3 | 120 | m_##name##Executable = Weak<UnlinkedFunctionExecutable>(createBuiltinExecutable(m_##name##Source, m_vm.propertyNames->builtinNames().functionName##PublicName()), this, &m_##name##Executable);\ |
81345200 A |
121 | return m_##name##Executable.get();\ |
122 | } | |
123 | JSC_FOREACH_BUILTIN(DEFINE_BUILTIN_EXECUTABLES) | |
124 | #undef EXPOSE_BUILTIN_SOURCES | |
125 | ||
126 | } |