public override Completion InternalConstruct(IReadOnlyList <IValue> arguments, Object?newTarget) { var pattern = arguments.At(0, UndefinedValue.Instance); var flags = arguments.At(1, UndefinedValue.Instance); var patternIsRegExpComp = IsRegExp(pattern); if (patternIsRegExpComp.IsAbrupt()) { return(patternIsRegExpComp); } var patternIsRegExp = patternIsRegExpComp.Other; if (newTarget == null) { newTarget = this; if (patternIsRegExp && flags == UndefinedValue.Instance) { var patternObject = (pattern as Object) !; var patternConstructor = patternObject.Get("constructor"); if (patternConstructor.IsAbrupt()) { return(patternConstructor); } if (patternObject == newTarget) { return(Completion.NormalCompletion(pattern)); } } } IValue P, F; if (pattern is RegExpObject r) { P = new StringValue(r.OriginalSource); if (flags == UndefinedValue.Instance) { F = new StringValue(r.OriginalFlags); } else { F = flags; } } else if (patternIsRegExp) { var patternObject = (pattern as Object) !; var PComp = patternObject.Get("source"); if (PComp.IsAbrupt()) { return(PComp); } P = PComp.value !; if (flags == UndefinedValue.Instance) { var FComp = patternObject.Get("flags"); if (FComp.IsAbrupt()) { return(FComp); } F = FComp.value !; } else { F = flags; } } else { P = pattern; F = flags; } return(RegExpObject.RegExpAllocAndInitialize(P, F)); }
public override Completion InternalCall(IValue thisValue, IReadOnlyList <IValue> arguments) { var b = arguments.At(0, UndefinedValue.Instance).ToBoolean(); return(Completion.NormalCompletion(b)); }
private Completion CreateDynamicFunction(Object?newTarget, FunctionKind kind, IReadOnlyList <IValue> arguments) { if (Interpreter.Instance().ExecutionContextStackSize() < 2) { throw new InvalidOperationException("Spec 19.2.1.1.1 step 1"); } var callerContext = Interpreter.Instance().SecondExecutionContext(); var callerRealm = callerContext.Realm; var calleeRealm = Interpreter.Instance().CurrentRealm(); //TODO HostEnsureCanCompileStrings if (newTarget == null) { newTarget = this; } Func <Parser.Parser, AST.FunctionStatementList> goal; Func <Intrinsics, Object> fallbackProto; switch (kind) { case FunctionKind.Normal: goal = (p) => p.ParseFunctionBody(); fallbackProto = i => i.FunctionPrototype; break; default: throw new NotImplementedException("Async and/or generators"); } var argCount = arguments.Count; var P = ""; string bodyText; if (argCount == 0) { bodyText = ""; } else if (argCount == 1) { var bodyComp = arguments[0].ToJsString(); if (bodyComp.IsAbrupt()) { return(bodyComp); } bodyText = (bodyComp.value as StringValue) !.@string; } else { var firstArg = arguments[0]; var pComp = firstArg.ToJsString(); if (pComp.IsAbrupt()) { return(pComp); } P = (pComp.value as StringValue) !.@string; int k = 1; for (; k < argCount - 1; k++) { var nextArg = arguments[k]; var nextArgStringComp = nextArg.ToJsString(); if (nextArgStringComp.IsAbrupt()) { return(nextArgStringComp); } var nextArgString = (nextArgStringComp.value as StringValue) !.@string; P += "," + nextArgString; } var bodyComp = arguments[k].ToJsString(); if (bodyComp.IsAbrupt()) { return(bodyComp); } bodyText = (bodyComp.value as StringValue) !.@string; } AST.FormalParameters?parameters = new AST.FormalParameters(); try { if (!string.IsNullOrEmpty(P)) { parameters = new Parser.Parser(P).ParseFormalParameters(); } if (parameters == null) { throw new Parser.ParseFailureException($"parameters {P} could not be parsed."); } } catch (Parser.ParseFailureException e) { return(Completion.ThrowSyntaxError($"Failed to parse parameters \"{P}\".\n{e.Message}")); } AST.FunctionStatementList body; try { body = goal(new Parser.Parser(bodyText)); } catch (Parser.ParseFailureException e) { return(Completion.ThrowSyntaxError($"Failed to parse body \"{bodyText}\".\n{e.Message}")); } //TODO detect strict mode: ContainsUseStrict bool strict = body.IsStrictMode; if (!parameters.IsSimpleParameterList() && strict) { return(Completion.ThrowSyntaxError($"parameters must be simple in strict mode. \"{P}\"")); } //TODO implement tree walking for checking if parameters or body contains a SuperCall or SuperProperty //TODO generator yield, async await errors var protoComp = Utils.GetPrototypeFromConstructor(newTarget, fallbackProto); if (protoComp.IsAbrupt()) { return(protoComp); } var proto = protoComp.value; var F = FunctionObject.FunctionAllocate(proto !, strict, kind); var realmF = F.Realm; var scope = realmF.GlobalEnv; FunctionObject.FunctionInitialize(F, FunctionCreateKind.Normal, parameters, body, scope); //TODO generator, async generator if (kind == FunctionKind.Normal) { F.MakeConstructor(); } F.SetFunctionName("anonymous"); return(Completion.NormalCompletion(F)); }
private static Completion RegExpBuiltinExec(RegExpObject R, string S) { var length = S.Length; int lastIndex; { var lastIndexComp = R.Get("lastIndex"); if (lastIndexComp.IsAbrupt()) { return(lastIndexComp); } var lastIndexLength = lastIndexComp.value !.ToLength(); if (lastIndexLength.IsAbrupt()) { return(lastIndexLength); } lastIndex = (int)lastIndexLength.Other; } var flags = R.OriginalFlags; var global = flags.Contains('g', StringComparison.Ordinal); var sticky = flags.Contains('y', StringComparison.Ordinal); if (!global && !sticky) { lastIndex = 0; } var matcher = R.RegExpMatcher; var fullUnicode = flags.Contains('u', StringComparison.Ordinal); var matchSucceeded = false; Match?r = null; while (!matchSucceeded) { if (lastIndex > length) { if (global || sticky) { var set = R.Set("lastIndex", NumberValue.PositiveZero, true); if (set.IsAbrupt()) { return(set); } } return(Completion.NormalCompletion(NullValue.Instance)); } r = matcher.Match(S, lastIndex); if (!r.Success) { if (sticky) { var set = R.Set("lastIndex", NumberValue.PositiveZero, true); if (set.IsAbrupt()) { return(set); } return(Completion.NormalCompletion(NullValue.Instance)); } lastIndex = AdvanceStringIndex(S, lastIndex, fullUnicode); } else { matchSucceeded = true; } } var e = r !.Index + r.Length; if (fullUnicode) { // e is an index into the Input character list, derived from S, matched by matcher. // Let eUTF be the smallest index into S that corresponds to the character at element e of Input. // If e is greater than or equal to the number of elements in Input, then eUTF is the number of code units in S. // Set e to eUTF. var indexes = StringInfo.ParseCombiningCharacters(S); if (r.Index < indexes.Length) { var sub = StringInfo.GetNextTextElement(S, r.Index); e += sub.Length - 1; } } if (global || sticky) { var set = R.Set("lastIndex", new NumberValue(e), true); if (set.IsAbrupt()) { return(set); } } var n = r.Groups.Count; var A = ArrayObject.ArrayCreate(n + 1); Utils.CreateDataProperty(A, "index", new NumberValue(lastIndex)); Utils.CreateDataProperty(A, "input", new StringValue(S)); Utils.CreateDataProperty(A, "0", new StringValue(r.Value)); IValue groups; if (R.RegExpMatcher.GetGroupNames().Any()) { groups = Utils.ObjectCreate(null); } else { groups = UndefinedValue.Instance; } Utils.CreateDataProperty(A, "groups", groups); for (int i = 0; i <= n; i++) { var captureI = r.Groups[i]; IValue capturedValue; if (captureI.Success) { if (fullUnicode) { capturedValue = new StringValue(StringInfo.GetNextTextElement(S, captureI.Index)); } else { capturedValue = new StringValue(captureI.Value); } } else { capturedValue = UndefinedValue.Instance; } Utils.CreateDataProperty(A, i.ToString(CultureInfo.InvariantCulture), capturedValue); if (!string.IsNullOrEmpty(captureI.Name)) { Utils.CreateDataProperty(groups, captureI.Name, capturedValue); } } return(Completion.NormalCompletion(A)); }
public override Completion InternalConstruct(IReadOnlyList <IValue> arguments, Object?newTarget) { if (newTarget == null) { newTarget = this; } var proto = Utils.GetPrototypeFromConstructor(newTarget, i => i.ArrayPrototype); if (proto.IsAbrupt()) { return(proto); } if (arguments.Count == 0) { return(Completion.NormalCompletion(ArrayObject.ArrayCreate(0, proto.value as Object))); } else if (arguments.Count == 1) { var array = ArrayObject.ArrayCreate(0, proto.value as Object); int intLen; if (!(arguments[0] is NumberValue)) { var defineStatus = Utils.CreateDataProperty(array, "0", arguments[0]); if (!defineStatus.Other) { throw new InvalidOperationException("CreateDataProperty [0] in array constructor failed. Spec 22.1.1.2 step 6b"); } intLen = 1; } else { intLen = (int)(arguments[0] as NumberValue) !.number; if (intLen != (arguments[0] as NumberValue) !.number || intLen < 0) { return(Completion.ThrowRangeError("length argument cannot be used as a length")); } } array.Set("length", new NumberValue(intLen), true); return(Completion.NormalCompletion(array)); } else { var array = ArrayObject.ArrayCreate(arguments.Count, proto.value as Object); int k = 0; foreach (var arg in arguments) { var defineStatus = Utils.CreateDataProperty(array, k.ToString(System.Globalization.CultureInfo.InvariantCulture), arg); if (!defineStatus.Other) { throw new InvalidOperationException("CreateDataProperty in array constructor failed. Spec 22.1.1.3 step 8d"); } k++; } if ((array.Get("length").value as NumberValue) !.number != arguments.Count) { throw new InvalidOperationException("array length is invalid. Spec 22.1.1.3 step 9"); } return(Completion.NormalCompletion(array)); } }
public JavascriptException(Completion completion) : base(Description(completion)) { }