Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
org.htmlunit.corejs.javascript.NativeReflect Maven / Gradle / Ivy
/* -*- Mode: java; tab-width: 4; indent-tabs-mode: 1; c-basic-offset: 4 -*-
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.htmlunit.corejs.javascript;
import java.util.ArrayList;
import java.util.List;
/**
* This class implements the Reflect object.
*
* @author Ronald Brill
*/
final class NativeReflect extends ScriptableObject {
private static final long serialVersionUID = 2920773905356325445L;
private static final String REFLECT_TAG = "Reflect";
public static void init(Context cx, Scriptable scope, boolean sealed) {
NativeReflect reflect = new NativeReflect();
reflect.setPrototype(getObjectPrototype(scope));
reflect.setParentScope(scope);
reflect.defineProperty(
scope, "apply", 3, NativeReflect::apply, DONTENUM, DONTENUM | READONLY);
reflect.defineProperty(
scope, "construct", 2, NativeReflect::construct, DONTENUM, DONTENUM | READONLY);
reflect.defineProperty(
scope,
"defineProperty",
3,
NativeReflect::defineProperty,
DONTENUM,
DONTENUM | READONLY);
reflect.defineProperty(
scope,
"deleteProperty",
2,
NativeReflect::deleteProperty,
DONTENUM,
DONTENUM | READONLY);
reflect.defineProperty(scope, "get", 2, NativeReflect::get, DONTENUM, DONTENUM | READONLY);
reflect.defineProperty(
scope,
"getOwnPropertyDescriptor",
2,
NativeReflect::getOwnPropertyDescriptor,
DONTENUM,
DONTENUM | READONLY);
reflect.defineProperty(
scope,
"getPrototypeOf",
1,
NativeReflect::getPrototypeOf,
DONTENUM,
DONTENUM | READONLY);
reflect.defineProperty(scope, "has", 2, NativeReflect::has, DONTENUM, DONTENUM | READONLY);
reflect.defineProperty(
scope,
"isExtensible",
1,
NativeReflect::isExtensible,
DONTENUM,
DONTENUM | READONLY);
reflect.defineProperty(
scope, "ownKeys", 1, NativeReflect::ownKeys, DONTENUM, DONTENUM | READONLY);
reflect.defineProperty(
scope,
"preventExtensions",
1,
NativeReflect::preventExtensions,
DONTENUM,
DONTENUM | READONLY);
reflect.defineProperty(scope, "set", 3, NativeReflect::set, DONTENUM, DONTENUM | READONLY);
reflect.defineProperty(
scope,
"setPrototypeOf",
2,
NativeReflect::setPrototypeOf,
DONTENUM,
DONTENUM | READONLY);
reflect.defineProperty(SymbolKey.TO_STRING_TAG, REFLECT_TAG, DONTENUM | READONLY);
ScriptableObject.defineProperty(scope, REFLECT_TAG, reflect, DONTENUM);
if (sealed) {
reflect.sealObject();
}
}
private NativeReflect() {}
@Override
public String getClassName() {
return "Reflect";
}
private static Object apply(Context cx, Scriptable scope, Scriptable thisObj, Object[] args) {
if (args.length < 3) {
throw ScriptRuntime.typeErrorById(
"msg.method.missing.parameter",
"Reflect.apply",
"3",
Integer.toString(args.length));
}
Scriptable callable = ScriptableObject.ensureScriptable(args[0]);
if (args[1] instanceof Scriptable) {
thisObj = (Scriptable) args[1];
} else if (ScriptRuntime.isPrimitive(args[1])) {
thisObj = cx.newObject(scope, "Object", new Object[] {args[1]});
}
if (ScriptRuntime.isSymbol(args[2])) {
throw ScriptRuntime.typeErrorById("msg.arg.not.object", ScriptRuntime.typeof(args[2]));
}
ScriptableObject argumentsList = ScriptableObject.ensureScriptableObject(args[2]);
return ScriptRuntime.applyOrCall(
true, cx, scope, callable, new Object[] {thisObj, argumentsList});
}
/** see https://262.ecma-international.org/12.0/#sec-reflect.construct */
private static Scriptable construct(
Context cx, Scriptable scope, Scriptable thisObj, Object[] args) {
/*
* 1. If IsConstructor(target) is false, throw a TypeError exception.
* 2. If newTarget is not present, set newTarget to target.
* 3. Else if IsConstructor(newTarget) is false, throw a TypeError exception.
* 4. Let args be ? CreateListFromArrayLike(argumentsList).
* 5. Return ? Construct(target, args, newTarget).
*/
if (args.length < 1) {
throw ScriptRuntime.typeErrorById(
"msg.method.missing.parameter",
"Reflect.construct",
"3",
Integer.toString(args.length));
}
if (!(args[0] instanceof Constructable)) {
throw ScriptRuntime.typeErrorById("msg.not.ctor", ScriptRuntime.typeof(args[0]));
}
Constructable ctor = (Constructable) args[0];
if (args.length < 2) {
return ctor.construct(cx, scope, ScriptRuntime.emptyArgs);
}
if (args.length > 2 && !(args[2] instanceof Constructable)) {
throw ScriptRuntime.typeErrorById("msg.not.ctor", ScriptRuntime.typeof(args[2]));
}
Object[] callArgs = ScriptRuntime.getApplyArguments(cx, args[1]);
Object newTargetPrototype = null;
if (args.length > 2) {
Scriptable newTarget = ScriptableObject.ensureScriptable(args[2]);
if (newTarget instanceof BaseFunction) {
newTargetPrototype = ((BaseFunction) newTarget).getPrototypeProperty();
} else {
newTargetPrototype = newTarget.get("prototype", newTarget);
}
if (!(newTargetPrototype instanceof Scriptable)
|| ScriptRuntime.isSymbol(newTargetPrototype)
|| Undefined.isUndefined(newTargetPrototype)) {
newTargetPrototype = null;
}
}
// hack to set the right prototype before calling the ctor
if (ctor instanceof BaseFunction && newTargetPrototype != null) {
BaseFunction ctorBaseFunction = (BaseFunction) ctor;
Scriptable result = ctorBaseFunction.createObject(cx, scope);
if (result != null) {
result.setPrototype((Scriptable) newTargetPrototype);
Object val = ctorBaseFunction.call(cx, scope, result, callArgs);
if (val instanceof Scriptable) {
return (Scriptable) val;
}
return result;
}
}
Scriptable newScriptable = ctor.construct(cx, scope, callArgs);
if (newTargetPrototype != null) {
newScriptable.setPrototype((Scriptable) newTargetPrototype);
}
return newScriptable;
}
private static Object defineProperty(
Context cx, Scriptable scope, Scriptable thisObj, Object[] args) {
if (args.length < 3) {
throw ScriptRuntime.typeErrorById(
"msg.method.missing.parameter",
"Reflect.defineProperty",
"3",
Integer.toString(args.length));
}
ScriptableObject target = checkTarget(args);
ScriptableObject desc = ScriptableObject.ensureScriptableObject(args[2]);
try {
return target.defineOwnProperty(cx, args[1], desc);
} catch (EcmaError e) {
return false;
}
}
private static Object deleteProperty(
Context cx, Scriptable scope, Scriptable thisObj, Object[] args) {
ScriptableObject target = checkTarget(args);
if (args.length > 1) {
if (ScriptRuntime.isSymbol(args[1])) {
return ScriptableObject.deleteProperty(target, (Symbol) args[1]);
}
return ScriptableObject.deleteProperty(target, ScriptRuntime.toString(args[1]));
}
return false;
}
private static Object get(Context cx, Scriptable scope, Scriptable thisObj, Object[] args) {
ScriptableObject target = checkTarget(args);
if (args.length > 1) {
if (ScriptRuntime.isSymbol(args[1])) {
Object prop = ScriptableObject.getProperty(target, (Symbol) args[1]);
return prop == Scriptable.NOT_FOUND ? Undefined.SCRIPTABLE_UNDEFINED : prop;
}
if (args[1] instanceof Double) {
Object prop = ScriptableObject.getProperty(target, ScriptRuntime.toIndex(args[1]));
return prop == Scriptable.NOT_FOUND ? Undefined.SCRIPTABLE_UNDEFINED : prop;
}
Object prop = ScriptableObject.getProperty(target, ScriptRuntime.toString(args[1]));
return prop == Scriptable.NOT_FOUND ? Undefined.SCRIPTABLE_UNDEFINED : prop;
}
return Undefined.SCRIPTABLE_UNDEFINED;
}
private static Scriptable getOwnPropertyDescriptor(
Context cx, Scriptable scope, Scriptable thisObj, Object[] args) {
ScriptableObject target = checkTarget(args);
if (args.length > 1) {
if (ScriptRuntime.isSymbol(args[1])) {
ScriptableObject desc = target.getOwnPropertyDescriptor(cx, args[1]);
return desc == null ? Undefined.SCRIPTABLE_UNDEFINED : desc;
}
ScriptableObject desc =
target.getOwnPropertyDescriptor(cx, ScriptRuntime.toString(args[1]));
return desc == null ? Undefined.SCRIPTABLE_UNDEFINED : desc;
}
return Undefined.SCRIPTABLE_UNDEFINED;
}
private static Scriptable getPrototypeOf(
Context cx, Scriptable scope, Scriptable thisObj, Object[] args) {
ScriptableObject target = checkTarget(args);
return target.getPrototype();
}
private static Object has(Context cx, Scriptable scope, Scriptable thisObj, Object[] args) {
ScriptableObject target = checkTarget(args);
if (args.length > 1) {
if (ScriptRuntime.isSymbol(args[1])) {
return ScriptableObject.hasProperty(target, (Symbol) args[1]);
}
return ScriptableObject.hasProperty(target, ScriptRuntime.toString(args[1]));
}
return false;
}
private static Object isExtensible(
Context cx, Scriptable scope, Scriptable thisObj, Object[] args) {
ScriptableObject target = checkTarget(args);
return target.isExtensible();
}
private static Scriptable ownKeys(
Context cx, Scriptable scope, Scriptable thisObj, Object[] args) {
ScriptableObject target = checkTarget(args);
final List strings = new ArrayList<>();
final List symbols = new ArrayList<>();
for (Object o : target.getIds(true, true)) {
if (o instanceof Symbol) {
symbols.add(o);
} else {
strings.add(ScriptRuntime.toString(o));
}
}
Object[] keys = new Object[strings.size() + symbols.size()];
System.arraycopy(strings.toArray(), 0, keys, 0, strings.size());
System.arraycopy(symbols.toArray(), 0, keys, strings.size(), symbols.size());
return cx.newArray(scope, keys);
}
private static Object preventExtensions(
Context cx, Scriptable scope, Scriptable thisObj, Object[] args) {
ScriptableObject target = checkTarget(args);
return target.preventExtensions();
}
private static Object set(Context cx, Scriptable scope, Scriptable thisObj, Object[] args) {
ScriptableObject target = checkTarget(args);
if (args.length < 2) {
return true;
}
ScriptableObject receiver =
args.length > 3 ? ScriptableObject.ensureScriptableObject(args[3]) : target;
if (receiver != target) {
ScriptableObject descriptor = target.getOwnPropertyDescriptor(cx, args[1]);
if (descriptor != null) {
Object setter = descriptor.get("set");
if (setter != null && setter != NOT_FOUND) {
((Function) setter).call(cx, scope, receiver, new Object[] {args[2]});
return true;
}
if (Boolean.FALSE.equals(descriptor.get("configurable"))) {
return false;
}
}
}
if (ScriptRuntime.isSymbol(args[1])) {
receiver.put((Symbol) args[1], receiver, args[2]);
} else if (args[1] instanceof Double) {
receiver.put(ScriptRuntime.toIndex(args[1]), receiver, args[2]);
} else {
receiver.put(ScriptRuntime.toString(args[1]), receiver, args[2]);
}
return true;
}
private static Object setPrototypeOf(
Context cx, Scriptable scope, Scriptable thisObj, Object[] args) {
if (args.length < 2) {
throw ScriptRuntime.typeErrorById(
"msg.method.missing.parameter",
"Reflect.js_setPrototypeOf",
"2",
Integer.toString(args.length));
}
ScriptableObject target = checkTarget(args);
if (target.getPrototype() == args[1]) {
return true;
}
if (!target.isExtensible()) {
return false;
}
if (args[1] == null) {
target.setPrototype(null);
return true;
}
if (ScriptRuntime.isSymbol(args[1])) {
throw ScriptRuntime.typeErrorById("msg.arg.not.object", ScriptRuntime.typeof(args[0]));
}
ScriptableObject proto = ScriptableObject.ensureScriptableObject(args[1]);
if (target.getPrototype() == proto) {
return true;
}
// avoid cycles
Scriptable p = proto;
while (p != null) {
if (target == p) {
return false;
}
p = p.getPrototype();
}
target.setPrototype(proto);
return true;
}
private static ScriptableObject checkTarget(Object[] args) {
if (args.length == 0 || args[0] == null || args[0] == Undefined.instance) {
Object argument = args.length == 0 ? Undefined.instance : args[0];
throw ScriptRuntime.typeErrorById(
"msg.no.properties", ScriptRuntime.toString(argument));
}
if (ScriptRuntime.isSymbol(args[0])) {
throw ScriptRuntime.typeErrorById("msg.arg.not.object", ScriptRuntime.typeof(args[0]));
}
return ScriptableObject.ensureScriptableObject(args[0]);
}
}