Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / tools / gn / functions.cc
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "tools/gn/functions.h"
6
7 #include <iostream>
8
9 #include "base/environment.h"
10 #include "base/strings/string_util.h"
11 #include "tools/gn/config.h"
12 #include "tools/gn/config_values_generator.h"
13 #include "tools/gn/err.h"
14 #include "tools/gn/input_file.h"
15 #include "tools/gn/parse_tree.h"
16 #include "tools/gn/scheduler.h"
17 #include "tools/gn/scope.h"
18 #include "tools/gn/settings.h"
19 #include "tools/gn/token.h"
20 #include "tools/gn/value.h"
21
22 namespace {
23
24 // This is called when a template is invoked. When we see a template
25 // declaration, that funciton is RunTemplate.
26 Value RunTemplateInvocation(Scope* scope,
27                             const FunctionCallNode* invocation,
28                             const std::vector<Value>& args,
29                             BlockNode* block,
30                             const FunctionCallNode* rule,
31                             Err* err) {
32   if (!EnsureNotProcessingImport(invocation, scope, err))
33     return Value();
34
35   Scope block_scope(scope);
36   if (!FillTargetBlockScope(scope, invocation,
37                             invocation->function().value().as_string(),
38                             block, args, &block_scope, err))
39     return Value();
40
41   // Run the block for the rule invocation.
42   block->ExecuteBlockInScope(&block_scope, err);
43   if (err->has_error())
44     return Value();
45
46   // Now run the rule itself with that block as the current scope.
47   rule->block()->ExecuteBlockInScope(&block_scope, err);
48   if (err->has_error())
49     return Value();
50
51   block_scope.CheckForUnusedVars(err);
52   return Value();
53 }
54
55 }  // namespace
56
57 // ----------------------------------------------------------------------------
58
59 bool EnsureNotProcessingImport(const ParseNode* node,
60                                const Scope* scope,
61                                Err* err) {
62   if (scope->IsProcessingImport()) {
63     *err = Err(node, "Not valid from an import.",
64         "Imports are for defining defaults, variables, and rules. The\n"
65         "appropriate place for this kind of thing is really in a normal\n"
66         "BUILD file.");
67     return false;
68   }
69   return true;
70 }
71
72 bool EnsureNotProcessingBuildConfig(const ParseNode* node,
73                                     const Scope* scope,
74                                     Err* err) {
75   if (scope->IsProcessingBuildConfig()) {
76     *err = Err(node, "Not valid from the build config.",
77         "You can't do this kind of thing from the build config script, "
78         "silly!\nPut it in a regular BUILD file.");
79     return false;
80   }
81   return true;
82 }
83
84 bool FillTargetBlockScope(const Scope* scope,
85                           const FunctionCallNode* function,
86                           const std::string& target_type,
87                           const BlockNode* block,
88                           const std::vector<Value>& args,
89                           Scope* block_scope,
90                           Err* err) {
91   if (!block) {
92     FillNeedsBlockError(function, err);
93     return false;
94   }
95
96   // Copy the target defaults, if any, into the scope we're going to execute
97   // the block in.
98   const Scope* default_scope = scope->GetTargetDefaults(target_type);
99   if (default_scope) {
100     if (!default_scope->NonRecursiveMergeTo(block_scope, function,
101                                             "target defaults", err))
102       return false;
103   }
104
105   // The name is the single argument to the target function.
106   if (!EnsureSingleStringArg(function, args, err))
107     return false;
108
109   // Set the target name variable to the current target, and mark it used
110   // because we don't want to issue an error if the script ignores it.
111   const base::StringPiece target_name("target_name");
112   block_scope->SetValue(target_name, Value(function, args[0].string_value()),
113                         function);
114   block_scope->MarkUsed(target_name);
115   return true;
116 }
117
118 void FillNeedsBlockError(const FunctionCallNode* function, Err* err) {
119   *err = Err(function->function(), "This function call requires a block.",
120       "The block's \"{\" must be on the same line as the function "
121       "call's \")\".");
122 }
123
124 bool EnsureSingleStringArg(const FunctionCallNode* function,
125                            const std::vector<Value>& args,
126                            Err* err) {
127   if (args.size() != 1) {
128     *err = Err(function->function(), "Incorrect arguments.",
129                "This function requires a single string argument.");
130     return false;
131   }
132   return args[0].VerifyTypeIs(Value::STRING, err);
133 }
134
135 const Label& ToolchainLabelForScope(const Scope* scope) {
136   return scope->settings()->toolchain_label();
137 }
138
139 Label MakeLabelForScope(const Scope* scope,
140                         const FunctionCallNode* function,
141                         const std::string& name) {
142   const Label& toolchain_label = ToolchainLabelForScope(scope);
143   return Label(scope->GetSourceDir(), name, toolchain_label.dir(),
144                toolchain_label.name());
145 }
146
147 namespace functions {
148
149 // assert ----------------------------------------------------------------------
150
151 const char kAssert[] = "assert";
152 const char kAssert_Help[] =
153     "assert: Assert an expression is true at generation time.\n"
154     "\n"
155     "  assert(<condition> [, <error string>])\n"
156     "\n"
157     "  If the condition is false, the build will fail with an error. If the\n"
158     "  optional second argument is provided, that string will be printed\n"
159     "  with the error message.\n"
160     "\n"
161     "Examples:\n"
162     "  assert(is_win)\n"
163     "  assert(defined(sources), \"Sources must be defined\")\n";
164
165 Value RunAssert(Scope* scope,
166                 const FunctionCallNode* function,
167                 const std::vector<Value>& args,
168                 Err* err) {
169   if (args.size() != 1 && args.size() != 2) {
170     *err = Err(function->function(), "Wrong number of arguments.",
171                "assert() takes one or two argument, "
172                "were you expecting somethig else?");
173   } else if (args[0].type() != Value::BOOLEAN) {
174     *err = Err(function->function(), "Assertion value not a bool.");
175   } else if (!args[0].boolean_value()) {
176     if (args.size() == 2) {
177       // Optional string message.
178       if (args[1].type() != Value::STRING) {
179         *err = Err(function->function(), "Assertion failed.",
180             "<<<ERROR MESSAGE IS NOT A STRING>>>");
181       } else {
182         *err = Err(function->function(), "Assertion failed.",
183             args[1].string_value());
184       }
185     } else {
186       *err = Err(function->function(), "Assertion failed.");
187     }
188
189     if (args[0].origin()) {
190       // If you do "assert(foo)" we'd ideally like to show you where foo was
191       // set, and in this case the origin of the args will tell us that.
192       // However, if you do "assert(foo && bar)" the source of the value will
193       // be the assert like, which isn't so helpful.
194       //
195       // So we try to see if the args are from the same line or not. This will
196       // break if you do "assert(\nfoo && bar)" and we may show the second line
197       // as the source, oh well. The way around this is to check to see if the
198       // origin node is inside our function call block.
199       Location origin_location = args[0].origin()->GetRange().begin();
200       if (origin_location.file() != function->function().location().file() ||
201           origin_location.line_number() !=
202               function->function().location().line_number()) {
203         err->AppendSubErr(Err(args[0].origin()->GetRange(), "",
204                               "This is where it was set."));
205       }
206     }
207   }
208   return Value();
209 }
210
211 // config ----------------------------------------------------------------------
212
213 const char kConfig[] = "config";
214 const char kConfig_Help[] =
215     "config: Defines a configuration object.\n"
216     "\n"
217     "  Configuration objects can be applied to targets and specify sets of\n"
218     "  compiler flags, includes, defines, etc. They provide a way to\n"
219     "  conveniently group sets of this configuration information.\n"
220     "\n"
221     "  A config is referenced by its label just like a target.\n"
222     "\n"
223     "  The values in a config are additive only. If you want to remove a flag\n"
224     "  you need to remove the corresponding config that sets it. The final\n"
225     "  set of flags, defines, etc. for a target is generated in this order:\n"
226     "\n"
227     "   1. The values specified directly on the target (rather than using a\n"
228     "      config.\n"
229     "   2. The configs specified in the target's \"configs\" list, in order.\n"
230     "   3. Direct dependent configs from a breadth-first traversal of the\n"
231     "      dependency tree in the order that the targets appear in \"deps\".\n"
232     "   4. All dependent configs from a breadth-first traversal of the\n"
233     "      dependency tree in the order that the targets appear in \"deps\".\n"
234     "\n"
235     "Variables valid in a config definition:\n"
236     CONFIG_VALUES_VARS_HELP
237     "\n"
238     "Variables on a target used to apply configs:\n"
239     "  all_dependent_configs, configs, direct_dependent_configs,\n"
240     "  forward_dependent_configs_from\n"
241     "\n"
242     "Example:\n"
243     "  config(\"myconfig\") {\n"
244     "    includes = [ \"include/common\" ]\n"
245     "    defines = [ \"ENABLE_DOOM_MELON\" ]\n"
246     "  }\n"
247     "\n"
248     "  executable(\"mything\") {\n"
249     "    configs = [ \":myconfig\" ]\n"
250     "  }\n";
251
252 Value RunConfig(const FunctionCallNode* function,
253                 const std::vector<Value>& args,
254                 Scope* scope,
255                 Err* err) {
256   if (!EnsureSingleStringArg(function, args, err) ||
257       !EnsureNotProcessingImport(function, scope, err))
258     return Value();
259
260   Label label(MakeLabelForScope(scope, function, args[0].string_value()));
261
262   if (g_scheduler->verbose_logging())
263     g_scheduler->Log("Defining config", label.GetUserVisibleName(true));
264
265   // Create the new config.
266   scoped_ptr<Config> config(new Config(scope->settings(), label));
267   config->set_defined_from(function);
268
269   // Fill it.
270   const SourceDir& input_dir = scope->GetSourceDir();
271   ConfigValuesGenerator gen(&config->config_values(), scope, input_dir, err);
272   gen.Run();
273   if (err->has_error())
274     return Value();
275
276   // Mark as complete.
277   scope->settings()->build_settings()->ItemDefined(config.PassAs<Item>());
278   return Value();
279 }
280
281 // declare_args ----------------------------------------------------------------
282
283 const char kDeclareArgs[] = "declare_args";
284 const char kDeclareArgs_Help[] =
285     "declare_args: Declare build arguments used by this file.\n"
286     "\n"
287     "  Introduces the given arguments into the current scope. If they are\n"
288     "  not specified on the command line or in a toolchain's arguments,\n"
289     "  the default values given in the declare_args block will be used.\n"
290     "  However, these defaults will not override command-line values.\n"
291     "\n"
292     "  See also \"gn help buildargs\" for an overview.\n"
293     "\n"
294     "Example:\n"
295     "  declare_args() {\n"
296     "    enable_teleporter = true\n"
297     "    enable_doom_melon = false\n"
298     "  }\n"
299     "\n"
300     "  If you want to override the (default disabled) Doom Melon:\n"
301     "    gn --args=\"enable_doom_melon=true enable_teleporter=false\"\n"
302     "  This also sets the teleporter, but it's already defaulted to on so\n"
303     "  it will have no effect.\n";
304
305 Value RunDeclareArgs(Scope* scope,
306                      const FunctionCallNode* function,
307                      const std::vector<Value>& args,
308                      BlockNode* block,
309                      Err* err) {
310   Scope block_scope(scope);
311   block->ExecuteBlockInScope(&block_scope, err);
312   if (err->has_error())
313     return Value();
314
315   // Pass the values from our scope into the Args object for adding to the
316   // scope with the proper values (taking into account the defaults given in
317   // the block_scope, and arguments passed into the build).
318   Scope::KeyValueMap values;
319   block_scope.GetCurrentScopeValues(&values);
320   scope->settings()->build_settings()->build_args().DeclareArgs(
321       values, scope, err);
322   return Value();
323 }
324
325 // defined ---------------------------------------------------------------------
326
327 const char kDefined[] = "defined";
328 const char kDefined_Help[] =
329     "defined: Returns whether an identifier is defined.\n"
330     "\n"
331     "  Returns true if the given argument is defined. This is most useful in\n"
332     "  templates to assert that the caller set things up properly.\n"
333     "\n"
334     "Example:\n"
335     "\n"
336     "  template(\"mytemplate\") {\n"
337     "    # To help users call this template properly...\n"
338     "    assert(defined(sources), \"Sources must be defined\")\n"
339     "\n"
340     "    # If we want to accept an optional \"values\" argument, we don't\n"
341     "    # want to dereference something that may not be defined.\n"
342     "    if (!defined(outputs)) {\n"
343     "      outputs = []\n"
344     "    }\n"
345     "  }\n";
346
347 Value RunDefined(Scope* scope,
348                  const FunctionCallNode* function,
349                  const ListNode* args_list,
350                  Err* err) {
351   const std::vector<const ParseNode*>& args_vector = args_list->contents();
352   const IdentifierNode* identifier = NULL;
353   if (args_vector.size() != 1 ||
354       !(identifier = args_vector[0]->AsIdentifier())) {
355     *err = Err(function, "Bad argument to defined().",
356         "defined() takes one argument which should be an identifier.");
357     return Value();
358   }
359
360   if (scope->GetValue(identifier->value().value()))
361     return Value(function, true);
362   return Value(function, false);
363 }
364
365 // getenv ----------------------------------------------------------------------
366
367 const char kGetEnv[] = "getenv";
368 const char kGetEnv_Help[] =
369     "getenv: Get an environment variable.\n"
370     "\n"
371     "  value = getenv(env_var_name)\n"
372     "\n"
373     "  Returns the value of the given enironment variable. If the value is\n"
374     "  not found, it will try to look up the variable with the \"opposite\"\n"
375     "  case (based on the case of the first letter of the variable), but\n"
376     "  is otherwise case-sensitive.\n"
377     "\n"
378     "  If the environment variable is not found, the empty string will be\n"
379     "  returned. Note: it might be nice to extend this if we had the concept\n"
380     "  of \"none\" in the language to indicate lookup failure.\n"
381     "\n"
382     "Example:\n"
383     "\n"
384     "  home_dir = getenv(\"HOME\")\n";
385
386 Value RunGetEnv(Scope* scope,
387                 const FunctionCallNode* function,
388                 const std::vector<Value>& args,
389                 Err* err) {
390   if (!EnsureSingleStringArg(function, args, err))
391     return Value();
392
393   scoped_ptr<base::Environment> env(base::Environment::Create());
394
395   std::string result;
396   if (!env->GetVar(args[0].string_value().c_str(), &result))
397     return Value(function, "");  // Not found, return empty string.
398   return Value(function, result);
399 }
400
401 // import ----------------------------------------------------------------------
402
403 const char kImport[] = "import";
404 const char kImport_Help[] =
405     "import: Import a file into the current scope.\n"
406     "\n"
407     "  The import command loads the rules and variables resulting from\n"
408     "  executing the given file into the current scope.\n"
409     "\n"
410     "  By convention, imported files are named with a .gni extension.\n"
411     "\n"
412     "  An import is different than a C++ \"include\". The imported file is\n"
413     "  executed in a standalone environment from the caller of the import\n"
414     "  command. The results of this execution are cached for other files that\n"
415     "  import the same .gni file.\n"
416     "\n"
417     "  Note that you can not import a BUILD.gn file that's otherwise used\n"
418     "  in the build. Files must either be imported or implicitly loaded as\n"
419     "  a result of deps rules, but not both.\n"
420     "\n"
421     "  The imported file's scope will be merged with the scope at the point\n"
422     "  import was called. If there is a conflict (both the current scope and\n"
423     "  the imported file define some variable or rule with the same name but\n"
424     "  different value), a runtime error will be thrown. Therefore, it's good\n"
425     "  practice to minimize the stuff that an imported file defines.\n"
426     "\n"
427     "Examples:\n"
428     "\n"
429     "  import(\"//build/rules/idl_compilation_rule.gni\")\n"
430     "\n"
431     "  # Looks in the current directory.\n"
432     "  import(\"my_vars.gni\")\n";
433
434 Value RunImport(Scope* scope,
435                 const FunctionCallNode* function,
436                 const std::vector<Value>& args,
437                 Err* err) {
438   if (!EnsureSingleStringArg(function, args, err))
439     return Value();
440
441   const SourceDir& input_dir = scope->GetSourceDir();
442   SourceFile import_file =
443       input_dir.ResolveRelativeFile(args[0].string_value());
444   scope->settings()->import_manager().DoImport(import_file, function,
445                                                scope, err);
446   return Value();
447 }
448
449 // set_sources_assignment_filter -----------------------------------------------
450
451 const char kSetSourcesAssignmentFilter[] = "set_sources_assignment_filter";
452 const char kSetSourcesAssignmentFilter_Help[] =
453     "set_sources_assignment_filter: Set a pattern to filter source files.\n"
454     "\n"
455     "  The sources assignment filter is a list of patterns that remove files\n"
456     "  from the list implicitly whenever the \"sources\" variable is\n"
457     "  assigned to. This is intended to be used to globally filter out files\n"
458     "  with platform-specific naming schemes when they don't apply, for\n"
459     "  example, you may want to filter out all \"*_win.cc\" files on non-\n"
460     "  Windows platforms.\n"
461     "\n"
462     "  See \"gn help patterns\" for specifics on patterns.\n"
463     "\n"
464     "  Typically this will be called once in the master build config script\n"
465     "  to set up the filter for the current platform. Subsequent calls will\n"
466     "  overwrite the previous values.\n"
467     "\n"
468     "  If you want to bypass the filter and add a file even if it might\n"
469     "  be filtered out, call set_sources_assignment_filter([]) to clear the\n"
470     "  list of filters. This will apply until the current scope exits\n"
471     "\n"
472     "Example:\n"
473     "  # Filter out all _win files.\n"
474     "  set_sources_assignment_filter([ \"*_win.cc\", \"*_win.h\" ])\n";
475
476 Value RunSetSourcesAssignmentFilter(Scope* scope,
477                                     const FunctionCallNode* function,
478                                     const std::vector<Value>& args,
479                                     Err* err) {
480   if (args.size() != 1) {
481     *err = Err(function, "set_sources_assignment_filter takes one argument.");
482   } else {
483     scoped_ptr<PatternList> f(new PatternList);
484     f->SetFromValue(args[0], err);
485     if (!err->has_error())
486       scope->set_sources_assignment_filter(f.Pass());
487   }
488   return Value();
489 }
490
491 // print -----------------------------------------------------------------------
492
493 const char kPrint[] = "print";
494 const char kPrint_Help[] =
495     "print(...)\n"
496     "  Prints all arguments to the console separated by spaces. A newline is\n"
497     "  automatically appended to the end.\n"
498     "\n"
499     "  This function is intended for debugging. Note that build files are run\n"
500     "  in parallel so you may get interleaved prints. A buildfile may also\n"
501     "  be executed more than once in parallel in the context of different\n"
502     "  toolchains so the prints from one file may be duplicated or\n"
503     "  interleaved with itself.\n"
504     "\n"
505     "Examples:\n"
506     "  print(\"Hello world\")\n"
507     "\n"
508     "  print(sources, deps)\n";
509
510 Value RunPrint(Scope* scope,
511                const FunctionCallNode* function,
512                const std::vector<Value>& args,
513                Err* err) {
514   for (size_t i = 0; i < args.size(); i++) {
515     if (i != 0)
516       std::cout << " ";
517     std::cout << args[i].ToString(false);
518   }
519   std::cout << std::endl;
520   return Value();
521 }
522
523 // -----------------------------------------------------------------------------
524
525 FunctionInfo::FunctionInfo()
526     : self_evaluating_args_runner(NULL),
527       generic_block_runner(NULL),
528       executed_block_runner(NULL),
529       no_block_runner(NULL),
530       help(NULL) {
531 }
532
533 FunctionInfo::FunctionInfo(SelfEvaluatingArgsFunction seaf, const char* in_help)
534     : self_evaluating_args_runner(seaf),
535       generic_block_runner(NULL),
536       executed_block_runner(NULL),
537       no_block_runner(NULL),
538       help(in_help) {
539 }
540
541 FunctionInfo::FunctionInfo(GenericBlockFunction gbf, const char* in_help)
542     : self_evaluating_args_runner(NULL),
543       generic_block_runner(gbf),
544       executed_block_runner(NULL),
545       no_block_runner(NULL),
546       help(in_help) {
547 }
548
549 FunctionInfo::FunctionInfo(ExecutedBlockFunction ebf, const char* in_help)
550     : self_evaluating_args_runner(NULL),
551       generic_block_runner(NULL),
552       executed_block_runner(ebf),
553       no_block_runner(NULL),
554       help(in_help) {
555 }
556
557 FunctionInfo::FunctionInfo(NoBlockFunction nbf, const char* in_help)
558     : self_evaluating_args_runner(NULL),
559       generic_block_runner(NULL),
560       executed_block_runner(NULL),
561       no_block_runner(nbf),
562       help(in_help) {
563 }
564
565 // Setup the function map via a static initializer. We use this because it
566 // avoids race conditions without having to do some global setup function or
567 // locking-heavy singleton checks at runtime. In practice, we always need this
568 // before we can do anything interesting, so it's OK to wait for the
569 // initializer.
570 struct FunctionInfoInitializer {
571   FunctionInfoMap map;
572
573   FunctionInfoInitializer() {
574     #define INSERT_FUNCTION(command) \
575         map[k##command] = FunctionInfo(&Run##command, k##command##_Help);
576
577     INSERT_FUNCTION(Assert)
578     INSERT_FUNCTION(Component)
579     INSERT_FUNCTION(Config)
580     INSERT_FUNCTION(Copy)
581     INSERT_FUNCTION(Custom)
582     INSERT_FUNCTION(DeclareArgs)
583     INSERT_FUNCTION(Defined)
584     INSERT_FUNCTION(ExecScript)
585     INSERT_FUNCTION(Executable)
586     INSERT_FUNCTION(GetEnv)
587     INSERT_FUNCTION(Group)
588     INSERT_FUNCTION(Import)
589     INSERT_FUNCTION(Print)
590     INSERT_FUNCTION(ProcessFileTemplate)
591     INSERT_FUNCTION(ReadFile)
592     INSERT_FUNCTION(RebasePath)
593     INSERT_FUNCTION(SetDefaults)
594     INSERT_FUNCTION(SetDefaultToolchain)
595     INSERT_FUNCTION(SetSourcesAssignmentFilter)
596     INSERT_FUNCTION(SharedLibrary)
597     INSERT_FUNCTION(SourceSet)
598     INSERT_FUNCTION(StaticLibrary)
599     INSERT_FUNCTION(Template)
600     INSERT_FUNCTION(Test)
601     INSERT_FUNCTION(Tool)
602     INSERT_FUNCTION(Toolchain)
603     INSERT_FUNCTION(ToolchainArgs)
604     INSERT_FUNCTION(WriteFile)
605
606     #undef INSERT_FUNCTION
607   }
608 };
609 const FunctionInfoInitializer function_info;
610
611 const FunctionInfoMap& GetFunctions() {
612   return function_info.map;
613 }
614
615 Value RunFunction(Scope* scope,
616                   const FunctionCallNode* function,
617                   const ListNode* args_list,
618                   BlockNode* block,
619                   Err* err) {
620   const Token& name = function->function();
621
622   const FunctionInfoMap& function_map = GetFunctions();
623   FunctionInfoMap::const_iterator found_function =
624       function_map.find(name.value());
625   if (found_function == function_map.end()) {
626     // No built-in function matching this, check for a template.
627     const FunctionCallNode* rule =
628         scope->GetTemplate(function->function().value().as_string());
629     if (rule) {
630       Value args = args_list->Execute(scope, err);
631       if (err->has_error())
632         return Value();
633       return RunTemplateInvocation(scope, function, args.list_value(), block,
634                                    rule, err);
635     }
636
637     *err = Err(name, "Unknown function.");
638     return Value();
639   }
640
641   if (found_function->second.self_evaluating_args_runner) {
642     return found_function->second.self_evaluating_args_runner(
643         scope, function, args_list, err);
644   }
645
646   // All other function types take a pre-executed set of args.
647   Value args = args_list->Execute(scope, err);
648   if (err->has_error())
649     return Value();
650
651   if (found_function->second.generic_block_runner) {
652     if (!block) {
653       FillNeedsBlockError(function, err);
654       return Value();
655     }
656     return found_function->second.generic_block_runner(
657         scope, function, args.list_value(), block, err);
658   }
659
660   if (found_function->second.executed_block_runner) {
661     if (!block) {
662       FillNeedsBlockError(function, err);
663       return Value();
664     }
665
666     Scope block_scope(scope);
667     block->ExecuteBlockInScope(&block_scope, err);
668     if (err->has_error())
669       return Value();
670     return found_function->second.executed_block_runner(
671         function, args.list_value(), &block_scope, err);
672   }
673
674   // Otherwise it's a no-block function.
675   return found_function->second.no_block_runner(scope, function,
676                                                 args.list_value(), err);
677 }
678
679 }  // namespace functions