package com.oracle.truffle.js.builtins;
import java.nio.ByteBuffer;
import java.util.EnumSet;
import java.util.LinkedHashMap;
import java.util.Objects;
import java.util.StringJoiner;
import com.oracle.truffle.api.Assumption;
import com.oracle.truffle.api.CompilerAsserts;
import com.oracle.truffle.api.CompilerDirectives;
import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
import com.oracle.truffle.api.Truffle;
import com.oracle.truffle.api.dsl.Bind;
import com.oracle.truffle.api.dsl.Cached;
import com.oracle.truffle.api.dsl.Fallback;
import com.oracle.truffle.api.dsl.ImportStatic;
import com.oracle.truffle.api.dsl.Specialization;
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.interop.InteropLibrary;
import com.oracle.truffle.api.interop.TruffleObject;
import com.oracle.truffle.api.interop.UnsupportedMessageException;
import com.oracle.truffle.api.library.CachedLibrary;
import com.oracle.truffle.api.object.DynamicObject;
import com.oracle.truffle.api.profiles.BranchProfile;
import com.oracle.truffle.api.profiles.ConditionProfile;
import com.oracle.truffle.js.builtins.ConstructorBuiltinsFactory.CallBigIntNodeGen;
import com.oracle.truffle.js.builtins.ConstructorBuiltinsFactory.CallBooleanNodeGen;
import com.oracle.truffle.js.builtins.ConstructorBuiltinsFactory.CallCollatorNodeGen;
import com.oracle.truffle.js.builtins.ConstructorBuiltinsFactory.CallDateNodeGen;
import com.oracle.truffle.js.builtins.ConstructorBuiltinsFactory.CallDateTimeFormatNodeGen;
import com.oracle.truffle.js.builtins.ConstructorBuiltinsFactory.CallNumberFormatNodeGen;
import com.oracle.truffle.js.builtins.ConstructorBuiltinsFactory.CallNumberNodeGen;
import com.oracle.truffle.js.builtins.ConstructorBuiltinsFactory.CallRequiresNewNodeGen;
import com.oracle.truffle.js.builtins.ConstructorBuiltinsFactory.CallStringNodeGen;
import com.oracle.truffle.js.builtins.ConstructorBuiltinsFactory.CallSymbolNodeGen;
import com.oracle.truffle.js.builtins.ConstructorBuiltinsFactory.CallTypedArrayNodeGen;
import com.oracle.truffle.js.builtins.ConstructorBuiltinsFactory.ConstructAggregateErrorNodeGen;
import com.oracle.truffle.js.builtins.ConstructorBuiltinsFactory.ConstructArrayBufferNodeGen;
import com.oracle.truffle.js.builtins.ConstructorBuiltinsFactory.ConstructArrayNodeGen;
import com.oracle.truffle.js.builtins.ConstructorBuiltinsFactory.ConstructBigIntNodeGen;
import com.oracle.truffle.js.builtins.ConstructorBuiltinsFactory.ConstructBooleanNodeGen;
import com.oracle.truffle.js.builtins.ConstructorBuiltinsFactory.ConstructCollatorNodeGen;
import com.oracle.truffle.js.builtins.ConstructorBuiltinsFactory.ConstructDataViewNodeGen;
import com.oracle.truffle.js.builtins.ConstructorBuiltinsFactory.ConstructDateNodeGen;
import com.oracle.truffle.js.builtins.ConstructorBuiltinsFactory.ConstructDateTimeFormatNodeGen;
import com.oracle.truffle.js.builtins.ConstructorBuiltinsFactory.ConstructDisplayNamesNodeGen;
import com.oracle.truffle.js.builtins.ConstructorBuiltinsFactory.ConstructErrorNodeGen;
import com.oracle.truffle.js.builtins.ConstructorBuiltinsFactory.ConstructFinalizationRegistryNodeGen;
import com.oracle.truffle.js.builtins.ConstructorBuiltinsFactory.ConstructFunctionNodeGen;
import com.oracle.truffle.js.builtins.ConstructorBuiltinsFactory.ConstructJSAdapterNodeGen;
import com.oracle.truffle.js.builtins.ConstructorBuiltinsFactory.ConstructJSProxyNodeGen;
import com.oracle.truffle.js.builtins.ConstructorBuiltinsFactory.ConstructJavaImporterNodeGen;
import com.oracle.truffle.js.builtins.ConstructorBuiltinsFactory.ConstructListFormatNodeGen;
import com.oracle.truffle.js.builtins.ConstructorBuiltinsFactory.ConstructLocaleNodeGen;
import com.oracle.truffle.js.builtins.ConstructorBuiltinsFactory.ConstructMapNodeGen;
import com.oracle.truffle.js.builtins.ConstructorBuiltinsFactory.ConstructNumberFormatNodeGen;
import com.oracle.truffle.js.builtins.ConstructorBuiltinsFactory.ConstructNumberNodeGen;
import com.oracle.truffle.js.builtins.ConstructorBuiltinsFactory.ConstructObjectNodeGen;
import com.oracle.truffle.js.builtins.ConstructorBuiltinsFactory.ConstructPluralRulesNodeGen;
import com.oracle.truffle.js.builtins.ConstructorBuiltinsFactory.ConstructRegExpNodeGen;
import com.oracle.truffle.js.builtins.ConstructorBuiltinsFactory.ConstructRelativeTimeFormatNodeGen;
import com.oracle.truffle.js.builtins.ConstructorBuiltinsFactory.ConstructSegmenterNodeGen;
import com.oracle.truffle.js.builtins.ConstructorBuiltinsFactory.ConstructSetNodeGen;
import com.oracle.truffle.js.builtins.ConstructorBuiltinsFactory.ConstructStringNodeGen;
import com.oracle.truffle.js.builtins.ConstructorBuiltinsFactory.ConstructSymbolNodeGen;
import com.oracle.truffle.js.builtins.ConstructorBuiltinsFactory.ConstructWeakMapNodeGen;
import com.oracle.truffle.js.builtins.ConstructorBuiltinsFactory.ConstructWeakRefNodeGen;
import com.oracle.truffle.js.builtins.ConstructorBuiltinsFactory.ConstructWeakSetNodeGen;
import com.oracle.truffle.js.builtins.ConstructorBuiltinsFactory.CreateDynamicFunctionNodeGen;
import com.oracle.truffle.js.builtins.ConstructorBuiltinsFactory.PromiseConstructorNodeGen;
import com.oracle.truffle.js.nodes.CompileRegexNode;
import com.oracle.truffle.js.nodes.JSGuards;
import com.oracle.truffle.js.nodes.JavaScriptBaseNode;
import com.oracle.truffle.js.nodes.JavaScriptNode;
import com.oracle.truffle.js.nodes.ScriptNode;
import com.oracle.truffle.js.nodes.access.ArrayLiteralNode;
import com.oracle.truffle.js.nodes.access.ArrayLiteralNode.ArrayContentType;
import com.oracle.truffle.js.nodes.access.ErrorStackTraceLimitNode;
import com.oracle.truffle.js.nodes.access.GetIteratorNode;
import com.oracle.truffle.js.nodes.access.GetMethodNode;
import com.oracle.truffle.js.nodes.access.GetPrototypeFromConstructorNode;
import com.oracle.truffle.js.nodes.access.InitErrorObjectNode;
import com.oracle.truffle.js.nodes.access.IsJSObjectNode;
import com.oracle.truffle.js.nodes.access.IsRegExpNode;
import com.oracle.truffle.js.nodes.access.IteratorCloseNode;
import com.oracle.truffle.js.nodes.access.IteratorStepNode;
import com.oracle.truffle.js.nodes.access.IteratorValueNode;
import com.oracle.truffle.js.nodes.access.OrdinaryCreateFromConstructorNode;
import com.oracle.truffle.js.nodes.access.PropertyGetNode;
import com.oracle.truffle.js.nodes.access.PropertySetNode;
import com.oracle.truffle.js.nodes.access.ReadElementNode;
import com.oracle.truffle.js.nodes.array.ArrayCreateNode;
import com.oracle.truffle.js.nodes.cast.JSNumberToBigIntNode;
import com.oracle.truffle.js.nodes.cast.JSNumericToNumberNode;
import com.oracle.truffle.js.nodes.cast.JSToBigIntNode;
import com.oracle.truffle.js.nodes.cast.JSToBooleanNode;
import com.oracle.truffle.js.nodes.cast.JSToDoubleNode;
import com.oracle.truffle.js.nodes.cast.JSToIndexNode;
import com.oracle.truffle.js.nodes.cast.JSToNumericNode;
import com.oracle.truffle.js.nodes.cast.JSToObjectNode;
import com.oracle.truffle.js.nodes.cast.JSToPrimitiveNode;
import com.oracle.truffle.js.nodes.cast.JSToPrimitiveNode.Hint;
import com.oracle.truffle.js.nodes.cast.JSToStringNode;
import com.oracle.truffle.js.nodes.cast.ToArrayLengthNode;
import com.oracle.truffle.js.nodes.function.EvalNode;
import com.oracle.truffle.js.nodes.function.JSBuiltin;
import com.oracle.truffle.js.nodes.function.JSBuiltinNode;
import com.oracle.truffle.js.nodes.function.JSFunctionCallNode;
import com.oracle.truffle.js.nodes.intl.CreateRegExpNode;
import com.oracle.truffle.js.nodes.intl.InitializeCollatorNode;
import com.oracle.truffle.js.nodes.intl.InitializeDateTimeFormatNode;
import com.oracle.truffle.js.nodes.intl.InitializeDisplayNamesNode;
import com.oracle.truffle.js.nodes.intl.InitializeListFormatNode;
import com.oracle.truffle.js.nodes.intl.InitializeLocaleNode;
import com.oracle.truffle.js.nodes.intl.InitializeNumberFormatNode;
import com.oracle.truffle.js.nodes.intl.InitializePluralRulesNode;
import com.oracle.truffle.js.nodes.intl.InitializeRelativeTimeFormatNode;
import com.oracle.truffle.js.nodes.intl.InitializeSegmenterNode;
import com.oracle.truffle.js.nodes.promise.PromiseResolveThenableNode;
import com.oracle.truffle.js.nodes.unary.IsCallableNode;
import com.oracle.truffle.js.runtime.BigInt;
import com.oracle.truffle.js.runtime.Boundaries;
import com.oracle.truffle.js.runtime.Errors;
import com.oracle.truffle.js.runtime.Evaluator;
import com.oracle.truffle.js.runtime.GraalJSException;
import com.oracle.truffle.js.runtime.JSArguments;
import com.oracle.truffle.js.runtime.JSConfig;
import com.oracle.truffle.js.runtime.JSContext;
import com.oracle.truffle.js.runtime.JSErrorType;
import com.oracle.truffle.js.runtime.JSException;
import com.oracle.truffle.js.runtime.JSRealm;
import com.oracle.truffle.js.runtime.JSRuntime;
import com.oracle.truffle.js.runtime.PromiseHook;
import com.oracle.truffle.js.runtime.SafeInteger;
import com.oracle.truffle.js.runtime.Symbol;
import com.oracle.truffle.js.runtime.array.ArrayAllocationSite;
import com.oracle.truffle.js.runtime.array.ScriptArray;
import com.oracle.truffle.js.runtime.array.dyn.AbstractWritableArray;
import com.oracle.truffle.js.runtime.array.dyn.ConstantObjectArray;
import com.oracle.truffle.js.runtime.builtins.BuiltinEnum;
import com.oracle.truffle.js.runtime.builtins.JSAdapter;
import com.oracle.truffle.js.runtime.builtins.JSArray;
import com.oracle.truffle.js.runtime.builtins.JSArrayBuffer;
import com.oracle.truffle.js.runtime.builtins.JSBoolean;
import com.oracle.truffle.js.runtime.builtins.JSDataView;
import com.oracle.truffle.js.runtime.builtins.JSDate;
import com.oracle.truffle.js.runtime.builtins.JSError;
import com.oracle.truffle.js.runtime.builtins.JSFinalizationRegistry;
import com.oracle.truffle.js.runtime.builtins.JSFunction;
import com.oracle.truffle.js.runtime.builtins.JSMap;
import com.oracle.truffle.js.runtime.builtins.JSNumber;
import com.oracle.truffle.js.runtime.builtins.JSPromise;
import com.oracle.truffle.js.runtime.builtins.JSProxy;
import com.oracle.truffle.js.runtime.builtins.JSRegExp;
import com.oracle.truffle.js.runtime.builtins.JSSet;
import com.oracle.truffle.js.runtime.builtins.JSSharedArrayBuffer;
import com.oracle.truffle.js.runtime.builtins.JSString;
import com.oracle.truffle.js.runtime.builtins.JSOrdinary;
import com.oracle.truffle.js.runtime.builtins.JSWeakMap;
import com.oracle.truffle.js.runtime.builtins.JSWeakRef;
import com.oracle.truffle.js.runtime.builtins.JSWeakSet;
import com.oracle.truffle.js.runtime.builtins.intl.JSCollator;
import com.oracle.truffle.js.runtime.builtins.intl.JSDateTimeFormat;
import com.oracle.truffle.js.runtime.builtins.intl.JSDisplayNames;
import com.oracle.truffle.js.runtime.builtins.intl.JSListFormat;
import com.oracle.truffle.js.runtime.builtins.intl.JSLocale;
import com.oracle.truffle.js.runtime.builtins.intl.JSNumberFormat;
import com.oracle.truffle.js.runtime.builtins.intl.JSPluralRules;
import com.oracle.truffle.js.runtime.builtins.intl.JSRelativeTimeFormat;
import com.oracle.truffle.js.runtime.builtins.intl.JSSegmenter;
import com.oracle.truffle.js.runtime.java.JavaImporter;
import com.oracle.truffle.js.runtime.java.JavaPackage;
import com.oracle.truffle.js.runtime.objects.IteratorRecord;
import com.oracle.truffle.js.runtime.objects.JSDynamicObject;
import com.oracle.truffle.js.runtime.objects.JSLazyString;
import com.oracle.truffle.js.runtime.objects.JSObject;
import com.oracle.truffle.js.runtime.objects.Null;
import com.oracle.truffle.js.runtime.objects.Undefined;
import com.oracle.truffle.js.runtime.util.SimpleArrayList;
import com.oracle.truffle.js.runtime.util.TRegexUtil;
public final class ConstructorBuiltins extends JSBuiltinsContainer.SwitchEnum<ConstructorBuiltins.Constructor> {
public static final JSBuiltinsContainer BUILTINS = new ConstructorBuiltins();
protected ConstructorBuiltins() {
super(null, Constructor.class);
}
public enum Constructor implements BuiltinEnum<Constructor> {
Array(1),
Boolean(1),
Date(7),
RegExp(2),
String(1),
Object(1),
Number(1),
BigInt(1),
Function(1),
ArrayBuffer(1),
Collator(0),
NumberFormat(0),
ListFormat(0),
PluralRules(0),
DateTimeFormat(0),
RelativeTimeFormat(0),
Segmenter(0),
DisplayNames(2),
Locale(1),
Error(1),
RangeError(1),
TypeError(1),
ReferenceError(1),
SyntaxError(1),
EvalError(1),
URIError(1),
AggregateError(2),
Int8Array(3),
Uint8Array(3),
Uint8ClampedArray(3),
Int16Array(3),
Uint16Array(3),
Int32Array(3),
Uint32Array(3),
Float32Array(3),
Float64Array(3),
BigInt64Array(3),
BigUint64Array(3),
DataView(1),
Map(0),
Set(0),
WeakRef(1),
FinalizationRegistry(1),
WeakMap(0),
WeakSet(0),
GeneratorFunction(1),
Proxy(2),
Promise(1),
AsyncFunction(1),
SharedArrayBuffer(1),
AsyncGeneratorFunction(1),
TypedArray(0),
Symbol(0),
JSAdapter(1),
JavaImporter(1);
private final int length;
Constructor(int length) {
this.length = length;
}
@Override
public int getLength() {
return length;
}
@Override
public boolean isConstructor() {
return true;
}
@Override
public boolean isNewTargetConstructor() {
return EnumSet.range(Array, AsyncGeneratorFunction).contains(this);
}
@Override
public int getECMAScriptVersion() {
if (AsyncGeneratorFunction == this) {
return JSConfig.ECMAScript2018;
} else if (EnumSet.of(SharedArrayBuffer, AsyncFunction).contains(this)) {
return JSConfig.ECMAScript2017;
} else if (EnumSet.range(Map, Symbol).contains(this)) {
return 6;
}
return BuiltinEnum.super.getECMAScriptVersion();
}
}
@Override
protected Object createNode(JSContext context, JSBuiltin builtin, boolean construct, boolean newTarget, Constructor builtinEnum) {
switch (builtinEnum) {
case Array:
if (newTarget) {
return ConstructArrayNodeGen.create(context, builtin, true, args().newTarget().varArgs().createArgumentNodes(context));
}
return ConstructArrayNodeGen.create(context, builtin, false, args().function().varArgs().createArgumentNodes(context));
case Boolean:
return construct ? (newTarget
? ConstructBooleanNodeGen.create(context, builtin, true, args().newTarget().fixedArgs(1).createArgumentNodes(context))
: ConstructBooleanNodeGen.create(context, builtin, false, args().function().fixedArgs(1).createArgumentNodes(context)))
: CallBooleanNodeGen.create(context, builtin, args().fixedArgs(1).createArgumentNodes(context));
case Date:
return construct ? (newTarget
? ConstructDateNodeGen.create(context, builtin, true, args().newTarget().varArgs().createArgumentNodes(context))
: ConstructDateNodeGen.create(context, builtin, false, args().function().varArgs().createArgumentNodes(context)))
: CallDateNodeGen.create(context, builtin, args().createArgumentNodes(context));
case RegExp:
return construct ? (newTarget
? ConstructRegExpNodeGen.create(context, builtin, false, true, args().newTarget().fixedArgs(2).createArgumentNodes(context))
: ConstructRegExpNodeGen.create(context, builtin, false, false, args().function().fixedArgs(2).createArgumentNodes(context)))
: ConstructRegExpNodeGen.create(context, builtin, true, false, args().function().fixedArgs(2).createArgumentNodes(context));
case String:
return construct ? (newTarget
? ConstructStringNodeGen.create(context, builtin, true, args().newTarget().varArgs().createArgumentNodes(context))
: ConstructStringNodeGen.create(context, builtin, false, args().function().varArgs().createArgumentNodes(context)))
: CallStringNodeGen.create(context, builtin, args().varArgs().createArgumentNodes(context));
case WeakRef:
if (construct) {
return newTarget ? ConstructWeakRefNodeGen.create(context, builtin, true, args().newTarget().fixedArgs(1).createArgumentNodes(context))
: ConstructWeakRefNodeGen.create(context, builtin, false, args().function().fixedArgs(1).createArgumentNodes(context));
} else {
return createCallRequiresNew(context, builtin);
}
case FinalizationRegistry:
if (construct) {
return newTarget ? ConstructFinalizationRegistryNodeGen.create(context, builtin, true, args().newTarget().fixedArgs(1).createArgumentNodes(context))
: ConstructFinalizationRegistryNodeGen.create(context, builtin, false, args().function().fixedArgs(1).createArgumentNodes(context));
} else {
return createCallRequiresNew(context, builtin);
}
case Collator:
return construct ? (newTarget
? ConstructCollatorNodeGen.create(context, builtin, true, args().newTarget().fixedArgs(2).createArgumentNodes(context))
: ConstructCollatorNodeGen.create(context, builtin, false, args().function().fixedArgs(2).createArgumentNodes(context)))
: CallCollatorNodeGen.create(context, builtin, args().fixedArgs(2).createArgumentNodes(context));
case ListFormat:
return construct ? (newTarget
? ConstructListFormatNodeGen.create(context, builtin, true, args().newTarget().fixedArgs(2).createArgumentNodes(context))
: ConstructListFormatNodeGen.create(context, builtin, false, args().function().fixedArgs(2).createArgumentNodes(context)))
: createCallRequiresNew(context, builtin);
case NumberFormat:
return construct ? (newTarget
? ConstructNumberFormatNodeGen.create(context, builtin, true, args().newTarget().fixedArgs(2).createArgumentNodes(context))
: ConstructNumberFormatNodeGen.create(context, builtin, false, args().function().fixedArgs(2).createArgumentNodes(context)))
: CallNumberFormatNodeGen.create(context, builtin, args().fixedArgs(2).createArgumentNodes(context));
case PluralRules:
return construct ? (newTarget
? ConstructPluralRulesNodeGen.create(context, builtin, true, args().newTarget().fixedArgs(2).createArgumentNodes(context))
: ConstructPluralRulesNodeGen.create(context, builtin, false, args().function().fixedArgs(2).createArgumentNodes(context)))
: createCallRequiresNew(context, builtin);
case DateTimeFormat:
return construct ? (newTarget
? ConstructDateTimeFormatNodeGen.create(context, builtin, true, args().newTarget().fixedArgs(2).createArgumentNodes(context))
: ConstructDateTimeFormatNodeGen.create(context, builtin, false, args().function().fixedArgs(2).createArgumentNodes(context)))
: CallDateTimeFormatNodeGen.create(context, builtin, args().fixedArgs(2).createArgumentNodes(context));
case RelativeTimeFormat:
return construct ? (newTarget
? ConstructRelativeTimeFormatNodeGen.create(context, builtin, true, args().newTarget().fixedArgs(2).createArgumentNodes(context))
: ConstructRelativeTimeFormatNodeGen.create(context, builtin, false, args().function().fixedArgs(2).createArgumentNodes(context)))
: createCallRequiresNew(context, builtin);
case Segmenter:
return construct ? (newTarget
? ConstructSegmenterNodeGen.create(context, builtin, true, args().newTarget().fixedArgs(2).createArgumentNodes(context))
: ConstructSegmenterNodeGen.create(context, builtin, false, args().function().fixedArgs(2).createArgumentNodes(context)))
: createCallRequiresNew(context, builtin);
case DisplayNames:
return construct ? (newTarget
? ConstructDisplayNamesNodeGen.create(context, builtin, true, args().newTarget().fixedArgs(2).createArgumentNodes(context))
: ConstructDisplayNamesNodeGen.create(context, builtin, false, args().function().fixedArgs(2).createArgumentNodes(context)))
: createCallRequiresNew(context, builtin);
case Locale:
return construct ? (newTarget
? ConstructLocaleNodeGen.create(context, builtin, true, args().newTarget().fixedArgs(2).createArgumentNodes(context))
: ConstructLocaleNodeGen.create(context, builtin, false, args().function().fixedArgs(2).createArgumentNodes(context)))
: createCallRequiresNew(context, builtin);
case Object:
if (newTarget) {
return ConstructObjectNodeGen.create(context, builtin, true, args().newTarget().varArgs().createArgumentNodes(context));
}
return ConstructObjectNodeGen.create(context, builtin, false, args().function().varArgs().createArgumentNodes(context));
case Number:
return construct ? (newTarget
? ConstructNumberNodeGen.create(context, builtin, true, args().newTarget().varArgs().createArgumentNodes(context))
: ConstructNumberNodeGen.create(context, builtin, false, args().function().varArgs().createArgumentNodes(context)))
: CallNumberNodeGen.create(context, builtin, args().varArgs().createArgumentNodes(context));
case BigInt:
return construct ? ConstructBigIntNodeGen.create(context, builtin, args().createArgumentNodes(context))
: CallBigIntNodeGen.create(context, builtin, args().varArgs().createArgumentNodes(context));
case Function:
if (newTarget) {
return ConstructFunctionNodeGen.create(context, builtin, false, false, true, args().newTarget().varArgs().createArgumentNodes(context));
}
return ConstructFunctionNodeGen.create(context, builtin, false, false, false, args().function().varArgs().createArgumentNodes(context));
case ArrayBuffer:
if (construct) {
return newTarget ? ConstructArrayBufferNodeGen.create(context, builtin, false, true, args().newTarget().fixedArgs(1).createArgumentNodes(context))
: ConstructArrayBufferNodeGen.create(context, builtin, false, false, args().function().fixedArgs(1).createArgumentNodes(context));
} else {
return createCallRequiresNew(context, builtin);
}
case Error:
case RangeError:
case TypeError:
case ReferenceError:
case SyntaxError:
case EvalError:
case URIError:
if (newTarget) {
return ConstructErrorNodeGen.create(context, builtin, true, args().newTarget().fixedArgs(1).createArgumentNodes(context));
}
return ConstructErrorNodeGen.create(context, builtin, false, args().function().fixedArgs(1).createArgumentNodes(context));
case AggregateError:
if (newTarget) {
return ConstructAggregateErrorNodeGen.create(context, builtin, true, args().newTarget().fixedArgs(2).createArgumentNodes(context));
}
return ConstructAggregateErrorNodeGen.create(context, builtin, false, args().function().fixedArgs(2).createArgumentNodes(context));
case TypedArray:
return CallTypedArrayNodeGen.create(context, builtin, args().varArgs().createArgumentNodes(context));
case Int8Array:
case Uint8Array:
case Uint8ClampedArray:
case Int16Array:
case Uint16Array:
case Int32Array:
case Uint32Array:
case Float32Array:
case Float64Array:
case BigInt64Array:
case BigUint64Array:
if (construct) {
if (newTarget) {
return JSConstructTypedArrayNodeGen.create(context, builtin, args().newTarget().fixedArgs(3).createArgumentNodes(context));
} else {
return JSConstructTypedArrayNodeGen.create(context, builtin, args().function().fixedArgs(3).createArgumentNodes(context));
}
} else {
return createCallRequiresNew(context, builtin);
}
case DataView:
if (construct) {
return newTarget ? ConstructDataViewNodeGen.create(context, builtin, true, args().newTarget().fixedArgs(3).createArgumentNodes(context))
: ConstructDataViewNodeGen.create(context, builtin, false, args().function().fixedArgs(3).createArgumentNodes(context));
} else {
return createCallRequiresNew(context, builtin);
}
case Map:
if (construct) {
return newTarget ? ConstructMapNodeGen.create(context, builtin, true, args().newTarget().fixedArgs(1).createArgumentNodes(context))
: ConstructMapNodeGen.create(context, builtin, false, args().function().fixedArgs(1).createArgumentNodes(context));
} else {
return createCallRequiresNew(context, builtin);
}
case Set:
if (construct) {
return newTarget ? ConstructSetNodeGen.create(context, builtin, true, args().newTarget().fixedArgs(1).createArgumentNodes(context))
: ConstructSetNodeGen.create(context, builtin, false, args().function().fixedArgs(1).createArgumentNodes(context));
} else {
return createCallRequiresNew(context, builtin);
}
case WeakMap:
if (construct) {
return newTarget ? ConstructWeakMapNodeGen.create(context, builtin, true, args().newTarget().fixedArgs(1).createArgumentNodes(context))
: ConstructWeakMapNodeGen.create(context, builtin, false, args().function().fixedArgs(1).createArgumentNodes(context));
} else {
return createCallRequiresNew(context, builtin);
}
case WeakSet:
if (construct) {
return newTarget ? ConstructWeakSetNodeGen.create(context, builtin, true, args().newTarget().fixedArgs(1).createArgumentNodes(context))
: ConstructWeakSetNodeGen.create(context, builtin, false, args().function().fixedArgs(1).createArgumentNodes(context));
} else {
return createCallRequiresNew(context, builtin);
}
case GeneratorFunction:
if (newTarget) {
return ConstructFunctionNodeGen.create(context, builtin, true, false, true, args().newTarget().varArgs().createArgumentNodes(context));
}
return ConstructFunctionNodeGen.create(context, builtin, true, false, false, args().function().varArgs().createArgumentNodes(context));
case SharedArrayBuffer:
if (construct) {
return newTarget ? ConstructArrayBufferNodeGen.create(context, builtin, true, true, args().newTarget().fixedArgs(1).createArgumentNodes(context))
: ConstructArrayBufferNodeGen.create(context, builtin, true, false, args().function().fixedArgs(1).createArgumentNodes(context));
} else {
return createCallRequiresNew(context, builtin);
}
case AsyncFunction:
if (newTarget) {
return ConstructFunctionNodeGen.create(context, builtin, false, true, true, args().newTarget().varArgs().createArgumentNodes(context));
}
return ConstructFunctionNodeGen.create(context, builtin, false, true, false, args().function().varArgs().createArgumentNodes(context));
case AsyncGeneratorFunction:
if (newTarget) {
return ConstructFunctionNodeGen.create(context, builtin, true, true, true, args().newTarget().varArgs().createArgumentNodes(context));
}
return ConstructFunctionNodeGen.create(context, builtin, true, true, false, args().function().varArgs().createArgumentNodes(context));
case Symbol:
return construct ? ConstructSymbolNodeGen.create(context, builtin, args().createArgumentNodes(context))
: CallSymbolNodeGen.create(context, builtin, args().fixedArgs(1).createArgumentNodes(context));
case Proxy:
if (construct) {
return newTarget ? ConstructJSProxyNodeGen.create(context, builtin, true, args().newTarget().fixedArgs(3).createArgumentNodes(context))
: ConstructJSProxyNodeGen.create(context, builtin, false, args().function().fixedArgs(3).createArgumentNodes(context));
} else {
return createCallRequiresNew(context, builtin);
}
case Promise:
if (construct) {
return newTarget ? PromiseConstructorNodeGen.create(context, builtin, args().newTarget().fixedArgs(1).createArgumentNodes(context))
: PromiseConstructorNodeGen.create(context, builtin, args().function().fixedArgs(1).createArgumentNodes(context));
} else {
return createCallRequiresNew(context, builtin);
}
case JSAdapter:
return ConstructJSAdapterNodeGen.create(context, builtin, args().fixedArgs(3).createArgumentNodes(context));
case JavaImporter:
return ConstructJavaImporterNodeGen.create(context, builtin, args().varArgs().createArgumentNodes(context));
}
return null;
}
private static CallRequiresNewNode createCallRequiresNew(JSContext context, JSBuiltin builtin) {
return CallRequiresNewNodeGen.create(context, builtin, args().createArgumentNodes(context));
}
public abstract static class ConstructWithNewTargetNode extends JSBuiltinNode {
protected final boolean isNewTargetCase;
protected ConstructWithNewTargetNode(JSContext context, JSBuiltin builtin, boolean isNewTargetCase) {
super(context, builtin);
this.isNewTargetCase = isNewTargetCase;
}
protected JSRealm getRealmFromNewTarget(Object newTarget) {
if (isNewTargetCase) {
return JSRuntime.getFunctionRealm(newTarget, getContext());
}
return getContext().getRealm();
}
protected abstract DynamicObject getIntrinsicDefaultProto(JSRealm realm);
protected DynamicObject swapPrototype(DynamicObject resultObj, DynamicObject newTarget) {
if (isNewTargetCase) {
return setPrototypeFromNewTarget(resultObj, newTarget);
}
return resultObj;
}
protected DynamicObject setPrototypeFromNewTarget(DynamicObject resultObj, DynamicObject newTarget) {
Object prototype = JSObject.get(newTarget, JSObject.PROTOTYPE);
if (!JSRuntime.isObject(prototype)) {
prototype = getIntrinsicDefaultProto(getRealmFromNewTarget(newTarget));
}
JSObject.setPrototype(resultObj, (DynamicObject) prototype);
return resultObj;
}
}
@ImportStatic({JSConfig.class})
public abstract static class ConstructArrayNode extends ConstructWithNewTargetNode {
public ConstructArrayNode(JSContext context, JSBuiltin builtin, boolean isNewTargetCase) {
super(context, builtin, isNewTargetCase);
}
@CompilationFinal private ConstructArrayAllocationSite arrayAllocationSite = createAllocationSite();
protected static boolean isOneNumberArg(Object[] args) {
return args.length == 1 && JSRuntime.isNumber(args[0]);
}
protected static boolean isOneForeignArg(Object[] args) {
return args.length == 1 && JSRuntime.isForeignObject(args[0]);
}
protected static boolean isOneIntegerArg(Object[] args) {
return args.length == 1 && args[0] instanceof Integer && (int) args[0] >= 0;
}
@Specialization(guards = {"args.length == 0"})
protected DynamicObject constructArray0(DynamicObject newTarget, @SuppressWarnings("unused") Object[] args) {
return swapPrototype(JSArray.createConstantEmptyArray(getContext(), arrayAllocationSite), newTarget);
}
@Specialization(guards = "isOneIntegerArg(args)")
protected DynamicObject constructArrayWithIntLength(DynamicObject newTarget, Object[] args) {
int length = (int) args[0];
if (JSConfig.TrackArrayAllocationSites && arrayAllocationSite != null && arrayAllocationSite.isTyped()) {
ScriptArray initialType = arrayAllocationSite.getInitialArrayType();
if (initialType != null) {
return swapPrototype(JSArray.create(getContext(), initialType, ((AbstractWritableArray) initialType).allocateArray(length), length), newTarget);
}
}
return swapPrototype(JSArray.createConstantEmptyArray(getContext(), arrayAllocationSite, length), newTarget);
}
@Specialization(guards = {"args.length == 1", "toArrayLengthNode.isTypeNumber(len)"}, replaces = "constructArrayWithIntLength")
protected DynamicObject constructWithLength(DynamicObject newTarget, @SuppressWarnings("unused") Object[] args,
@Cached @SuppressWarnings("unused") ToArrayLengthNode toArrayLengthNode,
@Cached("create(getContext())") ArrayCreateNode arrayCreateNode,
@Bind("toArrayLengthNode.executeLong(firstArg(args))") long len) {
DynamicObject array = arrayCreateNode.execute(len);
return swapPrototype(array, newTarget);
}
static Object firstArg(Object[] arguments) {
return arguments[0];
}
@Specialization(guards = "isOneForeignArg(args)", limit = "InteropLibraryLimit")
protected DynamicObject constructWithForeignArg(DynamicObject newTarget, Object[] args,
@CachedLibrary("firstArg(args)") InteropLibrary interop,
@Cached("create(getContext())") ArrayCreateNode arrayCreateNode,
@Cached("createBinaryProfile()") ConditionProfile isNumber,
@Cached("create()") BranchProfile rangeErrorProfile) {
Object len = args[0];
if (isNumber.profile(interop.isNumber(len))) {
if (interop.fitsInLong(len)) {
try {
long length = interop.asLong(len);
if (JSRuntime.isArrayIndex(length)) {
DynamicObject array = arrayCreateNode.execute(length);
return swapPrototype(array, newTarget);
}
} catch (UnsupportedMessageException umex) {
rangeErrorProfile.enter();
throw Errors.createTypeErrorInteropException(len, umex, "asLong", this);
}
}
rangeErrorProfile.enter();
throw Errors.createRangeErrorInvalidArrayLength();
} else {
return swapPrototype(JSArray.create(getContext(), ConstantObjectArray.createConstantObjectArray(), args, 1), newTarget);
}
}
@Specialization(guards = {"!isOneNumberArg(args)", "!isOneForeignArg(args)"})
protected DynamicObject constructArrayVarargs(DynamicObject newTarget, Object[] args,
@Cached("create()") BranchProfile isIntegerCase,
@Cached("create()") BranchProfile isDoubleCase,
@Cached("create()") BranchProfile isObjectCase,
@Cached("createBinaryProfile()") ConditionProfile isLengthZero) {
if (isLengthZero.profile(args == null || args.length == 0)) {
return swapPrototype(JSArray.create(getContext(), ScriptArray.createConstantEmptyArray(), args, 0), newTarget);
} else {
ArrayContentType type = ArrayLiteralNode.identifyPrimitiveContentType(args, false);
if (type == ArrayContentType.Integer) {
isIntegerCase.enter();
return swapPrototype(JSArray.createZeroBasedIntArray(getContext(), ArrayLiteralNode.createIntArray(args)), newTarget);
} else if (type == ArrayContentType.Double) {
isDoubleCase.enter();
return swapPrototype(JSArray.createZeroBasedDoubleArray(getContext(), ArrayLiteralNode.createDoubleArray(args)), newTarget);
} else {
isObjectCase.enter();
return swapPrototype(JSArray.create(getContext(), ConstantObjectArray.createConstantObjectArray(), args, args.length), newTarget);
}
}
}
@Override
public JavaScriptNode copy() {
ConstructArrayNode copy = (ConstructArrayNode) super.copy();
copy.arrayAllocationSite = createAllocationSite();
return copy;
}
private static ConstructArrayAllocationSite createAllocationSite() {
return JSConfig.TrackArrayAllocationSites ? new ConstructArrayAllocationSite() : null;
}
@Override
protected DynamicObject getIntrinsicDefaultProto(JSRealm realm) {
return realm.getArrayPrototype();
}
private static final class ConstructArrayAllocationSite implements ArrayAllocationSite {
private static final ScriptArray UNINIT_ARRAY_TYPE = ScriptArray.createConstantEmptyArray();
@CompilationFinal private ScriptArray concreteArrayType = UNINIT_ARRAY_TYPE;
@CompilationFinal private Assumption assumption = Truffle.getRuntime().createAssumption("Array allocation site (untyped)");
public boolean isTyped() {
return assumption.isValid() && concreteArrayType != UNINIT_ARRAY_TYPE && concreteArrayType != null;
}
@Override
public void notifyArrayTransition(ScriptArray arrayType, int length) {
CompilerAsserts.neverPartOfCompilation("do not notify array transitions from compiled code");
assert JSConfig.TrackArrayAllocationSites;
if (arrayType instanceof AbstractWritableArray && length > 0) {
if (concreteArrayType == UNINIT_ARRAY_TYPE) {
concreteArrayType = arrayType;
assumption.invalidate("TypedArray type initialization");
assumption = Truffle.getRuntime().createAssumption("Array allocation site (typed)");
} else if (concreteArrayType != arrayType) {
concreteArrayType = null;
assumption.invalidate("TypedArray type rewrite");
}
}
}
@Override
public ScriptArray getInitialArrayType() {
if (isTyped()) {
return concreteArrayType;
}
return null;
}
}
}
public abstract static class CallBooleanNode extends JSBuiltinNode {
public CallBooleanNode(JSContext context, JSBuiltin builtin) {
super(context, builtin);
}
@Specialization
protected boolean callBoolean(Object value, @Cached("create()") JSToBooleanNode toBoolean) {
return toBoolean.executeBoolean(value);
}
}
public abstract static class ConstructBooleanNode extends ConstructWithNewTargetNode {
public ConstructBooleanNode(JSContext context, JSBuiltin builtin, boolean isNewTargetCase) {
super(context, builtin, isNewTargetCase);
}
@Specialization
protected DynamicObject constructBoolean(DynamicObject newTarget, Object value,
@Cached("create()") JSToBooleanNode toBoolean) {
return swapPrototype(JSBoolean.create(getContext(), toBoolean.executeBoolean(value)), newTarget);
}
@Override
protected DynamicObject getIntrinsicDefaultProto(JSRealm realm) {
return realm.getBooleanPrototype();
}
}
public abstract static class CallDateNode extends JSBuiltinNode {
public CallDateNode(JSContext context, JSBuiltin builtin) {
super(context, builtin);
}
@Specialization
@TruffleBoundary
protected String callDate() {
JSRealm realm = getContext().getRealm();
return JSDate.toString(realm.currentTimeMillis(), realm);
}
}
@ImportStatic({JSConfig.class})
public abstract static class ConstructDateNode extends ConstructWithNewTargetNode {
public ConstructDateNode(JSContext context, JSBuiltin builtin, boolean isNewTargetCase) {
super(context, builtin, isNewTargetCase);
}
@Child private JSToPrimitiveNode toPrimitiveNode;
@Child private JSToDoubleNode toDoubleNode;
private final ConditionProfile stringOrNumberProfile = ConditionProfile.createBinaryProfile();
private final ConditionProfile isDateProfile = ConditionProfile.createBinaryProfile();
private final ConditionProfile gotFieldsProfile = ConditionProfile.createBinaryProfile();
private Object toPrimitive(Object target) {
if (toPrimitiveNode == null) {
CompilerDirectives.transferToInterpreterAndInvalidate();
toPrimitiveNode = insert(JSToPrimitiveNode.create(Hint.None));
}
return toPrimitiveNode.execute(target);
}
protected double toDouble(Object target) {
if (toDoubleNode == null) {
CompilerDirectives.transferToInterpreterAndInvalidate();
toDoubleNode = insert(JSToDoubleNode.create());
}
return toDoubleNode.executeDouble(target);
}
@Specialization(guards = {"args.length == 0"})
protected DynamicObject constructDateZero(DynamicObject newTarget, @SuppressWarnings("unused") Object[] args) {
return swapPrototype(JSDate.create(getContext(), now()), newTarget);
}
@Specialization(guards = {"args.length == 1"})
protected DynamicObject constructDateOne(DynamicObject newTarget, Object[] args,
@Cached("createBinaryProfile()") ConditionProfile isSpecialCase,
@CachedLibrary(limit = "InteropLibraryLimit") InteropLibrary interop) {
double dateValue = getDateValue(args[0], interop);
return swapPrototype(JSDate.create(getContext(), timeClip(dateValue, isSpecialCase)), newTarget);
}
@Specialization(guards = {"args.length >= 2"})
protected DynamicObject constructDateMult(DynamicObject newTarget, Object[] args) {
double val = constructorImpl(args);
return swapPrototype(JSDate.create(getContext(), val), newTarget);
}
private static double timeClip(double dateValue, ConditionProfile isSpecialCase) {
if (isSpecialCase.profile(Double.isInfinite(dateValue) || Double.isNaN(dateValue) || Math.abs(dateValue) > JSDate.MAX_DATE)) {
return Double.NaN;
}
return (long) dateValue;
}
@TruffleBoundary
private double now() {
return getContext().getRealm().currentTimeMillis();
}
@TruffleBoundary
private double parseDate(String target) {
Integer[] fields = getContext().getEvaluator().parseDate(getContext().getRealm(), target.trim());
if (gotFieldsProfile.profile(fields != null)) {
return JSDate.makeDate(fields[0], fields[1], fields[2], fields[3], fields[4], fields[5], fields[6], fields[7], getContext());
}
return Double.NaN;
}
private double getDateValue(Object arg0, InteropLibrary interop) {
if (getContext().getEcmaScriptVersion() >= 6) {
if (isDateProfile.profile(JSDate.isJSDate(arg0))) {
return JSDate.getTimeMillisField((DynamicObject) arg0);
} else if (interop.isInstant(arg0)) {
return JSDate.getDateValueFromInstant(arg0, interop);
}
}
Object value = toPrimitive(arg0);
if (stringOrNumberProfile.profile(JSRuntime.isString(value))) {
return parseDate(JSRuntime.toStringIsString(value));
} else {
double dval = toDouble(value);
if (Double.isInfinite(dval) || Double.isNaN(dval)) {
return Double.NaN;
} else {
return dval;
}
}
}
private double constructorImpl(Object[] args) {
double[] argsEvaluated = new double[args.length];
boolean isNaN = false;
for (int i = 0; i < args.length; i++) {
double d = toDouble(args[i]);
if (Double.isNaN(d)) {
isNaN = true;
}
argsEvaluated[i] = d;
}
if (isNaN) {
return Double.NaN;
}
return JSDate.executeConstructor(argsEvaluated, false, getContext());
}
@Override
protected DynamicObject getIntrinsicDefaultProto(JSRealm realm) {
return realm.getDatePrototype();
}
}
public abstract static class ConstructRegExpNode extends ConstructWithNewTargetNode {
private final boolean isCall;
public ConstructRegExpNode(JSContext context, JSBuiltin builtin, boolean isCall, boolean isNewTargetCase) {
super(context, builtin, isNewTargetCase);
this.isCall = isCall;
}
@Child private JSToStringNode patternToStringNode;
@Child private JSToStringNode flagsToStringNode;
@Child private CompileRegexNode compileRegexNode;
@Child private CreateRegExpNode createRegExpNode;
@Child private PropertyGetNode getConstructorNode;
@Child private PropertyGetNode getSourceNode;
@Child private PropertyGetNode getFlagsNode;
@Child private TRegexUtil.InteropReadStringMemberNode interopReadPatternNode;
private final BranchProfile regexpObject = BranchProfile.create();
private final BranchProfile regexpMatcherObject = BranchProfile.create();
private final BranchProfile regexpNonObject = BranchProfile.create();
private final BranchProfile regexpObjectNewFlagsBranch = BranchProfile.create();
private final ConditionProfile callIsRegExpProfile = ConditionProfile.createBinaryProfile();
private final ConditionProfile constructorEquivalentProfile = ConditionProfile.createBinaryProfile();
@Specialization
protected DynamicObject constructRegExp(DynamicObject newTarget, Object pattern, Object flags,
@Cached("create(getContext())") IsRegExpNode isRegExpNode) {
boolean hasMatchSymbol = isRegExpNode.executeBoolean(pattern);
if (isCall) {
if (callIsRegExpProfile.profile(hasMatchSymbol && flags == Undefined.instance && JSDynamicObject.isJSDynamicObject(pattern))) {
DynamicObject patternObj = (DynamicObject) pattern;
Object patternConstructor = getConstructor(patternObj);
if (constructorEquivalentProfile.profile(patternConstructor == getContext().getRealm().getRegExpConstructor())) {
return patternObj;
}
}
return constructRegExpImpl(pattern, flags, hasMatchSymbol, true);
} else {
return swapPrototype(constructRegExpImpl(pattern, flags, hasMatchSymbol, newTarget == getContext().getRealm().getRegExpConstructor()), newTarget);
}
}
protected DynamicObject constructRegExpImpl(Object patternObj, Object flags, boolean hasMatchSymbol, boolean legacyFeaturesEnabled) {
Object p;
Object f;
boolean isJSRegExp = JSRegExp.isJSRegExp(patternObj);
if (isJSRegExp) {
regexpObject.enter();
Object compiledRegex = JSRegExp.getCompiledRegex((DynamicObject) patternObj);
if (flags == Undefined.instance) {
return getCreateRegExpNode().createRegExp(compiledRegex);
} else {
if (getContext().getEcmaScriptVersion() < 6) {
throw Errors.createTypeError("Cannot supply flags when constructing one RegExp from another");
}
String flagsStr = flagsToString(flags);
regexpObjectNewFlagsBranch.enter();
Object newCompiledRegex = getCompileRegexNode().compile(getInteropReadPatternNode().execute(compiledRegex, TRegexUtil.Props.CompiledRegex.PATTERN), flagsStr);
return getCreateRegExpNode().createRegExp(newCompiledRegex);
}
} else if (hasMatchSymbol) {
regexpMatcherObject.enter();
DynamicObject patternJSObj = (DynamicObject) patternObj;
p = getSource(patternJSObj);
if (flags == Undefined.instance) {
f = getFlags(patternJSObj);
} else {
f = flags;
}
} else {
regexpNonObject.enter();
p = patternObj;
f = flags;
}
String patternStr = getPatternToStringNode().executeString(p);
String flagsStr = flagsToString(f);
Object compiledRegex = getCompileRegexNode().compile(patternStr, flagsStr);
return getCreateRegExpNode().createRegExp(compiledRegex, legacyFeaturesEnabled);
}
private JSToStringNode getPatternToStringNode() {
if (patternToStringNode == null) {
CompilerDirectives.transferToInterpreterAndInvalidate();
patternToStringNode = insert(JSToStringNode.createUndefinedToEmpty());
}
return patternToStringNode;
}
private TRegexUtil.InteropReadStringMemberNode getInteropReadPatternNode() {
if (interopReadPatternNode == null) {
CompilerDirectives.transferToInterpreterAndInvalidate();
interopReadPatternNode = insert(TRegexUtil.InteropReadStringMemberNode.create());
}
return interopReadPatternNode;
}
private CompileRegexNode getCompileRegexNode() {
if (compileRegexNode == null) {
CompilerDirectives.transferToInterpreterAndInvalidate();
compileRegexNode = insert(CompileRegexNode.create(getContext()));
}
return compileRegexNode;
}
private CreateRegExpNode getCreateRegExpNode() {
if (createRegExpNode == null) {
CompilerDirectives.transferToInterpreterAndInvalidate();
createRegExpNode = insert(CreateRegExpNode.create(getContext()));
}
return createRegExpNode;
}
private String flagsToString(Object f) {
if (flagsToStringNode == null) {
CompilerDirectives.transferToInterpreterAndInvalidate();
flagsToStringNode = insert(JSToStringNode.createUndefinedToEmpty());
}
return flagsToStringNode.executeString(f);
}
private Object getConstructor(DynamicObject obj) {
if (getConstructorNode == null) {
CompilerDirectives.transferToInterpreterAndInvalidate();
getConstructorNode = insert(PropertyGetNode.create(JSObject.CONSTRUCTOR, false, getContext()));
}
return getConstructorNode.getValue(obj);
}
private Object getSource(DynamicObject obj) {
if (getSourceNode == null) {
CompilerDirectives.transferToInterpreterAndInvalidate();
getSourceNode = insert(PropertyGetNode.create(JSRegExp.SOURCE, false, getContext()));
}
return getSourceNode.getValue(obj);
}
private Object getFlags(DynamicObject obj) {
if (getFlagsNode == null) {
CompilerDirectives.transferToInterpreterAndInvalidate();
getFlagsNode = insert(PropertyGetNode.create(JSRegExp.FLAGS, false, getContext()));
}
return getFlagsNode.getValue(obj);
}
@Override
protected DynamicObject getIntrinsicDefaultProto(JSRealm realm) {
return realm.getRegExpPrototype();
}
}
public abstract static class CallStringNode extends JSBuiltinNode {
public CallStringNode(JSContext context, JSBuiltin builtin) {
super(context, builtin);
}
@Specialization(guards = {"args.length == 0"})
protected String callStringInt0(@SuppressWarnings("unused") Object[] args) {
return "";
}
@Specialization(guards = {"args.length != 0"})
protected String callStringGeneric(Object[] args,
@Cached("createSymbolToString()") JSToStringNode toStringNode) {
return toStringNode.executeString(args[0]);
}
}
public abstract static class ConstructStringNode extends ConstructWithNewTargetNode {
public ConstructStringNode(JSContext context, JSBuiltin builtin, boolean newTargetCase) {
super(context, builtin, newTargetCase);
}
@Specialization(guards = {"args.length == 0"})
protected DynamicObject constructStringInt0(DynamicObject newTarget, @SuppressWarnings("unused") Object[] args) {
return swapPrototype(JSString.create(getContext(), ""), newTarget);
}
@Specialization(guards = {"args.length != 0"})
protected DynamicObject constructString(DynamicObject newTarget, Object[] args,
@Cached("create()") JSToStringNode toStringNode) {
return swapPrototype(JSString.create(getContext(), toStringNode.executeString(args[0])), newTarget);
}
@Override
protected DynamicObject getIntrinsicDefaultProto(JSRealm realm) {
return realm.getStringPrototype();
}
}
public abstract static class ConstructWeakRefNode extends ConstructWithNewTargetNode {
public ConstructWeakRefNode(JSContext context, JSBuiltin builtin, boolean newTargetCase) {
super(context, builtin, newTargetCase);
}
@Specialization(guards = {"isJSObject(target)"})
protected DynamicObject constructWeakRef(DynamicObject newTarget, Object target) {
return swapPrototype(JSWeakRef.create(getContext(), target), newTarget);
}
@Specialization(guards = {"!isJSObject(target)"})
protected DynamicObject constructWeakRefNonObject(@SuppressWarnings("unused") DynamicObject newTarget, @SuppressWarnings("unused") Object target) {
throw Errors.createTypeError("WeakRef: target must be an object");
}
@Override
protected DynamicObject getIntrinsicDefaultProto(JSRealm realm) {
return realm.getWeakRefPrototype();
}
}
public abstract static class ConstructFinalizationRegistryNode extends ConstructWithNewTargetNode {
public ConstructFinalizationRegistryNode(JSContext context, JSBuiltin builtin, boolean newTargetCase) {
super(context, builtin, newTargetCase);
}
@Specialization(guards = {"isCallable(cleanupCallback)"})
protected DynamicObject constructFinalizationRegistry(DynamicObject newTarget, TruffleObject cleanupCallback) {
return swapPrototype(JSFinalizationRegistry.create(getContext(), cleanupCallback), newTarget);
}
@Specialization(guards = {"!isCallable(cleanupCallback)"})
protected DynamicObject constructFinalizationRegistryNonObject(@SuppressWarnings("unused") DynamicObject newTarget, @SuppressWarnings("unused") Object cleanupCallback) {
throw Errors.createTypeError("FinalizationRegistry: cleanup must be callable");
}
@Override
protected DynamicObject getIntrinsicDefaultProto(JSRealm realm) {
return realm.getFinalizationRegistryPrototype();
}
}
public abstract static class CallCollatorNode extends JSBuiltinNode {
@Child InitializeCollatorNode initializeCollatorNode;
public CallCollatorNode(JSContext context, JSBuiltin builtin) {
super(context, builtin);
initializeCollatorNode = InitializeCollatorNode.createInitalizeCollatorNode(context);
}
@Specialization
protected DynamicObject callCollator(Object locales, Object options) {
DynamicObject collator = JSCollator.create(getContext());
return initializeCollatorNode.executeInit(collator, locales, options);
}
}
public abstract static class ConstructCollatorNode extends ConstructWithNewTargetNode {
@Child InitializeCollatorNode initializeCollatorNode;
public ConstructCollatorNode(JSContext context, JSBuiltin builtin, boolean newTargetCase) {
super(context, builtin, newTargetCase);
initializeCollatorNode = InitializeCollatorNode.createInitalizeCollatorNode(context);
}
@Specialization
protected DynamicObject constructCollator(DynamicObject newTarget, Object locales, Object options) {
DynamicObject collator = swapPrototype(JSCollator.create(getContext()), newTarget);
return initializeCollatorNode.executeInit(collator, locales, options);
}
@Override
protected DynamicObject getIntrinsicDefaultProto(JSRealm realm) {
return realm.getCollatorPrototype();
}
}
public abstract static class ConstructListFormatNode extends ConstructWithNewTargetNode {
@Child InitializeListFormatNode initializeListFormatNode;
public ConstructListFormatNode(JSContext context, JSBuiltin builtin, boolean newTargetCase) {
super(context, builtin, newTargetCase);
initializeListFormatNode = InitializeListFormatNode.createInitalizeListFormatNode(context);
}
@Specialization
protected DynamicObject constructListFormat(DynamicObject newTarget, Object locales, Object options) {
DynamicObject listFormat = swapPrototype(JSListFormat.create(getContext()), newTarget);
return initializeListFormatNode.executeInit(listFormat, locales, options);
}
@Override
protected DynamicObject getIntrinsicDefaultProto(JSRealm realm) {
return realm.getListFormatPrototype();
}
}
public abstract static class ConstructRelativeTimeFormatNode extends ConstructWithNewTargetNode {
@Child InitializeRelativeTimeFormatNode initializeRelativeTimeFormatNode;
public ConstructRelativeTimeFormatNode(JSContext context, JSBuiltin builtin, boolean newTargetCase) {
super(context, builtin, newTargetCase);
initializeRelativeTimeFormatNode = InitializeRelativeTimeFormatNode.createInitalizeRelativeTimeFormatNode(context);
}
@Specialization
protected DynamicObject constructRelativeTimeFormat(DynamicObject newTarget, Object locales, Object options) {
DynamicObject listFormat = swapPrototype(JSRelativeTimeFormat.create(getContext()), newTarget);
return initializeRelativeTimeFormatNode.executeInit(listFormat, locales, options);
}
@Override
protected DynamicObject getIntrinsicDefaultProto(JSRealm realm) {
return realm.getRelativeTimeFormatPrototype();
}
}
public abstract static class ConstructSegmenterNode extends ConstructWithNewTargetNode {
@Child InitializeSegmenterNode initializeSegmenterNode;
public ConstructSegmenterNode(JSContext context, JSBuiltin builtin, boolean newTargetCase) {
super(context, builtin, newTargetCase);
initializeSegmenterNode = InitializeSegmenterNode.createInitalizeSegmenterNode(context);
}
@Specialization
protected DynamicObject constructSegmenter(DynamicObject newTarget, Object locales, Object options) {
DynamicObject segmenter = swapPrototype(JSSegmenter.create(getContext()), newTarget);
return initializeSegmenterNode.executeInit(segmenter, locales, options);
}
@Override
protected DynamicObject getIntrinsicDefaultProto(JSRealm realm) {
return realm.getSegmenterPrototype();
}
}
public abstract static class ConstructDisplayNamesNode extends ConstructWithNewTargetNode {
@Child InitializeDisplayNamesNode initializeDisplayNamesNode;
public ConstructDisplayNamesNode(JSContext context, JSBuiltin builtin, boolean newTargetCase) {
super(context, builtin, newTargetCase);
initializeDisplayNamesNode = InitializeDisplayNamesNode.createInitalizeDisplayNamesNode(context);
}
@Specialization
protected DynamicObject constructDisplayNames(DynamicObject newTarget, Object locales, Object options) {
DynamicObject displayNames = swapPrototype(JSDisplayNames.create(getContext()), newTarget);
return initializeDisplayNamesNode.executeInit(displayNames, locales, options);
}
@Override
protected DynamicObject getIntrinsicDefaultProto(JSRealm realm) {
return realm.getDisplayNamesPrototype();
}
}
public abstract static class ConstructLocaleNode extends ConstructWithNewTargetNode {
@Child InitializeLocaleNode initializeLocaleNode;
public ConstructLocaleNode(JSContext context, JSBuiltin builtin, boolean newTargetCase) {
super(context, builtin, newTargetCase);
initializeLocaleNode = InitializeLocaleNode.createInitalizeLocaleNode(context);
}
@Specialization
protected DynamicObject constructLocale(DynamicObject newTarget, Object tag, Object options) {
DynamicObject locale = swapPrototype(JSLocale.create(getContext()), newTarget);
return initializeLocaleNode.executeInit(locale, tag, options);
}
@Override
protected DynamicObject getIntrinsicDefaultProto(JSRealm realm) {
return realm.getLocalePrototype();
}
}
public abstract static class CallNumberFormatNode extends JSBuiltinNode {
@Child InitializeNumberFormatNode initializeNumberFormatNode;
public CallNumberFormatNode(JSContext context, JSBuiltin builtin) {
super(context, builtin);
initializeNumberFormatNode = InitializeNumberFormatNode.createInitalizeNumberFormatNode(context);
}
@Specialization
protected DynamicObject callNumberFormat(Object locales, Object options) {
DynamicObject numberFormat = JSNumberFormat.create(getContext());
return initializeNumberFormatNode.executeInit(numberFormat, locales, options);
}
}
public abstract static class ConstructNumberFormatNode extends ConstructWithNewTargetNode {
@Child InitializeNumberFormatNode initializeNumberFormatNode;
public ConstructNumberFormatNode(JSContext context, JSBuiltin builtin, boolean newTargetCase) {
super(context, builtin, newTargetCase);
initializeNumberFormatNode = InitializeNumberFormatNode.createInitalizeNumberFormatNode(context);
}
@Specialization
protected DynamicObject constructNumberFormat(DynamicObject newTarget, Object locales, Object options) {
DynamicObject numberFormat = swapPrototype(JSNumberFormat.create(getContext()), newTarget);
return initializeNumberFormatNode.executeInit(numberFormat, locales, options);
}
@Override
protected DynamicObject getIntrinsicDefaultProto(JSRealm realm) {
return realm.getNumberFormatPrototype();
}
}
public abstract static class ConstructPluralRulesNode extends ConstructWithNewTargetNode {
@Child InitializePluralRulesNode initializePluralRulesNode;
public ConstructPluralRulesNode(JSContext context, JSBuiltin builtin, boolean newTargetCase) {
super(context, builtin, newTargetCase);
initializePluralRulesNode = InitializePluralRulesNode.createInitalizePluralRulesNode(context);
}
@Specialization
protected DynamicObject constructPluralRules(DynamicObject newTarget, Object locales, Object options) {
DynamicObject pluralRules = swapPrototype(JSPluralRules.create(getContext()), newTarget);
return initializePluralRulesNode.executeInit(pluralRules, locales, options);
}
@Override
protected DynamicObject getIntrinsicDefaultProto(JSRealm realm) {
return realm.getPluralRulesPrototype();
}
}
public abstract static class CallDateTimeFormatNode extends JSBuiltinNode {
@Child InitializeDateTimeFormatNode initializeDateTimeFormatNode;
public CallDateTimeFormatNode(JSContext context, JSBuiltin builtin) {
super(context, builtin);
initializeDateTimeFormatNode = InitializeDateTimeFormatNode.createInitalizeDateTimeFormatNode(context, "any", "date");
}
@Specialization
protected DynamicObject callDateTimeFormat(Object locales, Object options) {
DynamicObject dateTimeFormat = JSDateTimeFormat.create(getContext());
return initializeDateTimeFormatNode.executeInit(dateTimeFormat, locales, options);
}
}
public abstract static class ConstructDateTimeFormatNode extends ConstructWithNewTargetNode {
@Child InitializeDateTimeFormatNode initializeDateTimeFormatNode;
public ConstructDateTimeFormatNode(JSContext context, JSBuiltin builtin, boolean newTargetCase) {
super(context, builtin, newTargetCase);
initializeDateTimeFormatNode = InitializeDateTimeFormatNode.createInitalizeDateTimeFormatNode(context, "any", "date");
}
@Specialization
protected DynamicObject constructDateTimeFormat(DynamicObject newTarget, Object locales, Object options) {
DynamicObject dateTimeFormat = swapPrototype(JSDateTimeFormat.create(getContext()), newTarget);
return initializeDateTimeFormatNode.executeInit(dateTimeFormat, locales, options);
}
@Override
protected DynamicObject getIntrinsicDefaultProto(JSRealm realm) {
return realm.getDateTimeFormatPrototype();
}
}
@ImportStatic({JSConfig.class})
public abstract static class ConstructObjectNode extends ConstructWithNewTargetNode {
public ConstructObjectNode(JSContext context, JSBuiltin builtin, boolean isNewTargetCase) {
super(context, builtin, isNewTargetCase);
}
protected static boolean arg0NullOrUndefined(Object[] args) {
Object arg0 = args[0];
return (arg0 == Undefined.instance) || (arg0 == Null.instance);
}
protected static Object firstArgument(Object[] arguments) {
return (arguments.length == 0) ? Undefined.instance : arguments[0];
}
@Specialization(guards = {"isNewTargetCase"})
protected DynamicObject constructObjectNewTarget(DynamicObject newTarget, @SuppressWarnings("unused") Object[] arguments) {
return newObject(newTarget);
}
@Specialization(guards = {"arguments.length == 0"})
protected DynamicObject constructObject0(DynamicObject newTarget, @SuppressWarnings("unused") Object[] arguments) {
return newObject(newTarget);
}
@Specialization(guards = {"!isNewTargetCase", "arguments.length > 0", "!arg0NullOrUndefined(arguments)"}, limit = "InteropLibraryLimit")
protected Object constructObjectJSObject(@SuppressWarnings("unused") DynamicObject newTarget, Object[] arguments,
@Cached("createToObject(getContext())") JSToObjectNode toObjectNode,
@CachedLibrary("firstArgument(arguments)") InteropLibrary interop,
@Cached("createBinaryProfile()") ConditionProfile isNull) {
Object arg0 = arguments[0];
if (isNull.profile(interop.isNull(arg0))) {
return newObject(Null.instance);
} else {
return toObjectNode.execute(arg0);
}
}
@Specialization(guards = {"arguments.length > 0", "arg0NullOrUndefined(arguments)"})
protected DynamicObject constructObjectNullOrUndefined(DynamicObject newTarget, @SuppressWarnings("unused") Object[] arguments) {
return newObject(newTarget);
}
private DynamicObject newObject(DynamicObject newTarget) {
return swapPrototype(JSOrdinary.create(getContext()), newTarget);
}
@Override
protected DynamicObject getIntrinsicDefaultProto(JSRealm realm) {
return realm.getObjectPrototype();
}
}
public abstract static class CallNumberNode extends JSBuiltinNode {
public CallNumberNode(JSContext context, JSBuiltin builtin) {
super(context, builtin);
}
@Specialization(guards = {"args.length == 0"})
protected int callNumberZero(@SuppressWarnings("unused") Object[] args) {
return 0;
}
@Specialization(guards = {"args.length > 0"})
protected Number callNumber(Object[] args,
@Cached("create()") JSToNumericNode toNumericNode,
@Cached("create()") JSNumericToNumberNode toNumberFromNumericNode) {
return toNumberFromNumericNode.executeNumeric(toNumericNode.execute(args[0]));
}
}
public abstract static class ConstructNumberNode extends ConstructWithNewTargetNode {
public ConstructNumberNode(JSContext context, JSBuiltin builtin, boolean isNewTargetCase) {
super(context, builtin, isNewTargetCase);
}
@Specialization(guards = {"args.length == 0"})
protected DynamicObject constructNumberZero(DynamicObject newTarget, @SuppressWarnings("unused") Object[] args) {
return swapPrototype(JSNumber.create(getContext(), 0), newTarget);
}
@Specialization(guards = {"args.length > 0"})
protected DynamicObject constructNumber(DynamicObject newTarget, Object[] args,
@Cached("create()") JSToNumericNode toNumericNode,
@Cached("create()") JSNumericToNumberNode toNumberFromNumericNode) {
return swapPrototype(JSNumber.create(getContext(), toNumberFromNumericNode.executeNumeric(toNumericNode.execute(args[0]))), newTarget);
}
@Override
protected DynamicObject getIntrinsicDefaultProto(JSRealm realm) {
return realm.getNumberPrototype();
}
}
public abstract static class CallBigIntNode extends JSBuiltinNode {
@Child JSToPrimitiveNode toPrimitiveNode;
public CallBigIntNode(JSContext context, JSBuiltin builtin) {
super(context, builtin);
}
private Object toPrimitive(Object target) {
if (toPrimitiveNode == null) {
CompilerDirectives.transferToInterpreterAndInvalidate();
toPrimitiveNode = insert(JSToPrimitiveNode.create(Hint.Number));
}
return toPrimitiveNode.execute(target);
}
@Specialization(guards = {"args.length == 0"})
protected void callBigIntZero(@SuppressWarnings("unused") Object[] args) {
throw Errors.createErrorCanNotConvertToBigInt(JSErrorType.TypeError, Undefined.instance);
}
@Specialization(guards = {"args.length > 0"})
protected Object callBigInt(Object[] args,
@Cached("create()") JSNumberToBigIntNode numberToBigIntNode,
@Cached("create()") JSToBigIntNode toBigIntNode) {
Object value = args[0];
Object primitiveObj = toPrimitive(value);
if (JSRuntime.isNumber(primitiveObj)) {
return numberToBigIntNode.executeBigInt(primitiveObj);
} else {
return toBigIntNode.executeBigInteger(value);
}
}
}
public abstract static class ConstructBigIntNode extends JSBuiltinNode {
public ConstructBigIntNode(JSContext context, JSBuiltin builtin) {
super(context, builtin);
}
@Specialization
protected static final DynamicObject construct() {
throw Errors.createTypeError("BigInt is not a constructor");
}
}
public abstract static class ConstructFunctionNode extends ConstructWithNewTargetNode {
private final boolean generatorFunction;
private final boolean asyncFunction;
@Child private JSToStringNode toStringNode;
@Child private CreateDynamicFunctionNode functionNode;
public ConstructFunctionNode(JSContext context, JSBuiltin builtin, boolean generatorFunction, boolean asyncFunction, boolean isNewTargetCase) {
super(context, builtin, isNewTargetCase);
this.generatorFunction = generatorFunction;
this.asyncFunction = asyncFunction;
this.toStringNode = JSToStringNode.create();
this.functionNode = CreateDynamicFunctionNodeGen.create(context, generatorFunction, asyncFunction);
}
@Specialization
protected final DynamicObject constructFunction(DynamicObject newTarget, Object[] args,
@Cached("createBinaryProfile()") ConditionProfile hasArgsProfile,
@Cached("createBinaryProfile()") ConditionProfile hasParamsProfile) {
int argc = args.length;
String[] params;
String body;
if (hasArgsProfile.profile(argc > 0)) {
params = new String[argc - 1];
for (int i = 0; i < argc - 1; i++) {
params[i] = toStringNode.executeString(args[i]);
}
body = toStringNode.executeString(args[argc - 1]);
} else {
params = new String[0];
body = "";
}
String paramList = hasParamsProfile.profile(argc > 1) ? join(params) : "";
return swapPrototype(functionNode.executeFunction(paramList, body, getSourceName()), newTarget);
}
@TruffleBoundary
private static String join(String[] params) {
StringJoiner sj = new StringJoiner(",");
for (String param : params) {
sj.add(param);
}
return sj.toString();
}
@Override
protected DynamicObject getIntrinsicDefaultProto(JSRealm realm) {
if (generatorFunction && asyncFunction) {
return realm.getAsyncGeneratorFunctionPrototype();
} else if (generatorFunction) {
return realm.getGeneratorFunctionPrototype();
} else if (asyncFunction) {
return realm.getAsyncFunctionPrototype();
} else {
return realm.getFunctionPrototype();
}
}
private String getSourceName() {
String sourceName = null;
if (isCallerSensitive()) {
sourceName = EvalNode.findAndFormatEvalOrigin(getContext().getRealm().getCallNode(), getContext());
}
if (sourceName == null) {
sourceName = Evaluator.FUNCTION_SOURCE_NAME;
}
return sourceName;
}
@Override
public boolean isCallerSensitive() {
return getContext().isOptionV8CompatibilityMode();
}
}
static final class LRUCache<K, V> extends LinkedHashMap<K, V> {
private static final long serialVersionUID = 7813848977534444613L;
private final int maxCacheSize;
LRUCache(int maxCacheSize) {
super(16, 0.75F, true);
this.maxCacheSize = maxCacheSize;
}
@Override
protected boolean removeEldestEntry(java.util.Map.Entry<K, V> eldest) {
return size() > maxCacheSize;
}
}
abstract static class CreateDynamicFunctionNode extends JavaScriptBaseNode {
private final boolean generatorFunction;
private final boolean asyncFunction;
private final JSContext context;
protected CreateDynamicFunctionNode(JSContext context, boolean generatorFunction, boolean asyncFunction) {
this.generatorFunction = generatorFunction;
this.asyncFunction = asyncFunction;
this.context = context;
}
protected abstract DynamicObject executeFunction(String paramList, String body, String sourceName);
protected static boolean equals(String a, String b) {
return a.equals(b);
}
protected LRUCache<CachedSourceKey, ScriptNode> createCache() {
return new LRUCache<>(context.getContextOptions().getFunctionConstructorCacheSize());
}
@SuppressWarnings("unused")
@Specialization(guards = {"equals(cachedParamList, paramList)", "equals(cachedBody, body)", "equals(cachedSourceName, sourceName)"}, limit = "1")
protected final DynamicObject doCached(String paramList, String body, String sourceName,
@Cached("paramList") String cachedParamList,
@Cached("body") String cachedBody,
@Cached("sourceName") String cachedSourceName,
@Cached("parseFunction(paramList, body, sourceName)") ScriptNode parsedFunction) {
return evalParsedFunction(context.getRealm(), parsedFunction);
}
@Specialization(replaces = "doCached")
protected final DynamicObject doUncached(String paramList, String body, String sourceName,
@Cached("createCache()") LRUCache<CachedSourceKey, ScriptNode> cache,
@Cached("createCountingProfile()") ConditionProfile cacheHit) {
ScriptNode cached = cacheLookup(cache, new CachedSourceKey(paramList, body, sourceName));
if (cacheHit.profile(cached == null)) {
return parseAndEvalFunction(cache, context.getRealm(), paramList, body, sourceName);
} else {
return evalParsedFunction(context.getRealm(), cached);
}
}
@TruffleBoundary
protected ScriptNode cacheLookup(LRUCache<CachedSourceKey, ScriptNode> cache, CachedSourceKey sourceKey) {
synchronized (cache) {
return cache.get(sourceKey);
}
}
@TruffleBoundary(transferToInterpreterOnException = false)
protected final ScriptNode parseFunction(String paramList, String body, String sourceName) {
CompilerAsserts.neverPartOfCompilation();
return context.getEvaluator().parseFunction(context, paramList, body, generatorFunction, asyncFunction, sourceName);
}
@TruffleBoundary(transferToInterpreterOnException = false)
private static DynamicObject evalParsedFunction(JSRealm realm, ScriptNode parsedFunction) {
return (DynamicObject) parsedFunction.run(realm);
}
@TruffleBoundary(transferToInterpreterOnException = false)
private DynamicObject parseAndEvalFunction(LRUCache<CachedSourceKey, ScriptNode> cache, JSRealm realm, String paramList, String body, String sourceName) {
ScriptNode parsedBody = parseFunction(paramList, body, sourceName);
synchronized (cache) {
cache.put(new CachedSourceKey(paramList, body, sourceName), parsedBody);
}
return evalParsedFunction(realm, parsedBody);
}
protected static class CachedSourceKey {
private final String body;
private final String paramList;
private final String sourceName;
CachedSourceKey(String paramList, String body, String sourceName) {
this.body = body;
this.paramList = paramList;
this.sourceName = sourceName;
}
@Override
public boolean equals(Object o) {
if (!(o instanceof CachedSourceKey)) {
return false;
}
CachedSourceKey k = (CachedSourceKey) o;
return k.body.equals(body) && k.paramList.equals(paramList) && k.sourceName.equals(sourceName);
}
@Override
public int hashCode() {
return Objects.hash(body, paramList, sourceName);
}
}
}
public abstract static class CallTypedArrayNode extends JSBuiltinNode {
public CallTypedArrayNode(JSContext context, JSBuiltin builtin) {
super(context, builtin);
}
@Specialization
protected Object callTypedArray(@SuppressWarnings("unused") Object... args) {
throw Errors.createTypeError("wrong");
}
}
public abstract static class ConstructArrayBufferNode extends ConstructWithNewTargetNode {
private final ConditionProfile badLengthCondition = ConditionProfile.createBinaryProfile();
private final boolean useShared;
@Child private GetPrototypeFromConstructorNode getPrototypeFromConstructorNode;
public ConstructArrayBufferNode(JSContext context, JSBuiltin builtin, boolean useShared, boolean isNewTargetCase) {
super(context, builtin, isNewTargetCase);
this.useShared = useShared;
if (isNewTargetCase) {
getPrototypeFromConstructorNode = GetPrototypeFromConstructorNode.create(context, null, realm -> getIntrinsicDefaultProto(realm));
}
}
protected boolean isHostByteBuffer(Object buffer) {
return getContext().getRealm().getEnv().isHostObject(buffer);
}
@Specialization(guards = {"!isByteBuffer(length)", "!isHostByteBuffer(length)"})
protected DynamicObject constructFromLength(DynamicObject newTarget, Object length,
@Cached("create()") JSToIndexNode toIndexNode) {
long byteLength = toIndexNode.executeLong(length);
DynamicObject prototype = null;
if (isNewTargetCase) {
prototype = getPrototypeFromConstructorNode.executeWithConstructor(newTarget);
}
if (badLengthCondition.profile(byteLength > getContext().getContextOptions().getMaxTypedArrayLength())) {
throw Errors.createRangeError("Array buffer allocation failed");
}
DynamicObject arrayBuffer;
JSContext contextFromNewTarget = getContext();
if (useShared) {
arrayBuffer = JSSharedArrayBuffer.createSharedArrayBuffer(contextFromNewTarget, (int) byteLength);
} else {
if (getContext().isOptionDirectByteBuffer()) {
arrayBuffer = JSArrayBuffer.createDirectArrayBuffer(contextFromNewTarget, (int) byteLength);
} else {
arrayBuffer = JSArrayBuffer.createArrayBuffer(contextFromNewTarget, (int) byteLength);
}
}
if (isNewTargetCase) {
JSObject.setPrototype(arrayBuffer, prototype);
}
return arrayBuffer;
}
@Specialization(guards = "isHostByteBuffer(buffer)")
protected DynamicObject constructFromHostByteBuffer(DynamicObject newTarget, Object buffer,
@Cached("create()") BranchProfile errorBranch,
@Cached("createBinaryProfile()") ConditionProfile isDirect) {
Object maybeBuffer = getContext().getRealm().getEnv().asHostObject(buffer);
if (maybeBuffer instanceof ByteBuffer) {
ByteBuffer byteBuffer = (ByteBuffer) maybeBuffer;
if (isDirect.profile(byteBuffer.isDirect())) {
return swapPrototype(JSArrayBuffer.createDirectArrayBuffer(getContext(), byteBuffer), newTarget);
} else {
return swapPrototype(JSArrayBuffer.createArrayBuffer(getContext(), Boundaries.byteBufferArray(byteBuffer)), newTarget);
}
} else {
errorBranch.enter();
throw Errors.createTypeError("Unsupported input data type");
}
}
@Override
protected DynamicObject getIntrinsicDefaultProto(JSRealm realm) {
return useShared ? realm.getSharedArrayBufferPrototype() : realm.getArrayBufferPrototype();
}
}
public abstract static class ConstructErrorNode extends ConstructWithNewTargetNode {
private final JSErrorType errorType;
@Child private ErrorStackTraceLimitNode stackTraceLimitNode;
@Child private InitErrorObjectNode initErrorObjectNode;
public ConstructErrorNode(JSContext context, JSBuiltin builtin, boolean isNewTargetCase) {
super(context, builtin, isNewTargetCase);
this.errorType = JSErrorType.valueOf(getBuiltin().getName());
this.stackTraceLimitNode = ErrorStackTraceLimitNode.create(context);
this.initErrorObjectNode = InitErrorObjectNode.create(context);
assert errorType != JSErrorType.AggregateError;
}
@Specialization
protected DynamicObject constructError(DynamicObject newTarget, String message) {
return constructErrorImpl(newTarget, message);
}
@Specialization
protected DynamicObject constructError(DynamicObject newTarget, Object message,
@Cached("create()") JSToStringNode toStringNode) {
return constructErrorImpl(newTarget, message == Undefined.instance ? null : toStringNode.executeString(message));
}
private DynamicObject constructErrorImpl(DynamicObject newTarget, String messageOpt) {
JSContext context = getContext();
JSRealm realm = context.getRealm();
DynamicObject errorObj = JSError.createErrorObject(getContext(), realm, errorType);
swapPrototype(errorObj, newTarget);
int stackTraceLimit = stackTraceLimitNode.executeInt();
DynamicObject errorFunction = realm.getErrorConstructor(errorType);
DynamicObject skipUntil = newTarget == Undefined.instance ? errorFunction : newTarget;
GraalJSException exception = JSException.createCapture(errorType, messageOpt, errorObj, realm, stackTraceLimit, skipUntil);
return initErrorObjectNode.execute(errorObj, exception, messageOpt);
}
@Override
protected DynamicObject getIntrinsicDefaultProto(JSRealm realm) {
return realm.getErrorPrototype(errorType);
}
}
@ImportStatic(JSRuntime.class)
public abstract static class ConstructAggregateErrorNode extends ConstructWithNewTargetNode {
@Child private ErrorStackTraceLimitNode stackTraceLimitNode;
@Child private InitErrorObjectNode initErrorObjectNode;
public ConstructAggregateErrorNode(JSContext context, JSBuiltin builtin, boolean isNewTargetCase) {
super(context, builtin, isNewTargetCase);
this.stackTraceLimitNode = ErrorStackTraceLimitNode.create(context);
this.initErrorObjectNode = InitErrorObjectNode.create(context);
}
GetMethodNode createGetIteratorMethod() {
return GetMethodNode.create(getContext(), null, Symbol.SYMBOL_ITERATOR);
}
@Specialization
protected DynamicObject constructError(DynamicObject newTarget, Object errorsObj, Object messageObj,
@Cached("create()") JSToStringNode toStringNode,
@Cached("createGetIteratorMethod()") GetMethodNode getIteratorMethodNode,
@Cached("createCall()") JSFunctionCallNode iteratorCallNode,
@Cached("create()") IsJSObjectNode isObjectNode,
@Cached("create(getContext())") IteratorStepNode iteratorStepNode,
@Cached("create(getContext())") IteratorValueNode getIteratorValueNode,
@Cached("create(NEXT, getContext())") PropertyGetNode getNextMethodNode,
@Cached("create()") BranchProfile growProfile) {
String message = messageObj == Undefined.instance ? null : toStringNode.executeString(messageObj);
Object usingIterator = getIteratorMethodNode.executeWithTarget(errorsObj);
SimpleArrayList<Object> errors = GetIteratorNode.iterableToList(errorsObj, usingIterator, iteratorCallNode, isObjectNode, iteratorStepNode, getIteratorValueNode, getNextMethodNode, this,
growProfile);
JSContext context = getContext();
JSRealm realm = context.getRealm();
DynamicObject errorsArray = JSArray.createConstantObjectArray(context, errors.toArray());
DynamicObject errorObj = JSError.createErrorObject(context, realm, JSErrorType.AggregateError);
swapPrototype(errorObj, newTarget);
int stackTraceLimit = stackTraceLimitNode.executeInt();
DynamicObject errorFunction = realm.getErrorConstructor(JSErrorType.AggregateError);
GraalJSException exception = JSException.createCapture(JSErrorType.AggregateError, message, errorObj, realm, stackTraceLimit, errorFunction);
initErrorObjectNode.execute(errorObj, exception, message, errorsArray);
return errorObj;
}
@Override
protected DynamicObject getIntrinsicDefaultProto(JSRealm realm) {
return realm.getErrorPrototype(JSErrorType.AggregateError);
}
}
public abstract static class ConstructDataViewNode extends ConstructWithNewTargetNode {
public ConstructDataViewNode(JSContext context, JSBuiltin builtin, boolean isNewTargetCase) {
super(context, builtin, isNewTargetCase);
}
@Specialization
protected final DynamicObject constructDataView(DynamicObject newTarget, Object buffer, Object byteOffset, Object byteLength,
@Cached("create()") BranchProfile errorBranch,
@Cached("createBinaryProfile()") ConditionProfile arrayBufferCondition,
@Cached("createBinaryProfile()") ConditionProfile byteLengthCondition,
@Cached("create()") JSToIndexNode offsetToIndexNode,
@Cached("create()") JSToIndexNode lengthToIndexNode) {
boolean direct;
if (arrayBufferCondition.profile(JSArrayBuffer.isJSHeapArrayBuffer(buffer))) {
direct = false;
} else if (JSArrayBuffer.isJSDirectOrSharedArrayBuffer(buffer)) {
direct = true;
} else {
errorBranch.enter();
throw Errors.createTypeError("Not an ArrayBuffer");
}
DynamicObject arrayBuffer = (DynamicObject) buffer;
long offset = offsetToIndexNode.executeLong(byteOffset);
if (!getContext().getTypedArrayNotDetachedAssumption().isValid() && JSArrayBuffer.isDetachedBuffer(arrayBuffer)) {
errorBranch.enter();
throw Errors.createTypeError("detached buffer cannot be used");
}
int bufferByteLength = direct ? JSArrayBuffer.getDirectByteLength(arrayBuffer) : JSArrayBuffer.getByteLength(arrayBuffer);
if (offset > bufferByteLength) {
errorBranch.enter();
throw Errors.createRangeError("offset > bufferByteLength");
}
final long viewByteLength;
if (byteLengthCondition.profile(byteLength != Undefined.instance)) {
viewByteLength = lengthToIndexNode.executeLong(byteLength);
if (viewByteLength < 0) {
errorBranch.enter();
throw Errors.createRangeError("viewByteLength < 0");
}
if (offset + viewByteLength > bufferByteLength) {
errorBranch.enter();
throw Errors.createRangeError("offset + viewByteLength > bufferByteLength");
}
} else {
viewByteLength = bufferByteLength - offset;
}
assert offset >= 0 && offset <= Integer.MAX_VALUE && viewByteLength >= 0 && viewByteLength <= Integer.MAX_VALUE;
DynamicObject result = swapPrototype(JSDataView.createDataView(getContext(), arrayBuffer, (int) offset, (int) viewByteLength), newTarget);
if (!getContext().getTypedArrayNotDetachedAssumption().isValid() && JSArrayBuffer.isDetachedBuffer(arrayBuffer)) {
errorBranch.enter();
throw Errors.createTypeErrorDetachedBuffer();
}
return result;
}
@Override
protected DynamicObject getIntrinsicDefaultProto(JSRealm realm) {
return realm.getDataViewPrototype();
}
}
public abstract static class CallRequiresNewNode extends JSBuiltinNode {
public CallRequiresNewNode(JSContext context, JSBuiltin builtin) {
super(context, builtin);
}
@Specialization
protected final DynamicObject call() {
throw Errors.createTypeErrorFormat("Constructor %s requires 'new'", getBuiltin().getName());
}
}
public abstract static class ConstructJSAdapterNode extends JSBuiltinNode {
public ConstructJSAdapterNode(JSContext context, JSBuiltin builtin) {
super(context, builtin);
}
@Specialization(guards = {"isJSObject(adaptee)", "isUndefined(undefined1)", "isUndefined(undefined2)"})
protected DynamicObject constructJSAdapter(DynamicObject adaptee, @SuppressWarnings("unused") Object undefined1, @SuppressWarnings("unused") Object undefined2) {
return JSAdapter.create(getContext(), adaptee, null, null);
}
@Specialization(guards = {"isJSObject(overrides)", "isJSObject(adaptee)", "isUndefined(undefined2)"})
protected DynamicObject constructJSAdapter(DynamicObject overrides, DynamicObject adaptee, @SuppressWarnings("unused") Object undefined2) {
return JSAdapter.create(getContext(), adaptee, overrides, null);
}
@Specialization(guards = {"isJSObject(proto)", "isJSObject(overrides)", "isJSObject(adaptee)"})
protected DynamicObject constructJSAdapter(DynamicObject proto, DynamicObject overrides, DynamicObject adaptee) {
return JSAdapter.create(getContext(), adaptee, overrides, proto);
}
@Fallback
protected DynamicObject constructJSAdapter(Object proto, Object overrides, Object adaptee) {
Object notAnObject;
if (!JSRuntime.isObject(proto)) {
notAnObject = proto;
} else if (!JSRuntime.isObject(overrides)) {
notAnObject = overrides;
} else if (!JSRuntime.isObject(adaptee)) {
notAnObject = adaptee;
} else {
throw Errors.shouldNotReachHere();
}
throw Errors.createTypeErrorNotAnObject(notAnObject);
}
}
@ImportStatic(value = {JSProxy.class})
public abstract static class ConstructJSProxyNode extends ConstructWithNewTargetNode {
private final ConditionProfile targetNonObject = ConditionProfile.createBinaryProfile();
private final ConditionProfile handlerNonObject = ConditionProfile.createBinaryProfile();
public ConstructJSProxyNode(JSContext context, JSBuiltin builtin, boolean isNewTargetCase) {
super(context, builtin, isNewTargetCase);
}
@Specialization
protected DynamicObject constructJSProxy(DynamicObject newTarget, Object target, Object handler) {
if (targetNonObject.profile(!JSGuards.isTruffleObject(target) || target instanceof Symbol || target == Undefined.instance || target == Null.instance || target instanceof JSLazyString ||
target instanceof SafeInteger || target instanceof BigInt)) {
throw Errors.createTypeError("target expected to be an object");
}
if (handlerNonObject.profile(!JSGuards.isJSObject(handler))) {
throw Errors.createTypeError("handler expected to be an object");
}
DynamicObject handlerObj = (DynamicObject) handler;
return swapPrototype(JSProxy.create(getContext(), target, handlerObj), newTarget);
}
@Override
protected DynamicObject getIntrinsicDefaultProto(JSRealm realm) {
return realm.getProxyPrototype();
}
public abstract DynamicObject execute(DynamicObject newTarget, Object target, Object handler);
}
public abstract static class ConstructJavaImporterNode extends JSBuiltinNode {
public ConstructJavaImporterNode(JSContext context, JSBuiltin builtin) {
super(context, builtin);
}
@Specialization
protected DynamicObject constructJavaImporter(Object[] args) {
SimpleArrayList<Object> pkgs = new SimpleArrayList<>(args.length);
for (Object pkg : args) {
if (JavaPackage.isJavaPackage(pkg)) {
pkgs.addUnchecked(pkg);
}
}
return JavaImporter.create(getContext(), pkgs.toArray());
}
}
public abstract static class JSConstructIterableOperation extends ConstructWithNewTargetNode {
public JSConstructIterableOperation(JSContext context, JSBuiltin builtin, boolean isNewTargetCase) {
super(context, builtin, isNewTargetCase);
}
@Child private IteratorCloseNode iteratorCloseNode;
@Child private GetIteratorNode getIteratorNode;
@Child private IteratorValueNode getIteratorValueNode;
@Child private IteratorStepNode iteratorStepNode;
@Child private JSFunctionCallNode callAdderNode;
@Child private PropertyGetNode getAdderFnNode;
protected final ConditionProfile needFillIterable = ConditionProfile.createBinaryProfile();
protected final BranchProfile errorBranch = BranchProfile.create();
protected void iteratorCloseAbrupt(DynamicObject iterator) {
if (iteratorCloseNode == null) {
CompilerDirectives.transferToInterpreterAndInvalidate();
iteratorCloseNode = insert(IteratorCloseNode.create(getContext()));
}
iteratorCloseNode.executeAbrupt(iterator);
}
protected IteratorRecord getIterator(Object iterator) {
if (getIteratorNode == null) {
CompilerDirectives.transferToInterpreterAndInvalidate();
getIteratorNode = insert(GetIteratorNode.create(getContext()));
}
return getIteratorNode.execute(iterator);
}
protected Object getIteratorValue(DynamicObject iteratorResult) {
if (getIteratorValueNode == null) {
CompilerDirectives.transferToInterpreterAndInvalidate();
getIteratorValueNode = insert(IteratorValueNode.create(getContext()));
}
return getIteratorValueNode.execute(iteratorResult);
}
protected Object iteratorStep(IteratorRecord iterator) {
if (iteratorStepNode == null) {
CompilerDirectives.transferToInterpreterAndInvalidate();
iteratorStepNode = insert(IteratorStepNode.create(getContext()));
}
return iteratorStepNode.execute(iterator);
}
protected Object call(Object target, DynamicObject function, Object... userArguments) {
if (callAdderNode == null) {
CompilerDirectives.transferToInterpreterAndInvalidate();
callAdderNode = insert(JSFunctionCallNode.createCall());
}
return callAdderNode.executeCall(JSArguments.create(target, function, userArguments));
}
protected Object getAdderFn(DynamicObject obj, String name) {
if (getAdderFnNode == null) {
CompilerDirectives.transferToInterpreterAndInvalidate();
getAdderFnNode = insert(PropertyGetNode.create(name, false, getContext()));
}
return getAdderFnNode.getValue(obj);
}
}
public abstract static class ConstructMapNode extends JSConstructIterableOperation {
private @Child ReadElementNode readElementNode;
public ConstructMapNode(JSContext context, JSBuiltin builtin, boolean isNewTargetCase) {
super(context, builtin, isNewTargetCase);
}
@Specialization
protected DynamicObject constructMap(DynamicObject newTarget, Object iterable) {
JSContext context = getContext();
DynamicObject mapObj = JSMap.create(context);
fillWithIterable(mapObj, iterable);
swapPrototype(mapObj, newTarget);
return mapObj;
}
protected void fillWithIterable(DynamicObject mapObj, Object iterable) {
if (needFillIterable.profile(iterable == Undefined.instance || iterable == Null.instance)) {
return;
} else {
Object adder = getAdderFn(mapObj, "set");
if (!JSFunction.isJSFunction(adder)) {
errorBranch.enter();
throw Errors.createTypeError("function set not callable");
}
DynamicObject adderFn = (DynamicObject) adder;
IteratorRecord iter = getIterator(iterable);
try {
while (true) {
Object next = iteratorStep(iter);
if (next == Boolean.FALSE) {
return;
}
Object nextItem = getIteratorValue((DynamicObject) next);
if (!JSDynamicObject.isJSDynamicObject(nextItem)) {
errorBranch.enter();
throw Errors.createTypeErrorIteratorResultNotObject(nextItem, this);
}
Object k = readElement(nextItem, 0);
Object v = readElement(nextItem, 1);
call(mapObj, adderFn, k, v);
}
} catch (Exception ex) {
iteratorCloseAbrupt(iter.getIterator());
throw ex;
}
}
}
private Object readElement(Object target, int index) {
if (readElementNode == null) {
CompilerDirectives.transferToInterpreterAndInvalidate();
readElementNode = insert(ReadElementNode.create(getContext()));
}
return readElementNode.executeWithTargetAndIndex(target, index);
}
@Override
protected DynamicObject getIntrinsicDefaultProto(JSRealm realm) {
return realm.getMapPrototype();
}
}
public abstract static class ConstructSetNode extends JSConstructIterableOperation {
public ConstructSetNode(JSContext context, JSBuiltin builtin, boolean isNewTargetCase) {
super(context, builtin, isNewTargetCase);
}
@Specialization
protected DynamicObject constructSet(DynamicObject newTarget, Object iterable) {
JSContext context = getContext();
DynamicObject setObj = JSSet.create(context);
fillWithIterable(setObj, iterable);
swapPrototype(setObj, newTarget);
return setObj;
}
protected void fillWithIterable(DynamicObject setObj, Object iterable) {
if (needFillIterable.profile(iterable == Undefined.instance || iterable == Null.instance)) {
return;
} else {
Object adder = getAdderFn(setObj, "add");
if (!JSFunction.isJSFunction(adder)) {
errorBranch.enter();
throw Errors.createTypeError("function add not callable");
}
DynamicObject adderFn = (DynamicObject) adder;
IteratorRecord iter = getIterator(iterable);
try {
while (true) {
Object next = iteratorStep(iter);
if (next == Boolean.FALSE) {
return;
}
Object nextValue = getIteratorValue((DynamicObject) next);
call(setObj, adderFn, nextValue);
}
} catch (Exception ex) {
iteratorCloseAbrupt(iter.getIterator());
throw ex;
}
}
}
@Override
protected DynamicObject getIntrinsicDefaultProto(JSRealm realm) {
return realm.getSetPrototype();
}
}
public abstract static class ConstructWeakSetNode extends ConstructSetNode {
public ConstructWeakSetNode(JSContext context, JSBuiltin builtin, boolean isNewTargetCase) {
super(context, builtin, isNewTargetCase);
}
@Override
@Specialization
protected DynamicObject constructSet(DynamicObject newTarget, Object iterable) {
JSContext context = getContext();
DynamicObject setObj = JSWeakSet.create(context);
fillWithIterable(setObj, iterable);
swapPrototype(setObj, newTarget);
return setObj;
}
@Override
protected DynamicObject getIntrinsicDefaultProto(JSRealm realm) {
return realm.getWeakSetPrototype();
}
}
public abstract static class ConstructWeakMapNode extends ConstructMapNode {
public ConstructWeakMapNode(JSContext context, JSBuiltin builtin, boolean isNewTargetCase) {
super(context, builtin, isNewTargetCase);
}
@Override
@Specialization
protected DynamicObject constructMap(DynamicObject newTarget, Object iterable) {
JSContext context = getContext();
DynamicObject mapObj = JSWeakMap.create(context);
fillWithIterable(mapObj, iterable);
swapPrototype(mapObj, newTarget);
return mapObj;
}
@Override
protected DynamicObject getIntrinsicDefaultProto(JSRealm realm) {
return realm.getWeakMapPrototype();
}
}
public abstract static class CallSymbolNode extends JSBuiltinNode {
public CallSymbolNode(JSContext context, JSBuiltin builtin) {
super(context, builtin);
}
@Specialization
protected Symbol callSymbolString(String value) {
return Symbol.create(value);
}
@Specialization(guards = "!isString(value)")
protected Symbol callSymbolGeneric(Object value,
@Cached JSToStringNode toStringNode) {
return Symbol.create(value == Undefined.instance ? null : toStringNode.executeString(value));
}
}
public abstract static class ConstructSymbolNode extends JSBuiltinNode {
public ConstructSymbolNode(JSContext context, JSBuiltin builtin) {
super(context, builtin);
}
@Specialization
protected static final DynamicObject construct() {
throw Errors.createTypeError("cannot construct a Symbol");
}
}
public abstract static class PromiseConstructorNode extends JSBuiltinNode {
@Child protected IsCallableNode isCallable;
@Child private PromiseResolveThenableNode promiseResolveThenable;
@Child private OrdinaryCreateFromConstructorNode createPromiseFromConstructor;
@Child private PropertySetNode setPromiseFulfillReactions;
@Child private PropertySetNode setPromiseRejectReactions;
@Child private PropertySetNode setPromiseIsHandled;
public PromiseConstructorNode(JSContext context, JSBuiltin builtin) {
super(context, builtin);
this.isCallable = IsCallableNode.create();
this.promiseResolveThenable = PromiseResolveThenableNode.create(context);
this.createPromiseFromConstructor = OrdinaryCreateFromConstructorNode.create(context, null, JSRealm::getPromisePrototype, JSPromise.INSTANCE);
this.setPromiseFulfillReactions = PropertySetNode.createSetHidden(JSPromise.PROMISE_FULFILL_REACTIONS, context);
this.setPromiseRejectReactions = PropertySetNode.createSetHidden(JSPromise.PROMISE_REJECT_REACTIONS, context);
this.setPromiseIsHandled = PropertySetNode.createSetHidden(JSPromise.PROMISE_IS_HANDLED, context);
}
@Specialization(guards = "isCallable.executeBoolean(executor)")
protected DynamicObject construct(VirtualFrame frame, DynamicObject newTarget, Object executor) {
DynamicObject promise = createPromiseFromConstructor.executeWithConstructor(frame, newTarget);
JSPromise.setPromiseState(promise, JSPromise.PENDING);
setPromiseFulfillReactions.setValue(promise, new SimpleArrayList<>());
setPromiseRejectReactions.setValue(promise, new SimpleArrayList<>());
setPromiseIsHandled.setValueBoolean(promise, false);
getContext().notifyPromiseHook(PromiseHook.TYPE_INIT, promise);
promiseResolveThenable.execute(promise, Undefined.instance, executor);
return promise;
}
@SuppressWarnings("unused")
@Specialization(guards = "!isCallable.executeBoolean(executor)")
protected DynamicObject notCallable(DynamicObject newTarget, Object executor) {
throw Errors.createTypeError("cannot create promise: executor not callable");
}
}
}