Skip to content

Commit

Permalink
[MERGE #2722 @jianchun] Date missing cross-site marshalling
Browse files Browse the repository at this point in the history
Merge pull request #2722 from jianchun:datemarshal

A lot of Date methods (the family of to???String) miss cross-site
marshalling. This change fixes that by removing
`DateImplementation::m_scriptContext` and pass in `requestContext`
everywhere.
  • Loading branch information
Jianchun Xu committed Mar 21, 2017
2 parents 90a5c3d + ef8206a commit c970d0f
Show file tree
Hide file tree
Showing 7 changed files with 123 additions and 101 deletions.
3 changes: 1 addition & 2 deletions lib/Runtime/Language/JavascriptConversion.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -415,8 +415,7 @@ namespace Js
// if IsES6ToPrimitiveEnabled flag is off we also fall back to OrdinaryToPrimitive
return MethodCallToPrimitive(aValue, hint, requestContext);
}
//NOTE: Consider passing requestContext to JavascriptDate::ToString
return CrossSite::MarshalVar(requestContext, JavascriptDate::ToString(dateObject));
return JavascriptDate::ToString(dateObject, requestContext);
}
}

Expand Down
57 changes: 29 additions & 28 deletions lib/Runtime/Library/DateImplementation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ namespace Js {
///----------------------------------------------------------------------------
///----------------------------------------------------------------------------

DateImplementation::DateImplementation(double value, ScriptContext* scriptContext)
DateImplementation::DateImplementation(double value)
{
// Assume DateImplementation is allocated in the recycler and is zero initialized
// Do not stack allocate of this struct, as it doesn't initialize all fields.
Expand All @@ -129,7 +129,6 @@ namespace Js {
Assert(!ThreadContext::IsOnStack(this));
AssertValue<byte>(this, 0, sizeof(DateImplementation));

m_scriptContext = scriptContext;
m_modified = false;

SetTvUtc(value);
Expand All @@ -155,92 +154,94 @@ namespace Js {
}

JavascriptString*
DateImplementation::GetString(DateStringFormat dsf, DateTimeFlag noDateTime)
DateImplementation::GetString(DateStringFormat dsf,
ScriptContext* requestContext, DateTimeFlag noDateTime)
{
if (JavascriptNumber::IsNan(m_tvUtc))
{
return m_scriptContext->GetLibrary()->GetInvalidDateString();
return requestContext->GetLibrary()->GetInvalidDateString();
}

switch (dsf)
{
default:
EnsureYmdLcl();
return GetDateDefaultString(&m_ymdLcl, &m_tzd, noDateTime, m_scriptContext);
EnsureYmdLcl(requestContext);
return GetDateDefaultString(&m_ymdLcl, &m_tzd, noDateTime, requestContext);

#ifdef ENABLE_GLOBALIZATION
case DateStringFormat::Locale:
EnsureYmdLcl();
EnsureYmdLcl(requestContext);

if( m_ymdLcl.year > 1600 && m_ymdLcl.year < 10000 )
{
// The year falls in the range which can be handled by both the Win32
// function GetDateFormat and the COM+ date type
// - the latter is for forward compatibility with JS 7.
JavascriptString *bs = GetDateLocaleString(&m_ymdLcl, &m_tzd, noDateTime, m_scriptContext);
JavascriptString *bs = GetDateLocaleString(&m_ymdLcl, &m_tzd, noDateTime, requestContext);
if (bs != nullptr)
{
return bs;
}
else
{
return GetDateDefaultString(&m_ymdLcl, &m_tzd, noDateTime, m_scriptContext);
return GetDateDefaultString(&m_ymdLcl, &m_tzd, noDateTime, requestContext);
}
}
else
{
return GetDateDefaultString(&m_ymdLcl, &m_tzd, noDateTime, m_scriptContext);
return GetDateDefaultString(&m_ymdLcl, &m_tzd, noDateTime, requestContext);
}
#endif

case DateStringFormat::GMT:
EnsureYmdUtc();
return GetDateGmtString(&m_ymdUtc, m_scriptContext);
return GetDateGmtString(&m_ymdUtc, requestContext);
}
}

JavascriptString*
DateImplementation::GetISOString()
DateImplementation::GetISOString(ScriptContext* requestContext)
{
// ES5 15.9.5.43: throw RangeError if time value is not a finite number
if (!Js::NumberUtilities::IsFinite(m_tvUtc))
{
JavascriptError::ThrowRangeError(m_scriptContext, JSERR_NeedNumber);
JavascriptError::ThrowRangeError(requestContext, JSERR_NeedNumber);
}

CompoundString *const bs = CompoundString::NewWithCharCapacity(30, m_scriptContext->GetLibrary());
CompoundString *const bs = CompoundString::NewWithCharCapacity(30, requestContext->GetLibrary());

GetDateComponent(bs, DateData::FullYear, 0);
GetDateComponent(bs, DateData::FullYear, 0, requestContext);
bs->AppendChars(_u('-'));
// month
GetDateComponent(bs, DateData::Month, 1/*adjustment*/);
GetDateComponent(bs, DateData::Month, 1/*adjustment*/, requestContext);
bs->AppendChars(_u('-'));
// date
GetDateComponent(bs, DateData::Date, 0);
GetDateComponent(bs, DateData::Date, 0, requestContext);
bs->AppendChars(_u('T'));
// hours
GetDateComponent(bs, DateData::Hours, 0);
GetDateComponent(bs, DateData::Hours, 0, requestContext);
bs->AppendChars(_u(':'));
// minutes
GetDateComponent(bs, DateData::Minutes, 0);
GetDateComponent(bs, DateData::Minutes, 0, requestContext);
bs->AppendChars(_u(':'));
// seconds
GetDateComponent(bs, DateData::Seconds, 0);
GetDateComponent(bs, DateData::Seconds, 0, requestContext);

// ES5 fill in milliseconds but v5.8 does not
bs->AppendChars(_u('.'));
// milliseconds
GetDateComponent(bs, DateData::Milliseconds, 0);
GetDateComponent(bs, DateData::Milliseconds, 0, requestContext);

bs->AppendChars(_u('Z'));

return bs;
}

void
DateImplementation::GetDateComponent(CompoundString *bs, DateData componentType, int adjust)
DateImplementation::GetDateComponent(CompoundString *bs, DateData componentType, int adjust,
ScriptContext* requestContext)
{
double value = this->GetDateData(componentType, true /* fUTC */, m_scriptContext);
double value = this->GetDateData(componentType, true /* fUTC */, requestContext);
if(Js::NumberUtilities::IsFinite(value))
{
const int ival = (int)value + adjust;
Expand Down Expand Up @@ -339,10 +340,10 @@ namespace Js {
///----------------------------------------------------------------------------

void
DateImplementation::SetTvLcl(double tv)
DateImplementation::SetTvLcl(double tv, ScriptContext* requestContext)
{
m_grfval = 0;
m_tvUtc = GetTvUtc(tv, m_scriptContext);
m_tvUtc = GetTvUtc(tv, requestContext);
}

JavascriptString*
Expand Down Expand Up @@ -580,7 +581,7 @@ namespace Js {
}
else
{
EnsureYmdLcl();
EnsureYmdLcl(scriptContext);
pymd = &m_ymdLcl;
}

Expand Down Expand Up @@ -1709,7 +1710,7 @@ namespace Js {
}
else
{
EnsureYmdLcl();
EnsureYmdLcl(scriptContext);
pymd = &m_ymdLcl;
tv = m_tvLcl;
}
Expand Down Expand Up @@ -1782,7 +1783,7 @@ namespace Js {
}
else
{
SetTvLcl(tv);
SetTvLcl(tv, scriptContext);
}

m_modified = true;
Expand Down
77 changes: 34 additions & 43 deletions lib/Runtime/Library/DateImplementation.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ namespace Js {
static double DoubleToTvUtc(double tv);
private:
DateImplementation(VirtualTableInfoCtorEnum) { m_modified = false; }
DateImplementation(double value, ScriptContext* scriptContext);
DateImplementation(double value);

BEGIN_ENUM_BYTE(DateStringFormat)
Default,
Expand Down Expand Up @@ -103,12 +103,14 @@ namespace Js {
void ClearModified() { m_modified = false; }

private:
JavascriptString* GetString(DateStringFormat dsf, DateTimeFlag noDateTime = DateTimeFlag::None);
JavascriptString* GetString(DateStringFormat dsf, ScriptContext* requestContext,
DateTimeFlag noDateTime = DateTimeFlag::None);

JavascriptString* GetISOString();
void GetDateComponent(CompoundString *bs, DateData componentType, int adjust);
JavascriptString* GetISOString(ScriptContext* requestContext);
void GetDateComponent(CompoundString *bs, DateData componentType, int adjust,
ScriptContext* requestContext);

void SetTvLcl(double tv);
void SetTvLcl(double tv, ScriptContext* requestContext);

double GetDateData(DateData dd, bool fUtc, ScriptContext* scriptContext);
double SetDateData(Arguments args, DateData dd, bool fUtc, ScriptContext* scriptContext);
Expand Down Expand Up @@ -175,11 +177,6 @@ namespace Js {
}
}

inline void EnsureTvLcl(void)
{
EnsureTvLcl(m_scriptContext);
}

///------------------------------------------------------------------------------
/// Make sure m_ymdLcl is valid. (Shared with hybrid debugging, which may use a fake scriptContext.)
///------------------------------------------------------------------------------
Expand All @@ -195,11 +192,6 @@ namespace Js {
m_grfval |= DateValueType::YearMonthDayLocal;
}

inline void EnsureYmdLcl(void)
{
EnsureYmdLcl(m_scriptContext);
}

///------------------------------------------------------------------------------
/// Make sure m_ymdUtc is valid.
///------------------------------------------------------------------------------
Expand All @@ -214,61 +206,61 @@ namespace Js {
}


inline Var GetFullYear()
inline Var GetFullYear(ScriptContext* requestContext)
{
EnsureYmdLcl();
return JavascriptNumber::ToVar(m_ymdLcl.year, m_scriptContext);
EnsureYmdLcl(requestContext);
return JavascriptNumber::ToVar(m_ymdLcl.year, requestContext);
}

inline Var GetYear()
inline Var GetYear(ScriptContext* requestContext)
{
EnsureYmdLcl();
EnsureYmdLcl(requestContext);
// WOOB bug 1099381: ES5 spec B.2.4: getYear() must return YearFromTime() - 1900.
// Note that negative value is OK for the spec.
int value = m_ymdLcl.year - 1900;
return JavascriptNumber::ToVar(value, m_scriptContext);
return JavascriptNumber::ToVar(value, requestContext);
}

inline Var GetMonth()
inline Var GetMonth(ScriptContext* requestContext)
{
EnsureYmdLcl();
return JavascriptNumber::ToVar(m_ymdLcl.mon, m_scriptContext);
EnsureYmdLcl(requestContext);
return JavascriptNumber::ToVar(m_ymdLcl.mon, requestContext);
}

inline Var GetDate()
inline Var GetDate(ScriptContext* requestContext)
{
EnsureYmdLcl();
return JavascriptNumber::ToVar(m_ymdLcl.mday + 1, m_scriptContext);
EnsureYmdLcl(requestContext);
return JavascriptNumber::ToVar(m_ymdLcl.mday + 1, requestContext);
}

inline Var GetDay()
inline Var GetDay(ScriptContext* requestContext)
{
EnsureYmdLcl();
return JavascriptNumber::ToVar(m_ymdLcl.wday, m_scriptContext);
EnsureYmdLcl(requestContext);
return JavascriptNumber::ToVar(m_ymdLcl.wday, requestContext);
}

inline Var GetHours()
inline Var GetHours(ScriptContext* requestContext)
{
EnsureYmdLcl();
return JavascriptNumber::ToVar((m_ymdLcl.time / 3600000)%24, m_scriptContext);
EnsureYmdLcl(requestContext);
return JavascriptNumber::ToVar((m_ymdLcl.time / 3600000)%24, requestContext);
}

inline Var GetMinutes()
inline Var GetMinutes(ScriptContext* requestContext)
{
EnsureYmdLcl();
return JavascriptNumber::ToVar((m_ymdLcl.time / 60000) % 60, m_scriptContext);
EnsureYmdLcl(requestContext);
return JavascriptNumber::ToVar((m_ymdLcl.time / 60000) % 60, requestContext);
}

inline Var GetSeconds()
inline Var GetSeconds(ScriptContext* requestContext)
{
EnsureYmdLcl();
return JavascriptNumber::ToVar((m_ymdLcl.time / 1000) % 60, m_scriptContext);
EnsureYmdLcl(requestContext);
return JavascriptNumber::ToVar((m_ymdLcl.time / 1000) % 60, requestContext);
}

inline Var GetDateMilliSeconds()
inline Var GetDateMilliSeconds(ScriptContext* requestContext)
{
EnsureYmdLcl();
return JavascriptNumber::ToVar(m_ymdLcl.time % 1000, m_scriptContext);
EnsureYmdLcl(requestContext);
return JavascriptNumber::ToVar(m_ymdLcl.time % 1000, requestContext);
}

template <class StringBuilder, class ScriptContext, class NewStringBuilderFunc>
Expand All @@ -287,7 +279,6 @@ namespace Js {
FieldNoBarrier(DateTime::YMD) m_ymdLcl;
Field(TZD) m_tzd;
Field(uint32) m_grfval; // Which fields are valid. m_tvUtc is always valid.
FieldNoBarrier(ScriptContext *) m_scriptContext;
Field(bool) m_modified : 1; // Whether SetDateData was called on this class

friend JavascriptDate;
Expand Down
Loading

0 comments on commit c970d0f

Please sign in to comment.