Skip to content

Commit 1e1ee55

Browse files
authored
Merge pull request github#6511 from asgerf/js/vue-component-renaming
Approved by erik-krogh
2 parents 297ae91 + eef7f55 commit 1e1ee55

File tree

7 files changed

+72
-61
lines changed

7 files changed

+72
-61
lines changed
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
lgtm,codescanning
2+
* The class `Vue::Instance` has been renamed to `Vue::Component`.

javascript/ql/src/Vue/ArrowMethodOnVueInstance.ql

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111

1212
import javascript
1313

14-
from Vue::Instance instance, DataFlow::Node def, DataFlow::FunctionNode arrow, ThisExpr dis
14+
from Vue::Component instance, DataFlow::Node def, DataFlow::FunctionNode arrow, ThisExpr dis
1515
where
1616
instance.getABoundFunction() = def and
1717
arrow.flowsTo(def) and

javascript/ql/src/semmle/javascript/frameworks/Vue.qll

Lines changed: 56 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,13 @@ module Vue {
2121
VueExtend() { this = vue().getAMemberCall("extend") }
2222
}
2323

24-
private newtype TInstance =
24+
private newtype TComponent =
2525
MkVueInstance(DataFlow::NewNode def) { def = vue().getAnInstantiation() } or
2626
MkExtendedVue(VueExtend extend) or
2727
MkExtendedInstance(VueExtend extend, DataFlow::NewNode sub) {
2828
sub = extend.getAnInstantiation()
2929
} or
30-
MkComponent(DataFlow::CallNode def) { def = vue().getAMemberCall("component") } or
30+
MkComponentRegistration(DataFlow::CallNode def) { def = vue().getAMemberCall("component") } or
3131
MkSingleFileComponent(VueFile file)
3232

3333
/** Gets the name of a lifecycle hook method. */
@@ -82,22 +82,31 @@ module Vue {
8282
}
8383

8484
/**
85-
* A Vue instance definition.
85+
* DEPRECATED. This class has been renamed to `Vue::Component`.
86+
*/
87+
deprecated class Instance = Component;
88+
89+
/**
90+
* A Vue component, such as a `new Vue({ ... })` call or a `.vue` file.
91+
*
92+
* Generally speaking, a component is always created by calling `Vue.extend()` or
93+
* calling `extend` on another component.
94+
* Often the `Vue.extend()` call is performed by the Vue
95+
* framework, however, so the call is not always visible in the user code.
96+
* For instance, `new Vue(obj)` is shorthand for `new (Vue.extend(obj))`.
8697
*
87-
* This includes both explicit instantiations of Vue objects, and
88-
* implicit instantiations in the form of components or Vue
89-
* extensions that have not yet been instantiated to a Vue instance.
98+
* This class covers both the explicit `Vue.extend()` calls an those implicit in the framework.
9099
*
91-
* The following instances are recognized:
100+
* The following types of components are recognized:
92101
* - `new Vue({...})`
93102
* - `Vue.extend({...})`
94103
* - `new ExtendedVue({...})`
95104
* - `Vue.component("my-component", {...})`
96105
* - single file components in .vue files
97106
*/
98-
abstract class Instance extends TInstance {
107+
class Component extends TComponent {
99108
/** Gets a textual representation of this element. */
100-
abstract string toString();
109+
string toString() { none() } // overridden in subclasses
101110

102111
/**
103112
* Holds if this element is at the specified location.
@@ -120,26 +129,26 @@ module Vue {
120129
* Gets the options passed to the Vue object, such as the object literal `{...}` in `new Vue{{...})`
121130
* or the default export of a single-file component.
122131
*/
123-
abstract DataFlow::Node getOwnOptionsObject();
132+
DataFlow::Node getOwnOptionsObject() { none() } // overridden in subclasses
124133

125134
/**
126-
* Gets the class component implementing this Vue instance, if any.
135+
* Gets the class implementing this Vue component, if any.
127136
*
128137
* Specifically, this is a class annotated with `@Component` which flows to the options
129-
* object of this Vue instance.
138+
* object of this Vue component.
130139
*/
131140
ClassComponent getAsClassComponent() { result.flowsTo(getOwnOptionsObject()) }
132141

133142
/**
134-
* Gets the node for option `name` for this instance, this does not include
143+
* Gets the node for option `name` for this component, not including
135144
* those from extended objects and mixins.
136145
*/
137146
DataFlow::Node getOwnOption(string name) {
138147
result = getOwnOptionsObject().getALocalSource().getAPropertyWrite(name).getRhs()
139148
}
140149

141150
/**
142-
* Gets the node for option `name` for this instance, including those from
151+
* Gets the node for option `name` for this component, including those from
143152
* extended objects and mixins.
144153
*/
145154
DataFlow::Node getOption(string name) {
@@ -164,25 +173,25 @@ module Vue {
164173
}
165174

166175
/**
167-
* Gets a source node flowing into the option `name` of this instance, including those from
176+
* Gets a source node flowing into the option `name` of this component, including those from
168177
* extended objects and mixins.
169178
*/
170179
pragma[nomagic]
171180
DataFlow::SourceNode getOptionSource(string name) { result = getOption(name).getALocalSource() }
172181

173182
/**
174-
* Gets the template element used by this instance, if any.
183+
* Gets the template element used by this component, if any.
175184
*/
176-
abstract Template::Element getTemplateElement();
185+
Template::Element getTemplateElement() { none() } // overridden in subclasses
177186

178187
/**
179-
* Gets the node for the `data` option object of this instance.
188+
* Gets the node for the `data` option object of this component.
180189
*/
181190
DataFlow::Node getData() {
182191
exists(DataFlow::Node data | data = getOption("data") |
183192
result = data
184193
or
185-
// a constructor variant is available for all instance definitions
194+
// a constructor variant is available for all component definitions
186195
exists(DataFlow::FunctionNode f |
187196
f.flowsTo(data) and
188197
result = f.getAReturn()
@@ -195,13 +204,13 @@ module Vue {
195204
}
196205

197206
/**
198-
* Gets the node for the `template` option of this instance.
207+
* Gets the node for the `template` option of this component.
199208
*/
200209
pragma[nomagic]
201210
DataFlow::SourceNode getTemplate() { result = getOptionSource("template") }
202211

203212
/**
204-
* Gets the node for the `render` option of this instance.
213+
* Gets the node for the `render` option of this component.
205214
*/
206215
pragma[nomagic]
207216
DataFlow::SourceNode getRender() {
@@ -211,19 +220,19 @@ module Vue {
211220
}
212221

213222
/**
214-
* Gets the node for the `methods` option of this instance.
223+
* Gets the node for the `methods` option of this component.
215224
*/
216225
pragma[nomagic]
217226
DataFlow::SourceNode getMethods() { result = getOptionSource("methods") }
218227

219228
/**
220-
* Gets the node for the `computed` option of this instance.
229+
* Gets the node for the `computed` option of this component.
221230
*/
222231
pragma[nomagic]
223232
DataFlow::SourceNode getComputed() { result = getOptionSource("computed") }
224233

225234
/**
226-
* Gets the node for the `watch` option of this instance.
235+
* Gets the node for the `watch` option of this component.
227236
*/
228237
pragma[nomagic]
229238
DataFlow::SourceNode getWatch() { result = getOptionSource("watch") }
@@ -240,7 +249,7 @@ module Vue {
240249
}
241250

242251
/**
243-
* Gets a node for a member of the `methods` option of this instance.
252+
* Gets a node for a member of the `methods` option of this component.
244253
*/
245254
pragma[nomagic]
246255
private DataFlow::SourceNode getAMethod() {
@@ -251,7 +260,7 @@ module Vue {
251260
}
252261

253262
/**
254-
* Gets a node for a member of the `computed` option of this instance that matches `kind`.
263+
* Gets a node for a member of the `computed` option of this component that matches `kind`.
255264
*/
256265
pragma[nomagic]
257266
private DataFlow::SourceNode getAnAccessor(DataFlow::MemberKind kind) {
@@ -264,7 +273,7 @@ module Vue {
264273
}
265274

266275
/**
267-
* Gets a node for a member `name` of the `computed` option of this instance that matches `kind`.
276+
* Gets a node for a member `name` of the `computed` option of this component that matches `kind`.
268277
*/
269278
private DataFlow::SourceNode getAccessor(string name, DataFlow::MemberKind kind) {
270279
result = getComputed().getAPropertySource(name) and kind = DataFlow::MemberKind::getter()
@@ -276,7 +285,7 @@ module Vue {
276285
}
277286

278287
/**
279-
* Gets the node for the life cycle hook of the `hookName` option of this instance.
288+
* Gets the node for the life cycle hook of the `hookName` option of this component.
280289
*/
281290
pragma[nomagic]
282291
DataFlow::SourceNode getALifecycleHook(string hookName) {
@@ -289,7 +298,7 @@ module Vue {
289298
}
290299

291300
/**
292-
* Gets a node for a function that will be invoked with `this` bound to this instance.
301+
* Gets a node for a function that will be invoked with `this` bound to this component.
293302
*/
294303
DataFlow::FunctionNode getABoundFunction() {
295304
result = getAMethod()
@@ -316,7 +325,7 @@ module Vue {
316325
}
317326

318327
/**
319-
* Gets the data flow node that flows into the property `name` of this instance, or is
328+
* Gets the data flow node that flows into the property `name` of this component, or is
320329
* returned form a getter defining that property.
321330
*/
322331
DataFlow::Node getAPropertyValue(string name) {
@@ -330,9 +339,9 @@ module Vue {
330339
}
331340

332341
/**
333-
* A Vue instance from `new Vue({...})`.
342+
* A Vue component from `new Vue({...})`.
334343
*/
335-
class VueInstance extends Instance, MkVueInstance {
344+
class VueInstance extends Component, MkVueInstance {
336345
DataFlow::NewNode def;
337346

338347
VueInstance() { this = MkVueInstance(def) }
@@ -353,7 +362,7 @@ module Vue {
353362
/**
354363
* An extended Vue from `Vue.extend({...})`.
355364
*/
356-
class ExtendedVue extends Instance, MkExtendedVue {
365+
class ExtendedVue extends Component, MkExtendedVue {
357366
VueExtend extend;
358367

359368
ExtendedVue() { this = MkExtendedVue(extend) }
@@ -374,7 +383,7 @@ module Vue {
374383
/**
375384
* An instance of an extended Vue, for example `instance` of `var Ext = Vue.extend({...}); var instance = new Ext({...})`.
376385
*/
377-
class ExtendedInstance extends Instance, MkExtendedInstance {
386+
class ExtendedInstance extends Component, MkExtendedInstance {
378387
VueExtend extend;
379388
DataFlow::NewNode sub;
380389

@@ -391,7 +400,7 @@ module Vue {
391400
override DataFlow::Node getOwnOptionsObject() { result = sub.getArgument(0) }
392401

393402
override DataFlow::Node getOption(string name) {
394-
result = Instance.super.getOption(name)
403+
result = Component.super.getOption(name)
395404
or
396405
result = MkExtendedVue(extend).(ExtendedVue).getOption(name)
397406
}
@@ -402,10 +411,10 @@ module Vue {
402411
/**
403412
* A Vue component from `Vue.component("my-component", { ... })`.
404413
*/
405-
class Component extends Instance, MkComponent {
414+
class ComponentRegistration extends Component, MkComponentRegistration {
406415
DataFlow::CallNode def;
407416

408-
Component() { this = MkComponent(def) }
417+
ComponentRegistration() { this = MkComponentRegistration(def) }
409418

410419
override string toString() { result = def.toString() }
411420

@@ -423,7 +432,7 @@ module Vue {
423432
/**
424433
* A single file Vue component in a `.vue` file.
425434
*/
426-
class SingleFileComponent extends Instance, MkSingleFileComponent {
435+
class SingleFileComponent extends Component, MkSingleFileComponent {
427436
VueFile file;
428437

429438
SingleFileComponent() { this = MkSingleFileComponent(file) }
@@ -496,7 +505,7 @@ module Vue {
496505
*/
497506
class InstanceHeapStep extends TaintTracking::SharedTaintStep {
498507
override predicate step(DataFlow::Node pred, DataFlow::Node succ) {
499-
exists(Instance i, string name, DataFlow::FunctionNode bound |
508+
exists(Component i, string name, DataFlow::FunctionNode bound |
500509
bound.flowsTo(i.getABoundFunction()) and
501510
not bound.getFunction() instanceof ArrowFunctionExpr and
502511
succ = bound.getReceiver().getAPropertyRead(name) and
@@ -531,13 +540,13 @@ module Vue {
531540
*/
532541
class VHtmlSourceWrite extends TaintTracking::SharedTaintStep {
533542
override predicate step(DataFlow::Node pred, DataFlow::Node succ) {
534-
exists(Vue::Instance instance, string expr, VHtmlAttribute attr |
543+
exists(Vue::Component component, string expr, VHtmlAttribute attr |
535544
attr.getAttr().getRoot() =
536-
instance.getTemplateElement().(Vue::Template::HtmlElement).getElement() and
545+
component.getTemplateElement().(Vue::Template::HtmlElement).getElement() and
537546
expr = attr.getAttr().getValue() and
538547
// only support for simple identifier expressions
539548
expr.regexpMatch("(?i)[a-z0-9_]+") and
540-
pred = instance.getAPropertyValue(expr) and
549+
pred = component.getAPropertyValue(expr) and
541550
succ = attr
542551
)
543552
}
@@ -638,15 +647,15 @@ module Vue {
638647
or
639648
result = routeConfig().getMember("beforeEnter").getParameter([0, 1]).getAnImmediateUse()
640649
or
641-
exists(Instance i |
642-
result = i.getABoundFunction().getAFunctionValue().getReceiver().getAPropertyRead("$route")
650+
exists(Component c |
651+
result = c.getABoundFunction().getAFunctionValue().getReceiver().getAPropertyRead("$route")
643652
or
644653
result =
645-
i.getALifecycleHook(["beforeRouteEnter", "beforeRouteUpdate", "beforeRouteLeave"])
654+
c.getALifecycleHook(["beforeRouteEnter", "beforeRouteUpdate", "beforeRouteLeave"])
646655
.getAFunctionValue()
647656
.getParameter([0, 1])
648657
or
649-
result = i.getWatchHandler("$route").getParameter([0, 1])
658+
result = c.getWatchHandler("$route").getParameter([0, 1])
650659
)
651660
)
652661
or
@@ -664,7 +673,7 @@ module Vue {
664673
this = routeObject().getAPropertyRead(name)
665674
or
666675
exists(string prop |
667-
this = any(Instance i).getWatchHandler(prop).getParameter([0, 1]) and
676+
this = any(Component c).getWatchHandler(prop).getParameter([0, 1]) and
668677
name = prop.regexpCapture("\\$route\\.(params|query|hash|path|fullPath)\\b.*", 1)
669678
)
670679
|

javascript/ql/src/semmle/javascript/frameworks/Vuex.qll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ private module VueAPI {
2626
* or equivalent.
2727
*/
2828
class VueConfigObject extends API::Node {
29-
VueConfigObject() { this.getARhs() = any(Vue::Instance i).getOwnOptionsObject() }
29+
VueConfigObject() { this.getARhs() = any(Vue::Component c).getOwnOptionsObject() }
3030

3131
/** Gets an API node representing `this` in the Vue component. */
3232
API::Node getAnInstanceRef() {

javascript/ql/src/semmle/javascript/security/dataflow/Xss.qll

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -346,8 +346,8 @@ module DomBasedXss {
346346
*/
347347
class VueTemplateSink extends DomBasedXss::Sink {
348348
VueTemplateSink() {
349-
// Note: don't use Vue::Instance#getTemplate as it includes an unwanted getALocalSource() step
350-
this = any(Vue::Instance i).getOption("template")
349+
// Note: don't use Vue::Component#getTemplate as it includes an unwanted getALocalSource() step
350+
this = any(Vue::Component c).getOption("template")
351351
}
352352
}
353353

@@ -357,8 +357,8 @@ module DomBasedXss {
357357
*/
358358
class VueCreateElementSink extends DomBasedXss::Sink {
359359
VueCreateElementSink() {
360-
exists(Vue::Instance i, DataFlow::FunctionNode f |
361-
f.flowsTo(i.getRender()) and
360+
exists(Vue::Component c, DataFlow::FunctionNode f |
361+
f.flowsTo(c.getRender()) and
362362
this = f.getParameter(0).getACall().getArgument(0)
363363
)
364364
}

javascript/ql/test/library-tests/frameworks/Vue/tests.expected

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
instance_getAPropertyValue
1+
component_getAPropertyValue
22
| compont-with-route.vue:0:0:0:0 | compont-with-route.vue | dataA | compont-with-route.vue:31:14:31:34 | this.$r ... ery.foo |
33
| compont-with-route.vue:0:0:0:0 | compont-with-route.vue | message | compont-with-route.vue:19:15:19:22 | 'Hello!' |
44
| single-component-file-1.vue:0:0:0:0 | single-component-file-1.vue | dataA | single-component-file-1.vue:6:40:6:41 | 42 |
@@ -28,7 +28,7 @@ instance_getAPropertyValue
2828
| tst.js:85:1:87:2 | new Vue ... e; }\\n}) | created | tst.js:86:38:86:41 | true |
2929
| tst.js:94:2:96:3 | new Vue ... f,\\n\\t}) | dataA | tst.js:89:22:89:23 | 42 |
3030
| tst.js:99:2:104:3 | new Vue ... \\t\\t}\\n\\t}) | dataA | tst.js:100:18:100:19 | 42 |
31-
instance_getOption
31+
component_getOption
3232
| compont-with-route.vue:0:0:0:0 | compont-with-route.vue | watch | compont-with-route.vue:10:12:16:5 | {\\n ... }\\n } |
3333
| single-component-file-1.vue:0:0:0:0 | single-component-file-1.vue | data | single-component-file-1.vue:6:11:6:45 | functio ... 42 } } |
3434
| single-file-component-3.vue:0:0:0:0 | single-file-component-3.vue | data | single-file-component-3-script.js:4:8:4:42 | functio ... 42 } } |
@@ -58,7 +58,7 @@ instance_getOption
5858
| tst.js:94:2:96:3 | new Vue ... f,\\n\\t}) | data | tst.js:95:9:95:9 | f |
5959
| tst.js:99:2:104:3 | new Vue ... \\t\\t}\\n\\t}) | data | tst.js:100:9:100:21 | { dataA: 42 } |
6060
| tst.js:99:2:104:3 | new Vue ... \\t\\t}\\n\\t}) | methods | tst.js:101:12:103:3 | {\\n\\t\\t\\tm: ... ; }\\n\\t\\t} |
61-
instance
61+
component
6262
| compont-with-route.vue:0:0:0:0 | compont-with-route.vue |
6363
| single-component-file-1.vue:0:0:0:0 | single-component-file-1.vue |
6464
| single-file-component-2.vue:0:0:0:0 | single-file-component-2.vue |

0 commit comments

Comments
 (0)