NativeStrictArguments(final Object[] values, final int numParams,final ScriptObject proto, final PropertyMap map) { super(proto, map); setIsArguments(); final ScriptFunction func = Global.instance().getTypeErrorThrower(); // We have to fill user accessor functions late as these are stored // in this object rather than in the PropertyMap of this object. final int flags = Property.NOT_ENUMERABLE | Property.NOT_CONFIGURABLE; initUserAccessors("caller", flags, func, func); initUserAccessors("callee", flags, func, func); setArray(ArrayData.allocate(values)); this.length = values.length; // extend/truncate named arg array as needed and copy values this.namedArgs = new Object[numParams]; if (numParams > values.length) { Arrays.fill(namedArgs, UNDEFINED); } System.arraycopy(values, 0, namedArgs, 0, Math.min(namedArgs.length, values.length)); }
/** * Get the guard for a property access. This returns an identity guard for non-configurable global properties * and a map guard for everything else. * * @param sobj the first object in the prototype chain * @param property the property * @param desc the callsite descriptor * @param explicitInstanceOfCheck true if we should do an explicit script object instanceof check instead of just casting * @return method handle for guard */ public static MethodHandle getGuard(final ScriptObject sobj, final Property property, final CallSiteDescriptor desc, final boolean explicitInstanceOfCheck) { if (!needsGuard(property, desc)) { return null; } if (NashornCallSiteDescriptor.isScope(desc)) { if (property != null && property.isBound() && !property.canChangeType()) { // This is a declared top level variables in main script or eval, use identity guard. return getIdentityGuard(sobj); } if (!(sobj instanceof Global) && (property == null || property.isConfigurable())) { // Undeclared variables in nested evals need stronger guards return combineGuards(getIdentityGuard(sobj), getMapGuard(sobj.getMap(), explicitInstanceOfCheck)); } } return getMapGuard(sobj.getMap(), explicitInstanceOfCheck); }
private PropertyMap addObjectProperty(final PropertyMap propertyMap, final List<Object> values, final String id, final Object value) { final Property oldProperty = propertyMap.findProperty(id); final PropertyMap newMap; final Class<?> type; final int flags; if (dualFields) { type = getType(value); flags = Property.DUAL_FIELDS; } else { type = Object.class; flags = 0; } if (oldProperty != null) { values.set(oldProperty.getSlot(), value); newMap = propertyMap.replaceProperty(oldProperty, new SpillProperty(id, flags, oldProperty.getSlot(), type));; } else { values.add(value); newMap = propertyMap.addProperty(new SpillProperty(id, flags, propertyMap.size(), type)); } return newMap; }
private Object createObject(final PropertyMap propertyMap, final List<Object> values, final ArrayData arrayData) { final long[] primitiveSpill = dualFields ? new long[values.size()] : null; final Object[] objectSpill = new Object[values.size()]; for (final Property property : propertyMap.getProperties()) { if (!dualFields || property.getType() == Object.class) { objectSpill[property.getSlot()] = values.get(property.getSlot()); } else { primitiveSpill[property.getSlot()] = ObjectClassGenerator.pack((Number) values.get(property.getSlot())); } } final ScriptObject object = dualFields ? new JD(propertyMap, primitiveSpill, objectSpill) : new JO(propertyMap, null, objectSpill); object.setInitialProto(global.getObjectPrototype()); object.setArray(arrayData); return object; }
/** * Get the guard for a property access. This returns an identity guard for non-configurable global properties * and a map guard for everything else. * * @param sobj the first object in the prototype chain * @param property the property * @param desc the callsite descriptor * @param explicitInstanceOfCheck true if we should do an explicit script object instanceof check instead of just casting * @return method handle for guard */ public static MethodHandle getGuard(final ScriptObject sobj, final Property property, final CallSiteDescriptor desc, final boolean explicitInstanceOfCheck) { if (!needsGuard(property, desc)) { return null; } if (NashornCallSiteDescriptor.isScope(desc) && sobj.isScope()) { if (property != null && property.isBound() && !property.canChangeType()) { // This is a declared top level variables in main script or eval, use identity guard. return getIdentityGuard(sobj); } if (!(sobj instanceof Global) && (property == null || property.isConfigurable())) { // Undeclared variables in nested evals need stronger guards return combineGuards(getIdentityGuard(sobj), getMapGuard(sobj.getMap(), explicitInstanceOfCheck)); } } return getMapGuard(sobj.getMap(), explicitInstanceOfCheck); }
/** * Runs launches "fx:bootstrap.js" with the given JavaScript files provided * as arguments. * * @param context the nashorn context * @param global the global scope * @param files the list of script files to provide * * @return error code * @throws IOException when any script file read results in I/O error */ private static int runFXScripts(final Context context, final Global global, final List<String> files) throws IOException { final Global oldGlobal = Context.getGlobal(); final boolean globalChanged = (oldGlobal != global); try { if (globalChanged) { Context.setGlobal(global); } global.addOwnProperty("$GLOBAL", Property.NOT_ENUMERABLE, global); global.addOwnProperty("$SCRIPTS", Property.NOT_ENUMERABLE, files); context.load(global, "fx:bootstrap.js"); } catch (final NashornException e) { context.getErrorManager().error(e.toString()); if (context.getEnv()._dump_on_error) { e.printStackTrace(context.getErr()); } return RUNTIME_ERROR; } finally { context.getOut().flush(); context.getErr().flush(); if (globalChanged) { Context.setGlobal(oldGlobal); } } return SUCCESS; }
/** * Compute property flags given local state of a field. May be overridden and extended, * * @param symbol symbol to check * @param hasArguments does the created object have an "arguments" property * * @return flags to use for fields */ protected int getPropertyFlags(final Symbol symbol, final boolean hasArguments) { int flags = 0; if (symbol.isParam()) { flags |= Property.IS_ALWAYS_OBJECT | Property.IS_PARAMETER; } if (hasArguments) { flags |= Property.IS_ALWAYS_OBJECT | Property.HAS_ARGUMENTS; } if (symbol.isScope()) { flags |= Property.NOT_CONFIGURABLE; } if (symbol.canBePrimitive()) { flags |= Property.CAN_BE_PRIMITIVE; } if (symbol.canBeUndefined()) { flags |= Property.CAN_BE_UNDEFINED; } return flags; }
private static PropertyMap createStrictModeMap(final PropertyMap map) { final int flags = Property.NOT_ENUMERABLE | Property.NOT_CONFIGURABLE; PropertyMap newMap = map; // Need to add properties directly to map since slots are assigned speculatively by newUserAccessors. newMap = newMap.addPropertyNoHistory(map.newUserAccessors("arguments", flags)); newMap = newMap.addPropertyNoHistory(map.newUserAccessors("caller", flags)); return newMap; }
/** * ECMA 15.2.4.7 Object.prototype.propertyIsEnumerable (V) * * @param self self reference * @param v property to check if enumerable * @return true if property is enumerable */ @Function(attributes = Attribute.NOT_ENUMERABLE) public static boolean propertyIsEnumerable(final Object self, final Object v) { final String str = JSType.toString(v); final Object obj = Global.toObject(self); if (obj instanceof ScriptObject) { final jdk.nashorn.internal.runtime.Property property = ((ScriptObject)obj).getMap().findProperty(str); return property != null && property.isEnumerable(); } return false; }
private static Type getPropertyType(final ScriptObject sobj, final String name) { final FindProperty find = sobj.findProperty(name, true); if (find == null) { return null; } final Property property = find.getProperty(); final Class<?> propertyClass = property.getType(); if (propertyClass == null) { // propertyClass == null means its value is Undefined. It is probably not initialized yet, so we won't make // a type assumption yet. return null; } else if (propertyClass.isPrimitive()) { return Type.typeFor(propertyClass); } final ScriptObject owner = find.getOwner(); if (property.hasGetterFunction(owner)) { // Can have side effects, so we can't safely evaluate it; since !propertyClass.isPrimitive(), it's Object. return Type.OBJECT; } // Safely evaluate the property, and return the narrowest type for the actual value (e.g. Type.INT for a boxed // integer). final Object value = property.needsDeclaration() ? ScriptRuntime.UNDEFINED : property.getObjectValue(owner, owner); if (value == ScriptRuntime.UNDEFINED) { return null; } return Type.typeFor(JSType.unboxedFieldType(value)); }
private static Object evaluatePropertySafely(final ScriptObject sobj, final String name) { final FindProperty find = sobj.findProperty(name, true); if (find == null) { return null; } final Property property = find.getProperty(); final ScriptObject owner = find.getOwner(); if (property.hasGetterFunction(owner)) { // Possible side effects; can't evaluate safely return null; } return property.getObjectValue(owner, owner); }