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