Esempio n. 1
0
 public static call HasBlock(this call kall)
 {
     if (kall.block != null && kall.block.calls.Count > 0)
     {
         return(kall);
     }
     throw ObjException.BlockRequired(kall);
 }
Esempio n. 2
0
 public static call NoBlock(this call kall)
 {
     if (kall.block != null && kall.block.calls.Count > 0)
     {
         throw ObjException.BlockNotAccepted(kall);
     }
     return(kall);
 }
Esempio n. 3
0
 public static call DomBuilt(this call kall, IDocument dom)
 {
     if (dom == null)
     {
         throw ObjException.MissingDomAndCalled(kall);
     }
     return(kall);
 }
Esempio n. 4
0
        public async Task eval(call kall)
        {
            bool hadResult   = resultSet;
            bool addedResult = await funcs[kall.name](kall);

            if (hadResult && addedResult)
            {
                throw ObjException.ExpressionDiscarded(kall, trace.FindLast(x => true));
            }
            hadResult = addedResult;
            trace.Add(kall);
        }
Esempio n. 5
0
        public static call ElementSelected(this call kall, obj env)
        {
            var lastCall = env.trace.Last();

            if (lastCall.name == "sel" || lastCall.name == "id")
            {
                return(kall);

                throw ObjException.MissingElementAndCalled(kall);
            }
            return(kall);
        }
Esempio n. 6
0
 public static call ArityMatches(this call kall, int expected)
 {
     if (kall.args == null && expected == 0)
     {
         return(kall);
     }
     if (kall.args?.Count != expected)
     {
         throw ObjException.ArityMismatch(kall, 1);
     }
     return(kall);
 }
Esempio n. 7
0
        public static obj TopLevel()
        {
            var topLevel = new obj();

            BrowsingContext ctx = new BrowsingContext(Configuration.Default.WithDefaultLoader());

            IDocument dom = null;
            IElement  el  = null;

            topLevel.funcs["true"] = async(kall) => {
                Ensure.ArityMatches(kall, 0).NoBlock();
                topLevel.result = true;
                return(true);
            };
            topLevel.funcs["false"] = async(kall) => {
                Ensure.ArityMatches(kall, 0).NoBlock();
                topLevel.result = false;
                return(true);
            };
            topLevel.funcs["out"] = async(kall) => {
                Ensure.ArityMatches(kall, 1);
                topLevel.Output[kall.args[0]] = topLevel.result;
                topLevel.result = null;
                return(false);
            };

            topLevel.funcs["all"] = async(kall) => {
                Ensure.HasBlock(kall);
                foreach (call k in kall.block.calls)
                {
                    await topLevel.eval(k);

                    if (topLevel.resultSet && topLevel.result is false)
                    {
                        topLevel.result = false;
                        return(false);
                    }
                }
                // If we didn't find any results set to false, it then set result to true
                topLevel.result = true;
                return(false);
            };

            topLevel.funcs["any"] = async(kall) => {
                Ensure.HasBlock(kall);
                foreach (call k in kall.block.calls)
                {
                    await topLevel.eval(k);

                    if (topLevel.resultSet && topLevel.result is true)
                    {
                        return(false);
                    }
                }
                // If we didn't find any truthy values, then
                topLevel.result = false;
                return(false);
            };

            topLevel.funcs["none"] = async(kall) => {
                Ensure.ArityMatches(kall, 0).HasBlock();
                foreach (call k in kall.block.calls)
                {
                    await topLevel.eval(k);

                    if (topLevel.resultSet && topLevel.result is true)
                    {
                        topLevel.result = false;
                        return(false);
                    }
                }
                // If we didn't find any truthy values, then this was true
                topLevel.result = true;
                return(false);
            };
            topLevel.funcs["has-text"] = async(kall) =>
            {
                Ensure.ArityMatches(kall, 1).NoBlock().ElementSelected(topLevel);
                topLevel.result = el.TextContent.Contains(kall.args[0]);
                return(true);
            };

            topLevel.funcs["sel"] = async(kall) => {
                Ensure.ArityMatches(kall, 1).NoBlock().DomBuilt(dom);
                el = dom.QuerySelector(kall.args[0]);
                return(false);
            };

            topLevel.funcs["id"] = async(kall) => {
                Ensure.ArityMatches(kall, 1).DomBuilt(dom).NoBlock();
                el = dom.GetElementById(kall.args[0]);
                return(false);
            };
            topLevel.funcs["site"] = async(kall) => {
                Ensure.ArityMatches(kall, 1);
                dom = await ctx.OpenAsync(kall.args[0]);

                var outName = kall.block?.calls?.FirstOrDefault(x => x.name == "out")?.args?[0] ?? kall.args[0];
                if (dom == null)
                {
                    var failMsg = ObjException.UrlFailed(kall).Message;
                    topLevel.Output[$"{outName}-error"] = failMsg;
                    topLevel.Output[outName]            = false;
                    return(false);
                }
                if (kall.block != null)
                {
                    try
                    {
                        await kall.block.eval(topLevel);
                    }
                    catch (ObjException)
                    {
                        // This sort of exception needs to pass through, since it indicates code is constructed incorrectly.
                        throw;
                    }
                    catch (Exception ex) {
                        topLevel.Output[$"{outName}-error"] = ex.Message;
                        // In this case, we don't know if the site is up or down,
                        // just that something went wrong
                        topLevel.Output[outName] = null;
                        return(false);
                    }
                }
                return(false);
            };

            return(topLevel);
        }