/* * Copyright (c) 1998-2011 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.ArrayList; import java.util.Iterator; /** * JavaScript object */ class ESArray extends ESObject { static ESId LENGTH = ESId.intern("length"); /** * Create a new object based on a prototype */ ESArray() { super("Array", null); put(LENGTH, ESNumber.create(0), DONT_ENUM|DONT_DELETE); } public void setProperty(int i, ESBase value) throws Throwable { super.setProperty(ESString.create(i), value); int length = getProperty(LENGTH).toInt32(); if (i >= length) super.setProperty(LENGTH, ESNumber.create(i + 1)); } public void setProperty(ESString key, ESBase value) throws Throwable { if (key.equals(LENGTH)) { int oldLength; int newLength; try { oldLength = getProperty(LENGTH).toInt32(); newLength = value.toInt32(); } catch (ESException e) { return; } for (int i = newLength; i < oldLength; i++) { try { delete(ESString.create(i)); } catch (Exception e) { } } if (newLength < 0) newLength = 0; super.setProperty(LENGTH, ESNumber.create(newLength)); return; } super.setProperty(key, value); try { int keyValue = Integer.parseInt(key.toString()); int length = getProperty(LENGTH).toInt32(); if (keyValue >= length) super.setProperty(LENGTH, ESNumber.create(keyValue + 1)); } catch (Exception e) { } } static ESString arrayToSource(ESObject obj, IntMap map, boolean isLoopPass) throws Throwable { Global resin = Global.getGlobalProto(); CharBuffer cb = new CharBuffer(); int mark = map.get(obj); if (mark > 0 && isLoopPass) return null; else if (mark > 0) { cb.append("#" + mark + "="); map.put(obj, -mark); } else if (mark == 0 && isLoopPass) { map.put(obj, resin.addMark()); return null; } else if (mark < 0 && ! isLoopPass) { return ESString.create("#" + -mark + "#"); } if (isLoopPass) map.put(obj, 0); int len = obj.getProperty(LENGTH).toInt32(); boolean noValue = true; cb.append("["); for (int i = 0; i < len; i++) { if (i != 0) cb.append(", "); ESBase value = obj.hasProperty(i); if (value != null && value != esNull && value != esUndefined && value != esEmpty) { if (isLoopPass) value.toSource(map, isLoopPass); else cb.append(value.toSource(map, isLoopPass)); } else if (i + 1 == len) cb.append(","); } cb.append("]"); return ESString.create(cb.toString()); } public Iterator keys() throws ESException { ArrayList values = new ArrayList(); try { int len = getProperty(LENGTH).toInt32(); for (int i = 0; i < len; i++) { Object prop = getProperty(i); // spec says add the key integers values.add(String.valueOf(i)); } } catch (Throwable e) { throw ESWrapperException.create(e); } return values.iterator(); } public ESString toSource(IntMap map, boolean isLoopPass) throws Throwable { return arrayToSource(this, map, isLoopPass); } public ESObject dup() { return new ESArray(false); } protected ESArray(boolean dummy) {} }