File indexing completed on 2024-05-12 15:43:25

0001 /*
0002  * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
0003  *           (C) 2008 Maksim Orlovich <maksim@kde.org>
0004  *
0005  *  This library is free software; you can redistribute it and/or
0006  *  modify it under the terms of the GNU Library General Public
0007  *  License as published by the Free Software Foundation; either
0008  *  version 2 of the License, or (at your option) any later version.
0009  *
0010  *  This library is distributed in the hope that it will be useful,
0011  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
0012  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0013  *  Library General Public License for more details.
0014  *
0015  *  You should have received a copy of the GNU Library General Public License
0016  *  along with this library; see the file COPYING.LIB.  If not, write to
0017  *  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
0018  *  Boston, MA 02110-1301, USA.
0019  *
0020  * Portions of this code that are (C) 2007, 2008 Apple Inc. were
0021  * originally distributed under the following terms
0022  *
0023  *  Redistribution and use in source and binary forms, with or without
0024  *  modification, are permitted provided that the following conditions
0025  *   are met:
0026  *
0027  *   1.  Redistributions of source code must retain the above copyright
0028  *       notice, this list of conditions and the following disclaimer.
0029  *   2.  Redistributions in binary form must reproduce the above copyright
0030  *       notice, this list of conditions and the following disclaimer in the
0031  *       documentation and/or other materials provided with the distribution.
0032  *   3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
0033  *       its contributors may be used to endorse or promote products derived
0034  *       from this software without specific prior written permission.
0035  *
0036  *   THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
0037  *   EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
0038  *   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
0039  *   DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
0040  *   DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
0041  *   (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
0042  *   LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
0043  *   ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
0044  *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
0045  *   THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
0046  */
0047 
0048 #ifndef JSVariableObject_h
0049 #define JSVariableObject_h
0050 
0051 #include "LocalStorage.h"
0052 #include "SymbolTable.h"
0053 #include "object.h"
0054 
0055 #include <wtf/Vector.h>
0056 
0057 namespace KJS
0058 {
0059 class Interpreter;
0060 
0061 class JSVariableObject : public JSObject
0062 {
0063 public:
0064     using KJS::JSObject::deleteProperty;
0065     bool deleteProperty(ExecState *, const Identifier &) override;
0066 
0067     void getOwnPropertyNames(ExecState *, PropertyNameArray &, PropertyMap::PropertyMode mode) override;
0068 
0069     void mark() override;
0070 
0071     enum {
0072         LengthSlot,
0073         TearOffNeeded, // Set when a tearoff is requested;
0074         // the actual tearoff will only happen once the function
0075         // stops running, though
0076         ScopeLink,
0077         NumVarObjectSlots = 3
0078     };
0079 
0080     int32_t &lengthSlot()
0081     {
0082         return localStorage[LengthSlot].val.int32Val;
0083     }
0084     const int32_t &lengthSlot() const
0085     {
0086         return localStorage[LengthSlot].val.int32Val;
0087     }
0088 
0089     bool &tearOffNeededSlot()
0090     {
0091         return localStorage[TearOffNeeded].val.boolVal;
0092     }
0093 
0094     ScopeChainLink &scopeLink()
0095     {
0096         return localStorage[ScopeLink].val.scopeVal;
0097     }
0098 protected:
0099     JSVariableObject(): localStorage(nullptr), symbolTable(nullptr) { }
0100     ~JSVariableObject() override;
0101 
0102     bool symbolTableGet(const Identifier &, PropertySlot &);
0103     bool symbolTablePut(const Identifier &, JSValue *, bool checkReadOnly);
0104 
0105 public:
0106     LocalStorageEntry *localStorage; // Storage for variables in the symbol table.
0107     SymbolTable       *symbolTable; // Maps name -> index in localStorage.
0108 };
0109 
0110 inline bool JSVariableObject::symbolTableGet(const Identifier &propertyName, PropertySlot &slot)
0111 {
0112     size_t index = symbolTable->get(propertyName.ustring().rep());
0113     if (index != missingSymbolMarker()) {
0114         slot.setValueSlot(this, &localStorage[index].val.valueVal);
0115         return true;
0116     }
0117     return false;
0118 }
0119 
0120 inline bool JSVariableObject::symbolTablePut(const Identifier &propertyName, JSValue *value, bool checkReadOnly)
0121 {
0122     size_t index = symbolTable->get(propertyName.ustring().rep());
0123     if (index == missingSymbolMarker()) {
0124         return false;
0125     }
0126     LocalStorageEntry &entry = localStorage[index];
0127     if (checkReadOnly && (entry.attributes & ReadOnly)) {
0128         return true;
0129     }
0130     entry.val.valueVal = value;
0131     return true;
0132 }
0133 
0134 inline JSVariableObject::~JSVariableObject()
0135 {
0136     if (localStorage) {
0137         scopeLink().deref();
0138         if (tearOffNeededSlot()) {
0139             delete[] localStorage;
0140         }
0141     }
0142 }
0143 
0144 inline JSObject *ScopeChainLink::object() const
0145 {
0146     if (isToScopeChainNode()) {
0147         return asScopeChainNode()->object;
0148     } else {
0149         return asVariableObject();
0150     }
0151 }
0152 
0153 inline ScopeChainLink ScopeChainLink::next() const
0154 {
0155     if (isToScopeChainNode()) {
0156         return asScopeChainNode()->next;
0157     } else {
0158         return asVariableObject()->scopeLink();
0159     }
0160 }
0161 
0162 inline void ScopeChain::mark()
0163 {
0164     for (ScopeChainLink n = m_top; n.ptr; n = n.next()) {
0165         JSObject *o = n.object();
0166         if (!o->marked()) {
0167             o->mark();
0168         }
0169     }
0170 }
0171 
0172 inline void ScopeChain::pushVariableObject(JSVariableObject *act)
0173 {
0174     // note: this assumes the new variable object is not in any
0175     // scope chain in the moment.
0176 
0177     // Set the item's next pointer to the current top.
0178     // there is no refcount ops since it's transferring a reference
0179     act->scopeLink() = m_top;
0180 
0181     // new top!
0182     m_top.set(act);
0183 }
0184 
0185 class KJS_EXPORT JSGlobalObject :  public JSObject // ### TODO: should inherit off JSVariableObject
0186 {
0187 public:
0188     JSGlobalObject(): m_interpreter(nullptr) {}
0189     JSGlobalObject(JSValue *proto): JSObject(proto), m_interpreter(nullptr) {}
0190     bool isGlobalObject() const override
0191     {
0192         return true;
0193     }
0194 
0195     void setInterpreter(Interpreter *intp)
0196     {
0197         m_interpreter = intp;
0198     }
0199     Interpreter *interpreter() const
0200     {
0201         return m_interpreter;
0202     }
0203 private:
0204     Interpreter *m_interpreter;
0205 };
0206 } // namespace KJS
0207 
0208 #endif // JSVariableObject_h