1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 * vim: set ts=8 sts=2 et sw=2 tw=80:
3 * This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "frontend/Frontend2.h"
9 #include "mozilla/Maybe.h" // mozilla::Maybe
10 #include "mozilla/OperatorNewExtensions.h" // mozilla::KnownNotNull
11 #include "mozilla/Range.h" // mozilla::Range
12 #include "mozilla/Span.h" // mozilla::Span
13 #include "mozilla/Variant.h" // mozilla::AsVariant
15 #include <stddef.h> // size_t
16 #include <stdint.h> // uint8_t, uint32_t
20 #include "frontend/AbstractScopePtr.h" // ScopeIndex
21 #include "frontend/BytecodeSection.h" // EmitScriptThingsVector
22 #include "frontend/CompilationStencil.h" // CompilationState, CompilationStencil
23 #include "frontend/FrontendContext.h" // AutoReportFrontendContext
24 #include "frontend/Parser.h" // NewEmptyLexicalScopeData, NewEmptyGlobalScopeData, NewEmptyVarScopeData, NewEmptyFunctionScopeData
25 #include "frontend/ParserAtom.h" // ParserAtomsTable, TaggedParserAtomIndex
26 #include "frontend/ScriptIndex.h" // ScriptIndex
27 #include "frontend/smoosh_generated.h" // CVec, Smoosh*, smoosh_*
28 #include "frontend/SourceNotes.h" // SrcNote
29 #include "frontend/Stencil.h" // ScopeStencil, RegExpIndex
30 #include "frontend/TokenStream.h" // TokenStreamAnyChars
31 #include "irregexp/RegExpAPI.h" // irregexp::CheckPatternSyntax
32 #include "js/CharacterEncoding.h" // JS::UTF8Chars, UTF8CharsToNewTwoByteCharsZ, JS::ConstUTF8CharsZ
33 #include "js/ColumnNumber.h" // JS::ColumnNumberOneOrigin, JS::LimitedColumnNumberOneOrigin
34 #include "js/friend/ErrorMessages.h" // js::GetErrorMessage, JSMSG_*
35 #include "js/GCAPI.h" // JS::AutoCheckCannotGC
36 #include "js/HeapAPI.h" // JS::GCCellPtr
37 #include "js/RegExpFlags.h" // JS::RegExpFlag, JS::RegExpFlags
38 #include "js/RootingAPI.h" // JS::MutableHandle
39 #include "js/UniquePtr.h" // js::UniquePtr
40 #include "js/Utility.h" // JS::UniqueTwoByteChars, StringBufferArena
41 #include "vm/JSScript.h" // JSScript
42 #include "vm/Scope.h" // GetScopeDataTrailingNames
43 #include "vm/ScopeKind.h" // ScopeKind
44 #include "vm/SharedStencil.h" // ImmutableScriptData, ScopeNote, TryNote, GCThingIndex
46 using mozilla::Utf8Unit
;
48 using namespace js::gc
;
49 using namespace js::frontend
;
56 // Given the result of SmooshMonkey's parser, Convert the list of atoms into
57 // the list of ParserAtoms.
58 bool ConvertAtoms(JSContext
* cx
, FrontendContext
* fc
,
59 const SmooshResult
& result
,
60 CompilationState
& compilationState
,
61 Vector
<TaggedParserAtomIndex
>& allAtoms
) {
62 size_t numAtoms
= result
.all_atoms_len
;
64 if (!allAtoms
.reserve(numAtoms
)) {
68 for (size_t i
= 0; i
< numAtoms
; i
++) {
69 auto s
= reinterpret_cast<const mozilla::Utf8Unit
*>(
70 smoosh_get_atom_at(result
, i
));
71 auto len
= smoosh_get_atom_len_at(result
, i
);
72 auto atom
= compilationState
.parserAtoms
.internUtf8(fc
, s
, len
);
76 // We don't collect atomization information in smoosh yet.
77 // Assume it needs to be atomized.
78 compilationState
.parserAtoms
.markUsedByStencil(atom
,
79 ParserAtom::Atomize::Yes
);
80 allAtoms
.infallibleAppend(atom
);
86 void CopyBindingNames(JSContext
* cx
, CVec
<SmooshBindingName
>& from
,
87 Vector
<TaggedParserAtomIndex
>& allAtoms
,
88 ParserBindingName
* to
) {
89 // We're setting trailing array's content before setting its length.
90 JS::AutoCheckCannotGC
nogc(cx
);
92 size_t numBindings
= from
.len
;
93 for (size_t i
= 0; i
< numBindings
; i
++) {
94 SmooshBindingName
& name
= from
.data
[i
];
95 new (mozilla::KnownNotNull
, &to
[i
]) ParserBindingName(
96 allAtoms
[name
.name
], name
.is_closed_over
, name
.is_top_level_function
);
100 void CopyBindingNames(JSContext
* cx
, CVec
<COption
<SmooshBindingName
>>& from
,
101 Vector
<TaggedParserAtomIndex
>& allAtoms
,
102 ParserBindingName
* to
) {
103 // We're setting trailing array's content before setting its length.
104 JS::AutoCheckCannotGC
nogc(cx
);
106 size_t numBindings
= from
.len
;
107 for (size_t i
= 0; i
< numBindings
; i
++) {
108 COption
<SmooshBindingName
>& maybeName
= from
.data
[i
];
109 if (maybeName
.IsSome()) {
110 SmooshBindingName
& name
= maybeName
.AsSome();
111 new (mozilla::KnownNotNull
, &to
[i
]) ParserBindingName(
112 allAtoms
[name
.name
], name
.is_closed_over
, name
.is_top_level_function
);
114 new (mozilla::KnownNotNull
, &to
[i
])
115 ParserBindingName(TaggedParserAtomIndex::null(), false, false);
120 // Given the result of SmooshMonkey's parser, convert a list of scope data
121 // into a list of ScopeStencil.
122 bool ConvertScopeStencil(JSContext
* cx
, FrontendContext
* fc
,
123 const SmooshResult
& result
,
124 Vector
<TaggedParserAtomIndex
>& allAtoms
,
125 CompilationState
& compilationState
) {
126 LifoAlloc
& alloc
= compilationState
.alloc
;
128 if (result
.scopes
.len
> TaggedScriptThingIndex::IndexLimit
) {
129 ReportAllocationOverflow(fc
);
133 for (size_t i
= 0; i
< result
.scopes
.len
; i
++) {
134 SmooshScopeData
& scopeData
= result
.scopes
.data
[i
];
137 switch (scopeData
.tag
) {
138 case SmooshScopeData::Tag::Global
: {
139 auto& global
= scopeData
.AsGlobal();
141 size_t numBindings
= global
.bindings
.len
;
142 GlobalScope::ParserData
* data
=
143 NewEmptyGlobalScopeData(fc
, alloc
, numBindings
);
148 CopyBindingNames(cx
, global
.bindings
, allAtoms
,
149 GetScopeDataTrailingNamesPointer(data
));
151 data
->slotInfo
.letStart
= global
.let_start
;
152 data
->slotInfo
.constStart
= global
.const_start
;
153 data
->length
= numBindings
;
155 if (!ScopeStencil::createForGlobalScope(
156 fc
, compilationState
, ScopeKind::Global
, data
, &index
)) {
161 case SmooshScopeData::Tag::Var
: {
162 auto& var
= scopeData
.AsVar();
164 size_t numBindings
= var
.bindings
.len
;
166 VarScope::ParserData
* data
=
167 NewEmptyVarScopeData(fc
, alloc
, numBindings
);
172 CopyBindingNames(cx
, var
.bindings
, allAtoms
,
173 GetScopeDataTrailingNamesPointer(data
));
175 // NOTE: data->slotInfo.nextFrameSlot is set in
176 // ScopeStencil::createForVarScope.
178 data
->length
= numBindings
;
180 uint32_t firstFrameSlot
= var
.first_frame_slot
;
181 ScopeIndex
enclosingIndex(var
.enclosing
);
182 if (!ScopeStencil::createForVarScope(
183 fc
, compilationState
, ScopeKind::FunctionBodyVar
, data
,
184 firstFrameSlot
, var
.function_has_extensible_scope
,
185 mozilla::Some(enclosingIndex
), &index
)) {
190 case SmooshScopeData::Tag::Lexical
: {
191 auto& lexical
= scopeData
.AsLexical();
193 size_t numBindings
= lexical
.bindings
.len
;
194 LexicalScope::ParserData
* data
=
195 NewEmptyLexicalScopeData(fc
, alloc
, numBindings
);
200 CopyBindingNames(cx
, lexical
.bindings
, allAtoms
,
201 GetScopeDataTrailingNamesPointer(data
));
203 // NOTE: data->slotInfo.nextFrameSlot is set in
204 // ScopeStencil::createForLexicalScope.
206 data
->slotInfo
.constStart
= lexical
.const_start
;
207 data
->length
= numBindings
;
209 uint32_t firstFrameSlot
= lexical
.first_frame_slot
;
210 ScopeIndex
enclosingIndex(lexical
.enclosing
);
211 if (!ScopeStencil::createForLexicalScope(
212 fc
, compilationState
, ScopeKind::Lexical
, data
, firstFrameSlot
,
213 mozilla::Some(enclosingIndex
), &index
)) {
218 case SmooshScopeData::Tag::Function
: {
219 auto& function
= scopeData
.AsFunction();
221 size_t numBindings
= function
.bindings
.len
;
222 FunctionScope::ParserData
* data
=
223 NewEmptyFunctionScopeData(fc
, alloc
, numBindings
);
228 CopyBindingNames(cx
, function
.bindings
, allAtoms
,
229 GetScopeDataTrailingNamesPointer(data
));
231 // NOTE: data->slotInfo.nextFrameSlot is set in
232 // ScopeStencil::createForFunctionScope.
234 if (function
.has_parameter_exprs
) {
235 data
->slotInfo
.setHasParameterExprs();
237 data
->slotInfo
.nonPositionalFormalStart
=
238 function
.non_positional_formal_start
;
239 data
->slotInfo
.varStart
= function
.var_start
;
240 data
->length
= numBindings
;
242 bool hasParameterExprs
= function
.has_parameter_exprs
;
243 bool needsEnvironment
= function
.non_positional_formal_start
;
244 ScriptIndex functionIndex
= ScriptIndex(function
.function_index
);
245 bool isArrow
= function
.is_arrow
;
247 ScopeIndex
enclosingIndex(function
.enclosing
);
248 if (!ScopeStencil::createForFunctionScope(
249 fc
, compilationState
, data
, hasParameterExprs
, needsEnvironment
,
250 functionIndex
, isArrow
, mozilla::Some(enclosingIndex
),
258 // `ConvertGCThings` depends on this condition.
259 MOZ_ASSERT(index
== i
);
265 // Given the result of SmooshMonkey's parser, convert a list of RegExp data
266 // into a list of RegExpStencil.
267 bool ConvertRegExpData(JSContext
* cx
, FrontendContext
* fc
,
268 const SmooshResult
& result
,
269 CompilationState
& compilationState
) {
270 auto len
= result
.regexps
.len
;
275 if (len
> TaggedScriptThingIndex::IndexLimit
) {
276 ReportAllocationOverflow(fc
);
280 if (!compilationState
.regExpData
.reserve(len
)) {
281 js::ReportOutOfMemory(fc
);
285 for (size_t i
= 0; i
< len
; i
++) {
286 SmooshRegExpItem
& item
= result
.regexps
.data
[i
];
287 auto s
= smoosh_get_slice_at(result
, item
.pattern
);
288 auto len
= smoosh_get_slice_len_at(result
, item
.pattern
);
290 JS::RegExpFlags::Flag flags
= JS::RegExpFlag::NoFlags
;
292 flags
|= JS::RegExpFlag::Global
;
294 if (item
.ignore_case
) {
295 flags
|= JS::RegExpFlag::IgnoreCase
;
297 if (item
.multi_line
) {
298 flags
|= JS::RegExpFlag::Multiline
;
301 flags
|= JS::RegExpFlag::DotAll
;
304 flags
|= JS::RegExpFlag::Sticky
;
307 flags
|= JS::RegExpFlag::Unicode
;
310 // FIXME: This check should be done at parse time.
312 JS::UniqueTwoByteChars
pattern(
313 UTF8CharsToNewTwoByteCharsZ(cx
, JS::UTF8Chars(s
, len
), &length
,
320 mozilla::Range
<const char16_t
> range(pattern
.get(), length
);
322 TokenStreamAnyChars
ts(fc
, compilationState
.input
.options
,
323 /* smg = */ nullptr);
325 // See Parser<FullParseHandler, Unit>::newRegExp.
327 if (!irregexp::CheckPatternSyntax(cx
->tempLifoAlloc(), fc
->stackLimit(), ts
,
332 const mozilla::Utf8Unit
* sUtf8
=
333 reinterpret_cast<const mozilla::Utf8Unit
*>(s
);
334 auto atom
= compilationState
.parserAtoms
.internUtf8(fc
, sUtf8
, len
);
339 // RegExp patterm must be atomized.
340 compilationState
.parserAtoms
.markUsedByStencil(atom
,
341 ParserAtom::Atomize::Yes
);
342 compilationState
.regExpData
.infallibleEmplaceBack(atom
,
343 JS::RegExpFlags(flags
));
349 // Convert SmooshImmutableScriptData into ImmutableScriptData.
350 UniquePtr
<ImmutableScriptData
> ConvertImmutableScriptData(
351 JSContext
* cx
, const SmooshImmutableScriptData
& smooshScriptData
,
353 Vector
<ScopeNote
, 0, SystemAllocPolicy
> scopeNotes
;
354 if (!scopeNotes
.resize(smooshScriptData
.scope_notes
.len
)) {
357 for (size_t i
= 0; i
< smooshScriptData
.scope_notes
.len
; i
++) {
358 SmooshScopeNote
& scopeNote
= smooshScriptData
.scope_notes
.data
[i
];
359 scopeNotes
[i
].index
= GCThingIndex(scopeNote
.index
);
360 scopeNotes
[i
].start
= scopeNote
.start
;
361 scopeNotes
[i
].length
= scopeNote
.length
;
362 scopeNotes
[i
].parent
= scopeNote
.parent
;
365 AutoReportFrontendContext
fc(cx
);
366 return ImmutableScriptData::new_(
367 &fc
, smooshScriptData
.main_offset
, smooshScriptData
.nfixed
,
368 smooshScriptData
.nslots
, GCThingIndex(smooshScriptData
.body_scope_index
),
369 smooshScriptData
.num_ic_entries
, isFunction
, smooshScriptData
.fun_length
,
371 mozilla::Span(smooshScriptData
.bytecode
.data
,
372 smooshScriptData
.bytecode
.len
),
373 mozilla::Span
<const SrcNote
>(), mozilla::Span
<const uint32_t>(),
374 scopeNotes
, mozilla::Span
<const TryNote
>());
377 // Given the result of SmooshMonkey's parser, convert a list of GC things
378 // used by a script into ScriptThingsVector.
379 bool ConvertGCThings(JSContext
* cx
, FrontendContext
* fc
,
380 const SmooshResult
& result
,
381 const SmooshScriptStencil
& smooshScript
,
382 CompilationState
& compilationState
,
383 Vector
<TaggedParserAtomIndex
>& allAtoms
,
384 ScriptIndex scriptIndex
) {
385 size_t ngcthings
= smooshScript
.gcthings
.len
;
387 // If there are no things, avoid the allocation altogether.
388 if (ngcthings
== 0) {
392 TaggedScriptThingIndex
* cursor
= nullptr;
393 if (!compilationState
.allocateGCThingsUninitialized(fc
, scriptIndex
,
394 ngcthings
, &cursor
)) {
398 for (size_t i
= 0; i
< ngcthings
; i
++) {
399 SmooshGCThing
& item
= smooshScript
.gcthings
.data
[i
];
401 // Pointer to the uninitialized element.
402 void* raw
= &cursor
[i
];
405 case SmooshGCThing::Tag::Null
: {
406 new (raw
) TaggedScriptThingIndex();
409 case SmooshGCThing::Tag::Atom
: {
410 new (raw
) TaggedScriptThingIndex(allAtoms
[item
.AsAtom()]);
413 case SmooshGCThing::Tag::Function
: {
414 new (raw
) TaggedScriptThingIndex(ScriptIndex(item
.AsFunction()));
417 case SmooshGCThing::Tag::Scope
: {
418 new (raw
) TaggedScriptThingIndex(ScopeIndex(item
.AsScope()));
421 case SmooshGCThing::Tag::RegExp
: {
422 new (raw
) TaggedScriptThingIndex(RegExpIndex(item
.AsRegExp()));
431 // Given the result of SmooshMonkey's parser, convert a specific script
432 // or function to a StencilScript, given a fixed set of source atoms.
434 // The StencilScript would then be in charge of handling the lifetime and
435 // (until GC things gets removed from stencil) tracing API of the GC.
436 bool ConvertScriptStencil(JSContext
* cx
, FrontendContext
* fc
,
437 const SmooshResult
& result
,
438 const SmooshScriptStencil
& smooshScript
,
439 Vector
<TaggedParserAtomIndex
>& allAtoms
,
440 CompilationState
& compilationState
,
441 ScriptIndex scriptIndex
) {
442 using ImmutableFlags
= js::ImmutableScriptFlagsEnum
;
444 const JS::ReadOnlyCompileOptions
& options
= compilationState
.input
.options
;
446 ScriptStencil
& script
= compilationState
.scriptData
[scriptIndex
];
447 ScriptStencilExtra
& scriptExtra
= compilationState
.scriptExtra
[scriptIndex
];
449 scriptExtra
.immutableFlags
=
450 ImmutableScriptFlags(smooshScript
.immutable_flags
);
452 // FIXME: The following flags should be set in jsparagus.
453 scriptExtra
.immutableFlags
.setFlag(ImmutableFlags::SelfHosted
,
454 options
.selfHostingMode
);
455 scriptExtra
.immutableFlags
.setFlag(ImmutableFlags::ForceStrict
,
456 options
.forceStrictMode());
457 scriptExtra
.immutableFlags
.setFlag(ImmutableFlags::HasNonSyntacticScope
,
458 options
.nonSyntacticScope
);
460 if (&smooshScript
== &result
.scripts
.data
[0]) {
461 scriptExtra
.immutableFlags
.setFlag(ImmutableFlags::TreatAsRunOnce
,
463 scriptExtra
.immutableFlags
.setFlag(ImmutableFlags::NoScriptRval
,
464 options
.noScriptRval
);
468 scriptExtra
.immutableFlags
.hasFlag(ImmutableFlags::IsFunction
);
470 if (smooshScript
.immutable_script_data
.IsSome()) {
471 auto index
= smooshScript
.immutable_script_data
.AsSome();
472 auto immutableScriptData
= ConvertImmutableScriptData(
473 cx
, result
.script_data_list
.data
[index
], isFunction
);
474 if (!immutableScriptData
) {
478 auto sharedData
= SharedImmutableScriptData::createWith(
479 fc
, std::move(immutableScriptData
));
484 if (!compilationState
.sharedData
.addAndShare(fc
, scriptIndex
, sharedData
)) {
488 script
.setHasSharedData();
491 scriptExtra
.extent
.sourceStart
= smooshScript
.extent
.source_start
;
492 scriptExtra
.extent
.sourceEnd
= smooshScript
.extent
.source_end
;
493 scriptExtra
.extent
.toStringStart
= smooshScript
.extent
.to_string_start
;
494 scriptExtra
.extent
.toStringEnd
= smooshScript
.extent
.to_string_end
;
495 scriptExtra
.extent
.lineno
= smooshScript
.extent
.lineno
;
496 scriptExtra
.extent
.column
=
497 JS::LimitedColumnNumberOneOrigin(1 + smooshScript
.extent
.column
);
500 if (smooshScript
.fun_name
.IsSome()) {
501 script
.functionAtom
= allAtoms
[smooshScript
.fun_name
.AsSome()];
503 script
.functionFlags
= FunctionFlags(smooshScript
.fun_flags
);
504 scriptExtra
.nargs
= smooshScript
.fun_nargs
;
505 if (smooshScript
.lazy_function_enclosing_scope_index
.IsSome()) {
506 script
.setLazyFunctionEnclosingScopeIndex(ScopeIndex(
507 smooshScript
.lazy_function_enclosing_scope_index
.AsSome()));
509 if (smooshScript
.was_function_emitted
) {
510 script
.setWasEmittedByEnclosingScript();
514 if (!ConvertGCThings(cx
, fc
, result
, smooshScript
, compilationState
, allAtoms
,
522 // Free given SmooshResult on leaving scope.
523 class AutoFreeSmooshResult
{
524 SmooshResult
* result_
;
527 AutoFreeSmooshResult() = delete;
529 explicit AutoFreeSmooshResult(SmooshResult
* result
) : result_(result
) {}
530 ~AutoFreeSmooshResult() {
532 smoosh_free(*result_
);
537 // Free given SmooshParseResult on leaving scope.
538 class AutoFreeSmooshParseResult
{
539 SmooshParseResult
* result_
;
542 AutoFreeSmooshParseResult() = delete;
544 explicit AutoFreeSmooshParseResult(SmooshParseResult
* result
)
546 ~AutoFreeSmooshParseResult() {
548 smoosh_free_parse_result(*result_
);
553 void InitSmoosh() { smoosh_init(); }
555 void ReportSmooshCompileError(JSContext
* cx
, FrontendContext
* fc
,
556 ErrorMetadata
&& metadata
, int errorNumber
, ...) {
558 va_start(args
, errorNumber
);
559 ReportCompileErrorUTF8(fc
, std::move(metadata
), /* notes = */ nullptr,
565 bool Smoosh::tryCompileGlobalScriptToExtensibleStencil(
566 JSContext
* cx
, FrontendContext
* fc
, CompilationInput
& input
,
567 JS::SourceText
<mozilla::Utf8Unit
>& srcBuf
,
568 UniquePtr
<ExtensibleCompilationStencil
>& stencilOut
) {
569 // FIXME: check info members and return with *unimplemented = true
570 // if any field doesn't match to smoosh_run.
572 auto bytes
= reinterpret_cast<const uint8_t*>(srcBuf
.get());
573 size_t length
= srcBuf
.length();
575 SmooshCompileOptions compileOptions
;
576 compileOptions
.no_script_rval
= input
.options
.noScriptRval
;
578 SmooshResult result
= smoosh_run(bytes
, length
, &compileOptions
);
579 AutoFreeSmooshResult
afsr(&result
);
581 if (result
.error
.data
) {
582 ErrorMetadata metadata
;
583 metadata
.filename
= JS::ConstUTF8CharsZ("<unknown>");
584 metadata
.lineNumber
= 1;
585 metadata
.columnNumber
= JS::ColumnNumberOneOrigin();
586 metadata
.isMuted
= false;
587 ReportSmooshCompileError(cx
, fc
, std::move(metadata
),
588 JSMSG_SMOOSH_COMPILE_ERROR
,
589 reinterpret_cast<const char*>(result
.error
.data
));
593 if (result
.unimplemented
) {
594 MOZ_ASSERT(!stencilOut
);
598 if (!input
.initForGlobal(fc
)) {
602 LifoAllocScope
parserAllocScope(&cx
->tempLifoAlloc());
604 Vector
<TaggedParserAtomIndex
> allAtoms(fc
);
605 CompilationState
compilationState(fc
, parserAllocScope
, input
);
606 if (!ConvertAtoms(cx
, fc
, result
, compilationState
, allAtoms
)) {
610 if (!ConvertScopeStencil(cx
, fc
, result
, allAtoms
, compilationState
)) {
614 if (!ConvertRegExpData(cx
, fc
, result
, compilationState
)) {
618 auto len
= result
.scripts
.len
;
620 // FIXME: What does it mean to have no scripts?
621 MOZ_ASSERT(!stencilOut
);
625 if (len
> TaggedScriptThingIndex::IndexLimit
) {
626 ReportAllocationOverflow(fc
);
630 if (!compilationState
.scriptData
.resize(len
)) {
631 js::ReportOutOfMemory(fc
);
635 if (!compilationState
.scriptExtra
.resize(len
)) {
636 js::ReportOutOfMemory(fc
);
640 // NOTE: Currently we don't support delazification or standalone function.
641 // Once we support, fix the following loop to include 0-th item
642 // and check if it's function.
643 MOZ_ASSERT_IF(result
.scripts
.len
> 0, result
.scripts
.data
[0].fun_flags
== 0);
644 for (size_t i
= 1; i
< result
.scripts
.len
; i
++) {
645 auto& script
= result
.scripts
.data
[i
];
646 if (script
.immutable_script_data
.IsSome()) {
647 compilationState
.nonLazyFunctionCount
++;
651 if (!compilationState
.prepareSharedDataStorage(fc
)) {
655 for (size_t i
= 0; i
< len
; i
++) {
656 if (!ConvertScriptStencil(cx
, fc
, result
, result
.scripts
.data
[i
], allAtoms
,
657 compilationState
, ScriptIndex(i
))) {
663 fc
->getAllocator()->make_unique
<frontend::ExtensibleCompilationStencil
>(
664 std::move(compilationState
));
669 stencilOut
= std::move(stencil
);
673 bool SmooshParseScript(JSContext
* cx
, const uint8_t* bytes
, size_t length
) {
674 SmooshParseResult result
= smoosh_test_parse_script(bytes
, length
);
675 AutoFreeSmooshParseResult
afspr(&result
);
676 if (result
.error
.data
) {
677 JS_ReportErrorNumberUTF8(cx
, GetErrorMessage
, nullptr,
678 result
.unimplemented
? JSMSG_SMOOSH_UNIMPLEMENTED
679 : JSMSG_SMOOSH_COMPILE_ERROR
,
680 reinterpret_cast<const char*>(result
.error
.data
));
687 bool SmooshParseModule(JSContext
* cx
, const uint8_t* bytes
, size_t length
) {
688 SmooshParseResult result
= smoosh_test_parse_module(bytes
, length
);
689 AutoFreeSmooshParseResult
afspr(&result
);
690 if (result
.error
.data
) {
691 JS_ReportErrorNumberUTF8(cx
, GetErrorMessage
, nullptr,
692 result
.unimplemented
? JSMSG_SMOOSH_UNIMPLEMENTED
693 : JSMSG_SMOOSH_COMPILE_ERROR
,
694 reinterpret_cast<const char*>(result
.error
.data
));
701 } // namespace frontend