@@ -209,6 +209,7 @@ void ContextifyContext::Init(Environment* env, Local<Object> target) {
209
209
210
210
env->SetMethod (target, " makeContext" , MakeContext);
211
211
env->SetMethod (target, " isContext" , IsContext);
212
+ env->SetMethod (target, " compileFunction" , CompileFunction);
212
213
}
213
214
214
215
@@ -987,6 +988,144 @@ class ContextifyScript : public BaseObject {
987
988
};
988
989
989
990
991
+ void ContextifyContext::CompileFunction (
992
+ const FunctionCallbackInfo<Value>& args) {
993
+ Environment* env = Environment::GetCurrent (args);
994
+ Isolate* isolate = env->isolate ();
995
+ Local<Context> context = env->context ();
996
+
997
+ // Argument 1: source code
998
+ CHECK (args[0 ]->IsString ());
999
+ Local<String> code = args[0 ].As <String>();
1000
+
1001
+ // Argument 2: filename
1002
+ CHECK (args[1 ]->IsString ());
1003
+ Local<String> filename = args[1 ].As <String>();
1004
+
1005
+ // Argument 3: line offset
1006
+ CHECK (args[2 ]->IsNumber ());
1007
+ Local<Integer> line_offset = args[2 ].As <Integer>();
1008
+
1009
+ // Argument 4: column offset
1010
+ CHECK (args[3 ]->IsNumber ());
1011
+ Local<Integer> column_offset = args[3 ].As <Integer>();
1012
+
1013
+ // Argument 5: cached data (optional)
1014
+ Local<Uint8Array> cached_data_buf;
1015
+ if (!args[4 ]->IsUndefined ()) {
1016
+ CHECK (args[4 ]->IsUint8Array ());
1017
+ cached_data_buf = args[4 ].As <Uint8Array>();
1018
+ }
1019
+
1020
+ // Argument 6: produce cache data
1021
+ CHECK (args[5 ]->IsBoolean ());
1022
+ bool produce_cached_data = args[5 ]->IsTrue ();
1023
+
1024
+ // Argument 7: parsing context (optional)
1025
+ Local<Context> parsing_context;
1026
+ if (!args[6 ]->IsUndefined ()) {
1027
+ CHECK (args[6 ]->IsObject ());
1028
+ ContextifyContext* sandbox =
1029
+ ContextifyContext::ContextFromContextifiedSandbox (
1030
+ env, args[6 ].As <Object>());
1031
+ CHECK_NOT_NULL (sandbox);
1032
+ parsing_context = sandbox->context ();
1033
+ } else {
1034
+ parsing_context = context;
1035
+ }
1036
+
1037
+ // Argument 8: context extensions (optional)
1038
+ Local<Array> context_extensions_buf;
1039
+ if (!args[7 ]->IsUndefined ()) {
1040
+ CHECK (args[7 ]->IsArray ());
1041
+ context_extensions_buf = args[7 ].As <Array>();
1042
+ }
1043
+
1044
+ // Argument 9: params for the function (optional)
1045
+ Local<Array> params_buf;
1046
+ if (!args[8 ]->IsUndefined ()) {
1047
+ CHECK (args[8 ]->IsArray ());
1048
+ params_buf = args[8 ].As <Array>();
1049
+ }
1050
+
1051
+ // Read cache from cached data buffer
1052
+ ScriptCompiler::CachedData* cached_data = nullptr ;
1053
+ if (!cached_data_buf.IsEmpty ()) {
1054
+ ArrayBuffer::Contents contents = cached_data_buf->Buffer ()->GetContents ();
1055
+ uint8_t * data = static_cast <uint8_t *>(contents.Data ());
1056
+ cached_data = new ScriptCompiler::CachedData (
1057
+ data + cached_data_buf->ByteOffset (), cached_data_buf->ByteLength ());
1058
+ }
1059
+
1060
+ ScriptOrigin origin (filename, line_offset, column_offset);
1061
+ ScriptCompiler::Source source (code, origin, cached_data);
1062
+ ScriptCompiler::CompileOptions options;
1063
+ if (source.GetCachedData () == nullptr ) {
1064
+ options = ScriptCompiler::kNoCompileOptions ;
1065
+ } else {
1066
+ options = ScriptCompiler::kConsumeCodeCache ;
1067
+ }
1068
+
1069
+ TryCatch try_catch (isolate);
1070
+ Context::Scope scope (parsing_context);
1071
+
1072
+ // Read context extensions from buffer
1073
+ std::vector<Local<Object>> context_extensions;
1074
+ if (!context_extensions_buf.IsEmpty ()) {
1075
+ for (uint32_t n = 0 ; n < context_extensions_buf->Length (); n++) {
1076
+ Local<Value> val;
1077
+ if (!context_extensions_buf->Get (context, n).ToLocal (&val)) return ;
1078
+ CHECK (val->IsObject ());
1079
+ context_extensions.push_back (val.As <Object>());
1080
+ }
1081
+ }
1082
+
1083
+ // Read params from params buffer
1084
+ std::vector<Local<String>> params;
1085
+ if (!params_buf.IsEmpty ()) {
1086
+ for (uint32_t n = 0 ; n < params_buf->Length (); n++) {
1087
+ Local<Value> val;
1088
+ if (!params_buf->Get (context, n).ToLocal (&val)) return ;
1089
+ CHECK (val->IsString ());
1090
+ params.push_back (val.As <String>());
1091
+ }
1092
+ }
1093
+
1094
+ MaybeLocal<Function> maybe_fun = ScriptCompiler::CompileFunctionInContext (
1095
+ context, &source, params.size (), params.data (),
1096
+ context_extensions.size (), context_extensions.data (), options);
1097
+
1098
+ Local<Function> fun;
1099
+ if (maybe_fun.IsEmpty () || !maybe_fun.ToLocal (&fun)) {
1100
+ ContextifyScript::DecorateErrorStack (env, try_catch);
1101
+ try_catch.ReThrow ();
1102
+ return ;
1103
+ }
1104
+
1105
+ if (produce_cached_data) {
1106
+ const std::unique_ptr<ScriptCompiler::CachedData>
1107
+ cached_data (ScriptCompiler::CreateCodeCacheForFunction (fun, code));
1108
+ bool cached_data_produced = cached_data != nullptr ;
1109
+ if (cached_data_produced) {
1110
+ MaybeLocal<Object> buf = Buffer::Copy (
1111
+ env,
1112
+ reinterpret_cast <const char *>(cached_data->data ),
1113
+ cached_data->length );
1114
+ if (fun->Set (
1115
+ parsing_context,
1116
+ env->cached_data_string (),
1117
+ buf.ToLocalChecked ()).IsNothing ()) return ;
1118
+ }
1119
+ if (fun->Set (
1120
+ parsing_context,
1121
+ env->cached_data_produced_string (),
1122
+ Boolean::New (isolate, cached_data_produced)).IsNothing ()) return ;
1123
+ }
1124
+
1125
+ args.GetReturnValue ().Set (fun);
1126
+ }
1127
+
1128
+
990
1129
void Initialize (Local<Object> target,
991
1130
Local<Value> unused,
992
1131
Local<Context> context) {
0 commit comments