@@ -1599,33 +1599,103 @@ MaybeHandle<JSFunction> Compiler::GetFunctionFromEval(
15991599 return result;
16001600}
16011601
1602- bool Compiler::CodeGenerationFromStringsAllowed (Isolate* isolate,
1603- Handle<Context> context,
1604- Handle<String> source) {
1602+ // Check whether embedder allows code generation in this context.
1603+ // (via v8::Isolate::SetAllowCodeGenerationFromStringsCallback)
1604+ bool CodeGenerationFromStringsAllowed (Isolate* isolate, Handle<Context> context,
1605+ Handle<String> source) {
16051606 DCHECK (context->allow_code_gen_from_strings ().IsFalse (isolate));
1606- // Check with callback if set.
1607+ DCHECK (isolate->allow_code_gen_callback ());
1608+
1609+ // Callback set. Let it decide if code generation is allowed.
1610+ VMState<EXTERNAL > state (isolate);
1611+ RuntimeCallTimerScope timer (
1612+ isolate, RuntimeCallCounterId::kCodeGenerationFromStringsCallbacks );
16071613 AllowCodeGenerationFromStringsCallback callback =
16081614 isolate->allow_code_gen_callback ();
1609- if (callback == nullptr ) {
1610- // No callback set and code generation disallowed.
1611- return false ;
1612- } else {
1613- // Callback set. Let it decide if code generation is allowed.
1614- VMState<EXTERNAL > state (isolate);
1615- return callback (v8::Utils::ToLocal (context), v8::Utils::ToLocal (source));
1615+ return callback (v8::Utils::ToLocal (context), v8::Utils::ToLocal (source));
1616+ }
1617+
1618+ // Check whether embedder allows code generation in this context.
1619+ // (via v8::Isolate::SetModifyCodeGenerationFromStringsCallback)
1620+ bool ModifyCodeGenerationFromStrings (Isolate* isolate, Handle<Context> context,
1621+ Handle<i::Object>* source) {
1622+ DCHECK (context->allow_code_gen_from_strings ().IsFalse (isolate));
1623+ DCHECK (isolate->modify_code_gen_callback ());
1624+ DCHECK (source);
1625+
1626+ // Callback set. Run it, and use the return value as source, or block
1627+ // execution if it's not set.
1628+ VMState<EXTERNAL > state (isolate);
1629+ ModifyCodeGenerationFromStringsCallback modify_callback =
1630+ isolate->modify_code_gen_callback ();
1631+ RuntimeCallTimerScope timer (
1632+ isolate, RuntimeCallCounterId::kCodeGenerationFromStringsCallbacks );
1633+ MaybeLocal<v8::String> modified_source =
1634+ modify_callback (v8::Utils::ToLocal (context), v8::Utils::ToLocal (*source));
1635+ if (modified_source.IsEmpty ()) return false ;
1636+
1637+ // Use the new source (which might be the same as the old source) and return.
1638+ *source = Utils::OpenHandle (*modified_source.ToLocalChecked (), false );
1639+ return true ;
1640+ }
1641+
1642+ // Run Embedder-mandated checks before generating code from a string.
1643+ //
1644+ // Returns a string to be used for compilation, or a flag that an object type
1645+ // was encountered that is neither a string, nor something the embedder knows
1646+ // how to handle.
1647+ //
1648+ // Returns: (assuming: std::tie(source, unknown_object))
1649+ // - !source.is_null(): compilation allowed, source contains the source string.
1650+ // - unknown_object is true: compilation allowed, but we don't know how to
1651+ // deal with source_object.
1652+ // - source.is_null() && !unknown_object: compilation should be blocked.
1653+ //
1654+ // - !source_is_null() and unknown_object can't be true at the same time.
1655+ std::pair<MaybeHandle<String>, bool > Compiler::ValidateDynamicCompilationSource (
1656+ Isolate* isolate, Handle<Context> context,
1657+ Handle<i::Object> source_object) {
1658+ Handle<String> source;
1659+ if (source_object->IsString ()) source = Handle<String>::cast (source_object);
1660+
1661+ // Check if the context unconditionally allows code gen from strings.
1662+ // allow_code_gen_from_strings can be many things, so we'll always check
1663+ // against the 'false' literal, so that e.g. undefined and 'true' are treated
1664+ // the same.
1665+ if (!context->allow_code_gen_from_strings ().IsFalse (isolate)) {
1666+ return {source, !source_object->IsString ()};
1667+ }
1668+
1669+ // Check if the context allows code generation for this string.
1670+ // allow_code_gen_callback only allows proper strings.
1671+ // (I.e., let allow_code_gen_callback decide, if it has been set.)
1672+ if (isolate->allow_code_gen_callback ()) {
1673+ if (source_object->IsString () &&
1674+ CodeGenerationFromStringsAllowed (isolate, context, source)) {
1675+ return {source, !source_object->IsString ()};
1676+ }
16161677 }
1678+
1679+ // Check if the context wants to block or modify this source object.
1680+ // Double-check that we really have a string now.
1681+ // (Let modify_code_gen_callback decide, if it's been set.)
1682+ if (isolate->modify_code_gen_callback ()) {
1683+ if (ModifyCodeGenerationFromStrings (isolate, context, &source_object) &&
1684+ source_object->IsString ())
1685+ return {Handle<String>::cast (source_object), false };
1686+ }
1687+
1688+ return {MaybeHandle<String>(), !source_object->IsString ()};
16171689}
16181690
1619- MaybeHandle<JSFunction> Compiler::GetFunctionFromString (
1620- Handle<Context> context, Handle <String> source,
1691+ MaybeHandle<JSFunction> Compiler::GetFunctionFromValidatedString (
1692+ Handle<Context> context, MaybeHandle <String> source,
16211693 ParseRestriction restriction, int parameters_end_pos) {
16221694 Isolate* const isolate = context->GetIsolate ();
16231695 Handle<Context> native_context (context->native_context (), isolate);
16241696
1625- // Check if native context allows code generation from
1626- // strings. Throw an exception if it doesn't.
1627- if (native_context->allow_code_gen_from_strings ().IsFalse (isolate) &&
1628- !CodeGenerationFromStringsAllowed (isolate, native_context, source)) {
1697+ // Raise an EvalError if we did not receive a string.
1698+ if (source.is_null ()) {
16291699 Handle<Object> error_message =
16301700 native_context->ErrorMessageForCodeGenerationFromStrings ();
16311701 THROW_NEW_ERROR (
@@ -1639,9 +1709,20 @@ MaybeHandle<JSFunction> Compiler::GetFunctionFromString(
16391709 int eval_position = kNoSourcePosition ;
16401710 Handle<SharedFunctionInfo> outer_info (
16411711 native_context->empty_function ().shared (), isolate);
1642- return Compiler::GetFunctionFromEval (
1643- source, outer_info, native_context, LanguageMode::kSloppy , restriction,
1644- parameters_end_pos, eval_scope_position, eval_position);
1712+ return Compiler::GetFunctionFromEval (source.ToHandleChecked (), outer_info,
1713+ native_context, LanguageMode::kSloppy ,
1714+ restriction, parameters_end_pos,
1715+ eval_scope_position, eval_position);
1716+ }
1717+
1718+ MaybeHandle<JSFunction> Compiler::GetFunctionFromString (
1719+ Handle<Context> context, Handle<Object> source,
1720+ ParseRestriction restriction, int parameters_end_pos) {
1721+ Isolate* const isolate = context->GetIsolate ();
1722+ Handle<Context> native_context (context->native_context (), isolate);
1723+ return GetFunctionFromValidatedString (
1724+ context, ValidateDynamicCompilationSource (isolate, context, source).first ,
1725+ restriction, parameters_end_pos);
16451726}
16461727
16471728namespace {
0 commit comments