📄 esobject.java
字号:
/* * Copyright (c) 1998-2006 Caucho Technology -- all rights reserved * * This file is part of Resin(R) Open Source * * Each copy or derived work must preserve the copyright notice and this * notice unmodified. * * Resin Open Source is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Resin Open Source is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty * of NON-INFRINGEMENT. See the GNU General Public License for more * details. * * You should have received a copy of the GNU General Public License * along with Resin Open Source; if not, write to the * Free SoftwareFoundation, Inc. * 59 Temple Place, Suite 330 * Boston, MA 02111-1307 USA * * @author Scott Ferguson */package com.caucho.es;import com.caucho.util.CharBuffer;import com.caucho.util.IntMap;import java.util.HashMap;import java.util.Iterator;/** * Implementation class for a JavaScript Object. */public class ESObject extends ESBase { static ESId TO_STRING = ESId.intern("toString"); static ESId VALUE_OF = ESId.intern("valueOf"); static ESId CALL = ESId.intern("call"); static ESId CONSTRUCT = ESId.intern("construct"); static int DIRTY = 0; static int CLEAN = DIRTY + 1; static int COW = CLEAN + 1; int copyState = DIRTY; ESString []propNames; ESBase []propValues; ESBase []propWatch; int []propFlags; int size; int fill; int mask; int mark; // for printing protected boolean snapPrototype; protected ESObject() { } /** * Simple constructor for parentless objects. */ public ESObject(String className, ESBase proto) { init(className, proto, 16); } protected ESObject(String className, ESBase proto, int hashSize) { init(className, proto, hashSize < 16 ? 16 : hashSize); } private void init(String className, ESBase proto, int hashSize) { if (proto == null) { Global resin = Global.getGlobalProto(); proto = resin == null ? null : resin.objProto; } if (className == null && proto != null) className = proto.className; prototype = proto; propNames = new ESString[hashSize]; propValues = new ESBase[hashSize]; propFlags = new int[hashSize]; mask = propNames.length - 1; size = 0; fill = 0; copyState = DIRTY; this.className = className == null ? "Object" : className; } void init(String className, ESBase proto) { init(className, proto, 16); } void setClean() { copyState = CLEAN; } /** * Expands the property table */ private void resize(int newSize) { ESString []newNames = new ESString[newSize]; ESBase []newValues = new ESBase[newSize]; int []newFlags = new int[newSize]; ESBase []newWatch = null; if (propWatch != null) newWatch = new ESBase[newSize]; mask = newNames.length - 1; for (int i = 0; i < propNames.length; i++) { if (propValues[i] == null && (propFlags[i] & WATCH) == 0) continue; int hash = propNames[i].hashCode() & mask; while (true) { if (newNames[hash] == null) { newNames[hash] = propNames[i]; newValues[hash] = propValues[i]; newFlags[hash] = propFlags[i]; if (newWatch != null) newWatch[hash] = propWatch[i]; break; } hash = (hash + 1) & mask; } } propNames = newNames; propValues = newValues; propFlags = newFlags; propWatch = newWatch; fill = size; } private void refill() { for (int i = 0; i < propNames.length; i++) { if (propValues[i] == null && (propFlags[i] & WATCH) == 0) { propNames[i] = null; continue; } int hash = propNames[i].hashCode() & mask; while (true) { if (propValues[hash] == null && (propFlags[hash] & WATCH) == 0) { propNames[hash] = propNames[i]; propValues[hash] = propValues[i]; propFlags[hash] = propFlags[i]; propNames[i] = null; propValues[i] = null; propFlags[i] = 0; break; } hash = (hash + 1) & mask; } } fill = size; } /** * Gets a property value. */ public ESBase getProperty(ESString name) throws Throwable { int hash = name.hashCode() & mask; while (true) { ESString propName = propNames[hash]; if (propName == name || name.equals(propName)) { ESBase value = propValues[hash]; return value == null ? prototype.getProperty(name) : value; } else if (propName == null) { ESBase value = prototype.getProperty(name); if (snapPrototype) setProperty(name, value); return value; } hash = (hash + 1) & mask; } } protected boolean canPut(ESString name) { int hash = name.hashCode() & mask; while (true) { ESString propName = propNames[hash]; if (name.equals(propName) && propValues[hash] != null) return (propFlags[hash] & READ_ONLY) == 0; else if (propName == null) { if (prototype instanceof ESObject) return ((ESObject) prototype).canPut(name); else return true; } hash = (hash + 1) & mask; } } /* public ESBase callWatch(ESString name, int hash, ESBase value) throws Exception { Global resin = Global.getGlobalProto(); Call call = resin.getCall(); call.top = 1; if (propWatch[hash] instanceof ESClosure) call.setArg(-1, ((ESClosure) propWatch[hash]).scope[0]); else call.setArg(-1, null); call.setArg(0, name); call.setArg(1, propValues[hash]); call.setArg(2, value); value = propWatch[hash].call(call, 3); resin.freeCall(call); return value; } */ /** * Puts a new value in the property table with the appropriate flags */ public void setProperty(ESString name, ESBase value) throws Throwable { if (copyState != DIRTY) { if (copyState == COW) copyAll(); copyState = DIRTY; } if (value == esEmpty) value = esUndefined; int hash = name.hashCode() & mask; while (true) { ESString propName = propNames[hash]; if (propValues[hash] == null) { if (! prototype.canPut(name)) return; if (propName == null) fill++; propNames[hash] = name; /* if ((propFlags[hash] & WATCH) != 0) value = callWatch(name, hash, value); */ propValues[hash] = value; propFlags[hash] = 0; size++; if (propNames.length <= 4 * size) { resize(4 * propNames.length); } else if (propNames.length <= 2 * fill) refill(); return; } else if (propName != name && ! propName.equals(name)) { hash = (hash + 1) & mask; continue; } else if ((propFlags[hash] & READ_ONLY) != 0) return; else { /* if ((propFlags[hash] & WATCH) != 0) value = callWatch(name, hash, value); */ propValues[hash] = value; return; } } } public void put(ESString name, ESBase value, int flags) { int hash = name.hashCode() & mask; while (true) { ESString propName = propNames[hash]; if (propName == null || propValues[hash] == null || propName.equals(name)) { if (propName == null) fill++; if (propValues[hash] == null) size++; propNames[hash] = name; propValues[hash] = value; propFlags[hash] = flags; if (propNames.length <= 4 * size) { resize(4 * propNames.length); } else if (propNames.length <= 2 * fill) refill(); return; } hash = (hash + 1) & mask; } } public void put(String name, ESBase value, int flags) { ESId id = ESId.intern(name); put(id, value, flags); } /** * Deletes the entry. Returns true if successful. */ public ESBase delete(ESString name) throws Throwable { if (copyState != DIRTY) { if (copyState == COW) copyAll(); copyState = DIRTY; } int hash = name.hashCode() & mask; while (true) { ESString hashName = propNames[hash]; if (hashName == null) return ESBoolean.FALSE; else if (propValues[hash] != null && hashName.equals(name)) { if ((propFlags[hash] & DONT_DELETE) != 0) return ESBoolean.FALSE; else { propValues[hash] = null; size--; return ESBoolean.TRUE; } } hash = (hash + 1) & mask; } } public void watch(ESString name, ESBase fun) { if (copyState != DIRTY) { if (copyState == COW) copyAll(); copyState = DIRTY; } int hash = name.hashCode() & mask;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -