►
From YouTube: Source Editor engineering deep dive
Description
The engineering session on architecture and implementations behind the Source Editor.
A
Okay,
we
are
recording
to
the
cloud
apparently
hello,
everyone
we
are
here
for
the
Source
editor
engineering,
deep
dive.
Today,
where
we
are
go,
it's
go.
It's
a
continuation
of
the
first
session,
where
we
had
the
high
level
introduction
into
the
Source
editor.
What
source
editor
is
what
source
letter
is
not
and
some
a
vision
of
this
product.
A
As
of
this
feature,
as
we
go
go
on
with
maintaining
it
within
source
code
groups
context,
this
session
is
dedicated
to
the
Deep
engineering
dive
into
how
this
thing
is
built,
how
to
build
new
applications
with
Source
header,
how
to
to
understand
what
is
going
on
there
and
how
technically
applied
on
the
in
the
real
time
real
life
projects.
A
So
I
will
start
with
with
the
presentation
and
for
that
I
probably
need
to
share
my
screen.
I'm
going
to.
B
Super
stuff,
let
me
just
rearrange
the
things
a
bit
and
okay.
We.
A
Are
we're
here
so,
as
I
said,
engineering
deep
dive
going
to
be
a
lot
of
exciting
things,
but
we'll
make
it
even
more
entertaining
by
having
a
dialogue.
So
what
is
Source
header?
We
have
covered
this
in
the
first
session
right.
We
have
this
high
level
introduction
that
Source
Center
is
the
thin
layer
on
top
of
the
Monaco
editor.
A
Why
thing
layer?
This
is
by
Design.
We
want
to
be
as
close
to
the
Monaco
API
as
possible.
They
once
you
reach
out
to
the
Monaco
API
documentation.
We
want.
All
of
this
still
be
valid
for
Source
editor,
so
ciety
builds
some
additional
functionality
on
top
of
that,
but
this
is
devices.
So
all
of
the
things
in
official
Monaco
documentation
should
be
valid.
A
The
core
because
of
this,
so
that
we
do
not
mess
up
with
the
native
Monaco
API.
The
core
of
the
source
header
should
at
any
point
of
time,
be
stable.
It
should
not
be
broken
it
preferably.
We
do
not
need
to
spend
any
time
maintaining
this
core.
It's
there.
It's
working,
no
big
deal
all
of
the
functionality.
All
of
the
new
features
to
the
source.
Header
come
from
the
extensions,
so
the
extensions
are
the
things
that
are
extend,
Source
header
and
provide
us
with
the
new
shiny
functionality.
A
This
has
been
covered
in
the
first
session,
but
what
this
Source
editor
is
technically,
let's
talk
about
this,
so
it's
framework
agnostic,
JavaScript
editor.
What
does
framework
agnostic
mean?
It
works
both
in
rails
and
as
an
example,
you
do
see
the
code
snippet
now
right,
yeah,
yes,
okay,
so
we
can
use
Source
header
in
rails.
Applications,
as
this
part
shows
it
is
used
for
for
the
blob
editing
in
the
web
editor.
So
that's
that's
how
we
configure
The
Source
header.
This
file
is
pretty
old.
A
That's
why
we
have
configured
Monaco,
editor
and
different
things
like
this,
but
the
idea
is,
we
can
use
it
in
rails
application
and
we
can
use
it
in
View
application.
The
View
application
example
is
Snippets
in
Snippets
we
use
sourceater
as
the
view
component
so
yeah
for
for
the
convenience.
We
have
the
view
component,
which
is
shared
view
component
to
implement
in
view
applications.
A
So
this
picture
the
the
one
thing
that
I
admitted
when
we
had
the
high
level
discussion
on
this
diagram
and
this
flow
or
chart
flow
or
whatever,
whatever
you
prefer
to
call
it.
So
there
is
one
more
thing
missing
between
Source
header
and
the
extensions
instance,
so
instance
is
one
instance
of
source
editor
on
the
page.
Think
about
instance,
as
one
visual
UI
element
this
representing
one
editor.
So,
for
example,
if
we
go
to
the
to
edit
a
snippet,
we
allow
up
to
10
blobs
to
be
able
to
snippet.
A
This
means
that
on
that
page,
we
will
have
10
different
instances.
So
one
instance
is
one
editor
frame
that
you
see
on
the
screen
when
it
comes
to
the
web
editor.
There
is
just
one
instance:
there
Source
error
supports
any
number
of
instances.
It's
very
extensible,
so
you
can
have
any
number
of
instances
you
want,
and
every
single
instance
can
have
their
own
set
of
sets
of
extensions,
we'll
all
be
talking
about
the
extensions
and
the
instances
of
it
a
bit
deeper.
A
A
We
have
this
screenshot
of
the
snippet
edit
form
with
two
blobs
here,
so
Global
editor
versus
instance.
This
is
the
relationship
one
to
many,
so
there
is
only
one
Global
editor
on
the
page,
but
there
are
maybe
there
may
be
many
instances
from
that
Global
editor.
So
what
does
it
give
us?
It
gives
us
shared
edited
settings,
so
we
set
the
global
pass,
the
global
options
to
the
global
editor
and
then
all
of
those
options,
for
example,
minimap
or
soft
trap,
or
anything
like
this.
A
Once
we
pass
those
options
to
the
global
editor,
any
instance
we
create
from
that
Global
editor
will
inherit
all
of
those
options,
so
this
is
to
share
common
options.
So,
on
the
on
the
Snippets,
it's
a
bit
different
I
have
to
sort
of
mention
this,
because
the
view
component
is
implemented
a
bit
different.
But
if
we're
talking
about
JavaScript
only
and
like
the
original
architecture,
it's
one
too
many
one
Global
letter
in
many
instances
there
are.
A
There
are
use
cases
when
you
do
not
need
the
global
options
of
the
global
editor
in
your
particular
instance.
So
one
off
case
in
this
case
we
can
use
instance
level
options.
When
you
create
an
instance
from
the
global
editor,
you
can
say
I
do
want
to
override
those
options
in
the
global
editor.
With
these
options
on
the
instance
level
and
the
options
are
pretty
much
interchangeable.
So
most
of
the
options
you
pass
to
the
global
editor
are
the
same.
A
You
can
pause
on
the
instance
level
and
you
can
override
those,
but
if
this
is
not
enough
for
you
for
some
reason,
I
haven't
seen.
Use
cases
like
this.
That
should
be
okay
to
create
a
new
Global
editor
for
this
set
of
instances
or
for
this
one
particular
instance,
but
this
is
sort
of
The
Last
Resort
thing
now
instance,
as
we,
the
the
definition
of
instance
that
we
have
in
the
source,
editor
corresponds.
A
A
All
of
the
document
documentation
should
be
valid
for
our
instance
of
regular
editor
and
then
Standalone
diff
editor
is
the
div
editor
that
we
can
that
we
can
show
to
the
users.
The
example
of
the
diff
editor
powered
by
Source
header
is
the
Legacy
web
ID.
When
you
go
to
commit
tab
or
you
go
to
reviewmergic
West,
that's
where
you
see
the
diff
editor
powered
by
source
source
editor.
A
A
The
the
way
we
do
this
so,
let's
get
to
some
code
here
so
Global
editor
versus
versus
instance.
The
example
is
again
the
the
way
Source
header
is
implemented
in
the
web.
Editor,
our
regular
blob
editor.
So
you
see
this
snippet
here
on
the
on
the
right.
So
the
main
things
here
is
that
we
create
the
root,
editor
or
Global
editor
or
whatever.
It
is
just
a
constant
right,
new
source
header,
we
import
The,
Source
header
and
then
we
just
create.
A
This
is
just
a
regular
class
new
source
header,
and
then
we
create
the
instance
with
this
Global
editor
create
instance.
As
I
said,
this
file
is
pretty
old.
So
technically,
this
should
be
this
dot
instance,
but
I
didn't
care
renaming
this
before
for
the
purpose
of
this
call,
it's
just.
It's
called
very
confusingly
in
this
file,
this
dot
editor,
but
this
is
technically
instance.
Now
we
create
it
with
root
editor
dot,
create
instance.
This
is
the
the
API,
the
part
of
the
proprietary
Source,
editor
API.
This
is
not
part
of
Monaco
API.
A
A
D
You
can
you
zoom
in
a
little
bit.
It's
just
very
small,
of
course,.
A
So,
oh
actually,
I
can
wait.
A
second
I
can.
B
A
In
so
thanks
so
create
instance,
takes
some
parameters
and
they're
pretty
straightforward.
So
L
is
the
element
on
which
you
want
to
bootstrap
The
Source
editor,
just
like
The
View
application.
This
element
will
be
replaced.
So
if
you
want
to
preserve
some
CSS
classes,
IDs
or
something
like
this,
you
have
to
keep
them
on
some
on
the
wrapper
element,
because
the
element
you
pass
here
as
the
hook
for
Source
editor
will
be
destroyed
and
a
source
area
will
replace
it.
Just
the
same
way.
View
application
is
bootstrapped.
A
Blob
path
is
the
is
the
name
of
the
blob.
It's
part
of
the
of
the
blob.
This
part
is
used
to
deter
to
identify
the
syntax
highlighting
for
this
file
type
based
on
the
extension.
So
with
that
being
said,
you
do
not
necessarily
need
to
have
the
path.
A
For
example,
if
we're
talking
about
CI
CI
editor,
it's
always
gitlab
ci.yaml,
but
technically
we
do
not
need
to
pass
the
full
path,
we're
interested,
in
extension,
only
so
it's
totally
valid
to
pass
it
as
asterisk
Dot
yaml,
and
that
will
be
enough
for
the
source
Editor
to
detect
that
this
is
the
yaml
file
and
we
need
to
apply
syntax
highlighting
for
the
yaml
file.
A
Blob
content
is
our
basic
content
to
start
Source
editor
with.
Usually
it
is
going
to
be
the
empty
string
if
we
want
to
show
the
empty
editor,
but
if
it's
editing
an
existing
blob
in
the
repository
we
pass.
The
current
content
of
The
Blob
into
the
source,
editor
Globe
original
content
is
used
only
for
the
diff
editor.
A
We
had
some
cases
where
in
in
particular
in
the
Legacy
web
ID,
where,
due
to
the
architecture
of
the
Legacy
webri,
we
had
collisions
when
Monaco,
so
underlying
engine
tried
to
destroy
different
instances
and
they
they
had
the
same
Global
ID,
which
was
not
really
cool.
We
protected
from
from
happening
by
General
Auto,
generating
the
you
ID.
A
But
if
you
want
to
control
this,
if,
for
example,
in
the
future,
you
want
to
know
and
know
for
sure
the
instance
you're
getting
to
by
your
ID.
This
is
the
place
to
pass
that
uid
and
then
access
it
by
this
uid
and
SDF
is
pretty
much
self-explanatory,
whether
we
are
creating
diff
in
diff
instance
or
not,
and
that's
that's
it.
A
This
is
the
entry
point
the
instance
options.
This
is
the
entry
points
for
your
custom
per
instance
options
if
you
want
to
override
something
from
the
global
editor
or
you
want
to
extend
those
options
on
this
particular
instance
level.
This
is
the
place
to
to
pass
the
options
and
that
which
what
it
does
is.
It
defines
whether
we
create
the
diff,
editor
or
simple
code
editor.
It
creates
the
instance.
A
The
editor
Source
editor
instance-
this
is
just
the
hook,
for
this
is
proprietary
gitlab
hook,
because
we
have
to
wait
for
startup
CSS
to
be
bootstrapped
before
we
can
sort
of
after
the
bootstrap
after
the
startup
CSS
is
booted.
A
We
have
to
relay
out
our
editor
because
the
CSS
coming
after
startup
CSS
might
change
the
layout
of
the
page,
and
hence
we
have
to
make
sure
that
sourceater
takes
the
whole
Space
it
has
in
its
parent.
So
this
is
just
for
for
gitlop
thing,
and
then
we
create
a
model.
A
We
are
going
to
talk
about
model
a
bit
later,
so
modal
is
just
the
code
representation
of
the
content
of
your
instance,
so
every
content
of
every
instance
is
going
to
be
represented
by
modal,
based
on
the
language
based
on
the
content
based
on
the
whether
it's
a
diff
or
not
diff.
So
different
things
like
this.
We
do
not
need
to
think
about
this
for
now
really
and
then
just
just
internal
magic.
A
We
create
we
put
all
the
instances
in
the
in
the
global
registry
of
our
Global
Editor
to
to
share
the
code
to
do
some
some
helper
things,
but
in
general
you
do
not
need
to
get
into
all
of
these
internals.
What
you
have
to
know
is
just
this
create
instance,
on
the
global
editor.
That's
it
all.
This
internals
are
just
internals
think
about
it
as
the
Black
Box.
A
So
getting
back
to
our
slides
again.
This
is
the
picture
of
the
main
components
here
right.
So
the
information
on
the
Monaco
we
get
from
the
official
Monaco
documentation,
information
on
the
source,
editor
core.
We
get
from
our
source,
header
module,
which
is
in
our
editor,
slash,
Source,
editor.js,
pretty
straightforward
instance.
We
get
from
sourceater
instance,
module
again
a
separate
editor
Source
editor
instance:
dot
GS
module.
A
It
comes
with
asterisk
I'm
gonna
talk
about
this
in
a
second
The
Source
header
view
component
again
represents
the
instance
level.
So
when
you
add
a
view
component
you're
adding
an
instance
of
the
source
header,
you
do
not
add
a
global
editor,
it's
the
instance
and
then
for
the
extension
again.
We
have
a
separate
extension
module.
A
Surprisingly
editor
Source
editor
extension,
the
this
one
comes
with
asterisk
as
well.
So
what,
by
what
I
mean
by
this
asterisks?
Is
that,
as
we
saw
in
this
create
instance
method
you
do
not
create,
you
do
not
create
neither
extension,
nor
instance
manually
explicitly.
You
do
not
get
to
these
modules
explicitly.
They
are
internal,
and
the
only
consumer
of
this
modules
is
create.
Instance,
function
on
your
Global
editor,
so
these
are
just
for
the
educational
purposes.
A
You
do
not
need
to
use
those,
they
are
kind
of
like
treat
them
as
private,
private,
private
modules
or
whatever
you
prefer
to
call
it.
So,
let's
talk
about
the
application
architecture,
typical
Source,
editor
application
architecture.
As
we
said,
as
we
said,
we
have
the
global
editor
at
the
top
that
we
create
with
new
Source
editor
Constructor
done.
Global
editor
can
have
one
or
many
instances
connected
to
it.
Then
every
instance
is
going
to
have
one
modal.
As
I
said,
this
is
texture.
This
is
code
representation
of
the
editor's
content.
A
It's
very
important
to
understand
that
every
instance
at
any
given
point
in
time
will
have
only
one
model,
so
it's
possible
to
attach
another
model
to
the
instance,
but
it
will
replace
the
previous
modal.
Where
is
it
useful?
This
is
the
architecture
that
is
used
in
the
Legacy
web
ID
Legacy
ID
is
built
with
global
editor,
just
one
instance
not
many
instances,
one
instance
and
then
every
tab
you
open
is
representing
its
own
module.
So
what
happens
is
when
you
click
a
file?
A
You
open
the
tab,
we
create
a
modal
and
that
model
replaces
the
previous
model.
In
the
existing
instance.
We
do
not
create
one
instance
per
tab.
We
create
one
model
per
tab,
because
creating
a
model
is
much
cheaper
than
creating
an
instance,
so
we
just
swap
the
modals
within
one
instance
and
that's
it
because
you
never
look
at
two
files
side
by
side
at
the
same
time.
A
So
there
is
no
danger
in
reusing
the
existing
instance
and
just
swapping
the
modals
so
one
model
at
a
time,
and
then
we
can
have
any
number
of
extensions
connected
to
each
particular
instance.
We
can
even
have
a
one
extension.
The
same
extension
shared
by
one
or
several
instances,
and
that's
that's
going
to
be
fine,
because
every
extension
is
represented
by
either
class
or
function
and
every
instance
can
import
that
class
or
function
and
just
apply
it
we're
going
to
talk
about
how
to
apply
extension
a
bit
later.
D
D
How
do
we
identify
an
instance,
so
you
said:
there's
one:
if
you
open,
you
can
have
multiple
instances,
the
same
model
but.
A
No,
no,
no
wait.
A
second
modal
is
connected
to
an
instance,
so
it's
not
possible
to
share
model
between
instances.
It's
possible
to
share
extensions
between
instances,
but
not
modal
modal
is
just
one
instance.
It's
like
one
to
one
one
modal
per
one
instance,
and
they
are
connected.
A
Okay,
that
makes
sense
so
and
if
you,
if
you,
if
you
mean
how
do
we
identify
what
instance
to
install
extension
for
then
or
is
this
now,
let's
let
me
just
get
up
not
here.
Let
me
get
to
two
two.
Two
two.
B
A
So
when
you
create
an
instance,
so
create
instance
function
Returns
the
instance,
so
you
can
store
it
in
a
in
a
constant
in
a
variable,
and
then
you
can
use
that
instance.
So
to
any
given
point
of
time,
you
know
exactly
what
what
instance
you're
you're
working
with,
because
you
can
save
it
in
in
the
constant.
If
you
need
multiple
instances,
you
create
multiple
constants,
for
example,
instant
ones
instance,
two
instance
three
and
that's
how
you
can
control
what
instance
to
install
extension
for
or
uninstall.
B
D
Yeah
I
think
that's
that
makes
sense.
Yeah,
okay,.
B
C
A
We
do
not
store
anything
in
the
local
storage.
We
technically
like
creating
a
model
is
super
cheap,
so
for
the
Legacy
web
ID.
What
we
do
is
when
you
open
a
new
tab.
We
just
discard
the
old
model.
It's
just
like
it's,
it's
very
cheap.
It's
really
the
code
representation
of
the
text,
so
we
just
create
the
new
model
and
connect
it
to
the
existing
instance.
If
we
go
back
to
the
previous
tab,
we
do
the
same.
C
A
Is
this
is
very
cheap
comparing
to
creating
new
instance
for
the
model,
because
otherwise
we
would
have
to,
as
I
said,
the
connection
between
instance
and
modal
is
one
model
per
instance
and
one
instance
per
modal.
If
we
would
be
to
store
to
preserve
the
models,
we
would
have
to
create
one
instance
per
Tab,
and
that
operation
is
a
bit
more
expensive
than
just
creating
and
discarding
models.
C
And,
for
example,
the
content,
because,
when
I
have
an
editor,
open
and
I
changed
something
and,
for
example,
I
open
a
new
duplicate,
the
top,
so
it's
content
being
saved
in
a
local
storage,
for
example,
nope.
A
Nope,
no,
it's
not
it's
not
stored.
It's
it's
the
content,
which
is
the
in
the
in
the
Legacy
web
idea.
We
did
not
store
anything
in
the
local
storage,
no
content,
nothing!
It's
we
I'm
trying
to
to
remember
now
how
how
in
particular,
we
we
deal
with
the
content
changes,
but
what
I
remember
for
sure
is
that
we
do
not
use
local
storage
there
and
we
discard
the
models.
A
The
changes
you
make
are
stored
in
the
memory
while
you're
in
the
in
the
web
ID.
So
when
we
go
back
to
the
previous
tab,
we
have
that
in
the
memory
the
content
and
we
just
create
a
new
the
new
model
with
that
value
in
in
the
memory.
A
The
the
problem
is
that,
as
I
mentioned,
this
is
a
bit
different
for
the
view
component
and
Snippets
do
use
view,
components,
The,
View
components,
The,
View
component,
technically
a
base,
the
the
idea
of
one
single
Global
editor
so
view
component.
If
we
check
it,
oh
it's
now,
it's
it's
not
somewhere
here
opened
so
view
component
for
Source
header
creates
Global
editor
for
every
instance.
A
Whenever
you
open
the
component
on
the
page,
it
internally
will
create
the
global
Global
editor
and
can
create
instance
for
this
for
This
Global
editor
internally
in
the
component.
E
A
But
no
not
in
the
architecture
like
as
I
said
with
the
Snippets
I
would
I
would
like
the
Snippets
to
follow
the
the
pattern
of
global
one
Global
editor
and
then
creating
one
instance
per
per
blob.
A
Okay,
the
the
performance
concerns
in
the
Snippets
were
related
not
to
the
to
the
architecture
but
to
the
fact
of
low
to
the
to
the
matter
of
loading
large
file
in
in
Monaco,
but
since
Monaco
loads
file,
loads
content
in
in
Chunk
in
you
see
only
like
I,
don't
know,
depending
on
the
height
of
the
other
it
blow.
It
creates
only
the
entries
for
the
visible
lines.
A
Then
it's
it's
pretty
pretty
negligible,
like
even
load
really
large
files
are
loaded
really
fast
there,
because
this
is
this
is
and
I
I'm
sure
Jacques
experienced
this
with
with
the
blob
viewer
like
the
the
problem
with
loading.
Large
files
is
not
related
to
actually
adding
them
in
the
code,
for
example,
but
due
to
the
fact
of
rendering
so
many
and
HTML
entries
that's
the
problem.
So
a.
D
E
E
A
Source
editor
fights
with
this
by
creating
only
like
five
lines:
50
or
50
lines
that
are
which
are
visible
at
the
moment
and
then
just
reusing
them
once
you
scroll
it
guts,
reuse,
the
those
50
lines,
so
it
never
renders
more
than
50
lines.
A
Great
thanks
for
the
question,
so
this
is
this:
is
the
architecture
of
the
typical
Global,
a
typical
Source,
later
architecture.
A
So
let's
talk
about
the
extension
because
that's
where
the
the
the
power
of
source
header
comes
from
right,
so
extension
under
the
hood
in
the
source
code
in
the
in
the
source
code,
not
the
group
but
source
code
of
gitlab
product.
We
have
the
this
file,
which
is
called
example,
underscore
Source,
underscore
X
editor
underscore
extension,
which
actually
provides
you
with
a
boilerplate
for
any
extension
you
you
need
to
create.
It
is
very
well
documented.
It
has
all
the
all.
The
things
explained
why
you
need
those.
A
When
do
you
want
to
use
those?
So
whenever
you
create
a
new
extension,
you
just
take
this
as
the
boilerplate
and
adjust
it
for
your
needs
for
the
needs
of
your
application.
But,
let's
briefly
go
through
the
main
points
of
the
extension.
The
there
are
only
a
few
things
that
the
extension
is
introducing.
So,
first
of
all,
every
extension
has
to
have
extension
name.
This
is
the
static
getter.
You
can
see
it
on
the
right
here.
A
In
this
case
it
returns.
My
fancy
extension-
we
will
be
talking.
We
will
talk
about
why
this
is
important
a
bit
later,
but
every
extension
should
have
this.
If
extension
doesn't
have
this
getter
the
extension
and
you
try
to
use
that
extension,
it
will
throw
in
the
console.
So
this
is
this
is
important,
then,
on
setup,
this
is
the
Callback
which
you
will
probably
use
most
of
the
times
on
setup
is
this
is
one
time
setup
which
sets
up
Monaco
in
most
cases
before
your
extension
is
available
to
the
instance.
A
A
When
this
happens,
the
so
the
the
next
the
next
callback
or
life
cycle
moment
of
the
extension
is
unused.
This
is
exactly
when
you
install
extension
for
your
instance
and
within
this
callback.
All
of
the
public
API
methods
of
your
extension
will
be
available
to
your
instance.
A
A
There
is
the
on
before
unused
pullback.
This
is
the
Callback.
When
you
want
to
uninstall
an
extension
on
before
unused
will
be
called
while
your
public,
your
extensions
public
API,
is
still
available.
It
is
still
here,
so
this
is
the
Callback
to
run
some
time
critical
cleanup,
while
your
extension
is
still
full
here.
You
want
to
do
some
cleanup,
which
is
time
critical,
like
remove
some
visual
elements
on
the
screen,
or
do
something
that
needs
to
be
done
now
and
then
on
unused.
A
This
is
the
Callback
which
is
called
when
your
extension
is
uninstalled,
so
your
instance
doesn't
have
access
to
your
extensions
API
anymore,
but
this
is
a
good
place
to
do
some
asynchronous
cleanup
like
unregister
some
some
keystrokes
or
do
something
which
is
not
time
critical,
but
still
needs
to
be
done.
So
this
is
this.
Separation
is
done
with
performance
in
mind
so
that
we
do
not
create
a
lot
of
the
activity
when
it's
uninstalling
extension
in
a
blocking
manner
blocking
the
main
thread.
A
If
you
want
to
do
if
your
operations
or
your
plane
up
is
not
time
sensitive.
Please
do
this
in
this
on
unused
callback.
It
will
be
done
and
do
it
in
async
manner
if
it
doesn't
require
to
be
done
right
now,
and
that
provides
this
is
the
Callback
that
defines
your
the
public
API
of
your
extension.
This
is
where
you
return.
Where
you
return
properties,
you
return
functions,
which
you
want
your
instance
to
be
extended
with
your
instance.
A
Won't
have
access
to
Onset
up
on
use
on
this
callbacks,
but
everything
that
is
returned
from
the
provides
callback
is
going
to
define
the
public
API
of
the
extension
and
will
extend
your
instance.
So
again,
if
we
take
a
look
on
the
life
cycle
of
the
extension,
it
all
starts
with
on
setup
than
its
own
use.
A
When
you
install
your
extension
on
before
and
use
when
you
it's
before,
you
uninstall
the
extension
and
then
when
you're
done
uninstalling
the
extension-
this
is
the
sort
of
the
final
point
and
between
these
two
points
on
on
use
and
on
before
unused.
This
is
where
your
extensions
API
is
available,
which
you
define
in
provides
and
return
in.
This
provides
callback.
A
Your
extensions
API
is
not
available
outside
of
this
point
again.
The
link
to
the
to
the
example
Source
header
extension-
if
you,
if
we
take
a
look
at
here
at
this
just
briefly,
so
we
get
this
static
getter,
we
have
on
setup,
it
does
have
instance
and
setup
options
defined,
as
the
parameters
here
instance
is
passed
passed
here
automatically
in
all
of
the
callbacks
instance.
You
don't
need
to
explicitly
pass
it
on.
It
will
be
there
for
your
needs.
A
You
don't
need
to
pass
anything
because
you
do
not
really
call
this
callback
functions
manually
and
that
provides
it
just
returns,
a
real
object
with
the
methods
or
properties
that
you
want
to
extend
your
instance
with.
A
There
are
different
examples
here
with
properties
functions
and
how
to
use
this.
So
this
is
a
good
source
of
information
about
how
to
write
the
extension
now.
Yes,
this
is
the
example.
We
yeah,
let's
take
a
look
at
the
real
time,
real
life
extension.
This
is
the
simplest
extension
we
have.
Apparently,
this
is
the
CI
schema
extension.
This
is
used
to
load.
The
CI
schema
for
pipeline
editor
when
you're
working
with
gitlab
CI
yaml
file
and
all
it
does.
As
you
can
see,
this
is
a
very
minimalistic
extension.
A
It
has
static
getter,
as
I
said,
if
you
don't
have
one,
your
extension
will
throw
in
the
console
and
it
doesn't
even
have
on
setup
on
you
on
use
on
unused
because
it
doesn't
need
those
all
it
does
is
provide
the
public
API
in
form
of
register.
Ci
schema
method,
this
method,
once
this
extension,
is
installed
for
an
for
an
instance.
A
This
method
will
be
available
for
your
instance
and
what
all
it
does
it
fetches
the
schema
and
applies
it
for
the
for
the
actual
modal
of
our
instance,
because
that's
the
textual
representation
of
our
content.
This
is
very
minimalistic
minimalistic
and
it.
This
kind
of
this
shows
that
extensions
can
be
as
complex
as
you
want
or
as
simple
as
you
want.
A
So
we
have
two
sort
of
polarized
extensions,
so
CI
schema
extension
is
the
minimalistic
one
and
then
we
have
technically
the
whole
Legacy
web
IDE
is
yet
another
extension,
so
all
of
the
functionality
related
to
editing
files
in
the
legacy
webad
is
just
is
just
another
extension.
If
you
go
to
editor
extensions,
there
will
be
Source
editor
web
ID
extension,
and
this
one
is
not
minimalistic,
but
still
pretty.
Okay
provide
again,
has
public
API
and
provides
it
has
on
you
on
use
on
setup.
A
So
it's
not
that
dramatically
complex
either,
but
it
it
definitely
has
much
more
than
just
the
schema
schema
extension
foreign.
A
So
how
do
we
use
the
extensions?
How
how
do
we
I'm
telling
we
install
install
extension?
How
do
we
install
by
simple
use
of
dot
use
method?
Instance,
dot
use
method,
so
this
is
something
that
we
have
to
talk
about
now.
How
do
we
install
thing
installing
an
extension?
So,
let's
assume
we
have
instance-
and
we
have
an
extension
that
we
want
to
install
for
the
for
this
instance.
As
I
said,
we
do,
we
rely
on
the
dot
use
method.
Again.
This
is
the
proprietary
method
of
source
header.
A
This
is
not
Monaco
API,
there's
a
source,
editor
API,
so
you
won't
find
a
documentation
on
use
in
Monaco
documentation,
so
we
do
instance
dot
use
and
then
the
the
signature
of
the
object
that
we
passed
there
is.
We
have
the
definition
and
we
have
the
setup
options.
Two
things
that
we
pass
as
as
the
different
as
the
descriptor
of
the
extension
definition
is,
the
extension
function
or
class
extensions
can
be
written
as
functions
or
classes.
Whatever
way
you
prefer.
A
So
this
is
where
you
pass
your
extension.
You
import
your
extension
in
your
module
and
then
you
pass
that
default
return
of
your
import.
As
definition
of
the
extension,
then,
where
is
the
setup
you
options
used?
It
is
passed
to
your
own
setup
as
the
second
argument,
so
that
you
have
a
way
of
fine-tuning
your
extension.
The
same
extension
on
different
might
might
behave
different
in
different
instances.
So
this
is
the
way
where
you
can
pass
the
setup
options
and,
depending
on
the
options
passed
there,
your
extension
might
behave
a
bit
differently.
A
So
these
are
the
two
things.
The
only
two
things
you
pass
to
the
use
function
in
order
to
install
the
extension.
Do
we
have
any
questions
about
this.
D
You
might
I've
got
a
a
question
about
uninstalling,
but
it
might
be
something
that
is
still
going
to
cover
yeah.
We.
A
So
what
happens
when
we
do
sort
of
we
have
this
dot
use
right,
but
what
happens
when
we
actually
call
this
method
on
our
instance?
So
again
we
have
an
extension.
We
have
our
instance
and
that
we
call
instance.use
for
for
this
extension,
we
pass
the
object
with
definition,
extension
and
let's
say
we
do
not
accept
any
setup
options.
We
don't
need
to
to
set
up
this
extension
in
the
simplest
possible
form.
Instance.
Use
will
be
just
I,
think
we
have
it
in
the
yeah.
So
you
see
here
use
also
accepts
the
array.
A
This
is
this:
is
the
edit
blob,
the
one
we
have
in
the
web
editor,
so
editor
instance,
dot
use,
accepts
the
array
of
different
extensions
and
the
setup
options
might
be
not
needed.
The
only
thing
that
is
required
is
definition
so
that
we,
so
that
instance
would
know
where
to
pull
in
the
extension
definition
from
that's
the
only
required
thing.
So
there
are
three
extensions
passed
here:
none
of
those
needs
any
setup
options.
A
So
what
happens
when
we
call
this
use
and
in
the
very
first
iterations
of
source
header,
we
had
a
lot
of
problems
with
this.
A
We,
what
we
tried
to
do
was
to
really
extend
instance,
so
make
instance
provide
all
of
those
methods
from
the
extensions,
but
what
we
ended
up
with
was
actually
that
we
were
mutating
the
instance,
and
this
led
to
the
situation
where
we
could
not
really
unuse
extensions,
because
if
you
mutate
the
instance,
you
don't
have
you
lose
the
information
of
what
method
comes
from
where
or
you
you
can.
You
have
to
create
a
really
complex
registry
of
these
dependencies
so
and
mutating
instance
is
really
bad
idea.
A
So
we
had
to
come
back
to
the
Whiteboard
so
to
speak
and
rethink
the
architecture
of
how
we
work
with
extensions
and
what
we
came
up
with
was
the
proxy
pattern
architecture.
What
this
means
is
we
go
the
other
way
around
instead
of
mutating
instance
and
letting
instance
sort
of
swallow,
the
extension.
What
we
do
is
extension
wraps
itself
around
the
instance
using
a
proxy
pattern.
A
So
whenever
we
create
We
call
instance.use,
we
are
getting
a
proxy
proxy
which
manages
relationship
between
instance
and
the
extension.
A
So
whenever
we
we
call
some
function
that
we
know
is
coming
from
the
extension,
so
we
do
instance
dot
extension
function.
This
is
not
the
function
from
the
instance.
This
is
function.
Coming
from
the
extension,
what
happens
is
so?
Yes,
as
I
said,
we
return
the
process
so
technically,
when
every
time
you,
you
call
instance
dot
something
you're
calling
a
proxy.
So
when
you
create
an
instance,
you
technically
get
a
proxy.
A
You
don't
get
the
raw
instance,
so
raw
instance
is
protected.
It's
going
to
be
immutable,
so
instance,
extension
function.
What
happens?
Is
our
proxy
gets
into
the
in
into
itself
and
tries
to
figure
out
whether
this
function
name
belongs
to
the
core
instance,
which
is
immutable
which
is
intact?
If
it's
not,
then
it
tries
to
figure
out
what
extension
this
function
is
belonging
to,
and
then
it
returns
this
function
from
our
extension,
not
from
the
instance.
A
This
leads
to
the
situation
where,
for
example,
if
we
need
to
install
the
second
extension
right,
as
we
saw
here,
we
here,
we
actually
have
three
different
extensions.
So
how
does
this
work
in
real
life?
We
already
have
one
extension.
What
happens
with
the
second
extension?
A
A
This.
This
is
something
that
I
call
the
stacking
Dole
architecture,
so
we
have
instance,
which
is
wrapped,
with
extension,
wrapped
with
extension,
wrapped
with
extension,
and
there
is
no
limit
to
this-
and
here
we
come
to
the
unused
or
uninstallation
of
the
extension
Point.
How
does
this
work?
So?
Let's
assume
we
have
this
this
structure
we
have.
We
have
instance,
we
applied
one
extension.
Then
we
applied
the
second
extension,
and
now
we
want
to
unuse
the
very
first
extension
that
has
been
applied.
A
It
has
been
installed,
not
the
last
one,
but
the
the
one
in
the
middle.
What
happens
here
is
that
our
proxy
keeps
track
of.
A
There
are
two
Registries
in
our
in
in
in
the
standard
instance,
instance
instance,
so
to
speak,
so
not
the
proxy
itself,
but
the
the
instance.
So
if
we
go
here,
for
example,
yes,
when
we
create
the
instance,
this
editor
is
returning
is
getting
the
proxy,
but
it
also
has
access
to
two
Registries.
One
registry
is
keeping
the
names
of
the
extensions.
A
Why
so?
Because
if
we
UNS
uninstall
an
extension
and
then
we
want
to
or
not
not
the
names
but
the
definitions,
so
if
we
uninstall
one
extension
and
then
we
want
to
install
it
again,
we
do
not
pull
it
back
from
from
the
code
from
from
the
network
again,
what
we
do
is
just
we
reach
out
to
our
registry.
Do
we
have
this
extension
registered
already
Yes?
We
had
it
it's
gone
now,
but
we
have
the
diff.
We
still
have
the
definition,
so
we
just
use
the
definition
to
speed
up
the
process.
A
We
always
keep
the
access
to
to
uninstalled
extensions
definitions
and
then
the
second
registry
keeps
track
of
all
the
props
and
methods
added
by
each
individual
extension.
It
has
technically
the
the
the
map
where
we
have
the
the
relation
between
extension
name
and
that's
why
the
static
getter
for
the
extension
is
important.
That's
going
to
be
the
key,
defining
your
extension
in
the
registry,
so
the
relationship
between
that
key,
so
the
name
of
your
extension
and
all
the
methods
and
props
provided
by
this
extension.
A
So
when
we
unuse
we
can
get
to
this
to
this
registry
and
know
exactly
what
props
and
methods
belong
to
this
extension,
we
are
going
to
unused
now
so
technically,
what
we
do
is
we
disassemble
this
proxy
that
we
have,
and
we
know
for
sure
what
methods
and
properties
come
with
each
particular
extension.
A
We
get
rid
of
all
the
methods
and
properties
related
to
that
extension.
We
are
unusing
and
then
we
assemble
the
proxy
back
and
return
it
back
to
the
user
again.
This
is
this
is
how
it
works
under
the
hood.
This
uninstall
unused
mechanism
is
really
it's
quite
robust,
and
this
allows
us
to
technically
do
things
like
when
we
are
in
the
web
editor
and
we
are
editing
a
file.
Let's
say
we
start
with.
A
A
Okay,
we
know
because
we
have
the
event
listener.
This
is
beyond
the
the
scope
of
source
header,
but
the
the
user
of
sourceter
notifies
The,
Source
header.
Okay,
we've
got
the
the
name
for
the
file
now
Source
editor
knows
that
we
are
working
with
markdown
file,
it
goes
and
pulls
in
the
markdown
extension,
because
we
have
the
MD
file
and
applies
it
so
automatically
by
just
typing
at
the
path
for
the
file
user
gets
the
updated
editor.
This
is
the
gradual,
complete
sort
of
gradual,
Improvement
or
gradual
complication
of
the
interface.
A
We
start
very
simple
and
then
based
on
the
user
action.
We
do
enrich
the
experience.
So
user
starts
working
with
this
and
then
they
suddenly
realize.
Oh
I.
Don't
really
need
this
to
be
the
markdown
file,
so
they
go
back
to
the
file
name
field.
They
remove
MD
and
name
it
dot.
Txt
Again,
The
Listener
tells
Source
header.
Well,
we
are
dealing
with
the
txt
file
now,
what
source
editor
does
it
goes
to
the
Registries
and
on
uses
the
markdown
markdown
extension,
because
it
has
no
value
for
the
txt
files.
A
So
it
removes
this
and
again
returns
this
proxy
assembles
if
there
were
some
other
extensions
and
Returns
the
proxy
without
markdown
extension,
robust
solution-
and
we
had
had
put
back
in
the
editor,
we
put
a
lot
of
thoughts
into
this
architecture
and
that's
pretty
much.
What
do
we
have
to
talk
about
in
this
technical
Deep
dive?
We
have
five
minutes.
A
It
took
a
bit
longer
than
I
anticipated,
but
do
you
have
any
questions?
No.
A
Yes,
that's
a
very
good
question,
the
the
only
thing
and
actually
we
have.
We
have
this
example
here,
so
the
order
of
the
order.
You
apply
your
extensions
in
matters
so,
as
we
saw
on
on
this
on
this
example,
so
Technically
when
you
apply
extension
one.
A
You
know
nothing
about
extension,
2
right,
but
then,
when
you
install
extension,
two
you'd
know
everything
about
extension,
one
so
the
order
you
apply
extension
in
matters,
and
since
we
are
when
you
use
in
this
particular
case,
when
you
use
use
extension,
two,
you
have
access
to
everything
that
this
proxy
returns,
both
to
the
core
instance
methods
and
to
the
methods
and
properties
provided
by
the
extension.
So
you
do
know
everything
about
the
extension
and
you
can
call
the
methods
and
properties
of
that
extension.
A
The
first
extension
knows
nothing
about
the
second
one,
but
it
can
do
some
checks
because
in
the
in
the
overall
proxy,
if
you
after
you
used
both
extensions,
you
can
you
have
access
to
to
the
methods
and
properties
of
both
extensions.
Let
me
show
this
on
an
on
the
example
yeah.
So
in
this
particular
example,
we
are
dealing
with
the
web
address,
so
we
first
we
install
the
toolbar
extension
and
then
we
have
the
Source
editor
base
extension.
A
So
there
is
the
base
extension
which
in
this
particular
case,
let's
check
this
out.
Let's
go
to
the
extensions.
A
A
A
If
we
don't
have
the
toolbar
extension
installed,
then
we
don't
have
access
to
the
to
to
all
the
two
totally
methods
within
the
toolbar
right.
So
we
have
to
double
check
this.
A
If
the
install
the
toolbar
extension
is
installed,
then
we
have,
then
we
can
go
on
with
setup
toolbar
extension,
and
then
we
know
for
sure
that
we
have
this
instance.toolbar
dot,
add
items
method
which
is
defined
in
the
toolbar
extension
toolbar,
add
items,
so
extensions
can
check
the
the
methods
available
from
other
extensions
and
then
they
can
hold
those
methods,
because
technically
at
any
given
point
of
time,
every
extension
is
dealing
with
the
proxy
of
the
instance,
which
knows
everything
about
the
already
installed
extensions.
A
So
in
this
case
we
can
build
extensions
which
depend
on
methods
from
other
extensions,
but
not
necessarily
digital
dependence.
So
in
this
case
the
bias
extension
can
totally
be
used
without
that
button.
Without
that
soft
trap
button,
because
that
button
is
used
only
for
for
the
I,
don't
know
for
for
markdown,
I
think
or
for
some
textual
thing,
but
if
the
toolbar
extension
is
not
available,
this
is
not
the
reason
to
not
install
the
base
extension
because
it
provides.
A
It
still
provides
some
public
API
for
highlighting,
for
example,
and
highlight
lines
and
remove
highlights
this
is
when
you
link
to
a
particular
line
in
the
editor.
A
This
functionality
is
still
valuable,
even
without
the
toolbar,
even
without
a
button.
But
if
the
toolbar
is
available,
we
extend
we.
We
extend
this
functionality
and
reach
this
functionality
with
with
new
button
in
on
the.
In
the
context
of
this
extension,
it
was
pretty
chaotic
explanation.
I
realized
this,
so
I
will
be
happy
to
jump
on
another
call
and
give
some
more
explanations,
but
in
general,
does
this
somehow
answer
the
question
yeah.
A
Cool,
so
we
are,
we
are
a
time
now
I'm
I'm,
happy
to
to
to
continue
the
discussion
if
you
want
to,
if
you
have
more
questions
now,
but
if
you,
if
you
need
to
drop
off,
that's
that's
totally
fine.
Well,.
C
Yeah
I'm,
not
in
a
hurry
and
okay
I
have
yeah.
First
of
all,
thank
you.
Both
very
nice,
comprehensive
presentation
and
I
really
think
it
will
help
to
understand
would
help
to
understand
how
the
editor
works
and
will
help
to
work
in
it
and
yeah.
My
question
is
like,
as
a
user
I
actually
would
like
to
see
the
feature
that,
when
I
do
edit
I
don't
know
to
create
a
new
file
and
do
something
in
the
editor
or
when
I
edit
an
existing
file.
C
That
I
am
like
when
I
accidentally,
like
close
my
tab
or,
if
I
refresh
page,
for
some
reason
that
my
contents
are
saved
and
I
think
this
functionality
is
not
available
now,
because
I
checked
and
yeah.
So
my
question
is:
what
is
the
reason
why
it
is
not
there?
Is
it
hard
to
implement,
or
nobody
was
thinking
about
it?
This.
A
Is
a
very
good
question
and
the
so
from
the
question:
I
assume
you
mean
the
web
editor,
so
the
editor
for
the
repository
yes
and
the
reason
why
this,
because
putting
the
content
storing
the
content
in
the
local
storage,
just
like
we
do
for
for.
A
It's
a
super
trivial
thing
right:
it's
not
done
for
the
web
editor
in
particular
on
purpose.
The
reason
being
we
are
talking
about
the
gits
commit
workflow.
So
if
you
make
changes
and
then
you
abandon
this
tab,
the
chain,
the
the
changes
are
stored
in
the
local
storage,
then
at
some
point
you
come
back
to
this
file
start
edit
this
and
reload
those
changes
from
the
local
storage,
because
we
do
not
have
any
way
to
present
the
changes
automatically
to
the
user.
So
user
has
to
explicitly
click
preview
changes.
In
order
to
see
the
changes.
A
There
is
a
very
high
danger
of
users
accidentally
committing
the
things
that
they
did
not
mean
to
commit,
because
simply
because
they
didn't
notice
this-
that
the
content
has
been
updated
with
the
content
from
local
storage
and
with
the
actively
developed
prod
projects
like
gitlab,
for
example,
if
you
work
with
an
actively
developed
file-
and
you
do
some
changes,
but
you
do
not
commit,
they
are
stored
in
the
local
storage.
But
there
are
many
many
different
changes
in
this
file
during
the
day
and
then
the
next
day
you
come
to
edit
this
file.
A
Again,
we
load
the
yesterday's
copy
of
this
file
and
then
you
accidentally
overwrite
all
of
the
changes
that
have
been
made
during
this
day
because
you
don't
see
the
changes.
This
is
the
user
experience
problem
which
we
have
to
deal
with
either
presenting
the
div
before
you
actually
click
commit
so
that
users
are
notified
about
the
changes
or,
as
we
do
now,
as
the
simple
most
boring
solution.
We
just
don't
support
this.
This
feature.
A
C
Yeah
but,
for
example,
like
just
a
normal
editor
like
this
code
or
idea,
yeah,
it's
different,
but
in
this
case,
if
you
close
the
top
right,
your
changes
are
still
there
and
even
if
remote
has
changed,
you
still
have
your
changes
so
because.
C
You
personally
do
you
think
that
which
is
still
valuable
enough
to
work
on
I.
A
Would
love
this
feature?
I
would
love
this
to
be
to
be
available
for
for
the
soil,
for
the
for
the
web?
Editor
the
but
as
I
said
technically,
there
is
like
there's
one
hour:
okay
right
to
introduce
the
local
storage
support,
the
uex
discussion
about
possible
complications
and
outcomes
of
this
decision
might
be
counted
in
months,
because
we
have
to
provide
users
with
a
proper
workflow
where
they
are
notified
about
the
changes
or
about
the
fact
that
they
are
actually
working
with
the
with
the
restored
version.
A
I
have
I
have
had
the
POC,
where
we
showed
the
notification
after
the
oh
I.
Think
it's
the
part
of
that
POC
for
consolidation,
consolidating
sources
and
content
editor
for
webi
or
for
web
editor,
but
the
the
idea
is
that
if
we
detect
that
there
is
the
content
stored
in
local
storage,
we
replace
it
replace
the
content
of
the
file.
A
With
with
that
content
and
show
the
The
Flash
to
the
user,
that
we
have
restored
this
content
from
the
local
storage
and
then
we
would
provide
two
buttons
preview
changes
so
that
you
can.
You
can
compare
the
changes
you
have
got
from
the
local
storage
to
the
actual
file
now
or
another
button,
just
reset
this
and
load
the
content
from
the
server.
So
there
are
different
things
to
approach
this.
But
again
this
involves
a
lot
of
user
experience.
Discussions.
B
A
A
E
A
A
For
the
question,
it's
technically
due
to
some
to
sum
it
up
a
bit
so
pretty
much
any
new
extension
again,
we
do
not
change
the
source
code
editor
or
a
source
editor
code.
Oh
now,
I'm
I'm,
going
to
confuse
all
those
things
now:
source
code,
Source
header,
editor
code
code,
editor.
So
all
of
the
functionality
comes
from
the
extensions
new
functions,
new
features.
Everything
comes
from
the
extensions
if
there
is
no
available
extension
for
this
file
type.
A
So
in
case
of
code
owners,
we
create
the
new
code
owners
extension
and
then
we
we
are
free
to
use
anything
and
Implement
anything
we
want.
This
allows
us
to
have
a
very
well
scoped
scoped
code,
very
easy
to
test
very
easy
to
catch
issues
because
they
are
scoped
and
in
general,
this
I
don't
know.
I
I,
really
like
the
the
current
architecture
of
the
of
the
source,
header
and
extensions
in
particular
how
these
two
things
work
together.
A
Yes,
so
I
think
this.
This
was
the
last
question,
at
least
in
the
in
the
document.
So
if
you
have
any
any
other
questions,
if
you've
find
some
something
that
you
you're
wondering
about
in
the
code
or
you
have
some
some
idea,
please
do
reach
out
to
me,
or
let's
just
discuss
transparently
in
the
group
channel,
so
that
everybody
could
participate
and
everybody
could
throw
ideas.
A
That
would
be
that'd,
be
super
great
to
continue
the
discussion
and
to
to
sort
of
to
get
outside
of
this
knowledge,
Silo
that
we
have
now
where
this
knowledge
is
sort
of
on
me.
But
we
want
to
spread
this
among
the
group
members.
So
if
you
would
like
to
to
chat
about
this,
let's
do
this
transparently
in
the
issue
in
on
in
the
slack
Channel.
C
A
A
B
A
Thanks
a
lot
have
a
great
day,
and
hopefully
the
recording
will
reach
the
the
slide
Channel.