Skip to content

Commit 28894b0

Browse files
committed
chakrashim: Fix bug in repl scenario
Earlier whenever repl was created (`node.exe` with zero parameters), global context was reused. However nodejs/node#5703 fixed it by creating new context for repl. This broke the chakrashim because the context was getting collected immediately. The reason was we were adding the reference of global context to the sandboxed object instead of newly created context. Fixed it by ensuring we add reference to right context. Also contextShim is always initialized when current context was pushed on the scope. However for scenarios like this, we might just create the context and access the objects like global, etc. of that context without going to push scope path. In that case ensure that things are initialized in the new context.
1 parent 97e8928 commit 28894b0

3 files changed

Lines changed: 81 additions & 62 deletions

File tree

deps/chakrashim/src/jsrtcontextshim.cc

Lines changed: 77 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -368,11 +368,34 @@ bool ContextShim::InitializeProxyOfGlobal() {
368368
});
369369
}
370370

371-
bool ContextShim::EnsureInitialized() {
371+
372+
bool ContextShim::InitializeCurrentContextShim() {
372373
if (initialized) {
373374
return true;
374375
}
375376

377+
JsContextRef oldContext;
378+
if (JsGetCurrentContext(&oldContext) != JsNoError) {
379+
return false;
380+
}
381+
JsContextRef thisContext = GetContextRef();
382+
if (JsSetCurrentContext(thisContext) != JsNoError) {
383+
return false;
384+
}
385+
if (!EnsureInitialized()) {
386+
Fatal("Failed to initialize context");
387+
}
388+
if (JsSetCurrentContext(oldContext) != JsNoError) {
389+
return false;
390+
}
391+
return true;
392+
}
393+
394+
bool ContextShim::EnsureInitialized() {
395+
if (initialized) {
396+
return true;
397+
}
398+
initializing = true;
376399
if (jsrt::InitializePromise() != JsNoError) {
377400
return false;
378401
}
@@ -390,6 +413,7 @@ bool ContextShim::EnsureInitialized() {
390413
}
391414

392415
initialized = true;
416+
initializing = false;
393417

394418
// Following is a special one-time initialization that needs to marshal
395419
// objects to this context. Do it after marking initialized = true.
@@ -482,76 +506,69 @@ void ContextShim::RunMicrotasks() {
482506
}
483507
}
484508

485-
JsValueRef ContextShim::GetUndefined() {
486-
return undefinedRef;
487-
}
488-
489-
JsValueRef ContextShim::GetTrue() {
490-
return trueRef;
491-
}
492-
493-
JsValueRef ContextShim::GetFalse() {
494-
return falseRef;
495-
}
496-
497-
JsValueRef ContextShim::GetNull() {
498-
return nullRef;
499-
}
500-
501-
JsValueRef ContextShim::GetZero() {
502-
return zero;
503-
}
504-
505-
JsValueRef ContextShim::GetObjectConstructor() {
506-
return globalConstructor[GlobalType::Object];
507-
}
508-
509-
JsValueRef ContextShim::GetBooleanObjectConstructor() {
510-
return globalConstructor[GlobalType::Boolean];
511-
}
512-
513-
JsValueRef ContextShim::GetNumberObjectConstructor() {
514-
return globalConstructor[GlobalType::Number];
515-
}
516-
517-
JsValueRef ContextShim::GetStringObjectConstructor() {
518-
return globalConstructor[GlobalType::String];
519-
}
520-
521-
JsValueRef ContextShim::GetDateConstructor() {
522-
return globalConstructor[GlobalType::Date];
523-
}
524-
525-
JsValueRef ContextShim::GetProxyConstructor() {
526-
return globalConstructor[GlobalType::Proxy];
527-
}
509+
// check initialization state first instead of calling
510+
// InitializeCurrentContextShim to save a function call for cases where
511+
// contextshim is already initialized
512+
#define DECLARE_GETOBJECT(name, object) \
513+
JsValueRef ContextShim::Get##name() { \
514+
if(!(initialized || initializing)) { \
515+
if (!InitializeCurrentContextShim()) { \
516+
Fatal("Failed to initialize current context"); \
517+
} \
518+
} \
519+
return object; \
520+
} \
528521

522+
DECLARE_GETOBJECT(True, trueRef)
523+
DECLARE_GETOBJECT(False, falseRef)
524+
DECLARE_GETOBJECT(Undefined, undefinedRef)
525+
DECLARE_GETOBJECT(Null, nullRef)
526+
DECLARE_GETOBJECT(Zero, zero)
527+
DECLARE_GETOBJECT(ProxyOfGlobal, proxyOfGlobal)
528+
DECLARE_GETOBJECT(ReflectObject, reflectObject)
529+
DECLARE_GETOBJECT(ObjectConstructor,
530+
globalConstructor[GlobalType::Object])
531+
DECLARE_GETOBJECT(BooleanObjectConstructor,
532+
globalConstructor[GlobalType::Boolean])
533+
DECLARE_GETOBJECT(NumberObjectConstructor,
534+
globalConstructor[GlobalType::Number])
535+
DECLARE_GETOBJECT(StringObjectConstructor,
536+
globalConstructor[GlobalType::String])
537+
DECLARE_GETOBJECT(DateConstructor,
538+
globalConstructor[GlobalType::Date])
539+
DECLARE_GETOBJECT(ProxyConstructor,
540+
globalConstructor[GlobalType::Proxy])
541+
DECLARE_GETOBJECT(GetOwnPropertyDescriptorFunction,
542+
getOwnPropertyDescriptorFunction)
543+
DECLARE_GETOBJECT(StringConcatFunction,
544+
globalPrototypeFunction[GlobalPrototypeFunction
545+
::String_concat])
546+
529547
JsValueRef ContextShim::GetGlobalType(GlobalType index) {
548+
if(!(initialized || initializing)) {
549+
if (!InitializeCurrentContextShim()) {
550+
Fatal("Failed to initialize current context");
551+
}
552+
}
530553
return globalConstructor[index];
531554
}
532555

533-
JsValueRef ContextShim::GetGetOwnPropertyDescriptorFunction() {
534-
return getOwnPropertyDescriptorFunction;
535-
}
536-
537-
JsValueRef ContextShim::GetStringConcatFunction() {
538-
return globalPrototypeFunction[GlobalPrototypeFunction::String_concat];
539-
}
540-
541556
JsValueRef ContextShim::GetGlobalPrototypeFunction(
542557
GlobalPrototypeFunction index) {
558+
if (!(initialized || initializing)) {
559+
if (!InitializeCurrentContextShim()) {
560+
Fatal("Failed to initialize current context");
561+
}
562+
}
543563
return globalPrototypeFunction[index];
544564
}
545565

546-
JsValueRef ContextShim::GetProxyOfGlobal() {
547-
return proxyOfGlobal;
548-
}
549-
550-
JsValueRef ContextShim::GetReflectObject() {
551-
return reflectObject;
552-
}
553-
554566
JsValueRef ContextShim::GetReflectFunctionForTrap(ProxyTraps trap) {
567+
if (!(initialized || initializing)) {
568+
if (!InitializeCurrentContextShim()) {
569+
Fatal("Failed to initialize current context");
570+
}
571+
}
555572
return reflectFunctions[trap];
556573
}
557574

deps/chakrashim/src/jsrtcontextshim.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ class ContextShim {
5353
JsValueRef globalObjectTemplateInstance);
5454
~ContextShim();
5555
bool EnsureInitialized();
56+
bool InitializeCurrentContextShim();
5657

5758
IsolateShim * GetIsolateShim();
5859
JsContextRef GetContextRef();
@@ -105,7 +106,8 @@ class ContextShim {
105106

106107
IsolateShim * isolateShim;
107108
JsContextRef context;
108-
bool initialized;
109+
bool initialized = false;
110+
bool initializing = false;
109111
bool exposeGC;
110112
JsValueRef keepAliveObject;
111113
int builtInCount;

deps/chakrashim/src/v8context.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ Local<Object> Context::Global() {
4141
// V8 Global is actually proxy where the actual global is it's prototype.
4242
// No need to create handle here, the context will keep it alive
4343
return Local<Object>(static_cast<Object *>(
44-
jsrt::ContextShim::GetCurrent()->GetProxyOfGlobal()));
44+
jsrt::IsolateShim::GetContextShim((JsContextRef*)this)->GetProxyOfGlobal()));
4545
}
4646

4747
extern bool g_exposeGC;

0 commit comments

Comments
 (0)